private BehaviorTreeStatus DefendOwnBase(CtfBlackboard blackboard)
        {
            double distance = WowInterface.ObjectManager.Player.Position.GetDistance(WsgDataset.OwnBasePosition);

            if (distance > 16.0)
            {
                WowInterface.MovementEngine.SetMovementAction(MovementAction.Move, WsgDataset.OwnBasePosition);
            }
            else
            {
                WowUnit nearEnemy = WowInterface.ObjectManager.GetNearEnemies <WowUnit>(WsgDataset.OwnBasePosition, 16.0).FirstOrDefault();

                if (nearEnemy != null)
                {
                    double distanceToEnemy = WowInterface.ObjectManager.Player.Position.GetDistance(nearEnemy.Position);

                    if (distanceToEnemy > 2.0)
                    {
                        WowInterface.MovementEngine.SetMovementAction(MovementAction.Move, nearEnemy.Position);
                    }
                    else if (ActionEvent.Run())
                    {
                        WowInterface.Globals.ForceCombat = true;
                        WowInterface.HookManager.WowTargetGuid(nearEnemy.Guid);
                    }
                }
            }
            return(BehaviorTreeStatus.Ongoing);
        }
        private BehaviorTreeStatus AttackNearWeakestEnemy(CtfBlackboard blackboard)
        {
            WowPlayer weakestPlayer = WowInterface.ObjectManager.GetNearEnemies <WowPlayer>(WowInterface.ObjectManager.Player.Position, 20.0).OrderBy(e => e.Health).FirstOrDefault();

            if (weakestPlayer != null)
            {
                double distance  = weakestPlayer.Position.GetDistance(WowInterface.ObjectManager.Player.Position);
                double threshold = WowInterface.CombatClass.IsMelee ? 3.0 : 28.0;

                if (distance > threshold)
                {
                    WowInterface.MovementEngine.SetMovementAction(MovementAction.Move, weakestPlayer.Position);
                }
                else if (ActionEvent.Run())
                {
                    WowInterface.Globals.ForceCombat = true;
                    WowInterface.HookManager.WowTargetGuid(weakestPlayer.Guid);
                }
            }
            else
            {
                return(BehaviorTreeStatus.Failed);
            }

            return(BehaviorTreeStatus.Ongoing);
        }
        private bool DoWeOutnumberOurEnemies(CtfBlackboard blackboard)
        {
            if (blackboard.MyTeamFlagCarrier != null && blackboard.MyTeamFlagCarrier.Guid == WowInterface.ObjectManager.PlayerGuid)
            {
                return(false);
            }

            int friends = WowInterface.ObjectManager.GetNearFriends <WowPlayer>(WowInterface.ObjectManager.Player.Position, 18.0).Count();
            int enemies = WowInterface.ObjectManager.GetNearEnemies <WowPlayer>(WowInterface.ObjectManager.Player.Position, 18.0).Count();

            return(enemies > 0 && friends >= enemies);
        }
        private BehaviorTreeStatus FleeFromComingEnemies(CtfBlackboard blackboard)
        {
            WowUnit nearestEnemy = WowInterface.ObjectManager.GetNearEnemies <WowUnit>(WowInterface.ObjectManager.Player.Position, 48.0).OrderBy(e => e.Position.GetDistance(WowInterface.ObjectManager.Player.Position)).FirstOrDefault();

            if (nearestEnemy != null)
            {
                WowInterface.MovementEngine.SetMovementAction(MovementAction.Flee, nearestEnemy.Position, nearestEnemy.Rotation);
                return(BehaviorTreeStatus.Ongoing);
            }
            else
            {
                return(BehaviorTreeStatus.Success);
            }
        }
        private BehaviorTreeStatus MoveToEnemyBaseAndGetFlag(CtfBlackboard blackboard)
        {
            double distance = WowInterface.ObjectManager.Player.Position.GetDistance(WsgDataset.EnemyBasePosition);

            if (distance > 2.0)
            {
                WowInterface.MovementEngine.SetMovementAction(MovementAction.Move, WsgDataset.EnemyBasePosition);
            }
            else
            {
                return(UseNearestFlag(blackboard));
            }

            return(BehaviorTreeStatus.Ongoing);
        }
        private bool AmIOneOfTheClosestToOwnFlagCarrier(CtfBlackboard blackboard, int memberCount)
        {
            if (memberCount <= 0 || blackboard.MyTeamFlagCarrier == null)
            {
                return(false);
            }

            // check wether i'm part of the closest x (memberCount) members to the flag carrier
            int index = WowInterface.ObjectManager.Partymembers
                        .OfType <WowPlayer>()
                        .Where(e => e.Guid != blackboard.MyTeamFlagCarrier.Guid)
                        .OrderBy(e => e.Position.GetDistance(WowInterface.ObjectManager.Player.Position))
                        .Select((player, id) => new { Player = player, Index = id })
                        .FirstOrDefault(_ => _.Player.Guid == WowInterface.ObjectManager.PlayerGuid)?.Index ?? -1;

            return(index > -1 && index <= memberCount);
        }
        private BehaviorTreeStatus MoveToNearestBuff(CtfBlackboard blackboard)
        {
            WowGameobject buffObject = WowInterface.ObjectManager.GetClosestWowGameobjectByDisplayId(new List <int>()
            {
                5991, 5995, 5931
            });

            if (buffObject != null &&
                buffObject.Position.GetDistance(WowInterface.ObjectManager.Player.Position) > 3.0)
            {
                WowInterface.MovementEngine.SetMovementAction(MovementAction.Move, buffObject.Position);
            }
            else
            {
                return(BehaviorTreeStatus.Failed);
            }

            return(BehaviorTreeStatus.Ongoing);
        }
        private BehaviorTreeStatus KillEnemyFlagCarrier(CtfBlackboard blackboard)
        {
            if (JBgBlackboard.EnemyTeamFlagCarrier == null)
            {
                WowInterface.Globals.ForceCombat = false;
                return(BehaviorTreeStatus.Success);
            }

            double distance  = WowInterface.ObjectManager.Player.Position.GetDistance(JBgBlackboard.EnemyTeamFlagCarrier.Position);
            double threshold = WowInterface.CombatClass.IsMelee ? 3.0 : 28.0;

            if (distance > threshold && !WowInterface.ObjectManager.Player.IsCasting)
            {
                WowInterface.MovementEngine.SetMovementAction(MovementAction.Move, BotUtils.MoveAhead(JBgBlackboard.EnemyTeamFlagCarrier.Position, JBgBlackboard.EnemyTeamFlagCarrier.Rotation, 1.0f));
            }
            else if (ActionEvent.Run())
            {
                WowInterface.Globals.ForceCombat = true;
                WowInterface.HookManager.WowTargetGuid(JBgBlackboard.EnemyTeamFlagCarrier.Guid);
            }

            return(BehaviorTreeStatus.Ongoing);
        }
        private BehaviorTreeStatus UseNearestFlag(CtfBlackboard blackboard)
        {
            WowGameobject nearestFlag = JBgBlackboard.NearFlags.OrderBy(e => e.Position.GetDistance(WowInterface.ObjectManager.Player.Position)).FirstOrDefault();

            if (nearestFlag != null)
            {
                double distance = WowInterface.ObjectManager.Player.Position.GetDistance(nearestFlag.Position);

                if (distance > 4.0)
                {
                    WowInterface.MovementEngine.SetMovementAction(MovementAction.Move, nearestFlag.Position);
                }
                else if (ActionEvent.Run())
                {
                    WowInterface.HookManager.WowObjectRightClick(nearestFlag);
                }
            }
            else
            {
                return(BehaviorTreeStatus.Failed);
            }

            return(BehaviorTreeStatus.Ongoing);
        }
        private BehaviorTreeStatus MoveToOwnFlagCarrierAndHelp(CtfBlackboard blackboard)
        {
            if (JBgBlackboard.MyTeamFlagCarrier == null)
            {
                return(BehaviorTreeStatus.Failed);
            }

            double distance = WowInterface.ObjectManager.Player.Position.GetDistance(JBgBlackboard.MyTeamFlagCarrier.Position);

            if (distance > 4.0)
            {
                WowInterface.MovementEngine.SetMovementAction(MovementAction.Move, JBgBlackboard.MyTeamFlagCarrier.Position);
            }
            else
            {
                WowUnit nearEnemy = WowInterface.ObjectManager.GetNearEnemies <WowUnit>(JBgBlackboard.MyTeamFlagCarrier.Position, 32.0).FirstOrDefault();

                if (nearEnemy != null)
                {
                    double distanceToEnemy = WowInterface.ObjectManager.Player.Position.GetDistance(nearEnemy.Position);
                    double threshold       = WowInterface.CombatClass.IsMelee ? 3.0 : 28.0;

                    if (distanceToEnemy > threshold)
                    {
                        WowInterface.MovementEngine.SetMovementAction(MovementAction.Move, nearEnemy.Position);
                    }
                    else if (ActionEvent.Run())
                    {
                        WowInterface.Globals.ForceCombat = true;
                        WowInterface.HookManager.WowTargetGuid(nearEnemy.Guid);
                    }
                }
            }

            return(BehaviorTreeStatus.Ongoing);
        }
 private bool EnemiesNearFlagCarrier(CtfBlackboard blackboard)
 {
     return(blackboard.MyTeamFlagCarrier.Position.GetDistance(WowInterface.ObjectManager.Player.Position) < 32.0);
 }
 private bool AmINearOwnFlagCarrier(CtfBlackboard blackboard)
 {
     return(WowInterface.ObjectManager.GetNearEnemies <WowUnit>(blackboard.MyTeamFlagCarrier.Position, 48.0).Any(e => !e.IsDead));
 }
        public WarsongGulchProfile(WowInterface wowInterface)
        {
            WowInterface = wowInterface;

            ActionEvent   = new TimegatedEvent(TimeSpan.FromMilliseconds(500));
            LosCheckEvent = new TimegatedEvent(TimeSpan.FromMilliseconds(1000));

            JBgBlackboard = new CtfBlackboard(UpdateBattlegroundInfo);

            KillEnemyFlagCarrierSelector = new Selector <CtfBlackboard>
                                           (
                "EnemyTeamFlagCarrierInRange",
                (b) => b.EnemyTeamFlagCarrier != null,
                new Selector <CtfBlackboard>
                (
                    "HasFlag",
                    (b) => b.MyTeamHasFlag ||
                    b.EnemyTeamFlagCarrier.Position.GetDistance(WsgDataset.EnemyBasePosition)
                    < WowInterface.ObjectManager.Player.Position.GetDistance(WsgDataset.EnemyBasePosition),
                    new Leaf <CtfBlackboard>("KillEnemyFlagCarrier", KillEnemyFlagCarrier),
                    new Leaf <CtfBlackboard>("MoveToEnemyBaseAndGetFlag", MoveToEnemyBaseAndGetFlag)
                ),
                new Selector <CtfBlackboard>
                (
                    "IsFlagNearOwnOrEnemyBase",
                    (b) => b.EnemyTeamFlagPos.GetDistance2D(WsgDataset.EnemyBasePositionMapCoords)
                    < b.EnemyTeamFlagPos.GetDistance2D(WsgDataset.OwnBasePositionMapCoords),
                    new Leaf <CtfBlackboard>("MoveToEnemyBase", (b) => MoveToPosition(WsgDataset.EnemyBasePosition)),
                    new Leaf <CtfBlackboard>("MoveToOwnBase", (b) => MoveToPosition(WsgDataset.OwnBasePosition))
                )
                                           );

            FlagSelector = new DualSelector <CtfBlackboard>
                           (
                "WhoHasTheFlag",
                (b) => b.MyTeamHasFlag,
                (b) => b.EnemyTeamHasFlag,

                // no team has the flag
                new Leaf <CtfBlackboard>("MoveToEnemyBaseAndGetFlag", MoveToEnemyBaseAndGetFlag),

                // only my team has the flag
                new Selector <CtfBlackboard>
                (
                    "AmITheFlagCarrier",
                    (b) => b.MyTeamFlagCarrier != null && b.MyTeamFlagCarrier.Guid == WowInterface.ObjectManager.PlayerGuid,
                    new Leaf <CtfBlackboard>("MoveToOwnBase", (b) => MoveToPosition(WsgDataset.OwnBasePosition)),
                    new Selector <CtfBlackboard>
                    (
                        "IsTheFlagCarrierInRange",
                        (b) => b.MyTeamFlagCarrier != null,
                        new Leaf <CtfBlackboard>("MoveToOwnFlagCarrier", (b) => MoveToPosition(b.MyTeamFlagCarrier.Position)),
                        new Leaf <CtfBlackboard>("DefendOwnBase", DefendOwnBase)
                    )
                ),

                // only enemy team has the flag
                KillEnemyFlagCarrierSelector,

                // both teams have the flag
                new Selector <CtfBlackboard>
                (
                    "AmITheFlagCarrier",
                    (b) => b.MyTeamFlagCarrier != null && b.MyTeamFlagCarrier.Guid == WowInterface.ObjectManager.PlayerGuid,
                    new Selector <CtfBlackboard>
                    (
                        "AmINearOwnBase",
                        (b) => WowInterface.ObjectManager.Player.Position.GetDistance(WsgDataset.OwnBasePosition) < 128.0,
                        new Leaf <CtfBlackboard>("MoveToHidingSpot", (b) => MoveToPosition(WsgDataset.FlagHidingSpot)),
                        new Leaf <CtfBlackboard>("MoveToOwnBase", (b) => MoveToPosition(WsgDataset.OwnBasePosition))
                    ),
                    KillEnemyFlagCarrierSelector
                )
                           );

            MainSelector = new Selector <CtfBlackboard>
                           (
                "IsGateOpen",
                (b) => IsGateOpen(),
                new Selector <CtfBlackboard>
                (
                    "IsFlagNear",
                    (b) => IsFlagNear(),
                    new Leaf <CtfBlackboard>("UseNearestFlag", UseNearestFlag),
                    new Selector <CtfBlackboard>
                    (
                        "IsAnyBuffNearMe",
                        (b) => IsAnyBuffNearMe(16.0),
                        new Leaf <CtfBlackboard>("MoveToNearestBuff", MoveToNearestBuff),
                        new Selector <CtfBlackboard>
                        (
                            "DoWeOutnumberOurEnemies",
                            (b) => DoWeOutnumberOurEnemies(b),
                            new Leaf <CtfBlackboard>("AttackNearWeakestEnemy", AttackNearWeakestEnemy),
                            FlagSelector
                        )
                    )
                ),
                new Leaf <CtfBlackboard>("MoveToGatePosition", (b) => MoveToPosition(WsgDataset.GatePosition))
                           );

            BehaviorTree = new AmeisenBotBehaviorTree <CtfBlackboard>
                           (
                "JBgWarsongGulchBehaviorTree",
                MainSelector,
                JBgBlackboard,
                TimeSpan.FromSeconds(1)
                           );
        }