Merge pull request 'master' (#6) from master into Namazu-Dailies-v2

Reviewed-on: guffels/Questionable#6
This commit is contained in:
guffels 2025-01-27 13:10:35 +00:00
commit 6c6149a47d
39 changed files with 1307 additions and 90 deletions

View File

@ -1,5 +1,5 @@
<Project> <Project>
<PropertyGroup Condition="$(MSBuildProjectName) != 'GatheringPathRenderer'"> <PropertyGroup Condition="$(MSBuildProjectName) != 'GatheringPathRenderer'">
<Version>4.15</Version> <Version>4.16</Version>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@ -82,7 +82,7 @@ public sealed class RendererPlugin : IDalamudPlugin
get get
{ {
#if DEBUG #if DEBUG
DirectoryInfo? solutionDirectory = _pluginInterface.AssemblyLocation.Directory?.Parent?.Parent?.Parent; DirectoryInfo? solutionDirectory = _pluginInterface.AssemblyLocation.Directory?.Parent?.Parent;
if (solutionDirectory != null) if (solutionDirectory != null)
{ {
DirectoryInfo pathProjectDirectory = DirectoryInfo pathProjectDirectory =
@ -91,7 +91,7 @@ public sealed class RendererPlugin : IDalamudPlugin
return pathProjectDirectory; return pathProjectDirectory;
} }
throw new Exception("Unable to resolve project path"); throw new Exception($"Unable to resolve project path ({_pluginInterface.AssemblyLocation.Directory})");
#else #else
var allPluginsDirectory = _pluginInterface.ConfigFile.Directory ?? throw new Exception("Unknown directory for plugin configs"); var allPluginsDirectory = _pluginInterface.ConfigFile.Directory ?? throw new Exception("Unknown directory for plugin configs");
return allPluginsDirectory return allPluginsDirectory

View File

@ -329,9 +329,9 @@
}, },
{ {
"Position": { "Position": {
"X": -0.75614685, "X": 3.8795898,
"Y": 38.80212, "Y": 38.80212,
"Z": -11.007636 "Z": 0.40251642
}, },
"TerritoryId": 146, "TerritoryId": 146,
"InteractionType": "WalkTo", "InteractionType": "WalkTo",
@ -359,7 +359,8 @@
null, null,
128 128
], ],
"Fly": true "Fly": true,
"DisableNavmesh": true
}, },
{ {
"DataId": 2000078, "DataId": 2000078,

View File

@ -112,9 +112,18 @@
"SkipConditions": { "SkipConditions": {
"AetheryteShortcutIf": { "AetheryteShortcutIf": {
"InSameTerritory": true "InSameTerritory": true
},
"StepIf": {
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
64
]
} }
}, }
"Comment": "TODO Verify enemy id"
}, },
{ {
"DataId": 2002309, "DataId": 2002309,

View File

@ -21,16 +21,30 @@
"Sequence": 1, "Sequence": 1,
"Steps": [ "Steps": [
{ {
"DataId": 1001426,
"Position": { "Position": {
"X": 123.33862, "X": 2.7922537,
"Y": 30.999996, "Y": 8.206551,
"Z": -384.9394 "Z": -274.32318
}, },
"TerritoryId": 141, "TerritoryId": 141,
"InteractionType": "Interact", "InteractionType": "WalkTo",
"Comment": "'Forging the Spirit'", "AetheryteShortcut": "Central Thanalan - Black Brush Station",
"AetheryteShortcut": "Central Thanalan - Black Brush Station" "SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
},
"StepIf": {
"NearPosition": {
"Position": {
"X": 123.33862,
"Y": 30.999996,
"Z": -384.9394
},
"TerritoryId": 141,
"MaximumDistance": 30
}
}
}
}, },
{ {
"DataId": 1001426, "DataId": 1001426,
@ -40,8 +54,8 @@
"Z": -384.9394 "Z": -384.9394
}, },
"TerritoryId": 141, "TerritoryId": 141,
"InteractionType": "Interact", "InteractionType": "AcceptQuest",
"Comment": "Quest Turn-In 'Forging the Spirit'" "PickUpQuestId": 638
}, },
{ {
"DataId": 1001425, "DataId": 1001425,

View File

@ -67,7 +67,7 @@
"TerritoryId": 148, "TerritoryId": 148,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 6, "ContentFinderConditionId": 6,
"AutoDutyEnabled": true "AutoDutyEnabled": false
} }
] ]
}, },

View File

@ -86,7 +86,7 @@
"TerritoryId": 137, "TerritoryId": 137,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 8, "ContentFinderConditionId": 8,
"AutoDutyEnabled": true "AutoDutyEnabled": false
} }
] ]
}, },

View File

@ -51,6 +51,7 @@
}, },
"TerritoryId": 156, "TerritoryId": 156,
"InteractionType": "Combat", "InteractionType": "Combat",
"DelaySecondsAtStart": 2,
"EnemySpawnType": "AfterItemUse", "EnemySpawnType": "AfterItemUse",
"ItemId": 2000766, "ItemId": 2000766,
"KillEnemyDataIds": [ "KillEnemyDataIds": [
@ -180,6 +181,7 @@
}, },
"TerritoryId": 156, "TerritoryId": 156,
"InteractionType": "Combat", "InteractionType": "Combat",
"DelaySecondsAtStart": 2,
"EnemySpawnType": "AfterItemUse", "EnemySpawnType": "AfterItemUse",
"ItemId": 2000766, "ItemId": 2000766,
"KillEnemyDataIds": [ "KillEnemyDataIds": [
@ -238,7 +240,8 @@
}, },
"TerritoryId": 156, "TerritoryId": 156,
"InteractionType": "UseItem", "InteractionType": "UseItem",
"ItemId": 2000766 "ItemId": 2000766,
"DelaySecondsAtStart": 2
} }
] ]
}, },

View File

