public override bool NeedRest(D3Player player)
 {
     return false;
 }
 protected override void DoEnter(D3Player Entity)
 {
     base.DoEnter(Entity);
     D3Control.output("Core.DoEnter() -- Begin");
     D3Control.output("http://en.tntd3.com");
     combatState = new DemonHunter.CombatState();
     D3Control.output("Core.DoEnter() -- End");
 }
        /// <summary>
        /// This happens when we are being attacked by some mobs or when we
        /// have found something to kill 
        /// </summary>
        protected override void DoExecute(D3Player Entity)
        {
            try
            {
                CWSpellTimer combatThresholdTimer = new CWSpellTimer(120 * 1000, false);// in case something is wrong
                Vector3D targetLoc = null;
                bool enemyFound = false;
                var timePre = DateTime.Now;
                while (true)
                {
                    Thread.Sleep(CombatConfig.CombatLoopSleepTime);
                    var timeNow = DateTime.Now;
                    //D3Control.output(string.Format("Loop time is {0}", DateTime.Now.Subtract(timePre).Milliseconds));
                    if (!D3Control.IsInGame() || D3Control.Player.IsDead || combatThresholdTimer.IsReady)
                        break;
                    checkThreadStatus();

                    checkBuff(D3Control.Player);

                    timePre = DateTime.Now;
                    LiveMobsAround = D3Control.RetrieveAllObjects(maxScanRange, Descriptor.eActorType.Monster);   // only live mobs will be returned.
                    if (checkIgnoreandMaxTrial(ref LiveMobsAround))
                        break;

                    timePre = DateTime.Now;
                    D3Unit TargetMob = null;
                    var nearMobs = GetNearByEnemy(ref LiveMobsAround, 18);

                    if (D3Control.canCast("Sweep Attack"))
                    {
                        if (nearMobs != null && nearMobs.Count > 1)
                        {
                            CastCrusaderSpell("Sweep Attack", D3Control.Player.Location);
                        }
                    }
                    if (D3Control.Player.HpPct < CombatConfig.drinkHealthPotionPct)
                        D3Control.usePotion();
                    bool InCombat = D3Control.Player.isInCombat;
                    if (!InCombat)
                    {
                        if (D3Control.GoodLootsAround())
                        {
                            if (nearMobs == null || nearMobs.Count == 0)
                                return;
                        }
                    }
                    TargetMob = GetNextTargetMob(ref LiveMobsAround);
                    if (TargetMob != null)
                    {
                        // D3Control.output(((D3Unit)TargetMob).ToString() );

                    }

                    if (D3.D3Control.curTarget == null)
                    {
                        if (TargetMob != null)
                        {   // ok no current target and find a target mob to kill, do it
                            D3Control.TargetManager.SetAttackTarget(TargetMob);
                        }
                        else
                        {
                            if (InCombat)
                            {
                                D3Control.output("In combat and cannot find next target??");
                                DoExit(D3Control.Player);
                                return;
                            }
                            else
                            {
                                D3Control.output("Out of combat?");
                                D3Control.TargetManager.ClearTarget();
                                DoExit(D3Control.Player);
                                return;
                            }
                        }
                    }
                    else
                    {   // current target is not null

                        if (!D3Control.curTarget.Equals(TargetMob))
                        {
                            try
                            {
                                if (!isFirstKillTarget(D3.D3Control.curTarget))
                                {
                                    if (TargetMob != null)
                                    {
                                        if (isFirstKillTarget(TargetMob))
                                        {
                                            D3Control.TargetManager.SetAttackTarget(TargetMob);
                                        }
                                        else
                                        {
                                            if (!D3Control.curTarget.IsElite)
                                            {
                                                D3Control.output("Target Switched?");
                                                D3Control.stopMoving();
                                                D3Control.TargetManager.SetAttackTarget(TargetMob);
                                            }
                                            else if (D3Control.LOS(D3Control.curTarget))
                                            {
                                                D3Control.output("Target Switched?");
                                                D3Control.stopMoving();
                                                D3Control.TargetManager.SetAttackTarget(TargetMob);
                                            }
                                        }
                                    }
                                }
                                else if (TargetMob != null)
                                {
                                    D3Control.output("Target Switched?");
                                    D3Control.stopMoving();
                                    D3Control.TargetManager.SetAttackTarget(TargetMob);
                                }
                            }
                            catch { }
                        }
                    }
                    if (targetLoc == null || !D3Control.isInCombatMoving())
                    {
                    STARTPulling:

                        if (D3Control.isObjectValid(D3Control.curTarget) && !D3Control.curTarget.IsDead && !D3Control.curTarget.IsNpc && D3Control.curTarget.Type == Descriptor.eActorType.Monster)
                        {
                            // make sure this function call is added if you have a while loop in DoExecute to handle the target selection.
                            // it handles some boss fights, where you have to kill the minions first.
                            targetLoc = D3Control.curTarget.Location;

                            D3Control.TargetManager.handleSpecialFight();
                            meleeRange = D3Control.getMobRange(D3Control.curTarget);
                            timePre = DateTime.Now;

                            try
                            {
                                doPulling(D3Control.Player);
                            }
                            catch { }
                            //D3Control.output(string.Format("Time 6 is {0}", DateTime.Now.Subtract(timePre).Milliseconds));
                            timePre = DateTime.Now;

                            continue;
                        }
                        else
                        {
                            D3Control.TargetManager.ClearTarget();
                            if (D3Control.isObjectValid(TargetMob) && !TargetMob.IsDead)
                            {
                                D3Control.TargetManager.SetAttackTarget((D3Unit)TargetMob);
                                TargetMob = null;
                                goto STARTPulling;
                            }
                            else
                                targetLoc = null;/*/**/

                        }
                        if (!D3Control.isObjectValid(TargetMob))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (targetLoc == new Vector3D()) // invalid location?
                        {
                            DoExit(D3Control.Player);
                            return;
                        }
                        if (InCombat)
                        {

                            if (D3Control.isObjectValid(TargetMob) && !TargetMob.IsDead)
                            {
                                D3Control.TargetManager.SetAttackTarget((D3Unit)TargetMob);
                                targetLoc = D3Control.curTarget.Location;
                            }
                            else
                            {
                                targetLoc = null;
                            }
                        }/**/
                    }
                }
            }
            catch { }
            DoExit(D3Control.Player);

            return;
        }

        protected override void DoExit(D3Player entity)
        {
            //on exit, if there is a previous state, go back to it
            if (PreviousState != null)
            {
                CallChangeStateEvent(entity, PreviousState, false, false);
            }
        }

        protected override void DoFinish(D3Player entity)
        {
        }

        static void checkThreadStatus()
        {
            if (keepSpellThread != null && keepSpellThread.IsAlive)
            {
            }
            else
            {
                try
                {
                    if (keepSpellThread != null)
                        keepSpellThread.Abort();
                }
                catch { }
                finally
                {
                    keepSpellThread = null;
                }
                keepSpellThread = new Thread(new ThreadStart(keepSpell)) { Name = "Check Buff" }; ;
                keepSpellThread.IsBackground = true;
                keepSpellThread.Start();
            }

            D3Control.checkLootThreadHandling();
        }

        bool checkIgnoreandMaxTrial(ref List<D3Object> Mobs)
        {
            bool res = false;
            bool checkIgnore = D3Control.TargetManager.toIgnore(ref LiveMobsAround);// D3Control.TargetManager.applyIgnoreSettings();
            if (checkIgnore || D3Control.ReachedMaxTrialLevel)
            {
                D3Control.TargetManager.ClearTarget();
                res = true;
            }
            return res;
        }

        void doPulling(D3Player entity)
        {
            //rendTimer.ChangeDuration(3 * 1000);
            var preTime = DateTime.Now;
            if (!GlobalBaseBotState.checkBeforePull(entity))
                return;
            if (!D3Control.TargetManager.isTargetGoodForAttack((D3Unit)D3Control.curTarget)) // check the internal timer expires, which means the target is not good for attack, then block this target, the block is done inside the fuction call
            {
                return;
            }

            D3Unit target = D3Control.curTarget;
            if (!moveToStartFight(entity))
            {
                return;
            }

            bool isElite = target.IsElite;
            bool isTS = D3Control.IsMobTS(target);

            if ((isElite || isTS) && D3Control.Player.isInCombat && target.DistanceFromPlayer < meleeRange)
            {

                if (target.DistanceFromPlayer < 25 && (CombatConfig.CrusaderDefaultSettings.FallingSwordSettings.OnTS && isTS || CombatConfig.CrusaderDefaultSettings.FallingSwordSettings.OnElite && isElite) && CastCrusaderSpell("Falling Sword", target.Location))
                {

                }
                else if ((CombatConfig.CrusaderDefaultSettings.HeavensFurySettings.OnTS && isTS || CombatConfig.CrusaderDefaultSettings.HeavensFurySettings.OnElite && isElite) && !D3Control.hasThreeAncients() && CastCrusaderSpell("Heavens Fury", target.Location))
                {
                }
                else if ((CombatConfig.CrusaderDefaultSettings.AkaratsChampionSettings.OnTS && isTS || CombatConfig.CrusaderDefaultSettings.AkaratsChampionSettings.OnElite && isElite) && CastCrusaderSpell("Akarats Champion", D3Control.Player.Location))
                {
                }
                else if ((CombatConfig.CrusaderDefaultSettings.BombardmentSettings.OnTS && isTS || CombatConfig.CrusaderDefaultSettings.BombardmentSettings.OnElite && isElite) && D3Control.CastLocationSpell("Bombardment", target.Location, true))
                {
                }
            }
            else if (target.DistanceFromPlayer < meleeRange)
            {
                if (target.DistanceFromPlayer < 25 && (CombatConfig.CrusaderDefaultSettings.FallingSwordSettings.OnCD) && CastCrusaderSpell("Falling Sword", target.Location))
                {
                }
                else if ((CombatConfig.CrusaderDefaultSettings.HeavensFurySettings.OnCD) && CastCrusaderSpell("Heavens Fury", target.Location))
                {
                }
                else if ((CombatConfig.CrusaderDefaultSettings.AkaratsChampionSettings.OnCD) && CastCrusaderSpell("Akarats Champion", D3Control.Player.Location))
                {
                }

                else if ((CombatConfig.CrusaderDefaultSettings.BombardmentSettings.OnCD) && D3Control.CastLocationSpell("Bombardment", target.Location, true))
                {
                }
            }

            if (target.DistanceFromPlayer >= 25 && target.DistanceFromPlayer <= 60 && !D3Control.LOS(target))
            {

                if (CastCrusaderTargetSpell("Steed Charge", target))
                {
                }
                if (D3Control.canCast("Shield Bash") && !D3.D3Control.LOS(target))
                {
                    var dashingTarget = selectFarestMob(50, ref LiveMobsAround, 50);
                    if (dashingTarget != null)
                    {
                        {
                            if (CastCrusaderTargetSpell("Shield Bash", target))
                            {
                                return;
                            }
                        }
                    }
                }

            }

            if (D3Control.isObjectValid(target) && !target.IsDead)
            {
                if (target.DistanceFromPlayer <= 20 || target.DistanceFromPlayer <= meleeRange)
                {
                    if (CastCrusaderTargetSpell("Fist of the Heavens", target))
                    {
                        return;
                    }
                    if (target.DistanceFromPlayer <= meleeRange && CastCrusaderSpell("Shield Glare", target.Location))
                    {
                        return;
                    }
                    {
                        if (CastCrusaderSpell("Provoke", target.Location))
                        {
                        }
                        else if (CastCrusaderTargetSpell("Punish", target))
                        {
                        }
                        else if (CastCrusaderTargetSpell("Slash", target))
                        {
                        }
                        else if (CastCrusaderSpell("Smite", target.Location))
                        {
                        }
                        else
                        {
                            CastCrusaderTargetSpell("Justice", target);
                        }

                        try2AvoidAOE();
                    }
                    // D3Control.output(string.Format("Time spent casting spells 3 {0}", DateTime.Now.Subtract(preTime).TotalMilliseconds));
                }
            }
            return;
        }

        List<D3Object> GetNearByEnemy(ref List<D3Object> Mobs, int range)
        {
            List<D3Object> res = new List<D3Object>();
            if (Mobs != null)
            {
                foreach (var mob in Mobs)
                {
                    if (D3Control.isObjectValid(mob) && !((D3Unit)mob).IsDead)
                    {
                        if (mob.DistanceFromPlayer <= range)
                        {
                            res.Add(mob);
                        }
                    }
                }
            }
            return res;
        }

        D3Unit GetNextTargetMob(ref List<D3Object> liveMobs)
        {
            D3Unit res = null;
            if (CombatConfig.SkillBuild == build.CrusaderDefault)
            {
                res = selectClosestMob(CombatConfig.CrusaderDefaultSettings.InCombatSearchRange, ref liveMobs, 50);
            }
            return res;
        }

        void handleAOE()
        {
            D3Unit closetEnemy = null;
            var nearMobs = GetNearByEnemy(ref LiveMobsAround, 15);
            var count = -1;
            if (nearMobs != null)
                count = nearMobs.Count;
            if (condemnOnly)
            {
                if (CastCrusaderTargetSpell("Condemn", nearMobs[0]))
                {
                    BlessedHammerTimer.Reset();
                    return;
                }
            }
            if (count > AOEMonsters)
            {
                if ((CombatConfig.CrusaderDefaultSettings.FallingSwordSettings.NearMobCount <= count) && CastCrusaderSpell("Falling Sword", D3Control.Player.Location))
                {
                }
                else if ((CombatConfig.CrusaderDefaultSettings.HeavensFurySettings.NearMobCount < count) && CastCrusaderSpell("Heavens Fury", nearMobs[0].Location))
                {

                }
                else if ((CombatConfig.CrusaderDefaultSettings.AkaratsChampionSettings.NearMobCount < count) && CastCrusaderSpell("Akarats Champion", D3Control.Player.Location))
                {
                }

                else if ((CombatConfig.CrusaderDefaultSettings.BombardmentSettings.NearMobCount < count) && D3Control.CastLocationSpell("Bombardment", nearMobs[0].Location, true))
                {
                }
                if (CastCrusaderTargetSpell("Condemn", nearMobs[0]))
                {
                    BlessedHammerTimer.Reset();
                    return;
                }
                else if (BlessedHammerTimer.IsReady && CastCrusaderSpell("Blessed Hammer", D3Control.Player.Location))
                {
                    BlessedHammerTimer.Reset();
                    return;
                }
                else if (BlessedHammerTimer.IsReady && CastCrusaderSpell("Blessed Shield", nearMobs[0].Location))
                {
                    BlessedHammerTimer.Reset();
                    return;
                }
            }
            else
                return;
        }

        void handleBlessHammer()
        {
            CWSpellTimer checkBuffTimer = new CWSpellTimer(1 * 1000);
            CWSpellTimer checkAncientTimer = new CWSpellTimer(3 * 1000);
            CWSpellTimer overPowerTimer = new CWSpellTimer(4 * 1000);
            //CWSpellTimer FGTimer = new CWSpellTimer(CombatConfig.BarbIKWWSettings.CastFuryGeneratorTimer * 1000);
            //if (D3Control.canCast("Whirlwind")) //
            {
                CWSpellTimer tempTimer2 = new CWSpellTimer(30 * 1000, false);
                var cancast = false;
                int retryTimes = 0;
                do
                {
                recast:

                    if (!D3Control.IsInGame() || D3Control.Player.IsDead)
                    {
                        return;
                    }
                    if (checkIgnoreandMaxTrial(ref LiveMobsAround))
                        break;
                    if (D3Control.Player.HpPct < 45)
                        D3Control.usePotion();
                    if (DoorCheckTimer.IsReady)
                    {
                        D3Control.openDoor(35);
                        DoorCheckTimer.Reset();
                    }
                    LiveMobsAround = D3Control.RetrieveAllObjects(maxScanRange, Descriptor.eActorType.Monster);   // only live mobs will be returned.

                    if (LiveMobsAround == null || LiveMobsAround.Count == 0)
                        return;
                    //float minDistance = float.MaxValue;
                    bool closeEnemy = false;
                    float minDistance = float.MaxValue;
                    bool hasElite = false;
                    D3Unit closestMob = null;
                    bool RGBossFight = false;
                    foreach (var mob in LiveMobsAround)
                    {
                        var distance = mob.DistanceFromPlayer;
                        if (D3Control.ISRG((D3Unit)mob))
                        {
                            RGBossFight = true;
                            RGBoss = mob;
                        }
                        if (minDistance > distance)
                        {
                            minDistance = distance;
                            closestMob = (D3Unit)mob;
                        }
                        if (!hasElite && ((D3Unit)mob).IsElite)
                            hasElite = true;
                        if (distance <= 55 && !D3Control.LOS(mob))
                        {
                            closeEnemy = true;
                        }
                    }
                    if (!RGBossFight)
                        RGBoss = null;
                    if (!closeEnemy) // no more enemy nearby?
                        return;
                    checkBuff(D3Control.Player);

                    if (CastCrusaderSpell("Akarats Champion", D3Control.Player.Location))
                    {
                    }

                    Vector3D wwSpot = WWCheckGlobeShrineLoc();
                    //var t1 = D3Control.Player.Location;
                    //var dist = wwSpot.GetDistanceTo(D3Control.Player.Location);

                    if (wwSpot == null)
                    {
                        if (D3Control.isObjectValid(RGBoss))
                            wwSpot = handleRGAOE(RGBoss.Location);
                        wwSpot = selectWWLocation(55, ref LiveMobsAround, 25);

                    }

                    if (wwSpot != null)
                    {

                        if (CastCrusaderSpell("Falling Sword", wwSpot))
                        {

                        }
                        if (CastCrusaderSpell("Provoke", D3Control.Player.Location))
                        {
                        }
                        D3Control.ClickMoveTo(wwSpot);
                        Thread.Sleep(1000);
                        int retryPre = 0;
                    tryPreiousSpot:
                        var distance = wwSpot.GetDistanceTo(D3Control.Player.Location);
                        int sleepTime = 100;
                        if (distance < 8)
                            sleepTime = 0;
                        if (CastCrusaderSpell("Blessed Hammer", wwSpot))
                        {
                            retryTimes = 0;
                            D3Control.stopMoving();
                            //D3Control.output("Strafe Successful?");
                            //Thread.Sleep(sleepTime);// wait a bit?
                            if (checkBuffTimer.IsReady)
                            {
                                checkBuff(D3Control.Player);
                                checkBuffTimer.Reset();
                            }
                            if (retryPre < 7 && D3Control.Player.Location.GetDistanceTo(wwSpot) > 10)
                            {
                                retryPre++;
                                Thread.Sleep(50);
                                goto tryPreiousSpot;
                            }/**/
                            //Thread.Sleep(100);// wait a bit?

                        }
                        else
                        {
                            if (retryTimes++ < 5 && D3Control.isSpellEnabled("Blessed Hammer"))
                            {
                                //LiveMobsAround = D3Control.RetrieveAllObjects(maxScanRange, Descriptor.eActorType.Monster);   // only live mobs will be returned.
                                //strafeSpot = selectStrafeLocation(55, ref LiveMobsAround, 40);
                                goto recast;
                            }
                            break;
                        }
                    }
                    else
                    {
                        D3Control.output("No Whirlwind target?");

                        break;
                    }

                    cancast = D3Control.canCast("Whirlwind");
                    if (!cancast)
                    {
                        D3Control.output("Cannot Cast Whirlwind");
                    }
                    else
                    {
                        Thread.Sleep(50);
                    }

                } while (cancast && !tempTimer2.IsReady);
            }
 public static void Emergency(D3Player player)
 {
 }
 protected override void DoFinish(D3Player entity)
 {
     D3Control.output("DoFinish");
 }
        public static void checkBuff(D3Player entity)
        {
            if (!D3Control.IsInGame())
                return;
            if (D3Control.Player.HpPct < CombatConfig.drinkHealthPotionPct)
                D3Control.usePotion();

            if (ArmorBuffCheckTimer.IsReady)
            {
                if (D3Control.canCast("Ice Armor") && !D3Control.HasBuff("Ice Armor") && CastWizardSpell("Ice Armor", D3Control.Player.Location))
                {
                    ArmorBuffCheckTimer.Reset();
                    return;
                }
                if (D3Control.canCast("Energy Armor") && !D3Control.HasBuff("Energy Armor") && CastWizardSpell("Energy Armor", D3Control.Player.Location))
                {
                    ArmorBuffCheckTimer.Reset();
                    return;
                }
                if (D3Control.canCast("Storm Armor") && !D3Control.HasBuff("Storm Armor") && CastWizardSpell("Storm Armor", D3Control.Player.Location))
                {
                    ArmorBuffCheckTimer.Reset();
                    return;
                }
                if (D3Control.canCast("Magic Weapon") && !D3Control.HasBuff("Magic Weapon"))
                {
                    if (CastWizardSpell("Magic Weapon", D3Control.Player.Location))
                    {
                        ArmorBuffCheckTimer.Reset();
                        return;
                    }
                }
                if (D3Control.canCast("Familiar") && !D3Control.isFamiliarAround())
                {
                    if (CastWizardSpell("Familiar", D3Control.Player.Location))
                    {
                        ArmorBuffCheckTimer.Reset();
                        return;
                    }
                }
            }
            if (D3Control.Player.isBeingCCed() || D3Control.Player.HpPct <= DiamondSkinHp)
            {
                if (D3Control.canCast("Diamond Skin"))
                {
                    if (CastWizardSpell("Diamond Skin", D3Control.Player.Location))
                    {
                        Thread.Sleep(500);
                        return;
                    }
                }
            }
            if (D3Control.Player.HpPct <= MirrorImageHp)
            {
                if (CastWizardSpell("Mirror Image", D3Control.Player.Location))
                {
                    return;
                }
            }
            return;
        }
 protected override void DoEnter(D3Player Entity)
 {
 }
        protected override void DoExecute(D3Player Entity)
        {
            try
            {
                CWSpellTimer combatThresholdTimer = new CWSpellTimer(120 * 1000, false);
                Vector3D targetLoc = null;
                bool enemyFound = false;
                var timePre = DateTime.Now;
                while (true)
                {
                    if (!D3Control.IsInGame() || D3Control.Player.IsDead || combatThresholdTimer.IsReady)
                        break;
                    checkThreadStatus();
                    Thread.Sleep(50);
                    checkBuff(D3Control.Player);
                    LiveMobsAround = D3Control.RetrieveAllObjects(maxScanRange, Descriptor.eActorType.Monster);
                    if (checkIgnoreandMaxTrial(ref LiveMobsAround))
                        break;

                    bool checkIgnore = D3Control.TargetManager.applyIgnoreSettings();
                    if (checkIgnoreandMaxTrial(ref LiveMobsAround))
                        break;

                    if (CombatConfig.DHDefaultSettings.playType == PlayType.range && HitAndRuntimer.IsReady)
                    {
                        var runAwayNearMobs = GetNearByEnemy(ref LiveMobsAround, 8);
                        if (runAwayNearMobs.Count > 0)
                        {   // find a safe place?
                            var target = Surroundings.FindMobBlock(ref LiveMobsAround, FindTypes.Min);
                            if (D3Control.canCast("Vault"))
                            {
                                CastDH2Spell("Vault", target);
                            }
                            else
                                D3Control.MoveTo(target, 5);
                            Thread.Sleep(200);
                            HitAndRuntimer.Reset();
                        }
                    }
                    timePre = DateTime.Now;
                    D3Unit TargetMob = null;
                    var nearMobs = GetNearByEnemy(ref LiveMobsAround, 30);
                    if (D3Control.Player.HpPct < 45)
                        D3Control.usePotion();
                    bool InCombat = D3Control.Player.isInCombat;
                    if (!InCombat)
                    {
                        if (D3Control.GoodLootsAround())
                        {
                            if (nearMobs == null || nearMobs.Count == 0)
                                return;
                        }
                    }
                    TargetMob = GetNextTargetMob(ref LiveMobsAround);
                    if (TargetMob != null)
                    {
                    }
                    if (D3.D3Control.curTarget == null)
                    {
                        if (TargetMob != null)
                        {
                            D3Control.TargetManager.SetAttackTarget(TargetMob);
                        }
                        else
                        {
                            if (InCombat)
                            {
                                D3Control.output("In combat and cannot find next target?");
                                DoExit(D3Control.Player);
                                return;
                            }
                            else
                            {
                                D3Control.output("Out of combat?");
                                D3Control.TargetManager.ClearTarget();
                                DoExit(D3Control.Player);
                                return;
                            }
                        }
                    }
                    else
                    {
                        if (!D3Control.curTarget.Equals(TargetMob))
                        {
                            try
                            {
                                if (!isFirstKillTarget(D3.D3Control.curTarget))
                                {
                                    if (TargetMob != null)
                                    {
                                        if (isFirstKillTarget(TargetMob))
                                        {
                                            D3Control.TargetManager.SetAttackTarget(TargetMob);
                                        }
                                        else
                                        {
                                            if (!D3Control.curTarget.IsElite)
                                            {
                                                D3Control.output("Change Target");
                                                D3Control.stopMoving();
                                                D3Control.TargetManager.SetAttackTarget(TargetMob);
                                            }
                                            else if (D3Control.LOS(D3Control.curTarget))
                                            {
                                                D3Control.output("Change Target");
                                                D3Control.stopMoving();
                                                D3Control.TargetManager.SetAttackTarget(TargetMob);
                                            }
                                        }
                                    }
                                }
                            }
                            catch { }
                        }
                    }
                    if (targetLoc == null || !D3Control.isInCombatMoving())
                    {
                    STARTPulling:

                        if (D3Control.isObjectValid(D3Control.curTarget) && !D3Control.curTarget.IsDead && !D3Control.curTarget.IsNpc && D3Control.curTarget.Type == Descriptor.eActorType.Monster)
                        {
                            targetLoc = D3Control.curTarget.Location;
                            D3Control.TargetManager.handleSpecialFight();
                            meleeRange = D3Control.getMobRange(D3Control.curTarget);
                            try
                            {
                                doPulling(D3Control.Player);
                            }
                            catch { }
                            continue;
                        }
                        else
                        {
                            D3Control.TargetManager.ClearTarget();
                            if (D3Control.isObjectValid(TargetMob) && !TargetMob.IsDead)
                            {
                                D3Control.TargetManager.SetAttackTarget((D3Unit)TargetMob);
                                TargetMob = null;
                                goto STARTPulling;
                            }
                            else
                                targetLoc = null;
                        }
                        if (!D3Control.isObjectValid(TargetMob))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (targetLoc == new Vector3D())
                        {
                            DoExit(D3Control.Player);
                            return;
                        }
                        if (InCombat)
                        {
                            if (D3Control.isObjectValid(TargetMob) && !TargetMob.IsDead)
                            {
                                D3Control.TargetManager.SetAttackTarget((D3Unit)TargetMob);
                                targetLoc = D3Control.curTarget.Location;
                            }
                            else
                            {
                                targetLoc = null;
                            }
                        }
                    }
                }
            }
            catch { }
            DoExit(D3Control.Player);
            return;
        }
 protected override void DoEnter(D3Player Entity)
 {
     base.DoEnter(Entity);
     D3Control.output("Core.DoEnter() -- Begin");
     D3Control.output("Default Witch Doctor 0.0.1");
     combatState = new WitchDoctor.CombatState();
     D3Control.output("Core.DoEnter() -- End");
 }
        public static void checkBuff(D3Player entity)
        {
            if (!D3Control.IsInGame())
                return;
            if (D3Control.GetPetCount(ZombieDogsID) < CombatConfig.WitchDoctorDefaultSettings.ZombieDogCount && CastWitchDoctorSpell("Summon Zombie Dogs", D3Control.Player.Location))
            {
                return;
            }

            if ((D3Control.getFACount() < 5 && CombatConfig.WitchDoctorDefaultSettings.FAOnCD) && CastWitchDoctorSpell("Fetish Army", D3Control.Player.Location))
            {
                return;
            }
            return;
        }
        public static void checkBuff(D3Player entity)
        {
            try
            {
                if (!D3Control.IsInGame())
                    return;
                var target = D3Control.curTarget;
                if (!D3Control.isObjectValid(target))
                {   // no target, do nothing?
                    return;
                }
                var distance = D3Control.curTarget.DistanceFromPlayer;
                if (CombatConfig.MonkR6Settings.BreathofHeavenOnCD || D3Control.Player.HpPct <= HeavenHp)
                {
                    if (CastMonkSpell("Breath of Heaven", D3Control.Player.Location))
                    {

                    }
                }
                if (D3Control.Player.HpPct <= SanctuaryHp)
                {
                    if (CastMonkSpell("Inner Sanctuary", D3Control.Player.Location))
                    {
                        Thread.Sleep(100);
                    }
                }
                if (D3Control.Player.HpPct <= SerenityHp)
                {
                    if (CastMonkSpell("Serenity", D3Control.Player.Location))
                    {
                        Thread.Sleep(100);
                    }
                }
                if (CombatConfig.SkillBuild == build.SunWuKong && distance < meleeRange)
                {
                    if (D3Control.canCast("Sweeping Wind") && !D3Control.HasBuff("Sweeping Wind"))
                    {
                        if (CombatConfig.MonkSunWukongSetting.SaveSpiritForSweeping)
                            saveSpiritForSW = true;
                        else
                            saveSpiritForSW = false;
                    }
                    else
                        saveSpiritForSW = false;
                    if (saveSpiritForSW || D3Control.Player.Spirit * 100 / D3Control.Player.MaxSpirit >= CombatConfig.MonkSunWukongSetting.SweepingWindPct && D3Control.canCast("Sweeping Wind"))//&& !D3Control.HasBuff("Sweeping Wind"))
                    {
                        if (CastMonkSpell("Sweeping Wind", D3Control.Player.Location))
                        {
                            saveSpiritForSW = false;
                            Thread.Sleep(100);
                        }
                    }
                }
                else if (D3Control.canCast("Sweeping Wind") && !D3Control.HasBuff("Sweeping Wind"))
                {
                    if (CastMonkSpell("Sweeping Wind", D3Control.Player.Location))
                    {
                        Thread.Sleep(100);
                    }
                }
                else
                    saveSpiritForSW = false;
                if (MantraTimer.IsReady)
                {
                    bool canCast = true;
                    if (D3Control.canCast("Sweeping Wind") && !D3Control.HasBuff("Sweeping Wind"))
                    {   // keep the SS buff first.
                        canCast = false;
                    }
                    if (canCast)
                    {
                        //if (D3Control.canCast("Mantra of Conviction"))
                        {
                            if (CastMonkSpell("Mantra of Conviction", D3Control.Player.Location))
                            {
                                MantraTimer.Reset();
                            }
                        }
                        //if (D3Control.canCast("Mantra of Retribution"))
                        {
                            if (CastMonkSpell("Mantra of Retribution", D3Control.Player.Location))
                            {
                                MantraTimer.Reset();
                            }
                        }
                        if (CombatConfig.SkillBuild != build.SunWuKong && distance < meleeRange)
                        {
                            //if (D3Control.canCast("Mantra of Salvation"))
                            {
                                if (CastMonkSpell("Mantra of Salvation", D3Control.Player.Location))
                                {
                                    MantraTimer.Reset();
                                }
                            }
                        }
                        //if (D3Control.canCast("Mantra of Healing"))
                        {
                            if (CastMonkSpell("Mantra of Healing", D3Control.Player.Location))
                            {
                                MantraTimer.Reset();
                            }
                        }
                    }
                }
                if (D3Control.isObjectValid(D3Control.curTarget) && D3Control.curTarget.DistanceFromPlayer <= 20 && CastMonkSpell("Blinding Flash", D3Control.Player.Location))
                {
                    Thread.Sleep(100);
                }

                if (D3Control.Player.isBeingCCed())
                {
                    if (CastMonkSpell("Epiphany", D3Control.Player.Location))
                    {
                        return;
                    }
                    else if (CastMonkSpell("Serenity", D3Control.Player.Location))
                    {
                        return;
                    }
                }
                if (CombatConfig.SkillBuild == build.SunWuKong && distance < meleeRange && D3Control.Player.MpPct <= CombatConfig.MonkSunWukongSetting.MysticAllyPct)
                {
                    if (CastMonkSpell("Mystic Ally", D3Control.Player.Location))
                        Thread.Sleep(100);
                }
                if (D3Control.Player.HpPct <= MysticAllyHp && CastMonkSpell("Mystic Ally", D3Control.Player.Location))
                {
                    Thread.Sleep(100);
                }
            }
            catch { }
            return;
        }
 public static void checkBuff(D3Player entity)
 {
     // check buff and aura
     if (!D3Control.IsInGame())
         return;
     if (battleRageChecktimer.IsReady && D3Control.canCast("Battle Rage") && !D3Control.HasBuff("Battle Rage"))
     {
         if (CastBarbarianSpell("Battle Rage", D3Control.Player.Location))
         {
             battleRageChecktimer.Reset();
         }
     }
     if (D3Control.canCast("War Cry") && warCryTimer.IsReady)
     {
         if (CastBarbarianSpell("War Cry", D3Control.Player.Location))
         {
             warCryTimer.Reset();
         }
     }
     if (D3Control.canCast("Threatening Shout") && D3Control.Player.isInCombat && D3Control.curTarget != null && D3Control.curTarget.DistanceFromPlayer < 25 && CastBarbarianSpell("Threatening Shout", D3Control.Player.Location))
     {
     }
     if (D3Control.Player.HpPct <= CombatConfig.BarbDefaultSettings.ignorePainHPPct)
     {
         if (CastBarbarianSpell("Ignore Pain", D3Control.Player.Location))
         {
         }
     }
     return;
 }
        public bool moveToStartFight(D3Player entity)
        {
            handleAOE();
            handleAOE2();
            if (D3Control.getDoorInWay(D3Control.curTarget) != null)
            {
                D3Control.output("Door,try to move closer and open");
                D3Control.MoveTo(D3Control.curTarget, 2.5f);
                return false;
            }
            if (D3Control.Player.HpPct <= MoveToHealthGlobeHp)//&& D3Control.Player.ArcanePower <= MoveToHealthGlobeMana)
            {
                D3Object healthGlobe = D3Control.ClosestHealthGlobe;
                if (healthGlobe != null)
                {
                    if (CastWizardSpell("Teleport", healthGlobe.Location))
                    {
                        D3Control.output("Teleported to the Health Globe");
                        return true;
                    }
                    else D3Control.MoveTo(healthGlobe, 2.5f);
                    return true;
                }
                else if (D3Control.Player.HpPct <= MoveToHealthGlobeHp && D3Control.Player.ArcanePower <= MoveToHealthGlobeMana)
                {
                    if (healthGlobe != null)
                    {
                        D3Control.MoveTo(healthGlobe, 2.5f);
                    }
                }
            }
            if (D3Control.curTarget == null)
                return false;

            if (CombatConfig.SkillBuild == build.TalRasha)
            {
                if (CombatConfig.WizardTalRashaSettings.playType == TalPlayType.Melee)
                {
                    meleeRange = 40;
                }
                else
                {
                    meleeRange = 15;
                }
            }

            else if (CombatConfig.WizardDefaultSettings.playType == PlayType.range || isInArchonForm() && CombatConfig.WizardDefaultSettings.RangeAttackinArchon)
            {
                if (meleeRange < 35)
                {
                    meleeRange = 35;
                }
            }

            if (D3Control.curTarget == null)
                return false;
            float dist = D3Control.curTarget.DistanceFromPlayer;
            var LOS = D3Control.LOS(D3Control.curTarget.Location);

            if (dist > meleeRange || LOS)
            {
                if (LOS)
                {
                    D3Control.output("LOS? move closer?");
                    if (dist > 5 && meleeRange > dist)
                    {
                        D3Control.MoveTo(D3Control.curTarget, dist - 5);      // a thread doing the move
                    }
                }
                else
                {
                    if (dist <= 50 && D3Control.canCast("Teleport") && CombatConfig.WizardDefaultSettings.playType == PlayType.tanking && CombatConfig.WizardDefaultSettings.TeleportToEnemy)  // really need this?
                    {
                        if ((EBRune)D3Control.GetSpellRuneIndex("Explosive Blast") == EBRune.ChainReaction || (EBRune)D3Control.GetSpellRuneIndex("Explosive Blast") == EBRune.TimeBomb)
                        {
                            if (CastWizardSpell("Explosive Blast", D3Control.curTarget.Location))
                            {
                                Thread.Sleep(300);
                            }

                        }
                        CastWizardSpell("Teleport", D3Control.curTarget.Location);
                        //CastWizardTargetSpell("Teleport", D3Control.curTarget);
                        // D3Control.output("Teleported to farest target");
                    }
                    else if (dist <= 50 && CombatConfig.SkillBuild == build.TalRasha && D3Control.canCast("Teleport") && CombatConfig.WizardTalRashaSettings.playType == TalPlayType.Melee)  // really need this?
                    {
                        var loc = Surroundings.FindMobBlock(ref LiveMobsAround, FindTypes.Max);

                        CastWizardSpell("Teleport", loc);

                    }
                }
                if (meleeRange > 15)
                {
                    D3Control.MoveTo(D3Control.curTarget, meleeRange);      // a thread doing the move
                }
                else
                    D3Control.MoveTo(D3Control.curTarget, 18);      // a thread doing the move
            }
            return true;
        }
        public static void checkBuff(D3Player entity)
        {
            if (!D3Control.IsInGame())
                return;
            if (CastDH2Spell("Companion", D3Control.Player.Location))
            {
                D3Control.output("Companion");
                return;
            }
            if (MarkForDeathTimer.IsReady)
            {
                if (CastDH2Spell("Marked for Death", D3Control.Player.Location))
                {
                    MarkForDeathTimer.Reset();
                    D3Control.output("Marked for Death");
                    return;
                }
            }
            if (D3Control.canCast("Sentry") && D3Control.curTarget != null && D3Control.curTarget.DistanceFromPlayer <= 40)
            {
                if ((CombatConfig.SkillBuild == build.Sentry || D3Control.getDHSentryNumber(35) < CombatConfig.DHDefaultSettings.SentryCount) && CastDH1Spell("Sentry", D3Control.Player.Location))
                {
                    return;
                }
            }
            if (D3Control.canCast("Shadow Power") && !D3Control.HasBuff("Shadow Power") && D3Control.Player.HpPct <= ShadowPowerHp)
            {
                if (CastDH2Spell("Shadow Power", D3Control.Player.Location))
                {
                    return;
                }

            }
            if (D3Control.canCast("Smoke Screen") && D3Control.Player.HpPct <= SmokeScreenHp)
            {
                if (CastDH2Spell("Smoke Screen", D3Control.Player.Location))
                {
                    return;
                }
            }
            if (D3Control.canCast("Preparation"))
            {
                var runeIndex = (preparationRune)D3Control.GetSpellRuneIndex("Preparation");
                if (runeIndex == preparationRune.Punishment)    // restore hatred
                {
                    if (D3Control.Player.Hatred < D3Control.Player.MaxHatred - 80)
                    {
                        if (CastDH2Spell("Preparation", D3Control.Player.Location))
                        {
                            return;
                        }
                    }
                }
                else if (runeIndex == preparationRune.BattleScars)    // restore life
                {
                    if (D3Control.Player.HpPct < 60)
                    {
                        if (CastDH2Spell("Preparation", D3Control.Player.Location))
                        {
                            return;
                        }
                    }
                }
                else if (runeIndex == preparationRune.FocusedMind)    // restore disc gradually
                {
                    if (D3Control.Player.Disc <= D3Control.Player.MaxDisc - 20)
                    {
                        if (CastDH2Spell("Preparation", D3Control.Player.Location))
                        {
                            return;
                        }
                    }
                }

                else if (D3Control.Player.Disc <= D3Control.Player.MaxDisc - 30)
                {
                    if (CastDH2Spell("Preparation", D3Control.Player.Location))
                    {
                        return;
                    }
                }
            }
            return;
        }
        protected override void DoExecute(D3Player Entity)
        {
            try
            {
                CWSpellTimer combatThresholdTimer = new CWSpellTimer(120 * 1000, false);
                Vector3D targetLoc = null;
                bool enemyFound = false;
                var timePre = DateTime.Now;
                while (true)
                {
                    try
                    {
                        Thread.Sleep(CombatConfig.CombatLoopSleepTime);
                        if (!D3Control.IsInGame() || D3Control.Player.IsDead || combatThresholdTimer.IsReady)
                            break;
                        checkThreadStatus();
                        checkBuff(D3Control.Player);
                        LiveMobsAround = D3Control.RetrieveAllObjects(maxScanRange, Descriptor.eActorType.Monster);
                        D3Unit TargetMob = null;
                        var runAwayNearMobs = GetNearByEnemy(ref LiveMobsAround, 8);
                        var nearMobs = GetNearByEnemy(ref LiveMobsAround, 12);
                        if (checkIgnoreandMaxTrial(ref LiveMobsAround))
                            break;
                        if (CombatConfig.WitchDoctorDefaultSettings.playType == PlayType.range && HitAndRuntimer.IsReady)
                        {
                            if (runAwayNearMobs.Count > 0)
                            {   // find a safe place?
                                var target = Surroundings.FindMobBlock(ref LiveMobsAround, FindTypes.Min);
                                D3Control.MoveTo(target, 5);
                                Thread.Sleep(200);
                                HitAndRuntimer.Reset();
                            }
                        }
                        if (D3Control.canCast("Sacrifice"))
                        {
                            if (nearMobs != null && nearMobs.Count >= SacrificeNearbyMonsters || D3Control.curTarget.IsElite && nearMobs != null && nearMobs.Count > 0)
                            {
                                CastWitchDoctorSpell("Sacrifice", D3Control.Player.Location);
                            }
                        }
                        if (D3Control.canCast("Soul Harvest"))
                        {
                            if (nearMobs != null && (CombatConfig.WitchDoctorDefaultSettings.playType == PlayType.range && nearMobs.Count > 0 || nearMobs.Count >= SHNearbyMonsters) || D3Control.isObjectValid(D3Control.curTarget) && D3Control.curTarget.IsElite && nearMobs != null && nearMobs.Count > 0)
                            {
                                CastWitchDoctorSpell("Soul Harvest", D3Control.Player.Location);
                            }
                        }
                        if (D3Control.Player.HpPct <= SpiritWalkHp || D3Control.Player.isBeingCCed())
                        {
                            if (CastWitchDoctorSpell("Spirit Walk", D3Control.Player.Location))
                            {
                                if (moveBackTimer.IsReady && MoveBackWithSpiritWalk)
                                {
                                    if (D3Control.curTarget.DistanceFromPlayer < 50)
                                    {
                                        moveBackTimer.Reset();
                                        var target = Surroundings.FindMobBlock(ref LiveMobsAround, FindTypes.Min);
                                        //D3Control.MoveTo(target, 5);

                                        D3Control.ClickMoveTo(target);//D3Control.getSideSpot(D3Control.Player.Location, 180, 20));
                                        CWSpellTimer temp1Timer = new CWSpellTimer(3 * 1000, false);

                                        while (D3Control.Player.isMovingForward && !temp1Timer.IsReady)
                                        {
                                            D3Control.output("Escaped with Spirit Walk");
                                            Thread.Sleep(50);
                                        }
                                    }
                                }
                            }
                        }

                        bool InCombat = D3Control.Player.isInCombat;
                        if (!InCombat)
                        {
                            if (D3Control.GoodLootsAround())
                            {
                                if (nearMobs == null || nearMobs.Count == 0)
                                    return;
                            }
                        }
                        TargetMob = GetNextTargetMob(ref LiveMobsAround);
                        if (TargetMob != null)
                        {
                        }
                        if (D3.D3Control.curTarget == null)
                        {
                            if (TargetMob != null)
                            {
                                D3Control.TargetManager.SetAttackTarget(TargetMob);
                            }
                            else
                            {
                                if (InCombat)
                                {
                                    D3Control.output("In combat and cannot find next target?");
                                    DoExit(D3Control.Player);
                                    return;
                                }
                                else
                                {
                                    D3Control.output("Out of combat?");
                                    D3Control.TargetManager.ClearTarget();
                                    DoExit(D3Control.Player);
                                    return;
                                }
                            }
                        }
                        else
                        {
                            if (!D3Control.curTarget.Equals(TargetMob))
                            {
                                try
                                {
                                    if (!isFirstKillTarget(D3.D3Control.curTarget))
                                    {
                                        if (TargetMob != null)
                                        {
                                            if (isFirstKillTarget(TargetMob))
                                            {
                                                D3Control.TargetManager.SetAttackTarget(TargetMob);
                                            }
                                            else
                                            {
                                                if (!D3Control.curTarget.IsElite)
                                                {
                                                    D3Control.output("Change Target");
                                                    D3Control.stopMoving();
                                                    D3Control.TargetManager.SetAttackTarget(TargetMob);
                                                }
                                                else if (D3Control.LOS(D3Control.curTarget))
                                                {
                                                    D3Control.output("Change Target");
                                                    D3Control.stopMoving();
                                                    D3Control.TargetManager.SetAttackTarget(TargetMob);
                                                }
                                            }
                                        }
                                    }
                                }
                                catch { }
                            }
                        }
                        if (targetLoc == null || !D3Control.isInCombatMoving())
                        {
                        STARTPulling:

                            if (D3Control.isObjectValid(D3Control.curTarget) && !D3Control.curTarget.IsDead && !D3Control.curTarget.IsNpc && D3Control.curTarget.Type == Descriptor.eActorType.Monster)
                            {
                                targetLoc = D3Control.curTarget.Location;
                                D3Control.TargetManager.handleSpecialFight();
                                meleeRange = D3Control.getMobRange(D3Control.curTarget);
                                try
                                {
                                    doPulling(D3Control.Player);
                                }
                                catch { }
                                finally
                                {

                                }
                                continue;
                            }
                            else
                            {
                                D3Control.TargetManager.ClearTarget();
                                if (D3Control.isObjectValid(TargetMob) && !TargetMob.IsDead)
                                {
                                    D3Control.TargetManager.SetAttackTarget((D3Unit)TargetMob);
                                    TargetMob = null;
                                    goto STARTPulling;
                                }
                                else
                                    targetLoc = null;
                            }
                            if (!D3Control.isObjectValid(TargetMob))
                            {
                                continue;
                            }
                        }
                        else
                        {
                            if (targetLoc == new Vector3D())
                            {
                                DoExit(D3Control.Player);
                                return;
                            }
                            if (InCombat)
                            {
                                if (D3Control.isObjectValid(TargetMob) && !TargetMob.IsDead)
                                {
                                    D3Control.TargetManager.SetAttackTarget((D3Unit)TargetMob);
                                    targetLoc = D3Control.curTarget.Location;
                                }
                                else
                                {
                                    targetLoc = null;
                                }
                            }
                        }
                    }
                    catch { }
                }
            }
            catch { }
            DoExit(D3Control.Player);
            return;
        }
 protected override void DoEnter(D3Player Entity)
 {
     if (!inited)
     {
         Astronaut.Common.Serializer<Config> serializer = new Astronaut.Common.Serializer<Config>();
         string subDir = "\\Scripts\\";
         string workingDir = System.IO.Directory.GetCurrentDirectory();
         try
         {
             CombatConfig = serializer.Load(workingDir + subDir + ConfigFileName);
         }
         catch { CombatConfig = new Config(); }
         meleeRange = CombatConfig.MeleeRange;
         inited = true;
         setPower();
     }
 }
        void doPulling(D3Player entity)
        {
            try
            {
                var preTime = DateTime.Now;
                if (!GlobalBaseBotState.checkBeforePull(entity))
                    return;
                if (!D3Control.TargetManager.isTargetGoodForAttack((D3Unit)D3Control.curTarget)) // check the internal timer expires, which means the target is not good for attack, then block this target, the block is done inside the fuction call
                {
                    return;
                }

                D3Unit target = D3Control.curTarget;
                if (!moveToStartFight(entity))
                {
                    return;
                }
                if (CombatConfig.SkillBuild == build.Carnevil)
                {
                    handleCarnEvil();
                }
                else if (CombatConfig.SkillBuild == build.HellTooth)
                {
                    handleHellTooth_WallOfDeathBuild();
                }
                var distance = D3Control.curTarget.DistanceFromPlayer;
                if (D3Control.isObjectValid(D3Control.curTarget) && !D3Control.LOS(target) && distance <= 24)
                {
                    if (CastWitchDoctorSpell("Wall of Zombies", target.Location))
                    {
                        return;
                    }
                    if (CastWitchDoctorSpell("Grasp of the Dead", target.Location))
                    {
                        return;
                    }
                }
                if (PiranhasElite && D3Control.curTarget.IsElite && distance <= 40 || !PiranhasElite && distance <= 40)
                {
                    if (D3Control.CastLocationSpell("Piranhas", target.Location, true))
                    {
                        return;
                    }
                }
                if (SpiritBarrageTimer.IsReady)
                {
                    if (CastWitchDoctorSpell("Spirit Barrage", target.Location))
                        SpiritBarrageTimer.Reset();
                }
                if (D3Control.canCast("Haunt"))
                {
                    //D3Control.output(string.Format("{0} in list before checking.", hauntTimerList.Count));
                    hauntTimerList.RemoveAll(D3Control.generalNotValidorDeadOnMobTimer);  // remove all the invalid or dead ones
                    //D3Control.output(string.Format("{0} in list after checking.", hauntTimerList.Count));

                    int dots = 0;   // to cast at lease 3 haunt if there are mobs not dot'ed?
                    if (castDotSpellOnTimerInfo("Haunt", hauntTimerList, D3Control.curTarget, CombatConfig.WitchDoctorDefaultSettings.SpellTimerHaunt * 1000)) // check the current target first.
                        dots++;

                    foreach (var mob in LiveMobsAround)
                    {
                        if (!hasEnoughResourceForSpell("Haunt"))
                            break;

                        if (!D3Control.isObjectValid(mob) || ((D3Unit)mob).IsDead || mob.DistanceFromPlayer > 60 || D3Control.LOS(mob))
                            continue;
                        if (castDotSpellOnTimerInfo("Haunt", hauntTimerList, mob, CombatConfig.WitchDoctorDefaultSettings.SpellTimerHaunt * 1000)) // check the current target first.
                        {
                            dots++;
                        }
                        if (dots > 3)   // cast on 3 mobs at time
                            break;
                    }
                    D3Control.output(string.Format("List count {0}, dots {1}", hauntTimerList.Count, dots));
                }
                if (D3Control.canCast("Zombie Charger") && !D3Control.LOS(target))
                {
                    if (ZombieChargerTimer.IsReady)
                    {
                        if (CastWitchDoctorSpell("Zombie Charger", target.Location))
                            ZombieChargerTimer.Reset();
                    }
                }
                if (D3Control.canCast("Acid Cloud"))
                {
                    if (CombatConfig.WitchDoctorDefaultSettings.SpellTimerAcid != 0)
                    {
                        for (int i = 0; i < AcidTimerList.Count; i++)
                        {
                            if (AcidTimerList[i].timer.IsReady)
                            {   // remove the expired ones
                                AcidTimerList.RemoveAt(i--);
                                continue;
                            }
                        }
                        int dots = 0;
                        foreach (var mob in LiveMobsAround)
                        {
                            try
                            {
                                if (!D3Control.isObjectValid(mob) && ((D3Unit)mob).IsDead || mob.DistanceFromPlayer > 60 || D3Control.LOS(mob))
                                    continue;
                                if (!hasEnoughResourceForSpell("Acid Cloud"))
                                    break;
                                if (castDotSpellOnLocationTimerInfo("Acid Cloud", ref AcidTimerList, mob, CombatConfig.WitchDoctorDefaultSettings.SpellTimerHaunt * 1000, CombatConfig.WitchDoctorDefaultSettings.AcidCloudRange)) // check the current target first.
                                {
                                    dots++;
                                }
                                if (dots > 2)   // cast on 3 mobs at time
                                    break;
                            }
                            catch { }
                        }
                    }
                    else
                    {
                        CastWitchDoctorTargetSpell("Acid Cloud", target);

                    }

                }
                if ((distance < 15 || distance < meleeRange) && D3Control.canCast("Locust Swarm"))
                {
                    if (LocustSwarmTimer.Duration != CombatConfig.WitchDoctorDefaultSettings.SpellTimerLocustSwam * 1000)
                        LocustSwarmTimer.ChangeDuration(CombatConfig.WitchDoctorDefaultSettings.SpellTimerLocustSwam * 1000);
                    if (LocustSwarmTimer.IsReady)
                    {
                        if (CastWitchDoctorTargetSpell("Locust Swarm", D3Control.curTarget))//D3Control.curTarget))
                            LocustSwarmTimer.Reset();
                    }
                }
                if (D3Control.isObjectValid(D3Control.curTarget) && !D3Control.LOS(target))
                {
                    if (CastWitchDoctorTargetSpell("Poison Dart", target))
                    {
                        return;
                    }
                    if (CastWitchDoctorTargetSpell("Corpse Spiders", target))
                    {
                        return;
                    }
                    if (CastWitchDoctorTargetSpell("Firebomb", target))
                    {
                        return;
                    }
                    if (CastWitchDoctorTargetSpell("Plague of Toads", target))
                    {
                        return;
                    }
                }
            }
            catch { }
            finally
            {
                try2AvoidAOE();
            }
            return;
        }
 protected override void DoExit(D3Player entity)
 {
     if (PreviousState != null)
     {
         CallChangeStateEvent(entity, PreviousState, false, false);
     }
 }
 public static void checkBuff(D3Player entity)
 {
     // check buff and aura
     if (!D3Control.IsInGame())
         return;
     if (D3Control.isObjectValid(D3Control.curTarget))
     {
         var distance = D3Control.curTarget.DistanceFromPlayer;
         if (distance < 25 && CastCrusaderSpell("Laws of Valor", D3Control.Player.Location))
         {
         }
         if (distance < 15 && CastCrusaderSpell("Laws of Justice", D3Control.Player.Location))
         {
         }
     }
     if (D3Control.Player.HpPct < 70 && CastCrusaderSpell("Laws of Hope", D3Control.Player.Location))
     {
     }
     if (D3Control.Player.HpPct <= IronSkinHp)
     {
         if (CastCrusaderSpell("Iron Skin", D3Control.Player.Location))
         {
         }
     }
     return;
 }
        void doPulling(D3Player entity)
        {
            try
            {
                bool strafeCasted = false;

                if (!GlobalBaseBotState.checkBeforePull(entity))
                    return;
                if (!D3Control.TargetManager.isTargetGoodForAttack((D3Unit)D3Control.curTarget)) // check the internal timer expires, which means the target is not good for attack, then block this target, the block is done inside the fuction call
                {
                    return;
                }
                /*if (D3Control.canCast("Strafe"))
                {
                    var nearbyMobs = GetNearByEnemy(ref LiveMobsAround, 45);
                    if (nearbyMobs != null)
                    {
                        D3Control.output(string.Format("Nearby Mobs count {0}", nearbyMobs.Count));
                        if (nearbyMobs.Count > 0)//D3Control.curTarget.DistanceFromPlayer < 50)
                        {
                            if (CombatConfig.SkillBuild == build.NatalyaWW && ( CombatConfig.DHNatalyaWWSettings.RoVOnCD || CombatConfig.DHNatalyaWWSettings.natalyaRoVTimer.IsReady))
                            {
                                if (CombatConfig.DHNatalyaWWSettings.RoVInterval * 1000 != CombatConfig.DHNatalyaWWSettings.natalyaRoVTimer.Duration)
                                    CombatConfig.DHNatalyaWWSettings.natalyaRoVTimer.ChangeDuration(CombatConfig.DHNatalyaWWSettings.RoVInterval * 1000);
                                if (D3Control.canCast("Rain of Vengeance")) // to test if the spell is enabled first then search the best location to cast it
                                {
                                    var loc = Surroundings.FindMobBlock(ref LiveMobsAround, FindTypes.Max);
                                    if (CastDH1Spell("Rain of Vengeance", loc))
                                    {
                                        return;
                                    }
                                }
                            }

                            if (CastDH1Spell("Strafe", nearbyMobs[0].Location))//D3Control.Player.Location))// target.Location))
                            {
                                strafeCasted = true;
                            }
                            else
                            {
                                D3Control.output(string.Format("Strafe failed? count {0}", nearbyMobs.Count));

                            }
                        }
                    }
                }/**/
                handleStrafe();
                var nearbyMobs12 = GetNearByEnemy(ref LiveMobsAround, 12);

                if (D3Control.canCast("Caltrops"))
                {

                    if (nearbyMobs12 != null && nearbyMobs12.Count > 0 && CaltropsTimer.IsReady && CastDH2Spell("Caltrops", D3Control.Player.Location))
                    {
                        CaltropsTimer.Reset();
                    }
                }
                D3Unit target = D3Control.curTarget;
                if (!moveToStartFight(entity))
                {
                    return;
                }
                if (strafeCasted)
                    return;
                if (D3Control.Player.Hatred > AOEHatred && D3Control.canCast("Spike Trap"))
                {
                    CastDH1Spell("Spike Trap", target.Location);
                    return;
                }

                if (CombatConfig.SkillBuild == build.Sentry)
                {
                    //bool SentryBuildNotCastHatredSpender = CombatConfig.SkillBuild == build.Sentry && !CombatConfig.DHSentrySettings.CastHatredSpender;
                    //if (!SentryBuildNotCastHatredSpender)
                    {
                        if (D3Control.Player.Hatred >= CombatConfig.DHSentrySettings.CastHatredThreshold && CastDH1Spell(CombatConfig.DHSentrySettings.CastHatredSpenderName, target.Location))
                        {
                            return;
                        }
                    }

                }
                else
                {
                    if (D3Control.Player.Hatred > AOEHatred && D3Control.canCast("Rapid Fire"))
                    {
                        if (CastDH1Spell("Rapid Fire", target.Location))
                        {
                            return;
                        }
                    }
                    if (D3Control.Player.Hatred > AOEHatred)
                    {
                        if (CastDHTargetSpell("Elemental Arrow", target, out castSuccessful))
                        {
                            if (castSuccessful)
                            {
                                return;
                            }
                        }
                    }

                    if (D3Control.Player.Hatred > AOEHatred && D3Control.canCast("Multishot"))
                    {
                        //GetNextTargetMob
                        var nearbyMobs = GetNearByEnemy(ref LiveMobsAround, 12); // to check nearby mobs first, if there are too many mobs nearby, focus on those first. else, try to find the densest block

                        if (nearbyMobs != null && nearbyMobs.Count > 0)
                        {   // if no mobs nearby,
                            CastDH1Spell("Multishot", target.Location);
                        }
                        else
                        {

                            var loc = Surroundings.FindMobBlock(ref LiveMobsAround, FindTypes.Max);
                            if (loc == null || loc.Length == 0)
                            {
                                CastDHTargetSpell("Multishot", nearbyMobs[0], out castSuccessful);
                            }
                            else
                            {
                                if (CastDH1Spell("Multishot", loc))
                                {
                                    return;
                                }
                            }
                        }
                    }

                    if (D3Control.Player.Hatred > AOEHatred && D3Control.canCast("Cluster Arrow"))
                    {
                        CastDH1Spell("Cluster Arrow", target.Location);
                    }

                    if (D3Control.curTarget.DistanceFromPlayer < 30)
                    {
                        if (D3Control.canCast("Chakram"))
                        {
                            var index = D3Control.GetSpellRuneIndex("Chakram");
                            if (shurikenCloudIndex == index)
                            {
                                if (ChakramTimer.IsReady && CastDH1Spell("Chakram", D3Control.Player.Location))
                                {
                                    ChakramTimer.Reset();
                                    return;
                                }
                            }
                            else
                            {
                                if (CastDH1Spell("Chakram", target.Location))
                                {
                                    return;
                                }
                            }
                        }
                        if (CastDH1Spell("Fan of Knives", target.Location))
                        {
                            return;
                        }
                        if (CastDH1Spell("Impale", target.Location))
                        {
                            return;
                        }
                    }
                }

                if ((CombatConfig.DHDefaultSettings.RoVSettings.OnCD || CombatConfig.DHDefaultSettings.RoVSettings.OnTS && D3Control.IsMobTS(D3Control.curTarget) || CombatConfig.DHDefaultSettings.RoVSettings.OnElite && D3Control.curTarget.IsElite || nearbyMobs12.Count >= CombatConfig.DHDefaultSettings.RoVSettings.NearMobCount))
                {
                    if (CastDH1Spell("Rain of Vengeance", target.Location))
                    {
                        return;
                    }
                }
                if ((CombatConfig.DHDefaultSettings.VengeanceSettings.OnCD || CombatConfig.DHDefaultSettings.VengeanceSettings.OnTS && D3Control.IsMobTS(D3Control.curTarget) || CombatConfig.DHDefaultSettings.VengeanceSettings.OnElite && D3Control.curTarget.IsElite || nearbyMobs12.Count >= CombatConfig.DHDefaultSettings.VengeanceSettings.NearMobCount))
                {
                    if (CastDH1Spell("Vengeance", target.Location))
                    {
                        return;
                    }
                }
                if (D3Control.Player.Hatred < CombatConfig.DHDefaultSettings.HatredGeneratorThreshold)
                {
                    if (CastDHTargetSpell("Evasive Fire", target, out castSuccessful))
                    {
                        return;
                    }
                    if (CastDH1Spell("Hungering Arrow", target.Location))
                    {
                        return;
                    }
                    if (CastDH1Spell("Entangling Shot", target.Location))
                    {
                        return;
                    }
                    if (CastDH1Spell("Grenades", target.Location))
                    {
                        return;
                    }
                    if (CastDHTargetSpell("Bola Shot", target, out castSuccessful))
                    {
                        if (castSuccessful)
                        {
                            return;
                        }
                        else
                        {
                            if (D3Control.isObjectValid(target))
                            {
                            }
                        }
                    }
                    if (CombatConfig.DHDefaultSettings.hasKRIDERSHOT && CastDH1Spell("Elemental Arrow", target.Location))
                    {
                        D3Control.output("Elemental Arrow to generate Hatred");
                        return;
                    }
                }
            }
            catch { }
            finally
            {
                try2AvoidAOE();
            }
            return;
        }
        void doPulling(D3Player entity)
        {
            try
            {
                var preTime = DateTime.Now;
                if (!GlobalBaseBotState.checkBeforePull(entity))
                    return;
                D3Unit target = D3Control.curTarget;
                if (!D3Control.TargetManager.isTargetGoodForAttack((D3Unit)D3Control.curTarget))
                {
                    return;
                }

                if (!moveToStartFight(entity))
                {
                    return;
                }
                if (CombatConfig.SkillBuild == build.TalRasha)
                {
                   // if (CombatConfig.WizardTalRashaSettings.playType == TalPlayType.Melee)
                        handleTalRasha();
                    //else if (CombatConfig.WizardTalRashaSettings.playType == TalPlayType.AetherWalker)
                    //    handleTalRashaAetherWalker();

                }

                if (D3Control.canCast("Teleport") && D3Control.Player.HpPct <= TeleportHp)  // really need this?
                {
                    var teleportTarget = selectFarestMob(50, ref LiveMobsAround, 50);
                    if (teleportTarget != null && D3Control.curTarget.DistanceFromPlayer >= TeleportDistance)
                    {
                        {
                            CastWizardSpell("Teleport", teleportTarget.Location);
                            D3Control.output("Teleported to farest target");
                            return;
                        }
                    }
                }
                var distance = D3Control.curTarget.DistanceFromPlayer;
                var isArchon = isInArchonForm();
                var ArchonTeleport = (ArchonRune)D3Control.GetSpellRuneIndex("Archon") == ArchonRune.Teleport;
                if (isArchon && ArchonTeleport)
                {
                    CastWizardDirectionSpell("Teleport", D3Control.curTarget.Location);
                }
                else if (distance <= 50 && D3Control.canCast("Teleport") && CombatConfig.WizardDefaultSettings.playType == PlayType.tanking && CombatConfig.WizardDefaultSettings.TeleportToEnemy)  // really need this?
                {
                    if ((EBRune)D3Control.GetSpellRuneIndex("Explosive Blast") == EBRune.ChainReaction || (EBRune)D3Control.GetSpellRuneIndex("Explosive Blast") == EBRune.TimeBomb)
                    {
                        if (CastWizardDirectionSpell("Explosive Blast", D3Control.curTarget.Location))
                        {
                            D3Control.output("Explosive Blast");

                            Thread.Sleep(300);
                        }

                    }
                    CastWizardDirectionSpell("Teleport", D3Control.curTarget.Location);
                    //CastWizardTargetSpell("Teleport", D3Control.curTarget);
                    // D3Control.output("Teleported to farest target");
                }
                if ((D3Control.curTarget.IsElite || CombatConfig.WizardDefaultSettings.ArchonOnCD) && distance < 40)
                {
                    if (CastWizardSpell("Archon", D3Control.Player.Location))
                    {
                        return;
                    }
                }
                bool successful = false;
                if (distance > 12 && CastWizardSpell("Disintegration Wave", target.Location))
                {
                    return;
                }
                if (target.DistanceFromPlayer < 10 && CastWizardSpell("Arcane Strike", D3Control.Player.Location))// target.Location))
                {
                    D3Control.output("Arcane Strike");

                    Thread.Sleep(250);
                    return;
                }
                if (HydraTimer.IsReady && D3Control.canCast("Hydra"))
                {
                    if (D3Control.getWizHydraNumber(24) <= HydraNumber)
                    {
                        CastWizardSpell("Hydra", target.Location);
                        HydraTimer.Reset();
                        return;
                    }
                }
                if (CastWizardSpell("Black Hole", target.Location))
                {
                    return;
                }
                if (D3Control.Player.ArcanePower >= ArcaneOrbMana)
                {
                    if (CastWizardSpell("Arcane Orb", target.Location))
                    {
                        return;
                    }
                }
                if (D3Control.Player.ArcanePower >= ArcaneTorrentMana)
                {
                    if (CastWizardSpell("Arcane Torrent", target.Location))
                    {
                        return;
                    }
                }
                if (SleetStormControl && target.DistanceFromPlayer <= 16 && D3Control.Player.ArcanePower >= RayofFrostMana || !SleetStormControl && D3Control.Player.ArcanePower >= RayofFrostMana)
                {
                    if (CastWizardSpell("Ray of Frost", target.Location))
                    {
                        return;
                    }
                }
                if (D3Control.Player.ArcanePower >= DisintegrateMana && D3Control.isObjectValid(D3Control.curTarget))
                {
                    if (CastWizardSpell("Disintegrate", target.Location))
                    {
                        return;
                    }
                }
                if (D3Control.isObjectValid(D3Control.curTarget))
                {
                    if (CastWizardSpell("Shock Pulse", target.Location))
                    {
                        return;
                    }
                    if (CastWizardSpell("Magic Missile", target.Location))
                    {
                        return;
                    }
                    if (CastWizardSpell("Electrocute", target.Location))
                    {
                        return;
                    }
                }
                if (!D3Control.pureLOS(target.Location))
                {
                    if (CastWizardTargetSpell("Spectral Blade", target))
                    {
                        return;
                    }
                }
            }
            catch { }
            finally
            {
                try2AvoidAOE();
            }
            return;
        }