예제 #1
0
        private static void HandleCombatLog(object sender, LuaEventArgs args)
        {
            // Since we hooked this in ctor, make sure we are the selected CC
            if (RoutineManager.Current.Name != SingularRoutine.Instance.Name)
            {
                return;
            }

            // convert args to usable form
            var  e           = new CombatLogEventArgs(args.EventName, args.FireTimeStamp, args.Args);
            bool itWasDamage = false;

            if (TrackDamage || SingularRoutine.CurrentWoWContext == WoWContext.Normal)
            {
                if (e.DestGuid == StyxWoW.Me.Guid && e.SourceGuid != StyxWoW.Me.Guid)
                {
                    long damageAmount = 0;
                    switch (e.EventName)
                    {
                    case "SWING_DAMAGE":
                        itWasDamage  = true;
                        damageAmount = (long)e.Args[11];
                        Logger.WriteDebug("HandleCombatLog(Damage): {0} = {1}", e.EventName, damageAmount);
                        break;

                    case "SPELL_DAMAGE":
                    case "SPELL_PERIODIC_DAMAGE":
                    case "RANGE_DAMAGE":
                        itWasDamage  = true;
                        damageAmount = (long)e.Args[14];
                        break;
                    }

                    if (TrackDamage)
                    {
                        if (itWasDamage)
                        {
                            Logger.WriteDebug("HandleCombatLog(Damage): {0} = {1}", e.EventName, damageAmount);
                        }
                        else
                        {
                            LogUndesirableEvent("On Character", e);
                        }

                        if (damageAmount > 0)
                        {
                            DamageHistory.Enqueue(new Damage(DateTime.UtcNow, damageAmount));
                        }
                    }

                    if (itWasDamage && SingularRoutine.CurrentWoWContext == WoWContext.Normal)
                    {
                        WoWUnit enemy = e.SourceUnit;
                        if (Unit.ValidUnit(enemy) && enemy.IsPlayer)
                        {
                            Logger.WriteDiagnostic("GankDetect: received {0} src={1} dst={2}", args.EventName, e.SourceGuid, e.DestGuid);

                            // if (guidLastEnemy != enemy.Guid || (TimeLastAttackedByEnemyPlayer - DateTime.UtcNow).TotalSeconds > 30)
                            {
                                guidLastEnemy = enemy.Guid;
                                string extra = "";
                                if (e.Args.GetUpperBound(0) >= 12)
                                {
                                    extra = string.Format(" using {0}", e.SpellName);
                                }

                                AttackedWithSpellSchool = WoWSpellSchool.None;
                                if (e.Args.GetUpperBound(0) >= 12)
                                {
                                    AttackedWithSpellSchool = e.SpellSchool;
                                }

                                Logger.WriteDiagnostic("GankDetect: attacked by Level {0} {1}{2}", enemy.Level, enemy.SafeName(), extra);
                                if (SingularSettings.Instance.TargetWorldPvpRegardless && (BotPoi.Current == null || BotPoi.Current.Guid != enemy.Guid))
                                {
                                    Logger.Write(LogColor.Hilite, "GankDetect: setting {0} as BotPoi Kill Target", enemy.SafeName());
                                    BotPoi.Current = new BotPoi(enemy, PoiType.Kill);
                                }
                            }

                            AttackingEnemyPlayer          = enemy;
                            TimeLastAttackedByEnemyPlayer = DateTime.UtcNow;
                        }
                    }
                }
            }

            // Logger.WriteDebug("[CombatLog] " + e.Event + " - " + e.SourceName + " - " + e.SpellName);

            switch (e.Event)
            {
            default:
                LogUndesirableEvent("From Character", e);
                break;

            // spell_cast_failed only passes filter in Singular debug mode
            case "SPELL_CAST_FAILED":
                Logger.WriteDiagnostic("[CombatLog] {0} {1}#{2} failure: '{3}'", e.Event, e.Spell.Name, e.SpellId, e.Args[14]);
                if (e.Args[14].ToString() == LocalizedLineOfSightFailure)
                {
                    WoWGuid guid = WoWGuid.Empty;
                    try
                    {
                        LastLineOfSightTarget = e.DestUnit;
                        guid = LastLineOfSightTarget == null ? WoWGuid.Empty : LastLineOfSightTarget.Guid;
                    }
                    catch
                    {
                    }

                    if (!guid.IsValid)
                    {
                        Logger.WriteFile("[CombatLog] no valid destunit so using CurrentTarget");
                        LastLineOfSightTarget = StyxWoW.Me.CurrentTarget;
                        guid = StyxWoW.Me.CurrentTargetGuid;
                    }

                    LastLineOfSightFailure = DateTime.UtcNow;
                    Logger.WriteFile("[CombatLog] cast failed due to los reported at {0} on target {1:X}", LastLineOfSightFailure.ToString("HH:mm:ss.fff"), e.DestGuid);
                }
                else if (e.Args[14].ToString() == LocalizedUnitNotInfrontFailure)
                {
                    WoWGuid guid = e.DestGuid;
                    LastUnitNotInfrontFailure = DateTime.UtcNow;
                    if (guid.IsValid && guid != WoWGuid.Empty)
                    {
                        LastUnitNotInfrontGuid = guid;
                        Logger.WriteFile("[CombatLog] not facing SpellTarget [{0}] at {1}", LastUnitNotInfrontGuid, LastUnitNotInfrontFailure.ToString("HH:mm:ss.fff"));
                    }
                    else
                    {
                        LastUnitNotInfrontGuid = Spell.LastSpellTarget;
                        Logger.WriteFile("[CombatLog] not facing LastTarget [{0}] at {1}", LastUnitNotInfrontGuid, LastUnitNotInfrontFailure.ToString("HH:mm:ss.fff"), guid);
                    }
                }
                else if (!MovementManager.IsMovementDisabled && StyxWoW.Me.Class == WoWClass.Warrior && e.Args[14].ToString() == LocalizedNoPathAvailableFailure)
                {
                    LastNoPathFailure = DateTime.UtcNow;
                    LastNoPathGuid    = StyxWoW.Me.CurrentTargetGuid;
                    if (!StyxWoW.Me.GotTarget())
                    {
                        Logger.WriteFile("[CombatLog] cast failed - no path available to current target");
                    }
                    else
                    {
                        Logger.WriteFile("[CombatLog] cast failed - no path available to {0}, heightOffGround={1}, pos={2}",
                                         StyxWoW.Me.CurrentTarget.SafeName(),
                                         StyxWoW.Me.CurrentTarget.HeightOffTheGround(),
                                         StyxWoW.Me.CurrentTarget.Location
                                         );
                    }
                }
                else if (!SingularRoutine.IsManualMovementBotActive && (StyxWoW.Me.Class == WoWClass.Druid || StyxWoW.Me.Class == WoWClass.Shaman))
                {
                    if (LocalizedShapeshiftMessages.ContainsKey(e.Args[14].ToString()))
                    {
                        string symbolicName = LocalizedShapeshiftMessages[e.Args[14].ToString()];
                        SuppressShapeshiftUntil = DateTime.UtcNow.Add(TimeSpan.FromSeconds(30));
                        Logger.Write(LogColor.Cancel, "/cancel{0} - due to Shapeshift Error '{1}' on cast, suppress form for {2:F1} seconds", StyxWoW.Me.Shapeshift.ToString().CamelToSpaced(), symbolicName, (SuppressShapeshiftUntil - DateTime.UtcNow).TotalSeconds);
                        Lua.DoString("CancelShapeshiftForm()");
                    }
                }
                else if (StyxWoW.Me.Class == WoWClass.Rogue && SingularSettings.Instance.Rogue().UsePickPocket)
                {
                    if (e.Args[14].ToString() == LocalizedNoPocketsToPickFailure)
                    {
                        HandleRogueNoPocketsError();
                    }
                }
                break;

            case "SPELL_AURA_APPLIED":
            case "SPELL_CAST_SUCCESS":
                if (e.SourceGuid != StyxWoW.Me.Guid)
                {
                    return;
                }

                // Update the last spell we cast. So certain classes can 'switch' their logic around.
                Spell.LastSpellCast = e.SpellName;
                Logger.WriteDebug("Storing {0} as last spell cast.", Spell.LastSpellCast);

                // following commented block should not be needed since rewrite of Pet summon
                //
                //// Force a wait for all summoned minions. This prevents double-casting it.
                //if (StyxWoW.Me.Class == WoWClass.Warlock && e.SpellName.StartsWith("Summon "))
                //{
                //    StyxWoW.SleepForLagDuration();
                //}
                break;

            case "SWING_MISSED":
                if (e.Args[11].ToString() == "EVADE")
                {
                    HandleEvadeBuggedMob(args, e);
                }
                else if (e.Args[11].ToString() == "IMMUNE")
                {
                    WoWUnit unit = e.DestUnit;
                    if (unit != null && !unit.IsPlayer)
                    {
                        Logger.WriteDebug("{0} is immune to Physical spell school", unit.Name);
                        SpellImmunityManager.Add(unit.Entry, WoWSpellSchool.Physical, e.Spell);
                    }
                }
                break;

            case "SPELL_MISSED":
            case "RANGE_MISSED":
                // Why log misses?  Because users of classes with DoTs testing on training dummies
                // .. that they don't have enough +Hit for will get DoT spam.  This allows easy
                // .. diagnosis of false reports of rotation issues where a user simply isn't geared
                // .. this happens more at the beginning of an expansion especially
                if (SingularSettings.Debug)
                {
                    Logger.WriteDebug(
                        "[CombatLog] {0} {1}#{2} {3}",
                        e.Event,
                        e.Spell.Name,
                        e.SpellId,
                        e.Args[14]
                        );
                }

                if (e.Args[14].ToString() == "EVADE")
                {
                    HandleEvadeBuggedMob(args, e);
                }
                else if (e.Args[14].ToString() == "IMMUNE")
                {
                    WoWUnit unit = e.DestUnit;
                    if (unit != null && !unit.IsPlayer)
                    {
                        Logger.WriteDebug("{0} is immune to {1} spell school", unit.Name, e.SpellSchool);
                        SpellImmunityManager.Add(unit.Entry, e.SpellSchool, e.Spell);
                    }

                    if (StyxWoW.Me.Class == WoWClass.Rogue && e.SpellId == 6770)
                    {
                        WoWUnit unitImmune = unit;
                        if (unitImmune == null)
                        {
                            unitImmune = ObjectManager.GetObjectByGuid <WoWUnit>(Singular.ClassSpecific.Rogue.Common.lastSapTarget);
                        }

                        Singular.ClassSpecific.Rogue.Common.AddEntryToSapImmuneList(unitImmune);
                    }
                }
                break;

            case "UNIT_DIED":
                if (StyxWoW.Me.CurrentTarget != null && e.DestGuid == StyxWoW.Me.CurrentTarget.Guid)
                {
                    Spell.LastSpellCast = "";
                }

                try
                {
                    WoWUnit        corpse = e.SourceUnit;
                    WoWPartyMember pm     = Unit.GroupMemberInfos.First(m => m.Guid == corpse.Guid);
                    Logger.WriteDiagnostic("Combat Log: UNIT_DIED - Role={0} {1}", pm.Role & (~WoWPartyMember.GroupRole.Leader), corpse.SafeName());
                }
                catch
                {
                }
                break;
            }
        }
