예제 #1
0
        public static Composite CreateShamanNonHealBehavior()
        {
            return
                (new PrioritySelector(

                     new Decorator(
                         ret => !StyxWoW.Me.Combat,
                         Spell.Heal(
                             "Healing Surge",
                             ret => StyxWoW.Me,
                             ret => StyxWoW.Me.HealthPercent <= 70)
                         ),
                     new Decorator(
                         ret => StyxWoW.Me.Combat,
                         new PrioritySelector(
                             Spell.BuffSelf(
                                 "Healing Tide Totem",
                                 ret => Unit.NearbyFriendlyPlayers.Any(
                                     p => p.HealthPercent < SingularSettings.Instance.Shaman.HealingTideTotemPercent &&
                                     p.Distance <= Totems.GetTotemRange(WoWTotem.HealingTide))),
                             Spell.BuffSelf(
                                 "Healing Stream Totem",
                                 ret => !Totems.Exist(WoWTotemType.Water) &&
                                 Unit.NearbyFriendlyPlayers.Any(
                                     p => p.HealthPercent < SingularSettings.Instance.Shaman.HealHealingStreamTotem &&
                                     p.Distance <= Totems.GetTotemRange(WoWTotem.HealingTide))),
                             Spell.Heal(
                                 "Healing Surge",
                                 ret => StyxWoW.Me,
                                 ret => StyxWoW.Me.HealthPercent <= 30)
                             )
                         )
                     ));
        }
예제 #2
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)
                                                   )
                                               )
                                           )
                                       )
                                   )
                               )
                           )
                       ));
        }
