Compare commits

...

11 Commits
v4.6 ... master

36 changed files with 2204 additions and 529 deletions

View File

@ -48,6 +48,9 @@ internal static class SkipConditionsExtensions
Assignment(nameof(SkipStepConditions.Flying), skipStepConditions.Flying,
emptyStep.Flying)
.AsSyntaxNodeOrToken(),
Assignment(nameof(SkipStepConditions.Diving), skipStepConditions.Diving,
emptyStep.Diving)
.AsSyntaxNodeOrToken(),
Assignment(nameof(SkipStepConditions.Chocobo), skipStepConditions.Chocobo,
emptyStep.Chocobo)
.AsSyntaxNodeOrToken(),

View File

@ -1,7 +1,6 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"Disabled": true,
"QuestSequence": [
{
"Sequence": 0,
@ -14,7 +13,17 @@
"Z": 59.952637
},
"TerritoryId": 130,
"InteractionType": "AcceptQuest"
"InteractionType": "AcceptQuest",
"AetheryteShortcut": "Ul'dah",
"AethernetShortcut": [
"[Ul'dah] Aetheryte Plaza",
"[Ul'dah] Thaumaturges' Guild"
],
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
}
]
},
@ -40,6 +49,126 @@
"NextQuestId": 351
}
]
},
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": -71.92632,
"Y": 9.839797,
"Z": 283.98495
},
"TerritoryId": 141,
"InteractionType": "Combat",
"EnemySpawnType": "OverworldEnemies",
"ComplexCombatData": [
{
"DataId": 351,
"MinimumKillCount": 3,
"$": "Slay star marmots as a thaumaturge",
"CompletionQuestVariablesFlags": [
{
"Low": 3
},
null,
null,
null,
null,
null
]
},
{
"DataId": 385,
"MinimumKillCount": 3,
"$": "Slay huge hornets as a thaumaturge",
"CompletionQuestVariablesFlags": [
null,
{
"High": 3
},
null,
null,
null,
null
]
}
],
"AetheryteShortcut": "Ul'dah",
"AethernetShortcut": [
"[Ul'dah] Thaumaturges' Guild",
"[Ul'dah] Gate of Nald (Central Thanalan)"
],
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true,
"InTerritory": [
141
]
}
},
"CompletionQuestVariablesFlags": [
{
"Low": 3
},
{
"High": 3
},
null,
null,
null,
null
]
},
{
"Position": {
"X": 39.449,
"Y": 3.082914,
"Z": 272.46896
},
"TerritoryId": 141,
"InteractionType": "Combat",
"EnemySpawnType": "OverworldEnemies",
"ComplexCombatData": [
{
"DataId": 205,
"MinimumKillCount": 3,
"$": "Slay snapping shrews as a thaumaturge"
}
],
"CompletionQuestVariablesFlags": [
null,
{
"Low": 3
},
null,
null,
null,
null
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1001708,
"Position": {
"X": -250.3548,
"Y": 18,
"Z": 80.88806
},
"TerritoryId": 130,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "Ul'dah",
"AethernetShortcut": [
"[Ul'dah] Aetheryte Plaza",
"[Ul'dah] Thaumaturges' Guild"
],
"NextQuestId": 351
}
]
}
]
}

View File

@ -0,0 +1,231 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": ["liza", "pot0to"],
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1001708,
"Position": {
"X": -250.3548,
"Y": 18,
"Z": 80.88806
},
"TerritoryId": 130,
"InteractionType": "AcceptQuest",
"AetheryteShortcut": "Ul'dah",
"AethernetShortcut": [
"[Ul'dah] Aetheryte Plaza",
"[Ul'dah] Thaumaturges' Guild"
],
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1001710,
"Position": {
"X": -240.2533,
"Y": 18.8,
"Z": 86.900024
},
"TerritoryId": 130,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"TerritoryId": 130,
"InteractionType": "None",
"AetheryteShortcut": "Ul'dah",
"AethernetShortcut": [
"[Ul'dah] Thaumaturges' Guild",
"[Ul'dah] Gate of Nald (Central Thanalan)"
],
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true,
"InTerritory": [
141
],
"AetheryteUnlocked": "Central Thanalan - Black Brush Station"
},
"AethernetShortcutIf": {
"AetheryteUnlocked": "Central Thanalan - Black Brush Station"
}
}
},
{
"Position": {
"X": -62.183617,
"Y": -3.6582246,
"Z": 145.88391
},
"InteractionType": "WalkTo",
"TerritoryId": 141,
"SkipConditions": {
"StepIf": {
"Flying": "Unlocked",
"AetheryteUnlocked": "Central Thanalan - Black Brush Station"
}
}
},
{
"Position": {
"X": 149.07747,
"Y": -2,
"Z": -225.21188
},
"TerritoryId": 141,
"AetheryteShortcut": "Central Thanalan - Black Brush Station",
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
},
"Fly": true,
"InteractionType": "Combat",
"EnemySpawnType": "OverworldEnemies",
"ComplexCombatData": [
{
"DataId": 160,
"MinimumKillCount": 8,
"$": "Slay efts",
"CompletionQuestVariablesFlags": [
{
"Low": 8
},
null,
null,
null,
null,
null
]
}
]
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 1001710,
"Position": {
"X": -240.2533,
"Y": 18.8,
"Z": 86.900024
},
"TerritoryId": 130,
"InteractionType": "Interact",
"AetheryteShortcut": "Ul'dah",
"AethernetShortcut": [
"[Ul'dah] Aetheryte Plaza",
"[Ul'dah] Thaumaturges' Guild"
],
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
},
"DialogueChoices": [
{
"Type": "List",
"Prompt": "TEXT_CLSTHM100_00348_Q_000_1",
"Answer": "TEXT_CLSTHM100_00348_A_000_3"
}
]
}
]
},
{
"Sequence": 4,
"Steps": [
{
"DataId": 2001511,
"Position": {
"X": -366.29285,
"Y": -34.989014,
"Z": 293.56824
},
"TerritoryId": 145,
"InteractionType": "Combat",
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [
166,
1238
],
"Fly": true,
"AetheryteShortcut": "Eastern Thanalan - Camp Drybone",
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
}
]
},
{
"Sequence": 5,
"Steps": [
{
"DataId": 2001498,
"Position": {
"X": -366.29285,
"Y": -34.989014,
"Z": 293.56824
},
"TerritoryId": 145,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 6,
"Steps": [
{
"DataId": 1001710,
"Position": {
"X": -240.2533,
"Y": 18.8,
"Z": 86.900024
},
"TerritoryId": 130,
"InteractionType": "Interact",
"AetheryteShortcut": "Ul'dah",
"AethernetShortcut": [
"[Ul'dah] Aetheryte Plaza",
"[Ul'dah] Thaumaturges' Guild"
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1001708,
"Position": {
"X": -250.3548,
"Y": 18,
"Z": 80.88806
},
"TerritoryId": 130,
"InteractionType": "CompleteQuest",
"NextQuestId": 350
}
]
}
]
}

View File

@ -163,7 +163,8 @@
"InteractionType": "Combat",
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [
166
166,
1238
],
"Fly": true,
"AetheryteShortcut": "Eastern Thanalan - Camp Drybone",

View File

@ -6,14 +6,13 @@
"Sequence": 0,
"Steps": [
{
"DataId": 1000895,
"Position": {
"X": -335.74432,
"X": -335.8204,
"Y": 12.899764,
"Z": 1.3884888
"Z": 4.017052
},
"TerritoryId": 129,
"InteractionType": "AcceptQuest",
"InteractionType": "WalkTo",
"AetheryteShortcut": "Limsa Lominsa",
"AethernetShortcut": [
"[Limsa Lominsa] Aetheryte Plaza",
@ -24,6 +23,16 @@
"InSameTerritory": true
}
}
},
{
"DataId": 1000895,
"Position": {
"X": -335.74432,
"Y": 12.899764,
"Z": 1.3884888
},
"TerritoryId": 129,
"InteractionType": "AcceptQuest"
}
]
},

