public bool ExecuteStep(bool globalActive) { //can't execute this, because global is still active //can't execute this because we can't stop the current cast to execute this if ((globalActive && !_action.IgnoresGlobal()) || (RotationFramework.IsCast && !_forceCast)) { return(false); } //predicate is executed separately from targetfinder predicate //this way we can select one target, then check which spell to cast on the target //as opposed to finding a target to cast a specific spell on (not the desired result) Func <WoWUnit, bool> targetFinderPredicate = _checkRange ? (Func <WoWUnit, bool>)((u) => u.GetDistance <= _action.Range()) : ((u) => true); var watch = System.Diagnostics.Stopwatch.StartNew(); string spellName = "<noname>"; if (_action.GetType() == typeof(RotationSpell)) { RotationSpell spell = (RotationSpell)_action; spellName = spell.FullName(); } WoWUnit target = _targetFinder(targetFinderPredicate); watch.Stop(); RotationLogger.Trace($"({spellName}) targetFinder ({_targetFinder.Method.Name}) - {target?.Name}: {watch.ElapsedMilliseconds} ms"); watch.Restart(); if (target != null && _predicate(_action, target)) { watch.Stop(); RotationLogger.Trace($"({spellName}) predicate ({_targetFinder.Method.Name}): on {target.Name} {watch.ElapsedMilliseconds} ms"); watch.Restart(); var returnValue = _action.Execute(target, _forceCast); watch.Stop(); RotationLogger.Trace($"action ({spellName}): {watch.ElapsedMilliseconds} ms"); return(returnValue); } return(false); }
public static bool CastSpell(RotationSpell spell, WoWUnit unit, bool force = false) { // still waiting to make sure last spell was casted successfully, this can be interrupted // by interrupting the current cast to cast something else (which will clear the verification) if (RotationSpellVerifier.IsWaitingForVerification() && !force) { return(false); } // no need to check for spell availability // already wanding, don't turn it on again! if (spell.Spell.Name == "Shoot" && IsAutoRepeating("Shoot")) { return(true); } // targetfinder function already checks that they are in LoS and RotationStep takes care of the range check if (unit != null && spell.IsKnown() && spell.CanCast()) { Lua.LuaDoString("if IsMounted() then Dismount() end"); if (spell.Spell.CastTime > 0) { if (spell.Verification != RotationSpell.VerificationType.NONE) { //setting this for delegates, so we don't miss events //SetFocusGuid(unit.Guid); RotationSpellVerifier.QueueVerification(spell.Spell.Name, unit, spell.Verification); } //force iscast so we don't have to wait for client updates RotationFramework.IsCast = true; //ObjectManager.Me.ForceIsCast = true; } if (AreaSpells.Contains(spell.Spell.Name)) { SpellManager.CastSpellByIDAndPosition(spell.Spell.Id, unit.Position); } else { if (unit.Guid != RotationFramework.Me.Guid && unit.Guid != RotationFramework.Target.Guid) { MovementManager.Face(unit); } ExecuteActionOnUnit <object>(unit, (luaUnitId => { RotationLogger.Fight($"Casting {spell.FullName()} ({spell.Spell.Name} on {luaUnitId} with guid {unit.Guid}"); //MovementManager.StopMoveTo(false, (int) spell.CastTime()); Lua.LuaDoString($@" if {force.ToString().ToLower()} then SpellStopCasting() end CastSpellByName(""{spell.FullName()}"", ""{luaUnitId}""); --CombatTextSetActiveUnit(""{luaUnitId}""); FocusUnit(""{luaUnitId}""); " ); return(null); })); } return(true); } return(false); }