Beispiel #1
0
        private async static Task <bool> PoolSafetyChecks(WoWGameObject pool)
        {
            if (pool == null || !pool.IsValid)
            {
                BotPoi.Clear();
                return(true);
            }

            if (pool.Guid != _lastVisitedPoolGuid)
            {
                _lastVisitedPoolGuid = pool.Guid;
                TimeAtPoolTimer.Restart();
            }

            // safety check. if spending more than 5 mins at pool than black list it.
            if (TimeAtPoolTimer.ElapsedMilliseconds >= AutoAnglerSettings.Instance.MaxTimeAtPool * 60000)
            {
                Utility.BlacklistPool(pool, TimeSpan.FromMinutes(10), "Spend too much time at pool");
                return(true);
            }

            // move to another spot if we have too many failed casts
            if (_castCounter >= AutoAnglerSettings.Instance.MaxFailedCasts)
            {
                AutoAnglerBot.Log("Moving to a new fishing location since we have {0} failed casts",
                                  _castCounter);
                _castCounter = 0;
                RemovePointAtTop(pool);
                return(true);
            }
            return(false);
        }
Beispiel #2
0
        public static async Task <bool> HandleCombat()
        {
            if (!Me.IsFlying && Me.IsActuallyInCombat)
            {
                var mainHand = Me.Inventory.Equipped.MainHand;
                if ((mainHand == null || mainHand.Entry != AutoAnglerSettings.Instance.MainHand) &&
                    Utility.EquipWeapons())
                {
                    return(true);
                }

                if (await CombatBehavior.ExecuteCoroutine())
                {
                    return(true);
                }
            }

            if (BotPoi.Current.Type == PoiType.Kill)
            {
                var unit = BotPoi.Current.AsObject as WoWUnit;
                if (unit == null)
                {
                    BotPoi.Clear("Target not found");
                }
                else if (unit.IsDead)
                {
                    BotPoi.Clear("Target is dead");
                }
            }

            return(false);
        }
Beispiel #3
0
 public static void Clear()
 {
     if (BotPoi.Current.Type == PoiType.Loot)
     {
         BotPoi.Clear();
         lastguid = 0;
     }
 }
        //  2Sep2013 chinajade
        public static bool IsPoiIdle(BotPoi poi)
        {
            if (poi == null)
            {
                return(false);
            }

            return(s_idlePoiTypes.Contains(poi.Type));
        }
        // 24Feb2013-08:10UTC chinajade
        public override void OnFinished()
        {
            // Defend against being called multiple times (just in case)...
            if (!IsOnFinishedRun)
            {
                if (Targeting.Instance != null)
                {
                    Targeting.Instance.IncludeTargetsFilter -= TargetFilter_IncludeTargets;
                    Targeting.Instance.RemoveTargetsFilter  -= TargetFilter_RemoveTargets;
                    Targeting.Instance.WeighTargetsFilter   -= TargetFilter_WeighTargets;
                }


                // NB: we don't unhook _behaviorTreeHook_Main
                // This was installed when HB created the behavior, and its up to HB to unhook it

                BehaviorHookRemove("Combat_Main", ref _behaviorTreeHook_CombatMain);
                BehaviorHookRemove("Combat_Only", ref _behaviorTreeHook_CombatOnly);
                BehaviorHookRemove("Death_Main", ref _behaviorTreeHook_DeathMain);
                BehaviorHookRemove("Questbot_Main", ref _behaviorTreeHook_QuestbotMain);

                // Remove temporary blackspots...
                if (_temporaryBlackspots != null)
                {
                    BlackspotManager.RemoveBlackspots(_temporaryBlackspots.GetBlackspots());
                    _temporaryBlackspots = null;
                }

                // Restore configuration...
                if (_configMemento != null)
                {
                    _configMemento.Dispose();
                    _configMemento = null;
                }

                // Make sure we don't leave stale POIs set after finishing a QB.
                // This could happen if the user used a TerminateWhen to finish it
                // for example.
                BotPoi.Clear("Finished " + GetType().Name);

                TreeRoot.GoalText   = string.Empty;
                TreeRoot.StatusText = string.Empty;

                // Report the behavior run time...
                if (_behaviorRunTimer.IsRunning)
                {
                    _behaviorRunTimer.Stop();
                    QBCLog.DeveloperInfo("Behavior completed in {0}", Utility.PrettyTime(_behaviorRunTimer.Elapsed));
                }

                base.OnFinished();
                QBCLog.BehaviorLoggingContext = null;
                IsOnFinishedRun = true;
            }
        }
Beispiel #6
0
 public static void MoveTo(WoWPoint point)
 {
     if (BotPoi.Current.Type != PoiType.None)
     {
         BotPoi.Clear();
     }
     if (!ObjectManager.Me.Mounted && Mount.ShouldMount(point) && Mount.CanMount())
     {
         Mount.MountUp();
     }
     _lastPoint = point;
     _lastMove  = DateTime.Now;
     Navigator.MoveTo(point);
 }