View File

@ -0,0 +1,181 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"Position": {
"X": -335.8204,
"Y": 12.899764,
"Z": 4.017052
},
"TerritoryId": 129,
"InteractionType": "WalkTo",
"AetheryteShortcut": "Limsa Lominsa",
"AethernetShortcut": [
"[Limsa Lominsa] Aetheryte Plaza",
"[Limsa Lominsa] Arcanists' Guild"
],
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
},
{
"DataId": 1000895,
"Position": {
"X": -335.74432,
"Y": 12.899764,
"Z": 1.3884888
},
"TerritoryId": 129,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1000909,
"Position": {
"X": -326.37524,
"Y": 12.899658,
"Z": 9.994568
},
"TerritoryId": 129,
"InteractionType": "Interact",
"DialogueChoices": [
{
"Type": "YesNo",
"Prompt": "TEXT_CLSACN020_00453_Q1_000_000",
"Yes": true
}
]
}
]
},
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": -1.5568014,
"Y": 66.12121,
"Z": 102.35001
},
"TerritoryId": 135,
"InteractionType": "Combat",
"EnemySpawnType": "OverworldEnemies",
"ComplexCombatData": [
{
"DataId": 347,
"MinimumKillCount": 3,
"CompletionQuestVariablesFlags": [
{
"Low": 3
},
null,
null,
null,
null,
null
]
},
{
"DataId": 49,
"MinimumKillCount": 3,
"CompletionQuestVariablesFlags": [
null,
{
"Low": 3
},
null,
null,
null,
null
]
}
],
"AethernetShortcut": [
"[Limsa Lominsa] Arcanists' Guild",
"[Limsa Lominsa] Tempest Gate (Lower La Noscea)"
],
"CompletionQuestVariablesFlags": [
{
"Low": 3
},
{
"Low": 3
},
null,
null,
null,
null
]
},
{
"Position": {
"X": 157.63565,
"Y": 38.01287,
"Z": 48.92973
},
"TerritoryId": 135,
"InteractionType": "Combat",
"EnemySpawnType": "OverworldEnemies",
"ComplexCombatData": [
{
"DataId": 324,
"MinimumKillCount": 3,
"CompletionQuestVariablesFlags": [
null,
{
"High": 3
},
null,
null,
null,
null
]
}
],
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
{
"High": 3
},
null,
null,
null,
null
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1000909,
"Position": {
"X": -326.37524,
"Y": 12.899658,
"Z": 9.994568
},
"TerritoryId": 129,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "Limsa Lominsa",
"AethernetShortcut": [
"[Limsa Lominsa] Aetheryte Plaza",
"[Limsa Lominsa] Arcanists' Guild"
],
"NextQuestId": 455
}
]
}
]
}

View File

