]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Status Effects Toolshed (#41670)
authorPrincess Cheeseballs <66055347+Princess-Cheeseballs@users.noreply.github.com>
Tue, 30 Dec 2025 21:41:57 +0000 (13:41 -0800)
committerGitHub <noreply@github.com>
Tue, 30 Dec 2025 21:41:57 +0000 (21:41 +0000)
* toolshed :)

* Yeah they call me the gamer

* Fix test fails

* refactor: extract method ZeroAsNull

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru>
Content.Server/Toolshed/Commands/StatusEffects/StatusEffectCommand.cs [new file with mode: 0644]
Content.Server/Toolshed/TypeParsers/StatusEffects/StatusEffectCompletionParser.cs [new file with mode: 0644]
Content.Shared/StatusEffectNew/StatusEffectsSystem.cs
Resources/Locale/en-US/commands/toolshed-commands.ftl

diff --git a/Content.Server/Toolshed/Commands/StatusEffects/StatusEffectCommand.cs b/Content.Server/Toolshed/Commands/StatusEffects/StatusEffectCommand.cs
new file mode 100644 (file)
index 0000000..4182bac
--- /dev/null
@@ -0,0 +1,141 @@
+using Content.Server.Administration;
+using Content.Server.Toolshed.TypeParsers.StatusEffects;
+using Content.Shared.Administration;
+using Content.Shared.StatusEffectNew;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Toolshed;
+
+namespace Content.Server.Toolshed.Commands.StatusEffects;
+
+[ToolshedCommand, AdminCommand(AdminFlags.VarEdit)]
+public sealed class StatusEffectCommand : ToolshedCommand
+{
+    private StatusEffectsSystem? _statusEffectsSystem;
+
+    [CommandImplementation("add")]
+    public EntityUid? Add([PipedArgument] EntityUid input, [CommandArgument(typeof(StatusEffectCompletionParser))] EntProtoId status, float time, float delay = 0)
+    {
+        _statusEffectsSystem ??= GetSys<StatusEffectsSystem>();
+
+        _statusEffectsSystem.TryAddStatusEffectDuration(
+            input,
+            status,
+            TimeSpan.FromSeconds(time),
+            ZeroAsNull(delay));
+
+        return input;
+    }
+
+    [CommandImplementation("add")]
+    public IEnumerable<EntityUid> Add([PipedArgument] IEnumerable<EntityUid> input, [CommandArgument(typeof(StatusEffectCompletionParser))] EntProtoId status, float time, float delay = 0)
+    {
+        _statusEffectsSystem ??= GetSys<StatusEffectsSystem>();
+
+        foreach (var ent in input)
+        {
+            _statusEffectsSystem.TryAddStatusEffectDuration(
+                ent,
+                status,
+                TimeSpan.FromSeconds(time),
+                ZeroAsNull(delay));
+
+            yield return ent;
+        }
+    }
+
+    [CommandImplementation("update")]
+    public EntityUid? Update([PipedArgument] EntityUid input, [CommandArgument(typeof(StatusEffectCompletionParser))] EntProtoId status, float time, float delay = 0)
+    {
+        _statusEffectsSystem ??= GetSys<StatusEffectsSystem>();
+
+        _statusEffectsSystem.TryUpdateStatusEffectDuration(
+            input,
+            status,
+            ZeroAsNull(time),
+            ZeroAsNull(delay));
+
+        return input;
+    }
+
+    [CommandImplementation("update")]
+    public IEnumerable<EntityUid> Update([PipedArgument] IEnumerable<EntityUid> input, [CommandArgument(typeof(StatusEffectCompletionParser))] EntProtoId status, float time, float delay = 0)
+    {
+        _statusEffectsSystem ??= GetSys<StatusEffectsSystem>();
+
+        foreach (var ent in input)
+        {
+            _statusEffectsSystem.TryUpdateStatusEffectDuration(
+                ent,
+                status,
+                ZeroAsNull(time),
+                ZeroAsNull(delay));
+
+            yield return ent;
+        }
+    }
+
+    [CommandImplementation("set")]
+    public EntityUid? Set([PipedArgument] EntityUid input, [CommandArgument(typeof(StatusEffectCompletionParser))] EntProtoId status, float time = 0, float delay = 0)
+    {
+        _statusEffectsSystem ??= GetSys<StatusEffectsSystem>();
+
+        _statusEffectsSystem.TrySetStatusEffectDuration(
+            input,
+            status,
+            ZeroAsNull(time),
+            ZeroAsNull(delay));
+
+        return input;
+    }
+
+    [CommandImplementation("set")]
+    public IEnumerable<EntityUid> Set([PipedArgument] IEnumerable<EntityUid> input, [CommandArgument(typeof(StatusEffectCompletionParser))] EntProtoId status, float time = 0, float delay = 0)
+    {
+        _statusEffectsSystem ??= GetSys<StatusEffectsSystem>();
+
+        foreach (var ent in input)
+        {
+            _statusEffectsSystem.TrySetStatusEffectDuration(
+                ent,
+                status,
+                ZeroAsNull(time),
+                ZeroAsNull(delay));
+
+            yield return ent;
+        }
+    }
+
+    [CommandImplementation("remove")]
+    public EntityUid? Remove([PipedArgument] EntityUid input, [CommandArgument(typeof(StatusEffectCompletionParser))] EntProtoId status, float time = 0)
+    {
+        _statusEffectsSystem ??= GetSys<StatusEffectsSystem>();
+
+        _statusEffectsSystem.TryRemoveTime(
+            input,
+            status,
+            ZeroAsNull(time));
+
+        return input;
+    }
+
+    [CommandImplementation("remove")]
+    public IEnumerable<EntityUid> Remove([PipedArgument] IEnumerable<EntityUid> input, [CommandArgument(typeof(StatusEffectCompletionParser))] EntProtoId status, float time = 0)
+    {
+        _statusEffectsSystem ??= GetSys<StatusEffectsSystem>();
+
+        foreach (var ent in input)
+        {
+            _statusEffectsSystem.TryRemoveTime(
+                ent,
+                status,
+                ZeroAsNull(time));
+
+            yield return ent;
+        }
+    }
+
+    private static TimeSpan? ZeroAsNull(float delay)
+    {
+        return delay == 0 ? null : TimeSpan.FromSeconds(delay);
+    }
+}
diff --git a/Content.Server/Toolshed/TypeParsers/StatusEffects/StatusEffectCompletionParser.cs b/Content.Server/Toolshed/TypeParsers/StatusEffects/StatusEffectCompletionParser.cs
new file mode 100644 (file)
index 0000000..7faa782
--- /dev/null
@@ -0,0 +1,16 @@
+using Content.Shared.StatusEffectNew;
+using Robust.Shared.Console;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Toolshed;
+using Robust.Shared.Toolshed.Syntax;
+using Robust.Shared.Toolshed.TypeParsers;
+
+namespace Content.Server.Toolshed.TypeParsers.StatusEffects;
+
+public sealed class StatusEffectCompletionParser : CustomCompletionParser<EntProtoId>
+{
+    public override CompletionResult? TryAutocomplete(ParserContext ctx, CommandArgument? arg)
+    {
+        return CompletionResult.FromHintOptions(StatusEffectsSystem.StatusEffectPrototypes, GetArgHint(arg));
+    }
+}
index 82915b002a60ff237feb0b230d7d70f12ff1afb1..1c650e5e4cfeda7793837e28f4f6f677a02cd81b 100644 (file)
@@ -14,6 +14,7 @@ namespace Content.Shared.StatusEffectNew;
 /// </summary>
 public sealed partial class StatusEffectsSystem : EntitySystem
 {
+    [Dependency] private readonly IComponentFactory _factory = default!;
     [Dependency] private readonly IGameTiming _timing = default!;
     [Dependency] private readonly SharedContainerSystem _container = default!;
     [Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
@@ -22,6 +23,8 @@ public sealed partial class StatusEffectsSystem : EntitySystem
     private EntityQuery<StatusEffectContainerComponent> _containerQuery;
     private EntityQuery<StatusEffectComponent> _effectQuery;
 
+    public static HashSet<string> StatusEffectPrototypes = [];
+
     public override void Initialize()
     {
         base.Initialize();
@@ -35,8 +38,12 @@ public sealed partial class StatusEffectsSystem : EntitySystem
 
         SubscribeLocalEvent<RejuvenateRemovedStatusEffectComponent, StatusEffectRelayedEvent<RejuvenateEvent>>(OnRejuvenate);
 
+        SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReloaded);
+
         _containerQuery = GetEntityQuery<StatusEffectContainerComponent>();
         _effectQuery = GetEntityQuery<StatusEffectComponent>();
+
+        ReloadStatusEffectsCache();
     }
 
     public override void Update(float frameTime)
@@ -61,6 +68,25 @@ public sealed partial class StatusEffectsSystem : EntitySystem
         }
     }
 
