1
0
forked from liza/Questionable

Update validation for instant quests

This commit is contained in:
Liza 2024-07-19 09:14:18 +02:00
parent 86e2c0f1ca
commit f0af3045a7
Signed by: liza
GPG Key ID: 7199F8D727D55F67
11 changed files with 98 additions and 37 deletions

View File

@ -13,8 +13,7 @@
"Z": -25.223206 "Z": -25.223206
}, },
"TerritoryId": 820, "TerritoryId": 820,
"InteractionType": "AcceptQuest", "InteractionType": "AcceptQuest"
"Comment": "Quest is completed instantly"
} }
] ]
} }

View File

@ -29,7 +29,7 @@
}, },
"TerritoryId": 1190, "TerritoryId": 1190,
"InteractionType": "Instruction", "InteractionType": "Instruction",
"Comment": "(from left to right) pump, middle of the connecting pipes, barrels" "Comment": "Click (from left to right) pump, middle of the connecting pipes, barrels"
} }
] ]
}, },

View File

@ -0,0 +1,21 @@
{
"$schema": "https://carvel.li/questionable/quest-1.0",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1048390,
"Position": {
"X": 15.243713,
"Y": -14.000001,
"Z": 85.83191
},
"TerritoryId": 1185,
"InteractionType": "AcceptQuest"
}
]
}
]
}

View File

@ -0,0 +1,21 @@
{
"$schema": "https://carvel.li/questionable/quest-1.0",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1048510,
"Position": {
"X": 28.67163,
"Y": 50.13025,
"Z": -40.940002
},
"TerritoryId": 1185,
"InteractionType": "AcceptQuest"
}
]
}
]
}

View File

@ -13,8 +13,7 @@
"Z": -52.99463 "Z": -52.99463
}, },
"TerritoryId": 1186, "TerritoryId": 1186,
"InteractionType": "AcceptQuest", "InteractionType": "AcceptQuest"
"Comment": "Quest is completed instantly"
} }
] ]
} }

View File

@ -13,8 +13,7 @@
"Z": -38.132385 "Z": -38.132385
}, },
"TerritoryId": 1186, "TerritoryId": 1186,
"InteractionType": "AcceptQuest", "InteractionType": "AcceptQuest"
"Comment": "Quest is completed instantly"
} }
] ]
} }

View File

@ -83,7 +83,6 @@ internal sealed class QuestController
public QuestProgress? NextQuest => _nextQuest; public QuestProgress? NextQuest => _nextQuest;
public string? DebugState { get; private set; } public string? DebugState { get; private set; }
public string? Comment { get; private set; }
public void Reload() public void Reload()
{ {
@ -212,7 +211,6 @@ internal sealed class QuestController
if (questToRun == null) if (questToRun == null)
{ {
DebugState = "No quest active"; DebugState = "No quest active";
Comment = null;
Stop("No quest active"); Stop("No quest active");
return; return;
} }
@ -240,7 +238,6 @@ internal sealed class QuestController
if (sequence == null) if (sequence == null)
{ {
DebugState = "Sequence not found"; DebugState = "Sequence not found";
Comment = null;
Stop("Unknown sequence"); Stop("Unknown sequence");
return; return;
} }
@ -248,7 +245,6 @@ internal sealed class QuestController
if (questToRun.Step == 255) if (questToRun.Step == 255)
{ {
DebugState = "Step completed"; DebugState = "Step completed";
Comment = null;
if (_currentTask != null || _taskQueue.Count > 0) if (_currentTask != null || _taskQueue.Count > 0)
Stop("Step complete", continueIfAutomatic: true); Stop("Step complete", continueIfAutomatic: true);
return; return;
@ -257,14 +253,11 @@ internal sealed class QuestController
if (questToRun.Step >= sequence.Steps.Count) if (questToRun.Step >= sequence.Steps.Count)
{ {
DebugState = "Step not found"; DebugState = "Step not found";
Comment = null;
Stop("Unknown step"); Stop("Unknown step");
return; return;
} }
var step = sequence.Steps[questToRun.Step];
DebugState = null; DebugState = null;
Comment = step.Comment ?? sequence.Comment ?? q.Root.Comment;
} }
} }

View File

@ -22,6 +22,7 @@ internal sealed class QuestInfo
QuestLocks = quest.QuestLock.Select(x => (ushort)(x.Row & 0xFFFFF)).Where(x => x != 0).ToImmutableList(); QuestLocks = quest.QuestLock.Select(x => (ushort)(x.Row & 0xFFFFF)).Where(x => x != 0).ToImmutableList();
QuestLockJoin = (QuestJoin)quest.QuestLockJoin; QuestLockJoin = (QuestJoin)quest.QuestLockJoin;
IsMainScenarioQuest = quest.JournalGenre?.Value?.JournalCategory?.Value?.JournalSection?.Row is 0 or 1; IsMainScenarioQuest = quest.JournalGenre?.Value?.JournalCategory?.Value?.JournalSection?.Row is 0 or 1;
CompletesInstantly = quest.ToDoCompleteSeq[0] == 0;
} }
public ushort QuestId { get; } public ushort QuestId { get; }
@ -31,9 +32,10 @@ internal sealed class QuestInfo
public bool IsRepeatable { get; } public bool IsRepeatable { get; }
public ImmutableList<ushort> PreviousQuests { get; } public ImmutableList<ushort> PreviousQuests { get; }
public QuestJoin PreviousQuestJoin { get; } public QuestJoin PreviousQuestJoin { get; }
public bool IsMainScenarioQuest { get; }
public ImmutableList<ushort> QuestLocks { get; set; } public ImmutableList<ushort> QuestLocks { get; set; }
public QuestJoin QuestLockJoin { get; set; } public QuestJoin QuestLockJoin { get; set; }
public bool IsMainScenarioQuest { get; }
public bool CompletesInstantly { get; set; }
public string SimplifiedName => Name public string SimplifiedName => Name
.TrimStart(SeIconChar.QuestSync.ToIconChar(), SeIconChar.QuestRepeatable.ToIconChar(), ' '); .TrimStart(SeIconChar.QuestSync.ToIconChar(), SeIconChar.QuestRepeatable.ToIconChar(), ' ');

