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