@ -35,13 +35,163 @@
"Z": -225.17743 "Z": -225.17743
}, },
"TerritoryId": 147, "TerritoryId": 147,
"InteractionType": "Interact" "InteractionType": "Interact",
"AetheryteShortcut": "Northern Thanalan - Ceruleum Processing Plant",
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
} }
] ]
}, },
{ {
"Sequence": 2, "Sequence": 2,
"$": "This doesn't include the DRK/MCH/AST coffers that exist at level 50, but you cannot obtain them until HW",
"Steps": [ "Steps": [
{
"TerritoryId": 147,
"InteractionType": "UseItem",
"ItemId": 31337,
"$": "Lv49 Weapon Coffer",
"SkipConditions": {
"StepIf": {
"Item": {
"NotInInventory": true
}
}
}
},
{
"TerritoryId": 147,
"InteractionType": "UseItem",
"ItemId": 20642,
"$": "Lv50 PLD Coffer",
"SkipConditions": {
"StepIf": {
"Item": {
"NotInInventory": true
}
}
}
},
{
"TerritoryId": 147,
"InteractionType": "UseItem",
"ItemId": 20643,
"$": "Lv50 MNK Coffer",
"SkipConditions": {
"StepIf": {
"Item": {
"NotInInventory": true
}
}
}
},
{
"TerritoryId": 147,
"InteractionType": "UseItem",
"ItemId": 20644,
"$": "Lv50 WAR Coffer",
"SkipConditions": {
"StepIf": {
"Item": {
"NotInInventory": true
}
}
}
},
{
"TerritoryId": 147,
"InteractionType": "UseItem",
"ItemId": 20645,
"$": "Lv50 DRG Coffer",
"SkipConditions": {
"StepIf": {
"Item": {
"NotInInventory": true
}
}
}
},
{
"TerritoryId": 147,
"InteractionType": "UseItem",
"ItemId": 20646,
"$": "Lv50 BRD Coffer",
"SkipConditions": {
"StepIf": {
"Item": {
"NotInInventory": true
}
}
}
},
{
"TerritoryId": 147,
"InteractionType": "UseItem",
"ItemId": 20647,
"$": "Lv50 NIN Coffer",
"SkipConditions": {
"StepIf": {
"Item": {
"NotInInventory": true
}
}
}
},
{
"TerritoryId": 147,
"InteractionType": "UseItem",
"ItemId": 20648,
"$": "Lv50 WHM Coffer",
"SkipConditions": {
"StepIf": {
"Item": {
"NotInInventory": true
}
}
}
},
{
"TerritoryId": 147,
"InteractionType": "UseItem",
"ItemId": 20649,
"$": "Lv50 BLM Coffer",
"SkipConditions": {
"StepIf": {
"Item": {
"NotInInventory": true
}
}
}
},
{
"TerritoryId": 147,
"InteractionType": "UseItem",
"ItemId": 20650,
"$": "Lv50 SMN Coffer",
"SkipConditions": {
"StepIf": {
"Item": {
"NotInInventory": true
}
}
}
},
{
"TerritoryId": 147,
"InteractionType": "UseItem",
"ItemId": 20651,
"$": "Lv50 SCH Coffer",
"SkipConditions": {
"StepIf": {
"Item": {
"NotInInventory": true
}
}
}
},
{ {
"TerritoryId": 147, "TerritoryId": 147,
"InteractionType": "Duty", "InteractionType": "Duty",

View File

@ -5,6 +5,71 @@
{ {
"Sequence": 0, "Sequence": 0,
"Steps": [ "Steps": [
{
"TerritoryId": 132,
"InteractionType": "UseItem",
"ItemId": 30362,
"TargetTerritoryId": 140,
"SkipConditions": {
"StepIf": {
"InTerritory": [
140,
212
]
}
}
},
{
"Position": {
"X": -492.96475,
"Y": 20.999884,
"Z": -380.82272
},
"TerritoryId": 140,
"InteractionType": "WalkTo",
"$": "Avoid walking around Waking Sands table",
"SkipConditions": {
"StepIf": {
"InTerritory": [
212
]
}
}
},
{
"DataId": 2001711,
"Position": {
"X": -480.9181,
"Y": 18.00103,
"Z": -386.862
},
"TerritoryId": 140,
"InteractionType": "Interact",
"TargetTerritoryId": 212,
"SkipConditions": {
"StepIf": {
"InTerritory": [
212
]
}
}
},
{
"DataId": 2001715,
"Position": {
"X": 23.23944,
"Y": 2.090454,
"Z": -0.015319824
},
"TerritoryId": 212,
"InteractionType": "Interact",
"TargetTerritoryId": 212,
"SkipConditions": {
"StepIf": {
"ExtraCondition": "WakingSandsSolar"
}
}
},
{ {
"DataId": 1006690, "DataId": 1006690,
"Position": { "Position": {
@ -29,7 +94,14 @@
}, },
"TerritoryId": 212, "TerritoryId": 212,
"InteractionType": "Interact", "InteractionType": "Interact",
"TargetTerritoryId": 212 "TargetTerritoryId": 212,
"SkipConditions": {
"StepIf": {
"InTerritory": [
140
]
}
}
}, },
{ {
"DataId": 2001716, "DataId": 2001716,
@ -40,7 +112,14 @@
}, },
"TerritoryId": 212, "TerritoryId": 212,
"InteractionType": "Interact", "InteractionType": "Interact",
"TargetTerritoryId": 140 "TargetTerritoryId": 140,
"SkipConditions": {
"StepIf": {
"InTerritory": [
140
]
}
}
}, },
{ {
"DataId": 1006578, "DataId": 1006578,

View File

@ -0,0 +1,36 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1001426,
"Position": {
"X": 123.33862,
"Y": 30.999996,
"Z": -384.9394
},
"TerritoryId": 141,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1001426,
"Position": {
"X": 123.33862,
"Y": 30.999996,
"Z": -384.9394
},
"TerritoryId": 141,
"InteractionType": "CompleteQuest"
}
]
}
]
}

View File

@ -86,9 +86,10 @@
}, },
"TerritoryId": 614, "TerritoryId": 614,
"InteractionType": "CompleteQuest", "InteractionType": "CompleteQuest",
"Fly": true "Fly": true,
"NextQuestId": 2748
} }
] ]
} }
] ]
} }

View File

@ -131,9 +131,10 @@
} }
} }
}, },
"Fly": true "Fly": true,
"NextQuestId": 2737
} }
] ]
} }
] ]
} }

View File