예제 #2
0
        public override void Initialize()
        {
            DateTime timeStart = DateTime.UtcNow;

            Logger.WriteFile("Initialize: started"); // cannot call method which references SingularSettings

            TalentManager.Init();                    // initializes CurrentSpec which is referenced everywhere
            SingularSettings.Initialize();           // loads Singular global and spec-specific settings (must determine spec first)

            DetermineCurrentWoWContext();

            Task.Run(() => WriteSupportInfo());

            _lastLogLevel = GlobalSettings.Instance.LogLevel;

            // When we actually need to use it, we will.
            Spell.Init();
            Spell.GcdInitialize();

            EventHandlers.Init();
            MountManager.Init();
            HotkeyDirector.Init();
            MovementManager.Init();
            // SoulstoneManager.Init();   // switch to using Death behavior
            Dispelling.Init();
            PartyBuff.Init();
            Singular.Lists.BossList.Init();

            Targeting.Instance.WeighTargetsFilter += PullMoreWeighTargetsFilter;

            //Logger.Write("Combat log event handler started.");
            // Do this now, so we ensure we update our context when needed.
            BotEvents.Player.OnMapChanged += e =>
            {
                // Don't run this handler if we're not the current routine!
                if (!WeAreTheCurrentCombatRoutine)
                {
                    return;
                }

                // Only ever update the context. All our internal handlers will use the context changed event
                // so we're not reliant on anything outside of ourselves for updates.
                UpdateContext();
            };

            TreeHooks.Instance.HooksCleared += () =>
            {
                // Don't run this handler if we're not the current routine!
                if (!WeAreTheCurrentCombatRoutine)
                {
                    return;
                }

                Logger.Write(LogColor.Hilite, "Hooks cleared, re-creating behaviors");
                RebuildBehaviors(silent: true);
                Spell.GcdInitialize();   // probably not needed, but quick
            };

            GlobalSettings.Instance.PropertyChanged += (sender, e) =>
            {
                // Don't run this handler if we're not the current routine!
                if (!WeAreTheCurrentCombatRoutine)
                {
                    return;
                }

                // only LogLevel change will impact our behav trees
                // .. as we conditionally include/omit some diagnostic nodes if debugging
                // also need to keep a cached copy of prior value as the event
                // .. fires on the settor, not when the value is different
                if (e.PropertyName == "LogLevel" && _lastLogLevel != GlobalSettings.Instance.LogLevel)
                {
                    _lastLogLevel = GlobalSettings.Instance.LogLevel;
                    Logger.Write(LogColor.Hilite, "HonorBuddy {0} setting changed to {1}, re-creating behaviors", e.PropertyName, _lastLogLevel.ToString());
                    RebuildBehaviors();
                    Spell.GcdInitialize();   // probably not needed, but quick
                }
            };

            // install botevent handler so we can consolidate validation on whether
            // .. local botevent handlers should be called or not
            SingularBotEventInitialize();

            Logger.Write("Determining talent spec.");
            try
            {
                TalentManager.Update();
            }
            catch (Exception e)
            {
                StopBot(e.ToString());
            }
            Logger.Write("Current spec is " + SpecName());

            // write current settings to log file... only written at startup and when Save press in Settings UI
            Task.Run(() => SingularSettings.Instance.LogSettings());

            // Update the current WoWContext, and fire an event for the change.
            UpdateContext();

            // NOTE: Hook these events AFTER the context update.
            OnWoWContextChanged += (orig, ne) =>
            {
                Logger.Write(LogColor.Hilite, "Context changed, re-creating behaviors");
                SingularRoutine.DescribeContext();
                RebuildBehaviors();
                Spell.GcdInitialize();
                Singular.Lists.BossList.Init();
            };
            RoutineManager.Reloaded += (s, e) =>
            {
                Logger.Write(LogColor.Hilite, "Routines were reloaded, re-creating behaviors");
                RebuildBehaviors(silent: true);
                Spell.GcdInitialize();
            };


            // create silently since Start button will create a context change (at least first Start)
            // .. which will build behaviors again
            if (!Instance.RebuildBehaviors())
            {
                return;
            }

            //
            if (IsPluginEnabled("DrinkPotions"))
            {
                Logger.Write(LogColor.Hilite, "info: disabling DrinkPotions plugin, conflicts with Singular potion support");
                SetPluginEnabled("DrinkPotions", false);
            }

            SpellImmunityManager.Add(16292, WoWSpellSchool.Frost);      // http://www.wowhead.com/npc=16292/aquantion

            Logger.WriteDebug(Color.White, "Verified behaviors can be created!");
            Logger.Write("Initialization complete!");
            Logger.WriteDiagnostic(Color.White, "Initialize: completed taking {0:F2} seconds", (DateTime.UtcNow - timeStart).TotalSeconds);
        }
