示例#1
0
 private static bool FMIsInBloodElfStartingZone(FlightMaster fm)
 {
     return(fm.NPCId == 16189 ||
            fm.NPCId == 16192 ||
            fm.NPCId == 24851 ||
            fm.NPCId == 26560);
 }
示例#2
0
    public static FlightMaster GetClosestFlightMasterFrom(float maxRadius)
    {
        FlightMaster result = null;

        // Pre order the list
        List <FlightMaster> orderedListFM = FlightMasterDB.FlightMasterList
                                            .FindAll(fm => (fm.IsDiscovered || WFMSettings.CurrentSettings.TakeUndiscoveredTaxi) &&
                                                     ToolBox.FMIsOnMyContinent(fm) &&
                                                     !fm.IsDisabledByPlugin())
                                            .OrderBy(fm => fm.Position.DistanceTo(ObjectManager.Me.Position)).ToList();

        foreach (FlightMaster flightMaster in orderedListFM)
        {
            if (flightMaster.Position.DistanceTo(ObjectManager.Me.Position) < maxRadius)
            {
                float realDist = ToolBox.CalculatePathTotalDistance(ObjectManager.Me.Position, flightMaster.Position);
                Logger.Log($"[FROM] {flightMaster.Name} is {Math.Round(realDist)} yards away");
                if (realDist < maxRadius)
                {
                    maxRadius = realDist;
                    result    = flightMaster;
                }
            }
        }
        return(result);
    }
示例#3
0
    // Requires FM map open
    public static FlightMaster GetBestAlternativeTo(List <string> reachableTaxis)
    {
        float        num      = ObjectManager.Me.Position.DistanceTo(destinationVector);
        FlightMaster resultFM = null;

        // Pre order the list
        List <FlightMaster> orderedListFM = FlightMasterDB.FlightMasterList
                                            .FindAll(fm => reachableTaxis.Contains(fm.Name))
                                            .OrderBy(fm => fm.Position.DistanceTo(destinationVector)).ToList();

        foreach (FlightMaster flightMaster in orderedListFM)
        {
            if (flightMaster.Position.DistanceTo(destinationVector) < num)
            {
                float realDist = ToolBox.CalculatePathTotalDistance(flightMaster.Position, destinationVector);
                Logger.Log($"[TO2] {flightMaster.Name} is {Math.Round(realDist)} yards away from destination");
                if (realDist < num)
                {
                    num      = realDist;
                    resultFM = flightMaster;
                }
            }
        }
        return(resultFM);
    }
示例#4
0
    public override void Run()
    {
        MovementManager.StopMoveNewThread();
        MovementManager.StopMoveToNewThread();

        FlightMaster flightmasterFrom = Main.from;
        FlightMaster flightmasterTo   = Main.to;

        if (WFMMoveInteract.GoInteractwithFM(flightmasterFrom, true))
        {
            if (FlightMasterDB.UpdateKnownFMs(flightmasterFrom))
            {
                Logger.Log("Flightmaster list has changed. Trying to find a new path.");
                Main.to = null;
                Main.shouldTakeFlight = false;
                return;
            }

            List <string> reachableTaxis = new List <string>();
            // Look for current To and record reachables in case we can't find it
            for (int i = 0; i < 120; i++)
            {
                string nodeStatus = Lua.LuaDoString <string>($"return TaxiNodeGetType({i})");
                string nodeName   = Lua.LuaDoString <string>($"return TaxiNodeName({i})");

                if (nodeStatus == "REACHABLE")
                {
                    if (nodeName == flightmasterTo.Name)
                    {
                        TakeTaxi(flightmasterFrom, nodeName);
                        return;
                    }
                    reachableTaxis.Add(nodeName);
                }
            }

            // Find an alternative
            Logger.Log($"{flightmasterTo.Name} is unreachable, trying to find an alternative");
            FlightMaster alternativeFm = Main.GetBestAlternativeTo(reachableTaxis);
            if (alternativeFm != null)
            {
                Logger.Log($"Found an alternative flight : {alternativeFm.Name}");
                TakeTaxi(flightmasterFrom, alternativeFm.Name);
                return;
            }
            else
            {
                Main.shouldTakeFlight = false;
                ToolBox.PausePlugin("Couldn't find an alternative flight");
            }
        }
    }
