]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Prevent admin-frozen players from ghosting or suiciding, add "Freeze And Mute" verb...
authorno <165581243+pissdemon@users.noreply.github.com>
Sun, 12 May 2024 14:35:30 +0000 (16:35 +0200)
committerGitHub <noreply@github.com>
Sun, 12 May 2024 14:35:30 +0000 (10:35 -0400)
* prevent admin-frozen players from ghosting or suiciding

* Add "Freeze and Mute" admin verb

* Allow "Freeze And Mute" admin verb when player is already frozen but not muted

* Remove redundant scream handler (scream action just emotes, duh)

* AdminFrozenSystem: clean imports

* Update Content.Server/Chat/Commands/SuicideCommand.cs

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
* Update Ghost.cs

* retrigger ci (empty commit)

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Content.Client/Administration/Systems/AdminFrozenSystem.cs [new file with mode: 0644]
Content.Server/Administration/Systems/AdminFrozenSystem.cs [new file with mode: 0644]
Content.Server/Administration/Systems/AdminVerbSystem.cs
Content.Server/Chat/Commands/SuicideCommand.cs
Content.Server/Ghost/Ghost.cs
Content.Shared/Administration/AdminFrozenComponent.cs
Content.Shared/Administration/SharedAdminFrozenSystem.cs [moved from Content.Shared/Administration/AdminFrozenSystem.cs with 78% similarity]
Resources/Locale/en-US/administration/admin-verbs.ftl
Resources/Locale/en-US/chat/commands/ghost-command.ftl [new file with mode: 0644]
Resources/Locale/en-US/chat/commands/suicide-command.ftl

diff --git a/Content.Client/Administration/Systems/AdminFrozenSystem.cs b/Content.Client/Administration/Systems/AdminFrozenSystem.cs
new file mode 100644 (file)
index 0000000..885585f
--- /dev/null
@@ -0,0 +1,7 @@
+using Content.Shared.Administration;
+
+namespace Content.Client.Administration.Systems;
+
+public sealed class AdminFrozenSystem : SharedAdminFrozenSystem
+{
+}
diff --git a/Content.Server/Administration/Systems/AdminFrozenSystem.cs b/Content.Server/Administration/Systems/AdminFrozenSystem.cs
new file mode 100644 (file)
index 0000000..baf7b68
--- /dev/null
@@ -0,0 +1,16 @@
+using Content.Shared.Administration;
+
+namespace Content.Server.Administration.Systems;
+
+public sealed class AdminFrozenSystem : SharedAdminFrozenSystem
+{
+    /// <summary>
+    /// Freezes and mutes the given entity.
+    /// </summary>
+    public void FreezeAndMute(EntityUid uid)
+    {
+        var comp = EnsureComp<AdminFrozenComponent>(uid);
+        comp.Muted = true;
+        Dirty(uid, comp);
+    }
+}
index 5bb75b4c99c17019d979af5e177a40e1422c7d39..7aa4c8b400a598f3293337eb595c76d677c3dcb8 100644 (file)
@@ -67,6 +67,7 @@ namespace Content.Server.Administration.Systems
         [Dependency] private readonly StationSystem _stations = default!;
         [Dependency] private readonly StationSpawningSystem _spawning = default!;
         [Dependency] private readonly ExamineSystemShared _examine = default!;
+        [Dependency] private readonly AdminFrozenSystem _freeze = default!;
 
         private readonly Dictionary<ICommonSession, List<EditSolutionsEui>> _openSolutionUis = new();
 
@@ -131,24 +132,57 @@ namespace Content.Server.Administration.Systems
                     args.Verbs.Add(prayerVerb);
 
                     // Freeze
