Update dungeon/trial json schema to allow notes (similar to quest battles)
authorLiza Carvelli <liza@carvel.li>
Mon, 3 Mar 2025 01:52:57 +0000 (02:52 +0100)
committerLiza Carvelli <liza@carvel.li>
Mon, 3 Mar 2025 01:53:18 +0000 (02:53 +0100)
65 files changed:
QuestPathGenerator/RoslynElements/DutyOptionsExtensions.cs [new file with mode: 0644]
QuestPathGenerator/RoslynElements/QuestStepExtensions.cs
QuestPathGenerator/RoslynShortcuts.cs
QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/245_It's Probably Pirates.json
QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/343_Lord of the Inferno.json
QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/660_Into a Copper Hell.json
QuestPaths/2.x - A Realm Reborn/MSQ-1/Shared/677_Fire in the Gloom.json
QuestPaths/2.x - A Realm Reborn/MSQ-2/A3-South Shroud, Buscarron’s Druthers/514_Into the Beast's Maw.json
QuestPaths/2.x - A Realm Reborn/MSQ-2/A9-Haukke Manor/801_Skeletons in Her Closet.json
QuestPaths/2.x - A Realm Reborn/MSQ-2/B2-Eastern La Noscea, Brayflox, Cheese and Wine/832_The Things We Do for Cheese.json
QuestPaths/2.x - A Realm Reborn/MSQ-2/B4-Titan/857_Lord of Crags.json
QuestPaths/2.x - A Realm Reborn/MSQ-2/C1-Coerthas Central Highlands, The Enterprise/952_In Pursuit of the Past.json
QuestPaths/2.x - A Realm Reborn/MSQ-2/C3-Garuda/519_Lady of the Vortex.json
QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/3873_Rock the Castrum.json
QuestPaths/2.x - A Realm Reborn/MSQ-2/C9-Ultimate Weapon/4522_The Ultimate Weapon.json
QuestPaths/2.x - A Realm Reborn/MSQ-2/E4-2.4/75_The Path of the Righteous.json
QuestPaths/2.x - A Realm Reborn/MSQ-2/E5-2.5/366_The Rising Chorus.json
QuestPaths/3.x - Heavensward/MSQ/A3.2-The Dravanian Forelands/1617_Mourn in Passing.json
QuestPaths/3.x - Heavensward/MSQ/A3.3-The Churning Mists/1634_Into the Aery.json
QuestPaths/3.x - Heavensward/MSQ/A4-Ishgard/1640_A Knight's Calling.json
QuestPaths/3.x - Heavensward/MSQ/A6-The Dravanian Hinterlands/1660_Forbidden Knowledge.json
QuestPaths/3.x - Heavensward/MSQ/A7-Azys Lla/1669_Heavensward.json
QuestPaths/3.x - Heavensward/MSQ/C-3.2/2232_The Word of the Mother.json
QuestPaths/3.x - Heavensward/MSQ/E-3.4/2342_Shadows of the First.json
QuestPaths/3.x - Heavensward/MSQ/E-3.4/2345_The Beast That Mourned at the Heart of the Mountain.json
QuestPaths/3.x - Heavensward/MSQ/F-3.5/2354_Griffin, Griffin on the Wall.json
QuestPaths/4.x - Stormblood/MSQ/A1.3-Rhalgr's Reach 2/2469_Not without Incident.json
QuestPaths/4.x - Stormblood/MSQ/A5-Yanxia 2/2524_The Die Is Cast.json
QuestPaths/4.x - Stormblood/MSQ/A6.2-Peaks 2/2544_The Price of Freedom.json
QuestPaths/4.x - Stormblood/MSQ/B-4.1/2964_The Mad King's Trove.json
QuestPaths/4.x - Stormblood/MSQ/E-4.4/3144_Feel the Burn.json
QuestPaths/4.x - Stormblood/MSQ/F-4.5/3183_The Face of War.json
QuestPaths/5.x - Shadowbringers/MSQ/A4-Crystarium 2/3300_The Lightwardens.json
QuestPaths/5.x - Shadowbringers/MSQ/B-Il Mheg/3312_The Key to the Castle.json
QuestPaths/5.x - Shadowbringers/MSQ/C-Rak'tika/3340_The Burden of Knowledge.json
QuestPaths/5.x - Shadowbringers/MSQ/E-Kholusia 2/3643_Extinguishing the Last Light.json
QuestPaths/5.x - Shadowbringers/MSQ/H-5.2/3769_Beneath the Surface.json
QuestPaths/6.x - Endwalker/MSQ/A-Thavnair1-Labyrinthos1/4377_In the Dark of the Tower.json
QuestPaths/6.x - Endwalker/MSQ/D-Thavnair2/4409_Skies Aflame.json
QuestPaths/6.x - Endwalker/MSQ/E-Elpis/4437_Caging the Messenger.json
QuestPaths/6.x - Endwalker/MSQ/F-Labyrinthos2/4449_Her Children One and All.json
QuestPaths/6.x - Endwalker/MSQ/H-6.1/4529_Alzadaals Legacy.json
QuestPaths/6.x - Endwalker/MSQ/I-6.2/4592_In Search of Azdaja.json
QuestPaths/6.x - Endwalker/MSQ/J-6.3/4674_King of the Mountain.json
QuestPaths/6.x - Endwalker/MSQ/K-6.4/4736_Going Haam.json
QuestPaths/6.x - Endwalker/MSQ/L-6.5/4748_Down in the Dark.json
QuestPaths/7.x - Dawntrail/MSQ/A-Kozama'uka1-Urqopacha1/4879_For All Turali.json
QuestPaths/7.x - Dawntrail/MSQ/B-Kozama'uka2-Urqopacha2/4891_The High Luminary.json
QuestPaths/7.x - Dawntrail/MSQ/C-Yak T'el/4909_Road to the Golden City.json
QuestPaths/7.x - Dawntrail/MSQ/D-Shaaloani-HeritageFound1/4926_All Aboard.json
QuestPaths/7.x - Dawntrail/MSQ/E-SolutionNine-HeritageFound2/4945_The Resilient Son.json
QuestPaths/7.x - Dawntrail/MSQ/F-Living Memory/4959_Dawntrail.json
QuestPaths/7.x - Dawntrail/MSQ/G-7.1/5246_In Search of the Past.json
QuestPaths/quest-v1.json
Questionable.Model/Questing/DutyOptions.cs [new file with mode: 0644]
Questionable.Model/Questing/QuestStep.cs
Questionable/Controller/QuestRegistry.cs
Questionable/Controller/Steps/Common/SendNotification.cs
Questionable/Controller/Steps/Interactions/Duty.cs
Questionable/Controller/Steps/Shared/WaitAtEnd.cs
Questionable/Data/TerritoryData.cs
Questionable/External/AutoDutyIpc.cs
Questionable/Windows/ConfigComponents/ConfigComponent.cs
Questionable/Windows/ConfigComponents/DutyConfigComponent.cs
Questionable/Windows/ConfigComponents/SinglePlayerDutyConfigComponent.cs