示例#5
0
    public static bool FMIsOnMyContinent(FlightMaster fm)
    {
        if (PlayerInBloodElfStartingZone())
        {
            return(FMIsInBloodElfStartingZone(fm) || fm.Continent == ContinentId.Azeroth);
        }

        if (PlayerInDraneiStartingZone())
        {
            return(FMIsInDraneiStartingZone(fm));
        }

        return(!FMIsInDraneiStartingZone(fm) &&
               (fm.Continent == (ContinentId)Usefuls.ContinentId || (FMIsInBloodElfStartingZone(fm) && (ContinentId)Usefuls.ContinentId == ContinentId.Azeroth)));
    }
示例#6
0
 public static bool ExceptionConditionsAreMet(FlightMaster fm)
 {
     return(fm != null &&
            (fm.NPCId != 20234 || fm.Position.DistanceTo(ObjectManager.Me.Position) < 100) && // Shatter Point, Hellfire Peninsula
            (fm.NPCId != 19581 || GetReputation("The Aldor") > 0) && // Altar of Sha'tar, Shadowmoon Valley
            (fm.NPCId != 21766 || GetReputation("The Scryers") > 0) && // Sanctum of the Stars, Shadowmoon Valley
            (fm.NPCId != 30314 || Quest.GetLogQuestIsComplete(12896) || Quest.GetLogQuestIsComplete(12897)) && // The Shadow Vault, Icecrown
            (fm.NPCId != 28037 || Quest.GetLogQuestIsComplete(12523)) && // Nesingwary Base Camp, Sholazar Basin
            (fm.NPCId != 31069 || Quest.GetLogQuestIsComplete(13141)) && // Crusaders' Pinnacle, Icecrown
            (fm.NPCId != 32571 || Quest.GetLogQuestIsComplete(12956)) && // Dun Nifflelem, The Storm Peaks
            (fm.NPCId != 37915 || GetWoWVersion().Equals("3.3.5")) && // The Bulwark, Tirisfal
            (fm.NPCId != 37888 || GetWoWVersion().Equals("3.3.5")) && // Thondoril River, Western Plaguelands
            (fm.NPCId != 29480 || ObjectManager.Me.WowClass == WoWClass.DeathKnight) // Acherus: The Ebon Hold
            );
 }
