diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs
index 7eecaa32b43..a111a8ed2a7 100644
--- a/Content.Server/Chat/Systems/ChatSystem.cs
+++ b/Content.Server/Chat/Systems/ChatSystem.cs
@@ -241,6 +241,18 @@ public void TrySendInGameICMessage(
if (string.IsNullOrEmpty(message))
return;
+ // Check if the message is in sign language
+ if (desiredType == InGameICChatType.Speak || desiredType == InGameICChatType.Whisper)
+ {
+ var language = languageOverride ?? _language.GetLanguage(source);
+ if (language.SignLanguage)
+ {
+ SendEntityEmote(source, message, range, nameOverride,
+ ignoreActionBlocker, signLanguage: true);
+ return;
+ }
+ }
+
// This message may have a radio prefix, and should then be whispered to the resolved radio channel
if (checkRadioPrefix)
{
@@ -570,7 +582,8 @@ private void SendEntityEmote(
bool hideLog = false,
bool checkEmote = true,
bool ignoreActionBlocker = false,
- NetUserId? author = null
+ NetUserId? author = null,
+ bool? signLanguage = false
)
{
if (!_actionBlocker.CanEmote(source) && !ignoreActionBlocker)
@@ -581,14 +594,29 @@ private void SendEntityEmote(
string name = FormattedMessage.EscapeText(nameOverride ?? Name(ent));
// Emotes use Identity.Name, since it doesn't actually involve your voice at all.
- var wrappedMessage = Loc.GetString("chat-manager-entity-me-wrap-message",
+ var wrappedMessage = "";
+ var obfuscatedWrappedMessage = "";
+ if (signLanguage == true)
+ {
+ wrappedMessage = Loc.GetString("chat-manager-entity-signlanguage-message",
+ ("entityName", name),
+ ("message", FormattedMessage.EscapeText(action)));
+
+ obfuscatedWrappedMessage = Loc.GetString("chat-manager-entity-signlanguage-obfuscated",
+ ("entityName", name));
+ }
+ else
+ {
+ wrappedMessage = Loc.GetString("chat-manager-entity-me-wrap-message",
("entityName", name),
("entity", ent),
("message", FormattedMessage.RemoveMarkup(action)));
+ }
if (checkEmote)
TryEmoteChatInput(source, action);
- SendInVoiceRange(ChatChannel.Emotes, name, action, wrappedMessage, obfuscated: "", obfuscatedWrappedMessage: "", source, range, author);
+ SendInVoiceRange(ChatChannel.Emotes, name, action, wrappedMessage, obfuscated: "",
+ obfuscatedWrappedMessage, source, range, author, null, true);
if (!hideLog)
if (name != Name(source))
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Emote from {ToPrettyString(source):user} as {name}: {action}");
@@ -702,7 +730,7 @@ private MessageRangeCheckResult MessageRangeCheck(ICommonSession session, ICChat
///
/// Sends a chat message to the given players in range of the source entity.
///
- private void SendInVoiceRange(ChatChannel channel, string name, string message, string wrappedMessage, string obfuscated, string obfuscatedWrappedMessage, EntityUid source, ChatTransmitRange range, NetUserId? author = null, LanguagePrototype? languageOverride = null)
+ private void SendInVoiceRange(ChatChannel channel, string name, string message, string wrappedMessage, string obfuscated, string obfuscatedWrappedMessage, EntityUid source, ChatTransmitRange range, NetUserId? author = null, LanguagePrototype? languageOverride = null, bool? signLanguage = false)
{
var language = languageOverride ?? _language.GetLanguage(source);
foreach (var (session, data) in GetRecipients(source, VoiceRange))
@@ -715,9 +743,17 @@ private void SendInVoiceRange(ChatChannel channel, string name, string message,
continue;
EntityUid listener = session.AttachedEntity.Value;
+ // Quickly Checking if the Emote is a real one or Sign Language.
+ var notSignLanguage = false;
+ if (channel == ChatChannel.Emotes)
+ {
+ notSignLanguage = true;
+ if (signLanguage == true)
+ notSignLanguage = false;
+ }
// If the channel does not support languages, or the entity can understand the message, send the original message, otherwise send the obfuscated version
- if (channel == ChatChannel.LOOC || channel == ChatChannel.Emotes || _language.CanUnderstand(listener, language))
+ if (channel == ChatChannel.LOOC || notSignLanguage || _language.CanUnderstand(listener, language))
{
_chatManager.ChatMessageToOne(channel, message, wrappedMessage, source, entHideChat, session.Channel, author: author);
}
diff --git a/Content.Shared/Language/LanguagePrototype.cs b/Content.Shared/Language/LanguagePrototype.cs
index 801ab8a393b..d6238922373 100644
--- a/Content.Shared/Language/LanguagePrototype.cs
+++ b/Content.Shared/Language/LanguagePrototype.cs
@@ -16,6 +16,12 @@ public sealed class LanguagePrototype : IPrototype
[DataField(required: true)]
public bool ObfuscateSyllables;
+ //
+ // If true, will mark the language as a SignLanguage and will be handled as such.
+ //
+ [DataField]
+ public bool SignLanguage;
+
///
/// Lists all syllables that are used to obfuscate a message a listener cannot understand if obfuscateSyllables is true.
/// Otherwise uses all possible phrases the creature can make when trying to say anything.
diff --git a/Resources/Locale/en-US/chat/managers/chat-manager.ftl b/Resources/Locale/en-US/chat/managers/chat-manager.ftl
index fab815b4f90..262c7b9df0e 100644
--- a/Resources/Locale/en-US/chat/managers/chat-manager.ftl
+++ b/Resources/Locale/en-US/chat/managers/chat-manager.ftl
@@ -33,6 +33,9 @@ chat-manager-entity-me-wrap-message = [italic]{ PROPER($entity) ->
[true] {$entityName} {$message}[/italic]
}
+chat-manager-entity-signlanguage-message = [italic]{$entityName} signs "[BubbleContent]{$message}[/BubbleContent]"[/italic]
+chat-manager-entity-signlanguage-obfuscated = [italic]{$entityName} signs something.[/italic]
+
chat-manager-entity-looc-wrap-message = LOOC: {$entityName}: {$message}
chat-manager-send-ooc-wrap-message = OOC: {$playerName}: {$message}
chat-manager-send-ooc-patron-wrap-message = OOC: [color={$patronColor}]{$playerName}[/color]: {$message}
diff --git a/Resources/Locale/en-US/language/languages.ftl b/Resources/Locale/en-US/language/languages.ftl
index 69c5d0a4a76..209daf92de8 100644
--- a/Resources/Locale/en-US/language/languages.ftl
+++ b/Resources/Locale/en-US/language/languages.ftl
@@ -4,6 +4,9 @@ language-Universal-description = What are you?
language-GalacticCommon-name = Galactic common
language-GalacticCommon-description = The standard Galatic language, most commonly used for inter-species communications and legal work.
+language-SignLanguage-name = Sign Language
+language-SignLanguage-description = The standard Galactic sign language, used by those that are unable to speak Galactic Common or at all.
+
language-Bubblish-name = Bubblish
language-Bubblish-description = The language of Slimes. Being a mixture of bubbling noises and pops it's very difficult to speak for humans without the use of mechanical aids.
diff --git a/Resources/Prototypes/Language/languages.yml b/Resources/Prototypes/Language/languages.yml
index 90bce1baed2..adebe7d3afb 100644
--- a/Resources/Prototypes/Language/languages.yml
+++ b/Resources/Prototypes/Language/languages.yml
@@ -31,6 +31,14 @@
- nah
- wah
+# The common galactic Sign Language!
+- type: language
+ id: SignLanguage
+ signLanguage: true
+ obfuscateSyllables: false
+ replacement:
+ - "*incomprehensible*"
+
# Spoken by slimes.
- type: language
id: Bubblish