Update dungeon/trial json schema to allow notes (similar to quest battles)

This commit is contained in:
Liza 2025-03-03 02:52:57 +01:00
parent 6c27b7d85e
commit 5c904d6cb3
Signed by: liza
GPG Key ID: 2C41B84815CF6445
65 changed files with 393 additions and 177 deletions

View File

@ -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()))));
}
}

View File

@ -117,11 +117,8 @@ internal static class QuestStepExtensions
Assignment(nameof(QuestStep.JumpDestination), step.JumpDestination, Assignment(nameof(QuestStep.JumpDestination), step.JumpDestination,
emptyStep.JumpDestination) emptyStep.JumpDestination)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.ContentFinderConditionId), Assignment(nameof(QuestStep.DutyOptions), step.DutyOptions,
step.ContentFinderConditionId, emptyStep.ContentFinderConditionId) emptyStep.DutyOptions)
.AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.AutoDutyEnabled),
step.AutoDutyEnabled, emptyStep.AutoDutyEnabled)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.SinglePlayerDutyOptions), step.SinglePlayerDutyOptions, Assignment(nameof(QuestStep.SinglePlayerDutyOptions), step.SinglePlayerDutyOptions,
emptyStep.SinglePlayerDutyOptions) emptyStep.SinglePlayerDutyOptions)

View File

@ -62,6 +62,7 @@ public static class RoslynShortcuts
ComplexCombatData complexCombatData => complexCombatData.ToExpressionSyntax(), ComplexCombatData complexCombatData => complexCombatData.ToExpressionSyntax(),
QuestWorkValue questWorkValue => questWorkValue.ToExpressionSyntax(), QuestWorkValue questWorkValue => questWorkValue.ToExpressionSyntax(),
List<QuestWorkValue> list => list.ToExpressionSyntax(), // TODO fix in AssignmentList List<QuestWorkValue> list => list.ToExpressionSyntax(), // TODO fix in AssignmentList
DutyOptions dutyOptions => dutyOptions.ToExpressionSyntax(),
SinglePlayerDutyOptions dutyOptions => dutyOptions.ToExpressionSyntax(), SinglePlayerDutyOptions dutyOptions => dutyOptions.ToExpressionSyntax(),
SkipConditions skipConditions => skipConditions.ToExpressionSyntax(), SkipConditions skipConditions => skipConditions.ToExpressionSyntax(),
SkipStepConditions skipStepConditions => skipStepConditions.ToExpressionSyntax(), SkipStepConditions skipStepConditions => skipStepConditions.ToExpressionSyntax(),

View File

@ -112,8 +112,10 @@
{ {
"TerritoryId": 138, "TerritoryId": 138,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 4, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 4,
"Enabled": true
}
} }
] ]
}, },

View File

@ -75,8 +75,10 @@
{ {
"TerritoryId": 146, "TerritoryId": 146,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 56, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 56,
"Enabled": true
}
} }
] ]
}, },

View File

@ -62,8 +62,10 @@
{ {
"TerritoryId": 140, "TerritoryId": 140,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 3, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 3,
"Enabled": true
}
} }
] ]
}, },

View File

@ -57,8 +57,10 @@
{ {
"TerritoryId": 148, "TerritoryId": 148,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 2, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 2,
"Enabled": true
}
} }
] ]
}, },

View File

@ -44,8 +44,10 @@
{ {
"TerritoryId": 153, "TerritoryId": 153,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 1, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 1,
"Enabled": true
}
} }
] ]
}, },

View File

@ -66,8 +66,13 @@
{ {
"TerritoryId": 148, "TerritoryId": 148,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 6, "DutyOptions": {
"AutoDutyEnabled": false "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"
]
}
} }
] ]
}, },

View File

@ -85,8 +85,13 @@
{ {
"TerritoryId": 137, "TerritoryId": 137,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 8, "DutyOptions": {
"AutoDutyEnabled": false "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"
]
}
} }
] ]
}, },

View File

@ -45,8 +45,10 @@
{ {
"TerritoryId": 139, "TerritoryId": 139,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 57, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 57,
"Enabled": true
}
} }
] ]
}, },

View File

@ -59,8 +59,14 @@
{ {
"TerritoryId": 155, "TerritoryId": 155,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 11, "DutyOptions": {
"AutoDutyEnabled": true "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"
]
}
} }
] ]
}, },

View File

