Beispiel #1
0
        // Pull
        public static bool Pull(Cast cast, bool alwaysPull, List <AIOSpell> spells)
        {
            AIOSpell pullSpell = spells.Find(s => s != null && s.IsSpellUsable && s.KnownSpell);

            if (pullSpell == null)
            {
                RangeManager.SetRangeToMelee();
                return(false);
            }

            WoWUnit closestHostileFromTarget = GetClosestHostileFrom(ObjectManager.Target, 20);

            if (closestHostileFromTarget == null && !alwaysPull)
            {
                RangeManager.SetRangeToMelee();
                return(false);
            }

            float pullRange = pullSpell.MaxRange;

            if (ObjectManager.Target.GetDistance > pullRange - 2 ||
                ObjectManager.Target.GetDistance < 6 ||
                TraceLine.TraceLineGo(ObjectManager.Target.Position))
            {
                RangeManager.SetRangeToMelee();
                return(false);
            }

            if (closestHostileFromTarget != null && RangeManager.GetRange() < pullRange)
            {
                Logger.Log($"Pulling from distance (hostile unit {closestHostileFromTarget.Name} is too close)");
            }

            if (ObjectManager.Me.IsMounted)
            {
                MountTask.DismountMount();
            }

            RangeManager.SetRange(pullRange - 1);
            Thread.Sleep(300);

            if (cast.OnTarget(pullSpell))
            {
                Thread.Sleep(500);
                if (pullSpell.GetCurrentCooldown > 0)
                {
                    Usefuls.WaitIsCasting();
                    if (pullSpell.Name == "Shoot" || pullSpell.Name == "Throw" || pullSpell.Name == "Avenger's Shield")
                    {
                        Thread.Sleep(1500);
                    }
                    return(true);
                }
            }

            return(false);
        }
        public bool AdvancedCast(AIOSpell spell, bool stopWandAndCast = true, bool onSelf = false, WoWUnit onUnitFocus = null, Vector3 location = null)
        {
            WoWUnit Me     = ObjectManager.Me;
            float   buffer = 600;

            if (IsApproachingTarget)
            {
                return(true);
            }

            CurrentSpell         = spell;
            CurrentSpellLocation = location;

            CombatDebug("*----------- INTO PRE CAST FOR " + CurrentSpell.Name);

            if (!CurrentSpell.KnownSpell ||
                IsBackingUp ||
                Me.CastingTimeLeft > buffer ||
                !CurrentSpell.IsForcedCooldownReady ||
                Me.IsStunned)
            {
                return(false);
            }

            // Define target
            if (onUnitFocus != null)
            {
                CurrentSpellTarget = onUnitFocus;
            }
            else if (CurrentSpellLocation != null)
            {
                CurrentSpellTarget = null;
            }
            else if (onSelf)
            {
                CurrentSpellTarget = ObjectManager.Me;
            }
            else
            {
                if (CurrentSpell.MaxRange <= 0 && ObjectManager.Target.GetDistance > RangeManager.GetMeleeRangeWithTarget())
                {
                    return(false);
                }
                CurrentSpellTarget = ObjectManager.Target;
            }

            // Now that we know the target
            if (CurrentSpellLocation == null)
            {
                if (CurrentSpellTarget == null ||
                    CurrentSpellTarget.GetDistance > 100 ||
                    (CurrentSpellTarget.IsDead && !CurrentSpell.OnDeadTarget) ||
                    (CurrentSpell.MinRange > 0 && CurrentSpellTarget.GetDistance <= CurrentSpell.MinRange) ||
                    UnitImmunities.Contains(CurrentSpellTarget, CurrentSpell.Name) ||
                    (!CurrentSpellTarget.IsValid && !CurrentSpell.OnDeadTarget))    // double check this
                {
                    return(false);
                }
            }

            CombatDebug("*----------- INTO CAST FOR " + CurrentSpell.Name);

            // CHECK COST
            if (CurrentSpell.PowerType == -2 && Me.Health < CurrentSpell.Cost)
            {
                CombatDebug($"{CurrentSpell.Name}: Not enough health {CurrentSpell.Cost}/{Me.Health}, SKIPPING");
                return(false);
            }
            else if (CurrentSpell.PowerType == 0 && Me.Mana < CurrentSpell.Cost)
            {
                CombatDebug($"{CurrentSpell.Name}: Not enough mana {CurrentSpell.Cost}/{Me.Mana}, SKIPPING");
                return(false);
            }
            else if (CurrentSpell.PowerType == 1 && Me.Rage < CurrentSpell.Cost)
            {
                CombatDebug($"{CurrentSpell.Name}: Not enough rage {CurrentSpell.Cost}/{Me.Rage}, SKIPPING");
                return(false);
            }
            else if (CurrentSpell.PowerType == 2 && ObjectManager.Pet.Focus < CurrentSpell.Cost)
            {
                CombatDebug($"{CurrentSpell.Name}: Not enough pet focus {CurrentSpell.Cost}/{ObjectManager.Pet.Focus}, SKIPPING");
                return(false);
            }
            else if (CurrentSpell.PowerType == 3 && Me.Energy < CurrentSpell.Cost)
            {
                CombatDebug($"{CurrentSpell.Name}: Not enough energy {CurrentSpell.Cost}/{Me.Energy}, SKIPPING");
                return(false);
            }

            // DON'T CAST BECAUSE WANDING
            if (WandSpell != null &&
                ToolBox.UsingWand() &&
                !stopWandAndCast)
            {
                CombatDebug("Didn't cast because we were wanding");
                return(false);
            }

            // COOLDOWN CHECKS
            float _spellCD = CurrentSpell.GetCurrentCooldown;

            CombatDebug($"Cooldown is {_spellCD}");

            if (_spellCD >= 500)
            {
                CombatDebug("Didn't cast because cd is too long");
                return(false);
            }

            // STOP WAND FOR CAST
            if (WandSpell != null &&
                ToolBox.UsingWand() &&
                stopWandAndCast)
            {
                StopWandWaitGCD(WandSpell);
            }


            // Wait for remaining Cooldown
            if (_spellCD > 0f && _spellCD < buffer)
            {
                CombatDebug($"{CurrentSpell.Name} is almost ready, waiting");
                while (CurrentSpell.GetCurrentCooldown > 0 && CurrentSpell.GetCurrentCooldown < 500)
                {
                    Thread.Sleep(50);
                }
                Thread.Sleep(50); // safety
            }

            if (!CurrentSpell.IsSpellUsable)
            {
                CombatDebug("Didn't cast because spell somehow not usable");
                return(false);
            }

            bool stopMove = CurrentSpell.CastTime > 0 || CurrentSpell.IsChannel;

            if (CurrentSpellLocation != null || CurrentSpellTarget.Guid != Me.Guid)
            {
                Vector3 spellPosition = CurrentSpellLocation != null ? CurrentSpellLocation : CurrentSpellTarget.Position;
                if (CurrentSpell.MaxRange > 0 && spellPosition.DistanceTo(Me.Position) > CurrentSpell.MaxRange || TraceLine.TraceLineGo(spellPosition))
                {
                    if (Me.HaveBuff("Spirit of Redemption"))
                    {
                        return(false);
                    }

                    Logger.LogFight($"Target not in range/sight, recycling {CurrentSpell.Name}");

                    if (Fight.InFight)
                    {
                        IsApproachingTarget = true;
                    }
                    else
                    {
                        ApproachSpellTarget();
                    }

                    return(true);
                }
            }

            if (onUnitFocus != null)
            {
                ObjectManager.Me.FocusGuid = CurrentSpellTarget.Guid;
            }

            string unit = onUnitFocus != null ? "focus" : "target";

            unit = onSelf || CurrentSpellLocation != null ? "player" : unit;

            // Wait for remaining cast in case of buffer
            while (Me.CastingTimeLeft > 0)
            {
                Thread.Sleep(25);
            }

            if (stopMove)
            {
                MovementManager.StopMoveNewThread();
            }

            if (CombatLogON)
            {
                string rankString = CurrentSpell.Rank > 0 ? $"(Rank {CurrentSpell.Rank})" : "";
                string target     = CurrentSpellLocation != null?CurrentSpellLocation.ToString() : CurrentSpellTarget.Name;

                Logger.Log($"[Spell] Casting {CurrentSpell.Name.Replace("()", "")} {rankString} on {target}");
            }

            CurrentSpell.Launch(stopMove, false, true, unit);

            if (CurrentSpell.IsClickOnTerrain)
            {
                ClickOnTerrain.Pulse(CurrentSpellLocation);
            }

            Thread.Sleep(50);

            ToolBox.ClearCursor();

            // Wait for channel to end
            if (CurrentSpell.IsChannel)
            {
                CombatDebug($"{CurrentSpell.Name} is channel, wait cast");
                while (ToolBox.GetChannelTimeLeft("player") < 0)
                {
                    Thread.Sleep(50);
                }

                CurrentSpell.StartForcedCooldown();
                return(true);
            }

            // Wait for instant cast GCD
            if (CurrentSpell.CastTime <= 0)
            {
                CurrentSpell.StartForcedCooldown();
                Timer gcdLimit = new Timer(1500);
                CombatDebug($"{CurrentSpell.Name} is instant, wait GCD");
                while (DefaultBaseSpell.GetCurrentCooldown > buffer && !gcdLimit.IsReady)
                {
                    Thread.Sleep(50);
                }

                if (gcdLimit.IsReady)
                {
                    Logger.LogError("We had to resort to timer wait (GCD)");
                }

                return(true);
            }

            if (CurrentSpell.CastTime > 0)
            {
                // Wait for cast to end
                buffer = CurrentSpell.PreventDoubleCast ? 0 : buffer;
                CombatDebug($"{CurrentSpell.Name} is normal, wait until {buffer} left");
                while (Me.CastingTimeLeft > buffer)
                {
                    if (CurrentSpell.IsResurrectionSpell && CurrentSpellTarget.IsAlive)
                    {
                        Lua.RunMacroText("/stopcasting");
                    }

                    Thread.Sleep(50);
                }
                CurrentSpell.StartForcedCooldown();
            }

            return(true);
        }