@ -123,9 +123,10 @@
} }
} }
}, },
"Fly": true "Fly": true,
"NextQuestId": 2738
} }
] ]
} }
] ]
} }

View File

@ -159,9 +159,10 @@
} }
} }
}, },
"Fly": true "Fly": true,
"NextQuestId": 2739
} }
] ]
} }
] ]
} }

View File

@ -142,9 +142,10 @@
} }
} }
}, },
"Fly": true "Fly": true,
"NextQuestId": 2740
} }
] ]
} }
] ]
} }

View File

@ -24,7 +24,7 @@
}, },
"TerritoryId": 614, "TerritoryId": 614,
"InteractionType": "AcceptQuest", "InteractionType": "AcceptQuest",
"StopDistance": 0.1 "StopDistance": 0.25
} }
] ]
}, },
@ -67,7 +67,7 @@
}, },
"TerritoryId": 614, "TerritoryId": 614,
"InteractionType": "Interact", "InteractionType": "Interact",
"StopDistance": 0.1 "StopDistance": 0.25
} }
] ]
}, },
@ -84,9 +84,10 @@
"TerritoryId": 614, "TerritoryId": 614,
"InteractionType": "CompleteQuest", "InteractionType": "CompleteQuest",
"Fly": true, "Fly": true,
"AetheryteShortcut": "Yanxia - Namai" "AetheryteShortcut": "Yanxia - Namai",
"NextQuestId": 2740
} }
] ]
} }
] ]
} }

View File

@ -0,0 +1,143 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1023236,
"Position": {
"X": -300.06866,
"Y": 16.806112,
"Z": 539.45215
},
"TerritoryId": 614,
"InteractionType": "AcceptQuest",
"Fly": true
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1023237,
"Position": {
"X": -233.72241,
"Y": 17.628202,
"Z": 485.3131
},
"TerritoryId": 614,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": -463.34363,
"Y": 1.3011811,
"Z": 578.3476
},
"TerritoryId": 614,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 1023238,
"Position": {
"X": -464.49988,
"Y": 1.3011812,
"Z": 577.32495
},
"TerritoryId": 614,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 3,
"Steps": [
{
"Position": {
"X": -487.5986,
"Y": -0.5999999,
"Z": 578.5466
},
"TerritoryId": 614,
"InteractionType": "Dive",
"DisableNavmesh": true
},
{
"DataId": 2008799,
"Position": {
"X": -549.7063,
"Y": -109.51398,
"Z": 569.32935
},
"TerritoryId": 614,
"InteractionType": "Interact",
"Fly": true,
"Mount": true
}
]
},
{
"Sequence": 4,
"Steps": [
{
"Position": {
"X": -487.5986,
"Y": -0.5999999,
"Z": 578.5466
},
"TerritoryId": 614,
"InteractionType": "WalkTo",
"DisableNavmesh": true,
"RestartNavigationIfCancelled": false
},
{
"Position": {
"X": -463.34363,
"Y": 1.3011811,
"Z": 578.3476
},
"TerritoryId": 614,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 1023238,
"Position": {
"X": -464.49988,
"Y": 1.3011812,
"Z": 577.32495
},
"TerritoryId": 614,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1023237,
"Position": {
"X": -233.72241,
"Y": 17.628202,
"Z": 485.3131
},
"TerritoryId": 614,
"InteractionType": "CompleteQuest",
"Fly": true,
"NextQuestId": 2749
}
]
}
]
}

View File

@ -37,6 +37,21 @@
{ {
"Sequence": 2, "Sequence": 2,
"Steps": [ "Steps": [
{
"Position": {
"X": -239.56377,
"Y": 49.354053,
"Z": 284.94565
},
"TerritoryId": 614,
"InteractionType": "WalkTo",
"Fly": true,
"SkipConditions": {
"StepIf": {
"Flying": "Locked"
}
}
},
{ {
"DataId": 1023240, "DataId": 1023240,
"Position": { "Position": {
@ -59,6 +74,7 @@
"Y": 39.150906, "Y": 39.150906,
"Z": 206.95801 "Z": 206.95801
}, },
"StopDistance": 0.5,
"TerritoryId": 614, "TerritoryId": 614,
"InteractionType": "Combat", "InteractionType": "Combat",
"Fly": true, "Fly": true,
@ -113,9 +129,10 @@
}, },
"TerritoryId": 614, "TerritoryId": 614,
"InteractionType": "CompleteQuest", "InteractionType": "CompleteQuest",
"Fly": true "Fly": true,
"NextQuestId": 2750
} }
] ]
} }
] ]
} }

View File

@ -98,9 +98,10 @@
}, },
"TerritoryId": 614, "TerritoryId": 614,
"InteractionType": "CompleteQuest", "InteractionType": "CompleteQuest",
"Fly": true "Fly": true,
"NextQuestId": 2751
} }
] ]
} }
] ]
} }

View File

@ -112,9 +112,10 @@
}, },
"TerritoryId": 614, "TerritoryId": 614,
"InteractionType": "CompleteQuest", "InteractionType": "CompleteQuest",
"Fly": true "Fly": true,
"NextQuestId": 2747
} }
] ]
} }
] ]
} }

View File

@ -0,0 +1,161 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1050871,
"Position": {
"X": -51.895935,
"Y": -17.97287,
"Z": 182.7268
},
"TerritoryId": 1185,
"InteractionType": "AcceptQuest",
"AetheryteShortcut": "Tuliyollal",
"AethernetShortcut": [
"[Tuliyollal] Aetheryte Plaza",
"[Tuliyollal] The For'ard Cabins"
],
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1001657,
"Position": {
"X": 94.80432,
"Y": 7.9804688,
"Z": -34.042908
},
"TerritoryId": 131,
"InteractionType": "Interact",
"AetheryteShortcut": "Ul'dah",
"AethernetShortcut": [
"[Ul'dah] Aetheryte Plaza",
"[Ul'dah] Sapphire Avenue Exchange"
],
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
32
]
},
{
"DataId": 1006440,
"Position": {
"X": 140.3982,
"Y": 4,
"Z": -54.154297
},
"TerritoryId": 131,
"InteractionType": "Interact",
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
64
]
},
{
"DataId": 1051655,
"Position": {
"X": 137.74304,
"Y": 4,
"Z": 5.9662476
},
"TerritoryId": 131,
"InteractionType": "Interact",
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
128
]
}
]
},
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": 146.12386,
"Y": 4,
"Z": -23.562449
},
"StopDistance": 0.5,
"TerritoryId": 131,
"InteractionType": "Emote",
"Emote": "angry"
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 1051656,
"Position": {
"X": 56.443115,
"Y": 10,
"Z": 5.935669
},
"TerritoryId": 131,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 2012114,
"Position": {
"X": 0,
"Y": 1.15,
"Z": 10.23451
},
"TerritoryId": 1255,
"InteractionType": "Interact",
"TargetTerritoryId": 131,
"SkipConditions": {
"StepIf": {
"InTerritory": [
131
]
}
}
},
{
"DataId": 1051656,
"Position": {
"X": 56.443115,
"Y": 10,
"Z": 5.935669
},
"StopDistance": 7,
"TerritoryId": 131,
"InteractionType": "CompleteQuest",
"NextQuestId": 5189
}
]
}
]
}

