space doafters, like doafters but in space (#16670)
Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
@@ -48,10 +48,10 @@ public sealed class DoAfter
|
||||
public EntityCoordinates UserPosition;
|
||||
|
||||
/// <summary>
|
||||
/// Position of the target relative to their parent when the do after was started.
|
||||
/// Distance from the user to the target when the do after was started.
|
||||
/// </summary>
|
||||
[DataField("targetPosition")]
|
||||
public EntityCoordinates TargetPosition;
|
||||
[DataField("targetDistance")]
|
||||
public float TargetDistance;
|
||||
|
||||
/// <summary>
|
||||
/// If <see cref="DoAfterArgs.NeedHand"/> is true, this is the hand that was selected when the doafter started.
|
||||
@@ -94,7 +94,7 @@ public sealed class DoAfter
|
||||
CancelledTime = other.CancelledTime;
|
||||
Completed = other.Completed;
|
||||
UserPosition = other.UserPosition;
|
||||
TargetPosition = other.TargetPosition;
|
||||
TargetDistance = other.TargetDistance;
|
||||
InitialHand = other.InitialHand;
|
||||
InitialItem = other.InitialItem;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,13 @@ public sealed class DoAfterArgs
|
||||
[DataField("breakOnUserMove")]
|
||||
public bool BreakOnUserMove;
|
||||
|
||||
/// <summary>
|
||||
/// If this is true then any movement, even when weightless, will break the doafter.
|
||||
/// When there is no gravity, BreakOnUserMove is ignored. If it is false to begin with nothing will change.
|
||||
/// </summary>
|
||||
[DataField("breakOnWeightlessMove")]
|
||||
public bool BreakOnWeightlessMove;
|
||||
|
||||
/// <summary>
|
||||
/// If do_after stops when the target moves (if there is a target)
|
||||
/// </summary>
|
||||
@@ -219,6 +226,7 @@ public sealed class DoAfterArgs
|
||||
NeedHand = other.NeedHand;
|
||||
BreakOnHandChange = other.BreakOnHandChange;
|
||||
BreakOnUserMove = other.BreakOnUserMove;
|
||||
BreakOnWeightlessMove = other.BreakOnWeightlessMove;
|
||||
BreakOnTargetMove = other.BreakOnTargetMove;
|
||||
MovementThreshold = other.MovementThreshold;
|
||||
DistanceThreshold = other.DistanceThreshold;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared.Gravity;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -6,6 +7,7 @@ namespace Content.Shared.DoAfter;
|
||||
public abstract partial class SharedDoAfterSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IDynamicTypeFactory _factory = default!;
|
||||
[Dependency] private readonly SharedGravitySystem _gravity = default!;
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
@@ -151,19 +153,24 @@ public abstract partial class SharedDoAfterSystem : EntitySystem
|
||||
if (args.Used is { } @using && !xformQuery.TryGetComponent(@using, out usedXform))
|
||||
return true;
|
||||
|
||||
// TODO: Handle Inertia in space
|
||||
// TODO: Re-use existing xform query for these calculations.
|
||||
if (args.BreakOnUserMove && !userXform.Coordinates
|
||||
.InRange(EntityManager, _transform, doAfter.UserPosition, args.MovementThreshold))
|
||||
// when there is no gravity you will be drifting 99% of the time making many doafters impossible
|
||||
// so this just ignores your movement if you are weightless (unless the doafter sets BreakOnWeightlessMove then moving will still break it)
|
||||
if (args.BreakOnUserMove
|
||||
&& !userXform.Coordinates.InRange(EntityManager, _transform, doAfter.UserPosition, args.MovementThreshold)
|
||||
&& (args.BreakOnWeightlessMove || !_gravity.IsWeightless(args.User, xform: userXform)))
|
||||
return true;
|
||||
|
||||
if (args.BreakOnTargetMove)
|
||||
{
|
||||
DebugTools.Assert(targetXform != null, "Break on move is true, but no target specified?");
|
||||
if (targetXform != null && !targetXform.Coordinates.InRange(EntityManager, _transform,
|
||||
doAfter.TargetPosition, args.MovementThreshold))
|
||||
if (targetXform != null && targetXform.Coordinates.TryDistance(EntityManager, userXform.Coordinates, out var distance))
|
||||
{
|
||||
// once the target moves too far from you the do after breaks
|
||||
if (Math.Abs(distance - doAfter.TargetDistance) > args.MovementThreshold)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.AttemptFrequency == AttemptFrequency.EveryTick && !TryAttemptEvent(doAfter))
|
||||
return true;
|
||||
|
||||
@@ -193,12 +193,15 @@ public abstract partial class SharedDoAfterSystem : EntitySystem
|
||||
id = new DoAfterId(args.User, comp.NextId++);
|
||||
var doAfter = new DoAfter(id.Value.Index, args, GameTiming.CurTime);
|
||||
|
||||
if (args.BreakOnUserMove)
|
||||
if (args.BreakOnUserMove || args.BreakOnTargetMove)
|
||||
doAfter.UserPosition = Transform(args.User).Coordinates;
|
||||
|
||||
if (args.Target != null && args.BreakOnTargetMove)
|
||||
{
|
||||
// Target should never be null if the bool is set.
|
||||
doAfter.TargetPosition = Transform(args.Target.Value).Coordinates;
|
||||
var targetPosition = Transform(args.Target.Value).Coordinates;
|
||||
doAfter.UserPosition.TryDistance(EntityManager, targetPosition, out doAfter.TargetDistance);
|
||||
}
|
||||
|
||||
// For this we need to stay on the same hand slot and need the same item in that hand slot
|
||||
// (or if there is no item there we need to keep it free).
|
||||
|
||||
Reference in New Issue
Block a user