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;
|
public EntityCoordinates UserPosition;
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
[DataField("targetPosition")]
|
[DataField("targetDistance")]
|
||||||
public EntityCoordinates TargetPosition;
|
public float TargetDistance;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If <see cref="DoAfterArgs.NeedHand"/> is true, this is the hand that was selected when the doafter started.
|
/// 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;
|
CancelledTime = other.CancelledTime;
|
||||||
Completed = other.Completed;
|
Completed = other.Completed;
|
||||||
UserPosition = other.UserPosition;
|
UserPosition = other.UserPosition;
|
||||||
TargetPosition = other.TargetPosition;
|
TargetDistance = other.TargetDistance;
|
||||||
InitialHand = other.InitialHand;
|
InitialHand = other.InitialHand;
|
||||||
InitialItem = other.InitialItem;
|
InitialItem = other.InitialItem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,13 @@ public sealed class DoAfterArgs
|
|||||||
[DataField("breakOnUserMove")]
|
[DataField("breakOnUserMove")]
|
||||||
public bool 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>
|
/// <summary>
|
||||||
/// If do_after stops when the target moves (if there is a target)
|
/// If do_after stops when the target moves (if there is a target)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -219,6 +226,7 @@ public sealed class DoAfterArgs
|
|||||||
NeedHand = other.NeedHand;
|
NeedHand = other.NeedHand;
|
||||||
BreakOnHandChange = other.BreakOnHandChange;
|
BreakOnHandChange = other.BreakOnHandChange;
|
||||||
BreakOnUserMove = other.BreakOnUserMove;
|
BreakOnUserMove = other.BreakOnUserMove;
|
||||||
|
BreakOnWeightlessMove = other.BreakOnWeightlessMove;
|
||||||
BreakOnTargetMove = other.BreakOnTargetMove;
|
BreakOnTargetMove = other.BreakOnTargetMove;
|
||||||
MovementThreshold = other.MovementThreshold;
|
MovementThreshold = other.MovementThreshold;
|
||||||
DistanceThreshold = other.DistanceThreshold;
|
DistanceThreshold = other.DistanceThreshold;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Shared.Gravity;
|
||||||
using Content.Shared.Hands.Components;
|
using Content.Shared.Hands.Components;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
@@ -6,6 +7,7 @@ namespace Content.Shared.DoAfter;
|
|||||||
public abstract partial class SharedDoAfterSystem : EntitySystem
|
public abstract partial class SharedDoAfterSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IDynamicTypeFactory _factory = default!;
|
[Dependency] private readonly IDynamicTypeFactory _factory = default!;
|
||||||
|
[Dependency] private readonly SharedGravitySystem _gravity = default!;
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
@@ -151,18 +153,23 @@ public abstract partial class SharedDoAfterSystem : EntitySystem
|
|||||||
if (args.Used is { } @using && !xformQuery.TryGetComponent(@using, out usedXform))
|
if (args.Used is { } @using && !xformQuery.TryGetComponent(@using, out usedXform))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// TODO: Handle Inertia in space
|
|
||||||
// TODO: Re-use existing xform query for these calculations.
|
// TODO: Re-use existing xform query for these calculations.
|
||||||
if (args.BreakOnUserMove && !userXform.Coordinates
|
// when there is no gravity you will be drifting 99% of the time making many doafters impossible
|
||||||
.InRange(EntityManager, _transform, doAfter.UserPosition, args.MovementThreshold))
|
// 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;
|
return true;
|
||||||
|
|
||||||
if (args.BreakOnTargetMove)
|
if (args.BreakOnTargetMove)
|
||||||
{
|
{
|
||||||
DebugTools.Assert(targetXform != null, "Break on move is true, but no target specified?");
|
DebugTools.Assert(targetXform != null, "Break on move is true, but no target specified?");
|
||||||
if (targetXform != null && !targetXform.Coordinates.InRange(EntityManager, _transform,
|
if (targetXform != null && targetXform.Coordinates.TryDistance(EntityManager, userXform.Coordinates, out var distance))
|
||||||
doAfter.TargetPosition, args.MovementThreshold))
|
{
|
||||||
return true;
|
// 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))
|
if (args.AttemptFrequency == AttemptFrequency.EveryTick && !TryAttemptEvent(doAfter))
|
||||||
|
|||||||
@@ -193,12 +193,15 @@ public abstract partial class SharedDoAfterSystem : EntitySystem
|
|||||||
id = new DoAfterId(args.User, comp.NextId++);
|
id = new DoAfterId(args.User, comp.NextId++);
|
||||||
var doAfter = new DoAfter(id.Value.Index, args, GameTiming.CurTime);
|
var doAfter = new DoAfter(id.Value.Index, args, GameTiming.CurTime);
|
||||||
|
|
||||||
if (args.BreakOnUserMove)
|
if (args.BreakOnUserMove || args.BreakOnTargetMove)
|
||||||
doAfter.UserPosition = Transform(args.User).Coordinates;
|
doAfter.UserPosition = Transform(args.User).Coordinates;
|
||||||
|
|
||||||
if (args.Target != null && args.BreakOnTargetMove)
|
if (args.Target != null && args.BreakOnTargetMove)
|
||||||
|
{
|
||||||
// Target should never be null if the bool is set.
|
// 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
|
// 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).
|
// (or if there is no item there we need to keep it free).
|
||||||
|
|||||||
Reference in New Issue
Block a user