Improve quest chain handling (auto-accepting next quest, dialogue choices)

arr-p5 v1.4
Liza 2024-07-12 02:42:37 +02:00
parent edf753b457
commit 77168a9ee6
Signed by: liza
GPG Key ID: 7199F8D727D55F67
26 changed files with 1063 additions and 25 deletions

View File

@ -20,6 +20,104 @@
] ]
} }
] ]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1046319,
"Position": {
"X": -335.3476,
"Y": 69.418495,
"Z": 155.87085
},
"TerritoryId": 137,
"InteractionType": "Interact",
"AetheryteShortcut": "Eastern La Noscea - Wineport"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 1046319,
"Position": {
"X": -335.3476,
"Y": 69.418495,
"Z": 155.87085
},
"TerritoryId": 137,
"InteractionType": "SinglePlayerDuty"
}
]
},
{
"Sequence": 3,
"Steps": [
{
"Position": {
"X": 0,
"Y": 0,
"Z": 0
},
"TerritoryId": 1,
"InteractionType": "WalkTo",
"Comment": "Filler"
}
]
},
{
"Sequence": 4,
"Steps": [
{
"DataId": 1046319,
"Position": {
"X": -335.3476,
"Y": 69.418495,
"Z": 155.87085
},
"StopDistance": 5,
"TerritoryId": 137,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 5,
"Steps": [
{
"DataId": 1046320,
"Position": {
"X": 267.01758,
"Y": -25,
"Z": 264.88135
},
"TerritoryId": 138,
"InteractionType": "Interact",
"AetheryteShortcut": "Western La Noscea - Aleport"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1046289,
"Position": {
"X": -64.62195,
"Y": -17.95485,
"Z": 201.28174
},
"TerritoryId": 1185,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "Tuliyollal",
"AethernetShortcut": [
"[Tuliyollal] Aetheryte Plaza",
"[Tuliyollal] Bayside Bevy Marketplace"
]
}
]
} }
] ]
} }

View File

@ -152,6 +152,195 @@
"InteractionType": "Interact" "InteractionType": "Interact"
} }
] ]
},
{
"Sequence": 6,
"Steps": [
{
"DataId": 2013713,
"Position": {
"X": 362.35596,
"Y": 3.616333,
"Z": -241.77924
},
"StopDistance": 0.25,
"TerritoryId": 957,
"InteractionType": "Interact",
"Fly": true,
"SkipIf": [
"NotTargetable"
],
"DialogueChoices": [
{
"Type": "YesNo",
"Prompt": "TEXT_KINGBA531_04845_Q1_000_054",
"Yes": true
}
],
"Comment": "retry point"
},
{
"DataId": 1048364,
"Position": {
"X": 387.43045,
"Y": 5.8062716,
"Z": -203.20459
},
"TerritoryId": 957,
"InteractionType": "WaitForNpcAtPosition",
"StopDistance": 50,
"Mount": false,
"Sprint": false
},
{
"Position": {
"X": 386.85394,
"Y": 3.0972311,
"Z": -220.57103
},
"TerritoryId": 957,
"InteractionType": "WalkTo",
"Mount": false,
"Sprint": false
},
{
"DataId": 1048364,
"Position": {
"X": 398.46808,
"Y": 12.103142,
"Z": -174.068
},
"TerritoryId": 957,
"InteractionType": "WaitForNpcAtPosition",
"StopDistance": 50,
"Mount": false,
"Sprint": false
},
{
"Position": {
"X": 395.88028,
"Y": 10.267179,
"Z": -192.21916
},
"TerritoryId": 957,
"InteractionType": "WalkTo",
"Mount": false,
"Sprint": false
},
{
"DataId": 1048364,
"Position": {
"X": 395.6862,
"Y": 11.099065,
"Z": -169.7558
},
"TerritoryId": 957,
"InteractionType": "WaitForNpcAtPosition",
"StopDistance": 50,
"Mount": false,
"Sprint": false
},
{
"Position": {
"X": 398.42825,
"Y": 12.946791,
"Z": -180.08061
},
"TerritoryId": 957,
"InteractionType": "WalkTo",
"Mount": false,
"Sprint": false
},
{
"Position": {
"X": 368.02908,
"Y": 5.7749786,
"Z": -135.06207
},
"TerritoryId": 957,
"InteractionType": "WalkTo",
"Mount": false,
"Sprint": false
},
{
"Position": {
"X": 300.81885,
"Y": 18.925224,
"Z": -43.56831
},
"TerritoryId": 957,
"InteractionType": "WalkTo",
"Mount": false,
"Sprint": false
},
{
"DataId": 1048364,
"Position": {
"X": 274.41418,
"Y": 17.838093,
"Z": -2.1020741
},
"TerritoryId": 957,
"InteractionType": "WaitForNpcAtPosition",
"StopDistance": 50,
"Mount": false,
"Sprint": false
},
{
"Position": {
"X": 256.60135,
"Y": 19.312042,
"Z": -1.2628903
},
"TerritoryId": 957,
"InteractionType": "WalkTo",
"Mount": false,
"Sprint": false
},
{
"Position": {
"X": 244.453,
"Y": 16.725914,
"Z": 14.936783
},
"TerritoryId": 957,
"InteractionType": "WalkTo",
"Mount": false,
"Sprint": false
}
]
},
{
"Sequence": 7,
"Steps": [
{
"DataId": 1048368,
"Position": {
"X": 239.33765,
"Y": 11.061386,
"Z": 69.99304
},
"TerritoryId": 957,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1048331,
"Position": {
"X": 214.03821,
"Y": 5.2600574,
"Z": 628.3817
},
"TerritoryId": 957,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "Thavnair - Yedlihmad",
"NextQuestId": 4846
}
]
} }
] ]
} }

