public override void Initialize() { //Caching current class here to avoid issues with loading screens where Class return None and we cant build behaviors _myClass = Me.Class; Logger.Write("Starting Singular v" + Assembly.GetExecutingAssembly().GetName().Version); Logger.Write("Determining talent spec."); try { TalentManager.Update(); } catch (Exception e) { StopBot(e.ToString()); } Logger.Write("Current spec is " + TalentManager.CurrentSpec.ToString().CamelToSpaced()); if (!CreateBehaviors()) { return; } Logger.Write("Behaviors created!"); // When we actually need to use it, we will. EventHandlers.Init(); MountManager.Init(); //Logger.Write("Combat log event handler started."); }
public override void Initialize() { Logger.Write("Starting Singular v" + Assembly.GetExecutingAssembly().GetName().Version); // save some support info in case we need Logger.WriteFile("{0:F1} days since Windows was restarted", TimeSpan.FromMilliseconds(Environment.TickCount).TotalHours / 24.0); Logger.WriteFile("{0} FPS currently in WOW", GetFPS()); Logger.WriteFile("{0} ms of Latency in WOW", StyxWoW.WoWClient.Latency); Logger.Write("Determining talent spec."); try { TalentManager.Update(); } catch (Exception e) { StopBot(e.ToString()); } Logger.Write("Current spec is " + TalentManager.CurrentSpec.ToString().CamelToSpaced()); // Update the current WoWContext, and fire an event for the change. UpdateContext(); // NOTE: Hook these events AFTER the context update. OnWoWContextChanged += (orig, ne) => { Logger.Write(Color.LightGreen, "Context changed, re-creating behaviors"); RebuildBehaviors(); }; RoutineManager.Reloaded += (s, e) => { Logger.Write("Routines were reloaded, re-creating behaviors"); RebuildBehaviors(); }; // create silently since will creating again right after this if (!RebuildBehaviors(true)) { return; } Logger.WriteDebug("Verified behaviors can be created!"); // When we actually need to use it, we will. EventHandlers.Init(); MountManager.Init(); //Logger.Write("Combat log event handler started."); // create silently since Start button will create a context change (at least first Start) // .. which will build behaviors again Instance.RebuildBehaviors(true); Logger.WriteDebug("Behaviors created!"); Logger.Write("Initialization complete!"); }
public Composite CreateArcaneMageCombat() { return(new PrioritySelector( CreateEnsureTarget(), //Move away from frozen targets new Decorator( ret => Me.CurrentTarget.HasAura("Frost Nova") && Me.CurrentTarget.DistanceSqr < 5 * 5, new Action( ret => { Logger.Write("Getting away from frozen target"); WoWPoint moveTo = WoWMathHelper.CalculatePointFrom(Me.Location, Me.CurrentTarget.Location, 10f); if (Navigator.CanNavigateFully(Me.Location, moveTo)) { Navigator.MoveTo(moveTo); } })), CreateMoveToAndFace(34f, ret => Me.CurrentTarget), CreateSpellBuffOnSelf("Ice Block", ret => Me.HealthPercent < 10 && !Me.ActiveAuras.ContainsKey("Hypothermia")), new Decorator(ret => Me.ActiveAuras.ContainsKey("Ice Block"), new ActionIdle()), CreateSpellBuff("Frost Nova", ret => NearbyUnfriendlyUnits.Any(u => u.DistanceSqr <= 8 * 8)), CreateWaitForCast(true), CreateSpellCast("Evocation", ret => Me.ManaPercent < 20), new Decorator(ret => HaveManaGem() && Me.ManaPercent <= 30, new Action(ctx => UseManaGem())), CreateMagePolymorphOnAddBehavior(), CreateSpellCast("Counterspell", ret => Me.CurrentTarget.IsCasting), CreateSpellCast("Mirror Image", ret => Me.CurrentTarget.HealthPercent > 20), CreateSpellCast("Time Warp", ret => Me.CurrentTarget.HealthPercent > 20), new Decorator( ret => Me.CurrentTarget.HealthPercent > 50, new Sequence( new Action(ctx => Me.CurrentTarget.Face()), new Action(ctx => StyxWoW.SleepForLagDuration()), new PrioritySelector(CreateSpellCast("Flame Orb")) )), CreateSpellBuffOnSelf("Mana Shield", ret => !Me.Auras.ContainsKey("Mana Shield") && Me.HealthPercent <= 75), CreateSpellCast("Slow", ret => TalentManager.GetCount(1, 18) < 2 && !Me.CurrentTarget.ActiveAuras.ContainsKey("Slow") && Me.CurrentTarget.Distance > 5), CreateSpellCast("Arcane Missiles", ret => Me.ActiveAuras.ContainsKey("Arcane Missiles!") && Me.ActiveAuras.ContainsKey("Arcane Blast") && Me.ActiveAuras["Arcane Blast"].StackCount >= 2), CreateSpellCast("Arcane Barrage", ret => Me.ActiveAuras.ContainsKey("Arcane Blast") && Me.ActiveAuras["Arcane Blast"].StackCount >= 3), CreateSpellBuffOnSelf("Presence of Mind"), CreateSpellCast("Arcane Blast"), CreateFireRangedWeapon() )); }
public Composite CreateProtectionWarriorCombat() { NeedTankTargeting = true; return (new PrioritySelector( CreateEnsureTarget(), // Note: this will make sure we charge at any unit within proper range. (Like an actual tank would) // We can cast Charge while in combat if we have the talent. [Notice that I am NOT checking for the talent!] // chargeSpell.CanCast should return false if we can't cast it. CreateSpellCast("Charge", ret => Me.CurrentTarget.Distance.Between(8f, TalentManager.HasGlyph("Long Charge") ? 30f : 25f)), CreateSpellCast("Intercept", ret => Me.CurrentTarget.Distance.Between(8f, 25f)), CreateMoveToAndFace(5f, ret => Me.CurrentTarget), CreateAutoAttack(true), CreateSpellCast("Heroic Strike", ret => Me.CurrentRage >= 60), CreateSpellCast("Revenge"), // If we have Blood and Thunder talented, then try and apply Rend via tclap. (This will apply rend to all targets!) CreateSpellCast( "Thunder Clap", ret => NearbyUnfriendlyUnits.Any(u => HasAuraStacks("Rend", 1, u)) && TalentManager.GetCount(3, 3) != 0), CreateSpellBuff("Rend"), // To be honest, we should be throwing this whenever its off CD. But we'll use it for the 20% hit speed debuff for now. CreateSpellCast("Thunder Clap"), new Decorator( ret => NearbyUnfriendlyUnits.Count(u => u.Distance < 6) > 2, new PrioritySelector( CreateSpellCast("War Stomp"), CreateSpellCast("Thunder Clap"), CreateSpellCast("Shockwave"), CreateSpellCast("Shield Block") )), CreateSpellCast("Victory Rush"), CreateSpellCast("Arcane Torrent", ret => Me.CurrentTarget.IsCasting), CreateSpellCast("Shield Bash", ret => Me.CurrentTarget.IsCasting), CreateSpellCast("Shield Slam"), CreateSpellBuff("Demoralizing Shout", ret => Me.CurrentRage > 30 && Me.CurrentTarget.HealthPercent > 30), // Get sunders up, Devastate if we have it (extra damage) or just plain Sunder. new Decorator( ret => !Me.CurrentTarget.HasAura("Sunder Armor") || Me.CurrentTarget.Auras["Sunder Armor"].StackCount < 3, new PrioritySelector( CreateSpellCast("Devastate"), CreateSpellCast("Sunder Armor"))) )); }
public Composite CreateAfflictionCombat() { WantedPet = "Succubus"; return(new PrioritySelector( CreateEnsureTarget(), //CreateLosAndFace(ret => Me.CurrentTarget), CreateMoveToAndFace(35f, ret => Me.CurrentTarget), CreateWaitForCast(), CreateAutoAttack(true), // Emergencies new Decorator( ret => Me.HealthPercent < 20, new PrioritySelector( //CreateSpellBuff("Fear", ret => !Me.CurrentTarget.HasAura("Fear")), CreateSpellCast("Howl of Terror", ret => Me.CurrentTarget.Distance < 10 && Me.CurrentTarget.IsPlayer), CreateSpellCast("Death Coil", ret => !Me.CurrentTarget.HasAura("Howl of Terror") && !Me.CurrentTarget.HasAura("Fear")), CreateSpellBuffOnSelf("Soulburn", ret => Me.CurrentSoulShards > 0), CreateSpellCast("Drain Life") )), CreateSpellCast("Life Tap", ret => Me.ManaPercent < 10), CreateSpellCast("Health Funnel", ret => Me.GotAlivePet && Me.Pet.HealthPercent < 30), // Finishing sequence CreateSpellCast( "Soul Swap", ret => !Me.HasAura("Soul Swap") && Me.CurrentTarget.HealthPercent < 10 && Me.CurrentTarget.HasAura("Unstable Affliction") && !CurrentTargetIsEliteOrBoss), CreateSpellCast("Drain Soul", ret => Me.CurrentTarget.HealthPercent < 10), // Elites new Decorator( ret => CurrentTargetIsEliteOrBoss, new PrioritySelector( CreateSpellBuffOnSelf("Demon Soul"), CreateSpellBuff("Curse of Elements", ret => !Me.CurrentTarget.HasAura("Curse of Elements")), new Decorator( ret => SpellManager.CanCast("Summon Infernal"), new Action( ret => { SpellManager.Cast("Summon Infernal"); LegacySpellManager.ClickRemoteLocation(Me.CurrentTarget.Location); })) )), // AoE new Decorator( ret => NearbyUnfriendlyUnits.Count(u => u.Distance < 15) >= 5, new PrioritySelector( CreateSpellBuffOnSelf("Demon Soul"), CreateSpellBuffOnSelf( "Soulburn", ret => !Me.CurrentTarget.HasAura("Seed of Corruption") && Me.CurrentSoulShards > 0 && TalentManager.GetCount(1, 15) == 1), CreateSpellBuff("Seed of Corruption", ret => !Me.CurrentTarget.HasAura("Seed of Corruption")) )), // Standard Nuking CreateSpellCast("Shadow Bolt", ret => Me.HasAura("Shadow Trance")), CreateSpellBuff("Haunt"), CreateSpellCast("Soul Swap", ret => Me.HasAura("Soul Swap") && Me.CurrentTarget.HealthPercent > 10), CreateSpellBuff("Bane of Doom", ret => CurrentTargetIsEliteOrBoss && !Me.CurrentTarget.HasAura("Bane of Doom")), CreateSpellBuff("Bane of Agony", ret => !Me.CurrentTarget.HasAura("Bane of Agony") && !Me.CurrentTarget.HasAura("Bane of Doom")), CreateSpellBuff("Corruption", ret => !Me.CurrentTarget.HasAura("Corruption") && !Me.CurrentTarget.HasAura("Seed of Corruption")), CreateSpellBuff("Unstable Affliction", ret => !Me.CurrentTarget.HasAura("Unstable Affliction")), CreateSpellCast("Drain Soul", ret => Me.CurrentTarget.HealthPercent < 25), CreateSpellCast("Shadowflame", ret => Me.CurrentTarget.Distance < 5), CreateSpellBuffOnSelf("Demon Soul"), CreateSpellBuff("Curse of Weakness", ret => Me.CurrentTarget.IsPlayer && !Me.CurrentTarget.HasAura("Curse of Weakness")), CreateSpellCast("Life Tap", ret => Me.ManaPercent < 50 && Me.HealthPercent > 70), CreateSpellCast("Drain Life", ret => Me.HealthPercent < 70), CreateSpellCast("Health Funnel", ret => Me.GotAlivePet && Me.Pet.HealthPercent < 70), CreateSpellCast("Shadow Bolt") )); }
private Composite CreateRestoDruidHealOnlyBehavior(bool selfOnly) { NeedHealTargeting = true; const uint MAPLE_SEED_ID = 17034; return(new Decorator( ret => HealTargeting.Instance.FirstUnit != null, new PrioritySelector( ctx => selfOnly ? Me : HealTargeting.Instance.FirstUnit, CreateWaitForCast(), // Ensure we're in range of the unit to heal, and it's in LOS. //CreateMoveToAndFace(35f, ret => (WoWUnit)ret), //Cast Lifebloom on tank if //1- Tank doesn't have lifebloom //2- Tank has less then 3 stacks of lifebloom //3- Tank has 3 stacks of lifebloom but it will expire in 3 seconds CreateSpellCast( "Lifebloom", ret => Me.Combat && // Keep 3 stacks up on the tank/leader at all times. // If we're in ToL form, we can do rolling LBs for everyone. So ignore the fact that its the leader or not. // LB is cheap, and VERY powerful in ToL form since you can spam it on the entire raid, for a cheap HoT and quite good 'bloom' ((RaFHelper.Leader != null && (WoWUnit)ret == RaFHelper.Leader) || Me.Shapeshift == ShapeshiftForm.TreeOfLife) && ((WoWUnit)ret).HealthPercent > 60 && (!((WoWUnit)ret).HasAura("Lifebloom") || ((WoWUnit)ret).Auras["Lifebloom"].StackCount < 3 || ((WoWUnit)ret).Auras["Lifebloom"].TimeLeft <= TimeSpan.FromSeconds(3)), ret => (WoWUnit)ret), //Cast rebirth if the tank is dead. Check for Unburdened Rebirth glyph or Maple seed reagent CreateSpellCast( "Rebirth", ret => Me.Combat && RaFHelper.Leader != null && (WoWUnit)ret == RaFHelper.Leader && ((WoWUnit)ret).Dead && (TalentManager.HasGlyph("Unburdened Rebirth") || Me.BagItems.Any(i => i.Entry == MAPLE_SEED_ID)), ret => (WoWUnit)ret), CreateSpellCast( "Tranquility", ret => Me.Combat && Me.IsInParty && NearbyFriendlyPlayers.Count( p => p.IsAlive && p.HealthPercent <= SingularSettings.Instance.Druid.TranquilityHealth && p.Distance <= 30) >= SingularSettings.Instance.Druid.TranquilityCount), //Use Innervate on party members if we have Glyph of Innervate CreateSpellBuff( "Innervate", ret => TalentManager.HasGlyph("Innervate") && Me.Combat && (WoWUnit)ret != Me && Me.ManaPercent <= SingularSettings.Instance.Druid.InnervateMana && ((WoWUnit)ret).PowerType == WoWPowerType.Mana && ((WoWUnit)ret).ManaPercent <= SingularSettings.Instance.Druid.InnervateMana, ret => (WoWUnit)ret), CreateSpellCast( "Swiftmend", ret => Me.Combat && ((WoWUnit)ret).HealthPercent <= SingularSettings.Instance.Druid.Swiftmend && (((WoWUnit)ret).HasAura("Rejuvenation") || ((WoWUnit)ret).HasAura("Regrowth")), ret => (WoWUnit)ret), CreateSpellCast( "Wild Growth", ret => Me.IsInParty && NearbyFriendlyPlayers.Count( p => p.IsAlive && p.HealthPercent <= SingularSettings.Instance.Druid.WildGrowthHealth && p.Location.Distance(((WoWUnit)ret).Location) <= 30) >= SingularSettings.Instance.Druid.WildGrowthCount, ret => (WoWUnit)ret), CreateSpellBuff( "Regrowth", ret => ((WoWUnit)ret).HealthPercent <= SingularSettings.Instance.Druid.Regrowth, ret => (WoWUnit)ret), CreateSpellCast( "Healing Touch", ret => ((WoWUnit)ret).HealthPercent <= SingularSettings.Instance.Druid.HealingTouch, ret => (WoWUnit)ret), CreateSpellCast( "Nourish", ret => ((WoWUnit)ret).HealthPercent <= SingularSettings.Instance.Druid.Nourish && (((WoWUnit)ret).HasAura("Rejuvenation") || ((WoWUnit)ret).HasAura("Regrowth") || ((WoWUnit)ret).HasAura("Lifebloom") || ((WoWUnit)ret).HasAura("Wild Growth")), ret => (WoWUnit)ret), CreateSpellBuff( "Rejuvenation", ret => ((WoWUnit)ret).HealthPercent <= SingularSettings.Instance.Druid.Rejuvenation, ret => (WoWUnit)ret) ))); }
public Composite CreateBeastMasterCombat() { WantedPet = "1"; return(new PrioritySelector( new Decorator( ret => !Me.GotAlivePet, new Action(ret => PetManager.CallPet(WantedPet))), CreateEnsureTarget(), CreateHunterBackPedal(), // Make sure we're in range, and facing the damned target. (LOS check as well) CreateMoveToAndFace(35f, ret => Me.CurrentTarget), //Intimidation CreateSpellCast( "Intimidation", ret => Me.CurrentTarget.IsAlive && Me.GotAlivePet && (Me.CurrentTarget.CurrentTarget == null || Me.CurrentTarget.CurrentTarget == Me)), // Always keep it up on our target! CreateSpellBuff("Hunter's Mark"), CreateHunterTrapOnAddBehavior(), new Decorator( ret => Me.CurrentTarget.DistanceSqr < 5 * 5, new PrioritySelector( CreateSpellBuffOnSelf("Disengage"), CreateSpellCast("Raptor Strike") )), // Heal pet when below 70 CreateSpellCast( "Mend Pet", ret => (Me.Pet.HealthPercent < 70 || (Me.Pet.HappinessPercent < 90 && TalentManager.HasGlyph("Mend Pet"))) && !Me.Pet.HasAura("Mend Pet")), CreateSpellCast( "Concussive Shot", ret => Me.CurrentTarget.CurrentTarget == null || Me.CurrentTarget.CurrentTarget == Me), //Rapid fire on elite CreateSpellBuffOnSelf("Rapid Fire", ret => CurrentTargetIsElite), CreateSpellBuff("Serpent Sting"), // Ignore these two when our pet is raging CreateSpellCast("Focus Fire", ret => !Me.Pet.HasAura("Bestial Wrath")), CreateSpellCast("Kill Shot", ret => !Me.Pet.HasAura("Bestial Wrath")), // Basically, cast it whenever its up. CreateSpellCast("Kill Command"), // Only really cast this when we need a sting refresh. CreateSpellCast( "Cobra Shot", ret => Me.CurrentTarget.HasAura("Serpent Sting") && Me.CurrentTarget.Auras["Serpent Sting"].TimeLeft.TotalSeconds < 3), // Focus dump on arcane shot, unless our pet has bestial wrath, then we use it for better DPS CreateSpellCast("Arcane Shot"), // For when we have no Focus CreateSpellCast("Steady Shot"), CreateAutoAttack(true) )); }
public override void Initialize() { DateTime timeStart = DateTime.UtcNow; Logger.WriteFile("Initialize: started"); // cannot call method which references SingularSettings TalentManager.Init(); // initializes CurrentSpec which is referenced everywhere SingularSettings.Initialize(); // loads Singular global and spec-specific settings (must determine spec first) DetermineCurrentWoWContext(); Task.Run(() => WriteSupportInfo()); _lastLogLevel = GlobalSettings.Instance.LogLevel; // When we actually need to use it, we will. Spell.Init(); Spell.GcdInitialize(); EventHandlers.Init(); MountManager.Init(); HotkeyDirector.Init(); MovementManager.Init(); // SoulstoneManager.Init(); // switch to using Death behavior Dispelling.Init(); PartyBuff.Init(); Singular.Lists.BossList.Init(); Targeting.Instance.WeighTargetsFilter += PullMoreWeighTargetsFilter; //Logger.Write("Combat log event handler started."); // Do this now, so we ensure we update our context when needed. BotEvents.Player.OnMapChanged += e => { // Don't run this handler if we're not the current routine! if (!WeAreTheCurrentCombatRoutine) { return; } // Only ever update the context. All our internal handlers will use the context changed event // so we're not reliant on anything outside of ourselves for updates. UpdateContext(); }; TreeHooks.Instance.HooksCleared += () => { // Don't run this handler if we're not the current routine! if (!WeAreTheCurrentCombatRoutine) { return; } Logger.Write(LogColor.Hilite, "Hooks cleared, re-creating behaviors"); RebuildBehaviors(silent: true); Spell.GcdInitialize(); // probably not needed, but quick }; GlobalSettings.Instance.PropertyChanged += (sender, e) => { // Don't run this handler if we're not the current routine! if (!WeAreTheCurrentCombatRoutine) { return; } // only LogLevel change will impact our behav trees // .. as we conditionally include/omit some diagnostic nodes if debugging // also need to keep a cached copy of prior value as the event // .. fires on the settor, not when the value is different if (e.PropertyName == "LogLevel" && _lastLogLevel != GlobalSettings.Instance.LogLevel) { _lastLogLevel = GlobalSettings.Instance.LogLevel; Logger.Write(LogColor.Hilite, "HonorBuddy {0} setting changed to {1}, re-creating behaviors", e.PropertyName, _lastLogLevel.ToString()); RebuildBehaviors(); Spell.GcdInitialize(); // probably not needed, but quick } }; // install botevent handler so we can consolidate validation on whether // .. local botevent handlers should be called or not SingularBotEventInitialize(); Logger.Write("Determining talent spec."); try { TalentManager.Update(); } catch (Exception e) { StopBot(e.ToString()); } Logger.Write("Current spec is " + SpecName()); // write current settings to log file... only written at startup and when Save press in Settings UI Task.Run(() => SingularSettings.Instance.LogSettings()); // Update the current WoWContext, and fire an event for the change. UpdateContext(); // NOTE: Hook these events AFTER the context update. OnWoWContextChanged += (orig, ne) => { Logger.Write(LogColor.Hilite, "Context changed, re-creating behaviors"); SingularRoutine.DescribeContext(); RebuildBehaviors(); Spell.GcdInitialize(); Singular.Lists.BossList.Init(); }; RoutineManager.Reloaded += (s, e) => { Logger.Write(LogColor.Hilite, "Routines were reloaded, re-creating behaviors"); RebuildBehaviors(silent: true); Spell.GcdInitialize(); }; // create silently since Start button will create a context change (at least first Start) // .. which will build behaviors again if (!Instance.RebuildBehaviors()) { return; } // if (IsPluginEnabled("DrinkPotions")) { Logger.Write(LogColor.Hilite, "info: disabling DrinkPotions plugin, conflicts with Singular potion support"); SetPluginEnabled("DrinkPotions", false); } SpellImmunityManager.Add(16292, WoWSpellSchool.Frost); // http://www.wowhead.com/npc=16292/aquantion Logger.WriteDebug(Color.White, "Verified behaviors can be created!"); Logger.Write("Initialization complete!"); Logger.WriteDiagnostic(Color.White, "Initialize: completed taking {0:F2} seconds", (DateTime.UtcNow - timeStart).TotalSeconds); }
public override void Pulse() { #region Pulse - check for conditions that we should not Pulse during /* * if (!StyxWoW.IsInGame) * { * if (DateTime.UtcNow > _nextNotInGameMsgAllowed) * { * Logger.WriteDebug(Color.HotPink, "info: not in game"); * _nextNotInGameMsgAllowed = DateTime.UtcNow.AddSeconds(30); * } * return; * } * _nextNotInGameMsgAllowed = DateTime.MinValue; * * if (!StyxWoW.IsInWorld) * { * if (DateTime.UtcNow > _nextNotInWorldMsgAllowed) * { * Logger.WriteDebug(Color.HotPink, "info: not in world"); * _nextNotInWorldMsgAllowed = DateTime.UtcNow.AddSeconds(30); * } * return; * } * _nextNotInWorldMsgAllowed = DateTime.MinValue; */ #endregion _pulsePhase++; if (_pulsePhase == 1) { if (WaitForLatencyCheck.IsFinished) { Latency = StyxWoW.WoWClient.Latency; WaitForLatencyCheck.Reset(); } // output messages about pulldistance and behaviorflag changes here MonitorPullDistance(); MonitorBehaviorFlags(); /* * // now if combat disabled, bail out * bool combatDisabled = Bots.Grind.BehaviorFlags.Combat != (Bots.Grind.LevelBot.BehaviorFlags & Bots.Grind.BehaviorFlags.Combat); * if (combatDisabled != _lastCombatDisabledState) * { * _lastCombatDisabledState = combatDisabled; * Logger.Write(Color.HotPink, * combatDisabled * ? "info: botbase disabled BehaviorFlags.Combat" * : "info: botbase enabled BehaviorFlags.Combat" * ); * } */ // check time since last call and be sure user knows if Singular isn't being called if (SingularSettings.Debug) { TimeSpan since = CallWatch.TimeSpanSinceLastCall; if (since.TotalSeconds > (4 * CallWatch.SecondsBetweenWarnings)) { if (!Me.IsGhost && !Me.Mounted && !Me.IsFlying && DateTime.UtcNow > _nextNoCallMsgAllowed) { Logger.WriteDebug(Color.HotPink, "info: {0:F0} seconds since {1} BotBase last called Singular", since.TotalSeconds, GetBotName()); _nextNoCallMsgAllowed = DateTime.UtcNow.AddSeconds(4 * CallWatch.SecondsBetweenWarnings); } } } UpdateDiagnosticFPS(); } else if (_pulsePhase == 2) { // talentmanager.Pulse() intense if does work, so return if true if (TalentManager.Pulse()) { return; } // check and output casting state information UpdateDiagnosticCastingState(); UpdatePullMoreConditionals(); // Update the current context, check if we need to rebuild any behaviors. UpdateContext(); } else if (_pulsePhase == 3) { _pulsePhase = 0; // Pulse our StopAt manager StopMoving.Pulse(); PetManager.Pulse(); // Double cast maintenance Spell.MaintainDoubleCast(); HotkeyDirector.Pulse(); WatchAurasForProcs(); } if (Me.Class == WoWClass.Warlock) { ClassSpecific.Warlock.Common.CancelBurningRushIfNeeded(fromPulse: true); } // Output if Target changed CheckCurrentTarget(); // Output if Pet or Pet Target changed CheckCurrentPet(); // check Targeting pulses if (HealerManager.NeedHealTargeting) { BotBase bot = GetCurrentBotBase(); if (bot != null && (bot.PulseFlags & PulseFlags.Targeting) != PulseFlags.Targeting) { HealerManager.Instance.Pulse(); } } else if (TankManager.NeedTankTargeting && Group.MeIsTank) { BotBase bot = GetCurrentBotBase(); if (bot != null && (bot.PulseFlags & PulseFlags.Targeting) != PulseFlags.Targeting) { TankManager.Instance.Pulse(); } } }
public Composite CreateHunterBuffs() { WantedPet = "1"; return(new PrioritySelector( new Decorator( ctx => Me.CastingSpell != null && Me.CastingSpell.Name == "Revive " + WantedPet && Me.GotAlivePet, new Action(ctx => SpellManager.StopCasting())), CreateWaitForCast(), CreateSpellBuffOnSelf("Aspect of the Hawk"), CreateSpellBuffOnSelf("Track Hidden"), //new ActionLogMessage(false, "Checking for pet"), new Decorator( ret => !Me.GotAlivePet, new Sequence( new Action(ret => PetManager.CallPet(WantedPet)), new Action(ret => Thread.Sleep(1000)), new DecoratorContinue( ret => !Me.GotAlivePet && SpellManager.CanCast("Revive Pet"), new Sequence( new Action(ret => SpellManager.Cast("Revive Pet")), new Action(ret => StyxWoW.SleepForLagDuration()), new WaitContinue( 11, ret => !Me.IsCasting, new ActionAlwaysSucceed()))))), CreateSpellCast( "Mend Pet", ret => (Me.Pet.HealthPercent < 70 || (Me.Pet.HappinessPercent < 90 && TalentManager.HasGlyph("Mend Pet"))) && !Me.Pet.HasAura("Mend Pet")) )); }
public Composite CreateFireMageCombat() { return(new PrioritySelector( CreateEnsureTarget(), //Move away from frozen targets new Decorator( ret => Me.CurrentTarget.HasAura("Frost Nova") && Me.CurrentTarget.DistanceSqr < 5 * 5, new Action( ret => { Logger.Write("Getting away from frozen target"); WoWPoint moveTo = WoWMathHelper.CalculatePointFrom(Me.Location, Me.CurrentTarget.Location, 10f); if (Navigator.CanNavigateFully(Me.Location, moveTo)) { Navigator.MoveTo(moveTo); } })), // Make sure we're in range, and facing the damned target. (LOS check as well) CreateMoveToAndFace(39f, ret => Me.CurrentTarget), CreateSpellBuffOnSelf("Ice Block", ret => Me.HealthPercent < 10 && !Me.ActiveAuras.ContainsKey("Hypothermia")), new Decorator(ret => Me.ActiveAuras.ContainsKey("Ice Block"), new ActionIdle()), CreateSpellBuff("Frost Nova", ret => NearbyUnfriendlyUnits.Any(u => u.DistanceSqr <= 8 * 8)), CreateSpellCast("Evocation", ret => Me.ManaPercent < 20), new Decorator(ret => HaveManaGem() && Me.ManaPercent <= 30, new Action(ctx => UseManaGem())), CreateSpellBuffOnSelf("Mana Shield", ret => !Me.Auras.ContainsKey("Mana Shield") && Me.HealthPercent <= 75), CreateMagePolymorphOnAddBehavior(), CreateSpellCast("Counterspell", ret => Me.CurrentTarget.IsCasting), CreateSpellCast("Mirror Image", ret => Me.CurrentTarget.HealthPercent > 20), CreateSpellCast("Time Warp", ret => Me.CurrentTarget.HealthPercent > 20), new Decorator( ret => Me.CurrentTarget.HealthPercent > 50, new Sequence( new Action(ctx => Me.CurrentTarget.Face()), new Action(ctx => StyxWoW.SleepForLagDuration()), new PrioritySelector(CreateSpellCast("Flame Orb")) )), CreateSpellCast("Scorch", ret => (!Me.CurrentTarget.HasAura("Critical Mass") || Me.CurrentTarget.Auras["Critical Mass"].TimeLeft.TotalSeconds < 3) && TalentManager.GetCount(2, 20) != 0 && LastSpellCast != "Scorch"), CreateSpellCast("Pyroblast", ret => Me.ActiveAuras.ContainsKey("Hot Streak") && Me.ActiveAuras["Hot Streak"].TimeLeft.TotalSeconds > 1), CreateSpellCast("Fire Blast", ret => Me.ActiveAuras.ContainsKey("Impact")), CreateSpellBuff("Living Bomb", ret => !Me.CurrentTarget.HasAura("Living Bomb")), CreateSpellCast("Combustion", ret => Me.CurrentTarget.ActiveAuras.ContainsKey("Living Bomb") && Me.CurrentTarget.ActiveAuras.ContainsKey("Ignite") && Me.CurrentTarget.ActiveAuras.ContainsKey("Pyroblast!")), CreateSpellCast("Fireball"), CreateFireRangedWeapon() )); }