Example #1
0
 /// <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();
 }
Example #2
0
            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);
            }
Example #3
0
            /// <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);
            }
Example #4
0
            /// <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);
            }
Example #5
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);
            }
Example #6
0
            /// <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);
            }
Example #7
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);
                    }
                }
            }
Example #8
0
            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);
                        }
                    }
                }
            }
Example #9
0
 public void UpdateCache(Map.TileCollection tileCollection)
 {
     this.CachedTiles = tileCollection;
     this.ResetEventMultiUse.Set();
 }
Example #10
0
            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);
                        }
                    }
                }
            }
Example #11
0
        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);
            }
        }
Example #12
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;
        }