示例#7
0
    private void BackGroundPulse(object sender, DoWorkEventArgs args)
    {
        while (isLaunched)
        {
            try
            {
                if (inPause && pauseTimer.ElapsedMilliseconds > WFMSettings.CurrentSettings.PauseLengthInSeconds * 1000)
                {
                    Logger.Log($"{WFMSettings.CurrentSettings.PauseLengthInSeconds} seconds elapsed in pause");
                    ToolBox.UnPausePlugin();
                    MovementManager.StopMoveNewThread();
                    MovementManager.StopMoveToNewThread();
                }

                if (Conditions.InGameAndConnectedAndProductStartedNotInPause &&
                    !ObjectManager.Me.InCombatFlagOnly &&
                    !ObjectManager.Me.IsOnTaxi &&
                    ObjectManager.Me.IsAlive)
                {
                    nearestFlightMaster = GetNearestFlightMaster();

                    // Mark flightmaster as To be discovered
                    if (nearestFlightMaster != null &&
                        !nearestFlightMaster.IsDisabledByPlugin() &&
                        ToolBox.ExceptionConditionsAreMet(nearestFlightMaster) &&
                        !WFMSettings.CurrentSettings.KnownFlightsList.Contains(nearestFlightMaster.Name) &&
                        ToolBox.CalculatePathTotalDistance(ObjectManager.Me.Position, nearestFlightMaster.Position) < WFMSettings.CurrentSettings.DetectTaxiDistance * 1.2)
                    {
                        flightMasterToDiscover = nearestFlightMaster;
                    }

                    // Hook for HMP states locks and others
                    if (discoverFlightMasterState.NeedToRun && currentState?.Priority < discoverFlightMasterState.Priority)
                    {
                        Logger.Log("Stop on tracks to ensure discovery");
                        MovementManager.StopMove();
                        MovementManager.StopMoveTo();
                    }
                }
            }
            catch (Exception arg)
            {
                Logger.LogError(string.Concat(arg));
            }
            Thread.Sleep(3000);
        }
    }
 private static WoWUnit FindNearbyAliveFM(FlightMaster fm)
 {
     for (int i = 1; i <= 3; i++)
     {
         WoWUnit nearbyFm = ObjectManager.GetObjectWoWUnit().Find(unit => unit.Entry == fm.NPCId && unit.IsAlive);
         if (nearbyFm != null)
         {
             return(nearbyFm);
         }
         else
         {
             Logger.Log($"FM detection failed, retrying ({i}/3)");
             Thread.Sleep(1000);
         }
     }
     return(null);
 }
 private static bool InteractWithFm(FlightMaster fm)
 {
     Interact.InteractGameObject(ObjectManager.GetWoWUnitByEntry(fm.NPCId).First().GetBaseAddress);
     for (int i = 1; i <= 5; i++)
     {
         if (ObjectManager.Target.Entry != fm.NPCId)
         {
             Logger.Log($"Failed to interact with NPC, retrying ({i}/5)");
             Interact.InteractGameObject(ObjectManager.GetWoWUnitByEntry(fm.NPCId).First().GetBaseAddress);
             Thread.Sleep(500);
         }
         else
         {
             return(true);
         }
     }
     return(false);
 }
    public override void Run()
    {
        MovementManager.StopMoveNewThread();
        MovementManager.StopMoveToNewThread();
        FlightMaster fmToDiscover = Main.flightMasterToDiscover;

        Logger.Log($"Discovering flight master {fmToDiscover.Name}");

        // We go to the position
        if (WFMMoveInteract.GoInteractwithFM(fmToDiscover))
        {
            FlightMasterDB.SetFlightMasterToKnown(fmToDiscover.NPCId);
            Main.flightMasterToDiscover = null;
            ToolBox.UnPausePlugin();
            Main.shouldTakeFlight = false;

            FlightMasterDB.UpdateKnownFMs(fmToDiscover);
            MovementManager.StopMove(); // reset path
        }
    }
 private static bool FmMapIsOpen(FlightMaster fm)
 {
     Usefuls.SelectGossipOption(GossipOptionsType.taxi);
     for (int i = 1; i <= 5; i++)
     {
         if (!Main.isFMMapOpen)
         {
             Logger.LogDebug($"Failed to open FM map, retrying ({i}/5)");
             Lua.LuaDoString("CloseGossip()");
             Thread.Sleep(500);
             if (InteractWithFm(fm))
             {
                 Usefuls.SelectGossipOption(GossipOptionsType.taxi);
                 Thread.Sleep(500);
             }
         }
         else
         {
             return(true);
         }
     }
     return(false);
 }
示例#12
0
    public static FlightMaster GetClosestFlightMasterTo(float maxRadius)
    {
        FlightMaster result = null;

        // Pre order the list
        List <FlightMaster> orderedListFM = FlightMasterDB.FlightMasterList
                                            .FindAll(fm => fm.IsDiscovered && fm.NPCId != from.NPCId && ToolBox.FMIsOnMyContinent(fm))
                                            .OrderBy(fm => fm.Position.DistanceTo(destinationVector)).ToList();

        foreach (FlightMaster flightMaster in orderedListFM)
        {
            if (flightMaster.Position.DistanceTo(destinationVector) < maxRadius)
            {
                float realDist = ToolBox.CalculatePathTotalDistance(flightMaster.Position, destinationVector);
                Logger.Log($"[TO] {flightMaster.Name} is {Math.Round(realDist)} yards away from destination");
                if (realDist < maxRadius)
                {
                    maxRadius = realDist;
                    result    = flightMaster;
                }
            }
        }
        return(result);
    }
