forked from liza/Questionable
Make 'TargetTerritoryId' auto-pick warps for SelectString/SelectIconString (except for lifts in Ul'dah/Limsa, since airship landings are in normal territories)
This commit is contained in:
parent
c521860851
commit
320ce14aed
2
LLib
2
LLib
@ -1 +1 @@
|
||||
Subproject commit 93fac6efb01a1272192d929fd863328271512ea4
|
||||
Subproject commit aec507a840b7f0a20635c6ddbc7862e9025cea4f
|
@ -85,15 +85,7 @@
|
||||
"StopDistance": 7,
|
||||
"TerritoryId": 129,
|
||||
"InteractionType": "Interact",
|
||||
"TargetTerritoryId": 138,
|
||||
"DialogueChoices": [
|
||||
{
|
||||
"Type": "List",
|
||||
"ExcelSheet": "Warp",
|
||||
"Prompt": null,
|
||||
"Answer": 131109
|
||||
}
|
||||
]
|
||||
"TargetTerritoryId": 138
|
||||
},
|
||||
{
|
||||
"DataId": 14,
|
||||
|
@ -63,14 +63,6 @@
|
||||
"AethernetShortcut": [
|
||||
"[Gridania] Aetheryte Plaza",
|
||||
"[Gridania] Lancers' Guild"
|
||||
],
|
||||
"DialogueChoices": [
|
||||
{
|
||||
"Type": "List",
|
||||
"ExcelSheet": "Warp",
|
||||
"Prompt": null,
|
||||
"Answer": 131077
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -21,6 +21,21 @@ public class ExcelRef
|
||||
Type = EType.RowId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only used internally (not serialized) with specific values that have been read from the sheets already.
|
||||
/// </summary>
|
||||
private ExcelRef(string value, bool v)
|
||||
{
|
||||
if (!v)
|
||||
throw new ArgumentException(nameof(v));
|
||||
|
||||
_stringValue = value;
|
||||
_rowIdValue = null;
|
||||
Type = EType.RawString;
|
||||
}
|
||||
|
||||
public static ExcelRef FromSheetValue(string value) => new(value, true);
|
||||
|
||||
public EType Type { get; }
|
||||
|
||||
public string AsKey()
|
||||
@ -39,10 +54,19 @@ public class ExcelRef
|
||||
return _rowIdValue!.Value;
|
||||
}
|
||||
|
||||
public string AsRawString()
|
||||
{
|
||||
if (Type != EType.RawString)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
return _stringValue!;
|
||||
}
|
||||
|
||||
public enum EType
|
||||
{
|
||||
None,
|
||||
Key,
|
||||
RowId,
|
||||
RawString,
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Dalamud.Game.Addon.Lifecycle;
|
||||
@ -179,7 +180,8 @@ internal sealed class GameUiController : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe bool CheckQuestSelection(AddonSelectIconString* addonSelectIconString, Quest quest, List<string?> answers)
|
||||
private unsafe bool CheckQuestSelection(AddonSelectIconString* addonSelectIconString, Quest quest,
|
||||
List<string?> answers)
|
||||
{
|
||||
// it is possible for this to be a quest selection
|
||||
string questName = quest.Info.Name;
|
||||
@ -197,7 +199,7 @@ internal sealed class GameUiController : IDisposable
|
||||
{
|
||||
List<string?> answers = new();
|
||||
for (ushort i = 0; i < addonSelectIconString->AtkUnitBase.AtkValues[5].Int; i++)
|
||||
answers.Add( addonSelectIconString->AtkValues[i * 3 + 7].ReadAtkString());
|
||||
answers.Add(addonSelectIconString->AtkValues[i * 3 + 7].ReadAtkString());
|
||||
|
||||
return answers;
|
||||
}
|
||||
@ -205,7 +207,7 @@ internal sealed class GameUiController : IDisposable
|
||||
private int? HandleListChoice(string? actualPrompt, List<string?> answers, bool checkAllSteps)
|
||||
{
|
||||
List<DialogueChoiceInfo> dialogueChoices = [];
|
||||
var currentQuest = _questController.StartedQuest;
|
||||
var currentQuest = _questController.SimulatedQuest ?? _questController.StartedQuest;
|
||||
if (currentQuest != null)
|
||||
{
|
||||
var quest = currentQuest.Quest;
|
||||
@ -224,6 +226,29 @@ internal sealed class GameUiController : IDisposable
|
||||
else
|
||||
dialogueChoices.AddRange(step.DialogueChoices.Select(x => new DialogueChoiceInfo(quest, x)));
|
||||
}
|
||||
|
||||
// add all travel dialogue choices
|
||||
var targetTerritoryId = FindTargetTerritoryFromQuestStep(currentQuest);
|
||||
if (targetTerritoryId != null)
|
||||
{
|
||||
foreach (string? answer in answers)
|
||||
{
|
||||
if (answer == null)
|
||||
continue;
|
||||
|
||||
if (TryFindWarp(targetTerritoryId.Value, answer, out uint? warpId, out string? warpText))
|
||||
{
|
||||
_logger.LogInformation("Adding warp {Id}, {Prompt}", warpId, warpText);
|
||||
dialogueChoices.Add(new DialogueChoiceInfo(quest, new DialogueChoice
|
||||
{
|
||||
Type = EDialogChoiceType.List,
|
||||
ExcelSheet = null,
|
||||
Prompt = null,
|
||||
Answer = ExcelRef.FromSheetValue(warpText),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
_logger.LogDebug("Ignoring current quest dialogue choices, no active quest");
|
||||
@ -242,7 +267,8 @@ internal sealed class GameUiController : IDisposable
|
||||
.ToList();
|
||||
if (questChoices != null && questChoices.Count > 0)
|
||||
{
|
||||
_logger.LogInformation("Adding {Count} dialogue choices from not accepted quest {QuestName}", questChoices.Count, questInfo.Name);
|
||||
_logger.LogInformation("Adding {Count} dialogue choices from not accepted quest {QuestName}",
|
||||
questChoices.Count, questInfo.Name);
|
||||
dialogueChoices.AddRange(questChoices.Select(x => new DialogueChoiceInfo(knownQuest, x)));
|
||||
}
|
||||
}
|
||||
@ -334,25 +360,30 @@ internal sealed class GameUiController : IDisposable
|
||||
_logger.LogTrace("Prompt: '{Prompt}'", actualPrompt);
|
||||
|
||||
var currentQuest = _questController.StartedQuest;
|
||||
if (currentQuest == null)
|
||||
return;
|
||||
if (currentQuest != null)
|
||||
{
|
||||
var quest = currentQuest.Quest;
|
||||
if (checkAllSteps)
|
||||
{
|
||||
var sequence = quest.FindSequence(currentQuest.Sequence);
|
||||
if (sequence != null && HandleDefaultYesNo(addonSelectYesno, quest,
|
||||
sequence.Steps.SelectMany(x => x.DialogueChoices).ToList(), actualPrompt))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
|
||||
if (step != null && HandleDefaultYesNo(addonSelectYesno, quest, step.DialogueChoices, actualPrompt))
|
||||
return;
|
||||
}
|
||||
|
||||
var quest = currentQuest.Quest;
|
||||
if (checkAllSteps)
|
||||
{
|
||||
var sequence = quest.FindSequence(currentQuest.Sequence);
|
||||
if (sequence != null && HandleDefaultYesNo(addonSelectYesno, quest,
|
||||
sequence.Steps.SelectMany(x => x.DialogueChoices).ToList(), actualPrompt))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
|
||||
if (step != null && HandleDefaultYesNo(addonSelectYesno, quest, step.DialogueChoices, actualPrompt))
|
||||
if (HandleTravelYesNo(addonSelectYesno, currentQuest, actualPrompt))
|
||||
return;
|
||||
}
|
||||
|
||||
HandleTravelYesNo(addonSelectYesno, currentQuest, actualPrompt);
|
||||
var simulatedQuest = _questController.SimulatedQuest;
|
||||
if (simulatedQuest != null)
|
||||
HandleTravelYesNo(addonSelectYesno, simulatedQuest, actualPrompt);
|
||||
}
|
||||
|
||||
private unsafe bool HandleDefaultYesNo(AddonSelectYesno* addonSelectYesno, Quest quest,
|
||||
@ -387,21 +418,35 @@ internal sealed class GameUiController : IDisposable
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe void HandleTravelYesNo(AddonSelectYesno* addonSelectYesno,
|
||||
private unsafe bool HandleTravelYesNo(AddonSelectYesno* addonSelectYesno,
|
||||
QuestController.QuestProgress currentQuest, string actualPrompt)
|
||||
{
|
||||
if (_gameFunctions.ReturnRequestedAt >= DateTime.Now.AddSeconds(-2) && _returnRegex.IsMatch(actualPrompt))
|
||||
{
|
||||
_logger.LogInformation("Automatically confirming return...");
|
||||
addonSelectYesno->AtkUnitBase.FireCallbackInt(0);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
var targetTerritoryId = FindTargetTerritoryFromQuestStep(currentQuest);
|
||||
if (targetTerritoryId != null &&
|
||||
TryFindWarp(targetTerritoryId.Value, actualPrompt, out uint? warpId, out string? warpText))
|
||||
{
|
||||
_logger.LogInformation("Using warp {Id}, {Prompt}", warpId, warpText);
|
||||
addonSelectYesno->AtkUnitBase.FireCallbackInt(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private ushort? FindTargetTerritoryFromQuestStep(QuestController.QuestProgress currentQuest)
|
||||
{
|
||||
// this can be triggered either manually (in which case we should increase the step counter), or automatically
|
||||
// (in which case it is ~1 frame later, and the step counter has already been increased)
|
||||
var sequence = currentQuest.Quest.FindSequence(currentQuest.Sequence);
|
||||
if (sequence == null)
|
||||
return;
|
||||
return null;
|
||||
|
||||
QuestStep? step = sequence.FindStep(currentQuest.Step);
|
||||
if (step != null)
|
||||
@ -421,24 +466,44 @@ internal sealed class GameUiController : IDisposable
|
||||
if (step == null || step.TargetTerritoryId == null)
|
||||
{
|
||||
_logger.LogTrace("TravelYesNo: Not found");
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
_logger.LogDebug("Target territory for quest step: {TargetTerritory}", step.TargetTerritoryId);
|
||||
return step.TargetTerritoryId;
|
||||
}
|
||||
|
||||
private bool TryFindWarp(ushort targetTerritoryId, string actualPrompt, [NotNullWhen(true)] out uint? warpId,
|
||||
[NotNullWhen(true)] out string? warpText)
|
||||
{
|
||||
var warps = _dataManager.GetExcelSheet<Warp>()!
|
||||
.Where(x => x.RowId > 0 && x.TerritoryType.Row == step.TargetTerritoryId);
|
||||
.Where(x => x.RowId > 0 && x.TerritoryType.Row == targetTerritoryId);
|
||||
foreach (var entry in warps)
|
||||
{
|
||||
string? excelPrompt = entry.Question?.ToString();
|
||||
if (excelPrompt == null || !GameStringEquals(excelPrompt, actualPrompt))
|
||||
{
|
||||
_logger.LogDebug("Ignoring prompt '{Prompt}'", excelPrompt);
|
||||
continue;
|
||||
}
|
||||
string? excelName = entry.Name?.ToString();
|
||||
string? excelQuestion = entry.Question?.ToString();
|
||||
|
||||
_logger.LogInformation("Using warp {Id}, {Prompt}", entry.RowId, excelPrompt);
|
||||
addonSelectYesno->AtkUnitBase.FireCallbackInt(0);
|
||||
return;
|
||||
if (excelQuestion != null && GameStringEquals(excelQuestion, actualPrompt))
|
||||
{
|
||||
warpId = entry.RowId;
|
||||
warpText = excelQuestion;
|
||||
return true;
|
||||
}
|
||||
else if (excelName != null && GameStringEquals(excelName, actualPrompt))
|
||||
{
|
||||
warpId = entry.RowId;
|
||||
warpText = excelName;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogDebug("Ignoring prompt '{Prompt}'", excelQuestion);
|
||||
}
|
||||
}
|
||||
|
||||
warpId = null;
|
||||
warpText = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe void PointMenuPostSetup(AddonEvent type, AddonArgs args)
|
||||
@ -551,6 +616,8 @@ internal sealed class GameUiController : IDisposable
|
||||
return _gameFunctions.GetDialogueText(quest, excelSheet, excelRef.AsKey());
|
||||
else if (excelRef.Type == ExcelRef.EType.RowId)
|
||||
return _gameFunctions.GetDialogueTextByRowId(excelSheet, excelRef.AsRowId());
|
||||
else if (excelRef.Type == ExcelRef.EType.RawString)
|
||||
return excelRef.AsRawString();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user