Example #1
0
        public static Composite CreateRestoShamanCombatBehaviorSolo()
        {
            return(new PrioritySelector(

                       Helpers.Common.EnsureReadyToAttackFromMediumRange(),

                       Spell.WaitForCastOrChannel(),

                       new Decorator(
                           ret => !Spell.IsGlobalCooldown(),
                           new PrioritySelector(

                               CreateRestoDiagnosticOutputBehavior(on => null),

                               Helpers.Common.CreateInterruptBehavior(),
                               Totems.CreateTotemsBehavior(),

                               Movement.WaitForFacing(),
                               Movement.WaitForLineOfSpellSight(),

                               Dispelling.CreatePurgeEnemyBehavior("Purge"),

                               Common.CastElementalBlast(),
                               Spell.Buff("Flame Shock", 3, on => Me.CurrentTarget, req => true),
                               Spell.Cast("Lava Burst"),
                               Spell.Cast("Frost Shock"),
                               Spell.Cast("Chain Lightning", ret => Spell.UseAOE && Unit.UnfriendlyUnitsNearTarget(10f).Count() >= 2 && !Unit.UnfriendlyUnitsNearTarget(12f).Any(u => u.IsCrowdControlled())),
                               Spell.Cast("Lightning Bolt")
                               )
                           )
                       ));
        }
Example #2
0
        public override void Initialize()
        {
            RegisterHotkeys();
            LuaCore.PopulateSecondryStats();
            TalentManager.Init();
            TalentManager.Update();
            UpdateContext();
            // Do this now, so we ensure we update our context when needed.
            BotEvents.Player.OnMapChanged += e => UpdateContext();

            OnWoWContextChanged += (orig, ne) =>
            {
                Logging.Write("Context changed, re-creating behaviors");
                AssignBehaviors();
                Spell.GcdInitialize();
                Lists.BossList.Init();
            };
            Spell.GcdInitialize();
            Dispelling.Init();
            //testing cached units
            //CachedUnits.Initialize();
            EventHandlers.Init();
            Lists.BossList.Init();
            Instance.AssignBehaviors();
            Logging.Write("Initialization Completed");
        }
Example #3
0
        public static Composite CreateDiscCombatNormalCombat()
        {
            return(new PrioritySelector(

                       Spell.WaitForCastOrChannel(),

                       new Decorator(
                           ret => Unit.NearbyGroupMembers.Any(m => m.IsAlive),
                           CreateDiscHealOnlyBehavior()
                           ),

                       Helpers.Common.EnsureReadyToAttackFromMediumRange(),
                       Movement.CreateFaceTargetBehavior(),

                       new Decorator(
                           ret => !Spell.IsGlobalCooldown(),
                           new PrioritySelector(
                               CreateDiscDiagnosticOutputBehavior(CompositeBuilder.CurrentBehaviorType.ToString()),

                               Helpers.Common.CreateInterruptBehavior(),

                               Movement.WaitForFacing(),
                               Movement.WaitForLineOfSpellSight(),

                               // Artifact Weapon
                               // Light's Wrath notes:  UseDPSArtifactWeaponWhen.AtHighestDPSOpportunity would be good if the player has a larger number of attonement stacks.  However, this would only apply for dungeon context.
                               new Decorator(
                                   ret => PriestSettings.UseArtifactOnlyInAoE && Unit.NearbyUnitsInCombatWithMeOrMyStuff.Count() > 1,
                                   new PrioritySelector(
                                       Spell.Cast("Light's Wrath", ret => PriestSettings.UseDPSArtifactWeaponWhen == UseDPSArtifactWeaponWhen.OnCooldown)
                                       )
                                   ),
                               Spell.Cast("Light's Wrath", ret => !PriestSettings.UseArtifactOnlyInAoE && PriestSettings.UseDPSArtifactWeaponWhen == UseDPSArtifactWeaponWhen.OnCooldown),

                               Dispelling.CreatePurgeEnemyBehavior("Dispel Magic"),
                               Spell.Buff("Shadow Word: Pain", req => Me.CurrentTarget.HasAuraExpired("Shadow Word: Pain", 1) && Me.CurrentTarget.TimeToDeath(99) >= 8),
                               Spell.Buff("Shadow Word: Pain", true, on =>
            {
                WoWUnit unit = Unit.NearbyUnfriendlyUnits
                               .FirstOrDefault(
                    u => (u.TaggedByMe || u.Aggro) &&
                    u.Guid != Me.CurrentTargetGuid &&
                    u.IsTargetingMeOrPet &&
                    !u.HasMyAura("Shadow Word: Pain") &&
                    !u.IsCrowdControlled()
                    );
                return unit;
            }),

                               Spell.Buff("Schism", on => Me.CurrentTarget),
                               Spell.Cast("Penance", mov => true, on => Me.CurrentTarget, req => true, cancel => false),
                               Spell.Cast("Smite", mov => true, on => Me.CurrentTarget, req => true, cancel => false)
                               )
                           )
                       ));
        }
Example #4
0
        public static Composite CreatePriestDispelBehavior()
        {
            return(new PrioritySelector(

                       Spell.Cast("Mass Dispel",
                                  on => Me,
                                  req => Me.Combat &&
                                  PriestSettings.CountMassDispel > 0 &&
                                  Unit.NearbyGroupMembers.Count(u => u.IsAlive && u.SpellDistance() < 15 && Dispelling.CanDispel(u, DispelCapabilities.All)) >= PriestSettings.CountMassDispel),

                       Dispelling.CreateDispelBehavior()
                       ));
        }
Example #5
0
        public static Composite CreateRestoShamanCombatBehaviorBattlegrounds()
        {
            return(new PrioritySelector(

                       Spell.WaitForCastOrChannel(),

                       CreateRestoDiagnosticOutputBehavior(on => HealerManager.Instance.FirstUnit),

                       new Decorator(
                           ret => !Spell.IsGlobalCooldown() && HealerManager.Instance.TargetList.Any(t => !t.IsMe && t.IsAlive),
                           new PrioritySelector(
                               HealerManager.CreateStayNearTankBehavior(),
                               CreateRestoShamanHealingOnlyBehavior(selfOnly: false)
                               )
                           ),

                       new Decorator(
                           ret => !Spell.IsGlobalCooldown() && HealerManager.AllowHealerDPS(),
                           new PrioritySelector(

                               Helpers.Common.EnsureReadyToAttackFromMediumRange(),

                               Spell.WaitForCastOrChannel(),

                               new Decorator(
                                   ret => !Spell.IsGlobalCooldown(),
                                   new PrioritySelector(

                                       Helpers.Common.CreateInterruptBehavior(),
                                       Totems.CreateTotemsBehavior(),

                                       Movement.WaitForFacing(),
                                       Movement.WaitForLineOfSpellSight(),

                                       Dispelling.CreatePurgeEnemyBehavior("Purge"),

                                       Common.CastElementalBlast(),
                                       Spell.Buff("Flame Shock", 3, on => Me.CurrentTarget, req => true),
                                       Spell.Cast("Lava Burst"),
                                       Spell.Cast("Frost Shock"),
                                       Spell.Cast("Chain Lightning", ret => Spell.UseAOE && Unit.UnfriendlyUnitsNearTarget(10f).Count() >= 2 && !Unit.UnfriendlyUnitsNearTarget(12f).Any(u => u.IsCrowdControlled())),
                                       Spell.Cast("Lightning Bolt")
                                       )
                                   )
                               )
                           )
                       ));
        }
 public static Composite RetributionCombat()
 {
     return(new Throttle(
                new PrioritySelector(
                    //new Decorator(ret => AdvancedAI.PvPRot,
                    //    RetributionPaladinPvP.CreateRPPvPCombat),
                    new Throttle(1, 1,
                                 new Decorator(ret => Me.HasAura("Dire Fixation"),
                                               new PrioritySelector(
                                                   BossMechs.HorridonHeroic()))),
                    Common.CreateInterruptBehavior(),
                    Dispelling.CreateDispelBehavior(),
                    Spell.Cast("Inquisition",
                               ret =>
                               (!Me.HasAura("Inquisition") || Me.HasAuraExpired("Inquisition", 2)) &&
                               (Me.CurrentHolyPower >= 3 || Me.HasAura("Divine Purpose"))),
                    new Decorator(ret => Me.HasAura("Inquisition") && AdvancedAI.Burst,
                                  new PrioritySelector(
                                      Spell.Cast("Avenging Wrath", ret => Me.CurrentTarget.IsBoss),
                                      Spell.Cast("Holy Avenger", ret => Me.CurrentTarget.IsBoss),
                                      Spell.Cast("Guardian of Ancient Kings",
                                                 ret => Me.CurrentTarget.IsBoss),
                                      new Action(ret => { Item.UseHands(); return RunStatus.Failure; }),
                                      new Action(ret => { Item.UseTrinkets(); return RunStatus.Failure; }))),
                    Spell.Cast("Seal of Righteousness", ret => !Me.HasAura("Seal of Righteousness") && Clusters.GetClusterCount(Me, Unit.NearbyUnfriendlyUnits, ClusterType.Radius, 8f) >= 8),
                    Spell.Cast("Seal of Truth", ret => !Me.HasAura("Seal of Truth") && Clusters.GetClusterCount(Me, Unit.NearbyUnfriendlyUnits, ClusterType.Radius, 8f) < 8),
                    new Decorator(ret => Me.HasAura("Inquisition"),
                                  new PrioritySelector(
                                      Spell.Cast("Execution Sentence", ret => Me.CurrentTarget.IsBoss),
                                      Spell.Cast("Holy Prism"),
                                      Spell.CastOnGround("Light's Hammer", on => Me.CurrentTarget.Location, ret => Me.CurrentTarget.IsBoss),
                                      Spell.Cast("Divine Storm", ret => Clusters.GetClusterCount(Me, Unit.NearbyUnfriendlyUnits, ClusterType.Radius, 8f) >= 2 &&
                                                 (Me.CurrentHolyPower == 5 || Me.HasAura("Divine Purpose"))),
                                      Spell.Cast("Templar's Verdict", ret => Me.CurrentHolyPower == 5 || Me.HasAura("Divine Purpose")))),
                    Spell.Cast("Hammer of Wrath", ret => Me.CurrentHolyPower <= 4),
                    Spell.Cast("Exorcism", ret => Me.CurrentHolyPower <= 4),
                    Spell.Cast("Hammer of the Righteous", ret => Me.CurrentHolyPower <= 4 && Clusters.GetClusterCount(Me, Unit.NearbyUnfriendlyUnits, ClusterType.Radius, 8f) >= 2),
                    // Unit.NearbyUnfriendlyUnits.Count(u => u.DistanceSqr <= 8 * 8) >= 2),
                    Spell.Cast("Crusader Strike", ret => Me.CurrentHolyPower <= 4),
                    Spell.Cast("Judgment", on => SecTar, ret => Me.CurrentHolyPower <= 4 && Clusters.GetClusterCount(Me, Unit.NearbyUnfriendlyUnits, ClusterType.Radius, 15f) >= 2 && Me.HasAura("Glyph of Double Jeopardy")),
                    Spell.Cast("Judgment", ret => Me.CurrentHolyPower <= 4),
                    Spell.Cast("Divine Storm", ret => Me.HasAura("Inquisition") && Clusters.GetClusterCount(Me, Unit.NearbyUnfriendlyUnits, ClusterType.Radius, 8f) >= 2 &&
                               Me.GetAuraTimeLeft("Inquisition").TotalSeconds > 4),
                    Spell.Cast("Templar's Verdict", ret => Me.HasAura("Inquisition") && Me.GetAuraTimeLeft("Inquisition").TotalSeconds > 4))));
 }