示例#13
0
    public static bool UpdateKnownFMs(FlightMaster FMWithMapOpen)
    {
        if ((ContinentId)Usefuls.ContinentId == ContinentId.Azeroth && !azerothNodesUpdated ||
            (ContinentId)Usefuls.ContinentId == ContinentId.Kalimdor && !kalimdorNodesUpdated ||
            (ContinentId)Usefuls.ContinentId == ContinentId.Expansion01 && !outlandNodesUpdated ||
            (ContinentId)Usefuls.ContinentId == ContinentId.Northrend && !northrendNodesUpdated)
        {
            Logger.Log($"Updating known FlightMasters on {Usefuls.ContinentNameMpq} for this session");

            bool allInvalid          = true;
            bool latNodeWasInvalid   = false;
            bool modificationWasMade = false;
            bool endOfListReached    = false;

            // 3 attempts to discover flights
            for (int j = 1; j <= 3; j++)
            {
                if (endOfListReached)
                {
                    if ((ContinentId)Usefuls.ContinentId == ContinentId.Azeroth)
                    {
                        azerothNodesUpdated = true;
                    }
                    else if ((ContinentId)Usefuls.ContinentId == ContinentId.Kalimdor)
                    {
                        kalimdorNodesUpdated = true;
                    }
                    else if ((ContinentId)Usefuls.ContinentId == ContinentId.Expansion01)
                    {
                        outlandNodesUpdated = true;
                    }
                    else if ((ContinentId)Usefuls.ContinentId == ContinentId.Northrend)
                    {
                        northrendNodesUpdated = true;
                    }

                    break;
                }

                WFMMoveInteract.GoInteractwithFM(FMWithMapOpen);
                // Loop through nodes
                for (int i = 0; i < 120; i++)
                {
                    string nodeName = Lua.LuaDoString <string>($"return TaxiNodeName({i})");
                    if (nodeName != "INVALID")
                    {
                        allInvalid        = false;
                        latNodeWasInvalid = false;
                        if (SetFlightMasterToKnown(nodeName) && modificationWasMade == false)
                        {
                            modificationWasMade = true;
                        }
                    }
                    else
                    {
                        // we hit 2 invalids in a row - means this is the end of the list
                        if (latNodeWasInvalid)
                        {
                            endOfListReached = true;
                            break;
                        }

                        latNodeWasInvalid = true;
                        if (SetFlightMasterToUnknown(nodeName) && modificationWasMade == false)
                        {
                            modificationWasMade = true;
                        }
                    }
                }

                if (allInvalid)
                {
                    Lua.LuaDoString("CloseGossip()");
                    Logger.LogDebug($"All flight nodes are invalid, retrying ({j}/3)");
                    Thread.Sleep(500);
                }
            }

            if (allInvalid)
            {
                ToolBox.PausePlugin("Couldn't find a valid flight node");
            }

            return(modificationWasMade);
        }

        return(false);
    }
示例#14
0
    public static void SetFlightMasterToUnknown(int flightMasterID)
    {
        FlightMaster flightMaster = GetFlightMasterById(flightMasterID);

        SetFlightMasterToUnknown(flightMaster.Name);
    }