@ -38,8 +38,10 @@
{ {
"TerritoryId": 331, "TerritoryId": 331,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 58, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 58,
"Enabled": true
}
} }
] ]
}, },

View File

@ -195,8 +195,10 @@
{ {
"TerritoryId": 147, "TerritoryId": 147,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 15, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 15,
"Enabled": true
}
} }
] ]
}, },

View File

@ -46,8 +46,10 @@
{ {
"TerritoryId": 147, "TerritoryId": 147,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 16, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 16,
"Enabled": true
}
} }
] ]
}, },
@ -72,8 +74,10 @@
{ {
"TerritoryId": 1053, "TerritoryId": 1053,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 830, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 830,
"Enabled": true
}
} }
] ]
}, },

View File

@ -88,8 +88,10 @@
{ {
"TerritoryId": 155, "TerritoryId": 155,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 27, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 27,
"Enabled": true
}
} }
] ]
}, },

View File

@ -107,8 +107,10 @@
{ {
"TerritoryId": 156, "TerritoryId": 156,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 32, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 32,
"Enabled": true
}
} }
] ]
}, },

View File

@ -78,8 +78,10 @@
{ {
"TerritoryId": 398, "TerritoryId": 398,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 37, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 37,
"Enabled": true
}
} }
] ]
}, },

View File

@ -42,8 +42,10 @@
{ {
"TerritoryId": 418, "TerritoryId": 418,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 39, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 39,
"Enabled": true
}
} }
] ]
}, },

View File

@ -59,8 +59,10 @@
{ {
"TerritoryId": 419, "TerritoryId": 419,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 34, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 34,
"Enabled": true
}
} }
] ]
}, },

View File

@ -110,8 +110,10 @@
{ {
"TerritoryId": 399, "TerritoryId": 399,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 31, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 31,
"Enabled": true
}
} }
] ]
}, },

View File

@ -62,8 +62,10 @@
{ {
"TerritoryId": 402, "TerritoryId": 402,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 38, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 38,
"Enabled": true
}
} }
] ]
}, },
@ -88,7 +90,10 @@
{ {
"TerritoryId": 402, "TerritoryId": 402,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 90 "DutyOptions": {
"ContentFinderConditionId": 90,
"Enabled": false
}
} }
] ]
}, },

View File

@ -77,8 +77,11 @@
{ {
"TerritoryId": 463, "TerritoryId": 463,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 141, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 141,
"Enabled": true,
"TestedAutoDutyVersion": "0.0.0.191"
}
} }
] ]
}, },

View File

@ -57,8 +57,14 @@
{ {
"TerritoryId": 155, "TerritoryId": 155,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 182, "DutyOptions": {
"AutoDutyEnabled": false "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"
]
}
} }
] ]
}, },

View File

@ -198,7 +198,10 @@
{ {
"TerritoryId": 180, "TerritoryId": 180,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 60 "DutyOptions": {
"ContentFinderConditionId": 60,
"Enabled": false
}
} }
] ]
}, },

View File

@ -109,8 +109,10 @@
{ {
"TerritoryId": 152, "TerritoryId": 152,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 219, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 219,
"Enabled": true
}
} }
] ]
}, },

View File

@ -87,8 +87,10 @@
{ {
"TerritoryId": 680, "TerritoryId": 680,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 238, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 238,
"Enabled": true
}
} }
] ]
}, },

View File

@ -114,8 +114,10 @@
{ {
"TerritoryId": 614, "TerritoryId": 614,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 241, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 241,
"Enabled": true
}
} }
] ]
}, },

View File

@ -114,8 +114,10 @@
{ {
"TerritoryId": 620, "TerritoryId": 620,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 242, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 242,
"Enabled": true
}
} }
] ]
}, },

View File

@ -98,8 +98,10 @@
{ {
"TerritoryId": 621, "TerritoryId": 621,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 279, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 279,
"Enabled": true
}
} }
] ]
}, },

View File

@ -40,8 +40,10 @@
{ {
"TerritoryId": 614, "TerritoryId": 614,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 585, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 585,
"Enabled": true
}
} }
] ]
}, },

View File

@ -27,8 +27,10 @@
{ {
"TerritoryId": 829, "TerritoryId": 829,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 611, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 611,
"Enabled": true
}
} }
] ]
}, },

View File

@ -120,8 +120,10 @@
{ {
"TerritoryId": 813, "TerritoryId": 813,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 676, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 676,
"Enabled": true
}
} }
] ]
}, },

View File