예제 #3
0
        // Thanks to Singular Devs for the CombatLogEventArgs class and SpellImmunityManager.
        private static void HandleCombatLog(object sender, LuaEventArgs args)
        {
            var e = new CombatLogEventArgs(args.EventName, args.FireTimeStamp, args.Args);

            //var missType = Convert.ToString(e.Args[14]);

            switch (e.Event)
            {
            case "SWING_MISSED":
                if (e.Args[11].ToString() == "EVADE")
                {
                    CLULogger.TroubleshootLog("Mob is evading swing. Blacklisting it!");
                    Blacklist.Add(e.DestGuid, TimeSpan.FromMinutes(30));
                    if (StyxWoW.Me.CurrentTargetGuid == e.DestGuid)
                    {
                        StyxWoW.Me.ClearTarget();
                    }

                    BotPoi.Clear("Blacklisting evading mob");
                    StyxWoW.SleepForLagDuration();
                }
                else if (e.Args[11].ToString() == "IMMUNE")
                {
                    WoWUnit unit = e.DestUnit;
                    if (unit != null && !unit.IsPlayer)
                    {
                        CLULogger.TroubleshootLog("{0} is immune to {1} spell school", unit.Name, e.SpellSchool);
                        SpellImmunityManager.Add(unit.Entry, e.SpellSchool);
                    }
                }
                break;

            case "SPELL_MISSED":
            case "RANGE_MISSED":
                if (e.Args[14].ToString() == "EVADE")
                {
                    CLULogger.TroubleshootLog("Mob is evading ranged attack. Blacklisting it!");
                    Blacklist.Add(e.DestGuid, TimeSpan.FromMinutes(30));
                    if (StyxWoW.Me.CurrentTargetGuid == e.DestGuid)
                    {
                        StyxWoW.Me.ClearTarget();
                    }

                    BotPoi.Clear("Blacklisting evading mob");
                    StyxWoW.SleepForLagDuration();
                }
                else if (e.Args[14].ToString() == "IMMUNE")
                {
                    WoWUnit unit = e.DestUnit;
                    if (unit != null && !unit.IsPlayer)
                    {
                        CLULogger.TroubleshootLog("{0} is immune to {1} spell school", unit.Name, e.SpellSchool);
                        SpellImmunityManager.Add(unit.Entry, e.SpellSchool);
                    }
                }
                break;

            case "SPELL_AURA_REFRESH":
                if (e.SourceGuid == StyxWoW.Me.Guid)
                {
                    if (e.SpellId == 1822)
                    {
                        Classes.Druid.Common.RakeMultiplier = 1;

                        //TF
                        if (StyxWoW.Me.HasAura(5217))
                        {
                            Classes.Druid.Common.RakeMultiplier = Classes.Druid.Common.RakeMultiplier * 1.15;
                        }

                        //Savage Roar
                        if (StyxWoW.Me.HasAura(127538))
                        {
                            Classes.Druid.Common.RakeMultiplier = Classes.Druid.Common.RakeMultiplier * 1.3;
                        }

                        //Doc
                        if (StyxWoW.Me.HasAura(108373))
                        {
                            Classes.Druid.Common.RakeMultiplier = Classes.Druid.Common.RakeMultiplier * 1.25;
                        }
                    }
                    if (e.SpellId == 1079)
                    {
                        Classes.Druid.Common.ExtendedRip   = 0;
                        Classes.Druid.Common.RipMultiplier = 1;

                        //TF
                        if (StyxWoW.Me.HasAura(5217))
                        {
                            Classes.Druid.Common.RipMultiplier = Classes.Druid.Common.RipMultiplier * 1.15;
                        }

                        //Savage Roar
                        if (StyxWoW.Me.HasAura(127538))
                        {
                            Classes.Druid.Common.RipMultiplier = Classes.Druid.Common.RipMultiplier * 1.3;
                        }

                        //Doc
                        if (StyxWoW.Me.HasAura(108373))
                        {
                            Classes.Druid.Common.RipMultiplier = Classes.Druid.Common.RipMultiplier * 1.25;
                        }
                    }
                }
                break;

            case "SPELL_AURA_APPLIED":
                if (e.SourceGuid == StyxWoW.Me.Guid)
                {
                    if (e.SpellId == 1822)
                    {
                        Classes.Druid.Common.RakeMultiplier = 1;

                        //TF
                        if (StyxWoW.Me.HasAura(5217))
                        {
                            Classes.Druid.Common.RakeMultiplier = Classes.Druid.Common.RakeMultiplier * 1.15;
                        }

                        //Savage Roar
                        if (StyxWoW.Me.HasAura(127538))
                        {
                            Classes.Druid.Common.RakeMultiplier = Classes.Druid.Common.RakeMultiplier * 1.3;
                        }

                        //Doc
                        if (StyxWoW.Me.HasAura(108373))
                        {
                            Classes.Druid.Common.RakeMultiplier = Classes.Druid.Common.RakeMultiplier * 1.25;
                        }
                    }
                    if (e.SpellId == 1079)
                    {
                        Classes.Druid.Common.ExtendedRip   = 0;
                        Classes.Druid.Common.RipMultiplier = 1;

                        //TF
                        if (StyxWoW.Me.HasAura(5217))
                        {
                            Classes.Druid.Common.RipMultiplier = Classes.Druid.Common.RipMultiplier * 1.15;
                        }

                        //Savage Roar
                        if (StyxWoW.Me.HasAura(127538))
                        {
                            Classes.Druid.Common.RipMultiplier = Classes.Druid.Common.RipMultiplier * 1.3;
                        }

                        //Doc
                        if (StyxWoW.Me.HasAura(108373))
                        {
                            Classes.Druid.Common.RipMultiplier = Classes.Druid.Common.RipMultiplier * 1.25;
                        }
                    }
                }
                break;

            case "SPELL_AURA_REMOVED":
                if (e.SourceGuid == StyxWoW.Me.Guid)
                {
                    if (e.SpellId == 1822)
                    {
                        Classes.Druid.Common.RakeMultiplier = 0;
                    }
                    if (e.SpellId == 1079)
                    {
                        Classes.Druid.Common.ExtendedRip   = 0;
                        Classes.Druid.Common.RipMultiplier = 0;
                    }
                }
                break;
            }
        }
