public bool GetPathTo(Creature creature, Position destPos, List<byte> listDir, Int32 maxSearchDist, bool allowZChange, bool intendingToReachDes) { if (intendingToReachDes && gameMap.TileContainsType(destPos, Constants.TYPE_BLOCKS_AUTO_WALK)) { listDir.Clear(); return false; } listDir.Clear(); Position startPos = creature.CurrentPosition; Position endPos = destPos; if (endPos == null) { return false; } if (startPos.z != endPos.z) return false; AStarNodes nodes = new AStarNodes(); AStarNode startNode = nodes.CreateOpenNode(); startNode.x = startPos.x; startNode.y = startPos.y; startNode.g = 0; startNode.h = nodes.GetEstimatedDistance (startPos.x, startPos.y, endPos.x, endPos.y); startNode.f = startNode.g + startNode.h; startNode.parent = null; Position pos = new Position(); pos.z = startPos.z; short[,] neighbourOrderList = { {-1, 0}, {0, 1}, {1, 0}, {0, -1}, //diagonal {-1, -1}, {1, -1}, {1, 1}, {-1, 1}, }; //MapTile tile = null; AStarNode found = null; while (nodes.CountClosedNodes() < 100) { AStarNode n = nodes.GetBestNode(); if (n == null) { listDir.Clear(); return false; //No path found } if (n.x == endPos.x && n.y == endPos.y) { found = n; break; } else { for (int i = 0; i < 8; i++) { if (i > 3 && (allowZChange || intendingToReachDes)) { continue; } //Console.WriteLine("neighbourhood["+i+", 1]" + neighbourOrderList[i, 0]); pos.x = (ushort)(n.x + neighbourOrderList[i, 0]); pos.y = (ushort)(n.y + neighbourOrderList[i, 1]); int endPosX = endPos.x; int endPosY = endPos.y; int posX = pos.x; int posY = pos.y; bool outOfRange = false; if (Math.Abs(endPosX - posX) > maxSearchDist || Math.Abs(endPosY - posY) > maxSearchDist) { outOfRange = true; } if ((!outOfRange) && (!gameMap.TileContainsType(pos, Constants.TYPE_BLOCKS_AUTO_WALK)) || (destPos.x == pos.x && destPos.y == pos.y)) { if (i > 3 && !destPos.Equals(pos)) { nodes.CloseNode(n); continue; } int cost = 0; int extraCost = 0; int newg = n.g + cost + extraCost; AStarNode neighbourNode = nodes.GetNodeInList(pos.x, pos.y); if (neighbourNode != null) { if (neighbourNode.g <= newg) { continue; } nodes.OpenNode(neighbourNode); } else { neighbourNode = nodes.CreateOpenNode(); if (neighbourNode == null) { listDir.Clear(); return false; } } neighbourNode.x = pos.x; neighbourNode.y = pos.y; neighbourNode.parent = n; neighbourNode.g = newg; neighbourNode.h = (nodes.GetEstimatedDistance((int)neighbourNode.x, (int)neighbourNode.y, (int)endPos.x, (int)endPos.y)); neighbourNode.f = neighbourNode.g + neighbourNode.h; } } nodes.CloseNode(n); } } int prevX = endPos.x; int prevY = endPos.y; int dx, dy; while (found != null) { pos.x = (ushort)found.x; pos.y = (ushort)found.y; found = found.parent; dx = pos.x - prevX; dy = pos.y - prevY; prevX = pos.x; prevY = pos.y; if (dx == 1) listDir.Insert(0, (byte)Direction.WEST); else if (dx == -1) listDir.Insert(0, (byte)Direction.EAST); else if (dy == 1) listDir.Insert(0, (byte)Direction.NORTH); else if (dy == -1) listDir.Insert(0, (byte)Direction.SOUTH); } bool empty = true; if (listDir.Count == 0) empty = false; return (!empty); }