Example #1
0
        private void toolStripSecretButton_Click(object sender, EventArgs e)
        {
            PrioritySelector ps = TreeRoot.Current.Root as PrioritySelector;
            int n = 0;

            Logging.Write("** BotBase **");
            foreach (var p in ps.Children)
            {
                // add alternating amount of spaces to the end of log entries to prevent spam filter from blocking it
                n = (n + 1) % 2;
                Logging.Write("[{0}] {1}", p.GetType(), new string(' ', n));
            }

            //Logging.Write("** Profile Settings **");
            //foreach (var kv in PB.ProfileSettings.Settings)
            //    Logging.Write("{0} {1}", kv.Key, kv.Value);

            Logging.Write("** ActionSelector **");
            printComposite(PB.CurrentProfile.Branch, 0);

            //Logging.Write("** Material List **");
            //foreach (var kv in PB.MaterialList)
            //    Logging.Write("Ingredient ID: {0} Amount required:{1}", kv.Key, kv.Value);

            //Logging.Write("** DataStore **");
            //foreach (var kv in PB.DataStore)
            //    Logging.Write("item ID: {0} Amount in bag/bank/ah/alts:{1}", kv.Key, kv.Value);

            //if (PB.CsharpStringBuilder != null)
            //    Logging.Write(PB.CsharpStringBuilder.ToString());
        }
        public Composite GenerateBehaviorTree()
        {
            if (!SingularSettings.Debug)
            {
                return(new PrioritySelector(blist.Select(b => b.behavior).ToArray()));
            }

            PrioritySelector pri = new PrioritySelector();

            foreach (PrioritizedBehavior pb in blist)
            {
                if (!SingularSettings.TraceHeals)
                {
                    pri.AddChild(pb.behavior);
                }
                else
                {
                    CallTrace ct = new CallTrace(pb.Name, pb.behavior);
                    ct.TraceActive = true;
                    ct.TraceEnter  = false;
                    ct.TraceExit   = true;
                    pri.AddChild(ct);
                }
            }

            return(pri);
        }
Example #3
0
    //DynamicAddNode will allow the user to add any type of node to any composite node which exists inside of the treeNodeCollection list
    public void DynamicAddNode(Node nodeToAdd, string parentName = null)
    {
        //Check if the root exists, and a parent name for searching has been specified
        if (Root != null && parentName != null)
        {
            //Search for the name of the specified parent inside the list of all nodes inside of the tree
            Node parentToRecieve = treeNodeCollection.FirstOrDefault(o => o.NodeName == parentName);

            //Add the new node to the specified parent
            parentToRecieve.AddChild(nodeToAdd);

            //Add the new node to the list of all the nodes inside the tree
            AddToTreeNodeCollection(nodeToAdd);
        }

        //Else check if the root is null
        else if (Root == null)
        {
            //Debug that the user request is being overriden
            Debug.LogError("OVERRIDING REQUEST, ROOT IS NULL AND HAS TO BE ADDED");

            //Override and add a new root
            Root = new PrioritySelector(1, "root", behaviorTreeHandler);

            //Add the new root to the full list of nodes inside of the tree
            AddToTreeNodeCollection(Root);
        }

        //Else check if the specified parent is null
        else if (parentName == null)
        {
            //Debug that the user has to add a parent name
            Debug.LogError("INVALID PARENT. PLEASE ADD A PARENT NAME FOR SEARCHING");
        }
    }
Example #4
0
        private static SwitchArgument <RepairState> GetRepairStep(RepairContext context)
        {
            var closeAction = new Action(r =>
            {
                Repair.Close();
                context.State = BotManager.Current.Name != "Fate Bot"
                    ? RepairState.MovingBack : RepairState.None;

                Logger.AgilMessage("Ended repair step, now on: {0}", context.State);
            });

            var close = new Decorator(req => Equipment.GetCondition() >= context.MinimumDurability && Repair.IsOpen,
                                      closeAction);

            var dismount = new Decorator(req => Core.Me.IsMounted,
                                         new Action(r => Actionmanager.Dismount()));

            var selectYes = new Decorator(req => SelectYesno.IsOpen,
                                          new Action(r => SelectYesno.ClickYes()));

            var move         = Movement.SprintMove(r => context.Location);
            var repairAll    = new RepairAll();
            var selectRepair = new SetIconString(2);
            var setTarget    = new SetTarget(() => context.NpcId);

            var interact = new Decorator(req => !Repair.IsOpen && !SelectIconString.IsOpen && !SelectYesno.IsOpen,
                                         new Interact());

            var repairStep = new PrioritySelector(move, dismount, close, selectYes, repairAll, selectRepair,
                                                  setTarget, interact, new Action(r => RunStatus.Success));

            return(new SwitchArgument <RepairState>(repairStep, RepairState.Repairing));
        }
Example #5
0
        public void ReadXml(XmlReader reader)
        {
            int count;

            reader.MoveToContent();
            int.TryParse(reader["ChildrenCount"], out count);
            reader.ReadStartElement("Professionbuddy");
            PrioritySelector ps = (PrioritySelector)DecoratedChild;

            for (int i = 0; i < count; i++)
            {
                Type type = Type.GetType("HighVoltz.Composites." + reader.Name);
                if (type != null)
                {
                    IPBComposite comp = (IPBComposite)Activator.CreateInstance(type);
                    if (comp != null)
                    {
                        comp.ReadXml(reader);
                        ps.AddChild((Composite)comp);
                    }
                }
                else
                {
                    Professionbuddy.Err("PB:Failed to load type {0}", type);
                }
            }
            if (reader.NodeType == XmlNodeType.EndElement)
            {
                reader.ReadEndElement();
            }
        }
Example #6
0
        public void RebuildBehaviors()
        {
            Composite simcRoot = null;

            NameCount = 'A';

            simcRoot = new PrioritySelector(
                new Action(context =>
            {
                iterationCounter++;
                return(RunStatus.Failure);
            }),
                new Decorator(ret => IsPaused,
                              new Action(ret => RunStatus.Success)),
                CallActionList(ActionProxy.ActionImpl.oocapl, ret => !StyxWoW.Me.Combat),
                new Decorator(ret => StyxWoW.Me.Combat,
                              new LockSelector(
                                  new Decorator(
                                      ret => StyxWoW.Me.CurrentTarget != null && StyxWoW.Me.Combat,
                                      new PrioritySelector(CombatIteration(), actions.Selector, IterationEnd())))));

            TreeHooks.Instance.ReplaceHook(SimcraftHookName, simcRoot);

            if (Me.Specialization != Specialisation)
            {
                SelectorWindow.ShowDialog();
            }

            Specialisation = Me.Specialization;
        }
        public void WhenAChildReturnsSuccessOrRunning_ReturnTheSameAndDoNotCallNextChildInSequence(BehaviourStatus status)
        {
            var behaviours = Enumerable.Range(0, 10)
                             .Select(x => new MockBehaviour {
                ReturnStatus = BehaviourStatus.Failed
            })
                             .ToArray();

            behaviours[4].ReturnStatus = status;

            var sut = new PrioritySelector <MockContext>(behaviours);

            var behaviourStatus = sut.Tick(new MockContext());

            Assert.That(behaviourStatus, Is.EqualTo(status));

            for (int i = 0; i < 4; i++)
            {
                var mockBehaviour = behaviours[i];

                Assert.That(mockBehaviour.InitializeCallCount, Is.EqualTo(1));
                Assert.That(mockBehaviour.UpdateCallCount, Is.EqualTo(1));
            }

            for (int i = 5; i < behaviours.Length; i++)
            {
                var mockBehaviour = behaviours[i];

                Assert.That(mockBehaviour.InitializeCallCount, Is.EqualTo(0));
                Assert.That(mockBehaviour.UpdateCallCount, Is.EqualTo(0));
                Assert.That(mockBehaviour.TerminateCallCount, Is.EqualTo(0));
            }
        }
Example #8
0
        /// <summary>
        /// use Alchemist's Flask if no flask buff active. do over optimize since this is a precombatbuff behavior
        /// </summary>
        /// <returns></returns>

        public static Composite CreateUseXPBuffPotionsBehavior()
        {
            const int ACCELERATED_LEARNING = 178119;                    // (aura)
            const int EXCESS_POTION_OF_ACCELERATED_LEARNING = 120182;   // (item)

            if (!SingularSettings.Instance.UseXPBuffPotions)
            {
                return(new ActionAlwaysFail());
            }

            PrioritySelector pri = new PrioritySelector();

            if (Me.Level.Between(91, 99))
            {
                pri.AddChild(
                    new Decorator(
                        req => !Me.HasAura(ACCELERATED_LEARNING),
                        UseItem(EXCESS_POTION_OF_ACCELERATED_LEARNING)
                        )
                    );
            }

            if (!pri.Children.Any())
            {
                return(new ActionAlwaysFail());
            }

            return(new ThrottlePasses(
                       1,
                       TimeSpan.FromSeconds(15),
                       RunStatus.Failure,
                       pri
                       ));
        }
        // remove any occurance of IdentityComposite in the current BotBase, used on dispose or botbase change
        void BotBaseCleanUp(PrioritySelector bot)
        {
            PrioritySelector botbase = null;

            if (bot != null)
            {
                botbase = bot;
            }
            else if (TreeRoot.Current.Root is PrioritySelector)
            {
                botbase = TreeRoot.Current.Root as PrioritySelector;
            }
            // check if we already injected into the BotBase
            if (botbase != null)
            {
                bool isRunning = botbase.IsRunning;
                if (isRunning)
                {
                    TreeRoot.Stop();
                }
                for (int i = botbase.Children.Count - 1; i >= 0; i--)
                {
                    //if (botbase.Children[i] is IdentityComposite ) // this will not work after a recompile because the types are now in different assemblies
                    if (botbase.Children[i].GetType().Name.Contains("PBIdentityComposite"))
                    {
                        botbase.Children.RemoveAt(i);
                    }
                }
            }
        }
Example #10
0
        /// <summary>
        /// Factory method to create new Red Guard
        /// </summary>
        /// <returns></returns>
        public static Entity Create()
        {
            ChaseBehavior ChasingHero;
            //ChaseBehavior ChasingCompanions;
            AlwaysTurnRightBehavior Turning;
            RandomWanderBehavior    Wandering;
            AttackEnemyBehavior     Attacking;

            var e  = GameFactory.CreateThing(ThingType.RED_GUARD, true);
            var ai = new BTAIComp();

            e.AddComponent(ai);
            var sub = new PrioritySelector();

            ai.rootNode = sub;

            var tc = e.GetComponent <ThingComp>();

            tc.IsCollisionFree = false;
            tc.Color           = new Color(255, 10, 4);
            tc.Faction         = Faction.EVIL;

            var rwc = new RandomWanderComp();

            e.AddComponent(rwc);
            rwc.MinDirectionChangeTime = 2.7;
            rwc.MaxDirectionChangeTime = 11.3;

            // attack hero or companions
            Attacking = new AttackEnemyBehavior(attackString);

            // chase companions that are very close

            /*
             * ChasingCompanions = new ChaseBehavior(typeof(Companion));
             * ChasingCompanions.DeltaTimeBetweenMoves = RandomMath.RandomBetween(0.43f, 0.65f);
             * ChasingCompanions.ChaseRange = 1.5f; // RandomMath.RandomBetween(12f, 40f);
             * sub.AddChild(ChasingCompanions);
             */

            // chase hero
            ChasingHero = new ChaseBehavior(Level.Current.Hero);
            ChasingHero.DeltaTimeBetweenMoves = RandomMath.RandomBetween(0.47f, 0.75f);
            ChasingHero.ChaseRange            = 15f; // RandomMath.RandomBetween(12f, 40f);
            sub.AddChild(ChasingHero);

            Turning = new AlwaysTurnRightBehavior();                           // patrolling
            Turning.DeltaTimeBetweenMoves = ChasingHero.DeltaTimeBetweenMoves; //RandomMath.RandomBetween(0.57f, 1.05f);
            Turning.DeltaTimeBetweenMoves = 0.7f;
            sub.AddChild(Turning);

            Wandering = new RandomWanderBehavior();
            Wandering.DeltaTimeBetweenMoves = 0.7f;
            sub.AddChild(Wandering);

            e.Refresh();
            return(e);
        }
Example #11
0
        public static Composite GetComposite(WoWClass wowClass, WoWSpec spec, BehaviorType behavior, WoWContext context, out int behaviourCount)
        {
            behaviourCount = 0;
            if (_methods.Count <= 0)
            {
                Logger.Write("Building method list");
                foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
                {
                    // All behavior methods should not be generic, and should have zero parameters, with their return types being of type Composite.
                    _methods.AddRange(
                        type.GetMethods(BindingFlags.Static | BindingFlags.Public).Where(
                            mi => !mi.IsGenericMethod && mi.GetParameters().Length == 0).Where(
                                mi => mi.ReturnType.IsAssignableFrom(typeof (Composite))));
                }
                Logger.Write("Added " + _methods.Count + " methods");
            }
            var matchedMethods = new Dictionary<BehaviorAttribute, Composite>();

            foreach (MethodInfo mi in _methods)
            {
                // If the behavior is set as ignore. Don't use it? Duh?
                if (mi.GetCustomAttributes(typeof(IgnoreBehaviorCountAttribute), false).Any())
                    continue;

                // If there's no behavior attrib, then move along.
                foreach (var a in mi.GetCustomAttributes(typeof(BehaviorAttribute), false))
                {
                    var attribute = a as BehaviorAttribute;
                    if (attribute == null)
                        continue;

                    // Check if our behavior matches with what we want. If not, don't add it!
                    if (IsMatchingMethod(attribute, wowClass, spec, behavior, context))
                    {
                        Logger.Write(string.Format("Matched {0} to behavior {1} for {2} {3} with priority {4}", mi.Name,
                            behavior, wowClass.ToString().CamelToSpaced(), spec.ToString().CamelToSpaced(),
                            attribute.PriorityLevel));

                        // if it blows up here, you defined a method with the exact same attribute and priority as one already found
                        matchedMethods.Add(attribute, mi.Invoke(null, null) as Composite);
                    }
                }
            }
            // If we found no methods, rofls!
            if (matchedMethods.Count <= 0)
            {
                return null;
            }

            var result = new PrioritySelector();
            foreach (var kvp in matchedMethods.OrderByDescending(mm => mm.Key.PriorityLevel))
            {
                result.AddChild(kvp.Value);
                behaviourCount++;
            }

            return result;
        }
 void BotEvents_OnBotChanged(BotEvents.BotChangedEventArgs args)
 {
     if (TreeRoot.Current.Root is PrioritySelector)
     {
         PrioritySelector botbase = TreeRoot.Current.Root as PrioritySelector;
         BotBaseCleanUp(botbase);
         botbase.InsertChild(0, Root);
     }
 }
Example #13
0
 protected override Composite CreateBehavior()
 {
     PrioritySelector p = new PrioritySelector();
     foreach (var behavior in GetNodes().Select(b => b.Behavior))
     {
         p.AddChild(new Decorator(ret => GetConditionExec(), behavior));//
     }
     return new Decorator(ret => !IsDone, p);
 }
Example #14
0
 public override void Initialize()
 {
     Settings.DefualtSettings();
     Fight            = new PrioritySelector();
     BotMain.OnStart += OnStart;
     BotMain.OnStop  += OnStop;
     BotMain.OnTick  += Pulse;
     Log.Debug("Allrounder by xTenshiSanx has been loaded");
 }
