From 2f4f4e24e240fa186a50a686581d2de854580a78 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sat, 3 Aug 2024 22:17:18 +0200 Subject: [PATCH] Migrate QuestIds; add more quest paths --- GatheringPaths/2.x - A Realm Reborn/.gitkeep | 0 .../157_Spineless Basin_MIN.json | 152 ++++++++++++++++++ .../Western Thanalan/154_Hammerlea_MIN.json | 152 ++++++++++++++++++ .../6.x - Endwalker/Elysion/316__MIN.json | 61 +++++++ .../6.x - Endwalker/Elysion/317__MIN.json | 57 +++++++ .../6.x - Endwalker/Elysion/322__MIN.json | 61 +++++++ .../6.x - Endwalker/Elysion/336__MIN.json | 61 +++++++ .../6.x - Endwalker/Elysion/393__BTN.json | 57 +++++++ .../6.x - Endwalker/Elysion/394__BTN.json | 61 +++++++ .../6.x - Endwalker/Elysion/398__BTN.json | 61 +++++++ .../6.x - Endwalker/Elysion/399__BTN.json | 61 +++++++ QuestPathGenerator/QuestSourceGenerator.cs | 2 + QuestPathGenerator/RoslynShortcuts.cs | 23 ++- .../MIN/192_So You Want to Be a Miner.json | 28 ++++ .../MIN/597_Way of the Miner.json | 44 +++++ .../MIN/599_My First Pickaxe.json | 55 +++++++ .../Class Quests/MIN/600_Know Thy Land.json | 55 +++++++ QuestPaths/quest-v1.json | 6 + .../Questing/Converter/ElementIdConverter.cs | 19 +++ .../Questing/Converter/IdConverter.cs | 19 --- Questionable.Model/Questing/ElementId.cs | 86 ++++++++++ Questionable.Model/Questing/IId.cs | 58 ------- Questionable.Model/Questing/QuestStep.cs | 12 +- .../Questing/SkipAetheryteCondition.cs | 5 +- .../Questing/SkipStepConditions.cs | 4 +- Questionable/Controller/CombatController.cs | 4 +- Questionable/Controller/CommandHandler.cs | 10 +- Questionable/Controller/GameUiController.cs | 6 +- Questionable/Controller/QuestController.cs | 36 ++--- Questionable/Controller/QuestRegistry.cs | 24 +-- .../Controller/Steps/Common/NextQuest.cs | 26 +-- Questionable/Controller/Steps/ILastTask.cs | 2 +- .../Controller/Steps/Interactions/Combat.cs | 10 +- .../Controller/Steps/Interactions/UseItem.cs | 20 +-- .../Steps/Shared/AetheryteShortcut.cs | 46 ++++-- .../Controller/Steps/Shared/SkipCondition.cs | 10 +- .../Controller/Steps/Shared/WaitAtEnd.cs | 34 ++-- Questionable/Data/QuestData.cs | 6 +- Questionable/GameFunctions.cs | 36 ++--- Questionable/Model/Quest.cs | 2 +- Questionable/Questionable.csproj | 2 +- Questionable/Validation/ValidationIssue.cs | 2 +- .../Validators/AethernetShortcutValidator.cs | 6 +- .../Validators/BasicSequenceValidator.cs | 8 +- .../Validators/CompletionFlagsValidator.cs | 2 +- .../Validators/JsonSchemaValidator.cs | 8 +- .../Validators/NextQuestValidator.cs | 4 +- .../Validators/QuestDisabledValidator.cs | 2 +- .../Validators/UniqueStartStopValidator.cs | 8 +- Questionable/Windows/DebugOverlay.cs | 4 +- .../QuestComponents/ActiveQuestComponent.cs | 8 +- Questionable/Windows/QuestSelectionWindow.cs | 2 +- Questionable/Windows/UiUtils.cs | 8 +- 53 files changed, 1287 insertions(+), 249 deletions(-) delete mode 100644 GatheringPaths/2.x - A Realm Reborn/.gitkeep create mode 100644 GatheringPaths/2.x - A Realm Reborn/Central Thanalan/157_Spineless Basin_MIN.json create mode 100644 GatheringPaths/2.x - A Realm Reborn/Western Thanalan/154_Hammerlea_MIN.json create mode 100644 GatheringPaths/6.x - Endwalker/Elysion/316__MIN.json create mode 100644 GatheringPaths/6.x - Endwalker/Elysion/317__MIN.json create mode 100644 GatheringPaths/6.x - Endwalker/Elysion/322__MIN.json create mode 100644 GatheringPaths/6.x - Endwalker/Elysion/336__MIN.json create mode 100644 GatheringPaths/6.x - Endwalker/Elysion/393__BTN.json create mode 100644 GatheringPaths/6.x - Endwalker/Elysion/394__BTN.json create mode 100644 GatheringPaths/6.x - Endwalker/Elysion/398__BTN.json create mode 100644 GatheringPaths/6.x - Endwalker/Elysion/399__BTN.json create mode 100644 QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/192_So You Want to Be a Miner.json create mode 100644 QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/597_Way of the Miner.json create mode 100644 QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/599_My First Pickaxe.json create mode 100644 QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/600_Know Thy Land.json create mode 100644 Questionable.Model/Questing/Converter/ElementIdConverter.cs delete mode 100644 Questionable.Model/Questing/Converter/IdConverter.cs create mode 100644 Questionable.Model/Questing/ElementId.cs delete mode 100644 Questionable.Model/Questing/IId.cs diff --git a/GatheringPaths/2.x - A Realm Reborn/.gitkeep b/GatheringPaths/2.x - A Realm Reborn/.gitkeep deleted file mode 100644 index e69de29bb..000000000 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 index 000000000..66426fb79 --- /dev/null +++ b/GatheringPaths/2.x - A Realm Reborn/Central Thanalan/157_Spineless Basin_MIN.json @@ -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 index 000000000..4a13bd8e1 --- /dev/null +++ b/GatheringPaths/2.x - A Realm Reborn/Western Thanalan/154_Hammerlea_MIN.json @@ -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 index 000000000..d401f0dc1 --- /dev/null +++ b/GatheringPaths/6.x - Endwalker/Elysion/316__MIN.json @@ -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 index 000000000..2fb862040 --- /dev/null +++ b/GatheringPaths/6.x - Endwalker/Elysion/317__MIN.json @@ -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 index 000000000..7854b5194 --- /dev/null +++ b/GatheringPaths/6.x - Endwalker/Elysion/322__MIN.json @@ -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 index 000000000..c5f722ca8 --- /dev/null +++ b/GatheringPaths/6.x - Endwalker/Elysion/336__MIN.json @@ -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 index 000000000..d4c4076d5 --- /dev/null +++ b/GatheringPaths/6.x - Endwalker/Elysion/393__BTN.json @@ -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 index 000000000..a405c6658 --- /dev/null +++ b/GatheringPaths/6.x - Endwalker/Elysion/394__BTN.json @@ -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 index 000000000..8ad1fa44e --- /dev/null +++ b/GatheringPaths/6.x - Endwalker/Elysion/398__BTN.json @@ -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 index 000000000..64f577788 --- /dev/null +++ b/GatheringPaths/6.x - Endwalker/Elysion/399__BTN.json @@ -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 diff --git a/QuestPathGenerator/QuestSourceGenerator.cs b/QuestPathGenerator/QuestSourceGenerator.cs index 5060d3b44..8bff39152 100644 --- a/QuestPathGenerator/QuestSourceGenerator.cs +++ b/QuestPathGenerator/QuestSourceGenerator.cs @@ -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(), diff --git a/QuestPathGenerator/RoslynShortcuts.cs b/QuestPathGenerator/RoslynShortcuts.cs index 7e2054ee0..0a8e19e23 100644 --- a/QuestPathGenerator/RoslynShortcuts.cs +++ b/QuestPathGenerator/RoslynShortcuts.cs @@ -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( + 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 index 000000000..faaf1166b --- /dev/null +++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/192_So You Want to Be a Miner.json @@ -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 index 000000000..ab55d722f --- /dev/null +++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/597_Way of the Miner.json @@ -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 index 000000000..c9bcf3776 --- /dev/null +++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/599_My First Pickaxe.json @@ -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 index 000000000..ae8417c0c --- /dev/null +++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/MIN/600_Know Thy Land.json @@ -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 + } + ] + } + ] + } + ] +} diff --git a/QuestPaths/quest-v1.json b/QuestPaths/quest-v1.json index f18d33a74..9a031631e 100644 --- a/QuestPaths/quest-v1.json +++ b/QuestPaths/quest-v1.json @@ -251,6 +251,12 @@ }, "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 index 000000000..27cecb991 --- /dev/null +++ b/Questionable.Model/Questing/Converter/ElementIdConverter.cs @@ -0,0 +1,19 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Questionable.Model.Questing.Converter; + +public class ElementIdConverter : JsonConverter +{ + 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 index 188627d12..000000000 --- a/Questionable.Model/Questing/Converter/IdConverter.cs +++ /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 -{ - 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 index 000000000..e4b3c71ce --- /dev/null +++ b/Questionable.Model/Questing/ElementId.cs @@ -0,0 +1,86 @@ +using System; +using System.Globalization; + +namespace Questionable.Model.Questing; + +public abstract class ElementId : IComparable, IEquatable +{ + 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 index eefb5eba6..000000000 --- a/Questionable.Model/Questing/IId.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Globalization; - -namespace Questionable.Model.Questing -{ - public interface IId : IComparable - { - 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 - { - } -} diff --git a/Questionable.Model/Questing/QuestStep.cs b/Questionable.Model/Questing/QuestStep.cs index dec9d156c..58a7a5b6a 100644 --- a/Questionable.Model/Questing/QuestStep.cs +++ b/Questionable.Model/Questing/QuestStep.cs @@ -72,14 +72,14 @@ public sealed class QuestStep public IList PointMenuChoices { get; set; } = new List(); // 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() diff --git a/Questionable.Model/Questing/SkipAetheryteCondition.cs b/Questionable.Model/Questing/SkipAetheryteCondition.cs index 0109e4de9..870abe667 100644 --- a/Questionable.Model/Questing/SkipAetheryteCondition.cs +++ b/Questionable.Model/Questing/SkipAetheryteCondition.cs @@ -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 InTerritory { get; set; } = new(); } diff --git a/Questionable.Model/Questing/SkipStepConditions.cs b/Questionable.Model/Questing/SkipStepConditions.cs index 61d126f3e..c336abe66 100644 --- a/Questionable.Model/Questing/SkipStepConditions.cs +++ b/Questionable.Model/Questing/SkipStepConditions.cs @@ -13,8 +13,8 @@ public sealed class SkipStepConditions public List InTerritory { get; set; } = new(); public List NotInTerritory { get; set; } = new(); public SkipItemConditions? Item { get; set; } - public List QuestsAccepted { get; set; } = new(); - public List QuestsCompleted { get; set; } = new(); + public List QuestsAccepted { get; set; } = new(); + public List QuestsCompleted { get; set; } = new(); public EExtraSkipCondition? ExtraCondition { get; set; } public bool HasSkipConditions() diff --git a/Questionable/Controller/CombatController.cs b/Questionable/Controller/CombatController.cs index 4099da390..8c9998257 100644 --- a/Questionable/Controller/CombatController.cs +++ b/Questionable/Controller/CombatController.cs @@ -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 KillEnemyDataIds { get; init; } public required List ComplexCombatDatas { get; init; } diff --git a/Questionable/Controller/CommandHandler.cs b/Questionable/Controller/CommandHandler.cs index a7fcf8d4a..5e88cf85a 100644 --- a/Questionable/Controller/CommandHandler.cs +++ b/Questionable/Controller/CommandHandler.cs @@ -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})."); diff --git a/Questionable/Controller/GameUiController.cs b/Questionable/Controller/GameUiController.cs index fa55793d3..e7df22139 100644 --- a/Questionable/Controller/GameUiController.cs +++ b/Questionable/Controller/GameUiController.cs @@ -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 /// 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; diff --git a/Questionable/Controller/QuestController.cs b/Questionable/Controller/QuestController.cs index 569275b3d..dcd3b8b02 100644 --- a/Questionable/Controller/QuestController.cs +++ b/Questionable/Controller/QuestController.cs @@ -77,7 +77,7 @@ internal sealed class QuestController : MiniTaskController { 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 // 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 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 } 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 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 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 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 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 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 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 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 } _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 } } - 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 if (_taskQueue.Count == 0) { Stop("Skip"); - IncreaseStepCount(questQuestId, currentQuestSequence); + IncreaseStepCount(questQuestElementId, currentQuestSequence); } } else { Stop("SkipNx"); - IncreaseStepCount(questQuestId, currentQuestSequence); + IncreaseStepCount(questQuestElementId, currentQuestSequence); } } } diff --git a/Questionable/Controller/QuestRegistry.cs b/Questionable/Controller/QuestRegistry.cs index 426606b6b..67cd658e2 100644 --- a/Questionable/Controller/QuestRegistry.cs +++ b/Questionable/Controller/QuestRegistry.cs @@ -28,7 +28,7 @@ internal sealed class QuestRegistry private readonly ILogger _logger; private readonly ICallGateProvider _reloadDataIpc; - private readonly Dictionary _quests = new(); + private readonly Dictionary _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()!, 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 { diff --git a/Questionable/Controller/Steps/Common/NextQuest.cs b/Questionable/Controller/Steps/Common/NextQuest.cs index 5bddb2aad..ecc521b3a 100644 --- a/Questionable/Controller/Steps/Common/NextQuest.cs +++ b/Questionable/Controller/Steps/Common/NextQuest.cs @@ -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() - .With(step.NextQuestId, quest.QuestId); + .With(step.NextQuestId, quest.QuestElementId); } } internal sealed class SetQuest(QuestRegistry questRegistry, QuestController questController, GameFunctions gameFunctions, ILogger 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})"; } } diff --git a/Questionable/Controller/Steps/ILastTask.cs b/Questionable/Controller/Steps/ILastTask.cs index 8b12de452..71e8b0a60 100644 --- a/Questionable/Controller/Steps/ILastTask.cs +++ b/Questionable/Controller/Steps/ILastTask.cs @@ -4,6 +4,6 @@ namespace Questionable.Controller.Steps; internal interface ILastTask : ITask { - public IId QuestId { get; } + public ElementId QuestElementId { get; } public int Sequence { get; } } diff --git a/Questionable/Controller/Steps/Interactions/Combat.cs b/Questionable/Controller/Steps/Interactions/Combat.cs index 58161886a..d6a3f52a8 100644 --- a/Questionable/Controller/Steps/Interactions/Combat.cs +++ b/Questionable/Controller/Steps/Interactions/Combat.cs @@ -47,7 +47,7 @@ internal static class Combat ArgumentNullException.ThrowIfNull(step.ItemId); yield return serviceProvider.GetRequiredService() - .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() - .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 _completionQuestVariableFlags = null!; - public ITask With(IId questId, bool isLastStep, EEnemySpawnType enemySpawnType, IList killEnemyDataIds, + public ITask With(ElementId questElementId, bool isLastStep, EEnemySpawnType enemySpawnType, IList killEnemyDataIds, IList completionQuestVariablesFlags, IList 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) diff --git a/Questionable/Controller/Steps/Interactions/UseItem.cs b/Questionable/Controller/Steps/Interactions/UseItem.cs index d971b7829..ea46939ce 100644 --- a/Questionable/Controller/Steps/Interactions/UseItem.cs +++ b/Questionable/Controller/Steps/Interactions/UseItem.cs @@ -48,7 +48,7 @@ internal static class UseItem } var task = serviceProvider.GetRequiredService() - .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() - .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() - .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() - .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() - .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 CompletionQuestVariablesFlags { get; set; } = new List(); 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 completionQuestVariablesFlags) + public ITask With(ElementId? questId, uint dataId, uint itemId, IList 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 completionQuestVariablesFlags) + public ITask With(ElementId? questId, Vector3 position, uint itemId, IList 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 completionQuestVariablesFlags, + public ITask With(ElementId? questId, uint dataId, uint itemId, IList 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 completionQuestVariablesFlags) + public ITask With(ElementId? questId, uint itemId, IList completionQuestVariablesFlags) { QuestId = questId; ItemId = itemId; diff --git a/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs b/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs index ed8d1c07a..ba03874a8 100644 --- a/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs +++ b/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs @@ -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; + } } } } diff --git a/Questionable/Controller/Steps/Shared/SkipCondition.cs b/Questionable/Controller/Steps/Shared/SkipCondition.cs index 0b24ecaa8..a122d57cb 100644 --- a/Questionable/Controller/Steps/Shared/SkipCondition.cs +++ b/Questionable/Controller/Steps/Shared/SkipCondition.cs @@ -34,7 +34,7 @@ internal static class SkipCondition return null; return serviceProvider.GetRequiredService() - .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) diff --git a/Questionable/Controller/Steps/Shared/WaitAtEnd.cs b/Questionable/Controller/Steps/Shared/WaitAtEnd.cs index 55fede1b2..1b84c2bc0 100644 --- a/Questionable/Controller/Steps/Shared/WaitAtEnd.cs +++ b/Questionable/Controller/Steps/Shared/WaitAtEnd.cs @@ -30,7 +30,7 @@ internal static class WaitAtEnd if (step.CompletionQuestVariablesFlags.Count == 6 && QuestWorkUtils.HasCompletionFlags(step.CompletionQuestVariablesFlags)) { var task = serviceProvider.GetRequiredService() - .With((QuestId)quest.QuestId, step); + .With((QuestId)quest.QuestElementId, step); var delay = serviceProvider.GetRequiredService(); return [task, delay, Next(quest, sequence)]; } @@ -110,7 +110,7 @@ internal static class WaitAtEnd case EInteractionType.AcceptQuest: { var accept = serviceProvider.GetRequiredService() - .With(step.PickUpQuestId ?? quest.QuestId); + .With(step.PickUpQuestId ?? quest.QuestElementId); var delay = serviceProvider.GetRequiredService(); 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() - .With(step.TurnInQuestId ?? quest.QuestId); + .With(step.TurnInQuestId ?? quest.QuestElementId); var delay = serviceProvider.GetRequiredService(); 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; diff --git a/Questionable/Data/QuestData.cs b/Questionable/Data/QuestData.cs index d30a5f2e6..aef7b726d 100644 --- a/Questionable/Data/QuestData.cs +++ b/Questionable/Data/QuestData.cs @@ -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) diff --git a/Questionable/GameFunctions.cs b/Questionable/GameFunctions.cs index 521d89e80..83f3b27db 100644 --- a/Questionable/GameFunctions.cs +++ b/Questionable/GameFunctions.cs @@ -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()!.GetRow((uint)currentQuest.QuestId.Value + + _dataManager.GetExcelSheet()!.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(excelSheetName); diff --git a/Questionable/Model/Quest.cs b/Questionable/Model/Quest.cs index f778b137c..391e0602b 100644 --- a/Questionable/Model/Quest.cs +++ b/Questionable/Model/Quest.cs @@ -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; } diff --git a/Questionable/Questionable.csproj b/Questionable/Questionable.csproj index ceb37e8c4..1e9d92faf 100644 --- a/Questionable/Questionable.csproj +++ b/Questionable/Questionable.csproj @@ -1,6 +1,6 @@  - 1.24 + 2.0 dist $(SolutionDir)=X:\ x64 diff --git a/Questionable/Validation/ValidationIssue.cs b/Questionable/Validation/ValidationIssue.cs index c0c1c7b6a..314026209 100644 --- a/Questionable/Validation/ValidationIssue.cs +++ b/Questionable/Validation/ValidationIssue.cs @@ -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; diff --git a/Questionable/Validation/Validators/AethernetShortcutValidator.cs b/Questionable/Validation/Validators/AethernetShortcutValidator.cs index e094f83b2..f5820ac24 100644 --- a/Questionable/Validation/Validators/AethernetShortcutValidator.cs +++ b/Questionable/Validation/Validators/AethernetShortcutValidator.cs @@ -18,12 +18,12 @@ internal sealed class AethernetShortcutValidator : IQuestValidator public IEnumerable 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(); } - 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, diff --git a/Questionable/Validation/Validators/BasicSequenceValidator.cs b/Questionable/Validation/Validators/BasicSequenceValidator.cs index 0127bc195..a7330d8ff 100644 --- a/Questionable/Validation/Validators/BasicSequenceValidator.cs +++ b/Questionable/Validation/Validators/BasicSequenceValidator.cs @@ -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, diff --git a/Questionable/Validation/Validators/CompletionFlagsValidator.cs b/Questionable/Validation/Validators/CompletionFlagsValidator.cs index 2cfc58d7e..76b539e20 100644 --- a/Questionable/Validation/Validators/CompletionFlagsValidator.cs +++ b/Questionable/Validation/Validators/CompletionFlagsValidator.cs @@ -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, diff --git a/Questionable/Validation/Validators/JsonSchemaValidator.cs b/Questionable/Validation/Validators/JsonSchemaValidator.cs index 2efa6be8b..ca3625608 100644 --- a/Questionable/Validation/Validators/JsonSchemaValidator.cs +++ b/Questionable/Validation/Validators/JsonSchemaValidator.cs @@ -11,7 +11,7 @@ namespace Questionable.Validation.Validators; internal sealed class JsonSchemaValidator : IQuestValidator { - private readonly Dictionary _questNodes = new(); + private readonly Dictionary _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(); } diff --git a/Questionable/Validation/Validators/NextQuestValidator.cs b/Questionable/Validation/Validators/NextQuestValidator.cs index 325d8fbfa..9c0afbc0b 100644 --- a/Questionable/Validation/Validators/NextQuestValidator.cs +++ b/Questionable/Validation/Validators/NextQuestValidator.cs @@ -8,11 +8,11 @@ internal sealed class NextQuestValidator : IQuestValidator { public IEnumerable 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, diff --git a/Questionable/Validation/Validators/QuestDisabledValidator.cs b/Questionable/Validation/Validators/QuestDisabledValidator.cs index 298b34239..18764ecb0 100644 --- a/Questionable/Validation/Validators/QuestDisabledValidator.cs +++ b/Questionable/Validation/Validators/QuestDisabledValidator.cs @@ -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, diff --git a/Questionable/Validation/Validators/UniqueStartStopValidator.cs b/Questionable/Validation/Validators/UniqueStartStopValidator.cs index b385306d5..12adeecb6 100644 --- a/Questionable/Validation/Validators/UniqueStartStopValidator.cs +++ b/Questionable/Validation/Validators/UniqueStartStopValidator.cs @@ -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, diff --git a/Questionable/Windows/DebugOverlay.cs b/Questionable/Windows/DebugOverlay.cs index ed68542c7..5c7286de6 100644 --- a/Questionable/Windows/DebugOverlay.cs +++ b/Questionable/Windows/DebugOverlay.cs @@ -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); } } } diff --git a/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs b/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs index e566eaada..4f83cca88 100644 --- a/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs +++ b/Questionable/Windows/QuestComponents/ActiveQuestComponent.cs @@ -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; diff --git a/Questionable/Windows/QuestSelectionWindow.cs b/Questionable/Windows/QuestSelectionWindow.cs index ab8803cb2..123753375 100644 --- a/Questionable/Windows/QuestSelectionWindow.cs +++ b/Questionable/Windows/QuestSelectionWindow.cs @@ -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) diff --git a/Questionable/Windows/UiUtils.cs b/Questionable/Windows/UiUtils.cs index 701e874bf..6e750e9d3 100644 --- a/Questionable/Windows/UiUtils.cs +++ b/Questionable/Windows/UiUtils.cs @@ -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");