Beispiel #7
0
        private void HandleCombatLog(object sender, LuaEventArgs args)
        {
            var e = new CombatLogEventArgs(args.EventName, args.FireTimeStamp, args.Args);

            //Logger.WriteDebug("[CombatLog] " + e.Event + " - " + e.SourceName + " - " + e.SpellName);
            switch (e.Event)
            {
            case "SPELL_AURA_APPLIED":
            case "SPELL_CAST_SUCCESS":
                if (e.SourceGuid != Me.Guid)
                {
                    return;
                }

                // reset target of current spell since complete
                CastingSpellTarget = null;

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

                if (_sleepAfterSuccessSpells.Contains(e.SpellName))
                {
                    StyxWoW.SleepForLagDuration();
                }

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

            case "SPELL_MISSED":
                //Logger.Write(e.Args.ToRealString());
                if (e.Args[11].ToString() == "EVADE")
                {
                    Logger.Write("Mob is evading. 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();
                }
                break;
            }
        }
        public static async Task <bool> MailItems()
        {
            WoWPoint mboxLoc = BotPoi.Current.Location;
            var      mailbox = ObjectManager.GetObjectsOfType <WoWGameObject>().
                               FirstOrDefault(
                m => m.SubType == WoWGameObjectType.Mailbox &&
                m.Location.Distance(mboxLoc) < 10);

            if (mailbox == null)
            {
                if (Me.Location.DistanceSqr(BotPoi.Current.Location) > 4 * 4)
                {
                    Flightor.MoveTo(BotPoi.Current.Location);
                    return(true);
                }

                var profile = ProfileManager.CurrentOuterProfile;
                if (profile != null)
                {
                    profile.MailboxManager.Blacklist.Add(BotPoi.Current.AsMailbox);
                }

                BotPoi.Clear(string.Format("Unable to find mailbox @ {0}", BotPoi.Current.Location));
                return(false);
            }
            if (!mailbox.WithinInteractRange)
            {
                return(await FlyTo(BotPoi.Current.Location));
            }

            if (!mailbox.WithinInteractRange)
            {
                return(await FlyTo(mailbox.Location, mailbox.SafeName));
            }

            if (!MailFrame.Instance.IsVisible)
            {
                mailbox.Interact();
                await CommonCoroutines.SleepForLagDuration();

                return(true);
            }

            await Vendors.MailAllItemsCoroutine();

            Vendor ven = ProfileManager.CurrentOuterProfile.VendorManager.GetClosestVendor();

            BotPoi.Current = ven != null ? new BotPoi(ven, PoiType.Repair) : new BotPoi(PoiType.None);
            return(true);
        }
Beispiel #9
0
        //protected override Composite CreateBehavior_CombatMain()
        //{
        //	return new PrioritySelector(
        //		new Decorator(context => (State_MainBehavior == StateType_MainBehavior.PathIngressing)
        //									|| (State_MainBehavior == StateType_MainBehavior.PathRetreating),
        //			CreateBehavior())
        //		);
        //}


        protected override Composite CreateBehavior_CombatOnly()
        {
            return(new PrioritySelector(
                       // NB: Since we highlight the target we're watching while we're waiting...
                       // If we get into combat, we don't want Honorbuddy running off to chase the currently highlighted
                       // target (its usually an elite).  So, if the selected target not attacking us, we clear the target,
                       // so Honorbuddy can make a proper target selection.
                       new Decorator(context => Me.GotTarget && !Me.CurrentTarget.IsTargetingMeOrPet,
                                     new Action(context =>
            {
                BotPoi.Clear();
                Me.ClearTarget();
            }))
                       ));
        }
Beispiel #10
0
        public static void MoveTo(WoWPoint point)
        {
            if (BotPoi.Current.Type != PoiType.None)
            {
                BotPoi.Clear();
            }

            if (CharacterSettings.Instance.UseMount && !StyxWoW.Me.Mounted && Mount.CanMount() && Mount.ShouldMount(point))
            {
                Mount.MountUp(() => point);
            }
            _lastPoint = point;
            _lastMove  = DateTime.Now;
            Navigator.MoveTo(point);
        }
Beispiel #11
0
 public static void MoveTo(WoWPoint point)
 {
     if (BotPoi.Current.Type != PoiType.None)
     {
         BotPoi.Clear();
     }
     if (!ObjectManager.Me.Mounted && Mount.ShouldMount(point) && Mount.CanMount())
     {
         Mount.MountUp();
     }
     TreeRoot.StatusText = string.Format("PB: Moving to {0}", point);
     _lastPoint          = point;
     _lastMove           = DateTime.Now;
     Navigator.MoveTo(point);
 }
Beispiel #12
0
 private static void CombatLogEventHander(object sender, LuaEventArgs args)
 {
     foreach (object arg in args.Args)
     {
         if (arg is String)
         {
             var s = (string)arg;
             if (s.ToUpper() == "EVADE" || s.ToUpper() == "ENTKOMMEN")
             {
                 if (!AmplifySettings.Instance.MoveDisable)
                 {
                     if (StyxWoW.Me.GotTarget && !IsBattleGround())
                     {
                         if (LastTarget == null || Me.CurrentTarget.Guid != LastTarget) //Meaning they are not the same.
                         {
                             LastTarget = Me.CurrentTarget.Guid;                        // set guid to current target.
                             EvadeCount = 1;                                            //it didnt match last target and already evaded once.
                             Logging.Write("Target Evaded {0} Times", EvadeCount.ToString());
                         }
                         else
                         {
                             EvadeCount++;
                             Logging.Write("Target Evaded {0} Times", EvadeCount.ToString());
                             if (EvadeCount >= 3)
                             {
                                 Logging.Write("Target Evaded {0} Times", EvadeCount.ToString());
                                 Logging.Write("Target is Evade bugged.");
                                 Logging.Write("Blacklisting for 3 hours");
                                 Blacklist.Add(StyxWoW.Me.CurrentTargetGuid, TimeSpan.FromHours(3));
                                 StyxWoW.Me.ClearTarget();
                                 BotPoi.Clear();
                             }
                         }
                     }
                     else
                     if (StyxWoW.Me.GotTarget && (IsBattleGround() || !Me.IsInInstance))
                     {
                         Logging.Write("My target is Evade bugged.");
                         Logging.Write("Blacklisting for 1 Minute");
                         Blacklist.Add(StyxWoW.Me.CurrentTargetGuid, TimeSpan.FromMinutes(1));
                         StyxWoW.Me.ClearTarget();
                         BotPoi.Clear();
                     }
                 }
             }
         }
     }
 }
        protected override Composite CreateBehavior_CombatMain()
        {
            return(new Decorator(context => IsViableForItemUse(SelectedTarget),
                                 new PrioritySelector(
                                     // If the target has the Item's Aura...
                                     new Decorator(context => SelectedTarget.HasAura(ItemAppliesAuraId),
                                                   new PrioritySelector(
                                                       // Count our success if no associated quest...
                                                       new Decorator(context => QuestId == 0,
                                                                     new Action(context => { ++Counter; })),

                                                       // Wait additional time requested by profile writer...
                                                       new Wait(TimeSpan.FromMilliseconds(WaitTimeAfterItemUse),
                                                                context => false,
                                                                new ActionAlwaysSucceed()),

                                                       new Action(context =>
            {
                // If we can only use the item once per target, blacklist this target from subsequent selection...
                if ((UseItemStrategy == UseItemStrategyType.UseItemOncePerTarget) ||
                    (UseItemStrategy == UseItemStrategyType.UseItemOncePerTargetDontDefend))
                {
                    BlacklistForInteracting(SelectedTarget, TimeSpan.FromSeconds(180));
                }

                // If we can't defend ourselves from the target, blacklist it for combat and move on...
                if ((UseItemStrategy == UseItemStrategyType.UseItemContinuouslyOnTargetDontDefend) ||
                    (UseItemStrategy == UseItemStrategyType.UseItemOncePerTargetDontDefend))
                {
                    Blacklist.Add(SelectedTarget, BlacklistFlags.Combat, TimeSpan.FromSeconds(180));
                    BotPoi.Clear();
                    Me.ClearTarget();
                    SelectedTarget = null;
                }
            })
                                                       )),

                                     // If any mob aggros on us while are heading to deal with SelectedTarget, finish aggro mob first...
                                     // NB: We don't want to wait until the mob hits us and we get in combat;
                                     // otherwise, we may wind up at our target with multiple mobs to fight.
                                     UtilityBehaviorPS_SpankMobTargetingUs()
                                     )
                                 ));
        }
Beispiel #14
0
        // CreateBehavior supplied by QuestBehaviorBase.
        // Instead, provide CreateMainBehavior definition.

        // Dispose provided by QuestBehaviorBase.

        // IsDone provided by QuestBehaviorBase.
        // Call the QuestBehaviorBase.BehaviorDone() method when you want to indicate your behavior is complete.

        // OnFinished provided by QuestBehaviorBase.

        public override void OnStart()
        {
            // Let QuestBehaviorBase do basic initializaion of the behavior, deal with bad or deprecated attributes,
            // capture configuration state, install BT hooks, etc.  This will also update the goal text.
            var isBehaviorShouldRun = OnStart_QuestBehaviorCore();

            // If the quest is complete, this behavior is already done...
            // So we don't want to falsely inform the user of things that will be skipped.
            if (isBehaviorShouldRun)
            {
                const float defaultArrivalToleranceMin = 1;
                // Make certain ArrivalTolerance is coherent with Navigator.PathPrecision...
                if (DefaultArrivalTolerance < defaultArrivalToleranceMin)
                {
                    QBCLog.DeveloperInfo("ArrivalTolerance({0:F1}) is less than Minimum({1:F1})."
                                         + "  Setting ArrivalTolerance to be minimum to prevent navigational issues.",
                                         DefaultArrivalTolerance,
                                         defaultArrivalToleranceMin);
                    DefaultArrivalTolerance = defaultArrivalToleranceMin;
                }

                // Disable any settings that may cause us to dismount --
                // When we mount for travel via FlyTo, we don't want to be distracted by other things.
                // NOTE: the ConfigMemento in QuestBehaviorBase restores these settings to their
                // normal values when OnFinished() is called.
                LevelBot.BehaviorFlags &= ~(BehaviorFlags.Loot | BehaviorFlags.Pull);

                // Clear any existing POI (after we've disabled Pull/Loot behaviors)...
                // Otherwise, FlyTo can get stuck trying to pursue the previous POI, if one was
                // set immediately before the behavior was launched.  This is a boundary condition,
                // and it happens frequently enough to be really annoying.
                BotPoi.Clear();

                // Pick our destination proper...
                PotentialDestinations.WaypointVisitStrategy = HuntingGroundsType.WaypointVisitStrategyType.PickOneAtRandom;
                RoughDestination = PotentialDestinations.CurrentWaypoint();

                var actionDescription = $"Flying to '{RoughDestination.Name}' ({RoughDestination.Location})";
                this.UpdateGoalText(GetQuestId(), actionDescription);
                TreeRoot.StatusText = actionDescription;
            }
        }
Beispiel #15
0
        private static void UIErrorEventHander(object sender, LuaEventArgs args)
        {
            string Error = args.Args[0].ToString();

            if (Error == "Target not in line of sight" || Error == "Ziel ist nicht im Sichtfeld")
            {
                if (!AmplifySettings.Instance.MoveDisable && Me.CurrentTarget != null && Navigator.CanNavigateFully(Me.Location, Me.CurrentTarget.Location))
                {
                    Logging.Write("Target not in Line of Sight to {0} Blacklisting for 10 sec to allow Repositioning. ", Me.CurrentTarget.Name);
                    Blacklist.Add(StyxWoW.Me.CurrentTargetGuid, TimeSpan.FromSeconds(10));
                    StyxWoW.Me.ClearTarget();
                    BotPoi.Clear();
                }
                if (!AmplifySettings.Instance.MoveDisable && Me.CurrentTarget != null && !Navigator.CanNavigateFully(Me.Location, Me.CurrentTarget.Location))
                {
                    Logging.Write("Cant Navigate to {0} Blacklisting for 3min", Me.CurrentTarget.Name);
                    Blacklist.Add(StyxWoW.Me.CurrentTargetGuid, TimeSpan.FromMinutes(3));
                    StyxWoW.Me.ClearTarget();
                    BotPoi.Clear();
                }
            }
        }
Beispiel #16
0
 public static void RepairFly()
 {
     if (Flightor.MountHelper.CanMount && !_iGotThis)
     {
         _iGotThis   = true;
         _currentPOI = BotPoi.Current;
         BotPoi.Clear();
         _oldLoc = _me.Location;
         Log("Vendor/repair run discovered, attempting to fly");
         var _safeSpot = findSafeFlightPoint(_currentPOI.Location);
         if (_safeSpot.Equals(_currentPOI.Location))
         {
             flyTo(_currentPOI.Location);
         }
         else
         {
             performSafeFlight(_safeSpot, _currentPOI.Location);
         }
         _currentPOI.AsObject.Interact();
         StyxWoW.SleepForLagDuration();
         Thread.Sleep(1000);
         Vendors.RepairAllItems();
         Thread.Sleep(1000);
         Vendors.SellAllItems();
         Thread.Sleep(1000);
         Log("Vendor visited, flying back!");
         var _safeSpotBack = findSafeFlightPoint(_oldLoc);
         if (_safeSpotBack.Equals(_oldLoc))
         {
             flyTo(_oldLoc);
         }
         else
         {
             performSafeFlight(_safeSpotBack, _oldLoc);
         }
         Log("Back where we started (hopefully), thank you for flying with Crafty Airlines!");
         _iGotThis = false;
     }
 }
Beispiel #17
0
        public override void Pulse()
        {
            try


            {
                if (Battlegrounds.IsInsideBattleground && Me.ZoneId != 4384)
                {
                    ObjectManager.Update();
                    BGTimer.Start();
                    combatTimerBG.Start();
                }

                if (!Battlegrounds.IsInsideBattleground)
                {
                    combatTimerBG.Reset();
                    BGTimer.Reset();
                    SotaTimer.Reset();
                    Sotamsg.Reset();
                }



                if (combatTimerBG.Elapsed.TotalSeconds > 90 && combatTimerBG.Elapsed.TotalSeconds < 92)
                {
                    Logging.Write(Color.Red, "[BGHelper] - BG Mode Running - Starting NoW!");
                    //combatTimerBG.Stop();
                    //BGTimer.Reset();
                    //BGTimer.Stop();
                }


                while (BGTimer.Elapsed.TotalSeconds > EnterTimeout && Battlegrounds.IsInsideBattleground && combatTimerBG.Elapsed.TotalSeconds < settings.BgTimeout && Me.ZoneId != 4384)
                {
                    //combatTimer.Reset();
                    //BGTimer.Stop();
                    BotPoi.Clear();
                    //Thread.Sleep(110000);
                    antispam.Start();
                    if (antispam.Elapsed.TotalSeconds > 20)
                    {
                        PlaySound("Enter.wav");
                        Logging.Write(Color.Red, "[BGHelper] - BG Detected - Wait Routine Running");
                        antispam.Reset();
                    }
                }

                // SOTA
                while (Me.HasAura("Preparation") && Battlegrounds.IsInsideBattleground && Me.ZoneId == 4384)
                {
                    //combatTimer.Reset();
                    //BGTimer.Stop();
                    BotPoi.Clear();
                    //Thread.Sleep(110000);
                    antispam.Start();
                    if (antispam.Elapsed.TotalSeconds > 20)
                    {
                        PlaySound("Enter.wav");
                        Logging.Write(Color.Red, "[BGHelper] - We are in Sota - Wait Till BG Starts");
                        antispam.Reset();
                    }
                }

                if (!Me.HasAura("Preparation") && Battlegrounds.IsInsideBattleground && Me.ZoneId == 4384)
                {
                    Sotamsg.Start();
                    if (Sotamsg.Elapsed.TotalSeconds < 3)
                    {
                        Logging.Write(Color.Red, "[BGHelper] - Sota Running - Enjoy Botting!");
                    }
                }
            }
            catch (Exception e)
            {
                Log("ERROR: " + e.Message + ". See debug log.");
                Logging.WriteDebug("exception:");
                Logging.WriteException(e);
            }
        }
Beispiel #18
0
 public static void BlacklistPool(WoWGameObject pool, TimeSpan time, string reason)
 {
     Blacklist.Add(pool.Guid, BlacklistFlags.Node, time, reason);
     BotPoi.Clear(reason);
 }
Beispiel #19
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;
            }
        }
        private static void HandleEvadeBuggedMob(LuaEventArgs args, CombatLogEventArgs e)
        {
            WoWUnit unit = e.DestUnit;
            ulong   guid = e.DestGuid;

            if (unit == null && StyxWoW.Me.CurrentTarget != null)
            {
                unit = StyxWoW.Me.CurrentTarget;
                guid = StyxWoW.Me.CurrentTargetGuid;
                Logging.Write("Evade: bugged mob guid:{0}, so assuming current target instead", args.Args[7]);
            }

            if (unit != null)
            {
                if (!MobsThatEvaded.ContainsKey(unit.Guid))
                {
                    MobsThatEvaded.Add(unit.Guid, 0);
                }

                MobsThatEvaded[unit.Guid]++;
                if (MobsThatEvaded[unit.Guid] <= 5)
                {
                    Logging.Write("Mob {0} has evaded {1} times.  Keeping an eye on {2:X0} for now!", unit.Name,
                                  MobsThatEvaded[unit.Guid], unit.Guid);
                }
                else
                {
                    const int secondsToBlacklist = 10;

                    if (Blacklist.Contains(unit.Guid, BlacklistFlags.Combat))
                    {
                        Logging.Write(Colors.LightGoldenrodYellow,
                                      "Mob {0} has evaded {1} times. Previously blacklisted {2:X0} for {3} seconds!",
                                      unit.Name, MobsThatEvaded[unit.Guid], unit.Guid, secondsToBlacklist);
                    }
                    else
                    {
                        Logging.Write(Colors.LightGoldenrodYellow,
                                      "Mob {0} has evaded {1} times. Blacklisting {2:X0} for {3} seconds!", unit.Name,
                                      MobsThatEvaded[unit.Guid], unit.Guid, secondsToBlacklist);
                        Blacklist.Add(unit.Guid, BlacklistFlags.Combat, TimeSpan.FromSeconds(secondsToBlacklist));
                        if (!Blacklist.Contains(unit.Guid, BlacklistFlags.Combat))
                        {
                            Logging.Write(Colors.Pink, "error: blacklist does not contain entry for {0} so adding {1}",
                                          unit.Name, unit.Guid);
                        }
                    }

                    if (BotPoi.Current.Guid == unit.Guid)
                    {
                        Logging.Write("EvadeHandling: Current BotPOI type={0} is Evading, clearing now...",
                                      BotPoi.Current.Type);
                        BotPoi.Clear("Singular recognized Evade bugged mob");
                    }

                    if (StyxWoW.Me.CurrentTargetGuid == guid)
                    {
                        foreach (var target in Targeting.Instance.TargetList)
                        {
                            if (target.IsAlive && Classname.ValidUnit(target) &&
                                !Blacklist.Contains(target, BlacklistFlags.Combat))
                            {
                                Logging.Write(Colors.Pink, "Setting target to {0} to get off evade bugged mob!",
                                              target.Name);
                                target.Target();
                                return;
                            }
                        }

                        Logging.Write(Colors.Pink,
                                      "BotBase has 0 entries in Target list not blacklisted -- nothing else we can do at this point!");
                        // StyxWoW.Me.ClearTarget();
                    }
                }
            }

            /// line below was originally in Evade logic, but commenting to avoid Sleeps
            // StyxWoW.SleepForLagDuration();
        }
        /// <summary>
        ///  This behavior SHOULD be called at top of the combat behavior. This behavior won't let the rest of the combat behavior to be called
        /// if you don't have a target. Also it will find a proper target, if the current target is dead or you don't have a target and still in combat.
        /// Tank targeting is also dealed in this behavior.
        /// </summary>
        /// <returns></returns>
        public static Composite EnsureTarget()
        {
            return
                (new Decorator(
                     ret => !SingularSettings.DisableAllTargeting,
                     new PrioritySelector(

                         #region Switch from Current Target if a more important one exists!

                         new PrioritySelector(

                             #region Validate our CurrentTarget - ctx set to null if we need a new one, non-null if ok!

                             ctx =>
            {
                #region Tank Targeting
                // Handle tank targeting - only if in Combat, otherwise we'll choose based upon Targeting list
                if (TankManager.NeedTankTargeting && !SingularSettings.Instance.DisableTankTargetSwitching && Group.MeIsTank && StyxWoW.Me.Combat && TankManager.Instance.FirstUnit != null)
                {
                    if (Me.CurrentTarget != TankManager.Instance.FirstUnit)
                    {
                        if (TankManager.TargetingTimer.IsFinished)
                        {
                            Logger.Write(targetColor, "TankTarget: switching to first unit of TankTargeting");
                            return TankManager.Instance.FirstUnit;
                        }

                        if (!Unit.ValidUnit(Me.CurrentTarget, showReason: false))
                        {
                            Logger.Write(targetColor, "TankTarget: CurrentTarget invalid, switching to first unit of TankTargeting");
                            return TankManager.Instance.FirstUnit;
                        }
                    }

                    return Me.CurrentTarget;                   // pass our currenttarget to skip setting or switching
                }
                #endregion

                #region WORLD_PVP_FIRST_AND_FOREMOST
                if (SingularRoutine.CurrentWoWContext == WoWContext.Normal && SingularSettings.Instance.TargetWorldPvpRegardless)
                {
                    // if on an enemy player, stay there
                    if (Me.GotTarget() && Me.CurrentTarget.IsPlayer && Unit.ValidUnit(Me.CurrentTarget))
                    {
                        return Me.CurrentTarget;
                    }

                    // if attacked in last 15 seconds, go after them
                    if (EventHandlers.TimeSinceAttackedByEnemyPlayer.TotalSeconds < 15)
                    {
                        WoWUnit ganker = EventHandlers.AttackingEnemyPlayer;
                        if (Unit.ValidUnit(ganker))
                        {
                            if (!Me.GotTarget() || !Me.CurrentTarget.IsPlayer || !Unit.ValidUnit(Me.CurrentTarget))
                            {
                                if (ganker != Me.CurrentTarget)
                                {
                                    Logger.Write(targetColor, "Switching to Ganker: " + ganker.SafeName() + " who attacked us first!");
                                    Logger.WriteDebug("Setting BotPoi to Kill {0}", ganker.SafeName());
                                    BotPoi.Current = new BotPoi(ganker, PoiType.Kill);
                                }

                                return ganker;
                            }
                        }
                    }
                }
                #endregion

                #region TOTEM KILLER

                if (SingularRoutine.CurrentWoWContext == WoWContext.Normal && SingularSettings.Instance.TargetCurrentTargetTotems)
                {
                    if (Me.GotTarget() && !Me.CurrentTarget.IsPlayer && Unit.ValidUnit(Me.CurrentTarget))
                    {
                        if (Me.CurrentTarget.IsTotem)
                        {
                            if (Me.CurrentTarget.SummonedByUnit != null && !Me.CurrentTarget.SummonedByUnit.IsPlayer)
                            {
                                return Me.CurrentTarget;
                            }
                        }
                        else if ((DateTime.UtcNow - timePrevTotem).TotalSeconds > 15)
                        {
                            float range = Me.IsMelee() ? 15 : 39;
                            WoWUnit totem = ObjectManager.GetObjectsOfType <WoWUnit>(false, false)
                                            .FirstOrDefault(t => t.IsTotem && guidPrevTotem != t.Guid && t.SummonedByUnitGuid == Me.CurrentTargetGuid && Unit.ValidUnit(t) && t.SpellDistance() < range);
                            if (totem != null)
                            {
                                guidPrevTotem = totem.Guid;
                                timePrevTotem = DateTime.UtcNow;
                                Logger.Write(targetColor, "Switching to Totem: {0} set by {1}", totem.Name, totem.SummonedUnit.SafeName());
                                return totem;
                            }
                        }
                    }
                }

                #endregion

#if ALWAYS_SWITCH_TO_BOTPOI
                WoWUnit unit;
                // Check botpoi (our top priority.)  we switch to BotPoi if a kill type exists and not blacklisted
                // .. if blacklisted, clear the poi to give bot a chance to do something smarter
                // .. if we are already fighting it, we keep fighting it, end of story
                if (BotPoi.Current.Type == PoiType.Kill)
                {
                    if (BotPoi.Current.AsObject == null)
                    {
                        Logger.Write(targetColor, "BotPOI is (null) --- clearing");
                        BotPoi.Clear(string.Format("Singular: (null) object was target (possibly another components error)"));
                    }
                    else
                    {
                        unit = BotPoi.Current.AsObject.ToUnit();
                        if (unit != null && !unit.IsAlive)
                        {
                            Logger.WriteDiagnostic(targetColor, "BotPOI " + unit.SafeName() + " is dead --- clearing");
                            BotPoi.Clear(string.Format("Singular: {0} is dead", unit.SafeName()));
                        }
                        else if (!Unit.ValidUnit(unit, showReason: true))
                        {
                            Logger.Write(targetColor, "BotPOI " + unit.SafeName() + " not valid --- clearing");
                            BotPoi.Clear(string.Format("Singular: {0} invalid target", unit.SafeName()));
                        }
                        else
                        {
                            if (StyxWoW.Me.CurrentTargetGuid != unit.Guid)
                            {
                                Logger.Write(targetColor, "Switching to BotPoi: " + unit.SafeName() + "!");
                            }

                            return unit;
                        }
                    }
                }
#endif
                // Go below if current target is null or dead. We have other checks to deal with that
                if (!StyxWoW.Me.GotTarget() || StyxWoW.Me.CurrentTarget.IsDead)
                {
                    return null;
                }

                // target not aggroed yet or out of range? check for adds in melee pounding us
                if (!Me.IsInGroup() && Me.Combat && ((!StyxWoW.Me.CurrentTarget.Combat && !StyxWoW.Me.CurrentTarget.Aggro && !StyxWoW.Me.CurrentTarget.PetAggro) || StyxWoW.Me.SpellDistance() > 30 || !StyxWoW.Me.CurrentTarget.InLineOfSpellSight))
                {
                    // Look for agrroed mobs next. prioritize by IsPlayer, Relative Distance, then Health
                    var target = ObjectManager.GetObjectsOfType <WoWUnit>(false, false)
                                 .Where(
                        p => p.SpellDistance() < 10 &&
                        Unit.ValidUnit(p) &&
                        (p.Aggro || p.PetAggro) &&
                        p.InLineOfSpellSight
                        )
                                 // .OrderBy(u => CalcDistancePriority(u)).ThenBy(u => u.HealthPercent)
                                 .OrderBy(u => u.HealthPercent)
                                 .FirstOrDefault();

                    if (target != null && target.Guid != Me.CurrentTargetGuid)
                    {
                        // Return the closest one to us
                        Logger.Write(targetColor, "Switching to aggroed mob pounding on me " + target.SafeName() + "!");
                        return target;
                    }
                }

                // check if current target is owned by a player
                WoWUnit pOwner = Unit.GetPlayerParent(Me.CurrentTarget);
                if (pOwner != null)
                {
                    if (!Me.CurrentTarget.CanWeAttack())
                    {
                        Logger.Write(targetColor, "CurrentTarget " + Me.CurrentTarget.SafeName() + " is a non-attackable enemy player pet so clearing target!");
                        Blacklist.Add(Me.CurrentTargetGuid, BlacklistFlags.Pull | BlacklistFlags.Combat, TimeSpan.FromSeconds(60), "Unattackable Enemy Player Pet is CurrentTarget");
                        Me.ClearTarget();
                        return null;
                    }
                    else if (Unit.ValidUnit(pOwner) && !Blacklist.Contains(pOwner, BlacklistFlags.Combat))
                    {
                        Logger.Write(targetColor, "Current target owned by a player.  Switching to " + pOwner.SafeName() + "!");
                        if (BotPoi.Current.Type == PoiType.Kill && BotPoi.Current.Guid == Me.CurrentTarget.Guid)
                        {
                            BotPoi.Clear(string.Format("Singular detected {0} as Player Owned Pet", Me.CurrentTarget.SafeName()));
                        }

                        return pOwner;
                    }
                }

                // no valid BotPoi, so let's check Targeting.FirstUnit which is Bots #1 choice
#if IGNORE_TARGETING_UNLESS_SEARCHING_FOR_NEW_TARGET
#elif BOT_FIRSTUNIT_GETS_PRIORITY
                unit = Targeting.Instance.FirstUnit;
                if (unit != null && unit.IsAlive)
                {
                    if (Blacklist.Contains(unit.Guid, BlacklistFlags.Combat))
                    {
                        Logger.Write(targetColor, "Targeting.FirstUnit " + unit.SafeName() + " is blacklisted!");
                        if (unit == Me.CurrentTarget && (Me.CurrentTarget.Combat && Me.CurrentTarget.IsTargetingMeOrPet))
                        {
                            return unit;
                        }

                        return null;
                    }

                    if (StyxWoW.Me.CurrentTarget != unit)
                    {
                        Logger.Write(targetColor, "Current target is not Bots first choice.  Switching to " + unit.SafeName() + "!");
                    }

                    return unit;
                }
#else
                foreach (var unit in Targeting.Instance.TargetList)
                {
                    if (StyxWoW.Me.CurrentTargetGuid != unit.Guid && unit.IsAlive && !Blacklist.Contains(unit.Guid, BlacklistFlags.Combat))
                    {
                        Logger.Write(targetColor, "Bot has a higher priority target available.  Switching to " + unit.SafeName() + "!");
                        return unit;
                    }
                }
#endif
                // at this point, just check its okay to kill currenttarget
                if (Blacklist.Contains(StyxWoW.Me.CurrentTargetGuid, BlacklistFlags.Combat))
                {
                    Logger.Write(targetColor, "CurrentTarget " + Me.CurrentTarget.SafeName() + " blacklisted and not in combat with so clearing target!");
                    Me.ClearTarget();
                    return null;
                }

                // valid unit? keep it then
                if (Unit.ValidUnit(Me.CurrentTarget, showReason: true))
                {
                    return Me.CurrentTarget;
                }

                if (Me.CurrentTarget.IsPlayer && !Battlegrounds.IsInsideBattleground && Me.CurrentTarget.IsHostile && !Me.CurrentTarget.CanWeAttack())
                {
                    Logger.Write(targetColor, "CurrentTarget " + Me.CurrentTarget.SafeName() + " is a non-attackable enemy player so clearing target!");
                    Blacklist.Add(Me.CurrentTargetGuid, BlacklistFlags.Pull | BlacklistFlags.Combat, TimeSpan.FromSeconds(15), "Unattackable Enemy Player is CurrentTarget");
                    Me.ClearTarget();
                }

                // otherwise, let's get a new one
                Logger.WriteDebug(targetColor, "EnsureTarget: invalid target {0}, so forcing selection of a new one...", !Me.GotTarget() ? "(null)" : Me.CurrentTarget.SafeName());
                return null;
            },

                             #endregion

                             #region Target was selected -- change target if needed, or do nothing if already current target

                             new Decorator(
                                 ret => ret != null,
                                 new Sequence(
                                     CreateClearPendingCursorSpell(RunStatus.Success),
                                     new Decorator(
                                         req => ((WoWUnit)req).Guid != StyxWoW.Me.CurrentTargetGuid,
                                         new Sequence(
                                             new Action(ret => { if (SingularSettings.Debug)
                                                                 {
                                                                     Logger.WriteDebug(targetColor, "EnsureTarget: switching to target {0}", ((WoWUnit)ret).SafeName());
                                                                 }
                                                        }),
                                             new Action(ret => ((WoWUnit)ret).Target()),
                                             new WaitContinue(2, ret => StyxWoW.Me.GotTarget() && StyxWoW.Me.CurrentTarget == (WoWUnit)ret, new ActionAlwaysSucceed()),
                                             new Action(ret => TankManager.TargetingTimer.Reset())  // cheaper to just reset than to check if we need Tank Targeting
                                             )
                                         ),

                                     // fall through to spell priority at this point as we have our target and its valid
                                     new ActionAlwaysFail()
                                     )
                                 ),

                             #endregion

                             #endregion

                             #region Target Invalid (none or dead) - Find a New one if possible

                             new Decorator(
                                 ret => ret == null,
                                 new PrioritySelector(
                                     ctx =>
            {
                // If we have a RaF leader, then use its target.
                var rafLeader = RaFHelper.Leader;
                if (rafLeader != null && rafLeader.IsValid && !rafLeader.IsMe && rafLeader.Combat &&
                    rafLeader.GotTarget() && rafLeader.CurrentTarget.IsAlive && !Blacklist.Contains(rafLeader.CurrentTarget, BlacklistFlags.Combat))
                {
                    Logger.Write(targetColor, "Current target invalid. Switching to Tanks target " + rafLeader.CurrentTarget.SafeName() + "!");
                    return rafLeader.CurrentTarget;
                }

                /*
                 *                                      // if we have BotPoi then try it
                 *                                      if (SingularRoutine.CurrentWoWContext != WoWContext.Normal && BotPoi.Current.Type == PoiType.Kill)
                 *                                      {
                 *                                          var unit = BotPoi.Current.AsObject as WoWUnit;
                 *                                          if (unit == null)
                 *                                          {
                 *                                              Logger.Write(targetColor, "Current Kill POI invalid. Clearing POI!");
                 *                                              BotPoi.Clear("Singular detected null POI");
                 *                                          }
                 *                                          else if (!unit.IsAlive)
                 *                                          {
                 *                                              Logger.Write(targetColor, "Current Kill POI dead. Clearing POI " + unit.SafeName() + "!");
                 *                                              BotPoi.Clear("Singular detected Unit is dead");
                 *                                          }
                 *                                          else if (Blacklist.Contains(unit, BlacklistFlags.Combat))
                 *                                          {
                 *                                              Logger.Write(targetColor, "Current Kill POI is blacklisted. Clearing POI " + unit.SafeName() + "!");
                 *                                              BotPoi.Clear("Singular detected Unit is Blacklisted");
                 *                                          }
                 *                                          else
                 *                                          {
                 *                                              Logger.Write(targetColor, "Current target invalid. Switching to POI " + unit.SafeName() + "!");
                 *                                              return unit;
                 *                                          }
                 *                                      }
                 */
                // Look for agrroed mobs next. prioritize by IsPlayer, Relative Distance, then Health
                var target = Targeting.Instance.TargetList
                             .Where(
                    p => !Blacklist.Contains(p, BlacklistFlags.Combat) &&
                    Unit.ValidUnit(p)
                    // && p.DistanceSqr <= 40 * 40  // dont restrict check to 40 yds
                    && (p.Aggro || p.PetAggro || (p.Combat && p.GotTarget() && (p.IsTargetingMeOrPet || p.IsTargetingMyRaidMember))))
                             .OrderBy(u => u.IsPlayer)
                             .ThenBy(u => CalcDistancePriority(u))
                             .ThenBy(u => u.HealthPercent)
                             .FirstOrDefault();

                if (target != null)
                {
                    // Return the closest one to us
                    Logger.Write(targetColor, "Current target invalid. Switching to aggroed mob " + target.SafeName() + "!");
                    return target;
                }

                /*
                 *                                      // if we have BotPoi then try it
                 *                                      if (SingularRoutine.CurrentWoWContext == WoWContext.Normal && BotPoi.Current.Type == PoiType.Kill)
                 *                                      {
                 *                                          var unit = BotPoi.Current.AsObject as WoWUnit;
                 *                                          if (unit == null)
                 *                                          {
                 *                                              Logger.Write(targetColor, "Current Kill POI invalid. Clearing POI!");
                 *                                              BotPoi.Clear("Singular detected null POI");
                 *                                          }
                 *                                          else if (!unit.IsAlive)
                 *                                          {
                 *                                              Logger.Write(targetColor, "Current Kill POI dead. Clearing POI " + unit.SafeName() + "!");
                 *                                              BotPoi.Clear("Singular detected Unit is dead");
                 *                                          }
                 *                                          else if (Blacklist.Contains(unit, BlacklistFlags.Combat))
                 *                                          {
                 *                                              Logger.Write(targetColor, "Current Kill POI is blacklisted. Clearing POI " + unit.SafeName() + "!");
                 *                                              BotPoi.Clear("Singular detected Unit is Blacklisted");
                 *                                          }
                 *                                      }
                 */
                // now anything in the target list or a Player
                target = Targeting.Instance.TargetList
                         .Where(
                    p => !Blacklist.Contains(p, BlacklistFlags.Combat) &&
                    p.IsAlive
                    // && p.DistanceSqr <= 40 * 40 // don't restrict check to 40 yds
                    )
                         .OrderBy(u => u.IsPlayer)
                         .ThenBy(u => u.DistanceSqr)
                         .FirstOrDefault();

                if (target != null)
                {
                    // Return the closest one to us
                    Logger.Write(targetColor, "Current target invalid. Switching to TargetList mob " + target.SafeName() + "!");
                    return target;
                }

                /*
                 *                                  // Cache this query, since we'll be using it for 2 checks. No need to re-query it.
                 *                                  var agroMob =
                 *                                      ObjectManager.GetObjectsOfType<WoWUnit>(false, false)
                 *                                          .Where(p => !Blacklist.Contains(p, BlacklistFlags.Combat) && p.IsHostile && !p.IsDead
                 *                                                  && !p.Mounted && p.DistanceSqr <= 70 * 70 && p.IsPlayer && p.Combat && (p.IsTargetingMeOrPet || p.IsTargetingMyRaidMember))
                 *                                          .OrderBy(u => u.DistanceSqr)
                 *                                          .FirstOrDefault();
                 *
                 *                                  if (agroMob != null)
                 *                                  {
                 *                                      if (!agroMob.IsPet || agroMob.SummonedByUnit == null)
                 *                                      {
                 *                                          Logger.Write(targetColor, "Current target invalid. Switching to player attacking us " + agroMob.SafeName() + "!");
                 *                                      }
                 *                                      else
                 *                                      {
                 *                                          Logger.Write(targetColor, "Current target invalid. Enemy player pet {0} attacking us, switching to player {1}!", agroMob.SafeName(), agroMob.SummonedByUnit.SafeName());
                 *                                          agroMob = agroMob.SummonedByUnit;
                 *                                      }
                 *
                 *                                      return agroMob;
                 *                                  }
                 */
                // Look for agrroed mobs not in targetlist for some reason next. prioritize by IsPlayer, Relative Distance, then Health
                target = Unit.UnfriendlyUnits()
                         .Where(
                    p => !Blacklist.Contains(p, BlacklistFlags.Combat) &&
                    Unit.ValidUnit(p)
                    // && p.DistanceSqr <= 40 * 40  // dont restrict check to 40 yds
                    && (p.Aggro || p.PetAggro || (p.Combat && p.GotTarget() && (p.IsTargetingMeOrPet || p.IsTargetingMyRaidMember))))
                         .OrderBy(u => u.IsPlayer)
                         .ThenBy(u => CalcDistancePriority(u))
                         .ThenBy(u => u.HealthPercent)
                         .FirstOrDefault();

                if (target != null)
                {
                    // Return the closest one to us
                    Logger.Write(targetColor, "Current target invalid. Switching to Unfriendly mob " + target.SafeName() + " attacking us!");
                    return target;
                }

                // And there's nothing left, so just return null, kthx.
                // ... but show a message about botbase still calling our Combat behavior with nothing to kill
                if (DateTime.UtcNow >= _timeNextInvalidTargetMessage)
                {
                    _timeNextInvalidTargetMessage = DateTime.UtcNow + TimeSpan.FromSeconds(5);
                    Logger.Write(targetColor, "Bot TargetList is empty, no targets available");
                }

                return null;
            },

                                     // Make sure the target is VALID. If not, then ignore this next part. (Resolves some silly issues!)
                                     new Decorator(
                                         ret => ret != null && ((WoWUnit)ret).Guid != StyxWoW.Me.CurrentTargetGuid,
                                         new Sequence(
                                             CreateClearPendingCursorSpell(RunStatus.Success),
                                             new Action(ret => Logger.WriteDebug(targetColor, "EnsureTarget: set target to chosen target {0}", ((WoWUnit)ret).SafeName())),
                                             new Action(ret => ((WoWUnit)ret).Target()),
                                             new WaitContinue(2, ret => StyxWoW.Me.GotTarget() && StyxWoW.Me.CurrentTargetGuid == ((WoWUnit)ret).Guid, new ActionAlwaysSucceed())
                                             )
                                         ),

                                     // fall through... we'll catch whether we targeted or not in next check
                                     new ActionAlwaysFail()
                                     )
                                 )
                             ),

                         #endregion
                         new Decorator(
                             req => !Me.GotTarget() || !Unit.ValidUnit(Me.CurrentTarget),
                             new Action(r =>
            {
                if (_lastTargetMessageGuid != Me.CurrentTargetGuid || _nextTargetMessageTimer.IsFinished)
                {
                    Logger.Write(targetColor, "EnsureTarget: no valid target set by " + SingularRoutine.GetBotName() + " -- skipping " + Dynamics.CompositeBuilder.CurrentBehaviorType.ToString() + " spell priority");
                    _nextTargetMessageTimer.Reset();
                }

                _lastTargetMessageGuid = Me.CurrentTargetGuid;
                return RunStatus.Success;
            })
                             )

                         )
                     ));
        }
        private Composite SubBehavior_CombatWithViableMob()
        {
            return(new PrioritySelector(context => SelectedTarget = Me.CurrentTarget,
                                        // Recall pet, if necessary...
                                        new Decorator(context => (SelectedTarget.HealthPercent < RecallPetAtMobPercentHealth) &&
                                                      (Me.GotAlivePet && Me.Pet.GotTarget),
                                                      new ActionFail(context =>
            {
                QBCLog.Info("Recalling Pet from '{0}' (health: {1:F1})",
                            SelectedTarget.SafeName, SelectedTarget.HealthPercent);
                PetControl.SetStance_Passive();
                PetControl.Follow();
            })),

                                        // If we are beyond the max range allowed to use the item, move within range...
                                        new Decorator(context => SelectedTarget.Distance > MaxRangeToUseItem,
                                                      new ActionRunCoroutine(
                                                          interactUnitContext => UtilityCoroutine.MoveTo(
                                                              SelectedTarget.Location,
                                                              string.Format("within {0} feet of {1}", MaxRangeToUseItem, SelectedTarget.SafeName),
                                                              MovementBy,
                                                              (float)MaxRangeToUseItem))),

                                        // If time to use the item, do so...
                                        new Decorator(context => IsUseItemNeeded(SelectedTarget),
                                                      new PrioritySelector(
                                                          new ActionRunCoroutine(context => CommonCoroutines.StopMoving()),

                                                          // Halt combat until we are able to use the item...
                                                          new Decorator(context => ((UseItemStrategy == UseItemStrategyType.UseItemContinuouslyOnTargetDontDefend) ||
                                                                                    (UseItemStrategy == UseItemStrategyType.UseItemOncePerTargetDontDefend)),
                                                                        new ActionFail(context =>
            {
                // We use LUA to stop casting, since SpellManager.StopCasting() doesn't seem to work...
                if (Me.IsCasting)
                {
                    Lua.DoString("SpellStopCasting()");
                }

                if (Me.IsAutoAttacking)
                {
                    Lua.DoString("StopAttack()");
                }

                TreeRoot.StatusText = string.Format("Combat halted--waiting for {0} to become usable.",
                                                    Utility.GetItemNameFromId(ItemId));
            })),

                                                          new Sequence(
                                                              new ActionRunCoroutine(ctx =>
                                                                                     UtilityCoroutine.UseItemOnTarget(
                                                                                         ItemId,
                                                                                         SelectedTarget,
                                                                                         () => BehaviorDone(string.Format("Terminating behavior due to missing {0}",
                                                                                                                          Utility.GetItemNameFromId(ItemId))))),
                                                              // Allow a brief time for WoWclient to apply aura to mob...
                                                              new WaitContinue(TimeSpan.FromMilliseconds(5000),
                                                                               context => ItemUseAlwaysSucceeds || SelectedTarget.HasAura(ItemAppliesAuraId),
                                                                               new ActionAlwaysSucceed()),
                                                              new ActionFail(context =>
            {
                _waitTimerAfterUsingItem.Reset();

                if (ItemUseAlwaysSucceeds || SelectedTarget.HasAura(ItemAppliesAuraId))
                {
                    // Count our success if no associated quest...
                    if (!VariantQuestIds.Any())
                    {
                        ++Counter;
                    }

                    // If we can only use the item once per target, blacklist this target from subsequent selection...
                    if ((UseItemStrategy == UseItemStrategyType.UseItemOncePerTarget) ||
                        (UseItemStrategy == UseItemStrategyType.UseItemOncePerTargetDontDefend))
                    {
                        SelectedTarget.BlacklistForInteracting(TimeSpan.FromSeconds(InteractBlacklistTimeInSeconds));
                    }

                    // If we can't defend ourselves from the target, blacklist it for combat and move on...
                    if (Query.IsViable(SelectedTarget) &&
                        ((UseItemStrategy == UseItemStrategyType.UseItemContinuouslyOnTargetDontDefend) ||
                         (UseItemStrategy == UseItemStrategyType.UseItemOncePerTargetDontDefend)))
                    {
                        SelectedTarget.BlacklistForCombat(TimeSpan.FromSeconds(InteractBlacklistTimeInSeconds));
                        BotPoi.Clear();
                        Me.ClearTarget();
                        SelectedTarget = null;
                    }
                }

                if ((ItemAppliesAuraId > 0) && !SelectedTarget.HasAura(ItemAppliesAuraId))
                {
                    var auraNamesOnMob = ((SelectedTarget.Auras.Keys.Count > 0)
                                                            ? string.Join(", ", SelectedTarget.Auras.Keys)
                                                            : "none");

                    QBCLog.Warning("{1} did not acquire expected AuraId, \"{2}\"--retrying.{0}"
                                   + "    Auras on {1}: {3}",
                                   Environment.NewLine,
                                   SelectedTarget.SafeName,
                                   Utility.GetSpellNameFromId(ItemAppliesAuraId),
                                   auraNamesOnMob);
                }
            }),

                                                              // Prevent combat, if we're not supposed to defend...
                                                              new Decorator(context => ((UseItemStrategy == UseItemStrategyType.UseItemContinuouslyOnTargetDontDefend) ||
                                                                                        (UseItemStrategy == UseItemStrategyType.UseItemOncePerTargetDontDefend)),
                                                                            new ActionAlwaysSucceed())
                                                              )))
                                        ));
        }
