Пример #1
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)
                                                   )
                                               )
                                           )
                                       )
                                   )
                               )
                           )
                       ));
        }
Пример #2
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
                               )
                           )
                       ));
        }
Пример #3
0
        public static Composite CreateDpsShamanOffHealBehavior()
        {
            HealerManager.NeedHealTargeting = true;
            PrioritizedBehaviorList behavs = new PrioritizedBehaviorList();
            int cancelHeal = (int)Math.Max(SingularSettings.Instance.IgnoreHealTargetsAboveHealth, ShamanSettings.OffHealSettings.HealingSurge);

            bool 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, "Cleanse Spirit", null, Dispelling.CreateDispelBehavior());
 */
            #region Save the Group

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.OffHealSettings.AncestralSwiftness) + 500,
                               String.Format("Oh Shoot Heal @ {0}%", ShamanSettings.OffHealSettings.AncestralSwiftness),
                               null,
                               new Decorator(
                                   ret => (Me.Combat || ((WoWUnit)ret).Combat) && ((WoWUnit)ret).PredictedHealthPercent() < ShamanSettings.OffHealSettings.AncestralSwiftness,
                                   new PrioritySelector(
                                       Spell.HandleOffGCD(Spell.BuffSelf("Ancestral Swiftness")),
                                       Spell.Cast("Healing Surge", on => (WoWUnit)on)
                                       )
                                   )
                               );

            #endregion

            #region AoE Heals

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.OffHealSettings.HealingStreamTotem) + 300,
                               string.Format("Healing Stream Totem @ {0}%", ShamanSettings.OffHealSettings.HealingStreamTotem),
                               "Healing Stream Totem",
                               new Decorator(
                                   ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                   Spell.Cast(
                                       "Healing Stream Totem",
                                       on => (!Me.Combat || Totems.Exist(WoWTotemType.Water)) ? null : HealerManager.Instance.TargetList.FirstOrDefault(p => p.PredictedHealthPercent() < ShamanSettings.OffHealSettings.HealingStreamTotem && p.Distance <= Totems.GetTotemRange(WoWTotem.HealingStream))
                                       )
                                   )
                               );

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.OffHealSettings.HealingRain) + 200,
                               string.Format("Healing Rain @ {0}% Count={1}", ShamanSettings.OffHealSettings.HealingRain, ShamanSettings.OffHealSettings.MinHealingRainCount),
                               "Healing Rain",
                               Spell.CastOnGround("Healing Rain", on => Restoration.GetBestHealingRainTarget(), req => HealerManager.Instance.TargetList.Count() > 1, false)
                               );

            #endregion

            #region Single Target Heals

            behavs.AddBehavior(HealerManager.HealthToPriority(ShamanSettings.OffHealSettings.HealingSurge),
                               string.Format("Healing Surge @ {0}%", ShamanSettings.OffHealSettings.HealingSurge),
                               "Healing Surge",
                               Spell.Cast("Healing Surge",
                                          mov => true,
                                          on => (WoWUnit)on,
                                          req => ((WoWUnit)req).PredictedHealthPercent(includeMyHeals: true) < ShamanSettings.OffHealSettings.HealingSurge,
                                          cancel => ((WoWUnit)cancel).HealthPercent > cancelHeal
                                          )
                               );

            #endregion

            behavs.OrderBehaviors();

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

            return(new PrioritySelector(
                       ctx => HealerManager.FindLowestHealthTarget(), // HealerManager.Instance.FirstUnit,

                       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(),

                                       /*
                                        *                          Spell.Cast("Earth Shield",
                                        *                              ret => (WoWUnit)ret,
                                        *                              ret => ret is WoWUnit && Group.Tanks.Contains((WoWUnit)ret) && Group.Tanks.All(t => !t.HasMyAura("Earth Shield"))),
                                        */

                                       behavs.GenerateBehaviorTree(),

                                       new Decorator(
                                           ret => moveInRange,
                                           new Sequence(
                                               new Action(r => _moveToHealUnit = (WoWUnit)r),
                                               new PrioritySelector(
                                                   Movement.CreateMoveToLosBehavior(on => _moveToHealUnit),
                                                   Movement.CreateMoveToUnitBehavior(on => _moveToHealUnit, 30f, 25f)
                                                   )
                                               )
                                           )
                                       )
                                   )
                               )
                           )
                       ));
        }
