diff --git a/Questionable/Controller/GameUi/HelpUiController.cs b/Questionable/Controller/GameUi/HelpUiController.cs index 0d869add..504f8cd0 100644 --- a/Questionable/Controller/GameUi/HelpUiController.cs +++ b/Questionable/Controller/GameUi/HelpUiController.cs @@ -3,6 +3,7 @@ using Dalamud.Game.Addon.Lifecycle; using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Component.GUI; +using LLib.GameUI; using Microsoft.Extensions.Logging; namespace Questionable.Controller.GameUi; @@ -11,17 +12,45 @@ internal sealed class HelpUiController : IDisposable { private readonly QuestController _questController; private readonly IAddonLifecycle _addonLifecycle; + private readonly IGameGui _gameGui; private readonly ILogger _logger; - public HelpUiController(QuestController questController, IAddonLifecycle addonLifecycle, ILogger logger) + public HelpUiController( + QuestController questController, + IAddonLifecycle addonLifecycle, + IGameGui gameGui, + ILogger logger) { _questController = questController; _addonLifecycle = addonLifecycle; + _gameGui = gameGui; _logger = logger; + _questController.AutomationTypeChanged += CloseHelpWindowsWhenStartingQuests; + _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup); _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "ContentsTutorial", ContentsTutorialPostSetup); _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "MultipleHelpWindow", MultipleHelpWindowPostSetup); + _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "JobHudNotice", JobHudNoticePostSetup); + _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "Guide", GuidePostSetup); + } + + private unsafe void CloseHelpWindowsWhenStartingQuests(object sender, QuestController.EAutomationType e) + { + if (e is QuestController.EAutomationType.Manual) + return; + + if (_gameGui.TryGetAddonByName("Guide", out AtkUnitBase* addonGuide)) + { + _logger.LogInformation("Guide window is open"); + GuidePostSetup(addonGuide); + } + + if (_gameGui.TryGetAddonByName("JobHudNotice", out AtkUnitBase* addonJobHudNotice)) + { + _logger.LogInformation("JobHudNotice window is open"); + JobHudNoticePostSetup(addonJobHudNotice); + } } private unsafe void UnendingCodexPostSetup(AddonEvent type, AddonArgs args) @@ -36,7 +65,7 @@ internal sealed class HelpUiController : IDisposable private unsafe void ContentsTutorialPostSetup(AddonEvent type, AddonArgs args) { - if (_questController.StartedQuest?.Quest.Id.Value == 245) + if (_questController.StartedQuest?.Quest.Id.Value is 245 or 3872) { _logger.LogInformation("Closing ContentsTutorial"); AtkUnitBase* addon = (AtkUnitBase*)args.Addon; @@ -58,10 +87,38 @@ internal sealed class HelpUiController : IDisposable } } + private unsafe void JobHudNoticePostSetup(AddonEvent type, AddonArgs args) + { + if (_questController.IsRunning || _questController.AutomationType != QuestController.EAutomationType.Manual) + JobHudNoticePostSetup((AtkUnitBase*)args.Addon); + } + + private unsafe void JobHudNoticePostSetup(AtkUnitBase* addon) + { + _logger.LogInformation("Clicking the JobHudNotice window to open the relevant Guide page"); + addon->FireCallbackInt(0); + } + + private unsafe void GuidePostSetup(AddonEvent type, AddonArgs args) + { + if (_questController.IsRunning || _questController.AutomationType != QuestController.EAutomationType.Manual) + GuidePostSetup((AtkUnitBase*)args.Addon); + } + + private unsafe void GuidePostSetup(AtkUnitBase* addon) + { + _logger.LogInformation("Closing Guide window"); + addon->FireCallbackInt(-1); + } + public void Dispose() { + _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "Guide", GuidePostSetup); + _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "JobHudNotice", JobHudNoticePostSetup); _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "MultipleHelpWindow", MultipleHelpWindowPostSetup); _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "ContentsTutorial", ContentsTutorialPostSetup); _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup); + + _questController.AutomationTypeChanged -= CloseHelpWindowsWhenStartingQuests; } } diff --git a/Questionable/Controller/MiniTaskController.cs b/Questionable/Controller/MiniTaskController.cs index 949c1915..4099a17d 100644 --- a/Questionable/Controller/MiniTaskController.cs +++ b/Questionable/Controller/MiniTaskController.cs @@ -28,6 +28,7 @@ internal abstract class MiniTaskController : IDisposable private readonly ILogger _logger; private readonly string _actionCanceledText; + private readonly string _cantExecuteDueToStatusText; protected MiniTaskController(IChatGui chatGui, ICondition condition, IServiceProvider serviceProvider, InterruptHandler interruptHandler, IDataManager dataManager, ILogger logger) @@ -39,6 +40,7 @@ internal abstract class MiniTaskController : IDisposable _condition = condition; _actionCanceledText = dataManager.GetString(1314, x => x.Text)!; + _cantExecuteDueToStatusText = dataManager.GetString(7728, x => x.Text)!; _interruptHandler.Interrupted += HandleInterruption; } @@ -183,6 +185,19 @@ internal abstract class MiniTaskController : IDisposable else _taskQueue.InterruptWith([new WaitAtEnd.WaitDelay()]); + LogTasksAfterInterruption(); + } + + private void InterruptWithoutCombat() + { + _logger.LogWarning("Interrupted, attempting to redo previous tasks (not in combat)"); + _taskQueue.InterruptWith([new WaitAtEnd.WaitDelay()]); + + LogTasksAfterInterruption(); + } + + private void LogTasksAfterInterruption() + { _logger.LogInformation("Remaining tasks after interruption:"); foreach (ITask task in _taskQueue.RemainingTasks) _logger.LogInformation("- {TaskName}", task); @@ -204,6 +219,8 @@ internal abstract class MiniTaskController : IDisposable !_condition[ConditionFlag.InFlight] && _taskQueue.CurrentTaskExecutor?.ShouldInterruptOnDamage() == true) InterruptQueueWithCombat(); + else if (GameFunctions.GameStringEquals(_cantExecuteDueToStatusText, message.TextValue)) + InterruptWithoutCombat(); } } diff --git a/Questionable/Controller/QuestController.cs b/Questionable/Controller/QuestController.cs index 2c522556..954bb5be 100644 --- a/Questionable/Controller/QuestController.cs +++ b/Questionable/Controller/QuestController.cs @@ -111,9 +111,13 @@ internal sealed class QuestController : MiniTaskController, IDi _logger.LogInformation("Setting automation type to {NewAutomationType} (previous: {OldAutomationType})", value, _automationType); _automationType = value; + AutomationTypeChanged?.Invoke(this, value); } } + public delegate void AutomationTypeChangedEventHandler(object sender, EAutomationType e); + public event AutomationTypeChangedEventHandler? AutomationTypeChanged; + public (QuestProgress Progress, ECurrentQuestType Type)? CurrentQuestDetails { get