@ -49,8 +49,10 @@
{ {
"TerritoryId": 816, "TerritoryId": 816,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 649, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 649,
"Enabled": true
}
} }
] ]
}, },

View File

@ -61,8 +61,10 @@
{ {
"TerritoryId": 817, "TerritoryId": 817,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 651, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 651,
"Enabled": true
}
} }
] ]
}, },

View File

@ -62,8 +62,10 @@
{ {
"TerritoryId": 814, "TerritoryId": 814,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 659, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 659,
"Enabled": true
}
} }
] ]
}, },
@ -88,7 +90,10 @@
{ {
"TerritoryId": 880, "TerritoryId": 880,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 666 "DutyOptions": {
"ContentFinderConditionId": 666,
"Enabled": false
}
} }
] ]
}, },

View File

@ -40,8 +40,10 @@
{ {
"TerritoryId": 814, "TerritoryId": 814,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 714, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 714,
"Enabled": true
}
} }
] ]
}, },

View File

@ -55,8 +55,10 @@
{ {
"TerritoryId": 957, "TerritoryId": 957,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 783, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 783,
"Enabled": true
}
} }
] ]
}, },

View File

@ -71,8 +71,10 @@
{ {
"TerritoryId": 957, "TerritoryId": 957,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 789, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 789,
"Enabled": true
}
} }
] ]
}, },

View File

@ -39,8 +39,10 @@
{ {
"TerritoryId": 961, "TerritoryId": 961,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 787, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 787,
"Enabled": true
}
} }
] ]
}, },

View File

@ -38,8 +38,13 @@
{ {
"TerritoryId": 956, "TerritoryId": 956,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 786, "DutyOptions": {
"AutoDutyEnabled": false "ContentFinderConditionId": 786,
"Enabled": false,
"Notes": [
"No VBM module"
]
}
} }
] ]
}, },
@ -64,8 +69,10 @@
{ {
"TerritoryId": 1030, "TerritoryId": 1030,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 790, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 790,
"Enabled": true
}
} }
] ]
}, },

View File

@ -23,8 +23,13 @@
{ {
"TerritoryId": 957, "TerritoryId": 957,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 844, "DutyOptions": {
"AutoDutyEnabled": false "ContentFinderConditionId": 844,
"Enabled": false,
"Notes": [
"No VBM module"
]
}
} }
] ]
}, },

View File

@ -71,8 +71,13 @@
{ {
"TerritoryId": 1056, "TerritoryId": 1056,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 869, "DutyOptions": {
"AutoDutyEnabled": false "ContentFinderConditionId": 869,
"Enabled": false,
"Notes": [
"No VBM module"
]
}
} }
] ]
}, },

View File

@ -56,9 +56,10 @@
{ {
"TerritoryId": 958, "TerritoryId": 958,
"InteractionType": "Duty", "InteractionType": "Duty",
"Comment": "Lapis Manalis", "DutyOptions": {
"ContentFinderConditionId": 896, "ContentFinderConditionId": 896,
"AutoDutyEnabled": true "Enabled": true
}
} }
] ]
}, },

View File

@ -160,8 +160,13 @@
{ {
"TerritoryId": 962, "TerritoryId": 962,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 822, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 822,
"Enabled": false,
"Notes": [
"Navigation issues for area transitions"
]
}
} }
] ]
}, },

View File

@ -24,8 +24,10 @@
{ {
"TerritoryId": 1162, "TerritoryId": 1162,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 823, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 823,
"Enabled": true
}
} }
] ]
}, },

View File

@ -58,8 +58,10 @@
{ {
"TerritoryId": 1185, "TerritoryId": 1185,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 826, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 826,
"Enabled": true
}
} }
] ]
}, },

View File

@ -23,8 +23,10 @@
{ {
"TerritoryId": 1187, "TerritoryId": 1187,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 824, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 824,
"Enabled": true
}
} }
] ]
}, },

View File

@ -115,8 +115,10 @@
{ {
"TerritoryId": 1189, "TerritoryId": 1189,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 829, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 829,
"Enabled": true
}
} }
] ]
}, },

View File

@ -60,8 +60,10 @@
{ {
"TerritoryId": 1219, "TerritoryId": 1219,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 831, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 831,
"Enabled": true
}
} }
] ]
}, },

View File

