public bool PetSpell(string spellName, bool onFocus = false, bool noTargetNeeded = false) { int spellIndex = ToolBox.GetPetSpellIndex(spellName); if (ToolBox.PetKnowsSpell(spellName) && ToolBox.GetPetSpellReady(spellName) && !UnitImmunities.Contains(ObjectManager.Target, spellName) && (ObjectManager.Pet.HasTarget || noTargetNeeded)) { Thread.Sleep(ToolBox.GetLatency() + 100); Logger.Combat($"Cast (Pet) {spellName}"); if (!onFocus) { Lua.LuaDoString($"CastPetAction({spellIndex});"); } else { Lua.LuaDoString($"CastPetAction({spellIndex}, \'focus\');"); } 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); }