forked from liza/Questionable
Indicate navmesh build % in UI
This commit is contained in:
parent
59793d19dc
commit
c7f4865201
@ -302,6 +302,7 @@
|
|||||||
"WakingSandsSolar",
|
"WakingSandsSolar",
|
||||||
"RisingStonesSolar",
|
"RisingStonesSolar",
|
||||||
"RoguesGuild",
|
"RoguesGuild",
|
||||||
|
"NotRoguesGuild",
|
||||||
"DockStorehouse"
|
"DockStorehouse"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ public sealed class SkipConditionConverter() : EnumConverter<EExtraSkipCondition
|
|||||||
{ EExtraSkipCondition.WakingSandsSolar, "WakingSandsSolar" },
|
{ EExtraSkipCondition.WakingSandsSolar, "WakingSandsSolar" },
|
||||||
{ EExtraSkipCondition.RisingStonesSolar, "RisingStonesSolar"},
|
{ EExtraSkipCondition.RisingStonesSolar, "RisingStonesSolar"},
|
||||||
{ EExtraSkipCondition.RoguesGuild, "RoguesGuild"},
|
{ EExtraSkipCondition.RoguesGuild, "RoguesGuild"},
|
||||||
|
{ EExtraSkipCondition.NotRoguesGuild, "NotRoguesGuild"},
|
||||||
{ EExtraSkipCondition.DockStorehouse, "DockStorehouse"},
|
{ EExtraSkipCondition.DockStorehouse, "DockStorehouse"},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ public enum EExtraSkipCondition
|
|||||||
/// Location for ROG quests in Limsa Lominsa; located far underneath the actual lower decks.
|
/// Location for ROG quests in Limsa Lominsa; located far underneath the actual lower decks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
RoguesGuild,
|
RoguesGuild,
|
||||||
|
NotRoguesGuild,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Location for NIN quests in Eastern La Noscea; located far underneath the actual zone.
|
/// Location for NIN quests in Eastern La Noscea; located far underneath the actual zone.
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=tertium/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=tertium/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=tural/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=tural/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=urqopacha/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=urqopacha/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=vnavmesh/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=wachumeqimeqi/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=wachumeqimeqi/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=wachunpelo/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=wachunpelo/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=wolekdorf/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=wolekdorf/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
@ -89,6 +89,7 @@ internal sealed class MovementController : IDisposable
|
|||||||
public bool IsPathfinding => _pathfindTask is { IsCompleted: false };
|
public bool IsPathfinding => _pathfindTask is { IsCompleted: false };
|
||||||
public DestinationData? Destination { get; set; }
|
public DestinationData? Destination { get; set; }
|
||||||
public DateTime MovementStartedAt { get; private set; } = DateTime.Now;
|
public DateTime MovementStartedAt { get; private set; } = DateTime.Now;
|
||||||
|
public int BuiltNavmeshPercent => _navmeshIpc.GetBuildProgress();
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
|
@ -687,6 +687,17 @@ internal sealed class QuestController : MiniTaskController<QuestController>
|
|||||||
public bool IsRunning => !_taskQueue.AllTasksComplete;
|
public bool IsRunning => !_taskQueue.AllTasksComplete;
|
||||||
public TaskQueue TaskQueue => _taskQueue;
|
public TaskQueue TaskQueue => _taskQueue;
|
||||||
|
|
||||||
|
public string? CurrentTaskState
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_taskQueue.CurrentTaskExecutor is IDebugStateProvider debugStateProvider)
|
||||||
|
return debugStateProvider.GetDebugState();
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class QuestProgress
|
public sealed class QuestProgress
|
||||||
{
|
{
|
||||||
public Quest Quest { get; }
|
public Quest Quest { get; }
|
||||||
|
27
Questionable/Controller/Steps/Common/WaitNavmesh.cs
Normal file
27
Questionable/Controller/Steps/Common/WaitNavmesh.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
namespace Questionable.Controller.Steps.Common;
|
||||||
|
|
||||||
|
internal sealed class WaitNavmesh
|
||||||
|
{
|
||||||
|
internal sealed record Task : ITask
|
||||||
|
{
|
||||||
|
public override string ToString() => "Wait(navmesh)";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class Executor(MovementController movementController) : TaskExecutor<Task>, IDebugStateProvider
|
||||||
|
{
|
||||||
|
protected override bool Start() => true;
|
||||||
|
|
||||||
|
public override ETaskResult Update() =>
|
||||||
|
movementController.IsNavmeshReady ? ETaskResult.TaskComplete : ETaskResult.StillRunning;
|
||||||
|
|
||||||
|
public override bool ShouldInterruptOnDamage() => false;
|
||||||
|
|
||||||
|
public string? GetDebugState()
|
||||||
|
{
|
||||||
|
if (!movementController.IsNavmeshReady)
|
||||||
|
return $"Navmesh: {movementController.BuiltNavmeshPercent}%";
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -96,7 +96,9 @@ internal static class SinglePlayerDuty
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class WaitSinglePlayerDutyExecutor(
|
internal sealed class WaitSinglePlayerDutyExecutor(
|
||||||
BossModIpc bossModIpc) : TaskExecutor<WaitSinglePlayerDuty>, IStoppableTaskExecutor
|
BossModIpc bossModIpc,
|
||||||
|
MovementController movementController)
|
||||||
|
: TaskExecutor<WaitSinglePlayerDuty>, IStoppableTaskExecutor, IDebugStateProvider
|
||||||
{
|
{
|
||||||
protected override bool Start() => true;
|
protected override bool Start() => true;
|
||||||
|
|
||||||
@ -110,6 +112,14 @@ internal static class SinglePlayerDuty
|
|||||||
public void StopNow() => bossModIpc.DisableAi();
|
public void StopNow() => bossModIpc.DisableAi();
|
||||||
|
|
||||||
public override bool ShouldInterruptOnDamage() => false;
|
public override bool ShouldInterruptOnDamage() => false;
|
||||||
|
|
||||||
|
public string? GetDebugState()
|
||||||
|
{
|
||||||
|
if (!movementController.IsNavmeshReady)
|
||||||
|
return $"Navmesh: {movementController.BuiltNavmeshPercent}%";
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed record DisableAi : ITask
|
internal sealed record DisableAi : ITask
|
||||||
|
@ -20,7 +20,6 @@ namespace Questionable.Controller.Steps.Shared;
|
|||||||
internal static class AethernetShortcut
|
internal static class AethernetShortcut
|
||||||
{
|
{
|
||||||
internal sealed class Factory(
|
internal sealed class Factory(
|
||||||
MovementController movementController,
|
|
||||||
AetheryteData aetheryteData,
|
AetheryteData aetheryteData,
|
||||||
TerritoryData territoryData,
|
TerritoryData territoryData,
|
||||||
IClientState clientState)
|
IClientState clientState)
|
||||||
@ -31,8 +30,7 @@ internal static class AethernetShortcut
|
|||||||
if (step.AethernetShortcut == null)
|
if (step.AethernetShortcut == null)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
yield return new WaitCondition.Task(() => movementController.IsNavmeshReady,
|
yield return new WaitNavmesh.Task();
|
||||||
"Wait(navmesh ready)");
|
|
||||||
yield return new Task(step.AethernetShortcut.From, step.AethernetShortcut.To,
|
yield return new Task(step.AethernetShortcut.From, step.AethernetShortcut.To,
|
||||||
step.SkipConditions?.AethernetShortcutIf ?? new());
|
step.SkipConditions?.AethernetShortcutIf ?? new());
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ internal static class Gather
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class DelayedGatheringExecutor(
|
internal sealed class DelayedGatheringExecutor(
|
||||||
MovementController movementController,
|
|
||||||
GatheringData gatheringData,
|
GatheringData gatheringData,
|
||||||
GatheringPointRegistry gatheringPointRegistry,
|
GatheringPointRegistry gatheringPointRegistry,
|
||||||
TerritoryData territoryData,
|
TerritoryData territoryData,
|
||||||
@ -85,8 +84,7 @@ internal static class Gather
|
|||||||
yield return new WaitCondition.Task(() => clientState.TerritoryType == territoryId,
|
yield return new WaitCondition.Task(() => clientState.TerritoryType == territoryId,
|
||||||
$"Wait(territory: {territoryData.GetNameAndId(territoryId)})");
|
$"Wait(territory: {territoryData.GetNameAndId(territoryId)})");
|
||||||
|
|
||||||
yield return new WaitCondition.Task(() => movementController.IsNavmeshReady,
|
yield return new WaitNavmesh.Task();
|
||||||
"Wait(navmesh ready)");
|
|
||||||
|
|
||||||
yield return new GatheringTask(gatheringPointId, Task.GatheredItem);
|
yield return new GatheringTask(gatheringPointId, Task.GatheredItem);
|
||||||
yield return new WaitAtEnd.WaitDelay();
|
yield return new WaitAtEnd.WaitDelay();
|
||||||
|
@ -25,7 +25,6 @@ namespace Questionable.Controller.Steps.Shared;
|
|||||||
internal static class MoveTo
|
internal static class MoveTo
|
||||||
{
|
{
|
||||||
internal sealed class Factory(
|
internal sealed class Factory(
|
||||||
MovementController movementController,
|
|
||||||
IClientState clientState,
|
IClientState clientState,
|
||||||
AetheryteData aetheryteData,
|
AetheryteData aetheryteData,
|
||||||
TerritoryData territoryData,
|
TerritoryData territoryData,
|
||||||
@ -67,10 +66,7 @@ internal static class MoveTo
|
|||||||
$"Wait(territory: {territoryData.GetNameAndId(step.TerritoryId)})");
|
$"Wait(territory: {territoryData.GetNameAndId(step.TerritoryId)})");
|
||||||
|
|
||||||
if (!step.DisableNavmesh)
|
if (!step.DisableNavmesh)
|
||||||
{
|
yield return new WaitNavmesh.Task();
|
||||||
yield return new WaitCondition.Task(() => movementController.IsNavmeshReady,
|
|
||||||
"Wait(navmesh ready)");
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return new MoveTask(step, destination);
|
yield return new MoveTask(step, destination);
|
||||||
|
|
||||||
|
@ -310,6 +310,7 @@ internal static class SkipCondition
|
|||||||
EExtraSkipCondition.WakingSandsSolar => territoryType == 212 && position.X >= 24,
|
EExtraSkipCondition.WakingSandsSolar => territoryType == 212 && position.X >= 24,
|
||||||
EExtraSkipCondition.RisingStonesSolar => territoryType == 351 && position.Z <= -28,
|
EExtraSkipCondition.RisingStonesSolar => territoryType == 351 && position.Z <= -28,
|
||||||
EExtraSkipCondition.RoguesGuild => territoryType == 129 && position.Y <= -115,
|
EExtraSkipCondition.RoguesGuild => territoryType == 129 && position.Y <= -115,
|
||||||
|
EExtraSkipCondition.NotRoguesGuild => territoryType == 129 && position.Y > -115,
|
||||||
EExtraSkipCondition.DockStorehouse => territoryType == 137 && position.Y <= -20,
|
EExtraSkipCondition.DockStorehouse => territoryType == 137 && position.Y <= -20,
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(condition), condition, null)
|
_ => throw new ArgumentOutOfRangeException(nameof(condition), condition, null)
|
||||||
};
|
};
|
||||||
|
@ -30,6 +30,11 @@ internal interface IStoppableTaskExecutor : ITaskExecutor
|
|||||||
void StopNow();
|
void StopNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal interface IDebugStateProvider : ITaskExecutor
|
||||||
|
{
|
||||||
|
string? GetDebugState();
|
||||||
|
}
|
||||||
|
|
||||||
internal abstract class TaskExecutor<T> : ITaskExecutor
|
internal abstract class TaskExecutor<T> : ITaskExecutor
|
||||||
where T : class, ITask
|
where T : class, ITask
|
||||||
{
|
{
|
||||||
|
17
Questionable/External/NavmeshIpc.cs
vendored
17
Questionable/External/NavmeshIpc.cs
vendored
@ -20,6 +20,7 @@ internal sealed class NavmeshIpc
|
|||||||
private readonly ICallGateSubscriber<List<Vector3>> _pathListWaypoints;
|
private readonly ICallGateSubscriber<List<Vector3>> _pathListWaypoints;
|
||||||
private readonly ICallGateSubscriber<float, object> _pathSetTolerance;
|
private readonly ICallGateSubscriber<float, object> _pathSetTolerance;
|
||||||
private readonly ICallGateSubscriber<Vector3, bool, float, Vector3?> _queryPointOnFloor;
|
private readonly ICallGateSubscriber<Vector3, bool, float, Vector3?> _queryPointOnFloor;
|
||||||
|
private readonly ICallGateSubscriber<float> _buildProgress;
|
||||||
|
|
||||||
public NavmeshIpc(IDalamudPluginInterface pluginInterface, ILogger<NavmeshIpc> logger)
|
public NavmeshIpc(IDalamudPluginInterface pluginInterface, ILogger<NavmeshIpc> logger)
|
||||||
{
|
{
|
||||||
@ -35,6 +36,7 @@ internal sealed class NavmeshIpc
|
|||||||
_pathSetTolerance = pluginInterface.GetIpcSubscriber<float, object>("vnavmesh.Path.SetTolerance");
|
_pathSetTolerance = pluginInterface.GetIpcSubscriber<float, object>("vnavmesh.Path.SetTolerance");
|
||||||
_queryPointOnFloor =
|
_queryPointOnFloor =
|
||||||
pluginInterface.GetIpcSubscriber<Vector3, bool, float, Vector3?>("vnavmesh.Query.Mesh.PointOnFloor");
|
pluginInterface.GetIpcSubscriber<Vector3, bool, float, Vector3?>("vnavmesh.Query.Mesh.PointOnFloor");
|
||||||
|
_buildProgress = pluginInterface.GetIpcSubscriber<float>("vnavmesh.Nav.BuildProgress");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsReady
|
public bool IsReady
|
||||||
@ -136,4 +138,19 @@ internal sealed class NavmeshIpc
|
|||||||
else
|
else
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetBuildProgress()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
float progress = _buildProgress.InvokeFunc();
|
||||||
|
if (progress < 0)
|
||||||
|
return 100;
|
||||||
|
return (int)(progress * 100);
|
||||||
|
}
|
||||||
|
catch (IpcError)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,6 +235,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
serviceCollection.AddTaskExecutor<SinglePlayerDuty.SetTarget, SinglePlayerDuty.SetTargetExecutor>();
|
serviceCollection.AddTaskExecutor<SinglePlayerDuty.SetTarget, SinglePlayerDuty.SetTargetExecutor>();
|
||||||
|
|
||||||
serviceCollection.AddTaskExecutor<WaitCondition.Task, WaitCondition.WaitConditionExecutor>();
|
serviceCollection.AddTaskExecutor<WaitCondition.Task, WaitCondition.WaitConditionExecutor>();
|
||||||
|
serviceCollection.AddTaskExecutor<WaitNavmesh.Task, WaitNavmesh.Executor>();
|
||||||
serviceCollection.AddTaskFactory<WaitAtEnd.Factory>();
|
serviceCollection.AddTaskFactory<WaitAtEnd.Factory>();
|
||||||
serviceCollection.AddTaskExecutor<WaitAtEnd.WaitDelay, WaitAtEnd.WaitDelayExecutor>();
|
serviceCollection.AddTaskExecutor<WaitAtEnd.WaitDelay, WaitAtEnd.WaitDelayExecutor>();
|
||||||
serviceCollection.AddTaskExecutor<WaitAtEnd.WaitNextStepOrSequence, WaitAtEnd.WaitNextStepOrSequenceExecutor>();
|
serviceCollection.AddTaskExecutor<WaitAtEnd.WaitNextStepOrSequence, WaitAtEnd.WaitNextStepOrSequenceExecutor>();
|
||||||
|
@ -73,25 +73,34 @@ internal sealed partial class ActiveQuestComponent
|
|||||||
|
|
||||||
if (_combatController.IsRunning)
|
if (_combatController.IsRunning)
|
||||||
ImGui.TextColored(ImGuiColors.DalamudOrange, "In Combat");
|
ImGui.TextColored(ImGuiColors.DalamudOrange, "In Combat");
|
||||||
|
else if (_questController.CurrentTaskState is { } currentTaskState)
|
||||||
|
{
|
||||||
|
using var _ = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudOrange);
|
||||||
|
ImGui.TextUnformatted(currentTaskState);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImGui.BeginDisabled();
|
using var _ = ImRaii.Disabled();
|
||||||
ImGui.TextUnformatted(_questController.DebugState ?? string.Empty);
|
ImGui.TextUnformatted(_questController.DebugState ?? string.Empty);
|
||||||
ImGui.EndDisabled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestSequence? currentSequence = currentQuest.Quest.FindSequence(currentQuest.Sequence);
|
QuestSequence? currentSequence = currentQuest.Quest.FindSequence(currentQuest.Sequence);
|
||||||
QuestStep? currentStep = currentSequence?.FindStep(currentQuest.Step);
|
QuestStep? currentStep = currentSequence?.FindStep(currentQuest.Step);
|
||||||
if (!isMinimized)
|
if (!isMinimized)
|
||||||
{
|
{
|
||||||
bool colored = currentStep is
|
using (var color = new ImRaii.Color())
|
||||||
{ InteractionType: EInteractionType.Instruction or EInteractionType.WaitForManualProgress or EInteractionType.Snipe };
|
{
|
||||||
if (colored)
|
bool colored = currentStep is
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudOrange);
|
{
|
||||||
ImGui.TextUnformatted(currentStep?.Comment ??
|
InteractionType: EInteractionType.Instruction or EInteractionType.WaitForManualProgress
|
||||||
currentSequence?.Comment ?? currentQuest.Quest.Root.Comment ?? string.Empty);
|
or EInteractionType.Snipe
|
||||||
if (colored)
|
};
|
||||||
ImGui.PopStyleColor();
|
if (colored)
|
||||||
|
color.Push(ImGuiCol.Text, ImGuiColors.DalamudOrange);
|
||||||
|
|
||||||
|
ImGui.TextUnformatted(currentStep?.Comment ??
|
||||||
|
currentSequence?.Comment ?? currentQuest.Quest.Root.Comment ?? string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
//var nextStep = _questController.GetNextStep();
|
//var nextStep = _questController.GetNextStep();
|
||||||
//ImGui.BeginDisabled(nextStep.Step == null);
|
//ImGui.BeginDisabled(nextStep.Step == null);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user