Migrate QuestIds; add more quest paths v2.0
authorLiza Carvelli <liza@carvel.li>
Sat, 3 Aug 2024 20:17:18 +0000 (22:17 +0200)
committerLiza Carvelli <liza@carvel.li>
Sat, 3 Aug 2024 20:41:18 +0000 (22:41 +0200)
53 files changed:
GatheringPaths/2.x - A Realm Reborn/.gitkeep [deleted file]
GatheringPaths/2.x - A Realm Reborn/Central Thanalan/157_Spineless Basin_MIN.json [new file with mode: 0644]
GatheringPaths/2.x - A Realm Reborn/Western Thanalan/154_Hammerlea_MIN.json [new file with mode: 0644]
GatheringPaths/6.x - Endwalker/Elysion/316__MIN.json [new file with mode: 0644]
GatheringPaths/6.x - Endwalker/Elysion/317__MIN.json [new file with mode: 0644]
GatheringPaths/6.x - Endwalker/Elysion/322__MIN.json [new file with mode: 0644]
GatheringPaths/6.x - Endwalker/Elysion/336__MIN.json [new file with mode: 0644]
GatheringPaths/6.x - Endwalker/Elysion/393__BTN.json [new file with mode: 0644]
GatheringPaths/6.x - Endwalker/Elysion/394__BTN.json [new file with mode: 0644]
GatheringPaths/6.x - Endwalker/Elysion/398__BTN.json [new file with mode: 0644]
GatheringPaths/6.x - Endwalker/Elysion/399__BTN.json [new file with mode: 0644]
QuestPathGenerator/QuestSourceGenerator.cs
QuestPathGenerator/RoslynShortcuts.cs
QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/192_So You Want to Be a Miner.json [new file with mode: 0644]
QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/597_Way of the Miner.json [new file with mode: 0644]
QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/599_My First Pickaxe.json [new file with mode: 0644]
QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/600_Know Thy Land.json [new file with mode: 0644]
QuestPaths/quest-v1.json
Questionable.Model/Questing/Converter/ElementIdConverter.cs [new file with mode: 0644]
Questionable.Model/Questing/Converter/IdConverter.cs [deleted file]
Questionable.Model/Questing/ElementId.cs [new file with mode: 0644]
Questionable.Model/Questing/IId.cs [deleted file]
Questionable.Model/Questing/QuestStep.cs
Questionable.Model/Questing/SkipAetheryteCondition.cs
Questionable.Model/Questing/SkipStepConditions.cs
Questionable/Controller/CombatController.cs
Questionable/Controller/CommandHandler.cs
Questionable/Controller/GameUiController.cs
Questionable/Controller/QuestController.cs
Questionable/Controller/QuestRegistry.cs
Questionable/Controller/Steps/Common/NextQuest.cs
Questionable/Controller/Steps/ILastTask.cs
Questionable/Controller/Steps/Interactions/Combat.cs
Questionable/Controller/Steps/Interactions/UseItem.cs
Questionable/Controller/Steps/Shared/AetheryteShortcut.cs
Questionable/Controller/Steps/Shared/SkipCondition.cs
Questionable/Controller/Steps/Shared/WaitAtEnd.cs
Questionable/Data/QuestData.cs
Questionable/GameFunctions.cs
Questionable/Model/Quest.cs
Questionable/Questionable.csproj
Questionable/Validation/ValidationIssue.cs
Questionable/Validation/Validators/AethernetShortcutValidator.cs
Questionable/Validation/Validators/BasicSequenceValidator.cs
Questionable/Validation/Validators/CompletionFlagsValidator.cs
Questionable/Validation/Validators/JsonSchemaValidator.cs
Questionable/Validation/Validators/NextQuestValidator.cs
Questionable/Validation/Validators/QuestDisabledValidator.cs
Questionable/Validation/Validators/UniqueStartStopValidator.cs
Questionable/Windows/DebugOverlay.cs
Questionable/Windows/QuestComponents/ActiveQuestComponent.cs
Questionable/Windows/QuestSelectionWindow.cs
Questionable/Windows/UiUtils.cs