Example #15
0
        public static Composite CreateDispelBehavior()
        {
            PrioritySelector prio = new PrioritySelector();

            switch (StyxWoW.Me.Class)
            {
            case WoWClass.Paladin:
                prio.AddChild(Spell.Cast("Cleanse", on => _unitDispel, ret => BossMechs.MechDispell()));
                break;

            case WoWClass.Monk:
                prio.AddChild(Spell.Cast("Detox", on => _unitDispel, ret => BossMechs.MechDispell()));
                break;

            case WoWClass.Priest:
                if (StyxWoW.Me.Specialization == WoWSpec.PriestHoly || StyxWoW.Me.Specialization == WoWSpec.PriestDiscipline)
                {
                    prio.AddChild(Spell.Cast("Purify", on => _unitDispel, ret => BossMechs.MechDispell()));
                }
                break;

            case WoWClass.Druid:
                if (StyxWoW.Me.Specialization == WoWSpec.DruidRestoration)
                {
                    prio.AddChild(Spell.Cast("Nature's Cure", on => _unitDispel, ret => BossMechs.MechDispell()));
                }
                else
                {
                    prio.AddChild(Spell.Cast("Remove Corruption", on => _unitDispel, ret => BossMechs.MechDispell()));
                }
                break;

            case WoWClass.Shaman:
                if (StyxWoW.Me.Specialization == WoWSpec.ShamanRestoration)
                {
                    prio.AddChild(Spell.Cast("Purify Spirit", on => _unitDispel, ret => BossMechs.MechDispell()));
                }
                else
                {
                    prio.AddChild(Spell.Cast("Cleanse Spirit", on => _unitDispel, ret => BossMechs.MechDispell()));
                }
                break;

            case WoWClass.Mage:
                prio.AddChild(Spell.Cast("Remove Curse", on => _unitDispel, ret => BossMechs.MechDispell()));
                break;
            }

            return(new Sequence(
                       new Action(r => _unitDispel = (from unit in ObjectManager.GetObjectsOfType <WoWPlayer>(false)
                                                      where unit.IsAlive
                                                      where CanDispel(unit)
                                                      select unit).OrderByDescending(u => u.HealthPercent).LastOrDefault()),
                       //HealerManager.Instance.TargetList.FirstOrDefault(u => u.IsAlive && CanDispel(u))),
                       prio
                       ));
        }
Example #16
0
        public static Composite GetBehavior(AvoidanceContext context)
        {
            var reportUnknown = new Action(r => context.Capture.CaptureScreenshot(context));
            var update        = new Action(r => context.Update());
            var move          = CommonBehaviors.MoveAndStop(r => context.SafeLocation, 1f, true);
            var avoidCheck    = new PrioritySelector(new Decorator(req => context.IsAvoiding, move),
                                                     new Decorator(req => context.IsWaiting, new Action(r => RunStatus.Success)));

            return(new Sequence(update, avoidCheck));
        }
Example #17
0
        protected override Composite CreateBehavior()
        {
            var decorated = new PrioritySelector(new Composite[0]);

            foreach (var behavior in base.GetNodes())
            {
                decorated.AddChild(behavior.Behavior);
            }
            return(new Decorator(CheckNotAlreadyDone, decorated));
        }
Example #18
0
        protected override Composite CreateBehavior()
        {
            PrioritySelector decorated = new PrioritySelector(new Composite[0]);

            foreach (ProfileBehavior behavior in base.GetNodes())
            {
                decorated.AddChild(behavior.Behavior);
            }
            return(new Zeta.TreeSharp.Decorator(new CanRunDecoratorDelegate(CheckNotAlreadyDone), decorated));
        }
Example #19
0
        protected override Composite CreateBehavior()
        {
            PrioritySelector p = new PrioritySelector();

            foreach (var behavior in GetNodes().Select(b => b.Behavior))
            {
                p.AddChild(new Decorator(ret => GetConditionExec(), behavior));//
            }
            return(new Decorator(ret => !IsDone, p));
        }
        private IBehaviourNode CreateBehaviourTree()
        {
            // Shoot, Chase, Idle
            var ret = new PrioritySelector(
                BehaviourFactory.CreateShootTarget(),
                BehaviourFactory.CreateChaseTarget(),
                BehaviourFactory.CreateGuardPosition(() => GuardPosition));


            return(ret);
        }
Example #21
0
    public static Node CreateBehaviorTree(Dorf d)
    {
        PrioritySelector root = new PrioritySelector();

        root.AddChild(CreateFleeBehavior(d),Double.MaxValue);

        root.AddChild(CreateInteractionBehavior(d, d.Workplace),50.0);

        root.AddChild(CreateInteractionBehavior(d, d.Bed));

        return root;
    }
Example #22
0
    private PrioritySelector CreateSpiderBT()
    {
        Node idleMotion = IdleMotion();


        PrioritySelector attackSelector = AttackPattern();

        //PlayerAround around = new PlayerAround(attackSelector, gameObject, enemy, playerDistance);
        return(new PrioritySelector(new List <Node> {
            attackSelector, idleMotion
        }));
    }
Example #23
0
        public static Composite CreateBehavior(EquipmentContext equipContext, RepairContext repairContext)
        {
            var repair = repairContext.RepairEnabled ? RepairBehavior.CreateBehavior(repairContext)
                : new Action(r => RunStatus.Failure);

            var optimize = equipContext.OptimizerEnabled ? GearOptimizer.GetBehavior(equipContext)
                : new Action(r => RunStatus.Failure);

            var behavior = new PrioritySelector(repair, optimize);

            return(new Decorator(req => CanAct, behavior));
        }
Example #24
0
        public static Composite GetBehavior(EquipmentContext context)
        {
            var startup = new Decorator(req => !context.Optimizing, new Action(r => context.Optimizing = true));
            var cleanup = new Action(r => context.Reset());

            var optimize = new PrioritySelector(startup, EquipWeapon(context), EquipArmor(context, 2), EquipArmor(context, 7),
                                                EquipArmor(context, 3), EquipArmor(context, 4), EquipArmor(context, 5), EquipRing(context, 11, 12),
                                                EquipArmor(context, 6), EquipArmor(context, 8), EquipArmor(context, 9), EquipRing(context, 12, 11),
                                                EquipArmor(context, 10), EquipOffhand(context), cleanup);

            return(new Decorator(req => CanOptimize && NeedsOptimization(context), optimize));
        }
Example #25
0
        /// <summary>
        /// This will replace the main BehaviorTree hooks for Combat, Vendoring, and Looting.
        /// </summary>
        private static void ReplaceTreeHooks()
        {
            // This is the do-all-be-all god-head all encompasing piece of trinity
            TreeHooks.Instance.ReplaceHook("Combat", new Decorator(ctx => CheckHasTarget(ctx), HandleTargetAction()));

            // We still want the main VendorRun logic, we're just going to take control of *when* this logic kicks in
            PrioritySelector VendorRunPrioritySelector = (TreeHooks.Instance.Hooks["VendorRun"][0] as Decorator).Children[0] as PrioritySelector;

            TreeHooks.Instance.ReplaceHook("VendorRun", new Decorator(ret => TownRun.TownRunCanRun(ret), VendorRunPrioritySelector));

            // Loot tree is now empty and never runs (Loot is handled through combat)
            TreeHooks.Instance.ReplaceHook("Loot", new Decorator(ret => false, new Action()));
        }
Example #26
0
        // [Behavior(BehaviorType.Combat, priority: 999)]
        public static Composite CreateUseTrinketsBehaviour()
        {
            // Saving Settings via GUI will now force reinitialize so we can build the behaviors
            // basead upon the settings rather than continually checking the settings in the Btree
            //
            //

            if (SingularSettings.Instance.Trinket1Usage == TrinketUsage.Never && SingularSettings.Instance.Trinket2Usage == TrinketUsage.Never)
            {
                return(new Action(ret => { return RunStatus.Failure; }));
            }

            PrioritySelector ps = new PrioritySelector();

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.OnCooldown))
            {
                ps.AddChild(Item.UseEquippedTrinket(TrinketUsage.OnCooldown));
            }

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.OnCooldownInCombat))
            {
                ps.AddChild(Item.UseEquippedTrinket(TrinketUsage.OnCooldownInCombat));
            }

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.LowHealth))
            {
                ps.AddChild(new Decorator(ret => StyxWoW.Me.HealthPercent < SingularSettings.Instance.PotionHealth,
                                          Item.UseEquippedTrinket(TrinketUsage.LowHealth)));
            }

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.LowPower))
            {
                ps.AddChild(new Decorator(ret => StyxWoW.Me.PowerPercent < SingularSettings.Instance.PotionMana,
                                          Item.UseEquippedTrinket(TrinketUsage.LowPower)));
            }

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.CrowdControlled))
            {
                ps.AddChild(new Decorator(ret => Unit.IsCrowdControlled(StyxWoW.Me),
                                          Item.UseEquippedTrinket(TrinketUsage.CrowdControlled)));
            }

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.CrowdControlledSilenced))
            {
                ps.AddChild(new Decorator(ret => StyxWoW.Me.Silenced && Unit.IsCrowdControlled(StyxWoW.Me),
                                          Item.UseEquippedTrinket(TrinketUsage.CrowdControlledSilenced)));
            }

            return(ps);
        }
Example #27
0
        public static Composite CreateUseTrinketsBehaviour()
        {
            // Saving Settings via GUI will now force reinitialize so we can build the behaviors
            // basead upon the settings rather than continually checking the settings in the Btree
            //
            //

            if (SingularSettings.Instance.Trinket1Usage == TrinketUsage.Never && SingularSettings.Instance.Trinket2Usage == TrinketUsage.Never)
            {
                return new Action(ret => { return RunStatus.Failure; });
            }

            PrioritySelector ps = new PrioritySelector();

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.OnCooldown))
            {
                ps.AddChild(Item.UseEquippedTrinket(TrinketUsage.OnCooldown));
            }

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.OnCooldownInCombat))
            {
                ps.AddChild(Item.UseEquippedTrinket(TrinketUsage.OnCooldownInCombat));
            }

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.LowHealth))
            {
                ps.AddChild( new Decorator( ret => StyxWoW.Me.HealthPercent < SingularSettings.Instance.PotionHealth,
                                            Item.UseEquippedTrinket( TrinketUsage.LowHealth)));
            }

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.LowPower))
            {
                ps.AddChild( new Decorator( ret => StyxWoW.Me.PowerPercent < SingularSettings.Instance.PotionMana,
                                            Item.UseEquippedTrinket(TrinketUsage.LowPower)));
            }

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.CrowdControlled ))
            {
                ps.AddChild( new Decorator( ret => Unit.IsCrowdControlled( StyxWoW.Me),
                                            Item.UseEquippedTrinket( TrinketUsage.CrowdControlled )));
            }

            if (SingularSettings.IsTrinketUsageWanted(TrinketUsage.CrowdControlledSilenced ))
            {
                ps.AddChild( new Decorator( ret => StyxWoW.Me.Silenced && Unit.IsCrowdControlled( StyxWoW.Me),
                                            Item.UseEquippedTrinket(TrinketUsage.CrowdControlledSilenced)));
            }

            return ps;
        }
Example #28
0
        private static SwitchArgument <RepairState> GetReturnStep(RepairContext context)
        {
            var finalize = new Action(r =>
            {
                context.State = RepairState.None;
                Logger.AgilMessage("Finished moving back.");
                return(RunStatus.Success);
            });

            var move = Movement.SprintMove(r => context.Location);

            var returnStep = new PrioritySelector(move, finalize,
                                                  new Action(r => RunStatus.Success));

            return(new SwitchArgument <RepairState>(returnStep, RepairState.MovingBack));
        }
Example #29
0
        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement("Professionbuddy");
            PrioritySelector ps = (PrioritySelector)DecoratedChild;

            writer.WriteStartAttribute("ChildrenCount");
            writer.WriteValue(ps.Children.Count);
            writer.WriteEndAttribute();
            foreach (IPBComposite comp in ps.Children)
            {
                writer.WriteStartElement(comp.GetType().Name);
                ((IXmlSerializable)comp).WriteXml(writer);
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }
Example #30
0
        private static Composite CreateCombatRacialInRangeBehavior()
        {
            PrioritySelector priCombat = new PrioritySelector();

            // not a racial, but best place to handle it
            if (SpellManager.HasSpell("Lifeblood"))
            {
                priCombat.AddChild(
                    Spell.HandleOffGCD(Spell.BuffSelf("Lifeblood", ret => !PartyBuff.WeHaveBloodlust))
                    );
            }

            if (SpellManager.HasSpell("Berserking"))
            {
                priCombat.AddChild(
                    Spell.HandleOffGCD(Spell.BuffSelf("Berserking", ret => !PartyBuff.WeHaveBloodlust))
                    );
            }

            if (SpellManager.HasSpell("Blood Fury"))
            {
                priCombat.AddChild(
                    Spell.HandleOffGCD(Spell.BuffSelf("Blood Fury", ret => true))
                    );
            }

            if (priCombat.Children.Any())
            {
                return(new Decorator(
                           req =>
                {
                    if (!StyxWoW.Me.Combat || !StyxWoW.Me.GotTarget())
                    {
                        return false;
                    }
                    if (StyxWoW.Me.IsMelee())
                    {
                        return StyxWoW.Me.CurrentTarget.IsWithinMeleeRange;
                    }
                    return !StyxWoW.Me.IsMoving && StyxWoW.Me.CurrentTarget.SpellDistance() < 40;
                },
                           priCombat
                           ));
            }

            return(null);
        }
Example #31
0
        /// <summary>
        ///  Blows your wad all over the floor, copied from Singular
        /// </summary>
        /// <returns>Nothing but win</returns>
        public static Composite UseTrinkets()
        {
            if (CLUSettings.Instance.Trinket1Usage == TrinketUsage.Never && CLUSettings.Instance.Trinket2Usage == TrinketUsage.Never)
            {
                return(new Action(ret => { return RunStatus.Failure; }));
            }

            PrioritySelector ps = new PrioritySelector();

            if (CLUSettings.IsTrinketUsageWanted(TrinketUsage.OnCooldown))
            {
                ps.AddChild(Item.UseEquippedTrinket(TrinketUsage.OnCooldown));
            }

            if (CLUSettings.IsTrinketUsageWanted(TrinketUsage.OnCooldownInCombat))
            {
                ps.AddChild(Item.UseEquippedTrinket(TrinketUsage.OnCooldownInCombat));
            }

            if (CLUSettings.IsTrinketUsageWanted(TrinketUsage.LowHealth))
            {
                ps.AddChild(new Decorator(ret => StyxWoW.Me.HealthPercent < CLUSettings.Instance.MinHealth,
                                          Item.UseEquippedTrinket(TrinketUsage.LowHealth)));
            }

            if (CLUSettings.IsTrinketUsageWanted(TrinketUsage.LowPower))
            {
                ps.AddChild(new Decorator(ret => StyxWoW.Me.PowerPercent < CLUSettings.Instance.MinMana,
                                          Item.UseEquippedTrinket(TrinketUsage.LowPower)));
            }

            if (CLUSettings.IsTrinketUsageWanted(TrinketUsage.CrowdControlled))
            {
                ps.AddChild(new Decorator(ret => Unit.UnitIsControlled(Me, false),
                                          Item.UseEquippedTrinket(TrinketUsage.CrowdControlled)));
            }

            if (CLUSettings.IsTrinketUsageWanted(TrinketUsage.CrowdControlledSilenced))
            {
                ps.AddChild(new Decorator(ret => StyxWoW.Me.Silenced && Unit.UnitIsControlled(Me, false),
                                          Item.UseEquippedTrinket(TrinketUsage.CrowdControlledSilenced)));
            }

            return(ps);
            //return UseEquippedTrinket();
        }
        public void WhenAReevaluatedChildReturnsSuccess_ReturnSuccessAndResetChildren()
        {
            var behaviours = Enumerable.Range(0, 10)
                             .Select(x => new MockBehaviour {
                ReturnStatus = BehaviourStatus.Failed
            })
                             .ToArray();

            behaviours[4].ReturnStatus = BehaviourStatus.Running;

            var sut = new PrioritySelector <MockContext>(behaviours);

            sut.Tick(new MockContext());
            behaviours[0].ReturnStatus = BehaviourStatus.Succeeded;
            sut.Tick(new MockContext());

            Assert.That(behaviours[0].InitializeCallCount, Is.EqualTo(1));
            Assert.That(behaviours[0].UpdateCallCount, Is.EqualTo(2));
            Assert.That(behaviours[0].TerminateCallCount, Is.EqualTo(2));
            Assert.That(behaviours[0].ResetCount, Is.EqualTo(1));

            for (int i = 1; i < 4; i++)
            {
                var mockBehaviour = behaviours[i];

                Assert.That(mockBehaviour.InitializeCallCount, Is.EqualTo(1));
                Assert.That(mockBehaviour.UpdateCallCount, Is.EqualTo(1));
                Assert.That(mockBehaviour.TerminateCallCount, Is.EqualTo(1));
                Assert.That(mockBehaviour.ResetCount, Is.EqualTo(1));
            }

            Assert.That(behaviours[4].InitializeCallCount, Is.EqualTo(1));
            Assert.That(behaviours[4].UpdateCallCount, Is.EqualTo(1));
            Assert.That(behaviours[4].TerminateCallCount, Is.EqualTo(0));
            Assert.That(behaviours[4].ResetCount, Is.EqualTo(1));

            for (int i = 5; i < behaviours.Length; i++)
            {
                var mockBehaviour = behaviours[i];

                Assert.That(mockBehaviour.InitializeCallCount, Is.EqualTo(0));
                Assert.That(mockBehaviour.UpdateCallCount, Is.EqualTo(0));
                Assert.That(mockBehaviour.TerminateCallCount, Is.EqualTo(0));
                Assert.That(mockBehaviour.ResetCount, Is.EqualTo(0));
            }
        }
        public void WhenAllChildrenReturnFailure_ReturnFailure()
        {
            var behaviours = Enumerable.Range(0, 10)
                             .Select(x => new MockBehaviour {
                ReturnStatus = BehaviourStatus.Failed
            })
                             .ToArray();

            var sut = new PrioritySelector <MockContext>(behaviours);

            var behaviourStatus = sut.Tick(new MockContext());

            Assert.That(behaviourStatus, Is.EqualTo(BehaviourStatus.Failed));
            Assert.That(behaviours.AllInitialized(), Is.True);
            Assert.That(behaviours.AllUpdated(), Is.True);
            Assert.That(behaviours.AllTerminated(), Is.True);
        }
