150 lines
5.2 KiB
C#
150 lines
5.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using Dalamud.Plugin.Services;
|
|
using Questionable.Controller.Steps;
|
|
using Questionable.Controller.Steps.Common;
|
|
using Questionable.Controller.Steps.Movement;
|
|
using Questionable.Controller.Steps.Shared;
|
|
using Questionable.Data;
|
|
using Questionable.Model.Questing;
|
|
using SmartNav;
|
|
|
|
namespace Questionable.Navigation;
|
|
|
|
internal sealed class SmartNavTaskMapper(IClientState clientState, TerritoryData territoryData)
|
|
{
|
|
public IEnumerable<ITask> MapInstructions(IReadOnlyList<NavInstruction> instructions, QuestStep? step = null)
|
|
{
|
|
for (int i = 0; i < instructions.Count; i++)
|
|
{
|
|
foreach (ITask item in Map(instructions[i], NextTravelInstruction(instructions, i), step))
|
|
{
|
|
yield return item;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static NavInstruction? NextTravelInstruction(IReadOnlyList<NavInstruction> instructions, int i)
|
|
{
|
|
for (int j = i + 1; j < instructions.Count; j++)
|
|
{
|
|
NavInstruction navInstruction = instructions[j];
|
|
if ((!(navInstruction is NavInstruction.Land) && !(navInstruction is NavInstruction.Unmount) && !(navInstruction is NavInstruction.WaitForTerritory) && !(navInstruction is NavInstruction.WaitForNavmesh)) || 1 == 0)
|
|
{
|
|
return instructions[j];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private IEnumerable<ITask> Map(NavInstruction instruction, NavInstruction? nextTravel, QuestStep? step)
|
|
{
|
|
NavInstruction.Teleport teleport = instruction as NavInstruction.Teleport;
|
|
if ((object)teleport == null)
|
|
{
|
|
if (!(instruction is NavInstruction.AethernetHop aethernetHop))
|
|
{
|
|
if (!(instruction is NavInstruction.Move move))
|
|
{
|
|
if (!(instruction is NavInstruction.Land))
|
|
{
|
|
if (!(instruction is NavInstruction.Unmount))
|
|
{
|
|
NavInstruction.WaitForTerritory waitForTerritory = instruction as NavInstruction.WaitForTerritory;
|
|
if ((object)waitForTerritory == null)
|
|
{
|
|
if (!(instruction is NavInstruction.WaitForNavmesh))
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
yield return new WaitCondition.Task(() => waitForTerritory.Acceptable.Contains(clientState.TerritoryType), waitForTerritory.Description);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
yield return new Mount.UnmountTask();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
yield return new LandTask();
|
|
}
|
|
}
|
|
else if (move.IsFinal && step != null)
|
|
{
|
|
Vector3 destination = step.Position ?? move.Position;
|
|
yield return new MoveTask(step, destination)with
|
|
{
|
|
Fly = (move.Fly || step.Fly == true),
|
|
Land = (move.Fly || step.Land == true),
|
|
SmartNavRouted = true,
|
|
RouteTargetNodeId = move.TargetNodeId,
|
|
RouteApproachNodeId = move.ApproachNodeId
|
|
};
|
|
if (step != null)
|
|
{
|
|
bool? fly = step.Fly;
|
|
if (fly.HasValue && fly == true && (step.Land ?? false))
|
|
{
|
|
yield return new LandTask();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NavInstruction.Move move2 = move;
|
|
ushort territory = move2.Territory;
|
|
Vector3 position = move2.Position;
|
|
bool? mount = move2.Mount;
|
|
float? stopDistance = move2.StopDistance;
|
|
uint? dataId = move2.DataId;
|
|
bool disableNavmesh = move2.DisableNavmesh;
|
|
bool fly2 = move2.Fly;
|
|
bool landAtTarget = 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);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
yield return new AethernetRide.Task(aethernetHop.From, aethernetHop.To);
|
|
}
|
|
yield break;
|
|
}
|
|
yield return new AetheryteTeleport.Task(teleport.Target, teleport.ExpectedTerritory);
|
|
if (AetheryteTeleport.MoveAwayFromAetheryteExecutor.AppliesTo(teleport.Target) && (nextTravel as NavInstruction.AethernetHop)?.From != teleport.Target)
|
|
{
|
|
yield return new WaitCondition.Task(() => clientState.TerritoryType == teleport.ExpectedTerritory, "Wait(territory: " + territoryData.GetNameAndId(teleport.ExpectedTerritory) + ")");
|
|
yield return new AetheryteTeleport.MoveAwayFromAetheryte(teleport.Target);
|
|
}
|
|
}
|
|
}
|