Пример #4
0
        public static Composite CreateRestoShamanHealingOnlyBehavior(bool selfOnly, bool moveInRange)
        {
            HealerManager.NeedHealTargeting = true;
            PrioritizedBehaviorList behavs = new PrioritizedBehaviorList();

            behavs.AddBehavior(HealthToPriority(SingularSettings.Instance.Shaman.Heal.AncestralSwiftness),
                               "Unleash Elements",
                               "Unleash Elements",
                               Spell.Buff("Unleash Elements",
                                          ret => (WoWUnit)ret,
                                          ret => (Me.IsMoving || ((WoWUnit)ret).GetPredictedHealthPercent() < SingularSettings.Instance.Shaman.Heal.AncestralSwiftness) &&
                                          Common.IsImbuedForHealing(Me.Inventory.Equipped.MainHand)
                                          ));

            behavs.AddBehavior(HealthToPriority(SingularSettings.Instance.Shaman.Heal.AncestralSwiftness),
                               String.Format("Ancestral Swiftness @ {0}%", SingularSettings.Instance.Shaman.Heal.AncestralSwiftness),
                               "Ancestral Swiftness",
                               new Sequence(
                                   Spell.BuffSelf("Ancestral Swiftness", ret => ((WoWUnit)ret).GetPredictedHealthPercent() < SingularSettings.Instance.Shaman.Heal.AncestralSwiftness),
                                   Spell.Heal("Greater Healing Wave", ret => (WoWUnit)ret)
                                   ));

            behavs.AddBehavior(HealthToPriority(SingularSettings.Instance.Shaman.Heal.GreaterHealingWave), "Greater Healing Wave", "Greater Healing Wave",
                               Spell.Heal("Greater Healing Wave", ret => (WoWUnit)ret, ret => ((WoWUnit)ret).GetPredictedHealthPercent() < SingularSettings.Instance.Shaman.Heal.GreaterHealingWave));

            behavs.AddBehavior(HealthToPriority(SingularSettings.Instance.Shaman.Heal.HealingWave), "Healing Wave", "Healing Wave",
                               Spell.Heal("Healing Wave", ret => (WoWUnit)ret, ret => ((WoWUnit)ret).GetPredictedHealthPercent() < SingularSettings.Instance.Shaman.Heal.HealingWave));

            behavs.AddBehavior(HealthToPriority(SingularSettings.Instance.Shaman.Heal.HealingSurge), "Healing Surge", "Healing Surge",
                               Spell.Heal("Healing Surge", ret => (WoWUnit)ret, ret => ((WoWUnit)ret).GetPredictedHealthPercent() < SingularSettings.Instance.Shaman.Heal.HealingSurge));

            behavs.AddBehavior(HealthToPriority(SingularSettings.Instance.Shaman.Heal.ChainHeal), "Chain Heal", "Chain Heal",
                               new Decorator(
                                   ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                   new PrioritySelector(
                                       new PrioritySelector(
                                           context => Clusters.GetBestUnitForCluster(ChainHealPlayers, ClusterType.Chained, ChainHealHopRange),
                                           Spell.Heal(
                                               "Chain Heal", ret => (WoWPlayer)ret,
                                               ret => Clusters.GetClusterCount((WoWPlayer)ret, ChainHealPlayers, ClusterType.Chained, ChainHealHopRange) >= 3)
                                           )
                                       )
                                   )
                               );

            behavs.AddBehavior(HealthToPriority(SingularSettings.Instance.Shaman.Heal.HealingRain), "Healing Rain", "Healing Rain",
                               new Decorator(
                                   ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                   new PrioritySelector(
                                       context => Clusters.GetBestUnitForCluster(Unit.NearbyFriendlyPlayers.Cast <WoWUnit>(), ClusterType.Radius, 10f),
                                       Spell.CastOnGround(
                                           "Healing Rain",
                                           ret => ((WoWPlayer)ret).Location,
                                           ret => (StyxWoW.Me.GroupInfo.IsInRaid ? 3 : 2) < Clusters.GetClusterCount((WoWPlayer)ret, Unit.NearbyFriendlyPlayers.Cast <WoWUnit>(), ClusterType.Radius, 10f))
                                       )
                                   )
                               );

            behavs.AddBehavior(HealthToPriority(SingularSettings.Instance.Shaman.Heal.SpiritLinkTotem), "Spirit Link Totem", "Spirit Link Totem",
                               new Decorator(
                                   ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                   Spell.Cast(
                                       "Spirit Link Totem", ret => (WoWPlayer)ret,
                                       ret => Unit.NearbyFriendlyPlayers.Count(
                                           p => p.GetPredictedHealthPercent() < SingularSettings.Instance.Shaman.Heal.SpiritLinkTotem && p.Distance <= Totems.GetTotemRange(WoWTotem.SpiritLink)) >= (Me.GroupInfo.IsInRaid ? 3 : 2)
                                       )
                                   )
                               );

            behavs.AddBehavior(HealthToPriority(SingularSettings.Instance.Shaman.Heal.HealingTideTotemPercent), "Healing Tide Totem", "Healing Tide Totem",
                               new Decorator(
                                   ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                   Spell.Cast(
                                       "Healing Tide Totem",
                                       ret => Unit.NearbyFriendlyPlayers.Count(p => p.GetPredictedHealthPercent() < SingularSettings.Instance.Shaman.Heal.HealingTideTotemPercent && p.Distance <= Totems.GetTotemRange(WoWTotem.HealingTide)) >= (Me.GroupInfo.IsInRaid ? 3 : 2)
                                       )
                                   )
                               );

            behavs.AddBehavior(HealthToPriority(SingularSettings.Instance.Shaman.Heal.HealingStreamTotem), "Healing Stream Totem", "Healing Stream Totem",
                               new Decorator(
                                   ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                   Spell.Cast(
                                       "Healing Stream Totem",
                                       ret => Unit.NearbyFriendlyPlayers.Count(p => p.GetPredictedHealthPercent() < SingularSettings.Instance.Shaman.Heal.HealingStreamTotem && p.Distance <= Totems.GetTotemRange(WoWTotem.HealingTide)) >= (Me.GroupInfo.IsInRaid ? 3 : 2) &&
                                       !Totems.Exist(WoWTotemType.Water)
                                       )
                                   )
                               );

            behavs.AddBehavior(HealthToPriority(SingularSettings.Instance.Shaman.Heal.Ascendance), "Ascendance", "Ascendance",
                               new Decorator(
                                   ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                   Spell.BuffSelf(
                                       "Ascendance",
                                       ret => Unit.NearbyFriendlyPlayers.Count(p => p.GetPredictedHealthPercent() < SingularSettings.Instance.Shaman.Heal.Ascendance) >= (Me.GroupInfo.IsInRaid ? 3 : 2)
                                       )
                                   )
                               );


            behavs.OrderBehaviors();
            behavs.ListBehaviors();


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

                       Spell.WaitForCast(),

                       new Decorator(
                           ret => Me.IsCasting,
                           new ActionAlwaysSucceed()),

                       new Decorator(
                           ret => ret != null && ((WoWUnit)ret).GetPredictedHealthPercent() <= SingularSettings.Instance.IgnoreHealTargetsAboveHealth,

                           new PrioritySelector(

                               new Sequence(
                                   new Decorator(
                                       ret => guidLastHealTarget != ((WoWUnit)ret).Guid,
                                       new Action(ret =>
            {
                guidLastHealTarget = ((WoWUnit)ret).Guid;
                Logger.WriteDebug(Color.LightGreen, "Heal Target - {0} {1:F1}% @ {2:F1} yds", ((WoWUnit)ret).SafeName(), ((WoWUnit)ret).GetPredictedHealthPercent(), ((WoWUnit)ret).Distance);
            })),
                                   new Action(ret => { return RunStatus.Failure; })
                                   ),

/*
 *                      new Sequence(
 *                          new Action(ret => Logger.WriteDebug(Color.LightGreen, "-- past spellcast")),
 *                          new Action(ret => { return RunStatus.Failure; })
 *                          ),
 */
                               new Decorator(
                                   ret => !SpellManager.GlobalCooldown,

                                   new PrioritySelector(

                                       /*
                                        *                          new Sequence(
                                        *                              new Action(ret => Logger.WriteDebug(Color.LightGreen, "-- past gcd")),
                                        *                              new Action(ret => { return RunStatus.Failure; })
                                        *                              ),
                                        */
                                       Totems.CreateTotemsBehavior(),

                                       Spell.Heal("Earth Shield",
                                                  ret => (WoWUnit)ret,
                                                  ret => ret is WoWPlayer && Group.Tanks.Contains((WoWPlayer)ret) && Group.Tanks.All(t => !t.HasMyAura("Earth Shield"))),

                                       // Just pop RT on CD. Plain and simple. Calling GetBestRiptideTarget will see if we can spread RTs (T12 2pc)
                                       Spell.Heal("Riptide",
                                                  ret => GetBestRiptideTarget((WoWPlayer)ret),
                                                  ret => !Me.HasAnyAura("Tidal Waves", "Ancestral Swiftness") &&
                                                  (((WoWPlayer)ret).GetPredictedHealthPercent() > 15 || Spell.GetSpellCooldown("Ancestral Swiftness").TotalMinutes > 0f) // use Ancestral Swiftness value to check
                                                  ),

                                       behavs.GenerateBehaviorTree(),

                                       Spell.Heal("Riptide",
                                                  ret => GetBestRiptideTarget((WoWPlayer)ret),
                                                  ret => !Me.HasAura("Ancestral Swiftness"))

    #if false
                                       ,
                                       new Sequence(
                                           new Action(ret => Logger.WriteDebug(Color.LightGreen, "No Action - stunned:{0} silenced:{1}"
                                                                               , Me.Stunned || Me.IsStunned()
                                                                               , Me.Silenced
                                                                               )),
                                           new Action(ret => { return RunStatus.Failure; })
                                           )
                                       ,

                                       new Decorator(
                                           ret => StyxWoW.Me.Combat && StyxWoW.Me.GotTarget && !Unit.NearbyFriendlyPlayers.Any(u => u.IsInMyPartyOrRaid),
                                           new PrioritySelector(
                                               Movement.CreateMoveToLosBehavior(),
                                               Movement.CreateFaceTargetBehavior(),
                                               Helpers.Common.CreateInterruptSpellCast(ret => StyxWoW.Me.CurrentTarget),

                                               Spell.Cast("Earth Shock"),
                                               Spell.Cast("Lightning Bolt"),
                                               Movement.CreateMoveToTargetBehavior(true, 35f)
                                               ))
    #endif
                                       )
                                   ),

                               new Decorator(
                                   ret => moveInRange,
                                   Movement.CreateMoveToRangeAndStopBehavior(ret => (WoWUnit)ret, ret => 38f))
                               )
                           )
                       ));
        }
