From 89e43ce9e21eb63f543899b7217ad8acbb2a16c7 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sat, 8 Jun 2024 11:30:26 +0200 Subject: [PATCH] Mini-YA III, save window configs --- Questionable/.editorconfig | 2 +- Questionable/Configuration.cs | 10 ++ Questionable/Controller/GameUiController.cs | 138 ++++++++++++-------- Questionable/QuestionablePlugin.cs | 9 +- Questionable/Windows/DebugWindow.cs | 18 ++- 5 files changed, 114 insertions(+), 63 deletions(-) create mode 100644 Questionable/Configuration.cs diff --git a/Questionable/.editorconfig b/Questionable/.editorconfig index 6a4af82e..1e0e3b2f 100644 --- a/Questionable/.editorconfig +++ b/Questionable/.editorconfig @@ -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 diff --git a/Questionable/Configuration.cs b/Questionable/Configuration.cs new file mode 100644 index 00000000..6aa01ec3 --- /dev/null +++ b/Questionable/Configuration.cs @@ -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(); +} diff --git a/Questionable/Controller/GameUiController.cs b/Questionable/Controller/GameUiController.cs index fc15fb0b..131814db 100644 --- a/Questionable/Controller/GameUiController.cs +++ b/Questionable/Controller/GameUiController.cs @@ -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,10 +85,11 @@ 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) { - _questController.IncreaseDialogueChoicesSelected(); + 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,10 +111,11 @@ 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) { - _questController.IncreaseDialogueChoicesSelected(); + 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) { - _questController.IncreaseDialogueChoicesSelected(); + if (!checkAllSteps) + _questController.IncreaseDialogueChoicesSelected(); addonSelectIconString->AtkUnitBase.FireCallbackInt(answer.Value); } } - private int? HandleListChoice(string? actualPrompt, List answers) + private int? HandleListChoice(string? actualPrompt, List answers, bool checkAllSteps) { var currentQuest = _questController.CurrentQuest; if (currentQuest == null) @@ -154,14 +156,25 @@ internal sealed class GameUiController : IDisposable } var quest = currentQuest.Quest; - var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step); - if (step == null) + IList dialogueChoices; + if (checkAllSteps) { - _pluginLog.Information("Ignoring list choice, no active step"); - return null; + var sequence = quest.FindSequence(currentQuest.Sequence); + dialogueChoices = sequence?.Steps.SelectMany(x => x.DialogueChoices).ToList() ?? new List(); + } + 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; } - foreach (var dialogueChoice in 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,53 +256,71 @@ 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)) - return; + 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 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; - switch (dialogueChoice.Type) + if (dialogueChoice.Prompt != null) { - 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; + 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; + } } + else + excelPrompt = null; if (excelPrompt == null || !GameStringEquals(actualPrompt, excelPrompt)) continue; addonSelectYesno->AtkUnitBase.FireCallbackInt(dialogueChoice.Yes ? 0 : 1); - _questController.IncreaseDialogueChoicesSelected(); + if (!checkAllSteps) + _questController.IncreaseDialogueChoicesSelected(); return true; } 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()! @@ -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 /// /// Ensures characters like '-' are handled equally in both strings. /// - private bool GameStringEquals(string? a, string? b) + private static bool GameStringEquals(string? a, string? b) { if (a == null) return b == null; diff --git a/Questionable/QuestionablePlugin.cs b/Questionable/QuestionablePlugin.cs index c3f21cc6..56eeea99 100644 --- a/Questionable/QuestionablePlugin.cs +++ b/Questionable/QuestionablePlugin.cs @@ -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; diff --git a/Questionable/Windows/DebugWindow.cs b/Questionable/Windows/DebugWindow.cs index 34169e70..d1e83b08 100644 --- a/Questionable/Windows/DebugWindow.cs +++ b/Questionable/Windows/DebugWindow.cs @@ -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)