NPC steering tweaks (#26351)

- Fix the free node check considering the whole tile and not the poly.
- Clear maps on direction resets.
- More robust arrival checks for pathfinding nodes.
This commit is contained in:
metalgearsloth
2024-03-23 12:42:51 +11:00
committed by GitHub
parent 763d2bca9c
commit 64b648ff3c
2 changed files with 26 additions and 24 deletions

View File

@@ -58,7 +58,7 @@ public sealed partial class NPCSteeringSystem
// TODO: Ideally for "FreeSpace" we check all entities on the tile and build flags dynamically (pathfinder refactor in future).
var ents = _entSetPool.Get();
_lookup.GetLocalEntitiesIntersecting(node.GraphUid, node.ChunkOrigin, ents, flags: LookupFlags.Static);
_lookup.GetLocalEntitiesIntersecting(node.GraphUid, node.Box.Enlarged(-0.04f), ents, flags: LookupFlags.Static);
var result = true;
if (ents.Count > 0)
@@ -158,28 +158,6 @@ public sealed partial class NPCSteeringSystem
}
}
// Need to be pretty close if it's just a node to make sure LOS for door bashes or the likes.
float arrivalDistance;
if (targetCoordinates.Equals(steering.Coordinates))
{
// What's our tolerance for arrival.
// If it's a pathfinding node it might be different to the destination.
arrivalDistance = steering.Range;
}
// 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) && IsFreeSpace(uid, steering, node))
{
arrivalDistance = MathF.Max(0.05f, MathF.Min(node.Box.Width / 2f, node.Box.Height / 2f) - 0.05f);
}
// Try getting into blocked range I guess?
// TODO: Consider melee range or the likes.
else
{
arrivalDistance = SharedInteractionSystem.InteractionRange - 0.05f;
}
// Check if mapids match.
var targetMap = targetCoordinates.ToMap(EntityManager, _transform);
var ourMap = ourCoordinates.ToMap(EntityManager, _transform);
@@ -192,8 +170,30 @@ public sealed partial class NPCSteeringSystem
var direction = targetMap.Position - ourMap.Position;
// Need to be pretty close if it's just a node to make sure LOS for door bashes or the likes.
bool arrived;
if (targetCoordinates.Equals(steering.Coordinates))
{
// What's our tolerance for arrival.
// If it's a pathfinding node it might be different to the destination.
arrived = direction.Length() <= steering.Range;
}
// 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) && IsFreeSpace(uid, steering, node))
{
arrived = node.Box.Contains(ourCoordinates.Position);
}
// Try getting into blocked range I guess?
// TODO: Consider melee range or the likes.
else
{
arrived = direction.Length() <= SharedInteractionSystem.InteractionRange - 0.05f;
}
// Are we in range
if (direction.Length() <= arrivalDistance)
if (arrived)
{
// Node needs some kind of special handling like access or smashing.
if (steering.CurrentPath.TryPeek(out var node) && !IsFreeSpace(uid, steering, node))