2024-06-03 21:17:35 +00:00
|
|
|
|
using System;
|
2024-06-06 16:49:49 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Globalization;
|
2024-06-03 21:17:35 +00:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using Dalamud.Game.Addon.Lifecycle;
|
|
|
|
|
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
|
|
|
|
using Dalamud.Plugin.Services;
|
|
|
|
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
|
|
|
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
|
|
|
|
using LLib.GameUI;
|
|
|
|
|
using Lumina.Excel.GeneratedSheets;
|
|
|
|
|
using Questionable.Model.V1;
|
|
|
|
|
using Quest = Questionable.Model.Quest;
|
|
|
|
|
|
|
|
|
|
namespace Questionable.Controller;
|
|
|
|
|
|
|
|
|
|
internal sealed class GameUiController : IDisposable
|
|
|
|
|
{
|
|
|
|
|
private readonly IAddonLifecycle _addonLifecycle;
|
|
|
|
|
private readonly IDataManager _dataManager;
|
|
|
|
|
private readonly GameFunctions _gameFunctions;
|
|
|
|
|
private readonly QuestController _questController;
|
2024-06-06 16:49:49 +00:00
|
|
|
|
private readonly IGameGui _gameGui;
|
2024-06-03 21:17:35 +00:00
|
|
|
|
private readonly IPluginLog _pluginLog;
|
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
public GameUiController(IAddonLifecycle addonLifecycle, IDataManager dataManager, GameFunctions gameFunctions,
|
|
|
|
|
QuestController questController, IGameGui gameGui, IPluginLog pluginLog)
|
2024-06-03 21:17:35 +00:00
|
|
|
|
{
|
|
|
|
|
_addonLifecycle = addonLifecycle;
|
|
|
|
|
_dataManager = dataManager;
|
|
|
|
|
_gameFunctions = gameFunctions;
|
|
|
|
|
_questController = questController;
|
2024-06-06 16:49:49 +00:00
|
|
|
|
_gameGui = gameGui;
|
2024-06-03 21:17:35 +00:00
|
|
|
|
_pluginLog = pluginLog;
|
|
|
|
|
|
|
|
|
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup);
|
|
|
|
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "CutSceneSelectString", CutsceneSelectStringPostSetup);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectIconString", SelectIconStringPostSetup);
|
2024-06-03 21:17:35 +00:00
|
|
|
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectYesno", SelectYesnoPostSetup);
|
|
|
|
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "Credit", CreditPostSetup);
|
|
|
|
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 16:49:49 +00:00
|
|
|
|
internal unsafe void HandleCurrentDialogueChoices()
|
|
|
|
|
{
|
|
|
|
|
if (_gameGui.TryGetAddonByName("SelectString", out AddonSelectString* addonSelectString))
|
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information("SelectString window is open");
|
2024-06-08 09:30:26 +00:00
|
|
|
|
SelectStringPostSetup(addonSelectString, true);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_gameGui.TryGetAddonByName("CutSceneSelectString",
|
|
|
|
|
out AddonCutSceneSelectString* addonCutSceneSelectString))
|
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information("CutSceneSelectString window is open");
|
2024-06-08 09:30:26 +00:00
|
|
|
|
CutsceneSelectStringPostSetup(addonCutSceneSelectString, true);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_gameGui.TryGetAddonByName("SelectIconString", out AddonSelectIconString* addonSelectIconString))
|
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information("SelectIconString window is open");
|
2024-06-08 09:30:26 +00:00
|
|
|
|
SelectIconStringPostSetup(addonSelectIconString, true);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_gameGui.TryGetAddonByName("SelectYesno", out AddonSelectYesno* addonSelectYesno))
|
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information("SelectYesno window is open");
|
2024-06-08 09:30:26 +00:00
|
|
|
|
SelectYesnoPostSetup(addonSelectYesno, true);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-03 21:17:35 +00:00
|
|
|
|
private unsafe void SelectStringPostSetup(AddonEvent type, AddonArgs args)
|
|
|
|
|
{
|
|
|
|
|
AddonSelectString* addonSelectString = (AddonSelectString*)args.Addon;
|
2024-06-08 09:30:26 +00:00
|
|
|
|
SelectStringPostSetup(addonSelectString, false);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
private unsafe void SelectStringPostSetup(AddonSelectString* addonSelectString, bool checkAllSteps)
|
2024-06-06 16:49:49 +00:00
|
|
|
|
{
|
2024-06-03 21:17:35 +00:00
|
|
|
|
string? actualPrompt = addonSelectString->AtkUnitBase.AtkValues[2].ReadAtkString();
|
|
|
|
|
if (actualPrompt == null)
|
|
|
|
|
return;
|
|
|
|
|
|
2024-06-06 16:49:49 +00:00
|
|
|
|
List<string?> answers = new();
|
|
|
|
|
for (ushort i = 7; i < addonSelectString->AtkUnitBase.AtkValuesCount; ++i)
|
|
|
|
|
answers.Add(addonSelectString->AtkUnitBase.AtkValues[i].ReadAtkString());
|
2024-06-03 21:17:35 +00:00
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
int? answer = HandleListChoice(actualPrompt, answers, checkAllSteps);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
if (answer != null)
|
2024-06-03 21:17:35 +00:00
|
|
|
|
{
|
2024-06-08 09:30:26 +00:00
|
|
|
|
if (!checkAllSteps)
|
|
|
|
|
_questController.IncreaseDialogueChoicesSelected();
|
2024-06-06 16:49:49 +00:00
|
|
|
|
addonSelectString->AtkUnitBase.FireCallbackInt(answer.Value);
|
2024-06-03 21:17:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private unsafe void CutsceneSelectStringPostSetup(AddonEvent type, AddonArgs args)
|
|
|
|
|
{
|
|
|
|
|
AddonCutSceneSelectString* addonCutSceneSelectString = (AddonCutSceneSelectString*)args.Addon;
|
2024-06-08 09:30:26 +00:00
|
|
|
|
CutsceneSelectStringPostSetup(addonCutSceneSelectString, false);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
private unsafe void CutsceneSelectStringPostSetup(AddonCutSceneSelectString* addonCutSceneSelectString,
|
|
|
|
|
bool checkAllSteps)
|
2024-06-06 16:49:49 +00:00
|
|
|
|
{
|
2024-06-03 21:17:35 +00:00
|
|
|
|
string? actualPrompt = addonCutSceneSelectString->AtkUnitBase.AtkValues[2].ReadAtkString();
|
|
|
|
|
if (actualPrompt == null)
|
|
|
|
|
return;
|
|
|
|
|
|
2024-06-06 16:49:49 +00:00
|
|
|
|
List<string?> answers = new();
|
|
|
|
|
for (int i = 5; i < addonCutSceneSelectString->AtkUnitBase.AtkValuesCount; ++i)
|
|
|
|
|
answers.Add(addonCutSceneSelectString->AtkUnitBase.AtkValues[i].ReadAtkString());
|
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
int? answer = HandleListChoice(actualPrompt, answers, checkAllSteps);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
if (answer != null)
|
|
|
|
|
{
|
2024-06-08 09:30:26 +00:00
|
|
|
|
if (!checkAllSteps)
|
|
|
|
|
_questController.IncreaseDialogueChoicesSelected();
|
2024-06-06 16:49:49 +00:00
|
|
|
|
addonCutSceneSelectString->AtkUnitBase.FireCallbackInt(answer.Value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private unsafe void SelectIconStringPostSetup(AddonEvent type, AddonArgs args)
|
|
|
|
|
{
|
|
|
|
|
AddonSelectIconString* addonSelectIconString = (AddonSelectIconString*)args.Addon;
|
2024-06-08 09:30:26 +00:00
|
|
|
|
SelectIconStringPostSetup(addonSelectIconString, false);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
private unsafe void SelectIconStringPostSetup(AddonSelectIconString* addonSelectIconString, bool checkAllSteps)
|
2024-06-06 16:49:49 +00:00
|
|
|
|
{
|
|
|
|
|
string? actualPrompt = addonSelectIconString->AtkUnitBase.AtkValues[3].ReadAtkString();
|
|
|
|
|
if (string.IsNullOrEmpty(actualPrompt))
|
|
|
|
|
actualPrompt = null;
|
|
|
|
|
|
|
|
|
|
List<string?> answers = new();
|
|
|
|
|
for (ushort i = 0; i < addonSelectIconString->AtkUnitBase.AtkValues[5].Int; i++)
|
|
|
|
|
answers.Add(addonSelectIconString->AtkUnitBase.AtkValues[i * 3 + 7].ReadAtkString());
|
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
int? answer = HandleListChoice(actualPrompt, answers, checkAllSteps);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
if (answer != null)
|
|
|
|
|
{
|
2024-06-08 09:30:26 +00:00
|
|
|
|
if (!checkAllSteps)
|
|
|
|
|
_questController.IncreaseDialogueChoicesSelected();
|
2024-06-06 16:49:49 +00:00
|
|
|
|
addonSelectIconString->AtkUnitBase.FireCallbackInt(answer.Value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
private int? HandleListChoice(string? actualPrompt, List<string?> answers, bool checkAllSteps)
|
2024-06-06 16:49:49 +00:00
|
|
|
|
{
|
2024-06-03 21:17:35 +00:00
|
|
|
|
var currentQuest = _questController.CurrentQuest;
|
|
|
|
|
if (currentQuest == null)
|
2024-06-06 16:49:49 +00:00
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information("Ignoring list choice, no active quest");
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2024-06-03 21:17:35 +00:00
|
|
|
|
|
|
|
|
|
var quest = currentQuest.Quest;
|
2024-06-08 09:30:26 +00:00
|
|
|
|
IList<DialogueChoice> dialogueChoices;
|
|
|
|
|
if (checkAllSteps)
|
2024-06-06 16:49:49 +00:00
|
|
|
|
{
|
2024-06-08 09:30:26 +00:00
|
|
|
|
var sequence = quest.FindSequence(currentQuest.Sequence);
|
|
|
|
|
dialogueChoices = sequence?.Steps.SelectMany(x => x.DialogueChoices).ToList() ?? new List<DialogueChoice>();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
|
|
|
|
|
if (step == null)
|
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information("Ignoring list choice, no active step");
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dialogueChoices = step.DialogueChoices;
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
2024-06-03 21:17:35 +00:00
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
foreach (var dialogueChoice in dialogueChoices)
|
2024-06-03 21:17:35 +00:00
|
|
|
|
{
|
|
|
|
|
if (dialogueChoice.Answer == null)
|
2024-06-06 16:49:49 +00:00
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information("Ignoring entry in DialogueChoices, no answer");
|
2024-06-03 21:17:35 +00:00
|
|
|
|
continue;
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
2024-06-03 21:17:35 +00:00
|
|
|
|
|
2024-06-06 16:49:49 +00:00
|
|
|
|
string? excelPrompt = null, excelAnswer;
|
|
|
|
|
switch (dialogueChoice.Type)
|
|
|
|
|
{
|
|
|
|
|
case EDialogChoiceType.ContentTalkList:
|
|
|
|
|
if (dialogueChoice.Prompt != null)
|
|
|
|
|
{
|
|
|
|
|
excelPrompt =
|
|
|
|
|
_gameFunctions.GetContentTalk(uint.Parse(dialogueChoice.Prompt,
|
|
|
|
|
CultureInfo.InvariantCulture));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
excelAnswer =
|
|
|
|
|
_gameFunctions.GetContentTalk(uint.Parse(dialogueChoice.Answer, CultureInfo.InvariantCulture));
|
|
|
|
|
break;
|
|
|
|
|
case EDialogChoiceType.List:
|
|
|
|
|
if (dialogueChoice.Prompt != null)
|
|
|
|
|
{
|
|
|
|
|
excelPrompt =
|
|
|
|
|
_gameFunctions.GetDialogueText(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
excelAnswer =
|
|
|
|
|
_gameFunctions.GetDialogueText(quest, dialogueChoice.ExcelSheet, dialogueChoice.Answer);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actualPrompt == null && !string.IsNullOrEmpty(excelPrompt))
|
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information($"Unexpected excelPrompt: {excelPrompt}");
|
2024-06-03 21:17:35 +00:00
|
|
|
|
continue;
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
2024-06-03 21:17:35 +00:00
|
|
|
|
|
2024-06-06 16:49:49 +00:00
|
|
|
|
if (actualPrompt != null && (excelPrompt == null || !GameStringEquals(actualPrompt, excelPrompt)))
|
2024-06-03 21:17:35 +00:00
|
|
|
|
{
|
2024-06-06 16:49:49 +00:00
|
|
|
|
_pluginLog.Information($"Unexpected excelPrompt: {excelPrompt}, actualPrompt: {actualPrompt}");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-06-03 21:17:35 +00:00
|
|
|
|
|
2024-06-06 16:49:49 +00:00
|
|
|
|
for (int i = 0; i < answers.Count; ++i)
|
|
|
|
|
{
|
2024-06-08 09:30:26 +00:00
|
|
|
|
_pluginLog.Verbose($"Checking if {answers[i]} == {excelAnswer}");
|
2024-06-06 16:49:49 +00:00
|
|
|
|
if (GameStringEquals(answers[i], excelAnswer))
|
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information($"Returning {i}: '{answers[i]}' for '{actualPrompt}'");
|
|
|
|
|
return i;
|
|
|
|
|
}
|
2024-06-03 21:17:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-06 16:49:49 +00:00
|
|
|
|
|
|
|
|
|
_pluginLog.Information($"No matching answer found for {actualPrompt}.");
|
|
|
|
|
return null;
|
2024-06-03 21:17:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private unsafe void SelectYesnoPostSetup(AddonEvent type, AddonArgs args)
|
|
|
|
|
{
|
|
|
|
|
AddonSelectYesno* addonSelectYesno = (AddonSelectYesno*)args.Addon;
|
2024-06-08 09:30:26 +00:00
|
|
|
|
SelectYesnoPostSetup(addonSelectYesno, false);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
private unsafe void SelectYesnoPostSetup(AddonSelectYesno* addonSelectYesno, bool checkAllSteps)
|
2024-06-06 16:49:49 +00:00
|
|
|
|
{
|
2024-06-03 21:17:35 +00:00
|
|
|
|
string? actualPrompt = addonSelectYesno->AtkUnitBase.AtkValues[0].ReadAtkString();
|
|
|
|
|
if (actualPrompt == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
_pluginLog.Verbose($"Prompt: '{actualPrompt}'");
|
|
|
|
|
|
|
|
|
|
var currentQuest = _questController.CurrentQuest;
|
|
|
|
|
if (currentQuest == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var quest = currentQuest.Quest;
|
2024-06-08 09:30:26 +00:00
|
|
|
|
if (checkAllSteps)
|
|
|
|
|
{
|
|
|
|
|
var sequence = quest.FindSequence(currentQuest.Sequence);
|
|
|
|
|
if (sequence != null && HandleDefaultYesNo(addonSelectYesno, quest,
|
|
|
|
|
sequence.Steps.SelectMany(x => x.DialogueChoices).ToList(), actualPrompt, checkAllSteps))
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
|
|
|
|
|
if (step != null && HandleDefaultYesNo(addonSelectYesno, quest, step.DialogueChoices, actualPrompt,
|
|
|
|
|
checkAllSteps))
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-06-03 21:17:35 +00:00
|
|
|
|
|
|
|
|
|
HandleTravelYesNo(addonSelectYesno, currentQuest, actualPrompt);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
private unsafe bool HandleDefaultYesNo(AddonSelectYesno* addonSelectYesno, Quest quest,
|
|
|
|
|
IList<DialogueChoice> dialogueChoices, string actualPrompt, bool checkAllSteps)
|
2024-06-03 21:17:35 +00:00
|
|
|
|
{
|
2024-06-08 09:30:26 +00:00
|
|
|
|
_pluginLog.Verbose($"DefaultYesNo: Choice count: {dialogueChoices.Count}");
|
|
|
|
|
foreach (var dialogueChoice in dialogueChoices)
|
2024-06-03 21:17:35 +00:00
|
|
|
|
{
|
2024-06-06 16:49:49 +00:00
|
|
|
|
string? excelPrompt;
|
2024-06-08 09:30:26 +00:00
|
|
|
|
if (dialogueChoice.Prompt != null)
|
2024-06-06 16:49:49 +00:00
|
|
|
|
{
|
2024-06-08 09:30:26 +00:00
|
|
|
|
switch (dialogueChoice.Type)
|
|
|
|
|
{
|
|
|
|
|
case EDialogChoiceType.ContentTalkYesNo:
|
|
|
|
|
excelPrompt =
|
|
|
|
|
_gameFunctions.GetContentTalk(uint.Parse(dialogueChoice.Prompt,
|
|
|
|
|
CultureInfo.InvariantCulture));
|
|
|
|
|
break;
|
|
|
|
|
case EDialogChoiceType.YesNo:
|
|
|
|
|
excelPrompt =
|
|
|
|
|
_gameFunctions.GetDialogueText(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-06-06 16:49:49 +00:00
|
|
|
|
}
|
2024-06-08 09:30:26 +00:00
|
|
|
|
else
|
|
|
|
|
excelPrompt = null;
|
2024-06-06 16:49:49 +00:00
|
|
|
|
|
|
|
|
|
if (excelPrompt == null || !GameStringEquals(actualPrompt, excelPrompt))
|
2024-06-03 21:17:35 +00:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
addonSelectYesno->AtkUnitBase.FireCallbackInt(dialogueChoice.Yes ? 0 : 1);
|
2024-06-08 09:30:26 +00:00
|
|
|
|
if (!checkAllSteps)
|
|
|
|
|
_questController.IncreaseDialogueChoicesSelected();
|
2024-06-03 21:17:35 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-08 09:30:26 +00:00
|
|
|
|
private unsafe void HandleTravelYesNo(AddonSelectYesno* addonSelectYesno,
|
2024-06-03 21:17:35 +00:00
|
|
|
|
QuestController.QuestProgress currentQuest, string actualPrompt)
|
|
|
|
|
{
|
|
|
|
|
// 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)
|
2024-06-08 09:30:26 +00:00
|
|
|
|
return;
|
2024-06-03 21:17:35 +00:00
|
|
|
|
|
|
|
|
|
bool increaseStepCount = true;
|
|
|
|
|
QuestStep? step = sequence.FindStep(currentQuest.Step);
|
|
|
|
|
if (step != null)
|
|
|
|
|
_pluginLog.Verbose($"Current step: {step.TerritoryId}, {step.TargetTerritoryId}");
|
|
|
|
|
|
2024-06-06 16:49:49 +00:00
|
|
|
|
if (step == null || step.TargetTerritoryId == null)
|
2024-06-03 21:17:35 +00:00
|
|
|
|
{
|
|
|
|
|
_pluginLog.Verbose("TravelYesNo: Checking previous step...");
|
|
|
|
|
step = sequence.FindStep(currentQuest.Step == 255 ? (sequence.Steps.Count - 1) : (currentQuest.Step - 1));
|
|
|
|
|
increaseStepCount = false;
|
|
|
|
|
|
|
|
|
|
if (step != null)
|
|
|
|
|
_pluginLog.Verbose($"Previous step: {step.TerritoryId}, {step.TargetTerritoryId}");
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 16:49:49 +00:00
|
|
|
|
if (step == null || step.TargetTerritoryId == null)
|
2024-06-03 21:17:35 +00:00
|
|
|
|
{
|
|
|
|
|
_pluginLog.Verbose("TravelYesNo: Not found");
|
2024-06-08 09:30:26 +00:00
|
|
|
|
return;
|
2024-06-03 21:17:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var warps = _dataManager.GetExcelSheet<Warp>()!
|
|
|
|
|
.Where(x => x.RowId > 0 && x.TerritoryType.Row == step.TargetTerritoryId)
|
|
|
|
|
.Where(x => x.ConfirmEvent.Row == 0); // unsure if this is needed
|
|
|
|
|
foreach (var entry in warps)
|
|
|
|
|
{
|
|
|
|
|
string? excelPrompt = entry.Question?.ToString();
|
2024-06-06 16:49:49 +00:00
|
|
|
|
if (excelPrompt == null || !GameStringEquals(excelPrompt, actualPrompt))
|
2024-06-03 21:17:35 +00:00
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information($"Ignoring prompt '{excelPrompt}'");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_pluginLog.Information($"Using warp {entry.RowId}, {excelPrompt}");
|
|
|
|
|
addonSelectYesno->AtkUnitBase.FireCallbackInt(0);
|
|
|
|
|
if (increaseStepCount)
|
|
|
|
|
_questController.IncreaseStepCount();
|
2024-06-08 09:30:26 +00:00
|
|
|
|
return;
|
2024-06-03 21:17:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private unsafe void CreditPostSetup(AddonEvent type, AddonArgs args)
|
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information("Closing Credits sequence");
|
|
|
|
|
AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
|
|
|
|
|
addon->FireCallbackInt(-2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private unsafe void UnendingCodexPostSetup(AddonEvent type, AddonArgs args)
|
|
|
|
|
{
|
|
|
|
|
if (_questController.CurrentQuest?.Quest.QuestId == 4526)
|
|
|
|
|
{
|
|
|
|
|
_pluginLog.Information("Closing Unending Codex");
|
|
|
|
|
AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
|
|
|
|
|
addon->FireCallbackInt(-2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 16:49:49 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Ensures characters like '-' are handled equally in both strings.
|
|
|
|
|
/// </summary>
|
2024-06-08 09:30:26 +00:00
|
|
|
|
private static bool GameStringEquals(string? a, string? b)
|
2024-06-06 16:49:49 +00:00
|
|
|
|
{
|
|
|
|
|
if (a == null)
|
|
|
|
|
return b == null;
|
|
|
|
|
|
|
|
|
|
if (b == null)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return a.ReplaceLineEndings().Replace('\u2013', '-') == b.ReplaceLineEndings().Replace('\u2013', '-');
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-03 21:17:35 +00:00
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup);
|
|
|
|
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "Credit", CreditPostSetup);
|
|
|
|
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "SelectYesno", SelectYesnoPostSetup);
|
2024-06-06 16:49:49 +00:00
|
|
|
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "SelectIconString", SelectIconStringPostSetup);
|
2024-06-03 21:17:35 +00:00
|
|
|
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "CutSceneSelectString", CutsceneSelectStringPostSetup);
|
|
|
|
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup);
|
|
|
|
|
}
|
|
|
|
|
}
|