NPCs/Agent.Walk.cs
namespace Opium.AI;
partial class Agent
{
private Vector3? _walkTarget;
private Action _walkCallback;
public void WalkTo( Vector3 position, Action callback = null )
{
_walkTarget = position;
_walkCallback = callback;
}
public void CancelWalk()
{
WishMove = Vector3.Zero; // Stop moving if there's no target/path
_walkCallback?.Invoke();
_walkCallback = null;
_walkTarget = null;
}
private void UpdateWalk()
{
if ( _walkTarget == null )
{
CancelWalk();
return;
}
var path = GetPath( _walkTarget.Value! );
var targetIndex = 0;
for ( int i = 0; i < path.Count; ++i )
{
var pDist = path[i].Distance( Transform.Position );
var pDistRaised = path[i].WithZ( Transform.Position.z ).Distance( Transform.Position );
var zDist = MathF.Abs( path[i].z - Transform.Position.z );
if ( pDist > 4f )
{
if ( pDistRaised < 8 && zDist < 32 )
continue;
targetIndex = i;
break;
}
}
for ( int i = targetIndex; i < path.Count - 1; ++i )
{
var a = path[i];
var b = path[i + 1];
if ( StateMachine.DebugEnabled )
{
Gizmo.Draw.IgnoreDepth = true;
Gizmo.Draw.Line( a, b );
Gizmo.Draw.LineSphere( a, 4f );
}
}
if ( path.Count > 0 ) // Make sure the path is not empty
{
var target = path[targetIndex];
var globalDirection = (target - Transform.Position); // Global direction to the target
var distance = globalDirection.Length;
if ( distance > 0 ) // Make sure we're not already at the target
{
var localDirection = Transform.Rotation.Inverse * globalDirection; // Convert to local space
var direction = localDirection.Normal; // Normalize the direction
LookAt( target, 3f ); // Ensure the NPC looks at the target
WishMove = direction; // Move towards the target in local space
CheckForDoor( Transform.Position, target );
if ( StateMachine.DebugEnabled )
{
Gizmo.Draw.IgnoreDepth = true;
Gizmo.Draw.Color = Color.Green;
Gizmo.Draw.Arrow( Transform.Position, Transform.Position + (Transform.Rotation * localDirection) );
}
}
else
{
CancelWalk();
}
}
else
{
}
}
}