//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 ) ) )); }