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