View File

@ -0,0 +1,138 @@
{
"$schema": "https://carvel.li/questionable/quest-1.0",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1048331,
"Position": {
"X": 214.03821,
"Y": 5.2600574,
"Z": 628.3817
},
"TerritoryId": 957,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1048330,
"Position": {
"X": -28.732727,
"Y": -17.972864,
"Z": 194.72034
},
"TerritoryId": 1185,
"InteractionType": "Interact",
"AetheryteShortcut": "Tuliyollal",
"AethernetShortcut": [
"[Tuliyollal] Aetheryte Plaza",
"[Tuliyollal] Bayside Bevy Marketplace"
]
}
]
},
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": 327.87598,
"Y": -15.862221,
"Z": -236.6933
},
"TerritoryId": 1190,
"InteractionType": "WalkTo",
"AetheryteShortcut": "Shaaloani - Mehwahhetsoan",
"SkipIf": [
"FlyingUnlocked"
]
},
{
"Position": {
"X": 442.79218,
"Y": -16.660347,
"Z": -111.04725
},
"TerritoryId": 1190,
"InteractionType": "Combat",
"EnemySpawnType": "AutoOnEnterArea",
"KillEnemyDataIds": [
17627
],
"Fly": true
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 1048369,
"Position": {
"X": 441.5503,
"Y": -16.619904,
"Z": -109.14783
},
"StopDistance": 7,
"TerritoryId": 1190,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 4,
"Steps": [
{
"DataId": 1048333,
"Position": {
"X": 52.506226,
"Y": -5.20688E-07,
"Z": -54.154297
},
"TerritoryId": 963,
"InteractionType": "Interact",
"AetheryteShortcut": "Radz-at-Han"
}
]
},
{
"Sequence": 5,
"Steps": [
{
"DataId": 1048372,
"Position": {
"X": -53.177734,
"Y": -1.9999962,
"Z": 147.60046
},
"StopDistance": 7,
"TerritoryId": 963,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1048331,
"Position": {
"X": 214.03821,
"Y": 5.2600574,
"Z": 628.3817
},
"TerritoryId": 957,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "Thavnair - Yedlihmad",
"NextQuestId": 4847
}
]
}
]
}

View File

@ -0,0 +1,95 @@
{
"$schema": "https://carvel.li/questionable/quest-1.0",
"Author": "liza",
"TerritoryBlacklist": [
1218
],
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1048331,
"Position": {
"X": 214.03821,
"Y": 5.2600574,
"Z": 628.3817
},
"TerritoryId": 957,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1048374,
"Position": {
"X": -77.04285,
"Y": 99.946754,
"Z": -711.0552
},
"TerritoryId": 957,
"InteractionType": "SinglePlayerDuty",
"AetheryteShortcut": "Radz-at-Han",
"AethernetShortcut": [
"[Radz-at-Han] Aetheryte Plaza",
"[Radz-at-Han] The Gate of First Sight (Thavnair)"
],
"Fly": true
}
]
},
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": 0,
"Y": 0,
"Z": 0
},
"TerritoryId": 1,
"InteractionType": "WalkTo",
"Comment": "Filler"
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 1048374,
"Position": {
"X": -77.04285,
"Y": 99.946754,
"Z": -711.0552
},
"TerritoryId": 957,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1048330,
"Position": {
"X": -28.732727,
"Y": -17.972864,
"Z": 194.72034
},
"TerritoryId": 1185,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "Tuliyollal",
"AethernetShortcut": [
"[Tuliyollal] Aetheryte Plaza",
"[Tuliyollal] Bayside Bevy Marketplace"
]
}
]
}
]
}