Пример #5
0
        //private static WoWUnit _moveToHealTarget = null;
        //private static WoWUnit _lastMoveToTarget = null;

        public static Composite CreateHolyHealOnlyBehavior(bool selfOnly, bool moveInRange)
        {
            if (SingularRoutine.CurrentWoWContext == WoWContext.Normal)
            {
                return(new ActionAlwaysFail());
            }

            HealerManager.NeedHealTargeting = true;
            PrioritizedBehaviorList behavs = new PrioritizedBehaviorList();
            int cancelHeal = Math.Max(SingularSettings.Instance.IgnoreHealTargetsAboveHealth, Math.Max(PriestSettings.HolyHeal.Heal, PriestSettings.HolyHeal.Renew));

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

            if (SingularSettings.Instance.DispelDebuffs != RelativePriority.None)
            {
                int dispelPriority = (SingularSettings.Instance.DispelDebuffs == RelativePriority.HighPriority) ? 999 : -999;
                behavs.AddBehavior(dispelPriority, "Dispel", null, Common.CreatePriestDispelBehavior());
            }

            #region Save the Group

            if (PriestSettings.HolyHeal.DivineHymn != 0)
            {
                behavs.AddBehavior(HealthToPriority(PriestSettings.HolyHeal.DivineHymn) + 300, "Divine Hymn @ " + PriestSettings.HolyHeal.DivineHymn + "% MinCount: " + PriestSettings.HolyHeal.CountDivineHymn, "Divine Hymn",
                                   new Decorator(
                                       ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                       new PrioritySelector(
                                           context => HealerManager.GetBestCoverageTarget("Divine Hymn", PriestSettings.HolyHeal.DivineHymn, 0, 40, PriestSettings.HolyHeal.CountDivineHymn),
                                           new Decorator(
                                               ret => ret != null,
                                               Spell.Cast("Divine Hymn", mov => false, on => (WoWUnit)on, req => true, cancel => false)
                                               )
                                           )
                                       )
                                   );
            }

            if (PriestSettings.HolyHeal.GuardianSpirit != 0)
            {
                behavs.AddBehavior(HealthToPriority(PriestSettings.HolyHeal.GuardianSpirit) + 300, "Guardian Spirit @ " + PriestSettings.HolyHeal.GuardianSpirit + "%", "Guardian Spirit",
                                   Spell.Cast("Guardian Spirit",
                                              mov => false,
                                              on => (WoWUnit)on,
                                              req => ((WoWUnit)req).HealthPercent < PriestSettings.HolyHeal.GuardianSpirit
                                              )
                                   );
            }

            if (PriestSettings.LightOfTuure != 0)
            {
                behavs.AddBehavior(HealthToPriority(PriestSettings.LightOfTuure) + 300, "Light of T'uure @ " + PriestSettings.LightOfTuure + "%", "Light of T'uure",
                                   Spell.Cast("Light of T'uure",
                                              mov => false,
                                              on => (WoWUnit)on,
                                              req => ((WoWUnit)req).HealthPercent < PriestSettings.LightOfTuure && !((WoWUnit)req).HasAura("Light of T'uure") &&
                                              Group.Tanks.Contains(((WoWUnit)req))
                                              )
                                   );
            }

            #endregion

            #region AoE Heals

            int maxDirectHeal = Math.Max(PriestSettings.HolyHeal.FlashHeal, PriestSettings.HolyHeal.Heal);

            // instant, so cast this first ALWAYS
            if (PriestSettings.HolyHeal.HolyWordSanctify != 0)
            {
                behavs.AddBehavior(398, "Holy Word: Sanctify @ " + PriestSettings.HolyHeal.HolyWordSanctify + "% MinCount: " + PriestSettings.HolyHeal.CountHolyWordSanctify, "Holy Word: Sanctify",
                                   new Decorator(
                                       ret => true,
                                       new PrioritySelector(
                                           context => HealerManager.GetBestCoverageTarget("Holy Word: Sanctify", PriestSettings.HolyHeal.HolyWordSanctify, 40, 10, PriestSettings.HolyHeal.CountHolyWordSanctify),
                                           new Decorator(
                                               ret => ret != null,
                                               Spell.CastOnGround("Holy Word: Sanctify", on => (WoWUnit)on, req => true, false)
                                               )
                                           )
                                       )
                                   );
            }

            if (PriestSettings.HolyHeal.PrayerOfMending != 0)
            {
                behavs.AddBehavior(397, "Prayer of Mending @ " + PriestSettings.HolyHeal.PrayerOfMending + "%", "Prayer of Mending",
                                   Spell.Cast("Prayer of Mending",
                                              mov => true,
                                              on => (WoWUnit)on,
                                              req => !((WoWUnit)req).IsMe && ((WoWUnit)req).HealthPercent <PriestSettings.HolyHeal.PrayerOfMending,
                                                                                                           cancel => ((WoWUnit)cancel).HealthPercent> cancelHeal
                                              )
                                   );
            }

/*
 *          behavs.AddBehavior(HealthToPriority(PriestSettings.HolyHeal.HolyLevel90Talent) + 200, "Divine Star",
 *              "Divine Star",
 *              new Decorator(
 *                  ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
 *                  new Decorator(
 *                      ret =>
 *                          Clusters.GetClusterCount(Me,
 *                              HealerManager.Instance.TargetList.Where(
 *                                  u => u.HealthPercent < PriestSettings.HolyHeal.CountLevel90Talent).ToList(),
 *                              ClusterType.PathToUnit, 4) >= PriestSettings.HolyHeal.CountLevel90Talent,
 *                      Spell.Cast("Divine Star", on => (WoWUnit)on, req => true)
 *                      )
 *                  )
 *              );
 */

            if (PriestSettings.HolyHeal.HolyLevel90Talent != 0)
            {
                behavs.AddBehavior(397,
                                   "Halo @ " + PriestSettings.HolyHeal.HolyLevel90Talent + "% MinCount: " +
                                   PriestSettings.HolyHeal.CountLevel90Talent, "Halo",
                                   new Decorator(
                                       ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                       new Decorator(
                                           ret => ret != null
                                           &&
                                           HealerManager.Instance.TargetList.Count(
                                               u =>
                                               u.IsAlive && u.HealthPercent < PriestSettings.HolyHeal.HolyLevel90Talent &&
                                               u.Distance < 30) >= PriestSettings.HolyHeal.CountLevel90Talent && Unit.UnfriendlyUnits(30).Any(u => u.Combat && !u.IsCrowdControlled()),
                                           Spell.Cast("Halo", req => true)
                                           )
                                       )
                                   );
            }

            if (PriestSettings.HolyHeal.BindingHeal != 0)
            {
                behavs.AddBehavior(396, "Binding Heal @ " + PriestSettings.HolyHeal.BindingHeal + "% MinCount: 2", "Binding Heal",
                                   Spell.Cast("Binding Heal",
                                              mov => true,
                                              on => (WoWUnit)on,
                                              req => !((WoWUnit)req).IsMe && ((WoWUnit)req).HealthPercent < PriestSettings.HolyHeal.BindingHeal && Me.HealthPercent <PriestSettings.HolyHeal.BindingHeal,
                                                                                                                                                                     cancel => ((WoWUnit)cancel).HealthPercent> cancelHeal
                                              )
                                   );
            }

            if (PriestSettings.HolyHeal.CircleOfHealing != 0)
            {
                behavs.AddBehavior(395, "Circle of Healing @ " + PriestSettings.HolyHeal.CircleOfHealing + "% MinCount: " + PriestSettings.HolyHeal.CountCircleOfHealing, "Circle of Healing",
                                   new Decorator(
                                       ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                       new PrioritySelector(
                                           context => HealerManager.GetBestCoverageTarget("Circle of Healing", PriestSettings.HolyHeal.CircleOfHealing, 40, 30, PriestSettings.HolyHeal.CountCircleOfHealing),
                                           Spell.Cast("Circle of Healing", on => (WoWUnit)on)
                                           )
                                       )
                                   );
            }

            if (PriestSettings.HolyHeal.PrayerOfHealing != 0)
            {
                behavs.AddBehavior(394, "Prayer of Healing @ " + PriestSettings.HolyHeal.PrayerOfHealing + "% MinCount: " + PriestSettings.HolyHeal.CountPrayerOfHealing, "Prayer of Healing",
                                   new Decorator(
                                       ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                       new PrioritySelector(
                                           context => HealerManager.GetBestCoverageTarget("Prayer of Healing", PriestSettings.HolyHeal.PrayerOfHealing, 40, 20, PriestSettings.HolyHeal.CountPrayerOfHealing),
                                           Spell.Cast("Prayer of Healing", on => (WoWUnit)on)
                                           )
                                       )
                                   );
            }

            #endregion

            /*
             * HolyWordSanctify       Holy Word: Sanctify
             * HolyWordSerenity        Holy Word: Serenity
             * CircleOfHealing         Circle of Healing
             * PrayerOfHealing         Prayer of Healing
             * DivineHymn              Divine Hymn
             * GuardianSpirit          Guardian Spirit
             * VoidShift               Void Shift
             */

            #region Direct Heals

            if (maxDirectHeal != 0) // Nuke a Flash Heal
            {
                behavs.AddBehavior(400, "Surge of Light @ " + maxDirectHeal + "%", "Flash Heal",
                                   Spell.Cast("Flash Heal",
                                              mov => false,
                                              on => (WoWUnit)on,
                                              req => Me.HasActiveAura("Surge of Light") && ((WoWUnit)req).HealthPercent < 85
                                              )
                                   );
            }

            if (PriestSettings.HolyHeal.HolyWordSerenity != 0)
            {
                behavs.AddBehavior(HealthToPriority(1) + 4, "Holy Word: Serenity @ " + PriestSettings.HolyHeal.HolyWordSerenity + "%", "Holy Word: Serenity",
                                   Spell.CastHack("Holy Word: Serenity",
                                                  on => (WoWUnit)on,
                                                  req => ((WoWUnit)req).HealthPercent < PriestSettings.HolyHeal.HolyWordSerenity
                                                  )
                                   );
            }

            var cmt             = "";
            var flashHealHealth = PriestSettings.HolyHeal.FlashHeal;
            if (!SpellManager.HasSpell("Heal"))
            {
                flashHealHealth = Math.Max(flashHealHealth, PriestSettings.HolyHeal.Heal);
                cmt             = "(Adjusted for Heal)";
            }

            if (flashHealHealth != 0)
            {
                behavs.AddBehavior(HealthToPriority(PriestSettings.HolyHeal.FlashHeal), "Flash Heal @ " + flashHealHealth + "% " + cmt, "Flash Heal",
                                   Spell.Cast("Flash Heal",
                                              mov => true,
                                              on => (WoWUnit)on,
                                              req => ((WoWUnit)req).HealthPercent <flashHealHealth,
                                                                                   cancel => ((WoWUnit)cancel).HealthPercent> cancelHeal
                                              )
                                   );
            }

            if (PriestSettings.HolyHeal.Heal != 0)
            {
                behavs.AddBehavior(HealthToPriority(PriestSettings.HolyHeal.Heal), "Heal @ " + PriestSettings.HolyHeal.Heal + "%", "Heal",
                                   Spell.Cast("Heal",
                                              mov => true,
                                              on => (WoWUnit)on,
                                              req => ((WoWUnit)req).HealthPercent <PriestSettings.HolyHeal.Heal,
                                                                                   cancel => ((WoWUnit)cancel).HealthPercent> cancelHeal
                                              )
                                   );
            }

            #endregion

            #region Tank - Low Priority Buffs

            if (PriestSettings.HolyHeal.Renew != 0)
            {
                behavs.AddBehavior(HealthToPriority(102), "Tank - Buff Renew @ " + PriestSettings.HolyHeal.Renew + "%", "Renew",
                                   // roll Renew on Tanks
                                   Spell.Cast("Renew", on =>
                {
                    WoWUnit unit = HealerManager.GetBestTankTargetForHOT("Renew", PriestSettings.HolyHeal.Renew);
                    if (unit != null && Spell.CanCastHack("Renew", unit, skipWowCheck: true))
                    {
                        Logger.WriteDebug("Buffing RENEW ON TANK: {0}", unit.SafeName());
                        return(unit);
                    }
                    return(null);
                })
                                   );
            }
            #endregion


            #region Lowest Priority Healer Tasks

            if (SingularRoutine.CurrentWoWContext == WoWContext.Instances)
            {
                behavs.AddBehavior(HealthToPriority(103), "Lightwell", "Lightwell",
                                   new Throttle(TimeSpan.FromSeconds(20),
                                                new Sequence(
                                                    new Action(r =>
                {
                    _lightwellTarget = Group.Tanks.FirstOrDefault(t =>
                    {
                        if (t.IsAlive && t.Combat && t.GotTarget() && t.CurrentTarget.IsBoss())
                        {
                            if (t.Distance < 40 && t.SpellDistance(t.CurrentTarget) < 15)
                            {
                                Logger.WriteDiagnostic("Lightwell: found target {0}", t.SafeName());
                                return(true);
                            }
                        }
                        return(false);
                    });

                    return(_lightwellTarget == null ? RunStatus.Failure : RunStatus.Success);
                }),
                                                    Spell.CastOnGround("Lightwell",
                                                                       location => WoWMathHelper.CalculatePointFrom(Me.Location, _lightwellTarget.Location, (float)Math.Min(10.0, _lightwellTarget.Distance / 2)),
                                                                       req => _lightwellTarget != null,
                                                                       false,
                                                                       desc => string.Format("10 yds from {0}", _lightwellTarget.SafeName())
                                                                       )
                                                    )
                                                )
                                   );
            }
            #endregion

            behavs.OrderBehaviors();

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

            return(new PrioritySelector(
                       ctx => selfOnly ? StyxWoW.Me : HealerManager.FindLowestHealthTarget(), // 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
                               )
                           )
                       ));
        }