Example #7
0
        public static Composite CreateDiscCombatNormalPull()
        {
            return(new PrioritySelector(

                       Helpers.Common.EnsureReadyToAttackFromMediumRange(),
                       Movement.CreateFaceTargetBehavior(),
                       Spell.WaitForCastOrChannel(),

                       new Decorator(
                           ret => !Spell.IsGlobalCooldown(),
                           new PrioritySelector(
                               CreateDiscDiagnosticOutputBehavior(CompositeBuilder.CurrentBehaviorType.ToString()),

                               Spell.BuffSelf("Power Word: Shield", ret => PriestSettings.UseShieldPrePull && CanWePwsUnit(Me)),
                               Helpers.Common.CreateInterruptBehavior(),

                               Movement.WaitForFacing(),
                               Movement.WaitForLineOfSpellSight(),

                               Dispelling.CreatePurgeEnemyBehavior("Dispel Magic"),

                               // slow pull if no aggro and not competing for mobs
                               Spell.Cast(
                                   "Smite",
                                   mov => true,
                                   on => Me.CurrentTarget,
                                   req => !ObjectManager.GetObjectsOfType <WoWUnit>(true, false).Any(u => u.Aggro || (u.IsPlayer && !u.IsMe && u.DistanceSqr < 60 * 60))
                                   ),

                               Spell.Buff("Shadow Word: Pain", req => Me.CurrentTarget.HasAuraExpired("Shadow Word: Pain", 1) && Me.CurrentTarget.TimeToDeath(99) >= 8),
                               Spell.Buff("Shadow Word: Pain", true, on =>
            {
                WoWUnit unit = Unit.NearbyUnfriendlyUnits.FirstOrDefault(u => u.Guid != Me.CurrentTargetGuid && u.IsTargetingMeOrPet && !u.HasMyAura("Shadow Word: Pain") && !u.IsCrowdControlled());
                return unit;
            }),
                               Spell.Cast("Penance", mov => true, on => Me.CurrentTarget, req => true, cancel => false),
                               Common.CreateHolyFireBehavior(),
                               Spell.Cast("Smite", mov => true, on => Me.CurrentTarget, req => true, cancel => false)
                               )
                           )
                       ));
        }
Example #8
0
        public static Composite CreateMageCombatBuffs()
        {
            return(new Decorator(
                       req => !Me.CurrentTarget.IsTrivial(),
                       new PrioritySelector(

                           // Defensive
                           CastAlterTime(),

                           // new Wait( 1, until => !HasTalent(MageTalents.Invocation) || Me.HasAura("Invoker's Energy"), new ActionAlwaysSucceed())

                           Dispelling.CreatePurgeEnemyBehavior("Spellsteal"),
                           // CreateMageSpellstealBehavior(),

                           CreateMageRuneOfPowerBehavior(),

                           Spell.BuffSelf("Time Warp", ret => MageSettings.UseTimeWarp && NeedToTimeWarp)
                           )
                       ));
        }
Example #9
0
        public static Composite CreateHolyCombat()
        {
            return(new PrioritySelector(
                       new Decorator(
                           ret => HealerManager.AllowHealerDPS(),
                           new PrioritySelector(
                               Helpers.Common.EnsureReadyToAttackFromMediumRange(),
                               Spell.WaitForCastOrChannel(),

                               new Decorator(
                                   ret => !Spell.IsGlobalCooldown(),
                                   new PrioritySelector(

                                       Helpers.Common.CreateInterruptBehavior(),

                                       Movement.WaitForFacing(),
                                       Movement.WaitForLineOfSpellSight(),

                                       Dispelling.CreatePurgeEnemyBehavior("Dispel Magic"),
                                       Spell.Buff("Shadow Word: Pain", true),
                                       Spell.Buff("Holy Word: Chastise"),
                                       Spell.Buff("Shadow Word: Pain", true, on =>
            {
                WoWUnit unit = Unit.NearbyUnfriendlyUnits
                               .FirstOrDefault(
                    u => (u.TaggedByMe || u.Aggro) &&
                    u.Guid != Me.CurrentTargetGuid &&
                    u.IsTargetingMeOrPet &&
                    !u.HasMyAura("Shadow Word: Pain") &&
                    !u.IsCrowdControlled()
                    );
                return unit;
            }),
                                       Common.CreateHolyFireBehavior(),
                                       Spell.Cast("Smite", mov => true, on => Me.CurrentTarget, req => true, cancel => HealerManager.CancelHealerDPS())
                                       )
                                   )
                               )
                           )
                       ));
        }