예제 #4
0
        private static void HandleCombatLog(object sender, LuaEventArgs args)
        {
            var e = new CombatLogEventArgs(args.EventName, args.FireTimeStamp, args.Args);

            if (e.SourceGuid != StyxWoW.Me.Guid)
            {
                return;
            }

            // Logger.WriteDebug("[CombatLog] " + e.Event + " - " + e.SourceName + " - " + e.SpellName);

            switch (e.Event)
            {
            default:
                Logger.WriteDebug("[CombatLog] filter out this event -- " + e.Event + " - " + e.SourceName + " - " + e.SpellName);
                break;

            case "SPELL_CAST_FAILED":
                if (SingularSettings.Instance.EnableDebugLogging)
                {
                    Logger.WriteDebug("[CombatLog] {0}:{1} cast of {2}#{3} failed: '{4}'",
                                      e.SourceName,
                                      e.SourceGuid,
                                      e.SpellName,
                                      e.SpellId,
                                      e.Args[14]
                                      );
                }
                break;

            case "SPELL_AURA_APPLIED":
            case "SPELL_CAST_SUCCESS":
                if (e.SourceGuid != StyxWoW.Me.Guid)
                {
                    return;
                }

                // Update the last spell we cast. So certain classes can 'switch' their logic around.
                Spell.LastSpellCast = e.SpellName;
                //Logger.WriteDebug("Successfully cast " + Spell.LastSpellCast);

                // Force a wait for all summoned minions. This prevents double-casting it.
                if (StyxWoW.Me.Class == WoWClass.Warlock && e.SpellName.StartsWith("Summon "))
                {
                    StyxWoW.SleepForLagDuration();
                }
                break;

            case "SWING_MISSED":
                if (e.Args[11].ToString() == "EVADE")
                {
                    Logger.Write("Mob is evading swing. Blacklisting it!");
                    Blacklist.Add(e.DestGuid, TimeSpan.FromMinutes(30));
                    if (StyxWoW.Me.CurrentTargetGuid == e.DestGuid)
                    {
                        StyxWoW.Me.ClearTarget();
                    }

                    BotPoi.Clear("Blacklisting evading mob");
                    StyxWoW.SleepForLagDuration();
                }
                else if (e.Args[11].ToString() == "IMMUNE")
                {
                    WoWUnit unit = e.DestUnit;
                    if (unit != null && !unit.IsPlayer)
                    {
                        Logger.WriteDebug("{0} is immune to {1} spell school", unit.Name, e.SpellSchool);
                        SpellImmunityManager.Add(unit.Entry, e.SpellSchool);
                    }
                }
                break;

            case "SPELL_MISSED":
            case "RANGE_MISSED":
                // DoT casting spam can occur when running on test dummy with low +hit
                //  ..  and multiple misses occurring. this should help troubleshoot
                //  ..  false reports of flawed rotation
                if (SingularSettings.Instance.EnableDebugLogging)
                {
                    Logger.WriteFile(
                        "[CombatLog] {0} {1}#{2} {3}",
                        e.Event,
                        e.SpellName,
                        e.SpellId,
                        e.Args[14]
                        );
                }

                if (e.Args[14].ToString() == "EVADE")
                {
                    Logger.Write("Mob is evading ranged attack. Blacklisting it!");
                    Blacklist.Add(e.DestGuid, TimeSpan.FromMinutes(30));
                    if (StyxWoW.Me.CurrentTargetGuid == e.DestGuid)
                    {
                        StyxWoW.Me.ClearTarget();
                    }

                    BotPoi.Clear("Blacklisting evading mob");
                    StyxWoW.SleepForLagDuration();
                }
                else if (e.Args[14].ToString() == "IMMUNE")
                {
                    WoWUnit unit = e.DestUnit;
                    if (unit != null && !unit.IsPlayer)
                    {
                        Logger.WriteDebug("{0} is immune to {1} spell school", unit.Name, e.SpellSchool);
                        SpellImmunityManager.Add(unit.Entry, e.SpellSchool);
                    }
                }
                break;
            }
        }
