Handle configured dialogue prompts; hide UI in blacklisted territories; path updates v0.3
authorLiza Carvelli <liza@carvel.li>
Mon, 3 Jun 2024 21:17:35 +0000 (23:17 +0200)
committerLiza Carvelli <liza@carvel.li>
Mon, 3 Jun 2024 21:18:35 +0000 (23:18 +0200)
Automatically handles:
- SelectString
- CutSceneSelectString
- SelectYesno
- Credit
- Closing Unending Codex during 'Newfound Adventure'

36 files changed:
QuestPaths/Endwalker/AetherCurrents/Thavnair/4203_Alchemist or Dancer.json
QuestPaths/Endwalker/MSQ/A-Thavnair1-Labyrinthos1/4370_A Fishermans Friend.json
QuestPaths/Endwalker/MSQ/J-6.3/4674_King of the Mountain.json
QuestPaths/Endwalker/MSQ/J-6.3/4677_Desires Untold.json
QuestPaths/Endwalker/MSQ/K-6.4/4736_Going Haam.json
QuestPaths/Endwalker/MSQ/K-6.4/4737_Like Fear to Flame.json
QuestPaths/Endwalker/MSQ/K-6.4/4738_The Fallen Empire.json
QuestPaths/Endwalker/MSQ/K-6.4/4739_Bonds of Trust.json
QuestPaths/Endwalker/MSQ/K-6.4/4740_Lunar Rendezvous.json
QuestPaths/Endwalker/MSQ/K-6.4/4741_The Red Side of the Moon.json
QuestPaths/Endwalker/MSQ/K-6.4/4742_Abyssal Dark.json
QuestPaths/Endwalker/MSQ/K-6.4/4743_The Dark Throne.json
QuestPaths/Endwalker/MSQ/L-6.5/4744_Seeking the Light.json
QuestPaths/Endwalker/MSQ/L-6.5/4748_Down in the Dark.json
QuestPaths/Endwalker/MSQ/L-6.5/4749_Reunited at Last.json
QuestPaths/Endwalker/MSQ/L-6.5/4750_Growing Light.json
QuestPaths/Endwalker/MSQ/M-6.55/4751_When One Door Closes.json
QuestPaths/Endwalker/MSQ/M-6.55/4752_The Game Is Afoot.json
QuestPaths/Endwalker/MSQ/M-6.55/4753_The Coming Dawn.json
QuestPaths/Shadowbringers/MSQ/F-Tempest/3654_Shadowbringers.json
QuestPaths/Shadowbringers/MSQ/G-5.1/3673_Shaken Resolve.json
QuestPaths/Shadowbringers/MSQ/G-5.1/3674_A Grand Adventure.json
QuestPaths/TODO Quest YesNo.txt [new file with mode: 0644]
QuestPaths/quest-v1.json
Questionable/Controller/GameUiController.cs [new file with mode: 0644]
Questionable/Controller/QuestController.cs
Questionable/GameFunctions.cs
Questionable/Model/V1/Converter/DialogueChoiceTypeConverter.cs [new file with mode: 0644]
Questionable/Model/V1/Converter/InteractionTypeConverter.cs
Questionable/Model/V1/DialogueChoice.cs
Questionable/Model/V1/EDialogChoiceType.cs [new file with mode: 0644]
Questionable/Model/V1/EInteractionType.cs
Questionable/Model/V1/QuestSequence.cs
Questionable/Questionable.csproj
Questionable/QuestionablePlugin.cs
Questionable/Windows/DebugWindow.cs

index 8615adf1554972891fcbf4dce36cb084bde6065c..17fc03509658898784560bf194024131235f1138 100644 (file)
           },
           "TerritoryId": 957,
           "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            128
+          ],
           "$": "QuestVariables after: 16 1 0 0 0 128"
         },
         {
             "Z": -159.90234
           },
           "TerritoryId": 957,
-          "InteractionType": "WalkTo"
+          "InteractionType": "WalkTo",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
+          ]
         },
         {
           "DataId": 2011914,
           "TerritoryId": 957,
           "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
+          ],
           "$": "QuestVariables after: 32 17 0 0 0 160"
         },
         {
             "Z": -157.09167
           },
           "TerritoryId": 957,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            64
+          ]
         }
       ]
     },
index 357f41b7d2c8666b890fd3546da4a98abf0ecf46..4f29e2b676376b7725cddf96b3331287efd9ea3f 100644 (file)
             "Z": 799.2217
           },
           "TerritoryId": 957,
-          "InteractionType": "CutsceneSelectString",
+          "InteractionType": "Interact",
           "DialogueChoices": [
             {
+              "Type": "List",
+              "Prompt": "TEXT_AKTKMA114_04370_Q2_000_086",
               "Answer": "TEXT_AKTKMA114_04370_A2_000_088"
             },
             {
+              "Type": "List",
+              "Prompt": "TEXT_AKTKMA114_04370_Q3_000_096",
               "Answer": "TEXT_AKTKMA114_04370_A3_000_098"
             },
             {
+              "Type": "List",
+              "Prompt": "TEXT_AKTKMA114_04370_Q5_000_106",
               "Answer": "TEXT_AKTKMA114_04370_A5_000_107"
             }
           ]
             "Z": 681.7273
           },
           "TerritoryId": 957,
-          "InteractionType": "CutsceneSelectString",
+          "InteractionType": "Interact",
           "DialogueChoices": [
             {
+              "Type": "List",
+              "Prompt": "TEXT_AKTKMA114_04370_Q6_000_147",
               "Answer": "TEXT_AKTKMA114_04370_A6_000_149"
             },
             {
+              "Type": "List",
+              "Prompt": "TEXT_AKTKMA114_04370_Q7_000_157",
               "Answer": "TEXT_AKTKMA114_04370_A7_000_158"
             },
             {
+              "Type": "List",
+              "Prompt": "TEXT_AKTKMA114_04370_Q8_000_162",
               "Answer": "TEXT_AKTKMA114_04370_A8_000_164"
             }
           ]
             "Z": 517.72327
           },
           "TerritoryId": 957,