Пример #6
0
        public static Composite CreateDiscHealOnlyBehavior()
        {
            if (SingularRoutine.CurrentWoWContext == WoWContext.Normal)
            {
                return(new ActionAlwaysFail());
            }

            HealerManager.NeedHealTargeting = true;
            PrioritizedBehaviorList behavs = new PrioritizedBehaviorList();
            int cancelHeal = (int)Math.Max(SingularSettings.Instance.IgnoreHealTargetsAboveHealth, PriestSettings.DiscHeal.Heal);

            cancelHeal = (int)Math.Max(cancelHeal, PriestSettings.DiscHeal.FlashHeal);

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

            if (SingularSettings.Instance.DispelDebuffs != RelativePriority.None)
            {
                int dispelPriority = (SingularSettings.Instance.DispelDebuffs == RelativePriority.HighPriority) ? 999 : -999;
                behavs.AddBehavior(dispelPriority, "Dispel", null, Common.CreatePriestDispelBehavior());
            }

            #region Save the Group

            behavs.AddBehavior(HealthToPriority(PriestSettings.DiscHeal.PainSuppression) + PriEmergencyBase, "Pain Suppression @ " + PriestSettings.DiscHeal.PainSuppression + "%", "Pain Suppression",
                               new Decorator(
                                   req => Me.Combat,
                                   Spell.Cast("Pain Suppression",
                                              mov => false,
                                              on => (WoWUnit)on,
                                              req => ((WoWUnit)req).IsPlayer &&
                                              ((WoWUnit)req).HealthPercent < PriestSettings.DiscHeal.PainSuppression
                                              )
                                   )
                               );

            behavs.AddBehavior(HealthToPriority(PriestSettings.DiscHeal.PowerWordBarrier) + PriEmergencyBase, "Power Word: Barrier @ " + PriestSettings.DiscHeal.PowerWordBarrier + "%", "Power Word: Barrier",
                               new Decorator(
                                   ret => Me.Combat && (StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid),
                                   new PrioritySelector(
                                       context => GetBestPowerWordBarrierTarget(),
                                       new Decorator(
                                           ret => ret != null,
                                           new PrioritySelector(
                                               new Sequence(
                                                   new Action(r => Logger.WriteDebug("PW:B - attempting cast")),
                                                   Spell.CastOnGround("Power Word: Barrier", on => (WoWUnit)on, req => true, false)
                                                   ),
                                               new Action(ret => {
                if (ret != null)
                {
                    if (!((WoWUnit)ret).IsValid)
                    {
                        Logger.WriteDebug("PW:B - FAILED - Healing Target object became invalid");
                    }
                    else if (((WoWUnit)ret).Distance > 40)
                    {
                        Logger.WriteDebug("PW:B - FAILED - Healing Target moved out of range");
                    }
                    else if (!Spell.CanCastHack("Power Word: Barrier"))
                    {
                        Logger.WriteDebug("PW:B - FAILED - Spell.CanCastHack() said NO to Power Word: Barrier");
                    }
                    else if (GameWorld.IsInLineOfSpellSight(StyxWoW.Me.GetTraceLinePos(), ((WoWUnit)ret).Location))
                    {
                        Logger.WriteDebug("PW:B - FAILED - Spell.CanCastHack() unit location not in Line of Sight");
                    }
                    else if (Spell.IsSpellOnCooldown("Power Word: Barrier"))
                    {
                        Logger.WriteDebug("PW:B - FAILED - Power Word: Barrier is on cooldown");
                    }
                    else
                    {
                        Logger.WriteDebug("PW:B - Something FAILED with Power Word: Barrier cast sequence (target={0}, h={1:F1}%, d={2:F1} yds, spellmax={3:F1} yds, cooldown={4})",
                                          ((WoWUnit)ret).SafeName(),
                                          ((WoWUnit)ret).HealthPercent,
                                          ((WoWUnit)ret).Distance,
                                          Spell.ActualMaxRange("Power Word: Barrier", (WoWUnit)ret),
                                          Spell.IsSpellOnCooldown("Power Word: Barrier")
                                          );
                    }
                }
                return(RunStatus.Failure);
            })
                                               )
                                           )
                                       )
                                   )
                               );


            #endregion

            #region Tank Buffing

            behavs.AddBehavior(HealthToPriority(99) + PriHighBase, "Power Word: Shield - Tank", "Power Word: Shield",
                               new Decorator(
                                   req => Me.Combat,
                                   Spell.Buff(
                                       "Power Word: Shield",
                                       on => Group.Tanks
                                       .FirstOrDefault(u => u.IsAlive && CanWePwsUnit(u) && Spell.CanCastHack("Power Word: Shield", u))
                                       )
                                   )
                               );

            behavs.AddBehavior(HealthToPriority(99) + PriHighBase, "Plea - Tank Attonement", "Plea",
                               new Decorator(
                                   req => Me.Combat,
                                   Spell.Cast(
                                       "Plea",
                                       on => Group.Tanks
                                       .FirstOrDefault(u => u.IsAlive && !u.HasActiveAura("Atonement") && Spell.CanCastHack("Plea", u))
                                       )
                                   )
                               );


            #endregion

            #region Save the Highest Priority Targets
            const int SaveEssential = 30;
            behavs.AddBehavior(HealthToPriority(SaveEssential) + PriSaveEssential, "Save Highest Priority Target below " + SaveEssential + "%", "Shadow Mend",
                               new Decorator(
                                   req => Me.Combat,
                                   new PrioritySelector(
                                       ctx => HealerManager.FindHighestPriorityTarget(),

                                       Spell.HandleOffGCD(Spell.Buff("Power Infusion", on => Me, req => req != null, gcd: HasGcd.No)),

                                       Spell.Buff(
                                           "Power Word: Shield",
                                           on => (WoWUnit)on,
                                           req => ((WoWUnit)req).HealthPercent < PriestSettings.DiscHeal.PowerWordShield &&
                                           CanWePwsUnit((WoWUnit)req)
                                           ),
                                       Spell.Cast(
                                           "Plea",
                                           on => (WoWUnit)on,
                                           req => !((WoWUnit)req).HasActiveAura("Atonement")
                                           ),
                                       Spell.Cast(
                                           "Shadow Mend",
                                           on => (WoWUnit)on,
                                           req => ((WoWUnit)req).HealthPercent < PriestSettings.DiscHeal.ShadowMend
                                           )
                                       )
                                   )
                               );
            #endregion

            #region AoE Heals
            if (PriestSettings.DiscHeal.DiscLevel90Talent != 0)
            {
                behavs.AddBehavior(HealthToPriority(PriestSettings.DiscHeal.DiscLevel90Talent) + PriAoeBase, "Halo @ " + PriestSettings.DiscHeal.DiscLevel90Talent + "% MinCount: " + PriestSettings.DiscHeal.CountLevel90Talent, "Halo",
                                   new Decorator(
                                       ret => SingularRoutine.CurrentWoWContext == WoWContext.Battlegrounds || SingularRoutine.CurrentWoWContext == WoWContext.Instances,
                                       new Decorator(
                                           ret => ret != null && HealerManager.Instance.TargetList.Count(u => u.IsAlive && u.HealthPercent < PriestSettings.DiscHeal.DiscLevel90Talent && u.Distance < 30) >= PriestSettings.DiscHeal.CountLevel90Talent &&
                                           Spell.CanCastHack("Halo", (WoWUnit)ret),
                                           new PrioritySelector(
                                               Spell.HandleOffGCD(Spell.BuffSelf("Archangel", req => ((WoWUnit)req) != null && Me.HasAura("Evangelism", 5))),
                                               Spell.CastOnGround("Halo", on => (WoWUnit)on, req => true)
                                               )
                                           )
                                       )
                                   );
            }

            if (PriestSettings.DiscHeal.DiscLevel90Talent != 0)
            {
                behavs.AddBehavior(HealthToPriority(PriestSettings.DiscHeal.DiscLevel90Talent) + PriAoeBase, "Cascade @ " + PriestSettings.DiscHeal.DiscLevel90Talent + "% MinCount: " + PriestSettings.DiscHeal.CountLevel90Talent, "Cascade",
                                   new Decorator(
                                       ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                       new PrioritySelector(
                                           context => HealerManager.GetBestCoverageTarget("Cascade", PriestSettings.DiscHeal.DiscLevel90Talent, 40, 30, PriestSettings.DiscHeal.CountLevel90Talent),
                                           new Decorator(
                                               ret => ret != null && Spell.CanCastHack("Cascade", (WoWUnit)ret),
                                               new PrioritySelector(
                                                   Spell.HandleOffGCD(Spell.BuffSelf("Archangel", req => Me.HasAura("Evangelism", 5))),
                                                   Spell.Cast("Cascade", mov => true, on => (WoWUnit)on, req => true)
                                                   )
                                               )
                                           )
                                       )
                                   );
            }

            if (PriestSettings.DiscHeal.PowerWordRadiance != 0)
            {
                behavs.AddBehavior(99 + PriAoeBase, "Power Word: Radiance", "Power Word: Radiance",
                                   new Decorator(
                                       ret => StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid,
                                       new PrioritySelector(
                                           context => HealerManager.GetBestCoverageTarget("Power Word: Radiance", PriestSettings.DiscHeal.PowerWordRadiance, 40, 30, PriestSettings.DiscHeal.CountPowerWordRadiance, o => o != null && !((WoWUnit)o).HasActiveAura("Atonement")),
                                           CastBuffsBehavior("Power Word: Radiance"),
                                           Spell.Cast("Power Word: Radiance", on => (WoWUnit)on)
                                           )
                                       )
                                   );
            }

            #endregion

            #region Direct Heals

            if (PriestSettings.DiscHeal.Plea != 0)
            {
                behavs.AddBehavior(100 + PriSingleBase,
                                   "Atonement Plea @ " + PriestSettings.DiscHeal.Plea + "%", "Plea",
                                   new Decorator(
                                       req => !((WoWUnit)req).HasActiveAura("Atonement"),
                                       new PrioritySelector(
                                           CastBuffsBehavior("Plea"),
                                           Spell.Cast("Plea",
                                                      mov => false,
                                                      on => (WoWUnit)on,
                                                      req => true,
                                                      cancel => false
                                                      )
                                           )
                                       )
                                   );
            }

            if (HasReflectiveShield)
            {
                behavs.AddBehavior(100 + PriSingleBase, "Power Word: Shield Self (Glyph of Reflective Shield)", "Power Word: Shield",
                                   Spell.BuffSelf("Power Word: Shield", req => CanWePwsUnit(Me) && Unit.NearbyUnitsInCombatWithUsOrOurStuff.Any())
                                   );
            }

            if (PriestSettings.DiscHeal.PowerWordShield != 0)
            {
                behavs.AddBehavior(99 + PriSingleBase, "Power Word: Shield @ " + PriestSettings.DiscHeal.PowerWordShield + "%", "Power Word: Shield",
                                   Spell.Buff("Power Word: Shield", on => (WoWUnit)on, req => ((WoWUnit)req).HealthPercent < PriestSettings.DiscHeal.PowerWordShield && CanWePwsUnit((WoWUnit)req))
                                   );
            }

            #endregion

            behavs.OrderBehaviors();
            behavs.ListBehaviors();

            return(new PrioritySelector(
                       ctx => HealerManager.FindHighestPriorityTarget(),

                       Spell.WaitForCastOrChannel(),

                       new Decorator(
                           ret => !Spell.IsGlobalCooldown() && ret != null,
                           behavs.GenerateBehaviorTree()
                           )
                       ));
        }