Example #10
0
        public static Composite CreateRestoShamanHealingOnlyBehavior(bool selfOnly = false)
        {
            HealerManager.NeedHealTargeting = true;
            PrioritizedBehaviorList behavs = new PrioritizedBehaviorList();
            int cancelHeal = (int)Math.Max(SingularSettings.Instance.IgnoreHealTargetsAboveHealth, Math.Max(ShamanSettings.RestoHealSettings.HealingWave, ShamanSettings.RestoHealSettings.HealingSurge));

            bool moveInRange = false;

            if (!selfOnly)
            {
                moveInRange = (SingularRoutine.CurrentWoWContext == WoWContext.Battlegrounds);
            }

            Logger.WriteDebugInBehaviorCreate("Shaman Healing: will cancel cast of direct heal if health reaches {0:F1}%", cancelHeal);

            int dispelPriority = (SingularSettings.Instance.DispelDebuffs == RelativePriority.HighPriority) ? 999 : -999;

            if (SingularSettings.Instance.DispelDebuffs != RelativePriority.None)
            {
                behavs.AddBehavior(dispelPriority, "Purify Spirit", null, Dispelling.CreateDispelBehavior());
            }

            #region Save the Group

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.RestoHealSettings.SpiritLinkTotem) + 600, "Spirit Link Totem", "Spirit Link Totem",
                               new Decorator(
                                   ret => Me.Combat && (StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid),
                                   Spell.CastOnGround("Spirit Link Totem",
                                                      on => (WoWUnit)on,
                                                      ret => HealerManager.Instance.TargetList.Count(
                                                          p => p.PredictedHealthPercent() < ShamanSettings.RestoHealSettings.SpiritLinkTotem && p.Distance <= Totems.GetTotemRange(WoWTotem.SpiritLink)) >= ShamanSettings.RestoHealSettings.MinSpiritLinkCount
                                                      )
                                   )
                               );

            #endregion

            #region AoE Heals

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.RestoHealSettings.HealingTideTotem) + 400, "Healing Tide Totem", "Healing Tide Totem",
                               new Decorator(
                                   ret => (Me.Combat || ((WoWUnit)ret).Combat) &&
                                   (StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid) &&
                                   (!Totems.Exist(WoWTotem.Cloudburst) || (Totems.GetTotem(WoWTotem.Cloudburst).Expires - DateTime.UtcNow).TotalMilliseconds < 1500),
                                   Spell.Cast(
                                       "Healing Tide Totem",
                                       on => Me,
                                       req => Me.Combat && HealerManager.Instance.TargetList.Count(p => p.PredictedHealthPercent() < ShamanSettings.RestoHealSettings.HealingTideTotem && p.Distance <= Totems.GetTotemRange(WoWTotem.HealingTide)) >= ShamanSettings.RestoHealSettings.MinHealingTideCount
                                       )
                                   )
                               );

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.RestoHealSettings.HealingStreamTotem) + 300, "Healing Stream Totem", "Healing Stream Totem",
                               new Decorator(
                                   ret => Me.Combat && (StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid),
                                   Spell.Cast(
                                       "Healing Stream Totem",
                                       on =>
            {
                if (Totems.Exist(WoWTotemType.Water))
                {
                    return(null);
                }

                if (Spell.IsSpellOnCooldown(Totems.ToSpellId(WoWTotem.HealingStream)))
                {
                    return(null);
                }

                // if tank in group, make sure we are near the tank
                WoWUnit tank = HealerManager.TankToStayNear;
                if (tank != null)
                {
                    if (!HealerManager.IsTankSettledIntoFight(tank))
                    {
                        return(null);
                    }
                    if (tank.Distance > Totems.GetTotemRange(WoWTotem.HealingStream))
                    {
                        return(null);
                    }
                }

                WoWUnit unit = HealerManager.Instance.TargetList
                               .FirstOrDefault(
                    p => p.PredictedHealthPercent() < ShamanSettings.RestoHealSettings.HealingStreamTotem &&
                    p.Distance <= Totems.GetTotemRange(WoWTotem.HealingStream)
                    );

                return(unit);
            }
                                       )
                                   )
                               );

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.RestoHealSettings.GiftoftheQueen) + 300, "Gift of the Queen", "Gift of the Queen",
                               new Decorator(
                                   ret => Me.Combat && (StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid),
                                   new PrioritySelector(
                                       context => GetBestGiftoftheQueenTarget(),
                                       new Decorator(
                                           ret => ret != null,
                                           Spell.CastOnGround("Gift of the Queen", on => (WoWUnit)on, req => true, false)
                                           )
                                       )
                                   )
                               );

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.RestoHealSettings.CloudburstTotem) + 300, "Cloudburst Totem", "Cloudburst Totem",
                               new Decorator(
                                   ret => Me.Combat && (StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid),
                                   Spell.Cast(
                                       "Cloudburst Totem",
                                       on =>
            {
                if (Totems.Exist(WoWTotemType.Water))
                {
                    return(null);
                }

                if (Spell.IsSpellOnCooldown(Totems.ToSpellId(WoWTotem.Cloudburst)))
                {
                    return(null);
                }

                if (Unit.ValidUnit(Me.CurrentTarget) && (Me.CurrentTarget.TimeToDeath() < 20 || Unit.UnitsInCombatWithUsOrOurStuff().Count() < 3))
                {
                    return(null);
                }

                // if tank in group, make sure we are near the tank
                WoWUnit tank = HealerManager.TankToStayNear;
                if (tank != null)
                {
                    if (!HealerManager.IsTankSettledIntoFight(tank))
                    {
                        return(null);
                    }
                    if (tank.Distance > Totems.GetTotemRange(WoWTotem.Cloudburst))
                    {
                        return(null);
                    }
                }

                WoWUnit unit = HealerManager.Instance.TargetList
                               .Where(
                    p => p.HealthPercent < ShamanSettings.RestoHealSettings.CloudburstTotem &&
                    p.Distance <= Totems.GetTotemRange(WoWTotem.Cloudburst)
                    )
                               .OrderBy(p => (int)p.HealthPercent)
                               .FirstOrDefault();

                return(unit);
            }
                                       )
                                   )
                               );

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.RestoHealSettings.HealingRain) + 200, "Healing Rain", "Healing Rain",
                               new Decorator(
                                   ret => Me.Combat && (StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid),
                                   new PrioritySelector(
                                       context => GetBestHealingRainTarget(),
                                       new Decorator(
                                           ret => ret != null,
                                           Spell.CastOnGround("Healing Rain", on => (WoWUnit)on, req => true, false)
                                           )
                                       )
                                   )
                               );

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.RestoHealSettings.ChainHeal) + 150, "Chain Heal", "Chain Heal",
                               new Decorator(
                                   ret => Me.Combat && (StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid),
                                   new PrioritySelector(
                                       ctx => GetBestChainHealTarget(),
                                       new Decorator(
                                           ret => ret != null,
                                           new Sequence(
                                               new DecoratorContinue(
                                                   req => ((WoWUnit)req).HasAuraExpired("Riptide", TimeSpan.FromMilliseconds(ChainHealCastTime), true),
                                                   new Sequence(
                                                       Spell.Cast("Riptide", on => (WoWUnit)on, req => true, cancel => false),
                                                       new Wait(TimeSpan.FromMilliseconds(1500), until => !Spell.IsGlobalCooldown(LagTolerance.No), new ActionAlwaysSucceed()),
                                                       new Action(r => TidalWaveRefresh())
                                                       )
                                                   ),
                                               new WaitContinue(TimeSpan.FromMilliseconds(1500), until => !Spell.IsGlobalCooldown(LagTolerance.No), new ActionAlwaysSucceed()),
                                               Spell.Cast("Chain Heal", on => (WoWUnit)on),
                                               new Action(r => TidalWaveRefresh())
                                               )
                                           )
                                       )
                                   )
                               );

            #endregion

            #region Single Target Heals

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.RestoHealSettings.HealingWave), "Healing Wave", "Healing Wave",
                               new Decorator(ret => ((WoWUnit)ret).PredictedHealthPercent() < ShamanSettings.RestoHealSettings.HealingWave,
                                             new Sequence(
                                                 new WaitContinue(TimeSpan.FromMilliseconds(1500), until => !Spell.IsGlobalCooldown(), new ActionAlwaysSucceed()),
                                                 new WaitContinue(2, until => !Spell.IsGlobalCooldown(), new ActionAlwaysSucceed()),
                                                 Spell.Cast("Healing Wave",
                                                            mov => true,
                                                            on => (WoWUnit)on,
                                                            req => true,
                                                            cancel => ((WoWUnit)cancel).HealthPercent > cancelHeal),
                                                 new Action(r => TidalWaveConsume())
                                                 )
                                             )
                               );

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.RestoHealSettings.HealingSurge), "Healing Surge", "Healing Surge",
                               new Decorator(ret => ((WoWUnit)ret).PredictedHealthPercent() < ShamanSettings.RestoHealSettings.HealingSurge,
                                             new Sequence(
                                                 new WaitContinue(TimeSpan.FromMilliseconds(1500), until => !Spell.IsGlobalCooldown(), new ActionAlwaysSucceed()),
                                                 new WaitContinue(2, until => !Spell.IsGlobalCooldown(), new ActionAlwaysSucceed()),
                                                 Spell.Cast("Healing Surge",
                                                            mov => true,
                                                            on => (WoWUnit)on,
                                                            req => true,
                                                            cancel => ((WoWUnit)cancel).HealthPercent > cancelHeal),
                                                 new Action(r => TidalWaveConsume())
                                                 )
                                             )

                               );

            #endregion

            #region Healing Cooldowns

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.RestoHealSettings.Ascendance) + 100, "Ascendance", "Ascendance",
                               new Decorator(
                                   ret => ShamanSettings.UseAscendance && (StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid),
                                   Spell.BuffSelf(
                                       "Ascendance",
                                       ret => HealerManager.Instance.TargetList.Count(p => p.PredictedHealthPercent() < ShamanSettings.RestoHealSettings.Ascendance) >= ShamanSettings.RestoHealSettings.MinAscendanceCount
                                       )
                                   )
                               );

            #endregion

            behavs.OrderBehaviors();

            if (selfOnly == false && CompositeBuilder.CurrentBehaviorType == BehaviorType.Combat)
            {
                behavs.ListBehaviors();
            }


            return(new PrioritySelector(
                       ctx => selfOnly ? StyxWoW.Me : HealerManager.FindLowestHealthTarget(),
                       // HealerManager.Instance.FirstUnit,

                       CreateRestoDiagnosticOutputBehavior(ret => (WoWUnit)ret),

                       new Decorator(
                           ret =>
                           ret != null &&
                           (Me.Combat || ((WoWUnit)ret).Combat || ((WoWUnit)ret).PredictedHealthPercent() <= 99),

                           new PrioritySelector(
                               new Decorator(
                                   ret => !Spell.IsGlobalCooldown(),
                                   new PrioritySelector(

                                       Totems.CreateTotemsBehavior(),

                                       // roll Riptide on Tanks otherwise
                                       new Sequence(
                                           Spell.Cast("Riptide", on =>
            {
                WoWUnit unit = GetBestRiptideTankTarget();
                if (unit != null && Spell.CanCastHack("Riptide", unit, skipWowCheck: true))
                {
                    Logger.WriteDebug("Buffing RIPTIDE ON TANK: {0}", unit.SafeName());
                    return unit;
                }
                return null;
            }),
                                           new Action(r => TidalWaveRefresh())
                                           ),

                                       // cast Riptide if we are a low level
                                       CreateRestoShamanBuffRiptideLowLevel(),

                                       // cast Riptide if we need Tidal Waves -- skip if Ancestral Swiftness is
                                       CreateRestoShamanBuffTidalWaves(),

                                       behavs.GenerateBehaviorTree(),

                                       // cast Riptide if we need Tidal Waves -- skip if Ancestral Swiftness is
                                       new Decorator(
                                           ret =>
            {
                int rollCount =
                    HealerManager.Instance.TargetList.Count(
                        u => u.IsAlive && u.HasMyAura("Riptide"));
                // Logger.WriteDebug("GetBestRiptideTarget:  currently {0} group members have my Riptide", rollCount);
                return rollCount < ShamanSettings.RestoHealSettings.RollRiptideCount;
            },
                                           new Sequence(
                                               Spell.Cast("Riptide", on =>
            {
                // if tank needs Riptide, bail out on Rolling as they have priority
                if (GetBestRiptideTankTarget() != null)
                {
                    return null;
                }

                // get the best target from all wowunits in our group
                WoWUnit unit = GetBestRiptideTarget();
                if (unit != null)
                {
                    Logger.WriteDebug(Color.White, "ROLLING RIPTIDE on: {0}",
                                      unit.SafeName());
                }

                return unit;
            }),
                                               new Action(r => TidalWaveRefresh())
                                               )
                                           ),

                                       new Decorator(
                                           ret => moveInRange,
                                           new Sequence(
                                               new Action(r => _moveToHealUnit = (WoWUnit)r),
                                               new PrioritySelector(
                                                   Movement.CreateMoveToLosBehavior(on => _moveToHealUnit),
                                                   Movement.CreateMoveToUnitBehavior(on => _moveToHealUnit, 40f, 34f)
                                                   )
                                               )
                                           )
                                       )
                                   )
                               )
                           )
                       ));
        }
