Files
tbd-station-14/Content.Shared/Actions/SharedActionsSystem.DoAfter.cs
keronshb f885075d2e DoAfter support for Actions (#38253)
* Adds Action DoAfter Events

* Adds DoAfterArgs fields to DoAfterComp

* Adds a base doafter action

* Adds Attempt action doafter logic

* Adds doafter logic to actions

* Changes Action Attempt Doafter and action doafter to take in Performer and the original use delay. Use delay now triggers when a repeated action  is cancelled.

* Readds the TryPerformAction method and readds request perform action into the action doafter events

* Adds a force skip to DoAfter Cancel so we can skip the complete check

* Adds a Delay Reduction field to the comp and to the comp state

* Fixes doafter mispredict, changes doafter comp check to a guard clause, sets delay reduction if it exists.

* Cancels ActionDoAfter if charges is 0

* Serializes Attempt Frequency

* Comment for rework

* Changes todo into a comment

* Moves doafterargs to doafterargscomp

* Adds DoAfterArgs comp to BaseDoAfterAction

* Removes unused trycomp with actionDoAfter

* Replaces DoAfterRepateUseDelay const with timespan.zero

* Removes unused usings

* Makes SharedActionsSystem partial, adds DoAfter partial class to ActionSystem, moves ActionDoAfter logic to the SharedActionsSystem.DoAfter class

* Cleanup and prediction

* Renames OnActionDoAfterAttempt to OnActionDoAfter, moves both to Shared Action DoAfter

* Removes ActionAttemptDoAfterEvent and moves its summaries to ActionDoAfterEvent. Converts OnActionDoAfterAttempt into TryStartActionDoAfter

* Removes Extra check for charges and actiondoafters

* Sloptimization

* Cleanup

* Cleanup

* Adds param descs

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
2025-09-08 12:55:13 +03:00

86 lines
2.9 KiB
C#

using Content.Shared.Actions.Events;
using Content.Shared.DoAfter;
namespace Content.Shared.Actions;
public abstract partial class SharedActionsSystem
{
protected void InitializeActionDoAfter()
{
SubscribeLocalEvent<DoAfterArgsComponent, ActionDoAfterEvent>(OnActionDoAfter);
}
private bool TryStartActionDoAfter(Entity<DoAfterArgsComponent> ent, Entity<DoAfterComponent?> performer, TimeSpan? originalUseDelay, RequestPerformActionEvent input)
{
// relay to user
if (!Resolve(performer, ref performer.Comp))
return false;
var delay = ent.Comp.Delay;
var netEnt = GetNetEntity(performer);
var actionDoAfterEvent = new ActionDoAfterEvent(netEnt, originalUseDelay, input);
var doAfterArgs = new DoAfterArgs(EntityManager, performer, delay, actionDoAfterEvent, ent.Owner, performer)
{
AttemptFrequency = ent.Comp.AttemptFrequency,
Broadcast = ent.Comp.Broadcast,
Hidden = ent.Comp.Hidden,
NeedHand = ent.Comp.NeedHand,
BreakOnHandChange = ent.Comp.BreakOnHandChange,
BreakOnDropItem = ent.Comp.BreakOnDropItem,
BreakOnMove = ent.Comp.BreakOnMove,
BreakOnWeightlessMove = ent.Comp.BreakOnWeightlessMove,
MovementThreshold = ent.Comp.MovementThreshold,
DistanceThreshold = ent.Comp.DistanceThreshold,
BreakOnDamage = ent.Comp.BreakOnDamage,
DamageThreshold = ent.Comp.DamageThreshold,
RequireCanInteract = ent.Comp.RequireCanInteract
};
return _doAfter.TryStartDoAfter(doAfterArgs, performer);
}
private void OnActionDoAfter(Entity<DoAfterArgsComponent> ent, ref ActionDoAfterEvent args)
{
if (!_actionQuery.TryComp(ent, out var actionComp))
return;
var performer = GetEntity(args.Performer);
var action = (ent, actionComp);
// If this doafter is on repeat and was cancelled, start use delay as expected
if (args.Cancelled && ent.Comp.Repeat)
{
SetUseDelay(action, args.OriginalUseDelay);
RemoveCooldown(action);
StartUseDelay(action);
UpdateAction(action);
return;
}
args.Repeat = ent.Comp.Repeat;
// Set the use delay to 0 so this can repeat properly
if (ent.Comp.Repeat)
{
SetUseDelay(action, TimeSpan.Zero);
}
if (args.Cancelled)
return;
// Post original doafter, reduce the time on it now for other casts if ables
if (ent.Comp.DelayReduction != null)
args.Args.Delay = ent.Comp.DelayReduction.Value;
// Validate again for charges, blockers, etc
if (TryPerformAction(args.Input, performer, skipDoActionRequest: true))
return;
// Cancel this doafter if we can't validate the action
_doAfter.Cancel(args.DoAfter.Id, force: true);
}
}