diff --git a/QuestPathGenerator/RoslynElements/DutyOptionsExtensions.cs b/QuestPathGenerator/RoslynElements/DutyOptionsExtensions.cs
new file mode 100644 (file)
index 0000000..c7092a4
--- /dev/null
@@ -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<ExpressionSyntax>(
+                        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()))));
+    }
+}
index 1ff4fbc1b0df1207218e412d90bc003d95c18d9b..00a36dbe7ac516433adaa34a7acfa6b70de99e32 100644 (file)
@@ -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)
index 70cae35dbca0f23ce4c2872bfb1df5ef70d9bb58..e9e07b870cd5fbc894b186a377e7eeeed872fd3a 100644 (file)
@@ -62,6 +62,7 @@ public static class RoslynShortcuts
                 ComplexCombatData complexCombatData => complexCombatData.ToExpressionSyntax(),
                 QuestWorkValue questWorkValue => questWorkValue.ToExpressionSyntax(),
                 List<QuestWorkValue> list => list.ToExpressionSyntax(), // TODO fix in AssignmentList
+                DutyOptions dutyOptions => dutyOptions.ToExpressionSyntax(),
                 SinglePlayerDutyOptions dutyOptions => dutyOptions.ToExpressionSyntax(),
                 SkipConditions skipConditions => skipConditions.ToExpressionSyntax(),
                 SkipStepConditions skipStepConditions => skipStepConditions.ToExpressionSyntax(),
