All pastes #839122 Raw Edit

Anonymous

public text v1 · immutable
#839122 ·published 2007-12-30 21:22 UTC
rendered paste body
using System;
using System.Collections.Generic;
using System.Threading;

using ChiefD2.Collections;

using D2DataNew;
using D2PacketsNew;
using D2PacketsNew.D2Packets;

using Chief;

namespace ChiefD2
{
    public abstract class Bot
    {
        #region Regular Properties
        public IClient Client;

        private Thread GameEnterThread;

        public DateTime StartTime = DateTime.Now;
        public DateTime LeftLastGameTime = DateTime.Now;

        public int GameCount = 0;
        public int GameFailedCount = 0;

        public BotProfile BotProfile;
        #endregion

        #region Game Properties
        public Hero Hero;
        public Mercenary Mercenary;

        public Mapping.Map Map;
        public uint Seed;

        public Items Items = new Items();
        public Objects Objects = new Objects();
        public Units Units = new Units();

        public Log DebugLog = new Log("Debug.log");
        public Log PickItLog = new Log("PickIt.log");
        public Log ChickenLog = new Log("Chicken.log");
        #endregion

        #region Constructors
        public Bot()
        {
            this.Hero = new Hero();
            this.Mercenary = new Mercenary();

            this.Seed = 0;
        }

        public void Initiate(IClient client, BotProfile profile)
        {
            this.Client = client;
            this.BotProfile = profile;

            if (this.BotProfile.RejuvinationDrinkDelay == 0)
                throw new Exception("Setup the delays for BotProfile");

            this.Client.GameEntered += new ClientStateChangeEventHandler(GameEnterWatchForExceptions);
            this.Client.GameExited += new ClientStateChangeEventHandler(GameExitCleanUp);
            this.Client.LobbyEntered += new ClientStateChangeEventHandler(OnLobbyEnter);
            this.Client.Killed += new ClientStateChangeEventHandler(KillProcessEvent);

            this.Map = new ChiefD2.Mapping.Map(profile.Difficulty);

            #region Listeners
            #region Realm Server
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.RealmServerPacket.GameList, new D2PacketsNew.D2Packets.PacketEventHandler(GameList));
            #endregion