示例#15
0
    public static bool SetFlightMasterToKnown(int flightMasterID)
    {
        FlightMaster flightMaster = GetFlightMasterById(flightMasterID);

        return(SetFlightMasterToKnown(flightMaster.Name));
    }
    public static bool GoInteractwithFM(FlightMaster fm, bool openMapRequired = false)
    {
        if (GoToTask.ToPosition(fm.Position, 5f))
        {
            if (!Main.isLaunched ||
                !Conditions.InGameAndConnectedAndAliveAndProductStartedNotInPause ||
                ObjectManager.Me.Position.DistanceTo(fm.Position) > 10f)
            {
                return(false);
            }

            // We're in fight (possibly on mount)
            if (ObjectManager.Me.InCombatFlagOnly)
            {
                if (ObjectManager.Me.IsMounted)
                {
                    MountTask.DismountMount();
                }
                return(false);
            }

            // We have reached the FM
            if (ObjectManager.Me.IsMounted)
            {
                MountTask.DismountMount();
            }

            // Check if FM is here or dead
            WoWUnit nearbyFM = FindNearbyAliveFM(fm);
            if (nearbyFM == null)
            {
                fm.Disable("FlightMaster is absent or dead.");
                ResetFlags();
                return(false);
            }

            // Approach FM
            if (!GoToTask.ToPosition(nearbyFM.Position, 1f))
            {
                return(false);
            }

            Interact.InteractGameObject(ObjectManager.GetWoWUnitByEntry(fm.NPCId).First().GetBaseAddress);

            // Check if interaction successful
            if (!InteractWithFm(fm))
            {
                fm.Disable("Unable to interact with NPC");
                ResetFlags();
                return(false);
            }

            Usefuls.SelectGossipOption(GossipOptionsType.taxi);

            // Check if map open
            if (openMapRequired && !FmMapIsOpen(fm))
            {
                fm.Disable("Unable to open FM map");
                ResetFlags();
                return(false);
            }

            return(true);
        }
        // We haven't reach the FM yet
        return(false);
    }
示例#17
0
    private void TakeTaxi(FlightMaster fm, string taxiNodeName)
    {
        string clickNodeLua = "TakeTaxiNode(" + Lua.LuaDoString <int>("for i=0,120 do if string.find(TaxiNodeName(i),'" + taxiNodeName.Replace("'", "\\'") + "') then return i end end", "").ToString() + ")";

        Logger.LogDebug(clickNodeLua);
        Lua.LuaDoString(clickNodeLua, false);
        Thread.Sleep(500);

        // 5 tries to click on node if it failed
        for (int i = 1; i <= 5; i++)
        {
            if (ObjectManager.Me.IsCast)
            {
                Usefuls.WaitIsCasting();
                i = 1;
                Logger.Log("You're casting, wait");
                continue;
            }

            if (ObjectManager.Me.IsOnTaxi || Main.inPause)
            {
                break;
            }
            else
            {
                Logger.Log($"Taking taxi failed. Retrying ({i}/5)");
                Lua.LuaDoString($"CloseTaxiMap(); CloseGossip();");
                Main.errorTooFarAwayFromTaxiStand = false;
                Thread.Sleep(500);
                if (WFMMoveInteract.GoInteractwithFM(fm))
                {
                    Thread.Sleep(500);
                }
                Usefuls.SelectGossipOption(GossipOptionsType.taxi);
                Thread.Sleep(500);
                Lua.LuaDoString(clickNodeLua, false);
                Thread.Sleep(500);
            }
        }

        if (Main.inPause)
        {
            return;
        }

        if (Main.errorTooFarAwayFromTaxiStand)
        {
            ToolBox.PausePlugin("Taking taxi failed (error clicking node)");
        }
        else
        {
            Logger.Log($"Flying to {taxiNodeName}");
        }

        Thread.Sleep(Usefuls.Latency + 500);
        Main.shouldTakeFlight             = false;
        Main.errorTooFarAwayFromTaxiStand = false;
        Thread.Sleep(Usefuls.Latency + 500);

        if (!ObjectManager.Me.IsOnTaxi)
        {
            ToolBox.PausePlugin("Taking taxi failed");
        }
    }
示例#18
0
 private static bool FMIsInDraneiStartingZone(FlightMaster fm)
 {
     return(fm.NPCId == 17555 ||
            fm.NPCId == 17554);
 }
