diff --git a/Content.Client/Administration/UI/Tabs/ServerTab.xaml b/Content.Client/Administration/UI/Tabs/ServerTab.xaml index 80c186f7fd0..d377922b4b4 100644 --- a/Content.Client/Administration/UI/Tabs/ServerTab.xaml +++ b/Content.Client/Administration/UI/Tabs/ServerTab.xaml @@ -9,5 +9,6 @@ + diff --git a/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs b/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs index 7a70e42d066..03a1fde12b8 100644 --- a/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs @@ -1,4 +1,5 @@ -using Content.Shared.CCVar; +using Content.Shared._DV.CCVars; // DeltaV - Antagonist OOC +using Content.Shared.CCVar; using Robust.Client.AutoGenerated; using Robust.Client.Console; using Robust.Client.UserInterface; @@ -20,6 +21,7 @@ namespace Content.Client.Administration.UI.Tabs _config.OnValueChanged(CCVars.OocEnabled, OocEnabledChanged, true); _config.OnValueChanged(CCVars.LoocEnabled, LoocEnabledChanged, true); + _config.OnValueChanged(DCCVars.AntagOOCEnabled, AntagOocEnabledChanged, true); // DeltaV - antagonist OOC ServerShutdownButton.OnPressed += _ => _console.ExecuteCommand("shutdown"); } @@ -34,6 +36,13 @@ namespace Content.Client.Administration.UI.Tabs SetLoocButton.Pressed = value; } + // Begin DeltaV - Antagonist OOC + private void AntagOocEnabledChanged(bool value) + { + SetAntagOocButton.Pressed = value; + } + // End DeltaV - Antagonist OOC + protected override void Dispose(bool disposing) { base.Dispose(disposing); @@ -42,6 +51,7 @@ namespace Content.Client.Administration.UI.Tabs { _config.UnsubValueChanged(CCVars.OocEnabled, OocEnabledChanged); _config.UnsubValueChanged(CCVars.LoocEnabled, LoocEnabledChanged); + _config.UnsubValueChanged(DCCVars.AntagOOCEnabled, AntagOocEnabledChanged); // DeltaV - Antagonist OOC } } } diff --git a/Content.Client/Chat/Managers/ChatManager.cs b/Content.Client/Chat/Managers/ChatManager.cs index 5381737d101..38ca25fe7cc 100644 --- a/Content.Client/Chat/Managers/ChatManager.cs +++ b/Content.Client/Chat/Managers/ChatManager.cs @@ -59,6 +59,12 @@ internal sealed class ChatManager : IChatManager _consoleHost.ExecuteCommand($"asay \"{CommandParsing.Escape(str)}\""); break; + // Begin DeltaV - Antag OOC + case ChatSelectChannel.AntagOOC: + _consoleHost.ExecuteCommand($"antagsay \"{CommandParsing.Escape(str)}\""); + break; + // End DeltaV - Antag OOC + case ChatSelectChannel.Emotes: _consoleHost.ExecuteCommand($"me \"{CommandParsing.Escape(str)}\""); break; diff --git a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs index f7421dc6044..6ad8440b74a 100644 --- a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs +++ b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs @@ -23,6 +23,7 @@ using Content.Shared.Damage.ForceSay; using Content.Shared.Decals; using Content.Shared.Input; using Content.Shared.Radio; +using Content.Shared.Roles; // DeltaV - Antag OOC using Content.Shared.Roles.RoleCodeword; using Robust.Client.GameObjects; using Robust.Client.Graphics; @@ -69,6 +70,7 @@ public sealed partial class ChatUIController : UIController [UISystemDependency] private readonly TransformSystem? _transform = default; [UISystemDependency] private readonly MindSystem? _mindSystem = default!; [UISystemDependency] private readonly RoleCodewordSystem? _roleCodewordSystem = default!; + [UISystemDependency] private readonly SharedRoleSystem? _roleSystem = default!; // DeltaV - Antag OOC private static readonly ProtoId ChatNamePalette = "ChatNames"; private string[] _chatNameColors = default!; @@ -88,7 +90,8 @@ public sealed partial class ChatUIController : UIController {SharedChatSystem.AdminPrefix, ChatSelectChannel.Admin}, {SharedChatSystem.RadioCommonPrefix, ChatSelectChannel.Radio}, {SharedChatSystem.DeadPrefix, ChatSelectChannel.Dead}, - {SharedChatSystem.TelepathicPrefix, ChatSelectChannel.Telepathic} //Nyano - Summary: adds the telepathic prefix =. + {SharedChatSystem.TelepathicPrefix, ChatSelectChannel.Telepathic}, //Nyano - Summary: adds the telepathic prefix =. + {SharedChatSystem.AntagOOCPrefix, ChatSelectChannel.AntagOOC} // DeltaV - Antag OOC }; public static readonly Dictionary ChannelPrefixes = new() @@ -102,7 +105,8 @@ public sealed partial class ChatUIController : UIController {ChatSelectChannel.Admin, SharedChatSystem.AdminPrefix}, {ChatSelectChannel.Radio, SharedChatSystem.RadioCommonPrefix}, {ChatSelectChannel.Dead, SharedChatSystem.DeadPrefix}, - {ChatSelectChannel.Telepathic, SharedChatSystem.TelepathicPrefix } //Nyano - Summary: associates telepathic with =. + {ChatSelectChannel.Telepathic, SharedChatSystem.TelepathicPrefix }, //Nyano - Summary: associates telepathic with =. + {ChatSelectChannel.AntagOOC, SharedChatSystem.AntagOOCPrefix} // DeltaV - Antag OOC }; /// @@ -190,6 +194,7 @@ public sealed partial class ChatUIController : UIController _net.RegisterNetMessage(OnChatMessage); _net.RegisterNetMessage(OnDeleteChatMessagesBy); SubscribeNetworkEvent(OnDamageForceSay); + SubscribeNetworkEvent(OnMindRoleTypeChanged); // DeltaV - Antag OOC _config.OnValueChanged(CCVars.ChatEnableColorName, (value) => { _chatNameColorsEnabled = value; }); _chatNameColorsEnabled = _config.GetCVar(CCVars.ChatEnableColorName); @@ -560,6 +565,22 @@ public sealed partial class ChatUIController : UIController CanSendChannels |= ChatSelectChannel.Dead; } + // Begin DeltaV - Antag OOC + // antags and admins can see antagsay + var localUserId = _player.LocalSession?.UserId; + var antagOOCEligible = _admin.IsActive() + || (localUserId is { } userId + && _mindSystem != null + && _roleSystem != null + && _roleSystem.MindHasAntagonistOOC(_mindSystem.GetMind(userId))); + + if (antagOOCEligible) + { + FilterableChannels |= ChatChannel.AntagOOC; + CanSendChannels |= ChatSelectChannel.AntagOOC; + } + // End DeltaV - Antag OOC + // only admins can see / filter asay if (_admin.HasFlag(AdminFlags.Adminchat)) { @@ -790,6 +811,13 @@ public sealed partial class ChatUIController : UIController _manager.SendMessage(text, prefixChannel == 0 ? channel : prefixChannel); } + // Begin DeltaV - Antagonist OOC + private void OnMindRoleTypeChanged(MindRoleTypeChangedEvent ev, EntitySessionEventArgs _) + { + UpdateChannelPermissions(); + } + // End DeltaV - Antagonist OOC + private void OnDamageForceSay(DamageForceSayEvent ev, EntitySessionEventArgs _) { var chatBox = UIManager.ActiveScreen?.GetWidget() ?? UIManager.ActiveScreen?.GetWidget(); diff --git a/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml.cs b/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml.cs index ebdc74726f6..ac30b6f7017 100644 --- a/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml.cs +++ b/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml.cs @@ -28,6 +28,7 @@ public sealed partial class ChannelFilterPopup : Popup ChatChannel.Admin, ChatChannel.AdminAlert, ChatChannel.AdminChat, + ChatChannel.AntagOOC, // DeltaV - Antagonist OOC ChatChannel.Server }; diff --git a/Content.Client/UserInterface/Systems/Chat/Controls/ChannelSelectorButton.cs b/Content.Client/UserInterface/Systems/Chat/Controls/ChannelSelectorButton.cs index 041d8075e35..43be8cba16f 100644 --- a/Content.Client/UserInterface/Systems/Chat/Controls/ChannelSelectorButton.cs +++ b/Content.Client/UserInterface/Systems/Chat/Controls/ChannelSelectorButton.cs @@ -64,6 +64,7 @@ public sealed class ChannelSelectorButton : ChatPopupButton Color.LightSkyBlue, ChatSelectChannel.Dead => Color.MediumPurple, ChatSelectChannel.Admin => Color.HotPink, + ChatSelectChannel.AntagOOC => Color.Crimson, // DeltaV - Antagonist OOC ChatSelectChannel.Telepathic => Color.PaleVioletRed, //Nyano - Summary: determines the color for the chat. _ => Color.DarkGray }; diff --git a/Content.Client/UserInterface/Systems/Chat/Controls/ChannelSelectorPopup.cs b/Content.Client/UserInterface/Systems/Chat/Controls/ChannelSelectorPopup.cs index c1f3559d793..d8573544dd7 100644 --- a/Content.Client/UserInterface/Systems/Chat/Controls/ChannelSelectorPopup.cs +++ b/Content.Client/UserInterface/Systems/Chat/Controls/ChannelSelectorPopup.cs @@ -17,7 +17,8 @@ public sealed class ChannelSelectorPopup : Popup ChatSelectChannel.LOOC, ChatSelectChannel.OOC, ChatSelectChannel.Dead, - ChatSelectChannel.Admin + ChatSelectChannel.Admin, + ChatSelectChannel.AntagOOC // DeltaV - Antagonist OOC // NOTE: Console is not in there and it can never be permanently selected. // You can, however, still submit commands as console by prefixing with /. }; diff --git a/Content.Server/Chat/Managers/ChatManager.cs b/Content.Server/Chat/Managers/ChatManager.cs index f882ff70f37..c3dd51d097f 100644 --- a/Content.Server/Chat/Managers/ChatManager.cs +++ b/Content.Server/Chat/Managers/ChatManager.cs @@ -8,6 +8,7 @@ using Content.Server.Discord.DiscordLink; using Content.Server.Ghost; using Content.Server.Players.RateLimiting; using Content.Server.Preferences.Managers; +using Content.Shared._DV.CCVars; // DeltaV - antagonist OOC using Content.Shared.Administration; using Content.Shared.CCVar; using Content.Shared.Chat; @@ -15,6 +16,7 @@ using Content.Shared.Database; using Content.Shared.Mind; using Content.Shared.Players; // DeltaV - OOC muting using Content.Shared.Players.RateLimiting; +using Content.Shared.Roles; // DeltaV - antagonist OOC using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Network; @@ -60,6 +62,7 @@ internal sealed partial class ChatManager : IChatManager private bool _oocEnabled = true; private bool _adminOocEnabled = true; + private bool _antagOocEnabled = true; // DeltaV - antagonist OOC private readonly Dictionary _players = new(); @@ -70,6 +73,7 @@ internal sealed partial class ChatManager : IChatManager _configurationManager.OnValueChanged(CCVars.OocEnabled, OnOocEnabledChanged, true); _configurationManager.OnValueChanged(CCVars.AdminOocEnabled, OnAdminOocEnabledChanged, true); + _configurationManager.OnValueChanged(DCCVars.AntagOOCEnabled, OnAntagOocEnabledChanged, true); // DeltaV - antagonist OOC _sawmill = _logManager.GetSawmill("SERVER"); @@ -92,6 +96,16 @@ internal sealed partial class ChatManager : IChatManager DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-admin-ooc-chat-enabled-message" : "chat-manager-admin-ooc-chat-disabled-message")); } + // Begin DeltaV - Antagonist OOC + private void OnAntagOocEnabledChanged(bool val) + { + if (_antagOocEnabled == val) return; + + _antagOocEnabled = val; + DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-antag-ooc-chat-enabled-message" : "chat-manager-antag-ooc-chat-disabled-message")); + } + // End DeltaV - Antagonist OOC + public void DeleteMessagesBy(NetUserId uid) { if (!_players.TryGetValue(uid, out var user)) @@ -266,6 +280,11 @@ internal sealed partial class ChatManager : IChatManager case OOCChatType.Admin: SendAdminChat(player, message); break; + // Begin DeltaV - Antag OOC + case OOCChatType.AntagOOC: + SendAntagOOC(player, message); + break; + // End DeltaV - Antag OOC } } @@ -341,6 +360,41 @@ internal sealed partial class ChatManager : IChatManager _adminLogger.Add(LogType.Chat, $"Admin chat from {player:Player}: {message}"); } + // Begin DeltaV - Antagonist OOC + private void SendAntagOOC(ICommonSession player, string message) + { + var isAdmin = _adminManager.IsAdmin(player); + var roleSystem = _entityManager.System(); + var mindId = player.ContentData()?.Mind; + + if (!isAdmin) + { + if (!_antagOocEnabled) + return; + + if (!roleSystem.MindHasAntagonistOOC(mindId)) + { + _adminLogger.Add(LogType.Chat, LogImpact.Extreme, $"{player:Player} attempted to send antag OOC message but was not admin or antagonist-OOC eligible"); + return; + } + } + + var wrappedMessage = Loc.GetString("chat-manager-send-antag-ooc-wrap-message", + ("antagChannelName", Loc.GetString("chat-manager-antag-ooc-channel-name")), + ("playerName", player.Name), ("message", FormattedMessage.EscapeText(message))); + + var clients = _adminManager.ActiveAdmins.Select(p => p.Channel) + .Union(_player.Sessions + .Where(session => roleSystem.MindHasAntagonistOOC(session.ContentData()?.Mind)) + .Select(session => session.Channel)); + + ChatMessageToMany(ChatChannel.AntagOOC, message, wrappedMessage, EntityUid.Invalid, false, true, clients.ToList(), author: player.UserId); + + _discordLink.SendMessage(message, player.Name, ChatChannel.AntagOOC); + _adminLogger.Add(LogType.Chat, $"Antag OOC from {player:Player}: {message}"); + } + // End DeltaV - Antagonist OOC + #endregion #region Utility @@ -491,5 +545,6 @@ internal sealed partial class ChatManager : IChatManager public enum OOCChatType : byte { OOC, - Admin + Admin, + AntagOOC // DeltaV - Antagonist OOC } diff --git a/Content.Server/Discord/DiscordLink/DiscordChatLink.cs b/Content.Server/Discord/DiscordLink/DiscordChatLink.cs index 34ddc39f712..f23889b3d3b 100644 --- a/Content.Server/Discord/DiscordLink/DiscordChatLink.cs +++ b/Content.Server/Discord/DiscordLink/DiscordChatLink.cs @@ -1,4 +1,5 @@ using Content.Server.Chat.Managers; +using Content.Shared._DV.CCVars; // DeltaV - Antagonist OOC using Content.Shared.CCVar; using Content.Shared.Chat; using NetCord; @@ -20,6 +21,7 @@ public sealed class DiscordChatLink : IPostInjectInit private ulong? _oocChannelId; private ulong? _adminChannelId; + private ulong? _antagOocChannelId; // DeltaV - antagonist OOC public void Initialize() { @@ -31,6 +33,7 @@ public sealed class DiscordChatLink : IPostInjectInit _configurationManager.OnValueChanged(CCVars.OocDiscordChannelId, OnOocChannelIdChanged, true); _configurationManager.OnValueChanged(CCVars.AdminChatDiscordChannelId, OnAdminChannelIdChanged, true); + _configurationManager.OnValueChanged(DCCVars.AntagOOCDiscordChannelId, OnAntagOocChannelIdChanged, true); // DeltaV - antagonist OOC } public void Shutdown() @@ -39,6 +42,7 @@ public sealed class DiscordChatLink : IPostInjectInit _configurationManager.UnsubValueChanged(CCVars.OocDiscordChannelId, OnOocChannelIdChanged); _configurationManager.UnsubValueChanged(CCVars.AdminChatDiscordChannelId, OnAdminChannelIdChanged); + _configurationManager.UnsubValueChanged(DCCVars.AntagOOCDiscordChannelId, OnAntagOocChannelIdChanged); // DeltaV - antagonist OOC } #if DEBUG @@ -71,6 +75,19 @@ public sealed class DiscordChatLink : IPostInjectInit _adminChannelId = ulong.Parse(channelId); } + // Begin DeltaV - Antagonist OOC + private void OnAntagOocChannelIdChanged(string channelId) + { + if (string.IsNullOrEmpty(channelId)) + { + _antagOocChannelId = null; + return; + } + + _antagOocChannelId = ulong.Parse(channelId); + } + // End DeltaV - Antagonist OOC + private void OnMessageReceived(Message message) { if (message.Author.IsBot) @@ -94,6 +111,7 @@ public sealed class DiscordChatLink : IPostInjectInit { ChatChannel.OOC => _oocChannelId, ChatChannel.AdminChat => _adminChannelId, + ChatChannel.AntagOOC => _antagOocChannelId, // DeltaV - Antagonist OOC _ => throw new InvalidOperationException("Channel not linked to Discord."), }; diff --git a/Content.Server/_DV/Chat/AntagSayCommand.cs b/Content.Server/_DV/Chat/AntagSayCommand.cs new file mode 100644 index 00000000000..435a3bacd23 --- /dev/null +++ b/Content.Server/_DV/Chat/AntagSayCommand.cs @@ -0,0 +1,31 @@ +using Content.Server.Chat.Managers; +using Content.Shared.Administration; +using Robust.Shared.Console; + +namespace Content.Server._DV.Chat; + +[AnyCommand] +public sealed class AntagSayCommand : LocalizedCommands +{ + [Dependency] private readonly IChatManager _chatManager = default!; + + public override string Command => "antagsay"; + + public override void Execute(IConsoleShell shell, string argStr, string[] args) + { + if (shell.Player is not { } player) + { + shell.WriteError(Loc.GetString($"shell-cannot-run-command-from-server")); + return; + } + + if (args.Length < 1) + return; + + var message = string.Join(" ", args).Trim(); + if (string.IsNullOrEmpty(message)) + return; + + _chatManager.TrySendOOCMessage(player, message, OOCChatType.AntagOOC); + } +} diff --git a/Content.Server/_DV/Chat/SetAntagOOCCommand.cs b/Content.Server/_DV/Chat/SetAntagOOCCommand.cs new file mode 100644 index 00000000000..8ef39e8cd44 --- /dev/null +++ b/Content.Server/_DV/Chat/SetAntagOOCCommand.cs @@ -0,0 +1,41 @@ +using Content.Server.Administration; +using Content.Shared._DV.CCVars; +using Content.Shared.Administration; +using Robust.Shared.Configuration; +using Robust.Shared.Console; + +namespace Content.Server._DV.Chat; + +[AdminCommand(AdminFlags.Admin)] +public sealed class SetAntagOOCCommand : LocalizedCommands +{ + [Dependency] private readonly IConfigurationManager _configManager = default!; + + public override string Command => "setantagooc"; + + public override void Execute(IConsoleShell shell, string argStr, string[] args) + { + if (args.Length > 1) + { + shell.WriteError(Loc.GetString("shell-need-between-arguments", ("lower", 0), ("upper", 1))); + return; + } + + var antagOoc = _configManager.GetCVar(DCCVars.AntagOOCEnabled); + + if (args.Length == 0) + { + antagOoc = !antagOoc; + } + + if (args.Length == 1 && !bool.TryParse(args[0], out antagOoc)) + { + shell.WriteError(Loc.GetString("shell-invalid-bool")); + return; + } + + _configManager.SetCVar(DCCVars.AntagOOCEnabled, antagOoc); + + shell.WriteLine(Loc.GetString(antagOoc ? "cmd-setantagooc-antagooc-enabled" : "cmd-setantagooc-antagooc-disabled")); + } +} diff --git a/Content.Shared/Chat/ChatChannel.cs b/Content.Shared/Chat/ChatChannel.cs index 57e33a48516..b6be61a425a 100644 --- a/Content.Shared/Chat/ChatChannel.cs +++ b/Content.Shared/Chat/ChatChannel.cs @@ -4,7 +4,7 @@ namespace Content.Shared.Chat /// Represents chat channels that the player can filter chat tabs by. /// [Flags] - public enum ChatChannel : ushort + public enum ChatChannel : uint // DeltaV - MOAR CHANNELS { None = 0, @@ -90,6 +90,11 @@ namespace Content.Shared.Chat /// Telepathic = 1 << 15, + /// + /// DeltaV - OOC for antagonists + /// + AntagOOC = 1 << 16, + /// /// Channels considered to be IC. /// @@ -113,6 +118,7 @@ namespace Content.Shared.Chat { ChatChannel.OOC => Loc.GetString("chat-channel-humanized-ooc"), ChatChannel.AdminChat => Loc.GetString("chat-channel-humanized-admin"), + ChatChannel.AntagOOC => Loc.GetString("chat-channel-humanized-antagooc"), // DeltaV - Antagonist OOC _ => throw new ArgumentOutOfRangeException(nameof(channel), channel, null) }; } diff --git a/Content.Shared/Chat/ChatChannelExtensions.cs b/Content.Shared/Chat/ChatChannelExtensions.cs index 9b707a53a0e..14396a719bb 100644 --- a/Content.Shared/Chat/ChatChannelExtensions.cs +++ b/Content.Shared/Chat/ChatChannelExtensions.cs @@ -14,6 +14,7 @@ public static class ChatChannelExtensions ChatChannel.Admin => Color.Red, ChatChannel.AdminAlert => Color.Red, ChatChannel.AdminChat => Color.HotPink, + ChatChannel.AntagOOC => Color.Crimson, // DeltaV - Antagonist OOC ChatChannel.Whisper => Color.DarkGray, _ => Color.LightGray }; diff --git a/Content.Shared/Chat/ChatSelectChannel.cs b/Content.Shared/Chat/ChatSelectChannel.cs index 5104bbc3068..65c3c79c628 100644 --- a/Content.Shared/Chat/ChatSelectChannel.cs +++ b/Content.Shared/Chat/ChatSelectChannel.cs @@ -7,7 +7,7 @@ /// Maps to , giving better names. /// [Flags] - public enum ChatSelectChannel : ushort + public enum ChatSelectChannel : uint // DeltaV - Antagonist OOC { None = 0, @@ -51,6 +51,11 @@ /// Admin = ChatChannel.AdminChat, + /// + /// DeltaV - OOC for antagonists + /// + AntagOOC = ChatChannel.AntagOOC, + /// /// Nyano - Summary:. Telepathic channel for all psionic entities. /// diff --git a/Content.Shared/Chat/SharedChatSystem.cs b/Content.Shared/Chat/SharedChatSystem.cs index fbfb864bd86..7d7675b4455 100644 --- a/Content.Shared/Chat/SharedChatSystem.cs +++ b/Content.Shared/Chat/SharedChatSystem.cs @@ -33,6 +33,7 @@ public abstract partial class SharedChatSystem : EntitySystem 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 AntagOOCPrefix = '%'; // DeltaV - Antagonist OOC public const char WhisperPrefix = ','; public const char TelepathicPrefix = '='; //Nyano - Summary: Adds the telepathic channel's prefix. public const char DefaultChannelKey = 'h'; diff --git a/Content.Shared/Mind/RoleTypePrototype.cs b/Content.Shared/Mind/RoleTypePrototype.cs index 690bd894a06..35271b66262 100644 --- a/Content.Shared/Mind/RoleTypePrototype.cs +++ b/Content.Shared/Mind/RoleTypePrototype.cs @@ -32,4 +32,10 @@ public sealed partial class RoleTypePrototype : IPrototype /// [DataField] public string Symbol = FallbackSymbol; + + /// + /// DeltaV - Whether minds with this roletype can access AOOC + /// + [DataField] + public bool AntagonistOOC; } diff --git a/Content.Shared/Roles/SharedRoleSystem.cs b/Content.Shared/Roles/SharedRoleSystem.cs index 72f5eb42961..f0d5dc666d1 100644 --- a/Content.Shared/Roles/SharedRoleSystem.cs +++ b/Content.Shared/Roles/SharedRoleSystem.cs @@ -631,6 +631,21 @@ public abstract class SharedRoleSystem : EntitySystem return CheckAntagonistStatus(mindId.Value).ExclusiveAntag; } + // Begin DeltaV - Antagonist OOC + /// + /// Does this mind's current role type grant access to the Antagonist OOC channel + /// + /// The mind entity + /// True if the mind's RoleTypePrototype has AntagonistOOC set + public bool MindHasAntagonistOOC(EntityUid? mindId) + { + if (mindId is null || !TryComp(mindId.Value, out var mind)) + return false; + + return _prototypes.TryIndex(mind.RoleType, out var roleType) && roleType.AntagonistOOC; + } + // End DeltaV - Antagonist OOC + private (bool Antag, bool ExclusiveAntag) CheckAntagonistStatus(Entity mind) { if (!Resolve(mind.Owner, ref mind.Comp)) diff --git a/Content.Shared/_DV/CCVars/DCCVars.cs b/Content.Shared/_DV/CCVars/DCCVars.cs index 5b8fd35967c..48bbafe5c1d 100644 --- a/Content.Shared/_DV/CCVars/DCCVars.cs +++ b/Content.Shared/_DV/CCVars/DCCVars.cs @@ -343,4 +343,21 @@ public sealed partial class DCCVars /// public static readonly CVarDef RoundEndIsOOCVote = CVarDef.Create("deltav.round_end_is_ooc_vote", false, CVar.SERVER); + + /** + * Antagonist OOC + */ + + /// + /// Whether the Antagonist OOC channel is enabled. + /// Admins can always use it. + /// + public static readonly CVarDef AntagOOCEnabled = + CVarDef.Create("antag_ooc.enabled", true, CVar.NOTIFY); + + /// + /// The discord channel ID to relay Antagonist OOC messages to. + /// + public static readonly CVarDef AntagOOCDiscordChannelId = + CVarDef.Create("antag_ooc.discord_channel_id", string.Empty, CVar.SERVERONLY); } diff --git a/Resources/Locale/en-US/_DV/administration/ui/server-tab.ftl b/Resources/Locale/en-US/_DV/administration/ui/server-tab.ftl new file mode 100644 index 00000000000..bdb28ce3ffa --- /dev/null +++ b/Resources/Locale/en-US/_DV/administration/ui/server-tab.ftl @@ -0,0 +1 @@ +server-antag-ooc-toggle = Toggle Antag OOC diff --git a/Resources/Locale/en-US/_DV/chat/chat-channel.ftl b/Resources/Locale/en-US/_DV/chat/chat-channel.ftl new file mode 100644 index 00000000000..228fa5fbe9c --- /dev/null +++ b/Resources/Locale/en-US/_DV/chat/chat-channel.ftl @@ -0,0 +1 @@ +chat-channel-humanized-antagooc = Antagonist OOC diff --git a/Resources/Locale/en-US/_DV/chat/managers/chat_manager.ftl b/Resources/Locale/en-US/_DV/chat/managers/chat_manager.ftl index b30c3f53f89..7bdc33eeece 100644 --- a/Resources/Locale/en-US/_DV/chat/managers/chat_manager.ftl +++ b/Resources/Locale/en-US/_DV/chat/managers/chat_manager.ftl @@ -53,3 +53,10 @@ chat-manager-entity-me-audible-possessive-wrap-message = [italic]{ PROPER($entit *[false] The {$entityName}'s {$message}[/italic] [true] {CAPITALIZE($entityName)}'s {$message}[/italic] } + +chat-manager-antag-ooc-chat-enabled-message = Antagonist OOC chat has been enabled. +chat-manager-antag-ooc-chat-disabled-message = Antagonist OOC chat has been disabled. + +chat-manager-send-antag-ooc-wrap-message = {$antagChannelName}: {$playerName}: {$message} + +chat-manager-antag-ooc-channel-name = (ANTAG) diff --git a/Resources/Locale/en-US/_DV/chat/ui/chat-box.ftl b/Resources/Locale/en-US/_DV/chat/ui/chat-box.ftl index 283ce130bd0..94ff2ce91f2 100644 --- a/Resources/Locale/en-US/_DV/chat/ui/chat-box.ftl +++ b/Resources/Locale/en-US/_DV/chat/ui/chat-box.ftl @@ -1,3 +1,7 @@ hud-chatbox-select-channels = Channels: hud-chatbox-auto-highlights = Automatic Highlights: + +hud-chatbox-select-channel-AntagOOC = Antag OOC + +hud-chatbox-channel-AntagOOC = Antag OOC diff --git a/Resources/Locale/en-US/administration/commands/set-antag-ooc-command.ftl b/Resources/Locale/en-US/administration/commands/set-antag-ooc-command.ftl new file mode 100644 index 00000000000..631f5a660ed --- /dev/null +++ b/Resources/Locale/en-US/administration/commands/set-antag-ooc-command.ftl @@ -0,0 +1,4 @@ +cmd-setantagooc-desc = Allows you to enable or disable the Antagonist OOC channel for non-admins. +cmd-setantagooc-help = Usage: setantagooc OR setantagooc [value] +cmd-setantagooc-antagooc-enabled = Antagonist OOC chat has been enabled. +cmd-setantagooc-antagooc-disabled = Antagonist OOC chat has been disabled. diff --git a/Resources/Prototypes/Roles/role_types.yml b/Resources/Prototypes/Roles/role_types.yml index eb8db63977a..9771884819a 100644 --- a/Resources/Prototypes/Roles/role_types.yml +++ b/Resources/Prototypes/Roles/role_types.yml @@ -17,12 +17,14 @@ name: role-type-solo-antagonist-name color: '#d82000' symbol: "🗡" + antagonistOOC: true # DeltaV - antagonist OOC - type: roleType id: TeamAntagonist name: role-type-team-antagonist-name color: '#d82000' symbol: "⚔" + antagonistOOC: true # DeltaV - antagonist OOC - type: roleType id: FreeAgent @@ -47,3 +49,4 @@ name: role-type-silicon-antagonist-name color: '#c832e6' symbol: "⛞" + antagonistOOC: true # DeltaV - antagonist OOC