View File

@ -45,7 +45,7 @@
}, },
"TerritoryId": 1187, "TerritoryId": 1187,
"InteractionType": "Interact", "InteractionType": "Interact",
"Fly": true, "DisableNavmesh": true,
"DialogueChoices": [ "DialogueChoices": [
{ {
"Type": "YesNo", "Type": "YesNo",

View File

@ -0,0 +1,97 @@
{
"$schema": "https://carvel.li/questionable/quest-1.0",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1042301,
"Position": {
"X": -66.02582,
"Y": 39.994705,
"Z": 321.06494
},
"TerritoryId": 957,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 2012858,
"Position": {
"X": 280.78125,
"Y": 0.045776367,
"Z": 556.7252
},
"TerritoryId": 957,
"InteractionType": "Interact",
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
32
]
},
{
"DataId": 2012857,
"Position": {
"X": 303.36462,
"Y": 0.015197754,
"Z": 530.44934
},
"TerritoryId": 957,
"InteractionType": "Interact",
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
64
]
},
{
"DataId": 2012856,
"Position": {
"X": 281.94092,
"Y": 0.015197754,
"Z": 510.64307
},
"TerritoryId": 957,
"InteractionType": "Interact",
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
128
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1042301,
"Position": {
"X": -66.02582,
"Y": 39.994705,
"Z": 321.06494
},
"TerritoryId": 957,
"InteractionType": "CompleteQuest",
"Fly": true
}
]
}
]
}

View File

@ -0,0 +1,70 @@
{
"$schema": "https://carvel.li/questionable/quest-1.0",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1042301,
"Position": {
"X": -66.02582,
"Y": 39.994705,
"Z": 321.06494
},
"TerritoryId": 957,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 2012892,
"Position": {
"X": -120.19531,
"Y": 41.000854,
"Z": 340.41345
},
"TerritoryId": 957,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 1042458,
"Position": {
"X": 416.5254,
"Y": 8.834262,
"Z": -344.38086
},
"TerritoryId": 957,
"InteractionType": "Interact",
"AetheryteShortcut": "Thavnair - Palaka's Stand",
"Fly": true
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1042301,
"Position": {
"X": -66.02582,
"Y": 39.994705,
"Z": 321.06494
},
"TerritoryId": 957,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "Thavnair - Yedlihmad",
"Fly": true
}
]
}
]
}

View File

@ -0,0 +1,74 @@
{
"$schema": "https://carvel.li/questionable/quest-1.0",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1042301,
"Position": {
"X": -66.02582,
"Y": 39.994705,
"Z": 321.06494
},
"TerritoryId": 957,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 2012893,
"Position": {
"X": 267.32275,
"Y": 7.156433,
"Z": -476.34088
},
"TerritoryId": 957,
"InteractionType": "UseItem",
"ItemId": 2003403,
"AetheryteShortcut": "Thavnair - Palaka's Stand"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 2012894,
"Position": {
"X": 257.09924,
"Y": 6.6071167,
"Z": -468.0705
},
"TerritoryId": 957,
"InteractionType": "Combat",
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [
14678
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1042301,
"Position": {
"X": -66.02582,
"Y": 39.994705,
"Z": 321.06494
},
"TerritoryId": 957,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "Thavnair - Yedlihmad",
"Fly": true
}
]
}
]
}

View File

@ -0,0 +1,41 @@
{
"$schema": "https://carvel.li/questionable/quest-1.0",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1041960,
"Position": {
"X": -1.9379272,
"Y": -7.758,
"Z": 42.282715
},
"TerritoryId": 962,
"InteractionType": "AcceptQuest",
"AetheryteShortcut": "Old Sharlayan",
"SkipIf": [
"AetheryteShortcutIfInSameTerritory"
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1037060,
"Position": {
"X": 25.894531,
"Y": -15.646991,
"Z": 99.68713
},
"TerritoryId": 962,
"InteractionType": "CompleteQuest",
"NextQuestId": 4177
}
]
}
]
}