Example #11
0
        public static Composite CreateRestoShamanCombatBehaviorInstances()
        {
#if OLD_APPROACH
            return(new PrioritySelector(

                       ctx => HealerManager.Instance.TargetList.Any(t => !t.IsMe && t.IsAlive),

                       Safers.EnsureTarget(),
                       Movement.CreateFaceTargetBehavior(),

                       Spell.WaitForCastOrChannel(),

                       new Decorator(
                           ret => !Spell.IsGlobalCooldown(),
                           new PrioritySelector(

                               CreateRestoDiagnosticOutputBehavior(on => Me.CurrentTarget),

                               new Decorator(
                                   ret => (bool)ret,
                                   new PrioritySelector(
                                       HealerManager.CreateStayNearTankBehavior(),
                                       CreateRestoShamanHealingOnlyBehavior(selfOnly: false),
                                       Helpers.Common.CreateInterruptBehavior(),
                                       Dispelling.CreatePurgeEnemyBehavior("Purge"),
                                       Totems.CreateTotemsBehavior(),
                                       Spell.Cast("Lightning Bolt", ret => TalentManager.HasGlyph("Telluric Currents"))
                                       )
                                   ),

                               new Decorator(
                                   ret => !((bool)ret),
                                   new PrioritySelector(
                                       CreateRestoDiagnosticOutputBehavior(on => HealerManager.Instance.FirstUnit),
                                       Spell.Cast("Elemental Blast"),
                                       Spell.Buff("Flame Shock", true, on => Me.CurrentTarget, req => true, 3),
                                       Spell.Cast("Lava Burst"),
                                       Spell.Cast("Frost Shock"),
                                       Spell.Cast("Chain Lightning", ret => Spell.UseAOE && Unit.UnfriendlyUnitsNearTarget(10f).Count() >= 2 && !Unit.UnfriendlyUnitsNearTarget(12f).Any(u => u.IsCrowdControlled())),
                                       Spell.Cast("Lightning Bolt")
                                       )
                                   )

                               )
                           )
                       ));
#else
            return(new PrioritySelector(

                       Spell.WaitForCastOrChannel(),
                       CreateRestoDiagnosticOutputBehavior(on => HealerManager.FindLowestHealthTarget()),

                       HealerManager.CreateStayNearTankBehavior(),

                       new Decorator(
                           ret => Me.Combat && HealerManager.AllowHealerDPS(),
                           new PrioritySelector(

                               Helpers.Common.EnsureReadyToAttackFromMediumRange(),
                               Movement.CreateFaceTargetBehavior(),
                               Spell.WaitForCastOrChannel(),

                               new Decorator(
                                   ret => !Spell.IsGlobalCooldown(),
                                   new PrioritySelector(
                                       Helpers.Common.CreateInterruptBehavior(),

                                       Totems.CreateTotemsBehavior(),

                                       Movement.WaitForFacing(),
                                       Movement.WaitForLineOfSpellSight(),

                                       Common.CastElementalBlast(cancel: c => HealerManager.CancelHealerDPS()),
                                       Spell.Buff("Flame Shock", 3, on => Me.CurrentTarget, req => true),
                                       Spell.Cast("Lava Burst", on => Me.CurrentTarget, req => true, cancel => HealerManager.CancelHealerDPS()),
                                       Spell.Cast("Frost Shock"),
                                       Spell.Cast("Chain Lightning", on => Me.CurrentTarget, req => Spell.UseAOE && Unit.UnfriendlyUnitsNearTarget(10f).Count() >= 2 && !Unit.UnfriendlyUnitsNearTarget(12f).Any(u => u.IsCrowdControlled()), cancel => HealerManager.CancelHealerDPS()),
                                       Spell.Cast("Lightning Bolt", on => Me.CurrentTarget, req => true, cancel => HealerManager.CancelHealerDPS())
                                       )
                                   )
                               )
                           ),

                       new Decorator(
                           ret => Unit.NearbyGroupMembers.Any(m => m.IsAlive && !m.IsMe),
                           new PrioritySelector(
                               CreateRestoShamanHealingOnlyBehavior(selfOnly: false),
                               Helpers.Common.CreateInterruptBehavior(),
                               Dispelling.CreatePurgeEnemyBehavior("Purge"),
                               Totems.CreateTotemsBehavior(),
                               new Decorator(
                                   req => TalentManager.HasGlyph("Telluric Currents"),
                                   new PrioritySelector(
                                       Safers.EnsureTarget(),
                                       Movement.CreateFaceTargetBehavior(),
                                       Spell.Cast("Lightning Bolt",
                                                  mov => true,
                                                  on => Unit.NearbyUnitsInCombatWithUsOrOurStuff
                                                  .Where(u => u.IsAlive && u.SpellDistance() < 40 && Me.IsSafelyFacing(u))
                                                  .OrderByDescending(u => u.HealthPercent)
                                                  .FirstOrDefault(),
                                                  req => !HealerManager.Instance.TargetList.Any(h => h.IsAlive && h.SpellDistance() < 40 && h.HealthPercent < ShamanSettings.RestoHealSettings.TelluricHealthCast),
                                                  cancel => HealerManager.Instance.TargetList.Any(h => h.IsAlive && h.SpellDistance() < 40 && h.HealthPercent < ShamanSettings.RestoHealSettings.TelluricHealthCancel)
                                                  )
                                       )
                                   )
                               )
                           )
                       ));
#endif
        }
        public static Composite RestorationCombat()
        {
            HealerManager.NeedHealTargeting = true;
            //var cancelHeal = Math.Max(95, Math.Max(AvehealingWave(), Math.Max(AvegreaterhealingWave(), AvehealingSurge())));//95,93,55,25
            var cancelHeal = Math.Max(95, Math.Max(93, Math.Max(55, 25)));//95,93,55,25

            return(new PrioritySelector(
                       Spell.WaitForCastOrChannel(),
                       //new Decorator(ret => AdvancedAI.PvPRot,
                       //    RestorationShamanPvP.CreateRSPvPCombat),
                       new Decorator(ret => (Me.Combat || healtarget.Combat /*|| healtarget.GetPredictedHealthPercent() <= 99*/) && !Me.Mounted,
                                     new PrioritySelector(
                                         //Totems.CreateTotemsBehavior(),
                                         RollRiptide(),
                                         TidalWaves(),
                                         new Decorator(ret => AdvancedAI.Dispell,
                                                       Dispelling.CreateDispelBehavior()),
                                         Item.UsePotionAndHealthstone(40),
                                         new Throttle(1, 1,
                                                      new PrioritySelector(
                                                          Spell.Cast("Earth Shield",
                                                                     on => GetBestEarthShieldTargetInstance(),
                                                                     ret => !GetBestEarthShieldTargetInstance().CachedHasAura("Earth Shield")))),
                                         Spell.Cast("Spirit Link Totem",
                                                    on => healtarget,
                                                    ret => HealerManager.Instance.TargetList.Count(p => p.GetPredictedHealthPercent() < 40 && p.Distance <= Totems.GetTotemRange(WoWTotem.SpiritLink)) >= 3 && AdvancedAI.Burst),
                                         new Decorator(ret => healtarget.HealthPercent < 25,
                                                       new Sequence(
                                                           Spell.Cast("Ancestral Swiftness"),
                                                           Spell.Cast("Greater Healing Wave",
                                                                      on => healtarget))),
                                         Spell.Cast("Healing Tide Totem",
                                                    ret => Me.Combat && HealerManager.Instance.TargetList.Count(p => p.GetPredictedHealthPercent() < 60 && p.Distance <= Totems.GetTotemRange(WoWTotem.HealingTide)) >= (Me.GroupInfo.IsInRaid ? 3 : 2) && AdvancedAI.Burst),
                                         Spell.Cast("Healing Stream Totem",
                                                    ret => Me.Combat && !Totems.Exist(WoWTotemType.Water) && HealerManager.Instance.TargetList.Any(p => p.GetPredictedHealthPercent() < 95 && p.Distance <= Totems.GetTotemRange(WoWTotem.HealingTide))),
                                         Spell.Cast("Mana Tide Totem",
                                                    ret => !Totems.Exist(WoWTotemType.Water) && Me.ManaPercent < 80),
                                         HealingRain(),
                                         ChainHeal(),
                                         Spell.Cast("Elemental Blast",
                                                    on => BoltTar()),
                                         //ret => SpellManager.HasSpell("Elemental Blast"),
                                         //cancel => healtarget.HealthPercent < 40),
                                         Spell.Cast("Greater Healing Wave",
                                                    on => healtarget,
                                                    //ret => AvegreaterhealingWave() < Deficit(),//55
                                                    ret => healtarget.HealthPercent <55,
                                                                                     cancel => healtarget.HealthPercent> cancelHeal),
                                         Spell.Cast("Healing Wave",
                                                    on => healtarget,
                                                    //ret => AvehealingWave() < Deficit(),//93
                                                    ret => healtarget.HealthPercent <93,
                                                                                     cancel => healtarget.HealthPercent> cancelHeal),
                                         Spell.Cast("Healing Surge",
                                                    on => healtarget,
                                                    //ret => AvehealingSurge() < Deficit(),//25
                                                    ret => healtarget.HealthPercent <25,
                                                                                     cancel => healtarget.HealthPercent> cancelHeal),
                                         Spell.Cast("Ascendance",
                                                    ret => HealerManager.Instance.TargetList.Count(p => p.GetPredictedHealthPercent() < 50) >= 4 && !Me.CachedHasAura("Ascendance") && AdvancedAI.Burst),
                                         Riptide(),
                                         new Decorator(ret => AdvancedAI.InterruptsEnabled,
                                                       Common.CreateInterruptBehavior()),
                                         //Totems.CreateTotemsBehavior(),
                                         Spell.Cast("Lightning Bolt",
                                                    on => BoltTar(),
                                                    ret => TalentManager.HasGlyph("Telluric Currents"),
                                                    cancel => healtarget.HealthPercent < 70)))));
        }
Example #13
0
        public override void Initialize()
        {
            DateTime timeStart = DateTime.UtcNow;

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

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

            DetermineCurrentWoWContext();

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

            _lastLogLevel = GlobalSettings.Instance.LogLevel;

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

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

            Targeting.Instance.WeighTargetsFilter += PullMoreWeighTargetsFilter;

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

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

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

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

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

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

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

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

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

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

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


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

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

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

            Logger.WriteDebug(Color.White, "Verified behaviors can be created!");
            Logger.Write("Initialization complete!");
            Logger.WriteDiagnostic(Color.White, "Initialize: completed taking {0:F2} seconds", (DateTime.UtcNow - timeStart).TotalSeconds);
        }
