118 lines
3.5 KiB
C#
118 lines
3.5 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using Microsoft.Extensions.Logging;
|
|
using Questionable.Controller.CustomDelivery;
|
|
using Questionable.Controller.Steps;
|
|
using Questionable.Controller.Steps.Common;
|
|
using Questionable.Controller.Steps.Interactions;
|
|
using Questionable.Controller.Steps.Movement;
|
|
using Questionable.Controller.Steps.Shared;
|
|
using Questionable.Model.Questing;
|
|
using SmartNav;
|
|
|
|
namespace Questionable.Navigation;
|
|
|
|
internal sealed class SmartNavReRouteService(ReRoutePolicy reRoutePolicy, SmartNavTaskMapper taskMapper, Configuration configuration, ILogger<SmartNavReRouteService> logger)
|
|
{
|
|
private ETravelMode _travelMode;
|
|
|
|
public void SetDestination(uint territoryId, Vector3 position, ETravelMode travelMode = ETravelMode.Auto)
|
|
{
|
|
_travelMode = travelMode;
|
|
var (allowMount, allowFlight) = GetCapabilities(travelMode);
|
|
reRoutePolicy.SetDestination(territoryId, position, allowMount, allowFlight);
|
|
}
|
|
|
|
public void ClearDestination()
|
|
{
|
|
_travelMode = ETravelMode.Auto;
|
|
reRoutePolicy.ClearDestination();
|
|
}
|
|
|
|
public bool HandleMovementFailure(TaskQueue taskQueue)
|
|
{
|
|
if (!configuration.Navigation.ReRouteOnFailure)
|
|
{
|
|
return false;
|
|
}
|
|
string failedTargetNodeId = null;
|
|
string failedApproachNodeId = null;
|
|
if (taskQueue.CurrentTaskExecutor?.CurrentTask is MoveTask moveTask)
|
|
{
|
|
string routeTargetNodeId = moveTask.RouteTargetNodeId;
|
|
if (routeTargetNodeId != null)
|
|
{
|
|
failedTargetNodeId = routeTargetNodeId;
|
|
failedApproachNodeId = moveTask.RouteApproachNodeId;
|
|
}
|
|
}
|
|
List<ITask> list = ExtractNonMovementTasks(taskQueue);
|
|
if (taskQueue.CurrentTaskExecutor?.CurrentTask is DeliveryNpcApproachTask item)
|
|
{
|
|
list.Insert(0, item);
|
|
}
|
|
ReRouteDecision reRouteDecision = reRoutePolicy.HandleMovementFailure(failedTargetNodeId, failedApproachNodeId, list.Count > 0);
|
|
if (!(reRouteDecision is ReRouteDecision.SkipMovement))
|
|
{
|
|
if (reRouteDecision is ReRouteDecision.Replan replan)
|
|
{
|
|
taskQueue.Reset();
|
|
foreach (ITask item2 in taskMapper.MapInstructions(replan.Instructions, null, _travelMode))
|
|
{
|
|
taskQueue.Enqueue(item2);
|
|
}
|
|
foreach (ITask item3 in list)
|
|
{
|
|
taskQueue.Enqueue(item3);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
taskQueue.Reset();
|
|
foreach (ITask item4 in list)
|
|
{
|
|
taskQueue.Enqueue(item4);
|
|
}
|
|
logger.LogInformation("Re-route: skipping movement with {TaskCount} preserved tasks", list.Count);
|
|
return true;
|
|
}
|
|
|
|
private static List<ITask> ExtractNonMovementTasks(TaskQueue taskQueue)
|
|
{
|
|
return taskQueue.RemainingTasks.Where((ITask t) => !IsMovementTask(t)).ToList();
|
|
}
|
|
|
|
private static bool IsMovementTask(ITask task)
|
|
{
|
|
if (!(task is MoveTask))
|
|
{
|
|
if (task is Dive.Task task2)
|
|
{
|
|
if (task2.SmartNavRouted)
|
|
{
|
|
goto IL_006c;
|
|
}
|
|
}
|
|
else if (task is LandTask || task is Mount.MountTask || task is AetheryteTeleport.Task || task is AethernetRide.Task || task is WaitNavmesh.Task || task is WaitCondition.Task || task is WarpInteract.Task || task is TaxiInteract.Task || task is SubRegionTransport.Task || task is TicketTeleport.Task)
|
|
{
|
|
goto IL_006c;
|
|
}
|
|
return false;
|
|
}
|
|
goto IL_006c;
|
|
IL_006c:
|
|
return true;
|
|
}
|
|
|
|
internal static (bool AllowMount, bool AllowFlight) GetCapabilities(ETravelMode travelMode)
|
|
{
|
|
return travelMode switch
|
|
{
|
|
ETravelMode.OnFoot => (AllowMount: false, AllowFlight: false),
|
|
ETravelMode.GroundMount => (AllowMount: true, AllowFlight: false),
|
|
_ => (AllowMount: true, AllowFlight: true),
|
|
};
|
|
}
|
|
}
|