Beispiel #23
0
        public static async Task <bool> DoFishing()
        {
            if (AutoAnglerBot.Instance.Profile.FishAtHotspot && !Navigator.AtLocation(AutoAnglerBot.Instance.Profile.CurrentPoint))
            {
                return(false);
            }

            if (AutoAnglerSettings.Instance.Poolfishing &&
                BotPoi.Current.Type != PoiType.Harvest)
            {
                return(false);
            }

            if (await CheckLootFrame())
            {
                return(true);
            }

            // refresh water walking if needed
            if (!Me.Mounted && WaterWalking.CanCast &&
                !WaterWalking.IsActive &&
                await WaterWalking.Cast())
            {
                return(true);
            }

            if (AutoAnglerSettings.Instance.Poolfishing)
            {
                var pool = BotPoi.Current.AsObject as WoWGameObject;
                if (pool == null || !pool.IsValid)
                {
                    BotPoi.Clear();
                    return(false);
                }

                if (await MoveToPool(pool))
                {
                    return(true);
                }
            }

            if (await EquipPole())
            {
                return(true);
            }

            if (await EquipHat())
            {
                return(true);
            }

            if (await Applylure())
            {
                return(true);
            }

            if (await Applybait())
            {
                return(true);
            }

            if (!AutoAnglerSettings.Instance.Poolfishing &&
                AutoAnglerBot.Instance.ShouldFaceWaterNow)
            {
                AutoAnglerBot.Instance.ShouldFaceWaterNow = false;
                if (await FaceWater())
                {
                    return(true);
                }
            }

            if (Me.Mounted && await CommonCoroutines.Dismount("Fishing"))
            {
                return(true);
            }

            if (!await Coroutine.Wait(10000, () => !Me.IsFalling))
            {
                AutoAnglerBot.Log("Falling for 10 seconds; I don't think this will end good.");
                return(false);
            }

            if (Me.IsSwimming)
            {
                await JumpOnWaterSurface();
            }

            if (Me.IsMoving)
            {
                WoWMovement.MoveStop();
                if (!await Coroutine.Wait(4000, () => !Me.IsMoving))
                {
                    return(false);
                }
            }
            // Checks if we got a bite and recasts if needed.
            if (await CheckFishLine())
            {
                return(true);
            }

            return(false);
        }
