From 4e427e43099a71dac8858b0d8675087f5f01807f Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Thu, 23 Jan 2025 01:31:17 +0100 Subject: [PATCH 01/14] Minor ARR updates --- .../Class Quests/WAR/1052_Looking the Part.json | 13 +++++++++++-- .../C6-Mor Dhona/1001_Drowning Out the Voices.json | 5 ++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/WAR/1052_Looking the Part.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/WAR/1052_Looking the Part.json index a3ae2649..59241a3d 100644 --- a/QuestPaths/2.x - A Realm Reborn/Class Quests/WAR/1052_Looking the Part.json +++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/WAR/1052_Looking the Part.json @@ -112,9 +112,18 @@ "SkipConditions": { "AetheryteShortcutIf": { "InSameTerritory": true + }, + "StepIf": { + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 64 + ] } - }, - "Comment": "TODO Verify enemy id" + } }, { "DataId": 2002309, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1001_Drowning Out the Voices.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1001_Drowning Out the Voices.json index 1fcf9d81..59a79e75 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1001_Drowning Out the Voices.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1001_Drowning Out the Voices.json @@ -51,6 +51,7 @@ }, "TerritoryId": 156, "InteractionType": "Combat", + "DelaySecondsAtStart": 2, "EnemySpawnType": "AfterItemUse", "ItemId": 2000766, "KillEnemyDataIds": [ @@ -180,6 +181,7 @@ }, "TerritoryId": 156, "InteractionType": "Combat", + "DelaySecondsAtStart": 2, "EnemySpawnType": "AfterItemUse", "ItemId": 2000766, "KillEnemyDataIds": [ @@ -238,7 +240,8 @@ }, "TerritoryId": 156, "InteractionType": "UseItem", - "ItemId": 2000766 + "ItemId": 2000766, + "DelaySecondsAtStart": 2 } ] }, From 4f61ea45edf3c31d9d3455baf8425b9f73f92899 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Thu, 23 Jan 2025 01:43:09 +0100 Subject: [PATCH 02/14] Update colors for some specific status/error messages --- Questionable/Controller/MiniTaskController.cs | 4 ++-- Questionable/Controller/QuestController.cs | 2 +- Questionable/Controller/Steps/Interactions/AetherCurrent.cs | 3 ++- .../Controller/Steps/Interactions/EquipRecommended.cs | 5 +++-- Questionable/Controller/Steps/Shared/AetheryteShortcut.cs | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Questionable/Controller/MiniTaskController.cs b/Questionable/Controller/MiniTaskController.cs index c9aec197..949c1915 100644 --- a/Questionable/Controller/MiniTaskController.cs +++ b/Questionable/Controller/MiniTaskController.cs @@ -68,7 +68,7 @@ internal abstract class MiniTaskController : IDisposable { _logger.LogError(e, "Failed to start task {TaskName}", upcomingTask.ToString()); _chatGui.PrintError( - $"[Questionable] Failed to start task '{upcomingTask}', please check /xllog for details."); + $"Failed to start task '{upcomingTask}', please check /xllog for details.", CommandHandler.MessageTag, CommandHandler.TagColor); Stop("Task failed to start"); return; } @@ -93,7 +93,7 @@ internal abstract class MiniTaskController : IDisposable _logger.LogError(e, "Failed to update task {TaskName}", _taskQueue.CurrentTaskExecutor.CurrentTask.ToString()); _chatGui.PrintError( - $"[Questionable] Failed to update task '{_taskQueue.CurrentTaskExecutor.CurrentTask}', please check /xllog for details."); + $"Failed to update task '{_taskQueue.CurrentTaskExecutor.CurrentTask}', please check /xllog for details.", CommandHandler.MessageTag, CommandHandler.TagColor); Stop("Task failed to update"); return; } diff --git a/Questionable/Controller/QuestController.cs b/Questionable/Controller/QuestController.cs index d514f267..2c522556 100644 --- a/Questionable/Controller/QuestController.cs +++ b/Questionable/Controller/QuestController.cs @@ -623,7 +623,7 @@ internal sealed class QuestController : MiniTaskController, IDi catch (Exception e) { _logger.LogError(e, "Failed to create tasks"); - _chatGui.PrintError("[Questionable] Failed to start next task sequence, please check /xllog for details."); + _chatGui.PrintError("Failed to start next task sequence, please check /xllog for details.", CommandHandler.MessageTag, CommandHandler.TagColor); Stop("Tasks failed to create"); } } diff --git a/Questionable/Controller/Steps/Interactions/AetherCurrent.cs b/Questionable/Controller/Steps/Interactions/AetherCurrent.cs index 7632e574..7c1f6338 100644 --- a/Questionable/Controller/Steps/Interactions/AetherCurrent.cs +++ b/Questionable/Controller/Steps/Interactions/AetherCurrent.cs @@ -26,7 +26,8 @@ internal static class AetherCurrent if (!aetherCurrentData.IsValidAetherCurrent(step.TerritoryId, step.AetherCurrentId.Value)) { chatGui.PrintError( - $"[Questionable] Aether current with id {step.AetherCurrentId} is referencing an invalid aether current, will skip attunement"); + $"Aether current with id {step.AetherCurrentId} is referencing an invalid aether current, will skip attunement", + CommandHandler.MessageTag, CommandHandler.TagColor); return null; } diff --git a/Questionable/Controller/Steps/Interactions/EquipRecommended.cs b/Questionable/Controller/Steps/Interactions/EquipRecommended.cs index 295bb8cc..3e008cca 100644 --- a/Questionable/Controller/Steps/Interactions/EquipRecommended.cs +++ b/Questionable/Controller/Steps/Interactions/EquipRecommended.cs @@ -40,7 +40,8 @@ internal static class EquipRecommended public override string ToString() => "EquipRecommended"; } - internal sealed unsafe class DoEquipRecommended(IClientState clientState, IChatGui chatGui, ICondition condition) : TaskExecutor + internal sealed unsafe class DoEquipRecommended(IClientState clientState, IChatGui chatGui, ICondition condition) + : TaskExecutor { private bool _equipped; @@ -88,7 +89,7 @@ internal static class EquipRecommended if (!isAllEquipped) { - chatGui.Print("Equipping recommended gear.", "Questionable"); + chatGui.Print("Equipping recommended gear.", CommandHandler.MessageTag, CommandHandler.TagColor); recommendedEquipModule->EquipRecommendedGear(); } diff --git a/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs b/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs index b2748b18..4a56e929 100644 --- a/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs +++ b/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs @@ -201,7 +201,7 @@ internal static class AetheryteShortcut if (!aetheryteFunctions.IsAetheryteUnlocked(Task.TargetAetheryte)) { - chatGui.PrintError($"[Questionable] Aetheryte {Task.TargetAetheryte} is not unlocked."); + chatGui.PrintError($"Aetheryte {Task.TargetAetheryte} is not unlocked.", CommandHandler.MessageTag, CommandHandler.TagColor); throw new TaskException("Aetheryte is not unlocked"); } @@ -215,7 +215,7 @@ internal static class AetheryteShortcut } else { - chatGui.Print("[Questionable] Unable to teleport to aetheryte."); + chatGui.Print("Unable to teleport to aetheryte.", CommandHandler.MessageTag, CommandHandler.TagColor); throw new TaskException("Unable to teleport to aetheryte"); } } From 7731dd065898e98f06222dab9dfea7033ab5fadd Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Fri, 24 Jan 2025 19:40:36 +0100 Subject: [PATCH 03/14] Use Vesper Bay aetheryte tickets for 'Operation Archon' if you left the Waking Sands --- .../4521_Operation Archon.json | 83 ++++++++++++++++++- QuestPaths/quest-v1.json | 1 + .../Converter/SkipConditionConverter.cs | 1 + .../Questing/EExtraSkipCondition.cs | 1 + .../Controller/Steps/Shared/SkipCondition.cs | 1 + 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4521_Operation Archon.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4521_Operation Archon.json index 81c32c86..d470701a 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4521_Operation Archon.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4521_Operation Archon.json @@ -5,6 +5,71 @@ { "Sequence": 0, "Steps": [ + { + "TerritoryId": 132, + "InteractionType": "UseItem", + "ItemId": 30362, + "TargetTerritoryId": 140, + "SkipConditions": { + "StepIf": { + "InTerritory": [ + 140, + 212 + ] + } + } + }, + { + "Position": { + "X": -492.96475, + "Y": 20.999884, + "Z": -380.82272 + }, + "TerritoryId": 140, + "InteractionType": "WalkTo", + "$": "Avoid walking around Waking Sands table", + "SkipConditions": { + "StepIf": { + "InTerritory": [ + 212 + ] + } + } + }, + { + "DataId": 2001715, + "Position": { + "X": 23.23944, + "Y": 2.090454, + "Z": -0.015319824 + }, + "TerritoryId": 212, + "InteractionType": "Interact", + "TargetTerritoryId": 212, + "SkipConditions": { + "StepIf": { + "ExtraCondition": "WakingSandsSolar" + } + } + }, + { + "DataId": 2001711, + "Position": { + "X": -480.9181, + "Y": 18.00103, + "Z": -386.862 + }, + "TerritoryId": 140, + "InteractionType": "Interact", + "TargetTerritoryId": 212, + "SkipConditions": { + "StepIf": { + "InTerritory": [ + 212 + ] + } + } + }, { "DataId": 1006690, "Position": { @@ -29,7 +94,14 @@ }, "TerritoryId": 212, "InteractionType": "Interact", - "TargetTerritoryId": 212 + "TargetTerritoryId": 212, + "SkipConditions": { + "StepIf": { + "InTerritory": [ + 140 + ] + } + } }, { "DataId": 2001716, @@ -40,7 +112,14 @@ }, "TerritoryId": 212, "InteractionType": "Interact", - "TargetTerritoryId": 140 + "TargetTerritoryId": 140, + "SkipConditions": { + "StepIf": { + "InTerritory": [ + 140 + ] + } + } }, { "DataId": 1006578, diff --git a/QuestPaths/quest-v1.json b/QuestPaths/quest-v1.json index f0f82637..d1c1b23c 100644 --- a/QuestPaths/quest-v1.json +++ b/QuestPaths/quest-v1.json @@ -292,6 +292,7 @@ "type": "string", "enum": [ "WakingSandsMainArea", + "WakingSandsSolar", "RisingStonesSolar", "RoguesGuild", "DockStorehouse" diff --git a/Questionable.Model/Questing/Converter/SkipConditionConverter.cs b/Questionable.Model/Questing/Converter/SkipConditionConverter.cs index 3de919b9..eb917950 100644 --- a/Questionable.Model/Questing/Converter/SkipConditionConverter.cs +++ b/Questionable.Model/Questing/Converter/SkipConditionConverter.cs @@ -8,6 +8,7 @@ public sealed class SkipConditionConverter() : EnumConverter Values = new() { { EExtraSkipCondition.WakingSandsMainArea, "WakingSandsMainArea" }, + { EExtraSkipCondition.WakingSandsSolar, "WakingSandsSolar" }, { EExtraSkipCondition.RisingStonesSolar, "RisingStonesSolar"}, { EExtraSkipCondition.RoguesGuild, "RoguesGuild"}, { EExtraSkipCondition.DockStorehouse, "DockStorehouse"}, diff --git a/Questionable.Model/Questing/EExtraSkipCondition.cs b/Questionable.Model/Questing/EExtraSkipCondition.cs index d9d7b0be..8ec77d49 100644 --- a/Questionable.Model/Questing/EExtraSkipCondition.cs +++ b/Questionable.Model/Questing/EExtraSkipCondition.cs @@ -8,6 +8,7 @@ public enum EExtraSkipCondition { None, WakingSandsMainArea, + WakingSandsSolar, RisingStonesSolar, /// diff --git a/Questionable/Controller/Steps/Shared/SkipCondition.cs b/Questionable/Controller/Steps/Shared/SkipCondition.cs index ebf1dc1f..bd953539 100644 --- a/Questionable/Controller/Steps/Shared/SkipCondition.cs +++ b/Questionable/Controller/Steps/Shared/SkipCondition.cs @@ -307,6 +307,7 @@ internal static class SkipCondition return condition switch { EExtraSkipCondition.WakingSandsMainArea => territoryType == 212 && position.X < 24, + EExtraSkipCondition.WakingSandsSolar => territoryType == 212 && position.X >= 24, EExtraSkipCondition.RisingStonesSolar => territoryType == 351 && position.Z <= -28, EExtraSkipCondition.RoguesGuild => territoryType == 129 && position.Y <= -115, EExtraSkipCondition.DockStorehouse => territoryType == 137 && position.Y <= -20, From d85b204c791e2e869c9954347f84afbd74be48ad Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Fri, 24 Jan 2025 19:53:20 +0100 Subject: [PATCH 04/14] Automatically close job bar tutorials + Lv49 novice guide --- .../Controller/GameUi/HelpUiController.cs | 61 ++++++++++++++++++- Questionable/Controller/MiniTaskController.cs | 17 ++++++ Questionable/Controller/QuestController.cs | 4 ++ 3 files changed, 80 insertions(+), 2 deletions(-) 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 From 2ebc4b5a0d7882559e93dbdece72be700163ec15 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Fri, 24 Jan 2025 20:04:32 +0100 Subject: [PATCH 05/14] Fix 'Operation Archon' step order --- .../4521_Operation Archon.json | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4521_Operation Archon.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4521_Operation Archon.json index d470701a..2f33376f 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4521_Operation Archon.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4521_Operation Archon.json @@ -36,22 +36,6 @@ } } }, - { - "DataId": 2001715, - "Position": { - "X": 23.23944, - "Y": 2.090454, - "Z": -0.015319824 - }, - "TerritoryId": 212, - "InteractionType": "Interact", - "TargetTerritoryId": 212, - "SkipConditions": { - "StepIf": { - "ExtraCondition": "WakingSandsSolar" - } - } - }, { "DataId": 2001711, "Position": { @@ -70,6 +54,22 @@ } } }, + { + "DataId": 2001715, + "Position": { + "X": 23.23944, + "Y": 2.090454, + "Z": -0.015319824 + }, + "TerritoryId": 212, + "InteractionType": "Interact", + "TargetTerritoryId": 212, + "SkipConditions": { + "StepIf": { + "ExtraCondition": "WakingSandsSolar" + } + } + }, { "DataId": 1006690, "Position": { From ffccd347bd9e9affff348bf00597bd06ddef5c3b Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Fri, 24 Jan 2025 20:30:58 +0100 Subject: [PATCH 06/14] Add a delay to equipping recommended gear for specific instances where ilvl calculation would otherwise be off --- .../Steps/Interactions/EquipRecommended.cs | 68 +++++++++++-------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/Questionable/Controller/Steps/Interactions/EquipRecommended.cs b/Questionable/Controller/Steps/Interactions/EquipRecommended.cs index 3e008cca..a71cc3b0 100644 --- a/Questionable/Controller/Steps/Interactions/EquipRecommended.cs +++ b/Questionable/Controller/Steps/Interactions/EquipRecommended.cs @@ -43,7 +43,8 @@ internal static class EquipRecommended internal sealed unsafe class DoEquipRecommended(IClientState clientState, IChatGui chatGui, ICondition condition) : TaskExecutor { - private bool _equipped; + private bool _checkedOrTriggeredEquipmentUpdate; + private DateTime _continueAt = DateTime.MinValue; protected override bool Start() { @@ -60,44 +61,51 @@ internal static class EquipRecommended if (recommendedEquipModule->IsUpdating) return ETaskResult.StillRunning; - if (!_equipped) + if (!_checkedOrTriggeredEquipmentUpdate) { - InventoryManager* inventoryManager = InventoryManager.Instance(); - InventoryContainer* equippedItems = - inventoryManager->GetInventoryContainer(InventoryType.EquippedItems); - bool isAllEquipped = true; - foreach (var recommendedItemPtr in recommendedEquipModule->RecommendedItems) - { - var recommendedItem = recommendedItemPtr.Value; - if (recommendedItem == null || recommendedItem->ItemId == 0) - continue; - - bool isEquipped = false; - for (int i = 0; i < equippedItems->Size; ++i) - { - var equippedItem = equippedItems->Items[i]; - if (equippedItem.ItemId != 0 && equippedItem.ItemId == recommendedItem->ItemId) - { - isEquipped = true; - break; - } - } - - if (!isEquipped) - isAllEquipped = false; - } - - if (!isAllEquipped) + if (!IsAllRecommendeGearEquipped()) { chatGui.Print("Equipping recommended gear.", CommandHandler.MessageTag, CommandHandler.TagColor); recommendedEquipModule->EquipRecommendedGear(); + _continueAt = DateTime.Now.AddSeconds(1); } - _equipped = true; + _checkedOrTriggeredEquipmentUpdate = true; return ETaskResult.StillRunning; } - return ETaskResult.TaskComplete; + return DateTime.Now >= _continueAt ? ETaskResult.TaskComplete : ETaskResult.StillRunning; + } + + private bool IsAllRecommendeGearEquipped() + { + var recommendedEquipModule = RecommendEquipModule.Instance(); + InventoryManager* inventoryManager = InventoryManager.Instance(); + InventoryContainer* equippedItems = + inventoryManager->GetInventoryContainer(InventoryType.EquippedItems); + bool isAllEquipped = true; + foreach (var recommendedItemPtr in recommendedEquipModule->RecommendedItems) + { + var recommendedItem = recommendedItemPtr.Value; + if (recommendedItem == null || recommendedItem->ItemId == 0) + continue; + + bool isEquipped = false; + for (int i = 0; i < equippedItems->Size; ++i) + { + var equippedItem = equippedItems->Items[i]; + if (equippedItem.ItemId != 0 && equippedItem.ItemId == recommendedItem->ItemId) + { + isEquipped = true; + break; + } + } + + if (!isEquipped) + isAllEquipped = false; + } + + return isAllEquipped; } public override bool ShouldInterruptOnDamage() => true; From 004d9756d775acc858a2339d85a2c09455e8e397 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Fri, 24 Jan 2025 22:26:24 +0100 Subject: [PATCH 07/14] Add an optional teleport before interacting with Raubahn for Castrum Meridianum so lv50 job quests can run before the dungeon; open Lv49 weapon + Lv50 job gear coffer before queueing for Castrum --- .../3873_Rock the Castrum.json | 152 +++++++++++++++++- QuestPaths/quest-v1.json | 8 +- 2 files changed, 156 insertions(+), 4 deletions(-) diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/3873_Rock the Castrum.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/3873_Rock the Castrum.json index 7eec220a..dba66d15 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/3873_Rock the Castrum.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/3873_Rock the Castrum.json @@ -35,13 +35,163 @@ "Z": -225.17743 }, "TerritoryId": 147, - "InteractionType": "Interact" + "InteractionType": "Interact", + "AetheryteShortcut": "Northern Thanalan - Ceruleum Processing Plant", + "SkipConditions": { + "AetheryteShortcutIf": { + "InSameTerritory": true + } + } } ] }, { "Sequence": 2, + "$": "This doesn't include the DRK/MCH/AST coffers that exist at level 50, but you cannot obtain them until HW", "Steps": [ + { + "TerritoryId": 147, + "InteractionType": "UseItem", + "ItemId": 31337, + "$": "Lv49 Weapon Coffer", + "SkipConditions": { + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, + { + "TerritoryId": 147, + "InteractionType": "UseItem", + "ItemId": 20642, + "$": "Lv50 PLD Coffer", + "SkipConditions": { + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, + { + "TerritoryId": 147, + "InteractionType": "UseItem", + "ItemId": 20643, + "$": "Lv50 MNK Coffer", + "SkipConditions": { + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, + { + "TerritoryId": 147, + "InteractionType": "UseItem", + "ItemId": 20644, + "$": "Lv50 WAR Coffer", + "SkipConditions": { + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, + { + "TerritoryId": 147, + "InteractionType": "UseItem", + "ItemId": 20645, + "$": "Lv50 DRG Coffer", + "SkipConditions": { + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, + { + "TerritoryId": 147, + "InteractionType": "UseItem", + "ItemId": 20646, + "$": "Lv50 BRD Coffer", + "SkipConditions": { + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, + { + "TerritoryId": 147, + "InteractionType": "UseItem", + "ItemId": 20647, + "$": "Lv50 NIN Coffer", + "SkipConditions": { + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, + { + "TerritoryId": 147, + "InteractionType": "UseItem", + "ItemId": 20648, + "$": "Lv50 WHM Coffer", + "SkipConditions": { + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, + { + "TerritoryId": 147, + "InteractionType": "UseItem", + "ItemId": 20649, + "$": "Lv50 BLM Coffer", + "SkipConditions": { + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, + { + "TerritoryId": 147, + "InteractionType": "UseItem", + "ItemId": 20650, + "$": "Lv50 SMN Coffer", + "SkipConditions": { + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, + { + "TerritoryId": 147, + "InteractionType": "UseItem", + "ItemId": 20651, + "$": "Lv50 SCH Coffer", + "SkipConditions": { + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, { "TerritoryId": 147, "InteractionType": "Duty", diff --git a/QuestPaths/quest-v1.json b/QuestPaths/quest-v1.json index d1c1b23c..1902572a 100644 --- a/QuestPaths/quest-v1.json +++ b/QuestPaths/quest-v1.json @@ -47,6 +47,10 @@ }, "Comment": { "type": "string" + }, + "$": { + "type": "string", + "description": "Dev Comment (not visible in-game)" } }, "required": [ @@ -699,9 +703,7 @@ "const": "UseItem" }, "ItemId": { - "not": { - "const": 30362 - } + "minimum": 2000000 } } }, From e305bbfea9ad44c21f13bca33784cc3226ccbd4e Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Fri, 24 Jan 2025 22:36:13 +0100 Subject: [PATCH 08/14] Fix Southern Thanalan pathing in 'Legacy of Allag' --- .../Alliance Raid Quests/1709_Legacy of Allag.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/QuestPaths/2.x - A Realm Reborn/Alliance Raid Quests/1709_Legacy of Allag.json b/QuestPaths/2.x - A Realm Reborn/Alliance Raid Quests/1709_Legacy of Allag.json index 1e363fb4..064e9a43 100644 --- a/QuestPaths/2.x - A Realm Reborn/Alliance Raid Quests/1709_Legacy of Allag.json +++ b/QuestPaths/2.x - A Realm Reborn/Alliance Raid Quests/1709_Legacy of Allag.json @@ -329,9 +329,9 @@ }, { "Position": { - "X": -0.75614685, + "X": 3.8795898, "Y": 38.80212, - "Z": -11.007636 + "Z": 0.40251642 }, "TerritoryId": 146, "InteractionType": "WalkTo", @@ -359,7 +359,8 @@ null, 128 ], - "Fly": true + "Fly": true, + "DisableNavmesh": true }, { "DataId": 2000078, From b30c1b29d81b8c8289f10a2417f8c27b599cf70e Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sat, 25 Jan 2025 02:38:35 +0100 Subject: [PATCH 09/14] Remove Haukke Manor & Brayflox's Longstop from automatically supported duties --- .../MSQ-2/A9-Haukke Manor/801_Skeletons in Her Closet.json | 2 +- .../832_The Things We Do for Cheese.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/A9-Haukke Manor/801_Skeletons in Her Closet.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/A9-Haukke Manor/801_Skeletons in Her Closet.json index 9269a84b..a17b715c 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/A9-Haukke Manor/801_Skeletons in Her Closet.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/A9-Haukke Manor/801_Skeletons in Her Closet.json @@ -67,7 +67,7 @@ "TerritoryId": 148, "InteractionType": "Duty", "ContentFinderConditionId": 6, - "AutoDutyEnabled": true + "AutoDutyEnabled": false } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B2-Eastern La Noscea, Brayflox, Cheese and Wine/832_The Things We Do for Cheese.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B2-Eastern La Noscea, Brayflox, Cheese and Wine/832_The Things We Do for Cheese.json index 06402bac..960ac4ec 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B2-Eastern La Noscea, Brayflox, Cheese and Wine/832_The Things We Do for Cheese.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B2-Eastern La Noscea, Brayflox, Cheese and Wine/832_The Things We Do for Cheese.json @@ -86,7 +86,7 @@ "TerritoryId": 137, "InteractionType": "Duty", "ContentFinderConditionId": 8, - "AutoDutyEnabled": true + "AutoDutyEnabled": false } ] }, From 0a22db23f32c2d311485d87d62f668f29def3a0f Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sat, 25 Jan 2025 17:56:15 +0100 Subject: [PATCH 10/14] Move 'Forging the Spirit' into a separate quest file --- .../272_Life, Materia and Everything.json | 32 ++++++++++++----- .../638_Forging the Spirit.json | 36 +++++++++++++++++++ 2 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 QuestPaths/2.x - A Realm Reborn/Side Quests/Thanalan/Eastern Thanalan/638_Forging the Spirit.json diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/272_Life, Materia and Everything.json b/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/272_Life, Materia and Everything.json index 6af9e61b..f56212fb 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/272_Life, Materia and Everything.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/272_Life, Materia and Everything.json @@ -21,16 +21,30 @@ "Sequence": 1, "Steps": [ { - "DataId": 1001426, "Position": { - "X": 123.33862, - "Y": 30.999996, - "Z": -384.9394 + "X": 2.7922537, + "Y": 8.206551, + "Z": -274.32318 }, "TerritoryId": 141, - "InteractionType": "Interact", - "Comment": "'Forging the Spirit'", - "AetheryteShortcut": "Central Thanalan - Black Brush Station" + "InteractionType": "WalkTo", + "AetheryteShortcut": "Central Thanalan - Black Brush Station", + "SkipConditions": { + "AetheryteShortcutIf": { + "InSameTerritory": true + }, + "StepIf": { + "NearPosition": { + "Position": { + "X": 123.33862, + "Y": 30.999996, + "Z": -384.9394 + }, + "TerritoryId": 141, + "MaximumDistance": 30 + } + } + } }, { "DataId": 1001426, @@ -40,8 +54,8 @@ "Z": -384.9394 }, "TerritoryId": 141, - "InteractionType": "Interact", - "Comment": "Quest Turn-In 'Forging the Spirit'" + "InteractionType": "AcceptQuest", + "PickUpQuestId": 638 }, { "DataId": 1001425, diff --git a/QuestPaths/2.x - A Realm Reborn/Side Quests/Thanalan/Eastern Thanalan/638_Forging the Spirit.json b/QuestPaths/2.x - A Realm Reborn/Side Quests/Thanalan/Eastern Thanalan/638_Forging the Spirit.json new file mode 100644 index 00000000..dae2a859 --- /dev/null +++ b/QuestPaths/2.x - A Realm Reborn/Side Quests/Thanalan/Eastern Thanalan/638_Forging the Spirit.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "liza", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1001426, + "Position": { + "X": 123.33862, + "Y": 30.999996, + "Z": -384.9394 + }, + "TerritoryId": 141, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1001426, + "Position": { + "X": 123.33862, + "Y": 30.999996, + "Z": -384.9394 + }, + "TerritoryId": 141, + "InteractionType": "CompleteQuest" + } + ] + } + ] +} From a7706a11e75c0f09cb5252473bc4726b4e81cd6a Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sat, 25 Jan 2025 18:40:47 +0100 Subject: [PATCH 11/14] Add 'Gyorin the Namazu', add some missing NextQuestIds --- .../Yanxia/2734_Perchance to Hanami.json | 5 +- .../2736_Courage the Cowardly Lupin.json | 5 +- .../2737_Kurobana vs the Rice Sacks.json | 5 +- .../2738_Kurobana vs the Arrowheads.json | 5 +- .../Yanxia/2739_Kurobana Holmes.json | 5 +- .../Side Quests/Yanxia/2747_Amber Alert.json | 9 +- .../Yanxia/2748_Gyorin the Namazu.json | 143 ++++++++++++++++++ .../2749_No Wealth Like Mineral Wealth.json | 21 ++- .../Side Quests/Yanxia/2750_Fresh Flesh.json | 5 +- .../Yanxia/2751_Show Me the New Money.json | 5 +- 10 files changed, 188 insertions(+), 20 deletions(-) create mode 100644 QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2748_Gyorin the Namazu.json diff --git a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2734_Perchance to Hanami.json b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2734_Perchance to Hanami.json index 4c41c9a6..35b1eb35 100644 --- a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2734_Perchance to Hanami.json +++ b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2734_Perchance to Hanami.json @@ -86,9 +86,10 @@ }, "TerritoryId": 614, "InteractionType": "CompleteQuest", - "Fly": true + "Fly": true, + "NextQuestId": 2748 } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2736_Courage the Cowardly Lupin.json b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2736_Courage the Cowardly Lupin.json index a319d70c..137f6fc8 100644 --- a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2736_Courage the Cowardly Lupin.json +++ b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2736_Courage the Cowardly Lupin.json @@ -131,9 +131,10 @@ } } }, - "Fly": true + "Fly": true, + "NextQuestId": 2737 } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2737_Kurobana vs the Rice Sacks.json b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2737_Kurobana vs the Rice Sacks.json index 76c060a6..c0640ae1 100644 --- a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2737_Kurobana vs the Rice Sacks.json +++ b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2737_Kurobana vs the Rice Sacks.json @@ -123,9 +123,10 @@ } } }, - "Fly": true + "Fly": true, + "NextQuestId": 2738 } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2738_Kurobana vs the Arrowheads.json b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2738_Kurobana vs the Arrowheads.json index 7203fa8f..44eb2726 100644 --- a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2738_Kurobana vs the Arrowheads.json +++ b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2738_Kurobana vs the Arrowheads.json @@ -159,9 +159,10 @@ } } }, - "Fly": true + "Fly": true, + "NextQuestId": 2739 } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2739_Kurobana Holmes.json b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2739_Kurobana Holmes.json index a5211c3d..f5809f06 100644 --- a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2739_Kurobana Holmes.json +++ b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2739_Kurobana Holmes.json @@ -142,9 +142,10 @@ } } }, - "Fly": true + "Fly": true, + "NextQuestId": 2740 } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2747_Amber Alert.json b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2747_Amber Alert.json index 20d4eb7c..52185f15 100644 --- a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2747_Amber Alert.json +++ b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2747_Amber Alert.json @@ -24,7 +24,7 @@ }, "TerritoryId": 614, "InteractionType": "AcceptQuest", - "StopDistance": 0.1 + "StopDistance": 0.25 } ] }, @@ -67,7 +67,7 @@ }, "TerritoryId": 614, "InteractionType": "Interact", - "StopDistance": 0.1 + "StopDistance": 0.25 } ] }, @@ -84,9 +84,10 @@ "TerritoryId": 614, "InteractionType": "CompleteQuest", "Fly": true, - "AetheryteShortcut": "Yanxia - Namai" + "AetheryteShortcut": "Yanxia - Namai", + "NextQuestId": 2740 } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2748_Gyorin the Namazu.json b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2748_Gyorin the Namazu.json new file mode 100644 index 00000000..910bc8fe --- /dev/null +++ b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2748_Gyorin the Namazu.json @@ -0,0 +1,143 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "liza", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1023236, + "Position": { + "X": -300.06866, + "Y": 16.806112, + "Z": 539.45215 + }, + "TerritoryId": 614, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1023237, + "Position": { + "X": -233.72241, + "Y": 17.628202, + "Z": 485.3131 + }, + "TerritoryId": 614, + "InteractionType": "Interact", + "Fly": true + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "Position": { + "X": -463.34363, + "Y": 1.3011811, + "Z": 578.3476 + }, + "TerritoryId": 614, + "InteractionType": "WalkTo", + "Fly": true + }, + { + "DataId": 1023238, + "Position": { + "X": -464.49988, + "Y": 1.3011812, + "Z": 577.32495 + }, + "TerritoryId": 614, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "Position": { + "X": -487.5986, + "Y": -0.5999999, + "Z": 578.5466 + }, + "TerritoryId": 614, + "InteractionType": "Dive", + "DisableNavmesh": true + }, + { + "DataId": 2008799, + "Position": { + "X": -549.7063, + "Y": -109.51398, + "Z": 569.32935 + }, + "TerritoryId": 614, + "InteractionType": "Interact", + "Fly": true, + "Mount": true + } + ] + }, + { + "Sequence": 4, + "Steps": [ + { + "Position": { + "X": -487.5986, + "Y": -0.5999999, + "Z": 578.5466 + }, + "TerritoryId": 614, + "InteractionType": "WalkTo", + "DisableNavmesh": true, + "RestartNavigationIfCancelled": false + }, + { + "Position": { + "X": -463.34363, + "Y": 1.3011811, + "Z": 578.3476 + }, + "TerritoryId": 614, + "InteractionType": "WalkTo", + "Fly": true + }, + { + "DataId": 1023238, + "Position": { + "X": -464.49988, + "Y": 1.3011812, + "Z": 577.32495 + }, + "TerritoryId": 614, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1023237, + "Position": { + "X": -233.72241, + "Y": 17.628202, + "Z": 485.3131 + }, + "TerritoryId": 614, + "InteractionType": "CompleteQuest", + "Fly": true, + "NextQuestId": 2749 + } + ] + } + ] +} diff --git a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2749_No Wealth Like Mineral Wealth.json b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2749_No Wealth Like Mineral Wealth.json index b63fe369..d85ab406 100644 --- a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2749_No Wealth Like Mineral Wealth.json +++ b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2749_No Wealth Like Mineral Wealth.json @@ -37,6 +37,21 @@ { "Sequence": 2, "Steps": [ + { + "Position": { + "X": -239.56377, + "Y": 49.354053, + "Z": 284.94565 + }, + "TerritoryId": 614, + "InteractionType": "WalkTo", + "Fly": true, + "SkipConditions": { + "StepIf": { + "Flying": "Locked" + } + } + }, { "DataId": 1023240, "Position": { @@ -59,6 +74,7 @@ "Y": 39.150906, "Z": 206.95801 }, + "StopDistance": 0.5, "TerritoryId": 614, "InteractionType": "Combat", "Fly": true, @@ -113,9 +129,10 @@ }, "TerritoryId": 614, "InteractionType": "CompleteQuest", - "Fly": true + "Fly": true, + "NextQuestId": 2750 } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2750_Fresh Flesh.json b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2750_Fresh Flesh.json index dd88387b..79b79e9b 100644 --- a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2750_Fresh Flesh.json +++ b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2750_Fresh Flesh.json @@ -98,9 +98,10 @@ }, "TerritoryId": 614, "InteractionType": "CompleteQuest", - "Fly": true + "Fly": true, + "NextQuestId": 2751 } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2751_Show Me the New Money.json b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2751_Show Me the New Money.json index 080d2189..4a9a8aa8 100644 --- a/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2751_Show Me the New Money.json +++ b/QuestPaths/4.x - Stormblood/Side Quests/Yanxia/2751_Show Me the New Money.json @@ -112,9 +112,10 @@ }, "TerritoryId": 614, "InteractionType": "CompleteQuest", - "Fly": true + "Fly": true, + "NextQuestId": 2747 } ] } ] -} \ No newline at end of file +} From b2c0934f07ac5b09403aa6da4b468a7f78b21c1e Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sat, 25 Jan 2025 18:59:38 +0100 Subject: [PATCH 12/14] GatheringPathRenderer: Adjust dev lookup path --- GatheringPathRenderer/RendererPlugin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GatheringPathRenderer/RendererPlugin.cs b/GatheringPathRenderer/RendererPlugin.cs index 93c666a8..aa88906c 100644 --- a/GatheringPathRenderer/RendererPlugin.cs +++ b/GatheringPathRenderer/RendererPlugin.cs @@ -82,7 +82,7 @@ public sealed class RendererPlugin : IDalamudPlugin get { #if DEBUG - DirectoryInfo? solutionDirectory = _pluginInterface.AssemblyLocation.Directory?.Parent?.Parent?.Parent; + DirectoryInfo? solutionDirectory = _pluginInterface.AssemblyLocation.Directory?.Parent?.Parent; if (solutionDirectory != null) { DirectoryInfo pathProjectDirectory = @@ -91,7 +91,7 @@ public sealed class RendererPlugin : IDalamudPlugin return pathProjectDirectory; } - throw new Exception("Unable to resolve project path"); + throw new Exception($"Unable to resolve project path ({_pluginInterface.AssemblyLocation.Directory})"); #else var allPluginsDirectory = _pluginInterface.ConfigFile.Directory ?? throw new Exception("Unknown directory for plugin configs"); return allPluginsDirectory From e1b146ee1eb779c9234c74c880d27ba04e5590d7 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sat, 25 Jan 2025 20:00:27 +0100 Subject: [PATCH 13/14] Code cleanup --- Questionable/Controller/InterruptHandler.cs | 1 - Questionable/Controller/QuestController.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Questionable/Controller/InterruptHandler.cs b/Questionable/Controller/InterruptHandler.cs index 9171432f..49b24abc 100644 --- a/Questionable/Controller/InterruptHandler.cs +++ b/Questionable/Controller/InterruptHandler.cs @@ -94,7 +94,6 @@ internal sealed unsafe class InterruptHandler : IDisposable [FieldOffset(6)] public ushort Value; public byte AttackType => (byte)(Param1 & 0xF); - public uint Damage => Mult == 0 ? Value : Value + ((uint)ushort.MaxValue + 1) * Mult; public override string ToString() { diff --git a/Questionable/Controller/QuestController.cs b/Questionable/Controller/QuestController.cs index 954bb5be..def1c297 100644 --- a/Questionable/Controller/QuestController.cs +++ b/Questionable/Controller/QuestController.cs @@ -19,7 +19,7 @@ using Quest = Questionable.Model.Quest; namespace Questionable.Controller; -internal sealed class QuestController : MiniTaskController, IDisposable +internal sealed class QuestController : MiniTaskController { private readonly IClientState _clientState; private readonly GameFunctions _gameFunctions; From de90882ecbb609c2f79fecc1ec17b751dc8763f2 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sat, 25 Jan 2025 20:01:13 +0100 Subject: [PATCH 14/14] Add Post-Endwalker role quests --- Directory.Build.targets | 2 +- .../5188_Picking Up the Torch.json | 161 ++++++++++++++++ .../Role Quests/5189_Imposing Views.json | 129 +++++++++++++ .../Role Quests/5190_Enforcing Freedom.json | 175 +++++++++++++++++ .../Role Quests/5191_Bar the Passage.json | 182 ++++++++++++++++++ QuestPaths/quest-v1.json | 4 +- .../Questing/Converter/EmoteConverter.cs | 2 + Questionable.Model/Questing/EEmote.cs | 4 +- Questionable/Data/QuestData.cs | 11 ++ 9 files changed, 667 insertions(+), 3 deletions(-) create mode 100644 QuestPaths/7.x - Dawntrail/Role Quests/5188_Picking Up the Torch.json create mode 100644 QuestPaths/7.x - Dawntrail/Role Quests/5189_Imposing Views.json create mode 100644 QuestPaths/7.x - Dawntrail/Role Quests/5190_Enforcing Freedom.json create mode 100644 QuestPaths/7.x - Dawntrail/Role Quests/5191_Bar the Passage.json diff --git a/Directory.Build.targets b/Directory.Build.targets index cfa9441e..729f81b6 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,5 +1,5 @@ - 4.15 + 4.16 diff --git a/QuestPaths/7.x - Dawntrail/Role Quests/5188_Picking Up the Torch.json b/QuestPaths/7.x - Dawntrail/Role Quests/5188_Picking Up the Torch.json new file mode 100644 index 00000000..d8d59f15 --- /dev/null +++ b/QuestPaths/7.x - Dawntrail/Role Quests/5188_Picking Up the Torch.json @@ -0,0 +1,161 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "liza", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1050871, + "Position": { + "X": -51.895935, + "Y": -17.97287, + "Z": 182.7268 + }, + "TerritoryId": 1185, + "InteractionType": "AcceptQuest", + "AetheryteShortcut": "Tuliyollal", + "AethernetShortcut": [ + "[Tuliyollal] Aetheryte Plaza", + "[Tuliyollal] The For'ard Cabins" + ], + "SkipConditions": { + "AetheryteShortcutIf": { + "InSameTerritory": true + } + } + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1001657, + "Position": { + "X": 94.80432, + "Y": 7.9804688, + "Z": -34.042908 + }, + "TerritoryId": 131, + "InteractionType": "Interact", + "AetheryteShortcut": "Ul'dah", + "AethernetShortcut": [ + "[Ul'dah] Aetheryte Plaza", + "[Ul'dah] Sapphire Avenue Exchange" + ], + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 32 + ] + }, + { + "DataId": 1006440, + "Position": { + "X": 140.3982, + "Y": 4, + "Z": -54.154297 + }, + "TerritoryId": 131, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 64 + ] + }, + { + "DataId": 1051655, + "Position": { + "X": 137.74304, + "Y": 4, + "Z": 5.9662476 + }, + "TerritoryId": 131, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 128 + ] + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "Position": { + "X": 146.12386, + "Y": 4, + "Z": -23.562449 + }, + "StopDistance": 0.5, + "TerritoryId": 131, + "InteractionType": "Emote", + "Emote": "angry" + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 1051656, + "Position": { + "X": 56.443115, + "Y": 10, + "Z": 5.935669 + }, + "TerritoryId": 131, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 2012114, + "Position": { + "X": 0, + "Y": 1.15, + "Z": 10.23451 + }, + "TerritoryId": 1255, + "InteractionType": "Interact", + "TargetTerritoryId": 131, + "SkipConditions": { + "StepIf": { + "InTerritory": [ + 131 + ] + } + } + }, + { + "DataId": 1051656, + "Position": { + "X": 56.443115, + "Y": 10, + "Z": 5.935669 + }, + "StopDistance": 7, + "TerritoryId": 131, + "InteractionType": "CompleteQuest", + "NextQuestId": 5189 + } + ] + } + ] +} diff --git a/QuestPaths/7.x - Dawntrail/Role Quests/5189_Imposing Views.json b/QuestPaths/7.x - Dawntrail/Role Quests/5189_Imposing Views.json new file mode 100644 index 00000000..17c2bf46 --- /dev/null +++ b/QuestPaths/7.x - Dawntrail/Role Quests/5189_Imposing Views.json @@ -0,0 +1,129 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "liza", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1051656, + "Position": { + "X": 56.443115, + "Y": 10, + "Z": 5.935669 + }, + "StopDistance": 7, + "TerritoryId": 131, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 2014419, + "Position": { + "X": -158.86176, + "Y": 7.4921875, + "Z": 493.88867 + }, + "TerritoryId": 146, + "InteractionType": "Interact", + "AetheryteShortcut": "Southern Thanalan - Forgotten Springs", + "Fly": true + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "DataId": 1051661, + "Position": { + "X": 1.7852783, + "Y": 19.026453, + "Z": 581.62805 + }, + "StopDistance": 5, + "TerritoryId": 146, + "InteractionType": "Interact", + "DialogueChoices": [ + { + "Type": "List", + "Prompt": "TEXT_KINGBZ002_05189_Q1_000_000", + "Answer": "TEXT_KINGBZ002_05189_A1_000_001" + } + ] + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 1051663, + "Position": { + "X": 51.68225, + "Y": 0.7631253, + "Z": 711.57385 + }, + "TerritoryId": 146, + "InteractionType": "Combat", + "EnemySpawnType": "AfterInteraction", + "KillEnemyDataIds": [ + 18178 + ], + "Fly": true + } + ] + }, + { + "Sequence": 4, + "Steps": [ + { + "DataId": 1051663, + "Position": { + "X": 51.68225, + "Y": 0.7631253, + "Z": 711.57385 + }, + "TerritoryId": 146, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 5, + "Steps": [ + { + "DataId": 1051668, + "Position": { + "X": 170.42798, + "Y": 15.943722, + "Z": 897.94763 + }, + "TerritoryId": 146, + "InteractionType": "Interact", + "Fly": true + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1051668, + "Position": { + "X": 170.42798, + "Y": 15.943722, + "Z": 897.94763 + }, + "TerritoryId": 146, + "InteractionType": "CompleteQuest", + "NextQuestId": 5190 + } + ] + } + ] +} diff --git a/QuestPaths/7.x - Dawntrail/Role Quests/5190_Enforcing Freedom.json b/QuestPaths/7.x - Dawntrail/Role Quests/5190_Enforcing Freedom.json new file mode 100644 index 00000000..6f05c439 --- /dev/null +++ b/QuestPaths/7.x - Dawntrail/Role Quests/5190_Enforcing Freedom.json @@ -0,0 +1,175 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "liza", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1051668, + "Position": { + "X": 170.42798, + "Y": 15.943722, + "Z": 897.94763 + }, + "TerritoryId": 146, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1050871, + "Position": { + "X": -51.895935, + "Y": -17.97287, + "Z": 182.7268 + }, + "TerritoryId": 1185, + "InteractionType": "Interact", + "AetheryteShortcut": "Tuliyollal", + "AethernetShortcut": [ + "[Tuliyollal] Aetheryte Plaza", + "[Tuliyollal] The For'ard Cabins" + ] + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "DataId": 1051670, + "Position": { + "X": -15.976257, + "Y": -19.928413, + "Z": 224.90259 + }, + "TerritoryId": 1185, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 1051675, + "Position": { + "X": 358.23608, + "Y": 5.957184, + "Z": 428.36658 + }, + "StopDistance": 1, + "TerritoryId": 1190, + "InteractionType": "Interact", + "AetheryteShortcut": "Shaaloani - Hhusatahwi", + "Fly": true + } + ] + }, + { + "Sequence": 4, + "Steps": [ + { + "Position": { + "X": 363.81656, + "Y": 5.9295864, + "Z": 435.17932 + }, + "TerritoryId": 1190, + "InteractionType": "WalkTo" + }, + { + "DataId": 1051677, + "Position": { + "X": 371.4198, + "Y": 5.95728, + "Z": 425.4978 + }, + "TerritoryId": 1190, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 5, + "Steps": [ + { + "DataId": 1051677, + "Position": { + "X": 371.4198, + "Y": 5.95728, + "Z": 425.4978 + }, + "TerritoryId": 1190, + "InteractionType": "Emote", + "Emote": "unbound" + } + ] + }, + { + "Sequence": 6, + "Steps": [ + { + "DataId": 1051682, + "Position": { + "X": 387.5028, + "Y": -0.60167974, + "Z": 426.99304 + }, + "TerritoryId": 1190, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 7, + "Steps": [ + { + "Position": { + "X": 425.24307, + "Y": 0.7699772, + "Z": 473.79095 + }, + "TerritoryId": 1190, + "InteractionType": "WalkTo", + "Fly": true + }, + { + "DataId": 1051684, + "Position": { + "X": 426.04712, + "Y": 0.7461932, + "Z": 472.3125 + }, + "TerritoryId": 1190, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1050871, + "Position": { + "X": -51.895935, + "Y": -17.97287, + "Z": 182.7268 + }, + "TerritoryId": 1185, + "InteractionType": "CompleteQuest", + "AetheryteShortcut": "Tuliyollal", + "AethernetShortcut": [ + "[Tuliyollal] Aetheryte Plaza", + "[Tuliyollal] The For'ard Cabins" + ], + "NextQuestId": 5191 + } + ] + } + ] +} diff --git a/QuestPaths/7.x - Dawntrail/Role Quests/5191_Bar the Passage.json b/QuestPaths/7.x - Dawntrail/Role Quests/5191_Bar the Passage.json new file mode 100644 index 00000000..ac9a8790 --- /dev/null +++ b/QuestPaths/7.x - Dawntrail/Role Quests/5191_Bar the Passage.json @@ -0,0 +1,182 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "liza", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1050871, + "Position": { + "X": -51.895935, + "Y": -17.97287, + "Z": 182.7268 + }, + "TerritoryId": 1185, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1051689, + "Position": { + "X": 273.33484, + "Y": 15.999998, + "Z": 740.6576 + }, + "TerritoryId": 1190, + "InteractionType": "SinglePlayerDuty", + "AethernetShortcut": [ + "[Tuliyollal] The For'ard Cabins", + "[Tuliyollal] Xak Tural Skygate (Shaaloani)" + ] + } + ] + }, + { + "Sequence": 2 + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 1051691, + "Position": { + "X": 273.85364, + "Y": 15.999996, + "Z": 738.2771 + }, + "TerritoryId": 1190, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 4, + "Steps": [ + { + "DataId": 1050871, + "Position": { + "X": -51.895935, + "Y": -17.97287, + "Z": 182.7268 + }, + "TerritoryId": 1185, + "InteractionType": "Interact", + "AetheryteShortcut": "Tuliyollal", + "AethernetShortcut": [ + "[Tuliyollal] Aetheryte Plaza", + "[Tuliyollal] The For'ard Cabins" + ] + } + ] + }, + { + "Sequence": 5, + "Steps": [ + { + "DataId": 1051672, + "Position": { + "X": -14.816589, + "Y": -19.881973, + "Z": 223.3158 + }, + "TerritoryId": 1185, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 6, + "Steps": [ + { + "DataId": 1051673, + "Position": { + "X": -15.243774, + "Y": -19.762682, + "Z": 221.72876 + }, + "StopDistance": 5, + "TerritoryId": 1185, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 7, + "Steps": [ + { + "DataId": 1051670, + "Position": { + "X": -15.976257, + "Y": -19.928413, + "Z": 224.90259 + }, + "StopDistance": 5, + "TerritoryId": 1185, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 8, + "Steps": [ + { + "DataId": 1051671, + "Position": { + "X": -17.95996, + "Y": -19.784014, + "Z": 224.17017 + }, + "StopDistance": 5, + "TerritoryId": 1185, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 9, + "Steps": [ + { + "DataId": 1051674, + "Position": { + "X": -16.617126, + "Y": -19.752277, + "Z": 222.64429 + }, + "TerritoryId": 1185, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "Position": { + "X": -44.643284, + "Y": -17.972864, + "Z": 203.87883 + }, + "TerritoryId": 1185, + "InteractionType": "WalkTo" + }, + { + "DataId": 1046521, + "Position": { + "X": -46.616333, + "Y": -17.97287, + "Z": 180.3158 + }, + "StopDistance": 5, + "TerritoryId": 1185, + "InteractionType": "CompleteQuest", + "DisableNavmesh": true + } + ] + } + ] +} diff --git a/QuestPaths/quest-v1.json b/QuestPaths/quest-v1.json index 1902572a..0ca8c368 100644 --- a/QuestPaths/quest-v1.json +++ b/QuestPaths/quest-v1.json @@ -866,7 +866,9 @@ "mogdance", "salute", "laugh", - "greeting" + "greeting", + "angry", + "unbound" ] } } diff --git a/Questionable.Model/Questing/Converter/EmoteConverter.cs b/Questionable.Model/Questing/Converter/EmoteConverter.cs index bdfe5581..576a77e5 100644 --- a/Questionable.Model/Questing/Converter/EmoteConverter.cs +++ b/Questionable.Model/Questing/Converter/EmoteConverter.cs @@ -7,6 +7,7 @@ public sealed class EmoteConverter() : EnumConverter(Values) { private static readonly Dictionary Values = new() { + { EEmote.Angry, "angry" }, { EEmote.Bow, "bow" }, { EEmote.Cheer, "cheer" }, { EEmote.Clap, "clap" }, @@ -45,5 +46,6 @@ public sealed class EmoteConverter() : EnumConverter(Values) { EEmote.Box, "box" }, { EEmote.Greeting, "greeting" }, { EEmote.Uchiwasshoi, "uchiwasshoi" }, + { EEmote.Unbound, "unbound" }, }; } diff --git a/Questionable.Model/Questing/EEmote.cs b/Questionable.Model/Questing/EEmote.cs index 78e7b650..7855bd15 100644 --- a/Questionable.Model/Questing/EEmote.cs +++ b/Questionable.Model/Questing/EEmote.cs @@ -8,6 +8,7 @@ public enum EEmote { None = 0, + Angry = 2, Bow = 5, Cheer = 6, Clap = 7, @@ -45,6 +46,7 @@ public enum EEmote Respect = 140, Box = 166, Greeting = 172, - Uchiwasshoi = 278 + Uchiwasshoi = 278, + Unbound = 282, } diff --git a/Questionable/Data/QuestData.cs b/Questionable/Data/QuestData.cs index 65225863..f84edb95 100644 --- a/Questionable/Data/QuestData.cs +++ b/Questionable/Data/QuestData.cs @@ -189,6 +189,12 @@ internal sealed class QuestData AddPreviousQuest(new QuestId(3833), new QuestId(spearfishing)); */ + // Shadow Walk with Me + AddPreviousQuest(new QuestId(3629), new QuestId(3248)); + AddPreviousQuest(new QuestId(3629), new QuestId(3272)); + AddPreviousQuest(new QuestId(3629), new QuestId(3278)); + AddPreviousQuest(new QuestId(3629), new QuestId(3628)); + // The Hero's Journey AddPreviousQuest(new QuestId(3986), new QuestId(2115)); AddPreviousQuest(new QuestId(3986), new QuestId(2116)); @@ -197,6 +203,11 @@ internal sealed class QuestData AddPreviousQuest(new QuestId(3986), new QuestId(2395)); AddPreviousQuest(new QuestId(3986), new QuestId(3985)); + // Picking up the Torch has half the quests in the sheets(??) + AddPreviousQuest(new QuestId(5188), new QuestId(4841)); + AddPreviousQuest(new QuestId(5188), new QuestId(4847)); + AddPreviousQuest(new QuestId(5188), new QuestId(4959)); + // initial city quests are side quests // unclear if 470 can be started as the required quest isn't available anymore ushort[] limsaSideQuests =