if (!Destination.IsFlying)
                 {
                     (navPoints, bool recalculateNavmesh) = _movementOverrideController.AdjustPath(navPoints);
-                    if (recalculateNavmesh && Destination.NavmeshCalculations < 10)
+                    if (recalculateNavmesh && Destination.ShouldRecalculateNavmesh())
                     {
                         Destination.NavmeshCalculations++;
                         Destination.PartialRoute.AddRange(navPoints);
             {
                 _logger.LogInformation("Flying but swimming, restarting as non-flying path...");
                 Restart(Destination);
+                return;
             }
             else if (Destination is { IsFlying: true } && !_condition[ConditionFlag.Mounted])
             {
             if (Destination.MovementType == EMovementType.Landing)
             {
                 if (!_condition[ConditionFlag.InFlight])
-                    Stop();
+                Stop();
             }
             else if ((localPlayerPosition - Destination.Position).Length() < Destination.StopDistance)
             {
                 else
                     Stop();
             }
-            else if (!Destination.IsFlying && !_condition[ConditionFlag.Mounted] &&
-                     !_gameFunctions.HasStatusPreventingSprint() && Destination.CanSprint)
+            else
             {
                 List<Vector3> navPoints = _navmeshIpc.GetWaypoints();
                 Vector3? start = _clientState.LocalPlayer?.Position;
                 if (start != null)
                 {
-                    float actualDistance = 0;
-                    foreach (Vector3 end in navPoints)
+                    if (Destination.ShouldRecalculateNavmesh())
                     {
-                        actualDistance += (start.Value - end).Length();
-                        start = end;
+                        var nextWaypoint = navPoints.FirstOrDefault();
+                        if (nextWaypoint != default)
+                        {
+                            var distance = Vector2.Distance(new Vector2(start.Value.X, start.Value.Z),
+                                new Vector2(nextWaypoint.X, nextWaypoint.Z));
+                            if (Destination.LastWaypoint == null ||
+                                (Destination.LastWaypoint.Position - nextWaypoint).Length() > 0.1f)
+                            {
+                                Destination.LastWaypoint = new LastWaypointData(nextWaypoint)
+                                {
+                                    Distance2DAtLastUpdate = distance,
+                                    UpdatedAt = Environment.TickCount64,
+                                };
+                            }
+                            else if (Environment.TickCount64 - Destination.LastWaypoint.UpdatedAt > 500)
+                            {
+                                // check whether we've made any progress of any kind
+                                if (Math.Abs(distance - Destination.LastWaypoint.Distance2DAtLastUpdate) < 0.5f)
+                                {
+                                    int calculations = Destination.NavmeshCalculations;
+                                    _logger.LogWarning("Recalculating navmesh (n = {Calculations})", calculations);
+                                    Restart(Destination);
+                                    Destination.NavmeshCalculations = calculations + 1;
+                                }
+                                else
+                                {
+                                    Destination.LastWaypoint.Distance2DAtLastUpdate = distance;
+                                    Destination.LastWaypoint.UpdatedAt = Environment.TickCount64;
+                                }
+                            }
+                        }
                     }
 
-                    unsafe
+                    if (!Destination.IsFlying && !_condition[ConditionFlag.Mounted] &&
+                        !_gameFunctions.HasStatusPreventingSprint() && Destination.CanSprint)
                     {
-                        // 70 is ~10 seconds of sprint
-                        if (actualDistance > 100f &&
-                            ActionManager.Instance()->GetActionStatus(ActionType.GeneralAction, 4) == 0)
+                        float actualDistance = 0;
+                        foreach (Vector3 end in navPoints)
                         {
-                            _logger.LogInformation("Triggering Sprint");
-                            ActionManager.Instance()->UseAction(ActionType.GeneralAction, 4);
+                            actualDistance += (start.Value - end).Length();
+                            start = end;
+                        }
+
+                        unsafe
+                        {
+                            // 70 is ~10 seconds of sprint
+                            if (actualDistance > 100f &&
+                                ActionManager.Instance()->GetActionStatus(ActionType.GeneralAction, 4) == 0)
+                            {
+                                _logger.LogInformation("Triggering Sprint");
+                                ActionManager.Instance()->UseAction(ActionType.GeneralAction, 4);
+                            }
                         }
                     }
                 }
     {
         public int NavmeshCalculations { get; set; }
         public List<Vector3> PartialRoute { get; } = [];
+        public LastWaypointData? LastWaypoint { get; set; }
+
+        public bool ShouldRecalculateNavmesh() => NavmeshCalculations < 10;
+    }
+
+    public sealed record LastWaypointData(Vector3 Position)
+    {
+        public long UpdatedAt { get; set; }
+        public double Distance2DAtLastUpdate { get; set; }
     }
 
     public sealed class PathfindingFailedException : Exception