From 920d2f072444f54a5d51b764ac75e68556842de4 Mon Sep 17 00:00:00 2001
From: Liza Carvelli <liza@carvel.li>
Date: Mon, 9 Dec 2024 01:11:35 +0100
Subject: [PATCH] Add missing THM quests

---
 .../BLM/345_Way of the Thaumaturge.json       | 133 +++++++++-
 .../BLM/348_The Threat of Paucity.json        | 231 ++++++++++++++++++
 .../BLM/349_The Threat of Paucity.json        |   3 +-
 Questionable/Controller/QuestController.cs    |   2 +-
 Questionable/Functions/QuestFunctions.cs      |  11 +-
 .../QuestComponents/ActiveQuestComponent.cs   |  26 +-
 6 files changed, 395 insertions(+), 11 deletions(-)
 create mode 100644 QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/348_The Threat of Paucity.json

diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/345_Way of the Thaumaturge.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/345_Way of the Thaumaturge.json
index e0f046de1..f8891964b 100644
--- a/QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/345_Way of the Thaumaturge.json	
+++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/345_Way of the Thaumaturge.json	
@@ -1,7 +1,6 @@
 {
   "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
   "Author": "liza",
-  "Disabled": true,
   "QuestSequence": [
     {
       "Sequence": 0,
@@ -14,7 +13,17 @@
             "Z": 59.952637
           },
           "TerritoryId": 130,
-          "InteractionType": "AcceptQuest"
+          "InteractionType": "AcceptQuest",
+          "AetheryteShortcut": "Ul'dah",
+          "AethernetShortcut": [
+            "[Ul'dah] Aetheryte Plaza",
+            "[Ul'dah] Thaumaturges' Guild"
+          ],
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true
+            }
+          }
         }
       ]
     },
@@ -40,6 +49,126 @@
           "NextQuestId": 351
         }
       ]
+    },
+    {
+      "Sequence": 2,
+      "Steps": [
+        {
+          "Position": {
+            "X": -71.92632,
+            "Y": 9.839797,
+            "Z": 283.98495
+          },
+          "TerritoryId": 141,
+          "InteractionType": "Combat",
+          "EnemySpawnType": "OverworldEnemies",
+          "ComplexCombatData": [
+            {
+              "DataId": 351,
+              "MinimumKillCount": 3,
+              "$": "Slay star marmots as a thaumaturge",
+              "CompletionQuestVariablesFlags": [
+                {
+                  "Low": 3
+                },
+                null,
+                null,
+                null,
+                null,
+                null
+              ]
+            },
+            {
+              "DataId": 385,
+              "MinimumKillCount": 3,
+              "$": "Slay huge hornets as a thaumaturge",
+              "CompletionQuestVariablesFlags": [
+                null,
+                {
+                  "High": 3
+                },
+                null,
+                null,
+                null,
+                null
+              ]
+            }
+          ],
+          "AetheryteShortcut": "Ul'dah",
+          "AethernetShortcut": [
+            "[Ul'dah] Thaumaturges' Guild",
+            "[Ul'dah] Gate of Nald (Central Thanalan)"
+          ],
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true,
+              "InTerritory": [
+                141
+              ]
+            }
+          },
+          "CompletionQuestVariablesFlags": [
+            {
+              "Low": 3
+            },
+            {
+              "High": 3
+            },
+            null,
+            null,
+            null,
+            null
+          ]
+        },
+        {
+          "Position": {
+            "X": 39.449,
+            "Y": 3.082914,
+            "Z": 272.46896
+          },
+          "TerritoryId": 141,
+          "InteractionType": "Combat",
+          "EnemySpawnType": "OverworldEnemies",
+          "ComplexCombatData": [
+            {
+              "DataId": 205,
+              "MinimumKillCount": 3,
+              "$": "Slay snapping shrews as a thaumaturge"
+            }
+          ],
+          "CompletionQuestVariablesFlags": [
+            null,
+            {
+              "Low": 3
+            },
+            null,
+            null,
+            null,
+            null
+          ]
+        }
+      ]
+    },
+    {
+      "Sequence": 255,
+      "Steps": [
+        {
+          "DataId": 1001708,
+          "Position": {
+            "X": -250.3548,
+            "Y": 18,
+            "Z": 80.88806
+          },
+          "TerritoryId": 130,
+          "InteractionType": "CompleteQuest",
+          "AetheryteShortcut": "Ul'dah",
+          "AethernetShortcut": [
+            "[Ul'dah] Aetheryte Plaza",
+            "[Ul'dah] Thaumaturges' Guild"
+          ],
+          "NextQuestId": 351
+        }
+      ]
     }
   ]
 }
diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/348_The Threat of Paucity.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/348_The Threat of Paucity.json
new file mode 100644
index 000000000..196b0fdb0
--- /dev/null
+++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/348_The Threat of Paucity.json	
@@ -0,0 +1,231 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
+  "Author": ["liza", "pot0to"],
+  "QuestSequence": [
+    {
+      "Sequence": 0,
+      "Steps": [
+        {
+          "DataId": 1001708,
+          "Position": {
+            "X": -250.3548,
+            "Y": 18,
+            "Z": 80.88806
+          },
+          "TerritoryId": 130,
+          "InteractionType": "AcceptQuest",
+          "AetheryteShortcut": "Ul'dah",
+          "AethernetShortcut": [
+            "[Ul'dah] Aetheryte Plaza",
+            "[Ul'dah] Thaumaturges' Guild"
+          ],
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true
+            }
+          }
+        }
+      ]
+    },
+    {
+      "Sequence": 1,
+      "Steps": [
+        {
+          "DataId": 1001710,
+          "Position": {
+            "X": -240.2533,
+            "Y": 18.8,
+            "Z": 86.900024
+          },
+          "TerritoryId": 130,
+          "InteractionType": "Interact"
+        }
+      ]
+    },
+    {
+      "Sequence": 2,
+      "Steps": [
+        {
+          "TerritoryId": 130,
+          "InteractionType": "None",
+          "AetheryteShortcut": "Ul'dah",
+          "AethernetShortcut": [
+            "[Ul'dah] Thaumaturges' Guild",
+            "[Ul'dah] Gate of Nald (Central Thanalan)"
+          ],
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true,
+              "InTerritory": [
+                141
+              ],
+              "AetheryteUnlocked": "Central Thanalan - Black Brush Station"
+            },
+            "AethernetShortcutIf": {
+              "AetheryteUnlocked": "Central Thanalan - Black Brush Station"
+            }
+          }
+        },
+        {
+          "Position": {
+            "X": -62.183617,
+            "Y": -3.6582246,
+            "Z": 145.88391
+          },
+          "InteractionType": "WalkTo",
+          "TerritoryId": 141,
+          "SkipConditions": {
+            "StepIf": {
+              "Flying": "Unlocked",
+              "AetheryteUnlocked": "Central Thanalan - Black Brush Station"
+            }
+          }
+        },
+        {
+          "Position": {
+            "X": 149.07747,
+            "Y": -2,
+            "Z": -225.21188
+          },
+          "TerritoryId": 141,
+          "AetheryteShortcut": "Central Thanalan - Black Brush Station",
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true
+            }
+          },
+          "Fly": true,
+          "InteractionType": "Combat",
+          "EnemySpawnType": "OverworldEnemies",
+          "ComplexCombatData": [
+            {
+              "DataId": 160,
+              "MinimumKillCount": 8,
+              "$": "Slay efts",
+              "CompletionQuestVariablesFlags": [
+                {
+                  "Low": 8
+                },
+                null,
+                null,
+                null,
+                null,
+                null
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Sequence": 3,
+      "Steps": [
+        {
+          "DataId": 1001710,
+          "Position": {
+            "X": -240.2533,
+            "Y": 18.8,
+            "Z": 86.900024
+          },
+          "TerritoryId": 130,
+          "InteractionType": "Interact",
+          "AetheryteShortcut": "Ul'dah",
+          "AethernetShortcut": [
+            "[Ul'dah] Aetheryte Plaza",
+            "[Ul'dah] Thaumaturges' Guild"
+          ],
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true
+            }
+          },
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_CLSTHM100_00348_Q_000_1",
+              "Answer": "TEXT_CLSTHM100_00348_A_000_3"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Sequence": 4,
+      "Steps": [
+        {
+          "DataId": 2001511,
+          "Position": {
+            "X": -366.29285,
+            "Y": -34.989014,
+            "Z": 293.56824
+          },
+          "TerritoryId": 145,
+          "InteractionType": "Combat",
+          "EnemySpawnType": "AfterInteraction",
+          "KillEnemyDataIds": [
+            166,
+            1238
+          ],
+          "Fly": true,
+          "AetheryteShortcut": "Eastern Thanalan - Camp Drybone",
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true
+            }
+          }
+        }
+      ]
+    },
+    {
+      "Sequence": 5,
+      "Steps": [
+        {
+          "DataId": 2001498,
+          "Position": {
+            "X": -366.29285,
+            "Y": -34.989014,
+            "Z": 293.56824
+          },
+          "TerritoryId": 145,
+          "InteractionType": "Interact"
+        }
+      ]
+    },
+    {
+      "Sequence": 6,
+      "Steps": [
+        {
+          "DataId": 1001710,
+          "Position": {
+            "X": -240.2533,
+            "Y": 18.8,
+            "Z": 86.900024
+          },
+          "TerritoryId": 130,
+          "InteractionType": "Interact",
+          "AetheryteShortcut": "Ul'dah",
+          "AethernetShortcut": [
+            "[Ul'dah] Aetheryte Plaza",
+            "[Ul'dah] Thaumaturges' Guild"
+          ]
+        }
+      ]
+    },
+    {
+      "Sequence": 255,
+      "Steps": [
+        {
+          "DataId": 1001708,
+          "Position": {
+            "X": -250.3548,
+            "Y": 18,
+            "Z": 80.88806
+          },
+          "TerritoryId": 130,
+          "InteractionType": "CompleteQuest",
+          "NextQuestId": 350
+        }
+      ]
+    }
+  ]
+}
diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/349_The Threat of Paucity.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/349_The Threat of Paucity.json
index fdcc2b859..a987d067a 100644
--- a/QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/349_The Threat of Paucity.json	
+++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/BLM/349_The Threat of Paucity.json	
@@ -163,7 +163,8 @@
           "InteractionType": "Combat",
           "EnemySpawnType": "AfterInteraction",
           "KillEnemyDataIds": [
-            166
+            166,
+            1238
           ],
           "Fly": true,
           "AetheryteShortcut": "Eastern Thanalan - Camp Drybone",