index 0d3aada9033e69ee2973d5eef1f544926911046a..2104a8f028f04a1ce2830159bcacb582dc07687a 100644 (file)
         {
           "TerritoryId": 138,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 4,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 4,
+            "Enabled": true
+          }
         }
       ]
     },
index be80477d9d519b7a37b210a9d5ace7a94a87bafc..1edd6de011538660e4015f940713e06c8a3dea51 100644 (file)
         {
           "TerritoryId": 146,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 56,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 56,
+            "Enabled": true
+          }
         }
       ]
     },
index 299a07d4615e37fb3eb1530943da4241eb961e3c..ae27c13c9f21d73d171dd1918841b7c3114f5413 100644 (file)
         {
           "TerritoryId": 140,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 3,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 3,
+            "Enabled": true
+          }
         }
       ]
     },
index 726eae29145256e79ec39a0089a6848feb34a506..636b99f2ece30c20f0cbc0acd8dbcddf28ed6c4a 100644 (file)
         {
           "TerritoryId": 148,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 2,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 2,
+            "Enabled": true
+          }
         }
       ]
     },
index 45b28b3fdc642c47c0fc7bccc1bd4fbb84e1a38e..c9cb93f1c3380d3056d595edd380bbc3e10bfe41 100644 (file)
         {
           "TerritoryId": 153,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 1,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 1,
+            "Enabled": true
+          }
         }
       ]
     },
index a17b715c197d7819b5817cf41c3cd72805f287b3..e8b7817f47a3707fbefaa5b42f8600dfb26acd24 100644 (file)
         {
           "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"
+            ]
+          }
         }
       ]
     },
index 960ac4ec6f4cb74c0f48cec9c29d58d24514459c..69c77dced6a7c59c1dcf63f9cfc9c6fd9b5eab52 100644 (file)
         {
           "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"
+            ]
+          }
         }
       ]
     },
index 4cc4c5768b02d7c83374371a901ab7f58de6722e..b3516cdea3eb6c1a36891407de211d4d6bb55032 100644 (file)
         {
           "TerritoryId": 139,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 57,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 57,
+            "Enabled": true
+          }
         }
       ]
     },
index 57ef1fa996b6ea163ecb71dc71e1500b22be5b92..a9844776c0e53baa82a16f71d80e0e156177b6f5 100644 (file)
         {
           "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"
+            ]
+          }
         }
       ]
     },
index d9315eca218d283fd20745a059d02595815d5923..bb48332f181c5e4a1f5471e76a482dfe04edde4b 100644 (file)
         {
           "TerritoryId": 331,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 58,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 58,
+            "Enabled": true
+          }
         }
       ]
     },
index dba66d15cda73e2d22651296723d7be3e10d4582..d4914c2cbf33d007c88f3bf4e8b6050ce6abd644 100644 (file)
         {
           "TerritoryId": 147,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 15,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 15,
+            "Enabled": true
+          }
         }
       ]
     },
index 8122668a95f0d111552cdc3f92b9b442d0bcc3f3..aad57d7caa71112190dd32a911b2cefe06534250 100644 (file)
         {
           "TerritoryId": 147,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 16,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 16,
+            "Enabled": true
+          }
         }
       ]
     },
         {
           "TerritoryId": 1053,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 830,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 830,
+            "Enabled": true
+          }
         }
       ]
     },