-          "InteractionType": "CutsceneSelectString",
+          "InteractionType": "Interact",
           "DialogueChoices": [
             {
+              "Type": "List",
+              "Prompt": "TEXT_AKTKMA114_04370_Q9_000_198",
               "Answer": "TEXT_AKTKMA114_04370_A9_000_200"
             },
             {
+              "Type": "List",
+              "Prompt": "TEXT_AKTKMA114_04370_Q10_000_207",
               "Answer": "TEXT_AKTKMA114_04370_A10_000_209"
             },
             {
+              "Type": "List",
+              "Prompt": "TEXT_AKTKMA114_04370_Q11_000_216",
               "Answer": "TEXT_AKTKMA114_04370_A11_000_218"
             }
           ]
index 6f0cf2d862634766b0ed6bcc9d8c88b0fed335ee..dee5098f4e65017e0ab3606f8815513f4228d719 100644 (file)
@@ -1,6 +1,9 @@
 {
   "$schema": "https://carvel.li/questionable/quest-1.0",
   "Author": "liza",
+  "TerritoryBlacklist": [
+    1097
+  ],
   "QuestSequence": [
     {
       "Sequence": 0,
index 4d7218e36a5baf760531acf6f18b356e75b2479e..ce4256b1df93878f72a4c173b12eefb6d1427e2b 100644 (file)
@@ -1,6 +1,9 @@
 {
   "$schema": "https://carvel.li/questionable/quest-1.0",
   "Author": "liza",
+  "TerritoryBlacklist": [
+    1095
+  ],
   "QuestSequence": [
     {
       "Sequence": 0,
index a4a44a7ed5654a22462c5b945edece440824b336..d2815fbfd7c6cbe92ffc6b375ea6630130683613 100644 (file)
           },
           "StopDistance": 5,
           "TerritoryId": 962,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_AKTKMK102_04736_Q2_000_094",
+              "Yes": true
+            }
+          ]
         }
       ]
     },
index 0360fbc7d6666b934e46ad3da350ca9816b1c76f..b4972cf5b799067ffbf2bb04ddd36015ceaa692f 100644 (file)
           },
           "TerritoryId": 958,
           "InteractionType": "Interact",
-          "Comment": "TODO Check flags",
           "CompletionQuestVariablesFlags": [
             null,
             null,
     {
       "Sequence": 255,
       "Steps": [
+        {
+          "Position": {
+            "X": 534.8861,
+            "Y": -36.65,
+            "Z": -245.12135
+          },
+          "TerritoryId": 958,
+          "InteractionType": "WalkTo",
+          "SkipIf": [
+            "FlyingLocked"
+          ]
+        },
         {
           "DataId": 1045430,
           "Position": {
index 81e38a8a63890fa76e658364312e82aa18330cbb..79fc769babc482b651d3574d8768785070559ea3 100644 (file)
@@ -30,7 +30,8 @@
           },
           "TerritoryId": 958,
           "InteractionType": "Interact",
-          "Fly": true
+          "Fly": true,
+          "TargetTerritoryId": 1160
         }
       ]
     },
@@ -61,7 +62,6 @@
           },
           "TerritoryId": 1160,
           "InteractionType": "Interact",
-          "Comment": "TODO Check Flags",
           "CompletionQuestVariablesFlags": [
             null,
             null,
index bb8fb52f3e8eccd959f0000b866235bacd90c7b1..c6d94c9bd035ca1192e03279d0a7680181ca1170 100644 (file)
@@ -64,6 +64,7 @@
             "Y": 10.8,
             "Z": -231.61676
           },
+          "StopDistance": 5,
           "TerritoryId": 958,
           "InteractionType": "Interact"
         }
index 35d89bc3c80e3c0a8070d7f792ebc76273cf6502..347b99f388e4147b8ec81015d84a4168e42f5a74 100644 (file)
           "TerritoryId": 959,
           "InteractionType": "Interact",
           "AetheryteShortcut": "Mare Lamentorum - Bestways Burrow",
-          "SkipIf": ["FlyingUnlocked"],
-          "Comment": "Check if the flying unlocked check is good enough"
+          "SkipIf": [
+            "FlyingUnlocked"
+          ]
+        },
+        {
+          "Position": {
+            "X": -19.779482,
+            "Y": -56.63768,
+            "Z": -464.9354
+          },
+          "StopDistance": 1,
+          "TerritoryId": 959,
+          "InteractionType": "WalkTo",
+          "SkipIf": [
+            "FlyingLocked"
+          ],
+          "Fly": true
         },
         {
           "DataId": 1039686,
             "Z": -620.3861
           },
           "TerritoryId": 959,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "Fly": true
         }
       ]
     },
             null,
             null,
             32
-          ],
-          "Comment": "TODO Check Flags"
+          ]
         },
         {
           "DataId": 1045473,
             16
           ]
         }