@ -49,8 +49,10 @@
{ {
"TerritoryId": 1191, "TerritoryId": 1191,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 825, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 825,
"Enabled": true
}
} }
] ]
}, },
@ -75,7 +77,13 @@
{ {
"TerritoryId": 1220, "TerritoryId": 1220,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 995 "DutyOptions": {
"ContentFinderConditionId": 995,
"Enabled": false,
"Notes": [
"No VBM module"
]
}
} }
] ]
}, },

View File

@ -56,8 +56,10 @@
{ {
"TerritoryId": 1192, "TerritoryId": 1192,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 827, "DutyOptions": {
"AutoDutyEnabled": true "ContentFinderConditionId": 827,
"Enabled": true
}
} }
] ]
}, },
@ -82,7 +84,10 @@
{ {
"TerritoryId": 1221, "TerritoryId": 1221,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 984 "DutyOptions": {
"ContentFinderConditionId": 984,
"Enabled": false
}
} }
] ]
}, },

View File

@ -122,8 +122,14 @@
{ {
"TerritoryId": 1191, "TerritoryId": 1191,
"InteractionType": "Duty", "InteractionType": "Duty",
"ContentFinderConditionId": 1008, "DutyOptions": {
"AutoDutyEnabled": true "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"
]
}
} }
] ]
}, },

View File

@ -1238,13 +1238,35 @@
}, },
"then": { "then": {
"properties": { "properties": {
"ContentFinderConditionId": { "DutyOptions": {
"type": "integer", "type": "object",
"exclusiveMinimum": 0, "properties": {
"exclusiveMaximum": 3000 "ContentFinderConditionId": {
}, "type": "integer",
"AutoDutyEnabled": { "exclusiveMinimum": 0,
"type": "boolean" "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": { "DataId": {
"type": "null" "type": "null"
@ -1254,7 +1276,7 @@
} }
}, },
"required": [ "required": [
"ContentFinderConditionId" "DutyOptions"
] ]
} }
}, },

View File

@ -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; } = [];
}

View File

@ -73,8 +73,7 @@ public sealed class QuestStep
public float? CombatDelaySecondsAtStart { get; set; } public float? CombatDelaySecondsAtStart { get; set; }
public JumpDestination? JumpDestination { get; set; } public JumpDestination? JumpDestination { get; set; }
public uint? ContentFinderConditionId { get; set; } public DutyOptions? DutyOptions { get; set; }
public bool AutoDutyEnabled { get; set; }
public SinglePlayerDutyOptions? SinglePlayerDutyOptions { get; set; } public SinglePlayerDutyOptions? SinglePlayerDutyOptions { get; set; }
public byte SinglePlayerDutyIndex => SinglePlayerDutyOptions?.Index ?? 0; public byte SinglePlayerDutyIndex => SinglePlayerDutyOptions?.Index ?? 0;
public SkipConditions? SkipConditions { get; set; } public SkipConditions? SkipConditions { get; set; }

View File

@ -165,8 +165,8 @@ internal sealed class QuestRegistry
foreach (var dutyStep in quest.AllSteps().Where(x => foreach (var dutyStep in quest.AllSteps().Where(x =>
x.Step.InteractionType is EInteractionType.Duty or EInteractionType.SinglePlayerDuty)) x.Step.InteractionType is EInteractionType.Duty or EInteractionType.SinglePlayerDuty))
{ {
if (dutyStep.Step is { InteractionType: EInteractionType.Duty, ContentFinderConditionId: not null }) if (dutyStep.Step is { InteractionType: EInteractionType.Duty, DutyOptions: { } dutyOptions })
_contentFinderConditionIds[dutyStep.Step.ContentFinderConditionId!.Value] = _contentFinderConditionIds[dutyOptions.ContentFinderConditionId] =
(quest.Id, dutyStep.Step); (quest.Id, dutyStep.Step);
else if (dutyStep.Step.InteractionType == EInteractionType.SinglePlayerDuty && else if (dutyStep.Step.InteractionType == EInteractionType.SinglePlayerDuty &&
_territoryData.TryGetContentFinderConditionForSoloInstance(quest.Id, _territoryData.TryGetContentFinderConditionForSoloInstance(quest.Id,
@ -262,15 +262,15 @@ internal sealed class QuestRegistry
.ToList(); .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)) if (_contentFinderConditionIds.TryGetValue(cfcId, out var value))
{ {
autoDutyEnabledByDefault = value.Step.AutoDutyEnabled; dutyOptions = value.Step.DutyOptions;
return true; return dutyOptions != null;
} }
autoDutyEnabledByDefault = false; dutyOptions = null;
return false; return false;
} }
} }