예제 #5
0
        private static void HandleCombatLog(object sender, LuaEventArgs args)
        {
            if (RoutineManager.Current.Name != AdvancedAI.Instance.Name)
            {
                return;
            }

            var e = new CombatLogEventArgs(args.EventName, args.FireTimeStamp, args.Args);

            if (e.SourceGuid != StyxWoW.Me.Guid)
            {
                return;
            }

            // Logger.WriteDebug("[CombatLog] " + e.Event + " - " + e.SourceName + " - " + e.SpellName);

            switch (e.Event)
            {
            // spell_cast_failed only passes filter in Singular debug mode
            case "SPELL_CAST_FAILED":
                Logging.WriteDiagnostic("[CombatLog] {0} {1}#{2} failure: '{3}'", e.Event, e.Spell.Name, e.SpellId, e.Args[14]);

                if (e.Args[14].ToString() == LocalizedLineOfSightFailure)
                {
                    ulong guid;
                    try
                    {
                        LastLineOfSightTarget = e.DestUnit;
                        guid = LastLineOfSightTarget == null ? 0 : LastLineOfSightTarget.Guid;
                    }
                    catch
                    {
                        LastLineOfSightTarget = StyxWoW.Me.CurrentTarget;
                        guid = StyxWoW.Me.CurrentTargetGuid;
                    }

                    LastLineOfSightFailure = DateTime.Now;
                    Logging.WriteDiagnostic("[CombatLog] cast fail due to los reported at {0} on target {1:X}", LastLineOfSightFailure.ToString("HH:mm:ss.fff"), e.DestGuid);
                }
                else if (StyxWoW.Me.Class == WoWClass.Druid)
                {
                    if (LocalizedShapeshiftMessages.ContainsKey(e.Args[14].ToString()))
                    {
                        string symbolicName = LocalizedShapeshiftMessages[e.Args[14].ToString()];
                        LastShapeshiftFailure = DateTime.Now;
                        Logging.WriteDiagnostic("[CombatLog] cast fail due to shapeshift error '{0}' while questing reported at {1}", symbolicName, LastShapeshiftFailure.ToString("HH:mm:ss.fff"));
                    }
                }
                else if (StyxWoW.Me.Class == WoWClass.Rogue)
                {
                    if (e.Args[14].ToString() == LocalizedNoPocketsToPickFailure)
                    {
                        // args on this event don't match standard SPELL_CAST_FAIL
                        // -- so, Singular only casts on current target so use that assumption
                        WoWUnit unit = StyxWoW.Me.CurrentTarget;
                        if (unit == null)
                        {
                            Logging.WriteDiagnostic("[CombatLog] has no pockets event did not have a valid unit");
                        }
                        else
                        {
                            Logging.WriteDiagnostic("[CombatLog] {0} has no pockets, blacklisting from pick pocket for 2 minutes", unit.SafeName());
                            Blacklist.Add(unit.Guid, BlacklistFlags.Node, TimeSpan.FromMinutes(2));
                        }
                    }
                }
                break;

#if SOMEONE_USES_LAST_SPELL_AT_SOME_POINT
            case "SPELL_AURA_APPLIED":
            case "SPELL_CAST_SUCCESS":
                if (e.SourceGuid != StyxWoW.Me.Guid)
                {
                    return;
                }

                // Update the last spell we cast. So certain classes can 'switch' their logic around.
                Spell.LastSpellCast = e.SpellName;
                //Logger.WriteDebug("Successfully cast " + Spell.LastSpellCast);

                // following commented block should not be needed since rewrite of Pet summon
                //
                //// Force a wait for all summoned minions. This prevents double-casting it.
                //if (StyxWoW.Me.Class == WoWClass.Warlock && e.SpellName.StartsWith("Summon "))
                //{
                //    StyxWoW.SleepForLagDuration();
                //}
                break;
#endif

            case "SWING_MISSED":
                if (e.Args[11].ToString() == "EVADE")
                {
                    HandleEvadeBuggedMob(args, e);
                }
                else if (e.Args[11].ToString() == "IMMUNE")
                {
                    WoWUnit unit = e.DestUnit;
                    if (unit != null && !unit.IsPlayer)
                    {
                        Logging.WriteDiagnostic("{0} is immune to Physical spell school", unit.Name);
                        SpellImmunityManager.Add(unit.Entry, WoWSpellSchool.Physical);
                    }
                }
                break;

            case "SPELL_MISSED":
            case "RANGE_MISSED":

                if (e.Args[14].ToString() == "EVADE")
                {
                    HandleEvadeBuggedMob(args, e);
                }
                else if (e.Args[14].ToString() == "IMMUNE")
                {
                    WoWUnit unit = e.DestUnit;
                    if (unit != null && !unit.IsPlayer)
                    {
                        Logging.WriteDiagnostic("{0} is immune to {1} spell school", unit.Name, e.SpellSchool);
                        SpellImmunityManager.Add(unit.Entry, e.SpellSchool);
                    }
                }
                break;
            }
        }