Quest automation + various fixes
This commit is contained in:
parent
1356818abe
commit
410d891f7f
@ -68,7 +68,15 @@
|
|||||||
"Z": -464.7746
|
"Z": -464.7746
|
||||||
},
|
},
|
||||||
"TerritoryId": 956,
|
"TerritoryId": 956,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
128
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1038716,
|
"DataId": 1038716,
|
||||||
@ -78,7 +86,15 @@
|
|||||||
"Z": -458.2132
|
"Z": -458.2132
|
||||||
},
|
},
|
||||||
"TerritoryId": 956,
|
"TerritoryId": 956,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
64
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -108,8 +124,8 @@
|
|||||||
"Z": -519.18823
|
"Z": -519.18823
|
||||||
},
|
},
|
||||||
"TerritoryId": 956,
|
"TerritoryId": 956,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "WaitForManualProgress",
|
||||||
"Comment": "Duty - Shoot Large Green Bird"
|
"Comment": "Shoot Large Green Bird"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -126,7 +126,15 @@
|
|||||||
"Z": -108.537415
|
"Z": -108.537415
|
||||||
},
|
},
|
||||||
"TerritoryId": 956,
|
"TerritoryId": 956,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
128
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1038707,
|
"DataId": 1038707,
|
||||||
@ -136,7 +144,15 @@
|
|||||||
"Z": -150.04199
|
"Z": -150.04199
|
||||||
},
|
},
|
||||||
"TerritoryId": 956,
|
"TerritoryId": 956,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
64
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1038708,
|
"DataId": 1038708,
|
||||||
@ -146,7 +162,15 @@
|
|||||||
"Z": -130.11371
|
"Z": -130.11371
|
||||||
},
|
},
|
||||||
"TerritoryId": 956,
|
"TerritoryId": 956,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -35,13 +35,13 @@
|
|||||||
"Comment": "A Frosty Reception",
|
"Comment": "A Frosty Reception",
|
||||||
"DialogueChoices": [
|
"DialogueChoices": [
|
||||||
{
|
{
|
||||||
"Type": "ContentTalkList",
|
"Type": "List",
|
||||||
"Prompt": "264",
|
"Prompt": 264,
|
||||||
"Answer": "267"
|
"Answer": 267
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Type": "ContentTalkYesNo",
|
"Type": "YesNo",
|
||||||
"Prompt": "268",
|
"Prompt": 268,
|
||||||
"Yes": true
|
"Yes": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -97,7 +97,7 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 960,
|
"TerritoryId": 960,
|
||||||
"InteractionType": "WaitForManualProgress",
|
"InteractionType": "WaitForManualProgress",
|
||||||
"Comment": "Duty - Find Errant Omicron"
|
"Comment": "Find Errant Omicron"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -113,7 +113,8 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Crystarium] Aetheryte Plaza",
|
"[Crystarium] Aetheryte Plaza",
|
||||||
"[Crystarium] The Dossal Gate"
|
"[Crystarium] The Dossal Gate"
|
||||||
]
|
],
|
||||||
|
"TargetTerritoryId": 844
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1032121,
|
"DataId": 1032121,
|
||||||
|
@ -33,7 +33,8 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Crystarium] Aetheryte Plaza",
|
"[Crystarium] Aetheryte Plaza",
|
||||||
"[Crystarium] The Dossal Gate"
|
"[Crystarium] The Dossal Gate"
|
||||||
]
|
],
|
||||||
|
"TargetTerritoryId": 844
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -82,7 +83,15 @@
|
|||||||
"TerritoryId": 815,
|
"TerritoryId": 815,
|
||||||
"InteractionType": "UseItem",
|
"InteractionType": "UseItem",
|
||||||
"ItemId": 2002904,
|
"ItemId": 2002904,
|
||||||
"$.1": "QuestVariables if done first: 1 32 0 0 0 64"
|
"$.1": "QuestVariables if done first: 1 32 0 0 0 64",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
64
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1027909,
|
"DataId": 1027909,
|
||||||
@ -94,7 +103,15 @@
|
|||||||
"TerritoryId": 815,
|
"TerritoryId": 815,
|
||||||
"InteractionType": "UseItem",
|
"InteractionType": "UseItem",
|
||||||
"ItemId": 2002904,
|
"ItemId": 2002904,
|
||||||
"$.1": "QuestVariables if done after [1]: 2 16 0 0 0 96"
|
"$.1": "QuestVariables if done after [1]: 2 16 0 0 0 96",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1027939,
|
"DataId": 1027939,
|
||||||
@ -105,7 +122,15 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 815,
|
"TerritoryId": 815,
|
||||||
"InteractionType": "UseItem",
|
"InteractionType": "UseItem",
|
||||||
"ItemId": 2002904
|
"ItemId": 2002904,
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
128
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -28,7 +28,14 @@
|
|||||||
"Z": 305.19568
|
"Z": 305.19568
|
||||||
},
|
},
|
||||||
"TerritoryId": 815,
|
"TerritoryId": 815,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_LUCKMG104_03676_Q2_000_100",
|
||||||
|
"Answer": "TEXT_LUCKMG104_03676_A1_000_100"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -61,7 +68,16 @@
|
|||||||
"StopDistance": 1,
|
"StopDistance": 1,
|
||||||
"TerritoryId": 815,
|
"TerritoryId": 815,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"$.1": "QuestVariables if done first: 16 16 16 0 0 32"
|
"$.1": "QuestVariables if done first: 16 16 16 0 0 32",
|
||||||
|
"Fly": true,
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2010810,
|
"DataId": 2010810,
|
||||||
@ -72,7 +88,15 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 815,
|
"TerritoryId": 815,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"$.1": "QuestVariables if done after [1]: 33 16 32 0 0 96"
|
"$.1": "QuestVariables if done after [1]: 33 16 32 0 0 96",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
64
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2010809,
|
"DataId": 2010809,
|
||||||
@ -83,13 +107,31 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 815,
|
"TerritoryId": 815,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"Comment": "Combat not necessary to progress quest"
|
"Comment": "Combat not necessary to progress quest",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
128
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Sequence": 4,
|
"Sequence": 4,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": 47.593674,
|
||||||
|
"Y": 42.681213,
|
||||||
|
"Z": -511.2799
|
||||||
|
},
|
||||||
|
"TerritoryId": 815,
|
||||||
|
"InteractionType": "WalkTo",
|
||||||
|
"Comment": "Should be far enough to reset combat"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1031732,
|
"DataId": 1031732,
|
||||||
"Position": {
|
"Position": {
|
||||||
@ -99,7 +141,14 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 815,
|
"TerritoryId": 815,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"AetheryteShortcut": "Amh Araeng - Inn at Journey's Head"
|
"AetheryteShortcut": "Amh Araeng - Inn at Journey's Head",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_LUCKMG104_03676_Q3_000_200",
|
||||||
|
"Answer": "TEXT_LUCKMG104_03676_A1_000_200"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -29,7 +29,15 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 820,
|
"TerritoryId": 820,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"$.1": "QuestValues if done first: 16 1 16 0 0 128"
|
"$.1": "QuestValues if done first: 16 1 16 0 0 128",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
128
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1027602,
|
"DataId": 1027602,
|
||||||
@ -44,7 +52,15 @@
|
|||||||
"[Eulmore] Aetheryte Plaza",
|
"[Eulmore] Aetheryte Plaza",
|
||||||
"[Eulmore] Southeast Derelicts"
|
"[Eulmore] Southeast Derelicts"
|
||||||
],
|
],
|
||||||
"$.1": "QuestValues if done after [1]: 32 17 16 16 0 160"
|
"$.1": "QuestValues if done after [1]: 32 17 16 16 0 160",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1029990,
|
"DataId": 1029990,
|
||||||
@ -58,6 +74,14 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Eulmore] Southeast Derelicts",
|
"[Eulmore] Southeast Derelicts",
|
||||||
"[Eulmore] The Glory Gate"
|
"[Eulmore] The Glory Gate"
|
||||||
|
],
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
64
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
"Z": -161.45575
|
"Z": -161.45575
|
||||||
},
|
},
|
||||||
"TerritoryId": 814,
|
"TerritoryId": 814,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "WaitForManualProgress",
|
||||||
"Comment": "Help Master Chai dodge enemies"
|
"Comment": "Help Master Chai dodge enemies"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -36,7 +36,8 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Crystarium] Aetheryte Plaza",
|
"[Crystarium] Aetheryte Plaza",
|
||||||
"[Crystarium] The Dossal Gate"
|
"[Crystarium] The Dossal Gate"
|
||||||
]
|
],
|
||||||
|
"TargetTerritoryId": 844
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1032121,
|
"DataId": 1032121,
|
||||||
@ -74,7 +75,14 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 351,
|
"TerritoryId": 351,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"Comment": "Estinien vs. Arch Ultima"
|
"Comment": "Estinien vs. Arch Ultima",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_LUCKMG110_03682_Q1_100_125",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -33,7 +33,8 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Crystarium] Aetheryte Plaza",
|
"[Crystarium] Aetheryte Plaza",
|
||||||
"[Crystarium] The Dossal Gate"
|
"[Crystarium] The Dossal Gate"
|
||||||
]
|
],
|
||||||
|
"TargetTerritoryId": 844
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1032121,
|
"DataId": 1032121,
|
||||||
|
@ -28,7 +28,8 @@
|
|||||||
"Z": 14.22064
|
"Z": 14.22064
|
||||||
},
|
},
|
||||||
"TerritoryId": 844,
|
"TerritoryId": 844,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"TargetTerritoryId": 819
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1030370,
|
"DataId": 1030370,
|
||||||
@ -38,7 +39,14 @@
|
|||||||
"Z": 13.321045
|
"Z": 13.321045
|
||||||
},
|
},
|
||||||
"TerritoryId": 819,
|
"TerritoryId": 819,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_LUCKMH103_03763_Q1_000_500",
|
||||||
|
"Answer": "TEXT_LUCKMH103_03763_A1_000_500"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -33,7 +33,8 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Crystarium] Aetheryte Plaza",
|
"[Crystarium] Aetheryte Plaza",
|
||||||
"[Crystarium] The Dossal Gate"
|
"[Crystarium] The Dossal Gate"
|
||||||
]
|
],
|
||||||
|
"TargetTerritoryId": 844
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1031722,
|
"DataId": 1031722,
|
||||||
@ -58,7 +59,8 @@
|
|||||||
"Z": 14.206055
|
"Z": 14.206055
|
||||||
},
|
},
|
||||||
"TerritoryId": 844,
|
"TerritoryId": 844,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"TargetTerritoryId": 819
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1027248,
|
"DataId": 1027248,
|
||||||
@ -71,7 +73,15 @@
|
|||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"Comment": "Chessamile",
|
"Comment": "Chessamile",
|
||||||
"$.0": "[1]",
|
"$.0": "[1]",
|
||||||
"$.1": "QuestVariables if done first: 1 0 0 0 0 64"
|
"$.1": "QuestVariables if done first: 1 0 0 0 0 64",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
64
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1027224,
|
"DataId": 1027224,
|
||||||
@ -84,7 +94,15 @@
|
|||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"Comment": "Bragi",
|
"Comment": "Bragi",
|
||||||
"$.0": "[2]",
|
"$.0": "[2]",
|
||||||
"$.1": "QuestVariables if done after [1]: 2 0 0 0 0 192"
|
"$.1": "QuestVariables if done after [1]: 2 0 0 0 0 192",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
128
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1027322,
|
"DataId": 1027322,
|
||||||
@ -98,7 +116,15 @@
|
|||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"Comment": "Glynard",
|
"Comment": "Glynard",
|
||||||
"$.0": "[3]",
|
"$.0": "[3]",
|
||||||
"$.1": "QuestVariables if done after [1, 2]: 3 0 0 0 0 200"
|
"$.1": "QuestVariables if done after [1, 2]: 3 0 0 0 0 200",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
8
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1027232,
|
"DataId": 1027232,
|
||||||
@ -115,7 +141,15 @@
|
|||||||
"[Crystarium] The Crystalline Mean"
|
"[Crystarium] The Crystalline Mean"
|
||||||
],
|
],
|
||||||
"$.0": "[4]",
|
"$.0": "[4]",
|
||||||
"$.1": "QuestVariables if done after [1, 2, 3]: 4 0 0 0 0 216"
|
"$.1": "QuestVariables if done after [1, 2, 3]: 4 0 0 0 0 216",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
16
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1027226,
|
"DataId": 1027226,
|
||||||
@ -130,6 +164,14 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Crystarium] The Crystalline Mean",
|
"[Crystarium] The Crystalline Mean",
|
||||||
"[Crystarium] The Cabinet of Curiosity"
|
"[Crystarium] The Cabinet of Curiosity"
|
||||||
|
],
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -47,7 +47,31 @@
|
|||||||
"TerritoryId": 817,
|
"TerritoryId": 817,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"Fly": true,
|
"Fly": true,
|
||||||
"Comment": "Duty - A Sleep Disturbed (Opo-Opo, Wolf, Serpent)"
|
"Comment": "A Sleep Disturbed (Opo-Opo, Wolf, Serpent)",
|
||||||
|
"$": "The dialogue choices and data ids here are recycled",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"DataId": 2011009,
|
||||||
|
"ExcelSheet": "GimmickYesNo",
|
||||||
|
"Prompt": 138,
|
||||||
|
"Yes": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"DataId": 2011006,
|
||||||
|
"ExcelSheet": "GimmickYesNo",
|
||||||
|
"Prompt": 139,
|
||||||
|
"Yes": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"DataId": 2011007,
|
||||||
|
"ExcelSheet": "GimmickYesNo",
|
||||||
|
"Prompt": 142,
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -36,6 +36,19 @@
|
|||||||
{
|
{
|
||||||
"Sequence": 2,
|
"Sequence": 2,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": -475.38354,
|
||||||
|
"Y": 400.55338,
|
||||||
|
"Z": -779.4299
|
||||||
|
},
|
||||||
|
"TerritoryId": 818,
|
||||||
|
"InteractionType": "WalkTo",
|
||||||
|
"Fly": true,
|
||||||
|
"SkipIf": [
|
||||||
|
"FlyingLocked"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Position": {
|
"Position": {
|
||||||
"X": -423.6145,
|
"X": -423.6145,
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 813,
|
"TerritoryId": 813,
|
||||||
"InteractionType": "WalkTo",
|
"InteractionType": "WalkTo",
|
||||||
"AetheryteShortcut": "Lakeland - Ostall Imperative",
|
"AetheryteShortcut": "Lakeland - Fort Jobb",
|
||||||
"Fly": true
|
"Fly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -95,7 +95,15 @@
|
|||||||
"TerritoryId": 813,
|
"TerritoryId": 813,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"DisableNavmesh": true,
|
"DisableNavmesh": true,
|
||||||
"$.1": "QuestVariables if done first: 1 0 0 0 0 64"
|
"$.1": "QuestVariables if done first: 1 0 0 0 0 64",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
64
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2010278,
|
"DataId": 2010278,
|
||||||
@ -106,7 +114,15 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 813,
|
"TerritoryId": 813,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"DisableNavmesh": true
|
"DisableNavmesh": true,
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
128
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2010282,
|
"DataId": 2010282,
|
||||||
@ -117,7 +133,16 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 813,
|
"TerritoryId": 813,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"DisableNavmesh": true
|
"DisableNavmesh": true,
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
],
|
||||||
|
"Comment": "TODO Check if pathfinding works automatically now"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://carvel.li/questionable/quest-1.0",
|
"$schema": "https://carvel.li/questionable/quest-1.0",
|
||||||
"Author": "liza",
|
"Author": "liza",
|
||||||
"Comment": "TODO Missing quest end",
|
|
||||||
"TerritoryBlacklist": [
|
"TerritoryBlacklist": [
|
||||||
898
|
898
|
||||||
],
|
],
|
||||||
@ -33,6 +32,7 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 814,
|
"TerritoryId": 814,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
|
"AetheryteShortcut": "Kholusia - Wright",
|
||||||
"Fly": true
|
"Fly": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -46,6 +46,21 @@
|
|||||||
"ContentFinderConditionId": 714
|
"ContentFinderConditionId": 714
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Sequence": 255,
|
||||||
|
"Steps": [
|
||||||
|
{
|
||||||
|
"DataId": 1032549,
|
||||||
|
"Position": {
|
||||||
|
"X": -1.9074707,
|
||||||
|
"Y": -200.00002,
|
||||||
|
"Z": -425.10114
|
||||||
|
},
|
||||||
|
"TerritoryId": 918,
|
||||||
|
"InteractionType": "Interact"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Sequence": 1,
|
"Sequence": 2,
|
||||||
"Comment": "TODO verify this is the correct sequence and/or where sequence 2 went",
|
|
||||||
"Steps": [
|
"Steps": [
|
||||||
{
|
{
|
||||||
"DataId": 1032529,
|
"DataId": 1032529,
|
||||||
@ -67,7 +66,8 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Crystarium] The Amaro Launch",
|
"[Crystarium] The Amaro Launch",
|
||||||
"[Crystarium] The Dossal Gate"
|
"[Crystarium] The Dossal Gate"
|
||||||
]
|
],
|
||||||
|
"TargetTerritoryId": 844
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1032121,
|
"DataId": 1032121,
|
||||||
@ -92,7 +92,8 @@
|
|||||||
"Z": 14.206055
|
"Z": 14.206055
|
||||||
},
|
},
|
||||||
"TerritoryId": 844,
|
"TerritoryId": 844,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"TargetTerritoryId": 819
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1030610,
|
"DataId": 1030610,
|
||||||
@ -107,6 +108,13 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Crystarium] The Dossal Gate",
|
"[Crystarium] The Dossal Gate",
|
||||||
"[Crystarium] The Pendants"
|
"[Crystarium] The Pendants"
|
||||||
|
],
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_LUCKMH110_03770_Q1_000_600",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -48,7 +48,14 @@
|
|||||||
"Z": -277.7906
|
"Z": -277.7906
|
||||||
},
|
},
|
||||||
"TerritoryId": 819,
|
"TerritoryId": 819,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_LUCKMI101_03771_Q3_000_148",
|
||||||
|
"Answer": "TEXT_LUCKMI101_03771_A3_000_149"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -98,6 +105,14 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 819,
|
"TerritoryId": 819,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
64
|
||||||
|
],
|
||||||
"$.1": "QuestVariables if done first: 1 16 0 0 0 64"
|
"$.1": "QuestVariables if done first: 1 16 0 0 0 64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -110,6 +125,14 @@
|
|||||||
"StopDistance": 5,
|
"StopDistance": 5,
|
||||||
"TerritoryId": 819,
|
"TerritoryId": 819,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
128
|
||||||
|
],
|
||||||
"$.1": "QuestVariables if done after [1]: 2 32 0 0 0 192"
|
"$.1": "QuestVariables if done after [1]: 2 32 0 0 0 192"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -120,7 +143,15 @@
|
|||||||
"Z": 173.38818
|
"Z": 173.38818
|
||||||
},
|
},
|
||||||
"TerritoryId": 819,
|
"TerritoryId": 819,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -142,15 +173,6 @@
|
|||||||
{
|
{
|
||||||
"Sequence": 255,
|
"Sequence": 255,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
{
|
|
||||||
"Position": {
|
|
||||||
"X": -140.22343,
|
|
||||||
"Y": 0.05337119,
|
|
||||||
"Z": 34.20123
|
|
||||||
},
|
|
||||||
"TerritoryId": 819,
|
|
||||||
"InteractionType": "WalkTo"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"DataId": 1027248,
|
"DataId": 1027248,
|
||||||
"Position": {
|
"Position": {
|
||||||
@ -159,7 +181,8 @@
|
|||||||
"Z": -51.438232
|
"Z": -51.438232
|
||||||
},
|
},
|
||||||
"TerritoryId": 819,
|
"TerritoryId": 819,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"AetheryteShortcut": "Crystarium"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Sequence": 2,
|
"Sequence": 2,
|
||||||
|
"Comment": "This isn't solving for the 'best' results, but for the closest waypoints",
|
||||||
"Steps": [
|
"Steps": [
|
||||||
{
|
{
|
||||||
"DataId": 2011078,
|
"DataId": 2011078,
|
||||||
@ -56,7 +57,15 @@
|
|||||||
],
|
],
|
||||||
"Fly": true,
|
"Fly": true,
|
||||||
"$.0": "[1]",
|
"$.0": "[1]",
|
||||||
"$.1": "QuestVariables if done first: 0 0 0 3 0 0 during fight; 16 1 0 2 16 8 after"
|
"$.1": "QuestVariables if done first: 0 0 0 3 0 0 during fight; 16 1 0 2 16 8 after",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
8
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2011076,
|
"DataId": 2011076,
|
||||||
@ -69,10 +78,19 @@
|
|||||||
"InteractionType": "Combat",
|
"InteractionType": "Combat",
|
||||||
"EnemySpawnType": "AfterItemUse",
|
"EnemySpawnType": "AfterItemUse",
|
||||||
"ItemId": 2003001,
|
"ItemId": 2003001,
|
||||||
"KillEnemyDataIds": [],
|
"KillEnemyDataIds": [
|
||||||
"Comment": "TODO Missing enemy ids",
|
12166
|
||||||
|
],
|
||||||
"Fly": true,
|
"Fly": true,
|
||||||
"$.1": "QuestVariables if done after [1]: 34 1 0 1 48 40"
|
"$.1": "QuestVariables if done after [1]: 34 1 0 1 48 40",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2011079,
|
"DataId": 2011079,
|
||||||
@ -86,10 +104,11 @@
|
|||||||
"EnemySpawnType": "AfterItemUse",
|
"EnemySpawnType": "AfterItemUse",
|
||||||
"ItemId": 2003001,
|
"ItemId": 2003001,
|
||||||
"KillEnemyDataIds": [
|
"KillEnemyDataIds": [
|
||||||
|
12168
|
||||||
],
|
],
|
||||||
"Comment": "TODO Missing enemy ids",
|
"Comment": "TODO Missing enemy ids",
|
||||||
"Fly": true,
|
"Fly": true,
|
||||||
"$.2": "QuestVariables if done after [1, 2]: 0 64 0 0 0 0"
|
"$.2": "QuestVariables if done after [1, 2]: irrelevant because it automatically progresses to the next step"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -79,7 +79,8 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Crystarium] Aetheryte Plaza",
|
"[Crystarium] Aetheryte Plaza",
|
||||||
"[Crystarium] The Dossal Gate"
|
"[Crystarium] The Dossal Gate"
|
||||||
]
|
],
|
||||||
|
"TargetTerritoryId": 844
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1033819,
|
"DataId": 1033819,
|
||||||
|
@ -42,7 +42,14 @@
|
|||||||
"Z": 604.27246
|
"Z": 604.27246
|
||||||
},
|
},
|
||||||
"TerritoryId": 814,
|
"TerritoryId": 814,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_LUCKMI105_03775_Q2_000_052",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -16,12 +16,19 @@
|
|||||||
"Z": 1.6021729
|
"Z": 1.6021729
|
||||||
},
|
},
|
||||||
"TerritoryId": 819,
|
"TerritoryId": 819,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_LUCKMI108_03778_Q1_000_001",
|
||||||
|
"Answer": "TEXT_LUCKMI108_03778_A1_000_002"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Sequence": 1,
|
"Sequence": 2,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
{
|
{
|
||||||
"TerritoryId": 931,
|
"TerritoryId": 931,
|
||||||
|
@ -85,8 +85,13 @@
|
|||||||
"Sequence": 5,
|
"Sequence": 5,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
{
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": 0,
|
||||||
|
"Y": 0,
|
||||||
|
"Z": 0
|
||||||
|
},
|
||||||
"TerritoryId": 820,
|
"TerritoryId": 820,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "WalkTo",
|
||||||
"AetheryteShortcut": "Eulmore"
|
"AetheryteShortcut": "Eulmore"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -75,7 +75,15 @@
|
|||||||
"Z": 3.982544
|
"Z": 3.982544
|
||||||
},
|
},
|
||||||
"TerritoryId": 819,
|
"TerritoryId": 819,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"AetheryteShortcut": "Crystarium",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_LUCKMI111_03781_Q1_000_153",
|
||||||
|
"Answer": "TEXT_LUCKMI111_03781_A1_000_154"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -29,7 +29,14 @@
|
|||||||
"Z": 7.156433
|
"Z": 7.156433
|
||||||
},
|
},
|
||||||
"TerritoryId": 819,
|
"TerritoryId": 819,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_LUCKMI112_03782_Q1_000_007",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1033888,
|
"DataId": 1033888,
|
||||||
@ -39,7 +46,14 @@
|
|||||||
"Z": -5.081299
|
"Z": -5.081299
|
||||||
},
|
},
|
||||||
"TerritoryId": 844,
|
"TerritoryId": 844,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_LUCKMI112_03782_Q2_000_044",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -64,7 +64,8 @@
|
|||||||
"EnemySpawnType": "AfterInteraction",
|
"EnemySpawnType": "AfterInteraction",
|
||||||
"KillEnemyDataIds": [
|
"KillEnemyDataIds": [
|
||||||
12661
|
12661
|
||||||
]
|
],
|
||||||
|
"Fly": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -55,7 +55,8 @@
|
|||||||
"Z": -6.9733887
|
"Z": -6.9733887
|
||||||
},
|
},
|
||||||
"TerritoryId": 351,
|
"TerritoryId": 351,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"TargetTerritoryId": 351
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2011332,
|
"DataId": 2011332,
|
||||||
|
@ -14,7 +14,14 @@
|
|||||||
},
|
},
|
||||||
"StopDistance": 5,
|
"StopDistance": 5,
|
||||||
"TerritoryId": 351,
|
"TerritoryId": 351,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_LUCKMJ104_04010_Q1_000_000",
|
||||||
|
"Answer": "TEXT_LUCKMJ104_04010_A1_000_002"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -29,7 +29,14 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 129,
|
"TerritoryId": 129,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"AetheryteShortcut": "Limsa Lominsa"
|
"AetheryteShortcut": "Limsa Lominsa",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_LUCKMJ108_04014_SYSTEM_100_010",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1002694,
|
"DataId": 1002694,
|
||||||
|
@ -39,6 +39,26 @@
|
|||||||
{
|
{
|
||||||
"Sequence": 2,
|
"Sequence": 2,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": 46.600548,
|
||||||
|
"Y": 77.45801,
|
||||||
|
"Z": -366.82053
|
||||||
|
},
|
||||||
|
"TerritoryId": 180,
|
||||||
|
"InteractionType": "WalkTo",
|
||||||
|
"Fly": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": 111.927666,
|
||||||
|
"Y": 26.050894,
|
||||||
|
"Z": -612.8873
|
||||||
|
},
|
||||||
|
"TerritoryId": 180,
|
||||||
|
"InteractionType": "WalkTo",
|
||||||
|
"Fly": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Position": {
|
"Position": {
|
||||||
"X": 82.19566,
|
"X": 82.19566,
|
||||||
|
@ -79,7 +79,15 @@
|
|||||||
"TerritoryId": 402,
|
"TerritoryId": 402,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"Fly": true,
|
"Fly": true,
|
||||||
"$.1": "QuestVariables if done first: 1 16 0 0 0 64"
|
"$.1": "QuestVariables if done first: 1 16 0 0 0 64",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
64
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1036359,
|
"DataId": 1036359,
|
||||||
@ -92,7 +100,15 @@
|
|||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"Mount": true,
|
"Mount": true,
|
||||||
"Fly": true,
|
"Fly": true,
|
||||||
"$.1": "QuestVariables if done after [1]: 2 16 0 0 0 96"
|
"$.1": "QuestVariables if done after [1]: 2 16 0 0 0 96",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1036357,
|
"DataId": 1036357,
|
||||||
@ -103,7 +119,15 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 402,
|
"TerritoryId": 402,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"DisableNavmesh": true
|
"DisableNavmesh": true,
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
128
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -119,7 +143,14 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 402,
|
"TerritoryId": 402,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"Fly": true
|
"Fly": true,
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_LUCKMK103_04060_Q1_000_100",
|
||||||
|
"Answer": "TEXT_LUCKMK103_04060_A2_000_100"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -33,6 +33,13 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Ul'dah] Aetheryte Plaza",
|
"[Ul'dah] Aetheryte Plaza",
|
||||||
"[Ul'dah] Alchemists' Guild"
|
"[Ul'dah] Alchemists' Guild"
|
||||||
|
],
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_LUCKMK106_04063_Q1_000_100",
|
||||||
|
"Answer": "TEXT_LUCKMK106_04063_A2_000_100"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -672,49 +672,40 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
"YesNo",
|
"YesNo",
|
||||||
"List",
|
"List"
|
||||||
"ContentTalkYesNo",
|
|
||||||
"ContentTalkList"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ExcelSheet": {
|
"ExcelSheet": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
|
||||||
"Prompt": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"Type",
|
"Type"
|
||||||
"Prompt"
|
|
||||||
],
|
],
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
"if": {
|
"if": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"Type": {
|
"Type": {
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"const": "YesNo"
|
"const": "YesNo"
|
||||||
},
|
|
||||||
{
|
|
||||||
"const": "ContentTalkYesNo"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"Prompt": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"integer"
|
||||||
|
]
|
||||||
|
},
|
||||||
"Yes": {
|
"Yes": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true
|
"default": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
"Prompt",
|
||||||
"Yes"
|
"Yes"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -723,24 +714,28 @@
|
|||||||
"if": {
|
"if": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"Type": {
|
"Type": {
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"const": "List"
|
"const": "List"
|
||||||
},
|
|
||||||
{
|
|
||||||
"const": "ContentTalkList"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"Prompt": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
"Answer": {
|
"Answer": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"string",
|
||||||
|
"integer"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
"Prompt",
|
||||||
"Answer"
|
"Answer"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,19 @@ namespace Questionable;
|
|||||||
internal sealed class Configuration : IPluginConfiguration
|
internal sealed class Configuration : IPluginConfiguration
|
||||||
{
|
{
|
||||||
public int Version { get; set; } = 1;
|
public int Version { get; set; } = 1;
|
||||||
public WindowConfig DebugWindowConfig { get; set; } = new();
|
public GeneralConfiguration General { get; } = new();
|
||||||
|
public AdvancedConfiguration Advanced { get; } = new();
|
||||||
|
public WindowConfig DebugWindowConfig { get; } = new();
|
||||||
|
public WindowConfig ConfigWindowConfig { get; } = new();
|
||||||
|
|
||||||
|
internal sealed class GeneralConfiguration
|
||||||
|
{
|
||||||
|
public bool AutoAcceptNextQuest { get; set; }
|
||||||
|
public uint MountId { get; set; } = 71;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class AdvancedConfiguration
|
||||||
|
{
|
||||||
|
public bool NeverFly { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using System.Globalization;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Dalamud.Game.Addon.Lifecycle;
|
using Dalamud.Game.Addon.Lifecycle;
|
||||||
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
||||||
|
using Dalamud.Game.ClientState.Objects;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
@ -23,16 +24,19 @@ internal sealed class GameUiController : IDisposable
|
|||||||
private readonly GameFunctions _gameFunctions;
|
private readonly GameFunctions _gameFunctions;
|
||||||
private readonly QuestController _questController;
|
private readonly QuestController _questController;
|
||||||
private readonly IGameGui _gameGui;
|
private readonly IGameGui _gameGui;
|
||||||
|
private readonly ITargetManager _targetManager;
|
||||||
private readonly ILogger<GameUiController> _logger;
|
private readonly ILogger<GameUiController> _logger;
|
||||||
|
|
||||||
public GameUiController(IAddonLifecycle addonLifecycle, IDataManager dataManager, GameFunctions gameFunctions,
|
public GameUiController(IAddonLifecycle addonLifecycle, IDataManager dataManager, GameFunctions gameFunctions,
|
||||||
QuestController questController, IGameGui gameGui, ILogger<GameUiController> logger)
|
QuestController questController, IGameGui gameGui, ITargetManager targetManager,
|
||||||
|
ILogger<GameUiController> logger)
|
||||||
{
|
{
|
||||||
_addonLifecycle = addonLifecycle;
|
_addonLifecycle = addonLifecycle;
|
||||||
_dataManager = dataManager;
|
_dataManager = dataManager;
|
||||||
_gameFunctions = gameFunctions;
|
_gameFunctions = gameFunctions;
|
||||||
_questController = questController;
|
_questController = questController;
|
||||||
_gameGui = gameGui;
|
_gameGui = gameGui;
|
||||||
|
_targetManager = targetManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup);
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup);
|
||||||
@ -181,40 +185,26 @@ internal sealed class GameUiController : IDisposable
|
|||||||
|
|
||||||
foreach (var dialogueChoice in dialogueChoices)
|
foreach (var dialogueChoice in dialogueChoices)
|
||||||
{
|
{
|
||||||
|
if (dialogueChoice.Type != EDialogChoiceType.List)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (dialogueChoice.Answer == null)
|
if (dialogueChoice.Answer == null)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Ignoring entry in DialogueChoices, no answer");
|
_logger.LogDebug("Ignoring entry in DialogueChoices, no answer");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
string? excelPrompt = null, excelAnswer;
|
if (dialogueChoice.DataId != null && dialogueChoice.DataId != _targetManager.Target?.DataId)
|
||||||
switch (dialogueChoice.Type)
|
|
||||||
{
|
{
|
||||||
case EDialogChoiceType.ContentTalkList:
|
_logger.LogDebug(
|
||||||
if (dialogueChoice.Prompt != null)
|
"Skipping entry in DialogueChoice expecting target dataId {ExpectedDataId}, actual target is {ActualTargetId}",
|
||||||
{
|
dialogueChoice.DataId, _targetManager.Target?.DataId);
|
||||||
excelPrompt =
|
|
||||||
_gameFunctions.GetContentTalk(uint.Parse(dialogueChoice.Prompt,
|
|
||||||
CultureInfo.InvariantCulture));
|
|
||||||
}
|
|
||||||
|
|
||||||
excelAnswer =
|
|
||||||
_gameFunctions.GetContentTalk(uint.Parse(dialogueChoice.Answer, CultureInfo.InvariantCulture));
|
|
||||||
break;
|
|
||||||
case EDialogChoiceType.List:
|
|
||||||
if (dialogueChoice.Prompt != null)
|
|
||||||
{
|
|
||||||
excelPrompt =
|
|
||||||
_gameFunctions.GetDialogueText(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
|
|
||||||
}
|
|
||||||
|
|
||||||
excelAnswer =
|
|
||||||
_gameFunctions.GetDialogueText(quest, dialogueChoice.ExcelSheet, dialogueChoice.Answer);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string? excelPrompt = ResolveReference(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
|
||||||
|
string? excelAnswer = ResolveReference(quest, dialogueChoice.ExcelSheet, dialogueChoice.Answer);
|
||||||
|
|
||||||
if (actualPrompt == null && !string.IsNullOrEmpty(excelPrompt))
|
if (actualPrompt == null && !string.IsNullOrEmpty(excelPrompt))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Unexpected excelPrompt: {ExcelPrompt}", excelPrompt);
|
_logger.LogInformation("Unexpected excelPrompt: {ExcelPrompt}", excelPrompt);
|
||||||
@ -288,29 +278,24 @@ internal sealed class GameUiController : IDisposable
|
|||||||
_logger.LogTrace("DefaultYesNo: Choice count: {Count}", dialogueChoices.Count);
|
_logger.LogTrace("DefaultYesNo: Choice count: {Count}", dialogueChoices.Count);
|
||||||
foreach (var dialogueChoice in dialogueChoices)
|
foreach (var dialogueChoice in dialogueChoices)
|
||||||
{
|
{
|
||||||
string? excelPrompt;
|
if (dialogueChoice.Type != EDialogChoiceType.YesNo)
|
||||||
if (dialogueChoice.Prompt != null)
|
|
||||||
{
|
|
||||||
switch (dialogueChoice.Type)
|
|
||||||
{
|
|
||||||
case EDialogChoiceType.ContentTalkYesNo:
|
|
||||||
excelPrompt =
|
|
||||||
_gameFunctions.GetContentTalk(uint.Parse(dialogueChoice.Prompt,
|
|
||||||
CultureInfo.InvariantCulture));
|
|
||||||
break;
|
|
||||||
case EDialogChoiceType.YesNo:
|
|
||||||
excelPrompt =
|
|
||||||
_gameFunctions.GetDialogueText(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
excelPrompt = null;
|
|
||||||
|
|
||||||
if (excelPrompt == null || !GameStringEquals(actualPrompt, excelPrompt))
|
if (dialogueChoice.DataId != null && dialogueChoice.DataId != _targetManager.Target?.DataId)
|
||||||
|
{
|
||||||
|
_logger.LogDebug(
|
||||||
|
"Skipping entry in DialogueChoice expecting target dataId {ExpectedDataId}, actual target is {ActualTargetId}",
|
||||||
|
dialogueChoice.DataId, _targetManager.Target?.DataId);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string? excelPrompt = ResolveReference(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
|
||||||
|
if (excelPrompt == null || !GameStringEquals(actualPrompt, excelPrompt))
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Unexpected excelPrompt: {ExcelPrompt}, actualPrompt: {ActualPrompt}",
|
||||||
|
excelPrompt, actualPrompt);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
addonSelectYesno->AtkUnitBase.FireCallbackInt(dialogueChoice.Yes ? 0 : 1);
|
addonSelectYesno->AtkUnitBase.FireCallbackInt(dialogueChoice.Yes ? 0 : 1);
|
||||||
if (!checkAllSteps)
|
if (!checkAllSteps)
|
||||||
@ -343,7 +328,8 @@ internal sealed class GameUiController : IDisposable
|
|||||||
increaseStepCount = false;
|
increaseStepCount = false;
|
||||||
|
|
||||||
if (step != null)
|
if (step != null)
|
||||||
_logger.LogTrace("Previous step: {CurrentTerritory}, {TargetTerritory}", step.TerritoryId, step.TargetTerritoryId);
|
_logger.LogTrace("Previous step: {CurrentTerritory}, {TargetTerritory}", step.TerritoryId,
|
||||||
|
step.TargetTerritoryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step == null || step.TargetTerritoryId == null)
|
if (step == null || step.TargetTerritoryId == null)
|
||||||
@ -403,6 +389,19 @@ internal sealed class GameUiController : IDisposable
|
|||||||
return a.ReplaceLineEndings().Replace('\u2013', '-') == b.ReplaceLineEndings().Replace('\u2013', '-');
|
return a.ReplaceLineEndings().Replace('\u2013', '-') == b.ReplaceLineEndings().Replace('\u2013', '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string? ResolveReference(Quest quest, string? excelSheet, ExcelRef? excelRef)
|
||||||
|
{
|
||||||
|
if (excelRef == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (excelRef.Type == ExcelRef.EType.Key)
|
||||||
|
return _gameFunctions.GetDialogueText(quest, excelSheet, excelRef.AsKey());
|
||||||
|
else if (excelRef.Type == ExcelRef.EType.RowId)
|
||||||
|
return _gameFunctions.GetDialogueTextByRowId(excelSheet, excelRef.AsRowId());
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup);
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup);
|
||||||
|
@ -76,7 +76,7 @@ internal sealed class MovementController : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!Destination.IsFlying && !_condition[ConditionFlag.Mounted] && navPoints.Count > 0 &&
|
else if (!Destination.IsFlying && !_condition[ConditionFlag.Mounted] && navPoints.Count > 0 &&
|
||||||
!_gameFunctions.HasStatusPreventingSprintOrMount() && Destination.CanSprint)
|
!_gameFunctions.HasStatusPreventingSprintOrMount(true) && Destination.CanSprint)
|
||||||
{
|
{
|
||||||
float actualDistance = 0;
|
float actualDistance = 0;
|
||||||
foreach (Vector3 end in navPoints)
|
foreach (Vector3 end in navPoints)
|
||||||
@ -210,7 +210,7 @@ internal sealed class MovementController : IDisposable
|
|||||||
_logger.LogInformation("Pathfinding to {Destination}", Destination);
|
_logger.LogInformation("Pathfinding to {Destination}", Destination);
|
||||||
|
|
||||||
_cancellationTokenSource = new();
|
_cancellationTokenSource = new();
|
||||||
_cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(10));
|
_cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(30));
|
||||||
_pathfindTask =
|
_pathfindTask =
|
||||||
_navmeshIpc.Pathfind(_clientState.LocalPlayer!.Position, to, fly, _cancellationTokenSource.Token);
|
_navmeshIpc.Pathfind(_clientState.LocalPlayer!.Position, to, fly, _cancellationTokenSource.Token);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ using Dalamud.Game.ClientState.Objects.Types;
|
|||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
|
using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Questionable.Controller.Steps;
|
using Questionable.Controller.Steps;
|
||||||
using Questionable.Data;
|
using Questionable.Data;
|
||||||
@ -28,6 +29,7 @@ internal sealed class QuestController
|
|||||||
private readonly ILogger<QuestController> _logger;
|
private readonly ILogger<QuestController> _logger;
|
||||||
private readonly QuestRegistry _questRegistry;
|
private readonly QuestRegistry _questRegistry;
|
||||||
private readonly IKeyState _keyState;
|
private readonly IKeyState _keyState;
|
||||||
|
private readonly Configuration _configuration;
|
||||||
private readonly IReadOnlyList<ITaskFactory> _taskFactories;
|
private readonly IReadOnlyList<ITaskFactory> _taskFactories;
|
||||||
|
|
||||||
private readonly Queue<ITask> _taskQueue = new();
|
private readonly Queue<ITask> _taskQueue = new();
|
||||||
@ -41,6 +43,7 @@ internal sealed class QuestController
|
|||||||
ILogger<QuestController> logger,
|
ILogger<QuestController> logger,
|
||||||
QuestRegistry questRegistry,
|
QuestRegistry questRegistry,
|
||||||
IKeyState keyState,
|
IKeyState keyState,
|
||||||
|
Configuration configuration,
|
||||||
IEnumerable<ITaskFactory> taskFactories)
|
IEnumerable<ITaskFactory> taskFactories)
|
||||||
{
|
{
|
||||||
_clientState = clientState;
|
_clientState = clientState;
|
||||||
@ -49,6 +52,7 @@ internal sealed class QuestController
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
_questRegistry = questRegistry;
|
_questRegistry = questRegistry;
|
||||||
_keyState = keyState;
|
_keyState = keyState;
|
||||||
|
_configuration = configuration;
|
||||||
_taskFactories = taskFactories.ToList().AsReadOnly();
|
_taskFactories = taskFactories.ToList().AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +83,20 @@ internal sealed class QuestController
|
|||||||
if (CurrentQuest != null && CurrentQuest.Quest.Data.TerritoryBlacklist.Contains(_clientState.TerritoryType))
|
if (CurrentQuest != null && CurrentQuest.Quest.Data.TerritoryBlacklist.Contains(_clientState.TerritoryType))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// not verified to work
|
||||||
|
if (_automatic && _currentTask == null && _taskQueue.Count == 0 && CurrentQuest is { Sequence: 0, Step: 255 }
|
||||||
|
&& DateTime.Now >= CurrentQuest.StepProgress.StartedAt.AddSeconds(15))
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Quest accept apparently didn't work out, resetting progress");
|
||||||
|
CurrentQuest = CurrentQuest with
|
||||||
|
{
|
||||||
|
Step = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
ExecuteNextStep(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UpdateCurrentTask();
|
UpdateCurrentTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +120,13 @@ internal sealed class QuestController
|
|||||||
{
|
{
|
||||||
_logger.LogInformation("New quest: {QuestName}", quest.Name);
|
_logger.LogInformation("New quest: {QuestName}", quest.Name);
|
||||||
CurrentQuest = new QuestProgress(quest, currentSequence, 0);
|
CurrentQuest = new QuestProgress(quest, currentSequence, 0);
|
||||||
Stop("Different Quest");
|
|
||||||
|
bool continueAutomatically = _configuration.General.AutoAcceptNextQuest;
|
||||||
|
|
||||||
|
if (_clientState.LocalPlayer?.Level < quest.Level)
|
||||||
|
continueAutomatically = false;
|
||||||
|
|
||||||
|
Stop("Different Quest", continueAutomatically);
|
||||||
}
|
}
|
||||||
else if (CurrentQuest != null)
|
else if (CurrentQuest != null)
|
||||||
{
|
{
|
||||||
@ -208,7 +232,7 @@ internal sealed class QuestController
|
|||||||
CurrentQuest = CurrentQuest with
|
CurrentQuest = CurrentQuest with
|
||||||
{
|
{
|
||||||
Step = CurrentQuest.Step + 1,
|
Step = CurrentQuest.Step + 1,
|
||||||
StepProgress = new()
|
StepProgress = new(DateTime.Now),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -216,7 +240,7 @@ internal sealed class QuestController
|
|||||||
CurrentQuest = CurrentQuest with
|
CurrentQuest = CurrentQuest with
|
||||||
{
|
{
|
||||||
Step = 255,
|
Step = 255,
|
||||||
StepProgress = new()
|
StepProgress = new(DateTime.Now),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,6 +440,8 @@ internal sealed class QuestController
|
|||||||
public bool HasCurrentTaskMatching<T>() =>
|
public bool HasCurrentTaskMatching<T>() =>
|
||||||
_currentTask is T;
|
_currentTask is T;
|
||||||
|
|
||||||
|
public bool IsRunning => _currentTask != null || _taskQueue.Count > 0;
|
||||||
|
|
||||||
public sealed record QuestProgress(
|
public sealed record QuestProgress(
|
||||||
Quest Quest,
|
Quest Quest,
|
||||||
byte Sequence,
|
byte Sequence,
|
||||||
@ -423,12 +449,13 @@ internal sealed class QuestController
|
|||||||
StepProgress StepProgress)
|
StepProgress StepProgress)
|
||||||
{
|
{
|
||||||
public QuestProgress(Quest quest, byte sequence, int step)
|
public QuestProgress(Quest quest, byte sequence, int step)
|
||||||
: this(quest, sequence, step, new StepProgress())
|
: this(quest, sequence, step, new StepProgress(DateTime.Now))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO is this still required?
|
// TODO is this still required?
|
||||||
public sealed record StepProgress(
|
public sealed record StepProgress(
|
||||||
|
DateTime StartedAt,
|
||||||
int DialogueChoicesSelected = 0);
|
int DialogueChoicesSelected = 0);
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ internal sealed class QuestRegistry
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
quest.Name = questData.Name.ToString();
|
quest.Name = questData.Name.ToString();
|
||||||
|
quest.Level = questData.ClassJobLevel0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,13 @@ internal static class AethernetShortcut
|
|||||||
return ETaskResult.StillRunning;
|
return ETaskResult.StillRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aetheryteData.IsCityAetheryte(To))
|
if (aetheryteData.IsAirshipLanding(To))
|
||||||
|
{
|
||||||
|
if (aetheryteData.CalculateAirshipLandingDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
|
||||||
|
clientState.TerritoryType, To) > 5)
|
||||||
|
return ETaskResult.StillRunning;
|
||||||
|
}
|
||||||
|
else if (aetheryteData.IsCityAetheryte(To))
|
||||||
{
|
{
|
||||||
if (aetheryteData.CalculateDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
|
if (aetheryteData.CalculateDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
|
||||||
clientState.TerritoryType, To) > 11)
|
clientState.TerritoryType, To) > 11)
|
||||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
|
using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Questionable.Controller.Steps.BaseTasks;
|
using Questionable.Controller.Steps.BaseTasks;
|
||||||
using Questionable.Model;
|
using Questionable.Model;
|
||||||
@ -23,7 +24,7 @@ internal static class WaitAtEnd
|
|||||||
var task = serviceProvider.GetRequiredService<WaitForCompletionFlags>()
|
var task = serviceProvider.GetRequiredService<WaitForCompletionFlags>()
|
||||||
.With(quest, step);
|
.With(quest, step);
|
||||||
var delay = serviceProvider.GetRequiredService<WaitDelay>();
|
var delay = serviceProvider.GetRequiredService<WaitDelay>();
|
||||||
return [task, delay, new NextStep()];
|
return [task, delay, Next(quest, sequence, step)];
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (step.InteractionType)
|
switch (step.InteractionType)
|
||||||
@ -41,7 +42,7 @@ internal static class WaitAtEnd
|
|||||||
case EInteractionType.WalkTo:
|
case EInteractionType.WalkTo:
|
||||||
case EInteractionType.Jump:
|
case EInteractionType.Jump:
|
||||||
// no need to wait if we're just moving around
|
// no need to wait if we're just moving around
|
||||||
return [new NextStep()];
|
return [Next(quest, sequence, step)];
|
||||||
|
|
||||||
case EInteractionType.WaitForObjectAtPosition:
|
case EInteractionType.WaitForObjectAtPosition:
|
||||||
ArgumentNullException.ThrowIfNull(step.DataId);
|
ArgumentNullException.ThrowIfNull(step.DataId);
|
||||||
@ -52,7 +53,7 @@ internal static class WaitAtEnd
|
|||||||
serviceProvider.GetRequiredService<WaitObjectAtPosition>()
|
serviceProvider.GetRequiredService<WaitObjectAtPosition>()
|
||||||
.With(step.DataId.Value, step.Position.Value),
|
.With(step.DataId.Value, step.Position.Value),
|
||||||
serviceProvider.GetRequiredService<WaitDelay>(),
|
serviceProvider.GetRequiredService<WaitDelay>(),
|
||||||
new NextStep()
|
Next(quest, sequence, step)
|
||||||
];
|
];
|
||||||
|
|
||||||
case EInteractionType.Interact when step.TargetTerritoryId != null:
|
case EInteractionType.Interact when step.TargetTerritoryId != null:
|
||||||
@ -81,17 +82,40 @@ internal static class WaitAtEnd
|
|||||||
[
|
[
|
||||||
waitInteraction,
|
waitInteraction,
|
||||||
serviceProvider.GetRequiredService<WaitDelay>(),
|
serviceProvider.GetRequiredService<WaitDelay>(),
|
||||||
new NextStep()
|
Next(quest, sequence, step)
|
||||||
];
|
];
|
||||||
|
|
||||||
case EInteractionType.Interact:
|
case EInteractionType.Interact:
|
||||||
default:
|
default:
|
||||||
return [serviceProvider.GetRequiredService<WaitDelay>(), new NextStep()];
|
return [serviceProvider.GetRequiredService<WaitDelay>(), Next(quest, sequence, step)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
|
public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
|
||||||
=> throw new InvalidOperationException();
|
=> throw new InvalidOperationException();
|
||||||
|
|
||||||
|
public ITask Next(Quest quest, QuestSequence sequence, QuestStep step)
|
||||||
|
{
|
||||||
|
bool lastStep = step == sequence.Steps.LastOrDefault();
|
||||||
|
if (sequence.Sequence == 0 && lastStep)
|
||||||
|
{
|
||||||
|
return new WaitConditionTask(() =>
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var questManager = QuestManager.Instance();
|
||||||
|
return questManager != null && questManager->IsQuestAccepted(quest.QuestId);
|
||||||
|
}
|
||||||
|
}, "Wait(questAccepted)");
|
||||||
|
}
|
||||||
|
else if (sequence.Sequence == 255 && lastStep)
|
||||||
|
{
|
||||||
|
return new WaitConditionTask(() => QuestManager.IsQuestComplete(quest.QuestId),
|
||||||
|
"Wait(questComplete)");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return new NextStep();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class WaitDelay() : AbstractDelayedTask(TimeSpan.FromSeconds(1))
|
internal sealed class WaitDelay() : AbstractDelayedTask(TimeSpan.FromSeconds(1))
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Dalamud.Game.ClientState.Conditions;
|
using System;
|
||||||
|
using Dalamud.Game.ClientState.Conditions;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
@ -8,6 +9,7 @@ internal sealed class UnmountTask(ICondition condition, ILogger<UnmountTask> log
|
|||||||
: ITask
|
: ITask
|
||||||
{
|
{
|
||||||
private bool _unmountTriggered;
|
private bool _unmountTriggered;
|
||||||
|
private DateTime _unmountedAt = DateTime.MinValue;
|
||||||
|
|
||||||
public bool Start()
|
public bool Start()
|
||||||
{
|
{
|
||||||
@ -16,6 +18,8 @@ internal sealed class UnmountTask(ICondition condition, ILogger<UnmountTask> log
|
|||||||
|
|
||||||
logger.LogInformation("Step explicitly wants no mount, trying to unmount...");
|
logger.LogInformation("Step explicitly wants no mount, trying to unmount...");
|
||||||
_unmountTriggered = gameFunctions.Unmount();
|
_unmountTriggered = gameFunctions.Unmount();
|
||||||
|
if (_unmountTriggered)
|
||||||
|
_unmountedAt = DateTime.Now;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,9 +28,15 @@ internal sealed class UnmountTask(ICondition condition, ILogger<UnmountTask> log
|
|||||||
if (!_unmountTriggered)
|
if (!_unmountTriggered)
|
||||||
{
|
{
|
||||||
_unmountTriggered = gameFunctions.Unmount();
|
_unmountTriggered = gameFunctions.Unmount();
|
||||||
|
if (_unmountTriggered)
|
||||||
|
_unmountedAt = DateTime.Now;
|
||||||
|
|
||||||
return ETaskResult.StillRunning;
|
return ETaskResult.StillRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DateTime.Now < _unmountedAt.AddSeconds(1))
|
||||||
|
return ETaskResult.StillRunning;
|
||||||
|
|
||||||
return condition[ConditionFlag.Mounted]
|
return condition[ConditionFlag.Mounted]
|
||||||
? ETaskResult.StillRunning
|
? ETaskResult.StillRunning
|
||||||
: ETaskResult.TaskComplete;
|
: ETaskResult.TaskComplete;
|
||||||
|
@ -45,8 +45,38 @@ internal static class UseItem
|
|||||||
=> throw new InvalidOperationException();
|
=> throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal abstract class UseItemBase : ITask
|
||||||
|
{
|
||||||
|
private bool _usedItem;
|
||||||
|
private DateTime _continueAt;
|
||||||
|
|
||||||
internal sealed class UseOnGround(GameFunctions gameFunctions) : AbstractDelayedTask
|
protected abstract bool UseItem();
|
||||||
|
|
||||||
|
public bool Start()
|
||||||
|
{
|
||||||
|
_usedItem = UseItem();
|
||||||
|
_continueAt = DateTime.Now.AddSeconds(2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ETaskResult Update()
|
||||||
|
{
|
||||||
|
if (DateTime.Now > _continueAt)
|
||||||
|
return ETaskResult.StillRunning;
|
||||||
|
|
||||||
|
if (!_usedItem)
|
||||||
|
{
|
||||||
|
_usedItem = UseItem();
|
||||||
|
_continueAt = DateTime.Now.AddSeconds(2);
|
||||||
|
return ETaskResult.StillRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ETaskResult.TaskComplete;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal sealed class UseOnGround(GameFunctions gameFunctions) : UseItemBase
|
||||||
{
|
{
|
||||||
public uint DataId { get; set; }
|
public uint DataId { get; set; }
|
||||||
public uint ItemId { get; set; }
|
public uint ItemId { get; set; }
|
||||||
@ -58,16 +88,12 @@ internal static class UseItem
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool StartInternal()
|
protected override bool UseItem() => gameFunctions.UseItemOnGround(DataId, ItemId);
|
||||||
{
|
|
||||||
gameFunctions.UseItemOnGround(DataId, ItemId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() => $"UseItem({ItemId} on ground at {DataId})";
|
public override string ToString() => $"UseItem({ItemId} on ground at {DataId})";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class UseOnObject(GameFunctions gameFunctions) : AbstractDelayedTask
|
internal sealed class UseOnObject(GameFunctions gameFunctions) : UseItemBase
|
||||||
{
|
{
|
||||||
public uint DataId { get; set; }
|
public uint DataId { get; set; }
|
||||||
public uint ItemId { get; set; }
|
public uint ItemId { get; set; }
|
||||||
@ -79,16 +105,12 @@ internal static class UseItem
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool StartInternal()
|
protected override bool UseItem() => gameFunctions.UseItem(DataId, ItemId);
|
||||||
{
|
|
||||||
gameFunctions.UseItem(DataId, ItemId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() => $"UseItem({ItemId} on {DataId})";
|
public override string ToString() => $"UseItem({ItemId} on {DataId})";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class Use(GameFunctions gameFunctions) : AbstractDelayedTask
|
internal sealed class Use(GameFunctions gameFunctions) : UseItemBase
|
||||||
{
|
{
|
||||||
public uint ItemId { get; set; }
|
public uint ItemId { get; set; }
|
||||||
|
|
||||||
@ -98,11 +120,7 @@ internal static class UseItem
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool StartInternal()
|
protected override bool UseItem() => gameFunctions.UseItem(ItemId);
|
||||||
{
|
|
||||||
gameFunctions.UseItem(ItemId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() => $"UseItem({ItemId})";
|
public override string ToString() => $"UseItem({ItemId})";
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,12 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
private readonly NavigationShortcutController _navigationShortcutController;
|
private readonly NavigationShortcutController _navigationShortcutController;
|
||||||
private readonly WindowSystem _windowSystem;
|
private readonly WindowSystem _windowSystem;
|
||||||
private readonly DebugWindow _debugWindow;
|
private readonly DebugWindow _debugWindow;
|
||||||
|
private readonly ConfigWindow _configWindow;
|
||||||
|
|
||||||
public DalamudInitializer(DalamudPluginInterface pluginInterface, IFramework framework,
|
public DalamudInitializer(DalamudPluginInterface pluginInterface, IFramework framework,
|
||||||
ICommandManager commandManager, QuestController questController, MovementController movementController,
|
ICommandManager commandManager, QuestController questController, MovementController movementController,
|
||||||
GameUiController gameUiController, NavigationShortcutController navigationShortcutController, WindowSystem windowSystem, DebugWindow debugWindow)
|
GameUiController gameUiController, NavigationShortcutController navigationShortcutController,
|
||||||
|
WindowSystem windowSystem, DebugWindow debugWindow, ConfigWindow configWindow)
|
||||||
{
|
{
|
||||||
_pluginInterface = pluginInterface;
|
_pluginInterface = pluginInterface;
|
||||||
_framework = framework;
|
_framework = framework;
|
||||||
@ -31,9 +33,14 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
_navigationShortcutController = navigationShortcutController;
|
_navigationShortcutController = navigationShortcutController;
|
||||||
_windowSystem = windowSystem;
|
_windowSystem = windowSystem;
|
||||||
_debugWindow = debugWindow;
|
_debugWindow = debugWindow;
|
||||||
|
_configWindow = configWindow;
|
||||||
|
|
||||||
|
_windowSystem.AddWindow(debugWindow);
|
||||||
|
_windowSystem.AddWindow(configWindow);
|
||||||
|
|
||||||
_pluginInterface.UiBuilder.Draw += _windowSystem.Draw;
|
_pluginInterface.UiBuilder.Draw += _windowSystem.Draw;
|
||||||
_pluginInterface.UiBuilder.OpenMainUi += _debugWindow.Toggle;
|
_pluginInterface.UiBuilder.OpenMainUi += _debugWindow.Toggle;
|
||||||
|
_pluginInterface.UiBuilder.OpenConfigUi += _configWindow.Toggle;
|
||||||
_framework.Update += FrameworkUpdate;
|
_framework.Update += FrameworkUpdate;
|
||||||
_commandManager.AddHandler("/qst", new CommandInfo(ProcessCommand)
|
_commandManager.AddHandler("/qst", new CommandInfo(ProcessCommand)
|
||||||
{
|
{
|
||||||
@ -60,6 +67,9 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
|
|
||||||
private void ProcessCommand(string command, string arguments)
|
private void ProcessCommand(string command, string arguments)
|
||||||
{
|
{
|
||||||
|
if (arguments is "c" or "config")
|
||||||
|
_configWindow.Toggle();
|
||||||
|
else
|
||||||
_debugWindow.Toggle();
|
_debugWindow.Toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,5 +79,7 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
_framework.Update -= FrameworkUpdate;
|
_framework.Update -= FrameworkUpdate;
|
||||||
_pluginInterface.UiBuilder.OpenMainUi -= _debugWindow.Toggle;
|
_pluginInterface.UiBuilder.OpenMainUi -= _debugWindow.Toggle;
|
||||||
_pluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
|
_pluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
|
||||||
|
|
||||||
|
_windowSystem.RemoveAllWindows();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,6 +217,18 @@ internal sealed class AetheryteData
|
|||||||
}
|
}
|
||||||
.AsReadOnly();
|
.AsReadOnly();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Airship landings are special as they're one-way only (except for Radz-at-Han, which is a normal aetheryte).
|
||||||
|
/// </summary>
|
||||||
|
public ReadOnlyDictionary<EAetheryteLocation, Vector3> AirshipLandingLocations { get; } =
|
||||||
|
new Dictionary<EAetheryteLocation, Vector3>
|
||||||
|
{
|
||||||
|
{ EAetheryteLocation.LimsaAirship, new(-19.44352f, 91.99999f, -9.892939f) },
|
||||||
|
{ EAetheryteLocation.GridaniaAirship, new(24.86354f, -19.000002f, 96f) },
|
||||||
|
{ EAetheryteLocation.UldahAirship, new(-16.954851f, 82.999985f, -9.421141f) },
|
||||||
|
{ EAetheryteLocation.KuganeAirship, new(-55.72525f, 79.10602f, 46.23109f) },
|
||||||
|
}.AsReadOnly();
|
||||||
|
|
||||||
public ReadOnlyDictionary<EAetheryteLocation, string> AethernetNames { get; }
|
public ReadOnlyDictionary<EAetheryteLocation, string> AethernetNames { get; }
|
||||||
public ReadOnlyDictionary<EAetheryteLocation, ushort> TerritoryIds { get; }
|
public ReadOnlyDictionary<EAetheryteLocation, ushort> TerritoryIds { get; }
|
||||||
public IReadOnlyList<ushort> TownTerritoryIds { get; set; }
|
public IReadOnlyList<ushort> TownTerritoryIds { get; set; }
|
||||||
@ -232,9 +244,22 @@ internal sealed class AetheryteData
|
|||||||
return (fromPosition - toPosition).Length();
|
return (fromPosition - toPosition).Length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float CalculateAirshipLandingDistance(Vector3 fromPosition, ushort fromTerritoryType, EAetheryteLocation to)
|
||||||
|
{
|
||||||
|
if (!TerritoryIds.TryGetValue(to, out ushort toTerritoryType) || fromTerritoryType != toTerritoryType)
|
||||||
|
return float.MaxValue;
|
||||||
|
|
||||||
|
if (!AirshipLandingLocations.TryGetValue(to, out Vector3 toPosition))
|
||||||
|
return float.MaxValue;
|
||||||
|
|
||||||
|
return (fromPosition - toPosition).Length();
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsCityAetheryte(EAetheryteLocation aetheryte)
|
public bool IsCityAetheryte(EAetheryteLocation aetheryte)
|
||||||
{
|
{
|
||||||
var territoryId = TerritoryIds[aetheryte];
|
var territoryId = TerritoryIds[aetheryte];
|
||||||
return TownTerritoryIds.Contains(territoryId);
|
return TownTerritoryIds.Contains(territoryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsAirshipLanding(EAetheryteLocation aetheryte) => AirshipLandingLocations.ContainsKey(aetheryte);
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,17 @@ using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
|||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using LLib.GameUI;
|
using LLib.GameUI;
|
||||||
using Lumina.Excel.CustomSheets;
|
using Lumina.Excel.CustomSheets;
|
||||||
using Lumina.Excel.GeneratedSheets;
|
using Lumina.Excel.GeneratedSheets2;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Questionable.Controller;
|
using Questionable.Controller;
|
||||||
using Questionable.Model.V1;
|
using Questionable.Model.V1;
|
||||||
using BattleChara = FFXIVClientStructs.FFXIV.Client.Game.Character.BattleChara;
|
using BattleChara = FFXIVClientStructs.FFXIV.Client.Game.Character.BattleChara;
|
||||||
|
using ContentFinderCondition = Lumina.Excel.GeneratedSheets.ContentFinderCondition;
|
||||||
|
using ContentTalk = Lumina.Excel.GeneratedSheets.ContentTalk;
|
||||||
|
using Emote = Lumina.Excel.GeneratedSheets.Emote;
|
||||||
using GameObject = Dalamud.Game.ClientState.Objects.Types.GameObject;
|
using GameObject = Dalamud.Game.ClientState.Objects.Types.GameObject;
|
||||||
using Quest = Questionable.Model.Quest;
|
using Quest = Questionable.Model.Quest;
|
||||||
|
using TerritoryType = Lumina.Excel.GeneratedSheets.TerritoryType;
|
||||||
|
|
||||||
namespace Questionable;
|
namespace Questionable;
|
||||||
|
|
||||||
@ -56,11 +60,12 @@ internal sealed unsafe class GameFunctions
|
|||||||
private readonly IClientState _clientState;
|
private readonly IClientState _clientState;
|
||||||
private readonly QuestRegistry _questRegistry;
|
private readonly QuestRegistry _questRegistry;
|
||||||
private readonly IGameGui _gameGui;
|
private readonly IGameGui _gameGui;
|
||||||
|
private readonly Configuration _configuration;
|
||||||
private readonly ILogger<GameFunctions> _logger;
|
private readonly ILogger<GameFunctions> _logger;
|
||||||
|
|
||||||
public GameFunctions(IDataManager dataManager, IObjectTable objectTable, ISigScanner sigScanner,
|
public GameFunctions(IDataManager dataManager, IObjectTable objectTable, ISigScanner sigScanner,
|
||||||
ITargetManager targetManager, ICondition condition, IClientState clientState, QuestRegistry questRegistry,
|
ITargetManager targetManager, ICondition condition, IClientState clientState, QuestRegistry questRegistry,
|
||||||
IGameGui gameGui, ILogger<GameFunctions> logger)
|
IGameGui gameGui, Configuration configuration, ILogger<GameFunctions> logger)
|
||||||
{
|
{
|
||||||
_dataManager = dataManager;
|
_dataManager = dataManager;
|
||||||
_objectTable = objectTable;
|
_objectTable = objectTable;
|
||||||
@ -69,6 +74,7 @@ internal sealed unsafe class GameFunctions
|
|||||||
_clientState = clientState;
|
_clientState = clientState;
|
||||||
_questRegistry = questRegistry;
|
_questRegistry = questRegistry;
|
||||||
_gameGui = gameGui;
|
_gameGui = gameGui;
|
||||||
|
_configuration = configuration;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_processChatBox =
|
_processChatBox =
|
||||||
Marshal.GetDelegateForFunctionPointer<ProcessChatBoxDelegate>(sigScanner.ScanText(Signatures.SendChat));
|
Marshal.GetDelegateForFunctionPointer<ProcessChatBoxDelegate>(sigScanner.ScanText(Signatures.SendChat));
|
||||||
@ -364,29 +370,33 @@ internal sealed unsafe class GameFunctions
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UseItem(uint itemId)
|
public bool UseItem(uint itemId)
|
||||||
{
|
{
|
||||||
AgentInventoryContext.Instance()->UseItem(itemId);
|
return AgentInventoryContext.Instance()->UseItem(itemId) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UseItem(uint dataId, uint itemId)
|
public bool UseItem(uint dataId, uint itemId)
|
||||||
{
|
{
|
||||||
GameObject? gameObject = FindObjectByDataId(dataId);
|
GameObject? gameObject = FindObjectByDataId(dataId);
|
||||||
if (gameObject != null)
|
if (gameObject != null)
|
||||||
{
|
{
|
||||||
_targetManager.Target = gameObject;
|
_targetManager.Target = gameObject;
|
||||||
AgentInventoryContext.Instance()->UseItem(itemId);
|
return AgentInventoryContext.Instance()->UseItem(itemId) == 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UseItemOnGround(uint dataId, uint itemId)
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UseItemOnGround(uint dataId, uint itemId)
|
||||||
{
|
{
|
||||||
GameObject? gameObject = FindObjectByDataId(dataId);
|
GameObject? gameObject = FindObjectByDataId(dataId);
|
||||||
if (gameObject != null)
|
if (gameObject != null)
|
||||||
{
|
{
|
||||||
var position = (FFXIVClientStructs.FFXIV.Common.Math.Vector3)gameObject.Position;
|
var position = (FFXIVClientStructs.FFXIV.Common.Math.Vector3)gameObject.Position;
|
||||||
ActionManager.Instance()->UseActionLocation(ActionType.KeyItem, itemId, location: &position);
|
return ActionManager.Instance()->UseActionLocation(ActionType.KeyItem, itemId, location: &position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UseEmote(uint dataId, EEmote emote)
|
public void UseEmote(uint dataId, EEmote emote)
|
||||||
@ -410,8 +420,11 @@ internal sealed unsafe class GameFunctions
|
|||||||
return gameObject != null && (gameObject.Position - position).Length() < 0.05f;
|
return gameObject != null && (gameObject.Position - position).Length() < 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasStatusPreventingSprintOrMount()
|
public bool HasStatusPreventingSprintOrMount(bool skipConfigCheck = false)
|
||||||
{
|
{
|
||||||
|
if (!skipConfigCheck && _configuration.Advanced.NeverFly)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (_condition[ConditionFlag.Swimming] && !IsFlyingUnlockedInCurrentZone())
|
if (_condition[ConditionFlag.Swimming] && !IsFlyingUnlockedInCurrentZone())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -437,13 +450,14 @@ internal sealed unsafe class GameFunctions
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
var playerState = PlayerState.Instance();
|
var playerState = PlayerState.Instance();
|
||||||
if (playerState != null && playerState->IsMountUnlocked(71))
|
if (playerState != null && _configuration.General.MountId != 0 &&
|
||||||
|
playerState->IsMountUnlocked(_configuration.General.MountId))
|
||||||
{
|
{
|
||||||
if (ActionManager.Instance()->GetActionStatus(ActionType.Mount, 71) == 0)
|
if (ActionManager.Instance()->GetActionStatus(ActionType.Mount, _configuration.General.MountId) == 0)
|
||||||
{
|
{
|
||||||
if (ActionManager.Instance()->UseAction(ActionType.Mount, 71))
|
if (ActionManager.Instance()->UseAction(ActionType.Mount, _configuration.General.MountId))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Using SDS Fenrir as mount");
|
_logger.LogInformation("Using preferred mount");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,11 +540,21 @@ internal sealed unsafe class GameFunctions
|
|||||||
return excelSheet.FirstOrDefault(x => x.Key == key)?.Value?.ToDalamudString().ToString();
|
return excelSheet.FirstOrDefault(x => x.Key == key)?.Value?.ToDalamudString().ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? GetContentTalk(uint rowId)
|
public string? GetDialogueTextByRowId(string? excelSheet, uint rowId)
|
||||||
|
{
|
||||||
|
if (excelSheet == "GimmickYesNo")
|
||||||
|
{
|
||||||
|
var questRow = _dataManager.GetExcelSheet<GimmickYesNo>()!.GetRow(rowId);
|
||||||
|
return questRow?.Unknown0?.ToString();
|
||||||
|
}
|
||||||
|
else if (excelSheet is "ContentTalk" or null)
|
||||||
{
|
{
|
||||||
var questRow = _dataManager.GetExcelSheet<ContentTalk>()!.GetRow(rowId);
|
var questRow = _dataManager.GetExcelSheet<ContentTalk>()!.GetRow(rowId);
|
||||||
return questRow?.Text?.ToString();
|
return questRow?.Text?.ToString();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(excelSheet), $"Unsupported excel sheet {excelSheet}");
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsOccupied()
|
public bool IsOccupied()
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@ internal sealed class Quest
|
|||||||
{
|
{
|
||||||
public required ushort QuestId { get; init; }
|
public required ushort QuestId { get; init; }
|
||||||
public required string Name { get; set; }
|
public required string Name { get; set; }
|
||||||
|
public ushort Level { get; set; }
|
||||||
public required QuestData Data { get; init; }
|
public required QuestData Data { get; init; }
|
||||||
|
|
||||||
public QuestSequence? FindSequence(byte currentSequence)
|
public QuestSequence? FindSequence(byte currentSequence)
|
||||||
|
@ -8,7 +8,5 @@ internal sealed class DialogueChoiceTypeConverter() : EnumConverter<EDialogChoic
|
|||||||
{
|
{
|
||||||
{ EDialogChoiceType.YesNo, "YesNo" },
|
{ EDialogChoiceType.YesNo, "YesNo" },
|
||||||
{ EDialogChoiceType.List, "List" },
|
{ EDialogChoiceType.List, "List" },
|
||||||
{ EDialogChoiceType.ContentTalkYesNo, "ContentTalkYesNo" },
|
|
||||||
{ EDialogChoiceType.ContentTalkList, "ContentTalkList" },
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
30
Questionable/Model/V1/Converter/ExcelRefConverter.cs
Normal file
30
Questionable/Model/V1/Converter/ExcelRefConverter.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Questionable.Model.V1.Converter;
|
||||||
|
|
||||||
|
internal sealed class ExcelRefConverter : JsonConverter<ExcelRef>
|
||||||
|
{
|
||||||
|
public override ExcelRef? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.String)
|
||||||
|
return new ExcelRef(reader.GetString()!);
|
||||||
|
else if (reader.TokenType == JsonTokenType.Number)
|
||||||
|
return new ExcelRef(reader.GetUInt32());
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, ExcelRef? value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
writer.WriteNullValue();
|
||||||
|
else if (value.Type == ExcelRef.EType.Key)
|
||||||
|
writer.WriteStringValue(value.AsKey());
|
||||||
|
else if (value.Type == ExcelRef.EType.RowId)
|
||||||
|
writer.WriteNumberValue(value.AsRowId());
|
||||||
|
else
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,17 @@ internal sealed class DialogueChoice
|
|||||||
[JsonConverter(typeof(DialogueChoiceTypeConverter))]
|
[JsonConverter(typeof(DialogueChoiceTypeConverter))]
|
||||||
public EDialogChoiceType Type { get; set; }
|
public EDialogChoiceType Type { get; set; }
|
||||||
public string? ExcelSheet { get; set; }
|
public string? ExcelSheet { get; set; }
|
||||||
public string? Prompt { get; set; }
|
|
||||||
|
[JsonConverter(typeof(ExcelRefConverter))]
|
||||||
|
public ExcelRef? Prompt { get; set; }
|
||||||
|
|
||||||
public bool Yes { get; set; } = true;
|
public bool Yes { get; set; } = true;
|
||||||
public string? Answer { get; set; }
|
|
||||||
|
[JsonConverter(typeof(ExcelRefConverter))]
|
||||||
|
public ExcelRef? Answer { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If set, only applies when focusing the given target id.
|
||||||
|
/// </summary>
|
||||||
|
public uint? DataId { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,4 @@ internal enum EDialogChoiceType
|
|||||||
None,
|
None,
|
||||||
YesNo,
|
YesNo,
|
||||||
List,
|
List,
|
||||||
ContentTalkYesNo,
|
|
||||||
ContentTalkList,
|
|
||||||
}
|
}
|
||||||
|
48
Questionable/Model/V1/ExcelRef.cs
Normal file
48
Questionable/Model/V1/ExcelRef.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Questionable.Model.V1;
|
||||||
|
|
||||||
|
public class ExcelRef
|
||||||
|
{
|
||||||
|
private readonly string? _stringValue;
|
||||||
|
private readonly uint? _rowIdValue;
|
||||||
|
|
||||||
|
public ExcelRef(string value)
|
||||||
|
{
|
||||||
|
_stringValue = value;
|
||||||
|
_rowIdValue = null;
|
||||||
|
Type = EType.Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExcelRef(uint value)
|
||||||
|
{
|
||||||
|
_stringValue = null;
|
||||||
|
_rowIdValue = value;
|
||||||
|
Type = EType.RowId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EType Type { get; }
|
||||||
|
|
||||||
|
public string AsKey()
|
||||||
|
{
|
||||||
|
if (Type != EType.Key)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
|
||||||
|
return _stringValue!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint AsRowId()
|
||||||
|
{
|
||||||
|
if (Type != EType.RowId)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
|
||||||
|
return _rowIdValue!.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum EType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Key,
|
||||||
|
RowId,
|
||||||
|
}
|
||||||
|
}
|
@ -106,6 +106,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
serviceCollection.AddSingleton<NavigationShortcutController>();
|
serviceCollection.AddSingleton<NavigationShortcutController>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<DebugWindow>();
|
serviceCollection.AddSingleton<DebugWindow>();
|
||||||
|
serviceCollection.AddSingleton<ConfigWindow>();
|
||||||
serviceCollection.AddSingleton<DalamudInitializer>();
|
serviceCollection.AddSingleton<DalamudInitializer>();
|
||||||
|
|
||||||
_serviceProvider = serviceCollection.BuildServiceProvider();
|
_serviceProvider = serviceCollection.BuildServiceProvider();
|
||||||
|
88
Questionable/Windows/ConfigWindow.cs
Normal file
88
Questionable/Windows/ConfigWindow.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using Dalamud.Interface.Colors;
|
||||||
|
using Dalamud.Plugin;
|
||||||
|
using Dalamud.Plugin.Services;
|
||||||
|
using ImGuiNET;
|
||||||
|
using LLib.ImGui;
|
||||||
|
using Lumina.Excel.GeneratedSheets;
|
||||||
|
|
||||||
|
namespace Questionable.Windows;
|
||||||
|
|
||||||
|
internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
|
||||||
|
{
|
||||||
|
private readonly DalamudPluginInterface _pluginInterface;
|
||||||
|
private readonly Configuration _configuration;
|
||||||
|
|
||||||
|
private readonly uint[] _mountIds;
|
||||||
|
private readonly string[] _mountNames;
|
||||||
|
|
||||||
|
[SuppressMessage("Performance", "CA1861", Justification = "One time initialization")]
|
||||||
|
public ConfigWindow(DalamudPluginInterface pluginInterface, Configuration configuration, IDataManager dataManager)
|
||||||
|
: base("Config - Questionable###QuestionableConfig", ImGuiWindowFlags.AlwaysAutoResize)
|
||||||
|
{
|
||||||
|
_pluginInterface = pluginInterface;
|
||||||
|
_configuration = configuration;
|
||||||
|
|
||||||
|
var mounts = dataManager.GetExcelSheet<Mount>()!
|
||||||
|
.Where(x => x is { RowId: > 0, Icon: > 0 })
|
||||||
|
.Select(x => (MountId: x.RowId, Name: x.Singular.ToString()))
|
||||||
|
.Where(x => !string.IsNullOrEmpty(x.Name))
|
||||||
|
.OrderBy(x => x.Name)
|
||||||
|
.ToList();
|
||||||
|
_mountIds = new uint[] { 0 }.Concat(mounts.Select(x => x.MountId)).ToArray();
|
||||||
|
_mountNames = new[] { "Mount Roulette" }.Concat(mounts.Select(x => x.Name)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public WindowConfig WindowConfig => _configuration.ConfigWindowConfig;
|
||||||
|
|
||||||
|
public override void Draw()
|
||||||
|
{
|
||||||
|
if (ImGui.BeginTabBar("QuestionableConfigTabs"))
|
||||||
|
{
|
||||||
|
if (ImGui.BeginTabItem("General"))
|
||||||
|
{
|
||||||
|
int selectedMount = Array.FindIndex(_mountIds, x => x == _configuration.General.MountId);
|
||||||
|
if (selectedMount == -1)
|
||||||
|
{
|
||||||
|
selectedMount = 0;
|
||||||
|
_configuration.General.MountId = _mountIds[selectedMount];
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.Combo("Preferred Mount", ref selectedMount, _mountNames, _mountNames.Length))
|
||||||
|
{
|
||||||
|
_configuration.General.MountId = _mountIds[selectedMount];
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.BeginTabItem("Advanced"))
|
||||||
|
{
|
||||||
|
ImGui.TextColored(ImGuiColors.DalamudRed,
|
||||||
|
"Enabling any option here may cause unexpected behavior. Use at your own risk.");
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
|
bool neverFly = _configuration.Advanced.NeverFly;
|
||||||
|
if (ImGui.Checkbox("Disable flying (even if unlocked for the zone)", ref neverFly))
|
||||||
|
{
|
||||||
|
_configuration.Advanced.NeverFly = neverFly;
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndTabBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Save() => _pluginInterface.SavePluginConfig(_configuration);
|
||||||
|
|
||||||
|
public void SaveWindowConfig() => Save();
|
||||||
|
}
|
@ -23,10 +23,9 @@ using Questionable.Model.V1;
|
|||||||
|
|
||||||
namespace Questionable.Windows;
|
namespace Questionable.Windows;
|
||||||
|
|
||||||
internal sealed class DebugWindow : LWindow, IPersistableWindowConfig, IDisposable
|
internal sealed class DebugWindow : LWindow, IPersistableWindowConfig
|
||||||
{
|
{
|
||||||
private readonly DalamudPluginInterface _pluginInterface;
|
private readonly DalamudPluginInterface _pluginInterface;
|
||||||
private readonly WindowSystem _windowSystem;
|
|
||||||
private readonly MovementController _movementController;
|
private readonly MovementController _movementController;
|
||||||
private readonly QuestController _questController;
|
private readonly QuestController _questController;
|
||||||
private readonly GameFunctions _gameFunctions;
|
private readonly GameFunctions _gameFunctions;
|
||||||
@ -37,14 +36,19 @@ internal sealed class DebugWindow : LWindow, IPersistableWindowConfig, IDisposab
|
|||||||
private readonly Configuration _configuration;
|
private readonly Configuration _configuration;
|
||||||
private readonly ILogger<DebugWindow> _logger;
|
private readonly ILogger<DebugWindow> _logger;
|
||||||
|
|
||||||
public DebugWindow(DalamudPluginInterface pluginInterface, WindowSystem windowSystem,
|
public DebugWindow(DalamudPluginInterface pluginInterface,
|
||||||
MovementController movementController, QuestController questController, GameFunctions gameFunctions,
|
MovementController movementController,
|
||||||
IClientState clientState, IFramework framework, ITargetManager targetManager, GameUiController gameUiController,
|
QuestController questController,
|
||||||
Configuration configuration, ILogger<DebugWindow> logger)
|
GameFunctions gameFunctions,
|
||||||
|
IClientState clientState,
|
||||||
|
IFramework framework,
|
||||||
|
ITargetManager targetManager,
|
||||||
|
GameUiController gameUiController,
|
||||||
|
Configuration configuration,
|
||||||
|
ILogger<DebugWindow> logger)
|
||||||
: base("Questionable", ImGuiWindowFlags.AlwaysAutoResize)
|
: base("Questionable", ImGuiWindowFlags.AlwaysAutoResize)
|
||||||
{
|
{
|
||||||
_pluginInterface = pluginInterface;
|
_pluginInterface = pluginInterface;
|
||||||
_windowSystem = windowSystem;
|
|
||||||
_movementController = movementController;
|
_movementController = movementController;
|
||||||
_questController = questController;
|
_questController = questController;
|
||||||
_gameFunctions = gameFunctions;
|
_gameFunctions = gameFunctions;
|
||||||
@ -61,8 +65,6 @@ internal sealed class DebugWindow : LWindow, IPersistableWindowConfig, IDisposab
|
|||||||
MinimumSize = new Vector2(200, 30),
|
MinimumSize = new Vector2(200, 30),
|
||||||
MaximumSize = default
|
MaximumSize = default
|
||||||
};
|
};
|
||||||
|
|
||||||
_windowSystem.AddWindow(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public WindowConfig WindowConfig => _configuration.DebugWindowConfig;
|
public WindowConfig WindowConfig => _configuration.DebugWindowConfig;
|
||||||
@ -127,6 +129,7 @@ internal sealed class DebugWindow : LWindow, IPersistableWindowConfig, IDisposab
|
|||||||
ImGui.Text(_questController.ToStatString());
|
ImGui.Text(_questController.ToStatString());
|
||||||
//ImGui.EndDisabled();
|
//ImGui.EndDisabled();
|
||||||
|
|
||||||
|
ImGui.BeginDisabled(_questController.IsRunning);
|
||||||
if (ImGuiComponents.IconButton(FontAwesomeIcon.Play))
|
if (ImGuiComponents.IconButton(FontAwesomeIcon.Play))
|
||||||
{
|
{
|
||||||
_questController.ExecuteNextStep(true);
|
_questController.ExecuteNextStep(true);
|
||||||
@ -139,6 +142,7 @@ internal sealed class DebugWindow : LWindow, IPersistableWindowConfig, IDisposab
|
|||||||
_questController.ExecuteNextStep(false);
|
_questController.ExecuteNextStep(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui.EndDisabled();
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
if (ImGuiComponents.IconButton(FontAwesomeIcon.Stop))
|
if (ImGuiComponents.IconButton(FontAwesomeIcon.Stop))
|
||||||
@ -151,7 +155,8 @@ internal sealed class DebugWindow : LWindow, IPersistableWindowConfig, IDisposab
|
|||||||
.FindSequence(currentQuest.Sequence)
|
.FindSequence(currentQuest.Sequence)
|
||||||
?.FindStep(currentQuest.Step);
|
?.FindStep(currentQuest.Step);
|
||||||
bool colored = currentStep != null && currentStep.InteractionType == EInteractionType.Instruction
|
bool colored = currentStep != null && currentStep.InteractionType == EInteractionType.Instruction
|
||||||
&& _questController.HasCurrentTaskMatching<WaitAtEnd.WaitNextStepOrSequence>();
|
&& _questController
|
||||||
|
.HasCurrentTaskMatching<WaitAtEnd.WaitNextStepOrSequence>();
|
||||||
|
|
||||||
if (colored)
|
if (colored)
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen);
|
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen);
|
||||||
@ -161,8 +166,16 @@ internal sealed class DebugWindow : LWindow, IPersistableWindowConfig, IDisposab
|
|||||||
_questController.Stop("Manual");
|
_questController.Stop("Manual");
|
||||||
_questController.IncreaseStepCount();
|
_questController.IncreaseStepCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colored)
|
if (colored)
|
||||||
ImGui.PopStyleColor();
|
ImGui.PopStyleColor();
|
||||||
|
|
||||||
|
bool autoAcceptNextQuest = _configuration.General.AutoAcceptNextQuest;
|
||||||
|
if (ImGui.Checkbox("Automatically accept next quest", ref autoAcceptNextQuest))
|
||||||
|
{
|
||||||
|
_configuration.General.AutoAcceptNextQuest = autoAcceptNextQuest;
|
||||||
|
_pluginInterface.SavePluginConfig(_configuration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ImGui.Text("No active quest");
|
ImGui.Text("No active quest");
|
||||||
@ -261,7 +274,8 @@ internal sealed class DebugWindow : LWindow, IPersistableWindowConfig, IDisposab
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ImGui.Button($"Copy"))
|
ImGui.Button($"Copy");
|
||||||
|
if (ImGui.IsItemClicked(ImGuiMouseButton.Left))
|
||||||
{
|
{
|
||||||
ImGui.SetClipboardText($$"""
|
ImGui.SetClipboardText($$"""
|
||||||
"Position": {
|
"Position": {
|
||||||
@ -273,6 +287,12 @@ internal sealed class DebugWindow : LWindow, IPersistableWindowConfig, IDisposab
|
|||||||
"InteractionType": ""
|
"InteractionType": ""
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
else if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||||
|
{
|
||||||
|
Vector3 position = _clientState.LocalPlayer!.Position;
|
||||||
|
ImGui.SetClipboardText(string.Create(CultureInfo.InvariantCulture,
|
||||||
|
$"new({position.X}f, {position.Y}f, {position.Z}f)"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,9 +337,4 @@ internal sealed class DebugWindow : LWindow, IPersistableWindowConfig, IDisposab
|
|||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_windowSystem.RemoveWindow(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user