index b6581b9a845373dc67ab4f00fba88293419d9f93..e8534c387d8d540a25d0958c10d36b15fb505104 100644 (file)
         {
           "TerritoryId": 155,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 27,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 27,
+            "Enabled": true
+          }
         }
       ]
     },
index 24d72b21450e123b90b1dc9ea4791494ed16f5fd..235ab5e60df3d4dfcd26e84c9fdb89cff4bb955a 100644 (file)
         {
           "TerritoryId": 156,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 32,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 32,
+            "Enabled": true
+          }
         }
       ]
     },
index a321c741548f0f4cff34c28f38dae7781778e856..df6d17db511d6afaa6ac6bfda3a2468d17e7c229 100644 (file)
         {
           "TerritoryId": 398,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 37,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 37,
+            "Enabled": true
+          }
         }
       ]
     },
index 02098cab905e6fd7fa8a504e2f55fc3cc3ff39c7..97ead078ac7016314517ee0fcef9c902742a1a0a 100644 (file)
         {
           "TerritoryId": 418,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 39,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 39,
+            "Enabled": true
+          }
         }
       ]
     },
index 9165e2a02cb358db79e12c50cb17265b1be776de..da55ca4199f57fb98ef2504548ee13bfe77b0619 100644 (file)
         {
           "TerritoryId": 419,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 34,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 34,
+            "Enabled": true
+          }
         }
       ]
     },
index dab4f3da34b3eb2ab4cc8ffa5e322fcfc5675364..6c94266ae5c7c0c0f52fd99d5bbe1d2b4ebce82b 100644 (file)
         {
           "TerritoryId": 399,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 31,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 31,
+            "Enabled": true
+          }
         }
       ]
     },
index 7bef51cc73884a2d985c283e59a7a5f999b8b88d..215f1849c4e0e0a3f707c480d894d46e2f8374a1 100644 (file)
         {
           "TerritoryId": 402,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 38,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 38,
+            "Enabled": true
+          }
         }
       ]
     },
         {
           "TerritoryId": 402,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 90
+          "DutyOptions": {
+            "ContentFinderConditionId": 90,
+            "Enabled": false
+          }
         }
       ]
     },
index fe2c33676b24ca535d28b998ba2da7d9811ce97f..f6016328caaff463f2de1d74a36f463728945578 100644 (file)
         {
           "TerritoryId": 463,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 141,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 141,
+            "Enabled": true,
+            "TestedAutoDutyVersion": "0.0.0.191"
+          }
         }
       ]
     },
index 3cee72be72b23f9da4bbf71510a34725f3f86a17..7821fc99dd7cc94823b632a524cf0c8cb5c8dc8e 100644 (file)
         {
           "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"
+            ]
+          }
         }
       ]
     },
index b04f3f54771b26a8f331229feed6ff1d5038322a..00e0988e65aaa6972e0348368fb444b31c9a136c 100644 (file)
         {
           "TerritoryId": 180,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 60
+          "DutyOptions": {
+            "ContentFinderConditionId": 60,
+            "Enabled": false
+          }
         }
       ]
     },
index 42aef1f00d79e91c30d3f0c45d6d23e64b82a516..9d1c4d89df13a44b1709dab459d3b5c560c9f8fc 100644 (file)
         {
           "TerritoryId": 152,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 219,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 219,
+            "Enabled": true
+          }
         }
       ]
     },
index 6477857e4c764af851a44068ce355822c028ad1b..c5d3ef594f110dafb60d2fb74636ba34ad7219f1 100644 (file)
         {
           "TerritoryId": 680,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 238,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 238,
+            "Enabled": true
+          }
         }
       ]
     },
