From 2503d1897fee61536a7ad1d23b25d586329c90dd Mon Sep 17 00:00:00 2001 From: Gwen Date: Sat, 4 Jan 2025 17:22:24 +0100 Subject: [PATCH 01/39] New set of sidequests for Triple Triad NPCs --- .../1762_The Secret to Success.json | 125 ++++++++++ .../1764_Introductory Dragonslaying.json | 98 ++++++++ .../1765_Intermediate Dragonslaying.json | 97 ++++++++ .../1766_Advanced Dragonslaying.json | 103 ++++++++ .../1769_Expert Dragonslaying.json | 185 ++++++++++++++ .../1889_Unknown Ultimatum.json | 121 +++++++++ .../1890_Personal Effects.json | 75 ++++++ .../1891_Ayleth Absconds.json | 98 ++++++++ .../1892_A Missing Tooth.json | 83 +++++++ .../1893_A Noble Purpose.json | 112 +++++++++ .../1898_A War without End.json | 229 ++++++++++++++++++ .../1730_Cold Days, Colder Nights.json | 140 +++++++++++ .../Ishgard/1870_Caught in the Act.json | 149 ++++++++++++ .../Side Quests/Ishgard/1873_Enlisted.json | 53 ++++ .../1840_A Secret from Everyone.json | 134 ++++++++++ 15 files changed, 1802 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1762_The Secret to Success.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1764_Introductory Dragonslaying.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1765_Intermediate Dragonslaying.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1766_Advanced Dragonslaying.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1769_Expert Dragonslaying.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1889_Unknown Ultimatum.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1890_Personal Effects.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1891_Ayleth Absconds.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1892_A Missing Tooth.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1893_A Noble Purpose.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1898_A War without End.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1730_Cold Days, Colder Nights.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1870_Caught in the Act.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1873_Enlisted.json create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/The Churning Mists/1840_A Secret from Everyone.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1762_The Secret to Success.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1762_The Secret to Success.json new file mode 100644 index 00000000..1c16e3f1 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1762_The Secret to Success.json @@ -0,0 +1,125 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1014133, + "Position": { + "X": -259.84595, + "Y": 126.44779, + "Z": 1.9073486 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "DataId": 2006005, + "Position": { + "X": -157.70203, + "Y": 110.73462, + "Z": -52.414795 + }, + "TerritoryId": 397, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 128 + ] + }, + { + "DataId": 2006006, + "Position": { + "X": -228.25977, + "Y": 112.47424, + "Z": -127.55017 + }, + "TerritoryId": 397, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 64 + ] + }, + { + "DataId": 2006007, + "Position": { + "X": -348.10413, + "Y": 116.50256, + "Z": -91.93567 + }, + "TerritoryId": 397, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 32 + ] + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 1014133, + "Position": { + "X": -259.84595, + "Y": 126.44779, + "Z": 1.9073486 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest" + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1764_Introductory Dragonslaying.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1764_Introductory Dragonslaying.json new file mode 100644 index 00000000..c526f673 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1764_Introductory Dragonslaying.json @@ -0,0 +1,98 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1014134, + "Position": { + "X": -293.23267, + "Y": 126.85495, + "Z": 5.2643433 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "Fly": true, + "DataId": 1014136, + "Position": { + "X": 292.74426, + "Y": 132.44626, + "Z": -244.73944 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + }, + { + "Position": { + "X": 289.0053, + "Y": 132.30807, + "Z": -233.57523 + }, + "DataId": 4041, + "TerritoryId": 397, + "InteractionType": "Combat", + "EnemySpawnType": "AfterInteraction", + "KillEnemyDataIds": [ + 4041 + ] + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 1014136, + "Position": { + "X": 292.74426, + "Y": 132.44626, + "Z": -244.73944 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "Fly": true, + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest", + "NextQuestId": 1765 + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1765_Intermediate Dragonslaying.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1765_Intermediate Dragonslaying.json new file mode 100644 index 00000000..ae7e2afe --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1765_Intermediate Dragonslaying.json @@ -0,0 +1,97 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1014138, + "Position": { + "X": -219.19586, + "Y": 112.21238, + "Z": -244.1596 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "Fly": true, + "DataId": 4470, + "Position": { + "X": -468.44992, + "Y": 93.85853, + "Z": -506.40417 + }, + "TerritoryId": 397, + "InteractionType": "Combat", + "EnemySpawnType": "AutoOnEnterArea", + "KillEnemyDataIds": [ + 4470 + ] + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "Position": { + "X": -219.1624, + "Y": 112.29031, + "Z": -239.88861 + }, + "TerritoryId": 397, + "InteractionType": "WalkTo", + "Fly": true + }, + { + "DataId": 1014138, + "Position": { + "X": -219.19586, + "Y": 112.21238, + "Z": -244.1596 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest", + "NextQuestId": 1766 + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1766_Advanced Dragonslaying.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1766_Advanced Dragonslaying.json new file mode 100644 index 00000000..4f9d54e2 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1766_Advanced Dragonslaying.json @@ -0,0 +1,103 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1014138, + "Position": { + "X": -219.19586, + "Y": 112.21238, + "Z": -244.1596 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "Fly": true, + "DataId": 1014140, + "Position": { + "X": -472.19043, + "Y": 93.87282, + "Z": -503.7156 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 4468, + "Position": { + "X": -696.8278, + "Y": 100.08534, + "Z": -603.926 + }, + "TerritoryId": 397, + "InteractionType": "Combat", + "KillEnemyDataIds": [ + 4468 + ], + "EnemySpawnType": "AutoOnEnterArea" + } + ] + }, + { + "Sequence": 4, + "Steps": [ + { + "DataId": 1014140, + "Position": { + "X": -472.19043, + "Y": 93.87282, + "Z": -503.7156 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "Fly": true, + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest", + "NextQuestId": 1769 + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1769_Expert Dragonslaying.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1769_Expert Dragonslaying.json new file mode 100644 index 00000000..41a0e1d5 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1769_Expert Dragonslaying.json @@ -0,0 +1,185 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Fly": true, + "DataId": 1014142, + "Position": { + "X": -290.33344, + "Y": 76.98337, + "Z": -259.93744 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "DataId": 2006013, + "Position": { + "X": -287.76996, + "Y": 77.74463, + "Z": -278.00415 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 1014142, + "Position": { + "X": -290.33344, + "Y": 76.98337, + "Z": -259.93744 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 4, + "Steps": [ + { + "DataId": 2006014, + "Position": { + "X": -291.8593, + "Y": 76.98169, + "Z": -261.0056 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + }, + { + "DataId": 4037, + "Position": { + "X": -285.1214, + "Y": 76.98337, + "Z": -275.5287 + }, + "TerritoryId": 397, + "InteractionType": "Combat", + "KillEnemyDataIds": [4037], + "EnemySpawnType": "AfterInteraction" + } + ] + }, + { + "Sequence": 5, + "Steps": [ + { + "DataId": 1014142, + "Position": { + "X": -290.33344, + "Y": 76.98337, + "Z": -259.93744 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 6, + "Steps": [ + { + "Fly": true, + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 7, + "Steps": [ + { + "DataId": 1014144, + "Position": { + "X": -258.16742, + "Y": 126.98671, + "Z": 12.77179 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 8, + "Steps": [ + { + "DataId": 2006015, + "Position": { + "X": -252.33844, + "Y": 127.00073, + "Z": 11.093262 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 9, + "Steps": [ + { + "DataId": 1014144, + "Position": { + "X": -258.16742, + "Y": 126.98671, + "Z": 12.77179 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest" + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1889_Unknown Ultimatum.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1889_Unknown Ultimatum.json new file mode 100644 index 00000000..2072032e --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1889_Unknown Ultimatum.json @@ -0,0 +1,121 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1014146, + "Position": { + "X": -258.74725, + "Y": 126.98546, + "Z": 12.649658 + }, + "TerritoryId": 397, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1014147, + "Position": { + "X": -256.97723, + "Y": 126.99508, + "Z": 13.168518 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "Fly": true, + "Position": { + "X": -298.8484, + "Y": 221.68138, + "Z": 548.0529 + }, + "TerritoryId": 397, + "InteractionType": "WalkTo" + }, + { + "Land": true, + "DataId": 1014149, + "Position": { + "X": -294.5144, + "Y": 221.58685, + "Z": 545.922 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 2006017, + "Position": { + "X": -253.34558, + "Y": 221.36255, + "Z": 528.92346 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + }, + { + "DataId": 4076, + "Position": { + "X": -257.5558, + "Y": 221.35532, + "Z": 520.9053 + }, + "TerritoryId": 397, + "InteractionType": "Combat", + "KillEnemyDataIds": [4076], + "EnemySpawnType": "AfterInteraction" + } + ] + }, + { + "Sequence": 4, + "Steps": [ + { + "DataId": 1014149, + "Position": { + "X": -294.5144, + "Y": 221.58685, + "Z": 545.922 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "Fly": true, + "DataId": 1014146, + "Position": { + "X": -258.74725, + "Y": 126.98546, + "Z": 12.649658 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest", + "NextQuestId": 1890 + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1890_Personal Effects.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1890_Personal Effects.json new file mode 100644 index 00000000..bddb0605 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1890_Personal Effects.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1014146, + "Position": { + "X": -258.74725, + "Y": 126.98546, + "Z": 12.649658 + }, + "TerritoryId": 397, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": -297.49585, + "Y": 219.87524, + "Z": 281.65045 + }, + "TerritoryId": 397, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 3992, + "MinimumKillCount": 5 + } + ] + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "Fly": true, + "DataId": 1014150, + "Position": { + "X": 507.13354, + "Y": 217.95148, + "Z": 791.37854 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "Fly": true, + "DataId": 1014146, + "Position": { + "X": -258.74725, + "Y": 126.98546, + "Z": 12.649658 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest", + "NextQuestId": 1891 + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1891_Ayleth Absconds.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1891_Ayleth Absconds.json new file mode 100644 index 00000000..03490c14 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1891_Ayleth Absconds.json @@ -0,0 +1,98 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1014146, + "Position": { + "X": -258.74725, + "Y": 126.98546, + "Z": 12.649658 + }, + "TerritoryId": 397, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Fly": true, + "DataId": 1014151, + "Position": { + "X": -156.08453, + "Y": 219.14235, + "Z": 669.7031 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + }, + { + "DataId": 732, + "Position": { + "X": -151.29321, + "Y": 218.95082, + "Z": 669.4895 + }, + "TerritoryId": 397, + "InteractionType": "Combat", + "EnemySpawnType": "AfterInteraction", + "KillEnemyDataIds": [ + 732 + ] + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "DataId": 1014151, + "Position": { + "X": -156.08453, + "Y": 219.14235, + "Z": 669.7031 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 1014151, + "Position": { + "X": -156.08453, + "Y": 219.14235, + "Z": 669.7031 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "Fly": true, + "DataId": 1014146, + "Position": { + "X": -258.74725, + "Y": 126.98546, + "Z": 12.649658 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest", + "NextQuestId": 1892 + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1892_A Missing Tooth.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1892_A Missing Tooth.json new file mode 100644 index 00000000..657fd96f --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1892_A Missing Tooth.json @@ -0,0 +1,83 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1014146, + "Position": { + "X": -258.74725, + "Y": 126.98546, + "Z": 12.649658 + }, + "TerritoryId": 397, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Fly": true, + "DataId": 2006019, + "Position": { + "X": -152.42242, + "Y": 219.62305, + "Z": 669.94727 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + }, + { + "DataId": 4782, + "Position": { + "X": -158.97404, + "Y": 219.45131, + "Z": 672.79553 + }, + "TerritoryId": 397, + "KillEnemyDataIds": [ + 4782 + ], + "InteractionType": "Combat", + "EnemySpawnType": "AfterInteraction" + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "DataId": 2006181, + "Position": { + "X": -152.42242, + "Y": 219.62305, + "Z": 669.94727 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "Fly": true, + "DataId": 1014146, + "Position": { + "X": -258.74725, + "Y": 126.98546, + "Z": 12.649658 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest", + "NextQuestId": 1983 + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1893_A Noble Purpose.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1893_A Noble Purpose.json new file mode 100644 index 00000000..7a5a5c64 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1893_A Noble Purpose.json @@ -0,0 +1,112 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1014146, + "Position": { + "X": -258.74725, + "Y": 126.98546, + "Z": 12.649658 + }, + "TerritoryId": 397, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1011907, + "Position": { + "X": -288.8686, + "Y": 127.06639, + "Z": 13.199036 + }, + "TerritoryId": 397, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 128 + ] + }, + { + "DataId": 1011910, + "Position": { + "X": -298.26813, + "Y": 126.67049, + "Z": -1.4191895 + }, + "TerritoryId": 397, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 64 + ] + }, + { + "DataId": 1014133, + "Position": { + "X": -259.84595, + "Y": 126.44779, + "Z": 1.9073486 + }, + "TerritoryId": 397, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 32 + ] + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "Fly": true, + "DataId": 1014152, + "Position": { + "X": 496.1776, + "Y": 133.93082, + "Z": -862.2416 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "Fly": true, + "DataId": 1014153, + "Position": { + "X": -295.82666, + "Y": 126.83744, + "Z": 3.829956 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest" + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1898_A War without End.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1898_A War without End.json new file mode 100644 index 00000000..fb968727 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1898_A War without End.json @@ -0,0 +1,229 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1014153, + "Position": { + "X": -295.82666, + "Y": 126.83744, + "Z": 3.829956 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "Fly": true, + "DataId": 1014154, + "Position": { + "X": -519.1577, + "Y": 119.39417, + "Z": -161.24213 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 4, + "Steps": [ + { + "DataId": 1014155, + "Position": { + "X": -527.245, + "Y": 118.94699, + "Z": -163.13422 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 5, + "Steps": [ + { + "DataId": 2006026, + "Position": { + "X": -525.7191, + "Y": 119.06604, + "Z": -165.72827 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 6, + "Steps": [ + { + "Fly": true, + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 7, + "Steps": [ + { + "Fly": true, + "Position": { + "X": -92.57648, + "Y": 96.33008, + "Z": -645.1057 + }, + "TerritoryId": 397, + "InteractionType": "WalkTo" + }, + { + "DataId": 2006027, + "Position": { + "X": -92.57648, + "Y": 96.33008, + "Z": -645.1057 + }, + "TerritoryId": 397, + "InteractionType": "UseItem", + "ItemId": 2001751 + } + ] + }, + { + "Sequence": 8, + "Steps": [ + { + "DataId": 2006028, + "Position": { + "X": -92.5155, + "Y": 93.52246, + "Z": -623.621 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + }, + { + "DataId": 4621, + "Position": { + "X": -92.37683, + "Y": 95.76039, + "Z": -640.7043 + }, + "TerritoryId": 397, + "InteractionType": "Combat", + "EnemySpawnType": "AfterInteraction", + "KillEnemyDataIds": [ + 4621 + ] + } + ] + }, + { + "Sequence": 9, + "Steps": [ + { + "DataId": 2006460, + "Position": { + "X": -92.57648, + "Y": 96.33008, + "Z": -645.1057 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 10, + "Steps": [ + { + "Fly": true, + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 11, + "Steps": [ + { + "DataId": 1014147, + "Position": { + "X": -256.97723, + "Y": 126.99508, + "Z": 13.168518 + }, + "TerritoryId": 397, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1013710, + "Position": { + "X": -294.6975, + "Y": 126.84874, + "Z": 4.5318604 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest" + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1730_Cold Days, Colder Nights.json b/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1730_Cold Days, Colder Nights.json new file mode 100644 index 00000000..0be23e3f --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1730_Cold Days, Colder Nights.json @@ -0,0 +1,140 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012170, + "Position": { + "X": 102.92212, + "Y": 3.6299734, + "Z": 65.56799 + }, + "TerritoryId": 418, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1012162, + "Position": { + "X": 135.97314, + "Y": 24.376427, + "Z": 12.619202 + }, + "TerritoryId": 418, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "DataId": 1012170, + "Position": { + "X": 102.92212, + "Y": 3.6299734, + "Z": 65.56799 + }, + "TerritoryId": 418, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 1014711, + "Position": { + "X": 58.03003, + "Y": -7.146736, + "Z": 82.41394 + }, + "TerritoryId": 418, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 128 + ] + }, + { + "DataId": 1014712, + "Position": { + "X": 93.91919, + "Y": -19.941168, + "Z": 78.20239 + }, + "TerritoryId": 418, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 64 + ] + }, + { + "DataId": 1014713, + "Position": { + "X": 131.9447, + "Y": -20.000105, + "Z": 62.027832 + }, + "TerritoryId": 418, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 32 + ] + } + ] + }, + { + "Sequence": 4, + "Steps": [ + { + "DataId": 1014714, + "Position": { + "X": 23.178406, + "Y": -12.020877, + "Z": 35.294067 + }, + "TerritoryId": 418, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012170, + "Position": { + "X": 102.92212, + "Y": 3.6299734, + "Z": 65.56799 + }, + "TerritoryId": 418, + "InteractionType": "CompleteQuest" + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1870_Caught in the Act.json b/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1870_Caught in the Act.json new file mode 100644 index 00000000..2016dfb6 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1870_Caught in the Act.json @@ -0,0 +1,149 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012180, + "Position": { + "X": -174.18176, + "Y": -12.555469, + "Z": -21.561035 + }, + "TerritoryId": 419, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 2006246, + "Position": { + "X": -218.40247, + "Y": -16.037292, + "Z": -34.683777 + }, + "TerritoryId": 419, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 128 + ] + }, + { + "DataId": 2006247, + "Position": { + "X": -229.23633, + "Y": -20.035156, + "Z": -83.05487 + }, + "TerritoryId": 419, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 64 + ] + }, + { + "DataId": 2006248, + "Position": { + "X": -252.1554, + "Y": -20.035156, + "Z": -57.66388 + }, + "TerritoryId": 419, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 32 + ] + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "DataId": 1012180, + "Position": { + "X": -174.18176, + "Y": -12.555469, + "Z": -21.561035 + }, + "TerritoryId": 419, + "InteractionType": "Interact" + } + ] + + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 1014721, + "Position": { + "X": 119.31018, + "Y": -12.634913, + "Z": -13.626343 + }, + "TerritoryId": 419, + "InteractionType": "Interact", + "AethernetShortcut": [ + "[Ishgard] The Jeweled Crozier", + "[Ishgard] Athenaeum Astrologicum" + ] + } + ] + }, + { + "Sequence": 4, + "Steps": [ + { + "DataId": 2006330, + "Position": { + "X": 118.791504, + "Y": -11.6427, + "Z": -13.351685 + }, + "TerritoryId": 419, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012180, + "Position": { + "X": -174.18176, + "Y": -12.555469, + "Z": -21.561035 + }, + "TerritoryId": 419, + "InteractionType": "CompleteQuest", + "AethernetShortcut": [ + "[Ishgard] Athenaeum Astrologicum", + "[Ishgard] The Jeweled Crozier" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1873_Enlisted.json b/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1873_Enlisted.json new file mode 100644 index 00000000..ef0a9cbd --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1873_Enlisted.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1014718, + "Position": { + "X": -29.526245, + "Y": 11.965078, + "Z": 48.355713 + }, + "TerritoryId": 419, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1011231, + "Position": { + "X": 503.1051, + "Y": 217.95148, + "Z": 790.2189 + }, + "TerritoryId": 397, + "InteractionType": "Interact", + "AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1014719, + "Position": { + "X": -293.6294, + "Y": 125.4389, + "Z": -19.058533 + }, + "TerritoryId": 397, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} \ No newline at end of file diff --git a/QuestPaths/3.x - Heavensward/Side Quests/The Churning Mists/1840_A Secret from Everyone.json b/QuestPaths/3.x - Heavensward/Side Quests/The Churning Mists/1840_A Secret from Everyone.json new file mode 100644 index 00000000..e5351603 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/The Churning Mists/1840_A Secret from Everyone.json @@ -0,0 +1,134 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "Thaksin", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012085, + "Position": { + "X": 286.88477, + "Y": 14.36517, + "Z": 645.1666 + }, + "TerritoryId": 400, + "InteractionType": "AcceptQuest" + } + ] + }, + + { + "Sequence": 1, + "Steps": [ + { + "Fly": true, + "DataId": 2005720, + "Position": { + "X": 565.9419, + "Y": -9.445435, + "Z": -14.328308 + }, + "TerritoryId": 400, + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 16 + ], + "InteractionType": "Interact" + }, + { + "DataId": 2005718, + "Position": { + "X": 664.39294, + "Y": -0.4730835, + "Z": -3.2807007 + }, + "Fly": true, + "TerritoryId": 400, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 64 + ] + }, + { + "DataId": 2005721, + "Position": { + "X": 653.83374, + "Y": -0.7172241, + "Z": -70.02368 + }, + "TerritoryId": 400, + "Fly": true, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, null, + null, null, + null, 8 + ] + }, + { + "DataId": 2005717, + "Position": { + "X": 639.00195, + "Y": 46.463623, + "Z": -113.05414 + }, + "TerritoryId": 400, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 128 + ] + }, + { + "DataId": 2005719, + "Position": { + "X": 527.0923, + "Y": -4.287842, + "Z": -84.916504 + }, + "Fly": true, + "TerritoryId": 400, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 32 + ] + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "Fly": true, + "DataId": 1012085, + "Position": { + "X": 286.88477, + "Y": 14.36517, + "Z": 645.1666 + }, + "TerritoryId": 400, + "InteractionType": "CompleteQuest" + } + ] + } + ] +} \ No newline at end of file From 65df686329e03e920bcd6859879b7cc0904200b5 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Wed, 8 Jan 2025 14:02:05 +0000 Subject: [PATCH 02/39] +1979 --- .../Azys Lla/1979_Basic Training.json | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1979_Basic Training.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1979_Basic Training.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1979_Basic Training.json new file mode 100644 index 00000000..2403b49b --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1979_Basic Training.json @@ -0,0 +1,57 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012145, + "Position": { + "X": -607.7516, + "Y": -176.4502, + "Z": -527.5502 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": -441.42657, + "Y": -167.25401, + "Z": -432.4462 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "KillEnemyDataIds": [4093], + "MinimumKillCount": "5", + "Fly": true, + "$": "5 in close range here, so if any dead it might be a little slower.", + "$.1": "this is the area the quest suggests; there /are/ spinner-rooks sooner, and walking there at level w/o flying might cause interruption, but they're more spread out everywhere else - YMMV." + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012145, + "Position": { + "X": -607.7516, + "Y": -176.4502, + "Z": -527.5502 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From 3889fbfb696a147eb06ebaa08a621890b365b6a8 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Thu, 9 Jan 2025 05:51:09 +0000 Subject: [PATCH 03/39] +1980, de-rust 1979 --- .../Azys Lla/1979_Basic Training.json | 114 +++++++++--------- .../Azys Lla/1980_Good Clean Fun.json | 60 +++++++++ 2 files changed, 119 insertions(+), 55 deletions(-) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1980_Good Clean Fun.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1979_Basic Training.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1979_Basic Training.json index 2403b49b..2955b31f 100644 --- a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1979_Basic Training.json +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1979_Basic Training.json @@ -1,57 +1,61 @@ { - "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", - "Author": "goatzone", - "QuestSequence": [ - { - "Sequence": 0, - "Steps": [ - { - "DataId": 1012145, - "Position": { - "X": -607.7516, - "Y": -176.4502, - "Z": -527.5502 - }, - "TerritoryId": 402, - "InteractionType": "AcceptQuest" - } - ] - }, - { - "Sequence": 1, - "Steps": [ - { - "Position": { - "X": -441.42657, - "Y": -167.25401, - "Z": -432.4462 - }, - "TerritoryId": 402, - "InteractionType": "Combat", - "EnemySpawnType": "OverworldEnemies", - "KillEnemyDataIds": [4093], - "MinimumKillCount": "5", - "Fly": true, - "$": "5 in close range here, so if any dead it might be a little slower.", - "$.1": "this is the area the quest suggests; there /are/ spinner-rooks sooner, and walking there at level w/o flying might cause interruption, but they're more spread out everywhere else - YMMV." - } - ] - }, - { - "Sequence": 255, - "Steps": [ - { - "DataId": 1012145, - "Position": { - "X": -607.7516, - "Y": -176.4502, - "Z": -527.5502 - }, - "TerritoryId": 402, - "InteractionType": "CompleteQuest", - "Fly": true - } - ] - } - ] + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012145, + "Position": { + "X": -607.7516, + "Y": -176.4502, + "Z": -527.5502 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": -441.42657, + "Y": -167.25401, + "Z": -432.4462 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 4093, + "MinimumKillCount": 5 + } + ], + "Fly": true, + "$": "5 in close range here, so if any dead it might be a little slower.", + "$.1": "this is the area the quest suggests; there /are/ spinner-rooks sooner, and walking there at level w/o flying might cause interruption, but they're more spread out everywhere else - YMMV." + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012145, + "Position": { + "X": -607.7516, + "Y": -176.4502, + "Z": -527.5502 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] } diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1980_Good Clean Fun.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1980_Good Clean Fun.json new file mode 100644 index 00000000..be941a7e --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1980_Good Clean Fun.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012146, + "Position": { + "X": -643.76294, + "Y": -176.4502, + "Z": -527.3976 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": -439.6144, + "Y": -186.3405, + "Z": -617.2911 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 4092, + "MinimumKillCount": 5 + } + ], + "Fly": true, + "$": "by starting here we can guarantee a more sane straightline progression instead of starting in the middle, going all the way to one side, then running all the way to the other side." + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012146, + "Position": { + "X": -643.76294, + "Y": -176.4502, + "Z": -527.3976 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "AetheryteShortcut": "Azys Lla - Helix" + } + ] + } + ] +} From b917cd4e9096a7cd7b075d1f4f0c7ae0e981ddc0 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Thu, 9 Jan 2025 06:03:06 +0000 Subject: [PATCH 04/39] +1981 --- .../1981_General Protection Fault.json | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1981_General Protection Fault.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1981_General Protection Fault.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1981_General Protection Fault.json new file mode 100644 index 00000000..8d59d544 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1981_General Protection Fault.json @@ -0,0 +1,55 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012147, + "Position": { + "X": -426.627, + "Y": -162.1281, + "Z": -328.6031 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": -528.74396, + "Y": -143.65883, + "Z": -580.686 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "AutoOnEnterArea", + "KillEnemyDataIds": [4503], + "Fly": true + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012147, + "Position": { + "X": -426.627, + "Y": -162.1281, + "Z": -328.6031 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From ba5975e6ffc2e2e912fd4b119399db34b99d74c3 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Thu, 9 Jan 2025 06:15:46 +0000 Subject: [PATCH 05/39] +1982 --- .../Azys Lla/1982_Excessive Force.json | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1982_Excessive Force.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1982_Excessive Force.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1982_Excessive Force.json new file mode 100644 index 00000000..c3906c89 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1982_Excessive Force.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012148, + "Position": { + "X": -173.2663, + "Y": -162.03395, + "Z": -510.39905 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": -189.43037, + "Y": -160.1837, + "Z": -499.3027 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 4091, + "MinimumKillCount": 3, + "$": "Slay clockwork paladins." + }, + { + "DataId": 4090, + "MinimumKillCount": 3, + "$": "Slay clockwork engineers." + } + ], + "$": "they're all around so we can just start here. possible issue with a FATE spawning here, YMMV." + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012148, + "Position": { + "X": -173.2663, + "Y": -162.03395, + "Z": -510.39905 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest" + } + ] + } + ] +} From 8d64475f0af6c6533d1e18e3030423c19bb0ce59 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Thu, 9 Jan 2025 06:34:20 +0000 Subject: [PATCH 06/39] +1983 --- .../1983_Chimerical Abominations.json | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1983_Chimerical Abominations.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1983_Chimerical Abominations.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1983_Chimerical Abominations.json new file mode 100644 index 00000000..e84881f9 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1983_Chimerical Abominations.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012289, + "Position": { + "X": 231.18933, + "Y": -72.92926, + "Z": -603.1434 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": 517.51276, + "Y": -40.378292, + "Z": -785.99677 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 4141, + "MinimumKillCount": 2 + } + ], + "Fly": true, + "$": "FATE spawns on top of the suggested area, so we move a bit east." + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012289, + "Position": { + "X": 231.18933, + "Y": -72.92926, + "Z": -603.1434 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From 6e19630e605f998d7f5548ec4baf7776b7f9c942 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Thu, 9 Jan 2025 11:39:45 +0000 Subject: [PATCH 07/39] +1984 --- .../Azys Lla/1984_Pollution Solution.json | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1984_Pollution Solution.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1984_Pollution Solution.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1984_Pollution Solution.json new file mode 100644 index 00000000..ef384a78 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1984_Pollution Solution.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012290, + "Position": { + "X": 760.5248, + "Y": -30.307041, + "Z": -579.67505 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": 668.9029, + "Y": -86.006, + "Z": -775.5664 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 4046, + "MinimumKillCount": 4 + } + ], + "Fly": true + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012290, + "Position": { + "X": 760.5248, + "Y": -30.307041, + "Z": -579.67505 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From 8d18b243527177dea9735da84d997d100be5bf97 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Thu, 9 Jan 2025 16:52:15 +0000 Subject: [PATCH 08/39] +1985 --- .../Azys Lla/1985_Good Hunting.json | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1985_Good Hunting.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1985_Good Hunting.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1985_Good Hunting.json new file mode 100644 index 00000000..689b47bb --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1985_Good Hunting.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012291, + "Position": { + "X": 804.074, + "Y": -26.326342, + "Z": -527.48914 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": 355.31863, + "Y": -46.22946, + "Z": -507.70428 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 4072, + "MinimumKillCount": 4 + } + ], + "Fly": true, + "$": "we go to the west of the marked area to avoid idling in the FATE that spawns on the east of it; we'll still path through it when we expend all the westward mobs, but that's just how they spawn, shrugging emoji." + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012291, + "Position": { + "X": 804.074, + "Y": -26.326342, + "Z": -527.48914 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From 1773afea46e09f56ab6da65035985a429c4ee535 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Thu, 9 Jan 2025 19:34:16 +0100 Subject: [PATCH 09/39] GatheringPathRenderer: minor updates --- Directory.Build.targets | 2 +- GatheringPathRenderer/.gitignore | 1 + GatheringPathRenderer/DalamudPackager.targets | 21 +++ .../GatheringPathRenderer.csproj | 8 + .../GatheringPathRenderer.json | 5 +- GatheringPathRenderer/RendererPlugin.cs | 22 ++- GatheringPathRenderer/Windows/ConfigWindow.cs | 33 +++++ GatheringPathRenderer/Windows/EditorWindow.cs | 19 ++- .../1002_Yawtanane Grasslands_BTN.json | 138 ++++++++++++++++++ 9 files changed, 241 insertions(+), 8 deletions(-) create mode 100644 GatheringPathRenderer/.gitignore create mode 100644 GatheringPathRenderer/DalamudPackager.targets create mode 100644 GatheringPathRenderer/Windows/ConfigWindow.cs create mode 100644 GatheringPaths/7.x - Dawntrail/Shaaloani/1002_Yawtanane Grasslands_BTN.json diff --git a/Directory.Build.targets b/Directory.Build.targets index 9c7a8c24..58a5fad2 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,5 +1,5 @@ - + 4.13 diff --git a/GatheringPathRenderer/.gitignore b/GatheringPathRenderer/.gitignore new file mode 100644 index 00000000..a60a458a --- /dev/null +++ b/GatheringPathRenderer/.gitignore @@ -0,0 +1 @@ +/dist diff --git a/GatheringPathRenderer/DalamudPackager.targets b/GatheringPathRenderer/DalamudPackager.targets new file mode 100644 index 00000000..7f129a87 --- /dev/null +++ b/GatheringPathRenderer/DalamudPackager.targets @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/GatheringPathRenderer/GatheringPathRenderer.csproj b/GatheringPathRenderer/GatheringPathRenderer.csproj index 6009a518..73d05cbe 100644 --- a/GatheringPathRenderer/GatheringPathRenderer.csproj +++ b/GatheringPathRenderer/GatheringPathRenderer.csproj @@ -1,4 +1,11 @@ + + 0.1 + dist + $(SolutionDir)=X:\ + x64 + + @@ -6,4 +13,5 @@ + diff --git a/GatheringPathRenderer/GatheringPathRenderer.json b/GatheringPathRenderer/GatheringPathRenderer.json index 8d68d1d8..56f91709 100644 --- a/GatheringPathRenderer/GatheringPathRenderer.json +++ b/GatheringPathRenderer/GatheringPathRenderer.json @@ -1,6 +1,7 @@ { "Name": "GatheringPathRenderer", "Author": "Liza Carvelli", - "Punchline": "dev only plugin: Renders gathering location.", - "Description": "dev only plugin: Renders gathering location (without ECommons polluting the entire normal project)." + "Punchline": "[Questionable dev plugin]: Renders gathering location.", + "Description": "[Questionable dev plugin]: Renders gathering location using Splatoon.", + "RepoUrl": "https://git.carvel.li/liza/Questionable/src/branch/master/GatheringPathRenderer" } diff --git a/GatheringPathRenderer/RendererPlugin.cs b/GatheringPathRenderer/RendererPlugin.cs index 5ef430ea..02e01bb7 100644 --- a/GatheringPathRenderer/RendererPlugin.cs +++ b/GatheringPathRenderer/RendererPlugin.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text.Encodings.Web; @@ -17,11 +18,11 @@ using ECommons.Schedulers; using ECommons.SplatoonAPI; using GatheringPathRenderer.Windows; using LLib.GameData; -using Questionable.Model; using Questionable.Model.Gathering; namespace GatheringPathRenderer; +[SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] public sealed class RendererPlugin : IDalamudPlugin { private const long OnTerritoryChange = -2; @@ -56,8 +57,10 @@ public sealed class RendererPlugin : IDalamudPlugin _editorCommands = new EditorCommands(this, dataManager, commandManager, targetManager, clientState, chatGui, configuration); - _editorWindow = new EditorWindow(this, _editorCommands, dataManager, targetManager, clientState, objectTable) + var configWindow = new ConfigWindow(pluginInterface, configuration); + _editorWindow = new EditorWindow(this, _editorCommands, dataManager, targetManager, clientState, objectTable, configWindow) { IsOpen = true }; + _windowSystem.AddWindow(configWindow); _windowSystem.AddWindow(_editorWindow); _currentClassJob = (EClassJob?)_clientState.LocalPlayer?.ClassJob.RowId ?? EClassJob.Adventurer; @@ -78,6 +81,7 @@ public sealed class RendererPlugin : IDalamudPlugin { get { +#if DEBUG DirectoryInfo? solutionDirectory = _pluginInterface.AssemblyLocation.Directory?.Parent?.Parent?.Parent; if (solutionDirectory != null) { @@ -88,6 +92,12 @@ public sealed class RendererPlugin : IDalamudPlugin } throw new Exception("Unable to resolve project path"); +#else + var allPluginsDirectory = _pluginInterface.ConfigFile.Directory ?? throw new Exception("Unknown directory for plugin configs"); + return allPluginsDirectory + .CreateSubdirectory("Questionable") + .CreateSubdirectory("GatheringPaths"); +#endif } } @@ -103,12 +113,18 @@ public sealed class RendererPlugin : IDalamudPlugin try { +#if DEBUG foreach (var expansionFolder in ExpansionData.ExpansionFolders.Values) LoadFromDirectory( new DirectoryInfo(Path.Combine(PathsDirectory.FullName, expansionFolder))); - _pluginLog.Information( $"Loaded {_gatheringLocations.Count} gathering root locations from project directory"); +#else + LoadFromDirectory(PathsDirectory); + _pluginLog.Information( + $"Loaded {_gatheringLocations.Count} gathering root locations from {PathsDirectory.FullName} directory"); +#endif + } catch (Exception e) { diff --git a/GatheringPathRenderer/Windows/ConfigWindow.cs b/GatheringPathRenderer/Windows/ConfigWindow.cs new file mode 100644 index 00000000..0e9ba04c --- /dev/null +++ b/GatheringPathRenderer/Windows/ConfigWindow.cs @@ -0,0 +1,33 @@ +using Dalamud.Interface.Windowing; +using Dalamud.Plugin; +using ImGuiNET; + +namespace GatheringPathRenderer.Windows; + +internal sealed class ConfigWindow : Window +{ + private readonly IDalamudPluginInterface _pluginInterface; + private readonly Configuration _configuration; + + public ConfigWindow(IDalamudPluginInterface pluginInterface, Configuration configuration) + : base("Gathering Path Config", ImGuiWindowFlags.AlwaysAutoResize) + { + _pluginInterface = pluginInterface; + _configuration = configuration; + + AllowPinning = false; + AllowClickthrough = false; + } + + public override void Draw() + { + string authorName = _configuration.AuthorName; + if (ImGui.InputText("Author name for new files", ref authorName, 256)) + { + _configuration.AuthorName = authorName; + Save(); + } + } + + private void Save() => _pluginInterface.SavePluginConfig(_configuration); +} diff --git a/GatheringPathRenderer/Windows/EditorWindow.cs b/GatheringPathRenderer/Windows/EditorWindow.cs index 1150558f..c117f4a9 100644 --- a/GatheringPathRenderer/Windows/EditorWindow.cs +++ b/GatheringPathRenderer/Windows/EditorWindow.cs @@ -6,6 +6,7 @@ using System.Numerics; using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Interface; using Dalamud.Interface.Colors; using Dalamud.Interface.Windowing; using Dalamud.Plugin.Services; @@ -32,8 +33,8 @@ internal sealed class EditorWindow : Window _targetLocation; public EditorWindow(RendererPlugin plugin, EditorCommands editorCommands, IDataManager dataManager, - ITargetManager targetManager, IClientState clientState, IObjectTable objectTable) - : base("Gathering Path Editor###QuestionableGatheringPathEditor", + ITargetManager targetManager, IClientState clientState, IObjectTable objectTable, ConfigWindow configWindow) + : base($"Gathering Path Editor {typeof(EditorWindow).Assembly.GetName().Version!.ToString(2)}###QuestionableGatheringPathEditor", ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoNavFocus | ImGuiWindowFlags.AlwaysAutoResize) { _plugin = plugin; @@ -48,6 +49,20 @@ internal sealed class EditorWindow : Window MinimumSize = new Vector2(300, 100), }; + TitleBarButtons.Add(new TitleBarButton + { + Icon = FontAwesomeIcon.Cog, + IconOffset = new Vector2(1.5f, 1), + Click = _ => configWindow.IsOpen = true, + Priority = int.MinValue, + ShowTooltip = () => + { + ImGui.BeginTooltip(); + ImGui.Text("Open Configuration"); + ImGui.EndTooltip(); + } + }); + RespectCloseHotkey = false; ShowCloseButton = false; AllowPinning = false; diff --git a/GatheringPaths/7.x - Dawntrail/Shaaloani/1002_Yawtanane Grasslands_BTN.json b/GatheringPaths/7.x - Dawntrail/Shaaloani/1002_Yawtanane Grasslands_BTN.json new file mode 100644 index 00000000..44d84892 --- /dev/null +++ b/GatheringPaths/7.x - Dawntrail/Shaaloani/1002_Yawtanane Grasslands_BTN.json @@ -0,0 +1,138 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json", + "Author": "liza", + "Steps": [ + { + "TerritoryId": 1190, + "InteractionType": "None" + } + ], + "Groups": [ + { + "Nodes": [ + { + "DataId": 34920, + "Locations": [ + { + "Position": { + "X": 192.6021, + "Y": 12.31054, + "Z": 631.2545 + } + }, + { + "Position": { + "X": 194.8373, + "Y": 12.50387, + "Z": 646.5401 + } + }, + { + "Position": { + "X": 180.8447, + "Y": 12.43262, + "Z": 610.7131 + } + } + ] + }, + { + "DataId": 34919, + "Locations": [ + { + "Position": { + "X": 186.171, + "Y": 12.54104, + "Z": 634.9042 + } + } + ] + } + ] + }, + { + "Nodes": [ + { + "DataId": 34917, + "Locations": [ + { + "Position": { + "X": 39.45634, + "Y": -0.06042051, + "Z": 502.3853 + } + } + ] + }, + { + "DataId": 34918, + "Locations": [ + { + "Position": { + "X": 46.03248, + "Y": -0.7049216, + "Z": 491.6059 + } + }, + { + "Position": { + "X": 36.15481, + "Y": -0.0501074, + "Z": 505.9388 + } + }, + { + "Position": { + "X": 24.72226, + "Y": 0.5922582, + "Z": 528.0809 + } + } + ] + } + ] + }, + { + "Nodes": [ + { + "DataId": 34922, + "Locations": [ + { + "Position": { + "X": 2.302937, + "Y": -4.586716, + "Z": 687.4797 + } + }, + { + "Position": { + "X": 30.02284, + "Y": -2.447479, + "Z": 704.4326 + } + }, + { + "Position": { + "X": 41.59287, + "Y": -0.8454803, + "Z": 692.0099 + } + } + ] + }, + { + "DataId": 34921, + "Locations": [ + { + "Position": { + "X": 18.47237, + "Y": -2.987581, + "Z": 690.8011 + } + } + ] + } + ] + } + ] +} \ No newline at end of file From 4dc89d8ed34fb98bdc058a1cc3301fb1b70f9fc4 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Thu, 9 Jan 2025 19:48:27 +0100 Subject: [PATCH 10/39] GatheringPathRenderer: minor updates --- GatheringPathRenderer/RendererPlugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GatheringPathRenderer/RendererPlugin.cs b/GatheringPathRenderer/RendererPlugin.cs index 02e01bb7..93c666a8 100644 --- a/GatheringPathRenderer/RendererPlugin.cs +++ b/GatheringPathRenderer/RendererPlugin.cs @@ -114,7 +114,7 @@ public sealed class RendererPlugin : IDalamudPlugin try { #if DEBUG - foreach (var expansionFolder in ExpansionData.ExpansionFolders.Values) + foreach (var expansionFolder in Questionable.Model.ExpansionData.ExpansionFolders.Values) LoadFromDirectory( new DirectoryInfo(Path.Combine(PathsDirectory.FullName, expansionFolder))); _pluginLog.Information( From 9c5fd2d3feb739e0acc2ce9c545c83ab12750367 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Thu, 9 Jan 2025 20:50:18 +0000 Subject: [PATCH 11/39] +1986 --- .../Azys Lla/1986_Defense Protocols.json | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1986_Defense Protocols.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1986_Defense Protocols.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1986_Defense Protocols.json new file mode 100644 index 00000000..ce12a094 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1986_Defense Protocols.json @@ -0,0 +1,55 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012292, + "Position": { + "X": 583.9779, + "Y": 10.93506, + "Z": 100.02283 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": 773.4017, + "Y": -0.06258035, + "Z": 147.04689 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "KillEnemyDataIds": [4669, 4970, 4671, 4672, 4673], + "Fly": true + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012292, + "Position": { + "X": 583.9779, + "Y": 10.93506, + "Z": 100.02283 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From 880082da0e464665173eb8f4c0addb9866580891 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Fri, 10 Jan 2025 13:35:19 +0000 Subject: [PATCH 12/39] +1987 --- .../Side Quests/Azys Lla/1987_Snikt.json | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1987_Snikt.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1987_Snikt.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1987_Snikt.json new file mode 100644 index 00000000..42a0325a --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1987_Snikt.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012293, + "Position": { + "X": 573.4187, + "Y": 13.072888, + "Z": 329.2439 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": 495.16974, + "Y": 31.67624, + "Z": 517.37463 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 4083, + "MinimumKillCount": 4 + } + ], + "Fly": true + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012293, + "Position": { + "X": 573.4187, + "Y": 13.072888, + "Z": 329.2439 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From 8d4b2320fb5b3bd18c7bed6ea5c6097b82de8c12 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Fri, 10 Jan 2025 13:58:21 +0000 Subject: [PATCH 13/39] +1988 --- .../Azys Lla/1988_A Crude Facsimile.json | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json new file mode 100644 index 00000000..0b418399 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json @@ -0,0 +1,104 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012294, + "Position": { + "X": 366.4148, + "Y": 20.214104, + "Z": 756.7101 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": 502.06363, + "Y": 16.87959, + "Z": 742.68134 + }, + "TerritoryId": 402, + "InteractionType": "WalkTo", + "Fly": true, + "$": "can get stuck on the spire structure when trying to land" + }, + { + "DataId": 2005900, + "Position": { + "X": 506.76733, + "Y": 16.861145, + "Z": 750.24023 + }, + "TerritoryId": 402, + "InteractionType": "Interact" + }, + { + "DataId": 2005903, + "Position": { + "X": 544.64014, + "Y": 15.945618, + "Z": 760.61633 + }, + "TerritoryId": 402, + "InteractionType": "Interact" + }, + { + "DataId": 2005899, + "Position": { + "X": 545.4031, + "Y": 20.2182, + "Z": 802.8534 + }, + "TerritoryId": 402, + "InteractionType": "Interact" + }, + { + "DataId": 2005902, + "Position": { + "X": 614.6791, + "Y": 20.2182, + "Z": 758.938 + }, + "TerritoryId": 402, + "InteractionType": "Interact" + }, + { + "DataId": 2005901, + "Position": { + "X": 605.3406, + "Y": 15.945618, + "Z": 708.06433 + }, + "TerritoryId": 402, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012294, + "Position": { + "X": 366.4148, + "Y": 20.214104, + "Z": 756.7101 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From 250cb44f484af417e61ce43430726a802e9b4d33 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Fri, 10 Jan 2025 14:30:20 +0000 Subject: [PATCH 14/39] +1989 --- .../Azys Lla/1988_A Crude Facsimile.json | 2 +- .../Side Quests/Azys Lla/1989_Recycling.json | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1989_Recycling.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json index 0b418399..969da2d8 100644 --- a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json @@ -30,7 +30,7 @@ "TerritoryId": 402, "InteractionType": "WalkTo", "Fly": true, - "$": "can get stuck on the spire structure when trying to land" + "$": "can get stuck on the spire structure when trying to land. could land elsewhere but we want to start with this one because it's the first on foot, so if done before flying unlocked that would necessitate walking directly past it." }, { "DataId": 2005900, diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1989_Recycling.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1989_Recycling.json new file mode 100644 index 00000000..1541b26d --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1989_Recycling.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012295, + "Position": { + "X": 214.64856, + "Y": 13.75853, + "Z": 536.9801 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": 144.31177, + "Y": 5.9740877, + "Z": 387.8086 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 4630, + "MinimumKillCount": 3 + } + ], + "Fly": true + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012295, + "Position": { + "X": 214.64856, + "Y": 13.75853, + "Z": 536.9801 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From 7fe5acbaca396c0a4a8763b5a3e616d0b822e42a Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Fri, 10 Jan 2025 15:07:11 +0000 Subject: [PATCH 15/39] +1990 --- .../1990_Inadequate Safety Measures.json | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1990_Inadequate Safety Measures.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1990_Inadequate Safety Measures.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1990_Inadequate Safety Measures.json new file mode 100644 index 00000000..e9a8aff8 --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1990_Inadequate Safety Measures.json @@ -0,0 +1,85 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012296, + "Position": { + "X": -658.32, + "Y": -75.48534, + "Z": 699.1531 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": -345.30673, + "Y": -89.61499, + "Z": 353.53 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 4075, + "MinimumKillCount": 3 + } + ], + "CompletionQuestVariablesFlags": [ + { "Low": 3 }, + null, + null, + null, + null, + null + ], + "Fly": true + }, + { + "Position": { + "X": -553.4664, + "Y": -104.895905, + "Z": 175.68343 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 4668, + "MinimumKillCount": 3 + } + ], + "Fly": true + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012296, + "Position": { + "X": -658.32, + "Y": -75.48534, + "Z": 699.1531 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From ec813ce9f4ece949500d866e19d359864f2ed559 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Fri, 10 Jan 2025 15:20:27 +0000 Subject: [PATCH 16/39] +1991 --- .../1991_Environmental Unbalance.json | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1991_Environmental Unbalance.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1991_Environmental Unbalance.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1991_Environmental Unbalance.json new file mode 100644 index 00000000..701a787c --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1991_Environmental Unbalance.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012297, + "Position": { + "X": -554.95544, + "Y": -89.69182, + "Z": 771.87756 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": -679.16223, + "Y": -48.151093, + "Z": 542.7097 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "OverworldEnemies", + "ComplexCombatData": [ + { + "DataId": 4095, + "MinimumKillCount": 4 + } + ], + "Fly": true + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012297, + "Position": { + "X": -554.95544, + "Y": -89.69182, + "Z": 771.87756 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From 93e6b6ec02dff2bcd26c4aa2b18c73d6b0bcaff2 Mon Sep 17 00:00:00 2001 From: Stefan Belmont Date: Fri, 10 Jan 2025 15:42:38 +0000 Subject: [PATCH 17/39] +1992 --- .../1992_Elevated Aggression Levels.json | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1992_Elevated Aggression Levels.json diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1992_Elevated Aggression Levels.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1992_Elevated Aggression Levels.json new file mode 100644 index 00000000..e3a7106c --- /dev/null +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1992_Elevated Aggression Levels.json @@ -0,0 +1,94 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012298, + "Position": { + "X": -192.67572, + "Y": -102.749916, + "Z": 476.9817 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": -375.98807, + "Y": -106.10026, + "Z": 710.48956 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "AutoOnEnterArea", + "ComplexCombatData": [ + { + "DataId": 4493, + "MinimumKillCount": 1 + } + ], + "CompletionQuestVariablesFlags": [null, null, null, null, null, 128], + "Fly": true + }, + { + "Position": { + "X": -372.88766, + "Y": -105.78837, + "Z": 746.95245 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "AutoOnEnterArea", + "ComplexCombatData": [ + { + "DataId": 4493, + "MinimumKillCount": 1 + } + ], + "CompletionQuestVariablesFlags": [null, null, null, null, null, 64] + }, + { + "Position": { + "X": -321.94852, + "Y": -106.57244, + "Z": 716.5662 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "AutoOnEnterArea", + "ComplexCombatData": [ + { + "DataId": 4493, + "MinimumKillCount": 1 + } + ] + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012298, + "Position": { + "X": -192.67572, + "Y": -102.749916, + "Z": 476.9817 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] +} From 8200342f2fcfde6022090595acd2d2b23cda8ae6 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Fri, 10 Jan 2025 17:01:37 +0100 Subject: [PATCH 18/39] Update icon for journal --- .../Windows/QuestComponents/QuickAccessButtonsComponent.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Questionable/Windows/QuestComponents/QuickAccessButtonsComponent.cs b/Questionable/Windows/QuestComponents/QuickAccessButtonsComponent.cs index 6093686a..0239d09b 100644 --- a/Questionable/Windows/QuestComponents/QuickAccessButtonsComponent.cs +++ b/Questionable/Windows/QuestComponents/QuickAccessButtonsComponent.cs @@ -91,8 +91,10 @@ internal sealed class QuickAccessButtonsComponent Reload?.Invoke(this, EventArgs.Empty); ImGui.SameLine(); - if (ImGuiComponents.IconButton(FontAwesomeIcon.ChartColumn)) + if (ImGuiComponents.IconButton(FontAwesomeIcon.BookBookmark)) _journalProgressWindow.IsOpen = true; + if (ImGui.IsItemHovered()) + ImGui.SetTooltip("Journal Progress"); if (_questRegistry.ValidationIssueCount > 0) From 108d103fd872805dd81f2526716a45d5c7cd78a2 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sat, 11 Jan 2025 16:54:55 +0100 Subject: [PATCH 19/39] Add some extra flight steps to avoid vnav issues; fix bad NextQuestId --- .../1762_The Secret to Success.json | 5 ++-- .../1765_Intermediate Dragonslaying.json | 8 ++++--- .../1766_Advanced Dragonslaying.json | 12 ++++++---- .../1890_Personal Effects.json | 23 ++++++++++++++++--- .../1892_A Missing Tooth.json | 4 ++-- .../1893_A Noble Purpose.json | 5 ++-- .../Side Quests/Ishgard/1873_Enlisted.json | 17 +++++++++++++- 7 files changed, 57 insertions(+), 17 deletions(-) diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1762_The Secret to Success.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1762_The Secret to Success.json index 1c16e3f1..449db054 100644 --- a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1762_The Secret to Success.json +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1762_The Secret to Success.json @@ -117,9 +117,10 @@ "Z": 4.5318604 }, "TerritoryId": 397, - "InteractionType": "CompleteQuest" + "InteractionType": "CompleteQuest", + "NextQuestId": 1764 } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1765_Intermediate Dragonslaying.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1765_Intermediate Dragonslaying.json index ae7e2afe..4bea2439 100644 --- a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1765_Intermediate Dragonslaying.json +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1765_Intermediate Dragonslaying.json @@ -28,7 +28,8 @@ "Z": -244.1596 }, "TerritoryId": 397, - "InteractionType": "Interact" + "InteractionType": "Interact", + "Fly": true } ] }, @@ -89,9 +90,10 @@ }, "TerritoryId": 397, "InteractionType": "CompleteQuest", - "NextQuestId": 1766 + "NextQuestId": 1766, + "Fly": true } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1766_Advanced Dragonslaying.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1766_Advanced Dragonslaying.json index 4f9d54e2..aadaebf0 100644 --- a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1766_Advanced Dragonslaying.json +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1766_Advanced Dragonslaying.json @@ -28,7 +28,8 @@ "Z": -244.1596 }, "TerritoryId": 397, - "InteractionType": "Interact" + "InteractionType": "Interact", + "Fly": true } ] }, @@ -58,12 +59,14 @@ "Y": 100.08534, "Z": -603.926 }, + "StopDistance": 0.5, "TerritoryId": 397, "InteractionType": "Combat", "KillEnemyDataIds": [ 4468 ], - "EnemySpawnType": "AutoOnEnterArea" + "EnemySpawnType": "AutoOnEnterArea", + "Fly": true } ] }, @@ -78,7 +81,8 @@ "Z": -503.7156 }, "TerritoryId": 397, - "InteractionType": "Interact" + "InteractionType": "Interact", + "Fly": true } ] }, @@ -100,4 +104,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1890_Personal Effects.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1890_Personal Effects.json index bddb0605..68341985 100644 --- a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1890_Personal Effects.json +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1890_Personal Effects.json @@ -34,7 +34,8 @@ "DataId": 3992, "MinimumKillCount": 5 } - ] + ], + "Fly": true } ] }, @@ -50,13 +51,29 @@ "Z": 791.37854 }, "TerritoryId": 397, - "InteractionType": "Interact" + "InteractionType": "Interact", + "AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest" } ] }, { "Sequence": 255, "Steps": [ + { + "Position": { + "X": -110.26132, + "Y": 153.61101, + "Z": 10.394781 + }, + "TerritoryId": 397, + "InteractionType": "WalkTo", + "Fly": true, + "SkipConditions": { + "StepIf": { + "Flying": "Locked" + } + } + }, { "Fly": true, "DataId": 1014146, @@ -72,4 +89,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1892_A Missing Tooth.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1892_A Missing Tooth.json index 657fd96f..d0ee8c1c 100644 --- a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1892_A Missing Tooth.json +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1892_A Missing Tooth.json @@ -75,9 +75,9 @@ }, "TerritoryId": 397, "InteractionType": "CompleteQuest", - "NextQuestId": 1983 + "NextQuestId": 1893 } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1893_A Noble Purpose.json b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1893_A Noble Purpose.json index 7a5a5c64..c5a003fc 100644 --- a/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1893_A Noble Purpose.json +++ b/QuestPaths/3.x - Heavensward/Side Quests/Coerthas Western Highlands/1893_A Noble Purpose.json @@ -104,9 +104,10 @@ "Z": 3.829956 }, "TerritoryId": 397, - "InteractionType": "CompleteQuest" + "InteractionType": "CompleteQuest", + "NextQuestId": 1898 } ] } ] -} \ No newline at end of file +} diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1873_Enlisted.json b/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1873_Enlisted.json index ef0a9cbd..c603466d 100644 --- a/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1873_Enlisted.json +++ b/QuestPaths/3.x - Heavensward/Side Quests/Ishgard/1873_Enlisted.json @@ -36,6 +36,21 @@ { "Sequence": 255, "Steps": [ + { + "Position": { + "X": -110.26132, + "Y": 153.61101, + "Z": 10.394781 + }, + "TerritoryId": 397, + "InteractionType": "WalkTo", + "Fly": true, + "SkipConditions": { + "StepIf": { + "Flying": "Locked" + } + } + }, { "DataId": 1014719, "Position": { @@ -50,4 +65,4 @@ ] } ] -} \ No newline at end of file +} From ad76ccf05798cb6d6a3771e42aeb34103b23d614 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sat, 11 Jan 2025 17:00:04 +0100 Subject: [PATCH 20/39] =?UTF-8?q?Make=20'CompleteQuest'=20work=20with=20It?= =?UTF-8?q?emId=20=E2=86=92=20UseItem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Questionable/Controller/Steps/Interactions/UseItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Questionable/Controller/Steps/Interactions/UseItem.cs b/Questionable/Controller/Steps/Interactions/UseItem.cs index 118c204a..bf779a02 100644 --- a/Questionable/Controller/Steps/Interactions/UseItem.cs +++ b/Questionable/Controller/Steps/Interactions/UseItem.cs @@ -29,7 +29,7 @@ internal static class UseItem { public IEnumerable CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step) { - if (step.InteractionType is EInteractionType.SinglePlayerDuty) + if (step.InteractionType is EInteractionType.SinglePlayerDuty or EInteractionType.CompleteQuest) { if (step.ItemId == null) return []; From 97cbeada2a45e76b59fd4b7e770ffedc2c39b366 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sun, 12 Jan 2025 02:13:23 +0100 Subject: [PATCH 21/39] Minor Azys Lla adjustments --- .../Azys Lla/1988_A Crude Facsimile.json | 256 +++++++++++------- .../1992_Elevated Aggression Levels.json | 206 +++++++------- 2 files changed, 268 insertions(+), 194 deletions(-) diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json index 969da2d8..18eef643 100644 --- a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1988_A Crude Facsimile.json @@ -1,104 +1,156 @@ { - "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", - "Author": "goatzone", - "QuestSequence": [ - { - "Sequence": 0, - "Steps": [ - { - "DataId": 1012294, - "Position": { - "X": 366.4148, - "Y": 20.214104, - "Z": 756.7101 - }, - "TerritoryId": 402, - "InteractionType": "AcceptQuest", - "Fly": true - } - ] - }, - { - "Sequence": 1, - "Steps": [ - { - "Position": { - "X": 502.06363, - "Y": 16.87959, - "Z": 742.68134 - }, - "TerritoryId": 402, - "InteractionType": "WalkTo", - "Fly": true, - "$": "can get stuck on the spire structure when trying to land. could land elsewhere but we want to start with this one because it's the first on foot, so if done before flying unlocked that would necessitate walking directly past it." - }, - { - "DataId": 2005900, - "Position": { - "X": 506.76733, - "Y": 16.861145, - "Z": 750.24023 - }, - "TerritoryId": 402, - "InteractionType": "Interact" - }, - { - "DataId": 2005903, - "Position": { - "X": 544.64014, - "Y": 15.945618, - "Z": 760.61633 - }, - "TerritoryId": 402, - "InteractionType": "Interact" - }, - { - "DataId": 2005899, - "Position": { - "X": 545.4031, - "Y": 20.2182, - "Z": 802.8534 - }, - "TerritoryId": 402, - "InteractionType": "Interact" - }, - { - "DataId": 2005902, - "Position": { - "X": 614.6791, - "Y": 20.2182, - "Z": 758.938 - }, - "TerritoryId": 402, - "InteractionType": "Interact" - }, - { - "DataId": 2005901, - "Position": { - "X": 605.3406, - "Y": 15.945618, - "Z": 708.06433 - }, - "TerritoryId": 402, - "InteractionType": "Interact" - } - ] - }, - { - "Sequence": 255, - "Steps": [ - { - "DataId": 1012294, - "Position": { - "X": 366.4148, - "Y": 20.214104, - "Z": 756.7101 - }, - "TerritoryId": 402, - "InteractionType": "CompleteQuest", - "Fly": true - } - ] - } - ] + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012294, + "Position": { + "X": 366.4148, + "Y": 20.214104, + "Z": 756.7101 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": 505.4667, + "Y": 16.87959, + "Z": 751.14856 + }, + "TerritoryId": 402, + "InteractionType": "WalkTo", + "Fly": true, + "$": "can get stuck on the spire structure when trying to land. could land elsewhere but we want to start with this one because it's the first on foot, so if done before flying unlocked that would necessitate walking directly past it.", + "SkipConditions": { + "StepIf": { + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 64 + ] + } + } + }, + { + "DataId": 2005900, + "Position": { + "X": 506.76733, + "Y": 16.861145, + "Z": 750.24023 + }, + "TerritoryId": 402, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 64 + ] + }, + { + "DataId": 2005903, + "Position": { + "X": 544.64014, + "Y": 15.945618, + "Z": 760.61633 + }, + "TerritoryId": 402, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 8 + ] + }, + { + "DataId": 2005899, + "Position": { + "X": 545.4031, + "Y": 20.2182, + "Z": 802.8534 + }, + "TerritoryId": 402, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 128 + ] + }, + { + "DataId": 2005902, + "Position": { + "X": 614.6791, + "Y": 20.2182, + "Z": 758.938 + }, + "TerritoryId": 402, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 16 + ] + }, + { + "DataId": 2005901, + "Position": { + "X": 605.3406, + "Y": 15.945618, + "Z": 708.06433 + }, + "TerritoryId": 402, + "InteractionType": "Interact", + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 32 + ] + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012294, + "Position": { + "X": 366.4148, + "Y": 20.214104, + "Z": 756.7101 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] } diff --git a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1992_Elevated Aggression Levels.json b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1992_Elevated Aggression Levels.json index e3a7106c..b41f31b3 100644 --- a/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1992_Elevated Aggression Levels.json +++ b/QuestPaths/3.x - Heavensward/Side Quests/Azys Lla/1992_Elevated Aggression Levels.json @@ -1,94 +1,116 @@ { - "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", - "Author": "goatzone", - "QuestSequence": [ - { - "Sequence": 0, - "Steps": [ - { - "DataId": 1012298, - "Position": { - "X": -192.67572, - "Y": -102.749916, - "Z": 476.9817 - }, - "TerritoryId": 402, - "InteractionType": "AcceptQuest", - "Fly": true - } - ] - }, - { - "Sequence": 1, - "Steps": [ - { - "Position": { - "X": -375.98807, - "Y": -106.10026, - "Z": 710.48956 - }, - "TerritoryId": 402, - "InteractionType": "Combat", - "EnemySpawnType": "AutoOnEnterArea", - "ComplexCombatData": [ - { - "DataId": 4493, - "MinimumKillCount": 1 - } - ], - "CompletionQuestVariablesFlags": [null, null, null, null, null, 128], - "Fly": true - }, - { - "Position": { - "X": -372.88766, - "Y": -105.78837, - "Z": 746.95245 - }, - "TerritoryId": 402, - "InteractionType": "Combat", - "EnemySpawnType": "AutoOnEnterArea", - "ComplexCombatData": [ - { - "DataId": 4493, - "MinimumKillCount": 1 - } - ], - "CompletionQuestVariablesFlags": [null, null, null, null, null, 64] - }, - { - "Position": { - "X": -321.94852, - "Y": -106.57244, - "Z": 716.5662 - }, - "TerritoryId": 402, - "InteractionType": "Combat", - "EnemySpawnType": "AutoOnEnterArea", - "ComplexCombatData": [ - { - "DataId": 4493, - "MinimumKillCount": 1 - } - ] - } - ] - }, - { - "Sequence": 255, - "Steps": [ - { - "DataId": 1012298, - "Position": { - "X": -192.67572, - "Y": -102.749916, - "Z": 476.9817 - }, - "TerritoryId": 402, - "InteractionType": "CompleteQuest", - "Fly": true - } - ] - } - ] + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "goatzone", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1012298, + "Position": { + "X": -192.67572, + "Y": -102.749916, + "Z": 476.9817 + }, + "TerritoryId": 402, + "InteractionType": "AcceptQuest", + "Fly": true + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "Position": { + "X": -375.98807, + "Y": -106.10026, + "Z": 710.48956 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "AutoOnEnterArea", + "ComplexCombatData": [ + { + "DataId": 4493, + "MinimumKillCount": 1 + } + ], + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 128 + ], + "Fly": true + }, + { + "Position": { + "X": -372.88766, + "Y": -105.78837, + "Z": 746.95245 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "AutoOnEnterArea", + "ComplexCombatData": [ + { + "DataId": 4493, + "MinimumKillCount": 1 + } + ], + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 64 + ] + }, + { + "Position": { + "X": -321.94852, + "Y": -106.57244, + "Z": 716.5662 + }, + "TerritoryId": 402, + "InteractionType": "Combat", + "EnemySpawnType": "AutoOnEnterArea", + "ComplexCombatData": [ + { + "DataId": 4493, + "MinimumKillCount": 1 + } + ], + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 32 + ] + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1012298, + "Position": { + "X": -192.67572, + "Y": -102.749916, + "Z": 476.9817 + }, + "TerritoryId": 402, + "InteractionType": "CompleteQuest", + "Fly": true + } + ] + } + ] } From a111a4f75b8a8bf6687da465dba5763e00a895e0 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sun, 12 Jan 2025 02:28:31 +0100 Subject: [PATCH 22/39] Optimize combat for overworld enemies --- Questionable/Controller/CombatController.cs | 88 +++++++++++++++++-- Questionable/Controller/MiniTaskController.cs | 2 +- .../Controller/Steps/Interactions/Combat.cs | 23 +++-- 3 files changed, 102 insertions(+), 11 deletions(-) diff --git a/Questionable/Controller/CombatController.cs b/Questionable/Controller/CombatController.cs index f44c4934..73fe17df 100644 --- a/Questionable/Controller/CombatController.cs +++ b/Questionable/Controller/CombatController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Numerics; using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects.Enums; @@ -10,7 +11,8 @@ using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Game.UI; -using FFXIVClientStructs.FFXIV.Common.Math; +using FFXIVClientStructs.FFXIV.Client.System.Framework; +using FFXIVClientStructs.FFXIV.Common.Component.BGCollision; using Microsoft.Extensions.Logging; using Questionable.Controller.CombatModules; using Questionable.Controller.Steps; @@ -38,6 +40,7 @@ internal sealed class CombatController : IDisposable private CurrentFight? _currentFight; private bool _wasInCombat; private ulong? _lastTargetId; + private List? _previousQuestVariables; public CombatController( IEnumerable combatModules, @@ -79,7 +82,9 @@ internal sealed class CombatController : IDisposable Data = combatData, LastDistanceCheck = DateTime.Now, }; - _wasInCombat = combatData.SpawnType is EEnemySpawnType.QuestInterruption or EEnemySpawnType.FinishCombatIfAny; + _wasInCombat = + combatData.SpawnType is EEnemySpawnType.QuestInterruption or EEnemySpawnType.FinishCombatIfAny; + UpdateLastTargetAndQuestVariables(null); return true; } else @@ -115,7 +120,31 @@ internal sealed class CombatController : IDisposable { // wait until the game cleans up the target if (lastTarget.IsDead) - return EStatus.InCombat; + { + ElementId? elementId = _currentFight.Data.ElementId; + QuestProgressInfo? questProgressInfo = elementId != null + ? _questFunctions.GetQuestProgressInfo(elementId) + : null; + + if (questProgressInfo != null && + questProgressInfo.Sequence == _currentFight.Data.Sequence && + QuestWorkUtils.HasCompletionFlags(_currentFight.Data.CompletionQuestVariablesFlags) && + QuestWorkUtils.MatchesQuestWork(_currentFight.Data.CompletionQuestVariablesFlags, + questProgressInfo)) + { + // would be the final enemy of the bunch + return EStatus.InCombat; + } + else if (questProgressInfo != null && + questProgressInfo.Sequence == _currentFight.Data.Sequence && + _previousQuestVariables != null && + !questProgressInfo.Variables.SequenceEqual(_previousQuestVariables)) + { + UpdateLastTargetAndQuestVariables(null); + } + else + return EStatus.InCombat; + } } else _lastTargetId = null; @@ -372,9 +401,18 @@ internal sealed class CombatController : IDisposable float hitboxOffset = player.HitboxRadius + gameObject.HitboxRadius; float actualDistance = Vector3.Distance(player.Position, gameObject.Position); float maxDistance = player.ClassJob.ValueNullable?.Role is 3 or 4 ? 20f : 2.9f; - if (actualDistance - hitboxOffset >= maxDistance) + bool outOfRange = actualDistance - hitboxOffset >= maxDistance; + bool isInLineOfSight = IsInLineOfSight(gameObject); + if (outOfRange || !isInLineOfSight) { - if (actualDistance - hitboxOffset <= 5) + bool useNavmesh = actualDistance - hitboxOffset > 5f; + if (!outOfRange && !isInLineOfSight) + { + maxDistance = Math.Min(maxDistance, actualDistance) / 2; + useNavmesh = true; + } + + if (!useNavmesh) { _logger.LogInformation("Moving to {TargetName} ({DataId}) to attack", gameObject.Name, gameObject.DataId); @@ -391,6 +429,44 @@ internal sealed class CombatController : IDisposable } } + internal unsafe bool IsInLineOfSight(IGameObject target) + { + Vector3 sourcePos = _clientState.LocalPlayer!.Position; + sourcePos.Y += 2; + + Vector3 targetPos = target.Position; + targetPos.Y += 2; + + Vector3 direction = targetPos - sourcePos; + float distance = direction.Length(); + + direction = Vector3.Normalize(direction); + + Vector3 originVect = new Vector3(sourcePos.X, sourcePos.Y, sourcePos.Z); + Vector3 directionVect = new Vector3(direction.X, direction.Y, direction.Z); + + RaycastHit hit; + var flags = stackalloc int[] { 0x4000, 0, 0x4000, 0 }; + var isLoSBlocked = + Framework.Instance()->BGCollisionModule->RaycastMaterialFilter(&hit, &originVect, &directionVect, distance, + 1, flags); + + return isLoSBlocked == false; + } + + private void UpdateLastTargetAndQuestVariables(IGameObject? target) + { + _lastTargetId = target?.GameObjectId; + _previousQuestVariables = _currentFight!.Data.ElementId != null + ? _questFunctions.GetQuestProgressInfo(_currentFight.Data.ElementId)?.Variables + : null; + /* + _logger.LogTrace("UpdateTargetData: {TargetId}; {QuestVariables}", + target?.GameObjectId.ToString("X8", CultureInfo.InvariantCulture) ?? "null", + _previousQuestVariables != null ? string.Join(", ", _previousQuestVariables) : "null"); + */ + } + public void Stop(string label) { using var scope = _logger.BeginScope(label); @@ -422,6 +498,8 @@ internal sealed class CombatController : IDisposable public sealed class CombatData { public required ElementId? ElementId { get; init; } + public required int Sequence { get; init; } + public required IList CompletionQuestVariablesFlags { 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/MiniTaskController.cs b/Questionable/Controller/MiniTaskController.cs index 06e5d874..6055a68c 100644 --- a/Questionable/Controller/MiniTaskController.cs +++ b/Questionable/Controller/MiniTaskController.cs @@ -173,7 +173,7 @@ internal abstract class MiniTaskController if (_condition[ConditionFlag.Mounted]) tasks.Add(new Mount.UnmountTask()); - tasks.Add(Combat.Factory.CreateTask(null, false, EEnemySpawnType.QuestInterruption, [], [], [], null)); + tasks.Add(Combat.Factory.CreateTask(null, -1, false, EEnemySpawnType.QuestInterruption, [], [], [], null)); tasks.Add(new WaitAtEnd.WaitDelay()); _taskQueue.InterruptWith(tasks); } diff --git a/Questionable/Controller/Steps/Interactions/Combat.cs b/Questionable/Controller/Steps/Interactions/Combat.cs index a4d9594d..463c32ce 100644 --- a/Questionable/Controller/Steps/Interactions/Combat.cs +++ b/Questionable/Controller/Steps/Interactions/Combat.cs @@ -102,17 +102,30 @@ internal static class Combat ArgumentNullException.ThrowIfNull(step.EnemySpawnType); bool isLastStep = sequence.Steps.Last() == step; - return CreateTask(quest.Id, isLastStep, step.EnemySpawnType.Value, step.KillEnemyDataIds, - step.CompletionQuestVariablesFlags, step.ComplexCombatData, step.CombatItemUse); + return CreateTask(quest.Id, + sequence.Sequence, + isLastStep, + step.EnemySpawnType.Value, + step.KillEnemyDataIds, + step.CompletionQuestVariablesFlags, + step.ComplexCombatData, + step.CombatItemUse); } - internal static Task CreateTask(ElementId? elementId, bool isLastStep, EEnemySpawnType enemySpawnType, - IList killEnemyDataIds, IList completionQuestVariablesFlags, - IList complexCombatData, CombatItemUse? combatItemUse) + internal static Task CreateTask(ElementId? elementId, + int sequence, + bool isLastStep, + EEnemySpawnType enemySpawnType, + IList killEnemyDataIds, + IList completionQuestVariablesFlags, + IList complexCombatData, + CombatItemUse? combatItemUse) { return new Task(new CombatController.CombatData { ElementId = elementId, + Sequence = sequence, + CompletionQuestVariablesFlags = completionQuestVariablesFlags, SpawnType = enemySpawnType, KillEnemyDataIds = killEnemyDataIds.ToList(), ComplexCombatDatas = complexCombatData.ToList(), From 2ffedfa72c8802421f32eae23d72944ce34abd5a Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sun, 12 Jan 2025 02:36:17 +0100 Subject: [PATCH 23/39] Specify loop count for AD --- Questionable/External/AutoDutyIpc.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Questionable/External/AutoDutyIpc.cs b/Questionable/External/AutoDutyIpc.cs index 71bae7fd..9d049062 100644 --- a/Questionable/External/AutoDutyIpc.cs +++ b/Questionable/External/AutoDutyIpc.cs @@ -67,7 +67,7 @@ internal sealed class AutoDutyIpc try { - _run.InvokeAction(cfcData.TerritoryId, 0, true); + _run.InvokeAction(cfcData.TerritoryId, 1, true); } catch (IpcError e) { From 76e8ac499573dc733f30e1d7a3d339d1bacb4565 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sun, 12 Jan 2025 02:40:09 +0100 Subject: [PATCH 24/39] Set minimum StopDistance to navmesh step size (0.25) --- .../Black Shroud/Gridania/970_Some Seedy Business.json | 2 +- QuestPaths/quest-v1.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/QuestPaths/2.x - A Realm Reborn/Side Quests/Black Shroud/Gridania/970_Some Seedy Business.json b/QuestPaths/2.x - A Realm Reborn/Side Quests/Black Shroud/Gridania/970_Some Seedy Business.json index 84536780..b5038e3b 100644 --- a/QuestPaths/2.x - A Realm Reborn/Side Quests/Black Shroud/Gridania/970_Some Seedy Business.json +++ b/QuestPaths/2.x - A Realm Reborn/Side Quests/Black Shroud/Gridania/970_Some Seedy Business.json @@ -57,7 +57,7 @@ }, "TerritoryId": 152, "InteractionType": "Interact", - "StopDistance": 0.1, + "StopDistance": 0.25, "AetheryteShortcut": "East Shroud - Hawthorne Hut", "Fly": true, "SkipConditions": { diff --git a/QuestPaths/quest-v1.json b/QuestPaths/quest-v1.json index d04fd82c..99105c93 100644 --- a/QuestPaths/quest-v1.json +++ b/QuestPaths/quest-v1.json @@ -80,7 +80,7 @@ "null" ], "description": "Set if pathfinding should stop closer or further away from the default stop distance", - "exclusiveMinimum": 0 + "minimum": 0.25 }, "IgnoreDistanceToObject": { "type": "boolean", From 10b8c1ddc2c4b5ace2efd6e27bd7099dcd43d96e Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sun, 12 Jan 2025 11:35:46 +0100 Subject: [PATCH 25/39] Set minimum StopDistance to navmesh step size (0.25) --- .../Black Shroud/Gridania/970_Some Seedy Business.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/QuestPaths/2.x - A Realm Reborn/Side Quests/Black Shroud/Gridania/970_Some Seedy Business.json b/QuestPaths/2.x - A Realm Reborn/Side Quests/Black Shroud/Gridania/970_Some Seedy Business.json index b5038e3b..03953144 100644 --- a/QuestPaths/2.x - A Realm Reborn/Side Quests/Black Shroud/Gridania/970_Some Seedy Business.json +++ b/QuestPaths/2.x - A Realm Reborn/Side Quests/Black Shroud/Gridania/970_Some Seedy Business.json @@ -83,7 +83,7 @@ }, "TerritoryId": 152, "InteractionType": "Interact", - "StopDistance": 0.1, + "StopDistance": 0.25, "AetheryteShortcut": "East Shroud - Hawthorne Hut", "Fly": true, "SkipConditions": { @@ -109,7 +109,7 @@ }, "TerritoryId": 152, "InteractionType": "Interact", - "StopDistance": 0.1, + "StopDistance": 0.25, "AetheryteShortcut": "East Shroud - Hawthorne Hut", "Fly": true, "SkipConditions": { From a2a36c51564120c58fe299c1a1fcebd2acb23079 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sun, 12 Jan 2025 17:59:10 +0100 Subject: [PATCH 26/39] Version bump --- Directory.Build.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index 58a5fad2..c0b49f3b 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,5 +1,5 @@ - 4.13 + 4.14 From 16b62316c59ceea19d22444a46a89fe1bac760df Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Mon, 13 Jan 2025 18:38:53 +0100 Subject: [PATCH 27/39] Leave TextAdvance active if waiting for a new quest sequence from the server --- Questionable/External/TextAdvanceIpc.cs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Questionable/External/TextAdvanceIpc.cs b/Questionable/External/TextAdvanceIpc.cs index dd4fa395..f840cc18 100644 --- a/Questionable/External/TextAdvanceIpc.cs +++ b/Questionable/External/TextAdvanceIpc.cs @@ -22,13 +22,16 @@ internal sealed class TextAdvanceIpc : IDisposable private readonly string _pluginName; private readonly ExternalTerritoryConfig _externalTerritoryConfig = new(); - public TextAdvanceIpc(IDalamudPluginInterface pluginInterface, IFramework framework, QuestController questController, Configuration configuration) + public TextAdvanceIpc(IDalamudPluginInterface pluginInterface, IFramework framework, + QuestController questController, Configuration configuration) { _framework = framework; _questController = questController; _configuration = configuration; _isInExternalControl = pluginInterface.GetIpcSubscriber("TextAdvance.IsInExternalControl"); - _enableExternalControl = pluginInterface.GetIpcSubscriber("TextAdvance.EnableExternalControl"); + _enableExternalControl = + pluginInterface.GetIpcSubscriber( + "TextAdvance.EnableExternalControl"); _disableExternalControl = pluginInterface.GetIpcSubscriber("TextAdvance.DisableExternalControl"); _pluginName = pluginInterface.InternalName; _framework.Update += OnUpdate; @@ -37,7 +40,7 @@ internal sealed class TextAdvanceIpc : IDisposable public void Dispose() { _framework.Update -= OnUpdate; - if(_isExternalControlActivated) + if (_isExternalControlActivated) { _disableExternalControl.InvokeFunc(_pluginName); } @@ -45,11 +48,13 @@ internal sealed class TextAdvanceIpc : IDisposable private void OnUpdate(IFramework framework) { - if(_configuration.General.ConfigureTextAdvance && _questController.IsRunning) + bool hasActiveQuest = _questController.IsRunning || + _questController.AutomationType != QuestController.EAutomationType.Manual; + if (_configuration.General.ConfigureTextAdvance && hasActiveQuest) { - if(!_isInExternalControl.InvokeFunc()) + if (!_isInExternalControl.InvokeFunc()) { - if(_enableExternalControl.InvokeFunc(_pluginName, _externalTerritoryConfig)) + if (_enableExternalControl.InvokeFunc(_pluginName, _externalTerritoryConfig)) { _isExternalControlActivated = true; } @@ -57,9 +62,9 @@ internal sealed class TextAdvanceIpc : IDisposable } else { - if(_isExternalControlActivated) + if (_isExternalControlActivated) { - if(_disableExternalControl.InvokeFunc(_pluginName) || !_isInExternalControl.InvokeFunc()) + if (_disableExternalControl.InvokeFunc(_pluginName) || !_isInExternalControl.InvokeFunc()) { _isExternalControlActivated = false; } From 7734692b0fbe61f32a5ca5ec1d0b4abf5a8441c2 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Thu, 16 Jan 2025 22:55:22 +0100 Subject: [PATCH 28/39] Throw an exception if using aethernet doesn't work and the destination is in another territory --- Questionable/Controller/Steps/Shared/AethernetShortcut.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Questionable/Controller/Steps/Shared/AethernetShortcut.cs b/Questionable/Controller/Steps/Shared/AethernetShortcut.cs index bfb2cc3f..e63b69c0 100644 --- a/Questionable/Controller/Steps/Shared/AethernetShortcut.cs +++ b/Questionable/Controller/Steps/Shared/AethernetShortcut.cs @@ -179,10 +179,12 @@ internal static class AethernetShortcut } } } - else + else if (clientState.TerritoryType == aetheryteData.TerritoryIds[Task.To]) logger.LogWarning( - "Aethernet shortcut not unlocked (from: {FromAetheryte}, to: {ToAetheryte}), walking manually", + "Aethernet shortcut not unlocked (from: {FromAetheryte}, to: {ToAetheryte}), skipping as we are already in the destination territory", Task.From, Task.To); + else + throw new TaskException($"Aethernet shortcut not unlocked (from: {Task.From}, to: {Task.To})"); return false; } From b2d57ae5a74038f3c342aeaf1f2e5ffdf4628d47 Mon Sep 17 00:00:00 2001 From: pot0to <19513249+pot0to@users.noreply.github.com> Date: Fri, 17 Jan 2025 23:48:03 -0800 Subject: [PATCH 29/39] adding new qitari quest --- .../Dailies/3833_Qhoterl's Chronicles.json | 61 ++++++++++++++----- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/QuestPaths/5.x - Shadowbringers/Allied Societies/Qitari/Dailies/3833_Qhoterl's Chronicles.json b/QuestPaths/5.x - Shadowbringers/Allied Societies/Qitari/Dailies/3833_Qhoterl's Chronicles.json index bdbb1696..864bef9b 100644 --- a/QuestPaths/5.x - Shadowbringers/Allied Societies/Qitari/Dailies/3833_Qhoterl's Chronicles.json +++ b/QuestPaths/5.x - Shadowbringers/Allied Societies/Qitari/Dailies/3833_Qhoterl's Chronicles.json @@ -1,7 +1,6 @@ -{ +{ "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", - "Author": "liza", - "Disabled": true, + "Author": "pot0to", "QuestSequence": [ { "Sequence": 0, @@ -9,9 +8,9 @@ { "DataId": 1032643, "Position": { - "X": 787.0145, - "Y": -45.82774, - "Z": -218.555 + "X": 787.0145, + "Y": -45.82774, + "Z": -218.555 }, "TerritoryId": 817, "InteractionType": "AcceptQuest" @@ -22,26 +21,56 @@ "Sequence": 255, "Steps": [ { + "DataId": 33005, "Position": { - "X": 788.1569, - "Y": -45.82557, - "Z": -212.9306 + "X": 214.7744, + "Y": -19.57758, + "Z": 623.6767 }, "TerritoryId": 817, - "InteractionType": "WalkTo", - "AetheryteShortcut": "Rak'tika - Fanow", + "InteractionType": "Gather", + "RequiredQuestAcceptedJob": [ + "Miner" + ], + "ItemsToGather": [ + { + "ItemId": 29537, + "ItemCount": 3 + } + ], + "Fly": true + }, + { + "DataId": 33020, + "Position": { + "X": 226.1767, + "Y": -20.10281, + "Z": 643.5543 + }, + "TerritoryId": 817, + "InteractionType": "Gather", + "RequiredQuestAcceptedJob": [ + "Botanist" + ], + "ItemsToGather": [ + { + "ItemId": 29563, + "ItemCount": 3 + } + ], "Fly": true }, { "DataId": 1032643, "Position": { - "X": 787.0145, - "Y": -45.82774, - "Z": -218.555 + "X": 787.0145, + "Y": -45.82774, + "Z": -218.555 }, - "StopDistance": 7, "TerritoryId": 817, - "InteractionType": "CompleteQuest" + "InteractionType": "CompleteQuest", + "AetheryteShortcut": "Rak'tika - Fanow", + "Fly": true } ] } From 4b9eae916a295781adea3db2a66c4dca0c6816ae Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sun, 19 Jan 2025 22:58:14 +0100 Subject: [PATCH 30/39] Add logic for using items on the Spotted Mudpuppy in 'Factual Folklore' --- .../927_Factual Folklore.json | 9 ++++++--- QuestPaths/quest-v1.json | 9 ++++++--- .../Converter/CombatItemUseConditionConverter.cs | 1 + Questionable.Model/Questing/ECombatItemUseCondition.cs | 1 + Questionable/Controller/CombatModules/ItemUseModule.cs | 4 ++++ 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B9-Coerthas Central Highlands, Whitebrim Front/927_Factual Folklore.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B9-Coerthas Central Highlands, Whitebrim Front/927_Factual Folklore.json index b9550d58..924c6a9d 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B9-Coerthas Central Highlands, Whitebrim Front/927_Factual Folklore.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B9-Coerthas Central Highlands, Whitebrim Front/927_Factual Folklore.json @@ -35,10 +35,13 @@ "Z": 89.58569 }, "TerritoryId": 155, - "InteractionType": "Instruction", - "Comment": "Use Quest item on enemy to weaken it first", - "$": "Status Effects: 22 (HP Penalty) + 62 (Damage Down)", + "InteractionType": "Combat", "EnemySpawnType": "AfterInteraction", + "CombatItemUse": { + "ItemId": 2000961, + "Condition": "MissingStatus", + "Value": 22 + }, "ComplexCombatData": [ { "DataId": 2196 diff --git a/QuestPaths/quest-v1.json b/QuestPaths/quest-v1.json index 99105c93..f0f82637 100644 --- a/QuestPaths/quest-v1.json +++ b/QuestPaths/quest-v1.json @@ -183,7 +183,8 @@ "null" ], "description": "The Item to use", - "exclusiveMinimum": 0 + "exclusiveMinimum": 0, + "maximum": 2010000 }, "SkipConditions": { "type": "object", @@ -648,13 +649,15 @@ "type": "object", "properties": { "ItemId": { - "type": "integer" + "type": "integer", + "maximum": 2010000 }, "Condition": { "type": "string", "enum": [ "Incapacitated", - "Health%" + "Health%", + "MissingStatus" ] }, "Value": { diff --git a/Questionable.Model/Questing/Converter/CombatItemUseConditionConverter.cs b/Questionable.Model/Questing/Converter/CombatItemUseConditionConverter.cs index 1b4086ff..deadc4f6 100644 --- a/Questionable.Model/Questing/Converter/CombatItemUseConditionConverter.cs +++ b/Questionable.Model/Questing/Converter/CombatItemUseConditionConverter.cs @@ -9,5 +9,6 @@ public sealed class CombatItemUseConditionConverter() : EnumConverterUseItem(_combatData.CombatItemUse.ItemId); } _continueAt = DateTime.Now.AddSeconds(2); @@ -147,6 +148,9 @@ internal sealed class ItemUseModule : ICombatModule if (_combatData.CombatItemUse.Condition == ECombatItemUseCondition.HealthPercent) return (100f * battleChara->Health / battleChara->MaxHealth) < _combatData.CombatItemUse.Value; + + if (_combatData.CombatItemUse.Condition == ECombatItemUseCondition.MissingStatus) + return !battleChara->StatusManager.HasStatus((uint)_combatData.CombatItemUse.Value); } return false; From f12b777d12e900caaccc16dfbb69dfc58a44b3a0 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Tue, 21 Jan 2025 19:28:02 +0100 Subject: [PATCH 31/39] Update ARR Mor Dhona quests --- .../1001_Drowning Out the Voices.json | 24 +++++++++++++++++-- .../C6-Mor Dhona/1004_Fool Me Twice.json | 2 +- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1001_Drowning Out the Voices.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1001_Drowning Out the Voices.json index d1a4fdbf..1fcf9d81 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1001_Drowning Out the Voices.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1001_Drowning Out the Voices.json @@ -19,6 +19,7 @@ }, { "Sequence": 1, + "Comment": "'Invalid target' messages can just be bad positioning?", "Steps": [ { "Position": { @@ -52,7 +53,6 @@ "InteractionType": "Combat", "EnemySpawnType": "AfterItemUse", "ItemId": 2000766, - "GroundTarget": true, "KillEnemyDataIds": [ 46 ], @@ -86,6 +86,27 @@ 64 ] }, + { + "Position": { + "X": -219.34567, + "Y": 4.551038, + "Z": -637.8296 + }, + "TerritoryId": 156, + "InteractionType": "WalkTo", + "SkipConditions": { + "StepIf": { + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 8 + ] + } + } + }, { "DataId": 2002234, "Position": { @@ -161,7 +182,6 @@ "InteractionType": "Combat", "EnemySpawnType": "AfterItemUse", "ItemId": 2000766, - "GroundTarget": true, "KillEnemyDataIds": [ 46 ], diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1004_Fool Me Twice.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1004_Fool Me Twice.json index daaad896..0629a682 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1004_Fool Me Twice.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C6-Mor Dhona/1004_Fool Me Twice.json @@ -72,7 +72,7 @@ "Z": -609.4606 }, "TerritoryId": 156, - "InteractionType": "UseItem", + "InteractionType": "SinglePlayerDuty", "ItemId": 2000771 } ] From 3a763d625a31ef1781b914cdd649e41b2c2d629d Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Tue, 21 Jan 2025 19:32:28 +0100 Subject: [PATCH 32/39] New experimental interrupt handler --- .../Controller/GatheringController.cs | 3 +- Questionable/Controller/InterruptHandler.cs | 165 ++++++++++++++++++ Questionable/Controller/MiniTaskController.cs | 22 ++- Questionable/Controller/QuestController.cs | 17 +- Questionable/Controller/Steps/Common/Mount.cs | 4 + .../Controller/Steps/Common/NextQuest.cs | 2 + .../Steps/Common/SendNotification.cs | 2 + .../Steps/Common/WaitConditionTask.cs | 2 + .../Controller/Steps/Gathering/DoGather.cs | 2 + .../Steps/Gathering/DoGatherCollectable.cs | 2 + .../Steps/Gathering/MoveToLandingLocation.cs | 1 + .../Steps/Gathering/TurnInDelivery.cs | 3 + .../Controller/Steps/Interactions/Action.cs | 4 + .../Steps/Interactions/AetherCurrent.cs | 2 + .../Steps/Interactions/AethernetShard.cs | 2 + .../Steps/Interactions/Aetheryte.cs | 2 + .../Controller/Steps/Interactions/Combat.cs | 2 + .../Controller/Steps/Interactions/Dive.cs | 2 + .../Controller/Steps/Interactions/Duty.cs | 6 + .../Controller/Steps/Interactions/Emote.cs | 4 + .../Steps/Interactions/EquipItem.cs | 2 + .../Steps/Interactions/EquipRecommended.cs | 2 + .../Controller/Steps/Interactions/Interact.cs | 2 + .../Controller/Steps/Interactions/Jump.cs | 2 + .../Controller/Steps/Interactions/Say.cs | 2 + .../Steps/Interactions/StatusOff.cs | 2 + .../Controller/Steps/Interactions/UseItem.cs | 2 + .../Controller/Steps/Leves/InitiateLeve.cs | 8 + .../Steps/Shared/AethernetShortcut.cs | 2 + .../Steps/Shared/AetheryteShortcut.cs | 4 + Questionable/Controller/Steps/Shared/Craft.cs | 3 + .../Controller/Steps/Shared/Gather.cs | 7 + .../Controller/Steps/Shared/MoveTo.cs | 8 + .../Steps/Shared/RedeemRewardItems.cs | 2 + .../Controller/Steps/Shared/SkipCondition.cs | 2 + .../Controller/Steps/Shared/StepDisabled.cs | 2 + .../Controller/Steps/Shared/SwitchClassJob.cs | 3 + .../Controller/Steps/Shared/WaitAtEnd.cs | 16 ++ .../Controller/Steps/Shared/WaitAtStart.cs | 3 +- Questionable/Controller/Steps/TaskExecutor.cs | 4 + Questionable/QuestionablePlugin.cs | 1 + 41 files changed, 321 insertions(+), 7 deletions(-) create mode 100644 Questionable/Controller/InterruptHandler.cs diff --git a/Questionable/Controller/GatheringController.cs b/Questionable/Controller/GatheringController.cs index bbe6d2e4..28de31f9 100644 --- a/Questionable/Controller/GatheringController.cs +++ b/Questionable/Controller/GatheringController.cs @@ -49,9 +49,10 @@ internal sealed unsafe class GatheringController : MiniTaskController logger, ICondition condition, IServiceProvider serviceProvider, + InterruptHandler interruptHandler, IDataManager dataManager, IPluginLog pluginLog) - : base(chatGui, condition, serviceProvider, dataManager, logger) + : base(chatGui, condition, serviceProvider, interruptHandler, dataManager, logger) { _movementController = movementController; _gatheringPointRegistry = gatheringPointRegistry; diff --git a/Questionable/Controller/InterruptHandler.cs b/Questionable/Controller/InterruptHandler.cs new file mode 100644 index 00000000..9171432f --- /dev/null +++ b/Questionable/Controller/InterruptHandler.cs @@ -0,0 +1,165 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using Dalamud.Game; +using Dalamud.Hooking; +using Dalamud.Plugin.Services; +using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.Game.Character; +using FFXIVClientStructs.FFXIV.Common.Math; +using JetBrains.Annotations; +using Microsoft.Extensions.Logging; +using Questionable.Data; + +namespace Questionable.Controller; + +internal sealed unsafe class InterruptHandler : IDisposable +{ + private readonly Hook _processActionEffectHook; + private readonly IClientState _clientState; + private readonly TerritoryData _territoryData; + private readonly ILogger _logger; + + private delegate void ProcessActionEffect(uint sourceId, Character* sourceCharacter, Vector3* pos, + EffectHeader* effectHeader, EffectEntry* effectArray, ulong* effectTail); + + public InterruptHandler(IGameInteropProvider gameInteropProvider, IClientState clientState, + TerritoryData territoryData, ILogger logger) + { + _clientState = clientState; + _territoryData = territoryData; + _logger = logger; + _processActionEffectHook = + gameInteropProvider.HookFromSignature(Signatures.ActionEffect, + HandleProcessActionEffect); + _processActionEffectHook.Enable(); + } + + public event EventHandler? Interrupted; + + private void HandleProcessActionEffect(uint sourceId, Character* sourceCharacter, Vector3* pos, + EffectHeader* effectHeader, EffectEntry* effectArray, ulong* effectTail) + { + try + { + if (!_territoryData.IsDutyInstance(_clientState.TerritoryType)) + { + for (int i = 0; i < effectHeader->TargetCount; i++) + { + uint targetId = (uint)(effectTail[i] & uint.MaxValue); + EffectEntry* effect = effectArray + 8 * i; + + if (targetId == _clientState.LocalPlayer?.GameObjectId && + effect->Type is EActionEffectType.Damage or EActionEffectType.BlockedDamage + or EActionEffectType.ParriedDamage) + { + _logger.LogTrace("Damage action effect on self, from {SourceId} ({EffectType})", sourceId, + effect->Type); + Interrupted?.Invoke(this, EventArgs.Empty); + break; + } + } + } + } + catch (Exception e) + { + _logger.LogWarning(e, "Unable to process action effect"); + } + finally + { + _processActionEffectHook.Original(sourceId, sourceCharacter, pos, effectHeader, effectArray, effectTail); + } + } + + public void Dispose() + { + _processActionEffectHook.Disable(); + _processActionEffectHook.Dispose(); + } + + private static class Signatures + { + internal const string ActionEffect = "40 ?? 56 57 41 ?? 41 ?? 41 ?? 48 ?? ?? ?? ?? ?? ?? ?? 48"; + } + + [StructLayout(LayoutKind.Explicit)] + private struct EffectEntry + { + [FieldOffset(0)] public EActionEffectType Type; + [FieldOffset(1)] public byte Param0; + [FieldOffset(2)] public byte Param1; + [FieldOffset(3)] public byte Param2; + [FieldOffset(4)] public byte Mult; + [FieldOffset(5)] public byte Flags; + [FieldOffset(6)] public ushort Value; + + public byte AttackType => (byte)(Param1 & 0xF); + public uint Damage => Mult == 0 ? Value : Value + ((uint)ushort.MaxValue + 1) * Mult; + + public override string ToString() + { + return + $"Type: {Type}, p0: {Param0:D3}, p1: {Param1:D3}, p2: {Param2:D3} 0x{Param2:X2} '{Convert.ToString(Param2, 2).PadLeft(8, '0')}', mult: {Mult:D3}, flags: {Flags:D3} | {Convert.ToString(Flags, 2).PadLeft(8, '0')}, value: {Value:D6} ATTACK TYPE: {AttackType}"; + } + } + + [StructLayout(LayoutKind.Explicit)] + private struct EffectHeader + { + [FieldOffset(0)] public ulong AnimationTargetId; + [FieldOffset(8)] public uint ActionID; + [FieldOffset(12)] public uint GlobalEffectCounter; + [FieldOffset(16)] public float AnimationLockTime; + [FieldOffset(20)] public uint SomeTargetID; + [FieldOffset(24)] public ushort SourceSequence; + [FieldOffset(26)] public ushort Rotation; + [FieldOffset(28)] public ushort AnimationId; + [FieldOffset(30)] public byte Variation; + [FieldOffset(31)] public ActionType ActionType; + [FieldOffset(33)] public byte TargetCount; + } + + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + private enum EActionEffectType : byte + { + None = 0, + Miss = 1, + FullResist = 2, + Damage = 3, + Heal = 4, + BlockedDamage = 5, + ParriedDamage = 6, + Invulnerable = 7, + NoEffectText = 8, + Unknown0 = 9, + MpLoss = 10, + MpGain = 11, + TpLoss = 12, + TpGain = 13, + ApplyStatusEffectTarget = 14, + ApplyStatusEffectSource = 15, + RecoveredFromStatusEffect = 16, + LoseStatusEffectTarget = 17, + LoseStatusEffectSource = 18, + StatusNoEffect = 20, + ThreatPosition = 24, + EnmityAmountUp = 25, + EnmityAmountDown = 26, + StartActionCombo = 27, + ComboSucceed = 28, + Retaliation = 29, + Knockback = 32, + Attract1 = 33, //Here is an issue bout knockback. some is 32 some is 33. + Attract2 = 34, + Mount = 40, + FullResistStatus = 52, + FullResistStatus2 = 55, + VFX = 59, + Gauge = 60, + JobGauge = 61, + SetModelState = 72, + SetHP = 73, + PartialInvulnerable = 74, + Interrupt = 75, + } +} diff --git a/Questionable/Controller/MiniTaskController.cs b/Questionable/Controller/MiniTaskController.cs index 6055a68c..c9aec197 100644 --- a/Questionable/Controller/MiniTaskController.cs +++ b/Questionable/Controller/MiniTaskController.cs @@ -17,26 +17,29 @@ using Mount = Questionable.Controller.Steps.Common.Mount; namespace Questionable.Controller; -internal abstract class MiniTaskController +internal abstract class MiniTaskController : IDisposable { protected readonly TaskQueue _taskQueue = new(); private readonly IChatGui _chatGui; private readonly ICondition _condition; private readonly IServiceProvider _serviceProvider; + private readonly InterruptHandler _interruptHandler; private readonly ILogger _logger; private readonly string _actionCanceledText; protected MiniTaskController(IChatGui chatGui, ICondition condition, IServiceProvider serviceProvider, - IDataManager dataManager, ILogger logger) + InterruptHandler interruptHandler, IDataManager dataManager, ILogger logger) { _chatGui = chatGui; _logger = logger; _serviceProvider = serviceProvider; + _interruptHandler = interruptHandler; _condition = condition; _actionCanceledText = dataManager.GetString(1314, x => x.Text)!; + _interruptHandler.Interrupted += HandleInterruption; } protected virtual void UpdateCurrentTask() @@ -198,8 +201,21 @@ internal abstract class MiniTaskController if (!isHandled) { if (GameFunctions.GameStringEquals(_actionCanceledText, message.TextValue) && - !_condition[ConditionFlag.InFlight]) + !_condition[ConditionFlag.InFlight] && + _taskQueue.CurrentTaskExecutor?.ShouldInterruptOnDamage() == true) InterruptQueueWithCombat(); } } + + protected virtual void HandleInterruption(object? sender, EventArgs e) + { + if (!_condition[ConditionFlag.InFlight] && + _taskQueue.CurrentTaskExecutor?.ShouldInterruptOnDamage() == true) + InterruptQueueWithCombat(); + } + + public virtual void Dispose() + { + _interruptHandler.Interrupted -= HandleInterruption; + } } diff --git a/Questionable/Controller/QuestController.cs b/Questionable/Controller/QuestController.cs index 9d17fed1..d514f267 100644 --- a/Questionable/Controller/QuestController.cs +++ b/Questionable/Controller/QuestController.cs @@ -75,8 +75,9 @@ internal sealed class QuestController : MiniTaskController, IDi YesAlreadyIpc yesAlreadyIpc, TaskCreator taskCreator, IServiceProvider serviceProvider, + InterruptHandler interruptHandler, IDataManager dataManager) - : base(chatGui, condition, serviceProvider, dataManager, logger) + : base(chatGui, condition, serviceProvider, interruptHandler, dataManager, logger) { _clientState = clientState; _gameFunctions = gameFunctions; @@ -801,11 +802,23 @@ internal sealed class QuestController : MiniTaskController, IDi _gatheringController.OnNormalToast(message); } - public void Dispose() + protected override void HandleInterruption(object? sender, EventArgs e) + { + if (!IsRunning) + return; + + if (AutomationType == EAutomationType.Manual) + return; + + base.HandleInterruption(sender, e); + } + + public override void Dispose() { _toastGui.ErrorToast -= OnErrorToast; _toastGui.Toast -= OnNormalToast; _condition.ConditionChange -= OnConditionChange; + base.Dispose(); } public sealed record StepProgress( diff --git a/Questionable/Controller/Steps/Common/Mount.cs b/Questionable/Controller/Steps/Common/Mount.cs index 1e03d8e9..4f35f4d9 100644 --- a/Questionable/Controller/Steps/Common/Mount.cs +++ b/Questionable/Controller/Steps/Common/Mount.cs @@ -110,6 +110,8 @@ internal static class Mount ? ETaskResult.TaskComplete : ETaskResult.StillRunning; } + + public override bool ShouldInterruptOnDamage() => false; } internal enum MountResult @@ -197,6 +199,8 @@ internal static class Mount return false; } + + public override bool ShouldInterruptOnDamage() => false; } public enum EMountIf diff --git a/Questionable/Controller/Steps/Common/NextQuest.cs b/Questionable/Controller/Steps/Common/NextQuest.cs index 7f4b0261..3ac7758d 100644 --- a/Questionable/Controller/Steps/Common/NextQuest.cs +++ b/Questionable/Controller/Steps/Common/NextQuest.cs @@ -61,5 +61,7 @@ internal static class NextQuest } public override ETaskResult Update() => ETaskResult.TaskComplete; + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Common/SendNotification.cs b/Questionable/Controller/Steps/Common/SendNotification.cs index cf116028..6d8bbcec 100644 --- a/Questionable/Controller/Steps/Common/SendNotification.cs +++ b/Questionable/Controller/Steps/Common/SendNotification.cs @@ -104,5 +104,7 @@ internal static class SendNotification } public override ETaskResult Update() => ETaskResult.TaskComplete; + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Common/WaitConditionTask.cs b/Questionable/Controller/Steps/Common/WaitConditionTask.cs index 367fdfec..8203c056 100644 --- a/Questionable/Controller/Steps/Common/WaitConditionTask.cs +++ b/Questionable/Controller/Steps/Common/WaitConditionTask.cs @@ -25,5 +25,7 @@ internal static class WaitCondition return DateTime.Now >= _continueAt ? ETaskResult.TaskComplete : ETaskResult.StillRunning; } + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Gathering/DoGather.cs b/Questionable/Controller/Steps/Gathering/DoGather.cs index 0f4c8c7f..bf4ab4aa 100644 --- a/Questionable/Controller/Steps/Gathering/DoGather.cs +++ b/Questionable/Controller/Steps/Gathering/DoGather.cs @@ -236,6 +236,8 @@ internal static class DoGather EAction action = PickAction(minerAction, botanistAction); return ActionManager.Instance()->GetActionStatus(ActionType.Action, (uint)action) == 0; } + + public override bool ShouldInterruptOnDamage() => false; } [SuppressMessage("ReSharper", "NotAccessedPositionalProperty.Local")] diff --git a/Questionable/Controller/Steps/Gathering/DoGatherCollectable.cs b/Questionable/Controller/Steps/Gathering/DoGatherCollectable.cs index 2b91f353..fcd5efad 100644 --- a/Questionable/Controller/Steps/Gathering/DoGatherCollectable.cs +++ b/Questionable/Controller/Steps/Gathering/DoGatherCollectable.cs @@ -198,6 +198,8 @@ internal static class DoGatherCollectable else return botanistAction; } + + public override bool ShouldInterruptOnDamage() => false; } [SuppressMessage("ReSharper", "NotAccessedPositionalProperty.Local")] diff --git a/Questionable/Controller/Steps/Gathering/MoveToLandingLocation.cs b/Questionable/Controller/Steps/Gathering/MoveToLandingLocation.cs index 38fa30cd..bc183013 100644 --- a/Questionable/Controller/Steps/Gathering/MoveToLandingLocation.cs +++ b/Questionable/Controller/Steps/Gathering/MoveToLandingLocation.cs @@ -59,5 +59,6 @@ internal static class MoveToLandingLocation public override ETaskResult Update() => moveExecutor.Update(); public bool OnErrorToast(SeString message) => moveExecutor.OnErrorToast(message); + public override bool ShouldInterruptOnDamage() => moveExecutor.ShouldInterruptOnDamage(); } } diff --git a/Questionable/Controller/Steps/Gathering/TurnInDelivery.cs b/Questionable/Controller/Steps/Gathering/TurnInDelivery.cs index caf2b0f4..0483605b 100644 --- a/Questionable/Controller/Steps/Gathering/TurnInDelivery.cs +++ b/Questionable/Controller/Steps/Gathering/TurnInDelivery.cs @@ -80,5 +80,8 @@ internal static class TurnInDelivery addon->FireCallback(2, pickGatheringItem); return ETaskResult.StillRunning; } + + // not even sure if any turn-in npcs are NEAR mobs; but we also need to be on a gathering/crafting job + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Interactions/Action.cs b/Questionable/Controller/Steps/Interactions/Action.cs index 7255fa0b..f7f97502 100644 --- a/Questionable/Controller/Steps/Interactions/Action.cs +++ b/Questionable/Controller/Steps/Interactions/Action.cs @@ -124,6 +124,8 @@ internal static class Action return ETaskResult.TaskComplete; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record UseMudraOnObject(uint DataId, EAction Action) : ITask @@ -187,5 +189,7 @@ internal static class Action logger.LogError("Unable to find relevant combo for {Action}", Task.Action); return ETaskResult.TaskComplete; } + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Interactions/AetherCurrent.cs b/Questionable/Controller/Steps/Interactions/AetherCurrent.cs index b244bbea..7632e574 100644 --- a/Questionable/Controller/Steps/Interactions/AetherCurrent.cs +++ b/Questionable/Controller/Steps/Interactions/AetherCurrent.cs @@ -65,5 +65,7 @@ internal static class AetherCurrent gameFunctions.IsAetherCurrentUnlocked(Task.AetherCurrentId) ? ETaskResult.TaskComplete : ETaskResult.StillRunning; + + public override bool ShouldInterruptOnDamage() => true; } } diff --git a/Questionable/Controller/Steps/Interactions/AethernetShard.cs b/Questionable/Controller/Steps/Interactions/AethernetShard.cs index b1af7fe9..db2c5212 100644 --- a/Questionable/Controller/Steps/Interactions/AethernetShard.cs +++ b/Questionable/Controller/Steps/Interactions/AethernetShard.cs @@ -53,5 +53,7 @@ internal static class AethernetShard aetheryteFunctions.IsAetheryteUnlocked(Task.AetheryteLocation) ? ETaskResult.TaskComplete : ETaskResult.StillRunning; + + public override bool ShouldInterruptOnDamage() => true; } } diff --git a/Questionable/Controller/Steps/Interactions/Aetheryte.cs b/Questionable/Controller/Steps/Interactions/Aetheryte.cs index d9754776..dd40fc69 100644 --- a/Questionable/Controller/Steps/Interactions/Aetheryte.cs +++ b/Questionable/Controller/Steps/Interactions/Aetheryte.cs @@ -52,5 +52,7 @@ internal static class Aetheryte aetheryteFunctions.IsAetheryteUnlocked(Task.AetheryteLocation) ? ETaskResult.TaskComplete : ETaskResult.StillRunning; + + public override bool ShouldInterruptOnDamage() => true; } } diff --git a/Questionable/Controller/Steps/Interactions/Combat.cs b/Questionable/Controller/Steps/Interactions/Combat.cs index 463c32ce..e63058a8 100644 --- a/Questionable/Controller/Steps/Interactions/Combat.cs +++ b/Questionable/Controller/Steps/Interactions/Combat.cs @@ -190,5 +190,7 @@ internal static class Combat return ETaskResult.TaskComplete; } } + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Interactions/Dive.cs b/Questionable/Controller/Steps/Interactions/Dive.cs index b5389774..eea9cd87 100644 --- a/Questionable/Controller/Steps/Interactions/Dive.cs +++ b/Questionable/Controller/Steps/Interactions/Dive.cs @@ -71,6 +71,8 @@ internal static class Dive return base.Update(); } + public override bool ShouldInterruptOnDamage() => false; + protected override ETaskResult UpdateInternal() { if (condition[ConditionFlag.Diving]) diff --git a/Questionable/Controller/Steps/Interactions/Duty.cs b/Questionable/Controller/Steps/Interactions/Duty.cs index 5e20accf..b59f8ce7 100644 --- a/Questionable/Controller/Steps/Interactions/Duty.cs +++ b/Questionable/Controller/Steps/Interactions/Duty.cs @@ -93,6 +93,8 @@ internal static class Duty ? ETaskResult.TaskComplete : ETaskResult.StillRunning; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record WaitAutoDutyTask(uint ContentFinderConditionId) : ITask @@ -117,6 +119,8 @@ internal static class Duty ? ETaskResult.TaskComplete : ETaskResult.StillRunning; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record OpenDutyFinderTask(uint ContentFinderConditionId) : ITask @@ -138,5 +142,7 @@ internal static class Duty } public override ETaskResult Update() => ETaskResult.TaskComplete; + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Interactions/Emote.cs b/Questionable/Controller/Steps/Interactions/Emote.cs index 085b0356..d6dd7146 100644 --- a/Questionable/Controller/Steps/Interactions/Emote.cs +++ b/Questionable/Controller/Steps/Interactions/Emote.cs @@ -51,6 +51,8 @@ internal static class Emote chatFunctions.UseEmote(Task.DataId, Task.Emote); return true; } + + public override bool ShouldInterruptOnDamage() => true; } internal sealed record UseOnSelf(EEmote Emote) : ITask @@ -65,5 +67,7 @@ internal static class Emote chatFunctions.UseEmote(Task.Emote); return true; } + + public override bool ShouldInterruptOnDamage() => true; } } diff --git a/Questionable/Controller/Steps/Interactions/EquipItem.cs b/Questionable/Controller/Steps/Interactions/EquipItem.cs index f5cd4e11..d761926d 100644 --- a/Questionable/Controller/Steps/Interactions/EquipItem.cs +++ b/Questionable/Controller/Steps/Interactions/EquipItem.cs @@ -183,5 +183,7 @@ internal static class EquipItem return false; } + + public override bool ShouldInterruptOnDamage() => true; } } diff --git a/Questionable/Controller/Steps/Interactions/EquipRecommended.cs b/Questionable/Controller/Steps/Interactions/EquipRecommended.cs index 3b2be0f1..295bb8cc 100644 --- a/Questionable/Controller/Steps/Interactions/EquipRecommended.cs +++ b/Questionable/Controller/Steps/Interactions/EquipRecommended.cs @@ -98,5 +98,7 @@ internal static class EquipRecommended return ETaskResult.TaskComplete; } + + public override bool ShouldInterruptOnDamage() => true; } } diff --git a/Questionable/Controller/Steps/Interactions/Interact.cs b/Questionable/Controller/Steps/Interactions/Interact.cs index 0ca70c11..0073349b 100644 --- a/Questionable/Controller/Steps/Interactions/Interact.cs +++ b/Questionable/Controller/Steps/Interactions/Interact.cs @@ -228,6 +228,8 @@ internal static class Interact } } + public override bool ShouldInterruptOnDamage() => true; + private enum EInteractionState { None, diff --git a/Questionable/Controller/Steps/Interactions/Jump.cs b/Questionable/Controller/Steps/Interactions/Jump.cs index f7b9892d..3238405c 100644 --- a/Questionable/Controller/Steps/Interactions/Jump.cs +++ b/Questionable/Controller/Steps/Interactions/Jump.cs @@ -80,6 +80,8 @@ internal static class Jump return ETaskResult.TaskComplete; } + + public override bool ShouldInterruptOnDamage() => true; } internal sealed class DoSingleJump( diff --git a/Questionable/Controller/Steps/Interactions/Say.cs b/Questionable/Controller/Steps/Interactions/Say.cs index f13ab4ab..ffb56215 100644 --- a/Questionable/Controller/Steps/Interactions/Say.cs +++ b/Questionable/Controller/Steps/Interactions/Say.cs @@ -48,5 +48,7 @@ internal static class Say chatFunctions.ExecuteCommand($"/say {Task.ChatMessage}"); return true; } + + public override bool ShouldInterruptOnDamage() => true; } } diff --git a/Questionable/Controller/Steps/Interactions/StatusOff.cs b/Questionable/Controller/Steps/Interactions/StatusOff.cs index 746f7394..c9b2b4ca 100644 --- a/Questionable/Controller/Steps/Interactions/StatusOff.cs +++ b/Questionable/Controller/Steps/Interactions/StatusOff.cs @@ -43,5 +43,7 @@ internal static class StatusOff { return gameFunctions.HasStatus(Task.Status) ? ETaskResult.StillRunning : ETaskResult.TaskComplete; } + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Interactions/UseItem.cs b/Questionable/Controller/Steps/Interactions/UseItem.cs index bf779a02..abc427ad 100644 --- a/Questionable/Controller/Steps/Interactions/UseItem.cs +++ b/Questionable/Controller/Steps/Interactions/UseItem.cs @@ -205,6 +205,8 @@ internal static class UseItem else return TimeSpan.FromSeconds(5); } + + public override bool ShouldInterruptOnDamage() => true; } internal sealed record UseOnGround( diff --git a/Questionable/Controller/Steps/Leves/InitiateLeve.cs b/Questionable/Controller/Steps/Leves/InitiateLeve.cs index ab584cef..31cf4705 100644 --- a/Questionable/Controller/Steps/Leves/InitiateLeve.cs +++ b/Questionable/Controller/Steps/Leves/InitiateLeve.cs @@ -50,6 +50,8 @@ internal static class InitiateLeve return ETaskResult.TaskComplete; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record OpenJournal(ElementId ElementId) : ITask @@ -85,6 +87,8 @@ internal static class InitiateLeve return ETaskResult.StillRunning; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record Initiate(ElementId ElementId) : ITask @@ -111,6 +115,8 @@ internal static class InitiateLeve return ETaskResult.StillRunning; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed class SelectDifficulty : ITask @@ -138,5 +144,7 @@ internal static class InitiateLeve return ETaskResult.StillRunning; } + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Shared/AethernetShortcut.cs b/Questionable/Controller/Steps/Shared/AethernetShortcut.cs index e63b69c0..460aa440 100644 --- a/Questionable/Controller/Steps/Shared/AethernetShortcut.cs +++ b/Questionable/Controller/Steps/Shared/AethernetShortcut.cs @@ -269,5 +269,7 @@ internal static class AethernetShortcut return ETaskResult.TaskComplete; } + + public override bool ShouldInterruptOnDamage() => true; } } diff --git a/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs b/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs index af575333..b2748b18 100644 --- a/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs +++ b/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs @@ -221,6 +221,8 @@ internal static class AetheryteShortcut } public override bool WasInterrupted() => condition[ConditionFlag.InCombat] || base.WasInterrupted(); + + public override bool ShouldInterruptOnDamage() => true; } internal sealed record MoveAwayFromAetheryte(EAetheryteLocation TargetAetheryte) : ITask @@ -264,5 +266,7 @@ internal static class AetheryteShortcut } public override ETaskResult Update() => moveExecutor.Update(); + + public override bool ShouldInterruptOnDamage() => true; } } diff --git a/Questionable/Controller/Steps/Shared/Craft.cs b/Questionable/Controller/Steps/Shared/Craft.cs index 26493ca0..d986368f 100644 --- a/Questionable/Controller/Steps/Shared/Craft.cs +++ b/Questionable/Controller/Steps/Shared/Craft.cs @@ -133,5 +133,8 @@ internal static class Craft return inventoryManager->GetInventoryItemCount(Task.ItemId, isHq: false, checkEquipped: false) + inventoryManager->GetInventoryItemCount(Task.ItemId, isHq: true, checkEquipped: false); } + + // we're on a crafting class, so combat doesn't make much sense (we also can't change classes in combat...) + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Shared/Gather.cs b/Questionable/Controller/Steps/Shared/Gather.cs index 73dd8d12..f4aad9c9 100644 --- a/Questionable/Controller/Steps/Shared/Gather.cs +++ b/Questionable/Controller/Steps/Shared/Gather.cs @@ -100,6 +100,8 @@ internal static class Gather minCollectability: (short)itemToGather.Collectability) >= itemToGather.ItemCount; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record GatheringTask( @@ -140,6 +142,9 @@ internal static class Gather gatheringController.OnErrorToast(ref message, ref isHandled); return isHandled; } + + // we're on a gathering class, so combat doesn't make much sense (we also can't change classes in combat...) + public override bool ShouldInterruptOnDamage() => false; } /// @@ -154,5 +159,7 @@ internal static class Gather { protected override bool Start() => true; public override ETaskResult Update() => ETaskResult.TaskComplete; + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Shared/MoveTo.cs b/Questionable/Controller/Steps/Shared/MoveTo.cs index 4df2870f..65689108 100644 --- a/Questionable/Controller/Steps/Shared/MoveTo.cs +++ b/Questionable/Controller/Steps/Shared/MoveTo.cs @@ -286,6 +286,8 @@ internal static class MoveTo return base.WasInterrupted(); } + public override bool ShouldInterruptOnDamage() => false; + public bool OnErrorToast(SeString message) { if (GameFunctions.GameStringEquals(_cannotExecuteAtThisTime, message.TextValue)) @@ -302,6 +304,8 @@ internal static class MoveTo protected override bool Start() => true; public override ETaskResult Update() => ETaskResult.TaskComplete; + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record MoveTask( @@ -361,6 +365,8 @@ internal static class MoveTo return ETaskResult.TaskComplete; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed class LandTask : ITask @@ -421,5 +427,7 @@ internal static class MoveTo return false; } + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Shared/RedeemRewardItems.cs b/Questionable/Controller/Steps/Shared/RedeemRewardItems.cs index 408b92f7..c7abcae7 100644 --- a/Questionable/Controller/Steps/Shared/RedeemRewardItems.cs +++ b/Questionable/Controller/Steps/Shared/RedeemRewardItems.cs @@ -74,5 +74,7 @@ internal static class RedeemRewardItems return DateTime.Now <= _continueAt ? ETaskResult.StillRunning : ETaskResult.TaskComplete; } + + public override bool ShouldInterruptOnDamage() => true; } } diff --git a/Questionable/Controller/Steps/Shared/SkipCondition.cs b/Questionable/Controller/Steps/Shared/SkipCondition.cs index 5abab059..ebf1dc1f 100644 --- a/Questionable/Controller/Steps/Shared/SkipCondition.cs +++ b/Questionable/Controller/Steps/Shared/SkipCondition.cs @@ -315,5 +315,7 @@ internal static class SkipCondition } public override ETaskResult Update() => ETaskResult.SkipRemainingTasksForStep; + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Shared/StepDisabled.cs b/Questionable/Controller/Steps/Shared/StepDisabled.cs index f7065359..de58cac3 100644 --- a/Questionable/Controller/Steps/Shared/StepDisabled.cs +++ b/Questionable/Controller/Steps/Shared/StepDisabled.cs @@ -31,5 +31,7 @@ internal static class StepDisabled logger.LogInformation("Skipping step, as it is disabled"); return ETaskResult.SkipRemainingTasksForStep; } + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Shared/SwitchClassJob.cs b/Questionable/Controller/Steps/Shared/SwitchClassJob.cs index 59477fec..18bfef7e 100644 --- a/Questionable/Controller/Steps/Shared/SwitchClassJob.cs +++ b/Questionable/Controller/Steps/Shared/SwitchClassJob.cs @@ -52,5 +52,8 @@ internal static class SwitchClassJob } protected override ETaskResult UpdateInternal() => ETaskResult.TaskComplete; + + // can we even take damage while switching jobs? we should be out of combat... + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Shared/WaitAtEnd.cs b/Questionable/Controller/Steps/Shared/WaitAtEnd.cs index 0b3a02ba..d39c7c2a 100644 --- a/Questionable/Controller/Steps/Shared/WaitAtEnd.cs +++ b/Questionable/Controller/Steps/Shared/WaitAtEnd.cs @@ -157,6 +157,8 @@ internal static class WaitAtEnd Delay = Task.Delay; return true; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed class WaitNextStepOrSequence : ITask @@ -169,6 +171,8 @@ internal static class WaitAtEnd protected override bool Start() => true; public override ETaskResult Update() => ETaskResult.StillRunning; + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record WaitForCompletionFlags(QuestId Quest, QuestStep Step) : ITask @@ -190,6 +194,8 @@ internal static class WaitAtEnd ? ETaskResult.TaskComplete : ETaskResult.StillRunning; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record WaitObjectAtPosition( @@ -209,6 +215,8 @@ internal static class WaitAtEnd gameFunctions.IsObjectAtPosition(Task.DataId, Task.Destination, Task.Distance) ? ETaskResult.TaskComplete : ETaskResult.StillRunning; + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record WaitQuestAccepted(ElementId ElementId) : ITask @@ -226,6 +234,8 @@ internal static class WaitAtEnd ? ETaskResult.TaskComplete : ETaskResult.StillRunning; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record WaitQuestCompleted(ElementId ElementId) : ITask @@ -241,6 +251,8 @@ internal static class WaitAtEnd { return questFunctions.IsQuestComplete(Task.ElementId) ? ETaskResult.TaskComplete : ETaskResult.StillRunning; } + + public override bool ShouldInterruptOnDamage() => false; } internal sealed record NextStep(ElementId ElementId, int Sequence) : ILastTask @@ -253,6 +265,8 @@ internal static class WaitAtEnd protected override bool Start() => true; public override ETaskResult Update() => ETaskResult.NextStep; + + public override bool ShouldInterruptOnDamage() => false; } internal sealed class EndAutomation : ILastTask @@ -268,5 +282,7 @@ internal static class WaitAtEnd protected override bool Start() => true; public override ETaskResult Update() => ETaskResult.End; + + public override bool ShouldInterruptOnDamage() => false; } } diff --git a/Questionable/Controller/Steps/Shared/WaitAtStart.cs b/Questionable/Controller/Steps/Shared/WaitAtStart.cs index c2c304b4..8386e636 100644 --- a/Questionable/Controller/Steps/Shared/WaitAtStart.cs +++ b/Questionable/Controller/Steps/Shared/WaitAtStart.cs @@ -31,6 +31,7 @@ internal static class WaitAtStart Delay = Task.Delay; return true; } - } + public override bool ShouldInterruptOnDamage() => false; + } } diff --git a/Questionable/Controller/Steps/TaskExecutor.cs b/Questionable/Controller/Steps/TaskExecutor.cs index d0315dbc..30e10b64 100644 --- a/Questionable/Controller/Steps/TaskExecutor.cs +++ b/Questionable/Controller/Steps/TaskExecutor.cs @@ -13,6 +13,8 @@ internal interface ITaskExecutor bool Start(ITask task); + bool ShouldInterruptOnDamage(); + bool WasInterrupted(); ETaskResult Update(); @@ -56,4 +58,6 @@ internal abstract class TaskExecutor : ITaskExecutor } public abstract ETaskResult Update(); + + public abstract bool ShouldInterruptOnDamage(); } diff --git a/Questionable/QuestionablePlugin.cs b/Questionable/QuestionablePlugin.cs index a4b5bae9..e0794c2d 100644 --- a/Questionable/QuestionablePlugin.cs +++ b/Questionable/QuestionablePlugin.cs @@ -247,6 +247,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); From 325d5368a50b3f8089168232eaccb51b17f051ae Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Tue, 21 Jan 2025 21:44:08 +0100 Subject: [PATCH 33/39] Interrupts: Add a special case for certain movement tasks --- .../Controller/Steps/Shared/MoveTo.cs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Questionable/Controller/Steps/Shared/MoveTo.cs b/Questionable/Controller/Steps/Shared/MoveTo.cs index 65689108..60d83aed 100644 --- a/Questionable/Controller/Steps/Shared/MoveTo.cs +++ b/Questionable/Controller/Steps/Shared/MoveTo.cs @@ -228,6 +228,17 @@ internal static class MoveTo } } } + else if (!ShouldResolveCombatBeforeNextInteraction() && + _movementController is { IsPathfinding: false, IsPathRunning: false } && + mountExecutor.EvaluateMountState() == Mount.MountResult.DontMount) + { + // except for e.g. jumping which would maybe break if combat navigates us away, if we don't + // need a mount anymore we can just skip combat and assume that the interruption is handled + // later. + // + // without this, the character would just stand around while getting hit + _nestedExecutor = (new NoOpTaskExecutor(), new NoOpTask(), true); + } } else if (nestedExecutor.Executor.Update() == ETaskResult.TaskComplete) { @@ -286,7 +297,16 @@ internal static class MoveTo return base.WasInterrupted(); } - public override bool ShouldInterruptOnDamage() => false; + public override bool ShouldInterruptOnDamage() + { + // have we stopped moving, and are we + // (a) waiting for a mount to complete, or + // (b) want combat to be done before any other interaction? + return _movementController is { IsPathfinding: false, IsPathRunning: false } && + (_nestedExecutor is { Triggered: false, Executor: Mount.MountExecutor } || ShouldResolveCombatBeforeNextInteraction()); + } + + private bool ShouldResolveCombatBeforeNextInteraction() => Task.InteractionType is EInteractionType.Jump; public bool OnErrorToast(SeString message) { From 3a3196d869fc15d8637d37d910e80cd5c950414c Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Tue, 21 Jan 2025 21:45:01 +0100 Subject: [PATCH 34/39] No longer accept the level 30 job quest if relevant aetherytes aren't unlocked --- Questionable/Controller/QuestRegistry.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Questionable/Controller/QuestRegistry.cs b/Questionable/Controller/QuestRegistry.cs index d6641073..7808b095 100644 --- a/Questionable/Controller/QuestRegistry.cs +++ b/Questionable/Controller/QuestRegistry.cs @@ -234,7 +234,11 @@ internal sealed class QuestRegistry public List GetKnownClassJobQuests(EClassJob classJob) { - return _questData.GetClassJobQuests(classJob) + List allQuests = [.._questData.GetClassJobQuests(classJob)]; + if (classJob.AsJob() != classJob) + allQuests.AddRange(_questData.GetClassJobQuests(classJob.AsJob())); + + return allQuests .Where(x => IsKnownQuest(x.QuestId)) .ToList(); } From b3d9ce382d6b814a5af4ce0b12950b79cb80994f Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Tue, 21 Jan 2025 21:50:05 +0100 Subject: [PATCH 35/39] Version bump --- Directory.Build.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index c0b49f3b..cfa9441e 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,5 +1,5 @@ - 4.14 + 4.15 From 2cf059ec38985bf125e7e009d73a0b39808f1f10 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Wed, 22 Jan 2025 18:37:15 +0100 Subject: [PATCH 36/39] CodeGen update --- .../RoslynElements/CombatItemUseExtensions.cs | 29 +++++++++++++++++++ .../RoslynElements/QuestStepExtensions.cs | 3 ++ QuestPathGenerator/RoslynShortcuts.cs | 1 + 3 files changed, 33 insertions(+) create mode 100644 QuestPathGenerator/RoslynElements/CombatItemUseExtensions.cs diff --git a/QuestPathGenerator/RoslynElements/CombatItemUseExtensions.cs b/QuestPathGenerator/RoslynElements/CombatItemUseExtensions.cs new file mode 100644 index 00000000..93e5d696 --- /dev/null +++ b/QuestPathGenerator/RoslynElements/CombatItemUseExtensions.cs @@ -0,0 +1,29 @@ +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Questionable.Model.Questing; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static Questionable.QuestPathGenerator.RoslynShortcuts; + +namespace Questionable.QuestPathGenerator.RoslynElements; + +internal static class CombatItemUseExtensions +{ + public static ExpressionSyntax ToExpressionSyntax(this CombatItemUse combatItemuse) + { + var emptyItemuse = new CombatItemUse(); + return ObjectCreationExpression( + IdentifierName(nameof(CombatItemUse))) + .WithInitializer( + InitializerExpression( + SyntaxKind.ObjectInitializerExpression, + SeparatedList( + SyntaxNodeList( + Assignment(nameof(CombatItemUse.ItemId), combatItemuse.ItemId, + emptyItemuse.ItemId) + .AsSyntaxNodeOrToken(), + Assignment(nameof(CombatItemUse.Condition), combatItemuse.Condition, emptyItemuse.Condition) + .AsSyntaxNodeOrToken(), + Assignment(nameof(combatItemuse.Value), combatItemuse.Value, emptyItemuse.Value) + .AsSyntaxNodeOrToken())))); + } +} diff --git a/QuestPathGenerator/RoslynElements/QuestStepExtensions.cs b/QuestPathGenerator/RoslynElements/QuestStepExtensions.cs index 6b76bb95..2d3ec803 100644 --- a/QuestPathGenerator/RoslynElements/QuestStepExtensions.cs +++ b/QuestPathGenerator/RoslynElements/QuestStepExtensions.cs @@ -107,6 +107,9 @@ internal static class QuestStepExtensions .AsSyntaxNodeOrToken(), AssignmentList(nameof(QuestStep.ComplexCombatData), step.ComplexCombatData) .AsSyntaxNodeOrToken(), + Assignment(nameof(QuestStep.CombatItemUse), step.CombatItemUse, + emptyStep.CombatItemUse) + .AsSyntaxNodeOrToken(), Assignment(nameof(QuestStep.CombatDelaySecondsAtStart), step.CombatDelaySecondsAtStart, emptyStep.CombatDelaySecondsAtStart) diff --git a/QuestPathGenerator/RoslynShortcuts.cs b/QuestPathGenerator/RoslynShortcuts.cs index c5fb47f5..2c1df09f 100644 --- a/QuestPathGenerator/RoslynShortcuts.cs +++ b/QuestPathGenerator/RoslynShortcuts.cs @@ -71,6 +71,7 @@ public static class RoslynShortcuts GatheringNodeGroup nodeGroup => nodeGroup.ToExpressionSyntax(), GatheringNode nodeLocation => nodeLocation.ToExpressionSyntax(), GatheringLocation location => location.ToExpressionSyntax(), + CombatItemUse combatItemUse => combatItemUse.ToExpressionSyntax(), not null when value.GetType().IsEnum => MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(value.GetType().Name), IdentifierName(value.GetType().GetEnumName(value)!)), _ => throw new Exception($"Unsupported data type {value.GetType()} = {value}") From 05d63942649ccd93f86fb66c593868f505a17859 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Wed, 22 Jan 2025 18:38:03 +0100 Subject: [PATCH 37/39] Minor ARR MSQ updates --- .../757_On to Little Ala Mhigo.json | 10 ++++++++++ .../897_The Talk of Coerthas.json | 3 ++- .../924_Ye of Little Faith.json | 3 ++- .../961_Representing the Representative.json | 9 +++++++++ .../962_The Reluctant Researcher.json | 9 +++++++++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/A5-Southern Thanalan, Little Ala Mhigo/757_On to Little Ala Mhigo.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/A5-Southern Thanalan, Little Ala Mhigo/757_On to Little Ala Mhigo.json index 27a25019..19fac78d 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/A5-Southern Thanalan, Little Ala Mhigo/757_On to Little Ala Mhigo.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/A5-Southern Thanalan, Little Ala Mhigo/757_On to Little Ala Mhigo.json @@ -36,6 +36,16 @@ "InteractionType": "WalkTo", "TargetTerritoryId": 146 }, + { + "Position": { + "X": -47.50145, + "Y": 16.362688, + "Z": -439.62503 + }, + "TerritoryId": 146, + "InteractionType": "WalkTo", + "$": "vnav sometimes attempts to walk to the aetheryte using exactly one waypoint between zone boundary and aetheryte, which means walking into walls" + }, { "TerritoryId": 146, "InteractionType": "AttuneAetheryte", diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B7-Coerthas Central Highlands, Camp Dragonhead/897_The Talk of Coerthas.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B7-Coerthas Central Highlands, Camp Dragonhead/897_The Talk of Coerthas.json index fc0042f5..b5543417 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B7-Coerthas Central Highlands, Camp Dragonhead/897_The Talk of Coerthas.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B7-Coerthas Central Highlands, Camp Dragonhead/897_The Talk of Coerthas.json @@ -103,7 +103,8 @@ }, "TerritoryId": 155, "InteractionType": "WalkTo", - "$": "NW Skyfire Locks door (inside)" + "$": "NW Skyfire Locks door (inside)", + "Mount": true }, { "Position": { diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B9-Coerthas Central Highlands, Whitebrim Front/924_Ye of Little Faith.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B9-Coerthas Central Highlands, Whitebrim Front/924_Ye of Little Faith.json index f3401f9b..66891113 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B9-Coerthas Central Highlands, Whitebrim Front/924_Ye of Little Faith.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B9-Coerthas Central Highlands, Whitebrim Front/924_Ye of Little Faith.json @@ -49,7 +49,8 @@ }, "TerritoryId": 155, "InteractionType": "WalkTo", - "Comment": "North Whitebrim, Stairs (bottom)" + "Comment": "North Whitebrim, Stairs (bottom)", + "Mount": true }, { "Position": { diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C2-Western La Noscea, Isles of Umbra/961_Representing the Representative.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C2-Western La Noscea, Isles of Umbra/961_Representing the Representative.json index 6d2279b9..f4d1379f 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C2-Western La Noscea, Isles of Umbra/961_Representing the Representative.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C2-Western La Noscea, Isles of Umbra/961_Representing the Representative.json @@ -76,6 +76,15 @@ { "Sequence": 3, "Steps": [ + { + "Position": { + "X": 303.96317, + "Y": -36.40591, + "Z": 316.74185 + }, + "TerritoryId": 138, + "InteractionType": "WalkTo" + }, { "DataId": 1006501, "Position": { diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C2-Western La Noscea, Isles of Umbra/962_The Reluctant Researcher.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C2-Western La Noscea, Isles of Umbra/962_The Reluctant Researcher.json index 8266ce99..23eb5a02 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C2-Western La Noscea, Isles of Umbra/962_The Reluctant Researcher.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C2-Western La Noscea, Isles of Umbra/962_The Reluctant Researcher.json @@ -26,6 +26,15 @@ { "Sequence": 1, "Steps": [ + { + "Position": { + "X": 303.96317, + "Y": -36.40591, + "Z": 316.74185 + }, + "TerritoryId": 138, + "InteractionType": "WalkTo" + }, { "DataId": 1007640, "Position": { From 5e45af38d19b4e1b0d059382bb07a92e91d6c24a Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Wed, 22 Jan 2025 18:38:24 +0100 Subject: [PATCH 38/39] Fix target switching logic in combat --- Questionable/Controller/CombatController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Questionable/Controller/CombatController.cs b/Questionable/Controller/CombatController.cs index 73fe17df..ea10fa7c 100644 --- a/Questionable/Controller/CombatController.cs +++ b/Questionable/Controller/CombatController.cs @@ -157,7 +157,7 @@ internal sealed class CombatController : IDisposable { int currentTargetPriority = GetKillPriority(target); var nextTarget = FindNextTarget(); - int nextTargetPriority = GetKillPriority(target); + int nextTargetPriority = nextTarget != null ? GetKillPriority(nextTarget) : 0; if (nextTarget != null && nextTarget.Equals(target)) { @@ -176,7 +176,7 @@ internal sealed class CombatController : IDisposable } else if (nextTarget != null) { - if (nextTargetPriority > currentTargetPriority) + if (nextTargetPriority > currentTargetPriority || currentTargetPriority == 0) SetTarget(nextTarget); } else From e0580239e4473ccbc0810443e92529cff8863a47 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Wed, 22 Jan 2025 19:16:56 +0100 Subject: [PATCH 39/39] Enable flight for turning in 'The Wind's Blessing' --- .../Side Quests/Kozama'uka/5083_The Wind's Blessing.json | 1 + 1 file changed, 1 insertion(+) diff --git a/QuestPaths/7.x - Dawntrail/Side Quests/Kozama'uka/5083_The Wind's Blessing.json b/QuestPaths/7.x - Dawntrail/Side Quests/Kozama'uka/5083_The Wind's Blessing.json index 903ee73e..c02008d7 100644 --- a/QuestPaths/7.x - Dawntrail/Side Quests/Kozama'uka/5083_The Wind's Blessing.json +++ b/QuestPaths/7.x - Dawntrail/Side Quests/Kozama'uka/5083_The Wind's Blessing.json @@ -96,6 +96,7 @@ }, "TerritoryId": 1188, "InteractionType": "CompleteQuest", + "Fly": true, "NextQuestId": 5084 } ]