Example #34
0
    //AddRoot will add the root to the tree. Incase the root already exists, it will notify the user to use the DynamicAddNode function instead.
    public void AddRoot()
    {
        //Check if the root is not null
        if (Root != null)
        {
            //If the root is not null then the root exists, so debug that the root exists
            Debug.LogError("ROOT EXISTS. USE DYNAMICADDNODE FUNCTION");
        }
        else
        {
            //If it is null, add a new root to the tree
            Root = new PrioritySelector(1, "root", behaviorTreeHandler);

            //Add the new root to the full list of nodes inside of the tree
            AddToTreeNodeCollection(Root);
        }
    }
Example #35
0
        public static Composite CreateShamanEnhancementHealPvp()
        {
            Composite healBT =
                new PrioritySelector(
                    new Decorator( ret => StyxWoW.Me.HasAura("Maelstrom Weapon", 5),
                        new PrioritySelector(
                            ctx => Unit.GroupMembers.Where( p => p.IsAlive && p.GetPredictedHealthPercent() < 50 && p.Distance < 40).FirstOrDefault(),
                            Spell.Cast( "Healing Surge", ret => StyxWoW.Me, ret => StyxWoW.Me.GetPredictedHealthPercent() < 75 ),
                            Spell.Cast( "Healing Surge", ret => (WoWPlayer) ret, ret => StyxWoW.Me.GetPredictedHealthPercent() < 50 )
                            )
                        ),

                    new Decorator(
                        ret => !StyxWoW.Me.Combat,
                        Spell.Heal("Healing Surge", ret => StyxWoW.Me, ret => StyxWoW.Me.GetPredictedHealthPercent() <= 80)
                        )
                    );

            return healBT;
        }
Example #36
0
    // Use this for initialization
    void Start()
    {
        mate = buddy.transform;
        speed = 1.1f;
        direction = mate.position - transform.position;

        root = new SequenceSelector(); redSeq = new SequenceSelector();
        colors = new PrioritySelector(); movement = new PrioritySelector();
        close = new Condition(() => Mathf.Abs(Vector3.Distance(transform.position, mate.position)) < kindaClose);
        red = new Action(Red); green = new Action(Green);
        toward = new Action(Toward); away = new Action(Away);

        root.AddChild(colors, movement);

        colors.AddChild(redSeq,1.0); colors.AddChild(green);
        redSeq.AddChild(close,red);

        movement.AddChild(away,farAway);
        towardPrio = movement.AddChild(toward);
        toward.name = "toward";
    }
Example #37
0
        public static Composite Cast(SpellFindDelegate ssd, SimpleBooleanDelegate checkMovement, UnitSelectionDelegate onUnit,
            SimpleBooleanDelegate requirements, SimpleBooleanDelegate cancel = null, LagTolerance allow = LagTolerance.Yes, bool skipWowCheck = false, CanCastDelegate canCast = null, HasGcd gcd = HasGcd.Yes)
        {
            // only need to check these at creation time
            if (ssd == null || checkMovement == null || onUnit == null || requirements == null)
                return new ActionAlwaysFail();

            if (canCast == null)
                canCast = CanCastHack;

            Composite comp =  new PrioritySelector(

                // create a CastContext object to save passed in context and other values
                ctx => new CastContext(ctx, ssd, onUnit, gcd),

                new Sequence(
                    // cast the spell, saving state information including if we queued this cast
                    new Action(ret =>
                    {
                        CastContext cctx = ret.CastContext();

                        if (cctx.spell == null)
                            return RunStatus.Failure;   

                        if (cctx.unit == null)
                            return RunStatus.Failure;

                        if (!requirements(cctx.context))
                            return RunStatus.Failure;

                        if (checkMovement(cctx.context) && Me.IsMoving && !AllowMovingWhileCasting(cctx.spell))
                        {
                            if (SingularSettings.DebugSpellCasting)
                                Logger.WriteDebug("skipping Spell.Cast({0},[{1}]) because we are moving", cctx.unit.SafeName(), cctx.spell.Name);
                            return RunStatus.Failure;
                        }

                        // check we can cast it on target without checking for movement
                        // if (!Spell.CanCastHack(_spell, cctx.unit, true, false, allow == LagTolerance.Yes))
                        if (!canCast(cctx.sfr, cctx.unit, skipWowCheck))
                        {
                            if (SingularSettings.DebugSpellCasting)
                                Logger.WriteDebug("skipping Spell.Cast({0},[{1}]) because CanCastHack failed", cctx.unit.SafeName(), cctx.spell.Name);
                            return RunStatus.Failure;
                        }

                        // save status of queueing spell (lag tolerance - the prior spell still completing)
                        cctx.IsSpellBeingQueued = allow == LagTolerance.Yes && (Spell.GcdActive || StyxWoW.Me.IsCasting || StyxWoW.Me.IsChanneling);

                        const int PENANCE = 047540;
                        LogCast(
                            cctx.spell.Name, 
                            cctx.unit, 
                            cctx.health, 
                            cctx.distance,
                            cctx.spell.IsHeal() ? true : (cctx.spell.Id == PENANCE && cctx.unit.IsFriendly)
                            );

                        if (SingularSettings.DebugSpellCasting)
                            Logger.WriteDebug("Cast('{0}'): dist:{1:F3}, need({2}), hitbox:{3:F3}",
                                cctx.spell.Name, 
                                cctx.unit.Distance,
                                cctx.spell.IsMeleeSpell
                                    ? "Melee"
                                    : (!cctx.spell.HasRange ? "None" : string.Format("min={0:F3},max={1:F3}", cctx.spell.MinRange, cctx.spell.MaxRange)),
                                cctx.unit.CombatReach
                                );

                        if (!Spell.CastPrimative(cctx.spell, cctx.unit))
                        {
                            Logger.Write(Color.LightPink, "cast of {0} on {1} failed!", cctx.spell.Name, cctx.unit.SafeName());
                            return RunStatus.Failure;
                        }

                        SingularRoutine.UpdateDiagnosticCastingState();
                        return RunStatus.Success;
                    }),

                    new Action(r =>
                    {
                        if (SingularSettings.DebugSpellCasting)
                        {
                            CastContext cctx = r.CastContext();
                            Logger.WriteFile("Spell.Cast[{0}]: checking to ensure cast in progress", cctx.spell.Name);
                        }
                        return RunStatus.Success;
                    }),

                // for instant spell, wait for GCD to start
                // for non-instant spell, wait for .IsCasting / .IsChanneling to start
                    new PrioritySelector(
                        new Wait(
                            TimeSpan.FromMilliseconds(350),
                            until =>
                            {
                                CastContext cctx = until.CastContext();
                                if (gcd == HasGcd.No)
                                {
                                    if (SingularSettings.DebugSpellCasting)
                                        Logger.WriteFile("Spell.Cast[{0}]: has no GCD, status GCD={1}, remains={2}", cctx.spell.Name, Spell.IsGlobalCooldown(allow).ToYN(), (long)Spell.GcdTimeLeft.TotalMilliseconds);
                                    return true;
                                }

                                if (cctx.spell.IsInstantCast() && Spell.GcdTimeLeft.TotalMilliseconds > 650)
                                {
                                    if (SingularSettings.DebugSpellCasting)
                                        Logger.WriteFile("Spell.Cast[{0}]: is instant, status GCD={1}, remains={2}", cctx.spell.Name, Spell.IsGlobalCooldown(allow).ToYN(), (long)Spell.GcdTimeLeft.TotalMilliseconds);
                                    return true;
                                }

                                if (Me.CurrentCastTimeLeft.TotalMilliseconds > 750)
                                {
                                    if (SingularSettings.DebugSpellCasting)
                                        Logger.WriteFile( "Spell.Cast[{0}]: cast time {1} left, iscasting={2}", cctx.spell.Name, (long)Me.CurrentCastTimeLeft.TotalMilliseconds, Spell.IsCasting(allow).ToYN());
                                    return true;
                                }

                                if (Me.CurrentChannelTimeLeft.TotalMilliseconds > 750)
                                {
                                    if (SingularSettings.DebugSpellCasting)
                                        Logger.WriteFile( "Spell.Cast[{0}]: channel spell and channel has {1} left, ischanneling={2}", cctx.spell.Name, (long)Me.CurrentChannelTimeLeft.TotalMilliseconds, Spell.IsChannelling(allow).ToYN());
                                    return true;
                                }

                                return false;
                            },
                            new ActionAlwaysSucceed()
                            ),
                        new Action( r => {
                            if (SingularSettings.DebugSpellCasting)
                            {
                                CastContext cctx = r.CastContext();
                                Logger.WriteFile( "Spell.Cast[{0}]: timed out failing to detect spell in progress - gcdleft={1}/{2}, castleft={3}/{4}, chanleft={5}/{6}", cctx.spell.Name, Spell.IsGlobalCooldown(allow).ToYN(), (long)Spell.GcdTimeLeft.TotalMilliseconds, Spell.IsCasting(allow).ToYN(), (long)Me.CurrentCastTimeLeft.TotalMilliseconds, Spell.IsCasting(allow).ToYN(), (long)Me.CurrentChannelTimeLeft.TotalMilliseconds);
                            }
                            return RunStatus.Success;
                            })
                        ),

        // now check for one of the possible done casting states
                    new PrioritySelector(

                        // for cast already ended, assume it has no Global Cooldown
                        new Decorator(
                            ret => !Spell.IsGlobalCooldown() && !Spell.IsCastingOrChannelling(),
                            new Action(r =>
                            {
                                CastContext cctx = r.CastContext();
                                if (SingularSettings.DebugSpellCasting)
                                {
                                    if (!Spell.IsGlobalCooldown())
                                        Logger.WriteFile("Spell.Cast(\"{0}\"): complete, no gcd active, lag={0} hasgcd={1}", cctx.spell.Name, allow, gcd);
                                    else
                                        Logger.WriteFile("Spell.Cast(\"{0}\"): complete, no cast in progress", cctx.spell.Name);
                                }
                                return RunStatus.Success;
                            })
                            ),

                        // for instant or no cancel method given, we are done
                        new Decorator(
                            ret => gcd == HasGcd.No || cancel == null || ret.CastContext().spell.IsInstantCast(),
                            new Action(r =>
                            {
                                CastContext cctx = r.CastContext();
                                if (SingularSettings.DebugSpellCasting)
                                {
                                    if (gcd == HasGcd.No)
                                        Logger.WriteFile("Spell.Cast(\"{0}\"): complete, hasgcd=No", cctx.spell.Name);
                                    else if (r.CastContext().spell.IsInstantCast())
                                        Logger.WriteFile("Spell.Cast(\"{0}\"): complete, is instant cast", cctx.spell.Name);
                                    else
                                        Logger.WriteFile("Spell.Cast(\"{0}\"): complete, no cancel delegate given", cctx.spell.Name);
                                }
                                return RunStatus.Success;
                            })
                            ),

                        // while casting/channeling call the cancel method to see if we should abort
                        new Wait(12,
                            until =>
                            {
                                CastContext cctx = until.CastContext();
                                SingularRoutine.UpdateDiagnosticCastingState();

                                // Interrupted or finished casting. 
                                if (!Spell.IsCastingOrChannelling(allow))
                                {
                                    Logger.WriteDebug("Spell.Cast(\"{0}\"): complete, iscasting=false", cctx.spell.Name);
                                    return true;
                                }

                                // check cancel delegate if we are finished
                                if (cancel(cctx.context))
                                {
                                    SpellManager.StopCasting();
                                    Logger.Write(LogColor.Cancel, "/cancel {0} on {1} @ {2:F1}%", cctx.spell.Name, cctx.unit.SafeName(), cctx.unit.HealthPercent);
                                    return true;
                                }
                                // continue casting/channeling at this point
                                return false;
                            },
                            new ActionAlwaysSucceed()
                            ),

                        // if we are here, we timed out after 12 seconds (very odd)
                        new Action(r =>
                        {
                            CastContext cctx = r.CastContext();
                            Logger.WriteDebug("Spell.Cast(\"{0}\"): aborting, timed out waiting on cast, gcd={1} cast={2} chanl={3}", cctx.spell.Name, Spell.IsGlobalCooldown().ToYN(), Spell.IsCasting().ToYN(), Spell.IsChannelling().ToYN());
                            return RunStatus.Success;
                        })

                        ),

                        // made it this far then we are RunStatus.Success, so reset wowunit reference and return
                        new Action(ret =>
                        {
                            CastContext cctx = ret.CastContext();
                            cctx.unit = null;
                            cctx.spell = null;
                            return RunStatus.Success;
                        })
                    ),

                // cast Sequence failed, so only thing left is to reset cached references and report failure
                new Action(ret =>
                {
                    CastContext cctx = ret.CastContext();
                    cctx.unit = null;
                    cctx.spell = null;
                    return RunStatus.Failure;
                })
                );

            // when no cancel method in place, we will return immediately so.....
            // .. throttle attempts at casting this spell.  note: this only limits this 
            // .. instance of the spell.cast behavior.  in other words, if this is for a cast
            // .. of flame shock, it would only throttle this behavior tree instance, not any 
            // .. other trees which also call Spell.Cast("flame shock")
            if (cancel == null)
                comp = new Throttle( TimeSpan.FromMilliseconds(SingularSettings.Instance.SameSpellThrottle), comp);

            return comp;
        }