View File

@ -27,21 +27,37 @@ internal sealed class BasicSequenceValidator : IQuestValidator
yield break; yield break;
} }
int maxSequence = sequences.Select(x => x.Sequence) if (quest.Info.CompletesInstantly)
.Where(x => x != 255)
.Max();
for (int i = 0; i < maxSequence; i++)
{ {
var foundSequences = sequences.Where(x => x.Sequence == i).ToList(); foreach (var sequence in sequences)
var issue = ValidateSequences(quest, i, foundSequences); {
if (issue != null) if (sequence == foundStart)
yield return issue; continue;
yield return new ValidationIssue
{
QuestId = quest.QuestId,
Sequence = (byte)sequence.Sequence,
Step = null,
Severity = EIssueSeverity.Error,
Description = "Instant quest should not have any sequences after the start",
};
}
} }
else
// some quests finish instantly
if (maxSequence > 0 || foundStart.Steps.Count > 1)
{ {
int maxSequence = sequences.Select(x => x.Sequence)
.Where(x => x != 255)
.Max();
for (int i = 0; i < maxSequence; i++)
{
var foundSequences = sequences.Where(x => x.Sequence == i).ToList();
var issue = ValidateSequences(quest, i, foundSequences);
if (issue != null)
yield return issue;
}
var foundEnding = sequences.Where(x => x.Sequence == 255).ToList(); var foundEnding = sequences.Where(x => x.Sequence == 255).ToList();
var endingIssue = ValidateSequences(quest, 255, foundEnding); var endingIssue = ValidateSequences(quest, 255, foundEnding);
if (endingIssue != null) if (endingIssue != null)

View File

@ -172,7 +172,13 @@ internal sealed class QuestSelectionWindow : LWindow
ImGui.TextUnformatted("Repeatable"); ImGui.TextUnformatted("Repeatable");
} }
if (!_questRegistry.IsKnownQuest(quest.QuestId)) if (quest.CompletesInstantly)
{
ImGui.SameLine();
ImGui.TextUnformatted("Instant");
}
if (!isKnownQuest)
{ {
ImGui.SameLine(); ImGui.SameLine();
ImGui.TextUnformatted("NoQuestPath"); ImGui.TextUnformatted("NoQuestPath");

View File

@ -220,11 +220,19 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
else else
{ {
ImGui.BeginDisabled(); ImGui.BeginDisabled();
ImGui.TextUnformatted(_questController.DebugState ?? "--"); ImGui.TextUnformatted(_questController.DebugState ?? string.Empty);
ImGui.EndDisabled(); ImGui.EndDisabled();
} }
ImGui.TextUnformatted(_questController.Comment ?? "--"); QuestSequence? currentSequence = currentQuest.Quest.FindSequence(currentQuest.Sequence);
QuestStep? currentStep = currentSequence?.FindStep(currentQuest.Step);
bool colored = currentStep is
{ InteractionType: EInteractionType.Instruction or EInteractionType.WaitForManualProgress };
if (colored)
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudOrange);
ImGui.TextUnformatted(currentStep?.Comment ?? currentSequence?.Comment ?? currentQuest.Quest.Root.Comment ?? string.Empty);
if (colored)
ImGui.PopStyleColor();
//var nextStep = _questController.GetNextStep(); //var nextStep = _questController.GetNextStep();
//ImGui.BeginDisabled(nextStep.Step == null); //ImGui.BeginDisabled(nextStep.Step == null);
@ -257,15 +265,12 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
_questController.Stop("Manual"); _questController.Stop("Manual");
} }
QuestStep? currentStep = currentQuest.Quest
.FindSequence(currentQuest.Sequence)
?.FindStep(currentQuest.Step);
bool lastStep = currentStep == bool lastStep = currentStep ==
currentQuest.Quest.FindSequence(currentQuest.Sequence)?.Steps.LastOrDefault(); currentQuest.Quest.FindSequence(currentQuest.Sequence)?.Steps.LastOrDefault();
bool colored = currentStep != null colored = currentStep != null
&& !lastStep && !lastStep
&& currentStep.InteractionType == EInteractionType.Instruction && currentStep.InteractionType == EInteractionType.Instruction
&& _questController.HasCurrentTaskMatching<WaitAtEnd.WaitNextStepOrSequence>(); && _questController.HasCurrentTaskMatching<WaitAtEnd.WaitNextStepOrSequence>();
ImGui.BeginDisabled(lastStep); ImGui.BeginDisabled(lastStep);
if (colored) if (colored)