-      ]
+      ],
+      "Comment": "TODO Check Flags (32)"
     },
     {
       "Sequence": 255,
index f9feb9c3986743ba0f727c75857df8c69b3f385a..d1d08aa6c0eb533d53a1b10d9007078cdd340b2c 100644 (file)
@@ -53,8 +53,7 @@
             null,
             null,
             128
-          ],
-          "Comment": "TODO Check Flags"
+          ]
         },
         {
           "DataId": 2013355,
index 524a09c230eb8d025c7c55e596185e301601013e..5076d2effff82e26d4432616905ce9ce690d8bdb 100644 (file)
@@ -1,6 +1,9 @@
 {
   "$schema": "https://carvel.li/questionable/quest-1.0",
   "Author": "liza",
+  "TerritoryBlacklist": [
+    1140
+  ],
   "QuestSequence": [
     {
       "Sequence": 0,
index 4817a88921d0d6a4ecf277386c5b96a07a09644d..ae89437887b4ce2f3c7d9fc10d1ceb36fa93fb1c 100644 (file)
           "TerritoryId": 959,
           "InteractionType": "Interact",
           "AetheryteShortcut": "Mare Lamentorum - Bestways Burrow",
-          "SkipIf": ["FlyingUnlocked"]
+          "SkipIf": [
+            "FlyingUnlocked"
+          ]
+        },
+        {
+          "Position": {
+            "X": -19.779482,
+            "Y": -56.63768,
+            "Z": -464.9354
+          },
+          "StopDistance": 1,
+          "TerritoryId": 959,
+          "InteractionType": "WalkTo",
+          "SkipIf": [
+            "FlyingLocked"
+          ],
+          "Fly": true
         },
         {
           "DataId": 1045466,
           "AethernetShortcut": [
             "[Radz-at-Han] Aetheryte Plaza",
             "[Radz-at-Han] Meghaduta"
+          ],
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_AKTKMK109_04743_Q1_000_000",
+              "Yes": true
+            }
           ]
         }
       ]
index 87f9eda5b095352e847f7b3a1d6a1ddff3f6e9d0..6403e2cdcd94a681e64804b1cdcd7d3d3f0dcf90 100644 (file)
@@ -27,7 +27,7 @@
             "Y": 55,
             "Z": -68.61987
           },
-          "StopDistance": 5,
+          "StopDistance": 7,
           "TerritoryId": 963,
           "InteractionType": "Interact"
         }
index 206d1297863a04d498d436082e1e07371f0fd252..1684a79dc087582a562398006324bbb7f4e65970 100644 (file)
@@ -1,6 +1,10 @@
 {
   "$schema": "https://carvel.li/questionable/quest-1.0",
   "Author": "liza",
+  "TerritoryBlacklist": [
+    1164,
+    1168
+  ],
   "QuestSequence": [
     {
       "Sequence": 0,
             "Z": -440.63483
           },
           "TerritoryId": 1184,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_AKTKML105_04748_SYSTEM_000_406",
+              "Yes": true
+            }
+          ]
         }
       ]
     },
index 2e89161493ae8dd47c8e3c4b5a10f5deb7cf70d9..82c54ad7040f9a618aeff2e3436346b0c3fcf804 100644 (file)
@@ -12,6 +12,7 @@
             "Y": 56.66061,
             "Z": 467.39905
           },
+          "StopDistance": 15,
           "TerritoryId": 1162,
           "InteractionType": "Interact"
         }
@@ -43,7 +44,8 @@
             "Z": -191.51605
           },
           "TerritoryId": 958,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "AetheryteShortcut": "Garlemald - Tertium"
         }
       ]
     },
@@ -59,6 +61,7 @@
           },
           "TerritoryId": 962,
           "InteractionType": "Interact",
+          "AetheryteShortcut": "Old Sharlayan",
           "AethernetShortcut": [
             "[Old Sharlayan] Aetheryte Plaza",
             "[Old Sharlayan] The Rostra"
index 2ca6af02ec9ab8f648aa3294dbdfa44640a50261..d68a56d1e79f84da75c6595d1563c2a13ff7a0a5 100644 (file)
@@ -12,6 +12,7 @@
             "Y": 41.530136,
             "Z": -165.27051
           },
+          "StopDistance": 7,
           "TerritoryId": 962,
           "InteractionType": "Interact"
         }
           },
           "TerritoryId": 819,
           "InteractionType": "Interact",
+          "AetheryteShortcut": "Crystarium",
           "AethernetShortcut": [
             "[Crystarium] Aetheryte Plaza",
             "[Crystarium] The Dossal Gate"
+          ],
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_AKTKML107_04750_SYSTEM_000_101",
+              "Yes": true
+            }
           ]
         }
       ]
         }
       ]
     },
+    {
+      "Sequence": 3,
+      "Steps": [
+        {
+          "DataId": 1045684,
+          "Position": {
+            "X": -0.96136475,
+            "Y": 0,
+            "Z": -3.3417358
+          },
+          "StopDistance": 5,
+          "TerritoryId": 844,
+          "InteractionType": "Interact"
+        }
+      ]
+    },
     {
       "Sequence": 4,
       "Steps": [
@@ -63,6 +88,7 @@
           },
           "TerritoryId": 963,
           "InteractionType": "Interact",
+          "AetheryteShortcut": "Radz-at-Han",
           "AethernetShortcut": [
             "[Radz-at-Han] Aetheryte Plaza",
             "[Radz-at-Han] Meghaduta"
       "Sequence": 255,
       "Steps": [
         {
-          "DataId": 196,
+          "DataId": 1039645,
           "Position": {
-            "X": -42.61847,
-            "Y": -0.015319824,
-            "Z": -197.61963
+            "X": -338.33832,
+            "Y": 55,
+            "Z": -68.40625
           },
           "TerritoryId": 963,
           "InteractionType": "Interact",
           "AethernetShortcut": [
             "[Radz-at-Han] Mehryde's Meyhane",
-            "[Radz-at-Han] Aetheryte Plaza"
+            "[Radz-at-Han] Meghaduta"
           ]
         }
       ]
index 93d122de1f794c740cc1e8cc47596dd1d6e5acd1..8a666924163aff976393e50f9e311aebb4813ee5 100644 (file)
             "Z": -68.40625
           },
           "TerritoryId": 963,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_AKTKMM103_04753_Q1_000_000",
+              "Answer": "TEXT_AKTKMM103_04753_A1_000_001"
+            }
+          ]
         }
       ]
     },
             "Y": 4.357494,
             "Z": 0.7476196
           },
+          "StopDistance": 7,
           "TerritoryId": 962,
           "InteractionType": "Interact",