Beispiel #24
0
        private static void HandleEvadeBuggedMob(LuaEventArgs args, CombatLogEventArgs e)
        {
            WoWUnit unit = e.DestUnit;
            WoWGuid guid = e.DestGuid;

            if (unit == null && StyxWoW.Me.GotTarget())
            {
                unit = StyxWoW.Me.CurrentTarget;
                guid = StyxWoW.Me.CurrentTargetGuid;
                Logger.Write("Evade: bugged mob guid:{0}, so assuming current target instead", args.Args[7]);
            }

            if (unit != null)
            {
                if (!MobsThatEvaded.ContainsKey(unit.Guid))
                {
                    MobsThatEvaded.Add(unit.Guid, 0);
                }

                MobsThatEvaded[unit.Guid] = MobsThatEvaded[unit.Guid] + 1;
                if (MobsThatEvaded[unit.Guid] < SingularSettings.Instance.EvadedAttacksAllowed)
                {
                    Logger.Write("Mob {0} has evaded {1} times. Not blacklisting yet, but will count evades on {2:X0} for now", unit.SafeName(), MobsThatEvaded[unit.Guid], unit.Guid);
                }
                else
                {
                    const int MinutesToBlacklist = 5;

                    if (Blacklist.Contains(unit.Guid, BlacklistFlags.Combat))
                    {
                        Logger.Write(Color.LightGoldenrodYellow, "Mob {0} has evaded {1} times. Previously blacklisted {2:X0} for {3} minutes!", unit.SafeName(), MobsThatEvaded[unit.Guid], unit.Guid, MinutesToBlacklist);
                    }
                    else
                    {
                        string fragment = string.Format("Mob {0} has evaded {1} times", unit.SafeName(), MobsThatEvaded[unit.Guid]);
                        Logger.Write(Color.LightGoldenrodYellow, "{0}. Blacklisting {1:X0} for {2} minutes!", fragment, unit.Guid, MinutesToBlacklist);
                        Blacklist.Add(unit.Guid, BlacklistFlags.Combat, TimeSpan.FromMinutes(MinutesToBlacklist), "Singular - " + fragment);
                        if (!Blacklist.Contains(unit.Guid, BlacklistFlags.Combat))
                        {
                            Logger.Write(Color.Pink, "error: blacklist does not contain entry for {0} after Blacklist.Add", unit.SafeName());
                        }
                    }

                    if (BotPoi.Current.Guid == unit.Guid)
                    {
                        Logger.Write("EvadeHandling: Current BotPOI type={0} is Evading, clearing now...", BotPoi.Current.Type);
                        BotPoi.Clear("Singular recognized Evade bugged mob");
                    }

                    if (StyxWoW.Me.CurrentTargetGuid == guid)
                    {
                        foreach (var target in Targeting.Instance.TargetList)
                        {
                            if (Unit.ValidUnit(target) &&
                                !Blacklist.Contains(target.Guid, BlacklistFlags.Pull | BlacklistFlags.Combat) &&
                                unit.EvadedAttacksCount() < SingularSettings.Instance.EvadedAttacksAllowed
                                )
                            {
                                Logger.Write(Color.Pink, "Setting target to {0} to get off evade bugged mob!", target.SafeName());
                                target.Target();
                                return;
                            }
                        }

                        Logger.Write(Color.Pink, "BotBase has 0 entries in Target list not blacklisted -- nothing else we can do at this point!");
                        // StyxWoW.Me.ClearTarget();
                    }
                }
            }

            /// line below was originally in Evade logic, but commenting to avoid Sleeps
            // StyxWoW.SleepForLagDuration();
        }
