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 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 path, int delay) { foreach (Chief.Pathing.AStarNode node in path) MoveWaitStatic(node.X, node.Y, delay); } public bool TeleportPath(List 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 Prebuffs = new List(); #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; } } }