Пример #7
0
        private static void CreateMistweaverHealingWowhead(bool selfOnly, PrioritizedBehaviorList behavs)
        {
            // save a group
            if (!selfOnly)
            {
                behavs.AddBehavior(
                    HealthToPriority(MonkSettings.MistHealSettings.Revival) + 900,
                    String.Format("Revival on {0} targets @ {1}%", MonkSettings.MistHealSettings.CountRevival, MonkSettings.MistHealSettings.Revival),
                    "Revival",
                    new Decorator(
                        req => (req as WoWUnit).HealthPercent < MonkSettings.MistHealSettings.Revival,
                        Spell.Cast("Revival", on =>
                {
                    if (Spell.IsSpellOnCooldown("Revival"))
                    {
                        return(null);
                    }

                    List <WoWUnit> revlist = HealerManager.Instance.TargetList
                                             .Where(u => u.HealthPercent < MonkSettings.MistHealSettings.Revival && u.DistanceSqr < 100 * 100 && u.InLineOfSpellSight)
                                             .ToList();
                    if (revlist.Count() < MonkSettings.MistHealSettings.CountRevival)
                    {
                        return(null);
                    }

                    Logger.Write(LogColor.Hilite, "Revival: found {0} heal targets below {1}%", revlist.Count(), MonkSettings.MistHealSettings.Revival);
                    return(revlist.FirstOrDefault(u => u != null && u.IsValid));
                })
                        )
                    );
            }

            // save a player
            behavs.AddBehavior(
                HealthToPriority(MonkSettings.MistHealSettings.LifeCocoon) + 800,
                String.Format("Life Cocoon @ {0}%", MonkSettings.MistHealSettings.LifeCocoon),
                "Life Cocoon",
                Spell.Buff("Life Cocoon", on => (WoWUnit)on, req => (Me.Combat || (req as WoWUnit).Combat) && (req as WoWUnit).PredictedHealthPercent(includeMyHeals: true) < MonkSettings.MistHealSettings.LifeCocoon)
                );

            if (!selfOnly)
            {
                behavs.AddBehavior(
                    HealthToPriority(1) + 700,
                    "Summon Jade Serpent Statue",
                    "Summon Jade Serpent Statue",
                    new Decorator(
                        req => Group.Tanks.Any(t => t.Combat && !t.IsMoving && t.GotTarget() && t.CurrentTarget.IsHostile && t.SpellDistance(t.CurrentTarget) < 10),
                        CreateSummonJadeSerpentStatueBehavior()
                        )
                    );
            }

            if (!selfOnly)
            {
                behavs.AddBehavior(
                    HealthToPriority(99) + 700,
                    "Thunder Focus Tea on me", "Thunder Focus Tea",
                    new Decorator(
                        req => (Me.Combat && (StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.IsInRaid)),
                        Spell.Cast("Thunder Focus Tea", on => Me)
                        )
                    );

                behavs.AddBehavior(
                    HealthToPriority(100) + 700,
                    String.Format("Roll Renewing Mist on at least {0} targets", MonkSettings.MistHealSettings.RollRenewingMistCount),
                    "Renewing Mist",
                    new Decorator(
                        req => true,
                        CreateMistweaverRollRenewingMist()
                        )
                    );
            }

            behavs.AddBehavior(
                HealthToPriority(MonkSettings.MistHealSettings.ChiWave) + 600,
                String.Format("Chi Wave on {0} targets @ {1}%", MonkSettings.MistHealSettings.CountChiWave, MonkSettings.MistHealSettings.ChiWave),
                "Chi Wave",
                new Decorator(
                    req => (req as WoWUnit).PredictedHealthPercent() < MonkSettings.MistHealSettings.ChiWave,
                    Spell.Cast("Chi Wave", on => GetBestChiWaveTarget())
                    )
                );

            behavs.AddBehavior(
                HealthToPriority(1) + 500,
                "Expel Harm in Combat for Chi",
                "Expel Harm",
                Spell.Buff("Expel Harm", on => Common.BestExpelHarmTarget(),
                           req => Me.Combat
                           )
                );

            behavs.AddBehavior(
                HealthToPriority(MonkSettings.MistHealSettings.Effuse),
                String.Format("Effuse @ {0}%", MonkSettings.MistHealSettings.Effuse),
                "Effuse",
                new Decorator(
                    req => ((WoWUnit)req).PredictedHealthPercent() < MonkSettings.MistHealSettings.Effuse &&
                    Spell.CanCastHack("Effuse", (WoWUnit)req),
                    new PrioritySelector(
                        Spell.Cast("Effuse", on => (WoWUnit)on),
                        new Action(r =>
            {
                Logger.WriteDebug("Effuse: failed to ensure Soothing Mist first");
                return(RunStatus.Failure);
            })
                        )
                    )
                );

            behavs.AddBehavior(
                HealthToPriority(MonkSettings.MistHealSettings.Vivify),
                String.Format("Vivify @ {0}%", MonkSettings.MistHealSettings.Vivify),
                "Vivify",
                new Decorator(
                    req => ((WoWUnit)req).PredictedHealthPercent() < MonkSettings.MistHealSettings.Vivify &&
                    Spell.CanCastHack("Vivify", (WoWUnit)req),
                    new PrioritySelector(
                        Spell.Cast("Vivify", on => (WoWUnit)on),
                        new Action(r =>
            {
                Logger.WriteDebug("Vivify: failed to ensure Soothing Mist first");
                return(RunStatus.Failure);
            })
                        )
                    )
                );

            behavs.AddBehavior(
                HealthToPriority(MonkSettings.MistHealSettings.EnvelopingMist),
                String.Format("Enveloping Mist @ {0}%", MonkSettings.MistHealSettings.EnvelopingMist),
                "Enveloping Mist",
                new Decorator(
                    req => ((WoWUnit)req).HasAuraExpired("Enveloping Mist") &&
                    ((WoWUnit)req).PredictedHealthPercent() < MonkSettings.MistHealSettings.EnvelopingMist &&
                    Spell.CanCastHack("Enveloping Mist", (WoWUnit)req),
                    new PrioritySelector(
                        Spell.Cast("Enveloping Mist", on => (WoWUnit)on),
                        new Action(r =>
            {
                Logger.WriteDebug("EnvelopingMist: failed to ensure Soothing Mist first");
                return(RunStatus.Failure);
            })
                        )
                    )
                );
        }
