muffin v7.5.13

This commit is contained in:
alydev 2026-08-22 10:25:22 +10:00
parent 911ed68baa
commit acf3e3cb18
69 changed files with 2731 additions and 1425 deletions

View file

@ -5,21 +5,28 @@ 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)
{
public void SetDestination(uint territoryId, Vector3 position)
private ETravelMode _travelMode;
public void SetDestination(uint territoryId, Vector3 position, ETravelMode travelMode = ETravelMode.Auto)
{
reRoutePolicy.SetDestination(territoryId, position);
_travelMode = travelMode;
var (allowMount, allowFlight) = GetCapabilities(travelMode);
reRoutePolicy.SetDestination(territoryId, position, allowMount, allowFlight);
}
public void ClearDestination()
{
_travelMode = ETravelMode.Auto;
reRoutePolicy.ClearDestination();
}
@ -51,7 +58,7 @@ internal sealed class SmartNavReRouteService(ReRoutePolicy reRoutePolicy, SmartN
if (reRouteDecision is ReRouteDecision.Replan replan)
{
taskQueue.Reset();
foreach (ITask item2 in taskMapper.MapInstructions(replan.Instructions))
foreach (ITask item2 in taskMapper.MapInstructions(replan.Instructions, null, _travelMode))
{
taskQueue.Enqueue(item2);
}
@ -79,10 +86,33 @@ internal sealed class SmartNavReRouteService(ReRoutePolicy reRoutePolicy, SmartN
private static bool IsMovementTask(ITask task)
{
if (task is MoveTask || 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)
if (!(task is MoveTask))
{
return true;
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;
}
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),
};
}
}

View file

@ -53,7 +53,27 @@ internal sealed class SmartNavRouteEnqueuer(NavRouter navRouter, PlayerNavStateB
{
return false;
}
List<NavInstruction> list = instructionBuilder.Build(routeResult, territoryId).TakeWhile((NavInstruction x) => !(x is NavInstruction.Move move) || !move.IsFinal).ToList();
List<NavInstruction> list = instructionBuilder.Build(routeResult, territoryId).TakeWhile(delegate(NavInstruction x)
{
if (x is NavInstruction.Move move)
{
if (move.IsFinal)
{
goto IL_0026;
}
}
else if (x is NavInstruction.Swim { IsFinal: not false })
{
goto IL_0026;
}
bool flag = false;
goto IL_002c;
IL_0026:
flag = true;
goto IL_002c;
IL_002c:
return !flag;
}).ToList();
if (list.Count == 0)
{
return false;
@ -120,6 +140,18 @@ internal sealed class SmartNavRouteEnqueuer(NavRouter navRouter, PlayerNavStateB
{
return false;
}
if (instruction is NavInstruction.Swim)
{
return false;
}
if (instruction is NavInstruction.DiveEntry)
{
return false;
}
if (instruction is NavInstruction.Surface)
{
return false;
}
if (instruction is NavInstruction.AethernetHop)
{
return false;

View file

@ -5,6 +5,7 @@ using System.Numerics;
using Dalamud.Plugin.Services;
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.Data;
@ -15,13 +16,22 @@ namespace Questionable.Navigation;
internal sealed class SmartNavTaskMapper(IClientState clientState, TerritoryData territoryData)
{
public IEnumerable<ITask> MapInstructions(IReadOnlyList<NavInstruction> instructions, QuestStep? step = null)
private const float SurfaceExitRise = 3f;
public IEnumerable<ITask> MapInstructions(IReadOnlyList<NavInstruction> instructions, QuestStep? step = null, ETravelMode travelMode = ETravelMode.Auto)
{
for (int i = 0; i < instructions.Count; i++)
{
foreach (ITask item in Map(instructions[i], NextTravelInstruction(instructions, i), step))
{
yield return item;
if (item is MoveTask task && !(instructions[i] is NavInstruction.Swim))
{
yield return ApplyTravelMode(task, travelMode);
}
else
{
yield return item;
}
}
}
}
@ -48,66 +58,131 @@ internal sealed class SmartNavTaskMapper(IClientState clientState, TerritoryData
{
if (!(instruction is NavInstruction.Move move))
{
if (!(instruction is NavInstruction.Land))
if (!(instruction is NavInstruction.Swim swim))
{
if (!(instruction is NavInstruction.Unmount))
if (!(instruction is NavInstruction.DiveEntry dive))
{
NavInstruction.WaitForTerritory waitForTerritory = instruction as NavInstruction.WaitForTerritory;
if ((object)waitForTerritory == null)
if (!(instruction is NavInstruction.Surface surface))
{
if (!(instruction is NavInstruction.WaitForNavmesh))
if (!(instruction is NavInstruction.Land))
{
if (!(instruction is NavInstruction.InteractWarp interactWarp))
if (!(instruction is NavInstruction.Unmount))
{
if (!(instruction is NavInstruction.UseTeleportTicket useTeleportTicket))
NavInstruction.WaitForTerritory waitForTerritory = instruction as NavInstruction.WaitForTerritory;
if ((object)waitForTerritory == null)
{
if (!(instruction is NavInstruction.SubRegionTransport subRegionTransport))
if (!(instruction is NavInstruction.WaitForNavmesh))
{
throw new InvalidOperationException($"Unmapped NavInstruction: {instruction}");
if (!(instruction is NavInstruction.InteractWarp interactWarp))
{
if (!(instruction is NavInstruction.UseTeleportTicket useTeleportTicket))
{
if (!(instruction is NavInstruction.SubRegionTransport subRegionTransport))
{
throw new InvalidOperationException($"Unmapped NavInstruction: {instruction}");
}
yield return new SubRegionTransport.Task(subRegionTransport.From, subRegionTransport.To, subRegionTransport.Territory);
}
else
{
yield return new TicketTeleport.Task(useTeleportTicket.ItemId, useTeleportTicket.Territory);
}
}
else
{
yield return new WarpInteract.Task(interactWarp.NpcDataId, interactWarp.WarpRowId, interactWarp.FromTerritory, interactWarp.ToTerritory);
}
}
else
{
yield return new WaitNavmesh.Task();
}
yield return new SubRegionTransport.Task(subRegionTransport.From, subRegionTransport.To, subRegionTransport.Territory);
}
else
{
yield return new TicketTeleport.Task(useTeleportTicket.ItemId, useTeleportTicket.Territory);
yield return new WaitCondition.Task(() => waitForTerritory.Acceptable.Contains(clientState.TerritoryType), waitForTerritory.Description);
}
}
else
{
yield return new WarpInteract.Task(interactWarp.NpcDataId, interactWarp.WarpRowId, interactWarp.FromTerritory, interactWarp.ToTerritory);
yield return new Mount.UnmountTask();
}
}
else
{
yield return new WaitNavmesh.Task();
yield return new LandTask();
}
}
else
{
yield return new WaitCondition.Task(() => waitForTerritory.Acceptable.Contains(clientState.TerritoryType), waitForTerritory.Description);
ushort territory = surface.Territory;
Vector3 position = surface.Position;
position.Y = surface.Position.Y + 3f;
Vector3 destination = position;
bool? mount = true;
string targetNodeId = surface.TargetNodeId;
string approachNodeId = surface.ApproachNodeId;
yield return new MoveTask(territory, destination, mount, MountRequired: false, DismountRequired: false, null, null, DisableNavmesh: true, null, Fly: true, Land: false, IgnoreDistanceToObject: false, RestartNavigation: true, EInteractionType.None, SmartNavRouted: true, AllowZoneTransition: false, targetNodeId, approachNodeId);
}
}
else
{
yield return new Mount.UnmountTask();
yield return new Dive.Task
{
SmartNavRouted = true
};
ushort territory2 = dive.Territory;
Vector3 position = dive.Position;
position.Y = dive.Position.Y - 25f;
Vector3 destination2 = position;
string approachNodeId = dive.TargetNodeId;
string targetNodeId = dive.ApproachNodeId;
yield return new MoveTask(territory2, destination2, null, MountRequired: false, DismountRequired: false, null, null, DisableNavmesh: true, null, Fly: true, Land: false, IgnoreDistanceToObject: false, RestartNavigation: true, EInteractionType.None, SmartNavRouted: true, AllowZoneTransition: false, approachNodeId, targetNodeId);
}
}
else if (swim.IsFinal && step != null)
{
Vector3 destination3 = step.Position ?? swim.Position;
yield return new MoveTask(step, destination3)with
{
Fly = true,
Land = false,
SmartNavRouted = true,
RouteTargetNodeId = swim.TargetNodeId,
RouteApproachNodeId = swim.ApproachNodeId
};
}
else
{
yield return new LandTask();
NavInstruction.Swim swim2 = swim;
ushort territory3 = swim2.Territory;
Vector3 position2 = swim2.Position;
float? stopDistance = swim2.StopDistance;
string targetNodeId = swim2.TargetNodeId;
string approachNodeId = swim2.ApproachNodeId;
yield return new MoveTask(territory3, position2, null, MountRequired: false, DismountRequired: false, stopDistance, null, DisableNavmesh: false, null, Fly: true, Land: false, IgnoreDistanceToObject: false, RestartNavigation: true, EInteractionType.None, SmartNavRouted: true, AllowZoneTransition: false, targetNodeId, approachNodeId);
}
}
else if (move.IsFinal && step != null)
{
Vector3 destination = step.Position ?? move.Position;
yield return new MoveTask(step, destination)with
Vector3 destination4 = step.Position ?? move.Position;
MoveTask moveTask = new MoveTask(step, destination4)with
{
Fly = (move.Fly || step.Fly == true),
Land = (move.Fly || step.Land == true),
SmartNavRouted = true,
RouteTargetNodeId = move.TargetNodeId,
RouteApproachNodeId = move.ApproachNodeId
Fly = (move.Fly || step.Fly == true)
};
MoveTask moveTask2 = moveTask;
bool flag = move.Fly || step.Land == true;
if (!flag)
{
EArrivalMode arrivalMode = step.ArrivalMode;
bool flag2 = (uint)(arrivalMode - 2) <= 1u;
flag = flag2;
}
moveTask2.Land = flag;
moveTask.SmartNavRouted = true;
moveTask.RouteTargetNodeId = move.TargetNodeId;
moveTask.RouteApproachNodeId = move.ApproachNodeId;
yield return moveTask;
if (step != null)
{
bool? fly = step.Fly;
@ -116,22 +191,30 @@ internal sealed class SmartNavTaskMapper(IClientState clientState, TerritoryData
yield return new LandTask();
}
}
if (step.ArrivalMode == EArrivalMode.StayMounted && !step.DismountRequired)
{
yield return new Mount.MountTask(step.TerritoryId, Mount.EMountIf.Always);
}
else if (step.ArrivalMode == EArrivalMode.Dismount && !step.MountRequired)
{
yield return new Mount.UnmountTask();
}
}
else
{
NavInstruction.Move move2 = move;
ushort territory = move2.Territory;
Vector3 position = move2.Position;
bool? mount = move2.Mount;
float? stopDistance = move2.StopDistance;
ushort territory4 = move2.Territory;
Vector3 position3 = move2.Position;
bool? mount2 = move2.Mount;
float? stopDistance2 = move2.StopDistance;
uint? dataId = move2.DataId;
bool disableNavmesh = move2.DisableNavmesh;
bool fly2 = move2.Fly;
bool landAtTarget = move2.LandAtTarget;
bool flag = move2.Fly;
bool flag2 = move2.LandAtTarget;
bool allowZoneTransition = move2.AllowZoneTransition;
string targetNodeId = move2.TargetNodeId;
string approachNodeId = move2.ApproachNodeId;
yield return new MoveTask(territory, position, mount, MountRequired: false, DismountRequired: false, stopDistance, dataId, disableNavmesh, null, fly2, landAtTarget, IgnoreDistanceToObject: false, RestartNavigation: true, EInteractionType.None, SmartNavRouted: true, allowZoneTransition, targetNodeId, approachNodeId);
string approachNodeId = move2.TargetNodeId;
string targetNodeId = move2.ApproachNodeId;
yield return new MoveTask(territory4, position3, mount2, MountRequired: false, DismountRequired: false, stopDistance2, dataId, disableNavmesh, null, flag, flag2, IgnoreDistanceToObject: false, RestartNavigation: true, EInteractionType.None, SmartNavRouted: true, allowZoneTransition, approachNodeId, targetNodeId);
}
}
else
@ -147,4 +230,50 @@ internal sealed class SmartNavTaskMapper(IClientState clientState, TerritoryData
yield return new AetheryteTeleport.MoveAwayFromAetheryte(teleport.Target);
}
}
private static MoveTask ApplyTravelMode(MoveTask task, ETravelMode travelMode)
{
if (travelMode == ETravelMode.Auto)
{
return task;
}
if (task.MountRequired)
{
return task with
{
Mount = true,
Fly = (travelMode == ETravelMode.Flying && task.Fly),
Land = (travelMode == ETravelMode.Flying && task.Land)
};
}
if (task.DismountRequired)
{
return task with
{
Mount = false,
Fly = false,
Land = false
};
}
return travelMode switch
{
ETravelMode.OnFoot => task with
{
Mount = false,
Fly = false,
Land = false
},
ETravelMode.GroundMount => task with
{
Mount = true,
Fly = false,
Land = false
},
ETravelMode.Flying => task with
{
Mount = true
},
_ => task,
};
}
}