Skip to content

Commit

Permalink
NPC steering tweaks (#26351)
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
metalgearsloth authored Mar 23, 2024
1 parent 763d2bc commit 64b648f
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 18 deletions.
36 changes: 18 additions & 18 deletions Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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))
Expand Down
2 changes: 2 additions & 0 deletions Content.Server/NPC/Systems/NPCSteeringSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 64b648f

Please sign in to comment.