-                    var frozen = HasComp<AdminFrozenComponent>(args.Target);
-                    args.Verbs.Add(new Verb
+                    var frozen = TryComp<AdminFrozenComponent>(args.Target, out var frozenComp);
+                    var frozenAndMuted = frozenComp?.Muted ?? false;
+
+                    if (!frozen)
                     {
-                        Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze.
-                        Text = frozen
-                            ? Loc.GetString("admin-verbs-unfreeze")
-                            : Loc.GetString("admin-verbs-freeze"),
-                        Category = VerbCategory.Admin,
-                        Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")),
-                        Act = () =>
+                        args.Verbs.Add(new Verb
                         {
-                            if (frozen)
-                                RemComp<AdminFrozenComponent>(args.Target);
-                            else
+                            Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze.
+                            Text = Loc.GetString("admin-verbs-freeze"),
+                            Category = VerbCategory.Admin,
+                            Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")),
+                            Act = () =>
+                            {
                                 EnsureComp<AdminFrozenComponent>(args.Target);
-                        },
-                        Impact = LogImpact.Medium,
-                    });
+                            },
+                            Impact = LogImpact.Medium,
+                        });
+                    }
+
+                    if (!frozenAndMuted)
+                    {
+                        // allow you to additionally mute someone when they are already frozen
+                        args.Verbs.Add(new Verb
+                        {
+                            Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze.
+                            Text = Loc.GetString("admin-verbs-freeze-and-mute"),
+                            Category = VerbCategory.Admin,
+                            Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")),
+                            Act = () =>
+                            {
+                                _freeze.FreezeAndMute(args.Target);
+                            },
+                            Impact = LogImpact.Medium,
+                        });
+                    }
+
+                    if (frozen)
+                    {
+                        args.Verbs.Add(new Verb
+                        {
+                            Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze.
+                            Text = Loc.GetString("admin-verbs-unfreeze"),
+                            Category = VerbCategory.Admin,
+                            Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")),
+                            Act = () =>
+                            {
+                                RemComp<AdminFrozenComponent>(args.Target);
+                            },
+                            Impact = LogImpact.Medium,
+                        });
+                    }
 
                     // Erase
                     args.Verbs.Add(new Verb
index c967ba78d7fa78f7c8c28d8276cf50503129ecdd..0c541b48b7ad7cef9ac862ee91ba8648e8df357f 100644 (file)
@@ -1,4 +1,5 @@
 using Content.Server.GameTicking;
+using Content.Server.Popups;
 using Content.Shared.Administration;
 using Content.Shared.Mind;
 using Robust.Shared.Console;
@@ -26,17 +27,27 @@ namespace Content.Server.Chat.Commands
             if (player.Status != SessionStatus.InGame || player.AttachedEntity == null)
                 return;
 
-            var minds = IoCManager.Resolve<IEntityManager>().System<SharedMindSystem>();
+            var entityManager = IoCManager.Resolve<IEntityManager>();
+            var minds = entityManager.System<SharedMindSystem>();
             // This check also proves mind not-null for at the end when the mob is ghosted.
             if (!minds.TryGetMind(player, out var mindId, out var mind) ||
                 mind.OwnedEntity is not { Valid: true } victim)
             {
-                shell.WriteLine("You don't have a mind!");
+                shell.WriteLine(Loc.GetString("suicide-command-no-mind"));
                 return;
             }
 
-            var gameTicker = EntitySystem.Get<GameTicker>();
-            var suicideSystem = EntitySystem.Get<SuicideSystem>();
+            if (entityManager.HasComponent<AdminFrozenComponent>(victim))
+            {
+                var deniedMessage = Loc.GetString("suicide-command-denied");
+                shell.WriteLine(deniedMessage);
+                entityManager.System<PopupSystem>()
+                    .PopupEntity(deniedMessage, victim, victim);
+                return;
+            }
+
+            var gameTicker = entityManager.System<GameTicker>();
+            var suicideSystem = entityManager.System<SuicideSystem>();
             if (suicideSystem.Suicide(victim))
             {
                 // Prevent the player from returning to the body.
@@ -48,7 +59,7 @@ namespace Content.Server.Chat.Commands
             if (gameTicker.OnGhostAttempt(mindId, true, mind: mind))
                 return;
 
-            shell.WriteLine("You can't ghost right now.");
+            shell.WriteLine(Loc.GetString("ghost-command-denied"));
         }
     }
 }
index 1453bf3faa9108ad527d582fa228b957ae269dcf..69d81d95929e8dbbd09341f8d4f05c52bf1058f2 100644 (file)
@@ -1,4 +1,5 @@
 using Content.Server.GameTicking;
+using Content.Server.Popups;
 using Content.Shared.Administration;
 using Content.Shared.Mind;
 using Robust.Shared.Console;
@@ -11,15 +12,25 @@ namespace Content.Server.Ghost
         [Dependency] private readonly IEntityManager _entities = default!;
 
         public string Command => "ghost";
-        public string Description => "Give up on life and become a ghost.";
-        public string Help => "ghost";
+        public string Description => Loc.GetString("ghost-command-description");
+        public string Help => Loc.GetString("ghost-command-help-text");
 
         public void Execute(IConsoleShell shell, string argStr, string[] args)
         {
             var player = shell.Player;
             if (player == null)
             {
-                shell.WriteLine("You have no session, you can't ghost.");
+                shell.WriteLine(Loc.GetString("ghost-command-no-session"));
+                return;
+            }
+
+            if (player.AttachedEntity is { Valid: true } frozen &&
+                _entities.HasComponent<AdminFrozenComponent>(frozen))
+            {
+                var deniedMessage = Loc.GetString("ghost-command-denied");
+                shell.WriteLine(deniedMessage);
+                _entities.System<PopupSystem>()
+                    .PopupEntity(deniedMessage, frozen, frozen);
                 return;
             }
 
@@ -30,9 +41,9 @@ namespace Content.Server.Ghost
                 mind = _entities.GetComponent<MindComponent>(mindId);
             }
 
-            if (!EntitySystem.Get<GameTicker>().OnGhostAttempt(mindId, true, true, mind))
+            if (!_entities.System<GameTicker>().OnGhostAttempt(mindId, true, true, mind))
             {
-                shell.WriteLine("You can't ghost right now.");
+                shell.WriteLine(Loc.GetString("ghost-command-denied"));
             }
         }
     }