@ -0,0 +1,179 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1000909,
"Position": {
"X": -326.37524,
"Y": 12.899658,
"Z": 9.994568
},
"TerritoryId": 129,
"InteractionType": "AcceptQuest",
"AetheryteShortcut": "Limsa Lominsa",
"AethernetShortcut": [
"[Limsa Lominsa] Aetheryte Plaza",
"[Limsa Lominsa] Arcanists' Guild"
],
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
}
]
},
{
"Sequence": 1,
"Steps": [
{
"Position": {
"X": 667.4784,
"Y": 15.36824,
"Z": 443.4379
},
"TerritoryId": 138,
"InteractionType": "Combat",
"EnemySpawnType": "OverworldEnemies",
"KillEnemyDataIds": [
22
],
"AetheryteShortcut": "Western La Noscea - Swiftperch",
"CompletionQuestVariablesFlags": [
{
"Low": 3
},
null,
null,
null,
null,
null
]
},
{
"Position": {
"X": 686.6034,
"Y": 23.682272,
"Z": 422.78772
},
"TerritoryId": 138,
"InteractionType": "Combat",
"EnemySpawnType": "OverworldEnemies",
"KillEnemyDataIds": [
138
],
"CompletionQuestVariablesFlags": [
null,
{
"High": 3
},
null,
null,
null,
null
]
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 1000909,
"Position": {
"X": -326.37524,
"Y": 12.899658,
"Z": 9.994568
},
"TerritoryId": 129,
"InteractionType": "Interact",
"AetheryteShortcut": "Limsa Lominsa",
"AethernetShortcut": [
"[Limsa Lominsa] Aetheryte Plaza",
"[Limsa Lominsa] Arcanists' Guild"
]
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 1005199,
"Position": {
"X": -348.3177,
"Y": -2.3744698,
"Z": 11.917236
},
"TerritoryId": 129,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 4,
"Steps": [
{
"DataId": 1005200,
"Position": {
"X": -106.79791,
"Y": 45.688404,
"Z": -252.33844
},
"TerritoryId": 134,
"InteractionType": "SinglePlayerDuty",
"AetheryteShortcut": "Middle La Noscea - Summerford Farms",
"Fly": true
}
]
},
{
"Sequence": 5,
"Steps": [
{
"DataId": 1005201,
"Position": {
"X": -98.49707,
"Y": 47.27536,
"Z": -262.31793
},
"StopDistance": 5,
"TerritoryId": 134,
"InteractionType": "Interact",
"DialogueChoices": [
{
"Type": "List",
"Prompt": "TEXT_CLSACN100_00456_Q1_000_000",
"Answer": "TEXT_CLSACN100_00456_A1_000_001"
}
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1000909,
"Position": {
"X": -326.37524,
"Y": 12.899658,
"Z": 9.994568
},
"TerritoryId": 129,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "Limsa Lominsa",
"AethernetShortcut": [
"[Limsa Lominsa] Aetheryte Plaza",
"[Limsa Lominsa] Arcanists' Guild"
],
"NextQuestId": 1103
}
]
}
]
}

View File

@ -0,0 +1,160 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1017169,
"Position": {
"X": -342.15308,
"Y": 59.03801,
"Z": 315.14453
},
"TerritoryId": 400,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1017170,
"Position": {
"X": -344.22827,
"Y": 59.038006,
"Z": 317.1587
},
"StopDistance": 7,
"TerritoryId": 400,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 2007198,
"Position": {
"X": -339.65057,
"Y": 58.976074,
"Z": 319.50854
},
"StopDistance": 4.5,
"TerritoryId": 400,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 1017432,
"Position": {
"X": -743.6179,
"Y": 81,
"Z": 372.1521
},
"TerritoryId": 400,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 4,
"Steps": [
{
"DataId": 1017169,
"Position": {
"X": -342.15308,
"Y": 59.03801,
"Z": 315.14453
},
"TerritoryId": 400,
"InteractionType": "Interact",
"Fly": true,
"DialogueChoices": [
{
"Type": "List",
"Prompt": "TEXT_BANMOG003_02322_Q1_000_000",
"Answer": "TEXT_BANMOG003_02322_A1_000_001"
}
]
}
]
},
{
"Sequence": 5,
"Steps": [
{
"DataId": 1017172,
"Position": {
"X": -329.3355,
"Y": 59.056396,
"Z": 298.23755
},
"TerritoryId": 400,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 6,
"Steps": [
{
"TerritoryId": 400,
"InteractionType": "Craft",
"ItemId": 15721,
"ItemCount": 1
},
{
"DataId": 1017169,
"Position": {
"X": -342.15308,
"Y": 59.03801,
"Z": 315.14453
},
"TerritoryId": 400,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 7,
"Steps": [
{
"DataId": 1017432,
"Position": {
"X": -743.6179,
"Y": 81,
"Z": 372.1521
},
"TerritoryId": 400,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1017170,
"Position": {
"X": -344.22827,
"Y": 59.038006,
"Z": 317.1587
},
"TerritoryId": 400,
"InteractionType": "CompleteQuest",
"Fly": true
}
]
}
]
}

View File

@ -1,153 +1,198 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "AnimaMachinae",
"QuestSequence": [
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "AnimaMachinae",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1016093,
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"TerritoryId": 401,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": -544.89056,
"Y": 61.602722,
"Z": -373.9669
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 2006649,
"Position": {
"X": -539.0555,
"Y": 64.22522,
"Z": -377.0047
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"StopDistance": 3,
"$": "0 0 0 0 0 0 --> 1 0 0 0 0 16",
"CompletionQuestVariablesFlags": [null,null,null,null,null,16]
},
{
"Position": {
"X": -505.35422,
"Y": -28.166508,
"Z": -528.1072
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 2006647,
"Position": {
"X": -504.78372,
"Y": -26.68805,
"Z": -530.93774
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"StopDistance": 3,
"$": "1 0 0 0 0 16 --> 2 0 0 0 0 80",
"CompletionQuestVariablesFlags": [null,null,null,null,null,64]
},
{
"Position": {
"X": -478.25208,
"Y": -31.101946,
"Z": -663.0455
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 2006648,
"Position": {
"X": -477.40906,
"Y": -28.885437,
"Z": -668.32996
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"StopDistance": 3,
"$": "2 0 0 0 0 80 --> 3 0 0 0 0 112",
"CompletionQuestVariablesFlags": [null,null,null,null,null,32]
},
{
"Position": {
"X": -102.45963,
"Y": -1.2632592,
"Z": -619.294
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 2006646,
"Position": {
"X": -96.20813,
"Y": 0.32037354,
"Z": -620.26404
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"StopDistance": 3,
"$": "3 0 0 0 0 112 --> 0 0 0 0 0 0"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
}
]
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
]
},
{
"Sequence": 1,
"Steps": [
{
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"StopDistance": 3,
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"NearPosition": {
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"MaximumDistance": 50,
"TerritoryId": 401
}
}
}
},
{
"DataId": 1016093,
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"TerritoryId": 401,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": -544.89056,
"Y": 61.602722,
"Z": -373.9669
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 2006649,
"Position": {
"X": -539.0555,
"Y": 64.22522,
"Z": -377.0047
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"StopDistance": 3,
"$": "0 0 0 0 0 0 --> 1 0 0 0 0 16",
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
16
]
},
{
"Position": {
"X": -505.35422,
"Y": -28.166508,
"Z": -528.1072
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 2006647,
"Position": {
"X": -504.78372,
"Y": -26.68805,
"Z": -530.93774
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"StopDistance": 3,
"$": "1 0 0 0 0 16 --> 2 0 0 0 0 80",
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
64
]
},
{
"Position": {
"X": -478.25208,
"Y": -31.101946,
"Z": -663.0455
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 2006648,
"Position": {
"X": -477.40906,
"Y": -28.885437,
"Z": -668.32996
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"StopDistance": 3,
"$": "2 0 0 0 0 80 --> 3 0 0 0 0 112",
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
32
]
},
{
"Position": {
"X": -102.45963,
"Y": -1.2632592,
"Z": -619.294
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 2006646,
"Position": {
"X": -96.20813,
"Y": 0.32037354,
"Z": -620.26404
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"StopDistance": 3,
"$": "3 0 0 0 0 112 --> 0 0 0 0 0 0"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
}
]
}
]
}

View File

@ -1,129 +1,119 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "AnimaMachinae",
"QuestSequence": [
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "AnimaMachinae",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"Position": {
"X": -797.36957,
"Y": -130.0076,
"Z": -404.2746
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 2006651,
"Position": {
"X": 664.3624,
"Y": -30.86908,
"Z": -137.0108
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
128
]
},
{
"DataId": 2006652,
"Position": {
"X": 847.2876,
"Y": -50.58368,
"Z": 7.2174683
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
64
]
},
{
"DataId": 2006653,
"Position": {
"X": 860.2273,
"Y": -84.45868,
"Z": 19.272095
},
"TerritoryId": 401,
"InteractionType": "Combat",
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
32
],
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [
5235
]
},
{
"DataId": 2006654,
"Position": {
"X": 642.63354,
"Y": -92.57648,
"Z": 63.035034
},
"TerritoryId": 401,
"InteractionType": "Combat",
"Fly": true,
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [
5235
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true,
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu"
}
]
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 2006651,
"Position": {
"X": 664.3624,
"Y": -30.86908,
"Z": -137.0108
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
128
]
},
{
"DataId": 2006652,
"Position": {
"X": 847.2876,
"Y": -50.58368,
"Z": 7.2174683
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
64
]
},
{
"DataId": 2006653,
"Position": {
"X": 860.2273,
"Y": -84.45868,
"Z": 19.272095
},
"TerritoryId": 401,
"InteractionType": "Combat",
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
32
],
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [
5235
]
},
{
"DataId": 2006654,
"Position": {
"X": 642.63354,
"Y": -92.57648,
"Z": 63.035034
},
"TerritoryId": 401,
"InteractionType": "Combat",
"Fly": true,
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [
5235
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true,
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu"
}
]
}
]
}

View File

@ -1,104 +1,128 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "AnimaMachinae",
"QuestSequence": [
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "AnimaMachinae",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1016093,
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"TerritoryId": 401,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 2006655,
"Position": {
"X": -48.325317,
"Y": 17.990356,
"Z": -852.47577
},
"TerritoryId": 401,
"InteractionType": "Action",
"Fly": true,
"Action": "Buffet (Sanuwa)"
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 2006656,
"Position": {
"X": 95.23157,
"Y": -11.886841,
"Z": -817.6242
},
"TerritoryId": 401,
"InteractionType": "Action",
"Fly": true,
"Action": "Buffet (Sanuwa)"
}
]
},
{
"Sequence": 4,
"Steps": [
{
"DataId": 2006657,
"Position": {
"X": 205.8899,
"Y": -6.9123535,
"Z": -785.70233
},
"TerritoryId": 401,
"InteractionType": "Action",
"Fly": true,
"Action": "Buffet (Sanuwa)"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true,
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu"
}
]
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
]
},
{
"Sequence": 1,
"Steps": [
{
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"StopDistance": 3,
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"NearPosition": {
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"MaximumDistance": 50,
"TerritoryId": 401
}
}
}
},
{
"DataId": 1016093,
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"TerritoryId": 401,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 2006655,
"Position": {
"X": -48.325317,
"Y": 17.990356,
"Z": -852.47577
},
"TerritoryId": 401,
"InteractionType": "Action",
"Fly": true,
"Action": "Buffet (Sanuwa)"
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 2006656,
"Position": {
"X": 95.23157,
"Y": -11.886841,
"Z": -817.6242
},
"TerritoryId": 401,
"InteractionType": "Action",
"Fly": true,
"Action": "Buffet (Sanuwa)"
}
]
},
{
"Sequence": 4,
"Steps": [
{
"DataId": 2006657,
"Position": {
"X": 205.8899,
"Y": -6.9123535,
"Z": -785.70233
},
"TerritoryId": 401,
"InteractionType": "Action",
"Fly": true,
"Action": "Buffet (Sanuwa)"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true,
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu"
}
]
}
]
}

