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)
                           );
        }
        public WarsongGulchProfile(AmeisenBotInterfaces bot)
        {
            Bot = bot;

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

            JBgBlackboard = new(UpdateBattlegroundInfo);

            KillEnemyFlagCarrierSelector = new
                                           (
                (b) => b.EnemyTeamFlagCarrier != null,
                new Selector <CtfBlackboard>
                (
                    (b) => b.MyTeamHasFlag ||
                    b.EnemyTeamFlagCarrier.Position.GetDistance(WsgDataset.EnemyBasePosition)
                    < Bot.Player.Position.GetDistance(WsgDataset.EnemyBasePosition),
                    new Leaf <CtfBlackboard>(KillEnemyFlagCarrier),
                    new Leaf <CtfBlackboard>(MoveToEnemyBaseAndGetFlag)
                ),
                new Selector <CtfBlackboard>
                (
                    (b) => b.EnemyTeamFlagPos.GetDistance2D(WsgDataset.EnemyBasePositionMapCoords)
                    < b.EnemyTeamFlagPos.GetDistance2D(WsgDataset.OwnBasePositionMapCoords),
                    new Leaf <CtfBlackboard>((b) => MoveToPosition(WsgDataset.EnemyBasePosition)),
                    new Leaf <CtfBlackboard>((b) => MoveToPosition(WsgDataset.OwnBasePosition))
                )
                                           );

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

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

                // only my team has the flag
                new Selector <CtfBlackboard>
                (
                    (b) => b.MyTeamFlagCarrier != null && b.MyTeamFlagCarrier.Guid == Bot.Wow.PlayerGuid,
                    // i'm the flag carrier
                    new Leaf <CtfBlackboard>((b) => MoveToPosition(WsgDataset.OwnBasePosition)),
                    new Selector <CtfBlackboard>
                    (
                        (b) => b.MyTeamFlagCarrier != null,
                        new Leaf <CtfBlackboard>((b) => MoveToPosition(b.MyTeamFlagCarrier.Position)),
                        new Leaf <CtfBlackboard>(DefendOwnBase)
                    )
                ),

                // only enemy team has the flag
                KillEnemyFlagCarrierSelector,

                // both teams have the flag
                new Selector <CtfBlackboard>
                (
                    (b) => b.MyTeamFlagCarrier != null && b.MyTeamFlagCarrier.Guid == Bot.Wow.PlayerGuid,
                    new Selector <CtfBlackboard>
                    (
                        (b) => Bot.Player.Position.GetDistance(WsgDataset.OwnBasePosition) < 128.0f,
                        new Leaf <CtfBlackboard>((b) => MoveToPosition(WsgDataset.FlagHidingSpot)),
                        new Leaf <CtfBlackboard>((b) => MoveToPosition(WsgDataset.OwnBasePosition))
                    ),
                    new Selector <CtfBlackboard>
                    (
                        (b) => b.MyTeamFlagCarrier != null &&
                        b.MyTeamFlagCarrier.DistanceTo(Bot.Player) < 50.0f &&
                        Bot.GetNearFriends <IWowPlayer>(b.MyTeamFlagCarrier.Position, 25.0f).Count() < 2,
                        // assist our flag carrier
                        new Leaf <CtfBlackboard>((b) => MoveToPosition(b.MyTeamFlagCarrier.Position)),
                        // go kill other flag carrier
                        KillEnemyFlagCarrierSelector
                    )
                )
                           );

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

            BehaviorTree = new
                           (
                MainSelector,
                JBgBlackboard,
                TimeSpan.FromSeconds(1)
                           );
        }