+          "AetheryteShortcut": "Old Sharlayan",
           "AethernetShortcut": [
             "[Old Sharlayan] Aetheryte Plaza",
             "[Old Sharlayan] The Baldesion Annex"
index 0e40c9dbe8f56660671b6083a4aa613a7a9c9900..3268c428640d86fda59f07f41d9b18ebaefb9ed6 100644 (file)
@@ -1,6 +1,9 @@
 {
   "$schema": "https://carvel.li/questionable/quest-1.0",
   "Author": "liza",
+  "TerritoryBlacklist": [
+    1177
+  ],
   "QuestSequence": [
     {
       "Sequence": 0,
@@ -62,6 +65,7 @@
             "Y": -14.169313,
             "Z": 105.30249
           },
+          "StopDistance": 7,
           "TerritoryId": 962,
           "InteractionType": "Interact"
         }
@@ -77,6 +81,7 @@
             "Y": -15.127002,
             "Z": 139.42163
           },
+          "StopDistance": 5,
           "TerritoryId": 962,
           "InteractionType": "Interact"
         }
index 3747b3b367e8eb9ead2ce84a08d51207286f9449..5d1dec8b876799f7a2c966fef059b0958ce9be05 100644 (file)
@@ -12,6 +12,7 @@
             "Y": -15.127001,
             "Z": 139.45215
           },
+          "StopDistance": 5,
           "TerritoryId": 962,
           "InteractionType": "Interact"
         }
           "AethernetShortcut": [
             "[Old Sharlayan] Scholar's Harbor",
             "[Old Sharlayan] The Studium"
+          ],
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            16
           ]
         },
         {
             "Z": 103.28821
           },
           "TerritoryId": 962,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
+          ]
         },
         {
           "DataId": 2013417,
             "Z": 59.00659
           },
           "TerritoryId": 962,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            64
+          ]
         },
         {
           "DataId": 2013416,
             "Z": 20.523315
           },
           "TerritoryId": 962,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            128
+          ]
         }
       ]
     },
             "Z": 0.7476196
           },
           "TerritoryId": 962,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_AKTKMM103_04753_SYSTEM_000_302",
+              "Yes": true
+            }
+          ]
         }
       ]
     },
             "Y": 4.357494,
             "Z": 0.7476196
           },
+          "StopDistance": 5,
           "TerritoryId": 962,
           "InteractionType": "Interact"
         }
index 23b3f745ac7998ae27f11d3e33b2a1291b4955f8..2d5d419785472d3af423a63fb749d62b9dfe6edf 100644 (file)
@@ -2,6 +2,10 @@
   "$schema": "https://carvel.li/questionable/quest-1.0",
   "Author": "liza",
   "Comment": "TODO Missing Quest Start",
+  "TerritoryBlacklist": [
+    838,
+    847
+  ],
   "QuestSequence": [
     {
       "Sequence": 7,
index de3cd85459930d61255432c53614357a1a111f4c..4ff0ea5488c8cdd4b6811b2a0a754747c57e25d7 100644 (file)
             "Z": -9.10968
           },
           "TerritoryId": 351,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_LUCKMG101_03673_Q1_000_500",
+              "Answer": "TEXT_LUCKMG101_03673_A1_000_500"
+            }
+          ]
         }
       ]
     },
@@ -38,7 +45,8 @@
             "Z": -656.1909
           },
           "TerritoryId": 156,
-          "InteractionType": "WalkTo"
+          "InteractionType": "WalkTo",
+          "Mount": true
         },
         {
           "DataId": 1018433,
index b6a47fc7e3aa3a57f69054721c49b00fd4d65ae4..ab3cba3e2cc21a26804d6c548584f268a0fc102f 100644 (file)
@@ -26,6 +26,7 @@
             "Y": -0.67464465,
             "Z": 653.1527
           },
+          "StopDistance": 0.5,
           "TerritoryId": 813,
           "InteractionType": "WalkTo",
           "AetheryteShortcut": "Lakeland - Fort Jobb",
diff --git a/QuestPaths/TODO Quest YesNo.txt b/QuestPaths/TODO Quest YesNo.txt
new file mode 100644 (file)
index 0000000..64c5478
--- /dev/null
@@ -0,0 +1,13 @@
+Currying Flavor:
+  "DialogueChoices": [
+    {
+      "Type": "List",
+      "Prompt": "TEXT_AKTKMK101_04735_Q1_000_000",
+      "Answer": "TEXT_AKTKMK101_04735_A1_000_003"
+    },
+    {
+      "Type": "YesNo",
+      "Prompt": "TEXT_AKTKMK101_04735_Q2_000_182",
+      "Yes": true
+    }
+  ]
index 6162ef64a8f2c01da7fb3c01634d4e0549ae870b..ff33740aa79ce0575f6ac9aec610ba5a1e6d8bcc 100644 (file)
                     "Duty",
                     "SinglePlayerDuty",
                     "Jump",
-                    "CutsceneSelectString",
                     "ShouldBeAJump",
                     "Instruction"
                   ]
                   "if": {
                     "properties": {
                       "InteractionType": {
-                        "const": "CutsceneSelectString"
+                        "const": "Interact"
                       }
                     }
                   },
                         "items": {
                           "type": "object",
                           "properties": {
+                            "Type": {
+                              "type": "string",
+                              "enum": [
+                                "YesNo",
+                                "List"
+                              ]
+                            },
                             "ExcelSheet": {
                               "type": "string"
                             },
-                            "Answer": {
+                            "Prompt": {
                               "type": "string"
                             }
                           },
                           "required": [
-                            "Answer"
+                            "Type",
+                            "Prompt"
+                          ],
+                          "allOf": [
+                            {
+                              "if": {
+                                "properties": {
+                                  "Type": {
+                                    "const": "YesNo"
+                                  }
+                                }
+                              },
+                              "then": {
+                                "properties": {
+                                  "Yes": {
+                                    "type": "boolean",
+                                    "default": true
+                                  }
+                                },
+                                "required": [
+                                  "Yes"
+                                ]
+                              }
+                            },
+                            {
+                              "if": {
+                                "properties": {
+                                  "Type": {
+                                    "const": "List"
+                                  }
+                                }
+                              },
+                              "then": {
+                                "properties": {
+                                  "Answer": {
+                                    "type": "string"
+                                  }
+                                },
+                                "required": [
+                                  "Answer"
+                                ]
+                              }
+                            }
                           ]
                         }
                       }
