private static void ClearVerificationOlderThan(uint seconds) { if (_verification.Item1 != _emptyVerify.Item1 && _verification.Item4.AddSeconds(seconds) < DateTime.Now) { RotationLogger.Debug($"Force clearing verification because spell could not be verified for {seconds} seconds"); _verification = _emptyVerify; } }
public static void ForceClearVerification(string spellName) { lock (_verificationLock) { RotationLogger.Debug($"Force clearing verification for {spellName}"); _verification = _emptyVerify; } }
public static void QueueVerification(string spellName, WoWUnit target, RotationSpell.VerificationType type) { lock (_verificationLock) { RotationLogger.Debug($"Queueing verification for {spellName} on {Thread.CurrentThread.Name}"); _verification = new Tuple <string, ulong, RotationSpell.VerificationType, DateTime>(spellName, target.Guid, type, DateTime.Now); RegisterCombatLogClearer(); } }
public RotationSpellbook() { EventsLuaWithArgs.OnEventsLuaStringWithArgs += LuaEventHandler; _playerSpells.AddRange(GetSpellsFromLua()); _playerSpells.AddRange(GetSpellsFromLua("BOOKTYPE_PET")); foreach (var playerSpell in _playerSpells) { RotationLogger.Debug($"Fightclass framework found in spellbook: {playerSpell.Name} Rank {playerSpell.Rank}"); } }
public static void ForceClearVerification() { lock (_verificationLock) { if (_verification.Item1 != _emptyVerify.Item1) { RotationLogger.Debug($"Force clearing verification with current spell waiting on {_verification.Item1}"); _verification = _emptyVerify; } } }
public static void NotifyForDelegate(string id, List <string> args) { lock (_verificationLock) { if (!string.IsNullOrEmpty(_delegateVerification) && id == _delegateVerification && args[0] == "focus") { RotationLogger.Debug($"Clearing verification for {_verification.Item1} after delegated event {id}"); _verification = _emptyVerify; _delegateVerification = string.Empty; } } }
private void LuaEventHandler(string id, List <string> args) { if (id == "LEARNED_SPELL_IN_TAB") { RotationLogger.Debug($"Updating known spells because of {id}"); SpellUpdateHandler(); } if (id == "PET_BAR_UPDATE" && _lastUpdate.AddSeconds(1) < DateTime.Now) { _lastUpdate = DateTime.Now; RotationLogger.Debug($"Updating known spells because of {id}"); SpellUpdateHandler(); } }
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 void RunRotation(List <RotationStep> rotation) { float globalCd = GetGlobalCooldown(); bool gcdEnabled = globalCd != 0; IsCast = Me.IsCast || Me.IsCasting(); if (_slowRotation) { if (IsCast) { var temp = Me.CastingTimeLeft; RotationLogger.Fight($"Slow rotation - still casting! Wait for {temp + 100}"); Thread.Sleep(temp + 100); } //if no spell was executed successfully, we are assuming to still be on GCD and sleep the thread until the GCD ends //this prevents the rotation from re-checking if a no-gcd spell like Vanish, Judgement etc is ready else if (gcdEnabled) { RotationLogger.Fight($"No spell casted, waiting for {(globalCd * 1000 + 100)} for global cooldown to end!"); Thread.Sleep((int)(globalCd * 1000 + 100)); } } var watch = System.Diagnostics.Stopwatch.StartNew(); if (_framelock) { RunInFrameLock(rotation, gcdEnabled); } else { RunInLock(rotation, gcdEnabled); } watch.Stop(); if (watch.ElapsedMilliseconds > 150) { RotationLogger.Fight("Iteration took " + watch.ElapsedMilliseconds + "ms"); } }
/* * Example of NotifyForDelegate when usign COMBAT_TEXT_UPDATE instead of FocusUnit * * * public static void NotifyForDelegate(string id, List<string> args) * { * lock (VerificationLock) * { * if (_delegateVerification?.Count > 0 && id == "COMBAT_TEXT_UPDATE" && _delegateVerification.Contains(args[0])) * { * string eventName = args[0]; * string auraOrHealerName = args[1]; * * if (eventName.Contains("HEAL") && auraOrHealerName == RotationFramework.Me.Name) * { * Blindly.Run(() => * { * Thread.Sleep(Usefuls.Latency / 2); * RotationLogger.Debug($"Clearing verification for {_verification.Item1} after delegated event {eventName}"); * _verification = EmptyVerify; * _delegateVerification = new List<string>(); * }); * } * else if (eventName.Contains("AURA") && auraOrHealerName == _verification.Item1) * { * Blindly.Run(() => * { * Thread.Sleep(Usefuls.LatencyReal); * RotationLogger.Debug($"Clearing verification for {_verification.Item1} after delegated event {eventName}"); * _verification = EmptyVerify; * _delegateVerification = new List<string>(); * }); * * } * } * } * } */ public static void ClearIfOutOfRange() { lock (_verificationLock) { if (_verification.Item1 != _emptyVerify.Item1) { bool isInRange = RotationCombatUtil.ExecuteActionOnTarget( _verification.Item2, luaUnitId => Lua.LuaDoString <bool>($@" local spellInRange = IsSpellInRange(""{_verification.Item1}"", ""{luaUnitId}"") == 1; --DEFAULT_CHAT_FRAME:AddMessage(""Checking range of {_verification.Item1} on {luaUnitId} is "" .. (spellInRange and 'true' or 'false')); return spellInRange;") ); if (!isInRange && !RotationFramework.Me.IsCast) { RotationLogger.Debug($"Force clearing verification for {_verification.Item1} on {_verification.Item2} because we're out of range"); _verification = _emptyVerify; } } } }
public static void NotifyCombatLog(List <string> args) { lock (_verificationLock) { string timestamp = args[0]; string eventName = args[1]; string sourceGuid = args[2]; string sourceName = args[3]; string sourceFlags = args[4]; string destGuid = args[5]; string destName = args[6]; string destFlags = args[7]; // we have to check that the event fired is an expected event for the type of spell being casted // so that spells expecting an aura will only be verified on aura appliance RotationSpell.VerificationType type = GetVerificationType(); if (_successEvents[type].Contains(eventName)) { string spellId = args[8]; string spellName = args[9]; string spellSchool = args[10]; RotationLogger.Trace($"{eventName} {sourceGuid} {sourceName} {destGuid} {destName} {spellId} {spellName} {spellSchool}"); ulong castedBy = GetGUIDForLuaGUID(sourceGuid); if (castedBy == _playerGuid && IsSpellWaitingForVerification(spellName)) { var delegated = _eventDelegates.FirstOrDefault(e => e.Item1 == eventName); if (delegated != null) { string delegatedEvent = delegated.Item2; RotationLogger.Debug($"Delegating {eventName} to {delegatedEvent}"); CreatePassiveEventDelegate(delegatedEvent); } else { RotationLogger.Debug($"Clearing verification for {spellName}"); _verification = _emptyVerify; } } ulong spellTarget = GetGUIDForLuaGUID(destGuid); if (castedBy == 0 && IsWaitingForSpellOnTarget(spellName, spellTarget)) { var delegated = _eventDelegates.FirstOrDefault(e => e.Item1 == eventName); if (delegated != null) { string delegatedEvent = delegated.Item2; RotationLogger.Debug($"Delegating {eventName} to {delegatedEvent}"); CreatePassiveEventDelegate(delegatedEvent); } else { RotationLogger.Debug($"Clearing verification for spell with no source {spellName}"); _verification = _emptyVerify; } } } if (eventName == "SPELL_CAST_FAILED") { string spellId = args[8]; string spellName = args[9]; string spellSchool = args[10]; string failedType = args[11]; ulong castedBy = GetGUIDForLuaGUID(sourceGuid); if (castedBy == _playerGuid && IsSpellWaitingForVerification(spellName) && failedType != "Another action is in progress") { RotationLogger.Debug($"Clearing verification for {spellName} because {failedType}"); _verification = _emptyVerify; } } if (eventName == "UNIT_DIED") { ulong deadUnit = GetGUIDForLuaGUID(destGuid); if (IsWaitingOnTarget(deadUnit)) { RotationLogger.Debug($"Clearing verification because target died"); _verification = _emptyVerify; } if (deadUnit == _playerGuid) { RotationLogger.Debug($"Clearing verification because we died"); _verification = _emptyVerify; } } ClearVerificationOlderThan(10); } }
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); }