View File

@ -1,108 +1,161 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "AnimaMachinae",
"QuestSequence": [
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "AnimaMachinae",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1011952,
"Position": {
"X": -277.63788,
"Y": -184.59735,
"Z": 741.60376
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"AetheryteShortcut": "The Sea of Clouds - Camp Cloudtop"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 2006662,
"Position": {
"X": 150.77429,
"Y": -133.98956,
"Z": 610.00977
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
8
]
},
{
"DataId": 2006661,
"Position": {
"X": 207.2633,
"Y": -124.101685,
"Z": 631.8303
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
16
]
},
{
"DataId": 2006658,
"Position": {
"X": 407.187,
"Y": -122.51471,
"Z": 724.0558
},
"TerritoryId": 401,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true,
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu"
}
]
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1011952,
"Position": {
"X": -277.63788,
"Y": -184.59735,
"Z": 741.60376
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"AetheryteShortcut": "The Sea of Clouds - Camp Cloudtop"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": 151.96031,
"Y": -135.00737,
"Z": 611.10016
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
8
]
}
}
},
{
"DataId": 2006662,
"Position": {
"X": 150.77429,
"Y": -133.98956,
"Z": 610.00977
},
"TerritoryId": 401,
"InteractionType": "Interact",
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
8
]
},
{
"Position": {
"X": 208.36453,
"Y": -125.28946,
"Z": 630.55835
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
16
]
}
}
},
{
"DataId": 2006661,
"Position": {
"X": 207.2633,
"Y": -124.101685,
"Z": 631.8303
},
"TerritoryId": 401,
"InteractionType": "Interact",
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
16
]
},
{
"Position": {
"X": 402.99722,
"Y": -125.28946,
"Z": 724.59906
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 2006658,
"Position": {
"X": 407.187,
"Y": -122.51471,
"Z": 724.0558
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Mount": false
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true,
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu"
}
]
}
]
}

View File

@ -0,0 +1,100 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 2006663,
"Position": {
"X": 665.0034,
"Y": -158.7702,
"Z": 662.2567
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
128
]
},
{
"DataId": 2006665,
"Position": {
"X": 728.1146,
"Y": -157.45789,
"Z": 815.5488
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
32
],
"Comment": "Enemy despawns when out of range"
},
{
"DataId": 2006664,
"Position": {
"X": 625.3605,
"Y": -160.29602,
"Z": 835.62976
},
"TerritoryId": 401,
"InteractionType": "Interact",
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
64
]
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
}
]
}
]
}

View File

