Exemplo n.º 1
0
            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);
                    }
                }
            }
Exemplo n.º 2
0
            /// <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);
            }
Exemplo n.º 3
0
        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;
        }