space doafters, like doafters but in space (#16670)

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas
2023-06-03 19:33:41 +00:00
committed by GitHub
parent a2318532e0
commit 10932cc384
4 changed files with 30 additions and 12 deletions

View File

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

View File

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

View File

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

View File

@@ -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).