Example #14
0
        public static Composite CreatePriestShadowNormalCombat()
        {
            return(new PrioritySelector(
                       Helpers.Common.EnsureReadyToAttackFromLongRange(),
                       Spell.WaitForCastOrChannel(),
                       CreateFightAssessment(),
                       new Decorator(
                           ret => !Spell.IsGlobalCooldown(),
                           new PrioritySelector(

                               SingularRoutine.MoveBehaviorInlineToCombat(BehaviorType.Heal),
                               SingularRoutine.MoveBehaviorInlineToCombat(BehaviorType.CombatBuffs),

                               Helpers.Common.CreateInterruptBehavior(),

                               Movement.WaitForFacing(),
                               Movement.WaitForLineOfSpellSight(),

                               new Decorator(
                                   req => !Me.CurrentTarget.IsTrivial(),
                                   new PrioritySelector(

                                       Dispelling.CreatePurgeEnemyBehavior("Dispel Magic"),

                                       // Mana Management stuff - send in the fiends
                                       Common.CreateShadowfiendBehavior(),

                                       // Defensive stuff
                                       Spell.BuffSelf("Dispersion",
                                                      ret => Me.ManaPercent < PriestSettings.DispersionMana ||
                                                      Me.HealthPercent < 40 ||
                                                      (Me.ManaPercent < SingularSettings.Instance.MinMana && Me.IsSwimming) ||
                                                      Unit.NearbyUnfriendlyUnits.Count(t => t.GotTarget() && t.CurrentTarget.IsTargetingMyStuff()) >= 3),

                                       Common.CreatePriestShackleUndeadAddBehavior(),
                                       Common.CreatePsychicScreamBehavior(),

                                       Spell.HandleOffGCD(
                                           new PrioritySelector(
                                               ctx => Me.CurrentTarget.TimeToDeath() > 15 || cntAoeTargets > 1,
                                               new Sequence(
                                                   Spell.BuffSelfAndWait(sp => "Vampiric Embrace", req => ((bool)req) && Me.HealthPercent < PriestSettings.VampiricEmbracePct),
                                                   Spell.BuffSelf("Power Infusion")
                                                   ),
                                               Spell.Cast("Power Infusion", req => ((bool)req) || Me.HasAura("Vampiric Embrace"))
                                               )
                                           )
                                       )
                                   ),

                               // Shadow immune npcs.
                               // Spell.Cast("Holy Fire", req => Me.CurrentTarget.IsImmune(WoWSpellSchool.Shadow)),

                               // AoE Rotation
                               new Decorator(
                                   ret => Spell.UseAOE && cntAoeTargets > 1,
                                   new PrioritySelector(
                                       ctx => AoeTargets.FirstOrDefault(u => Me.IsSafelyFacing(u) && u.InLineOfSpellSight),

                                       Spell.Cast("Void Eruption", when => !InVoidform),

                                       Spell.Cast(
                                           "Mind Sear",
                                           mov => true,
                                           on =>
            {
                IEnumerable <WoWUnit> aoeTargetsFacing = AoeTargets.Where(u => Me.IsSafelyFacing(u) && u.InLineOfSpellSight && u.IsTrivial());
                WoWUnit unit = Clusters.GetBestUnitForCluster(aoeTargetsFacing, ClusterType.Radius, 10);
                if (unit == null)
                {
                    return null;
                }
                if (3 > Clusters.GetClusterCount(unit, AoeTargets, ClusterType.Radius, 10))
                {
                    return null;
                }
                if (Unit.UnfriendlyUnits(50).Any(u => !u.IsTrivial() && unit.SpellDistance(u) < 12))
                {
                    return null;
                }

                Logger.Write(LogColor.Hilite, "^Trivial Farming: all trivial mobs within 12 yds of {0}", unit.SafeName());
                return unit;
            },
                                           cancel => Me.HealthPercent < PriestSettings.ShadowHeal
                                           ),

                                       Spell.Buff("Shadow Word: Pain", true), // no multi message for current target
                                       Spell.Buff("Vampiric Touch", true),    // no multi message for current target
                                       Spell.Buff(                            // multi-dot others w/ message
                                           "Vampiric Touch",
                                           true,
                                           on =>
            {
                WoWUnit dotTarget = AoeTargets.FirstOrDefault(u => u != Me.CurrentTarget && !u.HasMyAura("Vampiric Touch") && u.InLineOfSpellSight && !Spell.DoubleCastContains(u, "Vampiric Touch"));
                if (dotTarget != null && Spell.CanCastHack("Vampiric Touch", dotTarget))
                {
                    Logger.Write(LogColor.Hilite, "^Multi-DoT: cast Vampiric Touch on {0}", dotTarget.SafeName());
                    return dotTarget;
                }
                return null;
            },
                                           req => true
                                           ),
                                       Spell.Buff(                          // multi-dot others w/ message
                                           "Shadow Word: Pain",
                                           true,
                                           on =>
            {
                WoWUnit dotTarget = AoeTargets.FirstOrDefault(u => u != Me.CurrentTarget && !u.HasMyAura("Shadow Word: Pain") && u.InLineOfSpellSight && !Spell.DoubleCastContains(u, "Shadow Word: Pain"));
                if (dotTarget != null && Spell.CanCastHack("Shadow Word: Pain", dotTarget))
                {
                    Logger.Write(LogColor.Hilite, "^Multi-DoT: cast Shadow Word: Pain on {0}", dotTarget.SafeName());
                    return dotTarget;
                }
                return null;
            },
                                           req => true
                                           ),

                                       // When we enter void form, even if AOE, we use our single target rotation after maintaining debuffs.
                                       new Decorator(ret => InVoidform,
                                                     CreateMaintainVoidformBehaviour()),

                                       // filler spell
                                       Spell.Cast(
                                           "Mind Sear",
                                           mov => true,
                                           on => {
                IEnumerable <WoWUnit> AoeTargetsFacing = AoeTargets.Where(u => Me.IsSafelyFacing(u) && u.InLineOfSpellSight);
                WoWUnit unit = Clusters.GetBestUnitForCluster(AoeTargetsFacing, ClusterType.Radius, 10);
                if (unit == null)
                {
                    return null;
                }
                if (4 > Clusters.GetClusterCount(unit, AoeTargets, ClusterType.Radius, 10))
                {
                    return null;
                }
                return unit;
            },
                                           cancel => Me.HealthPercent < PriestSettings.ShadowHeal
                                           ),
                                       CastMindFlay(on => (WoWUnit)on, req => cntAoeTargets < 4)
                                       )
                                   ),


                               new Decorator(ret => InVoidform,
                                             CreateMaintainVoidformBehaviour()),


                               CreateBuildVoidformBehaviour()
                               )
                           )
                       ));
        }
Example #15
0
        public static Composite CreateElementalNormalCombat()
        {
            return(new PrioritySelector(

                       Helpers.Common.EnsureReadyToAttackFromLongRange(),

                       Spell.WaitForCastOrChannel(),

                       new Decorator(
                           ret => !Spell.IsGlobalCooldown(),
                           new PrioritySelector(

                               Helpers.Common.CreateInterruptBehavior(),

                               Totems.CreateTotemsBehavior(),

                               Movement.WaitForFacing(),
                               Movement.WaitForLineOfSpellSight(),

                               Dispelling.CreatePurgeEnemyBehavior("Purge"),

                               Common.CreateShamanDpsShieldBehavior(),

                               Spell.BuffSelf("Thunderstorm", ret => Unit.NearbyUnfriendlyUnits.Count(u => u.Distance < 10f) >= 3),

                               Common.CastElementalBlast(),

                               Spell.CastOnGround("Lightning Surge Totem",
                                                  on => Clusters.GetBestUnitForCluster(Unit.NearbyUnfriendlyUnits, ClusterType.Radius, 8f).Location,
                                                  ret => ShamanSettings.UseLightningSurgeTotem &&
                                                  SingularRoutine.CurrentWoWContext == WoWContext.Normal &&
                                                  Unit.UnfriendlyUnits(8).Count() >= ShamanSettings.LightningSurgeTotemCount),
                               Spell.BuffSelf("Earth Elemental", ret => ShamanSettings.EarthElementalHealthPercent <= Me.HealthPercent),
                               Spell.BuffSelf("Totem Mastery", req => !Me.HasAura("Ember Totem")), // Only one buff should need to be checked.
                               Spell.Buff("Flame Shock", true, req => !Me.CurrentTarget.HasMyAura("Flame Shock") && Me.CurrentTarget.TimeToDeath(int.MaxValue) > 6),
                               Spell.Cast("Fire Elemental"),
                               Spell.Cast("Earth Shock", req => MaelstormDeficit <= 0),
                               Spell.Cast("Ascendance"),
                               Spell.BuffSelf("Elemental Mastery"),
                               Spell.Cast("Lava Burst"),
                               Spell.CastOnGround("Earthquake Totem",
                                                  on => Clusters.GetBestUnitForCluster(Unit.NearbyUnfriendlyUnits, ClusterType.Radius, 8f).Location,
                                                  req => Spell.UseAOE &&
                                                  Me.CurrentTarget.Distance < 34 &&
                                                  (Me.ManaPercent > ShamanSettings.EarthquakeMaelPercent || Me.GetAuraTimeLeft("Lucidity") > TimeSpan.Zero) &&
                                                  Unit.UnfriendlyUnitsNearTarget(10f).Count() >= ShamanSettings.EarthquakeCount - 1),
                               Spell.Cast("Earth Shock", req => Me.CurrentMaelstrom >= 90),

                               // Artifact Weapon
                               new Decorator(
                                   ret => ShamanSettings.UseArtifactOnlyInAoE && Unit.UnfriendlyUnitsNearTarget(10f).Count() > 1, // Focused toward Chain Lightning
                                   new PrioritySelector(
                                       Spell.Cast("Stormkeeper",
                                                  ret =>
                                                  ShamanSettings.UseDPSArtifactWeaponWhen == UseDPSArtifactWeaponWhen.OnCooldown || !Common.HasTalent(ShamanTalents.Ascendance) ||
                                                  (ShamanSettings.UseDPSArtifactWeaponWhen == UseDPSArtifactWeaponWhen.AtHighestDPSOpportunity && Common.HasTalent(ShamanTalents.Ascendance) && Spell.GetSpellCooldown("Ascendance") > TimeSpan.FromSeconds(15))
                                                  )
                                       )
                                   ),
                               Spell.Cast("Stormkeeper",
                                          ret =>
                                          ShamanSettings.UseDPSArtifactWeaponWhen == UseDPSArtifactWeaponWhen.OnCooldown || !Common.HasTalent(ShamanTalents.Ascendance) ||
                                          (ShamanSettings.UseDPSArtifactWeaponWhen == UseDPSArtifactWeaponWhen.AtHighestDPSOpportunity && Common.HasTalent(ShamanTalents.Ascendance) && Spell.GetSpellCooldown("Ascendance") > TimeSpan.FromSeconds(15))
                                          ),

                               Spell.Cast("Chain Lightning", ret => Spell.UseAOE && Unit.UnfriendlyUnitsNearTarget(10f).Count() > 1 && !Unit.UnfriendlyUnitsNearTarget(10f).Any(u => u.IsCrowdControlled())),
                               Spell.Cast("Lightning Bolt")
                               )
                           )

                       // Movement.CreateMoveToUnitBehavior( on => StyxWoW.Me.CurrentTarget, 38f, 33f)
                       // Movement.CreateMoveToRangeAndStopBehavior(ret => Me.CurrentTarget, ret => NormalPullDistance)
                       ));
        }
