/// <summary> /// Gets a collection of pathfinder nodes to this creature. Returns an empty IEnumerable if unreachable. /// </summary> /// <param name="tileCollection">The list of tiles on screen to use for pathfinding.</param> /// <param name="pathFinder">The PathFinder object to use.</param> /// <returns></returns> public IEnumerable <Objects.PathFinder.Node> GetTilesToCreature(Map.TileCollection tileCollection, Objects.PathFinder pathFinder) { if (pathFinder == null) { return(Enumerable.Empty <Objects.PathFinder.Node>()); } if (this.Location.IsAdjacentTo(this.Client.Player.Location)) { return(new List <Objects.PathFinder.Node>() { new Objects.PathFinder.Node() { X = 8, Y = 6 } }); } if (!this.Location.IsOnScreen(this.Client.Player.Location)) { return(Enumerable.Empty <Objects.PathFinder.Node>()); } uint playerZ = this.Client.Player.Z; if (tileCollection.IsEmpty()) { return(Enumerable.Empty <Objects.PathFinder.Node>()); } Map.Tile playerTile = tileCollection.GetTile(count: this.Client.Player.ID); Map.Tile creatureTile = tileCollection.GetTile(count: this.ID); if (playerTile == null || creatureTile == null) { return(Enumerable.Empty <Objects.PathFinder.Node>()); } lock (pathFinder) { pathFinder.ResetGrid(); foreach (Map.Tile tile in tileCollection.GetTiles()) { if (tile == null) { continue; } if (!tile.IsWalkable()) { pathFinder.Grid[tile.MemoryLocation.X, tile.MemoryLocation.Y] = (byte)Enums.MiniMapSpeedValues.Unwalkable; } else { pathFinder.Grid[tile.MemoryLocation.X, tile.MemoryLocation.Y] = 1; } } pathFinder.Grid[playerTile.MemoryLocation.X, playerTile.MemoryLocation.Y] = 1; pathFinder.Grid[creatureTile.MemoryLocation.X, creatureTile.MemoryLocation.Y] = 1; return(pathFinder.FindPath(playerTile.MemoryLocation, creatureTile.MemoryLocation, true)); } }
/// <summary> /// Checks whether this location can shoot another location. /// </summary> /// <param name="c">The client to perform the operation on.</param> /// <param name="loc">The location to shoot at.</param> /// <param name="tileCollection">The tiles on screen to use for pathfinding.</param> /// <returns></returns> public bool CanShootLocation(Objects.Client c, Objects.Location loc, Map.TileCollection tileCollection) { if (!this.IsOnScreen(loc)) { return(false); } Map.Tile playerTile = tileCollection.GetTile(count: c.Player.ID); if (playerTile == null) { return(false); } Location playerLocation = playerTile.WorldLocation; if (playerLocation == loc) { return(true); } if (!playerLocation.IsOnScreen(this) || !playerLocation.IsOnScreen(loc)) { return(false); } int XSign = (this.X > loc.X) ? 1 : -1; int YSign = (this.Y > loc.Y) ? 1 : -1; double XDistance = Math.Abs(this.X - loc.X); double YDistance = Math.Abs(this.Y - loc.Y); double max = this.DistanceTo(loc); for (int i = 0; i <= max; i++) { Location check = this.Offset((int)Math.Ceiling(i * XDistance / max) * XSign, (int)Math.Ceiling(i * YDistance / max) * YSign); Map.Tile tile = tileCollection.GetTile(check); if (tile == null) { return(false); } if (tile.ContainsObjectProperty(Enums.ObjectPropertiesFlags.IsMissileBlocking)) { return(false); } } return(true); }
public IEnumerable<Node> FindPath(Objects.Location start, Objects.Location end, Map.TileCollection tiles, Objects.MiniMap.MergedChunk mergedChunk, bool considerPlayerWalkable = false, bool considerCreatureOnLocationWalkable = false) { if (start == null || end == null || tiles == null || mergedChunk == null) return Enumerable.Empty<Node>(); Objects.Location playerLoc = this.Client.Player.Location; Objects.Location topLeft = playerLoc.Offset(-Constants.Map.MemoryLocationCenterX, -Constants.Map.MemoryLocationCenterY), bottomRight = playerLoc.Offset(Constants.Map.MemoryLocationCenterX, Constants.Map.MemoryLocationCenterY); if (start.Z != end.Z || start.X < topLeft.X || start.Y < topLeft.Y || start.X > bottomRight.X || start.Y > bottomRight.Y || end.X < topLeft.X || end.Y < topLeft.Y || end.X > bottomRight.X || end.Y > bottomRight.Y) { return Enumerable.Empty<Node>(); } var nodes = mergedChunk.GetNodes(); Point gridLength = new Point(this.Grid.GetLength(0), this.Grid.GetLength(1)), nodeStartIndex = new Point(Math.Max(0, mergedChunk.WorldLocation.X - topLeft.X), Math.Max(0, mergedChunk.WorldLocation.Y - topLeft.Y)), nodeEndIndex = new Point(Math.Min(gridLength.X, nodeStartIndex.X + nodes.GetLength(0)), Math.Min(gridLength.Y, nodeStartIndex.Y + nodes.GetLength(1))), alignedStart = new Point(start.X - topLeft.X, start.Y - topLeft.Y), alignedEnd = new Point(end.X - topLeft.X, end.Y - topLeft.Y); lock (this.SyncObject) { // assign node values to pathfinder grid for (int x = 0; x < gridLength.X; x++) { for (int y = 0; y < gridLength.Y; y++) { if (considerPlayerWalkable) { var tile = tiles.GetTile(topLeft.Offset(x, y)); if (tile != null && tile.ContainsCreature(this.Client.Player.ID)) { this.Grid[x, y] = 1; continue; } } if (nodeStartIndex.X <= x && nodeEndIndex.X > x && nodeStartIndex.Y <= y && nodeEndIndex.Y > y) { Objects.MiniMap.Node node = nodes[x - nodeStartIndex.X, y - nodeStartIndex.Y]; this.Grid[x, y] = this.Client.MiniMap.IsTileWalkable(node.Color, node.Speed, alignedEnd.X == x && alignedEnd.Y == y, this.ConsiderUnexploredAsUnwalkable) ? node.Speed : (byte)Enums.MiniMapSpeedValues.Unwalkable; } else { this.Grid[x, y] = (byte)Enums.MiniMapSpeedValues.Unwalkable; } } } return this.FindPath(alignedStart, alignedEnd); } }
/// <summary> /// Gets a collection of pathfinder nodes to a given location. Returns 0 elements if unsuccessful. /// </summary> /// <param name="c">The client to perform the operation on.</param> /// <param name="loc">The location to reach.</param> /// <param name="tiles">A list of tiles to use for pathfinding.</param> /// <param name="pathFinder">The pathfinder to use.</param> /// <param name="considerPlayerWalkable">Whether to consider the player as walkable.</param> /// <param name="considerCreatureOnLocationWalkable">Whether to consider any creatures on the target location as walkable.</param> /// <returns></returns> public IEnumerable <Objects.PathFinder.Node> GetTilesToLocation(Objects.Client c, Location loc, Map.TileCollection tiles, Objects.PathFinder pathFinder, bool considerPlayerWalkable = false, bool considerCreatureOnLocationWalkable = false) { if (pathFinder == null) { return(Enumerable.Empty <Objects.PathFinder.Node>()); } //return pathFinder. if (!this.IsOnScreen(c.Player.Location)) { return(Enumerable.Empty <Objects.PathFinder.Node>()); } uint playerId = c.Player.ID; Map.Tile playerTile = tiles.GetTile(count: playerId); Map.Tile fromTile = tiles.GetTile(this); Map.Tile targetTile = tiles.GetTile(loc); if (playerTile == null || fromTile == null || targetTile == null) { return(Enumerable.Empty <Objects.PathFinder.Node>()); } // check if target tile is walkable if (!targetTile.IsWalkable() && (!considerPlayerWalkable || targetTile != playerTile)) { return(Enumerable.Empty <Objects.PathFinder.Node>()); } if (fromTile == targetTile) { return(Enumerable.AsEnumerable(new Objects.PathFinder.Node[] { new Objects.PathFinder.Node() })); } lock (pathFinder) { pathFinder.ResetGrid(); foreach (Map.Tile tile in tiles.GetTiles()) { if (tile == null) { continue; } if ((considerPlayerWalkable && tile == playerTile) || tile.IsWalkable()) { pathFinder.Grid[tile.MemoryLocation.X, tile.MemoryLocation.Y] = 1; } else { pathFinder.Grid[tile.MemoryLocation.X, tile.MemoryLocation.Y] = (byte)Enums.MiniMapSpeedValues.Unwalkable; } } pathFinder.Grid[fromTile.MemoryLocation.X, fromTile.MemoryLocation.Y] = 1; return(pathFinder.FindPath(fromTile.MemoryLocation, targetTile.MemoryLocation)); } }
/// <summary> /// Gets a collection of pathfinder nodes to a given location. Returns 0 elements if unsuccessful. /// </summary> /// <param name="c">The client to perform the operation on.</param> /// <param name="loc">The location to reach.</param> /// <param name="tiles">A list of tiles to use for pathfinding.</param> /// <param name="considerPlayerWalkable">Whether to consider the player as walkable.</param> /// <param name="considerCreatureOnLocationWalkable">Whether to consider any creatures on the target location as walkable.</param> /// <returns></returns> public IEnumerable <Objects.PathFinder.Node> GetTilesToLocation(Objects.Client c, Location loc, Map.TileCollection tiles, bool considerPlayerWalkable = false, bool considerCreatureOnLocationWalkable = false) { return(this.GetTilesToLocation(c, loc, tiles, c.PathFinder, considerPlayerWalkable, considerCreatureOnLocationWalkable)); }
/// <summary> /// Checks whether this location can reach another location. /// </summary> /// <param name="c">The client to perform the operation on.</param> /// <param name="loc">The location to reach.</param> /// <param name="tiles">A list of tiles to use for pathfinding.</param> /// <param name="pathFinder">The pathfinder to use.</param> /// <returns></returns> public bool CanReachLocation(Objects.Client c, Location loc, Map.TileCollection tiles, Objects.PathFinder pathFinder) { return(this.GetTilesToLocation(c, loc, tiles, pathFinder, false).ToArray <Objects.PathFinder.Node>().Length > 0); }
/// <summary> /// Checks whether this location can reach another location. /// </summary> /// <param name="c">The client to perform the operation on.</param> /// <param name="loc">The location to reach.</param> /// <param name="tiles">A list of tiles to use for pathfinding.</param> /// <returns></returns> public bool CanReachLocation(Objects.Client c, Location loc, Map.TileCollection tiles) { return(this.CanReachLocation(c, loc, tiles, c.LocalPathFinder)); }
/// <summary> /// Checks whether this creature is shootable. /// </summary> /// <param name="tileCollection">The tile collection to use for pathfinding.</param> /// <returns></returns> public bool IsShootable(Map.TileCollection tileCollection) { return(this.Client.Player.Location.CanShootLocation(this.Client, this.Location, tileCollection)); }
/// <summary> /// Gets a list of nodes to this creature. Includes start node and end node. Returns null if no path found. /// </summary> /// <param name="tileCollection">The list of tiles on screen to use for pathfinding.</param> /// <returns></returns> public IEnumerable <Objects.PathFinder.Node> GetTilesToCreature(Map.TileCollection tileCollection) { return(this.GetTilesToCreature(tileCollection, this.Client.PathFinder)); }
/// <summary> /// Checks whether this creature is reachable. /// </summary> /// <param name="tileCollection">The tiles on screen to use for pathfinding.</param> /// <param name="pathFinder">The pathfinder to use.</param> /// <returns></returns> public bool IsReachable(Map.TileCollection tileCollection, Objects.PathFinder pathFinder) { return(this.GetTilesToCreature(tileCollection, pathFinder).ToList <Objects.PathFinder.Node>().Count > 0); }
/// <summary> /// Checks whether this creature is reachable. /// </summary> /// <param name="tileCollection">The tiles on screen to use for pathfinding.</param> /// <returns></returns> public bool IsReachable(Map.TileCollection tileCollection) { return(this.IsReachable(tileCollection, this.Client.PathFinder)); }