/// <summary> /// Updates this targeter's cache. /// </summary> /// <param name="tileCollection">A collection of tiles to use for pathfinding.</param> /// <param name="visibleCreatures">A collection of currently visible creatures.</param> /// <param name="visiblePlayers">A collection of currently visible players.</param> public void UpdateCache(Map.TileCollection tileCollection, IEnumerable <Objects.Creature> visibleCreatures, IEnumerable <Objects.Creature> visiblePlayers) { this.CachedTiles = tileCollection; this.CachedCreatures = visibleCreatures; this.CachedPlayers = visiblePlayers; this.ResetEventCacheUpdated.Set(); }
public bool OpenCorpse(Map.TileCollection tileCollection, Objects.Map.Tile tile) { if (!this.Parent.Client.Player.Location.IsOnScreen(tile.WorldLocation)) { return(false); } if (this.DedicatedThread == null || !this.DedicatedThread.IsAlive) { this.DedicatedThread = new Thread(this.Run); this.DedicatedThread.Start(); this.ResetEventMultiUse.WaitOne(); } if (this.OpenCorpseCalled != null) { this.OpenCorpseCalled(tileCollection, tile); } return(true); }
/// <summary> /// Starts executing a waypoint. /// </summary> /// <param name="wp">The waypoint to execute.</param> /// <param name="cachedTiles">The cached tiles to use for pathfinding.</param> /// <returns></returns> public bool ExecuteWaypoint(Waypoint wp, Map.TileCollection cachedTiles) { // check if thread is busy if (this.ResetEvent.IsSet) { return(false); } this.CurrentWaypoint = wp; if (this.DedicatedThread == null || !this.DedicatedThread.IsAlive) { this.DedicatedThread = new Thread(this.Run); this.DedicatedThread.Start(); } this.UpdateCache(cachedTiles); this.ResetEvent.Set(); return(true); }
/// <summary> /// Starts executing a target. /// </summary> /// <param name="t">The target to execute.</param> /// <param name="cachedTiles">A collection of tiles to use for pathfinding.</param> /// <param name="visibleCreatures">A collection of currently visible creatures.</param> /// <param name="visiblePlayers">A collection of currently visible players.</param> /// <returns></returns> public bool ExecuteTarget(Target t, Map.TileCollection cachedTiles, IEnumerable <Objects.Creature> visibleCreatures, IEnumerable <Objects.Creature> visiblePlayers) { // check if thread is busy if (this.ResetEvent.IsSet) { return(false); } this.CurrentTarget = t; if (this.DedicatedThread == null || !this.DedicatedThread.IsAlive) { this.DedicatedThread = new Thread(this.Run); this.DedicatedThread.Start(); } this.UpdateCache(cachedTiles, visibleCreatures, visiblePlayers); this.ResetEvent.Set(); return(true); }
/// <summary> /// Attempts to get the best location to move to. Returns Objects.Location.Invalid if unsuccessful. /// </summary> /// <param name="setting">The setting to use.</param> /// <param name="tileCollection">The tiles that are visible on screen.</param> /// <param name="creaturesOnScreen">The creatures that are visible on screen.</param> /// <returns></returns> public Objects.Location GetBestLocation(Target.Setting setting, Map.TileCollection tileCollection, IEnumerable <Objects.Creature> creaturesOnScreen, Stack <Objects.Location> backtrackedLocations = null) { if (this.Creature == null) { return(null); } Map.Tile playerTile = tileCollection.GetTile(count: this.Parent.Client.Player.ID), targetTile = tileCollection.GetTile(count: this.Creature.ID); if (playerTile == null || targetTile == null) { return(null); } Map.TileCollection adjacentTiles = tileCollection.GetAdjacentTileCollection(targetTile); List <Objects.PathFinder.Node> pfNodes = null; int closest = 15; Objects.Location bestLocation = Objects.Location.Invalid; switch (setting.FightStance) { case Enums.FightStance.FollowDiagonalOnly: if (playerTile.WorldLocation.IsAdjacentDiagonalOnly(targetTile.WorldLocation)) { break; } int closestNonDiagonal = 15; Objects.Location bestNonDiagonalLocation = Objects.Location.Invalid; foreach (Map.Tile tile in adjacentTiles.GetTiles()) { if (!tile.IsWalkable()) { continue; } //if (!tile.WorldLocation.IsAdjacentDiagonalOnly(targetTile.WorldLocation)) continue; pfNodes = playerTile.WorldLocation.GetTilesToLocation(this.Parent.Client, tile.WorldLocation, tileCollection, this.Parent.PathFinder, true).ToList <Objects.PathFinder.Node>(); if (pfNodes.Count > 0) { if (this.Parent.CurrentSettings.AllowDiagonalMovement && playerTile.WorldLocation.IsAdjacentDiagonalOnly(targetTile.WorldLocation)) { continue; } if (pfNodes.Count - 1 < closest && tile.WorldLocation.IsAdjacentDiagonalOnly(targetTile.WorldLocation)) { closest = pfNodes.Count - 1; bestLocation = tile.WorldLocation; } else if (pfNodes.Count - 1 < closestNonDiagonal && tile.WorldLocation.IsAdjacentNonDiagonalOnly(targetTile.WorldLocation)) { closestNonDiagonal = pfNodes.Count - 1; bestNonDiagonalLocation = tile.WorldLocation; } } } if (!bestLocation.IsValid()) { bestLocation = bestNonDiagonalLocation; } break; case Enums.FightStance.FollowStrike: if (playerTile.WorldLocation.IsAdjacentNonDiagonalOnly(targetTile.WorldLocation)) { break; } foreach (Map.Tile tile in adjacentTiles.GetTiles()) { if (!tile.WorldLocation.IsAdjacentNonDiagonalOnly(targetTile.WorldLocation)) { continue; } pfNodes = playerTile.WorldLocation.GetTilesToLocation(this.Parent.Client, tile.WorldLocation, tileCollection, this.Parent.PathFinder, true).ToList <Objects.PathFinder.Node>(); if (pfNodes.Count > 0 && pfNodes.Count - 1 < closest && (!this.Parent.CurrentSettings.AllowDiagonalMovement || playerTile.WorldLocation.IsAdjacentDiagonalOnly(targetTile.WorldLocation))) { closest = pfNodes.Count - 1; bestLocation = tile.WorldLocation; } } break; case Enums.FightStance.DistanceFollow: case Enums.FightStance.DistanceWait: // map creature tiles and the path nodes to them from the player Dictionary <Map.Tile, List <Objects.PathFinder.Node> > creatureTiles = new Dictionary <Map.Tile, List <Objects.PathFinder.Node> >(); // add the current target creatureTiles.Add(targetTile, this.Creature.GetTilesToCreature(tileCollection, this.Parent.PathFinder).ToList <Objects.PathFinder.Node>()); // check whether to add other monsters as well if (this.Parent.CurrentSettings.ConsiderAllMonstersWhenKeepingAway) { foreach (Objects.Creature c in creaturesOnScreen) { Map.Tile t = tileCollection.GetTile(count: c.ID); if (t != null && !creatureTiles.ContainsKey(t)) { creatureTiles.Add(t, c.GetTilesToCreature(tileCollection, this.Parent.PathFinder).ToList <Objects.PathFinder.Node>()); } } } // check if the player needs to move // also set the player's location as default location to return bool needToMove = false; bestLocation = playerTile.WorldLocation; foreach (var keypair in creatureTiles) { // check if creature can reach the player if (keypair.Value.Count == 0) { continue; } if (keypair.Value.Count < setting.DistanceRange || (setting.FightStance == Enums.FightStance.DistanceFollow && keypair.Value.Count > setting.DistanceRange)) { needToMove = true; } } if (!needToMove) { break; } int bestRange = 1; Map.Tile bestTile = playerTile; // calculate distance to the player's tile foreach (var keypair in creatureTiles) { pfNodes = keypair.Value; if (pfNodes.Count == 0) { continue; } int count = pfNodes.Count; bestRange += Math.Abs(setting.DistanceRange - count) * (count < setting.DistanceRange ? 2 : 1); } if (backtrackedLocations != null && backtrackedLocations.Count > 0) { Objects.Location peekLoc = backtrackedLocations.Peek(); if (peekLoc.IsOnScreen(playerTile.WorldLocation)) { bestLocation = peekLoc; break; } } // calculate and set foreach (Map.Tile t in tileCollection.GetAdjacentTileCollection(playerTile).GetTiles()) { if (t == null || !t.IsWalkable()) { continue; } if (this.Parent.CurrentSettings.AllowDiagonalMovement && playerTile.WorldLocation.IsAdjacentDiagonalOnly(t.WorldLocation)) { continue; } // calculate distance for creatures int distance = 0; foreach (var keypair in creatureTiles) { pfNodes = keypair.Key.WorldLocation.GetTilesToLocation(this.Parent.Client, t.WorldLocation, tileCollection, this.Parent.PathFinder, true).ToList <Objects.PathFinder.Node>(); if (pfNodes.Count == 0) { continue; } int count = pfNodes.Count - 1; distance += Math.Abs(setting.DistanceRange - count) * (count < setting.DistanceRange ? 2 : 1); } // get next tile in same general direction bool good = false; int directionX = playerTile.WorldLocation.X - t.WorldLocation.X, directionY = playerTile.WorldLocation.Y - t.WorldLocation.Y; foreach (Map.Tile nextTile in tileCollection.GetAdjacentTileCollection(t).GetTiles()) { if (nextTile == null || !nextTile.IsWalkable()) { continue; } if (t.WorldLocation.X - nextTile.WorldLocation.X != directionX && t.WorldLocation.Y - nextTile.WorldLocation.Y != directionY) { continue; } if (nextTile == playerTile) { continue; } good = true; break; } if (!good) { continue; } // check of tile is better than previous tile if (bestRange > distance) { bestRange = distance; bestLocation = t.WorldLocation; } } break; case Enums.FightStance.FollowEconomic: break; } return(bestLocation); }
/// <summary> /// Attempts to get the best setting for this target. Also sets CurrentSettingIndex. Returns null if unsuccessful. /// </summary> /// <param name="creaturesOnScreen">A collection of creatures visible on screen.</param> /// <param name="playersOnScreen">A collection of players visible on screen.</param> /// <param name="tileCollection">A collection of tiles visible on screen.</param> /// <param name="setCreature">Whether to set this target's Creature.</param> /// <returns></returns> public Target.Setting GetBestSetting(IEnumerable <Objects.Creature> creaturesOnScreen, IEnumerable <Objects.Creature> playersOnScreen, Map.TileCollection tileCollection, bool setCreature) { // check if there are any settings to use bool found = false; foreach (Target.Setting s in this.GetSettings()) { if (s.UseThisSetting) { found = true; break; } } if (!found) { return(null); } // set up the player's tile and other variables Map.Tile playerTile = tileCollection.GetTile(count: this.Parent.Client.Player.ID); if (playerTile == null) { return(null); } List <Objects.Creature> creatures = new List <Objects.Creature>(), players = new List <Objects.Creature>(); foreach (Objects.Creature c in creaturesOnScreen) { if (c.Name.ToLower() == this.Name.ToLower()) { creatures.Add(c); } } foreach (Objects.Creature p in playersOnScreen.ToArray()) { if (p.ID != this.Parent.Client.Player.ID) { players.Add(p); } } // calculate best setting int bestCount = 0, bestIndex = 0, index = 0; Target.Setting bestSetting = null; Objects.Creature bestCreature = null; foreach (Target.Setting setting in this.GetSettings()) { if (!setting.UseThisSetting) { continue; } int count = 0, bestCreatureDistance = setting.Range + 1; Objects.Creature tempCreature = null; foreach (Objects.Creature c in creatures) { if (!c.IsVisible) { continue; } Map.Tile creatureTile = tileCollection.GetTile(count: c.ID); if (creatureTile == null) { continue; } if (!playerTile.WorldLocation.IsOnScreen(creatureTile.WorldLocation)) { continue; } if (this.Parent.CurrentSettings.FriendlyMode && players.Count > 0 && !c.HasAttackedMeRecently(4000)) { continue; } if (setting.MustBeShootable && !c.IsShootable(tileCollection)) { continue; } var pfNodes = c.GetTilesToCreature(tileCollection, this.Parent.PathFinder) .ToList <Objects.PathFinder.Node>(); if (setting.MustBeReachable && pfNodes.Count == 0) { continue; } if ((pfNodes.Count > 0 ? pfNodes.Count : playerTile.WorldLocation.DistanceTo(creatureTile.WorldLocation)) > setting.Range) { continue; } count++; if (setCreature) { int distance = pfNodes.Count > 0 ? pfNodes.Count : (int)playerTile.WorldLocation.DistanceTo(creatureTile.WorldLocation); if (distance < bestCreatureDistance) { bestCreatureDistance = distance; tempCreature = c; } } } if (count == 0 || count < setting.Count) { continue; } if (count > bestCount) { bestCount = count; bestSetting = setting; bestIndex = index; bestCreature = tempCreature; } index++; } this.CurrentSettingIndex = bestSetting != null ? bestIndex : -1; if (bestSetting != null && bestCreature != null) { this.Creature = bestCreature; } return(bestSetting); }
private void LootItems(Objects.Container lootContainer, IEnumerable <Loot> loots, Map.TileCollection tiles) { Random rand = new Random(); if (!this.Parent.StopwatchFoodEater.IsRunning) { this.Parent.StopwatchFoodEater.Start(); } int index = lootContainer.ItemsAmount - 1, retryCount = 0; while (index >= 0 && !this.Cancel) { // sanity checks if (lootContainer.ItemsAmount == 0 || !lootContainer.IsOpen) { break; } if (retryCount >= 3) { retryCount = 0; index--; continue; } // get item Objects.Item item = lootContainer.GetItemInSlot((byte)index); if (item == null) { index--; retryCount = 0; continue; } // check if it's food, eat it if so if (this.Parent.CurrentSettings.EatFood && this.Parent.StopwatchFoodEater.Elapsed.TotalSeconds > 20 && this.Parent.Client.ItemList.Food.All.Contains(item.ID)) { if (item.Count <= 1) { item.Use(); } else { for (int i = 0; i < Math.Min(item.Count, (ushort)3); i++) { item.Use(); Thread.Sleep(rand.Next(200, 325)); } } this.Parent.StopwatchFoodEater.Restart(); Thread.Sleep(rand.Next(200, 350)); index--; continue; } // check if we want to loot this item Loot loot = null; foreach (Loot l in loots) { if (l.ID == item.ID) { loot = l; break; } } if (loot == null) { index--; continue; } // loot this item bool successful = false; switch (loot.Destination) { case Loot.Destinations.Ground: Objects.Map.Tile playerTile = tiles.GetTile(count: this.Parent.Client.Player.ID); if (playerTile == null) { break; } List <Map.Tile> adjacentTiles = tiles.GetAdjacentTileCollection(playerTile).GetTiles().ToList(); adjacentTiles.Shuffle(); foreach (Objects.Map.Tile tile in adjacentTiles) { if (!tile.IsWalkable()) { continue; } item.Move(new Objects.ItemLocation(tile.WorldLocation)); successful = true; break; } break; case Loot.Destinations.EmptyContainer: Objects.ItemLocation toItem = this.Parent.Client.Inventory.GetFirstSuitableSlot(item, loot.Index); if (toItem == null) { break; } item.Move(toItem); successful = true; break; } // if successful, check if it's looted // if it wasn't looted, try again if (successful) { if (!item.WaitForInteraction(800)) { retryCount++; continue; } if (this.Parent.ItemLooted != null) { this.Parent.ItemLooted(item); } if (!this.Parent.CurrentSettings.FastLooting) { Thread.Sleep(rand.Next(400, 700)); } } retryCount = 0; index--; } if (this.Parent.CurrentSettings.OpenContainers && !this.Cancel && lootContainer.IsOpen && lootContainer.ItemsAmount > 0) { bool found = false; foreach (Objects.Item item in lootContainer.GetItems().Reverse()) { if (item.HasFlag(Enums.ObjectPropertiesFlags.IsContainer)) { for (int i = 0; i < 3; i++) { item.Use(); if (item.WaitForInteraction(800)) { break; } } found = true; break; } } if (found) { this.LootItems(lootContainer, loots, this.CachedTiles); } } }
private void Run() { Map.TileCollection tiles = null; Objects.Map.Tile corpseTile = null; Objects.Container lootContainer = null; Loot[] loots = null; Random rand = new Random(); this.OpenCorpseCalled += new OpenCorpseCalledHandler(delegate(Map.TileCollection tileCollection, Objects.Map.Tile tile) { tiles = tileCollection; corpseTile = tile; this.ResetEvent.Set(); }); this.LootItemsCalled += new LootItemsCalledHandler(delegate(Objects.Container container, IEnumerable <Loot> loot) { lootContainer = container; loots = loot.ToArray(); this.ResetEvent.Set(); }); // signal parent thread that this thread is ready this.ResetEventMultiUse.Set(); while (true) { try { this.Cancel = false; this.ResetEvent.Wait(); #region open corpse if (corpseTile != null) { while (!this.Cancel) { this.ResetEventMultiUse.WaitOne(); if (this.Cancel || corpseTile == null) { break; } if (!this.Parent.Client.Player.Location.IsOnScreen(corpseTile.WorldLocation)) { break; } if (this.Parent.Client.Player.IsWalking) { continue; } Map.TileObject topItem = corpseTile.GetTopUseItem(false); if (topItem == null || !topItem.HasFlag(Enums.ObjectPropertiesFlags.IsContainer)) { break; } Objects.Map.Tile playerTile = this.CachedTiles.GetTile(count: this.Parent.Client.Player.ID); if (playerTile == null) { break; } if (playerTile.WorldLocation.DistanceTo(corpseTile.WorldLocation) >= 2) { int distance = int.MaxValue; Objects.Map.Tile bestTile = corpseTile; foreach (Objects.Map.Tile tile in this.CachedTiles.GetAdjacentTileCollection(corpseTile).GetTiles()) { if (!tile.IsWalkable()) { continue; } var pathToTile = playerTile.WorldLocation.GetTilesToLocation(this.Parent.Client, tile.WorldLocation, this.CachedTiles, this.Parent.PathFinder, true).ToArray(); if (pathToTile.Length == 0) { continue; } if (distance > pathToTile.Length) { distance = pathToTile.Length; bestTile = tile; } } if (bestTile == corpseTile && !playerTile.WorldLocation.CanReachLocation(this.Parent.Client, bestTile.WorldLocation)) { break; } this.Parent.Client.Player.GoTo = bestTile.WorldLocation; continue; } for (int i = 0; i < 2; i++) { if (this.Cancel) { break; } Objects.Container container = this.Parent.Client.Inventory.GetContainer(this.Parent.Client.Inventory.GetClosedContainerNumber()); topItem.Use(); for (int j = 0; j < 5; j++) { Thread.Sleep(100); if (container.IsOpen) { break; } } if (!container.IsOpen) { continue; } if (this.CorpseOpened != null) { this.CorpseOpened(container); } break; } break; } corpseTile = null; } #endregion #region loot item(s) if (lootContainer != null) { if (!lootContainer.IsOpen || lootContainer.ItemsAmount == 0) { if (!this.Cancel && this.LootingFinished != null) { this.LootingFinished(lootContainer); } lootContainer = null; continue; } this.LootItems(lootContainer, loots, tiles); if (!this.Cancel && this.LootingFinished != null) { this.LootingFinished(lootContainer); } lootContainer = null; loots = null; } #endregion this.ResetEvent.Reset(); } catch (Exception ex) { if (this.ErrorOccurred != null) { this.ErrorOccurred(ex); } } } }
public void UpdateCache(Map.TileCollection tileCollection) { this.CachedTiles = tileCollection; this.ResetEventMultiUse.Set(); }
private void Run() { while (true) { try { this.ResetEvent.Wait(); if (this.WaypointExecutedBegin != null) { this.WaypointExecutedBegin(this.CurrentWaypoint); } bool success = false, firstRun = true; Objects.Location currentSubNode = Objects.Location.Invalid; while (!this.Cancel) { this.ResetEventTilesUpdated.WaitOne(); if (this.Cancel) { break; } Objects.Player player = this.Parent.Client.Player; Objects.Location playerLoc = player.Location; if (player.Z != this.CurrentWaypoint.Location.Z) { break; } if (firstRun) { firstRun = false; } else { if (this.Parent.Client.Window.StatusBar.GetText() == Enums.StatusBar.ThereIsNoWay) { this.Parent.Client.Window.StatusBar.SetText(string.Empty); success = false; break; } } bool isOnScreen = playerLoc.IsOnScreen(this.CurrentWaypoint.Location), doBreak = false; var tilesToLocation = isOnScreen ? playerLoc.GetTilesToLocation(this.Parent.Client, this.CurrentWaypoint.Location, this.CachedTiles, this.Parent.PathFinder) .ToList <Objects.PathFinder.Node>() : new List <Objects.PathFinder.Node>(); switch (this.CurrentWaypoint.Type) { case Waypoint.Types.Walk: #region walk if (playerLoc == this.CurrentWaypoint.Location) { doBreak = true; success = true; break; } if (isOnScreen && tilesToLocation.Count == 0) { doBreak = true; success = false; break; } if (!player.IsWalking || player.GoTo != this.CurrentWaypoint.Location) { player.GoTo = this.CurrentWaypoint.Location; } #endregion break; case Waypoint.Types.Node: #region node if (playerLoc == this.CurrentWaypoint.Location) { doBreak = true; success = true; break; } if (isOnScreen && tilesToLocation.Count == 0) { doBreak = true; success = false; break; } // check if the player is already walking to a node if (player.IsWalking) { int range = this.Parent.CurrentSettings.NodeRadius; Objects.Location currentGoTo = player.GoTo; bool found = false; for (int x = -range; x <= range; x++) { for (int y = -range; y <= range; y++) { Objects.Location subNode = this.CurrentWaypoint.Location.Offset(x, y); if (currentGoTo != subNode) { continue; } // check distance to node if (isOnScreen) { var tilesToSubNode = playerLoc.GetTilesToLocation(this.Parent.Client, subNode, this.CachedTiles, this.Parent.PathFinder, true).ToArray(); if (tilesToSubNode.Length <= this.Parent.CurrentSettings.NodeSkipRange) { success = true; doBreak = true; break; } } found = true; break; } if (found) { break; } } if (found) { break; } } else if (playerLoc.DistanceTo(this.CurrentWaypoint.Location) <= this.Parent.CurrentSettings.NodeSkipRange) { success = true; doBreak = true; break; } // find new node to walk to if (isOnScreen) { Map.Tile tile = this.CachedTiles.GetTile(this.CurrentWaypoint.Location); if (tile == null) { doBreak = true; success = false; break; } Map.TileCollection nearbyTiles = this.CachedTiles.GetNearbyTileCollection(tile, this.Parent.CurrentSettings.NodeRadius); Objects.Location loc = tilesToLocation.Count != 0 ? tile.WorldLocation : Objects.Location.Invalid; List <Map.Tile> goodTiles = new List <Map.Tile>(); foreach (Map.Tile nearbyTile in nearbyTiles.GetTiles()) { bool isReachable = playerLoc.CanReachLocation(this.Parent.Client, nearbyTile.WorldLocation, this.CachedTiles, this.Parent.PathFinder); if (isReachable) { goodTiles.Add(nearbyTile); } } if (goodTiles.Count > 0) { loc = goodTiles[new Random().Next(goodTiles.Count)].WorldLocation; } if (loc.IsValid()) { player.GoTo = loc; } else { doBreak = true; success = false; break; } } else if (this.Parent.CurrentSettings.UseAlternateNodeFinder) { int range = this.Parent.CurrentSettings.NodeRadius; Random rand = new Random(); Objects.Location loc = this.CurrentWaypoint.Location; for (int x = -range; x <= range; x++) { for (int y = -range; y <= range; y++) { Objects.Location subNode = this.CurrentWaypoint.Location.Offset( rand.Next(-range, range + 1), rand.Next(-range, range + 1)); if (!this.Parent.Client.Modules.MapViewer.IsWalkable(subNode)) { continue; } loc = subNode; break; } if (loc != this.CurrentWaypoint.Location) { break; } } player.GoTo = loc; } else // use stored subnodes { Objects.Location loc = this.CurrentWaypoint.Location; if (this.CurrentWaypoint.NodeLocations.Count > 0) { int index = -1, newIndex = new Random().Next(-1, this.CurrentWaypoint.NodeLocations.Count); if (newIndex != index) { loc = this.CurrentWaypoint.NodeLocations[newIndex]; } } player.GoTo = loc; } #endregion break; case Waypoint.Types.Machete: case Waypoint.Types.Pick: case Waypoint.Types.Rope: case Waypoint.Types.Shovel: #region tools // check if we're adjacent to the waypoint if (playerLoc.IsAdjacentTo(this.CurrentWaypoint.Location)) { Objects.Item tool = null; switch (this.CurrentWaypoint.Type) { case Waypoint.Types.Machete: tool = this.Parent.Client.Inventory.GetItem(this.Parent.Client.ItemList.Tools.Machete); break; case Waypoint.Types.Pick: tool = this.Parent.Client.Inventory.GetItem(this.Parent.Client.ItemList.Tools.Pick); break; case Waypoint.Types.Rope: tool = this.Parent.Client.Inventory.GetItem(this.Parent.Client.ItemList.Tools.Rope); break; case Waypoint.Types.Shovel: tool = this.Parent.Client.Inventory.GetItem(this.Parent.Client.ItemList.Tools.Shovel); break; } if (tool == null) { doBreak = true; success = false; break; } Map.Tile tile = this.CachedTiles.GetTile(this.CurrentWaypoint.Location); if (tile == null) { success = false; doBreak = true; break; } Map.TileObject topItem = tile.GetTopUseItem(true); if (this.CurrentWaypoint.Type != Waypoint.Types.Rope) { tool.UseOnTileObject(topItem); success = true; doBreak = true; } else { if (topItem.StackIndex != 0) { // find a non-blocking adjacent tile var adjacentTiles = this.CachedTiles.GetAdjacentTileCollection(tile).GetTiles() .ToList <Map.Tile>(); Map.Tile bestTile = tile; foreach (Map.Tile t in adjacentTiles.ToArray()) { if (!t.IsWalkable()) { adjacentTiles.Remove(t); } } if (adjacentTiles.Count > 0) { bestTile = adjacentTiles[new Random().Next(adjacentTiles.Count)]; } topItem.Move(bestTile.ToItemLocation()); } else { tool.UseOnTileObject(topItem); for (int i = 0; i < 3; i++) { Thread.Sleep(100); if (player.Z != this.CurrentWaypoint.Location.Z) { doBreak = true; success = true; break; } } } } break; } else if (isOnScreen) { Map.Tile tile = this.CachedTiles.GetTile(this.CurrentWaypoint.Location); if (tile == null) { success = false; doBreak = true; break; } Map.TileCollection adjacentTiles = this.CachedTiles.GetAdjacentTileCollection(tile); Objects.Location bestLoc = Objects.Location.Invalid; int distance = int.MaxValue; foreach (Map.Tile adjTile in adjacentTiles.GetTiles()) { if (!adjTile.IsWalkable()) { continue; } var tilesToAdjTile = playerLoc.GetTilesToLocation(this.Parent.Client, adjTile.WorldLocation, this.CachedTiles, this.Parent.PathFinder, true) .ToArray <Objects.PathFinder.Node>(); if (tilesToAdjTile.Length == 0) { continue; } if (tilesToAdjTile.Length < distance) { bestLoc = adjTile.WorldLocation; distance = tilesToAdjTile.Length; } } if (bestLoc.IsValid()) { player.GoTo = bestLoc; } else { doBreak = true; success = false; break; } } else if (!player.IsWalking) { player.GoTo = this.CurrentWaypoint.Location; } #endregion break; case Waypoint.Types.Ladder: #region ladder if (player.IsWalking) { break; } if (isOnScreen) { Map.Tile tile = this.CachedTiles.GetTile(this.CurrentWaypoint.Location); if (tile == null) { doBreak = true; success = false; break; } if (playerLoc.DistanceTo(this.CurrentWaypoint.Location) < 2) { Map.TileObject topItem = tile.GetTopUseItem(false); if (topItem == null) { doBreak = true; success = false; break; } for (int i = 0; i < 3; i++) { topItem.Use(); Thread.Sleep(300); if (player.Z != this.CurrentWaypoint.Location.Z) { doBreak = true; success = true; break; } } break; } // find suitable loc to walk to int distance = int.MaxValue; Objects.Location bestLoc = Objects.Location.Invalid; foreach (Map.Tile adjTile in this.CachedTiles.GetAdjacentTileCollection(tile).GetTiles()) { if (!adjTile.IsWalkable()) { continue; } var tilesToAdjTile = playerLoc.GetTilesToLocation(this.Parent.Client, adjTile.WorldLocation, this.CachedTiles, this.Parent.PathFinder, true) .ToArray <Objects.PathFinder.Node>(); if (tilesToAdjTile.Length == 0) { continue; } if (tilesToAdjTile.Length < distance) { distance = tilesToAdjTile.Length; bestLoc = adjTile.WorldLocation; } } if (bestLoc.IsValid()) { player.GoTo = bestLoc; } else { doBreak = true; success = false; } break; } else { player.GoTo = this.CurrentWaypoint.Location; } #endregion break; } if (doBreak) { break; } } if (this.WaypointExecutedEnd != null) { this.WaypointExecutedEnd(this.CurrentWaypoint, success); } this.ResetEvent.Reset(); } catch (Exception ex) { if (this.ErrorOccurred != null) { this.ErrorOccurred(ex); } } } }
private void btnWaypointsInsert_Click(object sender, EventArgs e) { if (!Client.Player.Connected || Client.Player.Health == 0) { return; } if (comboboxWaypointsOffset.SelectedIndex < 0 || comboboxWaypointsType.SelectedIndex < 0 || listboxWaypoints.SelectedIndex < 0) { return; } Modules.Cavebot.Waypoint.Types type; switch (comboboxWaypointsType.Text) { case "Node": type = Modules.Cavebot.Waypoint.Types.Node; break; case "Walk": type = Modules.Cavebot.Waypoint.Types.Walk; break; case "Rope": type = Modules.Cavebot.Waypoint.Types.Rope; break; case "Shovel": type = Modules.Cavebot.Waypoint.Types.Shovel; break; case "Machete": type = Modules.Cavebot.Waypoint.Types.Machete; break; case "Pick": type = Modules.Cavebot.Waypoint.Types.Pick; break; case "Ladder": type = Modules.Cavebot.Waypoint.Types.Ladder; break; case "Script": type = Modules.Cavebot.Waypoint.Types.Script; break; default: type = Modules.Cavebot.Waypoint.Types.Node; break; } int diffX = 0, diffY = 0; switch (comboboxWaypointsOffset.SelectedIndex) { case 0: break; case 1: diffY = -1; break; case 2: diffX = 1; break; case 3: diffY = 1; break; case 4: diffX = -1; break; } int index = listboxWaypoints.SelectedIndex; if (type == Modules.Cavebot.Waypoint.Types.Script) { Objects.Location loc = new Objects.Location(this.Client.Player.X + diffX, this.Client.Player.Y + diffY, this.Client.Player.Z); Modules.Cavebot.Waypoint wp = new Modules.Cavebot.Waypoint(this.Client.Modules.Cavebot, loc, Modules.Cavebot.Waypoint.Types.Script); this.Client.Modules.Cavebot.InsertWaypoint(wp, index); } else { Modules.Cavebot.Waypoint wp = new Modules.Cavebot.Waypoint(this.Client.Modules.Cavebot, new Objects.Location(this.Client.Player.X + diffX, this.Client.Player.Y + diffY, this.Client.Player.Z), type); if (type == Modules.Cavebot.Waypoint.Types.Node && numericSettingsNodeRadius.Value > 0) { ushort pX = this.Client.Player.X, pY = this.Client.Player.Y; byte pZ = this.Client.Player.Z, radius = (byte)numericSettingsNodeRadius.Value; Map.TileCollection tiles = this.Client.Map.GetTilesOnScreen(); Map.Tile playerTile = tiles.GetTile(count: this.Client.Player.ID); if (playerTile == null) { MessageBox.Show("Could not find player tile"); return; } List <Objects.Location> nodeLocations = new List <Objects.Location>(); for (ushort x = (ushort)(pX - radius); x < pX + radius; x++) { for (ushort y = (ushort)(pY - radius); y < pY + radius; y++) { if (x == pX && y == pY) { continue; } Map.Tile tile = tiles.GetTile(new Objects.Location(x, y, pZ)); if (tile == null) { continue; } if (tile.IsWalkable()) { nodeLocations.Add(tile.WorldLocation); } } } wp.NodeLocations.AddRange(nodeLocations); } this.Client.Modules.Cavebot.InsertWaypoint(wp, index); } }
private void CavebotLogic() { if (this.Client == null) return; Target currentTarget = new Target(this); Objects.Location currentSubNode = Objects.Location.Invalid, currentCorpseLocation = Objects.Location.Invalid; Random rand = new Random(); Map.TileCollection tileCollection = new Map.TileCollection(this.Client, new List<Map.Tile>()); Objects.MiniMap.MergedChunk mergedChunk = null; List<Objects.Location> corpseLocations = new List<Objects.Location>(); List<Objects.Creature> creaturesToLoot = new List<Objects.Creature>(); // key = creature ID, value = time when looted (Environment.TickCount) Dictionary<uint, long> creaturesAlreadyLooted = new Dictionary<uint, long>(); bool firstWaypoint = true, doSleep = true; // set this to true if the next round should sleep this.IsRunning = true; Target.Setting bestSetting = null; ushort oldTileID = 0; Objects.Location oldTileLoc = Objects.Location.Invalid; Stack<Objects.Location> backtrackedLocations = new Stack<Objects.Location>(); while (this.IsRunning) { try { if (doSleep) Thread.Sleep(500); else doSleep = true; if (this.CurrentSettings.UseGoldStacks) { Objects.Item goldStack = this.Client.Inventory.GetItem(this.Client.ItemList.Valuables.GoldCoin, 100); if (goldStack != null) goldStack.Use(); } #region Always loot if (this.Targets.Count == 0 && this.Loots.Count > 0) { foreach (Objects.Container container in this.Client.Inventory.GetContainers()) { if (container.IsOpen && !container.Name.EndsWith("Backpack") && !container.Name.EndsWith("Bag")) { this.LootItems(container); } } } #endregion // get tiles on screen tileCollection = this.Client.Map.GetTilesOnScreen(); // get minimap data Objects.Location playerLoc = this.Client.Player.Location; //mergedChunk = this.Client.MiniMap.GetMergedChunk(playerLoc.Offset(-this.Client.Addresses.Map.CenterX, // -this.Client.Addresses.Map.CenterY), // playerLoc.Offset(this.Client.Addresses.Map.CenterX, this.Client.Addresses.Map.CenterY)); #region Targeting and looting // check if current target is null, // if so, assign it to a new value // necessary to avoid exceptions if (currentTarget == null) currentTarget = new Target(this); if (backtrackedLocations.Count > 0) { var peekedLoc = backtrackedLocations.Peek(); if (peekedLoc.Z != playerLoc.Z) backtrackedLocations.Clear(); else if (peekedLoc.DistanceTo(playerLoc) >= 3) backtrackedLocations.Push(playerLoc); } else backtrackedLocations.Push(playerLoc); /*var ptile = tileCollection.GetTile(count: this.Client.Player.ID); //if (ptile != null && ptile.Items.Count > 1) this.Client.Window.SetTitleText(this.Client.Memory.ReadUInt32(ptile.Items[1].Address).ToString()); //if (ptile != null) this.Client.Window.SetTitleText(ptile.MemoryLocation.ToString() + " - " + ptile.TileNumber + " - " + ptile.WorldLocation); //else this.Client.Window.SetTitleText("null"); foreach (Map.Tile t in tileCollection.GetTiles()) { if (t.IsWalkable(this.Client)) { this.Client.Memory.WriteUInt16(t.Ground.Address + this.Client.Addresses.MapDistances.ObjectData, 231); } else this.Client.Memory.WriteUInt16(t.Ground.Address + this.Client.Addresses.MapDistances.ObjectData, 836); }*/ if (currentTarget.Creature != null && bestSetting != null) { // add dead creatures to corpse list if (this.CurrentSettings.KillBeforeLooting) { // clear old entries long currentTime = Environment.TickCount; List<uint> keysToRemove = new List<uint>(); foreach (var keypair in creaturesAlreadyLooted) { if (currentTime > keypair.Value + 1000 * 60 * 5) { keysToRemove.Add(keypair.Key); } } foreach (var key in keysToRemove) creaturesAlreadyLooted.Remove(key); foreach (Objects.Creature c in this.Client.BattleList.GetCreatures(true, true)) { if (creaturesAlreadyLooted.ContainsKey(c.ID)) continue; string name = c.Name.ToLower(); foreach (Target t in this.GetTargets()) { if (t.Name.ToLower() == name) { uint id = c.ID; bool found = false; foreach (Objects.Creature creature in creaturesToLoot) { if (creature.ID == id) { found = true; break; } } if (!found) creaturesToLoot.Add(c); } } } playerLoc = this.Client.Player.Location; foreach (Objects.Creature c in creaturesToLoot) { if (c.IsDead && playerLoc.IsOnScreen(c.Location)) { Objects.Location loc = c.Location; Map.Tile tile = tileCollection.GetTile(loc); if (tile == null) break; Map.TileObject topItem = tile.GetTopUseItem(false); if (!this.Client.GetObjectProperty(topItem.ID).HasFlag(Enums.ObjectPropertiesFlags.IsContainer)) break; if (!corpseLocations.Contains(loc)) corpseLocations.Add(loc); break; } } } bool doLoot = false; // set to true if the cavebot should loot open containers #region Creature checks and stance stuff // initiate "loop" to allow better codeflow while (true) { // check if creature's HP% is 0 and check for new targets if target is unlootable if (!currentTarget.DoLoot && currentTarget.Creature.HealthPercent == 0) { if (this.TargetKilled != null) this.TargetKilled(currentTarget); currentTarget.Creature = null; break; } // check if creature is dead, and loot it if so if (currentTarget.Creature.IsDead) { if (this.TargetKilled != null) this.TargetKilled(currentTarget); doLoot = currentTarget.DoLoot; if (doLoot) Thread.Sleep(rand.Next(100, 250)); break; } else if (currentTarget.Creature.HealthPercent == 0) { Thread.Sleep(50); continue; } else if (!currentTarget.Creature.IsVisible) { currentTarget.Creature = null; break; } // check if creature is still on screen if (!this.Client.Player.Location.IsOnScreen(currentTarget.Creature.Location) || (!currentTarget.Creature.IsVisible && currentTarget.Creature.HealthPercent > 0)) { if (this.Client.Player.Target != 0) this.Client.Packets.Attack(0); currentTarget.Creature = null; break; } // check if the cavebot should stop attacking the creature due to out of range if (this.CurrentSettings.StopAttackingWhenOutOfRange && currentTarget.Creature.Location.DistanceTo(this.Client.Player.Location) > bestSetting.Range + 2) { if (this.Client.Player.Target != 0) this.Client.Packets.Attack(0); currentTarget.Creature = null; break; } // check if the cavebot should stop attacking if the creature is not reachable and/or shootable if ((bestSetting.MustBeReachable && !currentTarget.Creature.IsReachable(tileCollection, this.PathFinder)) || (bestSetting.MustBeShootable && !currentTarget.Creature.IsShootable(tileCollection))) { if (this.Client.Player.Target != 0) this.Client.Packets.Attack(0); currentTarget.Creature = null; break; } // check if there is a better creature to attack if (!this.CurrentSettings.StickToCreature) { Target newTarget = this.GetBestTarget(tileCollection, this.Client.BattleList.GetCreatures(true, true), this.Client.BattleList.GetPlayers(true, true), true); if (newTarget != null && currentTarget != newTarget) { currentTarget = newTarget; doSleep = false; break; } } // check if player is attacking wrong creature if (currentTarget.Creature.ID != this.Client.Player.Target) { currentTarget.Creature.Attack(); Thread.Sleep(100); } // move according to stance, also change fight mode/stance if necessary if (this.Client.Player.FightMode != bestSetting.FightMode) this.Client.Player.FightMode = bestSetting.FightMode; Map.Tile playerTile = tileCollection.GetTile(count: this.Client.Player.ID); playerLoc = playerTile.WorldLocation; Map.Tile creatureTile = tileCollection.GetTile(count: currentTarget.Creature.ID); if (playerTile != null && creatureTile != null) { switch (bestSetting.FightStance) { case Enums.FightStance.Follow: if (this.Client.Player.FightStance != Enums.FightStance.Follow) this.Client.Player.FightStance = Enums.FightStance.Follow; break; case Enums.FightStance.FollowDiagonalOnly: case Enums.FightStance.DistanceFollow: case Enums.FightStance.DistanceWait: case Enums.FightStance.FollowStrike: if (this.Client.Player.FightStance != Enums.FightStance.Stand) this.Client.Player.FightStance = Enums.FightStance.Stand; Objects.Location targetLoc = currentTarget.GetBestLocation(bestSetting, tileCollection, this.Client.BattleList.GetCreatures(true, true), backtrackedLocations); if (!targetLoc.IsValid()) break; if (backtrackedLocations.Count > 0) { var peekedLoc = backtrackedLocations.Peek(); if (peekedLoc == targetLoc && peekedLoc.DistanceTo(playerLoc) < 2) backtrackedLocations.Pop(); } if (this.Client.Player.GoTo != targetLoc && playerLoc != targetLoc) { this.Client.Player.GoTo = targetLoc; /*Map.Tile t = tileCollection.GetTile(targetLoc); if (t == null) break; if (t.WorldLocation != oldTileLoc) { if (oldTileLoc.IsValid()) { Map.Tile oldTile = tileCollection.GetTile(oldTileLoc); this.Client.Memory.WriteUInt16(oldTile.Ground.Address + this.Client.Addresses.MapDistances.ObjectData, oldTileID); } oldTileLoc = t.WorldLocation; oldTileID = t.Ground.Data; this.Client.Memory.WriteUInt16(t.Ground.Address + this.Client.Addresses.MapDistances.ObjectData, 406); }*/ } break; case Enums.FightStance.Stand: if (this.Client.Player.FightStance != Enums.FightStance.Stand) this.Client.Player.FightStance = Enums.FightStance.Stand; break; } // Shoot rune or spell if (this.Client.Player.HealthPercent >= this.CurrentSettings.MinimumHealthToShoot && currentTarget.Creature.HealthPercent > 0) { ushort runeID = 0; if ((runeID = bestSetting.GetRuneID()) != 0) { Objects.Item rune = this.Client.Inventory.GetItem(runeID); if (rune != null) { if (!this.StopwatchExhaust.IsRunning || this.StopwatchExhaust.ElapsedMilliseconds >= this.CurrentSettings.Exhaust) { if (bestSetting.RuneIsAoE()) { Map.Tile bestTile = this.GetAreaEffectTile(bestSetting.GetAreaEffect(), tileCollection, currentTarget.Creature); if (bestTile != null) { rune.UseOnLocation(bestTile.WorldLocation); this.StopwatchExhaust.Reset(); this.StopwatchExhaust.Start(); } } else if (currentTarget.Creature.IsShootable(tileCollection)) { //rune.UseOnCreature(currentTarget.Creature); rune.UseOnBattleList(currentTarget.Creature); this.StopwatchExhaust.Reset(); this.StopwatchExhaust.Start(); } } } } else if (bestSetting.Spell != string.Empty) { if (this.Client.Player.Location.IsAdjacentNonDiagonalOnly(currentTarget.Creature.Location)) { Enums.Direction direction = Enums.Direction.Down; int diffX = playerTile.WorldLocation.X - creatureTile.WorldLocation.X, diffY = playerTile.WorldLocation.Y - creatureTile.WorldLocation.Y; if (diffX > 0) direction = Enums.Direction.Left; else if (diffX < 0) direction = Enums.Direction.Right; else if (diffY > 0) direction = Enums.Direction.Up; else if (diffY < 0) direction = Enums.Direction.Down; if ((Enums.Direction)this.Client.Player.Direction != direction) { this.Client.Packets.Turn(direction); Thread.Sleep(300); } if ((Enums.Direction)this.Client.Player.Direction == direction && (!this.StopwatchExhaust.IsRunning || this.StopwatchExhaust.ElapsedMilliseconds > this.CurrentSettings.Exhaust)) { this.Client.Packets.Say(bestSetting.Spell); this.StopwatchExhaust.Reset(); this.StopwatchExhaust.Start(); } } } } } // break loop break; } #endregion #region Loot creature if (doLoot && currentTarget.Creature != null) { Objects.Location loc = currentTarget.Creature.Location; currentTarget.Creature = null; if (this.CurrentSettings.KillBeforeLooting) corpseLocations.Add(loc); else { Objects.Container container = this.OpenCorpse(loc); if (container != null) { // loot container this.LootItems(container); container.Close(); Thread.Sleep(50); } } } #endregion } #region check for new target if (currentTarget.Creature == null) { Target newTarget = this.GetBestTarget(tileCollection, this.Client.BattleList.GetCreatures(true, true), this.Client.BattleList.GetPlayers(true, true), true); if (newTarget != null) { currentTarget = newTarget; doSleep = false; // reset exhaust stopwatch to prevent instant attack->rune this.StopwatchExhaust.Restart(); } } #endregion if (currentTarget.Creature != null) { // get target setting bestSetting = currentTarget.GetBestSetting(this.Client.BattleList.GetCreatures(true, true), this.Client.BattleList.GetPlayers(true, true), tileCollection, false); if (bestSetting == null) currentTarget.Creature = null; continue; } #region multiple corpse looting if (corpseLocations.Count > 0) { playerLoc = this.Client.Player.Location; Objects.Location closestLoc = Objects.Location.Invalid; double closestRange = double.MaxValue; foreach (Objects.Location loc in corpseLocations) { if (loc.Z != playerLoc.Z) continue; double dist = playerLoc.DistanceTo(loc); if (dist < closestRange) { closestRange = dist; closestLoc = loc; } } if (closestLoc != Objects.Location.Invalid && this.Client.Window.StatusBar.GetText() == Enums.StatusBar.ThereIsNoWay) { // remove multiples of a location foreach (Objects.Location loc in corpseLocations.ToArray()) { if (loc == closestLoc) corpseLocations.Remove(loc); } closestLoc = Objects.Location.Invalid; } else if (closestLoc != Objects.Location.Invalid) { if (playerLoc.DistanceTo(closestLoc) < 2) { Objects.Container container = this.OpenCorpse(closestLoc); if (container != null) { this.LootItems(container); container.Close(); } // remove multiples of a location foreach (Objects.Location loc in corpseLocations.ToArray()) { if (loc == closestLoc) corpseLocations.Remove(loc); } } else if (playerLoc.IsOnScreen(closestLoc) && !this.Client.Player.IsWalking) { Map.Tile tile = tileCollection.GetTile(closestLoc); Map.Tile playerTile = tileCollection.GetTile(count: this.Client.Player.ID); if (tile != null) { closestLoc = tile.WorldLocation; closestRange = playerTile.WorldLocation.DistanceTo(tile.WorldLocation); foreach (Map.Tile t in tileCollection.GetAdjacentTileCollection(tile).GetTiles()) { if (!t.IsWalkable()) continue; double dist = playerTile.WorldLocation.DistanceTo(t.WorldLocation); if (dist < closestRange) { closestLoc = tile.WorldLocation; closestRange = dist; } } this.Client.Player.GoTo = closestLoc; } } else if (!this.Client.Player.IsWalking) this.Client.Player.GoTo = closestLoc; } bool found = false; foreach (Objects.Location loc in corpseLocations) { if (loc.Z == playerLoc.Z) { found = true; break; } } if (found) continue; } #endregion #endregion #region Waypoints if (this.Waypoints.Count == 0) continue; if (firstWaypoint) { if (this.CurrentWaypointIndex == 0) { Waypoint closestWaypoint = null; int index = 0; playerLoc = this.Client.Player.Location; for (int i = 0; i < this.Waypoints.Count; i++) { Waypoint wp = this.Waypoints[i]; if (wp.Location.Z != playerLoc.Z) continue; if (closestWaypoint == null || wp.Location.DistanceTo(playerLoc) < closestWaypoint.Location.DistanceTo(playerLoc)) { closestWaypoint = wp; index = i; } } if (closestWaypoint != null) this.CurrentWaypointIndex = index; } firstWaypoint = false; } Waypoint currentWaypoint = this.GetWaypoints().ToArray<Waypoint>()[this.CurrentWaypointIndex]; if (currentWaypoint.Location.Z != this.Client.Player.Z) { // scan from index to end for a new waypoint for (int i = this.CurrentWaypointIndex; i < this.Waypoints.Count; i++) { Waypoint wp = this.Waypoints[i]; if (wp.Location.Z == this.Client.Player.Z) { this.CurrentWaypointIndex = i; currentWaypoint = wp; break; } } if (currentWaypoint.Location.Z != this.Client.Player.Z) { // scan from 0 to index for a new waypoint for (int i = 0; i < this.CurrentWaypointIndex; i++) { Waypoint wp = this.Waypoints[i]; if (wp.Location.Z == this.Client.Player.Z) { this.CurrentWaypointIndex = i; currentWaypoint = wp; break; } } } } if (currentWaypoint.Location.Z != this.Client.Player.Z) continue; if (this.Client.Window.StatusBar.GetText() == Enums.StatusBar.ThereIsNoWay) { this.Client.Window.StatusBar.SetText(string.Empty); this.CurrentWaypointIndex++; continue; } switch (currentWaypoint.Type) { case Modules.Cavebot.Waypoint.Types.Script: int oldIndex = this.CurrentWaypointIndex; currentWaypoint.Script.Run(false); if (oldIndex == this.CurrentWaypointIndex) this.CurrentWaypointIndex++; if (this.Client.Window.StatusBar.GetText() == Enums.StatusBar.ThereIsNoWay) { this.Client.Window.StatusBar.SetText(string.Empty); continue; } break; case Modules.Cavebot.Waypoint.Types.Node: if (currentSubNode.IsValid() && this.Client.Player.Location.DistanceTo(currentSubNode) <= this.CurrentSettings.NodeSkipRange) { this.CurrentWaypointIndex++; currentSubNode = Objects.Location.Invalid; break; } if (!this.Client.Player.IsWalking) { if (this.CurrentSettings.UseAlternateNodeFinder) { int tries = this.CurrentSettings.NodeRadius * 2; bool found = false; for (int i = 0; i < tries; i++) { Objects.Location loc = currentWaypoint.Location.Offset( rand.Next(-this.CurrentSettings.NodeRadius, this.CurrentSettings.NodeRadius), rand.Next(-this.CurrentSettings.NodeRadius, this.CurrentSettings.NodeRadius), 0); if (this.Client.Modules.MapViewer.IsWalkable(loc)) { currentSubNode = loc; found = true; break; } } if (!found) currentSubNode = currentWaypoint.Location; this.Client.Player.GoTo = currentSubNode; } else if (currentWaypoint.NodeLocations.Count > 0) { Objects.Location subNode = currentWaypoint.NodeLocations[rand.Next(0, currentWaypoint.NodeLocations.Count)]; this.Client.Player.GoTo = subNode; currentSubNode = subNode; } else { this.Client.Player.GoTo = currentWaypoint.Location; currentSubNode = currentWaypoint.Location; } } else { bool found = currentSubNode.IsValid() && currentWaypoint.Location == currentSubNode; if (currentSubNode.IsValid() && !found && currentWaypoint.NodeLocations.Count > 0) { foreach (Objects.Location loc in currentWaypoint.NodeLocations) { if (currentSubNode == loc) { found = true; break; } } } if (!found) { if (currentWaypoint.NodeLocations.Count > 0) { Objects.Location subNode = currentWaypoint.NodeLocations[rand.Next(0, currentWaypoint.NodeLocations.Count)]; this.Client.Player.GoTo = subNode; currentSubNode = subNode; } else { this.Client.Player.GoTo = currentWaypoint.Location; currentSubNode = currentWaypoint.Location; } } } break; case Modules.Cavebot.Waypoint.Types.Walk: if (this.Client.Player.Location == currentWaypoint.Location) this.CurrentWaypointIndex++; else if (!this.Client.Player.IsWalking) this.Client.Player.GoTo = currentWaypoint.Location; break; case Modules.Cavebot.Waypoint.Types.Rope: case Modules.Cavebot.Waypoint.Types.Shovel: case Modules.Cavebot.Waypoint.Types.Ladder: case Modules.Cavebot.Waypoint.Types.Machete: case Modules.Cavebot.Waypoint.Types.Pick: if (this.Client.Player.IsWalking) break; if (!this.Client.Player.Location.IsOnScreen(currentWaypoint.Location)) { this.Client.Player.GoTo = currentWaypoint.Location; break; } if ((this.Client.Player.Location.DistanceTo(currentWaypoint.Location) >= 2 || this.Client.Player.Location == currentWaypoint.Location) && currentWaypoint.Type != Modules.Cavebot.Waypoint.Types.Ladder) { Map.Tile playerTile = tileCollection.GetTile(count: this.Client.Player.ID); if (playerTile == null) break; Map.Tile wpTile = tileCollection.GetTile(currentWaypoint.Location); if (wpTile == null) break; double closest = 30; Objects.Location closestLoc = Objects.Location.Invalid; foreach (Map.Tile t in tileCollection.GetAdjacentTileCollection(wpTile).GetTiles()) { double dist = t.WorldLocation.DistanceTo(playerTile.WorldLocation); if (dist < closest && playerTile.WorldLocation.CanReachLocation(this.Client, t.WorldLocation, tileCollection)) { closest = dist; closestLoc = t.WorldLocation; } } if (closestLoc.IsValid()) this.Client.Player.GoTo = closestLoc; } else if (this.Client.Player.Location.IsAdjacentTo(currentWaypoint.Location) || currentWaypoint.Type == Modules.Cavebot.Waypoint.Types.Ladder) { Map.Tile playerTile = this.Client.Map.GetPlayerTile(); if (playerTile == null) break; Map.Tile t = tileCollection.GetTile(currentWaypoint.Location); if (t == null || t.ObjectsCount == 0) break; switch (currentWaypoint.Type) { case Modules.Cavebot.Waypoint.Types.Rope: if (!t.ContainsRopeHole()) { this.CurrentWaypointIndex++; break; } bool ropeHoleCleared = false; while (true) { Map.Tile ropeTile = this.Client.Map.GetTile(currentWaypoint.Location, null); if (ropeTile == null) break; Map.TileObject topItem = ropeTile.GetTopMoveItem(); if (topItem.StackIndex == 0) { ropeHoleCleared = true; break; } Objects.ObjectProperties props = this.Client.GetObjectProperty(topItem.ID); if (props.HasFlag(Enums.ObjectPropertiesFlags.IsImmobile)) break; List<Map.Tile> adjacentTiles = new List<Map.Tile>(this.Client.Map.GetAdjacentTiles(ropeTile).GetTiles()); adjacentTiles.Shuffle(); Map.Tile appropriateTile = null; foreach (Map.Tile tile in adjacentTiles) { if (tile.IsWalkable()) { appropriateTile = tile; break; } } if (appropriateTile == null) break; Map.TileObject toTopItem = appropriateTile.GetTopMoveItem(); topItem.Move(toTopItem.ToItemLocation()); Thread.Sleep(rand.Next(400, 800)); } if (!ropeHoleCleared) break; Objects.Item rope = this.Client.Inventory.GetItem(this.Client.ItemList.Tools.Rope); if (rope == null && !this.CurrentSettings.CanUseMagicRope) { this.CurrentWaypointIndex++; break; } if (rope != null) { // check if tile contains items blocking rope hole Map.Tile ropeTile = this.Client.Map.GetTile(currentWaypoint.Location, null); if (ropeTile == null) break; Map.TileObject topItem = ropeTile.GetTopUseItem(true); if (topItem.StackIndex != 0) break; for (int j = 0; j < 2; j++) { rope.UseOnTile(ropeTile); for (int i = 0; i < 12; i++) { if (this.Client.Player.Z != currentWaypoint.Location.Z) break; Thread.Sleep(100); } if (this.Client.Player.Z != currentWaypoint.Location.Z) break; } } if (this.CurrentSettings.CanUseMagicRope && currentWaypoint.Location.Z == this.Client.Player.Z && this.Client.Player.Mana >= 20) { this.Client.Player.GoTo = currentWaypoint.Location; for (int i = 0; i < 35; i++) { if (this.Client.Player.Location == currentWaypoint.Location) { this.Client.Packets.Say("exani tera"); for (int i2 = 0; i2 < 15; i2++) { if (this.Client.Player.Z != currentWaypoint.Location.Z) break; Thread.Sleep(100); } break; } Thread.Sleep(100); } } break; case Modules.Cavebot.Waypoint.Types.Ladder: if (!t.ContainsLadder()) { this.CurrentWaypointIndex++; break; } Map.TileObject ladderTileObject = t.GetTopUseItem(false); if (ladderTileObject == null) break; for (int i = 0; i < 3; i++) { ladderTileObject.Use(); for (int j = 0; j < 10; j++) { if (this.Client.Player.Z != currentWaypoint.Location.Z) break; Thread.Sleep(100); } if (this.Client.Player.Z != currentWaypoint.Location.Z) break; } this.CurrentWaypointIndex++; break; case Modules.Cavebot.Waypoint.Types.Shovel: Objects.Item shovel = this.Client.Inventory.GetItem(this.Client.ItemList.Tools.Shovel); if (shovel != null) shovel.UseOnLocation(currentWaypoint.Location); Thread.Sleep(500); this.CurrentWaypointIndex++; break; case Modules.Cavebot.Waypoint.Types.Pick: Objects.Item pick = this.Client.Inventory.GetItem(this.Client.ItemList.Tools.Pick); if (pick != null) pick.UseOnLocation(currentWaypoint.Location); Thread.Sleep(500); this.CurrentWaypointIndex++; break; case Modules.Cavebot.Waypoint.Types.Machete: Objects.Item machete = this.Client.Inventory.GetItem(this.Client.ItemList.Tools.Machete); if (machete != null) machete.UseOnLocation(currentWaypoint.Location); Thread.Sleep(500); this.CurrentWaypointIndex++; break; } } break; } #endregion } catch (ThreadAbortException ex) { } catch (Exception ex) { DateTime dt = DateTime.Now; if (ex is ThreadAbortException) { break; } else if (this.CurrentSettings.DebugMode) { try { System.IO.File.AppendAllText("errors-cavebot.txt", dt.ToString("[yyyy-MM-dd HH:mm:ss] ") + ex.Message + "\n" + ex.StackTrace + "\n" + "Variables:\nWaypoint: " + this.CurrentWaypointIndex + "/" + this.Waypoints.Count + "\nCurrentSubNode: " + (currentSubNode != null ? currentSubNode.ToString() : "null") + "\nCurrentTarget: " + (currentTarget == null ? "null" : "not null") + "\nCurrentTarget.Creature: " + ((currentTarget != null && currentTarget.Creature == null) ? "null" : "not null") + "\n"); } catch { System.IO.File.AppendAllText("errors-cavebot.txt", dt.ToString("[yyyy-MM-dd HH:mm:ss] ") + ex.Message + "\n" + ex.StackTrace + "\n"); } this.Restart(); return; } } } this.IsRunning = false; }