Example #16
0
        //private static WoWUnit _moveToHealTarget = null;
        //private static WoWUnit _lastMoveToTarget = null;

        // temporary lol name ... will revise after testing
        public static Composite CreateHealingOnlyBehavior(bool selfOnly, bool moveInRange)
        {
            BehaviorType behaveType = Dynamics.CompositeBuilder.CurrentBehaviorType;

            if (SingularRoutine.CurrentWoWContext == WoWContext.Normal)
            {
                return(new ActionAlwaysFail());
            }

            HealerManager.NeedHealTargeting = true;
            PrioritizedBehaviorList behavs = new PrioritizedBehaviorList();
            int cancelHeal    = (int)Math.Max(SingularSettings.Instance.IgnoreHealTargetsAboveHealth, Math.Max(DruidSettings.Heal.HealingTouch, DruidSettings.Heal.Regrowth));
            int maxDirectHeal = Math.Max(DruidSettings.Heal.HealingTouch, DruidSettings.Heal.Regrowth);

            Logger.WriteDebugInBehaviorCreate("Druid Healing: will cancel cast of direct heal if health reaches {0:F1}%", cancelHeal);

            #region Cleanse

            if (SingularSettings.Instance.DispelDebuffs != RelativePriority.None)
            {
                int dispelPriority = (SingularSettings.Instance.DispelDebuffs == RelativePriority.HighPriority) ? 999 : -999;
                behavs.AddBehavior(dispelPriority, "Nature's Cure", "Nature's Cure", Dispelling.CreateDispelBehavior());
            }

            #endregion

            #region Save the Group

            // Tank: Rebirth
            if (Helpers.Common.CombatRezTargetSetting != CombatRezTarget.None)
            {
                behavs.AddBehavior(799, "Rebirth Tank/Healer", "Rebirth",
                                   Helpers.Common.CreateCombatRezBehavior("Rebirth", filter => true, requirements => true)
                                   );
            }

            if (DruidSettings.Heal.HeartOfTheWild != 0)
            {
                behavs.AddBehavior(795, "Heart of the Wild @ " + DruidSettings.Heal.HeartOfTheWild + "% MinCount: " + DruidSettings.Heal.CountHeartOfTheWild, "Heart of the Wild",
                                   new Decorator(
                                       ret => Me.IsInGroup(),
                                       Spell.BuffSelf(
                                           "Heart of the Wild",
                                           req => ((WoWUnit)req).HealthPercent < DruidSettings.Heal.HeartOfTheWild &&
                                           DruidSettings.Heal.CountHeartOfTheWild <= HealerManager.Instance.TargetList
                                           .Count(p => p.IsAlive && p.HealthPercent <= DruidSettings.Heal.HeartOfTheWild && p.Location.DistanceSquared(((WoWUnit)req).Location) <= 30 * 30)
                                           )
                                       )
                                   );
            }

            if (DruidSettings.Heal.Tranquility != 0)
            {
                behavs.AddBehavior(798, "Tranquility @ " + DruidSettings.Heal.Tranquility + "% MinCount: " + DruidSettings.Heal.CountTranquility, "Tranquility",
                                   new Decorator(
                                       ret => Me.IsInGroup(),
                                       Spell.Cast(
                                           "Tranquility",
                                           mov => true,
                                           on => (WoWUnit)on,
                                           req => HealerManager.Instance.TargetList.Count(h => h.IsAlive && h.HealthPercent < DruidSettings.Heal.Tranquility && h.SpellDistance() < 40) >= DruidSettings.Heal.CountTranquility,
                                           cancel => false
                                           )
                                       )
                                   );
            }

            if (DruidSettings.Heal.Swiftmend != 0)
            {
                behavs.AddBehavior(797, "Swiftmend Direct @ " + DruidSettings.Heal.Swiftmend + "%", "Swiftmend",
                                   new Decorator(
                                       ret => (!Spell.IsSpellOnCooldown("Swiftmend") || Spell.GetCharges("Force of Nature") > 0) &&
                                       ((WoWUnit)ret).PredictedHealthPercent(includeMyHeals: true) < DruidSettings.Heal.Swiftmend &&
                                       (Me.IsInGroup()) &&
                                       Spell.CanCastHack("Rejuvenation", (WoWUnit)ret, skipWowCheck: true),
                                       new Sequence(
                                           new DecoratorContinue(
                                               req => !((WoWUnit)req).HasAnyAura("Rejuvenation", "Regrowth"),
                                               new PrioritySelector(
                                                   Spell.Buff("Rejuvenation", on => (WoWUnit)on),
                                                   Spell.Cast("Regrowth", on => (WoWUnit)on, req => !glyphRegrowth, cancel => false)
                                                   )
                                               ),
                                           new Wait(TimeSpan.FromMilliseconds(500), until => ((WoWUnit)until).HasAnyAura("Rejuvenation", "Regrowth"), new ActionAlwaysSucceed()),
                                           new Wait(TimeSpan.FromMilliseconds(1500), until => !Spell.IsGlobalCooldown() && !Spell.IsCastingOrChannelling(), new ActionAlwaysSucceed()),
                                           new PrioritySelector(
                                               Spell.Cast("Force of Nature", on => (WoWUnit)on, req => Spell.GetCharges("Force of Nature") > 1),
                                               Spell.Cast("Swiftmend", on => (WoWUnit)on)
                                               )
                                           )
                                       )
                                   );
            }

            #endregion

            #region Tank Buffing


            // Priority Buff: buff Mastery: Harmony
            if (Me.Level >= 80 && DruidSettings.Heal.BuffHarmony)
            {
                behavs.AddBehavior(100 + PriHighBase, "Buff Harmony w/ Healing Touch", "Healing Touch",
                                   new Sequence(
                                       Spell.Cast(
                                           "Healing Touch",
                                           mov => true,
                                           on => (WoWUnit)on,
                                           req =>
                {
                    if (Me.GetAuraTimeLeft("Harmony").TotalMilliseconds > 1500)
                    {
                        return(false);
                    }
                    if (((WoWUnit)req).HealthPercent < maxDirectHeal)
                    {
                        return(false);
                    }
                    if (Spell.DoubleCastContains(Me, "Harmony"))
                    {
                        return(false);
                    }
                    if (!Spell.CanCastHack("Healing Touch", (WoWUnit)req))
                    {
                        return(false);
                    }

                    Logger.Write(LogColor.Hilite, "^Harmony: buffing with Healing Touch");
                    return(true);
                },
                                           cancel => Me.GetAuraTimeLeft("Harmony").TotalMilliseconds > 1500 &&
                                           ((WoWUnit)cancel).HealthPercent > cancelHeal
                                           ),
                                       new Action(r => Spell.UpdateDoubleCast("Harmony", Me))
                                       )
                                   );
            }

            // Tank: Lifebloom
            behavs.AddBehavior(99 + PriHighBase, "Lifebloom - Tank", "Lifebloom",
                               Spell.Buff("Lifebloom", on => GetLifebloomTarget(), req => Me.Combat)
                               );

            // Tank: Rejuv if Lifebloom not trained yet
            if (DruidSettings.Heal.Rejuvenation != 0)
            {
                behavs.AddBehavior(98 + PriHighBase, "Rejuvenation - Tank", "Rejuvenation",
                                   Spell.Buff("Rejuvenation", on =>
                {
                    WoWUnit unit = GetBestTankTargetFor("Rejuvenation");
                    if (unit != null && Spell.CanCastHack("Rejuvenation", unit, skipWowCheck: true))
                    {
                        Logger.WriteDebug("Buffing Rejuvenation ON TANK: {0}", unit.SafeName());
                        return(unit);
                    }
                    return(null);
                })
                                   );
            }

            if (DruidSettings.Heal.Ironbark != 0)
            {
                if (SingularRoutine.CurrentWoWContext == WoWContext.Battlegrounds)
                {
                    behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.Ironbark) + PriHighBase, "Ironbark @ " + DruidSettings.Heal.Ironbark + "%", "Ironbark",
                                       Spell.Buff("Ironbark", on => (WoWUnit)on, req => ((WoWUnit)req).HealthPercent < DruidSettings.Heal.Ironbark)
                                       );
                }
                else
                {
                    behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.Ironbark) + PriHighBase, "Ironbark - Tank @ " + DruidSettings.Heal.Ironbark + "%", "Ironbark",
                                       Spell.Buff("Ironbark", on => Group.Tanks.FirstOrDefault(u => u.IsAlive && u.HealthPercent < DruidSettings.Heal.Ironbark && !u.HasActiveAura("Ironbark")))
                                       );
                }
            }

            if (DruidSettings.Heal.CenarionWard != 0)
            {
                if (SingularRoutine.CurrentWoWContext == WoWContext.Battlegrounds)
                {
                    behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.CenarionWard) + PriHighBase, "Cenarion Ward @ " + DruidSettings.Heal.CenarionWard + "%", "Cenarion Ward",
                                       Spell.Buff("Cenarion Ward", on => (WoWUnit)on, req => ((WoWUnit)req).HealthPercent < DruidSettings.Heal.CenarionWard)
                                       );
                }
                else
                {
                    behavs.AddBehavior(100 + PriHighBase, "Cenarion Ward - Tanks", "Cenarion Ward",
                                       Spell.Buff("Cenarion Ward", on => GetLifebloomTarget(), req => Me.Combat)
                                       );
                }
            }

            if (DruidSettings.Heal.NaturesVigil != 0)
            {
                if (SingularRoutine.CurrentWoWContext == WoWContext.Battlegrounds)
                {
                    behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.NaturesVigil) + PriHighBase, "Nature's Vigil @ " + DruidSettings.Heal.NaturesVigil + "%", "Nature's Vigil",
                                       Spell.Buff("Nature's Vigil", on => (WoWUnit)on, req => ((WoWUnit)req).HealthPercent < DruidSettings.Heal.NaturesVigil)
                                       );
                }
                else
                {
                    behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.NaturesVigil) + PriHighBase, "Nature's Vigil - Tank @ " + DruidSettings.Heal.NaturesVigil + "%", "Nature's Vigil",
                                       Spell.Buff("Nature's Vigil", on => Group.Tanks.FirstOrDefault(u => u.IsAlive && u.HealthPercent < DruidSettings.Heal.NaturesVigil && !u.HasActiveAura("Nature's Vigil")))
                                       );
                }
            }

            if (DruidSettings.Heal.TreeOfLife != 0)
            {
                behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.TreeOfLife) + PriHighBase, "Incarnation: Tree of Life @ " + DruidSettings.Heal.TreeOfLife + "% MinCount: " + DruidSettings.Heal.CountTreeOfLife, "Incarnation: Tree of Life",
                                   Spell.BuffSelf("Incarnation: Tree of Life",
                                                  req => ((WoWUnit)req).HealthPercent < DruidSettings.Heal.TreeOfLife &&
                                                  DruidSettings.Heal.CountTreeOfLife <= HealerManager.Instance.TargetList.Count(h => h.IsAlive && h.HealthPercent < DruidSettings.Heal.TreeOfLife))
                                   );
            }

            #endregion

            #region AoE Heals

            if (DruidSettings.Heal.Efflorescence != 0)
            {
                behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.Efflorescence) + PriAoeBase, "Efflorescence @ " + DruidSettings.Heal.Efflorescence, "Efflorescence",
                                   new Decorator(
                                       ret => Me.IsInGroup(),
                                       CreateMushroomSetBehavior()
                                       )
                                   );
            }

            if (DruidSettings.Heal.WildGrowth != 0)
            {
                behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.WildGrowth) + PriAoeBase, "Wild Growth @ " + DruidSettings.Heal.WildGrowth + "% MinCount: " + DruidSettings.Heal.CountWildGrowth, "Wild Growth",
                                   new Decorator(
                                       ret => Me.IsInGroup(),
                                       new PrioritySelector(
                                           // ctx => HealerManager.GetBestCoverageTarget("Wild Growth", Settings.Heal.WildGrowth, 40, 30, Settings.Heal.CountWildGrowth),
                                           Spell.Buff(
                                               "Wild Growth",
                                               on => (WoWUnit)on,
                                               req => ((WoWUnit)req).HealthPercent < DruidSettings.Heal.WildGrowth &&
                                               DruidSettings.Heal.CountWildGrowth <= HealerManager.Instance.TargetList
                                               .Count(p => p.IsAlive && p.HealthPercent <= DruidSettings.Heal.WildGrowth && p.Location.DistanceSquared(((WoWUnit)req).Location) <= 30 * 30))
                                           )
                                       )
                                   );
            }

            #endregion

            #region Direct Heals

            // Regrowth above ToL: Lifebloom so we use Clearcasting procs
            behavs.AddBehavior(200 + PriSingleBase, "Regrowth on Clearcasting", "Regrowth",
                               new Sequence(
                                   CastRegrowth(
                                       on =>
            {
                if (Spell.DoubleCastContains(Me, "Clearcasting"))
                {
                    return(null);
                }

                double clearLeft = Me.GetAuraTimeLeft("Clearcasting").TotalMilliseconds;

                // ignore if less than regrowth cast time left
                if (clearLeft < Spell.GetSpellCastTime("Regrowth").TotalMilliseconds)
                {
                    return(null);
                }

                WoWUnit target       = (WoWUnit)on;
                double healthPercent = target == null ? 0.0 : target.HealthPercent;

                // clearLeft > 3000, so clear target if not needed now and try again next pass
                if (target != null)
                {
                    // still have enough time remaining on Clearcasting buff, so hold free Regrowth a bit longer to see if greater need arises
                    if (healthPercent > maxDirectHeal)
                    {
                        target = null;
                    }
                    else if (!Spell.CanCastHack("Regrowth", target))
                    {
                        target = null;
                    }
                }

                if (target != null)
                {
                    Logger.Write(LogColor.Hilite, "^Clearcasting: Regrowth at Health {0:F1}%", healthPercent);
                }

                return(target);
            },
                                       req => true,
                                       cancel => ((WoWUnit)cancel).HealthPercent > cancelHeal && Me.GetAuraTimeLeft("Clearcasting").TotalMilliseconds > 4000 && !((WoWUnit)cancel).GetAuraTimeLeft("Lifebloom").TotalMilliseconds.Between(Me.CurrentCastTimeLeft.TotalMilliseconds, 8750)
                                       ),

                                   // add double cast entry to make sure we don't try to reuse immediately
                                   new Action(r => Spell.UpdateDoubleCast("Clearcasting", Me, 500))
                                   )
                               );

            behavs.AddBehavior(198 + PriSingleBase, "Rejuvenation @ " + DruidSettings.Heal.Rejuvenation + "%", "Rejuvenation",
                               new PrioritySelector(
                                   Spell.Buff("Rejuvenation",
                                              1,
                                              on => (WoWUnit)on,
                                              req => ((WoWUnit)req).HealthPercent < DruidSettings.Heal.Rejuvenation
                                              )
                                   )
                               );

            if (DruidSettings.Heal.HealingTouch != 0)
            {
                // roll 3 Rejuvs if Glyph of Rejuvenation equipped
                if (glyphRejuv)
                {
                    // make priority 1 higher than Noursh (-1 here due to way HealerManager.HealthToPriority works)
                    behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.HealingTouch - 1) + PriSingleBase, "Roll 3 Rejuvenations for Glyph", "Rejuvenation",
                                       new PrioritySelector(
                                           Spell.Buff("Rejuvenation",
                                                      1,
                                                      on =>
                    {
                        // iterate through so we can stop at either 3 with rejuv or first without
                        int cntHasAura = 0;
                        foreach (WoWUnit h in HealerManager.Instance.TargetList)
                        {
                            if (h.IsAlive)
                            {
                                if (!h.HasKnownAuraExpired("Rejuvenation", 1))
                                {
                                    cntHasAura++;
                                    if (cntHasAura >= 3)
                                    {
                                        return(null);
                                    }
                                }
                                else
                                {
                                    if (h.InLineOfSpellSight)
                                    {
                                        return(h);
                                    }
                                }
                            }
                        }

                        return(null);
                    },
                                                      req => true
                                                      )
                                           )
                                       );
                }
            }


            int  regrowthInstead   = 0;
            bool healingTouchKnown = SpellManager.HasSpell("Healing Touch");

            if (DruidSettings.Heal.HealingTouch != 0)
            {
                string whyRegrowth = "";
                if (SpellManager.HasSpell("Regrowth"))
                {
                    if (!healingTouchKnown)
                    {
                        regrowthInstead = Math.Max(DruidSettings.Heal.Regrowth, DruidSettings.Heal.HealingTouch);
                        whyRegrowth     = "Regrowth (since Healing Touch unknown) @ ";
                    }
                }

                if (regrowthInstead != 0)
                {
                    behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.HealingTouch) + PriSingleBase, whyRegrowth + regrowthInstead + "%", "Regrowth",
                                       new PrioritySelector(
                                           Spell.Cast(
                                               sp => (Me.Combat || !healingTouchKnown) ? "Regrowth" : "Healing Touch",
                                               mov => true,
                                               on => (WoWUnit)on,
                                               req => ((WoWUnit)req).HealthPercent <regrowthInstead,
                                                                                    cancel => ((WoWUnit)cancel).HealthPercent> cancelHeal
                                               )
                                           )
                                       );
                }
                else
                {
                    behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.HealingTouch) + PriSingleBase, "Healing Touch @ " + DruidSettings.Heal.HealingTouch + "%", "Healing Touch",
                                       new PrioritySelector(
                                           Spell.Cast("Healing Touch",
                                                      mov => true,
                                                      on => (WoWUnit)on,
                                                      req => ((WoWUnit)req).HealthPercent <DruidSettings.Heal.HealingTouch,
                                                                                           cancel => ((WoWUnit)cancel).HealthPercent> cancelHeal
                                                      )
                                           )
                                       );
                }
            }

            if (DruidSettings.Heal.Regrowth != 0 && regrowthInstead == 0)
            {
                behavs.AddBehavior(HealerManager.HealthToPriority(DruidSettings.Heal.Regrowth) + PriSingleBase, "Regrowth @ " + DruidSettings.Heal.Regrowth + "%", "Regrowth",
                                   new PrioritySelector(
                                       Spell.Cast("Regrowth",
                                                  mov => true,
                                                  on => (WoWUnit)on,
                                                  req => ((WoWUnit)req).HealthPercent <DruidSettings.Heal.Regrowth,
                                                                                       cancel => ((WoWUnit)cancel).HealthPercent> cancelHeal
                                                  )
                                       )
                                   );
            }

            #endregion

            #region Lowest Priority Healer Tasks

            behavs.AddBehavior(3, "Rejuvenation while Moving @ " + SingularSettings.Instance.IgnoreHealTargetsAboveHealth + "%", "Rejuvenation",
                               new Decorator(
                                   req => Me.IsMoving,
                                   Spell.Buff("Rejuvenation",
                                              on => HealerManager.Instance.TargetList.FirstOrDefault(h => h.IsAlive && h.HealthPercent < SingularSettings.Instance.IgnoreHealTargetsAboveHealth && !h.HasMyAura("Rejuvenation") && Spell.CanCastHack("Rejuvenation", h, true)),
                                              req => true
                                              )
                                   )
                               );

            #endregion

            behavs.OrderBehaviors();

            if (selfOnly == false && Singular.Dynamics.CompositeBuilder.CurrentBehaviorType == BehaviorType.Heal)
            {
                behavs.ListBehaviors();
            }

            return(new PrioritySelector(
                       ctx => selfOnly ? StyxWoW.Me : HealerManager.FindHighestPriorityTarget(), // HealerManager.Instance.FirstUnit,

                       Spell.WaitForCastOrChannel(),

                       new Decorator(
                           ret => !Spell.IsGlobalCooldown() && ret != null,
                           behavs.GenerateBehaviorTree()
                           ),

                       new Decorator(
                           ret => moveInRange,
                           Movement.CreateMoveToUnitBehavior(
                               ret => Battlegrounds.IsInsideBattleground ? (WoWUnit)ret : Group.Tanks.Where(a => a.IsAlive).OrderBy(a => a.Distance).FirstOrDefault(),
                               35f
                               )
                           )
                       ));
        }
 private static Composite CreateDispelBehavior()
 {
     return(new PrioritySelector(
                Spell.Cast("Cleanse", on => Me, ret => Dispelling.CanDispel(Me)),
                Spell.Cast("Cleanse", on => dispeltar, ret => Dispelling.CanDispel(dispeltar))));
 }