예제 #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 CreateShamanDpsHealBehavior()
        {
            Composite offheal;

            if (!SingularSettings.Instance.DpsOffHealAllowed)
            {
                offheal = new ActionAlwaysFail();
            }
            else
            {
                offheal = new Decorator(
                    ret => HealerManager.ActingAsOffHealer,
                    CreateDpsShamanOffHealBehavior()
                    );
            }

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

                           new Decorator(
                               ret => !Me.Combat &&
                               (!Me.IsMoving || Me.HasAura("Maelstrom Weapon", 5)) &&
                               Me.HealthPercent <= 85 && // not redundant... this eliminates unnecessary GetPredicted... checks
                               SpellManager.HasSpell("Healing Surge") &&
                               Me.PredictedHealthPercent(includeMyHeals: true) < 85,
                               new PrioritySelector(
                                   new Sequence(
                                       ctx => (float)Me.HealthPercent,
                                       new Action(r => Logger.WriteDebug("Healing Surge: {0:F1}% Predict:{1:F1}% and moving:{2}, cancast:{3}", (float)r, Me.PredictedHealthPercent(includeMyHeals: true), Me.IsMoving, Spell.CanCastHack("Healing Surge", Me, skipWowCheck: false))),
                                       Spell.Cast(
                                           "Healing Surge",
                                           mov => true,
                                           on => Me,
                                           req => true,
                                           cancel => Me.HealthPercent > 85
                                           ),
                                       new WaitContinue(TimeSpan.FromMilliseconds(500), until => !Me.IsCasting && Me.HealthPercent > (1.1 * ((float)until)), new ActionAlwaysSucceed()),
                                       new Action(r => Logger.WriteDebug("Healing Surge: After Heal Attempted: {0:F1}% Predicted: {1:F1}%", Me.HealthPercent, Me.PredictedHealthPercent(includeMyHeals: true)))
                                       ),
                                   new Action(r => Logger.WriteDebug("Healing Surge: After Heal Skipped: {0:F1}% Predicted: {1:F1}%", Me.HealthPercent, Me.PredictedHealthPercent(includeMyHeals: true)))
                                   )
                               ),

                           new Decorator(
                               ret => Me.Combat,

                               new PrioritySelector(

                                   Spell.BuffSelf("Astral Shift", ret => Me.HealthPercent < ShamanSettings.AstralShiftPercent || Common.StressfulSituation),
                                   Spell.BuffSelf(WoWTotem.StoneBulwark.ToSpellId(), ret => !Me.IsMoving && (Common.StressfulSituation || Me.HealthPercent < ShamanSettings.StoneBulwarkTotemPercent && !Totems.Exist(WoWTotem.EarthElemental))),
                                   Spell.BuffSelf("Shamanistic Rage", ret => Me.HealthPercent < ShamanSettings.ShamanisticRagePercent || Common.StressfulSituation),

                                   Spell.HandleOffGCD(
                                       Spell.BuffSelf("Ancestral Guidance",
                                                      ret => Me.HealthPercent < ShamanSettings.SelfAncestralGuidance &&
                                                      Me.GotTarget() &&
                                                      Me.CurrentTarget.TimeToDeath() > 8
                                                      )
                                       ),

                                   new Decorator(
                                       req => !Me.IsMoving && ShamanSettings.SelfHealingStreamTotem > 0 && !Totems.Exist(WoWTotemType.Water),
                                       Spell.BuffSelf(
                                           WoWTotem.HealingStream.ToSpellId(),
                                           req =>
            {
                int count = Unit.NearbyUnitsInCombatWithMeOrMyStuff.Count(u => !u.IsTrivial());
                if (count > 1)
                {
                    return true;
                }
                if (count > 0 && Me.HealthPercent < ShamanSettings.SelfHealingStreamTotem)
                {
                    if (!Me.GotTarget() || Me.CurrentTarget.IsPlayer || Me.CurrentTarget.TimeToDeath() > 5)
                    {
                        return true;
                    }
                    if (Me.HealthPercent < (ShamanSettings.SelfHealingStreamTotem / 2))
                    {
                        return true;
                    }
                }
                return false;
            }
                                           )
                                       ),

                                   // save myself if possible
                                   new Decorator(
                                       ret => (!Me.IsInGroup() || Battlegrounds.IsInsideBattleground) &&
                                       (!Me.IsMoving || Me.HasAura("Maelstrom Weapon", 5) || !Spell.IsSpellOnCooldown("Ancestral Swiftness")) &&
                                       Me.HealthPercent < ShamanSettings.SelfAncestralSwiftnessHeal &&
                                       Me.PredictedHealthPercent(includeMyHeals: true) < ShamanSettings.SelfAncestralSwiftnessHeal,
                                       new PrioritySelector(
                                           Spell.HandleOffGCD(Spell.BuffSelf("Ancestral Swiftness")),
                                           new PrioritySelector(
                                               new Sequence(
                                                   ctx => (float)Me.HealthPercent,
                                                   new Action(r => Logger.WriteDebug("Healing Surge: {0:F1}% Predict:{1:F1}% and moving:{2}, cancast:{3}", (float)r, Me.PredictedHealthPercent(includeMyHeals: true), Me.IsMoving, Spell.CanCastHack("Healing Surge", Me, skipWowCheck: false))),
                                                   Spell.Cast(
                                                       "Healing Surge",
                                                       mov => true,
                                                       on => Me,
                                                       req => true,
                                                       cancel => Me.HealthPercent > 85
                                                       ),
                                                   new WaitContinue(TimeSpan.FromMilliseconds(500), until => !Me.IsCasting && Me.HealthPercent > (1.1 * ((float)until)), new ActionAlwaysSucceed()),
                                                   new Action(r => Logger.WriteDebug("Healing Surge: After Heal Attempted: {0:F1}% Predicted: {1:F1}%", Me.HealthPercent, Me.PredictedHealthPercent(includeMyHeals: true)))
                                                   ),
                                               new Action(r => Logger.WriteDebug("Healing Surge: After Heal Skipped: {0:F1}% Predicted: {1:F1}%", Me.HealthPercent, Me.PredictedHealthPercent(includeMyHeals: true)))
                                               )
                                           )
                                       )
                                   )
                               ),

                           offheal
                           )
                       ));
        }