-                    },
-                    "required": [
-                      "DialogueChoices"
-                    ]
+                    }
                   }
                 },
                 {
diff --git a/Questionable/Controller/GameUiController.cs b/Questionable/Controller/GameUiController.cs
new file mode 100644 (file)
index 0000000..63884ed
--- /dev/null
@@ -0,0 +1,240 @@
+using System;
+using System.Linq;
+using Dalamud.Game.Addon.Lifecycle;
+using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
+using Dalamud.Plugin.Services;
+using FFXIVClientStructs.FFXIV.Client.UI;
+using FFXIVClientStructs.FFXIV.Component.GUI;
+using LLib.GameUI;
+using Lumina.Excel.GeneratedSheets;
+using Questionable.Model.V1;
+using Quest = Questionable.Model.Quest;
+
+namespace Questionable.Controller;
+
+internal sealed class GameUiController : IDisposable
+{
+    private readonly IClientState _clientState;
+    private readonly IAddonLifecycle _addonLifecycle;
+    private readonly IDataManager _dataManager;
+    private readonly GameFunctions _gameFunctions;
+    private readonly QuestController _questController;
+    private readonly IPluginLog _pluginLog;
+
+    public GameUiController(IClientState clientState, IAddonLifecycle addonLifecycle, IDataManager dataManager,
+        GameFunctions gameFunctions, QuestController questController, IPluginLog pluginLog)
+    {
+        _clientState = clientState;
+        _addonLifecycle = addonLifecycle;
+        _dataManager = dataManager;
+        _gameFunctions = gameFunctions;
+        _questController = questController;
+        _pluginLog = pluginLog;
+
+        _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup);
+        _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "CutSceneSelectString", CutsceneSelectStringPostSetup);
+        _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectYesno", SelectYesnoPostSetup);
+        _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "Credit", CreditPostSetup);
+        _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup);
+    }
+
+    private unsafe void SelectStringPostSetup(AddonEvent type, AddonArgs args)
+    {
+        AddonSelectString* addonSelectString = (AddonSelectString*)args.Addon;
+        string? actualPrompt = addonSelectString->AtkUnitBase.AtkValues[2].ReadAtkString();
+        if (actualPrompt == null)
+            return;
+
+        var currentQuest = _questController.CurrentQuest;
+        if (currentQuest == null)
+            return;
+
+        var quest = currentQuest.Quest;
+        var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
+        if (step == null)
+            return;
+
+        foreach (var dialogueChoice in step.DialogueChoices)
+        {
+            if (dialogueChoice.Answer == null)
+                continue;
+
+            string? excelPrompt =
+                _gameFunctions.GetExcelString(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
+            string? excelAnswer =
+                _gameFunctions.GetExcelString(quest, dialogueChoice.ExcelSheet, dialogueChoice.Answer);
+            if (excelPrompt == null || actualPrompt != excelPrompt)
+                continue;
+
+            for (ushort i = 7; i <= addonSelectString->AtkUnitBase.AtkValuesCount; ++i)
+            {
+                string? actualAnswer = addonSelectString->AtkUnitBase.AtkValues[i].ReadAtkString();
+                if (actualAnswer == null || actualAnswer != excelAnswer)
+                    continue;
+
+                _questController.IncreaseDialogueChoicesSelected();
+                addonSelectString->AtkUnitBase.FireCallbackInt(i - 7);
+                return;
+            }
+        }
+    }
+
+    private unsafe void CutsceneSelectStringPostSetup(AddonEvent type, AddonArgs args)
+    {
+        AddonCutSceneSelectString* addonCutSceneSelectString = (AddonCutSceneSelectString*)args.Addon;
+        string? actualPrompt = addonCutSceneSelectString->AtkUnitBase.AtkValues[2].ReadAtkString();
+        if (actualPrompt == null)
+            return;
+
+        var currentQuest = _questController.CurrentQuest;
+        if (currentQuest == null)
+            return;
+
+        var quest = currentQuest.Quest;
+        var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
+        if (step == null)
+            return;
+
+        foreach (DialogueChoice dialogueChoice in step.DialogueChoices)
+        {
+            if (dialogueChoice.Answer == null)
+                continue;
+
+            string? excelPrompt =
+                _gameFunctions.GetExcelString(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
+            string? excelAnswer =
+                _gameFunctions.GetExcelString(quest, dialogueChoice.ExcelSheet, dialogueChoice.Answer);
+            if (excelPrompt == null || actualPrompt != excelPrompt)
+                continue;
+
+            for (int i = 5; i < addonCutSceneSelectString->AtkUnitBase.AtkValuesCount; ++i)
+            {
+                string? actualAnswer = addonCutSceneSelectString->AtkUnitBase.AtkValues[i].ReadAtkString();
+                if (actualAnswer == null || actualAnswer != excelAnswer)
+                    continue;
+
+                _questController.IncreaseDialogueChoicesSelected();
+                addonCutSceneSelectString->AtkUnitBase.FireCallbackInt(i - 5);
+                return;
+            }
+        }
+    }
+
+    private unsafe void SelectYesnoPostSetup(AddonEvent type, AddonArgs args)
+    {
+        AddonSelectYesno* addonSelectYesno = (AddonSelectYesno*)args.Addon;
+        string? actualPrompt = addonSelectYesno->AtkUnitBase.AtkValues[0].ReadAtkString();
+        if (actualPrompt == null)
+            return;
+
+        _pluginLog.Verbose($"Prompt: '{actualPrompt}'");
+
+        var currentQuest = _questController.CurrentQuest;
+        if (currentQuest == null)
+            return;
+
+        var quest = currentQuest.Quest;
+        var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
+        if (step != null && HandleDefaultYesNo(addonSelectYesno, quest, step, actualPrompt))
+            return;
+
+        HandleTravelYesNo(addonSelectYesno, currentQuest, actualPrompt);
+    }
+
+    private unsafe bool HandleDefaultYesNo(AddonSelectYesno* addonSelectYesno, Quest quest, QuestStep step,
+        string actualPrompt)
+    {
+        _pluginLog.Verbose($"DefaultYesNo: Choice count: {step.DialogueChoices.Count}");
+        foreach (var dialogueChoice in step.DialogueChoices)
+        {
+            string? excelPrompt =
+                _gameFunctions.GetExcelString(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
+            if (excelPrompt == null || actualPrompt != excelPrompt)
+                continue;
+
+            addonSelectYesno->AtkUnitBase.FireCallbackInt(dialogueChoice.Yes ? 0 : 1);
+            _questController.IncreaseDialogueChoicesSelected();
+            return true;
+        }
+
+        return false;
+    }
+
+    private unsafe bool HandleTravelYesNo(AddonSelectYesno* addonSelectYesno,
+        QuestController.QuestProgress currentQuest, string actualPrompt)
+    {
+        // this can be triggered either manually (in which case we should increase the step counter), or automatically
+        // (in which case it is ~1 frame later, and the step counter has already been increased)
+        var sequence = currentQuest.Quest.FindSequence(currentQuest.Sequence);
+        if (sequence == null)
+            return false;
+
+        bool increaseStepCount = true;
+        QuestStep? step = sequence.FindStep(currentQuest.Step);
+        if (step != null)
+            _pluginLog.Verbose($"Current step: {step.TerritoryId}, {step.TargetTerritoryId}");
+
+        if (step == null || step.TargetTerritoryId == null || step.TerritoryId != _clientState.TerritoryType)
+        {
+            _pluginLog.Verbose("TravelYesNo: Checking previous step...");
+            step = sequence.FindStep(currentQuest.Step == 255 ? (sequence.Steps.Count - 1) : (currentQuest.Step - 1));
+            increaseStepCount = false;
+
+            if (step != null)
+                _pluginLog.Verbose($"Previous step: {step.TerritoryId}, {step.TargetTerritoryId}");
+        }
+
+        if (step == null || step.TargetTerritoryId == null || step.TerritoryId != _clientState.TerritoryType)
+        {
+            _pluginLog.Verbose("TravelYesNo: Not found");
+            return false;
+        }
+
+        var warps = _dataManager.GetExcelSheet<Warp>()!
+            .Where(x => x.RowId > 0 && x.TerritoryType.Row == step.TargetTerritoryId)
+            .Where(x => x.ConfirmEvent.Row == 0); // unsure if this is needed
+        foreach (var entry in warps)
+        {
+            string? excelPrompt = entry.Question?.ToString();
+            if (excelPrompt == null || excelPrompt != actualPrompt)
+            {
+                _pluginLog.Information($"Ignoring prompt '{excelPrompt}'");
+                continue;
+            }
+
+            _pluginLog.Information($"Using warp {entry.RowId}, {excelPrompt}");
+            addonSelectYesno->AtkUnitBase.FireCallbackInt(0);
+            if (increaseStepCount)
+                _questController.IncreaseStepCount();
+            return true;
+        }
+
+        return false;
+    }
+
+    private unsafe void CreditPostSetup(AddonEvent type, AddonArgs args)
+    {
+        _pluginLog.Information("Closing Credits sequence");
+        AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
+        addon->FireCallbackInt(-2);
+    }
+
+    private unsafe void UnendingCodexPostSetup(AddonEvent type, AddonArgs args)
+    {
+        if (_questController.CurrentQuest?.Quest.QuestId == 4526)
+        {
+            _pluginLog.Information("Closing Unending Codex");
+            AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
+            addon->FireCallbackInt(-2);
+        }
+    }
+
+    public void Dispose()
+    {
+        _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup);
+        _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "Credit", CreditPostSetup);
+        _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "SelectYesno", SelectYesnoPostSetup);
+        _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "CutSceneSelectString", CutsceneSelectStringPostSetup);
+        _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup);
+    }
+}
index ad9d91ec70dfcc7737a3e4170dc75466cf90366b..03425ba1451cc62ce59312ee3d712e026a58bfbe 100644 (file)
@@ -10,14 +10,11 @@ using Dalamud.Plugin;
 using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
 using FFXIVClientStructs.FFXIV.Client.Game;