View File

@ -0,0 +1,129 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1051656,
"Position": {
"X": 56.443115,
"Y": 10,
"Z": 5.935669
},
"StopDistance": 7,
"TerritoryId": 131,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 2014419,
"Position": {
"X": -158.86176,
"Y": 7.4921875,
"Z": 493.88867
},
"TerritoryId": 146,
"InteractionType": "Interact",
"AetheryteShortcut": "Southern Thanalan - Forgotten Springs",
"Fly": true
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 1051661,
"Position": {
"X": 1.7852783,
"Y": 19.026453,
"Z": 581.62805
},
"StopDistance": 5,
"TerritoryId": 146,
"InteractionType": "Interact",
"DialogueChoices": [
{
"Type": "List",
"Prompt": "TEXT_KINGBZ002_05189_Q1_000_000",
"Answer": "TEXT_KINGBZ002_05189_A1_000_001"
}
]
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 1051663,
"Position": {
"X": 51.68225,
"Y": 0.7631253,
"Z": 711.57385
},
"TerritoryId": 146,
"InteractionType": "Combat",
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [
18178
],
"Fly": true
}
]
},
{
"Sequence": 4,
"Steps": [
{
"DataId": 1051663,
"Position": {
"X": 51.68225,
"Y": 0.7631253,
"Z": 711.57385
},
"TerritoryId": 146,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 5,
"Steps": [
{
"DataId": 1051668,
"Position": {
"X": 170.42798,
"Y": 15.943722,
"Z": 897.94763
},
"TerritoryId": 146,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1051668,
"Position": {
"X": 170.42798,
"Y": 15.943722,
"Z": 897.94763
},
"TerritoryId": 146,
"InteractionType": "CompleteQuest",
"NextQuestId": 5190
}
]
}
]
}

View File

@ -0,0 +1,175 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1051668,
"Position": {
"X": 170.42798,
"Y": 15.943722,
"Z": 897.94763
},
"TerritoryId": 146,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1050871,
"Position": {
"X": -51.895935,
"Y": -17.97287,
"Z": 182.7268
},
"TerritoryId": 1185,
"InteractionType": "Interact",
"AetheryteShortcut": "Tuliyollal",
"AethernetShortcut": [
"[Tuliyollal] Aetheryte Plaza",
"[Tuliyollal] The For'ard Cabins"
]
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 1051670,
"Position": {
"X": -15.976257,
"Y": -19.928413,
"Z": 224.90259
},
"TerritoryId": 1185,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 1051675,
"Position": {
"X": 358.23608,
"Y": 5.957184,
"Z": 428.36658
},
"StopDistance": 1,
"TerritoryId": 1190,
"InteractionType": "Interact",
"AetheryteShortcut": "Shaaloani - Hhusatahwi",
"Fly": true
}
]
},
{
"Sequence": 4,
"Steps": [
{
"Position": {
"X": 363.81656,
"Y": 5.9295864,
"Z": 435.17932
},
"TerritoryId": 1190,
"InteractionType": "WalkTo"
},
{
"DataId": 1051677,
"Position": {
"X": 371.4198,
"Y": 5.95728,
"Z": 425.4978
},
"TerritoryId": 1190,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 5,
"Steps": [
{
"DataId": 1051677,
"Position": {
"X": 371.4198,
"Y": 5.95728,
"Z": 425.4978
},
"TerritoryId": 1190,
"InteractionType": "Emote",
"Emote": "unbound"
}
]
},
{
"Sequence": 6,
"Steps": [
{
"DataId": 1051682,
"Position": {
"X": 387.5028,
"Y": -0.60167974,
"Z": 426.99304
},
"TerritoryId": 1190,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 7,
"Steps": [
{
"Position": {
"X": 425.24307,
"Y": 0.7699772,
"Z": 473.79095
},
"TerritoryId": 1190,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 1051684,
"Position": {
"X": 426.04712,
"Y": 0.7461932,
"Z": 472.3125
},
"TerritoryId": 1190,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1050871,
"Position": {
"X": -51.895935,
"Y": -17.97287,
"Z": 182.7268
},
"TerritoryId": 1185,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "Tuliyollal",
"AethernetShortcut": [
"[Tuliyollal] Aetheryte Plaza",
"[Tuliyollal] The For'ard Cabins"
],
"NextQuestId": 5191
}
]
}
]
}

View File

@ -0,0 +1,182 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1050871,
"Position": {
"X": -51.895935,
"Y": -17.97287,
"Z": 182.7268
},
"TerritoryId": 1185,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1051689,
"Position": {
"X": 273.33484,
"Y": 15.999998,
"Z": 740.6576
},
"TerritoryId": 1190,
"InteractionType": "SinglePlayerDuty",
"AethernetShortcut": [
"[Tuliyollal] The For'ard Cabins",
"[Tuliyollal] Xak Tural Skygate (Shaaloani)"
]
}
]
},
{
"Sequence": 2
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 1051691,
"Position": {
"X": 273.85364,
"Y": 15.999996,
"Z": 738.2771
},
"TerritoryId": 1190,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 4,
"Steps": [
{
"DataId": 1050871,
"Position": {
"X": -51.895935,
"Y": -17.97287,
"Z": 182.7268
},
"TerritoryId": 1185,
"InteractionType": "Interact",
"AetheryteShortcut": "Tuliyollal",
"AethernetShortcut": [
"[Tuliyollal] Aetheryte Plaza",
"[Tuliyollal] The For'ard Cabins"
]
}
]
},
{
"Sequence": 5,
"Steps": [
{
"DataId": 1051672,
"Position": {
"X": -14.816589,
"Y": -19.881973,
"Z": 223.3158
},
"TerritoryId": 1185,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 6,
"Steps": [
{
"DataId": 1051673,
"Position": {
"X": -15.243774,
"Y": -19.762682,
"Z": 221.72876
},
"StopDistance": 5,
"TerritoryId": 1185,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 7,
"Steps": [
{
"DataId": 1051670,
"Position": {
"X": -15.976257,
"Y": -19.928413,
"Z": 224.90259
},
"StopDistance": 5,
"TerritoryId": 1185,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 8,
"Steps": [
{
"DataId": 1051671,
"Position": {
"X": -17.95996,
"Y": -19.784014,
"Z": 224.17017
},
"StopDistance": 5,
"TerritoryId": 1185,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 9,
"Steps": [
{
"DataId": 1051674,
"Position": {
"X": -16.617126,
"Y": -19.752277,
"Z": 222.64429
},
"TerritoryId": 1185,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"Position": {
"X": -44.643284,
"Y": -17.972864,
"Z": 203.87883
},
"TerritoryId": 1185,
"InteractionType": "WalkTo"
},
{
"DataId": 1046521,
"Position": {
"X": -46.616333,
"Y": -17.97287,
"Z": 180.3158
},
"StopDistance": 5,
"TerritoryId": 1185,
"InteractionType": "CompleteQuest",
"DisableNavmesh": true
}
]
}
]
}

View File

@ -47,6 +47,10 @@
}, },
"Comment": { "Comment": {
"type": "string" "type": "string"
},
"$": {
"type": "string",
"description": "Dev Comment (not visible in-game)"
} }
}, },
"required": [ "required": [
@ -292,6 +296,7 @@
"type": "string", "type": "string",
"enum": [ "enum": [
"WakingSandsMainArea", "WakingSandsMainArea",
"WakingSandsSolar",
"RisingStonesSolar", "RisingStonesSolar",
"RoguesGuild", "RoguesGuild",
"DockStorehouse" "DockStorehouse"
@ -698,9 +703,7 @@
"const": "UseItem" "const": "UseItem"
}, },
"ItemId": { "ItemId": {
"not": { "minimum": 2000000
"const": 30362
}
} }
} }
}, },
@ -863,7 +866,9 @@
"mogdance", "mogdance",
"salute", "salute",
"laugh", "laugh",
"greeting" "greeting",
"angry",
"unbound"
] ]
} }
} }

