Add experimental navmesh path replay (mostly for finding stuck places)
This commit is contained in:
parent
069833a8f8
commit
0bd15c03f5
@ -263,6 +263,16 @@
|
|||||||
{
|
{
|
||||||
"Sequence": 5,
|
"Sequence": 5,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": -136.90475,
|
||||||
|
"Y": -215.01514,
|
||||||
|
"Z": 330.17505
|
||||||
|
},
|
||||||
|
"TerritoryId": 1189,
|
||||||
|
"InteractionType": "WalkTo",
|
||||||
|
"Mount": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1047669,
|
"DataId": 1047669,
|
||||||
"Position": {
|
"Position": {
|
||||||
|
@ -53,6 +53,7 @@ internal sealed class QuestController
|
|||||||
|
|
||||||
|
|
||||||
public QuestProgress? CurrentQuest { get; set; }
|
public QuestProgress? CurrentQuest { get; set; }
|
||||||
|
public SimulationProgress? SimulatedQuest { get; set; }
|
||||||
public string? DebugState { get; private set; }
|
public string? DebugState { get; private set; }
|
||||||
public string? Comment { get; private set; }
|
public string? Comment { get; private set; }
|
||||||
|
|
||||||
@ -110,7 +111,16 @@ internal sealed class QuestController
|
|||||||
{
|
{
|
||||||
DebugState = null;
|
DebugState = null;
|
||||||
|
|
||||||
(ushort currentQuestId, byte currentSequence) = _gameFunctions.GetCurrentQuest();
|
ushort currentQuestId;
|
||||||
|
byte currentSequence;
|
||||||
|
if (SimulatedQuest != null)
|
||||||
|
{
|
||||||
|
currentQuestId = SimulatedQuest.Quest.QuestId;
|
||||||
|
currentSequence = SimulatedQuest.Sequence;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
(currentQuestId, currentSequence) = _gameFunctions.GetCurrentQuest();
|
||||||
|
|
||||||
if (currentQuestId == 0)
|
if (currentQuestId == 0)
|
||||||
{
|
{
|
||||||
if (CurrentQuest != null)
|
if (CurrentQuest != null)
|
||||||
@ -302,6 +312,14 @@ internal sealed class QuestController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SimulateQuest(Quest? quest)
|
||||||
|
{
|
||||||
|
if (quest != null)
|
||||||
|
SimulatedQuest = new SimulationProgress(quest, 0);
|
||||||
|
else
|
||||||
|
SimulatedQuest = null;
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateCurrentTask()
|
private void UpdateCurrentTask()
|
||||||
{
|
{
|
||||||
if (_gameFunctions.IsOccupied())
|
if (_gameFunctions.IsOccupied())
|
||||||
@ -464,6 +482,8 @@ internal sealed class QuestController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed record SimulationProgress(Quest Quest, byte Sequence);
|
||||||
|
|
||||||
public void Skip(ushort questQuestId, byte currentQuestSequence)
|
public void Skip(ushort questQuestId, byte currentQuestSequence)
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
|
@ -6,6 +6,7 @@ using Dalamud.Plugin.Services;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Questionable.Controller;
|
using Questionable.Controller;
|
||||||
using Questionable.Data;
|
using Questionable.Data;
|
||||||
|
using Questionable.Model;
|
||||||
using Questionable.Windows;
|
using Questionable.Windows;
|
||||||
|
|
||||||
namespace Questionable;
|
namespace Questionable;
|
||||||
@ -18,15 +19,18 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
private readonly QuestController _questController;
|
private readonly QuestController _questController;
|
||||||
private readonly MovementController _movementController;
|
private readonly MovementController _movementController;
|
||||||
private readonly NavigationShortcutController _navigationShortcutController;
|
private readonly NavigationShortcutController _navigationShortcutController;
|
||||||
|
private readonly IChatGui _chatGui;
|
||||||
private readonly WindowSystem _windowSystem;
|
private readonly WindowSystem _windowSystem;
|
||||||
private readonly QuestWindow _questWindow;
|
private readonly QuestWindow _questWindow;
|
||||||
private readonly ConfigWindow _configWindow;
|
|
||||||
private readonly DebugOverlay _debugOverlay;
|
private readonly DebugOverlay _debugOverlay;
|
||||||
|
private readonly ConfigWindow _configWindow;
|
||||||
|
private readonly QuestRegistry _questRegistry;
|
||||||
|
|
||||||
public DalamudInitializer(IDalamudPluginInterface pluginInterface, IFramework framework,
|
public DalamudInitializer(IDalamudPluginInterface pluginInterface, IFramework framework,
|
||||||
ICommandManager commandManager, QuestController questController, MovementController movementController,
|
ICommandManager commandManager, QuestController questController, MovementController movementController,
|
||||||
GameUiController gameUiController, NavigationShortcutController navigationShortcutController,
|
GameUiController gameUiController, NavigationShortcutController navigationShortcutController, IChatGui chatGui,
|
||||||
WindowSystem windowSystem, QuestWindow questWindow, DebugOverlay debugOverlay, ConfigWindow configWindow)
|
WindowSystem windowSystem, QuestWindow questWindow, DebugOverlay debugOverlay, ConfigWindow configWindow,
|
||||||
|
QuestRegistry questRegistry)
|
||||||
{
|
{
|
||||||
_pluginInterface = pluginInterface;
|
_pluginInterface = pluginInterface;
|
||||||
_framework = framework;
|
_framework = framework;
|
||||||
@ -34,10 +38,12 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
_questController = questController;
|
_questController = questController;
|
||||||
_movementController = movementController;
|
_movementController = movementController;
|
||||||
_navigationShortcutController = navigationShortcutController;
|
_navigationShortcutController = navigationShortcutController;
|
||||||
|
_chatGui = chatGui;
|
||||||
_windowSystem = windowSystem;
|
_windowSystem = windowSystem;
|
||||||
_questWindow = questWindow;
|
_questWindow = questWindow;
|
||||||
_configWindow = configWindow;
|
|
||||||
_debugOverlay = debugOverlay;
|
_debugOverlay = debugOverlay;
|
||||||
|
_configWindow = configWindow;
|
||||||
|
_questRegistry = questRegistry;
|
||||||
|
|
||||||
_windowSystem.AddWindow(questWindow);
|
_windowSystem.AddWindow(questWindow);
|
||||||
_windowSystem.AddWindow(configWindow);
|
_windowSystem.AddWindow(configWindow);
|
||||||
@ -83,10 +89,46 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
}
|
}
|
||||||
else if (arguments.StartsWith("do", StringComparison.Ordinal))
|
else if (arguments.StartsWith("do", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
|
if (!_debugOverlay.DrawConditions())
|
||||||
|
{
|
||||||
|
_chatGui.PrintError("[Questionable] You don't have the debug overlay enabled.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (arguments.Length >= 4 && ushort.TryParse(arguments.AsSpan(3), out ushort questId))
|
if (arguments.Length >= 4 && ushort.TryParse(arguments.AsSpan(3), out ushort questId))
|
||||||
_debugOverlay.HighlightedQuest = questId;
|
{
|
||||||
|
if (_questRegistry.IsKnownQuest(questId))
|
||||||
|
{
|
||||||
|
_debugOverlay.HighlightedQuest = questId;
|
||||||
|
_chatGui.Print($"[Questionable] Set highlighted quest to {questId}.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_chatGui.PrintError($"[Questionable] Unknown quest {questId}.");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
_debugOverlay.HighlightedQuest = null;
|
_debugOverlay.HighlightedQuest = null;
|
||||||
|
_chatGui.Print("[Questionable] Cleared highlighted quest.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arguments.StartsWith("sim", StringComparison.InvariantCulture))
|
||||||
|
{
|
||||||
|
string[] parts = arguments.Split(' ');
|
||||||
|
if (parts.Length == 2 && ushort.TryParse(parts[1], out ushort questId))
|
||||||
|
{
|
||||||
|
if (_questRegistry.TryGetQuest(questId, out Quest? quest))
|
||||||
|
{
|
||||||
|
_questController.SimulateQuest(quest);
|
||||||
|
_chatGui.Print($"[Questionable] Simulating quest {questId}.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_chatGui.PrintError($"[Questionable] Unknown quest {questId}.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_questController.SimulateQuest(null);
|
||||||
|
_chatGui.Print("[Questionable] Cleared simulated quest.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (string.IsNullOrEmpty(arguments))
|
else if (string.IsNullOrEmpty(arguments))
|
||||||
_questWindow.Toggle();
|
_questWindow.Toggle();
|
||||||
|
@ -8,6 +8,7 @@ using Dalamud.Game.Text;
|
|||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
@ -202,6 +203,101 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
|
|||||||
_configuration.General.AutoAcceptNextQuest = autoAcceptNextQuest;
|
_configuration.General.AutoAcceptNextQuest = autoAcceptNextQuest;
|
||||||
_pluginInterface.SavePluginConfig(_configuration);
|
_pluginInterface.SavePluginConfig(_configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (_questController.SimulatedQuest != null)
|
||||||
|
{
|
||||||
|
ImGui.Separator();
|
||||||
|
ImGui.TextColored(ImGuiColors.DalamudRed, "Quest sim active (experimental)");
|
||||||
|
ImGui.Text($"Sequence: {_questController.SimulatedQuest.Sequence}");
|
||||||
|
|
||||||
|
ImGui.BeginDisabled(_questController.SimulatedQuest.Sequence == 0);
|
||||||
|
if (ImGuiComponents.IconButton(FontAwesomeIcon.Minus))
|
||||||
|
{
|
||||||
|
_movementController.Stop();
|
||||||
|
_questController.Stop("Sim-");
|
||||||
|
|
||||||
|
byte oldSequence = _questController.SimulatedQuest.Sequence;
|
||||||
|
byte newSequence = _questController.SimulatedQuest.Quest.Data.QuestSequence
|
||||||
|
.Select(x => (byte)x.Sequence)
|
||||||
|
.LastOrDefault(x => x < oldSequence, byte.MinValue);
|
||||||
|
|
||||||
|
_questController.SimulatedQuest = _questController.SimulatedQuest with
|
||||||
|
{
|
||||||
|
Sequence = newSequence,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndDisabled();
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.BeginDisabled(_questController.SimulatedQuest.Sequence >= 255);
|
||||||
|
if (ImGuiComponents.IconButton(FontAwesomeIcon.Plus))
|
||||||
|
{
|
||||||
|
_movementController.Stop();
|
||||||
|
_questController.Stop("Sim+");
|
||||||
|
|
||||||
|
byte oldSequence = _questController.SimulatedQuest.Sequence;
|
||||||
|
byte newSequence = _questController.SimulatedQuest.Quest.Data.QuestSequence
|
||||||
|
.Select(x => (byte)x.Sequence)
|
||||||
|
.FirstOrDefault(x => x > oldSequence, byte.MaxValue);
|
||||||
|
|
||||||
|
_questController.SimulatedQuest = _questController.SimulatedQuest with
|
||||||
|
{
|
||||||
|
Sequence = newSequence,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndDisabled();
|
||||||
|
|
||||||
|
var simulatedSequence =
|
||||||
|
_questController.SimulatedQuest.Quest.FindSequence(_questController.SimulatedQuest.Sequence);
|
||||||
|
if (simulatedSequence != null)
|
||||||
|
{
|
||||||
|
using var _ = ImRaii.PushId("SimulatedStep");
|
||||||
|
|
||||||
|
ImGui.Text($"Step: {currentQuest.Step} / {simulatedSequence.Steps.Count - 1}");
|
||||||
|
|
||||||
|
ImGui.BeginDisabled(currentQuest.Step == 0);
|
||||||
|
if (ImGuiComponents.IconButton(FontAwesomeIcon.Minus))
|
||||||
|
{
|
||||||
|
_movementController.Stop();
|
||||||
|
_questController.Stop("SimStep-");
|
||||||
|
|
||||||
|
_questController.CurrentQuest = currentQuest with
|
||||||
|
{
|
||||||
|
Step = Math.Min(currentQuest.Step - 1, simulatedSequence.Steps.Count - 1),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndDisabled();
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.BeginDisabled(currentQuest.Step >= simulatedSequence.Steps.Count);
|
||||||
|
if (ImGuiComponents.IconButton(FontAwesomeIcon.Plus))
|
||||||
|
{
|
||||||
|
_movementController.Stop();
|
||||||
|
_questController.Stop("SimStep+");
|
||||||
|
|
||||||
|
_questController.CurrentQuest = currentQuest with
|
||||||
|
{
|
||||||
|
Step = currentQuest.Step == simulatedSequence.Steps.Count - 1
|
||||||
|
? 255
|
||||||
|
: (currentQuest.Step + 1),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndDisabled();
|
||||||
|
|
||||||
|
if (ImGui.Button("Clear sim"))
|
||||||
|
{
|
||||||
|
_questController.SimulateQuest(null);
|
||||||
|
|
||||||
|
_movementController.Stop();
|
||||||
|
_questController.Stop("ClearSim");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ImGui.Text("No active quest");
|
ImGui.Text("No active quest");
|
||||||
|
Loading…
Reference in New Issue
Block a user