From 9fdfa0f1162b7fb23b47d40b846c3ddb13e5bb62 Mon Sep 17 00:00:00 2001 From: Utmanarn Date: Thu, 4 Jun 2026 19:25:58 +0200 Subject: [PATCH 1/5] Flavourful emotes (#5595) * Changed up how emoting works This was a long 10 hours just to get the chat to behave slightly different. At least we can now scream over radio! Will most definitely need some more work to get bugs out since this is the first implementation. * Not ok This was unmarked for some reason... I don't remember unmarking this. * DeltaV comments Added comments to explain changes. Moved localization files to the _DV folder. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Moved code Moved code to more suitable files and added some comments. * Rights for robots Now those with intrinsic radios can also emote! * Fixes up some small stuff Changes to fix some small issues with the code to align it more with modern standards. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix by-ref event Never worked with this event type before so gonna hope this works. * Update Content.Shared/Chat/SharedChatSystem.Emote.cs Signed-off-by: pathetic meowmeow * Update Content.Shared/Chat/SharedChatSystem.cs Signed-off-by: pathetic meowmeow * Update Content.Server/Chat/Systems/ChatSystem.cs Signed-off-by: pathetic meowmeow * fix style nits * remove conflicting chatsan --------- Signed-off-by: pathetic meowmeow Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: pathetic meowmeow --- .../Chat/Managers/ChatSanitizationManager.cs | 1 + Content.Server/Chat/Systems/ChatSystem.cs | 90 +++++++++++++++++-- .../Radio/EntitySystems/HeadsetSystem.cs | 40 ++++++++- .../Radio/EntitySystems/RadioSystem.cs | 59 ++++++++---- Content.Shared/Chat/SharedChatSystem.Emote.cs | 48 +++++++++- Content.Shared/Chat/SharedChatSystem.cs | 28 +++++- Content.Shared/_DV/Chat/SharedChatEvents.cs | 6 ++ .../_DV/Chat/SharedChatSystemEnums.cs | 15 ++++ .../en-US/_DV/headset/headset-component.ftl | 9 ++ .../en-US/_NF/chat/managers/chat_manager.ftl | 14 +++ 10 files changed, 278 insertions(+), 32 deletions(-) create mode 100644 Content.Shared/_DV/Chat/SharedChatEvents.cs create mode 100644 Content.Shared/_DV/Chat/SharedChatSystemEnums.cs create mode 100644 Resources/Locale/en-US/_DV/headset/headset-component.ftl diff --git a/Content.Server/Chat/Managers/ChatSanitizationManager.cs b/Content.Server/Chat/Managers/ChatSanitizationManager.cs index 106e5313e6e..d2ad0ce0ff2 100644 --- a/Content.Server/Chat/Managers/ChatSanitizationManager.cs +++ b/Content.Server/Chat/Managers/ChatSanitizationManager.cs @@ -91,6 +91,7 @@ private static readonly (Regex regex, string emoteKey)[] ShorthandToEmote = Entry("[':", "chatsan-tearfully-smiles"), Entry("('=", "chatsan-tearfully-smiles"), Entry("['=", "chatsan-tearfully-smiles"), + Entry("?", "chatsan-confused"), //DeltaV ]; [Dependency] private readonly IConfigurationManager _configurationManager = default!; diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 89319230f86..75487210613 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -40,6 +40,7 @@ using Robust.Shared.Random; using Robust.Shared.Replays; using Robust.Shared.Utility; +using Content.Shared._DV.Chat; // DeltaV - chat enhancements namespace Content.Server.Chat.Systems; @@ -248,7 +249,7 @@ public void TrySendInGameICMessage( // Was there an emote in the message? If so, send it. if (player != null && emoteStr != message && emoteStr != null) { - SendEntityEmote(source, emoteStr, range, nameOverride, ignoreActionBlocker); + SendEntityEmote(source, emoteStr, range, nameOverride, null, ignoreActionBlocker); // DeltaV - Had to change up for SendEntityEmote } // This can happen if the entire string is sanitized out. @@ -311,9 +312,18 @@ public void TrySendInGameICMessage( case InGameICChatType.Whisper: SendEntityWhisper(source, message, range, null, nameOverride, language, hideLog, ignoreActionBlocker); break; - case InGameICChatType.Emote: - SendEntityEmote(source, message, range, nameOverride, hideLog, ignoreActionBlocker: ignoreActionBlocker); - break; + case InGameICChatType.Emote: // DeltaV - Emote now has different types of emotes. + var type = ProcessEmoteMessage(source, message, out var modMessage); + if (type == EmoteType.Audible || type == EmoteType.AudiblePossessive) + { + if (checkRadioPrefix && TryProcessRadioMessage(source, modMessage, out var outputMessage, out var channel, capitalize: false)) + SendAudibleEntityEmote(source, outputMessage, range, nameOverride, channel, type, hideLog: hideLog, ignoreActionBlocker: ignoreActionBlocker); + else + SendAudibleEntityEmote(source, modMessage, range, nameOverride, null, type, hideLog: hideLog, ignoreActionBlocker: ignoreActionBlocker); + } + else + SendEntityEmote(source, modMessage, range, nameOverride, type, hideLog, ignoreActionBlocker: ignoreActionBlocker); + break; // DeltaV - End // Floofstation section case InGameICChatType.Subtle: SendEntitySubtle(source, message, range, nameOverride, hideLog: hideLog, ignoreActionBlocker); @@ -819,6 +829,7 @@ protected override void SendEntityEmote( string action, ChatTransmitRange range, string? nameOverride, + EmoteType? emoteType, // DeltaV bool hideLog = false, bool checkEmote = true, bool ignoreActionBlocker = false, @@ -832,11 +843,21 @@ protected override void SendEntityEmote( var ent = Identity.Entity(source, EntityManager); string name = FormattedMessage.EscapeText(nameOverride ?? Name(ent)); + // Begin DeltaV + string wrappedMessage; + // 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.RemoveMarkupOrThrow(action))); + if (emoteType == EmoteType.Possessive) // DeltaV - Emote types now get checked. + wrappedMessage = Loc.GetString("chat-manager-entity-me-possessive-wrap-message", + ("entityName", name), + ("entity", ent), + ("message", FormattedMessage.RemoveMarkupOrThrow(action))); + else + wrappedMessage = Loc.GetString("chat-manager-entity-me-wrap-message", + ("entityName", name), + ("entity", ent), + ("message", FormattedMessage.RemoveMarkupOrThrow(action))); + // End DeltaV if (checkEmote && !TryEmoteChatInput(source, action)) @@ -850,6 +871,59 @@ protected override void SendEntityEmote( _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Emote from {source}: {action}"); } + // DeltaV - Added this to differentiate between emotes that can be heard over radio and those which can't. + protected override void SendAudibleEntityEmote( + EntityUid source, + string action, + ChatTransmitRange range, + string? nameOverride, + RadioChannelPrototype? channel, + EmoteType? emoteType, + bool hideLog = false, + bool checkEmote = true, + bool ignoreActionBlocker = false, + NetUserId? author = null + ) + { + if (!_actionBlocker.CanSpeak(source) && !ignoreActionBlocker) + return; + + EmoteType type = emoteType ?? EmoteType.Audible; + + // get the entity's apparent name (if no override provided). + var ent = Identity.Entity(source, EntityManager); + string name = FormattedMessage.EscapeText(nameOverride ?? Name(ent)); + + string wrappedMessage; + + // Audible emotes use Identity.Name, since that is the status quo. Emotes like scream doesn't currently reveal identities so this won't either. [This may be changed with feedback as you can audibly emote over radios] + if (emoteType == EmoteType.AudiblePossessive) + wrappedMessage = Loc.GetString("chat-manager-entity-me-audible-possessive-wrap-message", + ("entityName", name), + ("entity", ent), + ("message", FormattedMessage.RemoveMarkupOrThrow(action))); + else + wrappedMessage = Loc.GetString("chat-manager-entity-me-audible-wrap-message", + ("entityName", name), + ("entity", ent), + ("message", FormattedMessage.RemoveMarkupOrThrow(action))); + + if (checkEmote && + !TryEmoteChatInput(source, action)) + return; + + SendInVoiceRange(ChatChannel.Emotes, action, wrappedMessage, source, range, author); + + var ev = new EntityAudiblyEmotedEvent(source, action, channel, type); + RaiseLocalEvent(source, ref ev, true); + if (!hideLog) + if (name != Name(source)) + _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Emote from {source} as {name}: {action}"); + else + _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Emote from {source}: {action}"); + } + // DeltaV - End + // ReSharper disable once InconsistentNaming private void SendLOOC(EntityUid source, ICommonSession player, string message, bool hideChat) { diff --git a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs index 7ee80a4a749..2e284b27d8c 100644 --- a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs +++ b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs @@ -10,6 +10,7 @@ using Content.Shared.Radio.EntitySystems; using Robust.Shared.Network; using Robust.Shared.Player; +using Content.Shared._DV.Chat; namespace Content.Server.Radio.EntitySystems; @@ -27,6 +28,7 @@ public override void Initialize() SubscribeLocalEvent(OnKeysChanged); SubscribeLocalEvent(OnSpeak); + SubscribeLocalEvent(OnAudibleEmote); // DeltaV SubscribeLocalEvent(OnEmpPulse); } @@ -51,13 +53,43 @@ private void UpdateRadioChannels(EntityUid uid, HeadsetComponent headset, Encryp EnsureComp(uid).Channels = new(keyHolder.Channels); } + // DeltaV + // WARNING - Be very careful when modifying this method. + // The implementation right now has null forgiving operatiors in OnSpeak() and OnAudibleEmote() since this only returns true if channel is not null + private bool CheckRadioCapable(EntityUid uid, WearingHeadsetComponent headset, RadioChannelPrototype? channel) + { + if (channel != null + && TryComp(headset.Headset, out EncryptionKeyHolderComponent? keys) + && keys.Channels.Contains(channel.ID)) + { + if (!TryComp(uid, out var hands) || hands.Count < 1 || + TryComp(uid, out var cuffable) && _cuffable.IsCuffed((uid, cuffable))) + { + _popup.PopupEntity(Loc.GetString("headset-cant-reach"), uid, uid, PopupType.SmallCaution); + return false; + } + + return true; + } + + return false; + } + + private void OnAudibleEmote(EntityUid uid, WearingHeadsetComponent component, EntityAudiblyEmotedEvent args) + { + if (CheckRadioCapable(uid, component, args.Channel)) + { + _radio.SendRadioMessage(uid, args.Message, args.Channel!, component.Headset, emType: args.Type); + args.Channel = null; + } + } + // DeltaV - End + private void OnSpeak(EntityUid uid, WearingHeadsetComponent component, EntitySpokeEvent args) { - if (args.Channel != null - && TryComp(component.Headset, out EncryptionKeyHolderComponent? keys) - && keys.Channels.Contains(args.Channel.ID)) + if (CheckRadioCapable(uid, component, args.Channel)) // DeltaV - Put all the radio checks into the CheckRadioCapable() method. { - _radio.SendRadioMessage(uid, args.Message, args.Channel, component.Headset); + _radio.SendRadioMessage(uid, args.Message, args.Channel!, component.Headset); // DeltaV - Made the args.Channel null ignorant as CheckRadioCapable() guarantees it not null. args.Channel = null; // prevent duplicate messages from other listeners. } } diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index abc128dd695..364b7017824 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -4,6 +4,7 @@ using Content.Server._EinsteinEngines.Language; using Content.Server.Power.Components; using Content.Shared._Mono.Radio; +using Content.Shared._DV.Chat; using Content.Shared.Chat; using Content.Shared.Database; using Content.Shared._EinsteinEngines.Language; @@ -45,6 +46,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnIntrinsicReceive); SubscribeLocalEvent(OnIntrinsicSpeak); + SubscribeLocalEvent(OnIntrinsicAudibleEmote); // DeltaV - Robots should be allowed to emote over radio. _exemptQuery = GetEntityQuery(); } @@ -90,6 +92,16 @@ private void OnIntrinsicReceive(EntityUid uid, IntrinsicRadioReceiverComponent c } } + // DeltaV + private void OnIntrinsicAudibleEmote(EntityUid uid, IntrinsicRadioTransmitterComponent component, EntityAudiblyEmotedEvent args) + { + if (args.Channel != null && component.Channels.Contains(args.Channel.ID)) + { + SendRadioMessage(uid, args.Message, args.Channel, uid, emType: args.Type); + } + } + // DeltaV - End + /// /// Send radio message to all active radio listeners /// @@ -100,9 +112,10 @@ public void SendRadioMessage( EntityUid radioSource, int? frequency = null, LanguagePrototype? language = null, - bool escapeMarkup = true) // Frontier: added frequency + bool escapeMarkup = true, + EmoteType? emType = null) // Frontier: added frequency // DeltaV - EmoteType? added. { - SendRadioMessage(messageSource, message, _prototype.Index(channel), radioSource, frequency: frequency, escapeMarkup: escapeMarkup, language: language); // Frontier: added frequency / Einstein Engines - Language + SendRadioMessage(messageSource, message, _prototype.Index(channel), radioSource, frequency: frequency, escapeMarkup: escapeMarkup, language: language, emType: emType); // Frontier: added frequency / Einstein Engines - Language } /// @@ -117,7 +130,8 @@ public void SendRadioMessage( EntityUid radioSource, int? frequency = null, LanguagePrototype? language = null, - bool escapeMarkup = true) // Nuclear-14: add frequency + bool escapeMarkup = true, + EmoteType? emType = null) // DeltaV - EmoteType? added. // Nuclear-14: add frequency { // Einstein Engines - Language begin if (language == null) @@ -170,7 +184,7 @@ public void SendRadioMessage( // ("channel", channelText), // Frontier: $"\\[{channel.LocalizedName}\\]" + /// Checks which type of emote the message contains and returns the type while outputting the string without the prefixes. + /// + public static EmoteType? ProcessEmoteMessage(EntityUid source, string input, out string output) + { + output = input.Trim(); + EmoteType? type = null; + + if (input.Length == 0) + return type; + + if (!(input.StartsWith(AudibleEmotePrefix) || input.StartsWith(PossessiveEmotePrefix))) + { + type = EmoteType.Normal; + return type; + } + + var emoteType = input[0]; + output = input[1..].TrimStart(); + + if (emoteType == AudibleEmotePrefix) + { + emoteType = input[1]; // Check for if we want AudiblePossessiveEmote + type = EmoteType.Audible; + } + + if (emoteType == PossessiveEmotePrefix) + { + if (type == EmoteType.Audible) + { + type = EmoteType.AudiblePossessive; + output = input[2..].TrimStart(); + } + else + type = EmoteType.Possessive; + } + + return type; + } + // DeltaV - End + /// /// Creates and raises and then to let other systems do things like play audio. /// In the case that the Before event is cancelled, EmoteEvent will NOT be raised, and will optionally show a message to the player @@ -274,4 +318,4 @@ private string TrimPunctuation(string textInput) return textInput[trimStart..trimEnd]; } -} \ No newline at end of file +} diff --git a/Content.Shared/Chat/SharedChatSystem.cs b/Content.Shared/Chat/SharedChatSystem.cs index 4c5e503c5cb..4425ba3409b 100644 --- a/Content.Shared/Chat/SharedChatSystem.cs +++ b/Content.Shared/Chat/SharedChatSystem.cs @@ -1,6 +1,7 @@ using System.Collections.Frozen; using Content.Shared._Starlight.CollectiveMind; // Goobstation - Starlight collective mind port using System.Text.RegularExpressions; +using Content.Shared._DV.Chat; using Content.Shared.ActionBlocker; using Content.Shared.Chat.Prototypes; using Content.Shared.Popups; @@ -26,6 +27,8 @@ public abstract partial class SharedChatSystem : EntitySystem public const char OOCPrefix = '['; public const char EmotesPrefix = '@'; public const char EmotesAltPrefix = '*'; + public const char AudibleEmotePrefix = '!'; // DeltaV - You may now scream audibly! + public const char PossessiveEmotePrefix = '\''; // DeltaV - You may now be possessive of things! Whatever that means. public const char AdminPrefix = ']'; public const char WhisperPrefix = ','; public const char CollectiveMindPrefix = '+'; @@ -161,6 +164,7 @@ public bool TryProccessRadioMessage( string input, out string output, out RadioChannelPrototype? channel, + bool capitalize = true, // DeltaV - We might not want to capitalize the first letter if we send in emotes. bool quiet = false) { output = input.Trim(); @@ -171,7 +175,7 @@ public bool TryProccessRadioMessage( if (input.StartsWith(RadioCommonPrefix)) { - output = SanitizeMessageCapital(input[1..].TrimStart()); + output = capitalize ? SanitizeMessageCapital(input[1..].TrimStart()) : input[1..].TrimStart(); // DeltaV channel = _prototypeManager.Index(CommonChannel); return true; } @@ -181,7 +185,7 @@ public bool TryProccessRadioMessage( if (input.Length < 2 || char.IsWhiteSpace(input[1])) { - output = SanitizeMessageCapital(input[1..].TrimStart()); + output = capitalize ? SanitizeMessageCapital(input[1..].TrimStart()) : input[1..].TrimStart(); // DeltaV if (!quiet) _popup.PopupEntity(Loc.GetString("chat-manager-no-radio-key"), source, source); return true; @@ -189,7 +193,7 @@ public bool TryProccessRadioMessage( var channelKey = input[1]; channelKey = char.ToLower(channelKey); - output = SanitizeMessageCapital(input[2..].TrimStart()); + output = capitalize ? SanitizeMessageCapital(input[2..].TrimStart()) : input[2..].TrimStart(); // DeltaV if (channelKey == DefaultChannelKey) { @@ -376,11 +380,29 @@ public static string GetStringInsideTag(ChatMessage message, string tag) return rawmsg.Substring(tagStart, tagEnd - tagStart); } + // DeltaV + protected virtual void SendAudibleEntityEmote( + EntityUid source, + string action, + ChatTransmitRange range, + string? nameOverride, + RadioChannelPrototype? channel, + EmoteType? emoteType, + bool hideLog = false, + bool checkEmote = true, + bool ignoreActionBlocker = false, + NetUserId? author = null + ) + { + } + // DeltaV - End + protected virtual void SendEntityEmote( EntityUid source, string action, ChatTransmitRange range, string? nameOverride, + EmoteType? emoteType, bool hideLog = false, bool checkEmote = true, bool ignoreActionBlocker = false, diff --git a/Content.Shared/_DV/Chat/SharedChatEvents.cs b/Content.Shared/_DV/Chat/SharedChatEvents.cs new file mode 100644 index 00000000000..bc4b7b60cdd --- /dev/null +++ b/Content.Shared/_DV/Chat/SharedChatEvents.cs @@ -0,0 +1,6 @@ +using Content.Shared.Radio; + +namespace Content.Shared._DV.Chat; + +[ByRefEvent] +public record struct EntityAudiblyEmotedEvent(EntityUid Source, string Message, RadioChannelPrototype? Channel, EmoteType? Type); diff --git a/Content.Shared/_DV/Chat/SharedChatSystemEnums.cs b/Content.Shared/_DV/Chat/SharedChatSystemEnums.cs new file mode 100644 index 00000000000..3a4a9e26788 --- /dev/null +++ b/Content.Shared/_DV/Chat/SharedChatSystemEnums.cs @@ -0,0 +1,15 @@ +namespace Content.Shared._DV.Chat; + + +// Note for future: If you want to make this more robust to handle more types of emotes while still being able to check off audible as an option for it then it would +// probably be better to make it a struct and have audible be a flag for it and then the type of emote. This would avoid having to make two different types for audible and visual. +/// +/// Different ways of emoting. For that little extra in RP! +/// +public enum EmoteType : byte +{ + Normal, // Character emotes + Audible, // Character screams + Possessive, // Character's emote + AudiblePossessive // Character's scream +} diff --git a/Resources/Locale/en-US/_DV/headset/headset-component.ftl b/Resources/Locale/en-US/_DV/headset/headset-component.ftl new file mode 100644 index 00000000000..47547287fd1 --- /dev/null +++ b/Resources/Locale/en-US/_DV/headset/headset-component.ftl @@ -0,0 +1,9 @@ +chat-radio-message-audible-emote-wrap = [color={$color}]{$channel} {$name} {$message}[/color] +chat-radio-message-audible-possessive-emote-wrap = [color={$color}]{$channel} {$name}'s {$message}[/color] + +chat-radio-justice = Justice +chat-radio-prison = Prison +chat-radio-admeme-1 = Channel 1 +chat-radio-admeme-2 = Channel 2 +chat-radio-admeme-3 = Channel 3 +chat-radio-rootsong = Rootsong diff --git a/Resources/Locale/en-US/_NF/chat/managers/chat_manager.ftl b/Resources/Locale/en-US/_NF/chat/managers/chat_manager.ftl index a1da8555704..f3b171fd2a5 100644 --- a/Resources/Locale/en-US/_NF/chat/managers/chat_manager.ftl +++ b/Resources/Locale/en-US/_NF/chat/managers/chat_manager.ftl @@ -41,3 +41,17 @@ chat-speech-verb-feroxi-1 = blubs chat-speech-verb-feroxi-2 = swishes chat-speech-verb-feroxi-3 = gnashes chat-speech-verb-feroxi-4 = growls + +chat-manager-entity-me-possessive-wrap-message = [italic]{ PROPER($entity) -> + *[false] The {$entityName}'s {$message}[/italic] + [true] {CAPITALIZE($entityName)}'s {$message}[/italic] + } + +chat-manager-entity-me-audible-wrap-message = [italic]{ PROPER($entity) -> + *[false] The {$entityName} {$message}[/italic] + [true] {CAPITALIZE($entityName)} {$message}[/italic] + } +chat-manager-entity-me-audible-possessive-wrap-message = [italic]{ PROPER($entity) -> + *[false] The {$entityName}'s {$message}[/italic] + [true] {CAPITALIZE($entityName)}'s {$message}[/italic] + } From 66af5ddec2157e8b19b3de73a6166a114478f8c3 Mon Sep 17 00:00:00 2001 From: asoggycroissant Date: Sun, 2 Aug 2026 23:01:03 -0500 Subject: [PATCH 2/5] Flavourful emotes (#5595) * Changed up how emoting works This was a long 10 hours just to get the chat to behave slightly different. At least we can now scream over radio! Will most definitely need some more work to get bugs out since this is the first implementation. * Not ok This was unmarked for some reason... I don't remember unmarking this. * DeltaV comments Added comments to explain changes. Moved localization files to the _DV folder. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Moved code Moved code to more suitable files and added some comments. * Rights for robots Now those with intrinsic radios can also emote! * Fixes up some small stuff Changes to fix some small issues with the code to align it more with modern standards. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix by-ref event Never worked with this event type before so gonna hope this works. * Update Content.Shared/Chat/SharedChatSystem.Emote.cs Signed-off-by: pathetic meowmeow * Update Content.Shared/Chat/SharedChatSystem.cs Signed-off-by: pathetic meowmeow * Update Content.Server/Chat/Systems/ChatSystem.cs Signed-off-by: pathetic meowmeow * fix style nits * remove conflicting chatsan --------- Signed-off-by: pathetic meowmeow Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: pathetic meowmeow --- Content.Server/Chat/Systems/ChatSystem.cs | 4 ++-- Content.Server/Radio/EntitySystems/HeadsetSystem.cs | 12 ++++++------ Content.Server/Radio/EntitySystems/RadioSystem.cs | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 75487210613..dcbd5dada0d 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -316,7 +316,7 @@ public void TrySendInGameICMessage( var type = ProcessEmoteMessage(source, message, out var modMessage); if (type == EmoteType.Audible || type == EmoteType.AudiblePossessive) { - if (checkRadioPrefix && TryProcessRadioMessage(source, modMessage, out var outputMessage, out var channel, capitalize: false)) + if (checkRadioPrefix && TryProccessRadioMessage(source, modMessage, out var outputMessage, out var channel, capitalize: false)) SendAudibleEntityEmote(source, outputMessage, range, nameOverride, channel, type, hideLog: hideLog, ignoreActionBlocker: ignoreActionBlocker); else SendAudibleEntityEmote(source, modMessage, range, nameOverride, null, type, hideLog: hideLog, ignoreActionBlocker: ignoreActionBlocker); @@ -912,7 +912,7 @@ protected override void SendAudibleEntityEmote( !TryEmoteChatInput(source, action)) return; - SendInVoiceRange(ChatChannel.Emotes, action, wrappedMessage, source, range, author); + SendInVoiceRange(ChatChannel.Emotes, name, action, wrappedMessage, obfuscated: "", obfuscatedWrappedMessage: "", source, range, author); var ev = new EntityAudiblyEmotedEvent(source, action, channel, type); RaiseLocalEvent(source, ref ev, true); diff --git a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs index 2e284b27d8c..08827efc3aa 100644 --- a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs +++ b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs @@ -62,12 +62,12 @@ private bool CheckRadioCapable(EntityUid uid, WearingHeadsetComponent headset, R && TryComp(headset.Headset, out EncryptionKeyHolderComponent? keys) && keys.Channels.Contains(channel.ID)) { - if (!TryComp(uid, out var hands) || hands.Count < 1 || - TryComp(uid, out var cuffable) && _cuffable.IsCuffed((uid, cuffable))) - { - _popup.PopupEntity(Loc.GetString("headset-cant-reach"), uid, uid, PopupType.SmallCaution); - return false; - } + // if (!TryComp(uid, out var hands) || hands.Count < 1 || + // TryComp(uid, out var cuffable) && _cuffable.IsCuffed((uid, cuffable))) + // { + // _popup.PopupEntity(Loc.GetString("headset-cant-reach"), uid, uid, PopupType.SmallCaution); + // return false; + // } return true; } diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index 364b7017824..bbdcb4f15e9 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -200,7 +200,7 @@ public void SendRadioMessage( // Einstein Engines - Language begin var obfuscated = _language.ObfuscateSpeech(content, language); - var obfuscatedWrapped = WrapRadioMessage(messageSource, channel, name, obfuscated, language); + var obfuscatedWrapped = WrapRadioMessage(messageSource, channel, name, obfuscated, language, emType); var notUdsMsg = new ChatMessage(ChatChannel.Radio, obfuscated, obfuscatedWrapped, NetEntity.Invalid, null); var ev = new RadioReceiveEvent(messageSource, channel, msg, notUdsMsg, language, radioSource); // Einstein Engines - Language end @@ -277,7 +277,7 @@ private string WrapRadioMessage( string name, string message, LanguagePrototype language, - EmoteType emType) + EmoteType? emType) { // TODO: code duplication with ChatSystem.WrapMessage var speech = _chat.GetSpeechVerb(source, message); @@ -292,19 +292,19 @@ private string WrapRadioMessage( //Moved from SendRadioMessage if (emType == EmoteType.Audible) - Loc.GetString("chat-radio-message-audible-emote-wrap", + return Loc.GetString("chat-radio-message-audible-emote-wrap", ("color", channel.Color), ("channel", $"\\[{channel.LocalizedName}\\]"), ("name", name), ("message", message)); else if (emType == EmoteType.AudiblePossessive) - Loc.GetString("chat-radio-message-audible-possessive-emote-wrap", + return Loc.GetString("chat-radio-message-audible-possessive-emote-wrap", ("color", channel.Color), ("channel", $"\\[{channel.LocalizedName}\\]"), ("name", name), ("message", message)); else - Loc.GetString(speech.Bold ? "chat-radio-message-wrap-bold" : "chat-radio-message-wrap", + return Loc.GetString(speech.Bold ? "chat-radio-message-wrap-bold" : "chat-radio-message-wrap", ("color", channel.Color), ("languageColor", languageColor), ("fontType", language.SpeechOverride.FontId ?? speech.FontId), From d96b4a89610391e56e86a15548374bf1d0aecfd1 Mon Sep 17 00:00:00 2001 From: asoggycroissant Date: Mon, 3 Aug 2026 21:35:29 -0500 Subject: [PATCH 3/5] EmoteType.Audible --- Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs | 8 ++++++++ Content.Server/Radio/EntitySystems/RadioSystem.cs | 4 ++-- Content.Server/Radio/RadioEvent.cs | 4 +++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs index 4f9cff4a4c5..d7410214782 100644 --- a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs @@ -13,6 +13,7 @@ using Content.Shared.Power; using Content.Shared.Radio; using Content.Shared.Chat; +using Content.Shared._DV.Chat; //Delta-V using Content.Shared.UserInterface; // Nuclear-14 using Content.Shared._NC.Radio; // Nuclear-14 using Robust.Server.GameObjects; // Nuclear-14 @@ -207,6 +208,13 @@ private void OnReceiveRadio(EntityUid uid, RadioSpeakerComponent component, ref // log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios var message = args.OriginalChatMsg.Message; // The chat system will handle the rest and re-obfuscate if needed. + + // Triad please dont speak emotes thanks + if (args.emType == EmoteType.Audible || args.emType == EmoteType.AudiblePossessive) + {_chat.TrySendInGameICMessage(uid, message, InGameICChatType.Emote, ChatTransmitRange.GhostRangeLimitNoAdminCheck, + nameOverride: name, checkRadioPrefix: false, languageOverride: args.Language); + return;} + _chat.TrySendInGameICMessage(uid, message, component.OutputChatType, ChatTransmitRange.GhostRangeLimitNoAdminCheck, nameOverride: name, checkRadioPrefix: false, languageOverride: args.Language); // Einstein Engines - Languages / Frontier: GhostRangeLimit Date: Wed, 5 Aug 2026 22:13:41 -0500 Subject: [PATCH 4/5] Removed unsued, changed notes --- Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs | 2 +- Content.Server/Radio/EntitySystems/RadioSystem.cs | 3 ++- Resources/Locale/en-US/_DV/headset/headset-component.ftl | 7 ------- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs index d7410214782..d7fcfc1f127 100644 --- a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs @@ -209,7 +209,7 @@ private void OnReceiveRadio(EntityUid uid, RadioSpeakerComponent component, ref // log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios var message = args.OriginalChatMsg.Message; // The chat system will handle the rest and re-obfuscate if needed. - // Triad please dont speak emotes thanks + // Triad - Prevent speaking emotes if (args.emType == EmoteType.Audible || args.emType == EmoteType.AudiblePossessive) {_chat.TrySendInGameICMessage(uid, message, InGameICChatType.Emote, ChatTransmitRange.GhostRangeLimitNoAdminCheck, nameOverride: name, checkRadioPrefix: false, languageOverride: args.Language); diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index 09d305b26ac..8e7a47abdf9 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -290,7 +290,7 @@ private string WrapRadioMessage( ? Loc.GetString("chat-manager-language-prefix", ("language", language.ChatName)) : ""; - // Triad Moved from SendRadioMessage + // Triad - Integrated from SendRadioMessage if (emType == EmoteType.Audible) return Loc.GetString("chat-radio-message-audible-emote-wrap", ("color", channel.Color), @@ -314,6 +314,7 @@ private string WrapRadioMessage( ("name", name), ("message", message), ("language", languageDisplay)); + // Traid - End } // Einstein Engines - Language end diff --git a/Resources/Locale/en-US/_DV/headset/headset-component.ftl b/Resources/Locale/en-US/_DV/headset/headset-component.ftl index 47547287fd1..7237b25eb40 100644 --- a/Resources/Locale/en-US/_DV/headset/headset-component.ftl +++ b/Resources/Locale/en-US/_DV/headset/headset-component.ftl @@ -1,9 +1,2 @@ chat-radio-message-audible-emote-wrap = [color={$color}]{$channel} {$name} {$message}[/color] chat-radio-message-audible-possessive-emote-wrap = [color={$color}]{$channel} {$name}'s {$message}[/color] - -chat-radio-justice = Justice -chat-radio-prison = Prison -chat-radio-admeme-1 = Channel 1 -chat-radio-admeme-2 = Channel 2 -chat-radio-admeme-3 = Channel 3 -chat-radio-rootsong = Rootsong From 8bfa2d5040a062968f82d26f40b48a9c773e4594 Mon Sep 17 00:00:00 2001 From: mnva <218184747+mnva0@users.noreply.github.com> Date: Thu, 6 Aug 2026 08:40:45 -0400 Subject: [PATCH 5/5] I should have caught this typo --- Content.Server/Radio/EntitySystems/RadioSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index 8e7a47abdf9..ae141609e89 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -314,7 +314,7 @@ private string WrapRadioMessage( ("name", name), ("message", message), ("language", languageDisplay)); - // Traid - End + // Triad - End } // Einstein Engines - Language end