Example #18
0
        public static Composite CreateShamanEnhancementNormalCombat()
        {
            return(new PrioritySelector(
                       Helpers.Common.EnsureReadyToAttackFromMelee(),
                       Spell.WaitForCastOrChannel(),

                       new Decorator(
                           ret => !Spell.IsGlobalCooldown(),
                           new PrioritySelector(

                               SingularRoutine.MoveBehaviorInlineToCombat(BehaviorType.Heal),
                               SingularRoutine.MoveBehaviorInlineToCombat(BehaviorType.CombatBuffs),

                               CreateEnhanceDiagnosticOutputBehavior(),

                               Helpers.Common.CreateInterruptBehavior(),

                               Totems.CreateTotemsBehavior(),

                               Movement.WaitForFacing(),
                               Movement.WaitForLineOfSpellSight(),

                               Spell.BuffSelf("Feral Spirit", ret => !Me.CurrentTarget.IsTrivial() && NeedFeralSpirit),

                               // Artifact Weapon
                               new Decorator(
                                   ret => ShamanSettings.UseArtifactOnlyInAoE && Unit.NearbyUnitsInCombatWithMeOrMyStuff.Count() > 1,
                                   new PrioritySelector(
                                       Spell.Cast("Doom Winds", ret => ShamanSettings.UseDPSArtifactWeaponWhen == UseDPSArtifactWeaponWhen.OnCooldown)
                                       )
                                   ),
                               Spell.Cast("Doom Winds", ret => !ShamanSettings.UseArtifactOnlyInAoE && ShamanSettings.UseDPSArtifactWeaponWhen == UseDPSArtifactWeaponWhen.OnCooldown),

                               new Decorator(
                                   req => AttackEvenIfGhostWolf,
                                   new PrioritySelector(

                                       Dispelling.CreatePurgeEnemyBehavior("Purge"),

                                       Common.CreateShamanDpsShieldBehavior(),
                                       // Spell.BuffSelf("Spiritwalker's Grace", ret => StyxWoW.Me.IsMoving && StyxWoW.Me.Combat),

                                       // pull more logic (use instants first, then ranged pulls if possible)

                                       Spell.CastOnGround("Lightning Surge Totem", on => Clusters.GetBestUnitForCluster(Unit.NearbyUnfriendlyUnits, ClusterType.Radius, 8f).Location,
                                                          ret => ShamanSettings.UseLightningSurgeTotem && SingularRoutine.CurrentWoWContext == WoWContext.Normal &&
                                                          Unit.UnfriendlyUnits(8).Count() >= ShamanSettings.LightningSurgeTotemCount),
                                       Spell.Cast("Ascendance", req => Me.HealthPercent <= ShamanSettings.AscendanceHealthPercent),
                                       Spell.Cast("Lava Lash", req => Me.HasActiveAura("Hot Hand")),
                                       Spell.Cast("Windsong"),
                                       Spell.Cast("Rockbiter",
                                                  req => (Common.HasTalent(ShamanTalents.Boulderfist) && !Me.HasActiveAura("Boulderfist")) ||
                                                  (Common.HasTalent(ShamanTalents.Landslide) && !Me.HasActiveAura("Landslide"))),
                                       Spell.Cast("Frostbrand", req => Common.HasTalent(ShamanTalents.Hailstorm) && !Me.HasActiveAura("Frostbrand")),
                                       Spell.Cast("Boulderfist", req => Me.CurrentMaelstrom < 130 && Spell.GetCharges("Boulderfist") >= 2),
                                       Spell.Cast("Flametongue", req => !Me.HasActiveAura("Flametongue")),
                                       Spell.Cast("Feral Spirit", ret => NeedFeralSpirit),
                                       Spell.Cast("Earthen Spike"),
                                       Spell.Cast("Crash Lightning", when => Unit.UnfriendlyUnitsNearTarget(10).Count(u => u.TaggedByMe || !u.TaggedByOther) >= 2),
                                       Spell.Cast("Stormstrike"),
                                       Spell.Cast("Crash Ligthning", req => Common.HasTalent(ShamanTalents.CrashingStorm)),
                                       Spell.Cast("Lava Lash", req => Me.CurrentMaelstrom > 110),
                                       Spell.Cast("Sundering", req => SingularRoutine.CurrentWoWContext != WoWContext.Instances),
                                       Spell.Cast("Rockbiter"),
                                       Spell.Cast("Lightning Bolt", req => !Me.CurrentTarget.IsWithinMeleeRange),
                                       // won't happen often, but if at range and no abilities enter ghost wolf
                                       CreateInCombatGapCloser()
                                       )
                                   )
                               )
                           ),

                       Movement.CreateMoveToMeleeBehavior(true)
                       ));
        }