示例#19
0
        protected override Composite CreateMainBehavior()
        {
            return(new PrioritySelector(
                       // PvP server considerations...
                       // Combat is disabled while on the Taxi.  If on the ground, we want it enabled
                       // in case we get attacked on a PvP server.
                       new Decorator(context => !LevelBot.BehaviorFlags.HasFlag(BehaviorFlags.Combat),
                                     new Action(context => { LevelBot.BehaviorFlags |= BehaviorFlags.Combat; })),

                       // Move to flight master, and interact to take taxi ride...
                       new Decorator(context => !Me.OnTaxi,
                                     new PrioritySelector(context =>
            {
                FlightMaster =
                    Query.FindMobsAndFactions(Utility.ToEnumerable <int>(MobId_FlightMaster))
                    .FirstOrDefault()
                    as WoWUnit;

                return context;
            },

                                                          // If flight master not in view, move to where he should be...
                                                          new Decorator(context => FlightMaster == null,
                                                                        new ActionRunCoroutine(
                                                                            context => UtilityCoroutine.MoveTo(
                                                                                WaitLocation,
                                                                                "FlightMaster location",
                                                                                MovementBy))),

                                                          // Make certain the bombs are in our backpack...
                                                          new ActionRunCoroutine(
                                                              ctx => _waitForInventoryItem
                                                              ?? (_waitForInventoryItem = new UtilityCoroutine.WaitForInventoryItem(
                                                                      () => ItemId_Bomb,
                                                                      () =>
            {
                QBCLog.ProfileError(
                    "Cannot continue without required item: {0}",
                    Utility.GetItemNameFromId(ItemId_Bomb));
                BehaviorDone();
            }))),
                                                          // Move to flightmaster, and gossip to hitch a ride...
                                                          new Decorator(context => FlightMaster != null,
                                                                        new PrioritySelector(
                                                                            new Decorator(context => !FlightMaster.WithinInteractRange,
                                                                                          new ActionRunCoroutine(
                                                                                              context => UtilityCoroutine.MoveTo(
                                                                                                  FlightMaster.Location,
                                                                                                  FlightMaster.SafeName,
                                                                                                  MovementBy))),
                                                                            new ActionRunCoroutine(context => CommonCoroutines.StopMoving()),
                                                                            new Decorator(ctx => Me.Mounted, new ActionRunCoroutine(ctx => CommonCoroutines.LandAndDismount())),
                                                                            new Decorator(context => !GossipFrame.Instance.IsVisible,
                                                                                          new Action(context => { FlightMaster.Interact(); })),
                                                                            new Action(context => { GossipFrame.Instance.SelectGossipOption(GossipOption); })
                                                                            ))
                                                          ))
                       ));
        }