View File

@ -23,9 +23,9 @@ internal static class SendNotification
{ {
EInteractionType.Snipe when !automatonIpc.IsAutoSnipeEnabled => EInteractionType.Snipe when !automatonIpc.IsAutoSnipeEnabled =>
new Task(step.InteractionType, step.Comment), new Task(step.InteractionType, step.Comment),
EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled) => EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.DutyOptions) =>
new Task(step.InteractionType, step.ContentFinderConditionId.HasValue new Task(step.InteractionType, step.DutyOptions?.ContentFinderConditionId is {} contentFinderConditionId
? territoryData.GetContentFinderCondition(step.ContentFinderConditionId.Value)?.Name ? territoryData.GetContentFinderCondition(contentFinderConditionId)?.Name
: step.Comment), : step.Comment),
EInteractionType.SinglePlayerDuty when !bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyOptions) => EInteractionType.SinglePlayerDuty when !bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyOptions) =>
new Task(step.InteractionType, quest.Info.Name), new Task(step.InteractionType, quest.Info.Name),

View File

@ -23,17 +23,17 @@ internal static class Duty
if (step.InteractionType != EInteractionType.Duty) if (step.InteractionType != EInteractionType.Duty)
yield break; 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 StartAutoDutyTask(step.DutyOptions.ContentFinderConditionId);
yield return new WaitAutoDutyTask(step.ContentFinderConditionId.Value); yield return new WaitAutoDutyTask(step.DutyOptions.ContentFinderConditionId);
yield return new WaitAtEnd.WaitNextStepOrSequence(); yield return new WaitAtEnd.WaitNextStepOrSequence();
} }
else else
{ {
yield return new OpenDutyFinderTask(step.ContentFinderConditionId.Value); yield return new OpenDutyFinderTask(step.DutyOptions.ContentFinderConditionId);
} }
} }
} }

View File

@ -53,7 +53,7 @@ internal static class WaitAtEnd
case EInteractionType.Snipe: case EInteractionType.Snipe:
return [new WaitNextStepOrSequence()]; 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): case EInteractionType.SinglePlayerDuty when !bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyOptions):
return [new EndAutomation()]; return [new EndAutomation()];

View File