Example #38
0
 protected override Composite CreateBehavior()
 {
     var decorated=new PrioritySelector(new Composite[0]);
     foreach (var behavior in base.GetNodes())
     {
         decorated.AddChild(behavior.Behavior);
     }
     return new Decorator(CheckNotAlreadyDone, decorated);
 }
Example #39
0
        public void Start()
        {
            Logic = new PrioritySelector(
                //PAUSE
                new Decorator(ret => TheVariables.PAUSE,
                    new Action(ret => RunStatus.Success)
                    ),

                //reset TheVariables - works
                new Decorator(ret => LokiPoe.ObjectManager.Me.IsInTown,
                    new Sequence(
                        new Action(ret => TheVariables.takePortalFromAreaToTown = null),
                        new Action(ret => TheVariables.makePortal = false),
                        new Action(ret => RunStatus.Failure)
                        )
                    ),
                new Decorator(ret => !LokiPoe.ObjectManager.Me.IsInTown,
                    new Sequence(
                        new Action(ret => TheVariables.takePortalFromTownToArea = null),
                        new Action(ret => RunStatus.Failure)
                        )
                    ),

                //Party stuff - works
                new Decorator(ret => TheVariables.acceptPartyInviteFrom.Length > 1,
                    TheLogic.AcceptPartyInvite()
                    ),
                new Decorator(ret => TheVariables.leaveParty,
                    TheLogic.LeaveParty()
                    ),

                //town-only-stuff
                new Decorator(ret => LokiPoe.ObjectManager.Me.IsInTown && TheVariables.moveToMiddleOfTown,
                    TheLogic.MoveToMiddleOfTown()
                    ),
                new Decorator(ret => LokiPoe.ObjectManager.Me.IsInTown && TheVariables.targetTown.Length > 1,
                    TheLogic.SwitchTown(TheVariables.targetTown)
                    ),

                //portal stuff - works
                new Decorator(ret => TheVariables.takePortalFromTownToArea != null || TheVariables.takePortalFromAreaToTown != null,
                    TheLogic.TakeTP()
                    ),
                new Decorator(ret => TheVariables.makePortal && !LokiPoe.ObjectManager.Me.IsInTown,
                    TheLogic.MakeTP()
                    ),

                //inArea or town stuff
                new Decorator(ret => TheVariables.takeNearestAreaTransition,
                    TheLogic.MoveToAndTakeAreaTransition()
                    //new Action(ret => ExileBoxer.Log.Debug("i want to take a transition now.."))
                    ),

                //inArea #0
                new Decorator(ret => TheVariables.takeNearestIslandTransition,
                    TheLogic.MoveToAndTakeIslandTransition()
                    ),

                //inArea stuff #1 - works
                //fight! return Success if we are fighting, so move does not get triggered pls!
                new Decorator(ret => !LokiPoe.ObjectManager.Me.IsInTown && TheVariables.checkBox2,
                    TheLogic.Fight()
                    ),

                //inArea stuff #2 - MOVE TO SHOULD BE THE VERY LAST THING PLEASE!!!!! - works
                new Decorator(ret => !LokiPoe.ObjectManager.Me.IsInTown && TheVariables.checkBox1,
                    new PrioritySelector(
                        new Decorator(ret => TheVariables.distanceLeader > TheVariables.numUpDown2,
                            @CommonBehaviors.MoveTo(ret => TheVariables.posLeader, ret => "", TheVariables.numUpDown3)
                        ),
                        new Decorator(ret => TheVariables.distanceLeader <= TheVariables.numUpDown3 && LokiPoe.ObjectManager.Me.IsMoving,
                            new Action(ret => Navigator.PlayerMover.Stop())
                            )
                        )
                    ),
                new Decorator(ret => !LokiPoe.ObjectManager.Me.IsInTown && !TheVariables.checkBox1,
                    new Action(ret => Navigator.PlayerMover.Stop())
                    )
                );

            gui = new GUI();
            gui.OnInit();

            ResetVariables();

            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... you really should!");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... :-)");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
            Log.Debug("you should open the GUI by pressing 'Bot-Config' ... ");
        }
Example #40
0
        public Composite GenerateBehaviorTree()
        {
            if (!SingularSettings.Debug)
                return new PrioritySelector(blist.Select(b => b.behavior).ToArray());

            PrioritySelector pri = new PrioritySelector();
            foreach (PrioritizedBehavior pb in blist)
            {
                if (!SingularSettings.TraceHeals)
                    pri.AddChild(pb.behavior);
                else
                {
                    CallTrace ct = new CallTrace(pb.Name, pb.behavior);
                    ct.TraceActive = true;
                    ct.TraceEnter = false;
                    ct.TraceExit = true;
                    pri.AddChild( ct );
                }
            }

            return pri;
        }
Example #41
0
 public Composite GenerateCombatBehavior(float range)
 {
     _context.CombatRange = range;
     var combatBehavior = new PrioritySelector();
     combatBehavior.AddChild(GenerateCheckAvailableTargetsBehavior(range));
     combatBehavior.AddChild(new Decorator(TargetAvailable(), GenerateAttackBehavior()));
     combatBehavior.AddChild(GenerateMoveToTargetBehavior());
     return combatBehavior;
 }
Example #42
0
        /// <summary>
        /// creates a behavior that provides kiting support.  intent is to move to closest safest spot possible away from target
        /// while optionally performing behaviors while moving there
        /// </summary>
        /// <param name="runawayAttack">behavior to use while running away (should not require facing target.) should be null if not needed</param>
        /// <param name="jumpturnAttack">behavior to use in middle of jump turn (while facing target.)  should be null if not needed</param>
        /// <returns></returns>
        public static void CreateKitingBehavior(Composite slowAttack, Composite runawayAttack, Composite jumpturnAttack)
        {
            // _SlowAttackBehavior = slowAttack;

            Composite kitingBehavior =
                new PrioritySelector(
                    new Decorator(
                        ret => bstate == State.None,
                        new Action(r => System.Diagnostics.Debug.Assert(false, "Kiting Failure:  should never run with state == State.None"))
                        ),

                    new Decorator(
                        ret => bstate != State.None,

                        new PrioritySelector(
                            new Decorator(ret => !StyxWoW.IsInGame, new Action(ret => EndKiting("not in game so cancelling"))),
                            new Decorator(ret => !Me.IsAlive, new Action(ret => EndKiting("i am dead so cancelling"))),
                            new Decorator(ret => jumpturnAttack != null && !Me.GotTarget(), new Action(ret => EndKiting("attack behavior but no target, cancelling"))),
                            new PrioritySelector(
                                ctx => SafeArea.NearestEnemyMobAttackingMe,
                                new Decorator(ret => ret == null, new Action(ret => EndKiting("no non-trivial mobs attacking me, so cancelling"))),
                                new Decorator(
                                    ret => (ret as WoWUnit).SpellDistance() > 20,
                                    new Action(ret => EndKiting(string.Format("closest non-trivial attacker {0} is {1:F1} yds away, so cancelling", (ret as WoWUnit).SafeName(), (ret as WoWUnit).SpellDistance())))
                                    ),
                                new Decorator(
                                    ret => (ret as WoWUnit).MovementInfo.CurrentSpeed >= Me.MovementInfo.CurrentSpeed
                                        && (ret as WoWUnit).IsMovingTowards(),
                                    new Action(ret => EndKiting(string.Format("closest non-trivial attacker {0} moving faster than me, so cancelling", (ret as WoWUnit).SafeName())))
                                    )
                                ),
                            new Decorator(ret => timeOut < DateTime.UtcNow, new Action(ret => EndKiting("taking too long, so cancelling"))),

                            new Decorator(ret => Me.Stunned || Me.IsStunned(), new Action(ret => EndKiting("stunned, cancelling"))),
                            new Decorator(ret => Me.Rooted || Me.IsRooted(), new Action(ret => EndKiting("rooted, cancelling"))),

                            new Decorator(ret => Me.Location.Distance(locSafeSpot) < DISTANCE_CLOSE_ENOUGH_TO_DESTINATION, new Action(ret => EndKiting(string.Format("reached safe spot {0:F1} yds away", StyxWoW.Me.Location.Distance(locKiteBegin))))),
                            new Decorator(ret => Me.Location.Distance(locSafeSpot) > DISTANCE_TOO_FAR_FROM_DESTINATION, new Action(ret => EndKiting(string.Format("too far from safe spot ( {0:F1} > {1:F1} yds), cancelling", Me.Location.Distance(locSafeSpot), DISTANCE_TOO_FAR_FROM_DESTINATION)))),

                            new Decorator(ret => bstate == State.Slow,
                                new Sequence(
                                    new SeqDbg(0f, Color.Cyan, s => "KITE: entering SlowAttack behavior"),
                                    new PrioritySelector(
                                        slowAttack ?? new SeqDbg( 0f, Color.Cyan, s => "KITE: no SlowAttack behavior so skipping"),
                                        new PriDbg(0f, Color.Cyan, s => "KITE: ended SlowAttack behavior with Failure")
                                        ),
                                    new Action(ret =>
                                    {
                                        Logger.WriteDebug(Color.Cyan, "KITE: SlowAttack done, transition to Moving");
                                        bstate = State.Moving;
                                    })
                                    )
                                ),

                            new Decorator(ret => bstate == State.Moving,
                                new Sequence(
                                    new Action(d => Navigator.MoveTo(locSafeSpot)),
                // following 3 lines make sure we are facing and have started moving in the correct direction.  it will force
                //  .. a minimum wait of 250 ms after movement has started in the correct direction
                                    new WaitContinue(TimeSpan.FromMilliseconds(250), r => Me.IsDirectlyFacing(locSafeSpot), new ActionAlwaysSucceed()),
                                    new WaitContinue(TimeSpan.FromMilliseconds(500), r => Me.IsMoving, new ActionAlwaysSucceed()),  // wait till we are moving (should be very quick)
                                    new DecoratorContinue(
                                        r => !Me.IsMoving,
                                        new Action(ret => {
                                            EndKiting("KITE: we stopped moving, so end kiting");
                                            return RunStatus.Success;
                                            })
                                        ),

                                    new Action(ret =>
                                    {
                                        if (runawayAttack != null)
                                        {
                                            bstate = State.NonFaceAttack;
                                            Logger.WriteDebug(Color.Cyan, "KITE: transition from Moving to NonFaceAttack");
                                            return RunStatus.Failure;
                                        }
                                        return RunStatus.Success;
                                    }),

                                    new Action(ret =>
                                    {
                                        if (jumpturnAttack != null)
                                        {
                                            if (JumpTurn.IsJumpTurnInProgress())
                                            {
                                                bstate = State.JumpTurnAndAttack;
                                                Logger.WriteDebug(Color.Cyan, "KITE: transition error - active jumpturn? forcing state JumpTurn");
                                                return RunStatus.Failure;
                                            }

                                            if (Me.IsMoving && Me.IsSafelyFacing(Me.CurrentTarget, 120f))
                                            {
                                                bstate = State.AttackWithoutJumpTurn;
                                                Logger.WriteDebug(Color.Cyan, "KITE: already facing so transition from Moving to AttackNoJumpTurn");
                                                return RunStatus.Failure;
                                            }

                                            if (JumpTurn.IsJumpTurnNeeded())
                                            {
                                                bstate = State.JumpTurnAndAttack;
                                                Logger.WriteDebug(Color.Cyan, "KITE: transition from Moving to JumpTurn");
                                                return RunStatus.Failure;
                                            }
                                        }
                                        return RunStatus.Success;
                                    })
                                    )

                /*
                                                new Action( ret => {
                                                    Navigator.MoveTo( safeSpot );
                                                    if (attackBehavior != null )
                                                    {
                                                        if (WoWMathHelper.IsFacing( Me.Location, Me.RenderFacing, safeSpot, SafeArea.ONE_DEGREE_AS_RADIAN ))
                                                        {
                                                            if (JumpTurn.IsNeeded())
                                                            {
                                                                bstate = State.JumpTurn;
                                                                Logger.WriteDebug(Color.Cyan, "KITE: transition from Moving to JumpTurn");
                                                            }
                                                            else if (JumpTurn.ActiveJumpTurn())
                                                            {
                                                                bstate = State.JumpTurn;
                                                                Logger.WriteDebug(Color.Cyan, "KITE: transition error - active jumpturn? forcing state JumpTurn");
                                                            }
                                                        }
                                                    }
                                                    })
                */
                                ),

                            new Decorator(ret => bstate == State.NonFaceAttack,
                                new PrioritySelector(
                                    new Sequence(
                                        new Action(ret => Logger.WriteDebug(Color.Cyan, "KITE: entering NonFaceAttack behavior")),
                                        runawayAttack ?? new Action(r => { return RunStatus.Failure; }),
                                        new Action(r => { return RunStatus.Failure; })
                                        ),
                                    new Action(ret =>
                                    {
                                        Logger.WriteDebug(Color.Cyan, "KITE: transition from NonFaceAttack to Moving");
                                        bstate = State.Moving;
                                    })
                                    )
                                ),

                            new Decorator(ret => bstate == State.AttackWithoutJumpTurn,
                                new PrioritySelector(
                                    new Sequence(
                                        new Action(ret => Logger.WriteDebug(Color.Cyan, "KITE: entering AttackNoJumpTurn behavior")),
                                        jumpturnAttack ?? new Action(r => { return RunStatus.Failure; }),
                                        new Action(r => { return RunStatus.Failure; })
                                        ),
                                    new Action(ret =>
                                    {
                                        Logger.WriteDebug(Color.Cyan, "KITE: transition from AttackNoJumpTurn to Moving");
                                        bstate = State.Moving;
                                    })
                                    )
                                ),

                            new Decorator(ret => bstate == State.JumpTurnAndAttack,
                                new PrioritySelector(
                                    JumpTurn.CreateBehavior(jumpturnAttack),
                                    new Decorator(ret => !JumpTurn.IsJumpTurnInProgress(),
                                        new Action(ret =>
                                        {
                                            bstate = State.Moving;
                                            Logger.WriteDebug(Color.Cyan, "KITE: transition from JumpTurn to Moving");
                                        })
                                        )
                                    )
                                ),

                            new Action(ret => Logger.WriteDebug(Color.Cyan, "KITE: fell through with state {0}", bstate.ToString()))
                            )
                        )
                    );

            TreeHooks.Instance.ReplaceHook(SingularRoutine.HookName("KitingBehavior"), kitingBehavior );
        }