            #region Game Server
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.LoadAct, new D2PacketsNew.D2Packets.PacketEventHandler(LoadAct));

            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.SkillLog, new D2PacketsNew.D2Packets.PacketEventHandler(SkillsLog));

            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.AssignPlayer, new D2PacketsNew.D2Packets.PacketEventHandler(AssignPlayer));
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.AssignNPC, new D2PacketsNew.D2Packets.PacketEventHandler(AssignNPC));
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.AssignGameObject, new D2PacketsNew.D2Packets.PacketEventHandler(AssignGameObject));
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.AssignSkill, new D2PacketsNew.D2Packets.PacketEventHandler(AssignSkill));
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.AssignPlayerCorpse, new D2PacketsNew.D2Packets.PacketEventHandler(AssignPlayerCorpse));
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.AttributeDWord, new D2PacketsNew.D2Packets.PacketEventHandler(AttributeDWord));

            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.NPCInfo, new D2PacketsNew.D2Packets.PacketEventHandler(NPCInfo));
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.MercAttributeDWord, new D2PacketsNew.D2Packets.PacketEventHandler(MercAttributeDWord));

            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.SetNPCMode, new D2PacketsNew.D2Packets.PacketEventHandler(SetNPCMode));

            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.NPCMove, new D2PacketsNew.D2Packets.PacketEventHandler(NPCMove));
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.WalkVerify, new D2PacketsNew.D2Packets.PacketEventHandler(WalkVerify));
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.PlayerReassign, new D2PacketsNew.D2Packets.PacketEventHandler(PlayerReassign));

            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.WorldItemAction, new D2PacketsNew.D2Packets.PacketEventHandler(WorldItemAction));
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.OwnedItemAction, new D2PacketsNew.D2Packets.PacketEventHandler(OwnedItemAction));

            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.LifeManaChange, new D2PacketsNew.D2Packets.PacketEventHandler(LifeManaChange));
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameServerPacket.PartyMemberUpdate, new D2PacketsNew.D2Packets.PacketEventHandler(PartyMemberUpdate));
            #endregion

            #region Game Client
            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameClientPacket.SelectSkill, new D2PacketsNew.D2Packets.PacketEventHandler(SelectSkill));

            this.Client.PacketHandler.AddAsyncListener(D2PacketsNew.D2Packets.GameClientPacket.RequestReassign, new D2PacketsNew.D2Packets.PacketEventHandler(RequestReassign));
            #endregion
            #endregion
        }
        #endregion

        #region Bot
        public void Start()
        {
            if (this.Client == null)
                throw new Exception("You have to call Bot.Initiate() before Bot.Start()!");

            this.Client.Start();
        }

        public void CleanUp()
        {
            this.Map.Clear();
            this.Seed = 0;

            this.Objects.Clear();
            this.Units.Clear();
            this.Items.Clear();
        }

        
        private void KillProcessEvent()
        {
            
        }
        /*
        private void GameEnterThatCreatesThread()
        {
            this.GameCount++;

            if (this.GameEnterThread != null)
            {
                this.GameEnterThread.Abort();
                this.GameEnterThread = null;
            }

            this.GameEnterThread = new Thread(new ThreadStart(GameEnterWatchForExceptions));
            this.GameEnterThread.Start();

            this.DebugLog.Append("Bot: " + "Entered game!");
        }

        private void GameExitThatDestroysThread()
        {
            this.LeftLastGameTime = DateTime.Now;

            this.DebugLog.Append("Bot: " + "Left game");

            if (this.GameEnterThread != null)
            {
                this.GameEnterThread.Abort();
                this.GameEnterThread = null;
            }

            OnGameExit();

            CleanUp();
        }
        */

        public void GameEnterWatchForExceptions()
        {
            this.GameCount++;

            try
            {
                OnGameEnter();
            }
            catch (GameFailedException gameFailed)
            {
                this.DebugLog.Append("Bot: " + "FAILED: " + gameFailed.Message);
                this.GameFailedCount++;
            }
            catch (Exception)
            {

            }
            finally 
            {
                this.Client.LeaveGame();
            }
        }

        public void GameExitCleanUp()
        {
            OnGameExit();

            CleanUp();
        }
        
        public abstract void OnLobbyEnter();

        public abstract void OnGameEnter();
        public abstract void OnGameExit();

        public abstract void Dispose();
        #endregion

        #region Packet listeners
        #region Realm Server
        private void GameList(D2Packet args)
        {
            D2PacketsNew.RealmServer.GameList gameList = new D2PacketsNew.RealmServer.GameList(args.Data);


            //this.Games.Add(gameList);
        }
        #endregion

        #region Game Server
        private void LoadAct(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.LoadAct loadAct = new D2PacketsNew.GameServer.LoadAct(args.Data);

            this.Seed = loadAct.MapId;
        }

        private void SkillsLog(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.SkillLog packet = new D2PacketsNew.GameServer.SkillLog(args.Data);

            if (this.Hero.UID == packet.UID)
            {
                foreach (D2PacketsNew.GameServer.BaseSkillLevel skillLevel in packet.Skills)
                {
                    this.Hero.Skills[skillLevel.Skill] = skillLevel.Level;
                }
            }
        }


        private void AssignPlayer(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.AssignPlayer packet = new D2PacketsNew.GameServer.AssignPlayer(args.Data);

            // Grab our bot's character UID, if it's not already found
            if (this.Hero.UID == 0)
            {
                this.Hero.Initialize(packet);

                this.Hero.Class = packet.Class;
            }
        }

        private void AssignNPC(D2PacketsNew.D2Packets.D2Packet args)
        {
            NPC npc = new NPC(new D2PacketsNew.GameServer.AssignNPC(args.Data));

            // Add NPC if it doesn't already exist, otherwise just update
            NPC npcInList = this.Units.Find(npc.UID);

            if (npcInList != null)
                npcInList = npc;
            else
                this.Units.Add(npc);
        }

        private void AssignGameObject(D2PacketsNew.D2Packets.D2Packet args)
        {
            Object theObject = new Object(new D2PacketsNew.GameServer.AssignGameObject(args.Data));

            // Add Object if it doesn't already exist, otherwise just update
            Object objectInList = this.Objects.Find(theObject.UID);

            if (objectInList != null)
                objectInList = theObject;
            else
                this.Objects.Add(theObject);
        }

        private void AssignSkill(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.AssignSkill packet = new D2PacketsNew.GameServer.AssignSkill(args.Data);

            // Grab our bot's character UID, if it's not already found
            if (this.Hero.UID == packet.UID)
            {
                this.Hero.SetSkillSelected(packet.Hand, packet.Skill);
            }
        }

        private void AssignPlayerCorpse(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.AssignPlayerCorpse packet = new D2PacketsNew.GameServer.AssignPlayerCorpse(args.Data);

            if (this.Hero.UID == packet.PlayerUID && !packet.Assign)
                this.Hero.CorpseUID = packet.CorpseUID;
        }

        private void AttributeDWord(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.AttributeDWord packet = new D2PacketsNew.GameServer.AttributeDWord(args.Data);

            int value = packet.Stat.BaseStat.Signed ? (int)(packet.Stat as D2DataNew.SignedStat).Value : (int)(packet.Stat as D2DataNew.UnsignedStat).Value;

            switch (packet.Stat.BaseStat.Type)
            {
                case StatType.Gold:
                    this.Hero.GoldInInventory = value;
                    break;
                case StatType.GoldBank:
                    this.Hero.GoldInStash = value;
                    break;
            }
        }


        private void NPCInfo(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.NPCInfo packet = new D2PacketsNew.GameServer.NPCInfo(args.Data);

            // Grab our bot's character UID, if it's not already found
            if (this.Mercenary.UID == 0)
            {
                this.Mercenary.UID = packet.UID;
            }
        }

        private void MercAttributeDWord(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.MercAttributeDWord packet = new D2PacketsNew.GameServer.MercAttributeDWord(args.Data);

            this.Mercenary.UID = packet.UID;

            switch (packet.Stat.BaseStat.Type)
            {
                case StatType.MaxLife:
                    this.Mercenary.MaxLife = (int)(packet.Stat as UnsignedStat).Value;
                    break;
                case StatType.Life:
                    this.Mercenary.Life = (int)(packet.Stat as UnsignedStat).Value;
                    break;
            }

            this.Mercenary.LifePercent = 100;
        }

        private void SetNPCMode(D2PacketsNew.D2Packets.D2Packet args)
        {
            uint uid = new D2PacketsNew.GameServer.SetNPCMode(args.Data).UID;

            NPC npc = this.Units.Find(uid);
            if (npc != null)
                npc.UpdateMode(new D2PacketsNew.GameServer.SetNPCMode(args.Data));
        }

        private void WalkVerify(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.WalkVerify packet = new D2PacketsNew.GameServer.WalkVerify(args.Data);

            this.Hero.X = packet.X;
            this.Hero.Y = packet.Y;
        }

        private void PlayerReassign(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.PlayerReassign packet = new D2PacketsNew.GameServer.PlayerReassign(args.Data);

            this.Hero.X = packet.X;
            this.Hero.Y = packet.Y;
        }

        private void NPCMove(D2PacketsNew.D2Packets.D2Packet args)
        {
            NPC npc = this.Units.Find(new D2PacketsNew.GameServer.NPCMove(args.Data).UID);

            if (npc != null)
            {
                npc.UpdatePosition(new D2PacketsNew.GameServer.NPCMove(args.Data));
            }
        }

        private void WorldItemAction(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.WorldItemAction packet = new D2PacketsNew.GameServer.WorldItemAction(args.Data);
            Item item = new Item(packet);

            if (!this.Items.Contains(item) && item != null)
                try
                {
                    this.Items.Add(item);
                }
                catch (NullReferenceException)
                { /* TODO: Why do I get this exception? Do some items not have UID's?*/ }

            switch (packet.Action)
            {
                case ItemActionType.PutInBelt:
                    Potion added = new Potion(item);
                    //Log.Instance.Append("Added a " + added.Type.ToString() + " to slot " + packet.X.ToString());
                    this.Hero.BeltColumn[packet.X].Enqueue(added);
                    break;

                case ItemActionType.RemoveFromBelt:
                    if (this.Hero.BeltColumn[packet.X].Count > 0)
                    {
                        //Log.Instance.Append("Removed potion from slot " + packet.X.ToString());
                        this.Hero.BeltColumn[packet.X].Dequeue();

                        this.Hero.LastDrink = DateTime.Now;
                    }
                    break;

                case ItemActionType.AddToGround:
                case ItemActionType.DropToGround:
                    //this.PickItLog.Append("Item dropped: " + packet.BaseItem.ToString() + "; " + item.Quality.ToString());

                    if (item.Destination == ItemDestination.Ground)
                    {
                        // Fire event
                        //this.ItemDropEvent(item);

                        // If it's a keeper, add it to queue
                        if (PickIt.Evaluate(item, this.Hero) != PickItResult.None && !this.Hero.ItemsToPickup.Contains(item))
                        {
                            this.PickItLog.Append("Enqueing " + packet.BaseItem.ToString() + " to be picked up!");
                            this.Hero.ItemsToPickup.Enqueue(item);
                        }
                    }
                    break;

                case ItemActionType.PutInContainer:
                    //Log.Instance.Append("Put in container: " + item.BaseItem.Type + ", " + item.Container.ToString());
                    if (item.Location == ItemLocation.Stash)
                    {
                        for (int y = 0; y < item.BaseItem.InvHeight; y++)
                        {
                            for (int x = 0; x < item.BaseItem.InvWidth; x++)
                            {
                                this.Hero.Stash[x + item.X, y + item.Y] = 1;
                            }
                        }
                    }

                    if (item.Location == ItemLocation.Inventory || item.Location == ItemLocation.Stash || item.Location == ItemLocation.Cube)
                    {
                        if (!this.Hero.Items.Contains(item) && item != null)
                            try
                            {
                                this.Hero.Items.Add(item);
                            }
                            catch (NullReferenceException)
                            { /* TODO: Why do I get this exception? Do some items not have UID's?*/ }
                    }
                    break;
            }
        }

        private void OwnedItemAction(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.OwnedItemAction packet = new D2PacketsNew.GameServer.OwnedItemAction(args.Data);

            Item item = new Item(packet);

            if (!this.Hero.Items.Contains(item) && item != null && packet.OwnerUID == this.Hero.UID)
                try
                {
                    this.Hero.Items.Add(item);
                }
                catch (NullReferenceException)
                { /* TODO: Why do I get this exception? Do some items not have UID's?*/ }

            if (!this.Mercenary.Items.ContainsKey(item.UID) && packet.OwnerUID == this.Mercenary.UID)
                try
                {
                    this.Mercenary.Items.Add(item.UID, item);
                }
                catch (NullReferenceException)
                { /* TODO: Why do I get this exception? Do some items not have UID's?*/ }
        }

        private void LifeManaChange(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.LifeManaChange packet = new D2PacketsNew.GameServer.LifeManaChange(args.Data);

            this.Hero.Life = packet.Life;
            this.Hero.Mana = packet.Mana;

            // If after BO/Oaksage, change max life || mana
            if (this.Hero.MaxLife < packet.Life)
                this.Hero.MaxLife = packet.Life;

            if (this.Hero.MaxMana < packet.Mana)
                this.Hero.MaxMana = packet.Mana;

            if (!CheckLife(this.Hero))
            {
                this.ChickenLog.Append("Ran out of potions when trying to heal yourself.");
                this.Client.LeaveGame();
            }
        }

        private void PartyMemberUpdate(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameServer.PartyMemberUpdate packet = new D2PacketsNew.GameServer.PartyMemberUpdate(args.Data);

            if (this.Mercenary.UID == packet.UID)
            {
                this.Mercenary.LifePercent = packet.LifePercent;

                if (!CheckLife(this.Mercenary))
                {
                    this.ChickenLog.Append("Ran out of potions when trying to heal merc.");
                    this.Client.LeaveGame();
                }
            }
        }
        #endregion

        #region Game Client
        private void SelectSkill(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameClient.SelectSkill packet = new D2PacketsNew.GameClient.SelectSkill(args.Data);

            this.Hero.SetSkillSelected(packet.Hand, packet.Skill);
        }

        private void RequestReassign(D2PacketsNew.D2Packets.D2Packet args)
        {
            D2PacketsNew.GameClient.RequestReassign packet = new D2PacketsNew.GameClient.RequestReassign(args.Data);

            // Grab our bot's character UID, if it's not already found
            if (this.Hero.UID == 0)
            {
                this.Hero.UID = packet.MeUID;
            }
        }
        #endregion
        #endregion

        #region Packet Actions
        public void SendGameMessage(string text)
        {
            this.Client.SendGS(new D2PacketsNew.GameClient.SendMessage(GameMessageType.GameMessage, text).Data);
        }
        public void ReceiveGameMessage(string text)
        {
            this.Client.ReceiveGC(new D2PacketsNew.GameServer.GameMessage(GameMessageType.GameMessage, 0, "test", text).Data);
            //this.Client.send
            //26 01 00 02 00 00 00 00 00 56 54 65 68 4d 66 65 72 7a 7a 00 61 73 64 66 00
        }

        public void Move(int x, int y)
        {
            this.Client.SendGS(new D2PacketsNew.GameClient.RunToLocation((ushort)x, (ushort)y).Data);

            uint myUID = this.Hero.UID;
            uint toX = (uint)x;
            uint toY = (uint)y;
            uint fromX = (uint)this.Hero.X;
            uint fromY = (uint)this.Hero.Y;

            byte[] PlayerMove = new byte[] 
                    { 
                        0x0F, // PlayerMove
                        0x00, // Client Type (always 0x00)
                        (byte)(myUID & 0xFF), (byte)((myUID >> 8) & 0xFF), (byte)((myUID >> 16) & 0xFF), (byte)(myUID >> 24), // Client ID
                        0x17, // Run/Walk (0x01 for walk, 0x17 for run)
                        (byte)(toX & 0xFF), (byte)((toX >> 8) & 0xFF), (byte)(toY & 0xFF), (byte)((toY >> 8) & 0xFF), // Location to walk to
                        0x00, // Unknown, always 0x00
                        (byte)(fromX & 0xFF), (byte)((fromX >> 8) & 0xFF), (byte)(fromY & 0xFF), (byte)((fromY >> 8) & 0xFF) // Current location of the client
                    };



            this.Client.ReceiveGC(PlayerMove);
        }
        public bool Move(IUnit unit)
        {
            if (unit == null)
                return false;

            this.Client.SendGS(new D2PacketsNew.GameClient.RunToLocation((ushort)unit.X, (ushort)unit.Y).Data);
            this.Client.SendGS(new D2PacketsNew.GameClient.RunToTarget(UnitType.NPC, unit.UID).Data);

            uint myUID = this.Hero.UID;
            uint toX = (uint)unit.X;
            uint toY = (uint)unit.Y;
            uint fromX = (uint)this.Hero.X;
            uint fromY = (uint)this.Hero.Y;

            byte[] PlayerMove = new byte[] 
                    { 
                        0x0F, // PlayerMove
                        0x00, // Client Type (always 0x00)
                        (byte)(myUID & 0xFF), (byte)((myUID >> 8) & 0xFF), (byte)((myUID >> 16) & 0xFF), (byte)(myUID >> 24), // Client ID
                        0x17, // Run/Walk (0x01 for walk, 0x17 for run)
                        (byte)(toX & 0xFF), (byte)((toX >> 8) & 0xFF), (byte)(toY & 0xFF), (byte)((toY >> 8) & 0xFF), // Location to walk to
                        0x00, // Unknown, always 0x00
                        (byte)(fromX & 0xFF), (byte)((fromX >> 8) & 0xFF), (byte)(fromY & 0xFF), (byte)((fromY >> 8) & 0xFF) // Current location of the client
                    };

            this.Client.ReceiveGC(PlayerMove);

            return true;
        }

        public bool MoveWait(int x, int y)
        {
            Move(x, y);

            D2PacketsNew.GameServer.WalkVerify verify = new D2PacketsNew.GameServer.WalkVerify(this.Client.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.WalkVerify, 5000).Data);

            if (verify == null)
                return false;

            return (verify.X == x && verify.Y == y);
        }

        public void MoveWaitStatic(int x, int y, int delay)
        {
            Move(x, y);
            System.Threading.Thread.Sleep(delay);
        }

        public bool PortalInteractWait(Object obj, int timeOut)
        {
            if (obj == null)
                return false;

            this.Client.SendGS(new D2PacketsNew.GameClient.UnitInteract(UnitType.GameObject, obj.UID).Data);

            if (this.Client.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.PlaySound, timeOut) == null)
                return false;

            this.Client.SendGS(new D2PacketsNew.GameClient.RequestReassign(UnitType.NPC, this.Hero.UID).Data);
            return true;
        }

        public bool TownFolkInteractWait(NPC Unit, int timeout)
        {
            this.Client.SendGS(new D2PacketsNew.GameClient.GoToTownFolk(UnitType.NPC, Unit.UID, (uint)Unit.X, (uint)Unit.Y).Data);
            this.Client.SendGS(new D2PacketsNew.GameClient.RunToTarget(UnitType.NPC, Unit.UID).Data);
            this.Client.SendGS(new D2PacketsNew.GameClient.UnitInteract(UnitType.NPC, Unit.UID).Data);

            if (this.Client.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.NPCInfo, timeout) == null)
                return false;

            this.Client.SendGS(new D2PacketsNew.GameClient.TownFolkInteract(UnitType.NPC, Unit.UID).Data);

            return true;
        }

        public bool TownFolkMenuSelectWait(NPC Unit, TownFolkMenuItem menu, int timeout)
        {
            uint unknown9;

            if (menu != TownFolkMenuItem.Trade)
            {
                this.DebugLog.Append("Trade is the only supported menu type--unknown 9?");
                throw new Exception("Trade is the only supported menu type--unknown 9?");
            }
            else
                // Apparently this only happens during trade selection:
                unknown9 = ETUtils.BEBitConverter.ToUInt32(new byte[] { 0x00, 0x00, 0x00, 0x00 }, 0);

            this.Client.SendGS(new D2PacketsNew.GameClient.TownFolkMenuSelect(menu, Unit.UID, unknown9).Data);

            if (menu == TownFolkMenuItem.Trade)
                return (this.Client.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.WorldItemAction, timeout) != null);

            return false;
        }

        public void TownFolkCancelInteraction(NPC Unit)
        {
            this.Client.SendGS(new D2PacketsNew.GameClient.TownFolkCancelInteraction(UnitType.NPC, Unit.UID).Data);
        }

        public bool TownFolkMoveWait(NPC unit, int x, int y, int timeout)
        {
            this.Client.SendGS(new D2PacketsNew.GameClient.GoToTownFolk(UnitType.NPC, unit.UID, (uint)x, (uint)y).Data);

            D2PacketsNew.GameServer.NPCMove move = new D2PacketsNew.GameServer.NPCMove(this.Client.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.NPCMove, timeout).Data);

            if (move == null)
                return false;

            return (move.UID == unit.UID && move.X == x && move.Y == y);
        }

        public bool BuyItemWait(NPC npc, Item item)
        {
            return this.BuyItemWait(npc, item, false);
        }
        public bool BuyItemWait(NPC npc, Item item, bool fillStack)
        {
            D2PacketsNew.GameClient.BuyFlags flags = fillStack ? D2PacketsNew.GameClient.BuyFlags.FillStack : D2PacketsNew.GameClient.BuyFlags.None;

            this.Client.SendGS(new D2PacketsNew.GameClient.BuyItem(npc.UID, item.UID, 0, flags).Data);

            return this.Client.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.TransactionComplete, 5000) != null;
        }

        public bool SelectSkill(SkillHand hand, SkillType type)
        {
            if (!this.Hero.IsSkillSelected(hand, type))
            {
                this.Client.SendGS(new D2PacketsNew.GameClient.SelectSkill(type, hand).Data);

                if (this.Client.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.AssignSkill, 5000) == null)
                    return false;
            }

            return true;
        }

        public bool SwitchWeaponSlotWait()
        {
            this.Client.SendGS(new D2PacketsNew.GameClient.SwitchWeapons().Data);

            D2PacketsNew.D2Packets.D2Packet packet = this.Client.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.OwnedItemAction, 5000);

            if (packet == null)
                return false;

            return (new D2PacketsNew.GameServer.OwnedItemAction(packet.Data)).EquipmentLocation == EquipmentLocation.RightHand;
        }

        public bool Drink(uint potionUID, bool toMerc)
        {
            this.Client.SendGS(new D2PacketsNew.GameClient.UseBeltItem(potionUID, toMerc).Data);

            D2Packet packet = this.Client.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.WorldItemAction, 5000);

            if (packet == null)
                return false;

            D2PacketsNew.GameServer.WorldItemAction action = new D2PacketsNew.GameServer.WorldItemAction(packet.Data);

            if (action == null)
                return false;

            this.ChickenLog.Append("Drinking a potion");

            return action.Action == ItemActionType.RemoveFromBelt;
        }

        public void CastLeftSkill(int x, int y)
        {
            this.Client.SendGS(new D2PacketsNew.GameClient.CastLeftSkill((ushort)x, (ushort)y).Data);
        }
        public void CastRightSkill(int x, int y)
        {
            this.Client.SendGS(new D2PacketsNew.GameClient.CastRightSkill((ushort)x, (ushort)y).Data);
        }

        public void CastSkillOnSelf(SkillType skill)
        {
            this.SelectSkill(SkillHand.Right, skill);
            this.CastRightSkill(this.Hero.X, this.Hero.Y);
        }

        public void Attack(NPC npc, SkillType skill)
        {
            this.SelectSkill(SkillHand.Left, skill);

            this.Client.SendGS(new D2PacketsNew.GameClient.CastLeftSkill((ushort)npc.X, (ushort)npc.Y).Data);
        }

        public bool TeleportWait(int x, int y)
        {
            this.SelectSkill(SkillHand.Right, SkillType.Teleport);

            this.CastRightSkill(x, y);

            if (this.Client.PacketHandler.WaitForPacket(GameServerPacket.PlayerReassign, 5000) == null)
                return false;

            System.Threading.Thread.Sleep(this.BotProfile.TeleportDelay);
            return true;
        }

        public bool PickUpItemFromGroundWait(Item item)
        {
            this.Client.SendGS(new D2PacketsNew.GameClient.PickItem(item.UID, false, 4).Data);

            D2Packet packet = this.Client.PacketHandler.WaitForPacket(GameServerPacket.WorldItemAction, 1000);

            if (packet == null)
                return false;

            D2PacketsNew.GameServer.WorldItemAction itemAction = new D2PacketsNew.GameServer.WorldItemAction(packet.Data);

            if (itemAction == null)
                return false;

            return itemAction.UID == item.UID;
        }
        #endregion

        #region Automatic
        public void AutoAttack(NPC monster, int timeOut)
        {
            SkillType BestAttack = this.Hero.GetBestMaxedSkill();

            switch (BestAttack)
            {
                // Combos
                case SkillType.Zeal:
                    if (this.Hero.Skills[SkillType.Fanaticism] > 0)
                        this.SelectSkill(SkillHand.Right, SkillType.Fanaticism);
                    break;
            }

            AutoKill(monster, BestAttack, 500, timeOut);
        }

        public bool AutoKill(NPC monster, SkillType attack, int delay, int timeOut)
        {
            DateTime start = DateTime.Now;

            while (monster.State != NPCMode.Dead && monster.State != NPCMode.Dying)
            {
                if (((TimeSpan)DateTime.Now.Subtract(start)).TotalMilliseconds > timeOut)
                    return false;

                this.Attack(monster, attack);
                System.Threading.Thread.Sleep(delay);
            }

            return true;
        }
        public bool AutoKillAll(List<NPC> monsters, SkillType attack, int delay, int timeOut)
        {
            DateTime start = DateTime.Now;

            // Champions are usually last, so let's kill those first
            for (int i = monsters.Count - 1; i >= 0; i--)
            {
                if (!this.AutoKill(monsters[i], attack, delay, timeOut))
                    return false;
            }

            return true;
        }

        public void AutoPickIt(int x, int y)
        {
            if (this.Hero.GetDistanceFrom(x, y) > 4)
                this.MoveWaitStatic(x, y, 150);

            while (this.Hero.ItemsToPickup.Count > 0)
            {
                Item item = this.Hero.ItemsToPickup.Dequeue();

                // Do we still want to pick this item up?--for example, we might not want any more
                // potions.
                if (PickIt.Evaluate(item, this.Hero) == PickItResult.None)
                    break;

                this.MoveWaitStatic(item.X, item.Y, 150);
                //System.Threading.Thread.Sleep(250);

                int errorCount = 0;

                while (!this.PickUpItemFromGroundWait(item))
                {
                    if (errorCount == 2)
                    {
                        this.PickItLog.Append("Couldn't pick up " + item.BaseItem.ToString());
                        break;
                    }

                    errorCount++;
                }

                if (errorCount < 2)
                {
                    // Fancy pickit log stuff here
                    this.PickItLog.Append("Picked up " + item.BaseItem.ToString() + " after " + (errorCount + 1).ToString() + " attempts.");
                }
            }
        }

        public void WalkPath(List<Chief.Pathing.AStarNode> path, int delay)
        {
            foreach (Chief.Pathing.AStarNode node in path)
                MoveWaitStatic(node.X, node.Y, delay);
        }

        public bool TeleportPath(List<Chief.Pathing.AStarNode> path)
        {
            foreach (Chief.Pathing.AStarNode node in path)
            {
                if (!TeleportWait(node.X, node.Y))
                    return false;
            }

            return true;
        }

        public void AutoPrebuff()
        {
            #region CTA
            bool hasCTA = this.Hero.IsWearingItem(delegate(Item item)
            {
                if (item.Runeword == BaseRuneword.GetByName("Call to Arms"))
                    return true;

                return false;
            });

            if (hasCTA)
            {
                this.DebugLog.Append("Trying to switch to CTA");
                bool hasCTABeenFound = false;

                for (int tries = 0; tries < 10; tries++)
                {
                    if (this.Hero.GetItemAt(EquipmentLocation.LeftHand) != null)
                        if (this.Hero.GetItemAt(EquipmentLocation.LeftHand).Runeword == BaseRuneword.GetByName("Call to Arms"))
                            hasCTABeenFound = true;

                    if (this.Hero.GetItemAt(EquipmentLocation.RightHand) != null)
                        if (this.Hero.GetItemAt(EquipmentLocation.RightHand).Runeword == BaseRuneword.GetByName("Call to Arms"))
                            hasCTABeenFound = true;

                    if (hasCTABeenFound)
                        break;

                    if (tries == 9)
                    {
                        this.DebugLog.Append("Tried switching to CTA 10 times, failed!");
                        break;
                    }

                    this.SwitchWeaponSlotWait();
                }

                if (hasCTABeenFound)
                {
                    this.DebugLog.Append("Found CTA");

                    this.CastSkillOnSelf(SkillType.BattleCommand);
                    System.Threading.Thread.Sleep(250);

                    this.CastSkillOnSelf(SkillType.BattleOrders);
                    System.Threading.Thread.Sleep(1000);

                    this.SwitchWeaponSlotWait();

                    System.Threading.Thread.Sleep(250);
                }
            }
            #endregion

            List<SkillType> Prebuffs = new List<SkillType>();

            #region Sorceress
            // Use the best possible ice armor
            if (this.Hero.Skills[SkillType.ChillingArmor] > 0)
                Prebuffs.Add(SkillType.ChillingArmor);
            else if (this.Hero.Skills[SkillType.ShiverArmor] > 0)
                Prebuffs.Add(SkillType.ShiverArmor);
            else if (this.Hero.Skills[SkillType.FrozenArmor] > 0)
                Prebuffs.Add(SkillType.FrozenArmor);

            if (this.Hero.Skills[SkillType.ThunderStorm] > 0)
                Prebuffs.Add(SkillType.ThunderStorm);
            #endregion

            #region Paladin

            if (this.Hero.Skills[SkillType.HolyShield] > 0)
                Prebuffs.Add(SkillType.HolyShield);

            // Switch back to appropriate aura
            if (this.Hero.Skills[SkillType.Fanaticism] > 10)
                Prebuffs.Add(SkillType.Fanaticism);
            if (this.Hero.Skills[SkillType.Concentration] > 10)
                Prebuffs.Add(SkillType.Concentration);
            #endregion

            #region Barbarian
            if (this.Hero.Skills[SkillType.BattleCommand] > 0)
                Prebuffs.Add(SkillType.BattleCommand);
            if (this.Hero.Skills[SkillType.BattleOrders] > 0)
                Prebuffs.Add(SkillType.BattleOrders);
            if (this.Hero.Skills[SkillType.Shout] > 0)
                Prebuffs.Add(SkillType.Shout);
            #endregion

            #region Assasin
            if (this.Hero.Skills[SkillType.Fade] > 0)
                Prebuffs.Add(SkillType.Fade);
            if (this.Hero.Skills[SkillType.BurstOfSpeed] > 0)
                Prebuffs.Add(SkillType.BurstOfSpeed);
            #endregion

            #region Druid
            /*
            if (this.Hero.Skills[SkillType.CycloneArmor] > 0)
                Prebuffs.Add(SkillType.CycloneArmor);
            // If he has Oak Sage AND doesn't have HeartOfTheWolverine
            if (this.Hero.Skills[SkillType.OakSage] > 0 && this.Hero.Skills[SkillType.HeartOfWolverine] == 0)
                Prebuffs.Add(SkillType.OakSage);
            else if (this.Hero.Skills[SkillType.HeartOfWolverine] > 0)
                Prebuffs.Add(SkillType.HeartOfWolverine);*/
            #endregion

            foreach (SkillType skill in Prebuffs)
            {
                this.CastSkillOnSelf(skill);

                int tries = 0;

                while (tries < 2)
                {
                    D2PacketsNew.GameServer.SetState state = new D2PacketsNew.GameServer.SetState(this.Client.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.SetState, 2000).Data);

                    if (state != null)
                        if (state.UID == this.Hero.UID)
                            break;

                    this.CastSkillOnSelf(skill);
                    tries++;
                }

                this.DebugLog.Append("AutoPrebuff: " + skill.ToString());
                System.Threading.Thread.Sleep(250);
            }
        }

        public bool AutoPortalInteract(Object portal, int tries, int timeOut)
        {
            DateTime start = DateTime.Now;

            int tryCount = 0;

            while (!this.PortalInteractWait(portal, 1000))
            {
                if (((TimeSpan)DateTime.Now.Subtract(start)).TotalMilliseconds > timeOut)
                    return false;

                tryCount++;

                if (tryCount > tries)
                    return false;
            }

            return true;
        }
        #endregion

        public bool CheckLife(NPC npc)
        {
            if (npc.UID != this.Hero.UID && npc.UID != this.Mercenary.UID)
            {
                this.ChickenLog.Append("Tried to check life of something other than Hero/Mercenary...?  " + (NPCClass)npc.ID);
                return true;
            }

            Potion potionToDrink = new Potion();

            double lifepercent = npc.GetLifePercent();

            if (npc.GetLifePercent() <= npc.HpChicken)
                this.Client.LeaveGame();

            if (npc.GetLifePercent() <= npc.HpNormal || npc.GetManaPercent() <= npc.ManaNormal)
            {
                potionToDrink = this.Hero.FindWorstPotion(npc);

                // couldn't find a potion
                if (potionToDrink == null)
                    return false;
            }

            if (npc.GetLifePercent() <= npc.HpRejuvination || npc.GetManaPercent() <= npc.ManaRejuvination)
            {
                potionToDrink = this.Hero.FindBestPotion(npc);

                // couldn't find a potion
                if (potionToDrink == null)
                    return false;
            }

            // If potion is initialized, we need to drink something
            if (potionToDrink.UID != 0)
            {
                int drinkTypeDelay;

                if (potionToDrink.Type != PotionType.Rejuvination)
                    drinkTypeDelay = this.BotProfile.NonRejuvinationDrinkDelay;
                else
                    drinkTypeDelay = this.BotProfile.RejuvinationDrinkDelay;

                while (((TimeSpan)DateTime.Now.Subtract(npc.LastDrink)).TotalMilliseconds <= drinkTypeDelay)
                    System.Threading.Thread.Sleep(10);

                //Log.Instance.Append("LifeCheck - IsMercenary: " + npc.IsMercenary.ToString() + "; NPC Life: " + npc.GetLifePercent().ToString() + "%; " + " NPC Mana: " + npc.GetManaPercent().ToString() + "%;" + " NPC LifeThreshold: " + npc.LifeThreshold.ToString() + "%;");

                npc.LastDrink = DateTime.Now;

                this.ChickenLog.Append("Drank potion: " + potionToDrink.Type.ToString() + " with " + npc.LifePercent.ToString() + "% life on Unit " + (NPCClass)npc.ID);
                this.Drink(potionToDrink.UID, npc.IsMercenary);
            }

            return true;
        }
    }
}