/// <summary> /// Make our path thicker to fill small gaps /// </summary> /// <param name="map">map to thicken</param> /// <param name="maxX">map max X</param> /// <param name="maxY">map max Y</param> /// <returns></returns> private Node[,] ThinkenPathsOnMap(Node[,] map, int maxX, int maxY, int factor) { Node[,] newMap = new Node[map.GetLength(0), map.GetLength(1)]; for (int y = 0; y <= maxY; y++) { for (int x = 0; x <= maxX; x++) { if (!map[x, y].IsBlocked) { foreach (Node node in AmeisenPath.GetNeighbours(map, new NodePosition(x, y))) { newMap[node.Position.X, node.Position.Y] = new Node( new NodePosition( map[node.Position.X, node.Position.Y].Position.X, map[node.Position.X, node.Position.Y].Position.Y, map[node.Position.X, node.Position.Y].Position.Z), false); } } else { newMap[x, y] = map[x, y]; } } } factor--; if (factor > 1) { return ThinkenPathsOnMap(newMap, maxX, maxY, factor); } else { return newMap; } }
/// <summary> /// Find a way to the given node and maybe thinken our path if wanted /// </summary> /// <param name="initialPosition">starting pos, you</param> /// <param name="targetPosition">target pos, the position to go to</param> /// <param name="thickenPath">if we should thinken our path, makes nodes connect better, but may be unsecure</param> /// <returns>path that was found or not</returns> private List<Node> FindWayToNode(Vector3 initialPosition, Vector3 targetPosition, bool thickenPath = false) { int distance = (int)Utils.GetDistance(initialPosition, targetPosition); // Get the map boundaries... limit nodes that we get from database... X int maxX = targetPosition.X >= initialPosition.X ? (int)targetPosition.X : (int)initialPosition.X; int minX = initialPosition.X <= targetPosition.X ? (int)initialPosition.X : (int)targetPosition.X; // Y int maxY = targetPosition.Y >= initialPosition.Y ? (int)targetPosition.Y : (int)initialPosition.Y; int minY = initialPosition.Y <= targetPosition.Y ? (int)initialPosition.Y : (int)targetPosition.Y; AmeisenLogger.Instance.Log(LogLevel.DEBUG, $"Trying to find path from {initialPosition.X},{initialPosition.Y},{initialPosition.Z} to: {targetPosition.X},{targetPosition.Y},{targetPosition.Z} Distance: {distance}", this); maxX += 10 * AmeisenDataHolder.Settings.PathfindingSearchRadius; minX -= 10 * AmeisenDataHolder.Settings.PathfindingSearchRadius; maxY += 10 * AmeisenDataHolder.Settings.PathfindingSearchRadius; minY -= 10 * AmeisenDataHolder.Settings.PathfindingSearchRadius; // Offsets to rebase nodes from negative values to positive X int offsetX = minX * -1; minX += offsetX; maxX += offsetX; // Y int offsetY = minY * -1; minY += offsetY; maxY += offsetY; initialPosition.X = (int)initialPosition.X + offsetX; initialPosition.Y = (int)initialPosition.Y + offsetY; targetPosition.X = (int)targetPosition.X + offsetX; targetPosition.Y = (int)targetPosition.Y + offsetY; // Get our nodes from the batabase List<MapNode> nodes = AmeisenDBManager.GetNodes( Me.ZoneID, Me.MapID, maxX - offsetX, minX - offsetX, maxY - offsetY, minY - offsetY); // We cant find ay path if there are no known nodes if (nodes.Count < 1) { return null; } Node[,] map = new Node[maxX + 1, maxY + 1]; // Init map with all things blocked and Rebase negative nodes to be positive InitMap(ref map, maxX, minX, maxY, minY); RebaseNodes(ref map, nodes, offsetX, offsetY); // Fill path-gaps if (thickenPath) { map = ThinkenPathsOnMap(map, maxX, maxY, 5); } else { map = ThinkenPathsOnMap(map, maxX, maxY, 1); } // Find the path List<Node> path = AmeisenPath.FindPathAStar(map, new NodePosition((int)initialPosition.X, (int)initialPosition.Y, (int)initialPosition.Z), new NodePosition((int)targetPosition.X, (int)targetPosition.Y, (int)targetPosition.Z), true, true, 5); //WriteMapToFile(map, initialPosition, targetPosition); if (path == null) { return null; } else { return RebasePath(path, offsetX, offsetY); } }