Example #43
0
        /// <summary>
        ///  Creates a behavior to start auto attacking to current target.
        /// </summary>
        /// <remarks>
        ///  Created 23/05/2011
        /// </remarks>
        /// <param name="includePet"> This will also toggle pet auto attack. </param>
        /// <returns></returns>
        public static Composite CreateAutoAttack(bool includePet)
        {
            PrioritySelector prio = new PrioritySelector();
            // const int spellIdAutoShot = 75;
            bool autoAttack = Me.Class == WoWClass.DeathKnight
                || (Me.Class == WoWClass.Druid && Me.Specialization != WoWSpec.DruidRestoration)
                || Me.Class == WoWClass.Monk
                || (Me.Class == WoWClass.Paladin && Me.Specialization != WoWSpec.PaladinHoly)
                || Me.Class == WoWClass.Rogue
                || (Me.Class == WoWClass.Shaman && Me.Specialization != WoWSpec.ShamanRestoration)
                || Me.Class == WoWClass.Warrior;

            if (autoAttack)
            {
                prio.AddChild(
                    new Throttle(TimeSpan.FromMilliseconds(500),
                        new Decorator(
                            ret => !StyxWoW.Me.IsAutoAttacking, // && StyxWoW.Me.AutoRepeatingSpellId != spellIdAutoShot,
                            new Action(ret =>
                                {
                                    Lua.DoString("StartAttack()");
                                    return RunStatus.Failure;
                                })
                            )
                        )
                    );
            }

            if ( includePet && (SingularRoutine.CurrentWoWContext != WoWContext.Normal || !SingularSettings.Instance.PetTankAdds ))
            {
                // pet assist: always keep pet on my target
                prio.AddChild(
                    new ThrottlePasses(TimeSpan.FromMilliseconds(500),
                        new Decorator(
                            // check pet targeting same target as Me
                            ret => Me.GotAlivePet && (!Me.Pet.GotTarget || Me.Pet.CurrentTargetGuid != Me.CurrentTargetGuid),
                            new Action( delegate
                                {
                                    PetManager.CastPetAction("Attack", Me.CurrentTarget);
                                    return RunStatus.Failure;
                                })
                            )
                        )
                    );
            }

            if ( includePet && SingularRoutine.CurrentWoWContext == WoWContext.Normal && SingularSettings.Instance.PetTankAdds )
            {
                // pet tank: if pet's target isn't targeting Me, check if we should switch to one that is targeting Me
                prio.AddChild(
                    new ThrottlePasses(TimeSpan.FromMilliseconds(500),
                        new Decorator(
                            ret => Me.GotAlivePet && (!Me.Pet.GotTarget || Me.Pet.CurrentTarget.CurrentTargetGuid != Me.Guid),
                            new PrioritySelector(
                                ctx => Unit.NearbyUnfriendlyUnits.Where(u => u.Combat && u.GotTarget && u.CurrentTarget.IsMe).FirstOrDefault() ?? Me.CurrentTarget,
                                new Decorator(
                                    ret => ret != null && Me.Pet.CurrentTargetGuid != ((WoWUnit)ret).Guid,
                                    new Action(r => {
                                        PetManager.CastPetAction("Attack", (WoWUnit)r);
                                        return RunStatus.Failure;
                                        })
                                    )
                                )
                            )
                        )
                    );
            }

            return prio;
        }
Example #44
0
        public static Composite CreatePsychicScreamBehavior(int health = -1)
        {
            if (health < 0)
                health = PriestSettings.PsychicScreamHealth;

            PrioritySelector pri = new PrioritySelector();
            if (PriestSettings.CrowdControlHealth > 0 && SpellManager.HasSpell("Psychic Horror"))
                pri.AddChild(
                    Spell.Cast(
                        "Psychic Horror",
                        ret =>
                        {
                            if (Me.HealthPercent <= PriestSettings.CrowdControlHealth)
                            {
                                int count = Unit.UnitsInCombatWithUsOrOurStuff(30).Count(u => !u.IsCrowdControlled() && !u.IsTrivial());
                                if (count == 0)
                                    return false;

                                if (count == 1 || !PriestSettings.PsychicScreamAllow || Spell.GetSpellCooldown("Psychic Scream").TotalSeconds > 3)
                                {
                                    return true;
                                }
                            }

                            return false;
                        })
                    );

                if (PriestSettings.PsychicScreamAllow && SpellManager.HasSpell("Psychic Scream"))
                    pri.AddChild(
                        Spell.Cast(
                            "Psychic Scream",
                            ret =>
                            {
                                if (!PriestSettings.PsychicScreamAllow)
                                    return false;

                                int count = Unit.UnitsInCombatWithUsOrOurStuff(8).Count(u => !u.IsCrowdControlled() && !u.IsTrivial());
                                if (count == 0)
                                    return false;

                                if (count >= PriestSettings.PsychicScreamAddCount)
                                    return true;

                                if (count > 1 && TalentManager.HasGlyph("Psychic Scream"))
                                    return true;

                                if (Me.HealthPercent <= health)
                                    return true;

                                return false;
                            })
                        );

            return pri;
        }
Example #45
0
        public static Composite CreateDispelBehavior()
        {
            if (SingularSettings.Instance.DispelDebuffs == RelativePriority.None)
                return new ActionAlwaysFail();

            PrioritySelector prio = new PrioritySelector();
            switch ( StyxWoW.Me.Class)
            {
                case WoWClass.Paladin:
                    prio.AddChild( Spell.Cast( "Cleanse", on => _unitDispel));
                    break;
                case WoWClass.Monk:
                    prio.AddChild( Spell.Cast( "Detox", on => _unitDispel));
                    break;
                case WoWClass.Priest:
                    if ( StyxWoW.Me.Specialization == WoWSpec.PriestHoly || StyxWoW.Me.Specialization == WoWSpec.PriestDiscipline )
                        prio.AddChild( Spell.Cast( "Purify", on => _unitDispel));
                    break;
                case WoWClass.Druid:
                    if ( StyxWoW.Me.Specialization == WoWSpec.DruidRestoration )
                        prio.AddChild( Spell.Cast( "Nature's Cure", on => _unitDispel));
                    else
                        prio.AddChild( Spell.Cast( "Remove Corruption", on => _unitDispel));
                    break;
                case WoWClass.Shaman:
                    if ( StyxWoW.Me.Specialization == WoWSpec.ShamanRestoration )
                        prio.AddChild(Spell.Cast("Purify Spirit", on => _unitDispel));
                    else
                        prio.AddChild(Spell.Cast("Cleanse Spirit", on => _unitDispel));
                    break;
                case WoWClass.Mage:
                    prio.AddChild(Spell.Cast("Remove Curse", on => _unitDispel));
                    break;
            }

            return new Sequence(
                new Action(r => _unitDispel = HealerManager.Instance.TargetList.FirstOrDefault(u => u.IsAlive && CanDispel(u))),
                prio
                );
        }
Example #46
0
        // [Behavior(BehaviorType.Combat, priority: 998)]
        public static Composite CreateRacialBehaviour()
        {
            PrioritySelector pri = new PrioritySelector();

            if (SpellManager.HasSpell("Stoneform"))
            {
                pri.AddChild(
                    new Decorator(
                        ret =>
                        {
                            if (!Spell.CanCastHack("Stoneform"))
                                return false;
                            if (StyxWoW.Me.GetAllAuras().Any(a => a.Spell.Mechanic == WoWSpellMechanic.Bleeding || a.Spell.DispelType == WoWDispelType.Disease || a.Spell.DispelType == WoWDispelType.Poison))
                                return true;
                            if (Unit.NearbyUnitsInCombatWithMeOrMyStuff.Count() > 2)
                                return true;
                            if (StyxWoW.Me.GotTarget() && StyxWoW.Me.CurrentTarget.CurrentTargetGuid == StyxWoW.Me.Guid && StyxWoW.Me.CurrentTarget.MaxHealth > (StyxWoW.Me.MaxHealth * 2))
                                return true;
                            return false;
                        },
                        Spell.HandleOffGCD(Spell.BuffSelf("Stoneform"))
                        )
                    );
            }

            if (SpellManager.HasSpell("Escape Artist"))
            {
                pri.AddChild(
                    Spell.HandleOffGCD(Spell.BuffSelf("Escape Artist", req => Unit.HasAuraWithMechanic(StyxWoW.Me, WoWSpellMechanic.Rooted, WoWSpellMechanic.Snared)))
                    );
            }

            if (SpellManager.HasSpell("Gift of the Naaru"))
            {
                pri.AddChild(
                    Spell.HandleOffGCD(Spell.BuffSelf("Gift of the Naaru", req => StyxWoW.Me.HealthPercent < SingularSettings.Instance.GiftNaaruHP))
                    );
            }

            if (SpellManager.HasSpell("Shadowmeld"))
            {
                pri.AddChild(
                    // even though not on GCD, return success so we resume at top of tree
                    new Sequence(
                        Spell.BuffSelf("Shadowmeld", ret => NeedShadowmeld()),
                        new Action( r => shadowMeldStart = DateTime.UtcNow )
                        )
                    );
            }

            // add racials cast within range during Combat
            Composite combatRacials = CreateCombatRacialInRangeBehavior();
            if (combatRacials != null)
                pri.AddChild(combatRacials);

            // just fail if no combat racials
            if (!SingularSettings.Instance.UseRacials || !pri.Children.Any() || SuppressGenericRacialBehavior)
                return new ActionAlwaysFail();

            return new Throttle(
                TimeSpan.FromMilliseconds(250),
                new Decorator(
                    req => !Spell.IsGlobalCooldown()
                        && !Spell.IsCastingOrChannelling()
                        && !SuppressGenericRacialBehavior,
                        pri
                    )
                );
        }
Example #47
0
        public Composite GenerateBehaviorTree()
        {
            if ( !SingularSettings.Debug )
                return new PrioritySelector(blist.Select(b => b.behavior).ToArray());

            PrioritySelector pri = new PrioritySelector();
            foreach (PrioritizedBehavior pb in blist)
            {
                pri.AddChild(new CallTrace(pb.Name, pb.behavior));
            }

            return pri;
        }
Example #48
0
        public static Composite CreateTotemsInstanceBehavior()
        {
            // create Fire Totems behavior first, then wrap if needed
            PrioritySelector fireTotemBehavior = new PrioritySelector();

            fireTotemBehavior.AddChild(
                    Spell.Buff(
                       "Fire Elemental Totem", 
                       req => Me.CurrentTarget.IsBoss()
                           && AllowElementalTotems
                       )
                    );

            if (TalentManager.CurrentSpec == WoWSpec.ShamanEnhancement)
            {
                fireTotemBehavior.AddChild(
                    Spell.Cast("Magma Totem", on => Me.CurrentTarget ?? Me, ret => IsMagmaTotemNeeded())
                    );
            }

            if (TalentManager.CurrentSpec == WoWSpec.ShamanRestoration)
                fireTotemBehavior = new PrioritySelector(
                    new Decorator(
                        ret => StyxWoW.Me.Combat && StyxWoW.Me.GotTarget() && !HealerManager.Instance.TargetList.Any(m => m.IsAlive), 
                        fireTotemBehavior
                        )
                    );
            else
                fireTotemBehavior.AddChild(
                    Spell.Cast("Searing Totem", ret => IsSearingTotemNeeded())
                    );


            // now 
            return new PrioritySelector(

                Spell.BuffSelf(WoWTotem.Tremor.ToSpellId(),
                    ret => Unit.GroupMembers.Any(f => f.Fleeing && f.Distance < Totems.GetTotemRange(WoWTotem.Tremor))
                        && !Exist(WoWTotem.StoneBulwark, WoWTotem.EarthElemental)),

                new Decorator(
                    req => Totems.ExistInRange(Me.Location, WoWTotem.EarthElemental)
                        && !Me.HasAura("Reinforce")
                        && !Spell.DoubleCastContains(Me, "Reinforce"),
                    new Sequence(
                        PetManager.CastAction("Reinforce", on => Me),
                        new Action(r => Spell.UpdateDoubleCast("Reinforce", Me))
                        )
                    ),

                new Decorator(
                    req => Totems.ExistInRange(Me.Location, WoWTotem.FireElemental)
                        && !Me.HasAura("Empower")
                        && !Spell.DoubleCastContains(Me, "Empower"),
                    new Sequence(
                        PetManager.CastAction("Empower", on => Me),
                        new Action(r => Spell.UpdateDoubleCast("Empower", Me))
                        )
                    ),

                new Decorator(
                    ret => ShouldWeDropTotemsYet,

                    new PrioritySelector(

                        // earth totems
                        Spell.Cast(WoWTotem.EarthElemental.ToSpellId(),
                            on => Me.CurrentTarget ?? Me,
                            req => {
                                if (!Totems.AllowElementalTotems)
                                    return false;

                                if (Exist(WoWTotem.StoneBulwark))
                                    return false;

                                if (Spell.IsSpellOnCooldown("Earth Elemental Totem"))
                                    return false;

                                // no living tanks in range
                                IEnumerable<WoWUnit> tanks = Group.Tanks.Where(u => u.DistanceSqr < 65 * 65);
                                if (!tanks.Any(t => t.IsAlive) || tanks.Any( t => t.IsDead))
                                {
                                    // we are okay if another Earth Elemental active
                                    if ( ObjectManager.GetObjectsOfType<WoWUnit>(false, false).Any( o => o.Entry == 15352))
                                        return false;

                                    // we are okay if nothing in combat with our group 
                                    if (!Unit.NearbyUnitsInCombatWithUsOrOurStuff.Any())
                                        return false;
                                }

                                // check we can cast it before messaging
                                if (!Spell.CanCastHack("Earth Elemental Totem"))
                                    return false;

                                Logger.Write(LogColor.Hilite, "^Earth Elemental Totem: tank is dead or not nearby");
                                return true;
                            }),

                        // Stone Bulwark handled in CombatBuffs with Astral Shift

                        // fire totems
                        fireTotemBehavior,

                        // water totems
                        Spell.BuffSelf("Mana Tide Totem",
                            ret =>
                            {
                                if (TalentManager.CurrentSpec != WoWSpec.ShamanRestoration)
                                    return false;

                                // Logger.WriteDebug("Mana Tide Totem Check:  current mana {0:F1}%", Me.ManaPercent);
                                if (Me.ManaPercent > ShamanSettings.ManaTideTotemPercent)
                                    return false;
                                if (Exist(WoWTotem.HealingTide, WoWTotem.HealingStream))
                                    return false;
                                return true;
                            }),


        /* Healing...: handle within Helaing logic
                        Spell.Cast("Healing Tide Totem", ret => ((bool)ret) && StyxWoW.Me.HealthPercent < 50
                            && !Exist(WoWTotem.ManaTide)),

                        Spell.Cast("Healing Stream Totem", ret => ((bool)ret) && StyxWoW.Me.HealthPercent < 80
                            && !Exist( WoWTotemType.Water)),
        */

                        // air totems
                        Spell.Cast("Stormlash Totem", ret => PartyBuff.WeHaveBloodlust && !Me.HasAura("Stormlash Totem")),

                        new Decorator(
                            ret => !Exist(WoWTotemType.Air),
                            new PrioritySelector(
                                Spell.Cast("Grounding Totem",
                                    on => Unit.NearbyUnfriendlyUnits.FirstOrDefault(u => u.SpellDistance() < 40 && u.IsTargetingMeOrPet && u.IsCasting)),

                                Spell.Cast("Capacitor Totem",
                                    on => Unit.NearbyUnfriendlyUnits.FirstOrDefault(u => u.SpellDistance() < GetTotemRange(WoWTotem.Capacitor) && u.IsTargetingMeOrPet)),

                                Spell.BuffSelf("Windwalk Totem",
                                    ret => Unit.HasAuraWithMechanic(StyxWoW.Me, WoWSpellMechanic.Rooted, WoWSpellMechanic.Snared))
                                )
                            )
                        )
                    )
                );

        }
