Status Effects Toolshed (#41670)

* 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>
This commit is contained in:
Princess Cheeseballs
2025-12-30 13:41:57 -08:00
committed by GitHub
parent a41101e8da
commit 0b1e8a4bbc
4 changed files with 193 additions and 2 deletions

View File

@@ -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);
}
}

View File

@@ -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));
}
}

View 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 =

View 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.