예제 #5
0
        public static Composite CreateShamanCombatBuffsPVP()
        {
            return(new PrioritySelector(

                       Totems.CreateTotemsBehavior(),

                       Spell.BuffSelf("Astral Shift", ret => Me.HealthPercent < ShamanSettings.AstralShiftPercent || Common.StressfulSituation),
                       Spell.BuffSelf(WoWTotem.StoneBulwark.ToSpellId(), ret => !Me.IsMoving && (Common.StressfulSituation || Me.HealthPercent < ShamanSettings.StoneBulwarkTotemPercent && !Totems.Exist(WoWTotem.EarthElemental))),
                       Spell.BuffSelf("Shamanistic Rage", ret => Me.HealthPercent < 70 || Me.ManaPercent < 70 || Common.StressfulSituation),

                       // hex someone if they are not current target, attacking us, and 12 yds or more away
                       new PrioritySelector(
                           ctx => Unit.NearbyUnfriendlyUnits
                           .Where(u => (u.CreatureType == WoWCreatureType.Beast || u.CreatureType == WoWCreatureType.Humanoid) &&
                                  (u.Aggro || u.PetAggro || (u.Combat && u.IsTargetingMeOrPet)) &&
                                  u.Distance.Between(10, 30) && Me.IsSafelyFacing(u) && u.InLineOfSpellSight && Me.GotTarget() && u.Location.Distance(Me.CurrentTarget.Location) > 10)
                           .OrderByDescending(u => u.Distance)
                           .FirstOrDefault(),
                           Spell.Cast("Hex", onUnit => (WoWUnit)onUnit)
                           ),

                       new Decorator(
                           req => {
                if (!Unit.ValidUnit(Me.CurrentTarget))
                {
                    return false;
                }
                if (Me.Specialization == WoWSpec.ShamanEnhancement && !Me.CurrentTarget.IsWithinMeleeRange)
                {
                    return false;
                }

                if (Me.CurrentTarget.TimeToDeath() > 5 || Me.CurrentTarget.HealthPercent > 20 || Me.HealthPercent < Me.CurrentTarget.HealthPercent)
                {
                    return true;
                }
                if (Unit.UnfriendlyUnits(40).Count(u => u.IsTargetingMyStuff()) >= 2)
                {
                    return true;
                }

                return false;
            },
                           new PrioritySelector(
                               Spell.BuffSelfAndWait(PartyBuff.BloodlustSpellName,
                                                     req => ShamanSettings.UseBloodlust &&
                                                     MovementManager.IsClassMovementAllowed &&
                                                     IsPvpFightWorthLusting,
                                                     gcd: HasGcd.No
                                                     ),

                               Spell.BuffSelf(
                                   "Ascendance",
                                   req => ShamanSettings.UseAscendance &&
                                   ((Me.GotTarget() && Me.CurrentTarget.HealthPercent > 70) ||
                                    Unit.NearbyUnfriendlyUnits.Count() > 1),
                                   gcd: HasGcd.No
                                   ),

                               Spell.BuffSelf(
                                   "Elemental Mastery",
                                   req => !PartyBuff.WeHaveBloodlust,
                                   gcd: HasGcd.No
                                   )
                               )
                           )
                       // , Spell.BuffSelf("Spiritwalker's Grace", ret => Me.IsMoving && Me.Combat)

                       ));
        }
예제 #6
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))
                               )
                           )
                       ));
        }
예제 #7
0
        private static Composite CreateElementalDiagnosticOutputBehavior()
        {
            if (!SingularSettings.Debug)
            {
                return(new ActionAlwaysFail());
            }

            return(new ThrottlePasses(1, 1,
                                      new Action(ret =>
            {
                uint stks = 0;
                string shield;

                WoWAura aura = Me.GetAuraByName("Lightning Shield");
                if (aura != null)
                {
                    stks = aura.StackCount;
                    if (!Me.HasAura("Lightning Shield", (int)stks))
                    {
                        Logger.WriteDebug(Color.MediumVioletRed, "Inconsistancy Error:  have {0} stacks but Me.HasAura('Lightning Shield', {0}) was False!!!!", stks, stks);
                    }
                }
                else
                {
                    aura = Me.GetAuraByName("Water Shield");
                    if (aura == null)
                    {
                        aura = Me.GetAuraByName("Earth Shield");
                        if (aura != null)
                        {
                            stks = aura.StackCount;
                        }
                    }
                }

                shield = aura == null ? "(null)" : aura.Name;

                string line = string.Format(".... [{0}] h={1:F1}%/m={2:F1}%, shield={3}, stks={4}, moving={5}",
                                            CompositeBuilder.CurrentBehaviorType.ToString(),
                                            Me.HealthPercent,
                                            Me.ManaPercent,
                                            shield,
                                            stks,
                                            Me.IsMoving.ToYN()
                                            );

                WoWUnit target = Me.CurrentTarget;
                if (target == null)
                {
                    line += ", target=(null)";
                }
                else
                {
                    line += string.Format(", target={0} @ {1:F1} yds, th={2:F1}%, face={3} loss={4}, fs={5}",
                                          target.SafeName(),
                                          target.Distance,
                                          target.HealthPercent,
                                          Me.IsSafelyFacing(target).ToYN(),
                                          target.InLineOfSpellSight.ToYN(),
                                          (long)target.GetAuraTimeLeft("Flame Shock").TotalMilliseconds
                                          );
                }


                if (Totems.Exist(WoWTotemType.Fire))
                {
                    line += ", fire=" + Totems.GetTotem(WoWTotemType.Fire).Name;
                }

                if (Totems.Exist(WoWTotemType.Earth))
                {
                    line += ", earth=" + Totems.GetTotem(WoWTotemType.Earth).Name;
                }

                if (Totems.Exist(WoWTotemType.Water))
                {
                    line += ", water=" + Totems.GetTotem(WoWTotemType.Water).Name;
                }

                if (Totems.Exist(WoWTotemType.Air))
                {
                    line += ", air=" + Totems.GetTotem(WoWTotemType.Air).Name;
                }

                Logger.WriteDebug(Color.Yellow, line);
                return RunStatus.Failure;
            })
                                      ));
        }