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

pull/5/head v0.18
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,
"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,
"Position": {

View File

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

View File

@ -148,29 +148,47 @@ internal sealed unsafe class GameFunctions
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();
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:
continue;
case 1: // normal quest
currentQuest = questManager->NormalQuestsSpan[tracked.Index].QuestId;
currentQuest = questManager->NormalQuestsSpan[trackedQuest.Index].QuestId;
break;
}
if (_questRegistry.IsKnownQuest(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();
if (scenarioTree == null)
return default;
@ -178,10 +196,14 @@ internal sealed unsafe class GameFunctions
if (scenarioTree->Data == null)
return default;
currentQuest = scenarioTree->Data->CurrentScenarioQuest;
ushort currentQuest = scenarioTree->Data->CurrentScenarioQuest;
if (currentQuest == 0)
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));
}

View File

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