Beispiel #25
0
        private static WoWUnit SecondTarget()
        {
            // Check BotPoi first
            if (BotPoi.Current.Type == PoiType.Kill)
            {
                var unit = BotPoi.Current.AsObject as WoWUnit;
                if (unit == null)
                {
                    Helpers.Logger.PrintLog("Current BotPoi is null, clearing BotPoi");
                    BotPoi.Clear();
                }
                else if (!unit.IsAlive)
                {
                    Helpers.Logger.PrintLog("Current unit is dead, clearing BotPoi");
                    BotPoi.Clear();
                }
                else if (Blacklist.Contains(unit, BlacklistFlags.Combat))
                {
                    Helpers.Logger.PrintLog("Current unit is blacklisted, clearing BotPoi");
                    BotPoi.Clear();
                }
                else
                {
                    Helpers.Logger.PrintLog("Current unit invalid, clearing BotPoi");
                    return(unit);
                }
            }

            // Look for agrroed mobs next. prioritize by IsPlayer, Relative Distance, then Health
            var target = Targeting.Instance.TargetList
                         .Where(
                p => !Blacklist.Contains(p, BlacklistFlags.Combat) &&
                p.ValidAttackUnit() &&
                (p.Aggro || p.PetAggro || (p.Combat && p.GotTarget && (p.IsTargetingMeOrPet || p.IsTargetingMyRaidMember))))

                         // Check if there's a player there, maybe we're getting ganked
                         .OrderBy(u => u.IsPlayer)
                         // Then order then pick the closest and lowest health target
                         .ThenBy(u => u.Distance)
                         .ThenBy(u => u.HealthPercent)
                         .FirstOrDefault();

            if (target != null)
            {
                // Return the target we selected
                Helpers.Logger.PrintLog("Switching to a unit aggro'd to us");
                return(target);
            }

            // At this point, look for anything in the target list
            target = Targeting.Instance.TargetList
                     .Where(p => !Blacklist.Contains(p, BlacklistFlags.Combat) && p.IsAlive)
                     .OrderBy(u => u.IsPlayer)
                     .ThenBy(u => u.DistanceSqr)
                     .FirstOrDefault();

            if (target != null)
            {
                // Return the closest one to us
                //Helpers.Logger.PrintLog("Switching to unit in the target list");
                return(target);
            }

            return(null);
        }
        private static Composite CreatePullMorePull()
        {
            if (false == IsPullMoreActive)
                return new ActionAlwaysFail();

            _rangePullMore = Me.IsMelee() ? SingularSettings.Instance.PullMoreDistMelee : SingularSettings.Instance.PullMoreDistRanged;

            return new Decorator(
                req => HotkeyDirector.IsPullMoreEnabled
                    && (_allowPullMoreUntil == DateTime.MinValue || _allowPullMoreUntil > DateTime.UtcNow)
                    && !Spell.IsCastingOrChannelling(),

                new Sequence(

                    new PrioritySelector(

                        new Decorator(
                            req => SingularSettings.Instance.UsePullMore == PullMoreUsageType.Auto && SingularRoutine.IsQuestBotActive && !IsQuestProfileLoaded,
                            new ActionAlwaysFail()
                            ),

                        new Decorator(
                            req => !IsAllowed( CapabilityFlags.MultiMobPull),
                            new Action(r => {
                                // disable pull more until we leave combat
                                Logger.WriteDiagnostic(Color.White, "Pull More: CapabilityFlag.MultiMobPull set to Disallow, finishing these before pulling more");
                                _allowPullMoreUntil = DateTime.UtcNow;
                                })
                            ),

                        new Decorator(
                            req => Me.HealthPercent < SingularSettings.Instance.PullMoreMinHealth,
                            new Action(r => {
                                // disable pull more until we leave combat
                                Logger.WriteDiagnostic(Color.White, "Pull More: health dropped to {0:F1}%, finishing these before pulling more", Me.HealthPercent);
                                _allowPullMoreUntil = DateTime.UtcNow;
                                })
                            ),

                        new Decorator(
                            req => (Singular.Utilities.EventHandlers.TimeSinceAttackedByEnemyPlayer.TotalSeconds < 15),
                            new Action(r =>
                            {
                                Logger.WriteDiagnostic(Color.White, "Pull More: attacked by player {0:F1} seconds ago, disabling pull more until out of combat", Singular.Utilities.EventHandlers.TimeSinceAttackedByEnemyPlayer.TotalSeconds);
                                _allowPullMoreUntil = DateTime.UtcNow;
                            })
                            ),

                        new PrioritySelector(

                            ctx => Unit.UnitsInCombatWithUsOrOurStuff(45)
                                .FirstOrDefault(u => u.TappedByAllThreatLists || (u.Elite && (u.Level + 8) > Me.Level) || (u.MaxHealth > (Me.MaxHealth * 2))),

                            new Decorator(
                                req => req != null,
                                new Action(r =>
                                {
                                    if ((r as WoWUnit).TappedByAllThreatLists)
                                        Logger.WriteDiagnostic(Color.White, "Pull More: attacked by important quest mob {0} #{1}, disabling pull more until killed", (r as WoWUnit).SafeName(), (r as WoWUnit).Entry);
                                    else if ((r as WoWUnit).Elite)
                                        Logger.WriteDiagnostic(Color.White, "Pull More: attacking non-trivial Elite {0} #{1}, disabling pull more until killed", (r as WoWUnit).SafeName(), (r as WoWUnit).Entry);
                                    else
                                        Logger.WriteDiagnostic(Color.White, "Pull More: attacking non-trivial Mob {0} #{1} maxhealth {2}, disabling pull more until killed", (r as WoWUnit).SafeName(), (r as WoWUnit).Entry, (r as WoWUnit).MaxHealth);

                                    _allowPullMoreUntil = DateTime.UtcNow;
                                })
                                )
                            ),

                        new Sequence(
                            ctx => BotPoi.Current == null ? null : BotPoi.Current.AsObject,

                            new Action(r => {
                                _mobCountInCombat = Unit.UnitsInCombatWithUsOrOurStuff(50).Count();
                                if (_mobCountInCombat >= SingularSettings.Instance.PullMoreMobCount)
                                {
                                    Logger.WriteDiagnostic(Color.White, "Pull More: in combat with {0} mobs, finishing these before pulling more", _mobCountInCombat);
                                    _allowPullMoreUntil = DateTime.UtcNow;
                                }
                                else if ( r == null )
                                {

                                }
                                else if (BotPoi.Current.Type != PoiType.Kill)
                                {

                                }
                                else if ((r as WoWObject).ToUnit() == null)
                                {

                                }
                                else
                                {
                                    // cleared validations, move on to next state
                                    return RunStatus.Success;
                                }

                                return RunStatus.Failure;
                            }),

                            // check if still pulling
                            new DecoratorContinue(
                                req => {
                                    WoWUnit unit = (req as WoWUnit);
                                    return unit.IsAlive && (!unit.IsTagged || !unit.IsTargetingMyStuff() || !unit.Combat);
                                    },

                                new Sequence(
                                    // check if timed out
                                    new Decorator(
                                        req => DateTime.UtcNow > _timeoutPullMoreAt,
                                        new Action( r =>
                                            {
                                            WoWUnit unit = (r as WoWUnit);
                                            Logger.Write( LogColor.Hilite, "Pull More: could not pull {0} @ {1:F1} yds within {2} seconds, blacklisting",
                                                unit.SafeName(),
                                                unit.SpellDistance(),
                                                SingularSettings.Instance.PullMoreTimeOut
                                                );
                                            Blacklist.Add(unit.Guid, BlacklistFlags.Pull, TimeSpan.FromMinutes(5), "Singular: pull more timed out");
                                            BotPoi.Clear("Singular: pull more timed out");
                                            return RunStatus.Failure;
                                            })
                                        ),
                                    // otherwise fail since target not engaged yet
                                    new ThrottlePasses(
                                        1, TimeSpan.FromSeconds(1), RunStatus.Failure,
                                        new Action( r =>
                                            {
                                            WoWUnit unit = (r as WoWUnit);
                                            Logger.WriteDebug("Pull More: waiting since current KillPoi {0} not attacking me yet (target={1}, combat={2}, tagged={3})",
                                                unit.SafeName(),
                                                unit.GotTarget() ? unit.SafeName() : "(null)",
                                                unit.Combat.ToYN(),
                                                unit.IsTagged.ToYN()
                                                );
                                            return RunStatus.Failure;
                                            })
                                        )
                                    )
                                ),

                            // now pull more
                            new ThrottlePasses(
                                1, TimeSpan.FromSeconds(1), RunStatus.Failure,
                                new Action( r => {
                                    WoWUnit unit = (r as WoWUnit);
                                    _timeoutPullMoreAt = DateTime.MaxValue;
                                    Func<WoWUnit, bool> whereClause = PullMoreTargetSelectionDelegate();

                                    // build list of location of mobs to avoid
                                    List<WoWPoint> mobToAvoid = Unit.UnfriendlyUnits()
                                        .Where( u => u.IsHostile
                                            && u.IsAlive
                                            && (
                                                (u.Elite && u.Level+8 > Me.Level)
                                                || (u.MaxHealth > Me.MaxHealth * 2)
                                                || (ProfileManager.CurrentProfile != null && ProfileManager.CurrentProfile.AvoidMobs != null && ProfileManager.CurrentProfile.AvoidMobs.Contains(u.Entry))
                                                )
                                            && u.DistanceSqr < 70 * 70)
                                        .Select( u => u.Location)
                                        .ToList();

                                    WoWUnit nextPull = Unit.UnfriendlyUnits()
                                        .Where(
                                            t => !t.IsPlayer
                                                && !t.IsPet
                                                && !t.IsPetBattleCritter
                                                && !t.IsTagged
                                                && (!t.Combat || (t.GotTarget() && !t.CurrentTarget.IsPlayer && !t.CurrentTarget.IsPet))
                                                && !Blacklist.Contains(t, BlacklistFlags.Pull | BlacklistFlags.Combat)
                                                && Unit.ValidUnit(t)
                                                && t.Level <= (Me.Level + 2)
                                                && (whereClause(t) || Targeting.Instance.TargetList.Any(u => u.Guid == t.Guid))
                                                && (ProfileManager.CurrentProfile == null || ProfileManager.CurrentProfile.AvoidMobs == null || !ProfileManager.CurrentProfile.AvoidMobs.Contains(t.Entry))
                                                && t.SpellDistance() <= _rangePullMore
                                                && !mobToAvoid.Any( loc => loc.DistanceSqr(t.Location) < 40)
                                            )
                                        .OrderBy(k => (long)k.DistanceSqr)
                                        .FirstOrDefault();

                                    // set target at botpoi
                                    if (nextPull != null && unit.Guid != nextPull.Guid)
                                    {

                                        Logger.WriteDebug("Pull More: more adds allowed since current KillPoi {0}, target={1}, combat={2}, tagged={3}",
                                            unit.SafeName(),
                                            unit.GotTarget() ? unit.SafeName() : "(null)",
                                            unit.Combat.ToYN(),
                                            unit.IsTagged.ToYN()
                                            );

                                        Logger.Write( LogColor.Hilite, "Pull More: pulling {0} #{1} - {2} @ {3:F1} yds", _PullMoreTargetFindType, _mobCountInCombat + 1, nextPull.SafeName(), nextPull.SpellDistance());
                                        BotPoi poi = new BotPoi(nextPull, PoiType.Kill, NavType.Run);
                                        Logger.WriteDebug("Setting BotPoi to Kill {0}", nextPull.SafeName());
                                        Styx.CommonBot.POI.BotPoi.Current = poi;
                                        if (Styx.CommonBot.POI.BotPoi.Current.Guid != poi.Guid)
                                            Logger.WriteDiagnostic(Color.White, "Pull More: ERROR, could not set POI: Current: {0}, Wanted: {1}", Styx.CommonBot.POI.BotPoi.Current, poi);
                                        else
                                        {
                                            nextPull.Target();
                                            _timeoutPullMoreAt = DateTime.UtcNow + TimeSpan.FromSeconds(SingularSettings.Instance.PullMoreTimeOut);
                                            if (_allowPullMoreUntil == DateTime.MinValue)
                                                _allowPullMoreUntil = DateTime.UtcNow + TimeSpan.FromSeconds(SingularSettings.Instance.PullMoreMaxTime);

                                            if (Me.Pet != null && (Me.Pet.CurrentTarget == null || Me.Pet.CurrentTargetGuid != Me.Guid))
                                            {
                                                PetManager.Attack(nextPull);
                                            }
                                        }
                                    }

                                    return RunStatus.Failure;
                                })
                            )
                        )
                    ),

                    new ActionAlwaysFail()
                    )
                );
        }
        internal static Composite TargetingPulse()
        {
            return(new Decorator(ret => AdvancedAI.Movement,
                                 new PrioritySelector(ctx =>
            {
                // If we have a RaF leader, then use its target.
                var rafLeader = RaFHelper.Leader;

                if (rafLeader != null && rafLeader.IsValid && !rafLeader.IsMe && rafLeader.Combat && rafLeader.CurrentTarget != null &&
                    rafLeader.CurrentTarget.IsAlive && !Blacklist.Contains(rafLeader.CurrentTarget, BlacklistFlags.Combat))
                {
                    Logging.Write(targetColor, "Current target invalid. Switching to Tanks target " + rafLeader.CurrentTarget.SafeName() + "!");
                    return rafLeader.CurrentTarget;
                }

                // if we have BotPoi then try it
                if (AdvancedAI.CurrentWoWContext != WoWContext.Normal && BotPoi.Current.Type == PoiType.Kill)
                {
                    var unit = BotPoi.Current.AsObject as WoWUnit;
                    if (unit == null)
                    {
                        Logging.Write(targetColor, "Current Kill POI invalid. Clearing POI!");
                        BotPoi.Clear("AdvancedAI detected null POI");
                    }
                    else if (!unit.IsAlive)
                    {
                        Logging.Write(targetColor, "Current Kill POI dead. Clearing POI " + unit.SafeName() + "!");
                        BotPoi.Clear("AdvancedAI detected Unit is dead");
                    }
                    else if (Blacklist.Contains(unit, BlacklistFlags.Combat))
                    {
                        Logging.Write(targetColor, "Current Kill POI is blacklisted. Clearing POI " + unit.SafeName() + "!");
                        BotPoi.Clear("AdvancedAI detected Unit is Blacklisted");
                    }
                    else
                    {
                        Logging.Write(targetColor, "Current target invalid. Switching to POI " + unit.SafeName() + "!");
                        return unit;
                    }
                }

                // Look for agrroed mobs next. prioritize by IsPlayer, Relative Distance, then Health
                var target = Targeting.Instance.TargetList.Where(p => !Blacklist.Contains(p, BlacklistFlags.Combat) && Unit.ValidUnit(p) &&
                                                                 (p.Aggro || p.PetAggro || (p.Combat && p.GotTarget && (p.IsTargetingMeOrPet || p.IsTargetingMyRaidMember))))
                             .OrderBy(u => u.IsPlayer)
                             .ThenBy(CalcDistancePriority)
                             .ThenBy(u => u.HealthPercent)
                             .FirstOrDefault();

                if (target != null)
                {
                    // Return the closest one to us
                    Logging.Write(targetColor, "Current target invalid. Switching to aggroed mob " + target.SafeName() + "!");
                    return target;
                }

                // if we have BotPoi then try it
                if (AdvancedAI.CurrentWoWContext == WoWContext.Normal && BotPoi.Current.Type == PoiType.Kill)
                {
                    var unit = BotPoi.Current.AsObject as WoWUnit;

                    if (unit == null)
                    {
                        Logging.Write(targetColor, "Current Kill POI invalid. Clearing POI!");
                        BotPoi.Clear("AdvancedAI detected null POI");
                    }
                    else if (!unit.IsAlive)
                    {
                        Logging.Write(targetColor, "Current Kill POI dead. Clearing POI " + unit.SafeName() + "!");
                        BotPoi.Clear("AdvancedAI detected Unit is dead");
                    }
                    else if (Blacklist.Contains(unit, BlacklistFlags.Combat))
                    {
                        Logging.Write(targetColor, "Current Kill POI is blacklisted. Clearing POI " + unit.SafeName() + "!");
                        BotPoi.Clear("AdvancedAI detected Unit is Blacklisted");
                    }
                    else
                    {
                        Logging.Write(targetColor, "Current target invalid. Switching to POI " + unit.SafeName() + "!");
                        return unit;
                    }
                }

                // now anything in the target list or a Player
                target = Targeting.Instance.TargetList.Where(p => !Blacklist.Contains(p, BlacklistFlags.Combat) && p.IsAlive)
                         .OrderBy(u => u.IsPlayer)
                         .ThenBy(u => u.DistanceSqr)
                         .FirstOrDefault();

                if (target != null)
                {
                    // Return the closest one to us
                    Logging.Write(targetColor, "Current target invalid. Switching to TargetList mob " + target.SafeName() + "!");
                    return target;
                }

                #region Commented
                //// Cache this query, since we'll be using it for 2 checks. No need to re-query it.
                //var agroMob =
                //    ObjectManager.GetObjectsOfType<WoWUnit>(false, false)
                //        .Where(p => !Blacklist.Contains(p, BlacklistFlags.Combat) && p.IsHostile && !p.IsDead
                //                && !p.Mounted && p.DistanceSqr <= 70 * 70 && p.IsPlayer && p.Combat && (p.IsTargetingMeOrPet || p.IsTargetingMyRaidMember))
                //        .OrderBy(u => u.DistanceSqr)
                //        .FirstOrDefault();

                //if (agroMob != null)
                //{
                //    if (!agroMob.IsPet || agroMob.SummonedByUnit == null)
                //    {
                //        Logger.Write(targetColor, "Current target invalid. Switching to player attacking us " + agroMob.SafeName() + "!");
                //    }
                //    else
                //    {
                //        Logger.Write(targetColor, "Current target invalid. Enemy player pet {0} attacking us, switching to player {1}!", agroMob.SafeName(), agroMob.SummonedByUnit.SafeName());
                //        agroMob = agroMob.SummonedByUnit;
                //    }

                //    return agroMob;
                //}
                #endregion

                // And there's nothing left, so just return null, kthx.
                // ... but show a message about botbase still calling our Combat behavior with nothing to kill
                if (DateTime.Now >= _timeNextInvalidTargetMessage)
                {
                    _timeNextInvalidTargetMessage = DateTime.Now + TimeSpan.FromSeconds(1);
                    Logging.Write(targetColor, "Bot TargetList is empty, no targets available");
                }
                return null;
            },

                                                      // Make sure the target is VALID. If not, then ignore this next part. (Resolves some silly issues!)
                                                      new Decorator(ret => ret != null && ((WoWUnit)ret).Guid != StyxWoW.Me.CurrentTargetGuid,
                                                                    new Sequence(
                                                                        CreateClearPendingCursorSpell(RunStatus.Success),
                                                                        new Action(ret =>
                                                                                   Logging.WriteDiagnostic(targetColor, "EnsureTarget: set target to chosen target {0}", ((WoWUnit)ret).SafeName())),
                                                                        new Action(ret => ((WoWUnit)ret).Target()),
                                                                        new WaitContinue(2, ret => StyxWoW.Me.CurrentTarget != null && StyxWoW.Me.CurrentTargetGuid == ((WoWUnit)ret).Guid,
                                                                                         new ActionAlwaysSucceed()))),
                                                      // looks like no success, so don't continue to spell priorities
                                                      new Decorator(ret => !Me.GotTarget || Me.CurrentTarget.IsDead,
                                                                    new ActionAlwaysSucceed()),
                                                      // otherwise, we are here if current target is valid or we set a good one, either way... fall through
                                                      new ActionAlwaysFail())));
        }