diff --git a/Questionable/Controller/QuestController.cs b/Questionable/Controller/QuestController.cs
index d6ae32a8c..5554404cf 100644
--- a/Questionable/Controller/QuestController.cs
+++ b/Questionable/Controller/QuestController.cs
@@ -762,7 +762,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>, IDi
         if (!IsInterruptible() || _nextQuest != null || _gatheringQuest != null || _simulatedQuest != null)
             return false;
 
-        ElementId? priorityQuestId = _questFunctions.GetNextPriorityQuestThatCanBeAccepted();
+        ElementId? priorityQuestId = _questFunctions.GetNextPriorityQuestsThatCanBeAccepted().FirstOrDefault();
         if (priorityQuestId == null)
             return false;
 
diff --git a/Questionable/Functions/QuestFunctions.cs b/Questionable/Functions/QuestFunctions.cs
index fb720e2fa..bb206a1b9 100644
--- a/Questionable/Functions/QuestFunctions.cs
+++ b/Questionable/Functions/QuestFunctions.cs
@@ -221,7 +221,7 @@ internal sealed unsafe class QuestFunctions
                 return (firstTrackedQuest, firstTrackedSequence);
             }
 
-            ElementId? priorityQuest = GetNextPriorityQuestThatCanBeAccepted();
+            ElementId? priorityQuest = GetNextPriorityQuestsThatCanBeAccepted().FirstOrDefault();
             if (priorityQuest != null)
             {
                 // if we have an accepted msq quest, and know of no quest of those currently in the to-do list...
@@ -336,12 +336,12 @@ internal sealed unsafe class QuestFunctions
             return null;
     }
 
-    public ElementId? GetNextPriorityQuestThatCanBeAccepted()
+    public List<ElementId> GetNextPriorityQuestsThatCanBeAccepted()
     {
         // all priority quests assume we're able to teleport to the beginning (and for e.g. class quests, the end)
         // ideally without having to wait 15m for Return.
         if (!_aetheryteFunctions.IsTeleportUnlocked())
-            return null;
+            return [];
 
         // ideally, we'd also be able to afford *some* teleports
         // this implicitly makes sure we're not starting one of the lv1 class quests if we can't afford to teleport back
@@ -363,7 +363,7 @@ internal sealed unsafe class QuestFunctions
 
                 return firstStep.IsTeleportableForPriorityQuests();
             })
-            .FirstOrDefault(x =>
+            .Where(x =>
             {
                 if (!_questRegistry.TryGetQuest(x, out Quest? quest))
                     return false;
@@ -390,7 +390,8 @@ internal sealed unsafe class QuestFunctions
 
                     return true;
                 });
-            });
+            })
+            .ToList();
     }
 
     private static int EstimateTeleportCosts(Quest quest)
diff --git a/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs b/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs
index 2652685f4..7ec46f3dd 100644
--- a/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs
+++ b/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using System.Numerics;
 using System.Text.RegularExpressions;
@@ -167,8 +168,29 @@ internal sealed partial class ActiveQuestComponent
                     ImGui.SameLine();
                     ImGui.TextColored(ImGuiColors.DalamudYellow, SeIconChar.Hyadelyn.ToIconString());
                     if (ImGui.IsItemHovered())
-                        ImGui.SetTooltip(
-                            "This quest sequence starts with a teleport to an Aetheryte.\nCertain priority quest (e.g. class quests) may be started/completed by the plugin prior to continuing with this quest.");
+                    {
+                        using var tooltip = ImRaii.Tooltip();
+                        if (tooltip)
+                        {
+                            ImGui.Text("This quest sequence starts with a teleport to an Aetheryte.");
+                            ImGui.Text(
+                                "Certain priority quest (e.g. class quests) may be started/completed by the plugin prior to continuing with this quest.");
+                            ImGui.Separator();
+                            ImGui.Text("Available priority quests:");
+
+                            List<ElementId> priorityQuests = _questFunctions.GetNextPriorityQuestsThatCanBeAccepted();
+                            if (priorityQuests.Count > 0)
+                            {
+                                foreach (var questId in priorityQuests)
+                                {
+                                    if (_questRegistry.TryGetQuest(questId, out var quest))
+                                        ImGui.BulletText($"{quest.Info.Name} ({questId})");
+                                }
+                            }
+                            else
+                                ImGui.BulletText("(none)");
+                        }
+                    }
                 }
             }