View File

@ -7,6 +7,7 @@ public sealed class EmoteConverter() : EnumConverter<EEmote>(Values)
{ {
private static readonly Dictionary<EEmote, string> Values = new() private static readonly Dictionary<EEmote, string> Values = new()
{ {
{ EEmote.Angry, "angry" },
{ EEmote.Bow, "bow" }, { EEmote.Bow, "bow" },
{ EEmote.Cheer, "cheer" }, { EEmote.Cheer, "cheer" },
{ EEmote.Clap, "clap" }, { EEmote.Clap, "clap" },
@ -45,5 +46,6 @@ public sealed class EmoteConverter() : EnumConverter<EEmote>(Values)
{ EEmote.Box, "box" }, { EEmote.Box, "box" },
{ EEmote.Greeting, "greeting" }, { EEmote.Greeting, "greeting" },
{ EEmote.Uchiwasshoi, "uchiwasshoi" }, { EEmote.Uchiwasshoi, "uchiwasshoi" },
{ EEmote.Unbound, "unbound" },
}; };
} }

View File

@ -8,6 +8,7 @@ public sealed class SkipConditionConverter() : EnumConverter<EExtraSkipCondition
private static readonly Dictionary<EExtraSkipCondition, string> Values = new() private static readonly Dictionary<EExtraSkipCondition, string> Values = new()
{ {
{ EExtraSkipCondition.WakingSandsMainArea, "WakingSandsMainArea" }, { EExtraSkipCondition.WakingSandsMainArea, "WakingSandsMainArea" },
{ EExtraSkipCondition.WakingSandsSolar, "WakingSandsSolar" },
{ EExtraSkipCondition.RisingStonesSolar, "RisingStonesSolar"}, { EExtraSkipCondition.RisingStonesSolar, "RisingStonesSolar"},
{ EExtraSkipCondition.RoguesGuild, "RoguesGuild"}, { EExtraSkipCondition.RoguesGuild, "RoguesGuild"},
{ EExtraSkipCondition.DockStorehouse, "DockStorehouse"}, { EExtraSkipCondition.DockStorehouse, "DockStorehouse"},

View File

@ -8,6 +8,7 @@ public enum EEmote
{ {
None = 0, None = 0,
Angry = 2,
Bow = 5, Bow = 5,
Cheer = 6, Cheer = 6,
Clap = 7, Clap = 7,
@ -45,6 +46,7 @@ public enum EEmote
Respect = 140, Respect = 140,
Box = 166, Box = 166,
Greeting = 172, Greeting = 172,
Uchiwasshoi = 278 Uchiwasshoi = 278,
Unbound = 282,
} }

View File

@ -8,6 +8,7 @@ public enum EExtraSkipCondition
{ {
None, None,
WakingSandsMainArea, WakingSandsMainArea,
WakingSandsSolar,
RisingStonesSolar, RisingStonesSolar,
/// <summary> /// <summary>

View File

@ -3,6 +3,7 @@ using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Component.GUI; using FFXIVClientStructs.FFXIV.Component.GUI;
using LLib.GameUI;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Questionable.Controller.GameUi; namespace Questionable.Controller.GameUi;
@ -11,17 +12,45 @@ internal sealed class HelpUiController : IDisposable
{ {
private readonly QuestController _questController; private readonly QuestController _questController;
private readonly IAddonLifecycle _addonLifecycle; private readonly IAddonLifecycle _addonLifecycle;
private readonly IGameGui _gameGui;
private readonly ILogger<HelpUiController> _logger; private readonly ILogger<HelpUiController> _logger;
public HelpUiController(QuestController questController, IAddonLifecycle addonLifecycle, ILogger<HelpUiController> logger) public HelpUiController(
QuestController questController,
IAddonLifecycle addonLifecycle,
IGameGui gameGui,
ILogger<HelpUiController> logger)
{ {
_questController = questController; _questController = questController;
_addonLifecycle = addonLifecycle; _addonLifecycle = addonLifecycle;
_gameGui = gameGui;
_logger = logger; _logger = logger;
_questController.AutomationTypeChanged += CloseHelpWindowsWhenStartingQuests;
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup); _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup);
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "ContentsTutorial", ContentsTutorialPostSetup); _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "ContentsTutorial", ContentsTutorialPostSetup);
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "MultipleHelpWindow", MultipleHelpWindowPostSetup); _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "MultipleHelpWindow", MultipleHelpWindowPostSetup);
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "JobHudNotice", JobHudNoticePostSetup);
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "Guide", GuidePostSetup);
}
private unsafe void CloseHelpWindowsWhenStartingQuests(object sender, QuestController.EAutomationType e)
{
if (e is QuestController.EAutomationType.Manual)
return;
if (_gameGui.TryGetAddonByName("Guide", out AtkUnitBase* addonGuide))
{
_logger.LogInformation("Guide window is open");
GuidePostSetup(addonGuide);
}
if (_gameGui.TryGetAddonByName("JobHudNotice", out AtkUnitBase* addonJobHudNotice))
{
_logger.LogInformation("JobHudNotice window is open");
JobHudNoticePostSetup(addonJobHudNotice);
}
} }
private unsafe void UnendingCodexPostSetup(AddonEvent type, AddonArgs args) private unsafe void UnendingCodexPostSetup(AddonEvent type, AddonArgs args)
@ -36,7 +65,7 @@ internal sealed class HelpUiController : IDisposable
private unsafe void ContentsTutorialPostSetup(AddonEvent type, AddonArgs args) private unsafe void ContentsTutorialPostSetup(AddonEvent type, AddonArgs args)
{ {
if (_questController.StartedQuest?.Quest.Id.Value == 245) if (_questController.StartedQuest?.Quest.Id.Value is 245 or 3872)
{ {
_logger.LogInformation("Closing ContentsTutorial"); _logger.LogInformation("Closing ContentsTutorial");
AtkUnitBase* addon = (AtkUnitBase*)args.Addon; AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
@ -58,10 +87,38 @@ internal sealed class HelpUiController : IDisposable
} }
} }
private unsafe void JobHudNoticePostSetup(AddonEvent type, AddonArgs args)
{
if (_questController.IsRunning || _questController.AutomationType != QuestController.EAutomationType.Manual)
JobHudNoticePostSetup((AtkUnitBase*)args.Addon);
}
private unsafe void JobHudNoticePostSetup(AtkUnitBase* addon)
{
_logger.LogInformation("Clicking the JobHudNotice window to open the relevant Guide page");
addon->FireCallbackInt(0);
}
private unsafe void GuidePostSetup(AddonEvent type, AddonArgs args)
{
if (_questController.IsRunning || _questController.AutomationType != QuestController.EAutomationType.Manual)
GuidePostSetup((AtkUnitBase*)args.Addon);
}
private unsafe void GuidePostSetup(AtkUnitBase* addon)
{
_logger.LogInformation("Closing Guide window");
addon->FireCallbackInt(-1);
}
public void Dispose() public void Dispose()
{ {
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "Guide", GuidePostSetup);
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "JobHudNotice", JobHudNoticePostSetup);
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "MultipleHelpWindow", MultipleHelpWindowPostSetup); _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "MultipleHelpWindow", MultipleHelpWindowPostSetup);
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "ContentsTutorial", ContentsTutorialPostSetup); _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "ContentsTutorial", ContentsTutorialPostSetup);
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup); _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup);
_questController.AutomationTypeChanged -= CloseHelpWindowsWhenStartingQuests;
} }
} }