View File

@ -0,0 +1,41 @@
{
"$schema": "https://carvel.li/questionable/quest-1.0",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1037060,
"Position": {
"X": 25.894531,
"Y": -15.646991,
"Z": 99.68713
},
"TerritoryId": 962,
"InteractionType": "AcceptQuest",
"AetheryteShortcut": "Old Sharlayan",
"SkipIf": [
"AetheryteShortcutIfInSameTerritory"
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1037059,
"Position": {
"X": 35.202515,
"Y": -15.646992,
"Z": 102.4032
},
"TerritoryId": 962,
"InteractionType": "CompleteQuest",
"NextQuestId": 4178
}
]
}
]
}

View File

@ -0,0 +1,41 @@
{
"$schema": "https://carvel.li/questionable/quest-1.0",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1037060,
"Position": {
"X": 25.894531,
"Y": -15.646991,
"Z": 99.68713
},
"TerritoryId": 962,
"InteractionType": "AcceptQuest",
"AetheryteShortcut": "Old Sharlayan",
"SkipIf": [
"AetheryteShortcutIfInSameTerritory"
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1037059,
"Position": {
"X": 35.202515,
"Y": -15.646992,
"Z": 102.4032
},
"TerritoryId": 962,
"InteractionType": "CompleteQuest",
"NextQuestId": 4179
}
]
}
]
}

View File

@ -0,0 +1,41 @@
{
"$schema": "https://carvel.li/questionable/quest-1.0",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1037060,
"Position": {
"X": 25.894531,
"Y": -15.646991,
"Z": 99.68713
},
"TerritoryId": 962,
"InteractionType": "AcceptQuest",
"AetheryteShortcut": "Old Sharlayan",
"SkipIf": [
"AetheryteShortcutIfInSameTerritory"
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1037059,
"Position": {
"X": 35.202515,
"Y": -15.646992,
"Z": 102.4032
},
"TerritoryId": 962,
"InteractionType": "CompleteQuest",
"NextQuestId": 5009
}
]
}
]
}

View File

@ -133,7 +133,6 @@
}, },
"TerritoryId": 813, "TerritoryId": 813,
"InteractionType": "Interact", "InteractionType": "Interact",
"DisableNavmesh": true,
"CompletionQuestVariablesFlags": [ "CompletionQuestVariablesFlags": [
null, null,
null, null,

View File

@ -106,7 +106,6 @@
"KillEnemyDataIds": [ "KillEnemyDataIds": [
12168 12168
], ],
"Comment": "TODO Missing enemy ids",
"Fly": true, "Fly": true,
"$.2": "QuestVariables if done after [1, 2]: irrelevant because it automatically progresses to the next step" "$.2": "QuestVariables if done after [1, 2]: irrelevant because it automatically progresses to the next step"
} }

View File

@ -38,7 +38,8 @@
"Z": -653.85443 "Z": -653.85443
}, },
"TerritoryId": 156, "TerritoryId": 156,
"InteractionType": "WalkTo" "InteractionType": "WalkTo",
"Mount": true
}, },
{ {
"Position": { "Position": {

View File

@ -15,6 +15,7 @@
"Y": -2.0168546E-08, "Y": -2.0168546E-08,
"Z": 1.9378662 "Z": 1.9378662
}, },
"StopDistance": 5,
"TerritoryId": 819, "TerritoryId": 819,
"InteractionType": "AcceptQuest" "InteractionType": "AcceptQuest"
} }
@ -80,7 +81,27 @@
}, },
"TerritoryId": 918, "TerritoryId": 918,
"InteractionType": "SinglePlayerDuty", "InteractionType": "SinglePlayerDuty",
"Comment": "Fight NPCs, then Elidibus" "Comment": "Fight NPCs, then Elidibus",
"DialogueChoices": [
{
"Type": "List",
"ExcelSheet": "ContentTalk",
"Prompt": 209,
"Answer": 211
},
{
"Type": "List",
"ExcelSheet": "ContentTalk",
"Prompt": 209,
"Answer": 216
},
{
"Type": "List",
"ExcelSheet": "ContentTalk",
"Prompt": 241,
"Answer": 222
}
]
} }
] ]
}, },

View File

