Improve logic for detecting side-quests based off of the quest/to-do list

This commit is contained in:
Liza 2024-06-19 00:17:51 +02:00
parent 9ad280008b
commit 2003906bb2
Signed by: liza
GPG Key ID: 7199F8D727D55F67
4 changed files with 58 additions and 13 deletions

View File

@ -51,6 +51,25 @@
{ {
"Sequence": 3, "Sequence": 3,
"Steps": [ "Steps": [
{
"Position": {
"X": 81.33277,
"Y": 1.8631814,
"Z": -96.56102
},
"TerritoryId": 963,
"InteractionType": "WalkTo",
"DisableNavmesh": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
-128
],
"Sprint": true
},
{ {
"DataId": 1037314, "DataId": 1037314,
"Position": { "Position": {

View File

@ -99,8 +99,7 @@
"TerritoryId": 957, "TerritoryId": 957,
"InteractionType": "WalkTo", "InteractionType": "WalkTo",
"DisableNavmesh": true, "DisableNavmesh": true,
"Mount": true, "Mount": true
"Comment": "FIXME Returning to the surface means navmesh won't move anymore, but the path is still 'running'"
}, },
{ {
"Position": { "Position": {

View File

@ -148,29 +148,47 @@ internal sealed unsafe class GameFunctions
public (ushort CurrentQuest, byte Sequence) GetCurrentQuestInternal() public (ushort CurrentQuest, byte Sequence) GetCurrentQuestInternal()
{ {
ushort currentQuest;
// if any quest that is currently tracked (i.e. in the to-do list) exists as mapped quest, we use that
var questManager = QuestManager.Instance(); var questManager = QuestManager.Instance();
if (questManager != null) if (questManager != null)
{ {
foreach (var tracked in questManager->TrackedQuestsSpan) // always prioritize accepting MSQ quests, to make sure we don't turn in one MSQ quest and then go off to do
// side quests until the end of time.
var msqQuest = GetMainStoryQuest(questManager);
if (msqQuest.CurrentQuest != 0 && !questManager->IsQuestAccepted(msqQuest.CurrentQuest))
return msqQuest;
// Use the quests in the same order as they're shown in the to-do list, e.g. if the MSQ is the first item,
// do the MSQ; if a side quest is the first item do that side quest.
//
// If no quests are marked as 'priority', accepting a new quest adds it to the top of the list.
for (int i = questManager->TrackedQuestsSpan.Length - 1; i >= 0; --i)
{ {
switch (tracked.QuestType) ushort currentQuest;
var trackedQuest = questManager->TrackedQuestsSpan[i];
switch (trackedQuest.QuestType)
{ {
default: default:
continue; continue;
case 1: // normal quest case 1: // normal quest
currentQuest = questManager->NormalQuestsSpan[tracked.Index].QuestId; currentQuest = questManager->NormalQuestsSpan[trackedQuest.Index].QuestId;
break; break;
} }
if (_questRegistry.IsKnownQuest(currentQuest)) if (_questRegistry.IsKnownQuest(currentQuest))
return (currentQuest, QuestManager.GetQuestSequence(currentQuest)); return (currentQuest, QuestManager.GetQuestSequence(currentQuest));
} }
// if we know no quest of those currently in the to-do list, just do MSQ
return msqQuest;
} }
return default;
}
// TODO This doesn't work with unaccepted quests in NG+, only accepted quests
private (ushort CurrentQuest, byte Sequence) GetMainStoryQuest(QuestManager* questManager)
{
var scenarioTree = AgentScenarioTree.Instance(); var scenarioTree = AgentScenarioTree.Instance();
if (scenarioTree == null) if (scenarioTree == null)
return default; return default;
@ -178,10 +196,14 @@ internal sealed unsafe class GameFunctions
if (scenarioTree->Data == null) if (scenarioTree->Data == null)
return default; return default;
currentQuest = scenarioTree->Data->CurrentScenarioQuest; ushort currentQuest = scenarioTree->Data->CurrentScenarioQuest;
if (currentQuest == 0) if (currentQuest == 0)
return default; return default;
// if the MSQ is hidden, we generally ignore it
if (questManager->IsQuestAccepted(currentQuest) && questManager->GetQuestById(currentQuest)->IsHidden)
return default;
return (currentQuest, QuestManager.GetQuestSequence(currentQuest)); return (currentQuest, QuestManager.GetQuestSequence(currentQuest));
} }

View File

@ -36,6 +36,7 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
private readonly GameUiController _gameUiController; private readonly GameUiController _gameUiController;
private readonly Configuration _configuration; private readonly Configuration _configuration;
private readonly NavmeshIpc _navmeshIpc; private readonly NavmeshIpc _navmeshIpc;
private readonly QuestRegistry _questRegistry;
private readonly ILogger<QuestWindow> _logger; private readonly ILogger<QuestWindow> _logger;
public QuestWindow(DalamudPluginInterface pluginInterface, public QuestWindow(DalamudPluginInterface pluginInterface,
@ -48,6 +49,7 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
GameUiController gameUiController, GameUiController gameUiController,
Configuration configuration, Configuration configuration,
NavmeshIpc navmeshIpc, NavmeshIpc navmeshIpc,
QuestRegistry questRegistry,
ILogger<QuestWindow> logger) ILogger<QuestWindow> logger)
: base("Questionable###Questionable", ImGuiWindowFlags.AlwaysAutoResize) : base("Questionable###Questionable", ImGuiWindowFlags.AlwaysAutoResize)
{ {
@ -61,6 +63,7 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
_gameUiController = gameUiController; _gameUiController = gameUiController;
_configuration = configuration; _configuration = configuration;
_navmeshIpc = navmeshIpc; _navmeshIpc = navmeshIpc;
_questRegistry = questRegistry;
_logger = logger; _logger = logger;
#if DEBUG #if DEBUG
@ -206,11 +209,11 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
var q = _gameFunctions.GetCurrentQuest(); var q = _gameFunctions.GetCurrentQuest();
ImGui.Text($"Current Quest: {q.CurrentQuest} → {q.Sequence}"); ImGui.Text($"Current Quest: {q.CurrentQuest} → {q.Sequence}");
#if false
var questManager = QuestManager.Instance(); var questManager = QuestManager.Instance();
if (questManager != null) if (questManager != null)
{ {
// unsure how these are sorted for (int i = questManager->TrackedQuestsSpan.Length - 1; i >= 0; --i)
for (int i = 0; i < 1 /*questManager->TrackedQuestsSpan.Length*/; ++i)
{ {
var trackedQuest = questManager->TrackedQuestsSpan[i]; var trackedQuest = questManager->TrackedQuestsSpan[i];
switch (trackedQuest.QuestType) switch (trackedQuest.QuestType)
@ -220,13 +223,15 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
break; break;
case 1: case 1:
_questRegistry.TryGetQuest(questManager->NormalQuestsSpan[trackedQuest.Index].QuestId,
out var quest);
ImGui.Text( ImGui.Text(
$"Tracked quest: {questManager->NormalQuestsSpan[trackedQuest.Index].QuestId}, {trackedQuest.Index}"); $"Tracked quest: {questManager->NormalQuestsSpan[trackedQuest.Index].QuestId}, {trackedQuest.Index}: {quest?.Name}");
break; break;
} }
} }
} }
#endif
if (_targetManager.Target != null) if (_targetManager.Target != null)
{ {