Add post-checks for do_after (#1940)
* Add post-checks for do_after So you can do InRangeUnobstructed or whatever at the end. Individual components should do their own check upfront to avoid the state ever being sent. I added a pre-made function for people to do InRangeUnobstructed. * Woops imports Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.GameObjects.Components.Damage;
|
|
||||||
using Content.Server.GameObjects.Components.GUI;
|
using Content.Server.GameObjects.Components.GUI;
|
||||||
using Content.Server.GameObjects.Components.Items.Storage;
|
using Content.Server.GameObjects.Components.Items.Storage;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
@@ -86,7 +85,16 @@ namespace Content.Server.GameObjects.EntitySystems.DoAfter
|
|||||||
|
|
||||||
if (IsFinished())
|
if (IsFinished())
|
||||||
{
|
{
|
||||||
Tcs.SetResult(DoAfterStatus.Finished);
|
// Do the final checks here
|
||||||
|
if (!TryPostCheck())
|
||||||
|
{
|
||||||
|
Tcs.SetResult(DoAfterStatus.Cancelled);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Tcs.SetResult(DoAfterStatus.Finished);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +106,11 @@ namespace Content.Server.GameObjects.EntitySystems.DoAfter
|
|||||||
|
|
||||||
private bool IsCancelled()
|
private bool IsCancelled()
|
||||||
{
|
{
|
||||||
|
if (EventArgs.User.Deleted || EventArgs.Target?.Deleted == true)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//https://github.com/tgstation/tgstation/blob/1aa293ea337283a0191140a878eeba319221e5df/code/__HELPERS/mobs.dm
|
//https://github.com/tgstation/tgstation/blob/1aa293ea337283a0191140a878eeba319221e5df/code/__HELPERS/mobs.dm
|
||||||
if (EventArgs.CancelToken.IsCancellationRequested)
|
if (EventArgs.CancelToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -157,10 +170,15 @@ namespace Content.Server.GameObjects.EntitySystems.DoAfter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryPostCheck()
|
||||||
|
{
|
||||||
|
return EventArgs.PostCheck?.Invoke() != false;
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsFinished()
|
private bool IsFinished()
|
||||||
{
|
{
|
||||||
if (Elapsed <= EventArgs.Delay)
|
if (Elapsed <= EventArgs.Delay)
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Physics;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
|
||||||
// ReSharper disable UnassignedReadonlyField
|
// ReSharper disable UnassignedReadonlyField
|
||||||
@@ -9,6 +12,18 @@ namespace Content.Server.GameObjects.EntitySystems.DoAfter
|
|||||||
{
|
{
|
||||||
public sealed class DoAfterEventArgs
|
public sealed class DoAfterEventArgs
|
||||||
{
|
{
|
||||||
|
// Premade checks
|
||||||
|
public Func<bool> GetInRangeUnobstructed(int collisionMask = (int) CollisionGroup.MobMask)
|
||||||
|
{
|
||||||
|
if (Target == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Can't supply a null target to DoAfterEventArgs.GetInRangeUnobstructed");
|
||||||
|
}
|
||||||
|
var interactionSystem = EntitySystem.Get<SharedInteractionSystem>();
|
||||||
|
Func<IEntity, bool> ignored = entity => entity == User || entity == Target;
|
||||||
|
return () => interactionSystem.InRangeUnobstructed(User.Transform.MapPosition, Target.Transform.MapPosition, collisionMask: collisionMask, predicate: ignored);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entity invoking do_after
|
/// The entity invoking do_after
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -49,6 +64,14 @@ namespace Content.Server.GameObjects.EntitySystems.DoAfter
|
|||||||
public bool BreakOnDamage { get; set; }
|
public bool BreakOnDamage { get; set; }
|
||||||
public bool BreakOnStun { get; set; }
|
public bool BreakOnStun { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Requires a function call once at the end (like InRangeUnobstructed).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Anything that needs a pre-check should do it itself so no DoAfterState is ever sent to the client.
|
||||||
|
/// </remarks>
|
||||||
|
public Func<bool>? PostCheck { get; set; } = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Additional conditions that need to be met. Return false to cancel.
|
/// Additional conditions that need to be met. Return false to cancel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user