mirror of
https://github.com/runuo/runuo
synced 2026-08-11 22:26:04 -04:00
Convert movement, actions (lift/use), combat, and spells to use Core.TickCount and avoid DateTime caveats (performance, system time dependency, etc) Refactor DateTime.Now to DateTime.UtcNow Add LOS check for Iron Maiden addon
204 lines
No EOL
3.8 KiB
C#
204 lines
No EOL
3.8 KiB
C#
using System;
|
|
using Server;
|
|
using Server.Movement;
|
|
using CalcMoves = Server.Movement.Movement;
|
|
|
|
namespace Server
|
|
{
|
|
public class PathFollower
|
|
{
|
|
// Should we use pathfinding? 'false' for not
|
|
private static bool Enabled = true;
|
|
|
|
private Mobile m_From;
|
|
private IPoint3D m_Goal;
|
|
private MovementPath m_Path;
|
|
private int m_Index;
|
|
private Point3D m_Next, m_LastGoalLoc;
|
|
private DateTime m_LastPathTime;
|
|
private MoveMethod m_Mover;
|
|
|
|
public MoveMethod Mover
|
|
{
|
|
get{ return m_Mover; }
|
|
set{ m_Mover = value; }
|
|
}
|
|
|
|
public IPoint3D Goal
|
|
{
|
|
get{ return m_Goal; }
|
|
}
|
|
|
|
public PathFollower( Mobile from, IPoint3D goal )
|
|
{
|
|
m_From = from;
|
|
m_Goal = goal;
|
|
}
|
|
|
|
public MoveResult Move( Direction d )
|
|
{
|
|
if ( m_Mover == null )
|
|
return ( m_From.Move( d ) ? MoveResult.Success : MoveResult.Blocked );
|
|
|
|
return m_Mover( d );
|
|
}
|
|
|
|
public Point3D GetGoalLocation()
|
|
{
|
|
if ( m_Goal is Item )
|
|
return ((Item)m_Goal).GetWorldLocation();
|
|
|
|
return new Point3D( m_Goal );
|
|
}
|
|
|
|
private static TimeSpan RepathDelay = TimeSpan.FromSeconds( 2.0 );
|
|
|
|
public void Advance( ref Point3D p, int index )
|
|
{
|
|
if ( m_Path != null && m_Path.Success )
|
|
{
|
|
Direction[] dirs = m_Path.Directions;
|
|
|
|
if ( index >= 0 && index < dirs.Length )
|
|
{
|
|
int x = p.X, y = p.Y;
|
|
|
|
CalcMoves.Offset( dirs[index], ref x, ref y );
|
|
|
|
p.X = x;
|
|
p.Y = y;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void ForceRepath()
|
|
{
|
|
m_Path = null;
|
|
}
|
|
|
|
public bool CheckPath()
|
|
{
|
|
if ( !Enabled )
|
|
return false;
|
|
|
|
bool repath = false;
|
|
|
|
Point3D goal = GetGoalLocation();
|
|
|
|
if ( m_Path == null )
|
|
repath = true;
|
|
else if ( (!m_Path.Success || goal != m_LastGoalLoc) && (m_LastPathTime + RepathDelay) <= DateTime.UtcNow )
|
|
repath = true;
|
|
else if ( m_Path.Success && Check( m_From.Location, m_LastGoalLoc, 0 ) )
|
|
repath = true;
|
|
|
|
if ( !repath )
|
|
return false;
|
|
|
|
m_LastPathTime = DateTime.UtcNow;
|
|
m_LastGoalLoc = goal;
|
|
|
|
m_Path = new MovementPath( m_From, goal );
|
|
|
|
m_Index = 0;
|
|
m_Next = m_From.Location;
|
|
|
|
Advance( ref m_Next, m_Index );
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool Check( Point3D loc, Point3D goal, int range )
|
|
{
|
|
if ( !Utility.InRange( loc, goal, range ) )
|
|
return false;
|
|
|
|
if ( range <= 1 && Math.Abs( loc.Z - goal.Z ) >= 16 )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool Follow( bool run, int range )
|
|
{
|
|
Point3D goal = GetGoalLocation();
|
|
Direction d;
|
|
|
|
if ( Check( m_From.Location, goal, range ) )
|
|
return true;
|
|
|
|
bool repathed = CheckPath();
|
|
|
|
if ( !Enabled || !m_Path.Success )
|
|
{
|
|
d = m_From.GetDirectionTo( goal );
|
|
|
|
if ( run )
|
|
d |= Direction.Running;
|
|
|
|
m_From.SetDirection( d );
|
|
Move( d );
|
|
|
|
return Check( m_From.Location, goal, range );
|
|
}
|
|
|
|
d = m_From.GetDirectionTo( m_Next );
|
|
|
|
if ( run )
|
|
d |= Direction.Running;
|
|
|
|
m_From.SetDirection( d );
|
|
|
|
MoveResult res = Move( d );
|
|
|
|
if ( res == MoveResult.Blocked )
|
|
{
|
|
if ( repathed )
|
|
return false;
|
|
|
|
m_Path = null;
|
|
CheckPath();
|
|
|
|
if ( !m_Path.Success )
|
|
{
|
|
d = m_From.GetDirectionTo( goal );
|
|
|
|
if ( run )
|
|
d |= Direction.Running;
|
|
|
|
m_From.SetDirection( d );
|
|
Move( d );
|
|
|
|
return Check( m_From.Location, goal, range );
|
|
}
|
|
|
|
d = m_From.GetDirectionTo( m_Next );
|
|
|
|
if ( run )
|
|
d |= Direction.Running;
|
|
|
|
m_From.SetDirection( d );
|
|
|
|
res = Move( d );
|
|
|
|
if ( res == MoveResult.Blocked )
|
|
return false;
|
|
}
|
|
|
|
if ( m_From.X == m_Next.X && m_From.Y == m_Next.Y )
|
|
{
|
|
if ( m_From.Z == m_Next.Z )
|
|
{
|
|
++m_Index;
|
|
Advance( ref m_Next, m_Index );
|
|
}
|
|
else
|
|
{
|
|
m_Path = null;
|
|
}
|
|
}
|
|
|
|
return Check( m_From.Location, goal, range );
|
|
}
|
|
}
|
|
} |