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();
     }
 }
Пример #4
0
 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;
         }
     }
 }
Пример #7
0
        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();
            }
        }
Пример #8
0
        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);
            }
        }
Пример #12
0
        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);
        }