Example #19
0
        internal static Composite CreatePaladinHealBehavior(bool selfOnly, bool moveInRange)
        {
            HealerManager.NeedHealTargeting = true;

            return
                (new PrioritySelector(
                     ctx => _healTarget = (selfOnly ? StyxWoW.Me : HealerManager.Instance.FirstUnit),
                     new Decorator(
                         ret => ret != null && (selfOnly || moveInRange || ((WoWUnit)ret).InLineOfSpellSight && ((WoWUnit)ret).DistanceSqr < 40 * 40),
                         new PrioritySelector(
                             Spell.WaitForCast(),
                             new Decorator(
                                 ret => moveInRange,
                                 Movement.CreateMoveToLosBehavior(ret => (WoWUnit)ret)),
                             Dispelling.CreateDispelBehavior(),

                             Spell.BuffSelf("Avenging Wrath",
                                            req => Unit.NearbyFriendlyPlayers.Count(p =>
                                                                                    p.HealthPercent <= SingularSettings.Instance.Paladin().AvengingHealth&&
                                                                                    p.DistanceSqr < 40 * 40) >= SingularSettings.Instance.Paladin().AvengingCount),

                             Spell.BuffSelf("Holy Avenger", req => Me.HasAura("Avenging Wrath")),

                             Spell.Cast(
                                 "Light of Dawn",
                                 ret => StyxWoW.Me,
                                 ret => Unit.NearbyFriendlyPlayers.Count(p =>
                                                                         p.HealthPercent <= SingularSettings.Instance.Paladin().AuraMasteryHealth&&
                                                                         p.DistanceSqr < 40 * 40 && StyxWoW.Me.IsSafelyFacing(p.Location)) >= SingularSettings.Instance.Paladin().AuraMasteryCount),

                             Spell.Cast(
                                 "Beacon of Light",
                                 ret => (WoWUnit)ret,
                                 ret => ret is WoWPlayer && !Common.HasTalent(PaladinTalents.BeaconOfVirtue) && Group.Tanks.Contains((WoWPlayer)ret) && Group.Tanks.All(t => !t.HasMyAura("Beacon of Light"))),
                             Spell.Cast(
                                 "Beacon of Light",
                                 ret => (WoWUnit)ret,
                                 ret => ret is WoWPlayer && Common.HasTalent(PaladinTalents.BeaconOfVirtue) && Unit.NearbyFriendlyPlayers.Count(p =>
                                                                                                                                                p.HealthPercent <= SingularSettings.Instance.Paladin().BeaconVirtueHealth&& p.DistanceSqr < 30 * 30) >= SingularSettings.Instance.Paladin().BeaconVirtueCount),
                             Spell.Cast(
                                 "Holy Shock",
                                 ret => (WoWUnit)ret,
                                 ret => ((WoWUnit)ret).HealthPercent <= SingularSettings.Instance.Paladin().HolyShockHealth),
                             Spell.Cast("Holy Prism", req => Me.GotTarget),
                             Spell.Cast(
                                 "Bestow Faith",
                                 ret => (WoWUnit)ret,
                                 ret => ((WoWUnit)ret).HealthPercent <= SingularSettings.Instance.Paladin().BestowFaithHealth),
                             Spell.Cast(
                                 "Lay on Hands",
                                 ret => (WoWUnit)ret,
                                 ret => StyxWoW.Me.Combat && !((WoWUnit)ret).HasAura("Forbearance") &&
                                 ((WoWUnit)ret).HealthPercent <= SingularSettings.Instance.Paladin().LayOnHandsHealth),
                             Spell.Cast(
                                 "Light of Dawn",
                                 ret => StyxWoW.Me,
                                 ret => Unit.NearbyFriendlyPlayers.Count(p =>
                                                                         p.HealthPercent <= SingularSettings.Instance.Paladin().LightOfDawnHealth&& p != StyxWoW.Me &&
                                                                         p.DistanceSqr < 30 * 30 && StyxWoW.Me.IsSafelyFacing(p.Location)) >= SingularSettings.Instance.Paladin().LightOfDawnCount),
                             Spell.Cast(
                                 "Tyr's Deliverance",
                                 ret => StyxWoW.Me,
                                 ret => PaladinSettings.UseDPSArtifactWeaponWhen != UseDPSArtifactWeaponWhen.None && Unit.NearbyFriendlyPlayers.Count(p =>
                                                                                                                                                      p.HealthPercent <= SingularSettings.Instance.Paladin().TyrsDeliveranceHealth&&
                                                                                                                                                      p.DistanceSqr < 15 * 15) >= SingularSettings.Instance.Paladin().TyrsDeliveranceCount),
                             Spell.Cast(
                                 "Flash of Light",
                                 ret => (WoWUnit)ret,
                                 ret => ((WoWUnit)ret).HealthPercent <= SingularSettings.Instance.Paladin().FlashOfLightHealth),
                             Spell.Cast(
                                 "Holy Light",
                                 ret => (WoWUnit)ret,
                                 ret => ((WoWUnit)ret).HealthPercent <= SingularSettings.Instance.Paladin().HolyLightHealth),
                             new Decorator(
                                 ret => StyxWoW.Me.Combat && StyxWoW.Me.GotTarget() && Unit.NearbyFriendlyPlayers.Count(u => u.IsInMyPartyOrRaid()) == 0,
                                 new PrioritySelector(
                                     Helpers.Common.EnsureReadyToAttackFromMelee(),
                                     Helpers.Common.CreateInterruptBehavior(),
                                     Spell.Buff("Judgment"),
                                     Spell.Cast("Holy Shock"),
                                     Spell.Cast("Crusader Strike"),
                                     Movement.CreateMoveToMeleeBehavior(true)
                                     )
                                 ),
                             new Decorator(
                                 ret => moveInRange,
                                 // Get in range
                                 Movement.CreateMoveToUnitBehavior(on => _healTarget, 35f, 30f)
                                 )
                             )
                         )
                     ));
        }
Example #20
0
        public static Composite CreateMistweaverMonkHealing(bool selfOnly = false)
        {
            HealerManager.NeedHealTargeting = true;
            PrioritizedBehaviorList behavs = new PrioritizedBehaviorList();

            int cancelHeal = SingularSettings.Instance.IgnoreHealTargetsAboveHealth;

            cancelHeal = (int)Math.Max(cancelHeal, MonkSettings.MistHealSettings.RenewingMist);
            cancelHeal = (int)Math.Max(cancelHeal, MonkSettings.MistHealSettings.EnvelopingMist);
            cancelHeal = (int)Math.Max(cancelHeal, MonkSettings.MistHealSettings.Effuse);

            bool moveInRange = false;

            if (!selfOnly)
            {
                moveInRange = (SingularRoutine.CurrentWoWContext == WoWContext.Battlegrounds);
            }

            Logger.WriteDebugInBehaviorCreate("Monk Healing: will cancel cast of direct heal if health reaches {0:F1}%", cancelHeal);

            int dispelPriority = (SingularSettings.Instance.DispelDebuffs == RelativePriority.HighPriority) ? 999 : -999;

            if (SingularSettings.Instance.DispelDebuffs != RelativePriority.None)
            {
                behavs.AddBehavior(dispelPriority, "Detox", "Detox", Dispelling.CreateDispelBehavior());
            }

            CreateMistweaverHealingRotation(selfOnly, behavs);

            behavs.OrderBehaviors();

            if (selfOnly == false && Singular.Dynamics.CompositeBuilder.CurrentBehaviorType == BehaviorType.Combat)
            {
                behavs.ListBehaviors();
            }


            return(new PrioritySelector(
                       // ctx => selfOnly ? StyxWoW.Me : HealerManager.FindLowestHealthTarget(),
                       // ctx => selfOnly ? StyxWoW.Me : HealerManager.Instance.FirstUnit,
                       ctx => selfOnly ? StyxWoW.Me : MyHealTarget,

                       CreateMistWeaverDiagnosticOutputBehavior(ret => (WoWUnit)ret),

                       new Decorator(
                           ret => ret != null &&
                           (Me.Combat || ((WoWUnit)ret).Combat || ((WoWUnit)ret).PredictedHealthPercent() <= 99),
                           // && HealerManager.SavingHealUnit == null
                           // && (selfOnly || !MonkSettings.MistHealSettings.HealFromMelee || !Me.GotTarget() || Me.CurrentTarget.IsWithinMeleeRange),

                           new PrioritySelector(
                               new Decorator(
                                   ret => !Spell.IsGlobalCooldown(),
                                   new PrioritySelector(

                                       behavs.GenerateBehaviorTree(),

                                       new Decorator(
                                           ret => moveInRange,
                                           new Sequence(
                                               new Action(r => _moveToHealUnit = (WoWUnit)r),
                                               new PrioritySelector(
                                                   Movement.CreateMoveToLosBehavior(on => _moveToHealUnit),
                                                   Movement.CreateMoveToUnitBehavior(on => _moveToHealUnit, 40f, 34f)
                                                   )
                                               )
                                           )
                                       )
                                   )
                               )
                           )
                       ));
        }