using Lumina.Excel.GeneratedSheets;
using Questionable.Model;
using Questionable.Model.Gathering;
+using Questionable.Model.Questing;
namespace GatheringPathRenderer;
var root = new GatheringRoot
{
Author = [_configuration.AuthorName],
- TerritoryId = _clientState.TerritoryType,
+ Steps =
+ [
+ new QuestStep
+ {
+ TerritoryId = _clientState.TerritoryType,
+ InteractionType = EInteractionType.None,
+ }
+ ],
Groups =
[
new GatheringNodeGroup
}
internal IEnumerable<GatheringLocationContext> GetLocationsInTerritory(ushort territoryId)
- => _gatheringLocations.Where(x => x.Root.TerritoryId == territoryId);
+ => _gatheringLocations.Where(x => x.Root.Steps.LastOrDefault()?.TerritoryId == territoryId);
internal void Save(FileInfo targetFile, GatheringRoot root)
{
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 141,
- "AetheryteShortcut": "Central Thanalan - Black Brush Station",
+ "Steps": [
+ {
+ "TerritoryId": 141,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Central Thanalan - Black Brush Station"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 140,
- "AetheryteShortcut": "Western Thanalan - Horizon",
+ "Steps": [
+ {
+ "TerritoryId": 140,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Western Thanalan - Horizon"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 397,
- "AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest",
+ "Steps": [
+ {
+ "TerritoryId": 397,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 397,
- "AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest",
+ "Steps": [
+ {
+ "TerritoryId": 397,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 397,
- "AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest",
+ "Steps": [
+ {
+ "TerritoryId": 397,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 397,
- "AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest",
+ "Steps": [
+ {
+ "TerritoryId": 397,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 400,
- "AetheryteShortcut": "The Churning Mists - Moghome",
+ "Steps": [
+ {
+ "TerritoryId": 400,
+ "InteractionType": "None",
+ "AetheryteShortcut": "The Churning Mists - Moghome"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 400,
- "AetheryteShortcut": "The Churning Mists - Zenith",
+ "Steps": [
+ {
+ "TerritoryId": 400,
+ "InteractionType": "None",
+ "AetheryteShortcut": "The Churning Mists - Zenith"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 400,
- "AetheryteShortcut": "The Churning Mists - Moghome",
+ "Steps": [
+ {
+ "TerritoryId": 400,
+ "InteractionType": "None",
+ "AetheryteShortcut": "The Churning Mists - Moghome"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 400,
- "AetheryteShortcut": "The Churning Mists - Zenith",
+ "Steps": [
+ {
+ "TerritoryId": 400,
+ "InteractionType": "None",
+ "AetheryteShortcut": "The Churning Mists - Zenith"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 398,
- "AetheryteShortcut": "The Dravanian Forelands - Anyx Trine",
+ "Steps": [
+ {
+ "TerritoryId": 398,
+ "InteractionType": "None",
+ "AetheryteShortcut": "The Dravanian Forelands - Anyx Trine"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 398,
- "AetheryteShortcut": "The Dravanian Forelands - Anyx Trine",
+ "Steps": [
+ {
+ "TerritoryId": 398,
+ "InteractionType": "None",
+ "AetheryteShortcut": "The Dravanian Forelands - Anyx Trine"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 399,
- "AetheryteShortcut": "Idyllshire",
- "AethernetShortcut": [
- "[Idyllshire] Aetheryte Plaza",
- "[Idyllshire] Epilogue Gate (Eastern Hinterlands)"
+ "Steps": [
+ {
+ "TerritoryId": 399,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Idyllshire",
+ "AethernetShortcut": [
+ "[Idyllshire] Aetheryte Plaza",
+ "[Idyllshire] Epilogue Gate (Eastern Hinterlands)"
+ ]
+ }
],
"Groups": [
{
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 399,
- "AetheryteShortcut": "Idyllshire",
- "AethernetShortcut": [
- "[Idyllshire] Aetheryte Plaza",
- "[Idyllshire] Prologue Gate (Western Hinterlands)"
+ "Steps": [
+ {
+ "TerritoryId": 399,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Idyllshire",
+ "AethernetShortcut": [
+ "[Idyllshire] Aetheryte Plaza",
+ "[Idyllshire] Prologue Gate (Western Hinterlands)"
+ ]
+ }
],
"Groups": [
{
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 401,
- "AetheryteShortcut": "The Sea of Clouds - Camp Cloudtop",
+ "Steps": [
+ {
+ "TerritoryId": 401,
+ "InteractionType": "None",
+ "AetheryteShortcut": "The Sea of Clouds - Camp Cloudtop"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 401,
- "AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
+ "Steps": [
+ {
+ "TerritoryId": 401,
+ "InteractionType": "None",
+ "AetheryteShortcut": "The Sea of Clouds - Ok' Zundu"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 622,
- "AetheryteShortcut": "Azim Steppe - Dawn Throne",
+ "Steps": [
+ {
+ "TerritoryId": 622,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Azim Steppe - Dawn Throne"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 622,
- "AetheryteShortcut": "Azim Steppe - Dawn Throne",
+ "Steps": [
+ {
+ "TerritoryId": 622,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Azim Steppe - Dawn Throne"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 622,
- "AetheryteShortcut": "Azim Steppe - Dawn Throne",
+ "Steps": [
+ {
+ "TerritoryId": 622,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Azim Steppe - Dawn Throne"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 612,
- "AetheryteShortcut": "Fringes - Castrum Oriens",
+ "Steps": [
+ {
+ "TerritoryId": 612,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Fringes - Castrum Oriens"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 612,
- "AetheryteShortcut": "Fringes - Castrum Oriens",
+ "Steps": [
+ {
+ "TerritoryId": 612,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Fringes - Castrum Oriens"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 612,
- "AetheryteShortcut": "Fringes - Castrum Oriens",
+ "Steps": [
+ {
+ "TerritoryId": 612,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Fringes - Castrum Oriens"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 612,
- "AetheryteShortcut": "Fringes - Castrum Oriens",
+ "Steps": [
+ {
+ "TerritoryId": 612,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Fringes - Castrum Oriens"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 612,
- "AetheryteShortcut": "Fringes - Castrum Oriens",
+ "Steps": [
+ {
+ "TerritoryId": 612,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Fringes - Castrum Oriens"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 621,
- "AetheryteShortcut": "Lochs - Porta Praetoria",
+ "Steps": [
+ {
+ "TerritoryId": 621,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Lochs - Porta Praetoria"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 621,
- "AetheryteShortcut": "Lochs - Ala Mhigan Quarter",
+ "Steps": [
+ {
+ "TerritoryId": 621,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Lochs - Ala Mhigan Quarter"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 621,
- "AetheryteShortcut": "Lochs - Porta Praetoria",
+ "Steps": [
+ {
+ "TerritoryId": 621,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Lochs - Porta Praetoria"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 620,
- "AetheryteShortcut": "Peaks - Ala Gannha",
+ "Steps": [
+ {
+ "TerritoryId": 620,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Peaks - Ala Gannha"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 620,
- "AetheryteShortcut": "Peaks - Ala Gannha",
+ "Steps": [
+ {
+ "TerritoryId": 620,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Peaks - Ala Gannha"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 620,
- "AetheryteShortcut": "Peaks - Ala Gannha",
+ "Steps": [
+ {
+ "TerritoryId": 620,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Peaks - Ala Gannha"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 620,
- "AetheryteShortcut": "Peaks - Ala Gannha",
+ "Steps": [
+ {
+ "TerritoryId": 620,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Peaks - Ala Gannha"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 613,
- "AetheryteShortcut": "Kugane",
- "AethernetShortcut": [
- "[Kugane] Aetheryte Plaza",
- "[Kugane] The Ruby Price"
+ "Steps": [
+ {
+ "TerritoryId": 613,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Kugane",
+ "AethernetShortcut": [
+ "[Kugane] Aetheryte Plaza",
+ "[Kugane] The Ruby Price"
+ ]
+ }
],
"Groups": [
{
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 613,
- "AetheryteShortcut": "Ruby Sea - Onokoro",
+ "Steps": [
+ {
+ "TerritoryId": 613,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Ruby Sea - Onokoro"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 613,
- "AetheryteShortcut": "Ruby Sea - Onokoro",
+ "Steps": [
+ {
+ "TerritoryId": 613,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Ruby Sea - Onokoro"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 613,
- "AetheryteShortcut": "Ruby Sea - Tamamizu",
+ "Steps": [
+ {
+ "TerritoryId": 613,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Ruby Sea - Tamamizu"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 613,
- "AetheryteShortcut": "Ruby Sea - Onokoro",
+ "Steps": [
+ {
+ "TerritoryId": 613,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Ruby Sea - Onokoro"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 613,
- "AetheryteShortcut": "Kugane",
- "AethernetShortcut": [
- "[Kugane] Aetheryte Plaza",
- "[Kugane] The Ruby Price"
+ "Steps": [
+ {
+ "TerritoryId": 613,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Kugane",
+ "AethernetShortcut": [
+ "[Kugane] Aetheryte Plaza",
+ "[Kugane] The Ruby Price"
+ ]
+ }
],
"FlyBetweenNodes": true,
"Groups": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 613,
- "AetheryteShortcut": "Ruby Sea - Tamamizu",
+ "Steps": [
+ {
+ "TerritoryId": 613,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Ruby Sea - Tamamizu"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 614,
- "AetheryteShortcut": "Yanxia - Namai",
+ "Steps": [
+ {
+ "TerritoryId": 614,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Yanxia - Namai"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 614,
- "AetheryteShortcut": "Yanxia - Namai",
+ "Steps": [
+ {
+ "TerritoryId": 614,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Yanxia - Namai"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 614,
- "AetheryteShortcut": "Yanxia - Namai",
+ "Steps": [
+ {
+ "TerritoryId": 614,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Yanxia - Namai"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 614,
- "AetheryteShortcut": "Yanxia - Namai",
+ "Steps": [
+ {
+ "TerritoryId": 614,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Yanxia - Namai"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 814,
- "AetheryteShortcut": "Kholusia - Wright",
+ "Steps": [
+ {
+ "TerritoryId": 814,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Kholusia - Wright"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 814,
- "AetheryteShortcut": "Kholusia - Wright",
+ "Steps": [
+ {
+ "TerritoryId": 814,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Kholusia - Wright"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 817,
+ "Steps": [
+ {
+ "TerritoryId": 817,
+ "InteractionType": "None"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 817,
+ "Steps": [
+ {
+ "TerritoryId": 817,
+ "InteractionType": "None"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 961,
- "AetheryteShortcut": "Elpis - Poieten Oikos",
+ "Steps": [
+ {
+ "TerritoryId": 961,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Elpis - Poieten Oikos"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 961,
- "AetheryteShortcut": "Elpis - Anagnorisis",
+ "Steps": [
+ {
+ "TerritoryId": 961,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Elpis - Anagnorisis"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1073,
+ "Steps": [
+ {
+ "TerritoryId": 1073,
+ "InteractionType": "None"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1073,
+ "Steps": [
+ {
+ "TerritoryId": 1073,
+ "InteractionType": "None"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1073,
+ "Steps": [
+ {
+ "TerritoryId": 1073,
+ "InteractionType": "None"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1073,
+ "Steps": [
+ {
+ "TerritoryId": 1073,
+ "InteractionType": "None"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1073,
+ "Steps": [
+ {
+ "TerritoryId": 1073,
+ "InteractionType": "None"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1073,
+ "Steps": [
+ {
+ "TerritoryId": 1073,
+ "InteractionType": "None"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1073,
+ "Steps": [
+ {
+ "TerritoryId": 1073,
+ "InteractionType": "None"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1073,
+ "Steps": [
+ {
+ "TerritoryId": 1073,
+ "InteractionType": "None"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 958,
- "AetheryteShortcut": "Garlemald - Camp Broken Glass",
+ "Steps": [
+ {
+ "TerritoryId": 958,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Garlemald - Camp Broken Glass"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 958,
- "AetheryteShortcut": "Garlemald - Camp Broken Glass",
+ "Steps": [
+ {
+ "TerritoryId": 958,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Garlemald - Camp Broken Glass"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 956,
- "AetheryteShortcut": "Labyrinthos - Archeion",
+ "Steps": [
+ {
+ "TerritoryId": 956,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Labyrinthos - Archeion"
+ }
+ ],
"Groups": [
{
"Nodes": [
]
}
]
-}
\ No newline at end of file
+}
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 956,
- "AetheryteShortcut": "Labyrinthos - Archeion",
+ "Steps": [
+ {
+ "TerritoryId": 956,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Labyrinthos - Archeion"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 959,
- "AetheryteShortcut": "Mare Lamentorum - Sinus Lacrimarum",
+ "Steps": [
+ {
+ "TerritoryId": 959,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Mare Lamentorum - Sinus Lacrimarum"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 959,
- "AetheryteShortcut": "Mare Lamentorum - Bestways Burrow",
+ "Steps": [
+ {
+ "TerritoryId": 959,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Mare Lamentorum - Bestways Burrow"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 957,
- "AetheryteShortcut": "Thavnair - Great Work",
+ "Steps": [
+ {
+ "TerritoryId": 957,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Thavnair - Great Work"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 957,
- "AetheryteShortcut": "Thavnair - Great Work",
+ "Steps": [
+ {
+ "TerritoryId": 957,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Thavnair - Great Work"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1188,
- "AetheryteShortcut": "Kozama'uka - Ok'hanu",
+ "Steps": [
+ {
+ "TerritoryId": 1188,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Kozama'uka - Ok'hanu"
+ }
+ ],
"FlyBetweenNodes": true,
"Groups": [
{
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1188,
- "AetheryteShortcut": "Kozama'uka - Ok'hanu",
+ "Steps": [
+ {
+ "TerritoryId": 1188,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Kozama'uka - Ok'hanu"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1188,
- "AetheryteShortcut": "Kozama'uka - Ok'hanu",
+ "Steps": [
+ {
+ "TerritoryId": 1188,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Kozama'uka - Ok'hanu"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1190,
- "AetheryteShortcut": "Shaaloani - Mehwahhetsoan",
+ "Steps": [
+ {
+ "TerritoryId": 1190,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Shaaloani - Mehwahhetsoan"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1190,
- "AetheryteShortcut": "Shaaloani - Hhusatahwi",
+ "Steps": [
+ {
+ "TerritoryId": 1190,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Shaaloani - Hhusatahwi"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1187,
- "AetheryteShortcut": "Urqopacha - Wachunpelo",
+ "Steps": [
+ {
+ "TerritoryId": 1187,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Urqopacha - Wachunpelo"
+ }
+ ],
"FlyBetweenNodes": false,
"Groups": [
{
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1187,
- "AetheryteShortcut": "Urqopacha - Wachunpelo",
+ "Steps": [
+ {
+ "TerritoryId": 1187,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Urqopacha - Wachunpelo"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1187,
- "AetheryteShortcut": "Urqopacha - Worlar's Echo",
+ "Steps": [
+ {
+ "TerritoryId": 1187,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Urqopacha - Worlar's Echo"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1187,
- "AetheryteShortcut": "Urqopacha - Wachunpelo",
+ "Steps": [
+ {
+ "TerritoryId": 1187,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Urqopacha - Wachunpelo"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1187,
- "AetheryteShortcut": "Urqopacha - Wachunpelo",
+ "Steps": [
+ {
+ "TerritoryId": 1187,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Urqopacha - Wachunpelo"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1187,
- "AetheryteShortcut": "Urqopacha - Worlar's Echo",
+ "Steps": [
+ {
+ "TerritoryId": 1187,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Urqopacha - Worlar's Echo"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1189,
- "AetheryteShortcut": "Yak T'el - Iq Br'aax",
+ "Steps": [
+ {
+ "TerritoryId": 1189,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Yak T'el - Iq Br'aax"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1189,
- "AetheryteShortcut": "Yak T'el - Iq Br'aax",
+ "Steps": [
+ {
+ "TerritoryId": 1189,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Yak T'el - Iq Br'aax"
+ }
+ ],
"FlyBetweenNodes": true,
"Groups": [
{
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1189,
- "AetheryteShortcut": "Yak T'el - Mamook",
+ "Steps": [
+ {
+ "TerritoryId": 1189,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Yak T'el - Mamook"
+ }
+ ],
"Groups": [
{
"Nodes": [
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza",
- "TerritoryId": 1189,
- "AetheryteShortcut": "Yak T'el - Iq Br'aax",
+ "Steps": [
+ {
+ "TerritoryId": 1189,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Yak T'el - Iq Br'aax"
+ }
+ ],
"Groups": [
{
"Nodes": [
"type": "string"
}
},
- "TerritoryId": {
- "type": "number"
- },
- "AetheryteShortcut": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
- },
- "AethernetShortcut": {
+ "Steps": {
"type": "array",
- "description": "A pair of aethernet locations (from + to) to use as a shortcut",
- "minItems": 2,
- "maxItems": 2,
"items": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/AethernetShard"
- }
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json#/$defs/Step"
+ },
+ "minItems": 1
},
"FlyBetweenNodes": {
"description": "If nodes are close enough together, flying makes no sense due to the pathfinding overhead",
"type": "object",
"properties": {
"Position": {
- "$ref": "#/$defs/Vector3"
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Vector3"
},
"MinimumAngle": {
"type": "number",
"required": [
"$schema",
"Author",
- "TerritoryId",
+ "Steps",
"Groups"
],
- "additionalProperties": false,
- "$defs": {
- "Vector3": {
- "type": "object",
- "description": "Position to (typically) walk to",
- "properties": {
- "X": {
- "type": "number"
- },
- "Y": {
- "type": "number"
- },
- "Z": {
- "type": "number"
- }
- },
- "required": [
- "X",
- "Y",
- "Z"
- ]
- }
- }
+ "additionalProperties": false
}
SeparatedList<ExpressionSyntax>(
SyntaxNodeList(
AssignmentList(nameof(GatheringRoot.Author), root.Author).AsSyntaxNodeOrToken(),
- Assignment(nameof(GatheringRoot.TerritoryId), root.TerritoryId, emptyRoot.TerritoryId)
- .AsSyntaxNodeOrToken(),
- Assignment(nameof(GatheringRoot.AetheryteShortcut), root.AetheryteShortcut,
- emptyRoot.AetheryteShortcut)
- .AsSyntaxNodeOrToken(),
- Assignment(nameof(GatheringRoot.AethernetShortcut), root.AethernetShortcut,
- emptyRoot.AethernetShortcut)
+ AssignmentList(nameof(GatheringRoot.Steps), root.Steps)
.AsSyntaxNodeOrToken(),
Assignment(nameof(GatheringRoot.FlyBetweenNodes), root.FlyBetweenNodes,
emptyRoot.FlyBetweenNodes)
{
"Sequence": 0,
"Steps": [
+ {
+ "TerritoryId": 886,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Ishgard",
+ "AethernetShortcut": [
+ "[Ishgard] Aetheryte Plaza",
+ "[Ishgard] Firmament"
+ ],
+ "SkipConditions": {
+ "AetheryteShortcutIf": {
+ "InTerritory": [
+ 886
+ ]
+ },
+ "AethernetShortcutIf": {
+ "InSameTerritory": true
+ }
+ }
+ },
{
"DataId": 1035211,
"Position": {
},
"TerritoryId": 886,
"InteractionType": "Interact",
- "AetheryteShortcut": "Ishgard",
"AethernetShortcut": [
- "[Ishgard] Aetheryte Plaza",
- "[Ishgard] Firmament"
+ "[Firmament] The Mendicant's Court",
+ "[Firmament] Western Risensong Quarter"
],
"DialogueChoices": [
{
{
"Sequence": 0,
"Steps": [
+ {
+ "TerritoryId": 886,
+ "InteractionType": "None",
+ "AetheryteShortcut": "Ishgard",
+ "AethernetShortcut": [
+ "[Ishgard] Aetheryte Plaza",
+ "[Ishgard] Firmament"
+ ],
+ "SkipConditions": {
+ "AetheryteShortcutIf": {
+ "InTerritory": [
+ 886
+ ]
+ },
+ "AethernetShortcutIf": {
+ "InSameTerritory": true
+ }
+ }
+ },
{
"DataId": 1033543,
"Position": {
},
"TerritoryId": 886,
"InteractionType": "Interact",
- "AetheryteShortcut": "Ishgard",
"AethernetShortcut": [
- "[Ishgard] Aetheryte Plaza",
- "[Ishgard] Firmament"
+ "[Firmament] The Mendicant's Court",
+ "[Firmament] The Mattock"
],
"DialogueChoices": [
{
"Steps": {
"type": "array",
"items": {
+ "$ref": "#/$defs/Step"
+ }
+ },
+ "Comment": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "Sequence"
+ ],
+ "additionalProperties": false
+ }
+ }
+ },
+ "required": [
+ "$schema",
+ "QuestSequence",
+ "Author"
+ ],
+ "additionalProperties": false,
+ "$defs": {
+ "Step": {
+ "type": "object",
+ "properties": {
+ "DataId": {
+ "type": "integer",
+ "description": "The data id of the NPC/Object/Aetheryte/Aether Current",
+ "exclusiveMinimum": 0
+ },
+ "Position": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Vector3"
+ },
+ "StopDistance": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "description": "Set if pathfinding should stop closer or further away from the default stop distance",
+ "exclusiveMinimum": 0
+ },
+ "IgnoreDistanceToObject": {
+ "type": "boolean",
+ "description": "Most interactions with objects are checked for a Y (height) difference of 2 in-game units. If set to true, the game won't attempt to get any closer if the height difference is larger than this."
+ },
+ "TerritoryId": {
+ "type": "integer",
+ "description": "The territory id associated with the location",
+ "exclusiveMinimum": 0
+ },
+ "TargetTerritoryId": {
+ "type": "integer",
+ "description": "If set, this step is complete (movement-wise) if this territory id is reached",
+ "exclusiveMinimum": 0
+ },
+ "InteractionType": {
+ "type": "string",
+ "description": "What to do at the position",
+ "enum": [
+ "None",
+ "Interact",
+ "WalkTo",
+ "AttuneAethernetShard",
+ "AttuneAetheryte",
+ "AttuneAetherCurrent",
+ "Combat",
+ "UseItem",
+ "EquipItem",
+ "EquipRecommended",
+ "Say",
+ "Emote",
+ "Action",
+ "WaitForNpcAtPosition",
+ "WaitForManualProgress",
+ "Duty",
+ "SinglePlayerDuty",
+ "Jump",
+ "Dive",
+ "Instruction",
+ "AcceptQuest",
+ "CompleteQuest",
+ "InitiateLeve"
+ ]
+ },
+ "Disabled": {
+ "description": "Whether this step is disabled (see SkipIf for more control)",
+ "type": "boolean"
+ },
+ "DisableNavmesh": {
+ "description": "If true, will go to the position in a straight line instead of using pathfinding",
+ "type": "boolean"
+ },
+ "Mount": {
+ "type": [
+ "boolean",
+ "null"
+ ],
+ "description": "If true, will mount regardless of distance to position. If false, will unmount."
+ },
+ "Fly": {
+ "type": "boolean",
+ "description": "If true and flying is unlocked in a zone, will use a flight path"
+ },
+ "Land": {
+ "type": "boolean",
+ "description": "If true and flying, will attempt to land on the ground"
+ },
+ "Sprint": {
+ "type": [
+ "boolean",
+ "null"
+ ]
+ },
+ "AetheryteShortcut": {
+ "description": "The Aetheryte to teleport to (before moving)",
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
+ },
+ "AethernetShortcut": {
+ "type": "array",
+ "description": "A pair of aethernet locations (from + to) to use as a shortcut",
+ "minItems": 2,
+ "maxItems": 2,
+ "items": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/AethernetShard"
+ }
+ },
+ "ItemId": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "description": "The Item to use",
+ "exclusiveMinimum": 0
+ },
+ "SkipConditions": {
+ "type": "object",
+ "properties": {
+ "StepIf": {
"type": "object",
"properties": {
- "DataId": {
- "type": "integer",
- "description": "The data id of the NPC/Object/Aetheryte/Aether Current",
- "exclusiveMinimum": 0
- },
- "Position": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Vector3"
- },
- "StopDistance": {
- "type": [
- "number",
- "null"
- ],
- "description": "Set if pathfinding should stop closer or further away from the default stop distance",
- "exclusiveMinimum": 0
- },
- "IgnoreDistanceToObject": {
- "type": "boolean",
- "description": "Most interactions with objects are checked for a Y (height) difference of 2 in-game units. If set to true, the game won't attempt to get any closer if the height difference is larger than this."
- },
- "TerritoryId": {
- "type": "integer",
- "description": "The territory id associated with the location",
- "exclusiveMinimum": 0
+ "Never": {
+ "type": "boolean"
},
- "TargetTerritoryId": {
- "type": "integer",
- "description": "If set, this step is complete (movement-wise) if this territory id is reached",
- "exclusiveMinimum": 0
+ "CompletionQuestVariablesFlags": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/CompletionFlags"
},
- "InteractionType": {
+ "Flying": {
"type": "string",
- "description": "What to do at the position",
"enum": [
- "None",
- "Interact",
- "WalkTo",
- "AttuneAethernetShard",
- "AttuneAetheryte",
- "AttuneAetherCurrent",
- "Combat",
- "UseItem",
- "EquipItem",
- "EquipRecommended",
- "Say",
- "Emote",
- "Action",
- "WaitForNpcAtPosition",
- "WaitForManualProgress",
- "Duty",
- "SinglePlayerDuty",
- "Jump",
- "Dive",
- "Instruction",
- "AcceptQuest",
- "CompleteQuest",
- "InitiateLeve"
+ "Locked",
+ "Unlocked"
]
},
- "Disabled": {
- "description": "Whether this step is disabled (see SkipIf for more control)",
- "type": "boolean"
+ "Chocobo": {
+ "type": "string",
+ "enum": [
+ "Locked",
+ "Unlocked"
+ ]
},
- "DisableNavmesh": {
- "description": "If true, will go to the position in a straight line instead of using pathfinding",
+ "NotTargetable": {
"type": "boolean"
},
- "Mount": {
- "type": [
- "boolean",
- "null"
- ],
- "description": "If true, will mount regardless of distance to position. If false, will unmount."
- },
- "Fly": {
- "type": "boolean",
- "description": "If true and flying is unlocked in a zone, will use a flight path"
+ "InTerritory": {
+ "type": "array",
+ "items": {
+ "type": "integer"
+ }
},
- "Land": {
- "type": "boolean",
- "description": "If true and flying, will attempt to land on the ground"
+ "NotInTerritory": {
+ "type": "array",
+ "items": {
+ "type": "integer"
+ }
},
- "Sprint": {
- "type": [
- "boolean",
- "null"
- ]
+ "Item": {
+ "type": "object",
+ "properties": {
+ "NotInInventory": {
+ "type": "boolean"
+ }
+ }
},
- "AetheryteShortcut": {
- "description": "The Aetheryte to teleport to (before moving)",
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
+ "QuestsAccepted": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
},
- "AethernetShortcut": {
+ "QuestsCompleted": {
"type": "array",
- "description": "A pair of aethernet locations (from + to) to use as a shortcut",
- "minItems": 2,
- "maxItems": 2,
"items": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/AethernetShard"
+ "type": "number"
}
},
- "ItemId": {
- "type": [
- "number",
- "null"
- ],
- "description": "The Item to use",
- "exclusiveMinimum": 0
+ "AetheryteLocked": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
},
- "SkipConditions": {
+ "AetheryteUnlocked": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
+ },
+ "NearPosition": {
"type": "object",
"properties": {
- "StepIf": {
- "type": "object",
- "properties": {
- "Never": {
- "type": "boolean"
- },
- "CompletionQuestVariablesFlags": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/CompletionFlags"
- },
- "Flying": {
- "type": "string",
- "enum": [
- "Locked",
- "Unlocked"
- ]
- },
- "Chocobo": {
- "type": "string",
- "enum": [
- "Locked",
- "Unlocked"
- ]
- },
- "NotTargetable": {
- "type": "boolean"
- },
- "InTerritory": {
- "type": "array",
- "items": {
- "type": "integer"
- }
- },
- "NotInTerritory": {
- "type": "array",
- "items": {
- "type": "integer"
- }
- },
- "Item": {
- "type": "object",
- "properties": {
- "NotInInventory": {
- "type": "boolean"
- }
- }
- },
- "QuestsAccepted": {
- "type": "array",
- "items": {
- "type": "number"
- }
- },
- "QuestsCompleted": {
- "type": "array",
- "items": {
- "type": "number"
- }
- },
- "AetheryteLocked": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
- },
- "AetheryteUnlocked": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
- },
- "NearPosition": {
- "type": "object",
- "properties": {
- "Position": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Vector3"
- },
- "MaximumDistance": {
- "type": "number"
- }
- },
- "required": [
- "Position",
- "MaximumDistance"
- ],
- "additionalProperties": false
- },
- "ExtraCondition": {
- "type": "string",
- "enum": [
- "WakingSandsMainArea",
- "RisingStonesSolar"
- ]
- }
- },
- "additionalProperties": false
- },
- "AetheryteShortcutIf": {
- "type": "object",
- "properties": {
- "Never": {
- "type": "boolean"
- },
- "InSameTerritory": {
- "type": "boolean"
- },
- "InTerritory": {
- "type": "array",
- "items": {
- "type": "integer"
- }
- },
- "AetheryteLocked": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
- },
- "AetheryteUnlocked": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
- }
- },
- "additionalProperties": false
+ "Position": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Vector3"
},
- "AethernetShortcutIf": {
- "type": "object",
- "properties": {
- "Never": {
- "type": "boolean"
- },
- "InSameTerritory": {
- "type": "boolean"
- },
- "AetheryteLocked": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
- },
- "AetheryteUnlocked": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
- }
- },
- "additionalProperties": false
+ "MaximumDistance": {
+ "type": "number"
}
},
+ "required": [
+ "Position",
+ "MaximumDistance"
+ ],
"additionalProperties": false
},
- "CompletionQuestVariablesFlags": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/CompletionFlags"
+ "ExtraCondition": {
+ "type": "string",
+ "enum": [
+ "WakingSandsMainArea",
+ "RisingStonesSolar"
+ ]
+ }
+ },
+ "additionalProperties": false
+ },
+ "AetheryteShortcutIf": {
+ "type": "object",
+ "properties": {
+ "Never": {
+ "type": "boolean"
},
- "RequiredQuestVariables": {
- "type": "array",
- "description": "Certain quests (primarily beast tribes/allied societies) have a RNG element to spawning targets, and the step should be skipped in its entirety if none of the sets below match",
- "minItems": 6,
- "maxItems": 6,
- "items": {
- "type": [
- "array",
- "null"
- ],
- "items": {
- "type": [
- "number",
- "object"
- ],
- "properties": {
- "High": {
- "type": [
- "number",
- "null"
- ],
- "minimum": 0,
- "maximum": 15
- },
- "Low": {
- "type": [
- "number",
- "null"
- ],
- "minimum": 0,
- "maximum": 15
- }
- },
- "minimum": 0,
- "maximum": 255
- }
- }
+ "InSameTerritory": {
+ "type": "boolean"
},
- "RequiredGatheredItems": {
+ "InTerritory": {
"type": "array",
"items": {
- "type": "object",
- "properties": {
- "ItemId": {
- "type": "number"
- },
- "AlternativeItemId": {
- "description": "For leves that allow you to gather two items with different chance percentage, this is the preferred item if the gathering chance is 100% (after buffs)",
- "type": "number"
- },
- "ItemCount": {
- "type": "number",
- "exclusiveMinimum": 0
- },
- "Collectability": {
- "type": "number",
- "minimum": 0,
- "maximum": 1000
- }
- },
- "required": [
- "ItemId",
- "ItemCount"
- ]
+ "type": "integer"
}
},
- "DelaySecondsAtStart": {
- "description": "Time to wait before starting",
+ "AetheryteLocked": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
+ },
+ "AetheryteUnlocked": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
+ }
+ },
+ "additionalProperties": false
+ },
+ "AethernetShortcutIf": {
+ "type": "object",
+ "properties": {
+ "Never": {
+ "type": "boolean"
+ },
+ "InSameTerritory": {
+ "type": "boolean"
+ },
+ "AetheryteLocked": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
+ },
+ "AetheryteUnlocked": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ },
+ "CompletionQuestVariablesFlags": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/CompletionFlags"
+ },
+ "RequiredQuestVariables": {
+ "type": "array",
+ "description": "Certain quests (primarily beast tribes/allied societies) have a RNG element to spawning targets, and the step should be skipped in its entirety if none of the sets below match",
+ "minItems": 6,
+ "maxItems": 6,
+ "items": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "type": [
+ "number",
+ "object"
+ ],
+ "properties": {
+ "High": {
"type": [
"number",
"null"
- ]
+ ],
+ "minimum": 0,
+ "maximum": 15
},
- "Comment": {
- "type": "string"
+ "Low": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0,
+ "maximum": 15
}
},
- "required": [
- "TerritoryId",
- "InteractionType"
- ],
- "allOf": [
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "Interact"
- }
+ "minimum": 0,
+ "maximum": 255
+ }
+ }
+ },
+ "RequiredGatheredItems": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "ItemId": {
+ "type": "number"
+ },
+ "AlternativeItemId": {
+ "description": "For leves that allow you to gather two items with different chance percentage, this is the preferred item if the gathering chance is 100% (after buffs)",
+ "type": "number"
+ },
+ "ItemCount": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "Collectability": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 1000
+ }
+ },
+ "required": [
+ "ItemId",
+ "ItemCount"
+ ]
+ }
+ },
+ "DelaySecondsAtStart": {
+ "description": "Time to wait before starting",
+ "type": [
+ "number",
+ "null"
+ ]
+ },
+ "Comment": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "TerritoryId",
+ "InteractionType"
+ ],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "Interact"
+ }
+ }
+ },
+ "then": {
+ "required": [
+ "DataId"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "WalkTo"
+ }
+ }
+ },
+ "then": {
+ "required": [
+ "Position"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "AttuneAetheryte"
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "Aetheryte": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
+ },
+ "DataId": {
+ "type": "null"
+ },
+ "Position": {
+ "type": "null"
+ }
+ },
+ "required": [
+ "Aetheryte"
+ ]
+ },
+ "else": {
+ "properties": {
+ "Aetheryte": {
+ "type": "null"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "AttuneAethernetShard"
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "AethernetShard": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/AethernetShard"
+ },
+ "DataId": {
+ "type": "null"
+ },
+ "Position": {
+ "type": "null"
+ }
+ },
+ "required": [
+ "AethernetShard"
+ ]
+ },
+ "else": {
+ "properties": {
+ "AethernetShard": {
+ "type": "null"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "AttuneAetherCurrent"
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "AetherCurrentId": {
+ "type": "integer",
+ "description": "The aether current id, used to check if a given aetheryte is unlocked",
+ "exclusiveMinimum": 0
+ }
+ },
+ "required": [
+ "DataId",
+ "Position",
+ "AetherCurrentId"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "Combat"
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "EnemySpawnType": {
+ "type": "string",
+ "description": "Determines how enemy spawning is handled in combat locations",
+ "enum": [
+ "AutoOnEnterArea",
+ "AfterInteraction",
+ "AfterItemUse",
+ "OverworldEnemies"
+ ]
+ },
+ "KillEnemyDataIds": {
+ "description": "The enemy data ids which are supposed to be killed",
+ "type": "array",
+ "items": {
+ "type": "integer"
+ }
+ },
+ "ComplexCombatData": {
+ "description": "If multiple different enemies are supposed to be killed in a single quest step, this typically is handled via items",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "DataId": {
+ "description": "The enemy data id which is supposed to be killed",
+ "type": "integer"
+ },
+ "MinimumKillCount": {
+ "description": "Overworld mobs: If this number of mobs has been killed, will wait a bit before attempting to pull another mob to see if the quest progresses",
+ "type": "integer"
+ },
+ "RewardItemId": {
+ "type": "integer"
+ },
+ "RewardItemCount": {
+ "type": "integer"
+ },
+ "CompletionQuestVariablesFlags": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/CompletionFlags"
+ },
+ "IgnoreQuestMarker": {
+ "type": "boolean"
}
},
- "then": {
- "required": [
- "DataId"
- ]
+ "required": [
+ "DataId"
+ ]
+ }
+ },
+ "CombatDelaySecondsAtStart": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "Position",
+ "EnemySpawnType"
+ ],
+ "oneOf": [
+ {
+ "required": [
+ "KillEnemyDataIds"
+ ]
+ },
+ {
+ "required": [
+ "ComplexCombatData"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "UseItem"
+ },
+ "ItemId": {
+ "not": {
+ "const": 30362
+ }
+ }
+ }
+ },
+ "then": {
+ "required": [
+ "Position"
+ ]
+ }
+ },
+ {
+ "if": {
+ "anyOf": [
+ {
+ "properties": {
+ "InteractionType": {
+ "const": "UseItem"
}
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "WalkTo"
- }
- }
+ }
+ },
+ {
+ "properties": {
+ "InteractionType": {
+ "const": "Combat"
},
- "then": {
- "required": [
- "Position"
- ]
+ "EnemySpawnType": {
+ "const": "AfterItemUse"
+ }
+ }
+ }
+ ]
+ },
+ "then": {
+ "properties": {
+ "GroundTarget": {
+ "type": [
+ "boolean",
+ "null"
+ ],
+ "default": false
+ }
+ },
+ "required": [
+ "ItemId"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "EquipItem"
+ }
+ }
+ },
+ "then": {
+ "required": [
+ "ItemId"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "anyOf": [
+ {
+ "const": "Emote"
+ },
+ {
+ "const": "AcceptQuest"
+ },
+ {
+ "const": "CompleteQuest"
+ },
+ {
+ "const": "SinglePlayerDuty"
+ }
+ ]
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "Emote": {
+ "type": "string",
+ "description": "The emote to use",
+ "enum": [
+ "stretch",
+ "wave",
+ "rally",
+ "deny",
+ "pray",
+ "slap",
+ "doubt",
+ "psych",
+ "cheer",
+ "happy",
+ "poke",
+ "flex",
+ "soothe",
+ "me",
+ "welcome",
+ "imperialsalute",
+ "pet",
+ "dance",
+ "respect",
+ "lookout",
+ "kneel",
+ "bow",
+ "uchiwasshoi",
+ "clap",
+ "victorypose"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "Emote"
+ }
+ }
+ },
+ "then": {
+ "required": [
+ "Position",
+ "Emote"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "anyOf": [
+ {
+ "const": "Say"
+ },
+ {
+ "const": "CompleteQuest"
+ }
+ ]
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "ChatMessage": {
+ "type": "object",
+ "description": "The text to use with /say",
+ "properties": {
+ "ExcelSheet": {
+ "type": "string"
+ },
+ "Key": {
+ "type": "string"
}
},
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "AttuneAetheryte"
- }
- }
+ "required": [
+ "Key"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "Say"
+ }
+ }
+ },
+ "then": {
+ "required": [
+ "ChatMessage"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "Action"
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "Action": {
+ "type": "string",
+ "description": "The action to use",
+ "enum": [
+ "Cure",
+ "Esuna",
+ "Physick",
+ "Buffet",
+ "Fumigate",
+ "Siphon Snout",
+ "Red Gulal",
+ "Yellow Gulal",
+ "Blue Gulal"
+ ]
+ }
+ },
+ "required": [
+ "Action"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "Jump"
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "JumpDestination": {
+ "type": "object",
+ "properties": {
+ "Position": {
+ "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Vector3"
},
- "then": {
- "properties": {
- "Aetheryte": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
- },
- "DataId": {
- "type": "null"
- },
- "Position": {
- "type": "null"
- }
- },
- "required": [
- "Aetheryte"
+ "StopDistance": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "description": "Set if pathfinding should stop closer or further away from the default stop distance",
+ "exclusiveMinimum": 0
+ },
+ "DelaySeconds": {
+ "type": [
+ "number",
+ "null"
]
},
- "else": {
- "properties": {
- "Aetheryte": {
- "type": "null"
- }
- }
+ "Type": {
+ "type": "string",
+ "enum": [
+ "SingleJump",
+ "RepeatedJumps"
+ ],
+ "default": "SingleJump"
}
},
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "AttuneAethernetShard"
- }
- }
+ "required": [
+ "Position"
+ ]
+ }
+ },
+ "required": [
+ "Position",
+ "JumpDestination"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "anyOf": [
+ {
+ "const": "Interact"
},
- "then": {
- "properties": {
- "AethernetShard": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/AethernetShard"
- },
- "DataId": {
- "type": "null"
- },
- "Position": {
- "type": "null"
- }
- },
- "required": [
- "AethernetShard"
- ]
+ {
+ "const": "SinglePlayerDuty"
},
- "else": {
- "properties": {
- "AethernetShard": {
- "type": "null"
- }
- }
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "AttuneAetherCurrent"
- }
- }
+ {
+ "const": "WaitForManualProgress"
},
- "then": {
- "properties": {
- "AetherCurrentId": {
- "type": "integer",
- "description": "The aether current id, used to check if a given aetheryte is unlocked",
- "exclusiveMinimum": 0
- }
- },
- "required": [
- "DataId",
- "Position",
- "AetherCurrentId"
- ]
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "Combat"
- }
- }
+ {
+ "const": "AcceptQuest"
},
- "then": {
- "properties": {
- "EnemySpawnType": {
- "type": "string",
- "description": "Determines how enemy spawning is handled in combat locations",
- "enum": [
- "AutoOnEnterArea",
- "AfterInteraction",
- "AfterItemUse",
- "OverworldEnemies"
- ]
- },
- "KillEnemyDataIds": {
- "description": "The enemy data ids which are supposed to be killed",
- "type": "array",
- "items": {
- "type": "integer"
- }
- },
- "ComplexCombatData": {
- "description": "If multiple different enemies are supposed to be killed in a single quest step, this typically is handled via items",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "DataId": {
- "description": "The enemy data id which is supposed to be killed",
- "type": "integer"
- },
- "MinimumKillCount": {
- "description": "Overworld mobs: If this number of mobs has been killed, will wait a bit before attempting to pull another mob to see if the quest progresses",
- "type": "integer"
- },
- "RewardItemId": {
- "type": "integer"
- },
- "RewardItemCount": {
- "type": "integer"
- },
- "CompletionQuestVariablesFlags": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/CompletionFlags"
- },
- "IgnoreQuestMarker": {
- "type": "boolean"
- }
- },
- "required": [
- "DataId"
- ]
- }
- },
- "CombatDelaySecondsAtStart": {
- "type": "number"
- }
- },
- "required": [
- "Position",
- "EnemySpawnType"
- ],
- "oneOf": [
- {
- "required": [
- "KillEnemyDataIds"
- ]
- },
- {
- "required": [
- "ComplexCombatData"
- ]
- }
- ]
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "UseItem"
- },
- "ItemId": {
- "not": {
- "const": 30362
- }
- }
- }
+ {
+ "const": "CompleteQuest"
},
- "then": {
- "required": [
- "Position"
- ]
- }
- },
- {
- "if": {
- "anyOf": [
- {
- "properties": {
- "InteractionType": {
- "const": "UseItem"
- }
- }
- },
- {
- "properties": {
- "InteractionType": {
- "const": "Combat"
- },
- "EnemySpawnType": {
- "const": "AfterItemUse"
- }
- }
- }
- ]
+ {
+ "const": "Instruction"
},
- "then": {
- "properties": {
- "GroundTarget": {
- "type": [
- "boolean",
- "null"
- ],
- "default": false
- }
- },
- "required": [
- "ItemId"
- ]
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "EquipItem"
- }
- }
+ {
+ "const": "Say"
},
- "then": {
- "required": [
- "ItemId"
- ]
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "anyOf": [
- {
- "const": "Emote"
- },
- {
- "const": "AcceptQuest"
- },
- {
- "const": "CompleteQuest"
- },
- {
- "const": "SinglePlayerDuty"
- }
- ]
- }
- }
+ {
+ "const": "Emote"
},
- "then": {
- "properties": {
- "Emote": {
- "type": "string",
- "description": "The emote to use",
- "enum": [
- "stretch",
- "wave",
- "rally",
- "deny",
- "pray",
- "slap",
- "doubt",
- "psych",
- "cheer",
- "happy",
- "poke",
- "flex",
- "soothe",
- "me",
- "welcome",
- "imperialsalute",
- "pet",
- "dance",
- "respect",
- "lookout",
- "kneel",
- "bow",
- "uchiwasshoi",
- "clap",
- "victorypose"
- ]
- }
- }
+ {
+ "const": "UseItem"
}
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "Emote"
- }
+ ]
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "DialogueChoices": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "Type": {
+ "type": "string",
+ "enum": [
+ "YesNo",
+ "List"
+ ]
+ },
+ "ExcelSheet": {
+ "type": "string"
}
},
- "then": {
- "required": [
- "Position",
- "Emote"
- ]
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "anyOf": [
- {
- "const": "Say"
- },
- {
- "const": "CompleteQuest"
+ "required": [
+ "Type"
+ ],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "Type": {
+ "const": "YesNo"
}
- ]
- }
- }
- },
- "then": {
- "properties": {
- "ChatMessage": {
- "type": "object",
- "description": "The text to use with /say",
+ }
+ },
+ "then": {
"properties": {
- "ExcelSheet": {
- "type": "string"
+ "Prompt": {
+ "type": [
+ "string",
+ "integer"
+ ]
},
- "Key": {
- "type": "string"
+ "Yes": {
+ "type": "boolean",
+ "default": true
}
},
"required": [
- "Key"
- ]
- }
- }
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "Say"
- }
- }
- },
- "then": {
- "required": [
- "ChatMessage"
- ]
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "Action"
- }
- }
- },
- "then": {
- "properties": {
- "Action": {
- "type": "string",
- "description": "The action to use",
- "enum": [
- "Cure",
- "Esuna",
- "Physick",
- "Buffet",
- "Fumigate",
- "Siphon Snout",
- "Red Gulal",
- "Yellow Gulal",
- "Blue Gulal"
+ "Prompt",
+ "Yes"
]
}
},
- "required": [
- "Action"
- ]
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "Jump"
- }
- }
- },
- "then": {
- "properties": {
- "JumpDestination": {
- "type": "object",
+ {
+ "if": {
"properties": {
- "Position": {
- "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Vector3"
- },
- "StopDistance": {
+ "Type": {
+ "const": "List"
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "Prompt": {
"type": [
- "number",
+ "string",
+ "integer",
"null"
- ],
- "description": "Set if pathfinding should stop closer or further away from the default stop distance",
- "exclusiveMinimum": 0
+ ]
},
- "DelaySeconds": {
+ "Answer": {
"type": [
- "number",
- "null"
+ "string",
+ "integer"
]
- },
- "Type": {
- "type": "string",
- "enum": [
- "SingleJump",
- "RepeatedJumps"
- ],
- "default": "SingleJump"
}
},
"required": [
- "Position"
- ]
- }
- },
- "required": [
- "Position",
- "JumpDestination"
- ]
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "anyOf": [
- {
- "const": "Interact"
- },
- {
- "const": "SinglePlayerDuty"
- },
- {
- "const": "WaitForManualProgress"
- },
- {
- "const": "AcceptQuest"
- },
- {
- "const": "CompleteQuest"
- },
- {
- "const": "Instruction"
- },
- {
- "const": "Say"
- },
- {
- "const": "Emote"
- },
- {
- "const": "UseItem"
- }
+ "Prompt",
+ "Answer"
]
}
}
- },
- "then": {
- "properties": {
- "DialogueChoices": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "Type": {
- "type": "string",
- "enum": [
- "YesNo",
- "List"
- ]
- },
- "ExcelSheet": {
- "type": "string"
- }
- },
- "required": [
- "Type"
- ],
- "allOf": [
- {
- "if": {
- "properties": {
- "Type": {
- "const": "YesNo"
- }
- }
- },
- "then": {
- "properties": {
- "Prompt": {
- "type": [
- "string",
- "integer"
- ]
- },
- "Yes": {
- "type": "boolean",
- "default": true
- }
- },
- "required": [
- "Prompt",
- "Yes"
- ]
- }
- },
- {
- "if": {
- "properties": {
- "Type": {
- "const": "List"
- }
- }
- },
- "then": {
- "properties": {
- "Prompt": {
- "type": [
- "string",
- "integer",
- "null"
- ]
- },
- "Answer": {
- "type": [
- "string",
- "integer"
- ]
- }
- },
- "required": [
- "Prompt",
- "Answer"
- ]
- }
- }
- ]
- }
- },
- "PointMenuChoices": {
- "type": "array",
- "items": {
- "type": "integer",
- "minimum": 0
- }
- }
- }
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "Duty"
- }
- }
- },
- "then": {
- "properties": {
- "ContentFinderConditionId": {
- "type": "integer",
- "exclusiveMinimum": 0,
- "exclusiveMaximum": 3000
- },
- "DataId": {
- "type": "null"
- },
- "Position": {
- "type": "null"
- }
- },
- "required": [
- "ContentFinderConditionId"
- ]
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "WaitForNpcAtPosition"
- }
- }
- },
- "then": {
- "properties": {
- "NpcWaitDistance": {
- "type": "number",
- "exclusiveMinimum": 0
- }
- }
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "AcceptQuest"
- }
- }
- },
- "then": {
- "properties": {
- "PickUpQuestId": {
- "type": [
- "null",
- "number",
- "string"
- ],
- "description": "Determines the quest which should be accepted. If empty/null, accepts the quest corresponding to the file name."
- }
- }
- }
- },
- {
- "if": {
- "properties": {
- "InteractionType": {
- "const": "CompleteQuest"
- }
- }
- },
- "then": {
- "properties": {
- "TurnInQuestId": {
- "type": [
- "null",
- "number",
- "string"
- ],
- "description": "Determines the quest which should be turned in. If empty/null, turns in the quest corresponding to the file name."
- },
- "NextQuestId": {
- "type": [
- "null",
- "number",
- "string"
- ],
- "description": "For quest chains (e.g. DT healer role quests) Which quest to do next, given that you meet the required level."
- }
- }
- }
+ ]
}
- ],
- "not": {
- "anyOf": [
- {
- "required": [
- "SkipIf"
- ]
- }
- ]
+ },
+ "PointMenuChoices": {
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "minimum": 0
+ }
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "Duty"
}
}
},
- "Comment": {
- "type": "string"
+ "then": {
+ "properties": {
+ "ContentFinderConditionId": {
+ "type": "integer",
+ "exclusiveMinimum": 0,
+ "exclusiveMaximum": 3000
+ },
+ "DataId": {
+ "type": "null"
+ },
+ "Position": {
+ "type": "null"
+ }
+ },
+ "required": [
+ "ContentFinderConditionId"
+ ]
}
},
- "required": [
- "Sequence"
- ],
- "additionalProperties": false
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "WaitForNpcAtPosition"
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "NpcWaitDistance": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "AcceptQuest"
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "PickUpQuestId": {
+ "type": [
+ "null",
+ "number",
+ "string"
+ ],
+ "description": "Determines the quest which should be accepted. If empty/null, accepts the quest corresponding to the file name."
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "CompleteQuest"
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "TurnInQuestId": {
+ "type": [
+ "null",
+ "number",
+ "string"
+ ],
+ "description": "Determines the quest which should be turned in. If empty/null, turns in the quest corresponding to the file name."
+ },
+ "NextQuestId": {
+ "type": [
+ "null",
+ "number",
+ "string"
+ ],
+ "description": "For quest chains (e.g. DT healer role quests) Which quest to do next, given that you meet the required level."
+ }
+ }
+ }
+ }
+ ],
+ "not": {
+ "anyOf": [
+ {
+ "required": [
+ "SkipIf"
+ ]
+ }
+ ]
}
}
- },
- "required": [
- "$schema",
- "QuestSequence",
- "Author"
- ],
- "additionalProperties": false
+ }
}
IshgardGatesOfJudgement = 88,
IshgardFirmament = 100001,
+ FirmamentMendicantsCourt = 2011373,
+ FirmamentMattock = 2011374,
+ FirmamentNewNest = 2011384,
+ FirmanentSaintRoellesDais = 2011385,
+ FirmamentFeatherfall = 2011386,
+ FirmamentHoarfrostHall = 2011387,
+ FirmamentWesternRisensongQuarter = 2011388,
+ FIrmamentEasternRisensongQuarter = 2011389,
+
Idyllshire = 75,
IdyllshireWest = 90,
IdyllshirePrologueGate = 91,
LivingMemoryLeynodePyro = 214,
LivingMemoryLeynodeAero = 215,
}
+
+public static class EAetheryteLocationExtensions
+{
+ public static bool IsFirmamentAetheryte(this EAetheryteLocation aetheryteLocation) =>
+ aetheryteLocation is EAetheryteLocation.IshgardFirmament
+ or EAetheryteLocation.FirmamentMendicantsCourt
+ or EAetheryteLocation.FirmamentMattock
+ or EAetheryteLocation.FirmamentNewNest
+ or EAetheryteLocation.FirmanentSaintRoellesDais
+ or EAetheryteLocation.FirmamentFeatherfall
+ or EAetheryteLocation.FirmamentHoarfrostHall
+ or EAetheryteLocation.FirmamentWesternRisensongQuarter
+ or EAetheryteLocation.FIrmamentEasternRisensongQuarter;
+}
using System.Text.Json.Serialization;
using Questionable.Model.Common;
using Questionable.Model.Common.Converter;
+using Questionable.Model.Questing;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Gathering;
{
[JsonConverter(typeof(StringListOrValueConverter))]
public List<string> Author { get; set; } = [];
- public ushort TerritoryId { get; set; }
- [JsonConverter(typeof(AetheryteConverter))]
- public EAetheryteLocation? AetheryteShortcut { get; set; }
-
- public AethernetShortcut? AethernetShortcut { get; set; }
+ public List<QuestStep> Steps { get; set; } = [];
public bool? FlyBetweenNodes { get; set; }
public List<GatheringNodeGroup> Groups { get; set; } = [];
}
{ EAetheryteLocation.IshgardGatesOfJudgement, "[Ishgard] The Gates of Judgement (Coerthas Central Highlands)" },
{ EAetheryteLocation.IshgardFirmament, "[Ishgard] Firmament" },
+ { EAetheryteLocation.FirmamentMendicantsCourt, "[Firmament] The Mendicant's Court" },
+ { EAetheryteLocation.FirmamentMattock, "[Firmament] The Mattock" },
+ { EAetheryteLocation.FirmamentNewNest, "[Firmament] The New Nest" },
+ { EAetheryteLocation.FirmanentSaintRoellesDais, "[Firmament] Saint Roelle's Dais" },
+ { EAetheryteLocation.FirmamentFeatherfall, "[Firmament] Featherfall" },
+ { EAetheryteLocation.FirmamentHoarfrostHall, "[Firmament] Hoarfrost Hall" },
+ { EAetheryteLocation.FirmamentWesternRisensongQuarter, "[Firmament] Western Risensong Quarter" },
+ { EAetheryteLocation.FIrmamentEasternRisensongQuarter, "[Firmament] Eastern Risensong Quarter" },
+
{ EAetheryteLocation.Idyllshire, "[Idyllshire] Aetheryte Plaza" },
{ EAetheryteLocation.IdyllshireWest, "[Idyllshire] West Idyllshire" },
{ EAetheryteLocation.IdyllshirePrologueGate, "[Idyllshire] Prologue Gate (Western Hinterlands)" },
"[Ishgard] The Last Vigil",
"[Ishgard] The Gates of Judgement (Coerthas Central Highlands)",
"[Ishgard] Firmament",
+ "[Firmament] The Mendicant's Court",
+ "[Firmament] The Mattock",
+ "[Firmament] The New Nest",
+ "[Firmament] Saint Roelle's Dais",
+ "[Firmament] Featherfall",
+ "[Firmament] Hoarfrost Hall",
+ "[Firmament] Western Risensong Quarter",
+ "[Firmament] Eastern Risensong Quarter",
"[Idyllshire] Aetheryte Plaza",
"[Idyllshire] West Idyllshire",
"[Idyllshire] Prologue Gate (Western Hinterlands)",
using Questionable.Data;
using Questionable.Functions;
using Questionable.Model;
+using Questionable.Model.Common;
using Questionable.Model.Questing;
+using AethernetShortcut = Questionable.Controller.Steps.Shared.AethernetShortcut;
using Quest = Questionable.Model.Quest;
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "HousingSelectBlock", HousingSelectBlockPostSetup);
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "JournalResult", JournalResultPostSetup);
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "GuildLeve", GuildLevePostSetup);
+ _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "TelepotTown", TeleportTownPostSetup);
}
private bool ShouldHandleUiInteractions => _isInitialCheck || _questController.IsRunning;
addon->Close(true);
}
+ private void TeleportTownPostSetup(AddonEvent type, AddonArgs args)
+ {
+ if (ShouldHandleUiInteractions &&
+ _questController.HasCurrentTaskMatching(out AethernetShortcut.UseAethernetShortcut? aethernetShortcut) &&
+ aethernetShortcut.From.IsFirmamentAetheryte())
+ {
+ // this might be better via atkvalues; but this works for now
+ uint toIndex = aethernetShortcut.To switch
+ {
+ EAetheryteLocation.FirmamentMendicantsCourt => 0,
+ EAetheryteLocation.FirmamentMattock => 1,
+ EAetheryteLocation.FirmamentNewNest => 2,
+ EAetheryteLocation.FirmanentSaintRoellesDais => 3,
+ EAetheryteLocation.FirmamentFeatherfall => 4,
+ EAetheryteLocation.FirmamentHoarfrostHall => 5,
+ EAetheryteLocation.FirmamentWesternRisensongQuarter => 6,
+ EAetheryteLocation.FIrmamentEasternRisensongQuarter => 7,
+ _ => uint.MaxValue,
+ };
+
+ if (toIndex == uint.MaxValue)
+ return;
+
+ _logger.LogInformation("Teleporting to {ToName} with menu index {ToIndex}", aethernetShortcut.From,
+ toIndex);
+ unsafe
+ {
+ var teleportToDestination = stackalloc AtkValue[]
+ {
+ new() { Type = ValueType.Int, Int = 11 },
+ new() { Type = ValueType.UInt, UInt = toIndex }
+ };
+
+ var addon = (AtkUnitBase*)args.Addon;
+ addon->FireCallback(2, teleportToDestination);
+ addon->FireCallback(2, teleportToDestination, true);
+ }
+ }
+ }
+
private StringOrRegex? ResolveReference(Quest? quest, string? excelSheet, ExcelRef? excelRef, bool isRegExp)
{
if (excelRef == null)
public void Dispose()
{
+ _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "TelepotTown", TeleportTownPostSetup);
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "GuildLeve", GuildLevePostSetup);
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "JournalResult", JournalResultPostSetup);
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "HousingSelectBlock", HousingSelectBlockPostSetup);
if (currentNode == null)
return;
+ ushort territoryId = _currentRequest.Root.Steps.Last().TerritoryId;
_taskQueue.Enqueue(_serviceProvider.GetRequiredService<MountTask>()
- .With(_currentRequest.Root.TerritoryId, MountTask.EMountIf.Always));
+ .With(territoryId, MountTask.EMountIf.Always));
bool fly = currentNode.Fly.GetValueOrDefault(_currentRequest.Root.FlyBetweenNodes.GetValueOrDefault(true)) &&
- _gameFunctions.IsFlyingUnlocked(_currentRequest.Root.TerritoryId);
+ _gameFunctions.IsFlyingUnlocked(territoryId);
if (currentNode.Locations.Count > 1)
{
Vector3 averagePosition = new Vector3
pointOnFloor = pointOnFloor.Value with { Y = pointOnFloor.Value.Y + (fly ? 3f : 0f) };
_taskQueue.Enqueue(_serviceProvider.GetRequiredService<Move.MoveInternal>()
- .With(_currentRequest.Root.TerritoryId, pointOnFloor ?? averagePosition, 50f, fly: fly,
+ .With(territoryId, pointOnFloor ?? averagePosition, 50f, fly: fly,
ignoreDistanceToObject: true));
}
_taskQueue.Enqueue(_serviceProvider.GetRequiredService<MoveToLandingLocation>()
- .With(_currentRequest.Root.TerritoryId, fly, currentNode));
+ .With(territoryId, fly, currentNode));
_taskQueue.Enqueue(_serviceProvider.GetRequiredService<Interact.DoInteract>()
.With(currentNode.DataId, null, EInteractionType.InternalGather, true));
private readonly IToastGui _toastGui;
private readonly Configuration _configuration;
private readonly YesAlreadyIpc _yesAlreadyIpc;
- private readonly IReadOnlyList<ITaskFactory> _taskFactories;
+ private readonly TaskCreator _taskCreator;
private readonly object _progressLock = new();
IToastGui toastGui,
Configuration configuration,
YesAlreadyIpc yesAlreadyIpc,
- IEnumerable<ITaskFactory> taskFactories)
+ TaskCreator taskCreator)
: base(chatGui, logger)
{
_clientState = clientState;
_toastGui = toastGui;
_configuration = configuration;
_yesAlreadyIpc = yesAlreadyIpc;
- _taskFactories = taskFactories.ToList().AsReadOnly();
+ _taskCreator = taskCreator;
_condition.ConditionChange += OnConditionChange;
_toastGui.Toast += OnNormalToast;
try
{
- var newTasks = _taskFactories
- .SelectMany(x =>
- {
- IList<ITask> tasks = x.CreateAllTasks(CurrentQuest.Quest, seq, step).ToList();
-
- if (tasks.Count > 0 && _logger.IsEnabled(LogLevel.Trace))
- {
- string factoryName = x.GetType().FullName ?? x.GetType().Name;
- if (factoryName.Contains('.', StringComparison.Ordinal))
- factoryName = factoryName[(factoryName.LastIndexOf('.') + 1)..];
-
- _logger.LogTrace("Factory {FactoryName} created Task {TaskNames}",
- factoryName, string.Join(", ", tasks.Select(y => y.ToString())));
- }
-
- return tasks;
- })
- .ToList();
- if (newTasks.Count == 0)
- {
- _logger.LogInformation("Nothing to execute for step?");
- return;
- }
-
- _logger.LogInformation("Tasks for {QuestId}, {Sequence}, {Step}: {Tasks}",
- CurrentQuest.Quest.Id, seq.Sequence, seq.Steps.IndexOf(step),
- string.Join(", ", newTasks.Select(x => x.ToString())));
- foreach (var task in newTasks)
+ foreach (var task in _taskCreator.CreateTasks(CurrentQuest.Quest, seq, step))
_taskQueue.Enqueue(task);
}
catch (Exception e)
using System.Linq;
using System.Numerics;
using Dalamud.Game.ClientState.Conditions;
+using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Plugin.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
if (aetheryteData.CalculateDistance(playerPosition, territoryType, From) <
aetheryteData.CalculateDistance(playerPosition, territoryType, To))
{
- if (aetheryteData.CalculateDistance(playerPosition, territoryType, From) < 11)
+ if (aetheryteData.CalculateDistance(playerPosition, territoryType, From) < (From.IsFirmamentAetheryte() ? 11f : 4f))
{
- logger.LogInformation("Using lifestream to teleport to {Destination}", To);
- lifestreamIpc.Teleport(To);
-
- _teleported = true;
+ DoTeleport();
return true;
}
else if (From == EAetheryteLocation.SolutionNine)
}
}
- MoveTo(From);
+ MoveTo();
return true;
}
}
return false;
}
- private void MoveTo(EAetheryteLocation from)
+ private void MoveTo()
{
logger.LogInformation("Moving to aethernet shortcut");
_moving = true;
movementController.NavigateTo(EMovementType.Quest, (uint)From, aetheryteData.Locations[From],
false, true,
- AetheryteConverter.IsLargeAetheryte(From) ? 10.9f : 6.9f);
+ From.IsFirmamentAetheryte()
+ ? 4.4f
+ : AetheryteConverter.IsLargeAetheryte(From)
+ ? 10.9f
+ : 6.9f);
+ }
+
+ private void DoTeleport()
+ {
+ if (From.IsFirmamentAetheryte())
+ {
+ logger.LogInformation("Using manual teleport interaction");
+ _teleported = gameFunctions.InteractWith((uint)From, ObjectKind.EventObj);
+ }
+ else
+ {
+ logger.LogInformation("Using lifestream to teleport to {Destination}", To);
+ lifestreamIpc.Teleport(To);
+ _teleported = true;
+ }
}
public ETaskResult Update()
if (condition[ConditionFlag.Mounted])
{
_triedMounting = false;
- MoveTo(From);
+ MoveTo();
return ETaskResult.StillRunning;
}
else
if (!_teleported)
{
- logger.LogInformation("Using lifestream to teleport to {Destination}", To);
- lifestreamIpc.Teleport(To);
-
- _teleported = true;
+ DoTeleport();
return ETaskResult.StillRunning;
}
using System;
using System.Collections.Generic;
+using System.Linq;
using Dalamud.Game.Text;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game;
using LLib.GameData;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps.Common;
using Questionable.Data;
-using Questionable.GatheringPaths;
using Questionable.Model;
using Questionable.Model.Gathering;
using Questionable.Model.Questing;
IClientState clientState,
GatheringData gatheringData,
TerritoryData territoryData,
- AetheryteData aetheryteData) : ITaskFactory
+ ILogger<Factory> logger) : ITaskFactory
{
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
{
if (HasRequiredItems(requiredGatheredItems))
continue;
- if (gatheringRoot.AetheryteShortcut != null && clientState.TerritoryType != gatheringRoot.TerritoryId)
+ using (var _ = logger.BeginScope("Gathering(inner)"))
{
- ushort expectedTerritoryId = gatheringRoot.TerritoryId;
- if (gatheringRoot.AethernetShortcut != null)
- expectedTerritoryId = aetheryteData.TerritoryIds[gatheringRoot.AethernetShortcut.From];
-
- yield return serviceProvider.GetRequiredService<AetheryteShortcut.UseAetheryteShortcut>()
- .With(null, gatheringRoot.AetheryteShortcut.Value, expectedTerritoryId);
- }
-
- if (gatheringRoot.AethernetShortcut != null)
- {
- yield return serviceProvider.GetRequiredService<AethernetShortcut.UseAethernetShortcut>()
- .With(gatheringRoot.AethernetShortcut.From, gatheringRoot.AethernetShortcut.To);
+ QuestSequence gatheringSequence = new QuestSequence
+ {
+ Sequence = 0,
+ Steps = gatheringRoot.Steps
+ };
+ foreach (var gatheringStep in gatheringSequence.Steps)
+ {
+ foreach (var task in serviceProvider.GetRequiredService<TaskCreator>()
+ .CreateTasks(quest, gatheringSequence, gatheringStep))
+ if (task is not WaitAtEnd.NextStep)
+ yield return task;
+ }
}
- yield return new WaitConditionTask(() => clientState.TerritoryType == gatheringRoot.TerritoryId,
- $"Wait(territory: {territoryData.GetNameAndId(gatheringRoot.TerritoryId)})");
+ ushort territoryId = gatheringRoot.Steps.Last().TerritoryId;
+ yield return new WaitConditionTask(() => clientState.TerritoryType == territoryId,
+ $"Wait(territory: {territoryData.GetNameAndId(territoryId)})");
yield return new WaitConditionTask(() => movementController.IsNavmeshReady,
"Wait(navmesh ready)");
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Extensions.Logging;
+using Questionable.Model;
+using Questionable.Model.Questing;
+
+namespace Questionable.Controller.Steps;
+
+internal sealed class TaskCreator
+{
+ private readonly IReadOnlyList<ITaskFactory> _taskFactories;
+ private readonly ILogger<TaskCreator> _logger;
+
+ public TaskCreator(IEnumerable<ITaskFactory> taskFactories, ILogger<TaskCreator> logger)
+ {
+ _taskFactories = taskFactories.ToList().AsReadOnly();
+ _logger = logger;
+ }
+
+ public IReadOnlyList<ITask> CreateTasks(Quest quest, QuestSequence sequence, QuestStep step)
+ {
+ var newTasks = _taskFactories
+ .SelectMany(x =>
+ {
+ IList<ITask> tasks = x.CreateAllTasks(quest, sequence, step).ToList();
+
+ if (tasks.Count > 0 && _logger.IsEnabled(LogLevel.Trace))
+ {
+ string factoryName = x.GetType().FullName ?? x.GetType().Name;
+ if (factoryName.Contains('.', StringComparison.Ordinal))
+ factoryName = factoryName[(factoryName.LastIndexOf('.') + 1)..];
+
+ _logger.LogTrace("Factory {FactoryName} created Task {TaskNames}",
+ factoryName, string.Join(", ", tasks.Select(y => y.ToString())));
+ }
+
+ return tasks;
+ })
+ .ToList();
+ if (newTasks.Count == 0)
+ _logger.LogInformation("Nothing to execute for step?");
+ else
+ {
+ _logger.LogInformation("Tasks for {QuestId}, {Sequence}, {Step}: {Tasks}",
+ quest.Id, sequence.Sequence, sequence.Steps.IndexOf(step),
+ string.Join(", ", newTasks.Select(x => x.ToString())));
+ }
+
+ return newTasks;
+ }
+}
using System.Linq;
using System.Numerics;
using Dalamud.Plugin.Services;
+using Dalamud.Utility;
using Lumina.Excel.GeneratedSheets;
using Questionable.Model.Common;
{
Dictionary<EAetheryteLocation, string> aethernetNames = new();
Dictionary<EAetheryteLocation, ushort> territoryIds = new();
- Dictionary<EAetheryteLocation, byte> aethernetGroups = new();
+ Dictionary<EAetheryteLocation, ushort> aethernetGroups = new();
+
+
+ void ConfigureAetheryte(EAetheryteLocation aetheryteLocation, string name, ushort territoryId,
+ ushort aethernetGroup)
+ {
+ aethernetNames[aetheryteLocation] = name;
+ territoryIds[aetheryteLocation] = territoryId;
+ aethernetGroups[aetheryteLocation] = aethernetGroup;
+ }
+
+ void ConfigureAetheryteWithPlaceName(EAetheryteLocation aetheryteLocation, uint placeNameId, ushort territoryId)
+ {
+ ConfigureAetheryte(aetheryteLocation,
+ dataManager.GetExcelSheet<PlaceName>()!.GetRow(placeNameId)!.Name.ToDalamudString().TextValue,
+ territoryId,
+ (ushort)((int)aetheryteLocation / 100));
+ }
+
foreach (var aetheryte in dataManager.GetExcelSheet<Aetheryte>()!.Where(x => x.RowId > 0))
{
string? aethernetName = aetheryte.AethernetName?.Value?.Name.ToString();
aethernetGroups[(EAetheryteLocation)aetheryte.RowId] = aetheryte.AethernetGroup;
}
- aethernetNames[EAetheryteLocation.IshgardFirmament] = "Firmament";
- territoryIds[EAetheryteLocation.IshgardFirmament] = 886;
- aethernetGroups[EAetheryteLocation.IshgardFirmament] = aethernetGroups[EAetheryteLocation.Ishgard];
+ ConfigureAetheryte(EAetheryteLocation.IshgardFirmament, "Firmament", 886,
+ aethernetGroups[EAetheryteLocation.Ishgard]);
+ ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentMendicantsCourt, 3436, 886);
+ ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentMattock, 3473, 886);
+ ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentNewNest, 3475, 886);
+ ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmanentSaintRoellesDais, 3474, 886);
+ ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentFeatherfall, 3525, 886);
+ ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentHoarfrostHall, 3528, 886);
+ ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentWesternRisensongQuarter, 3646, 886);
+ ConfigureAetheryteWithPlaceName(EAetheryteLocation.FIrmamentEasternRisensongQuarter, 3645, 886);
AethernetNames = aethernetNames.AsReadOnly();
TerritoryIds = territoryIds.AsReadOnly();
{ EAetheryteLocation.RadzAtHanKama, new(129.59485f, 26.993164f, 13.473633f) },
{ EAetheryteLocation.RadzAtHanHighCrucible, new(57.90796f, -24.704407f, -210.6203f) },
+ { EAetheryteLocation.FirmamentMendicantsCourt, new(23.941406f, -16.006714f, 169.35986f) },
+ { EAetheryteLocation.FirmamentMattock, new(76.035645f, -18.509216f, 10.299805f) },
+ { EAetheryteLocation.FirmamentNewNest, new(149.49255f, -50.003845f, 98.55798f) },
+ { EAetheryteLocation.FirmanentSaintRoellesDais, new(207.75159f, -40.024475f, -25.589417f) },
+ { EAetheryteLocation.FirmamentFeatherfall, new(-78.78235f, -0.015319824f, 75.97461f) },
+ { EAetheryteLocation.FirmamentHoarfrostHall, new(-132.55518f, 9.964111f, -14.66394f) },
+ { EAetheryteLocation.FirmamentWesternRisensongQuarter, new(-91.722046f, -0.015319824f, -115.19043f) },
+ { EAetheryteLocation.FIrmamentEasternRisensongQuarter, new(114.3053f, -20.004639f, -107.43884f) },
+
{ EAetheryteLocation.LabyrinthosArcheion, new(443.5338f, 170.6416f, -476.18835f) },
{ EAetheryteLocation.LabyrinthosSharlayanHamlet, new(8.377136f, -27.542603f, -46.67737f) },
{ EAetheryteLocation.LabyrinthosAporia, new(-729.18286f, -27.634155f, 302.1438f) },
public ReadOnlyDictionary<EAetheryteLocation, string> AethernetNames { get; }
public ReadOnlyDictionary<EAetheryteLocation, ushort> TerritoryIds { get; }
- public ReadOnlyDictionary<EAetheryteLocation, byte> AethernetGroups { get; }
+ public ReadOnlyDictionary<EAetheryteLocation, ushort> AethernetGroups { get; }
public IReadOnlyList<ushort> TownTerritoryIds { get; set; }
public float CalculateDistance(Vector3 fromPosition, ushort fromTerritoryType, EAetheryteLocation to)
public bool IsAetheryteUnlocked(EAetheryteLocation aetheryteLocation)
{
- if (aetheryteLocation == EAetheryteLocation.IshgardFirmament)
+ if (aetheryteLocation.IsFirmamentAetheryte())
return _serviceProvider.GetRequiredService<QuestFunctions>().IsQuestComplete(new QuestId(3672));
return IsAetheryteUnlocked((uint)aetheryteLocation, out _);
}
WaitAtEnd.WaitObjectAtPosition>();
serviceCollection.AddTransient<WaitAtEnd.WaitQuestAccepted>();
serviceCollection.AddTransient<WaitAtEnd.WaitQuestCompleted>();
+
+ serviceCollection.AddSingleton<TaskCreator>();
}
private static void AddControllers(ServiceCollection serviceCollection)
if (aethernetShortcut == null)
return null;
- byte fromGroup = _aetheryteData.AethernetGroups.GetValueOrDefault(aethernetShortcut.From);
- byte toGroup = _aetheryteData.AethernetGroups.GetValueOrDefault(aethernetShortcut.To);
+ ushort fromGroup = _aetheryteData.AethernetGroups.GetValueOrDefault(aethernetShortcut.From);
+ ushort toGroup = _aetheryteData.AethernetGroups.GetValueOrDefault(aethernetShortcut.To);
if (fromGroup != toGroup)
{
return new ValidationIssue