Example #49
0
        public static Composite CreateTotemsNormalBehavior()
        {
            // create Fire Totems behavior first, then wrap if needed
            Composite fireTotemBehavior =
                new PrioritySelector(
                    Spell.BuffSelf("Fire Elemental",
                        ret => ((bool)ret)
                            || (Unit.NearbyUnitsInCombatWithMe.Count() >= StressMobCount && !SpellManager.CanBuff(WoWTotem.EarthElemental.ToSpellId(), false))),
            /*  Magma - handle within AoE DPS logic only
                    Spell.BuffSelf("Magma Totem",
                        ret => Unit.NearbyUnitsInCombatWithMe.Count(u => u.Distance <= GetTotemRange(WoWTotem.Magma)) >= StressMobCount
                            && !Exist( WoWTotem.FireElemental)),
            */
                    Spell.BuffSelf("Searing Totem",
                        ret => Me.GotTarget
                            && Me.CurrentTarget.Distance < GetTotemRange(WoWTotem.Searing) - 2f
                            && !Exist( WoWTotemType.Fire))
                    );

            if ( Me.Specialization == WoWSpec.ShamanRestoration )
                fireTotemBehavior = new Decorator(ret => StyxWoW.Me.Combat && StyxWoW.Me.GotTarget && Unit.NearbyFriendlyPlayers.Count(u => u.IsInMyPartyOrRaid) == 0, fireTotemBehavior);

            // now
            return new PrioritySelector(

                // check for stress - enemy player or elite within 8 levels nearby
                // .. dont use NearbyUnitsInCombatWithMe since it checks .Tagged and we only care if we are being attacked
                ctx => Unit.NearbyUnitsInCombatWithMe.Count() >= StressMobCount
                    || Unit.NearbyUnfriendlyUnits.Any(u => u.IsTargetingMeOrPet && (u.IsPlayer || (u.Elite && u.Level + 8 > Me.Level))),

                // earth totems
                Spell.BuffSelf(WoWTotem.EarthElemental.ToSpellId(),
                    ret => (bool) ret && !Exist( WoWTotem.StoneBulwark)),

                Spell.BuffSelf(WoWTotem.StoneBulwark.ToSpellId(),
                    ret => Me.HealthPercent < SingularSettings.Instance.Shaman.StoneBulwarkTotemPercent && !Exist( WoWTotem.EarthElemental)),

                Spell.BuffSelf(WoWTotem.Tremor.ToSpellId(),
                    ret => Unit.GroupMembers.Any( f=> f.Fleeing && f.Distance < Totems.GetTotemRange(WoWTotem.Tremor)
                        && !Exist( WoWTotem.StoneBulwark, WoWTotem.EarthElemental ))),

                new PrioritySelector(
                    ctx => Unit.NearbyUnfriendlyUnits.Any(u => u.IsTargetingMeOrPet && u.IsPlayer && u.Combat),

                    Spell.BuffSelf(WoWTotem.Earthgrab.ToSpellId(),
                        ret => (bool)ret && !Exist(WoWTotemType.Earth)),

                    Spell.BuffSelf(WoWTotem.Earthbind.ToSpellId(),
                        ret => (bool)ret && !Exist(WoWTotemType.Earth))
                    ),

                // fire totems
                fireTotemBehavior,

                // water totems
                Spell.Cast("Mana Tide Totem", ret => ((bool)ret) && StyxWoW.Me.ManaPercent < 80
                    && !Exist( WoWTotem.HealingTide )),

            /* Healing...: handle within Helaing logic
                Spell.Cast("Healing Tide Totem", ret => ((bool)ret) && StyxWoW.Me.HealthPercent < 50
                    && !Exist(WoWTotem.ManaTide)),

                Spell.Cast("Healing Stream Totem", ret => ((bool)ret) && StyxWoW.Me.HealthPercent < 80
                    && !Exist( WoWTotemType.Water)),
            */

                // air totems
                Spell.Cast("Grounding Totem",
                    ret => ((bool) ret)
                        && Unit.NearbyUnfriendlyUnits.Any(u => u.Distance < 40 && u.IsTargetingMeOrPet && u.IsCasting)
                        && !Exist(WoWTotemType.Air)),

                Spell.Cast("Capacitor Totem",
                    ret => ((bool) ret)
                        && Unit.NearbyUnfriendlyUnits.Any(u => u.Distance < GetTotemRange(WoWTotem.Capacitor))
                        && !Exist(WoWTotemType.Air)),

                Spell.Cast("Stormlash Totem",
                    ret => ((bool)ret)
                        && Me.HasAnyAura( Common.BloodlustName, "Timewarp", "Ancient Hysteria")
                        && !Exist(WoWTotemType.Air))

                );
        }
Example #50
0
        protected override Composite CreateBehavior()
        {
            PrioritySelector decorated=new PrioritySelector(new Composite[0]);

            foreach (ProfileBehavior behavior in base.GetNodes())
            {
                decorated.AddChild(behavior.Behavior);
            }
            // Logging.Write("Count: ");

            return new Zeta.TreeSharp.Decorator(new CanRunDecoratorDelegate(CheckNotAlreadyDone), decorated);
        }
Example #51
0
        public static Composite EnsureReadyToAttackFromMelee()
        {
            PrioritySelector prio = new PrioritySelector(
                Safers.EnsureTarget() ,
                Movement.CreateMoveToLosBehavior(),
                Movement.CreateFaceTargetBehavior(),
                new Decorator(
                    req => Me.GotTarget && Me.CurrentTarget.Distance < SingularSettings.Instance.MeleeDismountRange,
                    Helpers.Common.CreateDismount( Dynamics.CompositeBuilder.CurrentBehaviorType.ToString())   // should be Pull or Combat 99% of the time
                    )
                );

            if (Dynamics.CompositeBuilder.CurrentBehaviorType == BehaviorType.Pull)
            {
                prio.AddChild(
                    new PrioritySelector(
                        ctx => Me.GotTarget && Me.CurrentTarget.IsAboveTheGround(),
                        new Decorator(
                            req => (bool)req,
                            new PrioritySelector(
                                Movement.CreateMoveToUnitBehavior(on => Me.CurrentTarget, 27, 22),
                                Movement.CreateEnsureMovementStoppedBehavior(22)
                                )
                            ),
                        new Decorator(
                            req => !(bool)req,
                            new PrioritySelector(
                                Movement.CreateMoveToMeleeBehavior(true),
                                Movement.CreateEnsureMovementStoppedWithinMelee()
                                )
                            )
                        )
                    );
            }
            else
            {
                prio.AddChild( Movement.CreateMoveToMeleeBehavior(true));
                prio.AddChild(Movement.CreateEnsureMovementStoppedWithinMelee());
            }

            return prio;
        }
Example #52
0
        /// <summary>Creates an interrupt spell cast composite. This attempts to use spells in order of range (shortest to longest).  
        /// behavior consists only of spells that apply to current toon based upon class, spec, and race
        /// </summary>
        public static Composite CreateInterruptBehavior()
        {
            if ( SingularSettings.Instance.InterruptTarget == CheckTargets.None )
                return new ActionAlwaysFail();

            Composite actionSelectTarget;
            if (SingularSettings.Instance.InterruptTarget == CheckTargets.Current)
                actionSelectTarget = new Action(
                    ret => {
                        WoWUnit u = Me.CurrentTarget;
                        _unitInterrupt = IsInterruptTarget(u) ? u : null;
                        if (_unitInterrupt != null && SingularSettings.Debug)
                            Logger.WriteDebug("Possible Interrupt Target: {0} @ {1:F1} yds casting {2} #{3} for {4} ms", _unitInterrupt.SafeName(), _unitInterrupt.Distance, _unitInterrupt.CastingSpell.Name, _unitInterrupt.CastingSpell.Id, _unitInterrupt.CurrentCastTimeLeft.TotalMilliseconds );
                    }
                    );
            else // if ( SingularSettings.Instance.InterruptTarget == InterruptType.All )
            {
                actionSelectTarget = new Action(
                    ret => {
                        _unitInterrupt = Unit.NearbyUnitsInCombatWithMeOrMyStuff.Where(u => IsInterruptTarget(u)).OrderBy( u => u.Distance ).FirstOrDefault();
                        if (_unitInterrupt != null && SingularSettings.Debug)
                            Logger.WriteDebug("Possible Interrupt Target: {0} @ {1:F1} yds casting {2} #{3} for {4} ms", _unitInterrupt.SafeName(), _unitInterrupt.Distance, _unitInterrupt.CastingSpell.Name, _unitInterrupt.CastingSpell.Id, _unitInterrupt.CurrentCastTimeLeft.TotalMilliseconds);
                        }
                    );
            }

            PrioritySelector prioSpell = new PrioritySelector();

            #region Pet Spells First!

            if (Me.Class == WoWClass.Warlock)
            {
                // this will be either a Optical Blast or Spell Lock
                prioSpell.AddChild(
                    Spell.Cast(
                        "Command Demon",
                        on => _unitInterrupt,
                        ret => _unitInterrupt != null
                            && _unitInterrupt.Distance < 40
                            && Singular.ClassSpecific.Warlock.Common.GetCurrentPet() == WarlockPet.Felhunter
                        )
                    );
            }

            #endregion

            #region Melee Range

            if ( Me.Class == WoWClass.Paladin )
                prioSpell.AddChild( Spell.Cast("Rebuke", ctx => _unitInterrupt));

            if ( Me.Class == WoWClass.Rogue)
            {
                prioSpell.AddChild( Spell.Cast("Kick", ctx => _unitInterrupt));
                prioSpell.AddChild( Spell.Cast("Gouge", ctx => _unitInterrupt, ret => !_unitInterrupt.IsBoss() && Me.IsSafelyFacing(_unitInterrupt)));
            }

            if ( Me.Class == WoWClass.Warrior)
                prioSpell.AddChild( Spell.Cast("Pummel", ctx => _unitInterrupt));

            if ( Me.Class == WoWClass.Monk )
                prioSpell.AddChild( Spell.Cast("Spear Hand Strike", ctx => _unitInterrupt));

            if ( Me.Class == WoWClass.Druid)
            {
                // Spell.Cast("Skull Bash (Cat)", ctx => _unitInterrupt, ret => StyxWoW.Me.Shapeshift == ShapeshiftForm.Cat));
                // Spell.Cast("Skull Bash (Bear)", ctx => _unitInterrupt, ret => StyxWoW.Me.Shapeshift == ShapeshiftForm.Bear));
                prioSpell.AddChild( Spell.Cast("Skull Bash", ctx => _unitInterrupt, ret => StyxWoW.Me.Shapeshift == ShapeshiftForm.Bear || StyxWoW.Me.Shapeshift == ShapeshiftForm.Cat));
                prioSpell.AddChild( Spell.Cast("Mighty Bash", ctx => _unitInterrupt, ret => !_unitInterrupt.IsBoss() && _unitInterrupt.IsWithinMeleeRange));
            }

            if ( Me.Class == WoWClass.DeathKnight)
                prioSpell.AddChild( Spell.Cast("Mind Freeze", ctx => _unitInterrupt));

            if ( Me.Race == WoWRace.Pandaren )
                prioSpell.AddChild( Spell.Cast("Quaking Palm", ctx => _unitInterrupt));

            #endregion

            #region 8 Yard Range

            if ( Me.Race == WoWRace.BloodElf )
                prioSpell.AddChild(Spell.Cast("Arcane Torrent", ctx => _unitInterrupt, req => _unitInterrupt.Distance < 8 && !Unit.NearbyUnfriendlyUnits.Any(u => u.IsSensitiveDamage( 8))));

            if ( Me.Race == WoWRace.Tauren)
                prioSpell.AddChild(Spell.Cast("War Stomp", ctx => _unitInterrupt, ret => _unitInterrupt.Distance < 8 && !_unitInterrupt.IsBoss() && !Unit.NearbyUnfriendlyUnits.Any(u => u.IsSensitiveDamage( 8))));

            #endregion

            #region 10 Yards

            if (Me.Class == WoWClass.Paladin)
                prioSpell.AddChild( Spell.Cast("Hammer of Justice", ctx => _unitInterrupt));

            if (Me.Specialization == WoWSpec.DruidBalance )
                prioSpell.AddChild( Spell.Cast("Hammer of Justice", ctx => _unitInterrupt));

            if (Me.Class == WoWClass.Warrior)
                prioSpell.AddChild( Spell.Cast("Disrupting Shout", ctx => _unitInterrupt));

            #endregion

            #region 25 yards

            if ( Me.Class == WoWClass.Shaman)
                prioSpell.AddChild( Spell.Cast("Wind Shear", ctx => _unitInterrupt, req => Me.IsSafelyFacing(_unitInterrupt)));

            #endregion

            #region 30 yards

            if (Me.Specialization == WoWSpec.PaladinProtection)
                prioSpell.AddChild( Spell.Cast("Avenger's Shield", ctx => _unitInterrupt));

            if (Me.Class == WoWClass.Shaman)
                // Gag Order only works on non-bosses due to it being a silence, not an interrupt!
                prioSpell.AddChild( Spell.Cast("Heroic Throw", ctx => _unitInterrupt, ret => TalentManager.HasGlyph("Gag Order") && !_unitInterrupt.IsBoss()));

            if ( Me.Class == WoWClass.Priest )
                prioSpell.AddChild( Spell.Cast("Silence", ctx => _unitInterrupt));

            if (Me.Class == WoWClass.DeathKnight)
                prioSpell.AddChild(Spell.Cast("Strangulate", ctx => _unitInterrupt));

            if (Me.Class == WoWClass.Mage)
                prioSpell.AddChild(Spell.Cast("Frostjaw", ctx => _unitInterrupt));

            #endregion

            #region 40 yards

            if ( Me.Class == WoWClass.Mage)
                prioSpell.AddChild( Spell.Cast("Counterspell", ctx => _unitInterrupt));

            if ( Me.Class == WoWClass.Hunter)
                prioSpell.AddChild( Spell.Cast("Silencing Shot", ctx => _unitInterrupt));

            if ( Me.Class == WoWClass.Druid)
                prioSpell.AddChild( Spell.Cast("Solar Beam", ctx => _unitInterrupt, ret => StyxWoW.Me.Shapeshift == ShapeshiftForm.Moonkin));

            if (Me.Specialization == WoWSpec.ShamanElemental || Me.Specialization == WoWSpec.ShamanEnhancement )
                prioSpell.AddChild( Spell.Cast("Solar Beam", ctx => _unitInterrupt, ret => true));

            #endregion

            return new Throttle(
                new Sequence(
                    actionSelectTarget,
                    new Decorator(
                        ret => _unitInterrupt != null,
                        // majority of these are off GCD, so throttle all to avoid most fail messages
                        new Throttle( TimeSpan.FromMilliseconds(500), prioSpell )
                        )
                    )
                );
        }