index 702737b31c46b0d4bc3dde9d1f680e43c3593380..eacefe65c5286ba76338eadfd03e270eee4cdc87 100644 (file)
         {
           "TerritoryId": 614,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 241,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 241,
+            "Enabled": true
+          }
         }
       ]
     },
index a0b37e35011249a74ca9f19d8c300871abb40715..798f15a1aeb186dd7094860f9860f0185a031764 100644 (file)
         {
           "TerritoryId": 620,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 242,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 242,
+            "Enabled": true
+          }
         }
       ]
     },
index 0856bbe6f830b0969e230791c883e415b28b925c..02436aeb8b69968ac2f0296a62b48cfa6f3a5f2f 100644 (file)
         {\r
           "TerritoryId": 621,\r
           "InteractionType": "Duty",\r
-          "ContentFinderConditionId": 279,\r
-          "AutoDutyEnabled": true\r
+          "DutyOptions": {\r
+            "ContentFinderConditionId": 279,\r
+            "Enabled": true\r
+          }\r
         }\r
       ]\r
     },\r
index fba0763d8d133d7d2fc50df886ffdd232cb1c2ed..1757d8031637d764c90b4ba07fa08d60fe548d65 100644 (file)
         {
           "TerritoryId": 614,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 585,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 585,
+            "Enabled": true
+          }
         }
       ]
     },
index fb9960de05dd45cbdebe87bde6923687c3c54dcc..0dcf29886434e116d12555b53e20cfba7c8c8bba 100644 (file)
         {
           "TerritoryId": 829,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 611,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 611,
+            "Enabled": true
+          }
         }
       ]
     },
index 7f9a5a9484b293186b80cb1bab914ef037ee413f..de440ed2d0001570edbdf89e39e086d06c1896a4 100644 (file)
         {
           "TerritoryId": 813,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 676,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 676,
+            "Enabled": true
+          }
         }
       ]
     },
index d1dfe7dcffb54586b63c376fd75f2b6dd9c37b63..ea66e5a68dc4ec49cb1d3a042eba26870fa63bf9 100644 (file)
         {
           "TerritoryId": 816,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 649,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 649,
+            "Enabled": true
+          }
         }
       ]
     },
index 39284d2f79f8983c93e2f6a5f7d1f73ceb2d3321..8a07ab80a336ba4393f4782457af45d454c7a677 100644 (file)
         {
           "TerritoryId": 817,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 651,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 651,
+            "Enabled": true
+          }
         }
       ]
     },
index 80cbd172fd0e382bd9d0b7160d3c6fcfd976a9e0..ef9aa4df009cd2d2a72f786be0f9acc28eb7a00c 100644 (file)
         {
           "TerritoryId": 814,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 659,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 659,
+            "Enabled": true
+          }
         }
       ]
     },
         {
           "TerritoryId": 880,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 666
+          "DutyOptions": {
+            "ContentFinderConditionId": 666,
+            "Enabled": false
+          }
         }
       ]
     },
index 41dd831524035e697f0877dd19b138b5b50fbfe3..61a471aa1a8b19b342e949d785c2c1891fc1e141 100644 (file)
         {
           "TerritoryId": 814,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 714,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 714,
+            "Enabled": true
+          }
         }
       ]
     },
index c4336959cf18b27641ca57b340de03f6ea5c205e..d07dba7e15ac47e47c45811e874a13c455fbb873 100644 (file)
         {
           "TerritoryId": 957,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 783,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 783,
+            "Enabled": true
+          }
         }
       ]
     },
index 9c0d3a4875b132022e2cece8b23546bf660d8f87..21ad7d9eafa420a4488b1c58ad1f2ef4833a1da9 100644 (file)
         {
           "TerritoryId": 957,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 789,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 789,
+            "Enabled": true
+          }
         }
       ]
     },
index 9dd680ebdc5b0081a8ba1a7954c84b5cb4a81626..89c6fc549333e563dc203262cb009e9793c596d5 100644 (file)
         {
           "TerritoryId": 961,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 787,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 787,
+            "Enabled": true
+          }
         }
       ]
     },