@ -19,7 +19,7 @@ internal sealed class TerritoryData
private readonly ImmutableDictionary<ushort, uint> _dutyTerritories; private readonly ImmutableDictionary<ushort, uint> _dutyTerritories;
private readonly ImmutableDictionary<uint, string> _instanceNames; private readonly ImmutableDictionary<uint, string> _instanceNames;
private readonly ImmutableDictionary<uint, ContentFinderConditionData> _contentFinderConditions; 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) public TerritoryData(IDataManager dataManager)
{ {
@ -52,7 +52,7 @@ internal sealed class TerritoryData
.Select(x => new ContentFinderConditionData(x, dataManager.Language)) .Select(x => new ContentFinderConditionData(x, dataManager.Language))
.ToImmutableDictionary(x => x.ContentFinderConditionId, x => x); .ToImmutableDictionary(x => x.ContentFinderConditionId, x => x);
_questsToCfc = dataManager.GetExcelSheet<Quest>() _questBattlesToContentFinderCondition = dataManager.GetExcelSheet<Quest>()
.Where(x => x is { RowId: > 0, IssuerLocation.RowId: > 0 }) .Where(x => x is { RowId: > 0, IssuerLocation.RowId: > 0 })
.SelectMany(GetQuestBattles) .SelectMany(GetQuestBattles)
.Select(x => (x.QuestId, x.Index, .Select(x => (x.QuestId, x.Index,
@ -90,7 +90,7 @@ internal sealed class TerritoryData
public bool TryGetContentFinderConditionForSoloInstance(ElementId questId, byte index, public bool TryGetContentFinderConditionForSoloInstance(ElementId questId, byte index,
[NotNullWhen(true)] out ContentFinderConditionData? contentFinderConditionData) [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); return _contentFinderConditions.TryGetValue(cfcId, out contentFinderConditionData);
else else
{ {
@ -101,7 +101,7 @@ internal sealed class TerritoryData
public IEnumerable<(ElementId QuestId, byte Index, ContentFinderConditionData Data)> GetAllQuestsWithQuestBattles() 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) private static string FixName(string name, ClientLanguage language)

View File

@ -4,6 +4,7 @@ using Dalamud.Plugin.Ipc.Exceptions;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps; using Questionable.Controller.Steps;
using Questionable.Data; using Questionable.Data;
using Questionable.Model.Questing;
namespace Questionable.External; namespace Questionable.External;
@ -31,22 +32,22 @@ internal sealed class AutoDutyIpc
_stop = pluginInterface.GetIpcSubscriber<object>("AutoDuty.Stop"); _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; return false;
if (!_configuration.Duties.RunInstancedContentWithAutoDuty) if (!_configuration.Duties.RunInstancedContentWithAutoDuty)
return false; return false;
if (_configuration.Duties.BlacklistedDutyCfcIds.Contains(cfcId.Value)) if (_configuration.Duties.BlacklistedDutyCfcIds.Contains(dutyOptions.ContentFinderConditionId))
return false; return false;
if (_configuration.Duties.WhitelistedDutyCfcIds.Contains(cfcId.Value) && if (_configuration.Duties.WhitelistedDutyCfcIds.Contains(dutyOptions.ContentFinderConditionId) &&
_territoryData.TryGetContentFinderCondition(cfcId.Value, out _)) _territoryData.TryGetContentFinderCondition(dutyOptions.ContentFinderConditionId, out _))
return true; return true;
return enabledByDefault && HasPath(cfcId.Value); return dutyOptions.Enabled && HasPath(dutyOptions.ContentFinderConditionId);
} }
public bool HasPath(uint cfcId) public bool HasPath(uint cfcId)

View File

@ -1,5 +1,9 @@
using System.Collections.Generic;
using System.Text; using System.Text;
using Dalamud.Game.Text; using Dalamud.Game.Text;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin; using Dalamud.Plugin;
using ImGuiNET; using ImGuiNET;
@ -61,4 +65,29 @@ internal abstract class ConfigComponent
++byteCount; ++byteCount;
return Encoding.UTF8.GetString(ptr, 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);
}
} }

View File

@ -18,6 +18,7 @@ using Questionable.Controller;
using Questionable.Data; using Questionable.Data;
using Questionable.External; using Questionable.External;
using Questionable.Model; using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Windows.ConfigComponents; namespace Questionable.Windows.ConfigComponents;
@ -125,12 +126,11 @@ internal sealed class DutyConfigComponent : ConfigComponent
{ {
foreach (var (cfcId, territoryId, name) in cfcNames) foreach (var (cfcId, territoryId, name) in cfcNames)
{ {
if (_questRegistry.TryGetDutyByContentFinderConditionId(cfcId, if (_questRegistry.TryGetDutyByContentFinderConditionId(cfcId, out DutyOptions? dutyOptions))
out bool autoDutyEnabledByDefault))
{ {
ImGui.TableNextRow(); ImGui.TableNextRow();
string[] labels = autoDutyEnabledByDefault string[] labels = dutyOptions.Enabled
? SupportedCfcOptions ? SupportedCfcOptions
: UnsupportedCfcOptions; : UnsupportedCfcOptions;
int value = 0; int value = 0;
@ -159,6 +159,8 @@ internal sealed class DutyConfigComponent : ConfigComponent
if (runInstancedContentWithAutoDuty && !_autoDutyIpc.HasPath(cfcId)) if (runInstancedContentWithAutoDuty && !_autoDutyIpc.HasPath(cfcId))
ImGuiComponents.HelpMarker("This duty is not supported by AutoDuty", ImGuiComponents.HelpMarker("This duty is not supported by AutoDuty",
FontAwesomeIcon.Times, ImGuiColors.DalamudRed); FontAwesomeIcon.Times, ImGuiColors.DalamudRed);
else if (dutyOptions.Notes.Count > 0)
DrawNotes(dutyOptions.Enabled, dutyOptions.Notes);
} }
if (ImGui.TableNextColumn()) if (ImGui.TableNextColumn())

View File

@ -460,32 +460,7 @@ internal sealed class SinglePlayerDutyConfigComponent : ConfigComponent
FontAwesomeIcon.Times, ImGuiColors.DalamudRed); FontAwesomeIcon.Times, ImGuiColors.DalamudRed);
} }
else if (dutyInfo.Notes.Count > 0) else if (dutyInfo.Notes.Count > 0)
{ DrawNotes(dutyInfo.EnabledByDefault, dutyInfo.Notes);
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);
}
}
} }
if (ImGui.TableNextColumn()) if (ImGui.TableNextColumn())