forked from liza/Questionable
Handle configured dialogue prompts; hide UI in blacklisted territories; path updates
Automatically handles: - SelectString - CutSceneSelectString - SelectYesno - Credit - Closing Unending Codex during 'Newfound Adventure'
This commit is contained in:
parent
51e5faae69
commit
a45cfda2e6
@ -44,6 +44,14 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 957,
|
"TerritoryId": 957,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
128
|
||||||
|
],
|
||||||
"$": "QuestVariables after: 16 1 0 0 0 128"
|
"$": "QuestVariables after: 16 1 0 0 0 128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -53,12 +61,28 @@
|
|||||||
"Z": -159.90234
|
"Z": -159.90234
|
||||||
},
|
},
|
||||||
"TerritoryId": 957,
|
"TerritoryId": 957,
|
||||||
"InteractionType": "WalkTo"
|
"InteractionType": "WalkTo",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2011914,
|
"DataId": 2011914,
|
||||||
"TerritoryId": 957,
|
"TerritoryId": 957,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
],
|
||||||
"$": "QuestVariables after: 32 17 0 0 0 160"
|
"$": "QuestVariables after: 32 17 0 0 0 160"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -69,7 +93,15 @@
|
|||||||
"Z": -157.09167
|
"Z": -157.09167
|
||||||
},
|
},
|
||||||
"TerritoryId": 957,
|
"TerritoryId": 957,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
64
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -43,15 +43,21 @@
|
|||||||
"Z": 799.2217
|
"Z": 799.2217
|
||||||
},
|
},
|
||||||
"TerritoryId": 957,
|
"TerritoryId": 957,
|
||||||
"InteractionType": "CutsceneSelectString",
|
"InteractionType": "Interact",
|
||||||
"DialogueChoices": [
|
"DialogueChoices": [
|
||||||
{
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_AKTKMA114_04370_Q2_000_086",
|
||||||
"Answer": "TEXT_AKTKMA114_04370_A2_000_088"
|
"Answer": "TEXT_AKTKMA114_04370_A2_000_088"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_AKTKMA114_04370_Q3_000_096",
|
||||||
"Answer": "TEXT_AKTKMA114_04370_A3_000_098"
|
"Answer": "TEXT_AKTKMA114_04370_A3_000_098"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_AKTKMA114_04370_Q5_000_106",
|
||||||
"Answer": "TEXT_AKTKMA114_04370_A5_000_107"
|
"Answer": "TEXT_AKTKMA114_04370_A5_000_107"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -69,15 +75,21 @@
|
|||||||
"Z": 681.7273
|
"Z": 681.7273
|
||||||
},
|
},
|
||||||
"TerritoryId": 957,
|
"TerritoryId": 957,
|
||||||
"InteractionType": "CutsceneSelectString",
|
"InteractionType": "Interact",
|
||||||
"DialogueChoices": [
|
"DialogueChoices": [
|
||||||
{
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_AKTKMA114_04370_Q6_000_147",
|
||||||
"Answer": "TEXT_AKTKMA114_04370_A6_000_149"
|
"Answer": "TEXT_AKTKMA114_04370_A6_000_149"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_AKTKMA114_04370_Q7_000_157",
|
||||||
"Answer": "TEXT_AKTKMA114_04370_A7_000_158"
|
"Answer": "TEXT_AKTKMA114_04370_A7_000_158"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_AKTKMA114_04370_Q8_000_162",
|
||||||
"Answer": "TEXT_AKTKMA114_04370_A8_000_164"
|
"Answer": "TEXT_AKTKMA114_04370_A8_000_164"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -95,15 +107,21 @@
|
|||||||
"Z": 517.72327
|
"Z": 517.72327
|
||||||
},
|
},
|
||||||
"TerritoryId": 957,
|
"TerritoryId": 957,
|
||||||
"InteractionType": "CutsceneSelectString",
|
"InteractionType": "Interact",
|
||||||
"DialogueChoices": [
|
"DialogueChoices": [
|
||||||
{
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_AKTKMA114_04370_Q9_000_198",
|
||||||
"Answer": "TEXT_AKTKMA114_04370_A9_000_200"
|
"Answer": "TEXT_AKTKMA114_04370_A9_000_200"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_AKTKMA114_04370_Q10_000_207",
|
||||||
"Answer": "TEXT_AKTKMA114_04370_A10_000_209"
|
"Answer": "TEXT_AKTKMA114_04370_A10_000_209"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_AKTKMA114_04370_Q11_000_216",
|
||||||
"Answer": "TEXT_AKTKMA114_04370_A11_000_218"
|
"Answer": "TEXT_AKTKMA114_04370_A11_000_218"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://carvel.li/questionable/quest-1.0",
|
"$schema": "https://carvel.li/questionable/quest-1.0",
|
||||||
"Author": "liza",
|
"Author": "liza",
|
||||||
|
"TerritoryBlacklist": [
|
||||||
|
1097
|
||||||
|
],
|
||||||
"QuestSequence": [
|
"QuestSequence": [
|
||||||
{
|
{
|
||||||
"Sequence": 0,
|
"Sequence": 0,
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://carvel.li/questionable/quest-1.0",
|
"$schema": "https://carvel.li/questionable/quest-1.0",
|
||||||
"Author": "liza",
|
"Author": "liza",
|
||||||
|
"TerritoryBlacklist": [
|
||||||
|
1095
|
||||||
|
],
|
||||||
"QuestSequence": [
|
"QuestSequence": [
|
||||||
{
|
{
|
||||||
"Sequence": 0,
|
"Sequence": 0,
|
||||||
|
@ -82,7 +82,14 @@
|
|||||||
},
|
},
|
||||||
"StopDistance": 5,
|
"StopDistance": 5,
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_AKTKMK102_04736_Q2_000_094",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -135,7 +135,6 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 958,
|
"TerritoryId": 958,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"Comment": "TODO Check flags",
|
|
||||||
"CompletionQuestVariablesFlags": [
|
"CompletionQuestVariablesFlags": [
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@ -150,6 +149,18 @@
|
|||||||
{
|
{
|
||||||
"Sequence": 255,
|
"Sequence": 255,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": 534.8861,
|
||||||
|
"Y": -36.65,
|
||||||
|
"Z": -245.12135
|
||||||
|
},
|
||||||
|
"TerritoryId": 958,
|
||||||
|
"InteractionType": "WalkTo",
|
||||||
|
"SkipIf": [
|
||||||
|
"FlyingLocked"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1045430,
|
"DataId": 1045430,
|
||||||
"Position": {
|
"Position": {
|
||||||
|
@ -30,7 +30,8 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 958,
|
"TerritoryId": 958,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"Fly": true
|
"Fly": true,
|
||||||
|
"TargetTerritoryId": 1160
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -61,7 +62,6 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 1160,
|
"TerritoryId": 1160,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"Comment": "TODO Check Flags",
|
|
||||||
"CompletionQuestVariablesFlags": [
|
"CompletionQuestVariablesFlags": [
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
"Y": 10.8,
|
"Y": 10.8,
|
||||||
"Z": -231.61676
|
"Z": -231.61676
|
||||||
},
|
},
|
||||||
|
"StopDistance": 5,
|
||||||
"TerritoryId": 958,
|
"TerritoryId": 958,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact"
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,23 @@
|
|||||||
"TerritoryId": 959,
|
"TerritoryId": 959,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"AetheryteShortcut": "Mare Lamentorum - Bestways Burrow",
|
"AetheryteShortcut": "Mare Lamentorum - Bestways Burrow",
|
||||||
"SkipIf": ["FlyingUnlocked"],
|
"SkipIf": [
|
||||||
"Comment": "Check if the flying unlocked check is good enough"
|
"FlyingUnlocked"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": -19.779482,
|
||||||
|
"Y": -56.63768,
|
||||||
|
"Z": -464.9354
|
||||||
|
},
|
||||||
|
"StopDistance": 1,
|
||||||
|
"TerritoryId": 959,
|
||||||
|
"InteractionType": "WalkTo",
|
||||||
|
"SkipIf": [
|
||||||
|
"FlyingLocked"
|
||||||
|
],
|
||||||
|
"Fly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1039686,
|
"DataId": 1039686,
|
||||||
@ -91,7 +106,8 @@
|
|||||||
"Z": -620.3861
|
"Z": -620.3861
|
||||||
},
|
},
|
||||||
"TerritoryId": 959,
|
"TerritoryId": 959,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"Fly": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -156,8 +172,7 @@
|
|||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
32
|
32
|
||||||
],
|
]
|
||||||
"Comment": "TODO Check Flags"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1045473,
|
"DataId": 1045473,
|
||||||
@ -179,7 +194,8 @@
|
|||||||
16
|
16
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"Comment": "TODO Check Flags (32)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Sequence": 255,
|
"Sequence": 255,
|
||||||
|
@ -53,8 +53,7 @@
|
|||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
128
|
128
|
||||||
],
|
]
|
||||||
"Comment": "TODO Check Flags"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2013355,
|
"DataId": 2013355,
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://carvel.li/questionable/quest-1.0",
|
"$schema": "https://carvel.li/questionable/quest-1.0",
|
||||||
"Author": "liza",
|
"Author": "liza",
|
||||||
|
"TerritoryBlacklist": [
|
||||||
|
1140
|
||||||
|
],
|
||||||
"QuestSequence": [
|
"QuestSequence": [
|
||||||
{
|
{
|
||||||
"Sequence": 0,
|
"Sequence": 0,
|
||||||
|
@ -31,7 +31,23 @@
|
|||||||
"TerritoryId": 959,
|
"TerritoryId": 959,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"AetheryteShortcut": "Mare Lamentorum - Bestways Burrow",
|
"AetheryteShortcut": "Mare Lamentorum - Bestways Burrow",
|
||||||
"SkipIf": ["FlyingUnlocked"]
|
"SkipIf": [
|
||||||
|
"FlyingUnlocked"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": -19.779482,
|
||||||
|
"Y": -56.63768,
|
||||||
|
"Z": -464.9354
|
||||||
|
},
|
||||||
|
"StopDistance": 1,
|
||||||
|
"TerritoryId": 959,
|
||||||
|
"InteractionType": "WalkTo",
|
||||||
|
"SkipIf": [
|
||||||
|
"FlyingLocked"
|
||||||
|
],
|
||||||
|
"Fly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1045466,
|
"DataId": 1045466,
|
||||||
@ -62,6 +78,13 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Radz-at-Han] Aetheryte Plaza",
|
"[Radz-at-Han] Aetheryte Plaza",
|
||||||
"[Radz-at-Han] Meghaduta"
|
"[Radz-at-Han] Meghaduta"
|
||||||
|
],
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_AKTKMK109_04743_Q1_000_000",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
"Y": 55,
|
"Y": 55,
|
||||||
"Z": -68.61987
|
"Z": -68.61987
|
||||||
},
|
},
|
||||||
"StopDistance": 5,
|
"StopDistance": 7,
|
||||||
"TerritoryId": 963,
|
"TerritoryId": 963,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact"
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://carvel.li/questionable/quest-1.0",
|
"$schema": "https://carvel.li/questionable/quest-1.0",
|
||||||
"Author": "liza",
|
"Author": "liza",
|
||||||
|
"TerritoryBlacklist": [
|
||||||
|
1164,
|
||||||
|
1168
|
||||||
|
],
|
||||||
"QuestSequence": [
|
"QuestSequence": [
|
||||||
{
|
{
|
||||||
"Sequence": 0,
|
"Sequence": 0,
|
||||||
@ -39,7 +43,14 @@
|
|||||||
"Z": -440.63483
|
"Z": -440.63483
|
||||||
},
|
},
|
||||||
"TerritoryId": 1184,
|
"TerritoryId": 1184,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_AKTKML105_04748_SYSTEM_000_406",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"Y": 56.66061,
|
"Y": 56.66061,
|
||||||
"Z": 467.39905
|
"Z": 467.39905
|
||||||
},
|
},
|
||||||
|
"StopDistance": 15,
|
||||||
"TerritoryId": 1162,
|
"TerritoryId": 1162,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact"
|
||||||
}
|
}
|
||||||
@ -43,7 +44,8 @@
|
|||||||
"Z": -191.51605
|
"Z": -191.51605
|
||||||
},
|
},
|
||||||
"TerritoryId": 958,
|
"TerritoryId": 958,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"AetheryteShortcut": "Garlemald - Tertium"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -59,6 +61,7 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
|
"AetheryteShortcut": "Old Sharlayan",
|
||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Old Sharlayan] Aetheryte Plaza",
|
"[Old Sharlayan] Aetheryte Plaza",
|
||||||
"[Old Sharlayan] The Rostra"
|
"[Old Sharlayan] The Rostra"
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"Y": 41.530136,
|
"Y": 41.530136,
|
||||||
"Z": -165.27051
|
"Z": -165.27051
|
||||||
},
|
},
|
||||||
|
"StopDistance": 7,
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact"
|
||||||
}
|
}
|
||||||
@ -29,9 +30,17 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 819,
|
"TerritoryId": 819,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
|
"AetheryteShortcut": "Crystarium",
|
||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Crystarium] Aetheryte Plaza",
|
"[Crystarium] Aetheryte Plaza",
|
||||||
"[Crystarium] The Dossal Gate"
|
"[Crystarium] The Dossal Gate"
|
||||||
|
],
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_AKTKML107_04750_SYSTEM_000_101",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -51,6 +60,22 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Sequence": 3,
|
||||||
|
"Steps": [
|
||||||
|
{
|
||||||
|
"DataId": 1045684,
|
||||||
|
"Position": {
|
||||||
|
"X": -0.96136475,
|
||||||
|
"Y": 0,
|
||||||
|
"Z": -3.3417358
|
||||||
|
},
|
||||||
|
"StopDistance": 5,
|
||||||
|
"TerritoryId": 844,
|
||||||
|
"InteractionType": "Interact"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Sequence": 4,
|
"Sequence": 4,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
@ -63,6 +88,7 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 963,
|
"TerritoryId": 963,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
|
"AetheryteShortcut": "Radz-at-Han",
|
||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Radz-at-Han] Aetheryte Plaza",
|
"[Radz-at-Han] Aetheryte Plaza",
|
||||||
"[Radz-at-Han] Meghaduta"
|
"[Radz-at-Han] Meghaduta"
|
||||||
@ -89,17 +115,17 @@
|
|||||||
"Sequence": 255,
|
"Sequence": 255,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
{
|
{
|
||||||
"DataId": 196,
|
"DataId": 1039645,
|
||||||
"Position": {
|
"Position": {
|
||||||
"X": -42.61847,
|
"X": -338.33832,
|
||||||
"Y": -0.015319824,
|
"Y": 55,
|
||||||
"Z": -197.61963
|
"Z": -68.40625
|
||||||
},
|
},
|
||||||
"TerritoryId": 963,
|
"TerritoryId": 963,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Radz-at-Han] Mehryde's Meyhane",
|
"[Radz-at-Han] Mehryde's Meyhane",
|
||||||
"[Radz-at-Han] Aetheryte Plaza"
|
"[Radz-at-Han] Meghaduta"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -13,7 +13,14 @@
|
|||||||
"Z": -68.40625
|
"Z": -68.40625
|
||||||
},
|
},
|
||||||
"TerritoryId": 963,
|
"TerritoryId": 963,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_AKTKMM103_04753_Q1_000_000",
|
||||||
|
"Answer": "TEXT_AKTKMM103_04753_A1_000_001"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -27,8 +34,10 @@
|
|||||||
"Y": 4.357494,
|
"Y": 4.357494,
|
||||||
"Z": 0.7476196
|
"Z": 0.7476196
|
||||||
},
|
},
|
||||||
|
"StopDistance": 7,
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
|
"AetheryteShortcut": "Old Sharlayan",
|
||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Old Sharlayan] Aetheryte Plaza",
|
"[Old Sharlayan] Aetheryte Plaza",
|
||||||
"[Old Sharlayan] The Baldesion Annex"
|
"[Old Sharlayan] The Baldesion Annex"
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://carvel.li/questionable/quest-1.0",
|
"$schema": "https://carvel.li/questionable/quest-1.0",
|
||||||
"Author": "liza",
|
"Author": "liza",
|
||||||
|
"TerritoryBlacklist": [
|
||||||
|
1177
|
||||||
|
],
|
||||||
"QuestSequence": [
|
"QuestSequence": [
|
||||||
{
|
{
|
||||||
"Sequence": 0,
|
"Sequence": 0,
|
||||||
@ -62,6 +65,7 @@
|
|||||||
"Y": -14.169313,
|
"Y": -14.169313,
|
||||||
"Z": 105.30249
|
"Z": 105.30249
|
||||||
},
|
},
|
||||||
|
"StopDistance": 7,
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact"
|
||||||
}
|
}
|
||||||
@ -77,6 +81,7 @@
|
|||||||
"Y": -15.127002,
|
"Y": -15.127002,
|
||||||
"Z": 139.42163
|
"Z": 139.42163
|
||||||
},
|
},
|
||||||
|
"StopDistance": 5,
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact"
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"Y": -15.127001,
|
"Y": -15.127001,
|
||||||
"Z": 139.45215
|
"Z": 139.45215
|
||||||
},
|
},
|
||||||
|
"StopDistance": 5,
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact"
|
||||||
}
|
}
|
||||||
@ -32,6 +33,14 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Old Sharlayan] Scholar's Harbor",
|
"[Old Sharlayan] Scholar's Harbor",
|
||||||
"[Old Sharlayan] The Studium"
|
"[Old Sharlayan] The Studium"
|
||||||
|
],
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
16
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -42,7 +51,15 @@
|
|||||||
"Z": 103.28821
|
"Z": 103.28821
|
||||||
},
|
},
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2013417,
|
"DataId": 2013417,
|
||||||
@ -52,7 +69,15 @@
|
|||||||
"Z": 59.00659
|
"Z": 59.00659
|
||||||
},
|
},
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
64
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2013416,
|
"DataId": 2013416,
|
||||||
@ -62,7 +87,15 @@
|
|||||||
"Z": 20.523315
|
"Z": 20.523315
|
||||||
},
|
},
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
128
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -111,7 +144,14 @@
|
|||||||
"Z": 0.7476196
|
"Z": 0.7476196
|
||||||
},
|
},
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_AKTKMM103_04753_SYSTEM_000_302",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -151,6 +191,7 @@
|
|||||||
"Y": 4.357494,
|
"Y": 4.357494,
|
||||||
"Z": 0.7476196
|
"Z": 0.7476196
|
||||||
},
|
},
|
||||||
|
"StopDistance": 5,
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact"
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
"$schema": "https://carvel.li/questionable/quest-1.0",
|
"$schema": "https://carvel.li/questionable/quest-1.0",
|
||||||
"Author": "liza",
|
"Author": "liza",
|
||||||
"Comment": "TODO Missing Quest Start",
|
"Comment": "TODO Missing Quest Start",
|
||||||
|
"TerritoryBlacklist": [
|
||||||
|
838,
|
||||||
|
847
|
||||||
|
],
|
||||||
"QuestSequence": [
|
"QuestSequence": [
|
||||||
{
|
{
|
||||||
"Sequence": 7,
|
"Sequence": 7,
|
||||||
|
@ -13,7 +13,14 @@
|
|||||||
"Z": -9.10968
|
"Z": -9.10968
|
||||||
},
|
},
|
||||||
"TerritoryId": 351,
|
"TerritoryId": 351,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_LUCKMG101_03673_Q1_000_500",
|
||||||
|
"Answer": "TEXT_LUCKMG101_03673_A1_000_500"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -38,7 +45,8 @@
|
|||||||
"Z": -656.1909
|
"Z": -656.1909
|
||||||
},
|
},
|
||||||
"TerritoryId": 156,
|
"TerritoryId": 156,
|
||||||
"InteractionType": "WalkTo"
|
"InteractionType": "WalkTo",
|
||||||
|
"Mount": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1018433,
|
"DataId": 1018433,
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
"Y": -0.67464465,
|
"Y": -0.67464465,
|
||||||
"Z": 653.1527
|
"Z": 653.1527
|
||||||
},
|
},
|
||||||
|
"StopDistance": 0.5,
|
||||||
"TerritoryId": 813,
|
"TerritoryId": 813,
|
||||||
"InteractionType": "WalkTo",
|
"InteractionType": "WalkTo",
|
||||||
"AetheryteShortcut": "Lakeland - Fort Jobb",
|
"AetheryteShortcut": "Lakeland - Fort Jobb",
|
||||||
|
13
QuestPaths/TODO Quest YesNo.txt
Normal file
13
QuestPaths/TODO Quest YesNo.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Currying Flavor:
|
||||||
|
"DialogueChoices": [
|
||||||
|
{
|
||||||
|
"Type": "List",
|
||||||
|
"Prompt": "TEXT_AKTKMK101_04735_Q1_000_000",
|
||||||
|
"Answer": "TEXT_AKTKMK101_04735_A1_000_003"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Type": "YesNo",
|
||||||
|
"Prompt": "TEXT_AKTKMK101_04735_Q2_000_182",
|
||||||
|
"Yes": true
|
||||||
|
}
|
||||||
|
]
|
@ -100,7 +100,6 @@
|
|||||||
"Duty",
|
"Duty",
|
||||||
"SinglePlayerDuty",
|
"SinglePlayerDuty",
|
||||||
"Jump",
|
"Jump",
|
||||||
"CutsceneSelectString",
|
|
||||||
"ShouldBeAJump",
|
"ShouldBeAJump",
|
||||||
"Instruction"
|
"Instruction"
|
||||||
]
|
]
|
||||||
@ -648,7 +647,7 @@
|
|||||||
"if": {
|
"if": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"InteractionType": {
|
"InteractionType": {
|
||||||
"const": "CutsceneSelectString"
|
"const": "Interact"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -659,9 +658,55 @@
|
|||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"Type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"YesNo",
|
||||||
|
"List"
|
||||||
|
]
|
||||||
|
},
|
||||||
"ExcelSheet": {
|
"ExcelSheet": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"Prompt": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"Type",
|
||||||
|
"Prompt"
|
||||||
|
],
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"Type": {
|
||||||
|
"const": "YesNo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"Yes": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"Yes"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"Type": {
|
||||||
|
"const": "List"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
"Answer": {
|
"Answer": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@ -671,11 +716,11 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"DialogueChoices"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"if": {
|
"if": {
|
||||||
|
240
Questionable/Controller/GameUiController.cs
Normal file
240
Questionable/Controller/GameUiController.cs
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Dalamud.Game.Addon.Lifecycle;
|
||||||
|
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
||||||
|
using Dalamud.Plugin.Services;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
|
using LLib.GameUI;
|
||||||
|
using Lumina.Excel.GeneratedSheets;
|
||||||
|
using Questionable.Model.V1;
|
||||||
|
using Quest = Questionable.Model.Quest;
|
||||||
|
|
||||||
|
namespace Questionable.Controller;
|
||||||
|
|
||||||
|
internal sealed class GameUiController : IDisposable
|
||||||
|
{
|
||||||
|
private readonly IClientState _clientState;
|
||||||
|
private readonly IAddonLifecycle _addonLifecycle;
|
||||||
|
private readonly IDataManager _dataManager;
|
||||||
|
private readonly GameFunctions _gameFunctions;
|
||||||
|
private readonly QuestController _questController;
|
||||||
|
private readonly IPluginLog _pluginLog;
|
||||||
|
|
||||||
|
public GameUiController(IClientState clientState, IAddonLifecycle addonLifecycle, IDataManager dataManager,
|
||||||
|
GameFunctions gameFunctions, QuestController questController, IPluginLog pluginLog)
|
||||||
|
{
|
||||||
|
_clientState = clientState;
|
||||||
|
_addonLifecycle = addonLifecycle;
|
||||||
|
_dataManager = dataManager;
|
||||||
|
_gameFunctions = gameFunctions;
|
||||||
|
_questController = questController;
|
||||||
|
_pluginLog = pluginLog;
|
||||||
|
|
||||||
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup);
|
||||||
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "CutSceneSelectString", CutsceneSelectStringPostSetup);
|
||||||
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectYesno", SelectYesnoPostSetup);
|
||||||
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "Credit", CreditPostSetup);
|
||||||
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void SelectStringPostSetup(AddonEvent type, AddonArgs args)
|
||||||
|
{
|
||||||
|
AddonSelectString* addonSelectString = (AddonSelectString*)args.Addon;
|
||||||
|
string? actualPrompt = addonSelectString->AtkUnitBase.AtkValues[2].ReadAtkString();
|
||||||
|
if (actualPrompt == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var currentQuest = _questController.CurrentQuest;
|
||||||
|
if (currentQuest == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var quest = currentQuest.Quest;
|
||||||
|
var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
|
||||||
|
if (step == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var dialogueChoice in step.DialogueChoices)
|
||||||
|
{
|
||||||
|
if (dialogueChoice.Answer == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string? excelPrompt =
|
||||||
|
_gameFunctions.GetExcelString(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
|
||||||
|
string? excelAnswer =
|
||||||
|
_gameFunctions.GetExcelString(quest, dialogueChoice.ExcelSheet, dialogueChoice.Answer);
|
||||||
|
if (excelPrompt == null || actualPrompt != excelPrompt)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (ushort i = 7; i <= addonSelectString->AtkUnitBase.AtkValuesCount; ++i)
|
||||||
|
{
|
||||||
|
string? actualAnswer = addonSelectString->AtkUnitBase.AtkValues[i].ReadAtkString();
|
||||||
|
if (actualAnswer == null || actualAnswer != excelAnswer)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_questController.IncreaseDialogueChoicesSelected();
|
||||||
|
addonSelectString->AtkUnitBase.FireCallbackInt(i - 7);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void CutsceneSelectStringPostSetup(AddonEvent type, AddonArgs args)
|
||||||
|
{
|
||||||
|
AddonCutSceneSelectString* addonCutSceneSelectString = (AddonCutSceneSelectString*)args.Addon;
|
||||||
|
string? actualPrompt = addonCutSceneSelectString->AtkUnitBase.AtkValues[2].ReadAtkString();
|
||||||
|
if (actualPrompt == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var currentQuest = _questController.CurrentQuest;
|
||||||
|
if (currentQuest == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var quest = currentQuest.Quest;
|
||||||
|
var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
|
||||||
|
if (step == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (DialogueChoice dialogueChoice in step.DialogueChoices)
|
||||||
|
{
|
||||||
|
if (dialogueChoice.Answer == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string? excelPrompt =
|
||||||
|
_gameFunctions.GetExcelString(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
|
||||||
|
string? excelAnswer =
|
||||||
|
_gameFunctions.GetExcelString(quest, dialogueChoice.ExcelSheet, dialogueChoice.Answer);
|
||||||
|
if (excelPrompt == null || actualPrompt != excelPrompt)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int i = 5; i < addonCutSceneSelectString->AtkUnitBase.AtkValuesCount; ++i)
|
||||||
|
{
|
||||||
|
string? actualAnswer = addonCutSceneSelectString->AtkUnitBase.AtkValues[i].ReadAtkString();
|
||||||
|
if (actualAnswer == null || actualAnswer != excelAnswer)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_questController.IncreaseDialogueChoicesSelected();
|
||||||
|
addonCutSceneSelectString->AtkUnitBase.FireCallbackInt(i - 5);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void SelectYesnoPostSetup(AddonEvent type, AddonArgs args)
|
||||||
|
{
|
||||||
|
AddonSelectYesno* addonSelectYesno = (AddonSelectYesno*)args.Addon;
|
||||||
|
string? actualPrompt = addonSelectYesno->AtkUnitBase.AtkValues[0].ReadAtkString();
|
||||||
|
if (actualPrompt == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_pluginLog.Verbose($"Prompt: '{actualPrompt}'");
|
||||||
|
|
||||||
|
var currentQuest = _questController.CurrentQuest;
|
||||||
|
if (currentQuest == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var quest = currentQuest.Quest;
|
||||||
|
var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
|
||||||
|
if (step != null && HandleDefaultYesNo(addonSelectYesno, quest, step, actualPrompt))
|
||||||
|
return;
|
||||||
|
|
||||||
|
HandleTravelYesNo(addonSelectYesno, currentQuest, actualPrompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe bool HandleDefaultYesNo(AddonSelectYesno* addonSelectYesno, Quest quest, QuestStep step,
|
||||||
|
string actualPrompt)
|
||||||
|
{
|
||||||
|
_pluginLog.Verbose($"DefaultYesNo: Choice count: {step.DialogueChoices.Count}");
|
||||||
|
foreach (var dialogueChoice in step.DialogueChoices)
|
||||||
|
{
|
||||||
|
string? excelPrompt =
|
||||||
|
_gameFunctions.GetExcelString(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
|
||||||
|
if (excelPrompt == null || actualPrompt != excelPrompt)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
addonSelectYesno->AtkUnitBase.FireCallbackInt(dialogueChoice.Yes ? 0 : 1);
|
||||||
|
_questController.IncreaseDialogueChoicesSelected();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe bool HandleTravelYesNo(AddonSelectYesno* addonSelectYesno,
|
||||||
|
QuestController.QuestProgress currentQuest, string actualPrompt)
|
||||||
|
{
|
||||||
|
// this can be triggered either manually (in which case we should increase the step counter), or automatically
|
||||||
|
// (in which case it is ~1 frame later, and the step counter has already been increased)
|
||||||
|
var sequence = currentQuest.Quest.FindSequence(currentQuest.Sequence);
|
||||||
|
if (sequence == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool increaseStepCount = true;
|
||||||
|
QuestStep? step = sequence.FindStep(currentQuest.Step);
|
||||||
|
if (step != null)
|
||||||
|
_pluginLog.Verbose($"Current step: {step.TerritoryId}, {step.TargetTerritoryId}");
|
||||||
|
|
||||||
|
if (step == null || step.TargetTerritoryId == null || step.TerritoryId != _clientState.TerritoryType)
|
||||||
|
{
|
||||||
|
_pluginLog.Verbose("TravelYesNo: Checking previous step...");
|
||||||
|
step = sequence.FindStep(currentQuest.Step == 255 ? (sequence.Steps.Count - 1) : (currentQuest.Step - 1));
|
||||||
|
increaseStepCount = false;
|
||||||
|
|
||||||
|
if (step != null)
|
||||||
|
_pluginLog.Verbose($"Previous step: {step.TerritoryId}, {step.TargetTerritoryId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (step == null || step.TargetTerritoryId == null || step.TerritoryId != _clientState.TerritoryType)
|
||||||
|
{
|
||||||
|
_pluginLog.Verbose("TravelYesNo: Not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var warps = _dataManager.GetExcelSheet<Warp>()!
|
||||||
|
.Where(x => x.RowId > 0 && x.TerritoryType.Row == step.TargetTerritoryId)
|
||||||
|
.Where(x => x.ConfirmEvent.Row == 0); // unsure if this is needed
|
||||||
|
foreach (var entry in warps)
|
||||||
|
{
|
||||||
|
string? excelPrompt = entry.Question?.ToString();
|
||||||
|
if (excelPrompt == null || excelPrompt != actualPrompt)
|
||||||
|
{
|
||||||
|
_pluginLog.Information($"Ignoring prompt '{excelPrompt}'");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_pluginLog.Information($"Using warp {entry.RowId}, {excelPrompt}");
|
||||||
|
addonSelectYesno->AtkUnitBase.FireCallbackInt(0);
|
||||||
|
if (increaseStepCount)
|
||||||
|
_questController.IncreaseStepCount();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void CreditPostSetup(AddonEvent type, AddonArgs args)
|
||||||
|
{
|
||||||
|
_pluginLog.Information("Closing Credits sequence");
|
||||||
|
AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
|
||||||
|
addon->FireCallbackInt(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void UnendingCodexPostSetup(AddonEvent type, AddonArgs args)
|
||||||
|
{
|
||||||
|
if (_questController.CurrentQuest?.Quest.QuestId == 4526)
|
||||||
|
{
|
||||||
|
_pluginLog.Information("Closing Unending Codex");
|
||||||
|
AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
|
||||||
|
addon->FireCallbackInt(-2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup);
|
||||||
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "Credit", CreditPostSetup);
|
||||||
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "SelectYesno", SelectYesnoPostSetup);
|
||||||
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "CutSceneSelectString", CutsceneSelectStringPostSetup);
|
||||||
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup);
|
||||||
|
}
|
||||||
|
}
|
@ -10,14 +10,11 @@ using Dalamud.Plugin;
|
|||||||
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.UI;
|
|
||||||
using LLib.GameUI;
|
|
||||||
using Questionable.Data;
|
using Questionable.Data;
|
||||||
using Questionable.External;
|
using Questionable.External;
|
||||||
using Questionable.Model;
|
using Questionable.Model;
|
||||||
using Questionable.Model.V1;
|
using Questionable.Model.V1;
|
||||||
using Questionable.Model.V1.Converter;
|
using Questionable.Model.V1.Converter;
|
||||||
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
|
|
||||||
|
|
||||||
namespace Questionable.Controller;
|
namespace Questionable.Controller;
|
||||||
|
|
||||||
@ -272,6 +269,27 @@ internal sealed class QuestController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void IncreaseDialogueChoicesSelected()
|
||||||
|
{
|
||||||
|
(QuestSequence? seq, QuestStep? step) = GetNextStep();
|
||||||
|
if (CurrentQuest == null || seq == null || step == null)
|
||||||
|
{
|
||||||
|
_pluginLog.Warning("Unable to retrieve next quest step, not increasing dialogue choice count");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentQuest = CurrentQuest with
|
||||||
|
{
|
||||||
|
StepProgress = CurrentQuest.StepProgress with
|
||||||
|
{
|
||||||
|
DialogueChoicesSelected = CurrentQuest.StepProgress.DialogueChoicesSelected + 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (CurrentQuest.StepProgress.DialogueChoicesSelected >= step.DialogueChoices.Count)
|
||||||
|
IncreaseStepCount();
|
||||||
|
}
|
||||||
|
|
||||||
public unsafe void ExecuteNextStep()
|
public unsafe void ExecuteNextStep()
|
||||||
{
|
{
|
||||||
(QuestSequence? seq, QuestStep? step) = GetNextStep();
|
(QuestSequence? seq, QuestStep? step) = GetNextStep();
|
||||||
@ -422,7 +440,8 @@ internal sealed class QuestController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_pluginLog.Warning($"Aethernet shortcut not unlocked (from: {step.AethernetShortcut.From}, to: {step.AethernetShortcut.To}), walking manually");
|
_pluginLog.Warning(
|
||||||
|
$"Aethernet shortcut not unlocked (from: {step.AethernetShortcut.From}, to: {step.AethernetShortcut.To}), walking manually");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step.TargetTerritoryId == _clientState.TerritoryType && !step.SkipIf.Contains(ESkipCondition.Never))
|
if (step.TargetTerritoryId == _clientState.TerritoryType && !step.SkipIf.Contains(ESkipCondition.Never))
|
||||||
@ -439,11 +458,6 @@ internal sealed class QuestController
|
|||||||
{
|
{
|
||||||
_pluginLog.Information("We're at the jump destination, skipping movement");
|
_pluginLog.Information("We're at the jump destination, skipping movement");
|
||||||
}
|
}
|
||||||
else if (step.InteractionType == EInteractionType.CutsceneSelectString &&
|
|
||||||
_condition[ConditionFlag.OccupiedInCutSceneEvent])
|
|
||||||
{
|
|
||||||
_pluginLog.Information("In cutscene selection, skipping movement");
|
|
||||||
}
|
|
||||||
else if (step.Position != null)
|
else if (step.Position != null)
|
||||||
{
|
{
|
||||||
float distance;
|
float distance;
|
||||||
@ -543,6 +557,9 @@ internal sealed class QuestController
|
|||||||
}
|
}
|
||||||
|
|
||||||
_gameFunctions.InteractWith(step.DataId.Value);
|
_gameFunctions.InteractWith(step.DataId.Value);
|
||||||
|
|
||||||
|
// if we have any dialogue, that is handled in GameUiController
|
||||||
|
if (step.DialogueChoices.Count == 0)
|
||||||
IncreaseStepCount();
|
IncreaseStepCount();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -712,41 +729,6 @@ internal sealed class QuestController
|
|||||||
// Need to manually forward
|
// Need to manually forward
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EInteractionType.CutsceneSelectString:
|
|
||||||
// to do this automatically, should likely be in Addon's post setup
|
|
||||||
if (_gameGui.TryGetAddonByName<AddonCutSceneSelectString>("CutSceneSelectString", out var addon) &&
|
|
||||||
LAddon.IsAddonReady(&addon->AtkUnitBase))
|
|
||||||
{
|
|
||||||
foreach (DialogueChoice dialogueChoice in step.DialogueChoices)
|
|
||||||
{
|
|
||||||
string? excelString = _gameFunctions.GetExcelString(CurrentQuest.Quest,
|
|
||||||
dialogueChoice.ExcelSheet, dialogueChoice.Answer);
|
|
||||||
if (excelString == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_pluginLog.Verbose($"Looking for option '{excelString}'");
|
|
||||||
for (int i = 5; i < addon->AtkUnitBase.AtkValuesCount; ++i)
|
|
||||||
{
|
|
||||||
var atkValue = addon->AtkUnitBase.AtkValues[i];
|
|
||||||
if (atkValue.Type != ValueType.String)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
string? atkString = atkValue.ReadAtkString();
|
|
||||||
_pluginLog.Verbose($"Option {i}: {atkString}");
|
|
||||||
if (excelString == atkString)
|
|
||||||
{
|
|
||||||
_pluginLog.Information($"Selecting option {i - 5}: {atkString}");
|
|
||||||
addon->AtkUnitBase.FireCallbackInt(i - 5);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (step.DataId != null && !_condition[ConditionFlag.OccupiedInCutSceneEvent])
|
|
||||||
_gameFunctions.InteractWith(step.DataId.Value);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_pluginLog.Warning($"Action '{step.InteractionType}' is not implemented");
|
_pluginLog.Warning($"Action '{step.InteractionType}' is not implemented");
|
||||||
break;
|
break;
|
||||||
@ -767,5 +749,6 @@ internal sealed class QuestController
|
|||||||
|
|
||||||
public sealed record StepProgress(
|
public sealed record StepProgress(
|
||||||
bool AetheryteShortcutUsed = false,
|
bool AetheryteShortcutUsed = false,
|
||||||
bool AethernetShortcutUsed = false);
|
bool AethernetShortcutUsed = false,
|
||||||
|
int DialogueChoicesSelected = 0);
|
||||||
}
|
}
|
||||||
|
@ -474,22 +474,18 @@ internal sealed unsafe class GameFunctions
|
|||||||
_pluginLog.Error($"Could not find content for content finder condition (cf: {contentFinderConditionId})");
|
_pluginLog.Error($"Could not find content for content finder condition (cf: {contentFinderConditionId})");
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? GetExcelString(Quest currentQuestQuest, string? excelSheetName, string key)
|
public string? GetExcelString(Quest currentQuest, string? excelSheetName, string key)
|
||||||
{
|
{
|
||||||
if (excelSheetName == null)
|
if (excelSheetName == null)
|
||||||
{
|
{
|
||||||
string questPrefix = $"quest/{(currentQuestQuest.QuestId / 100):000}/";
|
var questRow = _dataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets2.Quest>()!.GetRow((uint)currentQuest.QuestId + 0x10000);
|
||||||
string questSuffix = $"_{currentQuestQuest.QuestId:00000}";
|
if (questRow == null)
|
||||||
excelSheetName = _dataManager.Excel
|
|
||||||
.GetSheetNames()
|
|
||||||
.SingleOrDefault(x =>
|
|
||||||
x.StartsWith(questPrefix, StringComparison.Ordinal) &&
|
|
||||||
x.EndsWith(questSuffix, StringComparison.Ordinal));
|
|
||||||
if (excelSheetName == null)
|
|
||||||
{
|
{
|
||||||
_pluginLog.Error($"Could not find sheet matching '{questPrefix}*{questSuffix}");
|
_pluginLog.Error($"Could not find quest row for {currentQuest.QuestId}");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
excelSheetName = $"quest/{(currentQuest.QuestId / 100):000}/{questRow.Id}";
|
||||||
}
|
}
|
||||||
|
|
||||||
var excelSheet = _dataManager.Excel.GetSheet<QuestDialogueText>(excelSheetName);
|
var excelSheet = _dataManager.Excel.GetSheet<QuestDialogueText>(excelSheetName);
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Questionable.Model.V1.Converter;
|
||||||
|
|
||||||
|
public sealed class DialogueChoiceTypeConverter() : EnumConverter<EDialogChoiceType>(Values)
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<EDialogChoiceType, string> Values = new()
|
||||||
|
{
|
||||||
|
{ EDialogChoiceType.YesNo, "YesNo" },
|
||||||
|
{ EDialogChoiceType.List, "List" },
|
||||||
|
};
|
||||||
|
}
|
@ -20,7 +20,6 @@ public sealed class InteractionTypeConverter() : EnumConverter<EInteractionType>
|
|||||||
{ EInteractionType.Duty, "Duty" },
|
{ EInteractionType.Duty, "Duty" },
|
||||||
{ EInteractionType.SinglePlayerDuty, "SinglePlayerDuty" },
|
{ EInteractionType.SinglePlayerDuty, "SinglePlayerDuty" },
|
||||||
{ EInteractionType.Jump, "Jump" },
|
{ EInteractionType.Jump, "Jump" },
|
||||||
{ EInteractionType.CutsceneSelectString, "CutsceneSelectString" },
|
|
||||||
{ EInteractionType.ShouldBeAJump, "ShouldBeAJump" },
|
{ EInteractionType.ShouldBeAJump, "ShouldBeAJump" },
|
||||||
{ EInteractionType.Instruction, "Instruction" },
|
{ EInteractionType.Instruction, "Instruction" },
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
namespace Questionable.Model.V1;
|
using System.Text.Json.Serialization;
|
||||||
|
using Questionable.Model.V1.Converter;
|
||||||
|
|
||||||
public sealed class DialogueChoice
|
namespace Questionable.Model.V1;
|
||||||
|
|
||||||
|
public class DialogueChoice
|
||||||
{
|
{
|
||||||
|
[JsonConverter(typeof(DialogueChoiceTypeConverter))]
|
||||||
|
public EDialogChoiceType Type { get; set; }
|
||||||
public string? ExcelSheet { get; set; }
|
public string? ExcelSheet { get; set; }
|
||||||
public string Answer { get; set; } = null!;
|
public string Prompt { get; set; } = null!;
|
||||||
|
public bool Yes { get; set; } = true;
|
||||||
|
public string? Answer { get; set; }
|
||||||
}
|
}
|
||||||
|
8
Questionable/Model/V1/EDialogChoiceType.cs
Normal file
8
Questionable/Model/V1/EDialogChoiceType.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Questionable.Model.V1;
|
||||||
|
|
||||||
|
public enum EDialogChoiceType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
YesNo,
|
||||||
|
List
|
||||||
|
}
|
@ -20,7 +20,6 @@ public enum EInteractionType
|
|||||||
Duty,
|
Duty,
|
||||||
SinglePlayerDuty,
|
SinglePlayerDuty,
|
||||||
Jump,
|
Jump,
|
||||||
CutsceneSelectString,
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Needs to be adjusted for coords etc. in the quest data.
|
/// Needs to be adjusted for coords etc. in the quest data.
|
||||||
|
@ -7,4 +7,12 @@ public class QuestSequence
|
|||||||
public required int Sequence { get; set; }
|
public required int Sequence { get; set; }
|
||||||
public string? Comment { get; set; }
|
public string? Comment { get; set; }
|
||||||
public List<QuestStep> Steps { get; set; } = new();
|
public List<QuestStep> Steps { get; set; } = new();
|
||||||
|
|
||||||
|
public QuestStep? FindStep(int step)
|
||||||
|
{
|
||||||
|
if (step < 0 || step >= Steps.Count)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Steps[step];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0-windows</TargetFramework>
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
<Version>0.2</Version>
|
<Version>0.3</Version>
|
||||||
<LangVersion>12</LangVersion>
|
<LangVersion>12</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
@ -27,13 +27,13 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
private readonly ICommandManager _commandManager;
|
private readonly ICommandManager _commandManager;
|
||||||
private readonly GameFunctions _gameFunctions;
|
private readonly GameFunctions _gameFunctions;
|
||||||
private readonly QuestController _questController;
|
private readonly QuestController _questController;
|
||||||
|
|
||||||
private readonly MovementController _movementController;
|
private readonly MovementController _movementController;
|
||||||
|
private readonly GameUiController _gameUiController;
|
||||||
|
|
||||||
public QuestionablePlugin(DalamudPluginInterface pluginInterface, IClientState clientState,
|
public QuestionablePlugin(DalamudPluginInterface pluginInterface, IClientState clientState,
|
||||||
ITargetManager targetManager, IFramework framework, IGameGui gameGui, IDataManager dataManager,
|
ITargetManager targetManager, IFramework framework, IGameGui gameGui, IDataManager dataManager,
|
||||||
ISigScanner sigScanner, IObjectTable objectTable, IPluginLog pluginLog, ICondition condition, IChatGui chatGui,
|
ISigScanner sigScanner, IObjectTable objectTable, IPluginLog pluginLog, ICondition condition, IChatGui chatGui,
|
||||||
ICommandManager commandManager)
|
ICommandManager commandManager, IAddonLifecycle addonLifecycle)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(pluginInterface);
|
ArgumentNullException.ThrowIfNull(pluginInterface);
|
||||||
ArgumentNullException.ThrowIfNull(sigScanner);
|
ArgumentNullException.ThrowIfNull(sigScanner);
|
||||||
@ -55,6 +55,9 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
new MovementController(navmeshIpc, clientState, _gameFunctions, condition, pluginLog);
|
new MovementController(navmeshIpc, clientState, _gameFunctions, condition, pluginLog);
|
||||||
_questController = new QuestController(pluginInterface, dataManager, _clientState, _gameFunctions,
|
_questController = new QuestController(pluginInterface, dataManager, _clientState, _gameFunctions,
|
||||||
_movementController, pluginLog, condition, chatGui, framework, gameGui, aetheryteData, lifestreamIpc);
|
_movementController, pluginLog, condition, chatGui, framework, gameGui, aetheryteData, lifestreamIpc);
|
||||||
|
_gameUiController =
|
||||||
|
new GameUiController(clientState, addonLifecycle, dataManager, _gameFunctions, _questController, pluginLog);
|
||||||
|
|
||||||
_windowSystem.AddWindow(new DebugWindow(_movementController, _questController, _gameFunctions, clientState,
|
_windowSystem.AddWindow(new DebugWindow(_movementController, _questController, _gameFunctions, clientState,
|
||||||
targetManager));
|
targetManager));
|
||||||
|
|
||||||
@ -100,6 +103,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
_framework.Update -= FrameworkUpdate;
|
_framework.Update -= FrameworkUpdate;
|
||||||
_pluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
|
_pluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
|
||||||
|
|
||||||
|
_gameUiController.Dispose();
|
||||||
_movementController.Dispose();
|
_movementController.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using Dalamud.Game.ClientState.Objects;
|
using Dalamud.Game.ClientState.Objects;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Memory;
|
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Control;
|
using FFXIVClientStructs.FFXIV.Client.Game.Control;
|
||||||
@ -45,6 +42,15 @@ internal sealed class DebugWindow : Window
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool DrawConditions()
|
||||||
|
{
|
||||||
|
if (!_clientState.IsLoggedIn || _clientState.LocalPlayer == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var currentQuest = _questController.CurrentQuest;
|
||||||
|
return currentQuest == null || !currentQuest.Quest.Data.TerritoryBlacklist.Contains(_clientState.TerritoryType);
|
||||||
|
}
|
||||||
|
|
||||||
public override unsafe void Draw()
|
public override unsafe void Draw()
|
||||||
{
|
{
|
||||||
if (!_clientState.IsLoggedIn || _clientState.LocalPlayer == null)
|
if (!_clientState.IsLoggedIn || _clientState.LocalPlayer == null)
|
||||||
|
Loading…
Reference in New Issue
Block a user