diff --git a/Content.Server/Chat/Systems/ChatSystem.Radio.cs b/Content.Server/Chat/Systems/ChatSystem.Radio.cs index f09e6ae2c8..172ac780fd 100644 --- a/Content.Server/Chat/Systems/ChatSystem.Radio.cs +++ b/Content.Server/Chat/Systems/ChatSystem.Radio.cs @@ -33,6 +33,8 @@ public sealed partial class ChatSystem { _keyCodes.Add(proto.KeyCode, proto); } + + } private void ShutdownRadio() @@ -45,6 +47,10 @@ public sealed partial class ChatSystem // TODO: Turn common into a true frequency and support multiple aliases. var isRadioMessage = false; RadioChannelPrototype? channel = null; + + // Check if have headset and grab headset UID for later + var hasHeadset = _inventory.TryGetSlotEntity(source, "ears", out var entityUid) & TryComp(entityUid, out var _headsetComponent); + // First check if this is a message to the base radio frequency if (message.StartsWith(';')) { @@ -54,11 +60,25 @@ public sealed partial class ChatSystem isRadioMessage = true; } - // Check now if the remaining message is a targeted radio message + + // Check now if the remaining message is a radio message if ((message.StartsWith(':') || message.StartsWith('.')) && message.Length >= 2) { + // Redirect to defaultChannel of headsetComp if it goes to "h" channel code after making sure defaultChannel exists + if (message[1] == 'h' + && _headsetComponent != null + && _headsetComponent.defaultChannel != null + && _prototypeManager.TryIndex(_headsetComponent.defaultChannel, out RadioChannelPrototype? protoDefaultChannel)) + { + // Set Channel to headset defaultChannel + channel = protoDefaultChannel; + } + else // otherwise it's a normal, targeted channel keycode + { + _keyCodes.TryGetValue(message[1], out channel); + } + // Strip remaining message prefix. - _keyCodes.TryGetValue(message[1], out channel); message = message[2..].TrimStart(); isRadioMessage = true; } @@ -70,7 +90,8 @@ public sealed partial class ChatSystem if (message.Length <= 1) return (string.Empty, null); - if (channel == null) + // Check for headset before no-such-channel, otherwise you can get two PopupEntities if no headset and no channel + if (hasHeadset & channel == null ) { _popup.PopupEntity(Loc.GetString("chat-manager-no-such-channel"), source, source); channel = null; @@ -79,7 +100,7 @@ public sealed partial class ChatSystem // Re-capitalize message since we removed the prefix. message = SanitizeMessageCapital(message); - var hasHeadset = _inventory.TryGetSlotEntity(source, "ears", out var entityUid) && HasComp(entityUid); + if (!hasHeadset && !HasComp(source)) { diff --git a/Content.Server/Radio/Components/HeadsetComponent.cs b/Content.Server/Radio/Components/HeadsetComponent.cs index 3986ee8bc4..caf09fe875 100644 --- a/Content.Server/Radio/Components/HeadsetComponent.cs +++ b/Content.Server/Radio/Components/HeadsetComponent.cs @@ -2,6 +2,7 @@ using Content.Server.Radio.EntitySystems; using Content.Shared.Inventory; using Content.Shared.Radio; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Radio.Components; @@ -15,6 +16,15 @@ public sealed class HeadsetComponent : Component [DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] public readonly HashSet Channels = new() { "Common" }; + // Maybe make the defaultChannel an actual channel type some day, and use that for parsing messages + // [DataField("defaultChannel", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] + // public readonly HashSet defaultChannel = new(); + + + + [DataField("defaultChannel", customTypeSerializer: typeof(PrototypeIdSerializer))] + public readonly string? defaultChannel; + [DataField("enabled")] public bool Enabled = true; diff --git a/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml b/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml index 025f06ae57..44448d298f 100644 --- a/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml +++ b/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml @@ -23,6 +23,7 @@ channels: - Common - Supply + defaultChannel: Supply - type: Sprite sprite: Clothing/Ears/Headsets/cargo.rsi - type: Clothing @@ -39,6 +40,7 @@ - Command - Common - Supply + defaultChannel: Supply - type: Sprite sprite: Clothing/Ears/Headsets/cargo.rsi - type: Clothing @@ -61,6 +63,7 @@ - Security - Service - Supply + defaultChannel: CentCom - type: Sprite sprite: Clothing/Ears/Headsets/centcom.rsi - type: Clothing @@ -82,6 +85,7 @@ - Security - Service - Supply + defaultChannel: Command - type: Sprite sprite: Clothing/Ears/Headsets/command.rsi - type: Clothing @@ -97,6 +101,7 @@ channels: - Common - Engineering + defaultChannel: Engineering - type: Sprite sprite: Clothing/Ears/Headsets/engineering.rsi - type: Clothing @@ -113,6 +118,7 @@ - Command - Common - Engineering + defaultChannel: Engineering - type: Sprite sprite: Clothing/Ears/Headsets/engineering.rsi - type: Clothing @@ -128,6 +134,7 @@ channels: - Common - Medical + defaultChannel: Medical - type: Sprite sprite: Clothing/Ears/Headsets/medical.rsi - type: Clothing @@ -144,6 +151,7 @@ - Common - Medical - Science + defaultChannel: Science - type: Sprite sprite: Clothing/Ears/Headsets/medicalscience.rsi - type: Clothing @@ -159,6 +167,7 @@ channels: - Common - Supply + defaultChannel: Supply - type: Sprite sprite: Clothing/Ears/Headsets/mining.rsi - type: Clothing @@ -174,6 +183,7 @@ channels: - Common - Science + defaultChannel: Science - type: Sprite sprite: Clothing/Ears/Headsets/robotics.rsi - type: Clothing @@ -189,6 +199,7 @@ channels: - Common - Science + defaultChannel: Science - type: Sprite sprite: Clothing/Ears/Headsets/science.rsi - type: Clothing @@ -205,6 +216,7 @@ - Command - Common - Science + defaultChannel: Science - type: Sprite sprite: Clothing/Ears/Headsets/science.rsi - type: Clothing @@ -220,6 +232,7 @@ channels: - Common - Security + defaultChannel: Security - type: Sprite sprite: Clothing/Ears/Headsets/security.rsi - type: Clothing @@ -235,6 +248,7 @@ channels: - Common - Service + defaultChannel: Service - type: Sprite sprite: Clothing/Ears/Headsets/service.rsi - type: Clothing @@ -249,5 +263,6 @@ - type: Headset channels: - Common + defaultChannel: Common - type: Sprite sprite: Clothing/Ears/Headsets/base.rsi diff --git a/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml b/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml index cb2033620c..52b386733d 100644 --- a/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml +++ b/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml @@ -29,6 +29,7 @@ - Security - Service - Supply + defaultChannel: CentCom - type: Sprite sprite: Clothing/Ears/Headsets/centcom.rsi - type: Clothing @@ -49,6 +50,7 @@ - Security - Service - Supply + defaultChannel: Command - type: Sprite sprite: Clothing/Ears/Headsets/command.rsi - type: Clothing @@ -64,6 +66,7 @@ - Command - Common - Medical + defaultChannel: Medical - type: Sprite sprite: Clothing/Ears/Headsets/medical.rsi - type: Clothing @@ -79,6 +82,7 @@ - Command - Common - Security + defaultChannel: Security - type: Sprite sprite: Clothing/Ears/Headsets/security.rsi - type: Clothing @@ -94,6 +98,7 @@ - Command - Common - Engineering + defaultChannel: Engineering - type: Sprite sprite: Clothing/Ears/Headsets/engineering.rsi - type: Clothing @@ -109,6 +114,7 @@ - Command - Common - Science + defaultChannel: Science - type: Sprite sprite: Clothing/Ears/Headsets/science.rsi - type: Clothing @@ -124,6 +130,7 @@ - Command - Common - Supply + defaultChannel: Supply - type: Sprite sprite: Clothing/Ears/Headsets/cargo.rsi - type: Clothing @@ -138,6 +145,7 @@ - type: Headset channels: - Syndicate + defaultChannel: Syndicate - type: Sprite sprite: Clothing/Ears/Headsets/syndicate.rsi - type: Clothing