diff --git a/GatheringPaths/2.x - A Realm Reborn/.gitkeep b/GatheringPaths/2.x - A Realm Reborn/.gitkeep
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/GatheringPaths/2.x - A Realm Reborn/Central Thanalan/157_Spineless Basin_MIN.json b/GatheringPaths/2.x - A Realm Reborn/Central Thanalan/157_Spineless Basin_MIN.json
new file mode 100644 (file)
index 0000000..66426fb
--- /dev/null
@@ -0,0 +1,152 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 141,
+  "AetheryteShortcut": "Central Thanalan - Black Brush Station",
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 30425,
+          "Locations": [
+            {
+              "Position": {
+                "X": 118.6389,
+                "Y": 7.583679,
+                "Z": 262.4399
+              },
+              "MinimumAngle": 60,
+              "MaximumAngle": 170
+            },
+            {
+              "Position": {
+                "X": 113.4342,
+                "Y": 4.562373,
+                "Z": 271.4816
+              },
+              "MinimumAngle": 80,
+              "MaximumAngle": 190
+            },
+            {
+              "Position": {
+                "X": 116.9106,
+                "Y": 2.964557,
+                "Z": 285.8209
+              },
+              "MinimumAngle": 0,
+              "MaximumAngle": 115
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 30427,
+          "Locations": [
+            {
+              "Position": {
+                "X": 127.2449,
+                "Y": 15.54889,
+                "Z": 240.1923
+              },
+              "MinimumAngle": 15,
+              "MaximumAngle": 115
+            },
+            {
+              "Position": {
+                "X": 122.0915,
+                "Y": 14.071,
+                "Z": 225.1131
+              },
+              "MinimumAngle": 0,
+              "MaximumAngle": 110
+            },
+            {
+              "Position": {
+                "X": 120.8954,
+                "Y": 15.9651,
+                "Z": 213.8515
+              },
+              "MinimumAngle": 30,
+              "MaximumAngle": 115
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 30426,
+          "Locations": [
+            {
+              "Position": {
+                "X": 148.7842,
+                "Y": 16.44447,
+                "Z": 292.8037
+              },
+              "MinimumAngle": 30,
+              "MaximumAngle": 135
+            },
+            {
+              "Position": {
+                "X": 144.9166,
+                "Y": 18.86193,
+                "Z": 264.833
+              },
+              "MinimumAngle": 15,
+              "MaximumAngle": 95
+            },
+            {
+              "Position": {
+                "X": 152.6806,
+                "Y": 16.58945,
+                "Z": 300.3315
+              },
+              "MinimumAngle": 0,
+              "MaximumAngle": 75
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 30428,
+          "Locations": [
+            {
+              "Position": {
+                "X": 137.6659,
+                "Y": 6.65416,
+                "Z": 311.1226
+              },
+              "MinimumAngle": 15,
+              "MaximumAngle": 135
+            },
+            {
+              "Position": {
+                "X": 141.0331,
+                "Y": 5.844177,
+                "Z": 325.063
+              },
+              "MinimumAngle": 0,
+              "MaximumAngle": 150
+            },
+            {
+              "Position": {
+                "X": 130.6749,
+                "Y": 5.736229,
+                "Z": 300.4703
+              },
+              "MinimumAngle": -5,
+              "MaximumAngle": 100
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/GatheringPaths/2.x - A Realm Reborn/Western Thanalan/154_Hammerlea_MIN.json b/GatheringPaths/2.x - A Realm Reborn/Western Thanalan/154_Hammerlea_MIN.json
new file mode 100644 (file)
index 0000000..4a13bd8
--- /dev/null
@@ -0,0 +1,152 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 140,
+  "AetheryteShortcut": "Western Thanalan - Horizon",
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 30414,
+          "Locations": [
+            {
+              "Position": {
+                "X": 249.8601,
+                "Y": 55.12077,
+                "Z": 178.5377
+              },
+              "MinimumAngle": 125,
+              "MaximumAngle": 270
+            },
+            {
+              "Position": {
+                "X": 253.9519,
+                "Y": 55.95691,
+                "Z": 181.4238
+              },
+              "MinimumAngle": 180,
+              "MaximumAngle": 285
+            },
+            {
+              "Position": {
+                "X": 244.4912,
+                "Y": 53.49751,
+                "Z": 169.9265
+              },
+              "MinimumAngle": 150,
+              "MaximumAngle": 250
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 30413,
+          "Locations": [
+            {
+              "Position": {
+                "X": 292.9385,
+                "Y": 59.79165,
+                "Z": 187.855
+              },
+              "MinimumAngle": 45,
+              "MaximumAngle": 165
+            },
+            {
+              "Position": {
+                "X": 300.3293,
+                "Y": 63.1124,
+                "Z": 175.0616
+              },
+              "MinimumAngle": 65,
+              "MaximumAngle": 155
+            },
+            {
+              "Position": {
+                "X": 296.3942,
+                "Y": 61.46834,
+                "Z": 182.3181
+              },
+              "MinimumAngle": 70,
+              "MaximumAngle": 185
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 30415,
+          "Locations": [
+            {
+              "Position": {
+                "X": 262.1395,
+                "Y": 58.70948,
+                "Z": 239.3097
+              },
+              "MinimumAngle": 105,
+              "MaximumAngle": 210
+            },
+            {
+              "Position": {
+                "X": 284.4424,
+                "Y": 59.78878,
+                "Z": 222.5899
+              },
+              "MinimumAngle": 65,
+              "MaximumAngle": 240
+            },
+            {
+              "Position": {
+                "X": 278.6144,
+                "Y": 59.63044,
+                "Z": 231.8303
+              },
+              "MinimumAngle": 95,
+              "MaximumAngle": 185
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 30416,
+          "Locations": [
+            {
+              "Position": {
+                "X": 222.244,
+                "Y": 58.86799,
+                "Z": 244.9212
+              },
+              "MinimumAngle": 135,
+              "MaximumAngle": 275
+            },
+            {
+              "Position": {
+                "X": 212.3073,
+                "Y": 58.06055,
+                "Z": 245.9091
+              },
+              "MinimumAngle": 80,
+              "MaximumAngle": 220
+            },
+            {
+              "Position": {
+                "X": 235.9484,
+                "Y": 58.30469,
+                "Z": 249.0489
+              },
+              "MinimumAngle": 80,
+              "MaximumAngle": 190
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/GatheringPaths/6.x - Endwalker/Elysion/316__MIN.json b/GatheringPaths/6.x - Endwalker/Elysion/316__MIN.json
new file mode 100644 (file)
index 0000000..d401f0d
--- /dev/null
@@ -0,0 +1,61 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 1073,
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 31819,
+          "Locations": [
+            {
+              "Position": {
+                "X": -5.492728,
+                "Y": 499.6548,
+                "Z": 37.58726
+              },
+              "MinimumAngle": 145,
+              "MaximumAngle": 300
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 31700,
+          "Locations": [
+            {
+              "Position": {
+                "X": 27.22863,
+                "Y": 499.8322,
+                "Z": 2.94655
+              },
+              "MinimumAngle": -15,
+              "MaximumAngle": 210
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 31489,
+          "Locations": [
+            {
+              "Position": {
+                "X": 28.38036,
+                "Y": 500.019,
+                "Z": -0.7058061
+              },
+              "MinimumAngle": 0,
+              "MaximumAngle": 210
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/GatheringPaths/6.x - Endwalker/Elysion/317__MIN.json b/GatheringPaths/6.x - Endwalker/Elysion/317__MIN.json
new file mode 100644 (file)
index 0000000..2fb8620
--- /dev/null
@@ -0,0 +1,57 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 1073,
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 31822,
+          "Locations": [
+            {
+              "Position": {
+                "X": -4.054798,
+                "Y": 494.3483,
+                "Z": -54.37905
+              }
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 31821,
+          "Locations": [
+            {
+              "Position": {
+                "X": -5.287843,
+                "Y": 494.2204,
+                "Z": -66.80152
+              }
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 31820,
+          "Locations": [
+            {
+              "Position": {
+                "X": -9.143447,
+                "Y": 494.1166,
+                "Z": -82.62958
+              },
+              "MinimumAngle": -75,
+              "MaximumAngle": 95
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/GatheringPaths/6.x - Endwalker/Elysion/322__MIN.json b/GatheringPaths/6.x - Endwalker/Elysion/322__MIN.json
new file mode 100644 (file)
index 0000000..7854b51
--- /dev/null
@@ -0,0 +1,61 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 1073,
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 33842,
+          "Locations": [
+            {
+              "Position": {
+                "X": -71.72573,
+                "Y": 495.8044,
+                "Z": -23.42241
+              },
+              "MinimumAngle": -15,
+              "MaximumAngle": 90
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 33846,
+          "Locations": [
+            {
+              "Position": {
+                "X": -85.765,
+                "Y": 493.9822,
+                "Z": -11.33734
+              },
+              "MinimumAngle": -185,
+              "MaximumAngle": 20
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 33847,
+          "Locations": [
+            {
+              "Position": {
+                "X": -100.52,
+                "Y": 493.6702,
+                "Z": -9.731167
+              },
+              "MinimumAngle": -185,
+              "MaximumAngle": -25
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/GatheringPaths/6.x - Endwalker/Elysion/336__MIN.json b/GatheringPaths/6.x - Endwalker/Elysion/336__MIN.json
new file mode 100644 (file)
index 0000000..c5f722c
--- /dev/null
@@ -0,0 +1,61 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 1073,
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 33848,
+          "Locations": [
+            {
+              "Position": {
+                "X": -109.0629,
+                "Y": 491.0458,
+                "Z": 34.78553
+              },
+              "MinimumAngle": -110,
+              "MaximumAngle": 35
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 33849,
+          "Locations": [
+            {
+              "Position": {
+                "X": -110.2371,
+                "Y": 491.0116,
+                "Z": 54.68977
+              },
+              "MinimumAngle": -170,
+              "MaximumAngle": -45
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 33850,
+          "Locations": [
+            {
+              "Position": {
+                "X": -101.4737,
+                "Y": 490.7073,
+                "Z": 54.9267
+              },
+              "MinimumAngle": 90,
+              "MaximumAngle": 220
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/GatheringPaths/6.x - Endwalker/Elysion/393__BTN.json b/GatheringPaths/6.x - Endwalker/Elysion/393__BTN.json
new file mode 100644 (file)
index 0000000..d4c4076
--- /dev/null
@@ -0,0 +1,57 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 1073,
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 33851,
+          "Locations": [
+            {
+              "Position": {
+                "X": -10.66682,
+                "Y": 499.3763,
+                "Z": 34.01145
+              }
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 32269,
+          "Locations": [
+            {
+              "Position": {
+                "X": -16.14751,
+                "Y": 499.7353,
+                "Z": 22.38433
+              }
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 32766,
+          "Locations": [
+            {
+              "Position": {
+                "X": -28.72828,
+                "Y": 499.5391,
+                "Z": 33.41306
+              },
+              "MinimumAngle": 125,
+              "MaximumAngle": 335
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/GatheringPaths/6.x - Endwalker/Elysion/394__BTN.json b/GatheringPaths/6.x - Endwalker/Elysion/394__BTN.json
new file mode 100644 (file)
index 0000000..a405c66
--- /dev/null
@@ -0,0 +1,61 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 1073,
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 34347,
+          "Locations": [
+            {
+              "Position": {
+                "X": -13.64273,
+                "Y": 493.9979,
+                "Z": -58.21632
+              },
+              "MinimumAngle": -5,
+              "MaximumAngle": 210
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34348,
+          "Locations": [
+            {
+              "Position": {
+                "X": -22.23647,
+                "Y": 494.0945,
+                "Z": -59.94842
+              },
+              "MinimumAngle": 125,
+              "MaximumAngle": 360
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34334,
+          "Locations": [
+            {
+              "Position": {
+                "X": -20.58942,
+                "Y": 494.25,
+                "Z": -77.68658
+              },
+              "MinimumAngle": -45,
+              "MaximumAngle": 170
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/GatheringPaths/6.x - Endwalker/Elysion/398__BTN.json b/GatheringPaths/6.x - Endwalker/Elysion/398__BTN.json
new file mode 100644 (file)
index 0000000..8ad1fa4
--- /dev/null
@@ -0,0 +1,61 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 1073,
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 34353,
+          "Locations": [
+            {
+              "Position": {
+                "X": -59.17508,
+                "Y": 494.132,
+                "Z": -1.865536
+              },
+              "MinimumAngle": -35,
+              "MaximumAngle": 140
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34352,
+          "Locations": [
+            {
+              "Position": {
+                "X": -61.05396,
+                "Y": 495.2124,
+                "Z": -22.16576
+              },
+              "MinimumAngle": -30,
+              "MaximumAngle": 90
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34354,
+          "Locations": [
+            {
+              "Position": {
+                "X": -90.96052,
+                "Y": 493.2197,
+                "Z": -20.74431
+              },
+              "MinimumAngle": -70,
+              "MaximumAngle": 75
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/GatheringPaths/6.x - Endwalker/Elysion/399__BTN.json b/GatheringPaths/6.x - Endwalker/Elysion/399__BTN.json
new file mode 100644 (file)
index 0000000..64f5777
--- /dev/null
@@ -0,0 +1,61 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 1073,
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 34357,
+          "Locations": [
+            {
+              "Position": {
+                "X": -91.21072,
+                "Y": 490.3782,
+                "Z": 41.27306
+              },
+              "MinimumAngle": 140,
+              "MaximumAngle": 360
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34355,
+          "Locations": [
+            {
+              "Position": {
+                "X": -118.7086,
+                "Y": 490.4538,
+                "Z": 34.37638
+              },
+              "MinimumAngle": 40,
+              "MaximumAngle": 345
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34356,
+          "Locations": [
+            {
+              "Position": {
+                "X": -105.7026,
+                "Y": 490.5684,
+                "Z": 58.49864
+              },
+              "MinimumAngle": 0,
+              "MaximumAngle": 210
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
index 5060d3b44333e538f3cefa6922d18849b124a531..8bff39152bb92b07afcbc6f7f3a87733f3789956 100644 (file)
@@ -311,6 +311,8 @@ public class QuestSourceGenerator : ISourceGenerator
                                             AssignmentList(nameof(QuestStep.RequiredQuestVariables),
                                                     step.RequiredQuestVariables)
                                                 .AsSyntaxNodeOrToken(),
+                                            AssignmentList(nameof(QuestStep.RequiredGatheredItems),
+                                                step.RequiredGatheredItems),
                                             AssignmentList(nameof(QuestStep.CompletionQuestVariablesFlags),
                                                     step.CompletionQuestVariablesFlags)
                                                 .AsSyntaxNodeOrToken(),
index 7e2054ee083f74f79b3918e1c2eabbcc1e2ba912..0a8e19e23e3025dcd4ae22318961dba8344cc234 100644 (file)
@@ -329,7 +329,28 @@ public static class RoslynShortcuts
                                     Assignment(nameof(SkipAetheryteCondition.Never), skipAetheryteCondition.Never,
                                         emptyAetheryte.Never),
                                     Assignment(nameof(SkipAetheryteCondition.InSameTerritory),
-                                        skipAetheryteCondition.InSameTerritory, emptyAetheryte.InSameTerritory)))));
+                                        skipAetheryteCondition.InSameTerritory, emptyAetheryte.InSameTerritory),
+                                    AssignmentList(nameof(SkipAetheryteCondition.InTerritory),
+                                        skipAetheryteCondition.InTerritory)))));
+            }
+            else if (value is GatheredItem gatheredItem)
+            {
+                var emptyItem = new GatheredItem();
+                return ObjectCreationExpression(
+                        IdentifierName(nameof(GatheredItem)))
+                    .WithInitializer(
+                        InitializerExpression(
+                            SyntaxKind.ObjectInitializerExpression,
+                            SeparatedList<ExpressionSyntax>(
+                                SyntaxNodeList(
+                                    Assignment(nameof(GatheredItem.ItemId), gatheredItem.ItemId, emptyItem.ItemId)
+                                        .AsSyntaxNodeOrToken(),
+                                    Assignment(nameof(GatheredItem.ItemCount), gatheredItem.ItemCount,
+                                            emptyItem.ItemCount)
+                                        .AsSyntaxNodeOrToken(),
+                                    Assignment(nameof(GatheredItem.Collectability), gatheredItem.Collectability,
+                                            emptyItem.Collectability)
+                                        .AsSyntaxNodeOrToken()))));
             }
             else if (value is GatheringNodeGroup nodeGroup)
             {
diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/192_So You Want to Be a Miner.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/192_So You Want to Be a Miner.json
new file mode 100644 (file)
index 0000000..faaf116
--- /dev/null
@@ -0,0 +1,28 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
+  "Author": "liza",
+  "QuestSequence": [
+    {
+      "Sequence": 0,
+      "Steps": [
+        {
+          "DataId": 1002282,
+          "Position": {
+            "X": 3.5552979,
+            "Y": 7.5999613,
+            "Z": 153.2157
+          },
+          "TerritoryId": 131,
+          "InteractionType": "AcceptQuest",
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_CLSMIN001_00192_Q1_000_1",
+              "Yes": true
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/597_Way of the Miner.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/597_Way of the Miner.json
new file mode 100644 (file)
index 0000000..ab55d72
--- /dev/null
@@ -0,0 +1,44 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
+  "Author": "liza",
+  "QuestSequence": [
+    {
+      "Sequence": 0,
+      "Steps": [
+        {
+          "DataId": 1002282,
+          "Position": {
+            "X": 3.5552979,
+            "Y": 7.5999613,
+            "Z": 153.2157
+          },
+          "TerritoryId": 131,
+          "InteractionType": "AcceptQuest"
+        }
+      ]
+    },
+    {
+      "Sequence": 255,
+      "Steps": [
+        {
+          "DataId": 1002298,
+          "Position": {
+            "X": -18.997498,
+            "Y": 6.2,
+            "Z": 157.42725
+          },
+          "TerritoryId": 131,
+          "InteractionType": "CompleteQuest",
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_CLSMIN011_00597_Q1_000_1",
+              "Yes": true
+            }
+          ],
+          "NextQuestId": 599
+        }
+      ]
+    }
+  ]
+}
diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/599_My First Pickaxe.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/599_My First Pickaxe.json
new file mode 100644 (file)
index 0000000..c9bcf37
--- /dev/null
@@ -0,0 +1,55 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
+  "Author": "liza",
+  "QuestSequence": [
+    {
+      "Sequence": 0,
+      "Steps": [
+        {
+          "DataId": 1002298,
+          "Position": {
+            "X": -18.997498,
+            "Y": 6.2,
+            "Z": 157.42725
+          },
+          "TerritoryId": 131,
+          "InteractionType": "AcceptQuest"
+        }
+      ]
+    },
+    {
+      "Sequence": 255,
+      "Steps": [
+        {
+          "DataId": 1002298,
+          "Position": {
+            "X": -18.997498,
+            "Y": 6.2,
+            "Z": 157.42725
+          },
+          "TerritoryId": 131,
+          "InteractionType": "CompleteQuest",
+          "AetheryteShortcut": "Ul'dah",
+          "AethernetShortcut": [
+            "[Ul'dah] Aetheryte Plaza",
+            "[Ul'dah] Miners' Guild"
+          ],
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InTerritory": [
+                130,
+                131
+              ]
+            }
+          },
+          "RequiredGatheredItems": [
+            {
+              "ItemId": 5106,
+              "ItemCount": 10
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/600_Know Thy Land.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/600_Know Thy Land.json
new file mode 100644 (file)
index 0000000..ae8417c
--- /dev/null
@@ -0,0 +1,55 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
+  "Author": "liza",
+  "QuestSequence": [
+    {
+      "Sequence": 0,
+      "Steps": [
+        {
+          "DataId": 1002298,
+          "Position": {
+            "X": -18.997498,
+            "Y": 6.2,
+            "Z": 157.42725
+          },
+          "TerritoryId": 131,
+          "InteractionType": "AcceptQuest"
+        }
+      ]
+    },
+    {
+      "Sequence": 255,
+      "Steps": [
+        {
+          "DataId": 1002298,
+          "Position": {
+            "X": -18.997498,
+            "Y": 6.2,
+            "Z": 157.42725
+          },
+          "TerritoryId": 131,
+          "InteractionType": "CompleteQuest",
+          "AetheryteShortcut": "Ul'dah",
+          "AethernetShortcut": [
+            "[Ul'dah] Aetheryte Plaza",
+            "[Ul'dah] Miners' Guild"
+          ],
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InTerritory": [
+                130,
+                131
+              ]
+            }
+          },
+          "RequiredGatheredItems": [
+            {
+              "ItemId": 5432,
+              "ItemCount": 10
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
index f18d33a74eb154110ce6342d8668a3418033108b..9a031631e444348d5382093fa8d3268db9d83d95 100644 (file)
                         },
                         "InSameTerritory": {
                           "type": "boolean"
+                        },
+                        "InTerritory": {
+                          "type": "array",
+                          "items": {
+                            "type": "integer"
+                          }
                         }
                       },
                       "additionalProperties": false
diff --git a/Questionable.Model/Questing/Converter/ElementIdConverter.cs b/Questionable.Model/Questing/Converter/ElementIdConverter.cs
new file mode 100644 (file)
index 0000000..27cecb9
--- /dev/null
@@ -0,0 +1,19 @@
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Questionable.Model.Questing.Converter;
+
+public class ElementIdConverter : JsonConverter<ElementId>
+{
+    public override ElementId Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+    {
+        uint value = reader.GetUInt32();
+        return ElementId.From(value);
+    }
+
+    public override void Write(Utf8JsonWriter writer, ElementId value, JsonSerializerOptions options)
+    {
+        throw new NotImplementedException();
+    }
+}
diff --git a/Questionable.Model/Questing/Converter/IdConverter.cs b/Questionable.Model/Questing/Converter/IdConverter.cs
deleted file mode 100644 (file)
index 188627d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-using System;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace Questionable.Model.Questing.Converter;
-
-public class IdConverter : JsonConverter<IId>
-{
-    public override IId Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
-    {
-        uint value = reader.GetUInt32();
-        return Id.From(value);
-    }
-
-    public override void Write(Utf8JsonWriter writer, IId value, JsonSerializerOptions options)
-    {
-        throw new NotImplementedException();
-    }
-}
diff --git a/Questionable.Model/Questing/ElementId.cs b/Questionable.Model/Questing/ElementId.cs
new file mode 100644 (file)
index 0000000..e4b3c71
--- /dev/null
@@ -0,0 +1,86 @@
+using System;
+using System.Globalization;
+
+namespace Questionable.Model.Questing;
+
+public abstract class ElementId : IComparable<ElementId>, IEquatable<ElementId>
+{
+    protected ElementId(ushort value)
+    {
+        Value = value;
+    }
+
+    public ushort Value { get; }
+
+    public int CompareTo(ElementId? other)
+    {
+        if (ReferenceEquals(this, other)) return 0;
+        if (ReferenceEquals(null, other)) return 1;
+        return Value.CompareTo(other.Value);
+    }
+
+    public bool Equals(ElementId? other)
+    {
+        if (ReferenceEquals(null, other)) return false;
+        if (ReferenceEquals(this, other)) return true;
+        if (other.GetType() != GetType()) return false;
+        return Value == other.Value;
+    }
+
+    public override bool Equals(object? obj)
+    {
+        if (ReferenceEquals(null, obj)) return false;
+        if (ReferenceEquals(this, obj)) return true;
+        if (obj.GetType() != GetType()) return false;
+        return Equals((ElementId)obj);
+    }
+
+    public override int GetHashCode()
+    {
+        return Value.GetHashCode();
+    }
+
+    public static bool operator ==(ElementId? left, ElementId? right)
+    {
+        return Equals(left, right);
+    }
+
+    public static bool operator !=(ElementId? left, ElementId? right)
+    {
+        return !Equals(left, right);
+    }
+
+    public static ElementId From(uint value)
+    {
+        if (value >= 100_000 && value < 200_000)
+            return new LeveId((ushort)(value - 100_000));
+        else
+            return new QuestId((ushort)value);
+    }
+}
+
+public sealed class QuestId : ElementId
+{
+    public QuestId(ushort value)
+        : base(value)
+    {
+    }
+
+    public override string ToString()
+    {
+        return Value.ToString(CultureInfo.InvariantCulture);
+    }
+}
+
+public sealed class LeveId : ElementId
+{
+    public LeveId(ushort value)
+        : base(value)
+    {
+    }
+
+    public override string ToString()
+    {
+        return "L" + Value.ToString(CultureInfo.InvariantCulture);
+    }
+}
diff --git a/Questionable.Model/Questing/IId.cs b/Questionable.Model/Questing/IId.cs
deleted file mode 100644 (file)
index eefb5eb..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-using System;
-using System.Globalization;
-
-namespace Questionable.Model.Questing
-{
-    public interface IId : IComparable<IId>
-    {
-        public ushort Value { get; }
-    }
-
-    public static class Id
-    {
-        public static IId From(uint value)
-        {
-            if (value >= 100_000 && value < 200_000)
-                return new LeveId((ushort)(value - 100_000));
-            else
-                return new QuestId((ushort)value);
-        }
-    }
-
-    public sealed record QuestId(ushort Value) : IId
-    {
-        public override string ToString()
-        {
-            return "Q" + Value.ToString(CultureInfo.InvariantCulture);
-        }
-
-        public int CompareTo(IId? other)
-        {
-            if (ReferenceEquals(this, other)) return 0;
-            if (ReferenceEquals(null, other)) return 1;
-            return Value.CompareTo(other.Value);
-        }
-    }
-
-    public sealed record LeveId(ushort Value) : IId
-    {
-        public override string ToString()
-        {
-            return "L" + Value.ToString(CultureInfo.InvariantCulture);
-        }
-
-        public int CompareTo(IId? other)
-        {
-            if (ReferenceEquals(this, other)) return 0;
-            if (ReferenceEquals(null, other)) return 1;
-            return Value.CompareTo(other.Value);
-        }
-    }
-}
-
-namespace System.Runtime.CompilerServices
-{
-    internal static class IsExternalInit
-    {
-    }
-}
index dec9d156cb53f989552cf3b9aac6ce2d77088bdb..58a7a5b6a262ccb59a0dd16e16524457058339ac 100644 (file)
@@ -72,14 +72,14 @@ public sealed class QuestStep
     public IList<uint> PointMenuChoices { get; set; } = new List<uint>();
 
     // TODO: Not implemented
-    [JsonConverter(typeof(IdConverter))]
-    public IId? PickUpQuestId { get; set; }
+    [JsonConverter(typeof(ElementIdConverter))]
+    public ElementId? PickUpQuestId { get; set; }
 
-    [JsonConverter(typeof(IdConverter))]
-    public IId? TurnInQuestId { get; set; }
+    [JsonConverter(typeof(ElementIdConverter))]
+    public ElementId? TurnInQuestId { get; set; }
 
-    [JsonConverter(typeof(IdConverter))]
-    public IId? NextQuestId { get; set; }
+    [JsonConverter(typeof(ElementIdConverter))]
+    public ElementId? NextQuestId { get; set; }
 
     [JsonConstructor]
     public QuestStep()
index 0109e4de96378f0f5a491309cc0d31f0b9ac8186..870abe667572d13bc73185d6ce9055d5ff4f0acd 100644 (file)
@@ -1,7 +1,10 @@
-namespace Questionable.Model.Questing;
+using System.Collections.Generic;
+
+namespace Questionable.Model.Questing;
 
 public sealed class SkipAetheryteCondition
 {
     public bool Never { get; set; }
     public bool InSameTerritory { get; set; }
+    public List<ushort> InTerritory { get; set; } = new();
 }
index 61d126f3eaa7184071dc1a6e0c70db77a358dda7..c336abe66a4c0430b6c792d4a020ac68674a8b42 100644 (file)
@@ -13,8 +13,8 @@ public sealed class SkipStepConditions
     public List<ushort> InTerritory { get; set; } = new();
     public List<ushort> NotInTerritory { get; set; } = new();
     public SkipItemConditions? Item { get; set; }
-    public List<IId> QuestsAccepted { get; set; } = new();
-    public List<IId> QuestsCompleted { get; set; } = new();
+    public List<ElementId> QuestsAccepted { get; set; } = new();
+    public List<ElementId> QuestsCompleted { get; set; } = new();
     public EExtraSkipCondition? ExtraCondition { get; set; }
 
     public bool HasSkipConditions()
index 4099da390d4c579f8ed823d36d74a1fa5c73331b..8c9998257958b9725a1eacb85195b64d381a4c38 100644 (file)
@@ -168,7 +168,7 @@ internal sealed class CombatController : IDisposable
                     }
                 }
 
-                if (QuestWorkUtils.HasCompletionFlags(condition.CompletionQuestVariablesFlags) && _currentFight.Data.QuestId is QuestId questId)
+                if (QuestWorkUtils.HasCompletionFlags(condition.CompletionQuestVariablesFlags) && _currentFight.Data.QuestElementId is QuestId questId)
                 {
                     var questWork = _gameFunctions.GetQuestEx(questId);
                     if (questWork != null && QuestWorkUtils.MatchesQuestWork(condition.CompletionQuestVariablesFlags,
@@ -303,7 +303,7 @@ internal sealed class CombatController : IDisposable
 
     public sealed class CombatData
     {
-        public required IId QuestId { get; init; }
+        public required ElementId QuestElementId { get; init; }
         public required EEnemySpawnType SpawnType { get; init; }
         public required List<uint> KillEnemyDataIds { get; init; }
         public required List<ComplexCombatData> ComplexCombatDatas { get; init; }
index a7fcf8d4a91400ea18571c40b4ec6574a4310326..5e88cf85aef8ff19bce731ebd1971cdb20b56917 100644 (file)
@@ -130,9 +130,9 @@ internal sealed class CommandHandler : IDisposable
 
         if (arguments.Length >= 1 && uint.TryParse(arguments[0], out uint questId))
         {
-            if (_questRegistry.TryGetQuest(Id.From(questId), out Quest? quest))
+            if (_questRegistry.TryGetQuest(ElementId.From(questId), out Quest? quest))
             {
-                _debugOverlay.HighlightedQuest = quest.QuestId;
+                _debugOverlay.HighlightedQuest = quest.QuestElementId;
                 _chatGui.Print($"[Questionable] Set highlighted quest to {questId} ({quest.Info.Name}).");
             }
             else
@@ -149,9 +149,9 @@ internal sealed class CommandHandler : IDisposable
     {
         if (arguments.Length >= 1 && uint.TryParse(arguments[0], out uint questId))
         {
-            if (_gameFunctions.IsQuestLocked(Id.From(questId)))
+            if (_gameFunctions.IsQuestLocked(ElementId.From(questId)))
                 _chatGui.PrintError($"[Questionable] Quest {questId} is locked.");
-            else if (_questRegistry.TryGetQuest(Id.From(questId), out Quest? quest))
+            else if (_questRegistry.TryGetQuest(ElementId.From(questId), out Quest? quest))
             {
                 _questController.SetNextQuest(quest);
                 _chatGui.Print($"[Questionable] Set next quest to {questId} ({quest.Info.Name}).");
@@ -172,7 +172,7 @@ internal sealed class CommandHandler : IDisposable
     {
         if (arguments.Length >= 1 && ushort.TryParse(arguments[0], out ushort questId))
         {
-            if (_questRegistry.TryGetQuest(Id.From(questId), out Quest? quest))
+            if (_questRegistry.TryGetQuest(ElementId.From(questId), out Quest? quest))
             {
                 _questController.SimulateQuest(quest);
                 _chatGui.Print($"[Questionable] Simulating quest {questId} ({quest.Info.Name}).");
index fa55793d3b2a5fe5ffe2ddaa0126b49b231a3120..e7df22139d38e1a4e29b3b26896f0ebaf2920ff6 100644 (file)
@@ -600,7 +600,7 @@ internal sealed class GameUiController : IDisposable
 
     private unsafe void UnendingCodexPostSetup(AddonEvent type, AddonArgs args)
     {
-        if (_questController.StartedQuest?.Quest.QuestId.Value == 4526)
+        if (_questController.StartedQuest?.Quest.QuestElementId.Value == 4526)
         {
             _logger.LogInformation("Closing Unending Codex");
             AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
@@ -610,7 +610,7 @@ internal sealed class GameUiController : IDisposable
 
     private unsafe void ContentsTutorialPostSetup(AddonEvent type, AddonArgs args)
     {
-        if (_questController.StartedQuest?.Quest.QuestId.Value == 245)
+        if (_questController.StartedQuest?.Quest.QuestElementId.Value == 245)
         {
             _logger.LogInformation("Closing ContentsTutorial");
             AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
@@ -623,7 +623,7 @@ internal sealed class GameUiController : IDisposable
     /// </summary>
     private unsafe void MultipleHelpWindowPostSetup(AddonEvent type, AddonArgs args)
     {
-        if (_questController.StartedQuest?.Quest.QuestId.Value == 245)
+        if (_questController.StartedQuest?.Quest.QuestElementId.Value == 245)
         {
             _logger.LogInformation("Closing MultipleHelpWindow");
             AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
index 569275b3d73e6ca91282406e86f573c4e0c8509d..dcd3b8b0297bf805d5a801e9f823126767b8b42c 100644 (file)
@@ -77,7 +77,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
         {
             if (_simulatedQuest != null)
                 return (_simulatedQuest, CurrentQuestType.Simulated);
-            else if (_nextQuest != null && _gameFunctions.IsReadyToAcceptQuest(_nextQuest.Quest.QuestId))
+            else if (_nextQuest != null && _gameFunctions.IsReadyToAcceptQuest(_nextQuest.Quest.QuestElementId))
                 return (_nextQuest, CurrentQuestType.Next);
             else if (_startedQuest != null)
                 return (_startedQuest, CurrentQuestType.Normal);
@@ -182,13 +182,13 @@ internal sealed class QuestController : MiniTaskController<QuestController>
                 // if the quest is accepted, we no longer track it
                 bool canUseNextQuest;
                 if (_nextQuest.Quest.Info.IsRepeatable)
-                    canUseNextQuest = !_gameFunctions.IsQuestAccepted(_nextQuest.Quest.QuestId);
+                    canUseNextQuest = !_gameFunctions.IsQuestAccepted(_nextQuest.Quest.QuestElementId);
                 else
-                    canUseNextQuest = !_gameFunctions.IsQuestAcceptedOrComplete(_nextQuest.Quest.QuestId);
+                    canUseNextQuest = !_gameFunctions.IsQuestAcceptedOrComplete(_nextQuest.Quest.QuestElementId);
 
                 if (!canUseNextQuest)
                 {
-                    _logger.LogInformation("Next quest {QuestId} accepted or completed", _nextQuest.Quest.QuestId);
+                    _logger.LogInformation("Next quest {QuestId} accepted or completed", _nextQuest.Quest.QuestElementId);
                     _nextQuest = null;
                 }
             }
@@ -200,7 +200,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
                 currentSequence = _simulatedQuest.Sequence;
                 questToRun = _simulatedQuest;
             }
-            else if (_nextQuest != null && _gameFunctions.IsReadyToAcceptQuest(_nextQuest.Quest.QuestId))
+            else if (_nextQuest != null && _gameFunctions.IsReadyToAcceptQuest(_nextQuest.Quest.QuestElementId))
             {
                 questToRun = _nextQuest;
                 currentSequence = _nextQuest.Sequence; // by definition, this should always be 0
@@ -209,7 +209,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
             }
             else
             {
-                (IId? currentQuestId, currentSequence) = _gameFunctions.GetCurrentQuest();
+                (ElementId? currentQuestId, currentSequence) = _gameFunctions.GetCurrentQuest();
                 if (currentQuestId == null || currentQuestId.Value == 0)
                 {
                     if (_startedQuest != null)
@@ -221,7 +221,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
 
                     questToRun = null;
                 }
-                else if (_startedQuest == null || _startedQuest.Quest.QuestId != currentQuestId)
+                else if (_startedQuest == null || _startedQuest.Quest.QuestElementId != currentQuestId)
                 {
                     if (_questRegistry.TryGetQuest(currentQuestId, out var quest))
                     {
@@ -330,7 +330,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
         return (seq, seq.Steps[CurrentQuest.Step]);
     }
 
-    public void IncreaseStepCount(IId? questId, int? sequence, bool shouldContinue = false)
+    public void IncreaseStepCount(ElementId? questId, int? sequence, bool shouldContinue = false)
     {
         lock (_progressLock)
         {
@@ -341,11 +341,11 @@ internal sealed class QuestController : MiniTaskController<QuestController>
                 return;
             }
 
-            if (questId != null && CurrentQuest.Quest.QuestId != questId)
+            if (questId != null && CurrentQuest.Quest.QuestElementId != questId)
             {
                 _logger.LogWarning(
                     "Ignoring 'increase step count' for different quest (expected {ExpectedQuestId}, but we are at {CurrentQuestId}",
-                    questId, CurrentQuest.Quest.QuestId);
+                    questId, CurrentQuest.Quest.QuestElementId);
                 return;
             }
 
@@ -406,7 +406,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
 
     public void SimulateQuest(Quest? quest)
     {
-        _logger.LogInformation("SimulateQuest: {QuestId}", quest?.QuestId);
+        _logger.LogInformation("SimulateQuest: {QuestId}", quest?.QuestElementId);
         if (quest != null)
             _simulatedQuest = new QuestProgress(quest);
         else
@@ -415,7 +415,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
 
     public void SetNextQuest(Quest? quest)
     {
-        _logger.LogInformation("NextQuest: {QuestId}", quest?.QuestId);
+        _logger.LogInformation("NextQuest: {QuestId}", quest?.QuestElementId);
         if (quest != null)
             _nextQuest = new QuestProgress(quest);
         else
@@ -438,7 +438,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
 
     protected override void OnNextStep(ILastTask task)
     {
-        IncreaseStepCount(task.QuestId, task.Sequence, true);
+        IncreaseStepCount(task.QuestElementId, task.Sequence, true);
     }
 
     public void ExecuteNextStep(bool automatic)
@@ -453,7 +453,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
         if (CurrentQuest == null || seq == null || step == null)
         {
             _logger.LogWarning("Could not retrieve next quest step, not doing anything [{QuestId}, {Sequence}, {Step}]",
-                CurrentQuest?.Quest.QuestId, CurrentQuest?.Sequence, CurrentQuest?.Step);
+                CurrentQuest?.Quest.QuestElementId, CurrentQuest?.Sequence, CurrentQuest?.Step);
             return;
         }
 
@@ -488,7 +488,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
             }
 
             _logger.LogInformation("Tasks for {QuestId}, {Sequence}, {Step}: {Tasks}",
-                CurrentQuest.Quest.QuestId, seq.Sequence, seq.Steps.IndexOf(step),
+                CurrentQuest.Quest.QuestElementId, seq.Sequence, seq.Steps.IndexOf(step),
                 string.Join(", ", newTasks.Select(x => x.ToString())));
             foreach (var task in newTasks)
                 _taskQueue.Enqueue(task);
@@ -545,7 +545,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
         }
     }
 
-    public void Skip(IId questQuestId, byte currentQuestSequence)
+    public void Skip(ElementId questQuestElementId, byte currentQuestSequence)
     {
         lock (_progressLock)
         {
@@ -564,13 +564,13 @@ internal sealed class QuestController : MiniTaskController<QuestController>
                 if (_taskQueue.Count == 0)
                 {
                     Stop("Skip");
-                    IncreaseStepCount(questQuestId, currentQuestSequence);
+                    IncreaseStepCount(questQuestElementId, currentQuestSequence);
                 }
             }
             else
             {
                 Stop("SkipNx");
-                IncreaseStepCount(questQuestId, currentQuestSequence);
+                IncreaseStepCount(questQuestElementId, currentQuestSequence);
             }
         }
     }
index 426606b6b4e00b350017936cb633c07f03cec323..67cd658e21a675e83592f63b39dff81d47adaeff 100644 (file)
@@ -28,7 +28,7 @@ internal sealed class QuestRegistry
     private readonly ILogger<QuestRegistry> _logger;
     private readonly ICallGateProvider<object> _reloadDataIpc;
 
-    private readonly Dictionary<IId, Quest> _quests = new();
+    private readonly Dictionary<ElementId, Quest> _quests = new();
 
     public QuestRegistry(IDalamudPluginInterface pluginInterface, QuestData questData,
         QuestValidator questValidator, JsonSchemaValidator jsonSchemaValidator,
@@ -91,12 +91,12 @@ internal sealed class QuestRegistry
         {
             Quest quest = new()
             {
-                QuestId = new QuestId(questId),
+                QuestElementId = new QuestId(questId),
                 Root = questRoot,
                 Info = _questData.GetQuestInfo(new QuestId(questId)),
                 ReadOnly = true,
             };
-            _quests[quest.QuestId] = quest;
+            _quests[quest.QuestElementId] = quest;
         }
 
         _logger.LogInformation("Loaded {Count} quests from assembly", _quests.Count);
@@ -136,7 +136,7 @@ internal sealed class QuestRegistry
     private void LoadQuestFromStream(string fileName, Stream stream)
     {
         _logger.LogTrace("Loading quest from '{FileName}'", fileName);
-        IId? questId = ExtractQuestIdFromName(fileName);
+        ElementId? questId = ExtractQuestIdFromName(fileName);
         if (questId == null)
             return;
 
@@ -145,12 +145,12 @@ internal sealed class QuestRegistry
 
         Quest quest = new Quest
         {
-            QuestId = questId,
+            QuestElementId = questId,
             Root = questNode.Deserialize<QuestRoot>()!,
             Info = _questData.GetQuestInfo(questId),
             ReadOnly = false,
         };
-        _quests[quest.QuestId] = quest;
+        _quests[quest.QuestElementId] = quest;
     }
 
     private void LoadFromDirectory(DirectoryInfo directory, LogLevel logLevel = LogLevel.Information)
@@ -179,7 +179,7 @@ internal sealed class QuestRegistry
             LoadFromDirectory(childDirectory, logLevel);
     }
 
-    private static IId? ExtractQuestIdFromName(string resourceName)
+    private static ElementId? ExtractQuestIdFromName(string resourceName)
     {
         string name = resourceName.Substring(0, resourceName.Length - ".json".Length);
         name = name.Substring(name.LastIndexOf('.') + 1);
@@ -188,12 +188,12 @@ internal sealed class QuestRegistry
             return null;
 
         string[] parts = name.Split('_', 2);
-        return Id.From(uint.Parse(parts[0], CultureInfo.InvariantCulture));
+        return ElementId.From(uint.Parse(parts[0], CultureInfo.InvariantCulture));
     }
 
-    public bool IsKnownQuest(IId id)
+    public bool IsKnownQuest(ElementId elementId)
     {
-        if (id is QuestId questId)
+        if (elementId is QuestId questId)
             return IsKnownQuest(questId);
         else
             return false;
@@ -201,9 +201,9 @@ internal sealed class QuestRegistry
 
     public bool IsKnownQuest(QuestId questId) => _quests.ContainsKey(questId);
 
-    public bool TryGetQuest(IId id, [NotNullWhen(true)] out Quest? quest)
+    public bool TryGetQuest(ElementId elementId, [NotNullWhen(true)] out Quest? quest)
     {
-        if (id is QuestId questId)
+        if (elementId is QuestId questId)
             return TryGetQuest(questId, out quest);
         else
         {
index 5bddb2aad3e6373b8a280a5b9d8b03313a547b42..ecc521b3af5f1f0f417f436a06ee76fa83635108 100644 (file)
@@ -18,40 +18,40 @@ internal static class NextQuest
             if (step.NextQuestId == null)
                 return null;
 
-            if (step.NextQuestId == quest.QuestId)
+            if (step.NextQuestId == quest.QuestElementId)
                 return null;
 
             return serviceProvider.GetRequiredService<SetQuest>()
-                .With(step.NextQuestId, quest.QuestId);
+                .With(step.NextQuestId, quest.QuestElementId);
         }
     }
 
     internal sealed class SetQuest(QuestRegistry questRegistry, QuestController questController, GameFunctions gameFunctions, ILogger<SetQuest> logger) : ITask
     {
-        public IId NextQuestId { get; set; } = null!;
-        public IId CurrentQuestId { get; set; } = null!;
+        public ElementId NextQuestElementId { get; set; } = null!;
+        public ElementId CurrentQuestElementId { get; set; } = null!;
 
-        public ITask With(IId nextQuestId, IId currentQuestId)
+        public ITask With(ElementId nextQuestElementId, ElementId currentQuestElementId)
         {
-            NextQuestId = nextQuestId;
-            CurrentQuestId = currentQuestId;
+            NextQuestElementId = nextQuestElementId;
+            CurrentQuestElementId = currentQuestElementId;
             return this;
         }
 
         public bool Start()
         {
-            if (gameFunctions.IsQuestLocked(NextQuestId, CurrentQuestId))
+            if (gameFunctions.IsQuestLocked(NextQuestElementId, CurrentQuestElementId))
             {
-                logger.LogInformation("Can't set next quest to {QuestId}, quest is locked", NextQuestId);
+                logger.LogInformation("Can't set next quest to {QuestId}, quest is locked", NextQuestElementId);
             }
-            else if (questRegistry.TryGetQuest(NextQuestId, out Quest? quest))
+            else if (questRegistry.TryGetQuest(NextQuestElementId, out Quest? quest))
             {
-                logger.LogInformation("Setting next quest to {QuestId}: '{QuestName}'", NextQuestId, quest.Info.Name);
+                logger.LogInformation("Setting next quest to {QuestId}: '{QuestName}'", NextQuestElementId, quest.Info.Name);
                 questController.SetNextQuest(quest);
             }
             else
             {
-                logger.LogInformation("Next quest with id {QuestId} not found", NextQuestId);
+                logger.LogInformation("Next quest with id {QuestId} not found", NextQuestElementId);
                 questController.SetNextQuest(null);
             }
 
@@ -60,6 +60,6 @@ internal static class NextQuest
 
         public ETaskResult Update() => ETaskResult.TaskComplete;
 
-        public override string ToString() => $"SetNextQuest({NextQuestId})";
+        public override string ToString() => $"SetNextQuest({NextQuestElementId})";
     }
 }
index 8b12de4520c5427815d12dabf82c9bb7545b432d..71e8b0a60399823e0b9f3979ac0c1a53867c495d 100644 (file)
@@ -4,6 +4,6 @@ namespace Questionable.Controller.Steps;
 
 internal interface ILastTask : ITask
 {
-    public IId QuestId { get; }
+    public ElementId QuestElementId { get; }
     public int Sequence { get; }
 }
index 58161886a286118a797ce7b6d202823bfaf1890b..d6a3f52a8c3dee6ba41bec1821329c83583df757 100644 (file)
@@ -47,7 +47,7 @@ internal static class Combat
                     ArgumentNullException.ThrowIfNull(step.ItemId);
 
                     yield return serviceProvider.GetRequiredService<UseItem.UseOnObject>()
-                        .With(quest.QuestId, step.DataId.Value, step.ItemId.Value, step.CompletionQuestVariablesFlags,
+                        .With(quest.QuestElementId, step.DataId.Value, step.ItemId.Value, step.CompletionQuestVariablesFlags,
                             true);
                     yield return CreateTask(quest, sequence, step);
                     break;
@@ -73,7 +73,7 @@ internal static class Combat
 
             bool isLastStep = sequence.Steps.Last() == step;
             return serviceProvider.GetRequiredService<HandleCombat>()
-                .With(quest.QuestId, isLastStep, step.EnemySpawnType.Value, step.KillEnemyDataIds,
+                .With(quest.QuestElementId, isLastStep, step.EnemySpawnType.Value, step.KillEnemyDataIds,
                     step.CompletionQuestVariablesFlags, step.ComplexCombatData);
         }
     }
@@ -84,13 +84,13 @@ internal static class Combat
         private CombatController.CombatData _combatData = null!;
         private IList<QuestWorkValue?> _completionQuestVariableFlags = null!;
 
-        public ITask With(IId questId, bool isLastStep, EEnemySpawnType enemySpawnType, IList<uint> killEnemyDataIds,
+        public ITask With(ElementId questElementId, bool isLastStep, EEnemySpawnType enemySpawnType, IList<uint> killEnemyDataIds,
             IList<QuestWorkValue?> completionQuestVariablesFlags, IList<ComplexCombatData> complexCombatData)
         {
             _isLastStep = isLastStep;
             _combatData = new CombatController.CombatData
             {
-                QuestId = questId,
+                QuestElementId = questElementId,
                 SpawnType = enemySpawnType,
                 KillEnemyDataIds = killEnemyDataIds.ToList(),
                 ComplexCombatDatas = complexCombatData.ToList(),
@@ -107,7 +107,7 @@ internal static class Combat
                 return ETaskResult.StillRunning;
 
             // if our quest step has any completion flags, we need to check if they are set
-            if (QuestWorkUtils.HasCompletionFlags(_completionQuestVariableFlags) && _combatData.QuestId is QuestId questId)
+            if (QuestWorkUtils.HasCompletionFlags(_completionQuestVariableFlags) && _combatData.QuestElementId is QuestId questId)
             {
                 var questWork = gameFunctions.GetQuestEx(questId);
                 if (questWork == null)
index d971b782967227bd71600a733a74fe5fbd194a04..ea46939ce535db49636f4c05e87367cf2cd7d6a1 100644 (file)
@@ -48,7 +48,7 @@ internal static class UseItem
                 }
 
                 var task = serviceProvider.GetRequiredService<Use>()
-                    .With(quest.QuestId, step.ItemId.Value, step.CompletionQuestVariablesFlags);
+                    .With(quest.QuestElementId, step.ItemId.Value, step.CompletionQuestVariablesFlags);
                 return
                 [
                     unmount, task,
@@ -65,12 +65,12 @@ internal static class UseItem
                 ITask task;
                 if (step.DataId != null)
                     task = serviceProvider.GetRequiredService<UseOnGround>()
-                        .With(quest.QuestId, step.DataId.Value, step.ItemId.Value, step.CompletionQuestVariablesFlags);
+                        .With(quest.QuestElementId, step.DataId.Value, step.ItemId.Value, step.CompletionQuestVariablesFlags);
                 else
                 {
                     ArgumentNullException.ThrowIfNull(step.Position);
                     task = serviceProvider.GetRequiredService<UseOnPosition>()
-                        .With(quest.QuestId, step.Position.Value, step.ItemId.Value,
+                        .With(quest.QuestElementId, step.Position.Value, step.ItemId.Value,
                             step.CompletionQuestVariablesFlags);
                 }
 
@@ -79,13 +79,13 @@ internal static class UseItem
             else if (step.DataId != null)
             {
                 var task = serviceProvider.GetRequiredService<UseOnObject>()
-                    .With(quest.QuestId, step.DataId.Value, step.ItemId.Value, step.CompletionQuestVariablesFlags);
+                    .With(quest.QuestElementId, step.DataId.Value, step.ItemId.Value, step.CompletionQuestVariablesFlags);
                 return [unmount, task];
             }
             else
             {
                 var task = serviceProvider.GetRequiredService<Use>()
-                    .With(quest.QuestId, step.ItemId.Value, step.CompletionQuestVariablesFlags);
+                    .With(quest.QuestElementId, step.ItemId.Value, step.CompletionQuestVariablesFlags);
                 return [unmount, task];
             }
         }
@@ -118,7 +118,7 @@ internal static class UseItem
         private DateTime _continueAt;
         private int _itemCount;
 
-        public IId? QuestId { get; set; }
+        public ElementId? QuestId { get; set; }
         public uint ItemId { get; set; }
         public IList<QuestWorkValue?> CompletionQuestVariablesFlags { get; set; } = new List<QuestWorkValue?>();
         public bool StartingCombat { get; set; }
@@ -203,7 +203,7 @@ internal static class UseItem
 
         public uint DataId { get; set; }
 
-        public ITask With(IId? questId, uint dataId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
+        public ITask With(ElementId? questId, uint dataId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
         {
             QuestId = questId;
             DataId = dataId;
@@ -227,7 +227,7 @@ internal static class UseItem
 
         public Vector3 Position { get; set; }
 
-        public ITask With(IId? questId, Vector3 position, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
+        public ITask With(ElementId? questId, Vector3 position, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
         {
             QuestId = questId;
             Position = position;
@@ -249,7 +249,7 @@ internal static class UseItem
 
         public uint DataId { get; set; }
 
-        public ITask With(IId? questId, uint dataId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags,
+        public ITask With(ElementId? questId, uint dataId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags,
             bool startingCombat = false)
         {
             QuestId = questId;
@@ -270,7 +270,7 @@ internal static class UseItem
     {
         private readonly GameFunctions _gameFunctions = gameFunctions;
 
-        public ITask With(IId? questId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
+        public ITask With(ElementId? questId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
         {
             QuestId = questId;
             ItemId = itemId;
index ed8d1c07ad65baea3e13304bf99c06c8521e9dec..ba03874a84c097cd798acdfa386628d751100f0e 100644 (file)
@@ -67,32 +67,44 @@ internal static class AetheryteShortcut
         {
             _continueAt = DateTime.Now.AddSeconds(8);
             ushort territoryType = clientState.TerritoryType;
-            if (Step != null && ExpectedTerritoryId == territoryType)
+            if (Step != null)
             {
                 var skipConditions = Step.SkipConditions?.AetheryteShortcutIf ?? new();
-                if (!skipConditions.Never)
+                if (skipConditions is { Never: false, InTerritory.Count: > 0 })
                 {
-                    if (skipConditions is { InSameTerritory: true })
+                    if (skipConditions.InTerritory.Contains(territoryType))
                     {
-                        logger.LogInformation("Skipping aetheryte teleport due to SkipCondition");
+                        logger.LogInformation("Skipping aetheryte teleport due to SkipCondition (InTerritory)");
                         return false;
                     }
+                }
 
-                    Vector3 pos = clientState.LocalPlayer!.Position;
-                    if (Step.Position != null &&
-                        (pos - Step.Position.Value).Length() < Step.CalculateActualStopDistance())
+                if (ExpectedTerritoryId == territoryType)
+                {
+                    if (!skipConditions.Never)
                     {
-                        logger.LogInformation("Skipping aetheryte teleport, we're near the target");
-                        return false;
-                    }
+                        if (skipConditions is { InSameTerritory: true })
+                        {
+                            logger.LogInformation("Skipping aetheryte teleport due to SkipCondition (InSameTerritory)");
+                            return false;
+                        }
 
-                    if (aetheryteData.CalculateDistance(pos, territoryType, TargetAetheryte) < 20 ||
-                        (Step.AethernetShortcut != null &&
-                         (aetheryteData.CalculateDistance(pos, territoryType, Step.AethernetShortcut.From) < 20 ||
-                          aetheryteData.CalculateDistance(pos, territoryType, Step.AethernetShortcut.To) < 20)))
-                    {
-                        logger.LogInformation("Skipping aetheryte teleport");
-                        return false;
+                        Vector3 pos = clientState.LocalPlayer!.Position;
+                        if (Step.Position != null &&
+                            (pos - Step.Position.Value).Length() < Step.CalculateActualStopDistance())
+                        {
+                            logger.LogInformation("Skipping aetheryte teleport, we're near the target");
+                            return false;
+                        }
+
+                        if (aetheryteData.CalculateDistance(pos, territoryType, TargetAetheryte) < 20 ||
+                            (Step.AethernetShortcut != null &&
+                             (aetheryteData.CalculateDistance(pos, territoryType, Step.AethernetShortcut.From) < 20 ||
+                              aetheryteData.CalculateDistance(pos, territoryType, Step.AethernetShortcut.To) < 20)))
+                        {
+                            logger.LogInformation("Skipping aetheryte teleport");
+                            return false;
+                        }
                     }
                 }
             }
index 0b24ecaa8b1d996178ba62bab9910feb3efb7500..a122d57cb30b06b296b84b5897b2252ad07f7bfa 100644 (file)
@@ -34,7 +34,7 @@ internal static class SkipCondition
                 return null;
 
             return serviceProvider.GetRequiredService<CheckSkip>()
-                .With(step, skipConditions ?? new(), quest.QuestId);
+                .With(step, skipConditions ?? new(), quest.QuestElementId);
         }
     }
 
@@ -45,13 +45,13 @@ internal static class SkipCondition
     {
         public QuestStep Step { get; set; } = null!;
         public SkipStepConditions SkipConditions { get; set; } = null!;
-        public IId QuestId { get; set; } = null!;
+        public ElementId QuestElementId { get; set; } = null!;
 
-        public ITask With(QuestStep step, SkipStepConditions skipConditions, IId questId)
+        public ITask With(QuestStep step, SkipStepConditions skipConditions, ElementId questElementId)
         {
             Step = step;
             SkipConditions = skipConditions;
-            QuestId = questId;
+            QuestElementId = questElementId;
             return this;
         }
 
@@ -156,7 +156,7 @@ internal static class SkipCondition
                 return true;
             }
 
-            if (QuestId is QuestId questId)
+            if (QuestElementId is QuestId questId)
             {
                 QuestWork? questWork = gameFunctions.GetQuestEx(questId);
                 if (QuestWorkUtils.HasCompletionFlags(Step.CompletionQuestVariablesFlags) && questWork != null)
index 55fede1b24296c93ef4928ab942e416074ff4c48..1b84c2bc06732582eb5fd7b72b20445bbb1046a2 100644 (file)
@@ -30,7 +30,7 @@ internal static class WaitAtEnd
             if (step.CompletionQuestVariablesFlags.Count == 6 && QuestWorkUtils.HasCompletionFlags(step.CompletionQuestVariablesFlags))
             {
                 var task = serviceProvider.GetRequiredService<WaitForCompletionFlags>()
-                    .With((QuestId)quest.QuestId, step);
+                    .With((QuestId)quest.QuestElementId, step);
                 var delay = serviceProvider.GetRequiredService<WaitDelay>();
                 return [task, delay, Next(quest, sequence)];
             }
@@ -110,7 +110,7 @@ internal static class WaitAtEnd
                 case EInteractionType.AcceptQuest:
                 {
                     var accept = serviceProvider.GetRequiredService<WaitQuestAccepted>()
-                        .With(step.PickUpQuestId ?? quest.QuestId);
+                        .With(step.PickUpQuestId ?? quest.QuestElementId);
                     var delay = serviceProvider.GetRequiredService<WaitDelay>();
                     if (step.PickUpQuestId != null)
                         return [accept, delay, Next(quest, sequence)];
@@ -121,7 +121,7 @@ internal static class WaitAtEnd
                 case EInteractionType.CompleteQuest:
                 {
                     var complete = serviceProvider.GetRequiredService<WaitQuestCompleted>()
-                        .With(step.TurnInQuestId ?? quest.QuestId);
+                        .With(step.TurnInQuestId ?? quest.QuestElementId);
                     var delay = serviceProvider.GetRequiredService<WaitDelay>();
                     if (step.TurnInQuestId != null)
                         return [complete, delay, Next(quest, sequence)];
@@ -140,7 +140,7 @@ internal static class WaitAtEnd
 
         private static NextStep Next(Quest quest, QuestSequence sequence)
         {
-            return new NextStep(quest.QuestId, sequence.Sequence);
+            return new NextStep(quest.QuestElementId, sequence.Sequence);
         }
     }
 
@@ -216,11 +216,11 @@ internal static class WaitAtEnd
 
     internal sealed class WaitQuestAccepted(GameFunctions gameFunctions) : ITask
     {
-        public IId QuestId { get; set; } = null!;
+        public ElementId QuestElementId { get; set; } = null!;
 
-        public ITask With(IId questId)
+        public ITask With(ElementId questElementId)
         {
-            QuestId = questId;
+            QuestElementId = questElementId;
             return this;
         }
 
@@ -228,21 +228,21 @@ internal static class WaitAtEnd
 
         public ETaskResult Update()
         {
-            return gameFunctions.IsQuestAccepted(QuestId)
+            return gameFunctions.IsQuestAccepted(QuestElementId)
                 ? ETaskResult.TaskComplete
                 : ETaskResult.StillRunning;
         }
 
-        public override string ToString() => $"WaitQuestAccepted({QuestId})";
+        public override string ToString() => $"WaitQuestAccepted({QuestElementId})";
     }
 
     internal sealed class WaitQuestCompleted(GameFunctions gameFunctions) : ITask
     {
-        public IId QuestId { get; set; } = null!;
+        public ElementId QuestElementId { get; set; } = null!;
 
-        public ITask With(IId questId)
+        public ITask With(ElementId questElementId)
         {
-            QuestId = questId;
+            QuestElementId = questElementId;
             return this;
         }
 
@@ -250,15 +250,15 @@ internal static class WaitAtEnd
 
         public ETaskResult Update()
         {
-            return gameFunctions.IsQuestComplete(QuestId) ? ETaskResult.TaskComplete : ETaskResult.StillRunning;
+            return gameFunctions.IsQuestComplete(QuestElementId) ? ETaskResult.TaskComplete : ETaskResult.StillRunning;
         }
 
-        public override string ToString() => $"WaitQuestComplete({QuestId})";
+        public override string ToString() => $"WaitQuestComplete({QuestElementId})";
     }
 
-    internal sealed class NextStep(IId questId, int sequence) : ILastTask
+    internal sealed class NextStep(ElementId questElementId, int sequence) : ILastTask
     {
-        public IId QuestId { get; } = questId;
+        public ElementId QuestElementId { get; } = questElementId;
         public int Sequence { get; } = sequence;
 
         public bool Start() => true;
@@ -270,7 +270,7 @@ internal static class WaitAtEnd
 
     internal sealed class EndAutomation : ILastTask
     {
-        public IId QuestId => throw new InvalidOperationException();
+        public ElementId QuestElementId => throw new InvalidOperationException();
         public int Sequence => throw new InvalidOperationException();
 
         public bool Start() => true;
index d30a5f2e6edbef294fafd1eaf5d7cc24af5470e8..aef7b726d9a5800690bf2e6ff2745a91c8e52bdc 100644 (file)
@@ -23,12 +23,12 @@ internal sealed class QuestData
             .ToImmutableDictionary(x => x.QuestId, x => x);
     }
 
-    public QuestInfo GetQuestInfo(IId id)
+    public QuestInfo GetQuestInfo(ElementId elementId)
     {
-        if (id is QuestId questId)
+        if (elementId is QuestId questId)
             return GetQuestInfo(questId);
 
-        throw new ArgumentException("Invalid id", nameof(id));
+        throw new ArgumentException("Invalid id", nameof(elementId));
     }
 
     public QuestInfo GetQuestInfo(QuestId questId)
index 521d89e804f3bcd2de170b982f9a5ba82a610bc4..83f3b27dbe885380536a6c10b9c056a63e2b1565 100644 (file)
@@ -89,7 +89,7 @@ internal sealed unsafe class GameFunctions
 
     public DateTime ReturnRequestedAt { get; set; } = DateTime.MinValue;
 
-    public (IId? CurrentQuest, byte Sequence) GetCurrentQuest()
+    public (ElementId? CurrentQuest, byte Sequence) GetCurrentQuest()
     {
         var (currentQuest, sequence) = GetCurrentQuestInternal();
         PlayerState* playerState = PlayerState.Instance();
@@ -141,7 +141,7 @@ internal sealed unsafe class GameFunctions
         return (currentQuest, sequence);
     }
 
-    public (IId? CurrentQuest, byte Sequence) GetCurrentQuestInternal()
+    public (ElementId? CurrentQuest, byte Sequence) GetCurrentQuestInternal()
     {
         var questManager = QuestManager.Instance();
         if (questManager != null)
@@ -158,7 +158,7 @@ internal sealed unsafe class GameFunctions
             // If no quests are marked as 'priority', accepting a new quest adds it to the top of the list.
             for (int i = questManager->TrackedQuests.Length - 1; i >= 0; --i)
             {
-                IId currentQuest;
+                ElementId currentQuest;
                 var trackedQuest = questManager->TrackedQuests[i];
                 switch (trackedQuest.QuestType)
                 {
@@ -242,9 +242,9 @@ internal sealed unsafe class GameFunctions
         return questWork != null ? *questWork : null;
     }
 
-    public bool IsReadyToAcceptQuest(IId id)
+    public bool IsReadyToAcceptQuest(ElementId elementId)
     {
-        if (id is QuestId questId)
+        if (elementId is QuestId questId)
             return IsReadyToAcceptQuest(questId);
         return false;
     }
@@ -274,14 +274,14 @@ internal sealed unsafe class GameFunctions
         return true;
     }
 
-    public bool IsQuestAcceptedOrComplete(IId questId)
+    public bool IsQuestAcceptedOrComplete(ElementId questElementId)
     {
-        return IsQuestComplete(questId) || IsQuestAccepted(questId);
+        return IsQuestComplete(questElementId) || IsQuestAccepted(questElementId);
     }
 
-    public bool IsQuestAccepted(IId id)
+    public bool IsQuestAccepted(ElementId elementId)
     {
-        if (id is QuestId questId)
+        if (elementId is QuestId questId)
             return IsQuestAccepted(questId);
         return false;
     }
@@ -292,9 +292,9 @@ internal sealed unsafe class GameFunctions
         return questManager->IsQuestAccepted(questId.Value);
     }
 
-    public bool IsQuestComplete(IId id)
+    public bool IsQuestComplete(ElementId elementId)
     {
-        if (id is QuestId questId)
+        if (elementId is QuestId questId)
             return IsQuestComplete(questId);
         return false;
     }
@@ -305,14 +305,14 @@ internal sealed unsafe class GameFunctions
         return QuestManager.IsQuestComplete(questId.Value);
     }
 
-    public bool IsQuestLocked(IId id, IId? extraCompletedQuest = null)
+    public bool IsQuestLocked(ElementId elementId, ElementId? extraCompletedQuest = null)
     {
-        if (id is QuestId questId)
+        if (elementId is QuestId questId)
             return IsQuestLocked(questId, extraCompletedQuest);
         return false;
     }
 
-    public bool IsQuestLocked(QuestId questId, IId? extraCompletedQuest = null)
+    public bool IsQuestLocked(QuestId questId, ElementId? extraCompletedQuest = null)
     {
         var questInfo = _questData.GetQuestInfo(questId);
         if (questInfo.QuestLocks.Count > 0)
@@ -330,7 +330,7 @@ internal sealed unsafe class GameFunctions
         return !HasCompletedPreviousQuests(questInfo, extraCompletedQuest) || !HasCompletedPreviousInstances(questInfo);
     }
 
-    private bool HasCompletedPreviousQuests(QuestInfo questInfo, IId? extraCompletedQuest)
+    private bool HasCompletedPreviousQuests(QuestInfo questInfo, ElementId? extraCompletedQuest)
     {
         if (questInfo.PreviousQuests.Count == 0)
             return true;
@@ -707,15 +707,15 @@ internal sealed unsafe class GameFunctions
         if (excelSheetName == null)
         {
             var questRow =
-                _dataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets2.Quest>()!.GetRow((uint)currentQuest.QuestId.Value +
+                _dataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets2.Quest>()!.GetRow((uint)currentQuest.QuestElementId.Value +
                     0x10000);
             if (questRow == null)
             {
-                _logger.LogError("Could not find quest row for {QuestId}", currentQuest.QuestId);
+                _logger.LogError("Could not find quest row for {QuestId}", currentQuest.QuestElementId);
                 return null;
             }
 
-            excelSheetName = $"quest/{(currentQuest.QuestId.Value / 100):000}/{questRow.Id}";
+            excelSheetName = $"quest/{(currentQuest.QuestElementId.Value / 100):000}/{questRow.Id}";
         }
 
         var excelSheet = _dataManager.Excel.GetSheet<QuestDialogueText>(excelSheetName);
index f778b137c4bbe6d8be448446e8d9d9bd2d3a7abb..391e0602be592e9516486dcc3778b19b683ef3bb 100644 (file)
@@ -6,7 +6,7 @@ namespace Questionable.Model;
 
 internal sealed class Quest
 {
-    public required IId QuestId { get; init; }
+    public required ElementId QuestElementId { get; init; }
     public required QuestRoot Root { get; init; }
     public required QuestInfo Info { get; init; }
     public required bool ReadOnly { get; init; }
index ceb37e8c42122b4ddbef98156d63e02e204f07cf..1e9d92faf906befc2cd96c4def2864fb7faabc15 100644 (file)
@@ -1,6 +1,6 @@
 <Project Sdk="Dalamud.NET.Sdk/10.0.0">
     <PropertyGroup>
-        <Version>1.24</Version>
+        <Version>2.0</Version>
         <OutputPath>dist</OutputPath>
         <PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap>
         <Platforms>x64</Platforms>
index c0c1c7b6a0e7cfb85c43d76216c8fa276c99a7af..31402620948fcf230ccf080e9caa18b061581aec 100644 (file)
@@ -5,7 +5,7 @@ namespace Questionable.Validation;
 
 internal sealed record ValidationIssue
 {
-    public required IId? QuestId { get; init; }
+    public required ElementId? QuestId { get; init; }
     public required byte? Sequence { get; init; }
     public required int? Step { get; init; }
     public EBeastTribe BeastTribe { get; init; } = EBeastTribe.None;
index e094f83b231a9b6c5f26b7d620cfd70dc9f83b76..f5820ac2412b3e2704f8e2452a6567c60e0d9159 100644 (file)
@@ -18,12 +18,12 @@ internal sealed class AethernetShortcutValidator : IQuestValidator
     public IEnumerable<ValidationIssue> Validate(Quest quest)
     {
         return quest.AllSteps()
-            .Select(x => Validate(quest.QuestId, x.Sequence.Sequence, x.StepId, x.Step.AethernetShortcut))
+            .Select(x => Validate(quest.QuestElementId, x.Sequence.Sequence, x.StepId, x.Step.AethernetShortcut))
             .Where(x => x != null)
             .Cast<ValidationIssue>();
     }
 
-    private ValidationIssue? Validate(IId questId, int sequenceNo, int stepId, AethernetShortcut? aethernetShortcut)
+    private ValidationIssue? Validate(ElementId questElementId, int sequenceNo, int stepId, AethernetShortcut? aethernetShortcut)
     {
         if (aethernetShortcut == null)
             return null;
@@ -34,7 +34,7 @@ internal sealed class AethernetShortcutValidator : IQuestValidator
         {
             return new ValidationIssue
             {
-                QuestId = questId,
+                QuestId = questElementId,
                 Sequence = (byte)sequenceNo,
                 Step = stepId,
                 Type = EIssueType.InvalidAethernetShortcut,
index 0127bc195e24e226fb62c39de2e56bd903646d48..a7330d8ff8320eca6cfe9a0ef72110d0d3e813c2 100644 (file)
@@ -18,7 +18,7 @@ internal sealed class BasicSequenceValidator : IQuestValidator
         {
             yield return new ValidationIssue
             {
-                QuestId = quest.QuestId,
+                QuestId = quest.QuestElementId,
                 Sequence = 0,
                 Step = null,
                 Type = EIssueType.MissingSequence0,
@@ -37,7 +37,7 @@ internal sealed class BasicSequenceValidator : IQuestValidator
 
                 yield return new ValidationIssue
                 {
-                    QuestId = quest.QuestId,
+                    QuestId = quest.QuestElementId,
                     Sequence = (byte)sequence.Sequence,
                     Step = null,
                     Type = EIssueType.InstantQuestWithMultipleSteps,
@@ -73,7 +73,7 @@ internal sealed class BasicSequenceValidator : IQuestValidator
         {
             return new ValidationIssue
             {
-                QuestId = quest.QuestId,
+                QuestId = quest.QuestElementId,
                 Sequence = (byte)sequenceNo,
                 Step = null,
                 Type = EIssueType.MissingSequence,
@@ -85,7 +85,7 @@ internal sealed class BasicSequenceValidator : IQuestValidator
         {
             return new ValidationIssue
             {
-                QuestId = quest.QuestId,
+                QuestId = quest.QuestElementId,
                 Sequence = (byte)sequenceNo,
                 Step = null,
                 Type = EIssueType.DuplicateSequence,
index 2cfc58d7e2301172ac701f889a77b78f87c04c5f..76b539e208db2873f156f88f003f5ff02e0ed423 100644 (file)
@@ -45,7 +45,7 @@ internal sealed class CompletionFlagsValidator : IQuestValidator
                 {
                     yield return new ValidationIssue
                     {
-                        QuestId = quest.QuestId,
+                        QuestId = quest.QuestElementId,
                         Sequence = (byte)sequence.Sequence,
                         Step = i,
                         Type = EIssueType.DuplicateCompletionFlags,
index 2efa6be8b6d35860d57e6c3fa0de023441d74443..ca3625608bd9f5ebfe1e1c8e95c68e2e4e3d7626 100644 (file)
@@ -11,7 +11,7 @@ namespace Questionable.Validation.Validators;
 
 internal sealed class JsonSchemaValidator : IQuestValidator
 {
-    private readonly Dictionary<IId, JsonNode> _questNodes = new();
+    private readonly Dictionary<ElementId, JsonNode> _questNodes = new();
     private JsonSchema? _questSchema;
 
     public JsonSchemaValidator()
@@ -25,7 +25,7 @@ internal sealed class JsonSchemaValidator : IQuestValidator
     {
         _questSchema ??= JsonSchema.FromStream(AssemblyQuestLoader.QuestSchema).AsTask().Result;
 
-        if (_questNodes.TryGetValue(quest.QuestId, out JsonNode? questNode))
+        if (_questNodes.TryGetValue(quest.QuestElementId, out JsonNode? questNode))
         {
             var evaluationResult = _questSchema.Evaluate(questNode, new EvaluationOptions
             {
@@ -36,7 +36,7 @@ internal sealed class JsonSchemaValidator : IQuestValidator
             {
                 yield return new ValidationIssue
                 {
-                    QuestId = quest.QuestId,
+                    QuestId = quest.QuestElementId,
                     Sequence = null,
                     Step = null,
                     Type = EIssueType.InvalidJsonSchema,
@@ -47,7 +47,7 @@ internal sealed class JsonSchemaValidator : IQuestValidator
         }
     }
 
-    public void Enqueue(IId questId, JsonNode questNode) => _questNodes[questId] = questNode;
+    public void Enqueue(ElementId questElementId, JsonNode questNode) => _questNodes[questElementId] = questNode;
 
     public void Reset() => _questNodes.Clear();
 }
index 325d8fbfa7198466653c36aacda1be34e9e22458..9c0afbc0bb472dfa19f26706ba50cd90727e1b69 100644 (file)
@@ -8,11 +8,11 @@ internal sealed class NextQuestValidator : IQuestValidator
 {
     public IEnumerable<ValidationIssue> Validate(Quest quest)
     {
-        foreach (var invalidNextQuest in quest.AllSteps().Where(x => x.Step.NextQuestId == quest.QuestId))
+        foreach (var invalidNextQuest in quest.AllSteps().Where(x => x.Step.NextQuestId == quest.QuestElementId))
         {
             yield return new ValidationIssue
             {
-                QuestId = quest.QuestId,
+                QuestId = quest.QuestElementId,
                 Sequence = (byte)invalidNextQuest.Sequence.Sequence,
                 Step = invalidNextQuest.StepId,
                 Type = EIssueType.InvalidNextQuestId,
index 298b34239201b0a85f35dcb5dfd7fbc0809968dc..18764ecb0b4bd82eb17a9e3960358fe39afe743f 100644 (file)
@@ -11,7 +11,7 @@ internal sealed class QuestDisabledValidator : IQuestValidator
         {
             yield return new ValidationIssue
             {
-                QuestId = quest.QuestId,
+                QuestId = quest.QuestElementId,
                 Sequence = null,
                 Step = null,
                 Type = EIssueType.QuestDisabled,
index b385306d5a3f77f4dd9d39c1f15cb9ba1dbaeaf6..12adeecb6e4e553614038ea39b640b644c1fdbe8 100644 (file)
@@ -18,7 +18,7 @@ internal sealed class UniqueStartStopValidator : IQuestValidator
             {
                 yield return new ValidationIssue
                 {
-                    QuestId = quest.QuestId,
+                    QuestId = quest.QuestElementId,
                     Sequence = (byte)accept.Sequence.Sequence,
                     Step = accept.StepId,
                     Type = EIssueType.UnexpectedAcceptQuestStep,
@@ -32,7 +32,7 @@ internal sealed class UniqueStartStopValidator : IQuestValidator
         {
             yield return new ValidationIssue
             {
-                QuestId = quest.QuestId,
+                QuestId = quest.QuestElementId,
                 Sequence = 0,
                 Step = null,
                 Type = EIssueType.MissingQuestAccept,
@@ -50,7 +50,7 @@ internal sealed class UniqueStartStopValidator : IQuestValidator
             {
                 yield return new ValidationIssue
                 {
-                    QuestId = quest.QuestId,
+                    QuestId = quest.QuestElementId,
                     Sequence = (byte)complete.Sequence.Sequence,
                     Step = complete.StepId,
                     Type = EIssueType.UnexpectedCompleteQuestStep,
@@ -64,7 +64,7 @@ internal sealed class UniqueStartStopValidator : IQuestValidator
         {
             yield return new ValidationIssue
             {
-                QuestId = quest.QuestId,
+                QuestId = quest.QuestElementId,
                 Sequence = 255,
                 Step = null,
                 Type = EIssueType.MissingQuestComplete,
index ed68542c70766f4e11a6565d99fe7c6f6a9b13cb..5c7286de6df1f1274132117a8bc6070dc7519837 100644 (file)
@@ -46,7 +46,7 @@ internal sealed class DebugOverlay : Window
         IsOpen = true;
     }
 
-    public IId? HighlightedQuest { get; set; }
+    public ElementId? HighlightedQuest { get; set; }
 
     public override bool DrawConditions() => _configuration.Advanced.DebugOverlay;
 
@@ -103,7 +103,7 @@ internal sealed class DebugOverlay : Window
                 QuestStep? step = sequence.FindStep(i);
                 if (step != null && TryGetPosition(step, out Vector3? position))
                 {
-                    DrawStep($"{quest.QuestId} / {sequence.Sequence} / {i}", step, position.Value, 0xFFFFFFFF);
+                    DrawStep($"{quest.QuestElementId} / {sequence.Sequence} / {i}", step, position.Value, 0xFFFFFFFF);
                 }
             }
         }
index e566eaadad6c8e2d5456d9fc3891f5dfade5f4f6..4f83cca88ee4de3e4949ecbe88c62368ccfdbdd5 100644 (file)
@@ -151,7 +151,7 @@ internal sealed class ActiveQuestComponent
 
     private QuestWork? DrawQuestWork(QuestController.QuestProgress currentQuest)
     {
-        if (currentQuest.Quest.QuestId is not QuestId questId)
+        if (currentQuest.Quest.QuestElementId is not QuestId questId)
             return null;
 
         var questWork = _gameFunctions.GetQuestEx(questId);
@@ -210,7 +210,7 @@ internal sealed class ActiveQuestComponent
         {
             using var disabled = ImRaii.Disabled();
 
-            if (currentQuest.Quest.QuestId == _questController.NextQuest?.Quest.QuestId)
+            if (currentQuest.Quest.QuestElementId == _questController.NextQuest?.Quest.QuestElementId)
                 ImGui.TextUnformatted("(Next quest in story line not accepted)");
             else
                 ImGui.TextUnformatted("(Not accepted)");
@@ -262,7 +262,7 @@ internal sealed class ActiveQuestComponent
         if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.ArrowCircleRight, "Skip"))
         {
             _movementController.Stop();
-            _questController.Skip(currentQuest.Quest.QuestId, currentQuest.Sequence);
+            _questController.Skip(currentQuest.Quest.QuestElementId, currentQuest.Sequence);
         }
 
         if (colored)
@@ -274,7 +274,7 @@ internal sealed class ActiveQuestComponent
             ImGui.SameLine();
             if (ImGuiComponents.IconButton(FontAwesomeIcon.Atlas))
                 _commandManager.DispatchCommand("/questinfo",
-                    currentQuest.Quest.QuestId.ToString() ?? string.Empty, commandInfo);
+                    currentQuest.Quest.QuestElementId.ToString() ?? string.Empty, commandInfo);
         }
 
         bool autoAcceptNextQuest = _configuration.General.AutoAcceptNextQuest;
index ab8803cb2294945390c32631b111c775c0d91712..12375337567249dd789ae7056d83562557e8dad3 100644 (file)
@@ -105,7 +105,7 @@ internal sealed class QuestSelectionWindow : LWindow
 
         _quests = _questRegistry.AllQuests
             .Where(x => x.FindSequence(0)?.FindStep(0)?.TerritoryId == territoryId)
-            .Select(x => _questData.GetQuestInfo(x.QuestId))
+            .Select(x => _questData.GetQuestInfo(x.QuestElementId))
             .ToList();
 
         foreach (var unacceptedQuest in Map.Instance()->UnacceptedQuestMarkers)
index 701e874bf108d737f02a104f8a0999f17f9abac6..6e750e9d3bbeb442dbde24202bcb839521ad7eec 100644 (file)
@@ -19,13 +19,13 @@ internal sealed class UiUtils
         _pluginInterface = pluginInterface;
     }
 
-    public (Vector4 color, FontAwesomeIcon icon, string status) GetQuestStyle(IId questId)
+    public (Vector4 color, FontAwesomeIcon icon, string status) GetQuestStyle(ElementId questElementId)
     {
-        if (_gameFunctions.IsQuestAccepted(questId))
+        if (_gameFunctions.IsQuestAccepted(questElementId))
             return (ImGuiColors.DalamudYellow, FontAwesomeIcon.Running, "Active");
-        else if (_gameFunctions.IsQuestAcceptedOrComplete(questId))
+        else if (_gameFunctions.IsQuestAcceptedOrComplete(questElementId))
             return (ImGuiColors.ParsedGreen, FontAwesomeIcon.Check, "Complete");
-        else if (_gameFunctions.IsQuestLocked(questId))
+        else if (_gameFunctions.IsQuestLocked(questElementId))
             return (ImGuiColors.DalamudRed, FontAwesomeIcon.Times, "Locked");
         else
             return (ImGuiColors.DalamudYellow, FontAwesomeIcon.PersonWalkingArrowRight, "Available");