AssignmentList(nameof(QuestStep.RequiredQuestVariables),
step.RequiredQuestVariables)
.AsSyntaxNodeOrToken(),
- AssignmentList(nameof(QuestStep.RequiredGatheredItems),
- step.RequiredGatheredItems),
+ AssignmentList(nameof(QuestStep.ItemsToGather),
+ step.ItemsToGather),
AssignmentList(nameof(QuestStep.CompletionQuestVariablesFlags),
step.CompletionQuestVariablesFlags)
.AsSyntaxNodeOrToken(),
{
"Sequence": 255,
"Steps": [
+ {
+ "TerritoryId": 131,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 5106,
+ "ItemCount": 10
+ }
+ ]
+ },
{
"DataId": 1002298,
"Position": {
131
]
}
- },
- "RequiredGatheredItems": [
- {
- "ItemId": 5106,
- "ItemCount": 10
- }
- ]
+ }
}
]
}
{
"Sequence": 255,
"Steps": [
+ {
+ "TerritoryId": 131,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 5432,
+ "ItemCount": 10
+ }
+ ]
+ },
{
"DataId": 1002298,
"Position": {
131
]
}
- },
- "RequiredGatheredItems": [
- {
- "ItemId": 5432,
- "ItemCount": 10
- }
- ]
+ }
}
]
}
{
"Sequence": 0,
"Steps": [
+ {
+ "TerritoryId": 478,
+ "InteractionType": "Gather",
+ "ItemsToGather": []
+ },
{
"Position": {
"X": -71.31451,
},
"TerritoryId": 478,
"InteractionType": "WalkTo",
- "RequiredGatheredItems": [],
"AetheryteShortcut": "Idyllshire"
},
{
{
"Sequence": 255,
"Steps": [
+ {
+ "TerritoryId": 478,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 17946,
+ "ItemCount": 20
+ }
+ ]
+ },
{
"DataId": 1021349,
"Position": {
"[Idyllshire] Aetheryte Plaza",
"[Idyllshire] West Idyllshire"
],
- "RequiredGatheredItems": [
- {
- "ItemId": 17946,
- "ItemCount": 20
- }
- ],
"NextQuestId": 2623
}
]
{
"Sequence": 6,
"Steps": [
+ {
+ "TerritoryId": 478,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 17947,
+ "ItemCount": 20
+ }
+ ]
+ },
{
"DataId": 1017106,
"Position": {
},
"TerritoryId": 478,
"InteractionType": "Interact",
- "AetheryteShortcut": "Idyllshire",
- "RequiredGatheredItems": [
- {
- "ItemId": 17947,
- "ItemCount": 20
- }
- ]
+ "AetheryteShortcut": "Idyllshire"
}
]
},
{
"Sequence": 255,
"Steps": [
+ {
+ "TerritoryId": 478,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 17948,
+ "ItemCount": 5
+ }
+ ]
+ },
{
"DataId": 1021349,
"Position": {
"[Idyllshire] Aetheryte Plaza",
"[Idyllshire] West Idyllshire"
],
- "Comment": "Eorzean Time: 4:00-5:59 AM/PM",
- "RequiredGatheredItems": [
- {
- "ItemId": 17948,
- "ItemCount": 5
- }
- ]
+ "Comment": "Eorzean Time: 4:00-5:59 AM/PM"
}
]
}
{
"Sequence": 0,
"Steps": [
+ {
+ "TerritoryId": 478,
+ "InteractionType": "Gather",
+ "ItemsToGather": []
+ },
{
"DataId": 1018393,
"Position": {
},
"TerritoryId": 478,
"InteractionType": "Interact",
- "RequiredGatheredItems": [],
"AetheryteShortcut": "Idyllshire",
"DialogueChoices": [
{
{
"Sequence": 0,
"Steps": [
+ {
+ "TerritoryId": 613,
+ "InteractionType": "Gather",
+ "ItemsToGather": []
+ },
{
"DataId": 1025878,
"Position": {
},
"TerritoryId": 613,
"InteractionType": "Interact",
- "RequiredGatheredItems": [],
"AetheryteShortcut": "Ruby Sea - Tamamizu",
"DialogueChoices": [
{
{
"Sequence": 0,
"Steps": [
+ {
+ "TerritoryId": 635,
+ "InteractionType": "Gather",
+ "ItemsToGather": []
+ },
{
"DataId": 1020337,
"Position": {
},
"TerritoryId": 635,
"InteractionType": "Interact",
- "RequiredGatheredItems": [],
"AetheryteShortcut": "Rhalgr's Reach",
"AethernetShortcut": [
"[Rhalgr's Reach] Aetheryte Plaza",
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29517,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29518,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29519,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29520,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"TerritoryId": 817,
"InteractionType": "WalkTo",
"AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
- ]
+ "Fly": true
},
{
"DataId": 1032643,
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29521,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29522,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29523,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29524,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"TerritoryId": 817,
"InteractionType": "WalkTo",
"AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
- ]
+ "Fly": true
},
{
"DataId": 1032643,
"TerritoryId": 817,
"InteractionType": "WalkTo",
"AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
- ]
+ "Fly": true
},
{
"DataId": 1032643,
"TerritoryId": 817,
"InteractionType": "WalkTo",
"AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
- ]
+ "Fly": true
},
{
"DataId": 1032643,
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29528,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29529,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29530,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"TerritoryId": 817,
"InteractionType": "WalkTo",
"AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
- ]
+ "Fly": true
},
{
"DataId": 1032643,
"TerritoryId": 817,
"InteractionType": "WalkTo",
"AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
- ]
+ "Fly": true
},
{
"DataId": 1032643,
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29533,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29534,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29535,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"Sequence": 255,
"Steps": [
{
- "Position": {
- "X": 788.1569,
- "Y": -45.82557,
- "Z": -212.9306
- },
"TerritoryId": 817,
- "InteractionType": "WalkTo",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29536,
}
]
},
+ {
+ "Position": {
+ "X": 788.1569,
+ "Y": -45.82557,
+ "Z": -212.9306
+ },
+ "TerritoryId": 817,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
+ },
{
"DataId": 1032643,
"Position": {
"TerritoryId": 817,
"InteractionType": "WalkTo",
"AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
- ]
+ "Fly": true
},
{
"DataId": 1032643,
"TerritoryId": 817,
"InteractionType": "WalkTo",
"AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
- ]
+ "Fly": true
},
{
"DataId": 1032643,
{
"Sequence": 255,
"Steps": [
+ {
+ "TerritoryId": 817,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 29512,
+ "ItemCount": 1
+ }
+ ]
+ },
{
"DataId": 1032724,
"Position": {
},
"TerritoryId": 817,
"InteractionType": "CompleteQuest",
- "Fly": true,
- "RequiredGatheredItems": [
- {
- "ItemId": 29512,
- "ItemCount": 1
- }
- ]
+ "Fly": true
}
]
}
"Sequence": 2,
"Steps": [
{
- "DataId": 1032734,
- "Position": {
- "X": 802.6703,
- "Y": -45.915627,
- "Z": -214.70972
- },
"TerritoryId": 817,
- "InteractionType": "Interact",
- "AetheryteShortcut": "Rak'tika - Fanow",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 29513,
"ItemCount": 1
}
]
+ },
+ {
+ "DataId": 1032734,
+ "Position": {
+ "X": 802.6703,
+ "Y": -45.915627,
+ "Z": -214.70972
+ },
+ "TerritoryId": 817,
+ "InteractionType": "Interact",
+ "AetheryteShortcut": "Rak'tika - Fanow",
+ "Fly": true
}
]
},
{
"Sequence": 0,
"Steps": [
+ {
+ "TerritoryId": 820,
+ "InteractionType": "Gather",
+ "ItemsToGather": []
+ },
{
"DataId": 1031801,
"Position": {
},
"TerritoryId": 820,
"InteractionType": "Interact",
- "RequiredGatheredItems": [],
"AetheryteShortcut": "Eulmore",
"DialogueChoices": [
{
"Steps": [
{
"TerritoryId": 960,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38281,
"Sequence": 255,
"Steps": [
{
- "DataId": 2013072,
- "Position": {
- "X": 456.65674,
- "Y": 438.04077,
- "Z": 310.2312
- },
"TerritoryId": 960,
- "InteractionType": "Interact",
- "TargetTerritoryId": 960,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38282,
"ItemId": 38306,
"ItemCount": 3
}
- ],
- "AetheryteShortcut": "Ultima Thule - Base Omicron"
+ ]
+ },
+ {
+ "DataId": 2013072,
+ "Position": {
+ "X": 456.65674,
+ "Y": 438.04077,
+ "Z": 310.2312
+ },
+ "TerritoryId": 960,
+ "InteractionType": "Interact",
+ "AetheryteShortcut": "Ultima Thule - Base Omicron",
+ "TargetTerritoryId": 960
},
{
"DataId": 1043417,
},
{
"TerritoryId": 1073,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38284,
"Sequence": 255,
"Steps": [
{
- "DataId": 2013072,
- "Position": {
- "X": 456.65674,
- "Y": 438.04077,
- "Z": 310.2312
- },
"TerritoryId": 960,
- "InteractionType": "Interact",
- "TargetTerritoryId": 960,
- "AetheryteShortcut": "Ultima Thule - Base Omicron",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38283,
}
]
},
+ {
+ "DataId": 2013072,
+ "Position": {
+ "X": 456.65674,
+ "Y": 438.04077,
+ "Z": 310.2312
+ },
+ "TerritoryId": 960,
+ "InteractionType": "Interact",
+ "TargetTerritoryId": 960,
+ "AetheryteShortcut": "Ultima Thule - Base Omicron"
+ },
{
"DataId": 1043417,
"Position": {
},
{
"TerritoryId": 1073,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38285,
"Steps": [
{
"TerritoryId": 960,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38286,
},
{
"TerritoryId": 1073,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38287,
"Sequence": 2,
"Steps": [
{
- "DataId": 1044059,
- "Position": {
- "X": -15.304871,
- "Y": 494.9991,
- "Z": -68.16211
- },
"TerritoryId": 1073,
- "InteractionType": "Interact",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38289,
"ItemCount": 3
}
]
+ },
+ {
+ "DataId": 1044059,
+ "Position": {
+ "X": -15.304871,
+ "Y": 494.9991,
+ "Z": -68.16211
+ },
+ "TerritoryId": 1073,
+ "InteractionType": "Interact"
}
]
},
"Sequence": 1,
"Steps": [
{
- "DataId": 1044064,
- "Position": {
- "X": 86.503296,
- "Y": 269.08234,
- "Z": -515.0683
- },
"TerritoryId": 960,
- "InteractionType": "Interact",
- "AetheryteShortcut": "Ultima Thule - Abode of the Ea",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38290,
"ItemCount": 3
}
]
+ },
+ {
+ "DataId": 1044064,
+ "Position": {
+ "X": 86.503296,
+ "Y": 269.08234,
+ "Z": -515.0683
+ },
+ "TerritoryId": 960,
+ "InteractionType": "Interact",
+ "AetheryteShortcut": "Ultima Thule - Abode of the Ea",
+ "Fly": true
}
]
},
},
{
"TerritoryId": 1073,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38291,
},
{
"TerritoryId": 1073,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38292,
},
{
"TerritoryId": 1073,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38293,
"Sequence": 1,
"Steps": [
{
- "DataId": 1044071,
- "Position": {
- "X": 46.066895,
- "Y": 268.99976,
- "Z": -584.77155
- },
"TerritoryId": 960,
- "InteractionType": "Interact",
- "AetheryteShortcut": "Ultima Thule - Abode of the Ea",
- "Fly": true,
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38294,
"ItemCount": 3
}
]
+ },
+ {
+ "DataId": 1044071,
+ "Position": {
+ "X": 46.066895,
+ "Y": 268.99976,
+ "Z": -584.77155
+ },
+ "TerritoryId": 960,
+ "InteractionType": "Interact",
+ "AetheryteShortcut": "Ultima Thule - Abode of the Ea",
+ "Fly": true
}
]
},
"Sequence": 1,
"Steps": [
{
- "DataId": 1044074,
- "Position": {
- "X": -585.90063,
- "Y": 75.22713,
- "Z": 256.67188
- },
"TerritoryId": 960,
- "InteractionType": "Interact",
- "AetheryteShortcut": "Ultima Thule - Reah Tahra",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38295,
"ItemCount": 3
}
]
+ },
+ {
+ "DataId": 1044074,
+ "Position": {
+ "X": -585.90063,
+ "Y": 75.22713,
+ "Z": 256.67188
+ },
+ "TerritoryId": 960,
+ "InteractionType": "Interact",
+ "AetheryteShortcut": "Ultima Thule - Reah Tahra"
}
]
},
"Sequence": 2,
"Steps": [
{
- "DataId": 1044075,
- "Position": {
- "X": -64.4389,
- "Y": 493.32922,
- "Z": -4.409851
- },
"TerritoryId": 1073,
- "InteractionType": "Interact",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38296,
"ItemCount": 3
}
]
+ },
+ {
+ "DataId": 1044075,
+ "Position": {
+ "X": -64.4389,
+ "Y": 493.32922,
+ "Z": -4.409851
+ },
+ "TerritoryId": 1073,
+ "InteractionType": "Interact"
}
]
},
"Sequence": 1,
"Steps": [
{
- "DataId": 1044076,
- "Position": {
- "X": -499.96188,
- "Y": 77.00467,
- "Z": 241.07727
- },
- "StopDistance": 9,
"TerritoryId": 960,
- "InteractionType": "Interact",
- "AetheryteShortcut": "Ultima Thule - Reah Tahra",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38297,
"ItemCount": 3
}
]
+ },
+ {
+ "DataId": 1044076,
+ "Position": {
+ "X": -499.96188,
+ "Y": 77.00467,
+ "Z": 241.07727
+ },
+ "StopDistance": 9,
+ "TerritoryId": 960,
+ "InteractionType": "Interact",
+ "AetheryteShortcut": "Ultima Thule - Reah Tahra"
}
]
},
"Sequence": 1,
"Steps": [
{
- "DataId": 1044081,
- "Position": {
- "X": -503.99023,
- "Y": 74.16917,
- "Z": 261.82947
- },
"TerritoryId": 960,
- "InteractionType": "Interact",
+ "InteractionType": "Gather",
"AetheryteShortcut": "Ultima Thule - Reah Tahra",
- "RequiredGatheredItems": [
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38299,
"ItemCount": 3
}
]
+ },
+ {
+ "DataId": 1044081,
+ "Position": {
+ "X": -503.99023,
+ "Y": 74.16917,
+ "Z": 261.82947
+ },
+ "TerritoryId": 960,
+ "InteractionType": "Interact"
}
]
},
},
{
"TerritoryId": 1073,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38298,
{
"Sequence": 4,
"Steps": [
+ {
+ "TerritoryId": 960,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "QuestAcceptedAsClass": "Miner",
+ "ItemId": 38276,
+ "ItemCount": 3
+ },
+ {
+ "QuestAcceptedAsClass": "Botanist",
+ "ItemId": 38300,
+ "ItemCount": 3
+ }
+ ]
+ },
{
"DataId": 2013072,
"Position": {
"Prompt": "TEXT_BANOMI001_04601_Q5_000_000",
"Yes": true
}
- ],
- "RequiredGatheredItems": [
- {
- "QuestAcceptedAsClass": "Miner",
- "ItemId": 38276,
- "ItemCount": 3
- },
- {
- "QuestAcceptedAsClass": "Botanist",
- "ItemId": 38300,
- "ItemCount": 3
- }
]
},
{
"Steps": [
{
"TerritoryId": 960,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38277,
"Steps": [
{
"TerritoryId": 960,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38278,
"Steps": [
{
"TerritoryId": 398,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38279,
"Steps": [
{
"TerritoryId": 1073,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"QuestAcceptedAsClass": "Miner",
"ItemId": 38280,
{
"Sequence": 0,
"Steps": [
+ {
+ "TerritoryId": 962,
+ "InteractionType": "Gather",
+ "ItemsToGather": []
+ },
{
"DataId": 1042241,
"Position": {
},
"TerritoryId": 962,
"InteractionType": "Interact",
- "RequiredGatheredItems": [],
"AetheryteShortcut": "Old Sharlayan",
"AethernetShortcut": [
"[Old Sharlayan] Aetheryte Plaza",
{
"Sequence": 0,
"Steps": [
+ {
+ "TerritoryId": 816,
+ "InteractionType": "Gather",
+ "ItemsToGather": []
+ },
{
"DataId": 1044547,
"Position": {
},
"TerritoryId": 816,
"InteractionType": "Interact",
- "RequiredGatheredItems": [],
"AetheryteShortcut": "Il Mheg - Lydha Lran",
"Fly": true,
"DialogueChoices": [
{
"Sequence": 0,
"Steps": [
+ {
+ "TerritoryId": 956,
+ "InteractionType": "Gather",
+ "ItemsToGather": []
+ },
{
"Position": {
"X": -44.066154,
"TerritoryId": 956,
"InteractionType": "WalkTo",
"AetheryteShortcut": "Labyrinthos - Sharlayan Hamlet",
- "RequiredGatheredItems": [],
"Fly": true
},
{
{
"Sequence": 255,
"Steps": [
+ {
+ "TerritoryId": 962,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 35600,
+ "ItemCount": 6,
+ "Collectability": 600
+ }
+ ]
+ },
{
"DataId": 1038501,
"Position": {
"[Old Sharlayan] Aetheryte Plaza",
"[Old Sharlayan] The Studium"
],
- "RequiredGatheredItems": [
- {
- "ItemId": 35600,
- "ItemCount": 6,
- "Collectability": 600
- }
- ],
"NextQuestId": 4155
}
]
{
"Sequence": 255,
"Steps": [
+ {
+ "TerritoryId": 962,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 35601,
+ "ItemCount": 6,
+ "Collectability": 600
+ }
+ ]
+ },
{
"DataId": 1038501,
"Position": {
"[Old Sharlayan] Aetheryte Plaza",
"[Old Sharlayan] The Studium"
],
- "RequiredGatheredItems": [
- {
- "ItemId": 35601,
- "ItemCount": 6,
- "Collectability": 600
- }
- ],
"NextQuestId": 4156
}
]
{
"Sequence": 255,
"Steps": [
+ {
+ "TerritoryId": 962,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 35602,
+ "ItemCount": 6,
+ "Collectability": 600
+ }
+ ]
+ },
{
"DataId": 1038501,
"Position": {
"[Old Sharlayan] Aetheryte Plaza",
"[Old Sharlayan] The Studium"
],
- "RequiredGatheredItems": [
- {
- "ItemId": 35602,
- "ItemCount": 6,
- "Collectability": 600
- }
- ],
"NextQuestId": 4157
}
]
{
"Sequence": 5,
"Steps": [
+ {
+ "TerritoryId": 628,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 35847,
+ "ItemCount": 1
+ }
+ ]
+ },
{
"DataId": 1038508,
"Position": {
"AethernetShortcut": [
"[Kugane] Aetheryte Plaza",
"[Kugane] The Ruby Bazaar"
- ],
- "RequiredGatheredItems": [
- {
- "ItemId": 35847,
- "ItemCount": 1
- }
]
}
]
{
"Sequence": 255,
"Steps": [
+ {
+ "TerritoryId": 962,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 35603,
+ "ItemCount": 6,
+ "Collectability": 600
+ }
+ ]
+ },
{
"DataId": 1038501,
"Position": {
"[Old Sharlayan] Aetheryte Plaza",
"[Old Sharlayan] The Studium"
],
- "RequiredGatheredItems": [
- {
- "ItemId": 35603,
- "ItemCount": 6,
- "Collectability": 600
- }
- ],
"NextQuestId": 4159
}
]
{
"Sequence": 1,
"Steps": [
+ {
+ "TerritoryId": 962,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 35848,
+ "ItemCount": 1
+ }
+ ]
+ },
{
"DataId": 1038503,
"Position": {
"AethernetShortcut": [
"[Old Sharlayan] Aetheryte Plaza",
"[Old Sharlayan] The Studium"
- ],
- "RequiredGatheredItems": [
- {
- "ItemId": 35848,
- "ItemCount": 1
- }
]
}
]
"Steps": [
{
"TerritoryId": 1185,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"ItemId": 43899,
"ItemCount": 6,
"Collectability": 600
}
- ],
- "AetheryteShortcut": "Tuliyollal",
- "AethernetShortcut": [
- "[Tuliyollal] Aetheryte Plaza",
- "[Tuliyollal] Wachumeqimeqi"
]
},
{
},
"TerritoryId": 1185,
"InteractionType": "CompleteQuest",
- "NextQuestId": 4991
+ "NextQuestId": 4991,
+ "AetheryteShortcut": "Tuliyollal",
+ "AethernetShortcut": [
+ "[Tuliyollal] Aetheryte Plaza",
+ "[Tuliyollal] Wachumeqimeqi"
+ ]
}
]
}
"Steps": [
{
"TerritoryId": 1185,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"ItemId": 43900,
"ItemCount": 6,
"Collectability": 600
}
- ],
- "AetheryteShortcut": "Tuliyollal",
- "AethernetShortcut": [
- "[Tuliyollal] Aetheryte Plaza",
- "[Tuliyollal] Wachumeqimeqi"
]
},
{
},
"TerritoryId": 1185,
"InteractionType": "CompleteQuest",
- "NextQuestId": 4992
+ "NextQuestId": 4992,
+ "AetheryteShortcut": "Tuliyollal",
+ "AethernetShortcut": [
+ "[Tuliyollal] Aetheryte Plaza",
+ "[Tuliyollal] Wachumeqimeqi"
+ ]
}
]
}
"Steps": [
{
"TerritoryId": 1185,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"ItemId": 43901,
"ItemCount": 6,
"Collectability": 600
}
- ],
- "AetheryteShortcut": "Tuliyollal",
- "AethernetShortcut": [
- "[Tuliyollal] Aetheryte Plaza",
- "[Tuliyollal] Wachumeqimeqi"
]
},
{
},
"TerritoryId": 1185,
"InteractionType": "CompleteQuest",
- "NextQuestId": 4993
+ "NextQuestId": 4993,
+ "AetheryteShortcut": "Tuliyollal",
+ "AethernetShortcut": [
+ "[Tuliyollal] Aetheryte Plaza",
+ "[Tuliyollal] Wachumeqimeqi"
+ ]
}
]
}
"Steps": [
{
"TerritoryId": 1185,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"ItemId": 43913,
"ItemCount": 1
}
- ],
- "AetheryteShortcut": "Tuliyollal",
- "AethernetShortcut": [
- "[Tuliyollal] Aetheryte Plaza",
- "[Tuliyollal] Wachumeqimeqi"
]
},
{
},
"TerritoryId": 1185,
"InteractionType": "CompleteQuest",
- "NextQuestId": 4994
+ "NextQuestId": 4994,
+ "AetheryteShortcut": "Tuliyollal",
+ "AethernetShortcut": [
+ "[Tuliyollal] Aetheryte Plaza",
+ "[Tuliyollal] Wachumeqimeqi"
+ ]
}
]
}
"Steps": [
{
"TerritoryId": 1185,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"ItemId": 43902,
"ItemCount": 6,
"Collectability": 600
}
- ],
- "AetheryteShortcut": "Tuliyollal",
- "AethernetShortcut": [
- "[Tuliyollal] Aetheryte Plaza",
- "[Tuliyollal] Wachumeqimeqi"
]
},
{
},
"TerritoryId": 1185,
"InteractionType": "CompleteQuest",
- "NextQuestId": 4995
+ "NextQuestId": 4995,
+ "AetheryteShortcut": "Tuliyollal",
+ "AethernetShortcut": [
+ "[Tuliyollal] Aetheryte Plaza",
+ "[Tuliyollal] Wachumeqimeqi"
+ ]
}
]
}
}
}
},
+ {
+ "TerritoryId": 1189,
+ "InteractionType": "Gather",
+ "ItemsToGather": [
+ {
+ "ItemId": 43914,
+ "ItemCount": 1
+ }
+ ]
+ },
{
"Position": {
"X": 674.17834,
},
"TerritoryId": 1189,
"InteractionType": "WalkTo",
- "Fly": true,
- "RequiredGatheredItems": [
- {
- "ItemId": 43914,
- "ItemCount": 1
- }
- ]
+ "Fly": true
},
{
"Position": {
},
{
"TerritoryId": 1188,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"ItemId": 2003516,
"AlternativeItemId": 2003517,
},
{
"TerritoryId": 1189,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"ItemId": 2003529,
"AlternativeItemId": 2003530,
},
{
"TerritoryId": 1187,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"ItemId": 2003539,
"AlternativeItemId": 2003540,
},
{
"TerritoryId": 1189,
- "InteractionType": "None",
- "RequiredGatheredItems": [
+ "InteractionType": "Gather",
+ "ItemsToGather": [
{
"ItemId": 2003552,
"AlternativeItemId": 2003553,
"Jump",
"Dive",
"Craft",
+ "Gather",
"Snipe",
"Instruction",
"AcceptQuest",
"QuestsAccepted": {
"type": "array",
"items": {
- "type": ["number", "string"]
+ "type": [
+ "number",
+ "string"
+ ]
}
},
"QuestsCompleted": {
"type": "array",
"items": {
- "type": ["number", "string"]
+ "type": [
+ "number",
+ "string"
+ ]
}
},
"AetheryteLocked": {
"QuestsAccepted": {
"type": "array",
"items": {
- "type": ["number", "string"]
+ "type": [
+ "number",
+ "string"
+ ]
}
},
"QuestsCompleted": {
"type": "array",
"items": {
- "type": ["number", "string"]
+ "type": [
+ "number",
+ "string"
+ ]
}
},
"AetheryteLocked": {
}
}
},
- "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
- },
- "QuestAcceptedAsClass": {
- "type": "string",
- "enum": [
- "Miner",
- "Botanist"
- ]
- }
- },
- "required": [
- "ItemId",
- "ItemCount"
- ]
- }
- },
"DelaySecondsAtStart": {
"description": "Time to wait before starting",
"type": [
"ItemCount"
]
}
- }
- ],
- "not": {
- "anyOf": [
- {
+ },
+ {
+ "if": {
+ "properties": {
+ "InteractionType": {
+ "const": "Gather"
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "ItemsToGather": {
+ "type": "array",
+ "description": "Unlike crafting steps, which will always craft a single item id regardless of class, this allows for gathering different items depending on whether you've picked the quest up as miner or botanist",
+ "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
+ },
+ "QuestAcceptedAsClass": {
+ "type": "string",
+ "enum": [
+ "Miner",
+ "Botanist"
+ ]
+ }
+ },
+ "required": [
+ "ItemId",
+ "ItemCount"
+ ]
+ }
+ }
+ },
"required": [
- "SkipIf"
+ "ItemsToGather"
]
}
- ]
- }
+ }
+ ]
}
}
}
{ EInteractionType.Jump, "Jump" },
{ EInteractionType.Dive, "Dive" },
{ EInteractionType.Craft, "Craft" },
+ { EInteractionType.Gather, "Gather" },
{ EInteractionType.Snipe, "Snipe" },
{ EInteractionType.Instruction, "Instruction" },
{ EInteractionType.AcceptQuest, "AcceptQuest" },
Jump,
Dive,
Craft,
+ Gather,
Snipe,
/// <summary>
AcceptLeve,
InitiateLeve,
CompleteLeve,
-
- // unmapped extra types below
- InternalGather,
}
public SkipConditions? SkipConditions { get; set; }
public List<List<QuestWorkValue>?> RequiredQuestVariables { get; set; } = new();
- public List<GatheredItem> RequiredGatheredItems { get; set; } = [];
+ public List<GatheredItem> ItemsToGather { get; set; } = [];
public List<QuestWorkValue?> CompletionQuestVariablesFlags { get; set; } = [];
public List<DialogueChoice> DialogueChoices { get; set; } = [];
public List<uint> PointMenuChoices { get; set; } = [];
.Single(x => x is SatisfactionSupplyInfo);
if (_questRegistry.TryGetQuest(info.QuestId, out Quest? quest))
{
- var step = quest.FindSequence(0)!.FindStep(0)!;
- step.RequiredGatheredItems =
+ var step = quest.FindSequence(0)!.Steps.Single(x => x.InteractionType == EInteractionType.Gather);
+ step.ItemsToGather =
[
new GatheredItem
{
step.TargetTerritoryId);
if (step != null && (step.TerritoryId != _clientState.TerritoryType || step.TargetTerritoryId == null) &&
- step.RequiredGatheredItems.Count > 0)
+ step.InteractionType == EInteractionType.Gather)
{
- if (_gatheringData.TryGetGatheringPointId(step.RequiredGatheredItems[0].ItemId,
+ if (_gatheringData.TryGetGatheringPointId(step.ItemsToGather[0].ItemId,
(EClassJob?)_clientState.LocalPlayer?.ClassJob.Id ?? EClassJob.Adventurer,
out GatheringPointId? gatheringPointId) &&
_gatheringPointRegistry.TryGetGatheringPoint(gatheringPointId, out GatheringRoot? root))
pointOnFloor = pointOnFloor.Value with { Y = pointOnFloor.Value.Y + (fly ? 3f : 0f) };
_taskQueue.Enqueue(_moveFactory.Move(new MoveTo.MoveParams(territoryId, pointOnFloor ?? averagePosition,
- 50f,
- Fly: fly, IgnoreDistanceToObject: true)));
+ null, 50f, Fly: fly, IgnoreDistanceToObject: true)));
}
_taskQueue.Enqueue(new MoveToLandingLocation(territoryId, fly, currentNode, _moveFactory, _gameFunctions,
_objectTable, _loggerFactory.CreateLogger<MoveToLandingLocation>()));
_taskQueue.Enqueue(_mountFactory.Unmount());
- _taskQueue.Enqueue(_interactFactory.Interact(currentNode.DataId, null, EInteractionType.InternalGather, true));
+ _taskQueue.Enqueue(_interactFactory.Interact(currentNode.DataId, null, EInteractionType.Gather, true));
QueueGatherNode(currentNode);
}
while (_taskQueue.TryDequeue(out ITask? nextTask))
{
- if (nextTask is ILastTask or GatheringRequiredItems.SkipMarker)
+ if (nextTask is ILastTask or Gather.SkipMarker)
{
_currentTask = nextTask;
return;
target.ToString("G", CultureInfo.InvariantCulture), degrees, range);
bool fly = flyBetweenNodes && gameFunctions.IsFlyingUnlocked(territoryId);
- _moveTask = moveFactory.Move(new MoveTo.MoveParams(territoryId, target, 0.25f, DataId: gatheringNode.DataId,
- Fly: fly, IgnoreDistanceToObject: true));
+ _moveTask = moveFactory.Move(new MoveTo.MoveParams(territoryId, target, null, 0.25f,
+ DataId: gatheringNode.DataId, Fly: fly, IgnoreDistanceToObject: true));
return _moveTask.Start();
}
if (_interactionState == EInteractionState.InteractionConfirmed)
return ETaskResult.TaskComplete;
- if (interactionType == EInteractionType.InternalGather && condition[ConditionFlag.Gathering])
+ if (interactionType == EInteractionType.Gather && condition[ConditionFlag.Gathering])
return ETaskResult.TaskComplete;
}
mountFactory.Mount(140,
nextPosition != null ? Mount.EMountIf.AwayFromPosition : Mount.EMountIf.Always,
nextPosition),
- moveFactory.Move(new MoveTo.MoveParams(140, new(-408.92343f, 23.167036f, -351.16223f), 0.25f,
+ moveFactory.Move(new MoveTo.MoveParams(140, new(-408.92343f, 23.167036f, -351.16223f), null, 0.25f,
DataId: null, DisableNavMesh: true, Sprint: false, Fly: false))
];
}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Dalamud.Game.Text;
+using Dalamud.Plugin.Services;
+using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
+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.Model;
+using Questionable.Model.Gathering;
+using Questionable.Model.Questing;
+
+namespace Questionable.Controller.Steps.Shared;
+
+internal static class Gather
+{
+ internal sealed class Factory(
+ IServiceProvider serviceProvider,
+ MovementController movementController,
+ GatheringController gatheringController,
+ GatheringPointRegistry gatheringPointRegistry,
+ IClientState clientState,
+ GatheringData gatheringData,
+ TerritoryData territoryData,
+ ILogger<Factory> logger) : ITaskFactory
+ {
+ public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
+ {
+ if (step.InteractionType != EInteractionType.Gather)
+ yield break;
+
+ foreach (var itemToGather in step.ItemsToGather)
+ {
+ EClassJob currentClassJob = (EClassJob)clientState.LocalPlayer!.ClassJob.Id;
+ EClassJob classJob = currentClassJob;
+ if (itemToGather.QuestAcceptedAsClass != null)
+ {
+ classJob = (EClassJob)itemToGather.QuestAcceptedAsClass.Value;
+ if (!IsClassJobQuestWasAcceptedWith(quest.Id, classJob))
+ continue;
+ }
+
+ if (!gatheringData.TryGetGatheringPointId(itemToGather.ItemId, classJob,
+ out GatheringPointId? gatheringPointId))
+ throw new TaskException($"No gathering point found for item {itemToGather.ItemId}");
+
+ if (!gatheringPointRegistry.TryGetGatheringPoint(gatheringPointId, out GatheringRoot? gatheringRoot))
+ throw new TaskException($"No path found for gathering point {gatheringPointId}");
+
+ if (classJob != currentClassJob)
+ {
+ yield return new SwitchClassJob(classJob, clientState);
+ }
+
+ if (HasRequiredItems(itemToGather))
+ continue;
+
+ using (var _ = logger.BeginScope("Gathering(inner)"))
+ {
+ 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 WaitAtEnd.NextStep)
+ yield return CreateSkipMarkerTask();
+ else
+ yield return task;
+ }
+ }
+
+ 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)");
+
+ yield return CreateStartGatheringTask(gatheringPointId, itemToGather);
+ yield return new WaitAtEnd.WaitDelay();
+ }
+ }
+
+ private unsafe bool IsClassJobQuestWasAcceptedWith(ElementId questId, EClassJob expectedClassJob)
+ {
+ if (questId is not QuestId)
+ return true;
+
+ QuestWork* questWork = QuestManager.Instance()->GetQuestById(questId.Value);
+ if (questWork->AcceptClassJob != 0)
+ return (EClassJob)questWork->AcceptClassJob == expectedClassJob;
+
+ return true;
+ }
+
+ private unsafe bool HasRequiredItems(GatheredItem itemToGather)
+ {
+ InventoryManager* inventoryManager = InventoryManager.Instance();
+ return inventoryManager != null &&
+ inventoryManager->GetInventoryItemCount(itemToGather.ItemId,
+ minCollectability: (short)itemToGather.Collectability) >=
+ itemToGather.ItemCount;
+ }
+
+ private StartGathering CreateStartGatheringTask(GatheringPointId gatheringPointId, GatheredItem gatheredItem)
+ {
+ return new StartGathering(gatheringPointId, gatheredItem, gatheringController);
+ }
+
+ private static SkipMarker CreateSkipMarkerTask()
+ {
+ return new SkipMarker();
+ }
+ }
+
+ private sealed class StartGathering(
+ GatheringPointId gatheringPointId,
+ GatheredItem gatheredItem,
+ GatheringController gatheringController) : ITask
+ {
+ public bool Start()
+ {
+ return gatheringController.Start(new GatheringController.GatheringRequest(gatheringPointId,
+ gatheredItem.ItemId, gatheredItem.AlternativeItemId, gatheredItem.ItemCount,
+ gatheredItem.Collectability));
+ }
+
+ public ETaskResult Update()
+ {
+ if (gatheringController.Update() == GatheringController.EStatus.Complete)
+ return ETaskResult.TaskComplete;
+
+ return ETaskResult.StillRunning;
+ }
+
+ public override string ToString()
+ {
+ if (gatheredItem.Collectability == 0)
+ return $"Gather({gatheredItem.ItemCount}x {gatheredItem.ItemId})";
+ else
+ return
+ $"Gather({gatheredItem.ItemCount}x {gatheredItem.ItemId} {SeIconChar.Collectible.ToIconString()} {gatheredItem.Collectability})";
+ }
+ }
+
+ /// <summary>
+ /// A task that does nothing, but if we're skipping a step, this will be the task next in queue to be executed (instead of progressing to the next step) if gathering.
+ /// </summary>
+ internal sealed class SkipMarker : ITask
+ {
+ public bool Start() => true;
+ public ETaskResult Update() => ETaskResult.TaskComplete;
+ public override string ToString() => "Gather/SkipMarker";
+ }
+}
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Dalamud.Game.Text;
-using Dalamud.Plugin.Services;
-using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
-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.Model;
-using Questionable.Model.Gathering;
-using Questionable.Model.Questing;
-
-namespace Questionable.Controller.Steps.Shared;
-
-internal static class GatheringRequiredItems
-{
- internal sealed class Factory(
- IServiceProvider serviceProvider,
- MovementController movementController,
- GatheringController gatheringController,
- GatheringPointRegistry gatheringPointRegistry,
- IClientState clientState,
- GatheringData gatheringData,
- TerritoryData territoryData,
- ILogger<Factory> logger) : ITaskFactory
- {
- public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
- {
- foreach (var requiredGatheredItems in step.RequiredGatheredItems)
- {
- EClassJob currentClassJob = (EClassJob)clientState.LocalPlayer!.ClassJob.Id;
- EClassJob classJob = currentClassJob;
- if (requiredGatheredItems.QuestAcceptedAsClass != null)
- {
- classJob = (EClassJob)requiredGatheredItems.QuestAcceptedAsClass.Value;
- if (!IsClassJobQuestWasAcceptedWith(quest.Id, classJob))
- continue;
- }
-
- if (!gatheringData.TryGetGatheringPointId(requiredGatheredItems.ItemId, classJob,
- out GatheringPointId? gatheringPointId))
- throw new TaskException($"No gathering point found for item {requiredGatheredItems.ItemId}");
-
- if (!gatheringPointRegistry.TryGetGatheringPoint(gatheringPointId, out GatheringRoot? gatheringRoot))
- throw new TaskException($"No path found for gathering point {gatheringPointId}");
-
- if (classJob != currentClassJob)
- {
- yield return new SwitchClassJob(classJob, clientState);
- }
-
- if (HasRequiredItems(requiredGatheredItems))
- continue;
-
- using (var _ = logger.BeginScope("Gathering(inner)"))
- {
- 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 WaitAtEnd.NextStep)
- yield return CreateSkipMarkerTask();
- else
- yield return task;
- }
- }
-
- 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)");
-
- yield return CreateStartGatheringTask(gatheringPointId, requiredGatheredItems);
- yield return new WaitAtEnd.WaitDelay();
- }
- }
-
- private unsafe bool IsClassJobQuestWasAcceptedWith(ElementId questId, EClassJob expectedClassJob)
- {
- if (questId is not QuestId)
- return true;
-
- QuestWork* questWork = QuestManager.Instance()->GetQuestById(questId.Value);
- if (questWork->AcceptClassJob != 0)
- return (EClassJob)questWork->AcceptClassJob == expectedClassJob;
-
- return true;
- }
-
- private unsafe bool HasRequiredItems(GatheredItem requiredGatheredItems)
- {
- InventoryManager* inventoryManager = InventoryManager.Instance();
- return inventoryManager != null &&
- inventoryManager->GetInventoryItemCount(requiredGatheredItems.ItemId,
- minCollectability: (short)requiredGatheredItems.Collectability) >=
- requiredGatheredItems.ItemCount;
- }
-
- private StartGathering CreateStartGatheringTask(GatheringPointId gatheringPointId, GatheredItem gatheredItem)
- {
- return new StartGathering(gatheringPointId, gatheredItem, gatheringController);
- }
-
- private static SkipMarker CreateSkipMarkerTask()
- {
- return new SkipMarker();
- }
- }
-
- private sealed class StartGathering(
- GatheringPointId gatheringPointId,
- GatheredItem gatheredItem,
- GatheringController gatheringController) : ITask
- {
- public bool Start()
- {
- return gatheringController.Start(new GatheringController.GatheringRequest(gatheringPointId,
- gatheredItem.ItemId, gatheredItem.AlternativeItemId, gatheredItem.ItemCount,
- gatheredItem.Collectability));
- }
-
- public ETaskResult Update()
- {
- if (gatheringController.Update() == GatheringController.EStatus.Complete)
- return ETaskResult.TaskComplete;
-
- return ETaskResult.StillRunning;
- }
-
- public override string ToString()
- {
- if (gatheredItem.Collectability == 0)
- return $"Gather({gatheredItem.ItemCount}x {gatheredItem.ItemId})";
- else
- return
- $"Gather({gatheredItem.ItemCount}x {gatheredItem.ItemId} {SeIconChar.Collectible.ToIconString()} {gatheredItem.Collectability})";
- }
- }
-
- /// <summary>
- /// A task that does nothing, but if we're skipping a step, this will be the task next in queue to be executed (instead of progressing to the next step) if gathering.
- /// </summary>
- internal sealed class SkipMarker : ITask
- {
- public bool Start() => true;
- public ETaskResult Update() => ETaskResult.TaskComplete;
- public override string ToString() => "Gather/SkipMarker";
- }
-}
public ITask Move(MoveParams moveParams)
{
- return new MoveInternal(moveParams, movementController, gameFunctions,
+ return new MoveInternal(moveParams, movementController, mountFactory, gameFunctions,
loggerFactory.CreateLogger<MoveInternal>(), clientState, dataManager);
}
$"Wait(territory: {territoryData.GetNameAndId(step.TerritoryId)})");
if (!step.DisableNavmesh)
+ {
yield return new WaitConditionTask(() => movementController.IsNavmeshReady,
"Wait(navmesh ready)");
- float stopDistance = step.CalculateActualStopDistance();
- Vector3? position = clientState.LocalPlayer?.Position;
- float actualDistance = position == null ? float.MaxValue : Vector3.Distance(position.Value, destination);
-
- // if we teleport to a different zone, assume we always need to move; this is primarily relevant for cases
- // where you're e.g. in Lakeland, and the step navigates via Crystarium → Tesselation back into the same
- // zone.
- //
- // Side effects of this check being broken include:
- // - mounting when near the target npc (if you spawn close enough for the next step)
- // - trying to fly when near the target npc (if close enough where no movement is required)
- if (step.AetheryteShortcut != null &&
- aetheryteData.TerritoryIds[step.AetheryteShortcut.Value] != step.TerritoryId)
- {
- logger.LogDebug("Aetheryte: Changing distance to max, previous distance: {Distance}", actualDistance);
- actualDistance = float.MaxValue;
- }
-
- // Fixes a case where you're initiating the gathering step when standing next to the NPC already
- // TODO maybe this should be delayed up until starting movement
- if (questId is SatisfactionSupplyNpcId)
- {
- logger.LogDebug("SatisfactionSupply: Changing distance to max, previous distance: {Distance}",
- actualDistance);
- actualDistance = float.MaxValue;
- }
-
- if (step.Mount == true)
- yield return mountFactory.Mount(step.TerritoryId, Mount.EMountIf.Always);
- else if (step.Mount == false)
- yield return mountFactory.Unmount();
-
- if (!step.DisableNavmesh)
- {
- if (step.Mount == null)
- {
- Mount.EMountIf mountIf =
- actualDistance > stopDistance && step.Fly == true &&
- gameFunctions.IsFlyingUnlocked(step.TerritoryId)
- ? Mount.EMountIf.Always
- : Mount.EMountIf.AwayFromPosition;
- yield return mountFactory.Mount(step.TerritoryId, mountIf, destination);
- }
-
- if (actualDistance > stopDistance)
- {
- yield return Move(step, destination);
- }
- else
- logger.LogInformation("Skipping move task, distance: {ActualDistance} < {StopDistance}",
- actualDistance, stopDistance);
+ yield return Move(step, destination);
}
else
{
- // navmesh won't move close enough
- if (actualDistance > stopDistance)
- {
- yield return Move(step, destination);
- }
- else
- logger.LogInformation("Skipping move task, distance: {ActualDistance} < {StopDistance}",
- actualDistance, stopDistance);
+ yield return Move(step, destination);
}
- if (step.Fly == true && step.Land == true)
+ if (step is { Fly: true, Land: true })
yield return Land();
}
}
{
private readonly string _cannotExecuteAtThisTime;
private readonly MovementController _movementController;
+ private readonly Mount.Factory _mountFactory;
+ private readonly GameFunctions _gameFunctions;
private readonly ILogger<MoveInternal> _logger;
private readonly IClientState _clientState;
private readonly Vector3 _destination;
private readonly MoveParams _moveParams;
private bool _canRestart;
+ private ITask? _mountTask;
public MoveInternal(MoveParams moveParams,
MovementController movementController,
+ Mount.Factory mountFactory,
GameFunctions gameFunctions,
ILogger<MoveInternal> logger,
IClientState clientState,
IDataManager dataManager)
{
_movementController = movementController;
+ _mountFactory = mountFactory;
+ _gameFunctions = gameFunctions;
_logger = logger;
_clientState = clientState;
_cannotExecuteAtThisTime = dataManager.GetString<LogMessage>(579, x => x.Text)!;
public bool Start()
{
- _logger.LogInformation("Moving to {Destination}", _destination.ToString("G", CultureInfo.InvariantCulture));
- _startAction();
+ float stopDistance = _moveParams.StopDistance ?? QuestStep.DefaultStopDistance;
+ Vector3? position = _clientState.LocalPlayer?.Position;
+ float actualDistance = position == null ? float.MaxValue : Vector3.Distance(position.Value, _destination);
+
+ if (_moveParams.Mount == true)
+ {
+ var mountTask = _mountFactory.Mount(_moveParams.TerritoryId, Mount.EMountIf.Always);
+ if (mountTask.Start())
+ {
+ _mountTask = mountTask;
+ return true;
+ }
+ }
+ else if (_moveParams.Mount == false)
+ {
+ var mountTask = _mountFactory.Unmount();
+ if (mountTask.Start())
+ {
+ _mountTask = mountTask;
+ return true;
+ }
+ }
+
+ if (!_moveParams.DisableNavMesh)
+ {
+ if (_moveParams.Mount == null)
+ {
+ Mount.EMountIf mountIf =
+ actualDistance > stopDistance && _moveParams.Fly &&
+ _gameFunctions.IsFlyingUnlocked(_moveParams.TerritoryId)
+ ? Mount.EMountIf.Always
+ : Mount.EMountIf.AwayFromPosition;
+ var mountTask = _mountFactory.Mount(_moveParams.TerritoryId, mountIf, _destination);
+ if (mountTask.Start())
+ {
+ _mountTask = mountTask;
+ return true;
+ }
+ }
+ }
+
+ _mountTask = new NoOpTask();
return true;
}
public ETaskResult Update()
{
+ if (_mountTask != null)
+ {
+ if (_mountTask.Update() == ETaskResult.TaskComplete)
+ {
+ _mountTask = null;
+
+ _logger.LogInformation("Moving to {Destination}", _destination.ToString("G", CultureInfo.InvariantCulture));
+ _startAction();
+ }
+ return ETaskResult.StillRunning;
+ }
+
if (_movementController.IsPathfinding || _movementController.IsPathRunning)
return ETaskResult.StillRunning;
}
}
+ private sealed class NoOpTask : ITask
+ {
+ public bool Start() => true;
+
+ public ETaskResult Update() => ETaskResult.TaskComplete;
+ }
+
internal sealed record MoveParams(
ushort TerritoryId,
Vector3 Destination,
+ bool? Mount = null,
float? StopDistance = null,
uint? DataId = null,
bool DisableNavMesh = false,
public MoveParams(QuestStep step, Vector3 destination)
: this(step.TerritoryId,
destination,
+ step.Mount,
step.CalculateActualStopDistance(),
step.DataId,
step.DisableNavmesh,
// task factories
serviceCollection.AddTaskFactory<StepDisabled.Factory>();
serviceCollection.AddTaskFactory<EquipRecommended.BeforeDutyOrInstance>();
- serviceCollection.AddTaskFactory<GatheringRequiredItems.Factory>();
+ serviceCollection.AddTaskFactory<Gather.Factory>();
serviceCollection.AddTaskFactory<AetheryteShortcut.Factory>();
serviceCollection.AddTaskFactory<SkipCondition.Factory>();
serviceCollection.AddTaskFactory<AethernetShortcut.Factory>();