-using FFXIVClientStructs.FFXIV.Client.UI;
-using LLib.GameUI;
 using Questionable.Data;
 using Questionable.External;
 using Questionable.Model;
 using Questionable.Model.V1;
 using Questionable.Model.V1.Converter;
-using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
 
 namespace Questionable.Controller;
 
@@ -272,6 +269,27 @@ internal sealed class QuestController
         }
     }
 
+    public void IncreaseDialogueChoicesSelected()
+    {
+        (QuestSequence? seq, QuestStep? step) = GetNextStep();
+        if (CurrentQuest == null || seq == null || step == null)
+        {
+            _pluginLog.Warning("Unable to retrieve next quest step, not increasing dialogue choice count");
+            return;
+        }
+
+        CurrentQuest = CurrentQuest with
+        {
+            StepProgress = CurrentQuest.StepProgress with
+            {
+                DialogueChoicesSelected = CurrentQuest.StepProgress.DialogueChoicesSelected + 1
+            }
+        };
+
+        if (CurrentQuest.StepProgress.DialogueChoicesSelected >= step.DialogueChoices.Count)
+            IncreaseStepCount();
+    }
+
     public unsafe void ExecuteNextStep()
     {
         (QuestSequence? seq, QuestStep? step) = GetNextStep();
@@ -422,7 +440,8 @@ internal sealed class QuestController
                 }
             }
             else
