Add pathfinding support for NPCs climbing tables (#17415)

This commit is contained in:
Vordenburg
2023-07-28 02:37:29 -04:00
committed by GitHub
parent 494b9e5b93
commit 49f3f07e30
11 changed files with 114 additions and 15 deletions

View File

@@ -3,6 +3,7 @@ using System.Numerics;
using Content.Server.Examine;
using Content.Server.NPC.Components;
using Content.Server.NPC.Pathfinding;
using Content.Shared.Climbing;
using Content.Shared.Interaction;
using Content.Shared.Movement.Components;
using Content.Shared.NPC;
@@ -35,6 +36,30 @@ public sealed partial class NPCSteeringSystem
#region Seek
/// <summary>
/// Takes into account agent-specific context that may allow it to bypass a node which is not FreeSpace.
/// </summary>
private bool IsFreeSpace(
EntityUid uid,
NPCSteeringComponent steering,
PathPoly node)
{
if (node.Data.IsFreeSpace)
{
return true;
}
// Handle the case where the node is a climb, we can climb, and we are climbing.
else if ((node.Data.Flags & PathfindingBreadcrumbFlag.Climb) != 0x0 &&
(steering.Flags & PathFlags.Climbing) != 0x0 &&
TryComp<ClimbingComponent>(uid, out var climbing) &&
climbing.IsClimbing)
{
return true;
}
return false;
}
/// <summary>
/// Attempts to head to the target destination, either via the next pathfinding node or the final target.
/// </summary>
@@ -90,7 +115,7 @@ public sealed partial class NPCSteeringSystem
}
// If next node is a free tile then get within its bounds.
// This is to avoid popping it too early
else if (steering.CurrentPath.TryPeek(out var node) && node.Data.IsFreeSpace)
else if (steering.CurrentPath.TryPeek(out var node) && IsFreeSpace(uid, steering, node))
{
arrivalDistance = MathF.Min(node.Box.Width / 2f, node.Box.Height / 2f) - 0.01f;
}
@@ -117,7 +142,7 @@ public sealed partial class NPCSteeringSystem
if (direction.Length() <= arrivalDistance)
{
// Node needs some kind of special handling like access or smashing.
if (steering.CurrentPath.TryPeek(out var node) && !node.Data.IsFreeSpace)
if (steering.CurrentPath.TryPeek(out var node) && !IsFreeSpace(uid, steering, node))
{
// Ignore stuck while handling obstacles.
ResetStuck(steering, ourCoordinates);