From 10fa3024215468d8730457c67bfdaf1d348a00f8 Mon Sep 17 00:00:00 2001 From: alydev Date: Fri, 31 Jul 2026 00:47:50 +1000 Subject: [PATCH] v15.306.1.12 --- CHANGELOG.md | 6 +- Directory.Build.targets | 2 +- Questionable/Windows/Common/Ui/QstWidgets.cs | 24 +- .../QuestComponents/ActiveQuestComponent.cs | 277 +++++++++--------- .../QuestComponents/CreationUtilsComponent.cs | 2 +- .../QuickAccessButtonsComponent.cs | 40 +-- .../RemainingTasksComponent.cs | 2 - Questionable/Windows/QuestWindow.cs | 1 - 8 files changed, 182 insertions(+), 172 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07e7cfa8b..1942d5390 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,2 @@ -- Feature: added "instant" quests (So You Want To Be A Questionable User) to Journal Progress > Other Quests > Special Quests > Instant Quests -alydev - - the "Instant Quests" label can be right clicked to select "Add all to priority quests", this will let users run all available one-step quasi-quests in one go (in theory!) - - bug fix: don't apply NG+ label to Instant Quests category; sort by quest ID -alydev -- Feature: replaced button labels (visible on hover) to quick access buttons -alydev \ No newline at end of file +- Feature: Adjusted quest window buttons -alydev +- Change: show Remaining Tasks dropdown (if enabled) even if 0 tasks -alydev \ No newline at end of file diff --git a/Directory.Build.targets b/Directory.Build.targets index b4c9efbad..167ee08dc 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,6 +1,6 @@ - 15.306.1.11 + 15.306.1.12 diff --git a/Questionable/Windows/Common/Ui/QstWidgets.cs b/Questionable/Windows/Common/Ui/QstWidgets.cs index dfbea3eb6..31ce37b00 100644 --- a/Questionable/Windows/Common/Ui/QstWidgets.cs +++ b/Questionable/Windows/Common/Ui/QstWidgets.cs @@ -134,18 +134,22 @@ public static bool Chip(string text, Vector4 color) // Icon button with a tooltip and an optional count badge. public static bool RailButton(FontAwesomeIcon icon, string label, string? tooltip = null, Vector4? tint = null, - bool enabled = true, string? countBadge = null, Vector4? badgeColor = null, + bool enabled = true, string? countBadge = null, Vector4? badgeColor = null, bool showLabel = false, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0) { float size = ImGui.GetFrameHeight(); bool clicked; using (ImRaii.Disabled(!enabled)) { - clicked = ImGuiComponentsLocal.IconButton(icon, tint, activeColor: null, hoveredColor: null, - new Vector2(size, size), file, line); + if (showLabel) + clicked = ImGuiComponentsLocal.IconButtonWithText(icon, label, tint, activeColor: null, hoveredColor: null, + file: file, line: line); + else + clicked = ImGuiComponentsLocal.IconButton(icon, tint, activeColor: null, hoveredColor: null, + new Vector2(size, size), file, line); } - if (countBadge != null) + if (!showLabel && countBadge != null) { Vector2 max = ImGui.GetItemRectMax(); Vector2 badgeSize = ImGui.CalcTextSize(countBadge); @@ -155,10 +159,14 @@ public static bool RailButton(FontAwesomeIcon icon, string label, string? toolti if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)) { - using ImRaii.TooltipDisposable _ = ImRaii.Tooltip(); - if (tooltip?.Length != 0) - tooltip = $"\n{tooltip}"; - ImGui.TextUnformatted($"{label}{tooltip}"); + if (showLabel && tooltip?.Length != 0) + ImGui.SetTooltip(tooltip); + else + { + if (tooltip?.Length != 0) + tooltip = $"\n{tooltip}"; + ImGui.SetTooltip($"{label}{tooltip}"); + } } return clicked && enabled; diff --git a/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs b/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs index 3c21499ba..df81c09f3 100644 --- a/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs +++ b/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs @@ -22,35 +22,20 @@ internal sealed partial class ActiveQuestComponent ICommandManager commandManager, Configuration configuration, QuestRegistry questRegistry, - PriorityWindow priorityWindow, PathEditorWindow pathEditorWindow, UiUtils uiUtils, IChatGui chatGui, PathDataUpdater pathDataUpdater, + QuestData questData, + QuickAccessButtonsComponent quickAccessButtonsComponent, ILogger logger) { - private readonly IChatGui _chatGui = chatGui; - private readonly CombatController _combatController = combatController; - private readonly ICommandManager _commandManager = commandManager; - private readonly Configuration _configuration = configuration; - private readonly GatheringController _gatheringController = gatheringController; - private readonly ILogger _logger = logger; - private readonly MovementController _movementController = movementController; - private readonly PriorityWindow _priorityWindow = priorityWindow; - private readonly PathEditorWindow _pathEditorWindow = pathEditorWindow; - - private readonly QuestController _questController = questController; - private readonly QuestFunctions _questFunctions = questFunctions; - private readonly QuestRegistry _questRegistry = questRegistry; - private readonly UiUtils _uiUtils = uiUtils; [GeneratedRegex(@"\s\s+", RegexOptions.IgnoreCase, "en-US")] private static partial Regex MultipleWhitespaceRegex(); - public event EventHandler? Reload; - public void Draw(bool isMinimized) { - (QuestController.QuestProgress Progress, QuestController.ECurrentQuestType Type)? currentQuestDetails = _questController.CurrentQuestDetails; + (QuestController.QuestProgress Progress, QuestController.ECurrentQuestType Type)? currentQuestDetails = questController.CurrentQuestDetails; QuestController.QuestProgress? currentQuest = currentQuestDetails?.Progress; QuestController.ECurrentQuestType? currentQuestType = currentQuestDetails?.Type; if (pathDataUpdater.WaitingForPluginUpdate) @@ -60,19 +45,19 @@ public void Draw(bool isMinimized) if (ImGui.IsItemHovered()) ImGui.SetMouseCursor(ImGuiMouseCursor.Hand); if (ImGui.IsItemClicked()) - _commandManager.ProcessCommand("/xlplugins"); + commandManager.ProcessCommand("/xlplugins"); } if (currentQuest != null) { DrawQuestNames(currentQuest, currentQuestType); if (!isMinimized) QstWidgets.ThinProgressBar(CalculateQuestProgress(currentQuest), - _questController.IsRunning ? QstTheme.Success : QstTheme.Amber); + questController.IsRunning ? QstTheme.Success : QstTheme.Amber); QuestProgressInfo? questWork = DrawQuestWork(currentQuest, isMinimized); - if (_combatController.IsRunning) + if (combatController.IsRunning) ImGui.TextColored(QstTheme.Accent, _L("In Combat")); - else if (_questController.CurrentTaskState is { } currentTaskState) + else if (questController.CurrentTaskState is { } currentTaskState) { using ImRaii.ColorDisposable _ = ImRaii.PushColor(ImGuiCol.Text, QstTheme.Accent); using ImRaii.TextWrapDisposable wrap = ImRaii.TextWrapPos(0); @@ -82,7 +67,7 @@ public void Draw(bool isMinimized) { using ImRaii.DisabledDisposable _ = ImRaii.Disabled(); using ImRaii.TextWrapDisposable wrap = ImRaii.TextWrapPos(0); - ImGui.TextUnformatted(_questController.DebugState ?? string.Empty); + ImGui.TextUnformatted(questController.DebugState ?? string.Empty); } try @@ -109,7 +94,7 @@ EInteractionType.WaitForManualProgress or ImGui.TextUnformatted(comment); } - string stats = _questController.ToStatString(); + string stats = questController.ToStatString(); float lineHeight = ImGui.GetTextLineHeightWithSpacing(); Vector2 cursorStart = ImGui.GetCursorPos(); if (!string.IsNullOrWhiteSpace(stats)) @@ -121,7 +106,7 @@ EInteractionType.WaitForManualProgress or ImGui.SetCursorPos(new Vector2(cursorStart.X, cursorStart.Y + lineHeight * 2)); } - var builtNavmeshPercent = _movementController.BuiltNavmeshPercent; + var builtNavmeshPercent = movementController.BuiltNavmeshPercent; var navmeshBarColor = QstTheme.Success; if (builtNavmeshPercent > 100) { @@ -139,22 +124,22 @@ EInteractionType.WaitForManualProgress or using ImRaii.ColorDisposable _ = ImRaii.PushColor(ImGuiCol.Text, QstTheme.Danger); using ImRaii.TextWrapDisposable wrap = ImRaii.TextWrapPos(0); ImGui.TextUnformatted(e.ToString()); - _logger.LogError(e, "Could not handle active quest buttons"); + logger.LogError(e, "Could not handle active quest buttons"); } DrawSimulationControls(); - if (_configuration.Advanced.Debug) + if (configuration.Advanced.Debug) { ImGui.SameLine(); bool editButtonLeft = ImGuiComponentsLocal.IconButton(FontAwesomeIcon.Edit); bool editButtonRight = ImGui.IsItemClicked(ImGuiMouseButton.Right); if (editButtonLeft) - _pathEditorWindow.Open(currentQuest.Quest.Id); + pathEditorWindow.Open(currentQuest.Quest.Id); else if (editButtonRight) { QuestRegistry.OpenFolder(); - _logger.LogDebug("OpenFolder executed"); + logger.LogDebug("OpenFolder executed"); } if (ImGui.IsItemHovered()) ImGui.SetTooltip(_L("Left click: Open in Path Editor\nRight click: Open Quests folder")); @@ -162,7 +147,7 @@ EInteractionType.WaitForManualProgress or if (ImGuiComponentsLocal.IconButton(FontAwesomeIcon.Ban) && currentQuest != null) { GameMain.ExecuteCommand((int)GameCommand.AbandonQuest, (int)currentQuest.Quest.Id.Value); - _logger.LogDebug("AbandonQuest fired"); + logger.LogDebug("AbandonQuest fired"); } if (ImGui.IsItemHovered()) ImGui.SetTooltip("Ask the game to abandon this quest"); @@ -173,32 +158,41 @@ EInteractionType.WaitForManualProgress or if (pathDataUpdater.Status != _L("Idle") && (DateTime.Now - pathDataUpdater.StatusLastChanged).TotalSeconds < 30) ImGui.Text(pathDataUpdater.Status); else - ImGui.Text(_L("No active quest")); + ImGui.Text(_L("No supported quests")); if (!isMinimized) { var color = QstTheme.TextMuted; - if (_questRegistry.Count < 500) + if (questRegistry.Count < 500) color = QstTheme.Danger; - ImGui.TextColored(color, _LF("{0} quests loaded", _questRegistry.Count)); + ImGui.TextColored(color, _LF("{0} quests loaded", questRegistry.Count)); if (ImGui.IsItemClicked()) { - _configuration.PathData.InstalledDataVersion = 0; + configuration.PathData.InstalledDataVersion = 0; pathDataUpdater.CheckForUpdatesManually(); } if (ImGui.IsItemHovered()) ImGui.SetTooltip(_L("Click to reload quest path data from server")); + + foreach (IQuestInfo qInfo in GetTrackedQuests()) + { + if (uiUtils.ChecklistItem($"{qInfo.Name} ({qInfo.QuestId})", complete: false)) + ImGui.SetTooltip(_L("This quest is not yet supported.")); + } } if (ImGuiComponentsLocal.IconButton(FontAwesomeIcon.Stop)) { - _movementController.Stop(); - _questController.Stop(_L("Manual (no active quest)")); - _gatheringController.Stop(_L("Manual (no active quest)")); + movementController.Stop(); + questController.Stop(_L("Manual (no active quest)")); + gatheringController.Stop(_L("Manual (no active quest)")); } ImGui.SameLine(); - if (ImGuiComponentsLocal.IconButton(FontAwesomeIcon.SortAmountDown)) - _priorityWindow.ToggleOrUncollapse(); + quickAccessButtonsComponent.DrawPriorityQuestsButton(); + ImGui.SameLine(); + quickAccessButtonsComponent.DrawJournalProgressButton(showLabel: true); + ImGui.SameLine(); + quickAccessButtonsComponent.DrawTroubleshootingButton(showLabel: true, highlighted: true); } #if REPORTING @@ -217,6 +211,18 @@ EInteractionType.WaitForManualProgress or #endif } + internal unsafe IEnumerable GetTrackedQuests() + { + IEnumerable outp = []; + QuestManager* questManager = QuestManager.Instance(); + for (int i = questManager->TrackedQuests.Length - 1; i >= 0; --i) + if (questManager->TrackedQuests[i].QuestType == 1) + outp = outp.Append( + questData.GetQuestInfo( + QuestId.FromRowId(questManager->NormalQuests[questManager->TrackedQuests[i].Index].QuestId))); + return outp; + } + private void DrawQuestNames(QuestController.QuestProgress currentQuest, QuestController.ECurrentQuestType? currentQuestType) { @@ -242,7 +248,7 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, } else { - QuestController.QuestProgress? startedQuest = _questController.StartedQuest; + QuestController.QuestProgress? startedQuest = questController.StartedQuest; if (startedQuest != null) { if (startedQuest.Quest.Source == Quest.ESource.UserDirectory) @@ -271,17 +277,17 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, ImGui.TextColored(QstTheme.Danger, _L("Disabled")); } - bool hasLevelCondition = _configuration.Stop.Enabled && _configuration.Stop.LevelToStopAfter; - bool hasCompleteQuestConditions = _configuration.Stop.Enabled && - _configuration.Stop.QuestsToStopAfter.Any(x => - !_questFunctions.IsQuestComplete(x) && - !_questFunctions.IsQuestUnobtainable(x)); - bool hasAcceptQuestConditions = _configuration.Stop.Enabled && - _configuration.Stop.QuestsToStopWhenAccepted.Any(x => - !_questFunctions.IsQuestAcceptedOrComplete(x) && - !_questFunctions.IsQuestUnobtainable(x)); - - List priorityQuests = _questFunctions.NextPriorityQuestsThatCanBeAccepted; + bool hasLevelCondition = configuration.Stop.Enabled && configuration.Stop.LevelToStopAfter; + bool hasCompleteQuestConditions = configuration.Stop.Enabled && + configuration.Stop.QuestsToStopAfter.Any(x => + !questFunctions.IsQuestComplete(x) && + !questFunctions.IsQuestUnobtainable(x)); + bool hasAcceptQuestConditions = configuration.Stop.Enabled && + configuration.Stop.QuestsToStopWhenAccepted.Any(x => + !questFunctions.IsQuestAcceptedOrComplete(x) && + !questFunctions.IsQuestUnobtainable(x)); + + List priorityQuests = questFunctions.NextPriorityQuestsThatCanBeAccepted; bool anyAvailable = false; bool anyUnavailable = false; foreach (var p in priorityQuests) @@ -306,7 +312,7 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, unsafe { short currentLevel = PlayerState.Instance()->CurrentLevel; - if (currentLevel > 0 && currentLevel >= _configuration.Stop.TargetLevel) + if (currentLevel > 0 && currentLevel >= configuration.Stop.TargetLevel) iconColor = QstTheme.Success; else if (currentLevel > 0) iconColor = QstTheme.Info; @@ -326,11 +332,11 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, unsafe { int currentLevel = PlayerState.Instance()->CurrentLevel; - ImGui.BulletText(_LF("Stop at level {0}", _configuration.Stop.TargetLevel)); + ImGui.BulletText(_LF("Stop at level {0}", configuration.Stop.TargetLevel)); if (currentLevel > 0) { ImGui.SameLine(); - if (currentLevel >= _configuration.Stop.TargetLevel) + if (currentLevel >= configuration.Stop.TargetLevel) ImGui.TextColored(QstTheme.Success, _LF("(Current: {0} - Reached!)", currentLevel)); else ImGui.TextColored(QstTheme.Info, _LF("(Current: {0})", currentLevel)); @@ -346,12 +352,12 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, ImGui.BulletText(_L("Stop after completing any of these quests:")); ImGui.Indent(); - foreach (ElementId questId in _configuration.Stop.QuestsToStopAfter) + foreach (ElementId questId in configuration.Stop.QuestsToStopAfter) { - if (_questRegistry.TryGetQuest(questId, out Quest? quest)) + if (questRegistry.TryGetQuest(questId, out Quest? quest)) { - (Vector4 color, FontAwesomeIcon icon, string _) = _uiUtils.GetQuestStyle(questId); - _uiUtils.ChecklistItem($"{quest.Info.Name} ({questId})", color, icon); + (Vector4 color, FontAwesomeIcon icon, string _) = uiUtils.GetQuestStyle(questId); + uiUtils.ChecklistItem($"{quest.Info.Name} ({questId})", color, icon); } } @@ -365,12 +371,12 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, ImGui.BulletText(_L("Stop after accepting any of these quests:")); ImGui.Indent(); - foreach (ElementId questId in _configuration.Stop.QuestsToStopWhenAccepted) + foreach (ElementId questId in configuration.Stop.QuestsToStopWhenAccepted) { - if (_questRegistry.TryGetQuest(questId, out Quest? quest)) + if (questRegistry.TryGetQuest(questId, out Quest? quest)) { - (Vector4 color, FontAwesomeIcon icon, string _) = _uiUtils.GetQuestStyle(questId); - _uiUtils.ChecklistItem($"{quest.Info.Name} ({questId})", color, icon); + (Vector4 color, FontAwesomeIcon icon, string _) = uiUtils.GetQuestStyle(questId); + uiUtils.ChecklistItem($"{quest.Info.Name} ({questId})", color, icon); } } @@ -403,7 +409,7 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, { foreach (ElementId questId in availablePriorityQuests) { - if (_questRegistry.TryGetQuest(questId, out Quest? quest)) + if (questRegistry.TryGetQuest(questId, out Quest? quest)) ImGui.BulletText($"{quest.Info.Name} ({questId})"); } } @@ -415,7 +421,7 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, ImGui.Text(_L("Unavailable priority quests:")); foreach ((ElementId questId, string? reason) in unavailablePriorityQuests) { - if (_questRegistry.TryGetQuest(questId, out Quest? quest)) + if (questRegistry.TryGetQuest(questId, out Quest? quest)) ImGui.BulletText($"{quest.Info.Name} ({questId}) - {reason}"); } } @@ -442,7 +448,7 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, } } - QuestController.QuestProgress? nextQuest = _questController.NextQuest; + QuestController.QuestProgress? nextQuest = questController.NextQuest; if (nextQuest != null) { using ImRaii.ColorDisposable _ = ImRaii.PushColor(ImGuiCol.Text, QstTheme.Amber); @@ -485,7 +491,7 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, { string progressText = MultipleWhitespaceRegex().Replace(questWork.ToString(), " "); ImGui.SetClipboardText(progressText); - _chatGui.Print(_LF("Copied '{0}' to clipboard", progressText)); + chatGui.Print(_LF("Copied '{0}' to clipboard", progressText)); } if (ImGui.IsItemHovered()) @@ -508,7 +514,7 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, { using ImRaii.DisabledDisposable disabled = ImRaii.Disabled(); - if (currentQuest.Quest.Id == _questController.NextQuest?.Quest.Id) + if (currentQuest.Quest.Id == questController.NextQuest?.Quest.Id) ImGui.TextUnformatted(_L("(Next quest in story line not accepted)")); else ImGui.TextUnformatted(_L("(Not accepted)")); @@ -520,21 +526,21 @@ private void DrawQuestNames(QuestController.QuestProgress currentQuest, private void DrawQuestButtons(QuestController.QuestProgress currentQuest, QuestStep? currentStep, QuestProgressInfo? questProgressInfo, bool isMinimized) { - using (ImRaii.Disabled(_questController.IsRunning)) + using (ImRaii.Disabled(questController.IsRunning)) { if (ImGuiComponentsLocal.IconButton(FontAwesomeIcon.Play, QstTheme.Accent)) { // if we haven't accepted this quest, mark it as next quest so that we can optionally use aetherytes to travel if (questProgressInfo == null) - _questController.SetNextQuest(currentQuest.Quest); + questController.SetNextQuest(currentQuest.Quest); - _questController.Start(_L("UI start")); + questController.Start(_L("UI start")); } ImGui.SameLine(); if (ImGuiComponentsLocal.IconButtonWithText(FontAwesomeIcon.StepForward, _L("Step"))) - _questController.StartSingleStep(_L("UI step")); + questController.StartSingleStep(_L("UI step")); if (ImGui.IsItemHovered()) ImGui.SetTooltip(_L("Execute next step and then stop.")); } @@ -543,50 +549,22 @@ private void DrawQuestButtons(QuestController.QuestProgress currentQuest, QuestS if (ImGuiComponentsLocal.IconButton(FontAwesomeIcon.Stop)) { - _movementController.Stop(); - _questController.Stop(_L("UI stop")); - _gatheringController.Stop(_L("UI stop")); + movementController.Stop(); + questController.Stop(_L("UI stop")); + gatheringController.Stop(_L("UI stop")); } if (ImGui.IsItemHovered()) ImGui.SetTooltip(_L("Stop all actions now.")); - using (ImRaii.Disabled(!_questController.IsRunning)) - { - ImGui.SameLine(); - - bool anyStopArmed = _questController.StopAfterCurrentQuest - || _questController.StopAfterAcceptingNextQuest - || _questController.StopBeforeTeleport; - using (QstWidgets.SegmentGroup(anyStopArmed)) - { - if (QstWidgets.SegmentToggle(FontAwesomeIcon.FlagCheckered, _questController.StopAfterCurrentQuest, - _L("Cancel scheduled stop after current quest."), - _L("Stop after the current quest completes."))) - _questController.StopAfterCurrentQuest = !_questController.StopAfterCurrentQuest; - - ImGui.SameLine(); - - if (QstWidgets.SegmentToggle(FontAwesomeIcon.Check, _questController.StopAfterAcceptingNextQuest, - _L("Cancel scheduled stop after accepting the next quest."), - _L("Stop after accepting the next quest."))) - _questController.StopAfterAcceptingNextQuest = !_questController.StopAfterAcceptingNextQuest; - - if (!isMinimized) - ImGui.SameLine(); - - if (QstWidgets.SegmentToggle(FontAwesomeIcon.MapMarkerAlt, _questController.StopBeforeTeleport, - _L("Cancel scheduled stop before teleport."), - _L("Stop before the next aetheryte teleport or item use."))) - _questController.StopBeforeTeleport = !_questController.StopBeforeTeleport; - } - } + ImGui.SameLine(); + quickAccessButtonsComponent.DrawPriorityQuestsButton(); + ImGui.SameLine(); + quickAccessButtonsComponent.DrawJournalProgressButton(); + ImGui.SameLine(); + quickAccessButtonsComponent.DrawTroubleshootingButton(showLabel: true); if (isMinimized) - { - ImGui.SameLine(); - if (ImGuiComponentsLocal.IconButton(FontAwesomeIcon.RedoAlt)) - Reload?.Invoke(this, EventArgs.Empty); - } + quickAccessButtonsComponent.DrawReloadDataButton(); else { bool lastStep = currentStep == @@ -594,7 +572,7 @@ private void DrawQuestButtons(QuestController.QuestProgress currentQuest, QuestS bool colored = currentStep != null && !lastStep && currentStep.InteractionType == EInteractionType.Instruction - && _questController.HasCurrentTaskMatching(out WaitAtEnd.WaitNextStepOrSequence? _); + && questController.HasCurrentTaskMatching(out WaitAtEnd.WaitNextStepOrSequence? _); using (ImRaii.Disabled(lastStep)) { @@ -602,8 +580,8 @@ private void DrawQuestButtons(QuestController.QuestProgress currentQuest, QuestS { if (ImGuiComponentsLocal.IconButtonWithText(FontAwesomeIcon.ArrowCircleRight, _L("Skip"))) { - _movementController.Stop(); - _questController.Skip(currentQuest.Quest.Id, currentQuest.Sequence); + movementController.Stop(); + questController.Skip(currentQuest.Quest.Id, currentQuest.Sequence); } if (ImGui.IsItemHovered()) @@ -611,24 +589,53 @@ private void DrawQuestButtons(QuestController.QuestProgress currentQuest, QuestS } } - if (_commandManager.Commands.ContainsKey("/questinfo")) + if (commandManager.Commands.ContainsKey("/questinfo")) { ImGui.SameLine(); if (ImGuiComponentsLocal.IconButton(FontAwesomeIcon.Atlas)) - _commandManager.ProcessCommand($"/questinfo {currentQuest.Quest.Id}"); + commandManager.ProcessCommand($"/questinfo {currentQuest.Quest.Id}"); if (ImGui.IsItemHovered()) ImGui.SetTooltip(_LF("Show information about '{0}' in Quest Map plugin.", currentQuest.Quest.Info.Name)); } } + + using (ImRaii.Disabled(!questController.IsRunning)) + { + ImGui.SameLine(); + bool anyStopArmed = questController.StopAfterCurrentQuest + || questController.StopAfterAcceptingNextQuest + || questController.StopBeforeTeleport; + using (QstWidgets.SegmentGroup(anyStopArmed)) + { + if (QstWidgets.SegmentToggle(FontAwesomeIcon.FlagCheckered, questController.StopAfterCurrentQuest, + _L("Cancel scheduled stop after current quest."), + _L("Stop after the current quest completes."))) + questController.StopAfterCurrentQuest = !questController.StopAfterCurrentQuest; + + ImGui.SameLine(); + + if (QstWidgets.SegmentToggle(FontAwesomeIcon.Check, questController.StopAfterAcceptingNextQuest, + _L("Cancel scheduled stop after accepting the next quest."), + _L("Stop after accepting the next quest."))) + questController.StopAfterAcceptingNextQuest = !questController.StopAfterAcceptingNextQuest; + + ImGui.SameLine(); + + if (QstWidgets.SegmentToggle(FontAwesomeIcon.MapMarkerAlt, questController.StopBeforeTeleport, + _L("Cancel scheduled stop before teleport."), + _L("Stop before the next aetheryte teleport or item use."))) + questController.StopBeforeTeleport = !questController.StopBeforeTeleport; + } + } } private void DrawSimulationControls() { - if (_questController.SimulatedQuest == null) + if (questController.SimulatedQuest == null) return; - QuestController.QuestProgress? simulatedQuest = _questController.SimulatedQuest; + QuestController.QuestProgress? simulatedQuest = questController.SimulatedQuest; ImGui.Separator(); ImGui.TextColored(QstTheme.Danger, _L("Quest sim active (experimental)")); @@ -638,15 +645,15 @@ private void DrawSimulationControls() { if (ImGuiComponentsLocal.IconButton(FontAwesomeIcon.Minus)) { - _movementController.Stop(); - _questController.Stop("Sim-"); + movementController.Stop(); + questController.Stop("Sim-"); byte oldSequence = simulatedQuest.Sequence; byte newSequence = simulatedQuest.Quest.Root.QuestSequence .Select(x => x.Sequence) .LastOrDefault(x => x < oldSequence, byte.MinValue); - _questController.SimulatedQuest.SetSequence(newSequence); + questController.SimulatedQuest.SetSequence(newSequence); } } @@ -655,8 +662,8 @@ private void DrawSimulationControls() { if (ImGuiComponentsLocal.IconButton(FontAwesomeIcon.Plus)) { - _movementController.Stop(); - _questController.Stop("Sim+"); + movementController.Stop(); + questController.Stop("Sim+"); byte oldSequence = simulatedQuest.Sequence; byte newSequence = simulatedQuest.Quest.Root.QuestSequence @@ -678,8 +685,8 @@ private void DrawSimulationControls() { if (ImGuiComponentsLocal.IconButton(FontAwesomeIcon.Minus)) { - _movementController.Stop(); - _questController.Stop("SimStep-"); + movementController.Stop(); + questController.Stop("SimStep-"); simulatedQuest.SetStep(Math.Min(simulatedQuest.Step - 1, simulatedSequence.Steps.Count - 1)); @@ -691,8 +698,8 @@ private void DrawSimulationControls() { if (ImGuiComponentsLocal.IconButton(FontAwesomeIcon.Plus)) { - _movementController.Stop(); - _questController.Stop("SimStep+"); + movementController.Stop(); + questController.Stop("SimStep+"); simulatedQuest.SetStep( simulatedQuest.Step == simulatedSequence.Steps.Count - 1 @@ -702,29 +709,29 @@ private void DrawSimulationControls() } if (ImGui.Button(_L("Skip current task"))) - _questController.SkipSimulatedTask(); + questController.SkipSimulatedTask(); ImGui.SameLine(); if (ImGui.Button(_L("Clear sim"))) { - _questController.StopSimulate(); + questController.StopSimulate(); - _movementController.Stop(); - _questController.Stop(_L("Clear sim")); + movementController.Stop(); + questController.Stop(_L("Clear sim")); } } } public void DrawTitleBarPill(string windowTitle) { - if (_combatController.IsRunning) + if (combatController.IsRunning) QstWidgets.TitleBarPill(_L("Combat"), QstTheme.Accent, windowTitle); - else if (_questController.IsRunning - && (_questController.StopAfterCurrentQuest - || _questController.StopAfterAcceptingNextQuest - || _questController.StopBeforeTeleport)) + else if (questController.IsRunning + && (questController.StopAfterCurrentQuest + || questController.StopAfterAcceptingNextQuest + || questController.StopBeforeTeleport)) QstWidgets.TitleBarPill(_L("Stopping"), QstTheme.Amber, windowTitle); - else if (_questController.IsRunning) + else if (questController.IsRunning) QstWidgets.TitleBarPill(_L("Running"), QstTheme.Success, windowTitle); else QstWidgets.TitleBarPill(_L("Idle"), QstTheme.TextMuted, windowTitle); diff --git a/Questionable/Windows/QuestComponents/CreationUtilsComponent.cs b/Questionable/Windows/QuestComponents/CreationUtilsComponent.cs index 6cb3bc013..6251a9485 100644 --- a/Questionable/Windows/QuestComponents/CreationUtilsComponent.cs +++ b/Questionable/Windows/QuestComponents/CreationUtilsComponent.cs @@ -12,8 +12,8 @@ using FFXIVClientStructs.FFXIV.Client.Game.UI; using Questionable.Model.Common; using Questionable.Model.Questing; -using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; using Questionable.Windows.Common.Ui; +using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; namespace Questionable.Windows.QuestComponents; diff --git a/Questionable/Windows/QuestComponents/QuickAccessButtonsComponent.cs b/Questionable/Windows/QuestComponents/QuickAccessButtonsComponent.cs index cd9d38de0..5d7fa7bed 100644 --- a/Questionable/Windows/QuestComponents/QuickAccessButtonsComponent.cs +++ b/Questionable/Windows/QuestComponents/QuickAccessButtonsComponent.cs @@ -3,8 +3,6 @@ using Dalamud.Bindings.ImGui; using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Interface; -using Dalamud.Interface.Utility; -using Dalamud.Interface.Utility.Raii; using Questionable.Controller.Steps.Shared; using Questionable.Model.Questing; using Questionable.Windows.Common.Ui; @@ -28,15 +26,9 @@ internal sealed class QuickAccessButtonsComponent public void Draw() { - DrawPriorityQuestsButton(); - ImGui.SameLine(); - DrawJournalProgressButton(); - ImGui.SameLine(); DrawReloadDataButton(); ImGui.SameLine(); DrawRebuildNavmeshButton(); - ImGui.SameLine(); - DrawTroubleshootingButton(questController.CurrentQuest, questController.IsRunning); if (pluginInterface.IsDev) { @@ -45,45 +37,52 @@ public void Draw() } } - private void DrawPriorityQuestsButton() + internal void DrawPriorityQuestsButton(bool showLabel = false) { if (QstWidgets.RailButton(FontAwesomeIcon.ExclamationCircle, _L("Priority Quests"), _L("Configure priority quests which will be done as soon as possible."), - enabled: objectTable[0] != null)) + enabled: objectTable[0] != null, + showLabel: showLabel)) priorityWindow.ToggleOrUncollapse(); } - private void DrawRebuildNavmeshButton() + internal void DrawRebuildNavmeshButton(bool showLabel = false) { bool isNavmeshAvailable = commandManager.Commands.ContainsKey("/vnav"); string tooltip = isNavmeshAvailable ? _L("Hold CTRL to enable this button. Rebuilding the navmesh will take some time.") : _L("vnavmesh is not available. Please install it first."); if (QstWidgets.RailButton(FontAwesomeIcon.GlobeEurope, _L("Rebuild Navmesh"), tooltip, - enabled: isNavmeshAvailable && ImGui.IsKeyDown(ImGuiKey.ModCtrl))) + enabled: isNavmeshAvailable && ImGui.IsKeyDown(ImGuiKey.ModCtrl), + showLabel: showLabel)) commandManager.ProcessCommand("/vnav rebuild"); } - private void DrawReloadDataButton() + internal void DrawReloadDataButton(bool showLabel = false) { - if (QstWidgets.RailButton(FontAwesomeIcon.RedoAlt, _L("Reload Data"))) + if (QstWidgets.RailButton(FontAwesomeIcon.RedoAlt, _L("Reload Data"), + showLabel: showLabel)) Reload?.Invoke(this, EventArgs.Empty); } - private void DrawJournalProgressButton() + internal void DrawJournalProgressButton(bool showLabel = false) { - if (QstWidgets.RailButton(FontAwesomeIcon.BookBookmark, _L("Journal Progress"))) + if (QstWidgets.RailButton(FontAwesomeIcon.BookBookmark, _L("Journal Progress"), + showLabel: showLabel)) journalProgressWindow.ToggleOrUncollapse(); } - private void DrawTroubleshootingButton(QuestController.QuestProgress? questProgress, bool isRunning) + internal void DrawTroubleshootingButton(bool showLabel = false, bool highlighted = false) { + QuestController.QuestProgress? questProgress = questController.CurrentQuest; + bool isRunning = highlighted || questController.IsRunning; bool leftClicked = QstWidgets.RailButton(FontAwesomeIcon.Handshake, _L("Stuck?"), _L("Left click: Copy troubleshooting information to clipboard\nRight click: Copy list of completed quests to clipboard"), tint: isRunning ? QstTheme.Accent : null, - enabled: objectTable[0] != null); + enabled: objectTable[0] != null, + showLabel: showLabel); bool rightClicked = ImGui.IsItemClicked(ImGuiMouseButton.Right); if (leftClicked || rightClicked) { @@ -154,7 +153,7 @@ private void DrawTroubleshootingButton(QuestController.QuestProgress? questProgr } } - private void DrawValidationIssuesButton() + internal void DrawValidationIssuesButton(bool showLabel = false) { int errorCount = questRegistry.ValidationErrorCount; int infoCount = questRegistry.ValidationIssueCount - questRegistry.ValidationErrorCount; @@ -163,7 +162,8 @@ private void DrawValidationIssuesButton() if (QstWidgets.RailButton(hasErrors ? FontAwesomeIcon.ExclamationTriangle : FontAwesomeIcon.InfoCircle, _L("Quest Validation"), _LF("Quest validation: {0} errors, {1} infos", errorCount, infoCount), - tint: hasErrors ? QstTheme.Danger : QstTheme.Info)) + tint: hasErrors ? QstTheme.Danger : QstTheme.Info, + showLabel: showLabel)) questValidationWindow.ToggleOrUncollapse(); } } diff --git a/Questionable/Windows/QuestComponents/RemainingTasksComponent.cs b/Questionable/Windows/QuestComponents/RemainingTasksComponent.cs index 471fa0f79..b1ac91d7b 100644 --- a/Questionable/Windows/QuestComponents/RemainingTasksComponent.cs +++ b/Questionable/Windows/QuestComponents/RemainingTasksComponent.cs @@ -17,8 +17,6 @@ public void Draw() IList gatheringTasks = gatheringController.GetRemainingTaskNames(); bool isGathering = gatheringTasks.Count > 0; IList tasks = isGathering ? gatheringTasks : questController.GetRemainingTaskNames(); - if (tasks.Count == 0) - return; if (!QstWidgets.SectionHeader(_L("Remaining Tasks"), "RemainingTasks", count: tasks.Count)) return; diff --git a/Questionable/Windows/QuestWindow.cs b/Questionable/Windows/QuestWindow.cs index ae32bfba0..83cc0632d 100644 --- a/Questionable/Windows/QuestWindow.cs +++ b/Questionable/Windows/QuestWindow.cs @@ -102,7 +102,6 @@ public QuestWindow(IDalamudPluginInterface pluginInterface, } }); - _activeQuestComponent.Reload += OnReload; _quickAccessButtonsComponent.Reload += OnReload; _questController.IsQuestWindowOpenFunction = () => IsOpen; }