Beispiel #28
0
 public static void RepairFly()
 {
     if (Flightor.MountHelper.CanMount && !_iGotThis)
     {
         _iGotThis = true;
         _currentPOI = BotPoi.Current;
         BotPoi.Clear();
         _oldLoc = _me.Location;
         Log("Vendor/repair run discovered, attempting to fly");
         var _safeSpot = findSafeFlightPoint(_currentPOI.Location);
         if (_safeSpot.Equals(_currentPOI.Location))
         {
             flyTo(_currentPOI.Location);
         }
         else { performSafeFlight(_safeSpot, _currentPOI.Location); }
         _currentPOI.AsObject.Interact();
         StyxWoW.SleepForLagDuration();
         Thread.Sleep(1000);
         Vendors.RepairAllItems();
         Thread.Sleep(1000);
         Vendors.SellAllItems();
         Thread.Sleep(1000);
         Log("Vendor visited, flying back!");
         var _safeSpotBack = findSafeFlightPoint(_oldLoc);
         if (_safeSpotBack.Equals(_oldLoc))
         {
             flyTo(_oldLoc);
         }
         else { performSafeFlight(_safeSpotBack, _oldLoc); }
         Log("Back where we started (hopefully), thank you for flying with Crafty Airlines!");
         _iGotThis = false;
     }
 }
