Example #1
0
        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")))
                         )));
        }
Example #2
0
        public static bool On_Eat()
        {
            string fnname = "FTWCore.On_Eat";

            MyTimer.Start(fnname);
            bool retval;

            if (BotPoi.Current.Type != PoiType.None)
            {
                return(false);
            }

            if (StyxWoW.Me.HasAura("Food"))
            {
                retval = true;
            }
            else if (FTWCoreStatus.OnCooldown("On_Eat"))
            {
                retval = false;
            }
            else if (FTWUtils.MovementDisabled())
            {
                retval = false;
            }
            else if (StyxWoW.Me.Mounted)
            {
                retval = false;
            }
            else
            {
                WoWItem eat = Consumable.GetBestFood(false);
                if (eat == null)
                {
                    retval = false;
                }
                else
                {
                    Navigator.PlayerMover.MoveStop();
                    Styx.CommonBot.Rest.FeedImmediate();
                    DateTime stoptime = DateTime.Now.AddSeconds(10);
                    while (DateTime.Now < stoptime)
                    {
                        if (StyxWoW.Me.HasAura("Food"))
                        {
                            break;
                        }
                        Thread.Sleep(100);
                    }
                    FTWCoreStatus.SaveCooldown("On_Eat");
                    retval = true;
                }
            }
            MyTimer.Stop(fnname);
            return(retval);
        }
Example #3
0
        public static Composite BuildRestBehavior()
        {
            return(new Decorator(ret => !Helpers.Rogue.me.IsSwimming && !Helpers.Rogue.me.IsGhost &&
                                 Helpers.Rogue.me.IsAlive && !Helpers.Rogue.me.Mounted &&
                                 Styx.CommonBot.POI.BotPoi.Current.Type != Styx.CommonBot.POI.PoiType.Loot &&
                                 Helpers.Area.mLocation != Helpers.Enum.LocationContext.Raid &&
                                 Helpers.Area.mLocation != Helpers.Enum.LocationContext.HeroicDungeon,
                                 new PrioritySelector(

                                     new Decorator(ret => Helpers.Aura.Stealth && Helpers.Rogue.mHP < 25 && Helpers.Target.mNearbyEnemyUnits.Count(unit => unit.Distance <= 20) > 0,
                                                   new PrioritySelector(
                                                       new Action(
                                                           ret => {
                Logging.Write(LogLevel.Diagnostic, "Waiting so I don't get ganked by those mobs");
                //new WaitContinue(System.TimeSpan.FromSeconds(2), ret2 => false, new ActionAlwaysSucceed());
            })
                                                       )
                                                   ),
                                     Helpers.Spells.CastSelf("Stealth", ret => Helpers.Spells.GetAuraTimeLeft(Helpers.Rogue.me, "Food", Helpers.Rogue.me.Guid) > 17 &&
                                                             Helpers.Rogue.mHP <= 90 && !Helpers.Rogue.me.HasAura("Stealth")),
                                     new Decorator(
                                         ret =>
                                         Helpers.Spells.IsAuraActive(Helpers.Rogue.me, "Food") && Helpers.Rogue.mHP <= 90,
                                         new ActionAlwaysSucceed()),
                                     Helpers.Spells.CastSelf("Recuperate", ret => Helpers.Rogue.me.RawComboPoints >= 1 &&
                                                             !Helpers.Spells.IsAuraActive(
                                                                 Helpers.Rogue.me, "Recuperate") &&
                                                             Helpers.Rogue.CheckSpamLock()),
                                     new Decorator(
                                         ret => Consumable.GetBestFood(true) != null && Helpers.Rogue.mHP <= 70 && !Helpers.Rogue.me.MovementInfo.IsStrafing,
                                         new PrioritySelector(
                                             new Decorator(ret => Helpers.Rogue.me.IsMoving,
                                                           new Action(ret => Navigator.PlayerMover.MoveStop())
                                                           ),
                                             new Action(ret =>
            {
                Styx.CommonBot.Rest.FeedImmediate();
                new WaitContinue(System.TimeSpan.FromSeconds(2), ret2 => false, new ActionAlwaysSucceed());
            })
                                             )
                                         ),

                                     new Decorator(ret => Helpers.Rogue.mHP <= 30,
                                                   new PrioritySelector(
                                                       Helpers.Spells.CastSelf("Stealth",
                                                                               ret => !Helpers.Rogue.me.HasAura("Stealth")),
                                                       new Action(
                                                           ret =>
                                                           Logging.Write(LogLevel.Normal, "No food, waiting to heal!"))
                                                       )
                                                   )
                                     )
                                 ));
        }
Example #4
0
        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();
                }
            }
        }
Example #5
0
        protected override Composite CreateBehavior()
        {
            return(_root ?? (_root =
                                 new PrioritySelector(
                                     new Action(c =>
            {
                if (Me.HealthPercent < 2)
                {
                    return RunStatus.Failure;
                }
                if (Me.HealthPercent < 60 && !Me.IsActuallyInCombat)
                {
                    WoWItem food = Consumable.GetBestFood(true);
                    CharacterSettings.Instance.FoodName = food != null ? food.Name : string.Empty;
                    Rest.Feed();
                    return RunStatus.Running;
                }
                if (IsInVehicle)
                {
                    _isBehaviorDone = true;
                    return RunStatus.Success;
                }
                WoWUnit Horse = ObjectManager.GetObjectsOfType <WoWUnit>().Where(u => u.Entry == 28782).OrderBy(u => u.Distance).FirstOrDefault();
                if (Horse != null)
                {
                    if (!Me.IsActuallyInCombat)
                    {
                        if (Horse.Distance > 4)
                        {
                            Navigator.MoveTo(Horse.Location);
                        }
                        else
                        {
                            Horse.Interact();
                        }
                    }
                    if (Me.IsActuallyInCombat)
                    {
                        if (Me.CurrentTarget != null)
                        {
                            if (Me.CurrentTarget.Dead)
                            {
                                Me.ClearTarget();
                            }
                            else if (Me.CurrentTarget.Entry == 28768)
                            {
                                if (!Me.IsSafelyFacing(Horse))
                                {
                                    Horse.Face();
                                }
                            }
                            else if (!Me.IsSafelyFacing(Me.CurrentTarget))
                            {
                                Me.CurrentTarget.Face();
                            }
                            if (Me.IsMoving)
                            {
                                WoWMovement.MoveStop();
                            }
                            if (!Me.IsSafelyFacing(Me.CurrentTarget))
                            {
                                Me.CurrentTarget.Face();
                            }
                            if (SpellManager.CanCast("Icy Touch"))
                            {
                                SpellManager.Cast("Icy Touch");
                            }
                            if (SpellManager.CanCast("Plague Strike"))
                            {
                                SpellManager.Cast("Plague Strike");
                            }
                            if (SpellManager.CanCast("Blood Strike"))
                            {
                                SpellManager.Cast("Blood Strike");
                            }
                            if (SpellManager.CanCast("Death Coil"))
                            {
                                SpellManager.Cast("Death Coil");
                            }
                        }
                    }
                }
                else
                {
                    Navigator.MoveTo(Location);
                }

                return RunStatus.Running;
            }

                                                ))));
        }
Example #6
0
        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")))
                         )));
        }
Example #7
0
        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")))
                       ));
        }
Example #8
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()
                               )
                           )
                       ));
        }