Example #53
0
        public static Composite CreateTotemsNormalBehavior()
        {
            // create Fire Totems behavior first, then wrap if needed
            PrioritySelector fireTotemBehavior = new PrioritySelector();
            fireTotemBehavior.AddChild(
                Spell.Buff(WoWTotem.FireElemental.ToSpellId(),
                    req => Common.StressfulSituation
                        && Totems.AllowElementalTotems
                        && !Exist(WoWTotem.EarthElemental) 
                        && !Spell.CanCastHack("Earth Elemental Totem")

                    )
                );

            if (TalentManager.CurrentSpec == WoWSpec.ShamanEnhancement)
            {
                fireTotemBehavior.AddChild(
                    Spell.Cast("Magma Totem", on => Me.CurrentTarget ?? Me, ret => IsMagmaTotemNeeded())
                    );
            }

            fireTotemBehavior.AddChild(
                Spell.BuffSelf("Searing Totem", ret => IsSearingTotemNeeded() )
                );

            if (TalentManager.CurrentSpec == WoWSpec.ShamanRestoration)
            {
                fireTotemBehavior = new PrioritySelector(
                    new Decorator(
                        ret => StyxWoW.Me.Combat && StyxWoW.Me.GotTarget() && !Unit.NearbyGroupMembers.Any(), 
                        fireTotemBehavior
                        )
                    );
            }

            // now 
            return new PrioritySelector(

                new Throttle(1,
                    new Action(r =>
                    {
                        bool ccMechanic = Me.HasAuraWithMechanic(WoWSpellMechanic.Fleeing | WoWSpellMechanic.Polymorphed | WoWSpellMechanic.Asleep);
                        bool ccEffect = Me.HasAuraWithEffect(WoWApplyAuraType.ModFear | WoWApplyAuraType.ModPacify | WoWApplyAuraType.ModPacifySilence);
                        bool ccAttrib = Me.Fleeing;
                        if (ccMechanic || ccEffect || ccAttrib)
                            Logger.WriteDebug(Color.Pink, "... FEAR CHECKED OUT --  Mechanic={0}  Effect={1}  Attrib={2}", ccMechanic, ccEffect, ccAttrib);
                        return RunStatus.Failure;
                    })
                    ),


                Spell.BuffSelf(WoWTotem.Tremor.ToSpellId(),
                    ret => Unit.GroupMembers.Any(f => f.Fleeing && f.Distance < Totems.GetTotemRange(WoWTotem.Tremor))
                        && !Exist(WoWTotem.StoneBulwark, WoWTotem.EarthElemental)),

                new Decorator(
                    req => PetManager.NeedsPetSupport
                        && Totems.ExistInRange(Me.Location, WoWTotem.EarthElemental)
                        && !Me.HasAura("Reinforce")
                        && !Spell.DoubleCastContains(Me, "Reinforce"),
                    new Sequence(
                        PetManager.CastAction("Reinforce", on => Me),
                        new Action(r => Spell.UpdateDoubleCast("Reinforce", Me))
                        )
                    ),

                new Decorator(
                    req => PetManager.NeedsPetSupport
                        && Totems.ExistInRange(Me.Location, WoWTotem.FireElemental)
                        && !Me.HasAura("Empower")
                        && !Spell.DoubleCastContains(Me, "Empower"),
                    new Sequence(
                        PetManager.CastAction("Empower", on => Me),
                        new Action(r => Spell.UpdateDoubleCast("Empower", Me))
                        )
                    ),

                new Decorator(
                    ret => ShouldWeDropTotemsYet,

                    new PrioritySelector(

                        // check for stress - enemy player or elite within 8 levels nearby
                // .. dont use NearbyUnitsInCombatWithMe since it checks .Tagged and we only care if we are being attacked 
                        ctx => Common.StressfulSituation,

                        // earth totems
                        Spell.BuffSelf(WoWTotem.EarthElemental.ToSpellId(),
                            ret => ((bool)ret || Group.Tanks.Any(t => t.IsDead && t.Distance < 40))
                                && Totems.AllowElementalTotems
                                && !Exist(WoWTotem.StoneBulwark)
                            ),

                        Spell.BuffSelf(WoWTotem.StoneBulwark.ToSpellId(),
                            ret => Me.Combat && Me.HealthPercent < ShamanSettings.StoneBulwarkTotemPercent && !Exist(WoWTotem.EarthElemental)),

                        new PrioritySelector(
                            ctx => Unit.NearbyUnfriendlyUnits.Any(u => u.IsTargetingMeOrPet && u.IsPlayer && u.Combat),

                            Spell.BuffSelf(WoWTotem.Earthgrab.ToSpellId(),
                                ret => (bool)ret && !Exist(WoWTotemType.Earth)),

                            Spell.BuffSelf(WoWTotem.Earthbind.ToSpellId(),
                                ret => (bool)ret && !Exist(WoWTotemType.Earth))
                            ),

                        // fire totems
                        fireTotemBehavior,

                        // water totems
                        Spell.BuffSelf("Mana Tide Totem",
                            ret =>
                            {
                                if (TalentManager.CurrentSpec != WoWSpec.ShamanRestoration)
                                    return false;

                                // Logger.WriteDebug("Mana Tide Totem Check:  current mana {0:F1}%", Me.ManaPercent);
                                if (Me.ManaPercent > ShamanSettings.ManaTideTotemPercent )
                                    return false;
                                if (Exist(WoWTotem.HealingTide, WoWTotem.HealingStream))
                                    return false;
                                return true;
                            }),

        /* Healing...: handle within Helaing logic
                        Spell.Cast("Healing Tide Totem", ret => ((bool)ret) && StyxWoW.Me.HealthPercent < 50
                            && !Exist(WoWTotem.ManaTide)),

                        Spell.Cast("Healing Stream Totem", ret => ((bool)ret) && StyxWoW.Me.HealthPercent < 80
                            && !Exist( WoWTotemType.Water)),
        */

                        // air totems
                        Spell.Cast("Stormlash Totem", ret => PartyBuff.WeHaveBloodlust && !Me.HasAura("Stormlash Totem")),

                        new Decorator(
                            ret => !Exist(WoWTotemType.Air),
                            new PrioritySelector(
                                Spell.Cast("Grounding Totem",
                                    ret => Unit.NearbyUnfriendlyUnits.Any(u => u.SpellDistance() < 40 && u.IsTargetingMeOrPet && u.IsCasting)),

                                Spell.Cast("Capacitor Totem",
                                    ret => ((bool)ret)
                                        && Unit.NearbyUnfriendlyUnits.Any(u => u.SpellDistance() < GetTotemRange(WoWTotem.Capacitor))),

                                Spell.BuffSelf("Windwalk Totem",
                                    ret => Unit.HasAuraWithMechanic(StyxWoW.Me, WoWSpellMechanic.Rooted, WoWSpellMechanic.Snared))
                                )
                            )
                        )
                    )
                );

        }
Example #54
0
        public void RebuildBehaviors()
        {
            Composite simcRoot = null;
            NameCount = 'A';

            simcRoot = new PrioritySelector(
                new Action(context =>
                {
                    iterationCounter++;
                    return RunStatus.Failure;
                }),
                new Decorator(ret => IsPaused,
                    new Action(ret => RunStatus.Success)),
                CallActionList(ActionProxy.ActionImpl.oocapl, ret => !StyxWoW.Me.Combat),
                new Decorator(ret => StyxWoW.Me.Combat,
                    new LockSelector(
                        new Decorator(
                            ret => StyxWoW.Me.CurrentTarget != null && StyxWoW.Me.Combat,
                            new PrioritySelector(CombatIteration(), actions.Selector, IterationEnd())))));

            TreeHooks.Instance.ReplaceHook(SimcraftHookName, simcRoot);

            //if (Me.Specialization != Specialisation)
            //{
            //    SelectorWindow.ShowDialog();
            //}

            Specialisation = Me.Specialization;
        }
Example #55
0
        public static Composite CreateTotemsNormalBehavior()
        {
            // create Fire Totems behavior first, then wrap if needed
            Composite fireTotemBehavior =
                new PrioritySelector(
                 //   Spell.CastSelfSpell("Fire Elemental",
                   //     ret => ((bool)ret)
                   //         || (Unit.EnemyUnits.Count() >= StressMobCount && !SpellManager.CanBuff(WoWTotem.EarthElemental.ToSpellId(), false)), "Fire Elemental"),
               //   Magma - handle within AoE DPS logic only

                     Spell.CastSpell("Magma Totem",
                      ret => Unit.CountEnnemiesInRange(Me.CurrentTarget.Location, 20) >= 5 && !Exist(WoWTotemType.Fire) &&
                      !Totems.Exist(WoWTotem.FireElemental),"Magma Totem"),

                    Spell.CastSpell("Searing Totem", ret => !Totems.Exist(WoWTotemType.Fire), "Searing Totem")
                    );

            if (Me.Specialization == WoWSpec.ShamanRestoration)
                fireTotemBehavior = new Decorator(ret => StyxWoW.Me.Combat && StyxWoW.Me.GotTarget && !Me.GroupInfo.IsInParty, fireTotemBehavior);

            // now
            return new PrioritySelector(

                // check for stress - enemy player or elite within 8 levels nearby
                // .. dont use NearbyUnitsInCombatWithMe since it checks .Tagged and we only care if we are being attacked
                ctx => Unit.EnemyMeleeUnits.Count() >= StressMobCount,

                // earth totems
            //   Spell.CastSelfSpell(WoWTotem.EarthElemental.ToSpellId(),
             //      ret => (bool)ret && !Exist(WoWTotem.StoneBulwark),"Earth Elemental"),

                Spell.CastSelfSpell(WoWTotem.StoneBulwark.ToSpellId(),
                    ret => Me.HealthPercent < 50 && !Exist(WoWTotem.EarthElemental),"Stone Bulwark"),

                new PrioritySelector(
                    ctx => Unit.EnemyRangedUnits.Any(u => u.IsTargetingMeOrPet && u.IsPlayer && u.Combat),

                    Spell.CastSelfSpell(WoWTotem.Earthgrab.ToSpellId(),
                        ret => (bool)ret && !Exist(WoWTotem.StoneBulwark, WoWTotem.EarthElemental, WoWTotem.Earthbind),"Earth Grab"),

                    Spell.CastSelfSpell(WoWTotem.Earthbind.ToSpellId(),
                        ret => (bool)ret && !Exist(WoWTotem.StoneBulwark, WoWTotem.EarthElemental, WoWTotem.Earthgrab), "Earth Bind")
                    ),

                Spell.CastSelfSpell(WoWTotem.Tremor.ToSpellId(),
                    ret => Me.Fleeing && !Exist(WoWTotem.StoneBulwark, WoWTotem.EarthElemental), "Tremor"),

                // fire totems
                fireTotemBehavior,

                // water totems
                Spell.CastSpell("Mana Tide Totem", ret => ((bool)ret) && StyxWoW.Me.ManaPercent < 80
                    && !Exist(WoWTotem.HealingTide),"Mana Tide Totem"),

            /* Healing...: handle within Helaing logic
                Spell.Cast("Healing Tide Totem", ret => ((bool)ret) && StyxWoW.Me.HealthPercent < 50
                    && !Exist(WoWTotem.ManaTide)),

                Spell.Cast("Healing Stream Totem", ret => ((bool)ret) && StyxWoW.Me.HealthPercent < 80
                    && !Exist( WoWTotemType.Water)),
            */

                // air totems
                Spell.CastSpell("Grounding Totem",
                    ret => ((bool)ret)
                        && Unit.EnemyRangedUnits.Any(u => u.IsCasting)
                        && !Exist(WoWTotemType.Air), "Grounding Totem"),

                Spell.CastSpell("Capacitor Totem",
                    ret => ((bool)ret)
                        && Unit.EnemyRangedUnits.Any(u => u.DistanceSqr < GetTotemRange(WoWTotem.Capacitor) * GetTotemRange(WoWTotem.Capacitor))
                        && !Exist(WoWTotemType.Air),"Capacitor Totem"),

                Spell.CastSpell("Stormlash Totem",
                    ret => ((bool)ret)
                        && ((CLUSettings.Instance.Shaman.UseStormlashTotem == StormlashTotem.OnHaste && Me.HasAnyAura(Me.IsHorde ? "Bloodlust" : "Heroism", "Timewarp", "Ancient Hysteria") || CLUSettings.Instance.Shaman.UseStormlashTotem == StormlashTotem.OnCooldown)
                        && !Exist(WoWTotemType.Air)),"Stormlash Totem")

                );
        }
Example #56
0
        /// <summary>
        /// creates a Druid specific avoidance behavior based upon settings.  will check for safe landing
        /// zones before using WildCharge or rocket jump.  will additionally do a running away or jump turn
        /// attack while moving away from attacking mob if behaviors provided
        /// </summary>
        /// <param name="nonfacingAttack">behavior while running away (back to target - instants only)</param>
        /// <param name="jumpturnAttack">behavior while facing target during jump turn (instants only)</param>
        /// <returns></returns>
        public static Composite CreateMageAvoidanceBehavior(Composite nonfacingAttack = null, Composite jumpturnAttack = null)
        {
            Kite.CreateKitingBehavior(CreateSlowMeleeBehavior(), nonfacingAttack, jumpturnAttack);

            PrioritySelector pri = new PrioritySelector();

            if (SingularSettings.Instance.DisengageAllowed)
            {
                pri.AddChild(
                    new Decorator(
                        ret => Kite.IsDisengageWantedByUserSettings(),
                        new PrioritySelector(
                            Disengage.CreateDisengageBehavior("Blink", Disengage.Direction.Frontwards, 20, CreateSlowMeleeBehavior()),
                            Disengage.CreateDisengageBehavior("Rocket Jump", Disengage.Direction.Frontwards, 20, CreateSlowMeleeBehavior())
                            )
                        )
                    );
            }

            if (SingularSettings.Instance.KiteAllow)
            {
                pri.AddChild(
                    new Decorator(
                        ret => Kite.IsKitingWantedByUserSettings(),
                        new Sequence(
                            new Action( r => Logger.WriteDebug("MageAvoidance: requesting KITING!!!")),
                            Kite.BeginKitingBehavior()
                            )
                        )
                    );
            }

            if (!pri.Children.Any())
            {
                pri.AddChild(new ActionAlwaysFail());
            }

            return new Decorator( req => MovementManager.IsClassMovementAllowed, pri );
        }
Example #57
0
        private static Composite CreateCombatRacialInRangeBehavior()
        {
            PrioritySelector priCombat = new PrioritySelector();

            // not a racial, but best place to handle it
            if (SpellManager.HasSpell("Lifeblood"))
            {
                priCombat.AddChild(
                    Spell.HandleOffGCD(Spell.BuffSelf("Lifeblood", ret => !PartyBuff.WeHaveBloodlust))
                    );
            }

            if (SpellManager.HasSpell("Berserking"))
            {
                priCombat.AddChild(
                    Spell.HandleOffGCD(Spell.BuffSelf("Berserking", ret => !PartyBuff.WeHaveBloodlust))
                    );
            }

            if (SpellManager.HasSpell("Blood Fury"))
            {
                priCombat.AddChild(
                    Spell.HandleOffGCD(Spell.BuffSelf("Blood Fury", ret => true))
                    );
            }

            if (priCombat.Children.Any())
            {
                return new Decorator(
                    req =>
                    {
                        if (!StyxWoW.Me.Combat || !StyxWoW.Me.GotTarget())
                            return false;
                        if (StyxWoW.Me.IsMelee())
                            return StyxWoW.Me.CurrentTarget.IsWithinMeleeRange;
                        return !StyxWoW.Me.IsMoving && StyxWoW.Me.CurrentTarget.SpellDistance() < 40;
                    },
                    priCombat
                    );
            }

            return null;
        }