index 164cf764c861d1ca8ba17c4d66992e2eada25181..bfcf1db5261ff7c212482e2412f19bff56913141 100644 (file)
@@ -2,8 +2,13 @@
 
 namespace Content.Shared.Administration;
 
-[RegisterComponent, Access(typeof(AdminFrozenSystem))]
-[NetworkedComponent]
+[RegisterComponent, Access(typeof(SharedAdminFrozenSystem))]
+[NetworkedComponent, AutoGenerateComponentState]
 public sealed partial class AdminFrozenComponent : Component
 {
+    /// <summary>
+    /// Whether the player is also muted.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public bool Muted;
 }
similarity index 78%
rename from Content.Shared/Administration/AdminFrozenSystem.cs
rename to Content.Shared/Administration/SharedAdminFrozenSystem.cs
index 4ec9600b0bdce2b987eb852dac1b2cd4eb4c70fe..2fa22e00052a154c89fecd365caa61f69d2bf0e6 100644 (file)
@@ -1,15 +1,17 @@
 using Content.Shared.ActionBlocker;
+using Content.Shared.Emoting;
 using Content.Shared.Interaction.Events;
 using Content.Shared.Item;
 using Content.Shared.Movement.Events;
 using Content.Shared.Movement.Pulling.Components;
 using Content.Shared.Movement.Pulling.Events;
 using Content.Shared.Movement.Pulling.Systems;
+using Content.Shared.Speech;
 using Content.Shared.Throwing;
 
 namespace Content.Shared.Administration;
 
-public sealed class AdminFrozenSystem : EntitySystem
+public abstract class SharedAdminFrozenSystem : EntitySystem
 {
     [Dependency] private readonly ActionBlockerSystem _blocker = default!;
     [Dependency] private readonly PullingSystem _pulling = default!;
@@ -28,6 +30,16 @@ public sealed class AdminFrozenSystem : EntitySystem
         SubscribeLocalEvent<AdminFrozenComponent, PullAttemptEvent>(OnPullAttempt);
         SubscribeLocalEvent<AdminFrozenComponent, AttackAttemptEvent>(OnAttempt);
         SubscribeLocalEvent<AdminFrozenComponent, ChangeDirectionAttemptEvent>(OnAttempt);
+        SubscribeLocalEvent<AdminFrozenComponent, EmoteAttemptEvent>(OnEmoteAttempt);
+        SubscribeLocalEvent<AdminFrozenComponent, SpeakAttemptEvent>(OnSpeakAttempt);
+    }
+
+    private void OnSpeakAttempt(EntityUid uid, AdminFrozenComponent component, SpeakAttemptEvent args)
+    {
+        if (!component.Muted)
+            return;
+
+        args.Cancel();
     }
 
     private void OnAttempt(EntityUid uid, AdminFrozenComponent component, CancellableEntityEventArgs args)
@@ -62,4 +74,10 @@ public sealed class AdminFrozenSystem : EntitySystem
     {
         _blocker.UpdateCanMove(uid);
     }
+
+    private void OnEmoteAttempt(EntityUid uid, AdminFrozenComponent component, EmoteAttemptEvent args)
+    {
+        if (component.Muted)
+            args.Cancel();
+    }
 }
index 03f92f7c420f01835c08d1c248bff7b5f17b7757..16715087ee4006b91d85a095c866777a022cd7c2 100644 (file)
@@ -6,6 +6,7 @@ admin-verbs-admin-logs-entity = Entity Logs
 admin-verbs-teleport-to = Teleport To
 admin-verbs-teleport-here = Teleport Here
 admin-verbs-freeze = Freeze
+admin-verbs-freeze-and-mute = Freeze And Mute
 admin-verbs-unfreeze = Unfreeze
 admin-verbs-erase = Erase
 admin-verbs-erase-description = Removes the player from the round and crew manifest and deletes their chat messages.
diff --git a/Resources/Locale/en-US/chat/commands/ghost-command.ftl b/Resources/Locale/en-US/chat/commands/ghost-command.ftl
new file mode 100644 (file)
index 0000000..08e78d3
--- /dev/null
@@ -0,0 +1,5 @@
+ghost-command-description = Give up on life and become a ghost.
+ghost-command-help-text = The ghost command turns you into a ghost and makes the character you played permanently catatonic.
+                          Please note that you cannot return to your character's body after ghosting.
+ghost-command-no-session = You have no session, you can't ghost.
+ghost-command-denied = You cannot ghost right now.
index 6748aa630cd2d6ebf79ce5ba985d19effdfdbc69..36e861169b873ce4841091b6b27b462842ead5d1 100644 (file)
@@ -6,3 +6,5 @@ suicide-command-help-text = The suicide command gives you a quick way out of a r
 suicide-command-default-text-others = {$name} is attempting to bite their own tongue!
 suicide-command-default-text-self = You attempt to bite your own tongue!
 suicide-command-already-dead = You can't suicide. You're dead.
+suicide-command-no-mind = You have no mind!
+suicide-command-denied = You cannot suicide right now.