Пример #8
0
 private static void CreateMistweaverHealingRotation(bool selfOnly, PrioritizedBehaviorList behavs)
 {
     CreateMistweaverHealingWowhead(selfOnly, behavs);
 }
Пример #9
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)
                                                   )
                                               )
                                           )
                                       )
                                   )
                               )
                           )
                       ));
        }
Пример #10
0
        public static Composite CreateMonkOffHealBehavior()
        {
            HealerManager.NeedHealTargeting = SingularSettings.Instance.DpsOffHealAllowed;
            PrioritizedBehaviorList behavs = new PrioritizedBehaviorList();
            int cancelHeal = (int)Math.Max(SingularSettings.Instance.IgnoreHealTargetsAboveHealth, MonkSettings.OffHealSettings.Effuse);

            bool 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, "Cleanse Spirit", null, Dispelling.CreateDispelBehavior());
 */
            #region Save the Group


            #endregion

            #region AoE Heals

            behavs.AddBehavior(
                Mistweaver.HealthToPriority(MonkSettings.MistHealSettings.ChiWave) + 400,
                String.Format("Chi Wave on {0} targets @ {1}%", MonkSettings.OffHealSettings.CountChiWaveTalent, MonkSettings.OffHealSettings.ChiWaveTalent),
                "Chi Wave",
                CreateClusterHeal("Chi Wave", ClusterType.Cone, MonkSettings.OffHealSettings.ChiWaveTalent, MonkSettings.OffHealSettings.CountChiWaveTalent, 40)
                );

            behavs.AddBehavior(
                Mistweaver.HealthToPriority(MonkSettings.MistHealSettings.ChiBurstTalent) + 400,
                String.Format("Chi Burst on {0} targets @ {1}%", MonkSettings.OffHealSettings.CountChiBurstTalent, MonkSettings.OffHealSettings.ChiBurstTalent),
                "Chi Burst",
                CreateClusterHeal("Chi Burst", ClusterType.Cone, MonkSettings.OffHealSettings.ChiBurstTalent, MonkSettings.OffHealSettings.CountChiBurstTalent, 40)
                );


            #endregion

            #region Single Target Heals

            behavs.AddBehavior(Mistweaver.HealthToPriority(MonkSettings.OffHealSettings.Effuse),
                               string.Format("Effuse @ {0}%", MonkSettings.OffHealSettings.Effuse),
                               "Effuse",
                               Spell.Cast("Effuse",
                                          mov => true,
                                          on => (WoWUnit)on,
                                          req => ((WoWUnit)req).PredictedHealthPercent(includeMyHeals: true) < MonkSettings.OffHealSettings.Effuse,
                                          cancel => ((WoWUnit)cancel).HealthPercent > cancelHeal
                                          )
                               );

            #endregion

            behavs.OrderBehaviors();

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

            return(new PrioritySelector(
                       ctx => HealerManager.FindLowestHealthTarget(), // HealerManager.Instance.FirstUnit,

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

                           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, 30f, 25f)
                                                   )
                                               )
                                           )
                                       )
                                   )
                               )
                           )
                       ));
        }