Example #58
0
        internal static void HookBehaviorTree()
        {
            HookHandler.StoreHook(HookHandler.HookType.VendorRun);

            Logger.DBLog.InfoFormat("[FunkyTownRun] Treehooks..");
            #region VendorRun

            // Wipe the vendorrun and loot behavior trees, since we no longer want them

            Logger.DBLog.DebugFormat("[FunkyTownRun] VendorRun...");

            Decorator GilesDecorator = HookHandler.ReturnHookValue(HookHandler.HookType.VendorRun)[0] as Decorator;
            //PrioritySelector GilesReplacement = GilesDecorator.Children[0] as PrioritySelector;
            PrioritySelector GilesReplacement = GilesDecorator.Children[0] as PrioritySelector;
            //HookHandler.PrintChildrenTypes(GilesReplacement.Children);

            CanRunDecoratorDelegate canRunDelegateReturnToTown = TownPortalBehavior.FunkyTPOverlord;
            ActionDelegate actionDelegateReturnTown = TownPortalBehavior.FunkyTPBehavior;
            ActionDelegate actionDelegateTownPortalFinish = TownPortalBehavior.FunkyTownPortalTownRun;
            Sequence sequenceReturnTown = new Sequence(
                new Zeta.TreeSharp.Action(actionDelegateReturnTown),
                new Zeta.TreeSharp.Action(actionDelegateTownPortalFinish)
                );
            GilesReplacement.Children[1] = new Decorator(canRunDelegateReturnToTown, sequenceReturnTown);
            Logger.DBLog.DebugFormat("[FunkyTownRun] Town Portal - hooked...");

            ActionDelegate actionDelegatePrePause = TownRunManager.GilesStashPrePause;
            ActionDelegate actionDelegatePause = TownRunManager.GilesStashPause;

            #region Idenify

            CanRunDecoratorDelegate canRunDelegateFunkyIDManual = TownRunManager.IdenifyItemManualOverlord;
            ActionDelegate actionDelegateIDManual = TownRunManager.IdenifyItemManualBehavior;
            ActionDelegate actionDelegateIDFinish = TownRunManager.IdenifyItemManualFinishBehavior;
            Sequence sequenceIDManual = new Sequence(
                new Zeta.TreeSharp.Action(actionDelegateIDManual),
                new Zeta.TreeSharp.Action(actionDelegateIDFinish)
            );

            CanRunDecoratorDelegate canRunDelegateFunkyIDBookOfCain = TownRunManager.IdenifyItemBookOfCainOverlord;
            ActionDelegate actionDelegateIDBookOfCainMovement = TownRunManager.IdenifyItemBookOfCainMovementBehavior;
            ActionDelegate actionDelegateIDBookOfCainInteraction = TownRunManager.IdenifyItemBookOfCainInteractionBehavior;
            Sequence sequenceIDBookOfCain = new Sequence(
                new Zeta.TreeSharp.Action(actionDelegateIDBookOfCainMovement),
                new Zeta.TreeSharp.Action(actionDelegateIDBookOfCainInteraction),
                new Zeta.TreeSharp.Action(actionDelegateIDFinish)
            );

            PrioritySelector priorityIDItems = new PrioritySelector(
                new Decorator(canRunDelegateFunkyIDManual, sequenceIDManual),
                new Decorator(canRunDelegateFunkyIDBookOfCain, sequenceIDBookOfCain)
            );

            CanRunDecoratorDelegate canRunDelegateFunkyIDOverlord = TownRunManager.IdenifyItemOverlord;
            GilesReplacement.Children[2] = new Decorator(canRunDelegateFunkyIDOverlord, priorityIDItems);

            Logger.DBLog.DebugFormat("[FunkyTownRun] Idenify Items - hooked...");

            #endregion

            // Replace the pause just after identify stuff to ensure we wait before trying to run to vendor etc.
            CanRunDecoratorDelegate canRunDelegateEvaluateAction = TownRunManager.ActionsEvaluatedOverlord;
            ActionDelegate actionDelegateEvaluateAction = TownRunManager.ActionsEvaluatedBehavior;

            Sequence sequenceEvaluate = new Sequence(
                        new Zeta.TreeSharp.Action(actionDelegatePrePause),
                        new Zeta.TreeSharp.Action(actionDelegatePause),
                        new Zeta.TreeSharp.Action(actionDelegateEvaluateAction)
                    );

            GilesReplacement.Children[3] = new Decorator(canRunDelegateEvaluateAction, sequenceEvaluate);

            #region Salvage

            // Replace DB salvaging behavior tree with my optimized & "one-at-a-time" version
            CanRunDecoratorDelegate canRunDelegateSalvageGilesOverlord = TownRunManager.GilesSalvageOverlord;
            ActionDelegate actionDelegatePreSalvage = TownRunManager.GilesOptimisedPreSalvage;
            ActionDelegate actionDelegateSalvage = TownRunManager.GilesOptimisedSalvage;
            ActionDelegate actionDelegatePostSalvage = TownRunManager.GilesOptimisedPostSalvage;
            Sequence sequenceSalvage = new Sequence(
                    new Zeta.TreeSharp.Action(actionDelegatePreSalvage),
                    new Zeta.TreeSharp.Action(actionDelegateSalvage),
                    new Zeta.TreeSharp.Action(actionDelegatePostSalvage),
                    new Sequence(
                    new Zeta.TreeSharp.Action(actionDelegatePrePause),
                    new Zeta.TreeSharp.Action(actionDelegatePause)
                    )
                    );
            GilesReplacement.Children[4] = new Decorator(canRunDelegateSalvageGilesOverlord, sequenceSalvage);
            Logger.DBLog.DebugFormat("[FunkyTownRun] Salvage - hooked...");

            #endregion

            #region Stash

            // Replace DB stashing behavior tree with my optimized version with loot rule replacement
            CanRunDecoratorDelegate canRunDelegateStashGilesOverlord = TownRunManager.StashOverlord;
            ActionDelegate actionDelegatePreStash = TownRunManager.PreStash;
            ActionDelegate actionDelegatePostStash = TownRunManager.PostStash;

            ActionDelegate actionDelegateStashMovement = TownRunManager.StashMovement;
            ActionDelegate actionDelegateStashUpdate = TownRunManager.StashUpdate;
            ActionDelegate actionDelegateStashItems = TownRunManager.StashItems;

            Sequence sequencestash = new Sequence(
                    new Zeta.TreeSharp.Action(actionDelegatePreStash),
                    new Zeta.TreeSharp.Action(actionDelegateStashMovement),
                    new Zeta.TreeSharp.Action(actionDelegateStashUpdate),
                    new Zeta.TreeSharp.Action(actionDelegateStashItems),
                    new Zeta.TreeSharp.Action(actionDelegatePostStash),
                    new Sequence(
                    new Zeta.TreeSharp.Action(actionDelegatePrePause),
                    new Zeta.TreeSharp.Action(actionDelegatePause)
                    )
                    );
            GilesReplacement.Children[5] = new Decorator(canRunDelegateStashGilesOverlord, sequencestash);
            Logger.DBLog.DebugFormat("[FunkyTownRun] Stash - hooked...");

            #endregion

            #region Vendor

            // Replace DB vendoring behavior tree with my optimized & "one-at-a-time" version
            CanRunDecoratorDelegate canRunDelegateSellGilesOverlord = TownRunManager.GilesSellOverlord;
            ActionDelegate actionDelegatePreSell = TownRunManager.GilesOptimisedPreSell;
            ActionDelegate actionDelegateMovement = TownRunManager.VendorMovement;
            ActionDelegate actionDelegateSell = TownRunManager.GilesOptimisedSell;
            ActionDelegate actionDelegatePostSell = TownRunManager.GilesOptimisedPostSell;
            Sequence sequenceSell = new Sequence(
                    new Zeta.TreeSharp.Action(actionDelegatePreSell),
                    new Zeta.TreeSharp.Action(actionDelegateMovement),
                    new Zeta.TreeSharp.Action(actionDelegateSell),
                    new Zeta.TreeSharp.Action(actionDelegatePostSell),
                    new Sequence(
                    new Zeta.TreeSharp.Action(actionDelegatePrePause),
                    new Zeta.TreeSharp.Action(actionDelegatePause)
                    )
                    );
            GilesReplacement.Children[6] = new Decorator(canRunDelegateSellGilesOverlord, sequenceSell);
            Logger.DBLog.DebugFormat("[FunkyTownRun] Vendor - hooked...");

            #endregion

            #region Interaction Behavior
            CanRunDecoratorDelegate canRunDelegateInteraction = TownRunManager.InteractionOverlord;
            ActionDelegate actionDelegateInteractionMovementhBehavior = TownRunManager.InteractionMovement;
            ActionDelegate actionDelegateInteractionClickBehaviorBehavior = TownRunManager.InteractionClickBehavior;
            ActionDelegate actionDelegateInteractionLootingBehaviorBehavior = TownRunManager.InteractionLootingBehavior;
            ActionDelegate actionDelegateInteractionFinishBehaviorBehavior = TownRunManager.InteractionFinishBehavior;

            Sequence sequenceInteraction = new Sequence(
                    new Zeta.TreeSharp.Action(actionDelegateInteractionFinishBehaviorBehavior),
                    new Zeta.TreeSharp.Action(actionDelegateInteractionMovementhBehavior),
                    new Zeta.TreeSharp.Action(actionDelegateInteractionClickBehaviorBehavior),
                    new Zeta.TreeSharp.Action(actionDelegateInteractionLootingBehaviorBehavior),
                    new Zeta.TreeSharp.Action(actionDelegateInteractionFinishBehaviorBehavior)
                );
            GilesReplacement.InsertChild(7, new Decorator(canRunDelegateInteraction, sequenceInteraction));
            Logger.DBLog.DebugFormat("[FunkyTownRun] Interaction Behavior - Inserted...");

            #endregion

            #region Gambling Behavior

            CanRunDecoratorDelegate canRunDelegateGambling = TownRunManager.GamblingRunOverlord;
            ActionDelegate actionDelegateGamblingMovementBehavior = TownRunManager.GamblingMovement;
            ActionDelegate actionDelegateGamblingInteractionBehavior = TownRunManager.GamblingInteraction;
            ActionDelegate actionDelegateGamblingStartBehavior = TownRunManager.GamblingStart;
            ActionDelegate actionDelegateGamblingFinishBehavior = TownRunManager.GamblingFinish;

            Sequence sequenceGambling = new Sequence(
                    new Zeta.TreeSharp.Action(actionDelegateGamblingStartBehavior),
                    new Zeta.TreeSharp.Action(actionDelegateGamblingMovementBehavior),
                    new Zeta.TreeSharp.Action(actionDelegateGamblingInteractionBehavior),
                    new Zeta.TreeSharp.Action(actionDelegateGamblingFinishBehavior)
                );
            GilesReplacement.InsertChild(8, new Decorator(canRunDelegateGambling, sequenceGambling));
            Logger.DBLog.DebugFormat("[FunkyTownRun] Gambling Behavior - Inserted...");

            #endregion

            #region Finish Behavior

            int childrenCount = GilesReplacement.Children.Count;
            ActionDelegate actionFinishReset = TownRunManager.ActionsEvaluatedEndingBehavior;
            ActionDelegate actionDelegateFinishBehavior = TownRunManager.FinishBehavior;
            var finish = GilesReplacement.Children[childrenCount - 1];

            Sequence FinishSequence = new Sequence
            (
                finish,
                new Zeta.TreeSharp.Action(actionFinishReset),
                new Zeta.TreeSharp.Action(actionDelegateFinishBehavior)
            );
            GilesReplacement.Children[childrenCount - 1] = FinishSequence;
            Logger.DBLog.DebugFormat("[FunkyTownRun] Created Sequence Finish Behavior.");

            #endregion

            CanRunDecoratorDelegate canRunDelegateGilesTownRunCheck = TownRunManager.TownRunCheckOverlord;
            VendorCanRunDelegate = canRunDelegateGilesTownRunCheck;
            VendorPrioritySelector = GilesReplacement;
            var VendorComposite = new Decorator(canRunDelegateGilesTownRunCheck, GilesReplacement);
            VendorGUID = VendorComposite.Guid;

            HookHandler.SetHookValue(HookHandler.HookType.VendorRun, 0, VendorComposite);
            Logger.DBLog.DebugFormat("[FunkyTownRun] Vendor Run tree hooking finished.");
            #endregion

            initTreeHooks = true;
        }
Example #59
0
 public Composite GenerateMoveToTargetBehavior()
 {
     var Behavior = new PrioritySelector();
     var MoveToMob = new Action(delegate(object context)
                                    {
                                        if (_context.CurrentTarget == null) return;
                                        if (_context.CurrentTarget.GetNativeObject() == null) return;
                                        Vector3 position = _context.CurrentTarget.GetPosition();
                                        BotManager.Legs.Walk(position.X, position.Y);
                                    });
     Behavior.AddChild(MoveToMob);
     Behavior.AddChild(new Sleep(200));
     return Behavior;
 }
Example #60
0
        /// <summary>
        /// create standard Avoidance behavior (disengage and/or kiting)
        /// </summary>
        /// <param name="disengageSpell">spellName to use for disengage</param>
        /// <param name="disengageDist">distance spellName will jump</param>
        /// <param name="disengageDir">direction spellName jumps</param>
        /// <param name="crowdControl">behavior called to crowd control melee enemies or halt use of disengage</param>
        /// <param name="needDisengage">delegate to check for using disgenage. defaults checking settings for health and # attackers</param>
        /// <param name="needKiting">delegate to check for using kiting. defaults to checking settings for health and # attackers</param>
        /// <param name="cancelKiting">delegate to check if kiting should be cancelled. defaults to checking no attackers that aren't crowd controlled</param>
        /// <returns></returns>
        public static Composite CreateAvoidanceBehavior(
            string disengageSpell,
            int disengageDist,
            Disengage.Direction disengageDir,
            Composite crowdControl,
            SimpleBooleanDelegate needDisengage = null, 
            SimpleBooleanDelegate needKiting = null, 
            SimpleBooleanDelegate cancelKiting = null
            )
        {
            PrioritySelector pri = new PrioritySelector();

            // build default check for whether disengage is needed
            if (needDisengage == null)
            {
                needDisengage = req =>
                {
                    if (disengageSpell == null || disengageDir == Disengage.Direction.None)
                        return false;

                    if (!Kite.IsDisengageWantedByUserSettings() || !MovementManager.IsClassMovementAllowed || !SingularRoutine.IsAllowed(CapabilityFlags.Kiting))
                        return false;

                    if (Spell.IsSpellOnCooldown(disengageSpell) && (!SingularSettings.Instance.UseRacials || Spell.IsSpellOnCooldown("Rocket Jump")))
                        return false;

                    bool useDisengage = false;

                    if (SingularRoutine.CurrentWoWContext == WoWContext.Normal)
                    {
                        int countMelee = Unit.UnitsInCombatWithUsOrOurStuff(7).Sum( u => !u.IsPlayer || !u.IsMelee() ? 1 : SingularSettings.Instance.DisengageMobCount);
                        if (countMelee >= SingularSettings.Instance.DisengageMobCount)
                            useDisengage = true;
                        else if (Me.HealthPercent <= SingularSettings.Instance.DisengageHealth && countMelee > 0)
                            useDisengage = true;
                    }
                    else if (SingularRoutine.CurrentWoWContext == WoWContext.Battlegrounds)
                    {
                        useDisengage = Unit.UnfriendlyUnits(7).Any(u => u.IsMelee());
                    }

                    return useDisengage;
                };
            }

            // standard disengage behavior, with class specific check to make sure parties are crowd controlled
            if (SingularSettings.Instance.DisengageAllowed)
            {
                Composite behavRocketJump = new ActionAlwaysFail();
                if (SingularSettings.Instance.UseRacials && SpellManager.HasSpell("Rocket Jump"))
                    behavRocketJump = Disengage.CreateDisengageBehavior("Rocket Jump", 20, Disengage.Direction.Frontwards, null);

                pri.AddChild(
                    new Decorator(
                        ret => needDisengage(ret),
                        new Sequence(
                            crowdControl,   // return Failure if shouldnt disengage, otherwise Success to allow
                            new PrioritySelector(
                                // new Action(r => { Logger.Write( LogColor.Hilite, "^Avoidance: disengaging away from mobs!"); return RunStatus.Failure; } ),
                                Disengage.CreateDisengageBehavior(disengageSpell, disengageDist, disengageDir, null),
                                behavRocketJump
                                )
                            )
                        )
                    );
            }

            // build default needKiting check
            if (needKiting == null)
            {
                needKiting = req =>
                {
                    if (!Kite.IsKitingWantedByUserSettings() || !MovementManager.IsClassMovementAllowed || !SingularRoutine.IsAllowed(CapabilityFlags.Kiting))
                        return false;

                    bool useKiting = false;
                    int countMelee = Unit.UnitsInCombatWithUsOrOurStuff(7).Count();
                    if (countMelee >= SingularSettings.Instance.KiteMobCount)
                        useKiting = true;
                    else if (Me.HealthPercent <= SingularSettings.Instance.KiteHealth && countMelee > 0)
                        useKiting = true;

                    return useKiting;
                };
            }

            if (cancelKiting == null)
            {
                cancelKiting = req =>
                {
                    int countAttackers = Unit.UnitsInCombatWithUsOrOurStuff(7).Count();
                    return (countAttackers == 0);
                };
            }

            // add check to initiate kiting behavior
            if (SingularSettings.Instance.KiteAllow)
            {
                pri.AddChild(
                    new Decorator(
                        ret => needKiting(ret),
                        new Sequence(
                            crowdControl,
                            Kite.BeginKitingBehavior()
                            )
                        )
                    );
            }

            if (!pri.Children.Any())
            {
                return new ActionAlwaysFail();
            }

            return new Decorator(req => MovementManager.IsClassMovementAllowed, pri);
        }