View File

@ -94,7 +94,6 @@ internal sealed unsafe class InterruptHandler : IDisposable
[FieldOffset(6)] public ushort Value; [FieldOffset(6)] public ushort Value;
public byte AttackType => (byte)(Param1 & 0xF); public byte AttackType => (byte)(Param1 & 0xF);
public uint Damage => Mult == 0 ? Value : Value + ((uint)ushort.MaxValue + 1) * Mult;
public override string ToString() public override string ToString()
{ {

View File

@ -28,6 +28,7 @@ internal abstract class MiniTaskController<T> : IDisposable
private readonly ILogger<T> _logger; private readonly ILogger<T> _logger;
private readonly string _actionCanceledText; private readonly string _actionCanceledText;
private readonly string _cantExecuteDueToStatusText;
protected MiniTaskController(IChatGui chatGui, ICondition condition, IServiceProvider serviceProvider, protected MiniTaskController(IChatGui chatGui, ICondition condition, IServiceProvider serviceProvider,
InterruptHandler interruptHandler, IDataManager dataManager, ILogger<T> logger) InterruptHandler interruptHandler, IDataManager dataManager, ILogger<T> logger)
@ -39,6 +40,7 @@ internal abstract class MiniTaskController<T> : IDisposable
_condition = condition; _condition = condition;
_actionCanceledText = dataManager.GetString<LogMessage>(1314, x => x.Text)!; _actionCanceledText = dataManager.GetString<LogMessage>(1314, x => x.Text)!;
_cantExecuteDueToStatusText = dataManager.GetString<LogMessage>(7728, x => x.Text)!;
_interruptHandler.Interrupted += HandleInterruption; _interruptHandler.Interrupted += HandleInterruption;
} }
@ -68,7 +70,7 @@ internal abstract class MiniTaskController<T> : IDisposable
{ {
_logger.LogError(e, "Failed to start task {TaskName}", upcomingTask.ToString()); _logger.LogError(e, "Failed to start task {TaskName}", upcomingTask.ToString());
_chatGui.PrintError( _chatGui.PrintError(
$"[Questionable] Failed to start task '{upcomingTask}', please check /xllog for details."); $"Failed to start task '{upcomingTask}', please check /xllog for details.", CommandHandler.MessageTag, CommandHandler.TagColor);
Stop("Task failed to start"); Stop("Task failed to start");
return; return;
} }
@ -93,7 +95,7 @@ internal abstract class MiniTaskController<T> : IDisposable
_logger.LogError(e, "Failed to update task {TaskName}", _logger.LogError(e, "Failed to update task {TaskName}",
_taskQueue.CurrentTaskExecutor.CurrentTask.ToString()); _taskQueue.CurrentTaskExecutor.CurrentTask.ToString());
_chatGui.PrintError( _chatGui.PrintError(
$"[Questionable] Failed to update task '{_taskQueue.CurrentTaskExecutor.CurrentTask}', please check /xllog for details."); $"Failed to update task '{_taskQueue.CurrentTaskExecutor.CurrentTask}', please check /xllog for details.", CommandHandler.MessageTag, CommandHandler.TagColor);
Stop("Task failed to update"); Stop("Task failed to update");
return; return;
} }
@ -183,6 +185,19 @@ internal abstract class MiniTaskController<T> : IDisposable
else else
_taskQueue.InterruptWith([new WaitAtEnd.WaitDelay()]); _taskQueue.InterruptWith([new WaitAtEnd.WaitDelay()]);
LogTasksAfterInterruption();
}
private void InterruptWithoutCombat()
{
_logger.LogWarning("Interrupted, attempting to redo previous tasks (not in combat)");
_taskQueue.InterruptWith([new WaitAtEnd.WaitDelay()]);
LogTasksAfterInterruption();
}
private void LogTasksAfterInterruption()
{
_logger.LogInformation("Remaining tasks after interruption:"); _logger.LogInformation("Remaining tasks after interruption:");
foreach (ITask task in _taskQueue.RemainingTasks) foreach (ITask task in _taskQueue.RemainingTasks)
_logger.LogInformation("- {TaskName}", task); _logger.LogInformation("- {TaskName}", task);
@ -204,6 +219,8 @@ internal abstract class MiniTaskController<T> : IDisposable
!_condition[ConditionFlag.InFlight] && !_condition[ConditionFlag.InFlight] &&
_taskQueue.CurrentTaskExecutor?.ShouldInterruptOnDamage() == true) _taskQueue.CurrentTaskExecutor?.ShouldInterruptOnDamage() == true)
InterruptQueueWithCombat(); InterruptQueueWithCombat();
else if (GameFunctions.GameStringEquals(_cantExecuteDueToStatusText, message.TextValue))
InterruptWithoutCombat();
} }
} }

View File

@ -19,7 +19,7 @@ using Quest = Questionable.Model.Quest;
namespace Questionable.Controller; namespace Questionable.Controller;
internal sealed class QuestController : MiniTaskController<QuestController>, IDisposable internal sealed class QuestController : MiniTaskController<QuestController>
{ {
private readonly IClientState _clientState; private readonly IClientState _clientState;
private readonly GameFunctions _gameFunctions; private readonly GameFunctions _gameFunctions;
@ -111,9 +111,13 @@ internal sealed class QuestController : MiniTaskController<QuestController>, IDi
_logger.LogInformation("Setting automation type to {NewAutomationType} (previous: {OldAutomationType})", _logger.LogInformation("Setting automation type to {NewAutomationType} (previous: {OldAutomationType})",
value, _automationType); value, _automationType);
_automationType = value; _automationType = value;
AutomationTypeChanged?.Invoke(this, value);
} }
} }
public delegate void AutomationTypeChangedEventHandler(object sender, EAutomationType e);
public event AutomationTypeChangedEventHandler? AutomationTypeChanged;
public (QuestProgress Progress, ECurrentQuestType Type)? CurrentQuestDetails public (QuestProgress Progress, ECurrentQuestType Type)? CurrentQuestDetails
{ {
get get
@ -623,7 +627,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>, IDi
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Failed to create tasks"); _logger.LogError(e, "Failed to create tasks");
_chatGui.PrintError("[Questionable] Failed to start next task sequence, please check /xllog for details."); _chatGui.PrintError("Failed to start next task sequence, please check /xllog for details.", CommandHandler.MessageTag, CommandHandler.TagColor);
Stop("Tasks failed to create"); Stop("Tasks failed to create");
} }
} }

View File

@ -26,7 +26,8 @@ internal static class AetherCurrent
if (!aetherCurrentData.IsValidAetherCurrent(step.TerritoryId, step.AetherCurrentId.Value)) if (!aetherCurrentData.IsValidAetherCurrent(step.TerritoryId, step.AetherCurrentId.Value))
{ {
chatGui.PrintError( chatGui.PrintError(
$"[Questionable] Aether current with id {step.AetherCurrentId} is referencing an invalid aether current, will skip attunement"); $"Aether current with id {step.AetherCurrentId} is referencing an invalid aether current, will skip attunement",
CommandHandler.MessageTag, CommandHandler.TagColor);
return null; return null;
} }

View File

@ -40,9 +40,11 @@ internal static class EquipRecommended
public override string ToString() => "EquipRecommended"; public override string ToString() => "EquipRecommended";
} }
internal sealed unsafe class DoEquipRecommended(IClientState clientState, IChatGui chatGui, ICondition condition) : TaskExecutor<EquipTask> internal sealed unsafe class DoEquipRecommended(IClientState clientState, IChatGui chatGui, ICondition condition)
: TaskExecutor<EquipTask>
{ {
private bool _equipped; private bool _checkedOrTriggeredEquipmentUpdate;
private DateTime _continueAt = DateTime.MinValue;
protected override bool Start() protected override bool Start()
{ {
@ -59,44 +61,51 @@ internal static class EquipRecommended
if (recommendedEquipModule->IsUpdating) if (recommendedEquipModule->IsUpdating)
return ETaskResult.StillRunning; return ETaskResult.StillRunning;
if (!_equipped) if (!_checkedOrTriggeredEquipmentUpdate)
{ {
InventoryManager* inventoryManager = InventoryManager.Instance(); if (!IsAllRecommendeGearEquipped())
InventoryContainer* equippedItems =
inventoryManager->GetInventoryContainer(InventoryType.EquippedItems);
bool isAllEquipped = true;
foreach (var recommendedItemPtr in recommendedEquipModule->RecommendedItems)
{ {
var recommendedItem = recommendedItemPtr.Value; chatGui.Print("Equipping recommended gear.", CommandHandler.MessageTag, CommandHandler.TagColor);
if (recommendedItem == null || recommendedItem->ItemId == 0)
continue;
bool isEquipped = false;
for (int i = 0; i < equippedItems->Size; ++i)
{
var equippedItem = equippedItems->Items[i];
if (equippedItem.ItemId != 0 && equippedItem.ItemId == recommendedItem->ItemId)
{
isEquipped = true;
break;
}
}
if (!isEquipped)
isAllEquipped = false;
}
if (!isAllEquipped)
{
chatGui.Print("Equipping recommended gear.", "Questionable");
recommendedEquipModule->EquipRecommendedGear(); recommendedEquipModule->EquipRecommendedGear();
_continueAt = DateTime.Now.AddSeconds(1);
} }
_equipped = true; _checkedOrTriggeredEquipmentUpdate = true;
return ETaskResult.StillRunning; return ETaskResult.StillRunning;
} }
return ETaskResult.TaskComplete; return DateTime.Now >= _continueAt ? ETaskResult.TaskComplete : ETaskResult.StillRunning;
}
private bool IsAllRecommendeGearEquipped()
{
var recommendedEquipModule = RecommendEquipModule.Instance();
InventoryManager* inventoryManager = InventoryManager.Instance();
InventoryContainer* equippedItems =
inventoryManager->GetInventoryContainer(InventoryType.EquippedItems);
bool isAllEquipped = true;
foreach (var recommendedItemPtr in recommendedEquipModule->RecommendedItems)
{
var recommendedItem = recommendedItemPtr.Value;
if (recommendedItem == null || recommendedItem->ItemId == 0)
continue;
bool isEquipped = false;
for (int i = 0; i < equippedItems->Size; ++i)
{
var equippedItem = equippedItems->Items[i];
if (equippedItem.ItemId != 0 && equippedItem.ItemId == recommendedItem->ItemId)
{
isEquipped = true;
break;
}
}
if (!isEquipped)
isAllEquipped = false;
}
return isAllEquipped;
} }
public override bool ShouldInterruptOnDamage() => true; public override bool ShouldInterruptOnDamage() => true;

View File

@ -201,7 +201,7 @@ internal static class AetheryteShortcut
if (!aetheryteFunctions.IsAetheryteUnlocked(Task.TargetAetheryte)) if (!aetheryteFunctions.IsAetheryteUnlocked(Task.TargetAetheryte))
{ {
chatGui.PrintError($"[Questionable] Aetheryte {Task.TargetAetheryte} is not unlocked."); chatGui.PrintError($"Aetheryte {Task.TargetAetheryte} is not unlocked.", CommandHandler.MessageTag, CommandHandler.TagColor);
throw new TaskException("Aetheryte is not unlocked"); throw new TaskException("Aetheryte is not unlocked");
} }
@ -215,7 +215,7 @@ internal static class AetheryteShortcut
} }
else else
{ {
chatGui.Print("[Questionable] Unable to teleport to aetheryte."); chatGui.Print("Unable to teleport to aetheryte.", CommandHandler.MessageTag, CommandHandler.TagColor);
throw new TaskException("Unable to teleport to aetheryte"); throw new TaskException("Unable to teleport to aetheryte");
} }
} }

View File

@ -307,6 +307,7 @@ internal static class SkipCondition
return condition switch return condition switch
{ {
EExtraSkipCondition.WakingSandsMainArea => territoryType == 212 && position.X < 24, EExtraSkipCondition.WakingSandsMainArea => territoryType == 212 && position.X < 24,
EExtraSkipCondition.WakingSandsSolar => territoryType == 212 && position.X >= 24,
EExtraSkipCondition.RisingStonesSolar => territoryType == 351 && position.Z <= -28, EExtraSkipCondition.RisingStonesSolar => territoryType == 351 && position.Z <= -28,
EExtraSkipCondition.RoguesGuild => territoryType == 129 && position.Y <= -115, EExtraSkipCondition.RoguesGuild => territoryType == 129 && position.Y <= -115,
EExtraSkipCondition.DockStorehouse => territoryType == 137 && position.Y <= -20, EExtraSkipCondition.DockStorehouse => territoryType == 137 && position.Y <= -20,

View File

@ -189,6 +189,12 @@ internal sealed class QuestData
AddPreviousQuest(new QuestId(3833), new QuestId(spearfishing)); AddPreviousQuest(new QuestId(3833), new QuestId(spearfishing));
*/ */
// Shadow Walk with Me
AddPreviousQuest(new QuestId(3629), new QuestId(3248));
AddPreviousQuest(new QuestId(3629), new QuestId(3272));
AddPreviousQuest(new QuestId(3629), new QuestId(3278));
AddPreviousQuest(new QuestId(3629), new QuestId(3628));
// The Hero's Journey // The Hero's Journey
AddPreviousQuest(new QuestId(3986), new QuestId(2115)); AddPreviousQuest(new QuestId(3986), new QuestId(2115));
AddPreviousQuest(new QuestId(3986), new QuestId(2116)); AddPreviousQuest(new QuestId(3986), new QuestId(2116));
@ -197,6 +203,11 @@ internal sealed class QuestData
AddPreviousQuest(new QuestId(3986), new QuestId(2395)); AddPreviousQuest(new QuestId(3986), new QuestId(2395));
AddPreviousQuest(new QuestId(3986), new QuestId(3985)); AddPreviousQuest(new QuestId(3986), new QuestId(3985));
// Picking up the Torch has half the quests in the sheets(??)
AddPreviousQuest(new QuestId(5188), new QuestId(4841));
AddPreviousQuest(new QuestId(5188), new QuestId(4847));
AddPreviousQuest(new QuestId(5188), new QuestId(4959));
// initial city quests are side quests // initial city quests are side quests
// unclear if 470 can be started as the required quest isn't available anymore // unclear if 470 can be started as the required quest isn't available anymore
ushort[] limsaSideQuests = ushort[] limsaSideQuests =