public static Composite DefaultRestBehaviour() { return // Don't f*****g run the rest behavior (or any other) if we're dead or a ghost. Thats all. (new Decorator( ret => !Me.IsDead && !Me.IsGhost && !Me.IsCasting && Settings.EnableRest && BotPoi.Current.Type != PoiType.Loot && !Me.IsActuallyInCombat, new PrioritySelector( // Make sure we wait out res sickness. F**k the classes that can deal with it. :O new Decorator(ret => StyxWoW.Me.HasAura("Resurrection Sickness"), new Action(ret => { })), // 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 => !StyxWoW.Me.IsSwimming && StyxWoW.Me.HealthPercent <= IwmSettings.Instance.EatPercent && !StyxWoW.Me.HasAura("Food") && Consumable.GetBestFood(true) != null && !StyxWoW.Me.IsCasting, new PrioritySelector( new Decorator( ret => StyxWoW.Me.IsMoving, new Action(ret => Navigator.PlayerMover.MoveStop())), new Sequence( new Action(ret => Log.Info("[Rest] [Eating]")), new Action(ret => Styx.CommonBot.Rest.FeedImmediate()), CreateWaitForLagDuration()))), // Make sure we're a class with mana, if not, just ignore drinking all together! Other than that... same for food. new Decorator( ret => !StyxWoW.Me.IsSwimming && (StyxWoW.Me.PowerType == WoWPowerType.Mana) && StyxWoW.Me.ManaPercent <= IwmSettings.Instance.DrinkPercent && !StyxWoW.Me.HasAura("Drink") && Consumable.GetBestDrink(true) != null && !StyxWoW.Me.IsCasting, new PrioritySelector( new Decorator( ret => StyxWoW.Me.IsMoving, new Action(ret => Navigator.PlayerMover.MoveStop())), new Sequence( new Action(ret => Log.Info("[Rest] [Drinking]")), new Action(ret => Styx.CommonBot.Rest.DrinkImmediate()), CreateWaitForLagDuration()))), // This is to ensure we STAY SEATED while eating/drinking. No reason for us to get up before we have to. new Decorator( ret => (StyxWoW.Me.HasAura("Food") && StyxWoW.Me.HealthPercent < 98) || (StyxWoW.Me.HasAura("Drink") && StyxWoW.Me.PowerType == WoWPowerType.Mana && StyxWoW.Me.ManaPercent < 98), new ActionAlwaysSucceed()), new Decorator( ret => ((StyxWoW.Me.PowerType == WoWPowerType.Mana && StyxWoW.Me.ManaPercent <= 60) || StyxWoW.Me.HealthPercent <= 60) && !StyxWoW.Me.CurrentMap.IsBattleground, new Action( ret => Log.Warning("We have no food/drink. Waiting to recover our health/mana back"))) ))); }
public static bool On_Drink() { bool retval; if (BotPoi.Current.Type != PoiType.None) { return(false); } string fnname = "FTWCore.On_Drink"; MyTimer.Start(fnname); if (StyxWoW.Me.HasAura("Drink")) { retval = true; } else if (FTWCoreStatus.OnCooldown("On_Drink")) { retval = false; } else if (FTWUtils.MovementDisabled()) { retval = false; } else if (StyxWoW.Me.Mounted) { retval = false; } else { WoWItem drink = Consumable.GetBestDrink(false); if (drink == null) { retval = false; } else { Navigator.PlayerMover.MoveStop(); Styx.CommonBot.Rest.DrinkImmediate(); DateTime stoptime = DateTime.Now.AddSeconds(10); while (DateTime.Now < stoptime) { if (StyxWoW.Me.HasAura("Drink")) { break; } Thread.Sleep(100); } FTWCoreStatus.SaveCooldown("On_Drink"); retval = true; } } MyTimer.Stop(fnname); return(retval); }
public override void Pulse() { if (_updateTimer.IsFinished) { _updateTimer.Reset(); var drink = Consumable.GetBestDrink(false); var food = Consumable.GetBestFood(false); if (drink != null) { CharacterSettings.Instance.DrinkName = drink.Entry.ToString(); } if (food != null) { CharacterSettings.Instance.FoodName = food.Entry.ToString(); } } }
public static Composite CreateDefaultRestBehaviour() { return // Don't f*****g run the rest behavior (or any other) if we're dead or a ghost. Thats all. (new Decorator( ret => !StyxWoW.Me.Dead && !StyxWoW.Me.IsGhost && !StyxWoW.Me.IsCasting, new PrioritySelector( // Make sure we wait out res sickness. F**k the classes that can deal with it. :O new Decorator( ret => SingularSettings.Instance.WaitForResSickness && StyxWoW.Me.HasAura("Resurrection Sickness"), new Action(ret => { })), // Wait while cannibalizing new Decorator( ret => StyxWoW.Me.CastingSpell != null && StyxWoW.Me.CastingSpell.Name == "Cannibalize" && (StyxWoW.Me.HealthPercent < 95 || (StyxWoW.Me.PowerType == WoWPowerType.Mana && StyxWoW.Me.ManaPercent < 95)), new Sequence( new Action(ret => Logger.Write("Waiting for Cannibalize")), new ActionAlwaysSucceed())), // Cannibalize support goes before drinking/eating new Decorator( ret => (StyxWoW.Me.HealthPercent <= SingularSettings.Instance.MinHealth || (StyxWoW.Me.PowerType == WoWPowerType.Mana && StyxWoW.Me.ManaPercent <= SingularSettings.Instance.MinMana)) && SpellManager.CanCast("Cannibalize") && CorpseAround, new Sequence( new Action(ret => Navigator.PlayerMover.MoveStop()), new Action(ret => StyxWoW.SleepForLagDuration()), new Action(ret => SpellManager.Cast("Cannibalize")), new Action(ret => Thread.Sleep(1000)))), // 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 => !StyxWoW.Me.IsSwimming && StyxWoW.Me.HealthPercent <= SingularSettings.Instance.MinHealth && !StyxWoW.Me.HasAura("Food") && Consumable.GetBestFood(false) != null, new PrioritySelector( new Decorator( ret => StyxWoW.Me.IsMoving, new Action(ret => Navigator.PlayerMover.MoveStop())), new Action( ret => { Styx.Logic.Common.Rest.FeedImmediate(); StyxWoW.SleepForLagDuration(); }) )), // Make sure we're a class with mana, if not, just ignore drinking all together! Other than that... same for food. new Decorator( ret => !StyxWoW.Me.IsSwimming && (StyxWoW.Me.PowerType == WoWPowerType.Mana || StyxWoW.Me.Class == WoWClass.Druid) && StyxWoW.Me.ManaPercent <= SingularSettings.Instance.MinMana && !StyxWoW.Me.HasAura("Drink") && Consumable.GetBestDrink(false) != null, new PrioritySelector( new Decorator( ret => StyxWoW.Me.IsMoving, new Action(ret => Navigator.PlayerMover.MoveStop())), new Action( ret => { Styx.Logic.Common.Rest.DrinkImmediate(); StyxWoW.SleepForLagDuration(); }) )), // This is to ensure we STAY SEATED while eating/drinking. No reason for us to get up before we have to. new Decorator( ret => (StyxWoW.Me.HasAura("Food") && StyxWoW.Me.HealthPercent < 95) || (StyxWoW.Me.HasAura("Drink") && StyxWoW.Me.PowerType == WoWPowerType.Mana && StyxWoW.Me.ManaPercent < 95), new ActionAlwaysSucceed()), new Decorator( ret => ((StyxWoW.Me.PowerType == WoWPowerType.Mana && StyxWoW.Me.ManaPercent <= SingularSettings.Instance.MinMana) || StyxWoW.Me.HealthPercent <= SingularSettings.Instance.MinHealth) && !StyxWoW.Me.CurrentMap.IsBattleground, new Action(ret => Logger.Write("We have no food/drink. Waiting to recover our health/mana back"))) ))); }
public Composite CreateDefaultRestComposite(int minHealth, int minMana) { return(new PrioritySelector( // Don't rest if the leader is in combat. Ever. //new Decorator(ret=> Me.IsInParty, // new Decorator(ret=>RaFHelper.Leader != null && RaFHelper.Leader.Combat, // new ActionAlwaysFail())), // Make sure we wait out res sickness. F**k the classes that can deal with it. :O new Decorator( //Hackish way to avoid waiting for rez sickness at An End to All Things quest in DK zone ret => SingularSettings.Instance.WaitForResSickness && Me.HasAura("Resurrection Sickness") && !Me.QuestLog.ContainsQuest(12779), new ActionLogMessage(false, "Waiting for resurrection sickness to fade off")), // Wait while cannibalizing new Decorator( ret => Me.CastingSpell != null && Me.CastingSpell.Name == "Cannibalize" && (Me.HealthPercent < 95 || (Me.PowerType == WoWPowerType.Mana && Me.ManaPercent < 95)), new Sequence( new ActionLogMessage(false, "Waiting for Cannibalize"), new ActionAlwaysSucceed())), // Cannibalize support goes before drinking/eating new Decorator( ret => (Me.HealthPercent <= minHealth || (Me.PowerType == WoWPowerType.Mana && Me.ManaPercent <= minMana)) && CanCast("Cannibalize", Me, false) && CorpseAround, new Sequence( new Action(ret => Navigator.PlayerMover.MoveStop()), new Action(ret => StyxWoW.SleepForLagDuration()), new Action(ret => SpellManager.Cast("Cannibalize")), new Action(ret => Thread.Sleep(1000)))), // 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.IsSwimming && Me.HealthPercent <= minHealth && !Me.HasAura("Food") && Consumable.GetBestFood(false) != null, new PrioritySelector( new ActionLogMessage(true, "Checking movement for food."), new Decorator( ret => Me.IsMoving, new Action(ret => Navigator.PlayerMover.MoveStop())), new Action( ret => { Styx.Logic.Common.Rest.FeedImmediate(); StyxWoW.SleepForLagDuration(); }) )), // 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.IsSwimming && Me.PowerType == WoWPowerType.Mana && Me.ManaPercent <= minMana && !Me.HasAura("Drink") && Consumable.GetBestDrink(false) != null, new PrioritySelector( new ActionLogMessage(true, "Checking movement for water."), new Decorator( ret => Me.IsMoving, new Action(ret => Navigator.PlayerMover.MoveStop())), new Action( ret => { Styx.Logic.Common.Rest.DrinkImmediate(); StyxWoW.SleepForLagDuration(); }) )), // This is to ensure we STAY SEATED while eating/drinking. No reason for us to get up before we have to. new Decorator( ret => (Me.HasAura("Food") && Me.HealthPercent < 95) || (Me.HasAura("Drink") && Me.PowerType == WoWPowerType.Mana && Me.ManaPercent < 95), new ActionAlwaysSucceed()), new Decorator( ret => (Me.PowerType == WoWPowerType.Mana && Me.ManaPercent <= minMana) || Me.HealthPercent <= minHealth, new Action(ret => Logger.Write("We have no food/drink. Waiting to recover our health/mana back"))) )); }
/// <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() ) ) )); }