private Composite SubBehaviorPS_UpdatePathWaypoint()
 {
     return
         (new Decorator(ret => PathPatrol.Peek().Distance2DSquared(DragonVehicle.Location) <= (30 * 30),
                        new ActionFail(ret => PathPatrol.Dequeue())));
 }
        private Composite StateBehaviorPS_CompletingObjectives()
        {
            return(new PrioritySelector(
                       // If for some reason no longer in the vehicle, go fetch another...
                       new Decorator(context => !Query.IsViable(DragonVehicle),
                                     new Action(context =>
            {
                QBCLog.Warning("We've been jettisoned from vehicle unexpectedly--will try again.");
                BehaviorState = BehaviorStateType.MountingVehicle;
            })),

                       // If quest is complete, then head back...
                       new Decorator(context => Me.IsQuestComplete(GetQuestId()),
                                     new Action(context => { BehaviorState = BehaviorStateType.ReturningToBase; })),

                       new CompositeThrottle(Throttle.UserUpdate,
                                             new ActionFail(context => { TreeRoot.StatusText = "Completing Quest Objectives"; })),

                       SubBehaviorPS_UpdatePathWaypoint(),
                       SubBehaviorPS_Heal(),

                       // We go after the Ballistas first...
                       // NB: Soldiers will be collateral damage of pursing Ballistas.
                       // If the soldiers don't complete after doing Ballistas, we'll clean up
                       // the Soldiers next.
                       new Decorator(context => !IsViableTarget(SelectedTarget),
                                     new PrioritySelector(
                                         // Try to find target...
                                         new ActionFail(context =>
            {
                SelectedTarget = FindMobToKill(!Me.IsQuestObjectiveComplete(GetQuestId(), 2)
                                                            ? MobId_ScarletBallista
                                                            : MobId_TirisfalCrusader);
            }),
                                         // If no target found, move toward next waypoint...
                                         new Decorator(context => !IsViableTarget(SelectedTarget),
                                                       new Action(context => { Flightor.MoveTo(PathPatrol.Peek(), (float)FlightorMinHeight); }))
                                         )),

                       new Action(context =>
            {
                // NB: We would've preferred to strafe in this algorithm; however,
                // strafing triggers Flightor's unstuck handler too much.  Probably because
                // this is a vehicle/transport, instead of a 'flying mount'.

                // Show the target we're pursuing...
                Utility.Target(SelectedTarget);

                var myLocation = WoWMovement.ActiveMover.Location;
                var selectedTargetLocation = SelectedTarget.Location;
                var distance2DSqrToTarget = myLocation.Distance2DSquared(selectedTargetLocation);

                // Deal with needed evasion...
                if (StationPoint.HasValue)
                {
                    if (myLocation.Distance(StationPoint.Value) > FlyingPathPrecision)
                    {
                        Flightor.MoveTo(StationPoint.Value);
                        return RunStatus.Success;
                    }

                    StationPoint = null;
                }

                // See if we need a new 'on station' location...
                if (!StationPoint.HasValue)
                {
                    // If our weapon is not ready or we can't see target, move around station until it is...
                    if (!Weapon_FrozenDeathbolt.IsWeaponReady() ||
                        (IsViableTarget(SelectedTarget) && !SelectedTarget.InLineOfSight) ||
                        IsIncomingMissile())
                    {
                        StationPoint = FindNewStationPoint(SelectedTarget);
                        return RunStatus.Success;
                    }
                }

                // If we are too far from selected target, close the distance...
                if (distance2DSqrToTarget > (TargetDistance2DMax * TargetDistance2DMax))
                {
                    Flightor.MoveTo(FindDistanceClosePoint(SelectedTarget, PathPatrol.Peek().Z));
                    return RunStatus.Success;
                }

                // If we are too close to selected target, put some distance between us...
                if (distance2DSqrToTarget < (TargetDistance2DMin * TargetDistance2DMin))
                {
                    Flightor.MoveTo(FindDistanceGainPoint(SelectedTarget, TargetDistance2DMin));
                    return RunStatus.Success;
                }

                // If weapon is not ready, just keep on station/evading...
                if (!Weapon_FrozenDeathbolt.IsWeaponReady())
                {
                    return RunStatus.Success;
                }

                // If the weapon cannot address the target, blacklist target and find another...
                if (!Weapon_FrozenDeathbolt.WeaponAim(SelectedTarget))
                {
                    _targetBlacklist.Add(SelectedTarget, TimeSpan.FromSeconds(5));
                }

                // If weapon cannot fire for some reason, try again...
                if (!Weapon_FrozenDeathbolt.WeaponFire())
                {
                    return RunStatus.Success;
                }

                return RunStatus.Failure;       // fall through
            }),
                       // NB: Need to delay a bit for the weapon to actually launch.  Otherwise
                       // it screws the aim up if we move again before projectile is fired.
                       new Sleep(ctx => Delay.LagDuration + Delay.AfterWeaponFire)
                       //new Wait(Delay.LagDuration, context => Weapon_FrozenDeathbolt.IsWeaponReady(), new ActionAlwaysSucceed())
                       ));
        }