index 74943745730f0ee2496ee1fda7150f5da45fc6d3..fc0aac0ac480907064cdf23cd2a2a9d9b6df8d37 100644 (file)
         {
           "TerritoryId": 956,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 786,
-          "AutoDutyEnabled": false
+          "DutyOptions": {
+            "ContentFinderConditionId": 786,
+            "Enabled": false,
+            "Notes": [
+              "No VBM module"
+            ]
+          }
         }
       ]
     },
         {
           "TerritoryId": 1030,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 790,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 790,
+            "Enabled": true
+          }
         }
       ]
     },
index dc9324d1d674ca316a62b35af28307e11cf31c98..8638a86c455bbd95a80b7ab0ea22554cedc64b1b 100644 (file)
         {
           "TerritoryId": 957,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 844,
-          "AutoDutyEnabled": false
+          "DutyOptions": {
+            "ContentFinderConditionId": 844,
+            "Enabled": false,
+            "Notes": [
+              "No VBM module"
+            ]
+          }
         }
       ]
     },
index c91af5976cd2aca77ec40c33148977403520a2ff..561b1903182274507667a281ea13f1126d03a792 100644 (file)
         {
           "TerritoryId": 1056,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 869,
-          "AutoDutyEnabled": false
+          "DutyOptions": {
+            "ContentFinderConditionId": 869,
+            "Enabled": false,
+            "Notes": [
+              "No VBM module"
+            ]
+          }
         }
       ]
     },
index df1bd69f0f7df04d37a2fe77dadf324fea96f70c..14c3171c8103bd9b97785c61ee343eaefbe108a2 100644 (file)
         {
           "TerritoryId": 958,
           "InteractionType": "Duty",
-          "Comment": "Lapis Manalis",
-          "ContentFinderConditionId": 896,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 896,
+            "Enabled": true
+          }
         }
       ]
     },
index 8af360800cd71bd26c519db9453a12c7763175ed..30fa509b240c8f3fe7e8dcc6d4615089f203f261 100644 (file)
         {
           "TerritoryId": 962,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 822,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 822,
+            "Enabled": false,
+            "Notes": [
+              "Navigation issues for area transitions"
+            ]
+          }
         }
       ]
     },
index 96953ea2776b3e82ee6b81adef482bde03421553..8b1016df34c4bf627591680cac3b7b5c4bf1943e 100644 (file)
         {
           "TerritoryId": 1162,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 823,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 823,
+            "Enabled": true
+          }
         }
       ]
     },
index 28a6850cd69fd2e701126216a76b770135a75e19..986d7526e8a280c1879d7a97f0fbb669d55f61dc 100644 (file)
         {
           "TerritoryId": 1185,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 826,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 826,
+            "Enabled": true
+          }
         }
       ]
     },
index 2ef3a8e69877dc92c9f4ac3edea0dd66d483e692..39268a033b37d0b856cba6fec011c3bd00585266 100644 (file)
         {
           "TerritoryId": 1187,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 824,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 824,
+            "Enabled": true
+          }
         }
       ]
     },
index 528fde3f8830528fc51e476bc32dbc929c109ed4..9a1488ed33112d0f0813d30a529a789dff002aae 100644 (file)
         {
           "TerritoryId": 1189,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 829,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 829,
+            "Enabled": true
+          }
         }
       ]
     },
index 682576cb38d8f2eb2b6055df4568ba3764aca129..5c83c615de0006b9d0cb2e8511327b38e3f7c395 100644 (file)
         {
           "TerritoryId": 1219,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 831,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 831,
+            "Enabled": true
+          }
         }
       ]
     },
index 738c8782160bfb12bfaec9105ae2d285866d0e5c..e57ca85282e05d8b953fe427ab50309610375e0d 100644 (file)
         {
           "TerritoryId": 1191,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 825,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 825,
+            "Enabled": true
+          }
         }
       ]
     },
         {
           "TerritoryId": 1220,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 995
+          "DutyOptions": {
+            "ContentFinderConditionId": 995,
+            "Enabled": false,
+            "Notes": [
+              "No VBM module"
+            ]
+          }
         }
       ]
     },
