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

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

                               Spell.BuffSelfAndWait("Levitate", req => PriestSettings.UseLevitate && Me.IsFalling),
                               new Decorator(
                                   req => SingularRoutine.IsQuestBotActive && Me.HasMyAura("Levitate") && !Me.IsFalling,
                                   new Sequence(
                                       new SeqDiag(1, s => string.Format("Levitate: no longer needed since NOT falling and QuestBot active")),
                                       new Action(r => Me.CancelAura("Levitate")),
                                       new Wait(1, until => !Me.HasMyAura("Levitate"), new ActionAlwaysSucceed())
                                       )
                                   ),
                               //Spell.BuffSelf("Shadow Protection", ret => PriestSettings.UseShadowProtection && Unit.NearbyFriendlyPlayers.Any(u => !u.Dead && !u.IsGhost && (u.IsInMyPartyOrRaid() || u.IsMe) && !Unit.HasAura(u, "Shadow Protection", 0))), // we no longer have Shadow resist
                               Spell.BuffSelf("Fear Ward", ret => PriestSettings.UseFearWard),

                               Spell.BuffSelf("Shadowform", ret => !Shadow.InVoidform),

                               CreatePriestMovementBuffOnTank("PreCombat")
                               )
                           )
                       ));
        }
예제 #2
0
        public static Composite CheckIfWeShouldCancelBladestorm()
        {
            if (!HasTalent(WarriorTalents.Bladestorm))
            {
                return(new ActionAlwaysFail());
            }

            return(new ThrottlePasses(
                       1,
                       TimeSpan.FromSeconds(1),
                       RunStatus.Failure,
                       new Decorator(
                           req => StyxWoW.Me.HasAura("Bladestorm"),
                           new Action(r =>
            {
                // check if it makes sense to cancel to resume normal speed movement and charge
                if (!Me.Combat || !Unit.UnfriendlyUnits(20).Any(u => u.Aggro || (u.IsPlayer && u.IsHostile) || u.IsTargetingUs()))
                {
                    Logger.WriteDebug("Bladestorm: cancel since out of combat or no targets within 20 yds");
                    Me.CancelAura("Bladestorm");
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            })
                           )
                       ));
        }
예제 #3
0
        public static Composite CreateSpiritShellCancel()
        {
            if (PriestSettings.DiscHeal.SpiritShell <= 0 || !SpellManager.HasSpell(SPIRIT_SHELL_SPELL))
            {
                return(new ActionAlwaysFail());
            }

            return(new Decorator(
                       req => Me.HasMyAura("Spirit Shell") && !Me.Combat && !HealerManager.Instance.TargetList.Any(m => m.Combat && m.SpellDistance() < 50),
                       new Action(r =>
            {
                Logger.Write(LogColor.Cancel, "^Spirit Shell: cancel since not in Combat");
                Me.CancelAura("Spirit Shell");
            })
                       ));
        }
예제 #4
0
        /// <summary>
        /// implements standard Rest behavior.  self-heal optional and typically used by DPS that have healing spell,
        /// as healing specs are better served using a spell appropriate to amount of healing needed.  ressurrect
        /// is optional and done only if spell name passed
        /// </summary>
        /// <param name="spellHeal">name of healing spell</param>
        /// <param name="spellRez">name of ressurrect spell</param>
        /// <returns></returns>
        public static Composite CreateDefaultRestBehaviour(string spellHeal = null, string spellRez = null)
        {
            return(new PrioritySelector(

                       new Decorator(
                           ret => !Me.IsDead && !Me.IsGhost,
                           new PrioritySelector(

                               // Self-heal if possible
                               new Decorator(
                                   ret =>
            {
                if (IsEatingOrDrinking)
                {
                    return false;
                }
                if (spellHeal == null || Me.HealthPercent > 85)
                {
                    return false;
                }
                if (!SpellManager.HasSpell(spellHeal))
                {
                    return false;
                }
                if (!Spell.CanCastHack(spellHeal, Me))
                {
                    Logger.WriteDebug("DefaultRest: CanCast failed for {0}", spellHeal);
                    return false;
                }
                if (Me.PredictedHealthPercent(includeMyHeals: true) > 85)
                {
                    return false;
                }
                return true;
            },
                                   new Sequence(
                                       new PrioritySelector(
                                           Movement.CreateEnsureMovementStoppedBehavior(reason: "to heal"),
                                           new Wait(TimeSpan.FromMilliseconds(500), until => !Me.IsMoving, new ActionAlwaysSucceed())
                                           ),
                                       new PrioritySelector(
                                           new Sequence(
                                               ctx => Me.HealthPercent,
                                               new Action(r => Logger.WriteDebug("Rest Heal - {0} @ {1:F1}% Predict:{2:F1}% and moving:{3}, cancast:{4}",
                                                                                 spellHeal, (double)r, Me.PredictedHealthPercent(includeMyHeals: true), Me.IsMoving, Spell.CanCastHack(spellHeal, Me, skipWowCheck: false))),
                                               Spell.Cast(spellHeal,
                                                          mov => true,
                                                          on => Me,
                                                          req => true,
                                                          cancel =>
            {
                if (Me.HealthPercent < 90)
                {
                    return false;
                }
                Logger.WriteDiagnostic("Rest Heal - cancelling since health reached {0:F1}%", Me.HealthPercent);
                return true;
            },
                                                          LagTolerance.No
                                                          ),
                                               new Action(r => Logger.WriteDebug("Rest - Before Heal Cast Wait")),
                                               new WaitContinue(TimeSpan.FromMilliseconds(1500), until => Spell.CanCastHack(spellHeal, Me), new ActionAlwaysSucceed()),
                                               new Action(r => Logger.WriteDebug("Rest - Before Heal Health Increase Wait")),
                                               new WaitContinue(TimeSpan.FromMilliseconds(500), until => Me.HealthPercent > (1.1 * ((double)until)), new ActionAlwaysSucceed()),
                                               new Action(r => Logger.WriteDebug("Rest - Before Heal Cast Wait")),
                                               new Action(r =>
            {
                Logger.WriteDebug("Rest - After Heal Completed: {0:F1}% Predicted: {1:F1}%", Me.HealthPercent, Me.PredictedHealthPercent(includeMyHeals: true));
                return RunStatus.Success;
            })
                                               ),

                                           new Action(r => {
                Logger.WriteDebug("Rest - After Heal Skipped: {0:F1}% Predicted: {1:F1}%", Me.HealthPercent, Me.PredictedHealthPercent(includeMyHeals: true));
                return RunStatus.Failure;
            })
                                           )
                                       )
                                   ),

                               // Make sure we wait out res sickness.
                               Helpers.Common.CreateWaitForRessSickness(),

                               // Cannibalize support goes before drinking/eating. changed to a Sequence with wait because Rest behaviors that had a
                               // .. WaitForCast() before call to DefaultRest would prevent cancelling when health/mana reached
                               new Decorator(
                                   ret => SingularSettings.Instance.UseRacials &&
                                   (Me.PredictedHealthPercent(includeMyHeals: true) <= SingularSettings.Instance.MinHealth || (Me.PowerType == WoWPowerType.Mana && Me.ManaPercent <= SingularSettings.Instance.MinMana)) &&
                                   Spell.CanCastHack("Cannibalize") &&
                                   CorpseAround,
                                   new Sequence(
                                       new DecoratorContinue(ret => Me.IsMoving, Movement.CreateEnsureMovementStoppedBehavior(reason: "to cannibalize")),
                                       new Wait(1, ret => !Me.IsMoving, new ActionAlwaysSucceed()),
                                       new Action(ret => Logger.Write(LogColor.SpellHeal, "*Cannibalize @ health:{0:F1}%{1}", Me.HealthPercent, (Me.PowerType != WoWPowerType.Mana) ? "" : string.Format(" mana:{0:F1}%", Me.ManaPercent))),
                                       new Action(ret => Spell.CastPrimative("Cannibalize")),

                                       // wait until Cannibalize in progress
                                       new WaitContinue(
                                           1,
                                           ret => Me.CastingSpell != null && Me.CastingSpell.Name == "Cannibalize",
                                           new ActionAlwaysSucceed()
                                           ),
                                       // wait until cast or healing complete. use actual health percent here
                                       new WaitContinue(
                                           10,
                                           ret => Me.CastingSpell == null ||
                                           Me.CastingSpell.Name != "Cannibalize" ||
                                           (Me.HealthPercent > 95 && (Me.PowerType != WoWPowerType.Mana || Me.ManaPercent > 95)),
                                           new ActionAlwaysSucceed()
                                           ),
                                       // show completion message and cancel cast if needed
                                       new Action(ret =>
            {
                bool stillCasting = Me.CastingSpell != null && Me.CastingSpell.Name == "Cannibalize";
                Logger.WriteFile("{0} @ health:{1:F1}%{2}",
                                 stillCasting ? "/cancel Cannibalize" : "Cannibalize ended",
                                 Me.HealthPercent,
                                 (Me.PowerType != WoWPowerType.Mana) ? "" : string.Format(" mana:{0:F1}%", Me.ManaPercent)
                                 );

                if (stillCasting)
                {
                    SpellManager.StopCasting();
                }
            })
                                       )
                                   ),

                               // use a bandage if enabled (it's quicker)
                               new Decorator(
                                   ret => Me.IsAlive && Me.PredictedHealthPercent(includeMyHeals: true) <= SingularSettings.Instance.MinHealth,
                                   Item.CreateUseBandageBehavior()
                                   ),

                               // Make sure we're a class with mana, if not, just ignore drinking all together! Other than that... same for food.
                               new Decorator(
                                   ret => !Me.Combat &&
                                   !Me.Stunned &&
                                   !Me.IsSwimming && (Me.PowerType == WoWPowerType.Mana || Me.Class == WoWClass.Druid) &&
                                   Me.ManaPercent <= SingularSettings.Instance.MinMana &&
                                   !Me.HasAnyAura("Drink", "Refreshment") && Consumable.GetBestDrink(false) != null,
                                   new PrioritySelector(
                                       Movement.CreateEnsureMovementStoppedBehavior(reason: "to drink"),
                                       new Decorator(
                                           req => !Me.IsMoving,
                                           new Sequence(
                                               new Action(ret =>
            {
                Logger.Write("Drinking @ {0:F1}% mana", Me.ManaPercent);
                Styx.CommonBot.Rest.DrinkImmediate();
            }),
                                               Helpers.Common.CreateWaitForLagDuration(),
                                               new PrioritySelector(
                                                   new Wait(TimeSpan.FromMilliseconds(500), until => Me.HasAnyAura("Drink", "Refreshment"), new ActionAlwaysSucceed()),
                                                   new Action(r => Logger.WriteDiagnostic("Drinking: failed to see 'Drink' aura"))
                                                   )
                                               )
                                           )
                                       )
                                   ),

                               // Check if we're allowed to eat (and make sure we have some food. Don't bother going further if we have none.
                               new Decorator(
                                   ret => !Me.Combat &&
                                   !Me.Stunned &&
                                   !Me.IsSwimming &&
                                   Me.PredictedHealthPercent(includeMyHeals: true) <= SingularSettings.Instance.MinHealth &&
                                   !Me.HasAnyAura("Food", "Refreshment") && Consumable.GetBestFood(false) != null,
                                   new PrioritySelector(
                                       Movement.CreateEnsureMovementStoppedBehavior(reason: "to eat"),
                                       new Decorator(
                                           req => !Me.IsMoving,
                                           new Sequence(
                                               new Action(
                                                   ret =>
            {
                float myHealth = Me.PredictedHealthPercent(includeMyHeals: true);
                Logger.WriteDebug("NeedToEat:  predictedhealth @ {0:F1}", myHealth);
                Logger.Write("Eating @ {0:F1}% health", Me.HealthPercent);
                Styx.CommonBot.Rest.FeedImmediate();
            }),
                                               Helpers.Common.CreateWaitForLagDuration(),
                                               new PrioritySelector(
                                                   new Wait(TimeSpan.FromMilliseconds(500), until => Me.HasAnyAura("Food", "Refreshment"), new ActionAlwaysSucceed()),
                                                   new Action(r => Logger.WriteDiagnostic("Eating: failed to see 'Food' aura"))
                                                   )
                                               )
                                           )
                                       )
                                   ),

                               // STAY SEATED (in Rest) while eating/drinking aura active.
                               //  true: stay seated
                               //  false:  allow interruption of Drink
                               new Decorator(
                                   ret => Me.HasAnyAura("Drink", "Refreshment") &&
                                   (Me.PowerType == WoWPowerType.Mana || Me.Specialization == WoWSpec.DruidFeral) &&
                                   Me.ManaPercent < 95,
                                   new ActionAlwaysSucceed()
                                   ),

                               new Decorator(
                                   req => Me.HasAnyAura("Food", "Refreshment") && Me.HealthPercent < 95,
                                   new PrioritySelector(
                                       new Decorator(
                                           req => spellHeal != null &&
                                           Spell.CanCastHack(spellHeal, Me) &&
                                           Me.PowerType == WoWPowerType.Mana &&
                                           Me.ManaPercent >= 70 &&
                                           Me.HealthPercent < 85,
                                           new Sequence(
                                               new Action(r => Logger.Write(LogColor.Hilite, "^Stop eating and '{0}' since mana reached {1:F1}%", spellHeal, Me.ManaPercent)),
                                               new Action(r => Me.CancelAura("Food")),
                                               new Wait(TimeSpan.FromMilliseconds(500), until => !Me.HasAura("Food"), new ActionAlwaysSucceed())
                                               )
                                           ),

                                       new ActionAlwaysSucceed() // keep eating then
                                       )
                                   ),

                               // wait here if we are moving -OR- do not have food or drink
                               new Decorator(
                                   ret => WaitForRegenIfNoFoodDrink(),

                                   new PrioritySelector(
                                       new Decorator(
                                           ret => Me.IsMoving,
                                           new PrioritySelector(
                                               new Throttle(5, new Action(ret => Logger.Write("Still moving... waiting until Bot stops"))),
                                               new ActionAlwaysSucceed()
                                               )
                                           ),
                                       new Decorator(
                                           req => Me.IsSwimming,
                                           new PrioritySelector(
                                               new Throttle(15, new Action(ret => Logger.Write("Swimming. Waiting to recover our health/mana back"))),
                                               new ActionAlwaysSucceed()
                                               )
                                           ),
                                       new PrioritySelector(
                                           new Throttle(15, new Action(ret => Logger.Write("We have no food/drink. Waiting to recover our health/mana back"))),
                                           new ActionAlwaysSucceed()
                                           )
                                       )
                                   ),

                               // rez anyone near us if appropriate
                               new Decorator(ret => spellRez != null, Spell.Resurrect(spellRez)),

                               // hack:  some bots not calling PreCombatBuffBehavior, so force the call if we are about done resting
                               // SingularRoutine.Instance.PreCombatBuffBehavior,

                               Movement.CreateWorgenDarkFlightBehavior()
                               )
                           )
                       ));
        }
예제 #5
0
        public static Composite CreateMistweaverCombatBehaviorInstances()
        {
            return(new PrioritySelector(

                       CancelSoothingMistAsNeeded(),
                       CreateMistWeaverDiagnosticOutputBehavior(on => MyHealTarget),

                       new Decorator(
                           req => true,
                           new PrioritySelector(
                               // HealerManager.CreateMeleeHealerMovementBehavior( Common.CreateMonkCloseDistanceBehavior( min => 30, on => (WoWUnit) on)),
                               HealerManager.CreateStayNearTankBehavior(Common.CreateMonkCloseDistanceBehavior(min => 30, on => (WoWUnit)on)),

                               /*
                                *                  new Decorator(
                                *                      unit => MovementManager.IsClassMovementAllowed
                                *                          && !MonkSettings.DisableRoll
                                *                          && (unit as WoWUnit).SpellDistance() > 10
                                *                          && Me.IsSafelyFacing(unit as WoWUnit, 5f),
                                *                      Spell.Cast("Roll")
                                *                      )
                                *                  ),
                                */
                               new Decorator(
                                   ret => Me.Combat && HealerManager.AllowHealerDPS(),
                                   new PrioritySelector(

                                       CreateMistweaverMoveToEnemyTarget(),
                                       new Decorator(
                                           req => Me.GotTarget() && Me.CurrentTarget.IsAlive,
                                           Movement.CreateFaceTargetBehavior()
                                           ),

                                       Spell.WaitForCastOrChannel(),

                                       #region Spinning Crane Kick progress handler

                                       new Decorator(
                                           req => Me.HasActiveAura("Spinning Crane Kick"), // don't wait for Rushing Jade Wind since we can cast
                                           new PrioritySelector(
                                               new Action(r =>
            {
                Logger.WriteFile(SpinningCraneKick + ": in progress with {0} ms left", (long)Me.GetAuraTimeLeft(SpinningCraneKick).TotalMilliseconds);
                return RunStatus.Failure;
            }),
                                               new Decorator(
                                                   req =>
            {
                if (Me.GetAuraTimeLeft(SpinningCraneKick).TotalMilliseconds < 333)
                {
                    return false;
                }

                int countFriendly = Unit.NearbyGroupMembersAndPets.Count(u => u.SpellDistance() <= 8);
                if (countFriendly >= 3)
                {
                    return false;
                }

                if (HealerManager.CancelHealerDPS())
                {
                    Logger.Write(LogColor.Cancel, "/cancel {0} since only {1} friendly targets hit and cannot DPS", SpinningCraneKick, countFriendly);
                    return true;
                }

                int countEnemy = Unit.NearbyUnfriendlyUnits.Count(u => u.SpellDistance() <= 8);
                if ((countFriendly + countEnemy) < 3)
                {
                    Logger.Write(LogColor.Cancel, "/cancel {0} since only {1} friendly and {2} enemy targets hit", SpinningCraneKick, countFriendly, countEnemy);
                    return true;
                }
                return false;
            },
                                                   new Sequence(
                                                       new Action(r => Me.CancelAura(SpinningCraneKick)),
                                                       new Wait(1, until => !Me.HasActiveAura(SpinningCraneKick), new ActionAlwaysFail())
                                                       )
                                                   ),

                                               // dont go past here if SCK active
                                               new ActionAlwaysSucceed()
                                               )
                                           ),
                                       #endregion

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

                                               new Decorator(
                                                   req => Me.GotTarget() && Me.CurrentTarget.IsWithinMeleeRange,
                                                   Helpers.Common.CreateAutoAttack()
                                                   ),

                                               Helpers.Common.CreateInterruptBehavior(),

                                               Spell.Cast("Leg Sweep", ret => Spell.UseAOE && SingularRoutine.CurrentWoWContext == WoWContext.Normal && Me.CurrentTarget.IsWithinMeleeRange),

                                               Spell.Cast(
                                                   SpinningCraneKick,
                                                   ret => Spell.UseAOE && HealerManager.AllowHealerDPS() && Unit.NearbyUnfriendlyUnits.Count(u => u.SpellDistance() <= 8) >= MonkSettings.SpinningCraneKickCnt
                                                   ),

                                               Spell.Cast("Rising Sun Kick"),
                                               Spell.Cast("Blackout Kick", req => Me.GetAuraStacks("Teachings of the Monastery") >= 3),
                                               Spell.Cast("Tiger Palm")
                                               )
                                           ),

                                       Spell.Cast("Roll",
                                                  req => MovementManager.IsClassMovementAllowed &&
                                                  !MonkSettings.DisableRoll &&
                                                  Me.CurrentTarget.Distance > minDistRollAllowed
                                                  )
                                       )
                                   )
                               )
                           ),

                       new Decorator(
                           ret => !Spell.IsGlobalCooldown() && Unit.NearbyGroupMembers.Any(m => m.IsAlive && !m.IsMe),
                           new PrioritySelector(
                               CreateMistweaverMonkHealing(selfOnly: false),
                               new Decorator(
                                   req => true,
                                   Helpers.Common.CreateInterruptBehavior()
                                   )
                               )
                           ),

                       Spell.WaitForCastOrChannel()
                       ));
        }