@ -394,7 +394,8 @@
"FlyingUnlocked", "FlyingUnlocked",
"DifferentTerritory", "DifferentTerritory",
"ChocoboUnlocked", "ChocoboUnlocked",
"AetheryteShortcutIfInSameTerritory" "AetheryteShortcutIfInSameTerritory",
"NotTargetable"
] ]
} }
}, },

View File

@ -11,5 +11,6 @@ public sealed class SkipConditionConverter() : EnumConverter<ESkipCondition>(Val
{ ESkipCondition.FlyingUnlocked, "FlyingUnlocked" }, { ESkipCondition.FlyingUnlocked, "FlyingUnlocked" },
{ ESkipCondition.ChocoboUnlocked, "ChocoboUnlocked" }, { ESkipCondition.ChocoboUnlocked, "ChocoboUnlocked" },
{ ESkipCondition.AetheryteShortcutIfInSameTerritory, "AetheryteShortcutIfInSameTerritory" }, { ESkipCondition.AetheryteShortcutIfInSameTerritory, "AetheryteShortcutIfInSameTerritory" },
{ ESkipCondition.NotTargetable, "NotTargetable" },
}; };
} }

View File

@ -12,4 +12,5 @@ public enum ESkipCondition
FlyingUnlocked, FlyingUnlocked,
ChocoboUnlocked, ChocoboUnlocked,
AetheryteShortcutIfInSameTerritory, AetheryteShortcutIfInSameTerritory,
NotTargetable,
} }

View File