+    private void OnPrototypesReloaded(PrototypesReloadedEventArgs args)
+    {
+        if (!args.WasModified<EntityPrototype>())
+            return;
+
+        ReloadStatusEffectsCache();
+    }
+
+    private void ReloadStatusEffectsCache()
+    {
+        StatusEffectPrototypes.Clear();
+
+        foreach (var ent in _proto.EnumeratePrototypes<EntityPrototype>())
+        {
+            if (ent.TryGetComponent<StatusEffectComponent>(out _, _factory))
+                StatusEffectPrototypes.Add(ent.ID);
+        }
+    }
+
     private void OnStatusContainerInit(Entity<StatusEffectContainerComponent> ent, ref ComponentInit args)
     {
         ent.Comp.ActiveStatusEffects =
index 85eae1ef3da2418ac18d9a2e3566646717c66218..bfd2f780b1a9d29c0d4298be759cae9d2d8b8640 100644 (file)
@@ -6,9 +6,9 @@ command-description-acmd-perms =
     Returns the admin permissions of the given command, if any.
 command-description-acmd-caninvoke =
     Check if the given player can invoke the given command.
-command-description-bank-accounts = 
+command-description-bank-accounts =
     Returns all accounts on a station.
-command-description-bank-account = 
+command-description-bank-account =
     Returns a given bank account from a station.
 command-description-bank-adjust =
     Adjusts the money for the given bank account.
@@ -166,3 +166,11 @@ command-description-dynamicrule-executenow =
     Executes the piped dynamic rule as if it had reached its regular update time.
 command-description-dynamicrule-rules =
     Gets a list of all the rules spawned by the piped dynamic rule.
+command-description-statuseffect-add =
+    Adds time in seconds to a given status effect's duration, or creates one with a duration equal to time.
+command-description-statuseffect-update =
+    Sets the duration of a status effect to the higher of the inputted time or existing time. If time is 0, duration will be infinite.
+command-description-statuseffect-set =
+    Sets the duration of a status effect to the inputted time in seconds. If time is 0, duration will be infinite.
+command-description-statuseffect-remove =
+    Removes a time from a given status effect by prototype. If time isn't set, removes the status effect.