From 61719b756b0c9f68b0937af961ed35f36ad61fca Mon Sep 17 00:00:00 2001 From: FoxxoTrystan <45297731+FoxxoTrystan@users.noreply.github.com> Date: Fri, 19 Jul 2024 19:20:30 +0200 Subject: [PATCH] Sign Languages! (#553) # Description Gives a new way to speak, Sign Languages using the Language system by only adding a nullable variable. Sign Language uses the default Emote system, meaning its will not get picked up by Radio or others devices or get blocked by accents. When a Sign Language is on, "Say/Whisper" will talk in Sign Language, Emote will still act like normal emotes. The Glorious Sign Language has arrived... and there can be more then one! ---

Media

![image](https://github.com/user-attachments/assets/ac0c1a57-da49-4419-bb75-da0a308eee7d) ![image](https://github.com/user-attachments/assets/0739a740-4adf-4ba1-a852-0a382a534d8d)

--- # Changelog :cl: FoxxoTrystan - add: Added the ability to speak with Sign Language. --- Content.Server/Chat/Systems/ChatSystem.cs | 54 ++++++++++++++++--- Content.Shared/Language/LanguagePrototype.cs | 8 ++- Resources/Locale/en-US/language/languages.ftl | 3 ++ .../Locale/en-US/language/sign-language.ftl | 4 ++ Resources/Prototypes/Language/languages.yml | 9 ++++ 5 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 Resources/Locale/en-US/language/sign-language.ftl diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 58bc5dac65f..bfb38457e92 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -241,6 +241,17 @@ 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 ?? false) + { + SendEntityEmote(source, message, range, nameOverride, ignoreActionBlocker, signLanguage: true, languageOverride: languageOverride); + return; + } + } + // This message may have a radio prefix, and should then be whispered to the resolved radio channel if (checkRadioPrefix) { @@ -573,7 +584,9 @@ private void SendEntityEmote( bool hideLog = false, bool checkEmote = true, bool ignoreActionBlocker = false, - NetUserId? author = null + NetUserId? author = null, + LanguagePrototype? languageOverride = null, + bool? signLanguage = false ) { if (!_actionBlocker.CanEmote(source) && !ignoreActionBlocker) @@ -583,15 +596,32 @@ private void SendEntityEmote( var ent = Identity.Entity(source, EntityManager); string name = FormattedMessage.EscapeText(nameOverride ?? Name(ent)); + var language = languageOverride ?? _language.GetLanguage(source); + // Emotes use Identity.Name, since it doesn't actually involve your voice at all. - var wrappedMessage = Loc.GetString("chat-manager-entity-me-wrap-message", - ("entityName", name), - ("entity", ent), - ("message", FormattedMessage.RemoveMarkup(action))); + var wrappedMessage = ""; + var obfuscatedWrappedMessage = ""; + if (signLanguage == true) + { + wrappedMessage = Loc.GetString("entity-signlanguage-message", + ("entityName", name), + ("message", FormattedMessage.EscapeText(action))); + + obfuscatedWrappedMessage = Loc.GetString(_language.ObfuscateSpeech(action, language), + ("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, signLanguage: true); if (!hideLog) if (name != Name(source)) _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Emote from {ToPrettyString(source):user} as {name}: {action}"); @@ -705,7 +735,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)) @@ -718,9 +748,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.ID)) + if (channel == ChatChannel.LOOC || notSignLanguage || _language.CanUnderstand(listener, language.ID)) { _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 be54b45aa1f..79c17daccd8 100644 --- a/Content.Shared/Language/LanguagePrototype.cs +++ b/Content.Shared/Language/LanguagePrototype.cs @@ -16,7 +16,13 @@ public sealed class LanguagePrototype : IPrototype [DataField("fontSize")] public int? FontSize; - + + /// + /// If true, will mark the language as a SignLanguage and will be handled as such. + /// + [DataField("signLanguage")] + public bool? SignLanguage; + /// /// Obfuscation method used by this language. By default, uses /// 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/Locale/en-US/language/sign-language.ftl b/Resources/Locale/en-US/language/sign-language.ftl new file mode 100644 index 00000000000..f4548f995c5 --- /dev/null +++ b/Resources/Locale/en-US/language/sign-language.ftl @@ -0,0 +1,4 @@ +entity-signlanguage-message = [italic]{$entityName} signs "[BubbleContent]{$message}[/BubbleContent]"[/italic] + +language-signlanguage-1 = [italic]{$entityName} signs something.[/italic] +language-signlanguage-2 = [italic]{$entityName} makes weird hand gestures.[/italic] diff --git a/Resources/Prototypes/Language/languages.yml b/Resources/Prototypes/Language/languages.yml index 048fdc6f24c..bec1884fe5c 100644 --- a/Resources/Prototypes/Language/languages.yml +++ b/Resources/Prototypes/Language/languages.yml @@ -35,6 +35,15 @@ - nah - wah +- type: language + id: SignLanguage + signLanguage: true + obfuscation: + !type:ReplacementObfuscation + replacement: + - "language-signlanguage-1" + - "language-signlanguage-2" + # Spoken by slimes. - type: language id: Bubblish