index cafc8975c2f2937c0beeb174b3390df31f63d93b..0561e14d86414e10524e929ed3a0fdccfe288cd4 100644 (file)
         {
           "TerritoryId": 1192,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 827,
-          "AutoDutyEnabled": true
+          "DutyOptions": {
+            "ContentFinderConditionId": 827,
+            "Enabled": true
+          }
         }
       ]
     },
         {
           "TerritoryId": 1221,
           "InteractionType": "Duty",
-          "ContentFinderConditionId": 984
+          "DutyOptions": {
+            "ContentFinderConditionId": 984,
+            "Enabled": false
+          }
         }
       ]
     },
index 40f6d44d7eefd739d13bb137b7634f8df01f3dd4..00f23c4426749c7cb77c89188516b8798e5b0621 100644 (file)
         {
           "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"
+            ]
+          }
         }
       ]
     },
index e1670a970805c273a8834a99a036c17f14da2f14..2411657367f23ef26123bacdb88f7a7e2e06a7bb 100644 (file)
           },
           "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"
               }
             },
             "required": [
-              "ContentFinderConditionId"
+              "DutyOptions"
             ]
           }
         },
diff --git a/Questionable.Model/Questing/DutyOptions.cs b/Questionable.Model/Questing/DutyOptions.cs
new file mode 100644 (file)
index 0000000..12ea14e
--- /dev/null
@@ -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<string> Notes { get; set; } = [];
+}
index c14d2e7a82c0f128f0115a703eda594e93c3e7f0..26148ce26a31fc9375f72d2d68c37d57069915c9 100644 (file)
@@ -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; }
index 942a1fceb0ca80b051bb7b0f2a30f1cc1d6cc57a..8242273f316a40ead475b308ab0d14bbea39c956 100644 (file)
@@ -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;
     }
 }
index 97089936ce9ae73e7f65644e824b122982758284..dda0384832a10781468727fa71ad7ac38de73995 100644 (file)
@@ -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),
index f40c4671da73b17891ae41f2ad152e31b381fc80..250c015c79999960a3e1ae74546c7986cab499bc 100644 (file)
@@ -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);
             }
         }
     }
index 86e5d47d4c4146dcb4dc881ed3cd6ea7604d8a64..82decade910950b748f0917462450685c0c76d08 100644 (file)
@@ -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()];
 
index f35f9cee7e4db1ac4f65af6ab6e98a56ce5f44ad..342f631d48b2dca7a702c8956270161c76db7084 100644 (file)
@@ -19,7 +19,7 @@ internal sealed class TerritoryData
     private readonly ImmutableDictionary<ushort, uint> _dutyTerritories;
     private readonly ImmutableDictionary<uint, string> _instanceNames;
     private readonly ImmutableDictionary<uint, ContentFinderConditionData> _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<Quest>()
+        _questBattlesToContentFinderCondition = dataManager.GetExcelSheet<Quest>()
             .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)
index 67ea9fbddc61606a5a8139df9a83ad753ecf0ca8..29675cd1eb84f82208e8ea98c69479e22ce3d504 100644 (file)
@@ -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<object>("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)
index e82cf07b6729a7bdc86247f9b81c05d9b4f3bc0c..d8515634b2e508391fd3b1883d8681e6d00935c6 100644 (file)
@@ -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<string> 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);
+    }
 }
index a04319e1f0ec90f31a4a787b5a85742069c69f81..35f79cff1cafb4d24368c9b848abf64f5fd8cae2 100644 (file)
@@ -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())
index c51de1e5ef5ba690575716689af27a33873530f1..637ca7aab92575f0fa116759b92a7b3c14ad304e 100644 (file)
@@ -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())