示例#20
0
    private static void MovementEventsOnMovementPulse(List <Vector3> points, CancelEventArgs cancelable)
    {
        if (shouldTakeFlight &&
            points.Last() == destinationVector &&
            !inPause)
        {
            Logger.Log("Cancelled move to " + destinationVector);
            cancelable.Cancel = true;
        }

        if (!ObjectManager.Me.IsAlive || ObjectManager.Me.IsOnTaxi || shouldTakeFlight || !isLaunched || inPause)
        {
            return;
        }

        DateTime dateBegin = DateTime.Now;

        // If we have detected a potential FP travel
        float totalWalkingDistance = ToolBox.CalculatePathTotalDistance(ObjectManager.Me.Position, points.Last());

        // If the path is shorter than setting, we skip
        if (totalWalkingDistance < (double)WFMSettings.CurrentSettings.TaxiTriggerDistance)
        {
            //Logger.LogDebug($"Path ({Math.Round(totalWalkingDistance)} yards) is shorter than trigger setting {WFMSettings.CurrentSettings.TaxiTriggerDistance}. Let's walk.");
            return;
        }

        Logger.Log($"{Math.Round(totalWalkingDistance)} yards path is longer than trigger setting {WFMSettings.CurrentSettings.TaxiTriggerDistance}. " +
                   $"Searching for flights.");

        if (Logging.Status.Contains("Follow Path") &&
            !Logging.Status.Contains("Resurrect") &&
            totalWalkingDistance < (double)WFMSettings.CurrentSettings.SkipIfFollowPathDistance)
        {
            Logger.Log($"Currently following path. {totalWalkingDistance} yards is smaller than trigger setting {WFMSettings.CurrentSettings.SkipIfFollowPathDistance} yards. Ignoring flights.");
            return;
        }

        destinationVector = points.Last();

        from = GetClosestFlightMasterFrom(totalWalkingDistance);

        if (from == null)
        {
            Logger.Log("No FROM found");
            return;
        }

        double distanceToNearestFM = ToolBox.CalculatePathTotalDistance(ObjectManager.Me.Position, from.Position);
        double departureDistance   = distanceToNearestFM + WFMSettings.CurrentSettings.MinimumDistanceSaving;

        to = GetClosestFlightMasterTo(from.Position.DistanceTo(destinationVector));

        //Logger.Log($"Best FROM is {from?.Name}");
        //Logger.Log($"Best TO is {to?.Name}");

        if (from.Equals(to))
        {
            to = null;
        }

        // Calculate total real distance FROM/TO
        // if no TO found, we set the total distance back to walking distance
        double processedDistance;

        if (to == null)
        {
            processedDistance = totalWalkingDistance;
        }
        else
        {
            processedDistance = departureDistance + ToolBox.CalculatePathTotalDistance(to.Position, destinationVector);
        }

        //Logger.Log($"Walking distance is {Math.Round(totalWalkingDistance)}");
        //Logger.Log($"Processed distance is {Math.Round(processedDistance)}");

        // If total real distance does not save any distance or is longer, try to find alternative
        if (processedDistance >= totalWalkingDistance ||
            to == null)
        {
            if (to == null)
            {
                Logger.Log($"No direct flight path, trying to find an alternative, please wait");
            }
            else
            {
                Logger.Log($"Flight from {from.Name} to {to.Name} would save {Math.Round(totalWalkingDistance - processedDistance + WFMSettings.CurrentSettings.MinimumDistanceSaving)} yards. " +
                           $"You set a minimum of {WFMSettings.CurrentSettings.MinimumDistanceSaving} yards. Trying to find an alternative.");
            }

            // Pre order the list
            List <FlightMaster> orderedListFM = FlightMasterDB.FlightMasterList
                                                .FindAll(fm => fm.IsDiscovered && fm.NPCId != from.NPCId && ToolBox.FMIsOnMyContinent(fm))
                                                .OrderBy(fm => fm.Position.DistanceTo(destinationVector)).ToList();

            foreach (FlightMaster flightMaster in orderedListFM)
            {
                if (flightMaster.Position.DistanceTo(destinationVector) + departureDistance < processedDistance)
                {
                    // Look for the closest available FM near destination
                    double alternativeDistance = departureDistance + ToolBox.CalculatePathTotalDistance(flightMaster.Position, destinationVector);

                    Logger.Log($"Alternative TO : {flightMaster.Name} ({Math.Round(alternativeDistance)} yards total)");
                    if (alternativeDistance < processedDistance)
                    {
                        processedDistance = alternativeDistance;
                        to = flightMaster;
                    }
                }
            }
        }

        if (to != null &&
            from != null &&
            !from.Equals(to) &&
            processedDistance <= totalWalkingDistance)
        {
            double realProcessedDistance = Math.Round(processedDistance - WFMSettings.CurrentSettings.MinimumDistanceSaving);
            Logger.Log($"Flight found for {Math.Round(totalWalkingDistance)} yards path. Processed distance is {realProcessedDistance} yards." +
                       $" Taking Taxi from {from.Name} to {to.Name}. (You will save {Math.Round(totalWalkingDistance) - realProcessedDistance} yards)");
            MovementManager.StopMoveNewThread();
            MovementManager.StopMoveToNewThread();
            cancelable.Cancel = true;
            shouldTakeFlight  = true;
        }
        else
        {
            Logger.Log($"No relevant flight found for {Math.Round(totalWalkingDistance)} yards path");
        }
        Logger.Log($"Process time : {(DateTime.Now.Ticks - dateBegin.Ticks) / 10000} ms");
    }