public virtual MoveResult DoMoveImpl(Direction d)
{
if (m_Mobile.Deleted || m_Mobile.Frozen || m_Mobile.Paralyzed || (m_Mobile.Spell != null && m_Mobile.Spell.IsCasting) ||
m_Mobile.DisallowAllMoves)
{
return MoveResult.BadState;
}
else if (!CheckMove())
{
return MoveResult.BadState;
}
// This makes them always move one step, never any direction changes
m_Mobile.Direction = d;
int delay = (int)(TransformMoveDelay(m_Mobile.CurrentSpeed) * 1000);
m_NextMove += delay;
if (Core.TickCount - m_NextMove > 0)
{
m_NextMove = Core.TickCount;
}
m_Mobile.Pushing = false;
MoveImpl.IgnoreMovableImpassables = (m_Mobile.CanMoveOverObstacles && !m_Mobile.CanDestroyObstacles);
if ((m_Mobile.Direction & Direction.Mask) != (d & Direction.Mask))
{
bool v = m_Mobile.Move(d);
MoveImpl.IgnoreMovableImpassables = false;
return (v ? MoveResult.Success : MoveResult.Blocked);
}
else if (!m_Mobile.Move(d))
{
bool wasPushing = m_Mobile.Pushing;
bool blocked = true;
bool canOpenDoors = m_Mobile.CanOpenDoors;
bool canDestroyObstacles = m_Mobile.CanDestroyObstacles;
if (canOpenDoors || canDestroyObstacles)
{
m_Mobile.DebugSay("My movement was blocked, I will try to clear some obstacles.");
Map map = m_Mobile.Map;
if (map != null)
{
int x = m_Mobile.X, y = m_Mobile.Y;
Movement.Movement.Offset(d, ref x, ref y);
int destroyables = 0;
IPooledEnumerable eable = map.GetItemsInRange(new Point3D(x, y, m_Mobile.Location.Z), 1);
foreach (Item item in eable)
{
if (canOpenDoors && item is BaseDoor && (item.Z + item.ItemData.Height) > m_Mobile.Z &&
(m_Mobile.Z + 16) > item.Z)
{
if (item.X != x || item.Y != y)
{
continue;
}
BaseDoor door = (BaseDoor)item;
if (!door.Locked || !door.UseLocks())
{
m_Obstacles.Enqueue(door);
}
if (!canDestroyObstacles)
{
break;
}
}
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;
}
}
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)
{
Item item = m_Obstacles.Dequeue();
if (item is BaseDoor)
{
m_Mobile.DebugSay("Little do they expect, I've learned how to open doors. Didn't they read the script??");
m_Mobile.DebugSay("*twist*");
((BaseDoor)item).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)
{
Container cont = (Container)item;
for (int i = 0; i < cont.Items.Count; ++i)
{
Item check = cont.Items[i];
if (check.Movable && check.ItemData.Impassable && (item.Z + check.ItemData.Height) > m_Mobile.Z)
{
m_Obstacles.Enqueue(check);
}
}
cont.Destroy();
}
else
{
item.Delete();
}
}
}
if (!blocked)
{
blocked = !m_Mobile.Move(d);
}
}
}
if (blocked)
{
int offset = (Utility.RandomDouble() >= 0.6 ? 1 : -1);
for (int i = 0; i < 2; ++i)
{
m_Mobile.TurnInternal(offset);
if (m_Mobile.Move(m_Mobile.Direction))
{
MoveImpl.IgnoreMovableImpassables = false;
return MoveResult.SuccessAutoTurn;
}
}
MoveImpl.IgnoreMovableImpassables = false;
return (wasPushing ? MoveResult.BadState : MoveResult.Blocked);
}
else
{
MoveImpl.IgnoreMovableImpassables = false;
return MoveResult.Success;
}
}
MoveImpl.IgnoreMovableImpassables = false;
return MoveResult.Success;
}