From 3c4bb202bcb4505ab2611d4313380128d90da720 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sun, 9 Mar 2025 20:18:06 +0100 Subject: [PATCH] Add vnav stuck check --- Questionable/Controller/MovementController.cs | 76 +++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/Questionable/Controller/MovementController.cs b/Questionable/Controller/MovementController.cs index 338bea94..87934eeb 100644 --- a/Questionable/Controller/MovementController.cs +++ b/Questionable/Controller/MovementController.cs @@ -120,7 +120,7 @@ internal sealed class MovementController : IDisposable if (!Destination.IsFlying) { (navPoints, bool recalculateNavmesh) = _movementOverrideController.AdjustPath(navPoints); - if (recalculateNavmesh && Destination.NavmeshCalculations < 10) + if (recalculateNavmesh && Destination.ShouldRecalculateNavmesh()) { Destination.NavmeshCalculations++; Destination.PartialRoute.AddRange(navPoints); @@ -167,6 +167,7 @@ internal sealed class MovementController : IDisposable { _logger.LogInformation("Flying but swimming, restarting as non-flying path..."); Restart(Destination); + return; } else if (Destination is { IsFlying: true } && !_condition[ConditionFlag.Mounted]) { @@ -179,7 +180,7 @@ internal sealed class MovementController : IDisposable if (Destination.MovementType == EMovementType.Landing) { if (!_condition[ConditionFlag.InFlight]) - Stop(); + Stop(); } else if ((localPlayerPosition - Destination.Position).Length() < Destination.StopDistance) { @@ -228,28 +229,66 @@ internal sealed class MovementController : IDisposable else Stop(); } - else if (!Destination.IsFlying && !_condition[ConditionFlag.Mounted] && - !_gameFunctions.HasStatusPreventingSprint() && Destination.CanSprint) + else { List 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); + } } } } @@ -393,6 +432,15 @@ internal sealed class MovementController : IDisposable { public int NavmeshCalculations { get; set; } public List 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 -- 2.30.2