From 64b648ff3c5183393b28285909e6b62c2b66663e Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Sat, 23 Mar 2024 12:42:51 +1100 Subject: [PATCH] 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. --- .../NPC/Systems/NPCSteeringSystem.Context.cs | 36 +++++++++---------- .../NPC/Systems/NPCSteeringSystem.cs | 2 ++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs b/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs index c58dc261fefae2..5f871a6ecfa0b3 100644 --- a/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs +++ b/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs @@ -58,7 +58,7 @@ private bool IsFreeSpace( // 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,42 +158,42 @@ private bool TrySeek( } } + // Check if mapids match. + var targetMap = targetCoordinates.ToMap(EntityManager, _transform); + var ourMap = ourCoordinates.ToMap(EntityManager, _transform); + + if (targetMap.MapId != ourMap.MapId) + { + steering.Status = SteeringStatus.NoPath; + return false; + } + + 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. - float arrivalDistance; + 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. - arrivalDistance = steering.Range; + 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)) { - arrivalDistance = MathF.Max(0.05f, MathF.Min(node.Box.Width / 2f, node.Box.Height / 2f) - 0.05f); + arrived = node.Box.Contains(ourCoordinates.Position); } // Try getting into blocked range I guess? // TODO: Consider melee range or the likes. else { - arrivalDistance = SharedInteractionSystem.InteractionRange - 0.05f; + arrived = direction.Length() <= SharedInteractionSystem.InteractionRange - 0.05f; } - // Check if mapids match. - var targetMap = targetCoordinates.ToMap(EntityManager, _transform); - var ourMap = ourCoordinates.ToMap(EntityManager, _transform); - - if (targetMap.MapId != ourMap.MapId) - { - steering.Status = SteeringStatus.NoPath; - return false; - } - - var direction = targetMap.Position - ourMap.Position; - // 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)) diff --git a/Content.Server/NPC/Systems/NPCSteeringSystem.cs b/Content.Server/NPC/Systems/NPCSteeringSystem.cs index f9adbfa160fc45..153a1738555b78 100644 --- a/Content.Server/NPC/Systems/NPCSteeringSystem.cs +++ b/Content.Server/NPC/Systems/NPCSteeringSystem.cs @@ -274,6 +274,8 @@ private void SetDirection(InputMoverComponent component, NPCSteeringComponent st if (clear && value.Equals(Vector2.Zero)) { steering.CurrentPath.Clear(); + Array.Clear(steering.Interest); + Array.Clear(steering.Danger); } component.CurTickSprintMovement = value;