fix(AI): Fixes direction issue with NPCs (#371)
- [X] Fixes a bug with RunUO where direction is set multiple times and the run flag is not set properly. TODO: Fix other direction/movement issues and duplicate packets. Bumps release version
This commit is contained in:
parent
7ef1d41c6f
commit
67c23bf9ad
11 changed files with 207 additions and 297 deletions
|
|
@ -480,8 +480,6 @@ namespace Server
|
|||
|
||||
while (!Closing)
|
||||
{
|
||||
// m_Signal.WaitOne();
|
||||
|
||||
Mobile.ProcessDeltaQueue();
|
||||
Item.ProcessDeltaQueue();
|
||||
|
||||
|
|
|
|||
|
|
@ -294,7 +294,8 @@ namespace Server
|
|||
Locked
|
||||
}
|
||||
|
||||
[CustomEnum(new[] { "North", "Right", "East", "Down", "South", "Left", "West", "Up" }), Flags]
|
||||
[Flags]
|
||||
[CustomEnum(new[] { "North", "Right", "East", "Down", "South", "Left", "West", "Up" })]
|
||||
public enum Direction : byte
|
||||
{
|
||||
North = 0x0,
|
||||
|
|
@ -1348,9 +1349,7 @@ namespace Server
|
|||
if (m_Direction != value)
|
||||
{
|
||||
m_Direction = value;
|
||||
|
||||
Delta(MobileDelta.Direction);
|
||||
// ProcessDelta();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9144,7 +9143,7 @@ namespace Server
|
|||
|
||||
public void BoltEffect(int hue) => Effects.SendBoltEffect(this, true, hue);
|
||||
|
||||
public Direction GetDirectionTo(int x, int y)
|
||||
public Direction GetDirectionTo(int x, int y, bool run = false)
|
||||
{
|
||||
var dx = m_Location.m_X - x;
|
||||
var dy = m_Location.m_Y - y;
|
||||
|
|
@ -9165,30 +9164,25 @@ namespace Server
|
|||
{
|
||||
ret = rx > 0 ? Direction.Left : Direction.Right;
|
||||
}
|
||||
else if (rx >= 0 && ry >= 0)
|
||||
{
|
||||
ret = Direction.West;
|
||||
}
|
||||
else if (rx >= 0 && ry < 0)
|
||||
{
|
||||
ret = Direction.South;
|
||||
}
|
||||
else if (rx < 0 && ry < 0)
|
||||
{
|
||||
ret = Direction.East;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = Direction.North;
|
||||
ret = rx switch
|
||||
{
|
||||
>= 0 when ry >= 0 => Direction.West,
|
||||
>= 0 => Direction.South,
|
||||
< 0 when ry < 0 => Direction.East,
|
||||
_ => Direction.North
|
||||
};
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret | (run ? Direction.Running : 0);
|
||||
}
|
||||
|
||||
public Direction GetDirectionTo(Point2D p) => GetDirectionTo(p.m_X, p.m_Y);
|
||||
public Direction GetDirectionTo(Point3D p) => GetDirectionTo(p.m_X, p.m_Y);
|
||||
public Direction GetDirectionTo(Point2D p, bool run = false) => GetDirectionTo(p.m_X, p.m_Y, run);
|
||||
public Direction GetDirectionTo(Point3D p, bool run = false) => GetDirectionTo(p.m_X, p.m_Y, run);
|
||||
|
||||
public Direction GetDirectionTo(IPoint2D p) => p == null ? Direction.North : GetDirectionTo(p.X, p.Y);
|
||||
public Direction GetDirectionTo(IPoint2D p, bool run = false) =>
|
||||
p == null ? Direction.North | (run ? Direction.Running : 0) : GetDirectionTo(p.X, p.Y, run);
|
||||
|
||||
public void PublicOverheadMessage(MessageType type, int hue, bool ascii, string text, bool noLineOfSight = true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,25 +29,10 @@ namespace Server
|
|||
Enabled = ServerConfiguration.GetOrUpdateSetting("pathfinding.enable", true);
|
||||
}
|
||||
|
||||
public MoveResult Move(Direction d)
|
||||
{
|
||||
if (Mover == null)
|
||||
{
|
||||
return m_From.Move(d) ? MoveResult.Success : MoveResult.Blocked;
|
||||
}
|
||||
public MoveResult Move(Direction d) =>
|
||||
Mover?.Invoke(d) ?? (m_From.Move(d) ? MoveResult.Success : MoveResult.Blocked);
|
||||
|
||||
return Mover(d);
|
||||
}
|
||||
|
||||
public Point3D GetGoalLocation()
|
||||
{
|
||||
if (Goal is Item item)
|
||||
{
|
||||
return item.GetWorldLocation();
|
||||
}
|
||||
|
||||
return new Point3D(Goal);
|
||||
}
|
||||
public Point3D GetGoalLocation() => (Goal as Item)?.GetWorldLocation() ?? new Point3D(Goal);
|
||||
|
||||
public void Advance(ref Point3D p, int index)
|
||||
{
|
||||
|
|
@ -100,7 +85,7 @@ namespace Server
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool Check(Point3D loc, Point3D goal, int range) =>
|
||||
public static bool Check(Point3D loc, Point3D goal, int range) =>
|
||||
Utility.InRange(loc, goal, range) && (range > 1 || Math.Abs(loc.Z - goal.Z) < 16);
|
||||
|
||||
public bool Follow(bool run, int range)
|
||||
|
|
@ -117,28 +102,15 @@ namespace Server
|
|||
|
||||
if (!(Enabled && m_Path.Success))
|
||||
{
|
||||
d = m_From.GetDirectionTo(goal);
|
||||
|
||||
if (run)
|
||||
{
|
||||
d |= Direction.Running;
|
||||
}
|
||||
|
||||
d = m_From.GetDirectionTo(goal, run);
|
||||
m_From.SetDirection(d);
|
||||
Move(d);
|
||||
|
||||
return Check(m_From.Location, goal, range);
|
||||
}
|
||||
|
||||
d = m_From.GetDirectionTo(m_Next);
|
||||
|
||||
if (run)
|
||||
{
|
||||
d |= Direction.Running;
|
||||
}
|
||||
|
||||
d = m_From.GetDirectionTo(m_Next, run);
|
||||
m_From.SetDirection(d);
|
||||
|
||||
var res = Move(d);
|
||||
|
||||
if (res == MoveResult.Blocked)
|
||||
|
|
@ -153,31 +125,17 @@ namespace Server
|
|||
|
||||
if (!m_Path.Success)
|
||||
{
|
||||
d = m_From.GetDirectionTo(goal);
|
||||
|
||||
if (run)
|
||||
{
|
||||
d |= Direction.Running;
|
||||
}
|
||||
|
||||
d = m_From.GetDirectionTo(goal, run);
|
||||
m_From.SetDirection(d);
|
||||
Move(d);
|
||||
|
||||
return Check(m_From.Location, goal, range);
|
||||
}
|
||||
|
||||
d = m_From.GetDirectionTo(m_Next);
|
||||
|
||||
if (run)
|
||||
{
|
||||
d |= Direction.Running;
|
||||
}
|
||||
|
||||
d = m_From.GetDirectionTo(m_Next, run);
|
||||
m_From.SetDirection(d);
|
||||
|
||||
res = Move(d);
|
||||
|
||||
if (res == MoveResult.Blocked)
|
||||
if (Move(d) == MoveResult.Blocked)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,11 +57,7 @@ namespace Server.Mobiles
|
|||
return true;
|
||||
}
|
||||
|
||||
if (WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
|
||||
{
|
||||
m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
|
||||
}
|
||||
else
|
||||
if (!WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
|
||||
{
|
||||
if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,31 +42,32 @@ namespace Server.Mobiles
|
|||
|
||||
if (Core.TickCount - m_Mobile.LastMoveTime > 1000)
|
||||
{
|
||||
if (WalkMobileRange(m_Mobile.Combatant, 1, true, m_Mobile.RangeFight, m_Mobile.Weapon.MaxRange))
|
||||
if (
|
||||
m_Mobile.Combatant != null &&
|
||||
!WalkMobileRange(
|
||||
m_Mobile.Combatant,
|
||||
1,
|
||||
true,
|
||||
m_Mobile.RangeFight,
|
||||
m_Mobile.Weapon.MaxRange
|
||||
)
|
||||
)
|
||||
{
|
||||
// Be sure to face the combatant
|
||||
m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant.Location);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Mobile.Combatant != null)
|
||||
if (m_Mobile.Debug)
|
||||
{
|
||||
m_Mobile.DebugSay("I am still not in range of {0}", m_Mobile.Combatant.Name);
|
||||
}
|
||||
|
||||
if ((int)m_Mobile.GetDistanceToSqrt(m_Mobile.Combatant) > m_Mobile.RangePerception + 1)
|
||||
{
|
||||
if (m_Mobile.Debug)
|
||||
{
|
||||
m_Mobile.DebugSay("I am still not in range of {0}", m_Mobile.Combatant.Name);
|
||||
m_Mobile.DebugSay("I have lost {0}", m_Mobile.Combatant.Name);
|
||||
}
|
||||
|
||||
if ((int)m_Mobile.GetDistanceToSqrt(m_Mobile.Combatant) > m_Mobile.RangePerception + 1)
|
||||
{
|
||||
if (m_Mobile.Debug)
|
||||
{
|
||||
m_Mobile.DebugSay("I have lost {0}", m_Mobile.Combatant.Name);
|
||||
}
|
||||
|
||||
m_Mobile.Combatant = null;
|
||||
Action = ActionType.Guard;
|
||||
return true;
|
||||
}
|
||||
m_Mobile.Combatant = null;
|
||||
Action = ActionType.Guard;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1203,7 +1203,7 @@ namespace Server.Mobiles
|
|||
!m_Mobile.Combatant.IsDeadBondedPet)
|
||||
{
|
||||
m_Mobile.Warmode = true;
|
||||
m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant);
|
||||
// m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant, bRun);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1323,7 +1323,7 @@ namespace Server.Mobiles
|
|||
!m_Mobile.Combatant.IsDeadBondedPet)
|
||||
{
|
||||
m_Mobile.Warmode = true;
|
||||
m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant);
|
||||
// m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant, bRun);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1644,8 +1644,6 @@ namespace Server.Mobiles
|
|||
m_Mobile.DebugSay("My master told me to stay");
|
||||
}
|
||||
|
||||
// m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.ControlMaster );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1982,6 +1980,7 @@ namespace Server.Mobiles
|
|||
}
|
||||
|
||||
// This makes them always move one step, never any direction changes
|
||||
// TODO: This is firing off deltas which aren't needed. Look into replacing/removing this
|
||||
m_Mobile.Direction = d;
|
||||
|
||||
var delay = (int)(TransformMoveDelay(m_Mobile.CurrentSpeed) * 1000);
|
||||
|
|
@ -2005,145 +2004,145 @@ namespace Server.Mobiles
|
|||
return v ? MoveResult.Success : MoveResult.Blocked;
|
||||
}
|
||||
|
||||
if (!m_Mobile.Move(d))
|
||||
if (m_Mobile.Move(d))
|
||||
{
|
||||
var wasPushing = m_Mobile.Pushing;
|
||||
MoveImpl.IgnoreMovableImpassables = false;
|
||||
return MoveResult.Success;
|
||||
}
|
||||
|
||||
var blocked = true;
|
||||
var wasPushing = m_Mobile.Pushing;
|
||||
|
||||
var canOpenDoors = m_Mobile.CanOpenDoors;
|
||||
var canDestroyObstacles = m_Mobile.CanDestroyObstacles;
|
||||
var blocked = true;
|
||||
|
||||
if (canOpenDoors || canDestroyObstacles)
|
||||
var canOpenDoors = m_Mobile.CanOpenDoors;
|
||||
var canDestroyObstacles = m_Mobile.CanDestroyObstacles;
|
||||
|
||||
if (canOpenDoors || canDestroyObstacles)
|
||||
{
|
||||
m_Mobile.DebugSay("My movement was blocked, I will try to clear some obstacles.");
|
||||
|
||||
var map = m_Mobile.Map;
|
||||
|
||||
if (map != null)
|
||||
{
|
||||
m_Mobile.DebugSay("My movement was blocked, I will try to clear some obstacles.");
|
||||
int x = m_Mobile.X, y = m_Mobile.Y;
|
||||
Movement.Movement.Offset(d, ref x, ref y);
|
||||
|
||||
var map = m_Mobile.Map;
|
||||
var destroyables = 0;
|
||||
|
||||
if (map != null)
|
||||
var eable = map.GetItemsInRange(new Point3D(x, y, m_Mobile.Location.Z), 1);
|
||||
|
||||
foreach (var item in eable)
|
||||
{
|
||||
int x = m_Mobile.X, y = m_Mobile.Y;
|
||||
Movement.Movement.Offset(d, ref x, ref y);
|
||||
|
||||
var destroyables = 0;
|
||||
|
||||
var eable = map.GetItemsInRange(new Point3D(x, y, m_Mobile.Location.Z), 1);
|
||||
|
||||
foreach (var item in eable)
|
||||
if (canOpenDoors && item is BaseDoor door && door.Z + door.ItemData.Height > m_Mobile.Z &&
|
||||
m_Mobile.Z + 16 > door.Z)
|
||||
{
|
||||
if (canOpenDoors && item is BaseDoor door && door.Z + door.ItemData.Height > m_Mobile.Z &&
|
||||
m_Mobile.Z + 16 > door.Z)
|
||||
if (door.X != x || door.Y != y)
|
||||
{
|
||||
if (door.X != x || door.Y != y)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!door.Locked || !door.UseLocks())
|
||||
{
|
||||
m_Obstacles.Enqueue(door);
|
||||
}
|
||||
|
||||
if (!canDestroyObstacles)
|
||||
{
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (canDestroyObstacles && item.Movable && item.ItemData.Impassable &&
|
||||
item.Z + item.ItemData.Height > m_Mobile.Z && m_Mobile.Z + 16 > item.Z)
|
||||
{
|
||||
if (!m_Mobile.InRange(item.GetWorldLocation(), 1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
m_Obstacles.Enqueue(item);
|
||||
++destroyables;
|
||||
if (!door.Locked || !door.UseLocks())
|
||||
{
|
||||
m_Obstacles.Enqueue(door);
|
||||
}
|
||||
|
||||
if (!canDestroyObstacles)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
|
||||
if (destroyables > 0)
|
||||
else if (canDestroyObstacles && item.Movable && item.ItemData.Impassable &&
|
||||
item.Z + item.ItemData.Height > m_Mobile.Z && m_Mobile.Z + 16 > item.Z)
|
||||
{
|
||||
Effects.PlaySound(new Point3D(x, y, m_Mobile.Z), m_Mobile.Map, 0x3B3);
|
||||
}
|
||||
|
||||
if (m_Obstacles.Count > 0)
|
||||
{
|
||||
blocked = false; // retry movement
|
||||
}
|
||||
|
||||
while (m_Obstacles.Count > 0)
|
||||
{
|
||||
var item = m_Obstacles.Dequeue();
|
||||
|
||||
if (item is BaseDoor door)
|
||||
if (!m_Mobile.InRange(item.GetWorldLocation(), 1))
|
||||
{
|
||||
m_Mobile.DebugSay(
|
||||
"Little do they expect, I've learned how to open doors. Didn't they read the script??"
|
||||
);
|
||||
m_Mobile.DebugSay("*twist*");
|
||||
continue;
|
||||
}
|
||||
|
||||
door.Use(m_Mobile);
|
||||
m_Obstacles.Enqueue(item);
|
||||
++destroyables;
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
|
||||
if (destroyables > 0)
|
||||
{
|
||||
Effects.PlaySound(new Point3D(x, y, m_Mobile.Z), m_Mobile.Map, 0x3B3);
|
||||
}
|
||||
|
||||
if (m_Obstacles.Count > 0)
|
||||
{
|
||||
blocked = false; // retry movement
|
||||
}
|
||||
|
||||
while (m_Obstacles.Count > 0)
|
||||
{
|
||||
var item = m_Obstacles.Dequeue();
|
||||
|
||||
if (item is BaseDoor door)
|
||||
{
|
||||
m_Mobile.DebugSay(
|
||||
"Little do they expect, I've learned how to open doors. Didn't they read the script??"
|
||||
);
|
||||
m_Mobile.DebugSay("*twist*");
|
||||
|
||||
door.Use(m_Mobile);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Mobile.DebugSay(
|
||||
"Ugabooga. I'm so big and tough I can destroy it: {0}",
|
||||
item.GetType().Name
|
||||
);
|
||||
|
||||
if (item is Container cont)
|
||||
{
|
||||
for (var i = 0; i < cont.Items.Count; ++i)
|
||||
{
|
||||
var check = cont.Items[i];
|
||||
|
||||
if (check.Movable && check.ItemData.Impassable &&
|
||||
cont.Z + check.ItemData.Height > m_Mobile.Z)
|
||||
{
|
||||
m_Obstacles.Enqueue(check);
|
||||
}
|
||||
}
|
||||
|
||||
cont.Destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Mobile.DebugSay(
|
||||
"Ugabooga. I'm so big and tough I can destroy it: {0}",
|
||||
item.GetType().Name
|
||||
);
|
||||
|
||||
if (item is Container cont)
|
||||
{
|
||||
for (var i = 0; i < cont.Items.Count; ++i)
|
||||
{
|
||||
var check = cont.Items[i];
|
||||
|
||||
if (check.Movable && check.ItemData.Impassable &&
|
||||
cont.Z + check.ItemData.Height > m_Mobile.Z)
|
||||
{
|
||||
m_Obstacles.Enqueue(check);
|
||||
}
|
||||
}
|
||||
|
||||
cont.Destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Delete();
|
||||
}
|
||||
item.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!blocked)
|
||||
{
|
||||
blocked = !m_Mobile.Move(d);
|
||||
}
|
||||
if (!blocked)
|
||||
{
|
||||
blocked = !m_Mobile.Move(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blocked)
|
||||
if (blocked)
|
||||
{
|
||||
var offset = Utility.RandomDouble() >= 0.6 ? 1 : -1;
|
||||
|
||||
for (var i = 0; i < 2; ++i)
|
||||
{
|
||||
var offset = Utility.RandomDouble() >= 0.6 ? 1 : -1;
|
||||
m_Mobile.TurnInternal(offset);
|
||||
|
||||
for (var i = 0; i < 2; ++i)
|
||||
if (m_Mobile.Move(m_Mobile.Direction))
|
||||
{
|
||||
m_Mobile.TurnInternal(offset);
|
||||
|
||||
if (m_Mobile.Move(m_Mobile.Direction))
|
||||
{
|
||||
MoveImpl.IgnoreMovableImpassables = false;
|
||||
return MoveResult.SuccessAutoTurn;
|
||||
}
|
||||
MoveImpl.IgnoreMovableImpassables = false;
|
||||
return MoveResult.SuccessAutoTurn;
|
||||
}
|
||||
|
||||
MoveImpl.IgnoreMovableImpassables = false;
|
||||
return wasPushing ? MoveResult.BadState : MoveResult.Blocked;
|
||||
}
|
||||
|
||||
MoveImpl.IgnoreMovableImpassables = false;
|
||||
return MoveResult.Success;
|
||||
return wasPushing ? MoveResult.BadState : MoveResult.Blocked;
|
||||
}
|
||||
|
||||
MoveImpl.IgnoreMovableImpassables = false;
|
||||
|
|
@ -2281,10 +2280,9 @@ namespace Server.Mobiles
|
|||
return true;
|
||||
}
|
||||
}
|
||||
else if (!DoMove(m_Mobile.GetDirectionTo(m), true))
|
||||
else if (!DoMove(m_Mobile.GetDirectionTo(m, run), true))
|
||||
{
|
||||
m_Path = new PathFollower(m_Mobile, m);
|
||||
m_Path.Mover = DoMoveImpl;
|
||||
m_Path = new PathFollower(m_Mobile, m) { Mover = DoMoveImpl };
|
||||
|
||||
if (m_Path.Follow(run, 1))
|
||||
{
|
||||
|
|
@ -2341,22 +2339,8 @@ namespace Server.Mobiles
|
|||
}
|
||||
else
|
||||
{
|
||||
Direction dirTo;
|
||||
|
||||
if (iCurrDist > iWantDistMax)
|
||||
{
|
||||
dirTo = m_Mobile.GetDirectionTo(m);
|
||||
}
|
||||
else
|
||||
{
|
||||
dirTo = m.GetDirectionTo(m_Mobile);
|
||||
}
|
||||
|
||||
// Add the run flag
|
||||
if (bRun)
|
||||
{
|
||||
dirTo = dirTo | Direction.Running;
|
||||
}
|
||||
var dirTo = iCurrDist > iWantDistMax ?
|
||||
m_Mobile.GetDirectionTo(m, bRun) : m.GetDirectionTo(m_Mobile, bRun);
|
||||
|
||||
if (!DoMove(dirTo, true) && needCloser)
|
||||
{
|
||||
|
|
@ -2382,12 +2366,7 @@ namespace Server.Mobiles
|
|||
// Get the current distance
|
||||
var iNewDist = (int)m_Mobile.GetDistanceToSqrt(m);
|
||||
|
||||
if (iNewDist >= iWantDistMin && iNewDist <= iWantDistMax)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return iNewDist >= iWantDistMin && iNewDist <= iWantDistMax;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -37,30 +37,31 @@ namespace Server.Mobiles
|
|||
return true;
|
||||
}
|
||||
|
||||
if (WalkMobileRange(m_Mobile.Combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
|
||||
if (
|
||||
m_Mobile.Combatant != null &&
|
||||
!WalkMobileRange(
|
||||
m_Mobile.Combatant,
|
||||
1,
|
||||
true,
|
||||
m_Mobile.RangeFight,
|
||||
m_Mobile.RangeFight
|
||||
)
|
||||
)
|
||||
{
|
||||
// Be sure to face the combatant
|
||||
m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant.Location);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Mobile.Combatant != null)
|
||||
if (m_Mobile.Debug)
|
||||
{
|
||||
m_Mobile.DebugSay($"I am still not in range of {m_Mobile.Combatant.Name}");
|
||||
}
|
||||
|
||||
if ((int)m_Mobile.GetDistanceToSqrt(m_Mobile.Combatant) > m_Mobile.RangePerception + 1)
|
||||
{
|
||||
if (m_Mobile.Debug)
|
||||
{
|
||||
m_Mobile.DebugSay($"I am still not in range of {m_Mobile.Combatant.Name}");
|
||||
m_Mobile.DebugSay($"I have lost {m_Mobile.Combatant.Name}");
|
||||
}
|
||||
|
||||
if ((int)m_Mobile.GetDistanceToSqrt(m_Mobile.Combatant) > m_Mobile.RangePerception + 1)
|
||||
{
|
||||
if (m_Mobile.Debug)
|
||||
{
|
||||
m_Mobile.DebugSay($"I have lost {m_Mobile.Combatant.Name}");
|
||||
}
|
||||
|
||||
Action = ActionType.Guard;
|
||||
return true;
|
||||
}
|
||||
Action = ActionType.Guard;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,44 +67,33 @@ namespace Server.Mobiles
|
|||
}
|
||||
}
|
||||
|
||||
/*if (!m_Mobile.InLOS( combatant ))
|
||||
if (!MoveTo(combatant, true, m_Mobile.RangeFight))
|
||||
{
|
||||
if (AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ))
|
||||
{
|
||||
m_Mobile.Combatant = combatant = m_Mobile.FocusMob;
|
||||
m_Mobile.FocusMob = null;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (MoveTo(combatant, true, m_Mobile.RangeFight))
|
||||
{
|
||||
m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
|
||||
}
|
||||
else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
|
||||
{
|
||||
if (m_Mobile.Debug)
|
||||
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
|
||||
{
|
||||
m_Mobile.DebugSay("My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name);
|
||||
if (m_Mobile.Debug)
|
||||
{
|
||||
m_Mobile.DebugSay("My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob?.Name ?? "null");
|
||||
}
|
||||
|
||||
m_Mobile.Combatant = m_Mobile.FocusMob;
|
||||
Action = ActionType.Combat;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
m_Mobile.Combatant = m_Mobile.FocusMob;
|
||||
Action = ActionType.Combat;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1)
|
||||
{
|
||||
if (m_Mobile.Debug)
|
||||
if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1)
|
||||
{
|
||||
m_Mobile.DebugSay("I cannot find {0}, so my guard is up", combatant.Name);
|
||||
if (m_Mobile.Debug)
|
||||
{
|
||||
m_Mobile.DebugSay("I cannot find {0}, so my guard is up", combatant.Name);
|
||||
}
|
||||
|
||||
Action = ActionType.Guard;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Action = ActionType.Guard;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Mobile.Debug)
|
||||
{
|
||||
m_Mobile.DebugSay("I should be closer to {0}", combatant.Name);
|
||||
|
|
@ -117,7 +106,7 @@ namespace Server.Mobiles
|
|||
{
|
||||
// We are low on health, should we flee?
|
||||
|
||||
var flee = false;
|
||||
bool flee;
|
||||
|
||||
if (m_Mobile.Hits < combatant.Hits)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,11 +37,7 @@ namespace Server.Mobiles
|
|||
return true;
|
||||
}
|
||||
|
||||
if (WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
|
||||
{
|
||||
m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
|
||||
}
|
||||
else
|
||||
if (!WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
|
||||
{
|
||||
if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,10 +42,12 @@ namespace Server.Mobiles
|
|||
return true;
|
||||
}
|
||||
|
||||
if (WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
|
||||
if (!WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
|
||||
{
|
||||
m_Mobile.DebugSay("I should be closer to {0}", combatant.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
|
||||
|
||||
if (m_toDisarm?.IsChildOf(m_Mobile.Backpack) != false)
|
||||
{
|
||||
m_toDisarm = combatant.FindItemOnLayer(Layer.OneHanded) ?? combatant.FindItemOnLayer(Layer.TwoHanded);
|
||||
|
|
@ -111,17 +113,13 @@ namespace Server.Mobiles
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Mobile.DebugSay("I should be closer to {0}", combatant.Name);
|
||||
}
|
||||
|
||||
if (m_Mobile.Hits >= m_Mobile.HitsMax * 20 / 100 || !m_Mobile.CanFlee)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// We are low on health, should we flee?
|
||||
|
||||
// We are low on health, should we flee?
|
||||
bool flee;
|
||||
|
||||
if (m_Mobile.Hits < combatant.Hits)
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ namespace Server.Mobiles
|
|||
Warmode = false;
|
||||
FocusMob = Combatant = null;
|
||||
|
||||
CurrentSpeed = .01;
|
||||
CurrentSpeed = 0.01;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue