diff --git a/QuestPathGenerator/RoslynElements/DutyOptionsExtensions.cs b/QuestPathGenerator/RoslynElements/DutyOptionsExtensions.cs new file mode 100644 index 00000000..c7092a49 --- /dev/null +++ b/QuestPathGenerator/RoslynElements/DutyOptionsExtensions.cs @@ -0,0 +1,30 @@ +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Questionable.Model.Questing; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static Questionable.QuestPathGenerator.RoslynShortcuts; + +namespace Questionable.QuestPathGenerator.RoslynElements; + +internal static class DutyOptionsExtensions +{ + public static ExpressionSyntax ToExpressionSyntax(this DutyOptions dutyOptions) + { + var emptyOptions = new DutyOptions(); + return ObjectCreationExpression( + IdentifierName(nameof(DutyOptions))) + .WithInitializer( + InitializerExpression( + SyntaxKind.ObjectInitializerExpression, + SeparatedList( + SyntaxNodeList( + Assignment(nameof(DutyOptions.Enabled), + dutyOptions.Enabled, emptyOptions.Enabled) + .AsSyntaxNodeOrToken(), + Assignment(nameof(DutyOptions.ContentFinderConditionId), + dutyOptions.ContentFinderConditionId, emptyOptions.ContentFinderConditionId) + .AsSyntaxNodeOrToken(), + AssignmentList(nameof(DutyOptions.Notes), dutyOptions.Notes) + .AsSyntaxNodeOrToken())))); + } +} diff --git a/QuestPathGenerator/RoslynElements/QuestStepExtensions.cs b/QuestPathGenerator/RoslynElements/QuestStepExtensions.cs index 1ff4fbc1..00a36dbe 100644 --- a/QuestPathGenerator/RoslynElements/QuestStepExtensions.cs +++ b/QuestPathGenerator/RoslynElements/QuestStepExtensions.cs @@ -117,11 +117,8 @@ internal static class QuestStepExtensions Assignment(nameof(QuestStep.JumpDestination), step.JumpDestination, emptyStep.JumpDestination) .AsSyntaxNodeOrToken(), - Assignment(nameof(QuestStep.ContentFinderConditionId), - step.ContentFinderConditionId, emptyStep.ContentFinderConditionId) - .AsSyntaxNodeOrToken(), - Assignment(nameof(QuestStep.AutoDutyEnabled), - step.AutoDutyEnabled, emptyStep.AutoDutyEnabled) + Assignment(nameof(QuestStep.DutyOptions), step.DutyOptions, + emptyStep.DutyOptions) .AsSyntaxNodeOrToken(), Assignment(nameof(QuestStep.SinglePlayerDutyOptions), step.SinglePlayerDutyOptions, emptyStep.SinglePlayerDutyOptions) diff --git a/QuestPathGenerator/RoslynShortcuts.cs b/QuestPathGenerator/RoslynShortcuts.cs index 70cae35d..e9e07b87 100644 --- a/QuestPathGenerator/RoslynShortcuts.cs +++ b/QuestPathGenerator/RoslynShortcuts.cs @@ -62,6 +62,7 @@ public static class RoslynShortcuts ComplexCombatData complexCombatData => complexCombatData.ToExpressionSyntax(), QuestWorkValue questWorkValue => questWorkValue.ToExpressionSyntax(), List list => list.ToExpressionSyntax(), // TODO fix in AssignmentList + DutyOptions dutyOptions => dutyOptions.ToExpressionSyntax(), SinglePlayerDutyOptions dutyOptions => dutyOptions.ToExpressionSyntax(), SkipConditions skipConditions => skipConditions.ToExpressionSyntax(), SkipStepConditions skipStepConditions => skipStepConditions.ToExpressionSyntax(), diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/245_It's Probably Pirates.json b/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/245_It's Probably Pirates.json index 0d3aada9..2104a8f0 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/245_It's Probably Pirates.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/245_It's Probably Pirates.json @@ -112,8 +112,10 @@ { "TerritoryId": 138, "InteractionType": "Duty", - "ContentFinderConditionId": 4, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 4, + "Enabled": true + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/343_Lord of the Inferno.json b/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/343_Lord of the Inferno.json index be80477d..1edd6de0 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/343_Lord of the Inferno.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/343_Lord of the Inferno.json @@ -75,8 +75,10 @@ { "TerritoryId": 146, "InteractionType": "Duty", - "ContentFinderConditionId": 56, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 56, + "Enabled": true + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/660_Into a Copper Hell.json b/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/660_Into a Copper Hell.json index 299a07d4..ae27c13c 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/660_Into a Copper Hell.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/660_Into a Copper Hell.json @@ -62,8 +62,10 @@ { "TerritoryId": 140, "InteractionType": "Duty", - "ContentFinderConditionId": 3, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 3, + "Enabled": true + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/677_Fire in the Gloom.json b/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/677_Fire in the Gloom.json index 726eae29..636b99f2 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/677_Fire in the Gloom.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/677_Fire in the Gloom.json @@ -57,8 +57,10 @@ { "TerritoryId": 148, "InteractionType": "Duty", - "ContentFinderConditionId": 2, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 2, + "Enabled": true + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/A3-South Shroud, Buscarron’s Druthers/514_Into the Beast's Maw.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/A3-South Shroud, Buscarron’s Druthers/514_Into the Beast's Maw.json index 45b28b3f..c9cb93f1 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/A3-South Shroud, Buscarron’s Druthers/514_Into the Beast's Maw.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/A3-South Shroud, Buscarron’s Druthers/514_Into the Beast's Maw.json @@ -44,8 +44,10 @@ { "TerritoryId": 153, "InteractionType": "Duty", - "ContentFinderConditionId": 1, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 1, + "Enabled": true + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/A9-Haukke Manor/801_Skeletons in Her Closet.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/A9-Haukke Manor/801_Skeletons in Her Closet.json index a17b715c..e8b7817f 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/A9-Haukke Manor/801_Skeletons in Her Closet.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/A9-Haukke Manor/801_Skeletons in Her Closet.json @@ -66,8 +66,13 @@ { "TerritoryId": 148, "InteractionType": "Duty", - "ContentFinderConditionId": 6, - "AutoDutyEnabled": false + "DutyOptions": { + "ContentFinderConditionId": 6, + "Enabled": false, + "Notes": [ + "(after boss 2) Will not pick up the bloody parchment, and instead run off to open a random unrelated chest that it can't reach" + ] + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B2-Eastern La Noscea, Brayflox, Cheese and Wine/832_The Things We Do for Cheese.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B2-Eastern La Noscea, Brayflox, Cheese and Wine/832_The Things We Do for Cheese.json index 960ac4ec..69c77dce 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B2-Eastern La Noscea, Brayflox, Cheese and Wine/832_The Things We Do for Cheese.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B2-Eastern La Noscea, Brayflox, Cheese and Wine/832_The Things We Do for Cheese.json @@ -85,8 +85,13 @@ { "TerritoryId": 137, "InteractionType": "Duty", - "ContentFinderConditionId": 8, - "AutoDutyEnabled": false + "DutyOptions": { + "ContentFinderConditionId": 8, + "Enabled": false, + "Notes": [ + "(boss 2) Will walk out of the boss arena to try and attack optional enemies on the upper level, thus resetting the boss and breaking the path" + ] + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B4-Titan/857_Lord of Crags.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B4-Titan/857_Lord of Crags.json index 4cc4c576..b3516cde 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/B4-Titan/857_Lord of Crags.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/B4-Titan/857_Lord of Crags.json @@ -45,8 +45,10 @@ { "TerritoryId": 139, "InteractionType": "Duty", - "ContentFinderConditionId": 57, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 57, + "Enabled": true + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C1-Coerthas Central Highlands, The Enterprise/952_In Pursuit of the Past.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C1-Coerthas Central Highlands, The Enterprise/952_In Pursuit of the Past.json index 57ef1fa9..a9844776 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C1-Coerthas Central Highlands, The Enterprise/952_In Pursuit of the Past.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C1-Coerthas Central Highlands, The Enterprise/952_In Pursuit of the Past.json @@ -59,8 +59,14 @@ { "TerritoryId": 155, "InteractionType": "Duty", - "ContentFinderConditionId": 11, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 11, + "Enabled": false, + "Notes": [ + "(boss 1) AI will not face cleaves away from healer, typically killing them", + "(boss 3) AI will not face cleaves away from healer, which doesn't always kill them" + ] + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C3-Garuda/519_Lady of the Vortex.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C3-Garuda/519_Lady of the Vortex.json index d9315eca..bb48332f 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C3-Garuda/519_Lady of the Vortex.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C3-Garuda/519_Lady of the Vortex.json @@ -38,8 +38,10 @@ { "TerritoryId": 331, "InteractionType": "Duty", - "ContentFinderConditionId": 58, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 58, + "Enabled": true + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/3873_Rock the Castrum.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/3873_Rock the Castrum.json index dba66d15..d4914c2c 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/3873_Rock the Castrum.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/3873_Rock the Castrum.json @@ -195,8 +195,10 @@ { "TerritoryId": 147, "InteractionType": "Duty", - "ContentFinderConditionId": 15, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 15, + "Enabled": true + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4522_The Ultimate Weapon.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4522_The Ultimate Weapon.json index 8122668a..aad57d7c 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4522_The Ultimate Weapon.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4522_The Ultimate Weapon.json @@ -46,8 +46,10 @@ { "TerritoryId": 147, "InteractionType": "Duty", - "ContentFinderConditionId": 16, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 16, + "Enabled": true + } } ] }, @@ -72,8 +74,10 @@ { "TerritoryId": 1053, "InteractionType": "Duty", - "ContentFinderConditionId": 830, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 830, + "Enabled": true + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/E4-2.4/75_The Path of the Righteous.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/E4-2.4/75_The Path of the Righteous.json index b6581b9a..e8534c38 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/E4-2.4/75_The Path of the Righteous.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/E4-2.4/75_The Path of the Righteous.json @@ -88,8 +88,10 @@ { "TerritoryId": 155, "InteractionType": "Duty", - "ContentFinderConditionId": 27, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 27, + "Enabled": true + } } ] }, diff --git a/QuestPaths/2.x - A Realm Reborn/MSQ-2/E5-2.5/366_The Rising Chorus.json b/QuestPaths/2.x - A Realm Reborn/MSQ-2/E5-2.5/366_The Rising Chorus.json index 24d72b21..235ab5e6 100644 --- a/QuestPaths/2.x - A Realm Reborn/MSQ-2/E5-2.5/366_The Rising Chorus.json +++ b/QuestPaths/2.x - A Realm Reborn/MSQ-2/E5-2.5/366_The Rising Chorus.json @@ -107,8 +107,10 @@ { "TerritoryId": 156, "InteractionType": "Duty", - "ContentFinderConditionId": 32, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 32, + "Enabled": true + } } ] }, diff --git a/QuestPaths/3.x - Heavensward/MSQ/A3.2-The Dravanian Forelands/1617_Mourn in Passing.json b/QuestPaths/3.x - Heavensward/MSQ/A3.2-The Dravanian Forelands/1617_Mourn in Passing.json index a321c741..df6d17db 100644 --- a/QuestPaths/3.x - Heavensward/MSQ/A3.2-The Dravanian Forelands/1617_Mourn in Passing.json +++ b/QuestPaths/3.x - Heavensward/MSQ/A3.2-The Dravanian Forelands/1617_Mourn in Passing.json @@ -78,8 +78,10 @@ { "TerritoryId": 398, "InteractionType": "Duty", - "ContentFinderConditionId": 37, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 37, + "Enabled": true + } } ] }, diff --git a/QuestPaths/3.x - Heavensward/MSQ/A3.3-The Churning Mists/1634_Into the Aery.json b/QuestPaths/3.x - Heavensward/MSQ/A3.3-The Churning Mists/1634_Into the Aery.json index 02098cab..97ead078 100644 --- a/QuestPaths/3.x - Heavensward/MSQ/A3.3-The Churning Mists/1634_Into the Aery.json +++ b/QuestPaths/3.x - Heavensward/MSQ/A3.3-The Churning Mists/1634_Into the Aery.json @@ -42,8 +42,10 @@ { "TerritoryId": 418, "InteractionType": "Duty", - "ContentFinderConditionId": 39, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 39, + "Enabled": true + } } ] }, diff --git a/QuestPaths/3.x - Heavensward/MSQ/A4-Ishgard/1640_A Knight's Calling.json b/QuestPaths/3.x - Heavensward/MSQ/A4-Ishgard/1640_A Knight's Calling.json index 9165e2a0..da55ca41 100644 --- a/QuestPaths/3.x - Heavensward/MSQ/A4-Ishgard/1640_A Knight's Calling.json +++ b/QuestPaths/3.x - Heavensward/MSQ/A4-Ishgard/1640_A Knight's Calling.json @@ -59,8 +59,10 @@ { "TerritoryId": 419, "InteractionType": "Duty", - "ContentFinderConditionId": 34, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 34, + "Enabled": true + } } ] }, diff --git a/QuestPaths/3.x - Heavensward/MSQ/A6-The Dravanian Hinterlands/1660_Forbidden Knowledge.json b/QuestPaths/3.x - Heavensward/MSQ/A6-The Dravanian Hinterlands/1660_Forbidden Knowledge.json index dab4f3da..6c94266a 100644 --- a/QuestPaths/3.x - Heavensward/MSQ/A6-The Dravanian Hinterlands/1660_Forbidden Knowledge.json +++ b/QuestPaths/3.x - Heavensward/MSQ/A6-The Dravanian Hinterlands/1660_Forbidden Knowledge.json @@ -110,8 +110,10 @@ { "TerritoryId": 399, "InteractionType": "Duty", - "ContentFinderConditionId": 31, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 31, + "Enabled": true + } } ] }, diff --git a/QuestPaths/3.x - Heavensward/MSQ/A7-Azys Lla/1669_Heavensward.json b/QuestPaths/3.x - Heavensward/MSQ/A7-Azys Lla/1669_Heavensward.json index 7bef51cc..215f1849 100644 --- a/QuestPaths/3.x - Heavensward/MSQ/A7-Azys Lla/1669_Heavensward.json +++ b/QuestPaths/3.x - Heavensward/MSQ/A7-Azys Lla/1669_Heavensward.json @@ -62,8 +62,10 @@ { "TerritoryId": 402, "InteractionType": "Duty", - "ContentFinderConditionId": 38, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 38, + "Enabled": true + } } ] }, @@ -88,7 +90,10 @@ { "TerritoryId": 402, "InteractionType": "Duty", - "ContentFinderConditionId": 90 + "DutyOptions": { + "ContentFinderConditionId": 90, + "Enabled": false + } } ] }, diff --git a/QuestPaths/3.x - Heavensward/MSQ/C-3.2/2232_The Word of the Mother.json b/QuestPaths/3.x - Heavensward/MSQ/C-3.2/2232_The Word of the Mother.json index fe2c3367..f6016328 100644 --- a/QuestPaths/3.x - Heavensward/MSQ/C-3.2/2232_The Word of the Mother.json +++ b/QuestPaths/3.x - Heavensward/MSQ/C-3.2/2232_The Word of the Mother.json @@ -77,8 +77,11 @@ { "TerritoryId": 463, "InteractionType": "Duty", - "ContentFinderConditionId": 141, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 141, + "Enabled": true, + "TestedAutoDutyVersion": "0.0.0.191" + } } ] }, diff --git a/QuestPaths/3.x - Heavensward/MSQ/E-3.4/2342_Shadows of the First.json b/QuestPaths/3.x - Heavensward/MSQ/E-3.4/2342_Shadows of the First.json index 3cee72be..7821fc99 100644 --- a/QuestPaths/3.x - Heavensward/MSQ/E-3.4/2342_Shadows of the First.json +++ b/QuestPaths/3.x - Heavensward/MSQ/E-3.4/2342_Shadows of the First.json @@ -57,8 +57,14 @@ { "TerritoryId": 155, "InteractionType": "Duty", - "ContentFinderConditionId": 182, - "AutoDutyEnabled": false + "DutyOptions": { + "ContentFinderConditionId": 182, + "Enabled": false, + "Notes": [ + "(after boss 1) the drawbridges being up will lead you to die from the spikes", + "(after boss 1) the lift isn't working properly" + ] + } } ] }, diff --git a/QuestPaths/3.x - Heavensward/MSQ/E-3.4/2345_The Beast That Mourned at the Heart of the Mountain.json b/QuestPaths/3.x - Heavensward/MSQ/E-3.4/2345_The Beast That Mourned at the Heart of the Mountain.json index b04f3f54..00e0988e 100644 --- a/QuestPaths/3.x - Heavensward/MSQ/E-3.4/2345_The Beast That Mourned at the Heart of the Mountain.json +++ b/QuestPaths/3.x - Heavensward/MSQ/E-3.4/2345_The Beast That Mourned at the Heart of the Mountain.json @@ -198,7 +198,10 @@ { "TerritoryId": 180, "InteractionType": "Duty", - "ContentFinderConditionId": 60 + "DutyOptions": { + "ContentFinderConditionId": 60, + "Enabled": false + } } ] }, diff --git a/QuestPaths/3.x - Heavensward/MSQ/F-3.5/2354_Griffin, Griffin on the Wall.json b/QuestPaths/3.x - Heavensward/MSQ/F-3.5/2354_Griffin, Griffin on the Wall.json index 42aef1f0..9d1c4d89 100644 --- a/QuestPaths/3.x - Heavensward/MSQ/F-3.5/2354_Griffin, Griffin on the Wall.json +++ b/QuestPaths/3.x - Heavensward/MSQ/F-3.5/2354_Griffin, Griffin on the Wall.json @@ -109,8 +109,10 @@ { "TerritoryId": 152, "InteractionType": "Duty", - "ContentFinderConditionId": 219, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 219, + "Enabled": true + } } ] }, diff --git a/QuestPaths/4.x - Stormblood/MSQ/A1.3-Rhalgr's Reach 2/2469_Not without Incident.json b/QuestPaths/4.x - Stormblood/MSQ/A1.3-Rhalgr's Reach 2/2469_Not without Incident.json index 6477857e..c5d3ef59 100644 --- a/QuestPaths/4.x - Stormblood/MSQ/A1.3-Rhalgr's Reach 2/2469_Not without Incident.json +++ b/QuestPaths/4.x - Stormblood/MSQ/A1.3-Rhalgr's Reach 2/2469_Not without Incident.json @@ -87,8 +87,10 @@ { "TerritoryId": 680, "InteractionType": "Duty", - "ContentFinderConditionId": 238, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 238, + "Enabled": true + } } ] }, diff --git a/QuestPaths/4.x - Stormblood/MSQ/A5-Yanxia 2/2524_The Die Is Cast.json b/QuestPaths/4.x - Stormblood/MSQ/A5-Yanxia 2/2524_The Die Is Cast.json index 702737b3..eacefe65 100644 --- a/QuestPaths/4.x - Stormblood/MSQ/A5-Yanxia 2/2524_The Die Is Cast.json +++ b/QuestPaths/4.x - Stormblood/MSQ/A5-Yanxia 2/2524_The Die Is Cast.json @@ -114,8 +114,10 @@ { "TerritoryId": 614, "InteractionType": "Duty", - "ContentFinderConditionId": 241, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 241, + "Enabled": true + } } ] }, diff --git a/QuestPaths/4.x - Stormblood/MSQ/A6.2-Peaks 2/2544_The Price of Freedom.json b/QuestPaths/4.x - Stormblood/MSQ/A6.2-Peaks 2/2544_The Price of Freedom.json index a0b37e35..798f15a1 100644 --- a/QuestPaths/4.x - Stormblood/MSQ/A6.2-Peaks 2/2544_The Price of Freedom.json +++ b/QuestPaths/4.x - Stormblood/MSQ/A6.2-Peaks 2/2544_The Price of Freedom.json @@ -114,8 +114,10 @@ { "TerritoryId": 620, "InteractionType": "Duty", - "ContentFinderConditionId": 242, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 242, + "Enabled": true + } } ] }, diff --git a/QuestPaths/4.x - Stormblood/MSQ/B-4.1/2964_The Mad King's Trove.json b/QuestPaths/4.x - Stormblood/MSQ/B-4.1/2964_The Mad King's Trove.json index 0856bbe6..02436aeb 100644 --- a/QuestPaths/4.x - Stormblood/MSQ/B-4.1/2964_The Mad King's Trove.json +++ b/QuestPaths/4.x - Stormblood/MSQ/B-4.1/2964_The Mad King's Trove.json @@ -98,8 +98,10 @@ { "TerritoryId": 621, "InteractionType": "Duty", - "ContentFinderConditionId": 279, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 279, + "Enabled": true + } } ] }, diff --git a/QuestPaths/4.x - Stormblood/MSQ/E-4.4/3144_Feel the Burn.json b/QuestPaths/4.x - Stormblood/MSQ/E-4.4/3144_Feel the Burn.json index fba0763d..1757d803 100644 --- a/QuestPaths/4.x - Stormblood/MSQ/E-4.4/3144_Feel the Burn.json +++ b/QuestPaths/4.x - Stormblood/MSQ/E-4.4/3144_Feel the Burn.json @@ -40,8 +40,10 @@ { "TerritoryId": 614, "InteractionType": "Duty", - "ContentFinderConditionId": 585, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 585, + "Enabled": true + } } ] }, diff --git a/QuestPaths/4.x - Stormblood/MSQ/F-4.5/3183_The Face of War.json b/QuestPaths/4.x - Stormblood/MSQ/F-4.5/3183_The Face of War.json index fb9960de..0dcf2988 100644 --- a/QuestPaths/4.x - Stormblood/MSQ/F-4.5/3183_The Face of War.json +++ b/QuestPaths/4.x - Stormblood/MSQ/F-4.5/3183_The Face of War.json @@ -27,8 +27,10 @@ { "TerritoryId": 829, "InteractionType": "Duty", - "ContentFinderConditionId": 611, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 611, + "Enabled": true + } } ] }, diff --git a/QuestPaths/5.x - Shadowbringers/MSQ/A4-Crystarium 2/3300_The Lightwardens.json b/QuestPaths/5.x - Shadowbringers/MSQ/A4-Crystarium 2/3300_The Lightwardens.json index 7f9a5a94..de440ed2 100644 --- a/QuestPaths/5.x - Shadowbringers/MSQ/A4-Crystarium 2/3300_The Lightwardens.json +++ b/QuestPaths/5.x - Shadowbringers/MSQ/A4-Crystarium 2/3300_The Lightwardens.json @@ -120,8 +120,10 @@ { "TerritoryId": 813, "InteractionType": "Duty", - "ContentFinderConditionId": 676, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 676, + "Enabled": true + } } ] }, diff --git a/QuestPaths/5.x - Shadowbringers/MSQ/B-Il Mheg/3312_The Key to the Castle.json b/QuestPaths/5.x - Shadowbringers/MSQ/B-Il Mheg/3312_The Key to the Castle.json index d1dfe7dc..ea66e5a6 100644 --- a/QuestPaths/5.x - Shadowbringers/MSQ/B-Il Mheg/3312_The Key to the Castle.json +++ b/QuestPaths/5.x - Shadowbringers/MSQ/B-Il Mheg/3312_The Key to the Castle.json @@ -49,8 +49,10 @@ { "TerritoryId": 816, "InteractionType": "Duty", - "ContentFinderConditionId": 649, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 649, + "Enabled": true + } } ] }, diff --git a/QuestPaths/5.x - Shadowbringers/MSQ/C-Rak'tika/3340_The Burden of Knowledge.json b/QuestPaths/5.x - Shadowbringers/MSQ/C-Rak'tika/3340_The Burden of Knowledge.json index 39284d2f..8a07ab80 100644 --- a/QuestPaths/5.x - Shadowbringers/MSQ/C-Rak'tika/3340_The Burden of Knowledge.json +++ b/QuestPaths/5.x - Shadowbringers/MSQ/C-Rak'tika/3340_The Burden of Knowledge.json @@ -61,8 +61,10 @@ { "TerritoryId": 817, "InteractionType": "Duty", - "ContentFinderConditionId": 651, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 651, + "Enabled": true + } } ] }, diff --git a/QuestPaths/5.x - Shadowbringers/MSQ/E-Kholusia 2/3643_Extinguishing the Last Light.json b/QuestPaths/5.x - Shadowbringers/MSQ/E-Kholusia 2/3643_Extinguishing the Last Light.json index 80cbd172..ef9aa4df 100644 --- a/QuestPaths/5.x - Shadowbringers/MSQ/E-Kholusia 2/3643_Extinguishing the Last Light.json +++ b/QuestPaths/5.x - Shadowbringers/MSQ/E-Kholusia 2/3643_Extinguishing the Last Light.json @@ -62,8 +62,10 @@ { "TerritoryId": 814, "InteractionType": "Duty", - "ContentFinderConditionId": 659, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 659, + "Enabled": true + } } ] }, @@ -88,7 +90,10 @@ { "TerritoryId": 880, "InteractionType": "Duty", - "ContentFinderConditionId": 666 + "DutyOptions": { + "ContentFinderConditionId": 666, + "Enabled": false + } } ] }, diff --git a/QuestPaths/5.x - Shadowbringers/MSQ/H-5.2/3769_Beneath the Surface.json b/QuestPaths/5.x - Shadowbringers/MSQ/H-5.2/3769_Beneath the Surface.json index 41dd8315..61a471aa 100644 --- a/QuestPaths/5.x - Shadowbringers/MSQ/H-5.2/3769_Beneath the Surface.json +++ b/QuestPaths/5.x - Shadowbringers/MSQ/H-5.2/3769_Beneath the Surface.json @@ -40,8 +40,10 @@ { "TerritoryId": 814, "InteractionType": "Duty", - "ContentFinderConditionId": 714, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 714, + "Enabled": true + } } ] }, diff --git a/QuestPaths/6.x - Endwalker/MSQ/A-Thavnair1-Labyrinthos1/4377_In the Dark of the Tower.json b/QuestPaths/6.x - Endwalker/MSQ/A-Thavnair1-Labyrinthos1/4377_In the Dark of the Tower.json index c4336959..d07dba7e 100644 --- a/QuestPaths/6.x - Endwalker/MSQ/A-Thavnair1-Labyrinthos1/4377_In the Dark of the Tower.json +++ b/QuestPaths/6.x - Endwalker/MSQ/A-Thavnair1-Labyrinthos1/4377_In the Dark of the Tower.json @@ -55,8 +55,10 @@ { "TerritoryId": 957, "InteractionType": "Duty", - "ContentFinderConditionId": 783, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 783, + "Enabled": true + } } ] }, diff --git a/QuestPaths/6.x - Endwalker/MSQ/D-Thavnair2/4409_Skies Aflame.json b/QuestPaths/6.x - Endwalker/MSQ/D-Thavnair2/4409_Skies Aflame.json index 9c0d3a48..21ad7d9e 100644 --- a/QuestPaths/6.x - Endwalker/MSQ/D-Thavnair2/4409_Skies Aflame.json +++ b/QuestPaths/6.x - Endwalker/MSQ/D-Thavnair2/4409_Skies Aflame.json @@ -71,8 +71,10 @@ { "TerritoryId": 957, "InteractionType": "Duty", - "ContentFinderConditionId": 789, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 789, + "Enabled": true + } } ] }, diff --git a/QuestPaths/6.x - Endwalker/MSQ/E-Elpis/4437_Caging the Messenger.json b/QuestPaths/6.x - Endwalker/MSQ/E-Elpis/4437_Caging the Messenger.json index 9dd680eb..89c6fc54 100644 --- a/QuestPaths/6.x - Endwalker/MSQ/E-Elpis/4437_Caging the Messenger.json +++ b/QuestPaths/6.x - Endwalker/MSQ/E-Elpis/4437_Caging the Messenger.json @@ -39,8 +39,10 @@ { "TerritoryId": 961, "InteractionType": "Duty", - "ContentFinderConditionId": 787, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 787, + "Enabled": true + } } ] }, diff --git a/QuestPaths/6.x - Endwalker/MSQ/F-Labyrinthos2/4449_Her Children One and All.json b/QuestPaths/6.x - Endwalker/MSQ/F-Labyrinthos2/4449_Her Children One and All.json index 74943745..fc0aac0a 100644 --- a/QuestPaths/6.x - Endwalker/MSQ/F-Labyrinthos2/4449_Her Children One and All.json +++ b/QuestPaths/6.x - Endwalker/MSQ/F-Labyrinthos2/4449_Her Children One and All.json @@ -38,8 +38,13 @@ { "TerritoryId": 956, "InteractionType": "Duty", - "ContentFinderConditionId": 786, - "AutoDutyEnabled": false + "DutyOptions": { + "ContentFinderConditionId": 786, + "Enabled": false, + "Notes": [ + "No VBM module" + ] + } } ] }, @@ -64,8 +69,10 @@ { "TerritoryId": 1030, "InteractionType": "Duty", - "ContentFinderConditionId": 790, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 790, + "Enabled": true + } } ] }, diff --git a/QuestPaths/6.x - Endwalker/MSQ/H-6.1/4529_Alzadaals Legacy.json b/QuestPaths/6.x - Endwalker/MSQ/H-6.1/4529_Alzadaals Legacy.json index dc9324d1..8638a86c 100644 --- a/QuestPaths/6.x - Endwalker/MSQ/H-6.1/4529_Alzadaals Legacy.json +++ b/QuestPaths/6.x - Endwalker/MSQ/H-6.1/4529_Alzadaals Legacy.json @@ -23,8 +23,13 @@ { "TerritoryId": 957, "InteractionType": "Duty", - "ContentFinderConditionId": 844, - "AutoDutyEnabled": false + "DutyOptions": { + "ContentFinderConditionId": 844, + "Enabled": false, + "Notes": [ + "No VBM module" + ] + } } ] }, diff --git a/QuestPaths/6.x - Endwalker/MSQ/I-6.2/4592_In Search of Azdaja.json b/QuestPaths/6.x - Endwalker/MSQ/I-6.2/4592_In Search of Azdaja.json index c91af597..561b1903 100644 --- a/QuestPaths/6.x - Endwalker/MSQ/I-6.2/4592_In Search of Azdaja.json +++ b/QuestPaths/6.x - Endwalker/MSQ/I-6.2/4592_In Search of Azdaja.json @@ -71,8 +71,13 @@ { "TerritoryId": 1056, "InteractionType": "Duty", - "ContentFinderConditionId": 869, - "AutoDutyEnabled": false + "DutyOptions": { + "ContentFinderConditionId": 869, + "Enabled": false, + "Notes": [ + "No VBM module" + ] + } } ] }, diff --git a/QuestPaths/6.x - Endwalker/MSQ/J-6.3/4674_King of the Mountain.json b/QuestPaths/6.x - Endwalker/MSQ/J-6.3/4674_King of the Mountain.json index df1bd69f..14c3171c 100644 --- a/QuestPaths/6.x - Endwalker/MSQ/J-6.3/4674_King of the Mountain.json +++ b/QuestPaths/6.x - Endwalker/MSQ/J-6.3/4674_King of the Mountain.json @@ -56,9 +56,10 @@ { "TerritoryId": 958, "InteractionType": "Duty", - "Comment": "Lapis Manalis", - "ContentFinderConditionId": 896, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 896, + "Enabled": true + } } ] }, diff --git a/QuestPaths/6.x - Endwalker/MSQ/K-6.4/4736_Going Haam.json b/QuestPaths/6.x - Endwalker/MSQ/K-6.4/4736_Going Haam.json index 8af36080..30fa509b 100644 --- a/QuestPaths/6.x - Endwalker/MSQ/K-6.4/4736_Going Haam.json +++ b/QuestPaths/6.x - Endwalker/MSQ/K-6.4/4736_Going Haam.json @@ -160,8 +160,13 @@ { "TerritoryId": 962, "InteractionType": "Duty", - "ContentFinderConditionId": 822, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 822, + "Enabled": false, + "Notes": [ + "Navigation issues for area transitions" + ] + } } ] }, diff --git a/QuestPaths/6.x - Endwalker/MSQ/L-6.5/4748_Down in the Dark.json b/QuestPaths/6.x - Endwalker/MSQ/L-6.5/4748_Down in the Dark.json index 96953ea2..8b1016df 100644 --- a/QuestPaths/6.x - Endwalker/MSQ/L-6.5/4748_Down in the Dark.json +++ b/QuestPaths/6.x - Endwalker/MSQ/L-6.5/4748_Down in the Dark.json @@ -24,8 +24,10 @@ { "TerritoryId": 1162, "InteractionType": "Duty", - "ContentFinderConditionId": 823, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 823, + "Enabled": true + } } ] }, diff --git a/QuestPaths/7.x - Dawntrail/MSQ/A-Kozama'uka1-Urqopacha1/4879_For All Turali.json b/QuestPaths/7.x - Dawntrail/MSQ/A-Kozama'uka1-Urqopacha1/4879_For All Turali.json index 28a6850c..986d7526 100644 --- a/QuestPaths/7.x - Dawntrail/MSQ/A-Kozama'uka1-Urqopacha1/4879_For All Turali.json +++ b/QuestPaths/7.x - Dawntrail/MSQ/A-Kozama'uka1-Urqopacha1/4879_For All Turali.json @@ -58,8 +58,10 @@ { "TerritoryId": 1185, "InteractionType": "Duty", - "ContentFinderConditionId": 826, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 826, + "Enabled": true + } } ] }, diff --git a/QuestPaths/7.x - Dawntrail/MSQ/B-Kozama'uka2-Urqopacha2/4891_The High Luminary.json b/QuestPaths/7.x - Dawntrail/MSQ/B-Kozama'uka2-Urqopacha2/4891_The High Luminary.json index 2ef3a8e6..39268a03 100644 --- a/QuestPaths/7.x - Dawntrail/MSQ/B-Kozama'uka2-Urqopacha2/4891_The High Luminary.json +++ b/QuestPaths/7.x - Dawntrail/MSQ/B-Kozama'uka2-Urqopacha2/4891_The High Luminary.json @@ -23,8 +23,10 @@ { "TerritoryId": 1187, "InteractionType": "Duty", - "ContentFinderConditionId": 824, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 824, + "Enabled": true + } } ] }, diff --git a/QuestPaths/7.x - Dawntrail/MSQ/C-Yak T'el/4909_Road to the Golden City.json b/QuestPaths/7.x - Dawntrail/MSQ/C-Yak T'el/4909_Road to the Golden City.json index 528fde3f..9a1488ed 100644 --- a/QuestPaths/7.x - Dawntrail/MSQ/C-Yak T'el/4909_Road to the Golden City.json +++ b/QuestPaths/7.x - Dawntrail/MSQ/C-Yak T'el/4909_Road to the Golden City.json @@ -115,8 +115,10 @@ { "TerritoryId": 1189, "InteractionType": "Duty", - "ContentFinderConditionId": 829, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 829, + "Enabled": true + } } ] }, diff --git a/QuestPaths/7.x - Dawntrail/MSQ/D-Shaaloani-HeritageFound1/4926_All Aboard.json b/QuestPaths/7.x - Dawntrail/MSQ/D-Shaaloani-HeritageFound1/4926_All Aboard.json index 682576cb..5c83c615 100644 --- a/QuestPaths/7.x - Dawntrail/MSQ/D-Shaaloani-HeritageFound1/4926_All Aboard.json +++ b/QuestPaths/7.x - Dawntrail/MSQ/D-Shaaloani-HeritageFound1/4926_All Aboard.json @@ -60,8 +60,10 @@ { "TerritoryId": 1219, "InteractionType": "Duty", - "ContentFinderConditionId": 831, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 831, + "Enabled": true + } } ] }, diff --git a/QuestPaths/7.x - Dawntrail/MSQ/E-SolutionNine-HeritageFound2/4945_The Resilient Son.json b/QuestPaths/7.x - Dawntrail/MSQ/E-SolutionNine-HeritageFound2/4945_The Resilient Son.json index 738c8782..e57ca852 100644 --- a/QuestPaths/7.x - Dawntrail/MSQ/E-SolutionNine-HeritageFound2/4945_The Resilient Son.json +++ b/QuestPaths/7.x - Dawntrail/MSQ/E-SolutionNine-HeritageFound2/4945_The Resilient Son.json @@ -49,8 +49,10 @@ { "TerritoryId": 1191, "InteractionType": "Duty", - "ContentFinderConditionId": 825, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 825, + "Enabled": true + } } ] }, @@ -75,7 +77,13 @@ { "TerritoryId": 1220, "InteractionType": "Duty", - "ContentFinderConditionId": 995 + "DutyOptions": { + "ContentFinderConditionId": 995, + "Enabled": false, + "Notes": [ + "No VBM module" + ] + } } ] }, diff --git a/QuestPaths/7.x - Dawntrail/MSQ/F-Living Memory/4959_Dawntrail.json b/QuestPaths/7.x - Dawntrail/MSQ/F-Living Memory/4959_Dawntrail.json index cafc8975..0561e14d 100644 --- a/QuestPaths/7.x - Dawntrail/MSQ/F-Living Memory/4959_Dawntrail.json +++ b/QuestPaths/7.x - Dawntrail/MSQ/F-Living Memory/4959_Dawntrail.json @@ -56,8 +56,10 @@ { "TerritoryId": 1192, "InteractionType": "Duty", - "ContentFinderConditionId": 827, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 827, + "Enabled": true + } } ] }, @@ -82,7 +84,10 @@ { "TerritoryId": 1221, "InteractionType": "Duty", - "ContentFinderConditionId": 984 + "DutyOptions": { + "ContentFinderConditionId": 984, + "Enabled": false + } } ] }, diff --git a/QuestPaths/7.x - Dawntrail/MSQ/G-7.1/5246_In Search of the Past.json b/QuestPaths/7.x - Dawntrail/MSQ/G-7.1/5246_In Search of the Past.json index 40f6d44d..00f23c44 100644 --- a/QuestPaths/7.x - Dawntrail/MSQ/G-7.1/5246_In Search of the Past.json +++ b/QuestPaths/7.x - Dawntrail/MSQ/G-7.1/5246_In Search of the Past.json @@ -122,8 +122,14 @@ { "TerritoryId": 1191, "InteractionType": "Duty", - "ContentFinderConditionId": 1008, - "AutoDutyEnabled": true + "DutyOptions": { + "ContentFinderConditionId": 1008, + "Enabled": true, + "Notes": [ + "(boss 2) Requires vbm's auto-turn gaze option", + "(boss 3) Dashes (such as on SMN) will dash into the hole" + ] + } } ] }, diff --git a/QuestPaths/quest-v1.json b/QuestPaths/quest-v1.json index e1670a97..24116573 100644 --- a/QuestPaths/quest-v1.json +++ b/QuestPaths/quest-v1.json @@ -1238,13 +1238,35 @@ }, "then": { "properties": { - "ContentFinderConditionId": { - "type": "integer", - "exclusiveMinimum": 0, - "exclusiveMaximum": 3000 - }, - "AutoDutyEnabled": { - "type": "boolean" + "DutyOptions": { + "type": "object", + "properties": { + "ContentFinderConditionId": { + "type": "integer", + "exclusiveMinimum": 0, + "exclusiveMaximum": 3000 + }, + "Enabled": { + "type": "boolean" + }, + "Notes": { + "type": "array", + "items": { + "type": "string" + } + }, + "TestedAutoDutyVersion": { + "type": "string", + "pattern": "^0\\.\\d+\\.\\d+\\.\\d+$" + }, + "$": { + "type": "string" + } + }, + "required": [ + "ContentFinderConditionId", + "Enabled" + ] }, "DataId": { "type": "null" @@ -1254,7 +1276,7 @@ } }, "required": [ - "ContentFinderConditionId" + "DutyOptions" ] } }, diff --git a/Questionable.Model/Questing/DutyOptions.cs b/Questionable.Model/Questing/DutyOptions.cs new file mode 100644 index 00000000..12ea14e6 --- /dev/null +++ b/Questionable.Model/Questing/DutyOptions.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Questionable.Model.Questing; + +public class DutyOptions +{ + public bool Enabled { get; set; } + public uint ContentFinderConditionId { get; set; } + public List Notes { get; set; } = []; +} diff --git a/Questionable.Model/Questing/QuestStep.cs b/Questionable.Model/Questing/QuestStep.cs index c14d2e7a..26148ce2 100644 --- a/Questionable.Model/Questing/QuestStep.cs +++ b/Questionable.Model/Questing/QuestStep.cs @@ -73,8 +73,7 @@ public sealed class QuestStep public float? CombatDelaySecondsAtStart { get; set; } public JumpDestination? JumpDestination { get; set; } - public uint? ContentFinderConditionId { get; set; } - public bool AutoDutyEnabled { get; set; } + public DutyOptions? DutyOptions { get; set; } public SinglePlayerDutyOptions? SinglePlayerDutyOptions { get; set; } public byte SinglePlayerDutyIndex => SinglePlayerDutyOptions?.Index ?? 0; public SkipConditions? SkipConditions { get; set; } diff --git a/Questionable/Controller/QuestRegistry.cs b/Questionable/Controller/QuestRegistry.cs index 942a1fce..8242273f 100644 --- a/Questionable/Controller/QuestRegistry.cs +++ b/Questionable/Controller/QuestRegistry.cs @@ -165,8 +165,8 @@ internal sealed class QuestRegistry foreach (var dutyStep in quest.AllSteps().Where(x => x.Step.InteractionType is EInteractionType.Duty or EInteractionType.SinglePlayerDuty)) { - if (dutyStep.Step is { InteractionType: EInteractionType.Duty, ContentFinderConditionId: not null }) - _contentFinderConditionIds[dutyStep.Step.ContentFinderConditionId!.Value] = + if (dutyStep.Step is { InteractionType: EInteractionType.Duty, DutyOptions: { } dutyOptions }) + _contentFinderConditionIds[dutyOptions.ContentFinderConditionId] = (quest.Id, dutyStep.Step); else if (dutyStep.Step.InteractionType == EInteractionType.SinglePlayerDuty && _territoryData.TryGetContentFinderConditionForSoloInstance(quest.Id, @@ -262,15 +262,15 @@ internal sealed class QuestRegistry .ToList(); } - public bool TryGetDutyByContentFinderConditionId(uint cfcId, out bool autoDutyEnabledByDefault) + public bool TryGetDutyByContentFinderConditionId(uint cfcId, [NotNullWhen(true)] out DutyOptions? dutyOptions) { if (_contentFinderConditionIds.TryGetValue(cfcId, out var value)) { - autoDutyEnabledByDefault = value.Step.AutoDutyEnabled; - return true; + dutyOptions = value.Step.DutyOptions; + return dutyOptions != null; } - autoDutyEnabledByDefault = false; + dutyOptions = null; return false; } } diff --git a/Questionable/Controller/Steps/Common/SendNotification.cs b/Questionable/Controller/Steps/Common/SendNotification.cs index 97089936..dda03848 100644 --- a/Questionable/Controller/Steps/Common/SendNotification.cs +++ b/Questionable/Controller/Steps/Common/SendNotification.cs @@ -23,9 +23,9 @@ internal static class SendNotification { EInteractionType.Snipe when !automatonIpc.IsAutoSnipeEnabled => new Task(step.InteractionType, step.Comment), - EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled) => - new Task(step.InteractionType, step.ContentFinderConditionId.HasValue - ? territoryData.GetContentFinderCondition(step.ContentFinderConditionId.Value)?.Name + EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.DutyOptions) => + new Task(step.InteractionType, step.DutyOptions?.ContentFinderConditionId is {} contentFinderConditionId + ? territoryData.GetContentFinderCondition(contentFinderConditionId)?.Name : step.Comment), EInteractionType.SinglePlayerDuty when !bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyOptions) => new Task(step.InteractionType, quest.Info.Name), diff --git a/Questionable/Controller/Steps/Interactions/Duty.cs b/Questionable/Controller/Steps/Interactions/Duty.cs index f40c4671..250c015c 100644 --- a/Questionable/Controller/Steps/Interactions/Duty.cs +++ b/Questionable/Controller/Steps/Interactions/Duty.cs @@ -23,17 +23,17 @@ internal static class Duty if (step.InteractionType != EInteractionType.Duty) yield break; - ArgumentNullException.ThrowIfNull(step.ContentFinderConditionId); + ArgumentNullException.ThrowIfNull(step.DutyOptions); - if (autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled)) + if (autoDutyIpc.IsConfiguredToRunContent(step.DutyOptions)) { - yield return new StartAutoDutyTask(step.ContentFinderConditionId.Value); - yield return new WaitAutoDutyTask(step.ContentFinderConditionId.Value); + yield return new StartAutoDutyTask(step.DutyOptions.ContentFinderConditionId); + yield return new WaitAutoDutyTask(step.DutyOptions.ContentFinderConditionId); yield return new WaitAtEnd.WaitNextStepOrSequence(); } else { - yield return new OpenDutyFinderTask(step.ContentFinderConditionId.Value); + yield return new OpenDutyFinderTask(step.DutyOptions.ContentFinderConditionId); } } } diff --git a/Questionable/Controller/Steps/Shared/WaitAtEnd.cs b/Questionable/Controller/Steps/Shared/WaitAtEnd.cs index 86e5d47d..82decade 100644 --- a/Questionable/Controller/Steps/Shared/WaitAtEnd.cs +++ b/Questionable/Controller/Steps/Shared/WaitAtEnd.cs @@ -53,7 +53,7 @@ internal static class WaitAtEnd case EInteractionType.Snipe: return [new WaitNextStepOrSequence()]; - case EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled): + case EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.DutyOptions): case EInteractionType.SinglePlayerDuty when !bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyOptions): return [new EndAutomation()]; diff --git a/Questionable/Data/TerritoryData.cs b/Questionable/Data/TerritoryData.cs index f35f9cee..342f631d 100644 --- a/Questionable/Data/TerritoryData.cs +++ b/Questionable/Data/TerritoryData.cs @@ -19,7 +19,7 @@ internal sealed class TerritoryData private readonly ImmutableDictionary _dutyTerritories; private readonly ImmutableDictionary _instanceNames; private readonly ImmutableDictionary _contentFinderConditions; - private readonly ImmutableDictionary<(ElementId QuestId, byte Index), uint> _questsToCfc; + private readonly ImmutableDictionary<(ElementId QuestId, byte Index), uint> _questBattlesToContentFinderCondition; public TerritoryData(IDataManager dataManager) { @@ -52,7 +52,7 @@ internal sealed class TerritoryData .Select(x => new ContentFinderConditionData(x, dataManager.Language)) .ToImmutableDictionary(x => x.ContentFinderConditionId, x => x); - _questsToCfc = dataManager.GetExcelSheet() + _questBattlesToContentFinderCondition = dataManager.GetExcelSheet() .Where(x => x is { RowId: > 0, IssuerLocation.RowId: > 0 }) .SelectMany(GetQuestBattles) .Select(x => (x.QuestId, x.Index, @@ -90,7 +90,7 @@ internal sealed class TerritoryData public bool TryGetContentFinderConditionForSoloInstance(ElementId questId, byte index, [NotNullWhen(true)] out ContentFinderConditionData? contentFinderConditionData) { - if (_questsToCfc.TryGetValue((questId, index), out uint cfcId)) + if (_questBattlesToContentFinderCondition.TryGetValue((questId, index), out uint cfcId)) return _contentFinderConditions.TryGetValue(cfcId, out contentFinderConditionData); else { @@ -101,7 +101,7 @@ internal sealed class TerritoryData public IEnumerable<(ElementId QuestId, byte Index, ContentFinderConditionData Data)> GetAllQuestsWithQuestBattles() { - return _questsToCfc.Select(x => (x.Key.QuestId, x.Key.Index, _contentFinderConditions[x.Value])); + return _questBattlesToContentFinderCondition.Select(x => (x.Key.QuestId, x.Key.Index, _contentFinderConditions[x.Value])); } private static string FixName(string name, ClientLanguage language) diff --git a/Questionable/External/AutoDutyIpc.cs b/Questionable/External/AutoDutyIpc.cs index 67ea9fbd..29675cd1 100644 --- a/Questionable/External/AutoDutyIpc.cs +++ b/Questionable/External/AutoDutyIpc.cs @@ -4,6 +4,7 @@ using Dalamud.Plugin.Ipc.Exceptions; using Microsoft.Extensions.Logging; using Questionable.Controller.Steps; using Questionable.Data; +using Questionable.Model.Questing; namespace Questionable.External; @@ -31,22 +32,22 @@ internal sealed class AutoDutyIpc _stop = pluginInterface.GetIpcSubscriber("AutoDuty.Stop"); } - public bool IsConfiguredToRunContent(uint? cfcId, bool enabledByDefault) + public bool IsConfiguredToRunContent(DutyOptions? dutyOptions) { - if (cfcId == null) + if (dutyOptions == null || dutyOptions.ContentFinderConditionId == 0) return false; if (!_configuration.Duties.RunInstancedContentWithAutoDuty) return false; - if (_configuration.Duties.BlacklistedDutyCfcIds.Contains(cfcId.Value)) + if (_configuration.Duties.BlacklistedDutyCfcIds.Contains(dutyOptions.ContentFinderConditionId)) return false; - if (_configuration.Duties.WhitelistedDutyCfcIds.Contains(cfcId.Value) && - _territoryData.TryGetContentFinderCondition(cfcId.Value, out _)) + if (_configuration.Duties.WhitelistedDutyCfcIds.Contains(dutyOptions.ContentFinderConditionId) && + _territoryData.TryGetContentFinderCondition(dutyOptions.ContentFinderConditionId, out _)) return true; - return enabledByDefault && HasPath(cfcId.Value); + return dutyOptions.Enabled && HasPath(dutyOptions.ContentFinderConditionId); } public bool HasPath(uint cfcId) diff --git a/Questionable/Windows/ConfigComponents/ConfigComponent.cs b/Questionable/Windows/ConfigComponents/ConfigComponent.cs index e82cf07b..d8515634 100644 --- a/Questionable/Windows/ConfigComponents/ConfigComponent.cs +++ b/Questionable/Windows/ConfigComponents/ConfigComponent.cs @@ -1,5 +1,9 @@ +using System.Collections.Generic; using System.Text; using Dalamud.Game.Text; +using Dalamud.Interface; +using Dalamud.Interface.Colors; +using Dalamud.Interface.Utility.Raii; using Dalamud.Plugin; using ImGuiNET; @@ -61,4 +65,29 @@ internal abstract class ConfigComponent ++byteCount; return Encoding.UTF8.GetString(ptr, byteCount); } + + protected static void DrawNotes(bool enabledByDefault, IReadOnlyList notes) + { + using var color = new ImRaii.Color(); + color.Push(ImGuiCol.TextDisabled, !enabledByDefault ? ImGuiColors.DalamudYellow : ImGuiColors.ParsedBlue); + + ImGui.SameLine(); + using (ImRaii.PushFont(UiBuilder.IconFont)) + { + if (!enabledByDefault) + ImGui.TextDisabled(FontAwesomeIcon.ExclamationTriangle.ToIconString()); + else + ImGui.TextDisabled(FontAwesomeIcon.InfoCircle.ToIconString()); + } + + if (!ImGui.IsItemHovered()) + return; + + using var _ = ImRaii.Tooltip(); + + ImGui.TextColored(ImGuiColors.DalamudYellow, + "While testing, the following issues have been found:"); + foreach (string note in notes) + ImGui.BulletText(note); + } } diff --git a/Questionable/Windows/ConfigComponents/DutyConfigComponent.cs b/Questionable/Windows/ConfigComponents/DutyConfigComponent.cs index a04319e1..35f79cff 100644 --- a/Questionable/Windows/ConfigComponents/DutyConfigComponent.cs +++ b/Questionable/Windows/ConfigComponents/DutyConfigComponent.cs @@ -18,6 +18,7 @@ using Questionable.Controller; using Questionable.Data; using Questionable.External; using Questionable.Model; +using Questionable.Model.Questing; namespace Questionable.Windows.ConfigComponents; @@ -125,12 +126,11 @@ internal sealed class DutyConfigComponent : ConfigComponent { foreach (var (cfcId, territoryId, name) in cfcNames) { - if (_questRegistry.TryGetDutyByContentFinderConditionId(cfcId, - out bool autoDutyEnabledByDefault)) + if (_questRegistry.TryGetDutyByContentFinderConditionId(cfcId, out DutyOptions? dutyOptions)) { ImGui.TableNextRow(); - string[] labels = autoDutyEnabledByDefault + string[] labels = dutyOptions.Enabled ? SupportedCfcOptions : UnsupportedCfcOptions; int value = 0; @@ -159,6 +159,8 @@ internal sealed class DutyConfigComponent : ConfigComponent if (runInstancedContentWithAutoDuty && !_autoDutyIpc.HasPath(cfcId)) ImGuiComponents.HelpMarker("This duty is not supported by AutoDuty", FontAwesomeIcon.Times, ImGuiColors.DalamudRed); + else if (dutyOptions.Notes.Count > 0) + DrawNotes(dutyOptions.Enabled, dutyOptions.Notes); } if (ImGui.TableNextColumn()) diff --git a/Questionable/Windows/ConfigComponents/SinglePlayerDutyConfigComponent.cs b/Questionable/Windows/ConfigComponents/SinglePlayerDutyConfigComponent.cs index c51de1e5..637ca7aa 100644 --- a/Questionable/Windows/ConfigComponents/SinglePlayerDutyConfigComponent.cs +++ b/Questionable/Windows/ConfigComponents/SinglePlayerDutyConfigComponent.cs @@ -460,32 +460,7 @@ internal sealed class SinglePlayerDutyConfigComponent : ConfigComponent FontAwesomeIcon.Times, ImGuiColors.DalamudRed); } else if (dutyInfo.Notes.Count > 0) - { - using var color = new ImRaii.Color(); - if (!dutyInfo.EnabledByDefault) - color.Push(ImGuiCol.TextDisabled, ImGuiColors.DalamudYellow); - else - color.Push(ImGuiCol.TextDisabled, ImGuiColors.ParsedBlue); - - ImGui.SameLine(); - using (ImRaii.PushFont(UiBuilder.IconFont)) - { - if (!dutyInfo.EnabledByDefault) - ImGui.TextDisabled(FontAwesomeIcon.ExclamationTriangle.ToIconString()); - else - ImGui.TextDisabled(FontAwesomeIcon.InfoCircle.ToIconString()); - } - - if (ImGui.IsItemHovered()) - { - using var _ = ImRaii.Tooltip(); - - ImGui.TextColored(ImGuiColors.DalamudYellow, - "While testing, the following issues have been found:"); - foreach (string note in dutyInfo.Notes) - ImGui.BulletText(note); - } - } + DrawNotes(dutyInfo.EnabledByDefault, dutyInfo.Notes); } if (ImGui.TableNextColumn())