Skip to content

Commit

Permalink
Prevent admin-frozen players from ghosting or suiciding, add "Freeze …
Browse files Browse the repository at this point in the history
…And Mute" verb (#27813)

* 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 <[email protected]>

* Update Ghost.cs

* retrigger ci (empty commit)

---------

Co-authored-by: metalgearsloth <[email protected]>
  • Loading branch information
2 people authored and sleepyyapril committed Dec 21, 2024
1 parent a17c28a commit e061b5e
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 23 deletions.
7 changes: 7 additions & 0 deletions Content.Client/Administration/Systems/AdminFrozenSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using Content.Shared.Administration;

namespace Content.Client.Administration.Systems;

public sealed class AdminFrozenSystem : SharedAdminFrozenSystem
{
}
16 changes: 16 additions & 0 deletions Content.Server/Administration/Systems/AdminFrozenSystem.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
63 changes: 48 additions & 15 deletions Content.Server/Administration/Systems/AdminVerbSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,24 +137,57 @@ private void AddAdminVerbs(GetVerbsEvent<Verb> args)
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
Expand Down
2 changes: 2 additions & 0 deletions Content.Server/Chat/Commands/SuicideCommand.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Content.Server.GameTicking;
using Content.Server.Popups;
using Content.Server.Popups;
using Content.Shared.Administration;
using Content.Shared.Chat;
using Content.Shared.Mind;
Expand Down Expand Up @@ -55,6 +56,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args)
return;

shell.WriteLine(Loc.GetString("ghost-command-denied"));
shell.WriteLine(Loc.GetString("ghost-command-denied"));
}
}
}
21 changes: 16 additions & 5 deletions Content.Server/Ghost/Ghost.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Content.Server.GameTicking;
using Content.Server.Popups;
using Content.Shared.Administration;
using Content.Shared.Mind;
using Robust.Shared.Console;
Expand All @@ -11,15 +12,25 @@ public sealed class Ghost : IConsoleCommand
[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;
}

Expand All @@ -30,9 +41,9 @@ public void Execute(IConsoleShell shell, string argStr, string[] args)
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"));
}
}
}
Expand Down
9 changes: 7 additions & 2 deletions Content.Shared/Administration/AdminFrozenComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
@@ -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!;
Expand All @@ -28,6 +30,16 @@ public override void Initialize()
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)
Expand Down Expand Up @@ -62,4 +74,10 @@ private void UpdateCanMove(EntityUid uid, AdminFrozenComponent component, Entity
{
_blocker.UpdateCanMove(uid);
}

private void OnEmoteAttempt(EntityUid uid, AdminFrozenComponent component, EmoteAttemptEvent args)
{
if (component.Muted)
args.Cancel();
}
}
1 change: 1 addition & 0 deletions Resources/Locale/en-US/administration/admin-verbs.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions Resources/Locale/en-US/chat/commands/ghost-command.ftl
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/chat/commands/suicide-command.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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.

0 comments on commit e061b5e

Please sign in to comment.