-                _pluginLog.Warning($"Aethernet shortcut not unlocked (from: {step.AethernetShortcut.From}, to: {step.AethernetShortcut.To}), walking manually");
+                _pluginLog.Warning(
+                    $"Aethernet shortcut not unlocked (from: {step.AethernetShortcut.From}, to: {step.AethernetShortcut.To}), walking manually");
         }
 
         if (step.TargetTerritoryId == _clientState.TerritoryType && !step.SkipIf.Contains(ESkipCondition.Never))
@@ -439,11 +458,6 @@ internal sealed class QuestController
         {
             _pluginLog.Information("We're at the jump destination, skipping movement");
         }
-        else if (step.InteractionType == EInteractionType.CutsceneSelectString &&
-                 _condition[ConditionFlag.OccupiedInCutSceneEvent])
-        {
-            _pluginLog.Information("In cutscene selection, skipping movement");
-        }
         else if (step.Position != null)
         {
             float distance;
@@ -543,7 +557,10 @@ internal sealed class QuestController
                     }
 
                     _gameFunctions.InteractWith(step.DataId.Value);
-                    IncreaseStepCount();
+
+                    // if we have any dialogue, that is handled in GameUiController
+                    if (step.DialogueChoices.Count == 0)
+                        IncreaseStepCount();
                 }
                 else
                     _pluginLog.Warning("Not interacting on current step, DataId is null");
@@ -712,41 +729,6 @@ internal sealed class QuestController
                 // Need to manually forward
                 break;
 
-            case EInteractionType.CutsceneSelectString:
-                // to do this automatically, should likely be in Addon's post setup
-                if (_gameGui.TryGetAddonByName<AddonCutSceneSelectString>("CutSceneSelectString", out var addon) &&
-                    LAddon.IsAddonReady(&addon->AtkUnitBase))
-                {
-                    foreach (DialogueChoice dialogueChoice in step.DialogueChoices)
-                    {
-                        string? excelString = _gameFunctions.GetExcelString(CurrentQuest.Quest,
-                            dialogueChoice.ExcelSheet, dialogueChoice.Answer);
-                        if (excelString == null)
-                            return;
-
-                        _pluginLog.Verbose($"Looking for option '{excelString}'");
-                        for (int i = 5; i < addon->AtkUnitBase.AtkValuesCount; ++i)
-                        {
-                            var atkValue = addon->AtkUnitBase.AtkValues[i];
-                            if (atkValue.Type != ValueType.String)
-                                continue;
-
-                            string? atkString = atkValue.ReadAtkString();
-                            _pluginLog.Verbose($"Option {i}: {atkString}");
-                            if (excelString == atkString)
-                            {
-                                _pluginLog.Information($"Selecting option {i - 5}: {atkString}");
-                                addon->AtkUnitBase.FireCallbackInt(i - 5);
-                                return;
-                            }
-                        }
-                    }
-                }
-                else if (step.DataId != null && !_condition[ConditionFlag.OccupiedInCutSceneEvent])
-                    _gameFunctions.InteractWith(step.DataId.Value);
-
-                break;
-
             default:
                 _pluginLog.Warning($"Action '{step.InteractionType}' is not implemented");
                 break;
@@ -767,5 +749,6 @@ internal sealed class QuestController
 
     public sealed record StepProgress(
         bool AetheryteShortcutUsed = false,
-        bool AethernetShortcutUsed = false);
+        bool AethernetShortcutUsed = false,
+        int DialogueChoicesSelected = 0);
 }
index 79d728cd6b1f7742612a455ed519712c7b5ee25e..6a276159e477589eb1094f0e11195fa88a6a9f47 100644 (file)
@@ -474,22 +474,18 @@ internal sealed unsafe class GameFunctions
             _pluginLog.Error($"Could not find content for content finder condition (cf: {contentFinderConditionId})");
     }
 
-    public string? GetExcelString(Quest currentQuestQuest, string? excelSheetName, string key)
+    public string? GetExcelString(Quest currentQuest, string? excelSheetName, string key)
     {
         if (excelSheetName == null)
         {
-            string questPrefix = $"quest/{(currentQuestQuest.QuestId / 100):000}/";
-            string questSuffix = $"_{currentQuestQuest.QuestId:00000}";
-            excelSheetName = _dataManager.Excel
-                .GetSheetNames()
-                .SingleOrDefault(x =>
-                    x.StartsWith(questPrefix, StringComparison.Ordinal) &&
-                    x.EndsWith(questSuffix, StringComparison.Ordinal));
-            if (excelSheetName == null)
+            var questRow = _dataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets2.Quest>()!.GetRow((uint)currentQuest.QuestId + 0x10000);
+            if (questRow == null)
             {
-                _pluginLog.Error($"Could not find sheet matching '{questPrefix}*{questSuffix}");
+                _pluginLog.Error($"Could not find quest row for {currentQuest.QuestId}");
                 return null;
             }
+
+            excelSheetName = $"quest/{(currentQuest.QuestId / 100):000}/{questRow.Id}";
         }
 
         var excelSheet = _dataManager.Excel.GetSheet<QuestDialogueText>(excelSheetName);
diff --git a/Questionable/Model/V1/Converter/DialogueChoiceTypeConverter.cs b/Questionable/Model/V1/Converter/DialogueChoiceTypeConverter.cs
new file mode 100644 (file)
index 0000000..ea832ca
--- /dev/null
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+
+namespace Questionable.Model.V1.Converter;
+
+public sealed class DialogueChoiceTypeConverter() : EnumConverter<EDialogChoiceType>(Values)
+{
+    private static readonly Dictionary<EDialogChoiceType, string> Values = new()
+    {
+        { EDialogChoiceType.YesNo, "YesNo" },
+        { EDialogChoiceType.List, "List" },
+    };
+}
index 09a4dfafe1000f6e43fbe8896582fce65b8280af..fcd2228b2b9298e3f7e48e233fcf583eab64adb0 100644 (file)
@@ -20,7 +20,6 @@ public sealed class InteractionTypeConverter() : EnumConverter<EInteractionType>
         { EInteractionType.Duty, "Duty" },
         { EInteractionType.SinglePlayerDuty, "SinglePlayerDuty" },
         { EInteractionType.Jump, "Jump" },
-        { EInteractionType.CutsceneSelectString, "CutsceneSelectString" },
         { EInteractionType.ShouldBeAJump, "ShouldBeAJump" },
         { EInteractionType.Instruction, "Instruction" },
     };
