Add department-specific radio channels (#9061)
* Add department-specific radio channels
This commit adds working department-specific radio channels, while
minimizing damage to the current codebase. It is expected that a future
refactor will clean this up a bit.
ChatSystem now has a RadioPrefix() method that recognizes
department-specific channels (e.g. ":e" and ":m") in addition to the
global channel (";"). It strips the prefix from the message and assigns
messages an integer representing the destination channel, if any.
IListen and IRadio now accept optional 'channel' arguments with this
channel in mind.
The ugly is that the integer channel number is hard-coded and also shows
up in chat.
Comms are not modeled at this time. You cannot break comms (yet).
All headsets have channels soldered into them. You cannot change
encryption keys to hop on new channels. Steal a headset instead.
* Remove debugging print
* Convert to prototypes
* Use prototype names in headset prototype
* Adjust list style
* Document prototype fields
* cringe
* some cleanup
* colours
* Remove alphas at least
* cc
Co-authored-by: Kevin Zheng <kevinz5000@gmail.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
using Content.Shared.Actions.ActionTypes;
|
using Content.Shared.Actions.ActionTypes;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.EUI;
|
using Content.Server.EUI;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Eui;
|
using Content.Shared.Eui;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.Advertisements;
|
using Content.Server.Advertisements;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.VendingMachines;
|
using Content.Server.VendingMachines;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.Administration;
|
using Content.Server.Chat.Systems;
|
||||||
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
|
|||||||
88
Content.Server/Chat/Systems/ChatSystem.Radio.cs
Normal file
88
Content.Server/Chat/Systems/ChatSystem.Radio.cs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Content.Server.Headset;
|
||||||
|
using Content.Shared.Radio;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Server.Chat.Systems;
|
||||||
|
|
||||||
|
public sealed partial class ChatSystem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Cache of the keycodes for faster lookup.
|
||||||
|
/// </summary>
|
||||||
|
private Dictionary<char, RadioChannelPrototype> _keyCodes = new();
|
||||||
|
|
||||||
|
private void InitializeRadio()
|
||||||
|
{
|
||||||
|
_prototypeManager.PrototypesReloaded += OnPrototypeReload;
|
||||||
|
CacheRadios();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPrototypeReload(PrototypesReloadedEventArgs obj)
|
||||||
|
{
|
||||||
|
CacheRadios();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CacheRadios()
|
||||||
|
{
|
||||||
|
_keyCodes.Clear();
|
||||||
|
|
||||||
|
foreach (var proto in _prototypeManager.EnumeratePrototypes<RadioChannelPrototype>())
|
||||||
|
{
|
||||||
|
_keyCodes.Add(proto.KeyCode, proto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShutdownRadio()
|
||||||
|
{
|
||||||
|
_prototypeManager.PrototypesReloaded -= OnPrototypeReload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private (string, RadioChannelPrototype?) GetRadioPrefix(EntityUid source, string message)
|
||||||
|
{
|
||||||
|
// TODO: Turn common into a true frequency and support multiple aliases.
|
||||||
|
var channelMessage = message.StartsWith(':') || message.StartsWith('.');
|
||||||
|
var radioMessage = message.StartsWith(';') || channelMessage;
|
||||||
|
if (!radioMessage) return (message, null);
|
||||||
|
|
||||||
|
// Special case for empty messages
|
||||||
|
if (message.Length <= 1)
|
||||||
|
return (string.Empty, null);
|
||||||
|
|
||||||
|
// Look for a prefix indicating a destination radio channel.
|
||||||
|
RadioChannelPrototype? chan;
|
||||||
|
if (channelMessage && message.Length >= 2)
|
||||||
|
{
|
||||||
|
_keyCodes.TryGetValue(message[1], out chan);
|
||||||
|
|
||||||
|
if (chan == null)
|
||||||
|
{
|
||||||
|
_popup.PopupEntity(Loc.GetString("chat-manager-no-such-channel"), source, Filter.Entities(source));
|
||||||
|
chan = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip message prefix.
|
||||||
|
message = message[2..].TrimStart();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Remove semicolon
|
||||||
|
message = message[1..].TrimStart();
|
||||||
|
chan = _prototypeManager.Index<RadioChannelPrototype>("Common");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_inventory.TryGetSlotEntity(source, "ears", out var entityUid) &&
|
||||||
|
TryComp(entityUid, out HeadsetComponent? headset))
|
||||||
|
{
|
||||||
|
headset.RadioRequested = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_popup.PopupEntity(Loc.GetString("chat-manager-no-headset-on-message"), source, Filter.Entities(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (message, chan);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ using Content.Server.Administration.Managers;
|
|||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Ghost.Components;
|
using Content.Server.Ghost.Components;
|
||||||
using Content.Server.Headset;
|
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Radio.EntitySystems;
|
using Content.Server.Radio.EntitySystems;
|
||||||
@@ -23,22 +22,24 @@ using Robust.Shared.Console;
|
|||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Players;
|
using Robust.Shared.Players;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Chat;
|
namespace Content.Server.Chat.Systems;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ChatSystem is responsible for in-simulation chat handling, such as whispering, speaking, emoting, etc.
|
/// ChatSystem is responsible for in-simulation chat handling, such as whispering, speaking, emoting, etc.
|
||||||
/// ChatSystem depends on ChatManager to actually send the messages.
|
/// ChatSystem depends on ChatManager to actually send the messages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class ChatSystem : SharedChatSystem
|
public sealed partial class ChatSystem : SharedChatSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||||
[Dependency] private readonly IChatSanitizationManager _sanitizer = default!;
|
[Dependency] private readonly IChatSanitizationManager _sanitizer = default!;
|
||||||
[Dependency] private readonly IAdminManager _adminManager = default!;
|
[Dependency] private readonly IAdminManager _adminManager = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
|
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
|
||||||
@@ -56,6 +57,7 @@ public sealed class ChatSystem : SharedChatSystem
|
|||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
|
InitializeRadio();
|
||||||
_configurationManager.OnValueChanged(CCVars.LoocEnabled, OnLoocEnabledChanged, true);
|
_configurationManager.OnValueChanged(CCVars.LoocEnabled, OnLoocEnabledChanged, true);
|
||||||
|
|
||||||
SubscribeLocalEvent<GameRunLevelChangedEvent>(OnGameChange);
|
SubscribeLocalEvent<GameRunLevelChangedEvent>(OnGameChange);
|
||||||
@@ -63,6 +65,7 @@ public sealed class ChatSystem : SharedChatSystem
|
|||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
{
|
{
|
||||||
|
ShutdownRadio();
|
||||||
_configurationManager.UnsubValueChanged(CCVars.LoocEnabled, OnLoocEnabledChanged);
|
_configurationManager.UnsubValueChanged(CCVars.LoocEnabled, OnLoocEnabledChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,14 +229,18 @@ public sealed class ChatSystem : SharedChatSystem
|
|||||||
if (!_actionBlocker.CanSpeak(source)) return;
|
if (!_actionBlocker.CanSpeak(source)) return;
|
||||||
message = TransformSpeech(source, message);
|
message = TransformSpeech(source, message);
|
||||||
|
|
||||||
_listener.PingListeners(source, message);
|
(message, var channel) = GetRadioPrefix(source, message);
|
||||||
|
|
||||||
|
if (channel != null)
|
||||||
|
_listener.PingListeners(source, message, channel);
|
||||||
|
|
||||||
var messageWrap = Loc.GetString("chat-manager-entity-say-wrap-message",
|
var messageWrap = Loc.GetString("chat-manager-entity-say-wrap-message",
|
||||||
("entityName", Name(source)));
|
("entityName", Name(source)));
|
||||||
|
|
||||||
SendInVoiceRange(ChatChannel.Local, message, messageWrap, source, hideChat);
|
SendInVoiceRange(ChatChannel.Local, message, messageWrap, source, hideChat);
|
||||||
|
|
||||||
var ev = new EntitySpokeEvent(message);
|
var ev = new EntitySpokeEvent(message);
|
||||||
RaiseLocalEvent(source, ev, false);
|
RaiseLocalEvent(source, ev);
|
||||||
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Say from {ToPrettyString(source):user}: {message}");
|
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Say from {ToPrettyString(source):user}: {message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +249,6 @@ public sealed class ChatSystem : SharedChatSystem
|
|||||||
if (!_actionBlocker.CanSpeak(source)) return;
|
if (!_actionBlocker.CanSpeak(source)) return;
|
||||||
|
|
||||||
message = TransformSpeech(source, message);
|
message = TransformSpeech(source, message);
|
||||||
_listener.PingListeners(source, message);
|
|
||||||
var obfuscatedMessage = ObfuscateMessageReadability(message, 0.2f);
|
var obfuscatedMessage = ObfuscateMessageReadability(message, 0.2f);
|
||||||
|
|
||||||
var transformSource = Transform(source);
|
var transformSource = Transform(source);
|
||||||
@@ -410,34 +416,8 @@ public sealed class ChatSystem : SharedChatSystem
|
|||||||
|
|
||||||
private string SanitizeMessageCapital(EntityUid source, string message)
|
private string SanitizeMessageCapital(EntityUid source, string message)
|
||||||
{
|
{
|
||||||
if (message.StartsWith(';'))
|
|
||||||
{
|
|
||||||
// Special case for ";" messages
|
|
||||||
if (message.Length == 1)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
// Remove semicolon
|
|
||||||
message = message.Substring(1).TrimStart();
|
|
||||||
|
|
||||||
// Capitalize first letter
|
// Capitalize first letter
|
||||||
message = message[0].ToString().ToUpper() + message.Remove(0, 1);
|
message = message[0].ToString().ToUpper() + message.Remove(0, 1);
|
||||||
|
|
||||||
if (_inventory.TryGetSlotEntity(source, "ears", out var entityUid) &&
|
|
||||||
TryComp(entityUid, out HeadsetComponent? headset))
|
|
||||||
{
|
|
||||||
headset.RadioRequested = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_popup.PopupEntity(Loc.GetString("chat-manager-no-headset-on-message"), source, Filter.Entities(source));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Capitalize first letter
|
|
||||||
message = message[0].ToString().ToUpper() + message.Remove(0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2,6 +2,7 @@ using System.Globalization;
|
|||||||
using Content.Server.Access.Systems;
|
using Content.Server.Access.Systems;
|
||||||
using Content.Server.AlertLevel;
|
using Content.Server.AlertLevel;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.RoundEnd;
|
using Content.Server.RoundEnd;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Shared.Disease.Components;
|
|||||||
using Content.Server.Disease.Components;
|
using Content.Server.Disease.Components;
|
||||||
using Content.Server.Clothing.Components;
|
using Content.Server.Clothing.Components;
|
||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Shared.MobState.Components;
|
using Content.Shared.MobState.Components;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Content.Server.Administration.Logs;
|
|||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Database;
|
using Content.Server.Database;
|
||||||
using Content.Server.Ghost;
|
using Content.Server.Ghost;
|
||||||
using Content.Server.Maps;
|
using Content.Server.Maps;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using Content.Server.Radio.Components;
|
using Content.Server.Radio.Components;
|
||||||
using Content.Shared.Chat;
|
using Content.Shared.Chat;
|
||||||
|
using Content.Shared.Radio;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||||
|
|
||||||
namespace Content.Server.Ghost.Components
|
namespace Content.Server.Ghost.Components
|
||||||
{
|
{
|
||||||
@@ -12,27 +14,27 @@ namespace Content.Server.Ghost.Components
|
|||||||
[Dependency] private readonly IServerNetManager _netManager = default!;
|
[Dependency] private readonly IServerNetManager _netManager = default!;
|
||||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||||
|
|
||||||
[DataField("channels")]
|
[DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<RadioChannelPrototype>))]
|
||||||
private List<int> _channels = new(){1459};
|
private HashSet<string> _channels = new();
|
||||||
|
|
||||||
public IReadOnlyList<int> Channels => _channels;
|
public void Receive(string message, RadioChannelPrototype channel, EntityUid speaker)
|
||||||
|
|
||||||
public void Receive(string message, int channel, EntityUid speaker)
|
|
||||||
{
|
{
|
||||||
if (!_entMan.TryGetComponent(Owner, out ActorComponent? actor))
|
if (!_channels.Contains(channel.ID) || !_entMan.TryGetComponent(Owner, out ActorComponent? actor))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var playerChannel = actor.PlayerSession.ConnectedClient;
|
var playerChannel = actor.PlayerSession.ConnectedClient;
|
||||||
|
|
||||||
var msg = new MsgChatMessage();
|
var msg = new MsgChatMessage
|
||||||
|
{
|
||||||
msg.Channel = ChatChannel.Radio;
|
Channel = ChatChannel.Radio,
|
||||||
msg.Message = message;
|
Message = message,
|
||||||
//Square brackets are added here to avoid issues with escaping
|
//Square brackets are added here to avoid issues with escaping
|
||||||
msg.MessageWrap = Loc.GetString("chat-radio-message-wrap", ("channel", $"\\[{channel}\\]"), ("name", _entMan.GetComponent<MetaDataComponent>(speaker).EntityName));
|
MessageWrap = Loc.GetString("chat-radio-message-wrap", ("channel", $"\\[{channel.Name}\\]"), ("name", _entMan.GetComponent<MetaDataComponent>(speaker).EntityName))
|
||||||
|
};
|
||||||
|
|
||||||
_netManager.ServerSendMessage(msg, playerChannel);
|
_netManager.ServerSendMessage(msg, playerChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Broadcast(string message, EntityUid speaker) { }
|
public void Broadcast(string message, EntityUid speaker, RadioChannelPrototype channel) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
using Content.Server.Radio.Components;
|
using Content.Server.Radio.Components;
|
||||||
using Content.Server.Radio.EntitySystems;
|
using Content.Server.Radio.EntitySystems;
|
||||||
using Content.Shared.Chat;
|
using Content.Shared.Chat;
|
||||||
|
using Content.Shared.Radio;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||||
|
|
||||||
namespace Content.Server.Headset
|
namespace Content.Server.Headset
|
||||||
{
|
{
|
||||||
@@ -19,19 +23,16 @@ namespace Content.Server.Headset
|
|||||||
|
|
||||||
private RadioSystem _radioSystem = default!;
|
private RadioSystem _radioSystem = default!;
|
||||||
|
|
||||||
[DataField("channels")]
|
[DataField("channels", customTypeSerializer:typeof(PrototypeIdHashSetSerializer<RadioChannelPrototype>))]
|
||||||
private List<int> _channels = new(){1459};
|
public HashSet<string> Channels = new()
|
||||||
|
{
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
"Common"
|
||||||
[DataField("broadcastChannel")]
|
};
|
||||||
public int BroadcastFrequency { get; set; } = 1459;
|
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
[DataField("listenRange")]
|
[DataField("listenRange")]
|
||||||
public int ListenRange { get; private set; }
|
public int ListenRange { get; private set; }
|
||||||
|
|
||||||
public IReadOnlyList<int> Channels => _channels;
|
|
||||||
|
|
||||||
public bool RadioRequested { get; set; }
|
public bool RadioRequested { get; set; }
|
||||||
|
|
||||||
protected override void Initialize()
|
protected override void Initialize()
|
||||||
@@ -41,38 +42,40 @@ namespace Content.Server.Headset
|
|||||||
_radioSystem = EntitySystem.Get<RadioSystem>();
|
_radioSystem = EntitySystem.Get<RadioSystem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanListen(string message, EntityUid source)
|
public bool CanListen(string message, EntityUid source, RadioChannelPrototype prototype)
|
||||||
{
|
{
|
||||||
return RadioRequested;
|
return Channels.Contains(prototype.ID) && RadioRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Receive(string message, int channel, EntityUid source)
|
public void Receive(string message, RadioChannelPrototype channel, EntityUid source)
|
||||||
{
|
{
|
||||||
if (Owner.TryGetContainer(out var container))
|
if (!Channels.Contains(channel.ID) || !Owner.TryGetContainer(out var container)) return;
|
||||||
{
|
|
||||||
if (!_entMan.TryGetComponent(container.Owner, out ActorComponent? actor))
|
if (!_entMan.TryGetComponent(container.Owner, out ActorComponent? actor)) return;
|
||||||
return;
|
|
||||||
|
|
||||||
var playerChannel = actor.PlayerSession.ConnectedClient;
|
var playerChannel = actor.PlayerSession.ConnectedClient;
|
||||||
|
|
||||||
var msg = new MsgChatMessage();
|
var msg = new MsgChatMessage
|
||||||
|
{
|
||||||
msg.Channel = ChatChannel.Radio;
|
Channel = ChatChannel.Radio,
|
||||||
msg.Message = message;
|
Message = message,
|
||||||
//Square brackets are added here to avoid issues with escaping
|
//Square brackets are added here to avoid issues with escaping
|
||||||
msg.MessageWrap = Loc.GetString("chat-radio-message-wrap", ("channel", $"\\[{channel}\\]"), ("name", _entMan.GetComponent<MetaDataComponent>(source).EntityName));
|
MessageWrap = Loc.GetString("chat-radio-message-wrap", ("color", channel.Color), ("channel", $"\\[{channel.Name}\\]"), ("name", _entMan.GetComponent<MetaDataComponent>(source).EntityName))
|
||||||
|
};
|
||||||
|
|
||||||
_netManager.ServerSendMessage(msg, playerChannel);
|
_netManager.ServerSendMessage(msg, playerChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Listen(string message, EntityUid speaker, RadioChannelPrototype channel)
|
||||||
|
{
|
||||||
|
Broadcast(message, speaker, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Listen(string message, EntityUid speaker)
|
public void Broadcast(string message, EntityUid speaker, RadioChannelPrototype channel)
|
||||||
{
|
{
|
||||||
Broadcast(message, speaker);
|
if (!Channels.Contains(channel.ID)) return;
|
||||||
}
|
|
||||||
|
|
||||||
public void Broadcast(string message, EntityUid speaker)
|
_radioSystem.SpreadMessage(this, speaker, message, channel);
|
||||||
{
|
|
||||||
_radioSystem.SpreadMessage(this, speaker, message, BroadcastFrequency);
|
|
||||||
RadioRequested = false;
|
RadioRequested = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
|
using Content.Shared.Radio;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Server.Headset
|
namespace Content.Server.Headset
|
||||||
{
|
{
|
||||||
public sealed class HeadsetSystem : EntitySystem
|
public sealed class HeadsetSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -14,8 +18,21 @@ namespace Content.Server.Headset
|
|||||||
{
|
{
|
||||||
if (!args.IsInDetailsRange)
|
if (!args.IsInDetailsRange)
|
||||||
return;
|
return;
|
||||||
args.PushMarkup(Loc.GetString("examine-radio-frequency", ("frequency", component.BroadcastFrequency)));
|
// args.PushMarkup(Loc.GetString("examine-radio-frequency", ("frequency", component.BroadcastFrequency)));
|
||||||
args.PushMarkup(Loc.GetString("examine-headset"));
|
args.PushMarkup(Loc.GetString("examine-headset"));
|
||||||
|
|
||||||
|
foreach (var id in component.Channels)
|
||||||
|
{
|
||||||
|
if (id == "Common") continue;
|
||||||
|
|
||||||
|
var proto = _protoManager.Index<RadioChannelPrototype>(id);
|
||||||
|
args.PushMarkup(Loc.GetString("examine-headset-channel",
|
||||||
|
("color", proto.Color),
|
||||||
|
("key", proto.KeyCode),
|
||||||
|
("id", proto.Name),
|
||||||
|
("freq", proto.Frequency)));
|
||||||
|
}
|
||||||
|
|
||||||
args.PushMarkup(Loc.GetString("examine-headset-chat-prefix", ("prefix", ";")));
|
args.PushMarkup(Loc.GetString("examine-headset-chat-prefix", ("prefix", ";")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Communications;
|
using Content.Server.Communications;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Server.AlertLevel;
|
using Content.Server.AlertLevel;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Coordinates.Helpers;
|
using Content.Server.Coordinates.Helpers;
|
||||||
using Content.Server.Explosion.EntitySystems;
|
using Content.Server.Explosion.EntitySystems;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Radio.EntitySystems;
|
using Content.Server.Radio.EntitySystems;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Radio;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||||
|
|
||||||
namespace Content.Server.Radio.Components
|
namespace Content.Server.Radio.Components
|
||||||
{
|
{
|
||||||
@@ -18,12 +23,16 @@ namespace Content.Server.Radio.Components
|
|||||||
private RadioSystem _radioSystem = default!;
|
private RadioSystem _radioSystem = default!;
|
||||||
|
|
||||||
private bool _radioOn;
|
private bool _radioOn;
|
||||||
[DataField("channels")]
|
[DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<RadioChannelPrototype>))]
|
||||||
private List<int> _channels = new(){1459};
|
private HashSet<string> _channels = new();
|
||||||
|
|
||||||
|
public int BroadcastFrequency => IoCManager.Resolve<IPrototypeManager>()
|
||||||
|
.Index<RadioChannelPrototype>(BroadcastChannel).Frequency;
|
||||||
|
|
||||||
|
// TODO: Assert in componentinit that channels has this.
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
[DataField("broadcastChannel")]
|
[DataField("broadcastChannel", customTypeSerializer: typeof(PrototypeIdSerializer<RadioChannelPrototype>))]
|
||||||
public int BroadcastFrequency { get; set; } = 1459;
|
public string BroadcastChannel { get; set; } = "Common";
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("listenRange")] public int ListenRange { get; private set; } = 7;
|
[ViewVariables(VVAccess.ReadWrite)] [DataField("listenRange")] public int ListenRange { get; private set; } = 7;
|
||||||
|
|
||||||
@@ -38,8 +47,6 @@ namespace Content.Server.Radio.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ViewVariables] public IReadOnlyList<int> Channels => _channels;
|
|
||||||
|
|
||||||
protected override void Initialize()
|
protected override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -66,28 +73,30 @@ namespace Content.Server.Radio.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanListen(string message, EntityUid source)
|
public bool CanListen(string message, EntityUid source, RadioChannelPrototype prototype)
|
||||||
{
|
{
|
||||||
|
if (!_channels.Contains(prototype.ID)) return false;
|
||||||
|
|
||||||
return RadioOn &&
|
return RadioOn &&
|
||||||
EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(Owner, source, range: ListenRange);
|
EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(Owner, source, range: ListenRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Receive(string message, int channel, EntityUid speaker)
|
public void Receive(string message, RadioChannelPrototype channel, EntityUid speaker)
|
||||||
{
|
{
|
||||||
if (RadioOn)
|
if (_channels.Contains(channel.ID) && RadioOn)
|
||||||
{
|
{
|
||||||
Speak(message);
|
Speak(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Listen(string message, EntityUid speaker)
|
public void Listen(string message, EntityUid speaker, RadioChannelPrototype channel)
|
||||||
{
|
{
|
||||||
Broadcast(message, speaker);
|
Broadcast(message, speaker, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Broadcast(string message, EntityUid speaker)
|
public void Broadcast(string message, EntityUid speaker, RadioChannelPrototype channel)
|
||||||
{
|
{
|
||||||
_radioSystem.SpreadMessage(this, speaker, message, BroadcastFrequency);
|
_radioSystem.SpreadMessage(this, speaker, message, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Content.Shared.Radio;
|
||||||
|
|
||||||
namespace Content.Server.Radio.Components
|
namespace Content.Server.Radio.Components
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -8,8 +10,8 @@ namespace Content.Server.Radio.Components
|
|||||||
{
|
{
|
||||||
int ListenRange { get; }
|
int ListenRange { get; }
|
||||||
|
|
||||||
bool CanListen(string message, EntityUid source);
|
bool CanListen(string message, EntityUid source, RadioChannelPrototype channelPrototype);
|
||||||
|
|
||||||
void Listen(string message, EntityUid speaker);
|
void Listen(string message, EntityUid speaker, RadioChannelPrototype channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
using Content.Shared.Radio;
|
||||||
|
|
||||||
namespace Content.Server.Radio.Components
|
namespace Content.Server.Radio.Components
|
||||||
{
|
{
|
||||||
public interface IRadio : IComponent
|
public interface IRadio : IComponent
|
||||||
{
|
{
|
||||||
IReadOnlyList<int> Channels { get; }
|
void Receive(string message, RadioChannelPrototype channel, EntityUid speaker);
|
||||||
|
|
||||||
void Receive(string message, int channel, EntityUid speaker);
|
void Broadcast(string message, EntityUid speaker, RadioChannelPrototype channel);
|
||||||
|
|
||||||
void Broadcast(string message, EntityUid speaker);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Radio.Components;
|
using Content.Server.Radio.Components;
|
||||||
|
using Content.Shared.Radio;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
namespace Content.Server.Radio.EntitySystems
|
namespace Content.Server.Radio.EntitySystems
|
||||||
@@ -6,14 +7,15 @@ namespace Content.Server.Radio.EntitySystems
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public sealed class ListeningSystem : EntitySystem
|
public sealed class ListeningSystem : EntitySystem
|
||||||
{
|
{
|
||||||
public void PingListeners(EntityUid source, string message)
|
public void PingListeners(EntityUid source, string message, RadioChannelPrototype channel)
|
||||||
{
|
{
|
||||||
foreach (var listener in EntityManager.EntityQuery<IListen>(true))
|
foreach (var listener in EntityManager.EntityQuery<IListen>(true))
|
||||||
{
|
{
|
||||||
|
// TODO: Listening code is hella stinky so please refactor it someone.
|
||||||
// TODO: Map Position distance
|
// TODO: Map Position distance
|
||||||
if (listener.CanListen(message, source))
|
if (listener.CanListen(message, source, channel))
|
||||||
{
|
{
|
||||||
listener.Listen(message, source);
|
listener.Listen(message, source, channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Server.Radio.Components;
|
using Content.Server.Radio.Components;
|
||||||
|
using Content.Shared.Radio;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
namespace Content.Server.Radio.EntitySystems
|
namespace Content.Server.Radio.EntitySystems
|
||||||
@@ -23,20 +24,17 @@ namespace Content.Server.Radio.EntitySystems
|
|||||||
args.PushMarkup(Loc.GetString("handheld-radio-component-on-examine",("frequency", component.BroadcastFrequency)));
|
args.PushMarkup(Loc.GetString("handheld-radio-component-on-examine",("frequency", component.BroadcastFrequency)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SpreadMessage(IRadio source, EntityUid speaker, string message, int channel)
|
public void SpreadMessage(IRadio source, EntityUid speaker, string message, RadioChannelPrototype channel)
|
||||||
{
|
{
|
||||||
if (_messages.Contains(message)) return;
|
if (_messages.Contains(message)) return;
|
||||||
|
|
||||||
_messages.Add(message);
|
_messages.Add(message);
|
||||||
|
|
||||||
foreach (var radio in EntityManager.EntityQuery<IRadio>(true))
|
foreach (var radio in EntityManager.EntityQuery<IRadio>(true))
|
||||||
{
|
|
||||||
if (radio.Channels.Contains(channel))
|
|
||||||
{
|
{
|
||||||
//TODO: once voice identity gets added, pass into receiver via source.GetSpeakerVoice()
|
//TODO: once voice identity gets added, pass into receiver via source.GetSpeakerVoice()
|
||||||
radio.Receive(message, channel, speaker);
|
radio.Receive(message, channel, speaker);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_messages.Remove(message);
|
_messages.Remove(message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
|
|
||||||
namespace Content.Server.Roles
|
namespace Content.Server.Roles
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System.Threading;
|
|||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using Robust.Shared.Random;
|
|||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
|
|
||||||
namespace Content.Server.Salvage
|
namespace Content.Server.Salvage
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
|
|
||||||
namespace Content.Server.Speech
|
namespace Content.Server.Speech
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Shared.Speech;
|
using Content.Shared.Speech;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Station.Components;
|
using Content.Server.Station.Components;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Disease.Components;
|
using Content.Server.Disease.Components;
|
||||||
using Content.Server.Disease;
|
using Content.Server.Disease;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Ghost.Roles.Components;
|
using Content.Server.Ghost.Roles.Components;
|
||||||
using Content.Server.Mind.Commands;
|
using Content.Server.Mind.Commands;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Content.Server.Administration.Logs;
|
|||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Station.Components;
|
using Content.Server.Station.Components;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
using Content.Shared.MobState.Components;
|
using Content.Shared.MobState.Components;
|
||||||
using Content.Shared.Sound;
|
using Content.Shared.Sound;
|
||||||
|
|||||||
26
Content.Shared/Radio/RadioChannelPrototype.cs
Normal file
26
Content.Shared/Radio/RadioChannelPrototype.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Radio
|
||||||
|
{
|
||||||
|
[Prototype("radioChannel")]
|
||||||
|
public sealed class RadioChannelPrototype : IPrototype
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Human-readable name for the channel.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables] [DataField("name")] public string Name { get; private set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Single-character prefix to determine what channel a message should be sent to.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables] [DataField("keycode")] public char KeyCode { get; private set; } = '\0';
|
||||||
|
|
||||||
|
[ViewVariables] [DataField("frequency")] public int Frequency { get; private set; } = 0;
|
||||||
|
|
||||||
|
[ViewVariables] [DataField("color")] public Color Color { get; private set; } = Color.Lime;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
[IdDataFieldAttribute]
|
||||||
|
public string ID { get; } = default!;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ chat-manager-admin-ooc-chat-enabled-message = Admin OOC chat has been enabled.
|
|||||||
chat-manager-admin-ooc-chat-disabled-message = Admin OOC chat has been disabled.
|
chat-manager-admin-ooc-chat-disabled-message = Admin OOC chat has been disabled.
|
||||||
chat-manager-max-message-length-exceeded-message = Your message exceeded {$limit} character limit
|
chat-manager-max-message-length-exceeded-message = Your message exceeded {$limit} character limit
|
||||||
chat-manager-no-headset-on-message = You don't have a headset on!
|
chat-manager-no-headset-on-message = You don't have a headset on!
|
||||||
|
chat-manager-no-such-channel = There is no such channel!
|
||||||
chat-manager-whisper-headset-on-message = You can't whisper on the radio!
|
chat-manager-whisper-headset-on-message = You can't whisper on the radio!
|
||||||
chat-manager-server-wrap-message = SERVER: {"{0}"}
|
chat-manager-server-wrap-message = SERVER: {"{0}"}
|
||||||
chat-manager-sender-announcement-wrap-message = {$sender} Announcement:
|
chat-manager-sender-announcement-wrap-message = {$sender} Announcement:
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# Chat window radio wrap (prefix and postfix)
|
# Chat window radio wrap (prefix and postfix)
|
||||||
chat-radio-message-wrap = {$channel} {$name} says, "{"{"}0{"}"}"
|
chat-radio-message-wrap = [color={$color}]{$channel} {$name} says, "{"{"}0{"}"}"[/color]
|
||||||
|
|
||||||
examine-radio-frequency = It's set to broadcast over the {$frequency} frequency.
|
examine-radio-frequency = It's set to broadcast over the {$frequency} frequency.
|
||||||
|
|
||||||
examine-headset = A small screen on the headset displays the following available frequencies:
|
examine-headset = A small screen on the headset displays the following available frequencies:
|
||||||
|
examine-headset-channel = [color={$color}]:{$key} for {$id} ({$freq})[/color]
|
||||||
|
|
||||||
examine-headset-chat-prefix = Use {$prefix} for the currently tuned frequency.
|
examine-headset-chat-prefix = Use {$prefix} for the currently tuned frequency.
|
||||||
|
|||||||
@@ -19,6 +19,10 @@
|
|||||||
name: cargo headset
|
name: cargo headset
|
||||||
description: A headset used by the quartermaster and his slaves.
|
description: A headset used by the quartermaster and his slaves.
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Supply
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/cargo.rsi
|
sprite: Clothing/Ears/Headsets/cargo.rsi
|
||||||
|
|
||||||
@@ -28,6 +32,17 @@
|
|||||||
name: centcomm headset
|
name: centcomm headset
|
||||||
description: A headset used by the upper echelons of Nanotrasen.
|
description: A headset used by the upper echelons of Nanotrasen.
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Command
|
||||||
|
- CentCom
|
||||||
|
- Engineering
|
||||||
|
- Medical
|
||||||
|
- Science
|
||||||
|
- Security
|
||||||
|
- Service
|
||||||
|
- Supply
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/centcom.rsi
|
sprite: Clothing/Ears/Headsets/centcom.rsi
|
||||||
|
|
||||||
@@ -37,6 +52,16 @@
|
|||||||
name: command headset
|
name: command headset
|
||||||
description: A headset with a commanding channel.
|
description: A headset with a commanding channel.
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Command
|
||||||
|
- Engineering
|
||||||
|
- Medical
|
||||||
|
- Science
|
||||||
|
- Security
|
||||||
|
- Service
|
||||||
|
- Supply
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/command.rsi
|
sprite: Clothing/Ears/Headsets/command.rsi
|
||||||
|
|
||||||
@@ -46,6 +71,10 @@
|
|||||||
name: engineering headset
|
name: engineering headset
|
||||||
description: A headset for engineers to chat while the station burns around them.
|
description: A headset for engineers to chat while the station burns around them.
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Engineering
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/engineering.rsi
|
sprite: Clothing/Ears/Headsets/engineering.rsi
|
||||||
|
|
||||||
@@ -55,6 +84,10 @@
|
|||||||
name: medical headset
|
name: medical headset
|
||||||
description: A headset for the trained staff of the medbay.
|
description: A headset for the trained staff of the medbay.
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Medical
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/medical.rsi
|
sprite: Clothing/Ears/Headsets/medical.rsi
|
||||||
|
|
||||||
@@ -64,6 +97,11 @@
|
|||||||
name: medical research headset
|
name: medical research headset
|
||||||
description: A headset that is a result of the mating between medical and science.
|
description: A headset that is a result of the mating between medical and science.
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Medical
|
||||||
|
- Science
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/medicalscience.rsi
|
sprite: Clothing/Ears/Headsets/medicalscience.rsi
|
||||||
|
|
||||||
@@ -91,6 +129,10 @@
|
|||||||
name: science headset
|
name: science headset
|
||||||
description: A sciency headset. Like usual.
|
description: A sciency headset. Like usual.
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Science
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/science.rsi
|
sprite: Clothing/Ears/Headsets/science.rsi
|
||||||
|
|
||||||
@@ -100,6 +142,10 @@
|
|||||||
name: security headset
|
name: security headset
|
||||||
description: This is used by your elite security force.
|
description: This is used by your elite security force.
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Security
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/security.rsi
|
sprite: Clothing/Ears/Headsets/security.rsi
|
||||||
|
|
||||||
@@ -109,5 +155,9 @@
|
|||||||
name: service headset
|
name: service headset
|
||||||
description: Headset used by the service staff, tasked with keeping the station full, happy and clean.
|
description: Headset used by the service staff, tasked with keeping the station full, happy and clean.
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Service
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/service.rsi
|
sprite: Clothing/Ears/Headsets/service.rsi
|
||||||
|
|||||||
@@ -17,6 +17,16 @@
|
|||||||
id: ClothingHeadsetAltCommand
|
id: ClothingHeadsetAltCommand
|
||||||
name: command overear-headset
|
name: command overear-headset
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Command
|
||||||
|
- Engineering
|
||||||
|
- Medical
|
||||||
|
- Science
|
||||||
|
- Security
|
||||||
|
- Service
|
||||||
|
- Supply
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/command.rsi
|
sprite: Clothing/Ears/Headsets/command.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
@@ -27,6 +37,10 @@
|
|||||||
id: ClothingHeadsetAltMedical
|
id: ClothingHeadsetAltMedical
|
||||||
name: medical overear-headset
|
name: medical overear-headset
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Medical
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/medical.rsi
|
sprite: Clothing/Ears/Headsets/medical.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
@@ -37,6 +51,10 @@
|
|||||||
id: ClothingHeadsetAltSecurity
|
id: ClothingHeadsetAltSecurity
|
||||||
name: security overear-headset
|
name: security overear-headset
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Security
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/security.rsi
|
sprite: Clothing/Ears/Headsets/security.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
@@ -48,6 +66,10 @@
|
|||||||
name: syndicate overear-headset
|
name: syndicate overear-headset
|
||||||
description: A syndicate headset that can be used to hear all radio frequencies. Protects ears from flashbangs.
|
description: A syndicate headset that can be used to hear all radio frequencies. Protects ears from flashbangs.
|
||||||
components:
|
components:
|
||||||
|
- type: Headset
|
||||||
|
channels:
|
||||||
|
- Common
|
||||||
|
- Syndicate
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Clothing/Ears/Headsets/syndicate.rsi
|
sprite: Clothing/Ears/Headsets/syndicate.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
|
|||||||
66
Resources/Prototypes/radio_channels.yml
Normal file
66
Resources/Prototypes/radio_channels.yml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
- type: radioChannel
|
||||||
|
id: Common
|
||||||
|
name: "Common"
|
||||||
|
keycode: ";"
|
||||||
|
frequency: 1459
|
||||||
|
|
||||||
|
- type: radioChannel
|
||||||
|
id: CentCom
|
||||||
|
name: "CentCom"
|
||||||
|
keycode: 'y'
|
||||||
|
frequency: 1337
|
||||||
|
|
||||||
|
- type: radioChannel
|
||||||
|
id: Command
|
||||||
|
name: "Command"
|
||||||
|
keycode: 'c'
|
||||||
|
frequency: 1353
|
||||||
|
color: "#334e6d"
|
||||||
|
|
||||||
|
- type: radioChannel
|
||||||
|
id: Engineering
|
||||||
|
name: "Engineering"
|
||||||
|
keycode: 'e'
|
||||||
|
frequency: 1357
|
||||||
|
color: "#efb341"
|
||||||
|
|
||||||
|
- type: radioChannel
|
||||||
|
id: Medical
|
||||||
|
name: "Medical"
|
||||||
|
keycode: 'm'
|
||||||
|
frequency: 1355
|
||||||
|
color: "#52b4e9"
|
||||||
|
|
||||||
|
- type: radioChannel
|
||||||
|
id: Science
|
||||||
|
name: "Science"
|
||||||
|
keycode: 'n'
|
||||||
|
frequency: 1351
|
||||||
|
color: "#d381c9"
|
||||||
|
|
||||||
|
- type: radioChannel
|
||||||
|
id: Security
|
||||||
|
name: "Security"
|
||||||
|
keycode: 's'
|
||||||
|
frequency: 1359
|
||||||
|
color: "#de3a3a"
|
||||||
|
|
||||||
|
- type: radioChannel
|
||||||
|
id: Service
|
||||||
|
name: "Service"
|
||||||
|
keycode: 'v'
|
||||||
|
frequency: 1349
|
||||||
|
color: "#9fed58"
|
||||||
|
|
||||||
|
- type: radioChannel
|
||||||
|
id: Supply
|
||||||
|
name: "Supply"
|
||||||
|
keycode: 'u'
|
||||||
|
frequency: 1347
|
||||||
|
color: "#a46106"
|
||||||
|
|
||||||
|
- type: radioChannel
|
||||||
|
id: Syndicate
|
||||||
|
name: "Syndicate"
|
||||||
|
keycode: 't'
|
||||||
|
frequency: 1213
|
||||||
Reference in New Issue
Block a user