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