@ -162,7 +162,7 @@ internal sealed class GameUiController : IDisposable
return; return;
} }
var currentQuest = _questController.CurrentQuest; var currentQuest = _questController.StartedQuest;
if (currentQuest != null && actualPrompt == null) if (currentQuest != null && actualPrompt == null)
{ {
// it is possible for this to be a quest selection // it is possible for this to be a quest selection
@ -177,7 +177,7 @@ internal sealed class GameUiController : IDisposable
private int? HandleListChoice(string? actualPrompt, List<string?> answers, bool checkAllSteps) private int? HandleListChoice(string? actualPrompt, List<string?> answers, bool checkAllSteps)
{ {
List<DialogueChoiceInfo> dialogueChoices = []; List<DialogueChoiceInfo> dialogueChoices = [];
var currentQuest = _questController.CurrentQuest; var currentQuest = _questController.StartedQuest;
if (currentQuest != null) if (currentQuest != null)
{ {
var quest = currentQuest.Quest; var quest = currentQuest.Quest;
@ -305,7 +305,7 @@ internal sealed class GameUiController : IDisposable
_logger.LogTrace("Prompt: '{Prompt}'", actualPrompt); _logger.LogTrace("Prompt: '{Prompt}'", actualPrompt);
var currentQuest = _questController.CurrentQuest; var currentQuest = _questController.StartedQuest;
if (currentQuest == null) if (currentQuest == null)
return; return;
@ -421,7 +421,7 @@ internal sealed class GameUiController : IDisposable
private unsafe void PointMenuPostSetup(AtkUnitBase* addonPointMenu) private unsafe void PointMenuPostSetup(AtkUnitBase* addonPointMenu)
{ {
var currentQuest = _questController.CurrentQuest; var currentQuest = _questController.StartedQuest;
if (currentQuest == null) if (currentQuest == null)
{ {
_logger.LogInformation("Ignoring point menu, no active quest"); _logger.LogInformation("Ignoring point menu, no active quest");
@ -471,7 +471,7 @@ internal sealed class GameUiController : IDisposable
private unsafe void UnendingCodexPostSetup(AddonEvent type, AddonArgs args) private unsafe void UnendingCodexPostSetup(AddonEvent type, AddonArgs args)
{ {
if (_questController.CurrentQuest?.Quest.QuestId == 4526) if (_questController.StartedQuest?.Quest.QuestId == 4526)
{ {
_logger.LogInformation("Closing Unending Codex"); _logger.LogInformation("Closing Unending Codex");
AtkUnitBase* addon = (AtkUnitBase*)args.Addon; AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
@ -481,7 +481,7 @@ internal sealed class GameUiController : IDisposable
private unsafe void ContentsTutorialPostSetup(AddonEvent type, AddonArgs args) private unsafe void ContentsTutorialPostSetup(AddonEvent type, AddonArgs args)
{ {
if (_questController.CurrentQuest?.Quest.QuestId == 245) if (_questController.StartedQuest?.Quest.QuestId == 245)
{ {
_logger.LogInformation("Closing ContentsTutorial"); _logger.LogInformation("Closing ContentsTutorial");
AtkUnitBase* addon = (AtkUnitBase*)args.Addon; AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
@ -491,7 +491,7 @@ internal sealed class GameUiController : IDisposable
private unsafe void MultipleHelpWindowPostSetup(AddonEvent type, AddonArgs args) private unsafe void MultipleHelpWindowPostSetup(AddonEvent type, AddonArgs args)
{ {
if (_questController.CurrentQuest?.Quest.QuestId == 245) if (_questController.StartedQuest?.Quest.QuestId == 245)
{ {
_logger.LogInformation("Closing MultipleHelpWindow"); _logger.LogInformation("Closing MultipleHelpWindow");
AtkUnitBase* addon = (AtkUnitBase*)args.Addon; AtkUnitBase* addon = (AtkUnitBase*)args.Addon;

View File

@ -5,6 +5,7 @@ using Dalamud.Game.ClientState.Keys;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps; using Questionable.Controller.Steps;
using Questionable.Controller.Steps.BaseFactory;
using Questionable.External; using Questionable.External;
using Questionable.Model; using Questionable.Model;
using Questionable.Model.V1; using Questionable.Model.V1;
@ -55,19 +56,24 @@ internal sealed class QuestController
_taskFactories = taskFactories.ToList().AsReadOnly(); _taskFactories = taskFactories.ToList().AsReadOnly();
} }
public QuestProgress? CurrentQuest public (QuestProgress Progress, CurrentQuestType Type)? CurrentQuestDetails
{ {
get get
{ {
if (_simulatedQuest != null) if (_simulatedQuest != null)
return _simulatedQuest; return (_simulatedQuest, CurrentQuestType.Simulated);
else if (_nextQuest != null && _gameFunctions.IsReadyToAcceptQuest(_nextQuest.Quest.QuestId)) else if (_nextQuest != null && _gameFunctions.IsReadyToAcceptQuest(_nextQuest.Quest.QuestId))
return _nextQuest; return (_nextQuest, CurrentQuestType.Next);
else if (_startedQuest != null)
return (_startedQuest, CurrentQuestType.Normal);
else else
return _startedQuest; return null;
} }
} }
public QuestProgress? CurrentQuest => CurrentQuestDetails?.Progress;
public QuestProgress? StartedQuest => _startedQuest;
public QuestProgress? SimulatedQuest => _simulatedQuest; public QuestProgress? SimulatedQuest => _simulatedQuest;
public QuestProgress? NextQuest => _nextQuest; public QuestProgress? NextQuest => _nextQuest;
@ -106,7 +112,6 @@ internal sealed class QuestController
if (CurrentQuest != null && CurrentQuest.Quest.Root.TerritoryBlacklist.Contains(_clientState.TerritoryType)) if (CurrentQuest != null && CurrentQuest.Quest.Root.TerritoryBlacklist.Contains(_clientState.TerritoryType))
return; return;
// not verified to work
if (_automatic && _currentTask == null && _taskQueue.Count == 0 if (_automatic && _currentTask == null && _taskQueue.Count == 0
&& CurrentQuest is { Sequence: 0, Step: 0 } or { Sequence: 0, Step: 255 } && CurrentQuest is { Sequence: 0, Step: 0 } or { Sequence: 0, Step: 255 }
&& DateTime.Now >= CurrentQuest.StepProgress.StartedAt.AddSeconds(15)) && DateTime.Now >= CurrentQuest.StepProgress.StartedAt.AddSeconds(15))
@ -140,12 +145,16 @@ internal sealed class QuestController
// if the quest is accepted, we no longer track it // if the quest is accepted, we no longer track it
if (_gameFunctions.IsQuestAcceptedOrComplete(_nextQuest.Quest.QuestId)) if (_gameFunctions.IsQuestAcceptedOrComplete(_nextQuest.Quest.QuestId))
{ {
_logger.LogInformation("Next quest {QuestId} accepted or completed", _nextQuest.Quest.QuestId);
_nextQuest = null; _nextQuest = null;
currentSequence = 0; currentSequence = 0;
} }
else else
{ {
currentSequence = _nextQuest.Sequence; // by definition, this should always be 0 currentSequence = _nextQuest.Sequence; // by definition, this should always be 0
if (_nextQuest.Step == 0 && _currentTask == null && _taskQueue.Count == 0 && _automatic)
ExecuteNextStep(true);
} }
} }
@ -325,6 +334,8 @@ internal sealed class QuestController
{ {
if (CurrentQuest?.Step is >= 0 and < 255) if (CurrentQuest?.Step is >= 0 and < 255)
ExecuteNextStep(true); ExecuteNextStep(true);
else
_logger.LogInformation("Couldn't execute next step during Stop() call");
} }
else if (_automatic) else if (_automatic)
{ {
@ -422,6 +433,10 @@ internal sealed class QuestController
case ETaskResult.TaskComplete: case ETaskResult.TaskComplete:
_logger.LogInformation("{Task} → {Result}, remaining tasks: {RemainingTaskCount}", _logger.LogInformation("{Task} → {Result}, remaining tasks: {RemainingTaskCount}",
_currentTask, result, _taskQueue.Count); _currentTask, result, _taskQueue.Count);
if (_currentTask is WaitAtEnd.WaitQuestCompleted)
_simulatedQuest = null;
_currentTask = null; _currentTask = null;
// handled in next update // handled in next update
@ -566,7 +581,19 @@ internal sealed class QuestController
} }
} }
public void SkipSimulatedTask()
{
_currentTask = null;
}
public sealed record StepProgress( public sealed record StepProgress(
DateTime StartedAt, DateTime StartedAt,
int PointMenuCounter = 0); int PointMenuCounter = 0);
public enum CurrentQuestType
{
Normal,
Next,
Simulated,
}
} }

View File

@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions; using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
using FFXIVClientStructs.FFXIV.Client.Game.UI; using FFXIVClientStructs.FFXIV.Client.Game.UI;
using FFXIVClientStructs.FFXIV.Client.System.Framework; using FFXIVClientStructs.FFXIV.Client.System.Framework;
@ -32,7 +34,8 @@ internal static class SkipCondition
internal sealed class CheckTask( internal sealed class CheckTask(
ILogger<CheckTask> logger, ILogger<CheckTask> logger,
GameFunctions gameFunctions) : ITask GameFunctions gameFunctions,
IClientState clientState) : ITask
{ {
public QuestStep Step { get; set; } = null!; public QuestStep Step { get; set; } = null!;
public List<ESkipCondition> SkipConditions { get; set; } = null!; public List<ESkipCondition> SkipConditions { get; set; } = null!;
@ -71,6 +74,25 @@ internal static class SkipCondition
return true; return true;
} }
if (SkipConditions.Contains(ESkipCondition.NotTargetable) &&
Step is { DataId: not null })
{
IGameObject? gameObject = gameFunctions.FindObjectByDataId(Step.DataId.Value);
if (gameObject == null)
{
if ((Step.Position.GetValueOrDefault() - clientState.LocalPlayer!.Position).Length() < 100)
{
logger.LogInformation("Skipping step, object is not nearby (but we are)");
return true;
}
}
else if (!gameObject.IsTargetable)
{
logger.LogInformation("Skipping step, object is not targetable");
return true;
}
}
if (Step is if (Step is
{ {
DataId: not null, DataId: not null,

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.Text;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Questionable.Model; using Questionable.Model;
using Quest = Lumina.Excel.GeneratedSheets.Quest; using Quest = Lumina.Excel.GeneratedSheets.Quest;
@ -40,6 +41,8 @@ internal sealed class QuestData
.ToList(); .ToList();
} }
public bool IsIssuerOfAnyQuest(uint targetId) => _quests.Values.Any(x => x.IssuerDataId == targetId);
public void ShowQuestsIssuedByTarget() public void ShowQuestsIssuedByTarget()
{ {
var targetId = _targetManager.Target?.DataId; var targetId = _targetManager.Target?.DataId;
@ -53,6 +56,6 @@ internal sealed class QuestData
_chatGui.Print($"{quests.Count} quest(s) issued by target {_targetManager.Target?.Name}:"); _chatGui.Print($"{quests.Count} quest(s) issued by target {_targetManager.Target?.Name}:");
foreach (QuestInfo quest in quests) foreach (QuestInfo quest in quests)
_chatGui.Print($" {quest.QuestId}: {quest.Name}"); _chatGui.Print($" {quest.QuestId}_{quest.SimplifiedName}");
} }
} }

View File

@ -1,4 +1,6 @@
using ExcelQuest = Lumina.Excel.GeneratedSheets.Quest; using System;
using Dalamud.Game.Text;
using ExcelQuest = Lumina.Excel.GeneratedSheets.Quest;
namespace Questionable.Model; namespace Questionable.Model;
@ -16,4 +18,7 @@ internal sealed class QuestInfo
public string Name { get; } public string Name { get; }
public ushort Level { get; } public ushort Level { get; }
public uint IssuerDataId { get; } public uint IssuerDataId { get; }
public string SimplifiedName => Name
.TrimStart(SeIconChar.QuestSync.ToIconChar(), SeIconChar.QuestRepeatable.ToIconChar(), ' ');
} }

View File

@ -100,6 +100,6 @@ internal sealed class DebugOverlay : Window
ImGui.GetWindowDrawList().AddCircleFilled(screenPos, 3f, color); ImGui.GetWindowDrawList().AddCircleFilled(screenPos, 3f, color);
ImGui.GetWindowDrawList().AddText(screenPos + new Vector2(10, -8), color, ImGui.GetWindowDrawList().AddText(screenPos + new Vector2(10, -8), color,
$"{counter}: {step.InteractionType}\n{step.Position.Value.ToString("G", CultureInfo.InvariantCulture)}\n{step.Comment}"); $"{counter}: {step.InteractionType}\n{step.Position.Value.ToString("G", CultureInfo.InvariantCulture)} [{(step.Position.Value - _clientState.LocalPlayer!.Position).Length():N2}]\n{step.Comment}");
} }
} }

View File

@ -119,10 +119,37 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
private void DrawQuest() private void DrawQuest()
{ {
var currentQuest = _questController.CurrentQuest; var currentQuestDetails = _questController.CurrentQuestDetails;
QuestController.QuestProgress? currentQuest = currentQuestDetails?.Progress;
QuestController.CurrentQuestType? currentQuestType = currentQuestDetails?.Type;
if (currentQuest != null) if (currentQuest != null)
{ {
ImGui.TextUnformatted($"Quest: {currentQuest.Quest.Info.Name} / {currentQuest.Sequence} / {currentQuest.Step}"); if (currentQuestType == QuestController.CurrentQuestType.Simulated)
{
var simulatedQuest = _questController.SimulatedQuest ?? currentQuest;
using var _ = ImRaii.PushColor(ImGuiCol.Text, 0xFF0000FF);
ImGui.TextUnformatted(
$"Simulated Quest: {simulatedQuest.Quest.Info.Name} / {simulatedQuest.Sequence} / {simulatedQuest.Step}");
}
else if (currentQuestType == QuestController.CurrentQuestType.Next)
{
var startedQuest = _questController.StartedQuest;
if (startedQuest != null)
{
ImGui.TextUnformatted(
$"Quest: {startedQuest.Quest.Info.Name} / {startedQuest.Sequence} / {startedQuest.Step}");
}
using var _ = ImRaii.PushColor(ImGuiCol.Text, 0xFF00FFFF);
ImGui.TextUnformatted(
$"Next Quest: {currentQuest.Quest.Info.Name} / {currentQuest.Sequence} / {currentQuest.Step}");
}
else
{
ImGui.TextUnformatted(
$"Quest: {currentQuest.Quest.Info.Name} / {currentQuest.Sequence} / {currentQuest.Step}");
}
ImGui.BeginDisabled(); ImGui.BeginDisabled();
var questWork = _gameFunctions.GetQuestEx(currentQuest.Quest.QuestId); var questWork = _gameFunctions.GetQuestEx(currentQuest.Quest.QuestId);
@ -295,6 +322,12 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
ImGui.EndDisabled(); ImGui.EndDisabled();
if (ImGui.Button("Skip current task"))
{
_questController.SkipSimulatedTask();
}
ImGui.SameLine();
if (ImGui.Button("Clear sim")) if (ImGui.Button("Clear sim"))
{ {
_questController.SimulateQuest(null); _questController.SimulateQuest(null);
@ -378,7 +411,7 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
ImGui.EndDisabled(); ImGui.EndDisabled();
ImGui.SameLine(); ImGui.SameLine();
ImGui.BeginDisabled(gameObject->NamePlateIconId == 0); ImGui.BeginDisabled(!_questData.IsIssuerOfAnyQuest(_targetManager.Target.DataId));
if (ImGuiComponents.IconButton(FontAwesomeIcon.Bars)) if (ImGuiComponents.IconButton(FontAwesomeIcon.Bars))
_questData.ShowQuestsIssuedByTarget(); _questData.ShowQuestsIssuedByTarget();
ImGui.EndDisabled(); ImGui.EndDisabled();