@ -20,6 +20,30 @@
{
"Sequence": 1,
"Steps": [
{
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"StopDistance": 3,
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"NearPosition": {
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"MaximumDistance": 50,
"TerritoryId": 401
}
}
}
},
{
"DataId": 1016093,
"Position": {

View File

@ -35,6 +35,30 @@
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"StopDistance": 3,
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"NearPosition": {
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"MaximumDistance": 50,
"TerritoryId": 401
}
}
}
},
{
"DataId": 1016093,
"Position": {
@ -72,7 +96,14 @@
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"Fly": true,
"CompletionQuestVariablesFlags": [null,null,null,null,null,32]
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
32
]
},
{
"DataId": 1016221,
@ -85,7 +116,14 @@
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"Fly": true,
"CompletionQuestVariablesFlags": [null,null,null,null,null,64]
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
64
]
},
{
"DataId": 1016220,

View File

@ -36,6 +36,30 @@
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"StopDistance": 3,
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"NearPosition": {
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"MaximumDistance": 50,
"TerritoryId": 401
}
}
}
},
{
"DataId": 1016093,
"Position": {

View File

@ -36,6 +36,30 @@
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"StopDistance": 3,
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"NearPosition": {
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"MaximumDistance": 50,
"TerritoryId": 401
}
}
}
},
{
"DataId": 1016093,
"Position": {

View File

@ -20,6 +20,30 @@
{
"Sequence": 1,
"Steps": [
{
"Position": {
"X": 74.20459,
"Y": -48.533592,
"Z": -171.12994
},
"StopDistance": 3,
"TerritoryId": 398,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"NearPosition": {
"Position": {
"X": 74.20459,
"Y": -48.533592,
"Z": -171.12994
},
"MaximumDistance": 50,
"TerritoryId": 398
}
}
}
},
{
"DataId": 1017031,
"Position": {

View File

@ -20,6 +20,30 @@
{
"Sequence": 1,
"Steps": [
{
"Position": {
"X": 74.20459,
"Y": -48.533592,
"Z": -171.12994
},
"StopDistance": 3,
"TerritoryId": 398,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"NearPosition": {
"Position": {
"X": 74.20459,
"Y": -48.533592,
"Z": -171.12994
},
"MaximumDistance": 50,
"TerritoryId": 398
}
}
}
},
{
"DataId": 1017031,
"Position": {

View File

@ -20,6 +20,30 @@
{
"Sequence": 1,
"Steps": [
{
"Position": {
"X": 74.20459,
"Y": -48.533592,
"Z": -171.12994
},
"StopDistance": 3,
"TerritoryId": 398,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"NearPosition": {
"Position": {
"X": 74.20459,
"Y": -48.533592,
"Z": -171.12994
},
"MaximumDistance": 50,
"TerritoryId": 398
}
}
}
},
{
"DataId": 1017031,
"Position": {

View File

@ -20,6 +20,30 @@
{
"Sequence": 1,
"Steps": [
{
"Position": {
"X": 74.20459,
"Y": -48.533592,
"Z": -171.12994
},
"StopDistance": 3,
"TerritoryId": 398,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"NearPosition": {
"Position": {
"X": 74.20459,
"Y": -48.533592,
"Z": -171.12994
},
"MaximumDistance": 50,
"TerritoryId": 398
}
}
}
},
{
"DataId": 1017031,
"Position": {

View File

@ -211,6 +211,9 @@
"Unlocked"
]
},
"Diving": {
"type": ["boolean", "null"]
},
"NotTargetable": {
"type": "boolean"
},

View File

@ -12,6 +12,7 @@ public sealed class SkipStepConditions
public IList<QuestWorkValue?> CompletionQuestVariablesFlags { get; set; } = new List<QuestWorkValue?>();
public ELockedSkipCondition? Flying { get; set; }
public ELockedSkipCondition? Chocobo { get; set; }
public bool? Diving { get; set; }
public bool NotTargetable { get; set; }
public List<ushort> InTerritory { get; set; } = [];
public List<ushort> NotInTerritory { get; set; } = [];
@ -37,6 +38,7 @@ public sealed class SkipStepConditions
return (CompletionQuestVariablesFlags.Count > 0 && CompletionQuestVariablesFlags.Any(x => x != null)) ||
Flying != null ||
Chocobo != null ||
Diving != null ||
NotTargetable ||
InTerritory.Count > 0 ||
NotInTerritory.Count > 0 ||
@ -53,6 +55,6 @@ public sealed class SkipStepConditions
public override string ToString()
{
return
$"{nameof(Never)}: {Never}, {nameof(CompletionQuestVariablesFlags)}: {CompletionQuestVariablesFlags}, {nameof(Flying)}: {Flying}, {nameof(Chocobo)}: {Chocobo}, {nameof(NotTargetable)}: {NotTargetable}, {nameof(InTerritory)}: {string.Join(" ", InTerritory)}, {nameof(NotInTerritory)}: {string.Join(" ", NotInTerritory)}, {nameof(Item)}: {Item}, {nameof(QuestsAccepted)}: {string.Join(" ", QuestsAccepted)}, {nameof(QuestsCompleted)}: {string.Join(" ", QuestsCompleted)}, {nameof(NotNamePlateIconId)}: {string.Join(" ", NotNamePlateIconId)}, {nameof(NearPosition)}: {NearPosition}, {nameof(ExtraCondition)}: {ExtraCondition}";
$"{nameof(Never)}: {Never}, {nameof(CompletionQuestVariablesFlags)}: {CompletionQuestVariablesFlags}, {nameof(Flying)}: {Flying}, {nameof(Chocobo)}: {Chocobo}, {nameof(Diving)}: {Diving}, {nameof(NotTargetable)}: {NotTargetable}, {nameof(InTerritory)}: {string.Join(" ", InTerritory)}, {nameof(NotInTerritory)}: {string.Join(" ", NotInTerritory)}, {nameof(Item)}: {Item}, {nameof(QuestsAccepted)}: {string.Join(" ", QuestsAccepted)}, {nameof(QuestsCompleted)}: {string.Join(" ", QuestsCompleted)}, {nameof(NotNamePlateIconId)}: {string.Join(" ", NotNamePlateIconId)}, {nameof(NearPosition)}: {NearPosition}, {nameof(ExtraCondition)}: {ExtraCondition}";
}
}

View File

@ -762,7 +762,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>, IDi
if (!IsInterruptible() || _nextQuest != null || _gatheringQuest != null || _simulatedQuest != null)
return false;
ElementId? priorityQuestId = _questFunctions.GetNextPriorityQuestThatCanBeAccepted();
ElementId? priorityQuestId = _questFunctions.GetNextPriorityQuestsThatCanBeAccepted().FirstOrDefault();
if (priorityQuestId == null)
return false;

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game;
@ -54,7 +55,8 @@ internal static class SkipCondition
AetheryteFunctions aetheryteFunctions,
GameFunctions gameFunctions,
QuestFunctions questFunctions,
IClientState clientState) : TaskExecutor<SkipTask>
IClientState clientState,
ICondition condition) : TaskExecutor<SkipTask>
{
protected override unsafe bool Start()
{
@ -85,6 +87,18 @@ internal static class SkipCondition
return true;
}
if (skipConditions.Diving == true && condition[ConditionFlag.Diving])
{
logger.LogInformation("Skipping step, as you're currently diving underwater");
return true;
}
if (skipConditions.Diving == false && !condition[ConditionFlag.Diving])
{
logger.LogInformation("Skipping step, as you're not currently diving underwater");
return true;
}
if (skipConditions.InTerritory.Count > 0 &&
skipConditions.InTerritory.Contains(clientState.TerritoryType))
{

View File

@ -235,6 +235,16 @@ internal sealed class QuestData
.ToList();
}
public List<QuestInfo> GetAllByAlliedSociety(EAlliedSociety alliedSociety)
{
return _quests.Values
.Where(x => x is QuestInfo)
.Cast<QuestInfo>()
.Where(x => x.AlliedSociety == alliedSociety)
.OrderBy(x => x.QuestId)
.ToList();
}
public List<QuestInfo> GetClassJobQuests(EClassJob classJob)
{
List<uint> chapterIds = classJob switch

View File

@ -0,0 +1,134 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using FFXIVClientStructs.FFXIV.Client.Game;
using Microsoft.Extensions.Logging;
using Questionable.Data;
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Functions;
internal sealed class AlliedSocietyQuestFunctions
{
private readonly ILogger<AlliedSocietyQuestFunctions> _logger;
private readonly Dictionary<EAlliedSociety, List<NpcData>> _questsByAlliedSociety = [];
private readonly Dictionary<(uint NpcDataId, byte Seed, bool OutranksAll), List<QuestId>> _dailyQuests = [];
public AlliedSocietyQuestFunctions(QuestData questData, ILogger<AlliedSocietyQuestFunctions> logger)
{
_logger = logger;
foreach (var alliedSociety in Enum.GetValues<EAlliedSociety>().Where(x => x != EAlliedSociety.None))
{
var allQuests = questData.GetAllByAlliedSociety(alliedSociety);
var questsByIssuer = allQuests
.Where(x => x.IsRepeatable)
.GroupBy(x => x.IssuerDataId)
.ToDictionary(x => x.Key,
x => x.OrderBy(y => y.AlliedSocietyQuestGroup == 3).ThenBy(y => y.QuestId).ToList());
foreach ((uint issuerDataId, List<QuestInfo> quests) in questsByIssuer)
{
var npcData = new NpcData { IssuerDataId = issuerDataId, AllQuests = quests };
if (_questsByAlliedSociety.TryGetValue(alliedSociety, out List<NpcData>? existingNpcs))
existingNpcs.Add(npcData);
else
_questsByAlliedSociety[alliedSociety] = [npcData];
}
}
}
public unsafe List<QuestId> GetAvailableAlliedSocietyQuests(EAlliedSociety alliedSociety)
{
byte rankData = QuestManager.Instance()->BeastReputation[(int)alliedSociety - 1].Rank;
byte currentRank = (byte)(rankData & 0x7F);
if (currentRank == 0)
return [];
bool rankedUp = (rankData & 0x80) != 0;
byte seed = Marshal.ReadByte((nint)QuestManager.Instance() + 0x698); // TODO Use clientstructs
List<QuestId> result = [];
foreach (NpcData npcData in _questsByAlliedSociety[alliedSociety])
{
bool outranksAll = npcData.AllQuests.All(x => currentRank > x.AlliedSocietyRank);
var key = (NpcDataId: npcData.IssuerDataId, seed, outranksAll);
if (_dailyQuests.TryGetValue(key, out List<QuestId>? questIds))
result.AddRange(questIds);
else
{
var quests = CalculateAvailableQuests(npcData.AllQuests, seed, outranksAll, currentRank, rankedUp);
_logger.LogInformation("Available for {Tribe} (Seed: {Seed}, Issuer: {IssuerId}): {Quests}", alliedSociety, seed, npcData.IssuerDataId, string.Join(", ", quests));
_dailyQuests[key] = quests;
result.AddRange(quests);
}
}
return result;
}
private static List<QuestId> CalculateAvailableQuests(List<QuestInfo> allQuests, byte seed, bool outranksAll,
byte currentRank, bool rankedUp)
{
List<QuestInfo> eligible = [.. allQuests.Where(q => IsEligible(q, currentRank, rankedUp))];
List<QuestInfo> available = [];
if (eligible.Count == 0)
return [];
var rng = new Rng(seed);
if (outranksAll)
{
for (int i = 0, cnt = Math.Min(eligible.Count, 3); i < cnt; ++i)
{
var index = rng.Next(eligible.Count);
while (available.Contains(eligible[index]))
index = (index + 1) % eligible.Count;
available.Add(eligible[index]);
}
}
else
{
var firstExclusive = eligible.FindIndex(q => q.AlliedSocietyQuestGroup == 3);
if (firstExclusive >= 0)
available.Add(eligible[firstExclusive + rng.Next(eligible.Count - firstExclusive)]);
else
firstExclusive = eligible.Count;
for (int i = available.Count, cnt = Math.Min(firstExclusive, 3); i < cnt; ++i)
{
var index = rng.Next(firstExclusive);
while (available.Contains(eligible[index]))
index = (index + 1) % firstExclusive;
available.Add(eligible[index]);
}
}
return available.Select(x => (QuestId)x.QuestId).ToList();
}
private static bool IsEligible(QuestInfo questInfo, byte currentRank, bool rankedUp)
{
return rankedUp ? questInfo.AlliedSocietyRank == currentRank : questInfo.AlliedSocietyRank <= currentRank;
}
private sealed class NpcData
{
public required uint IssuerDataId { get; init; }
public required List<QuestInfo> AllQuests { get; init; } = [];
}
private record struct Rng(uint S0, uint S1 = 0, uint S2 = 0, uint S3 = 0)
{
public int Next(int range)
{
(S0, S1, S2, S3) = (S3, Transform(S0, S1), S1, S2);
return (int)(S1 % range);
}
// returns new value for s1
private static uint Transform(uint s0, uint s1)
{
var temp = s0 ^ (s0 << 11);
return s1 ^ temp ^ ((temp ^ (s1 >> 11)) >> 8);
}
}
}

View File

@ -28,6 +28,7 @@ internal sealed unsafe class QuestFunctions
private readonly QuestRegistry _questRegistry;
private readonly QuestData _questData;
private readonly AetheryteFunctions _aetheryteFunctions;
private readonly AlliedSocietyQuestFunctions _alliedSocietyQuestFunctions;
private readonly AlliedSocietyData _alliedSocietyData;
private readonly Configuration _configuration;
private readonly IDataManager _dataManager;
@ -38,6 +39,7 @@ internal sealed unsafe class QuestFunctions
QuestRegistry questRegistry,
QuestData questData,
AetheryteFunctions aetheryteFunctions,
AlliedSocietyQuestFunctions alliedSocietyQuestFunctions,
AlliedSocietyData alliedSocietyData,
Configuration configuration,
IDataManager dataManager,
@ -47,6 +49,7 @@ internal sealed unsafe class QuestFunctions
_questRegistry = questRegistry;
_questData = questData;
_aetheryteFunctions = aetheryteFunctions;
_alliedSocietyQuestFunctions = alliedSocietyQuestFunctions;
_alliedSocietyData = alliedSocietyData;
_configuration = configuration;
_dataManager = dataManager;
@ -152,11 +155,13 @@ internal sealed unsafe class QuestFunctions
{
// if we have multiple quests to turn in for an allied society, try and complete all of them
var (firstTrackedQuest, firstTrackedSequence) = trackedQuests.First();
EAlliedSociety firstTrackedAlliedSociety = _alliedSocietyData.GetCommonAlliedSocietyTurnIn(firstTrackedQuest);
EAlliedSociety firstTrackedAlliedSociety =
_alliedSocietyData.GetCommonAlliedSocietyTurnIn(firstTrackedQuest);
if (firstTrackedAlliedSociety != EAlliedSociety.None)
{
var alliedQuestsForSameSociety = trackedQuests.Skip(1)
.Where(quest => _alliedSocietyData.GetCommonAlliedSocietyTurnIn(quest.Quest) == firstTrackedAlliedSociety)
.Where(quest =>
_alliedSocietyData.GetCommonAlliedSocietyTurnIn(quest.Quest) == firstTrackedAlliedSociety)
.ToList();
if (alliedQuestsForSameSociety.Count > 0)
{
@ -177,14 +182,15 @@ internal sealed unsafe class QuestFunctions
// also include the first quest in the list for those
alliedQuestsForSameSociety.Insert(0, (firstTrackedQuest, firstTrackedSequence));
_alliedSocietyData.GetCommonAlliedSocietyNpcs(firstTrackedAlliedSociety, out uint[]? normalNpcs,
_alliedSocietyData.GetCommonAlliedSocietyNpcs(firstTrackedAlliedSociety,
out uint[]? normalNpcs,
out _);
if (normalNpcs.Length > 0)
{
var talkToNormalNpcs = alliedQuestsForSameSociety
.Where(x => x.Sequence < 255)
.Where(x => IsInteractStep(x.Quest, x.Sequence, normalNpcs))
.Where(x => IsInteractSequence(x.Quest, x.Sequence, normalNpcs))
.Cast<(ElementId, byte)?>()
.FirstOrDefault();
if (talkToNormalNpcs != null)
@ -215,7 +221,7 @@ internal sealed unsafe class QuestFunctions
return (firstTrackedQuest, firstTrackedSequence);
}
ElementId? priorityQuest = GetNextPriorityQuestThatCanBeAccepted();
ElementId? priorityQuest = GetNextPriorityQuestsThatCanBeAccepted().FirstOrDefault();
if (priorityQuest != null)
{
// if we have an accepted msq quest, and know of no quest of those currently in the to-do list...
@ -299,13 +305,16 @@ internal sealed unsafe class QuestFunctions
_alliedSocietyData.Mounts.ContainsKey(battleChara->Mount.MountId);
}
private bool IsInteractStep(ElementId questId, byte sequence, uint[] dataIds)
private bool IsInteractSequence(ElementId questId, byte sequenceNo, uint[] dataIds)
{
if (_questRegistry.TryGetQuest(questId, out var quest))
{
QuestStep? firstStepOfSequence = quest.FindSequence(sequence)?.FindStep(0);
return firstStepOfSequence is { InteractionType: EInteractionType.Interact, DataId: { } dataId } &&
dataIds.Contains(dataId);
QuestSequence? sequence = quest.FindSequence(sequenceNo);
return sequence != null &&
sequence.Steps.All(x =>
x is { InteractionType: EInteractionType.WalkTo } ||
(x is { InteractionType: EInteractionType.Interact, DataId: { } dataId } &&
dataIds.Contains(dataId)));
}
return false;
@ -327,12 +336,12 @@ internal sealed unsafe class QuestFunctions
return null;
}
public ElementId? GetNextPriorityQuestThatCanBeAccepted()
public List<ElementId> GetNextPriorityQuestsThatCanBeAccepted()
{
// all priority quests assume we're able to teleport to the beginning (and for e.g. class quests, the end)
// ideally without having to wait 15m for Return.
if (!_aetheryteFunctions.IsTeleportUnlocked())
return null;
return [];
// ideally, we'd also be able to afford *some* teleports
// this implicitly makes sure we're not starting one of the lv1 class quests if we can't afford to teleport back
@ -354,7 +363,7 @@ internal sealed unsafe class QuestFunctions
return firstStep.IsTeleportableForPriorityQuests();
})
.FirstOrDefault(x =>
.Where(x =>
{
if (!_questRegistry.TryGetQuest(x, out Quest? quest))
return false;
@ -381,7 +390,8 @@ internal sealed unsafe class QuestFunctions
return true;
});
});
})
.ToList();
}
private static int EstimateTeleportCosts(Quest quest)
@ -441,8 +451,11 @@ internal sealed unsafe class QuestFunctions
if (IsQuestAccepted(questId))
return false;
if (QuestManager.Instance()->IsDailyQuestCompleted(questId.Value))
return false;
if (quest.Info.AlliedSociety != EAlliedSociety.None)
{
if (QuestManager.Instance()->IsDailyQuestCompleted(questId.Value))
return false;
}
}
else
{
@ -540,6 +553,9 @@ internal sealed unsafe class QuestFunctions
if (questInfo.GrandCompany != GrandCompany.None && questInfo.GrandCompany != GetGrandCompany())
return true;
if (questInfo.AlliedSociety != EAlliedSociety.None && questInfo.IsRepeatable)
return !IsDailyAlliedSocietyQuestAndAvailableToday(questId);
return !HasCompletedPreviousQuests(questInfo, extraCompletedQuest) || !HasCompletedPreviousInstances(questInfo);
}
@ -563,6 +579,21 @@ internal sealed unsafe class QuestFunctions
return !HasCompletedPreviousQuests(questInfo, null);
}
public bool IsDailyAlliedSocietyQuest(QuestId questId)
{
var questInfo = (QuestInfo)_questData.GetQuestInfo(questId);
return questInfo.AlliedSociety != EAlliedSociety.None && questInfo.IsRepeatable;
}
public bool IsDailyAlliedSocietyQuestAndAvailableToday(QuestId questId)
{
if (!IsDailyAlliedSocietyQuest(questId))
return false;
var questInfo = (QuestInfo)_questData.GetQuestInfo(questId);
return _alliedSocietyQuestFunctions.GetAvailableAlliedSocietyQuests(questInfo.AlliedSociety).Contains(questId);
}
public bool IsQuestUnobtainable(ElementId elementId, ElementId? extraCompletedQuest = null)
{
if (elementId is QuestId questId)

View File

@ -60,6 +60,8 @@ internal sealed class QuestInfo : IQuestInfo
PreviousInstanceContentJoin = (EQuestJoin)quest.InstanceContentJoin;
GrandCompany = (GrandCompany)quest.GrandCompany.RowId;
AlliedSociety = (EAlliedSociety)quest.BeastTribe.RowId;
AlliedSocietyQuestGroup = quest.Unknown11;
AlliedSocietyRank = (int)quest.BeastReputationRank.RowId;
ClassJobs = QuestInfoUtils.AsList(quest.ClassJobCategory0.ValueNullable!);
IsSeasonalEvent = quest.Festival.RowId != 0;
NewGamePlusChapter = newGamePlusChapter;
@ -85,6 +87,8 @@ internal sealed class QuestInfo : IQuestInfo
public bool CompletesInstantly { get; }
public GrandCompany GrandCompany { get; }
public EAlliedSociety AlliedSociety { get; }
public byte AlliedSocietyQuestGroup { get; }
public int AlliedSocietyRank { get; }
public IReadOnlyList<EClassJob> ClassJobs { get; }
public bool IsSeasonalEvent { get; }
public uint NewGamePlusChapter { get; }

View File

@ -111,6 +111,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
serviceCollection.AddSingleton<GameFunctions>();
serviceCollection.AddSingleton<ChatFunctions>();
serviceCollection.AddSingleton<QuestFunctions>();
serviceCollection.AddSingleton<AlliedSocietyQuestFunctions>();
serviceCollection.AddSingleton<DalamudReflector>();
serviceCollection.AddSingleton<AetherCurrentData>();
@ -261,8 +262,10 @@ public sealed class QuestionablePlugin : IDalamudPlugin
serviceCollection.AddSingleton<QuickAccessButtonsComponent>();
serviceCollection.AddSingleton<RemainingTasksComponent>();
serviceCollection.AddSingleton<QuestJournalUtils>();
serviceCollection.AddSingleton<QuestJournalComponent>();
serviceCollection.AddSingleton<GatheringJournalComponent>();
serviceCollection.AddSingleton<AlliedSocietyJournalComponent>();
serviceCollection.AddSingleton<OneTimeSetupWindow>();
serviceCollection.AddSingleton<QuestWindow>();

View File

@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility.Raii;
using ImGuiNET;
using Questionable.Controller;
using Questionable.Data;
using Questionable.Functions;
using Questionable.Model;
using Questionable.Windows.QuestComponents;
namespace Questionable.Windows.JournalComponents;
internal sealed class AlliedSocietyJournalComponent
{
private static readonly string[] RankNames =
["Neutral", "Recognized", "Friendly", "Trusted", "Respected", "Honored", "Sworn", "Allied"];
private readonly QuestFunctions _questFunctions;
private readonly AlliedSocietyQuestFunctions _alliedSocietyQuestFunctions;
private readonly QuestData _questData;
private readonly QuestRegistry _questRegistry;
private readonly QuestJournalUtils _questJournalUtils;
private readonly QuestTooltipComponent _questTooltipComponent;
private readonly UiUtils _uiUtils;
public AlliedSocietyJournalComponent(
QuestFunctions questFunctions,
AlliedSocietyQuestFunctions alliedSocietyQuestFunctions,
QuestData questData,
QuestRegistry questRegistry,
QuestJournalUtils questJournalUtils,
QuestTooltipComponent questTooltipComponent,
UiUtils uiUtils)
{
_questFunctions = questFunctions;
_alliedSocietyQuestFunctions = alliedSocietyQuestFunctions;
_questData = questData;
_questRegistry = questRegistry;
_questJournalUtils = questJournalUtils;
_questTooltipComponent = questTooltipComponent;
_uiUtils = uiUtils;
}
public void DrawAlliedSocietyQuests()
{
using var tab = ImRaii.TabItem("Allied Societies");
if (!tab)
return;
foreach (EAlliedSociety alliedSociety in Enum.GetValues<EAlliedSociety>().Where(x => x != EAlliedSociety.None))
{
List<QuestInfo> quests = _alliedSocietyQuestFunctions.GetAvailableAlliedSocietyQuests(alliedSociety)
.Select(x => (QuestInfo)_questData.GetQuestInfo(x))
.ToList();
if (quests.Count == 0)
continue;
bool containsNewQuests = quests.Any(x => !_questFunctions.IsQuestComplete(x.QuestId));
if (containsNewQuests)
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudYellow);
if (!ImGui.CollapsingHeader($"{alliedSociety}###AlliedSociety{(int)alliedSociety}"))
continue;
if (containsNewQuests)
ImGui.PopStyleColor();
if (alliedSociety <= EAlliedSociety.Ixal)
{
for (byte i = 1; i <= 8; ++i)
{
var questsByRank = quests.Where(x => x.AlliedSocietyRank == i).ToList();
if (questsByRank.Count == 0)
continue;
ImGui.Text(RankNames[i - 1]);
foreach (var quest in questsByRank)
DrawQuest(quest);
}
}
else
{
foreach (var quest in quests)
DrawQuest(quest);
}
}
}
private void DrawQuest(QuestInfo questInfo)
{
var (color, icon, tooltipText) = _uiUtils.GetQuestStyle(questInfo.QuestId);
if (!_questRegistry.TryGetQuest(questInfo.QuestId, out var quest))
color = ImGuiColors.DalamudGrey;
if (_uiUtils.ChecklistItem($"{questInfo.Name} ({tooltipText})", color, icon))
_questTooltipComponent.Draw(questInfo);
_questJournalUtils.ShowContextMenu(questInfo, quest, nameof(AlliedSocietyJournalComponent));
}
}

View File

@ -30,8 +30,7 @@ internal sealed class QuestJournalComponent
private readonly UiUtils _uiUtils;
private readonly QuestTooltipComponent _questTooltipComponent;
private readonly IDalamudPluginInterface _pluginInterface;
private readonly QuestController _questController;
private readonly ICommandManager _commandManager;
private readonly QuestJournalUtils _questJournalUtils;
private readonly QuestValidator _questValidator;
private List<FilteredSection> _filteredSections = [];
@ -39,7 +38,7 @@ internal sealed class QuestJournalComponent
public QuestJournalComponent(JournalData journalData, QuestRegistry questRegistry, QuestFunctions questFunctions,
UiUtils uiUtils, QuestTooltipComponent questTooltipComponent, IDalamudPluginInterface pluginInterface,
QuestController questController, ICommandManager commandManager, QuestValidator questValidator)
QuestJournalUtils questJournalUtils, QuestValidator questValidator)
{
_journalData = journalData;
_questRegistry = questRegistry;
@ -47,8 +46,7 @@ internal sealed class QuestJournalComponent
_uiUtils = uiUtils;
_questTooltipComponent = questTooltipComponent;
_pluginInterface = pluginInterface;
_questController = questController;
_commandManager = commandManager;
_questJournalUtils = questJournalUtils;
_questValidator = questValidator;
}
@ -184,23 +182,7 @@ internal sealed class QuestJournalComponent
if (ImGui.IsItemHovered())
_questTooltipComponent.Draw(questInfo);
if (ImGui.BeginPopupContextItem($"##QuestPopup{questInfo.QuestId}", ImGuiPopupFlags.MouseButtonRight))
{
if (ImGui.MenuItem("Start as next quest", _questFunctions.IsReadyToAcceptQuest(questInfo.QuestId)))
{
_questController.SetNextQuest(quest);
_questController.Start("SeasonalEventSelection");
}
bool openInQuestMap = _commandManager.Commands.TryGetValue("/questinfo", out var commandInfo);
if (ImGui.MenuItem("View in Quest Map", questInfo.QuestId is QuestId && openInQuestMap))
{
_commandManager.DispatchCommand("/questinfo", questInfo.QuestId.ToString() ?? string.Empty,
commandInfo!);
}
ImGui.EndPopup();
}
_questJournalUtils.ShowContextMenu(questInfo, quest, nameof(QuestJournalComponent));
ImGui.TableNextColumn();
float spacing;

View File

@ -0,0 +1,44 @@
using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin.Services;
using ImGuiNET;
using Questionable.Controller;
using Questionable.Functions;
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Windows.JournalComponents;
internal sealed class QuestJournalUtils
{
private readonly QuestController _questController;
private readonly QuestFunctions _questFunctions;
private readonly ICommandManager _commandManager;
public QuestJournalUtils(QuestController questController, QuestFunctions questFunctions,
ICommandManager commandManager)
{
_questController = questController;
_questFunctions = questFunctions;
_commandManager = commandManager;
}
public void ShowContextMenu(IQuestInfo questInfo, Quest? quest, string label)
{
using var popup = ImRaii.ContextPopup($"##QuestPopup{questInfo.QuestId}", ImGuiPopupFlags.MouseButtonRight);
if (!popup)
return;
if (ImGui.MenuItem("Start as next quest", _questFunctions.IsReadyToAcceptQuest(questInfo.QuestId)))
{
_questController.SetNextQuest(quest);
_questController.Start(label);
}
bool openInQuestMap = _commandManager.Commands.TryGetValue("/questinfo", out var commandInfo);
if (ImGui.MenuItem("View in Quest Map", questInfo.QuestId is QuestId && openInQuestMap))
{
_commandManager.DispatchCommand("/questinfo", questInfo.QuestId.ToString() ?? string.Empty,
commandInfo!);
}
}
}

View File

@ -11,18 +11,21 @@ namespace Questionable.Windows;
internal sealed class JournalProgressWindow : LWindow, IDisposable
{
private readonly QuestJournalComponent _questJournalComponent;
private readonly AlliedSocietyJournalComponent _alliedSocietyJournalComponent;
private readonly GatheringJournalComponent _gatheringJournalComponent;
private readonly QuestRegistry _questRegistry;
private readonly IClientState _clientState;
public JournalProgressWindow(
QuestJournalComponent questJournalComponent,
AlliedSocietyJournalComponent alliedSocietyJournalComponent,
GatheringJournalComponent gatheringJournalComponent,
QuestRegistry questRegistry,
IClientState clientState)
: base("Journal Progress###QuestionableJournalProgress")
{
_questJournalComponent = questJournalComponent;
_alliedSocietyJournalComponent = alliedSocietyJournalComponent;
_gatheringJournalComponent = gatheringJournalComponent;
_questRegistry = questRegistry;
_clientState = clientState;
@ -60,6 +63,7 @@ internal sealed class JournalProgressWindow : LWindow, IDisposable
return;
_questJournalComponent.DrawQuests();
_alliedSocietyJournalComponent.DrawAlliedSocietyQuests();
_gatheringJournalComponent.DrawGatheringItems();
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text.RegularExpressions;
@ -167,8 +168,29 @@ internal sealed partial class ActiveQuestComponent
ImGui.SameLine();
ImGui.TextColored(ImGuiColors.DalamudYellow, SeIconChar.Hyadelyn.ToIconString());
if (ImGui.IsItemHovered())
ImGui.SetTooltip(
"This quest sequence starts with a teleport to an Aetheryte.\nCertain priority quest (e.g. class quests) may be started/completed by the plugin prior to continuing with this quest.");
{
using var tooltip = ImRaii.Tooltip();
if (tooltip)
{
ImGui.Text("This quest sequence starts with a teleport to an Aetheryte.");
ImGui.Text(
"Certain priority quest (e.g. class quests) may be started/completed by the plugin prior to continuing with this quest.");
ImGui.Separator();
ImGui.Text("Available priority quests:");
List<ElementId> priorityQuests = _questFunctions.GetNextPriorityQuestsThatCanBeAccepted();
if (priorityQuests.Count > 0)
{
foreach (var questId in priorityQuests)
{
if (_questRegistry.TryGetQuest(questId, out var quest))
ImGui.BulletText($"{quest.Info.Name} ({questId})");
}
}
else
ImGui.BulletText("(none)");
}
}
}
}

View File

@ -24,6 +24,15 @@ internal sealed class UiUtils
{
if (_questFunctions.IsQuestAccepted(elementId))
return (ImGuiColors.DalamudYellow, FontAwesomeIcon.PersonWalkingArrowRight, "Active");
else if (elementId is QuestId questId && _questFunctions.IsDailyAlliedSocietyQuestAndAvailableToday(questId))
{
if (!_questFunctions.IsReadyToAcceptQuest(questId))
return (ImGuiColors.ParsedGreen, FontAwesomeIcon.Check, "Complete");
else if (_questFunctions.IsQuestComplete(questId))
return (ImGuiColors.ParsedBlue, FontAwesomeIcon.Running, "Available (Complete)");
else
return (ImGuiColors.DalamudYellow, FontAwesomeIcon.Running, "Available");
}
else if (_questFunctions.IsQuestAcceptedOrComplete(elementId))
return (ImGuiColors.ParsedGreen, FontAwesomeIcon.Check, "Complete");
else if (_questFunctions.IsQuestUnobtainable(elementId))