Beispiel #29
0
        private async Task <bool> MainCoroutine()
        {
            // break if we are done or we are not in combat and targting is not empty, we want the botbase to clear path for us.
            if (IsDone || (!Me.Combat && Targeting.Instance.FirstUnit != null) || !Me.IsAlive)
            {
                return(false);
            }

            if (!Query.IsViable(SelectedNpc))
            {
                SelectedNpc = GetNpc();
            }

            if (!Query.IsViable(SelectedNpc) || !Me.IsActuallyInCombat && Targeting.Instance.FirstUnit == null)
            {
                // move to search area
                if (SearchLocation != Vector3.Zero && !Navigator.AtLocation(SearchLocation))
                {
                    await UtilityCoroutine.MoveTo(SearchLocation, "Search Area", MovementBy);
                }
                // Dismount after reaching search location.
                else if ((SearchLocation == Vector3.Zero || Navigator.AtLocation(SearchLocation)) && Me.Mounted)
                {
                    await UtilityCoroutine.ExecuteMountStrategy(MountStrategyType.Dismount);
                }
                else
                {
                    TreeRoot.StatusText = "Waiting for NPC to spawn";
                }
                return(true);
            }

            if (SelectedNpc.IsDead && SelectedNpc.TaggedByMe && !VariantQuestIds.Any())
            {
                BehaviorDone();
                return(true);
            }

            if (SelectedNpc.HasAura(ImmunityAuraId))
            {
                if (BotPoi.Current.AsObject == SelectedNpc)
                {
                    BotPoi.Clear("Mob is immune");
                }

                var targetedMob = Targeting.Instance.FirstUnit;
                if (targetedMob != null && ImmunityBreakingMobIds.Contains((int)targetedMob.Entry))
                {
                    if (targetedMob.IsTargetingMeOrPet)
                    {
                        // move close enough to shielded NPC so that the exploding mobs will hit it when killed.
                        var myMinDistance = Math.Max(2, MaxRange - targetedMob.MeleeRange);
                        if (SelectedNpc.DistanceSqr > myMinDistance * myMinDistance)
                        {
                            TreeRoot.StatusText = string.Format("Moving closer to {0} before killing {1}", SelectedNpc.SafeName, targetedMob.SafeName);
                            Navigator.MoveTo(SelectedNpc.Location);
                            return(true);
                        }
                        // wait for exploding mob to get within range of shielded mob.
                        if (targetedMob.Location.DistanceSquared(SelectedNpc.Location) > MaxRange * MaxRange)
                        {
                            TreeRoot.StatusText = string.Format(
                                "Waiting for {0} to move withing range of {1}",
                                targetedMob.SafeName,
                                SelectedNpc.SafeName);
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
Beispiel #30
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;
            }
        }