index d4c607e7191850a9a03f16842a4f9ed68c5871af..1f85c63eedce9a31987f0bf415da8775a003e8c3 100644 (file)
@@ -1,7 +1,14 @@
-namespace Questionable.Model.V1;
+using System.Text.Json.Serialization;
+using Questionable.Model.V1.Converter;
 
-public sealed class DialogueChoice
+namespace Questionable.Model.V1;
+
+public class DialogueChoice
 {
+    [JsonConverter(typeof(DialogueChoiceTypeConverter))]
+    public EDialogChoiceType Type { get; set; }
     public string? ExcelSheet { get; set; }
-    public string Answer { get; set; } = null!;
+    public string Prompt { get; set; } = null!;
+    public bool Yes { get; set; } = true;
+    public string? Answer { get; set; }
 }
diff --git a/Questionable/Model/V1/EDialogChoiceType.cs b/Questionable/Model/V1/EDialogChoiceType.cs
new file mode 100644 (file)
index 0000000..008418f
--- /dev/null
@@ -0,0 +1,8 @@
+namespace Questionable.Model.V1;
+
+public enum EDialogChoiceType
+{
+    None,
+    YesNo,
+    List
+}
index ae0267f0659169e4ff558c279346d4676ca1523e..f0ca8a32584711474eb550f5631852ac6e92b8ef 100644 (file)
@@ -20,7 +20,6 @@ public enum EInteractionType
     Duty,
     SinglePlayerDuty,
     Jump,
-    CutsceneSelectString,
 
     /// <summary>
     /// Needs to be adjusted for coords etc. in the quest data.
index cd691b13f9a3869dd83915596b14545e6b9ff244..4ea058ed39cf07ff04b6f066ecc958786f0f6119 100644 (file)
@@ -7,4 +7,12 @@ public class QuestSequence
     public required int Sequence { get; set; }
     public string? Comment { get; set; }
     public List<QuestStep> Steps { get; set; } = new();
+
+    public QuestStep? FindStep(int step)
+    {
+        if (step < 0 || step >= Steps.Count)
+            return null;
+
+        return Steps[step];
+    }
 }
index ac0f229bcdc96252a4128a235346d6d03f4b36a2..1bc72708ef799817226afacb1423b408281bd513 100644 (file)
@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
         <TargetFramework>net8.0-windows</TargetFramework>
-        <Version>0.2</Version>
+        <Version>0.3</Version>
         <LangVersion>12</LangVersion>
         <Nullable>enable</Nullable>
         <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
index 4d04fec286042e4ef47d9424f461ca177af13d60..5e81004058e6643596eb9a2e14d39c429e3c4000 100644 (file)
@@ -27,13 +27,13 @@ public sealed class QuestionablePlugin : IDalamudPlugin
     private readonly ICommandManager _commandManager;
     private readonly GameFunctions _gameFunctions;
     private readonly QuestController _questController;
-
     private readonly MovementController _movementController;
+    private readonly GameUiController _gameUiController;
 
     public QuestionablePlugin(DalamudPluginInterface pluginInterface, IClientState clientState,
         ITargetManager targetManager, IFramework framework, IGameGui gameGui, IDataManager dataManager,
         ISigScanner sigScanner, IObjectTable objectTable, IPluginLog pluginLog, ICondition condition, IChatGui chatGui,
-        ICommandManager commandManager)
+        ICommandManager commandManager, IAddonLifecycle addonLifecycle)
     {
         ArgumentNullException.ThrowIfNull(pluginInterface);
         ArgumentNullException.ThrowIfNull(sigScanner);
@@ -55,6 +55,9 @@ public sealed class QuestionablePlugin : IDalamudPlugin
             new MovementController(navmeshIpc, clientState, _gameFunctions, condition, pluginLog);
         _questController = new QuestController(pluginInterface, dataManager, _clientState, _gameFunctions,
             _movementController, pluginLog, condition, chatGui, framework, gameGui, aetheryteData, lifestreamIpc);
+        _gameUiController =
+            new GameUiController(clientState, addonLifecycle, dataManager, _gameFunctions, _questController, pluginLog);
+
         _windowSystem.AddWindow(new DebugWindow(_movementController, _questController, _gameFunctions, clientState,
             targetManager));
 
@@ -100,6 +103,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
         _framework.Update -= FrameworkUpdate;
         _pluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
 
+        _gameUiController.Dispose();
         _movementController.Dispose();
     }
 }
index 845fd530622d804582893fde45484ee210bc2f26..b3c684500c0bf75847986f4be0caf06500fa21c4 100644 (file)
@@ -1,12 +1,9 @@
 using System.Globalization;
-using System.Linq;
 using System.Numerics;
-using System.Runtime.InteropServices;
 using Dalamud.Game.ClientState.Objects;
 using Dalamud.Interface;
 using Dalamud.Interface.Components;
 using Dalamud.Interface.Windowing;
-using Dalamud.Memory;
 using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Client.Game;
 using FFXIVClientStructs.FFXIV.Client.Game.Control;
@@ -45,6 +42,15 @@ internal sealed class DebugWindow : Window
         };
     }
 
+    public override bool DrawConditions()
+    {
+        if (!_clientState.IsLoggedIn || _clientState.LocalPlayer == null)
+            return false;
+
+        var currentQuest = _questController.CurrentQuest;
+        return currentQuest == null || !currentQuest.Quest.Data.TerritoryBlacklist.Contains(_clientState.TerritoryType);
+    }
+
     public override unsafe void Draw()
     {
         if (!_clientState.IsLoggedIn || _clientState.LocalPlayer == null)