Mini-YA III, save window configs

This commit is contained in:
Liza 2024-06-08 11:30:26 +02:00
parent d8494b347b
commit 89e43ce9e2
Signed by: liza
GPG Key ID: 7199F8D727D55F67
5 changed files with 114 additions and 63 deletions

View File

@ -990,7 +990,7 @@ csharp_space_around_binary_operators = before_and_after
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:suggestion
csharp_prefer_braces = true:silent
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_prefer_primary_constructors = true:suggestion

View File

@ -0,0 +1,10 @@
using Dalamud.Configuration;
using LLib.ImGui;
namespace Questionable;
internal sealed class Configuration : IPluginConfiguration
{
public int Version { get; set; } = 1;
public WindowConfig DebugWindowConfig { get; set; } = new();
}

View File

@ -16,7 +16,6 @@ namespace Questionable.Controller;
internal sealed class GameUiController : IDisposable
{
private readonly IClientState _clientState;
private readonly IAddonLifecycle _addonLifecycle;
private readonly IDataManager _dataManager;
private readonly GameFunctions _gameFunctions;
@ -24,10 +23,9 @@ internal sealed class GameUiController : IDisposable
private readonly IGameGui _gameGui;
private readonly IPluginLog _pluginLog;
public GameUiController(IClientState clientState, IAddonLifecycle addonLifecycle, IDataManager dataManager,
GameFunctions gameFunctions, QuestController questController, IGameGui gameGui, IPluginLog pluginLog)
public GameUiController(IAddonLifecycle addonLifecycle, IDataManager dataManager, GameFunctions gameFunctions,
QuestController questController, IGameGui gameGui, IPluginLog pluginLog)
{
_clientState = clientState;
_addonLifecycle = addonLifecycle;
_dataManager = dataManager;
_gameFunctions = gameFunctions;
@ -48,36 +46,36 @@ internal sealed class GameUiController : IDisposable
if (_gameGui.TryGetAddonByName("SelectString", out AddonSelectString* addonSelectString))
{
_pluginLog.Information("SelectString window is open");
SelectStringPostSetup(addonSelectString);
SelectStringPostSetup(addonSelectString, true);
}
if (_gameGui.TryGetAddonByName("CutSceneSelectString",
out AddonCutSceneSelectString* addonCutSceneSelectString))
{
_pluginLog.Information("CutSceneSelectString window is open");
CutsceneSelectStringPostSetup(addonCutSceneSelectString);
CutsceneSelectStringPostSetup(addonCutSceneSelectString, true);
}
if (_gameGui.TryGetAddonByName("SelectIconString", out AddonSelectIconString* addonSelectIconString))
{
_pluginLog.Information("SelectIconString window is open");
SelectIconStringPostSetup(addonSelectIconString);
SelectIconStringPostSetup(addonSelectIconString, true);
}
if (_gameGui.TryGetAddonByName("SelectYesno", out AddonSelectYesno* addonSelectYesno))
{
_pluginLog.Information("SelectYesno window is open");
SelectYesnoPostSetup(addonSelectYesno);
SelectYesnoPostSetup(addonSelectYesno, true);
}
}
private unsafe void SelectStringPostSetup(AddonEvent type, AddonArgs args)
{
AddonSelectString* addonSelectString = (AddonSelectString*)args.Addon;
SelectStringPostSetup(addonSelectString);
SelectStringPostSetup(addonSelectString, false);
}
private unsafe void SelectStringPostSetup(AddonSelectString* addonSelectString)
private unsafe void SelectStringPostSetup(AddonSelectString* addonSelectString, bool checkAllSteps)
{
string? actualPrompt = addonSelectString->AtkUnitBase.AtkValues[2].ReadAtkString();
if (actualPrompt == null)
@ -87,9 +85,10 @@ internal sealed class GameUiController : IDisposable
for (ushort i = 7; i < addonSelectString->AtkUnitBase.AtkValuesCount; ++i)
answers.Add(addonSelectString->AtkUnitBase.AtkValues[i].ReadAtkString());
int? answer = HandleListChoice(actualPrompt, answers);
int? answer = HandleListChoice(actualPrompt, answers, checkAllSteps);
if (answer != null)
{
if (!checkAllSteps)
_questController.IncreaseDialogueChoicesSelected();
addonSelectString->AtkUnitBase.FireCallbackInt(answer.Value);
}
@ -98,10 +97,11 @@ internal sealed class GameUiController : IDisposable
private unsafe void CutsceneSelectStringPostSetup(AddonEvent type, AddonArgs args)
{
AddonCutSceneSelectString* addonCutSceneSelectString = (AddonCutSceneSelectString*)args.Addon;
CutsceneSelectStringPostSetup(addonCutSceneSelectString);
CutsceneSelectStringPostSetup(addonCutSceneSelectString, false);
}
private unsafe void CutsceneSelectStringPostSetup(AddonCutSceneSelectString* addonCutSceneSelectString)
private unsafe void CutsceneSelectStringPostSetup(AddonCutSceneSelectString* addonCutSceneSelectString,
bool checkAllSteps)
{
string? actualPrompt = addonCutSceneSelectString->AtkUnitBase.AtkValues[2].ReadAtkString();
if (actualPrompt == null)
@ -111,9 +111,10 @@ internal sealed class GameUiController : IDisposable
for (int i = 5; i < addonCutSceneSelectString->AtkUnitBase.AtkValuesCount; ++i)
answers.Add(addonCutSceneSelectString->AtkUnitBase.AtkValues[i].ReadAtkString());
int? answer = HandleListChoice(actualPrompt, answers);
int? answer = HandleListChoice(actualPrompt, answers, checkAllSteps);
if (answer != null)
{
if (!checkAllSteps)
_questController.IncreaseDialogueChoicesSelected();
addonCutSceneSelectString->AtkUnitBase.FireCallbackInt(answer.Value);
}
@ -122,10 +123,10 @@ internal sealed class GameUiController : IDisposable
private unsafe void SelectIconStringPostSetup(AddonEvent type, AddonArgs args)
{
AddonSelectIconString* addonSelectIconString = (AddonSelectIconString*)args.Addon;
SelectIconStringPostSetup(addonSelectIconString);
SelectIconStringPostSetup(addonSelectIconString, false);
}
private unsafe void SelectIconStringPostSetup(AddonSelectIconString* addonSelectIconString)
private unsafe void SelectIconStringPostSetup(AddonSelectIconString* addonSelectIconString, bool checkAllSteps)
{
string? actualPrompt = addonSelectIconString->AtkUnitBase.AtkValues[3].ReadAtkString();
if (string.IsNullOrEmpty(actualPrompt))
@ -135,16 +136,17 @@ internal sealed class GameUiController : IDisposable
for (ushort i = 0; i < addonSelectIconString->AtkUnitBase.AtkValues[5].Int; i++)
answers.Add(addonSelectIconString->AtkUnitBase.AtkValues[i * 3 + 7].ReadAtkString());
int? answer = HandleListChoice(actualPrompt, answers);
int? answer = HandleListChoice(actualPrompt, answers, checkAllSteps);
if (answer != null)
{
if (!checkAllSteps)
_questController.IncreaseDialogueChoicesSelected();
addonSelectIconString->AtkUnitBase.FireCallbackInt(answer.Value);
}
}
private int? HandleListChoice(string? actualPrompt, List<string?> answers)
private int? HandleListChoice(string? actualPrompt, List<string?> answers, bool checkAllSteps)
{
var currentQuest = _questController.CurrentQuest;
if (currentQuest == null)
@ -154,6 +156,14 @@ internal sealed class GameUiController : IDisposable
}
var quest = currentQuest.Quest;
IList<DialogueChoice> dialogueChoices;
if (checkAllSteps)
{
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)
{
@ -161,7 +171,10 @@ internal sealed class GameUiController : IDisposable
return null;
}
foreach (var dialogueChoice in step.DialogueChoices)
dialogueChoices = step.DialogueChoices;
}
foreach (var dialogueChoice in dialogueChoices)
{
if (dialogueChoice.Answer == null)
{
@ -211,6 +224,7 @@ internal sealed class GameUiController : IDisposable
for (int i = 0; i < answers.Count; ++i)
{
_pluginLog.Verbose($"Checking if {answers[i]} == {excelAnswer}");
if (GameStringEquals(answers[i], excelAnswer))
{
_pluginLog.Information($"Returning {i}: '{answers[i]}' for '{actualPrompt}'");
@ -226,10 +240,10 @@ internal sealed class GameUiController : IDisposable
private unsafe void SelectYesnoPostSetup(AddonEvent type, AddonArgs args)
{
AddonSelectYesno* addonSelectYesno = (AddonSelectYesno*)args.Addon;
SelectYesnoPostSetup(addonSelectYesno);
SelectYesnoPostSetup(addonSelectYesno, false);
}
private unsafe void SelectYesnoPostSetup(AddonSelectYesno* addonSelectYesno)
private unsafe void SelectYesnoPostSetup(AddonSelectYesno* addonSelectYesno, bool checkAllSteps)
{
string? actualPrompt = addonSelectYesno->AtkUnitBase.AtkValues[0].ReadAtkString();
if (actualPrompt == null)
@ -242,25 +256,39 @@ internal sealed class GameUiController : IDisposable
return;
var quest = currentQuest.Quest;
var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
if (step != null && HandleDefaultYesNo(addonSelectYesno, quest, step, actualPrompt))
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;
}
HandleTravelYesNo(addonSelectYesno, currentQuest, actualPrompt);
}
private unsafe bool HandleDefaultYesNo(AddonSelectYesno* addonSelectYesno, Quest quest, QuestStep step,
string actualPrompt)
private unsafe bool HandleDefaultYesNo(AddonSelectYesno* addonSelectYesno, Quest quest,
IList<DialogueChoice> dialogueChoices, string actualPrompt, bool checkAllSteps)
{
_pluginLog.Verbose($"DefaultYesNo: Choice count: {step.DialogueChoices.Count}");
foreach (var dialogueChoice in step.DialogueChoices)
_pluginLog.Verbose($"DefaultYesNo: Choice count: {dialogueChoices.Count}");
foreach (var dialogueChoice in dialogueChoices)
{
string? excelPrompt;
if (dialogueChoice.Prompt != null)
{
switch (dialogueChoice.Type)
{
case EDialogChoiceType.ContentTalkYesNo:
excelPrompt =
_gameFunctions.GetContentTalk(uint.Parse(dialogueChoice.Prompt, CultureInfo.InvariantCulture));
_gameFunctions.GetContentTalk(uint.Parse(dialogueChoice.Prompt,
CultureInfo.InvariantCulture));
break;
case EDialogChoiceType.YesNo:
excelPrompt =
@ -269,11 +297,15 @@ internal sealed class GameUiController : IDisposable
default:
continue;
}
}
else
excelPrompt = null;
if (excelPrompt == null || !GameStringEquals(actualPrompt, excelPrompt))
continue;
addonSelectYesno->AtkUnitBase.FireCallbackInt(dialogueChoice.Yes ? 0 : 1);
if (!checkAllSteps)
_questController.IncreaseDialogueChoicesSelected();
return true;
}
@ -281,14 +313,14 @@ internal sealed class GameUiController : IDisposable
return false;
}
private unsafe bool HandleTravelYesNo(AddonSelectYesno* addonSelectYesno,
private unsafe void HandleTravelYesNo(AddonSelectYesno* addonSelectYesno,
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)
return false;
return;
bool increaseStepCount = true;
QuestStep? step = sequence.FindStep(currentQuest.Step);
@ -308,7 +340,7 @@ internal sealed class GameUiController : IDisposable
if (step == null || step.TargetTerritoryId == null)
{
_pluginLog.Verbose("TravelYesNo: Not found");
return false;
return;
}
var warps = _dataManager.GetExcelSheet<Warp>()!
@ -327,10 +359,8 @@ internal sealed class GameUiController : IDisposable
addonSelectYesno->AtkUnitBase.FireCallbackInt(0);
if (increaseStepCount)
_questController.IncreaseStepCount();
return true;
return;
}
return false;
}
private unsafe void CreditPostSetup(AddonEvent type, AddonArgs args)
@ -353,7 +383,7 @@ internal sealed class GameUiController : IDisposable
/// <summary>
/// Ensures characters like '-' are handled equally in both strings.
/// </summary>
private bool GameStringEquals(string? a, string? b)
private static bool GameStringEquals(string? a, string? b)
{
if (a == null)
return b == null;

View File

@ -29,6 +29,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
private readonly QuestController _questController;
private readonly MovementController _movementController;
private readonly GameUiController _gameUiController;
private readonly Configuration _configuration;
public QuestionablePlugin(DalamudPluginInterface pluginInterface, IClientState clientState,
ITargetManager targetManager, IFramework framework, IGameGui gameGui, IDataManager dataManager,
@ -47,6 +48,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
_commandManager = commandManager;
_gameFunctions = new GameFunctions(dataManager, objectTable, sigScanner, targetManager, condition, clientState,
pluginLog);
_configuration = (Configuration?)_pluginInterface.GetPluginConfig() ?? new Configuration();
AetheryteData aetheryteData = new AetheryteData(dataManager);
NavmeshIpc navmeshIpc = new NavmeshIpc(pluginInterface);
@ -56,11 +58,10 @@ public sealed class QuestionablePlugin : IDalamudPlugin
_questController = new QuestController(pluginInterface, dataManager, _clientState, _gameFunctions,
_movementController, pluginLog, condition, chatGui, framework, gameGui, aetheryteData, lifestreamIpc);
_gameUiController =
new GameUiController(clientState, addonLifecycle, dataManager, _gameFunctions, _questController, gameGui,
pluginLog);
new GameUiController(addonLifecycle, dataManager, _gameFunctions, _questController, gameGui, pluginLog);
_windowSystem.AddWindow(new DebugWindow(_movementController, _questController, _gameFunctions, clientState,
framework, targetManager, _gameUiController));
_windowSystem.AddWindow(new DebugWindow(pluginInterface, _movementController, _questController, _gameFunctions,
clientState, framework, targetManager, _gameUiController, _configuration));
_pluginInterface.UiBuilder.Draw += _windowSystem.Draw;
_framework.Update += FrameworkUpdate;

View File

@ -5,19 +5,22 @@ using Dalamud.Game.ClientState.Objects;
using Dalamud.Interface;
using Dalamud.Interface.Components;
using Dalamud.Interface.Windowing;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.Game.Control;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using ImGuiNET;
using LLib.ImGui;
using Questionable.Controller;
using Questionable.Model;
using Questionable.Model.V1;
namespace Questionable.Windows;
internal sealed class DebugWindow : Window
internal sealed class DebugWindow : LWindow, IPersistableWindowConfig
{
private readonly DalamudPluginInterface _pluginInterface;
private readonly MovementController _movementController;
private readonly QuestController _questController;
private readonly GameFunctions _gameFunctions;
@ -25,12 +28,14 @@ internal sealed class DebugWindow : Window
private readonly IFramework _framework;
private readonly ITargetManager _targetManager;
private readonly GameUiController _gameUiController;
private readonly Configuration _configuration;
public DebugWindow(MovementController movementController, QuestController questController,
GameFunctions gameFunctions, IClientState clientState, IFramework framework,
ITargetManager targetManager, GameUiController gameUiController)
public DebugWindow(DalamudPluginInterface pluginInterface, MovementController movementController,
QuestController questController, GameFunctions gameFunctions, IClientState clientState, IFramework framework,
ITargetManager targetManager, GameUiController gameUiController, Configuration configuration)
: base("Questionable", ImGuiWindowFlags.AlwaysAutoResize)
{
_pluginInterface = pluginInterface;
_movementController = movementController;
_questController = questController;
_gameFunctions = gameFunctions;
@ -38,6 +43,7 @@ internal sealed class DebugWindow : Window
_framework = framework;
_targetManager = targetManager;
_gameUiController = gameUiController;
_configuration = configuration;
IsOpen = true;
SizeConstraints = new WindowSizeConstraints
@ -47,6 +53,10 @@ internal sealed class DebugWindow : Window
};
}
public WindowConfig WindowConfig => _configuration.DebugWindowConfig;
public void SaveWindowConfig() => _pluginInterface.SavePluginConfig(_configuration);
public override bool DrawConditions()
{
if (!_clientState.IsLoggedIn || _clientState.LocalPlayer == null)