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