forked from liza/Questionable
Add AutoDuty integration
This commit is contained in:
parent
f20b5e08a7
commit
8d85a0f896
@ -117,6 +117,9 @@ internal static class QuestStepExtensions
|
|||||||
Assignment(nameof(QuestStep.ContentFinderConditionId),
|
Assignment(nameof(QuestStep.ContentFinderConditionId),
|
||||||
step.ContentFinderConditionId, emptyStep.ContentFinderConditionId)
|
step.ContentFinderConditionId, emptyStep.ContentFinderConditionId)
|
||||||
.AsSyntaxNodeOrToken(),
|
.AsSyntaxNodeOrToken(),
|
||||||
|
Assignment(nameof(QuestStep.AutoDutyEnabled),
|
||||||
|
step.AutoDutyEnabled, emptyStep.AutoDutyEnabled)
|
||||||
|
.AsSyntaxNodeOrToken(),
|
||||||
Assignment(nameof(QuestStep.SkipConditions), step.SkipConditions,
|
Assignment(nameof(QuestStep.SkipConditions), step.SkipConditions,
|
||||||
emptyStep.SkipConditions)
|
emptyStep.SkipConditions)
|
||||||
.AsSyntaxNodeOrToken(),
|
.AsSyntaxNodeOrToken(),
|
||||||
|
@ -112,7 +112,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 138,
|
"TerritoryId": 138,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 4
|
"ContentFinderConditionId": 4,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -71,7 +71,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 146,
|
"TerritoryId": 146,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 56
|
"ContentFinderConditionId": 56,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -62,7 +62,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 140,
|
"TerritoryId": 140,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 3
|
"ContentFinderConditionId": 3,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -57,7 +57,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 148,
|
"TerritoryId": 148,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 2
|
"ContentFinderConditionId": 2,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -44,7 +44,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 153,
|
"TerritoryId": 153,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 1
|
"ContentFinderConditionId": 1,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -66,7 +66,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 148,
|
"TerritoryId": 148,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 6
|
"ContentFinderConditionId": 6,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -85,7 +85,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 137,
|
"TerritoryId": 137,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 8
|
"ContentFinderConditionId": 8,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -45,7 +45,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 139,
|
"TerritoryId": 139,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 57
|
"ContentFinderConditionId": 57,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -59,7 +59,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 155,
|
"TerritoryId": 155,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 11
|
"ContentFinderConditionId": 11,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -38,7 +38,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 331,
|
"TerritoryId": 331,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 58
|
"ContentFinderConditionId": 58,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -45,7 +45,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 147,
|
"TerritoryId": 147,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 15
|
"ContentFinderConditionId": 15,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -46,7 +46,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 147,
|
"TerritoryId": 147,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 16
|
"ContentFinderConditionId": 16,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -71,7 +72,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 1053,
|
"TerritoryId": 1053,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 830
|
"ContentFinderConditionId": 830,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -88,7 +88,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 155,
|
"TerritoryId": 155,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 27
|
"ContentFinderConditionId": 27,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -107,7 +107,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 156,
|
"TerritoryId": 156,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 32
|
"ContentFinderConditionId": 32,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -71,7 +71,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 155,
|
"TerritoryId": 155,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 5
|
"ContentFinderConditionId": 5,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -71,7 +71,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 155,
|
"TerritoryId": 155,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 5
|
"ContentFinderConditionId": 5,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -71,7 +71,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 155,
|
"TerritoryId": 155,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 5
|
"ContentFinderConditionId": 5,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -38,7 +38,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 397,
|
"TerritoryId": 397,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 36
|
"ContentFinderConditionId": 36,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -78,7 +78,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 398,
|
"TerritoryId": 398,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 37
|
"ContentFinderConditionId": 37,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -42,7 +42,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 418,
|
"TerritoryId": 418,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 39
|
"ContentFinderConditionId": 39,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -59,7 +59,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 419,
|
"TerritoryId": 419,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 34
|
"ContentFinderConditionId": 34,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -110,7 +110,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 399,
|
"TerritoryId": 399,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 31
|
"ContentFinderConditionId": 31,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -62,7 +62,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 402,
|
"TerritoryId": 402,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 38
|
"ContentFinderConditionId": 38,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -77,7 +77,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 463,
|
"TerritoryId": 463,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 141
|
"ContentFinderConditionId": 141,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -57,7 +57,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 155,
|
"TerritoryId": 155,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 182
|
"ContentFinderConditionId": 182,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -109,7 +109,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 152,
|
"TerritoryId": 152,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 219
|
"ContentFinderConditionId": 219,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -87,7 +87,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 680,
|
"TerritoryId": 680,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 238
|
"ContentFinderConditionId": 238,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -114,7 +114,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 614,
|
"TerritoryId": 614,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 241
|
"ContentFinderConditionId": 241,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -114,7 +114,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 620,
|
"TerritoryId": 620,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 242
|
"ContentFinderConditionId": 242,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -98,7 +98,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 621,
|
"TerritoryId": 621,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 279
|
"ContentFinderConditionId": 279,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -40,7 +40,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 614,
|
"TerritoryId": 614,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 585
|
"ContentFinderConditionId": 585,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -27,7 +27,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 829,
|
"TerritoryId": 829,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 611
|
"ContentFinderConditionId": 611,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -120,7 +120,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 813,
|
"TerritoryId": 813,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 676
|
"ContentFinderConditionId": 676,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -49,7 +49,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 816,
|
"TerritoryId": 816,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 649
|
"ContentFinderConditionId": 649,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -61,7 +61,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 817,
|
"TerritoryId": 817,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 651
|
"ContentFinderConditionId": 651,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -62,7 +62,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 814,
|
"TerritoryId": 814,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 659
|
"ContentFinderConditionId": 659,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -40,7 +40,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 814,
|
"TerritoryId": 814,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 714
|
"ContentFinderConditionId": 714,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -55,7 +55,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 957,
|
"TerritoryId": 957,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 783
|
"ContentFinderConditionId": 783,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -71,7 +71,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 957,
|
"TerritoryId": 957,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 789
|
"ContentFinderConditionId": 789,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -39,7 +39,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 961,
|
"TerritoryId": 961,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 787
|
"ContentFinderConditionId": 787,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -38,7 +38,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 956,
|
"TerritoryId": 956,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 786
|
"ContentFinderConditionId": 786,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -63,7 +64,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 1030,
|
"TerritoryId": 1030,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 790
|
"ContentFinderConditionId": 790,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 957,
|
"TerritoryId": 957,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 844
|
"ContentFinderConditionId": 844,
|
||||||
|
"AutoDutyEnabled": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -71,7 +71,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 1056,
|
"TerritoryId": 1056,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 869
|
"ContentFinderConditionId": 869,
|
||||||
|
"AutoDutyEnabled": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -57,7 +57,8 @@
|
|||||||
"TerritoryId": 958,
|
"TerritoryId": 958,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"Comment": "Lapis Manalis",
|
"Comment": "Lapis Manalis",
|
||||||
"ContentFinderConditionId": 896
|
"ContentFinderConditionId": 896,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -160,7 +160,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 822
|
"ContentFinderConditionId": 822,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 1162,
|
"TerritoryId": 1162,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 823
|
"ContentFinderConditionId": 823,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -58,7 +58,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 1185,
|
"TerritoryId": 1185,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 826
|
"ContentFinderConditionId": 826,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 1187,
|
"TerritoryId": 1187,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 824
|
"ContentFinderConditionId": 824,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -115,7 +115,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 1189,
|
"TerritoryId": 1189,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 829
|
"ContentFinderConditionId": 829,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -60,7 +60,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 1219,
|
"TerritoryId": 1219,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 831
|
"ContentFinderConditionId": 831,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -39,7 +39,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 1191,
|
"TerritoryId": 1191,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 825
|
"ContentFinderConditionId": 825,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -56,7 +56,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 1192,
|
"TerritoryId": 1192,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 827
|
"ContentFinderConditionId": 827,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -122,7 +122,8 @@
|
|||||||
{
|
{
|
||||||
"TerritoryId": 1191,
|
"TerritoryId": 1191,
|
||||||
"InteractionType": "Duty",
|
"InteractionType": "Duty",
|
||||||
"ContentFinderConditionId": 1008
|
"ContentFinderConditionId": 1008,
|
||||||
|
"AutoDutyEnabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1217,6 +1217,9 @@
|
|||||||
"exclusiveMinimum": 0,
|
"exclusiveMinimum": 0,
|
||||||
"exclusiveMaximum": 3000
|
"exclusiveMaximum": 3000
|
||||||
},
|
},
|
||||||
|
"AutoDutyEnabled": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"DataId": {
|
"DataId": {
|
||||||
"type": "null"
|
"type": "null"
|
||||||
},
|
},
|
||||||
|
@ -74,6 +74,7 @@ public sealed class QuestStep
|
|||||||
|
|
||||||
public JumpDestination? JumpDestination { get; set; }
|
public JumpDestination? JumpDestination { get; set; }
|
||||||
public uint? ContentFinderConditionId { get; set; }
|
public uint? ContentFinderConditionId { get; set; }
|
||||||
|
public bool AutoDutyEnabled { get; set; }
|
||||||
public SkipConditions? SkipConditions { get; set; }
|
public SkipConditions? SkipConditions { get; set; }
|
||||||
|
|
||||||
public List<List<QuestWorkValue>?> RequiredQuestVariables { get; set; } = new();
|
public List<List<QuestWorkValue>?> RequiredQuestVariables { get; set; } = new();
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Dalamud.Configuration;
|
using System.Collections.Generic;
|
||||||
|
using Dalamud.Configuration;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||||
using LLib.ImGui;
|
using LLib.ImGui;
|
||||||
@ -12,6 +13,7 @@ internal sealed class Configuration : IPluginConfiguration
|
|||||||
public int Version { get; set; } = 1;
|
public int Version { get; set; } = 1;
|
||||||
public int PluginSetupCompleteVersion { get; set; }
|
public int PluginSetupCompleteVersion { get; set; }
|
||||||
public GeneralConfiguration General { get; } = new();
|
public GeneralConfiguration General { get; } = new();
|
||||||
|
public DutyConfiguration Duties { get; } = new();
|
||||||
public NotificationConfiguration Notifications { get; } = new();
|
public NotificationConfiguration Notifications { get; } = new();
|
||||||
public AdvancedConfiguration Advanced { get; } = new();
|
public AdvancedConfiguration Advanced { get; } = new();
|
||||||
public WindowConfig DebugWindowConfig { get; } = new();
|
public WindowConfig DebugWindowConfig { get; } = new();
|
||||||
@ -32,6 +34,13 @@ internal sealed class Configuration : IPluginConfiguration
|
|||||||
public bool ConfigureTextAdvance { get; set; } = true;
|
public bool ConfigureTextAdvance { get; set; } = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal sealed class DutyConfiguration
|
||||||
|
{
|
||||||
|
public bool RunInstancedContentWithAutoDuty { get; set; }
|
||||||
|
public HashSet<uint> WhitelistedDutyCfcIds { get; set; } = [];
|
||||||
|
public HashSet<uint> BlacklistedDutyCfcIds { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
internal sealed class NotificationConfiguration
|
internal sealed class NotificationConfiguration
|
||||||
{
|
{
|
||||||
public bool Enabled { get; set; } = true;
|
public bool Enabled { get; set; } = true;
|
||||||
|
@ -29,7 +29,8 @@ internal sealed class QuestRegistry
|
|||||||
private readonly LeveData _leveData;
|
private readonly LeveData _leveData;
|
||||||
|
|
||||||
private readonly ICallGateProvider<object> _reloadDataIpc;
|
private readonly ICallGateProvider<object> _reloadDataIpc;
|
||||||
private readonly Dictionary<ElementId, Quest> _quests = new();
|
private readonly Dictionary<ElementId, Quest> _quests = [];
|
||||||
|
private readonly Dictionary<uint, (ElementId QuestId, QuestStep Step)> _contentFinderConditionIds = [];
|
||||||
|
|
||||||
public QuestRegistry(IDalamudPluginInterface pluginInterface, QuestData questData,
|
public QuestRegistry(IDalamudPluginInterface pluginInterface, QuestData questData,
|
||||||
QuestValidator questValidator, JsonSchemaValidator jsonSchemaValidator,
|
QuestValidator questValidator, JsonSchemaValidator jsonSchemaValidator,
|
||||||
@ -55,6 +56,7 @@ internal sealed class QuestRegistry
|
|||||||
{
|
{
|
||||||
_questValidator.Reset();
|
_questValidator.Reset();
|
||||||
_quests.Clear();
|
_quests.Clear();
|
||||||
|
_contentFinderConditionIds.Clear();
|
||||||
|
|
||||||
LoadQuestsFromAssembly();
|
LoadQuestsFromAssembly();
|
||||||
LoadQuestsFromProjectDirectory();
|
LoadQuestsFromProjectDirectory();
|
||||||
@ -70,6 +72,7 @@ internal sealed class QuestRegistry
|
|||||||
"Failed to load all quests from user directory (some may have been successfully loaded)");
|
"Failed to load all quests from user directory (some may have been successfully loaded)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadCfcIds();
|
||||||
ValidateQuests();
|
ValidateQuests();
|
||||||
Reloaded?.Invoke(this, EventArgs.Empty);
|
Reloaded?.Invoke(this, EventArgs.Empty);
|
||||||
try
|
try
|
||||||
@ -142,6 +145,18 @@ internal sealed class QuestRegistry
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LoadCfcIds()
|
||||||
|
{
|
||||||
|
foreach (var quest in _quests.Values)
|
||||||
|
{
|
||||||
|
foreach (var dutyStep in quest.AllSteps().Where(x =>
|
||||||
|
x.Step.InteractionType == EInteractionType.Duty && x.Step.ContentFinderConditionId != null))
|
||||||
|
{
|
||||||
|
_contentFinderConditionIds[dutyStep.Step.ContentFinderConditionId!.Value] = (quest.Id, dutyStep.Step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ValidateQuests()
|
private void ValidateQuests()
|
||||||
{
|
{
|
||||||
_questValidator.Validate(_quests.Values.Where(x => x.Source != Quest.ESource.Assembly).ToList());
|
_questValidator.Validate(_quests.Values.Where(x => x.Source != Quest.ESource.Assembly).ToList());
|
||||||
@ -223,4 +238,16 @@ internal sealed class QuestRegistry
|
|||||||
.Where(x => IsKnownQuest(x.QuestId))
|
.Where(x => IsKnownQuest(x.QuestId))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetDutyByContentFinderConditionId(uint cfcId, out bool autoDutyEnabledByDefault)
|
||||||
|
{
|
||||||
|
if (_contentFinderConditionIds.TryGetValue(cfcId, out var value))
|
||||||
|
{
|
||||||
|
autoDutyEnabledByDefault = value.Step.AutoDutyEnabled;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
autoDutyEnabledByDefault = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ internal static class SendNotification
|
|||||||
{
|
{
|
||||||
internal sealed class Factory(
|
internal sealed class Factory(
|
||||||
AutomatonIpc automatonIpc,
|
AutomatonIpc automatonIpc,
|
||||||
|
AutoDutyIpc autoDutyIpc,
|
||||||
TerritoryData territoryData) : SimpleTaskFactory
|
TerritoryData territoryData) : SimpleTaskFactory
|
||||||
{
|
{
|
||||||
public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
|
public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
|
||||||
@ -21,7 +22,7 @@ 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 =>
|
EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled) =>
|
||||||
new Task(step.InteractionType, step.ContentFinderConditionId.HasValue
|
new Task(step.InteractionType, step.ContentFinderConditionId.HasValue
|
||||||
? territoryData.GetContentFinderConditionName(step.ContentFinderConditionId.Value)
|
? territoryData.GetContentFinderConditionName(step.ContentFinderConditionId.Value)
|
||||||
: step.Comment),
|
: step.Comment),
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Dalamud.Game.ClientState.Conditions;
|
using Dalamud.Game.ClientState.Conditions;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
using Questionable.Controller.Steps.Shared;
|
||||||
|
using Questionable.Data;
|
||||||
|
using Questionable.External;
|
||||||
using Questionable.Functions;
|
using Questionable.Functions;
|
||||||
using Questionable.Model;
|
using Questionable.Model;
|
||||||
using Questionable.Model.Questing;
|
using Questionable.Model.Questing;
|
||||||
@ -9,26 +13,86 @@ namespace Questionable.Controller.Steps.Interactions;
|
|||||||
|
|
||||||
internal static class Duty
|
internal static class Duty
|
||||||
{
|
{
|
||||||
internal sealed class Factory : SimpleTaskFactory
|
internal sealed class Factory(AutoDutyIpc autoDutyIpc) : ITaskFactory
|
||||||
{
|
{
|
||||||
public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
|
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
||||||
{
|
{
|
||||||
if (step.InteractionType != EInteractionType.Duty)
|
if (step.InteractionType != EInteractionType.Duty)
|
||||||
return null;
|
yield break;
|
||||||
|
|
||||||
ArgumentNullException.ThrowIfNull(step.ContentFinderConditionId);
|
ArgumentNullException.ThrowIfNull(step.ContentFinderConditionId);
|
||||||
return new Task(step.ContentFinderConditionId.Value);
|
|
||||||
|
if (autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled))
|
||||||
|
{
|
||||||
|
yield return new StartAutoDutyTask(step.ContentFinderConditionId.Value);
|
||||||
|
yield return new WaitAutoDutyTask(step.ContentFinderConditionId.Value);
|
||||||
|
yield return new WaitAtEnd.WaitNextStepOrSequence();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yield return new OpenDutyFinderTask(step.ContentFinderConditionId.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed record Task(uint ContentFinderConditionId) : ITask
|
internal sealed record StartAutoDutyTask(uint ContentFinderConditionId) : ITask
|
||||||
|
{
|
||||||
|
public override string ToString() => $"StartAutoDuty({ContentFinderConditionId})";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class StartAutoDutyExecutor(
|
||||||
|
AutoDutyIpc autoDutyIpc,
|
||||||
|
TerritoryData territoryData,
|
||||||
|
IClientState clientState) : TaskExecutor<StartAutoDutyTask>
|
||||||
|
{
|
||||||
|
protected override bool Start()
|
||||||
|
{
|
||||||
|
autoDutyIpc.StartInstance(Task.ContentFinderConditionId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ETaskResult Update()
|
||||||
|
{
|
||||||
|
if (!territoryData.TryGetTerritoryIdForContentFinderCondition(Task.ContentFinderConditionId,
|
||||||
|
out uint territoryId))
|
||||||
|
throw new TaskException("Failed to get territory ID for content finder condition");
|
||||||
|
|
||||||
|
return clientState.TerritoryType == territoryId ? ETaskResult.TaskComplete : ETaskResult.StillRunning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed record WaitAutoDutyTask(uint ContentFinderConditionId) : ITask
|
||||||
|
{
|
||||||
|
public override string ToString() => $"Wait(AutoDuty, left instance {ContentFinderConditionId})";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class WaitAutoDutyExecutor(
|
||||||
|
AutoDutyIpc autoDutyIpc,
|
||||||
|
TerritoryData territoryData,
|
||||||
|
IClientState clientState) : TaskExecutor<WaitAutoDutyTask>
|
||||||
|
{
|
||||||
|
protected override bool Start() => true;
|
||||||
|
|
||||||
|
public override ETaskResult Update()
|
||||||
|
{
|
||||||
|
if (!territoryData.TryGetTerritoryIdForContentFinderCondition(Task.ContentFinderConditionId,
|
||||||
|
out uint territoryId))
|
||||||
|
throw new TaskException("Failed to get territory ID for content finder condition");
|
||||||
|
|
||||||
|
return clientState.TerritoryType != territoryId && autoDutyIpc.IsStopped()
|
||||||
|
? ETaskResult.TaskComplete
|
||||||
|
: ETaskResult.StillRunning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed record OpenDutyFinderTask(uint ContentFinderConditionId) : ITask
|
||||||
{
|
{
|
||||||
public override string ToString() => $"OpenDutyFinder({ContentFinderConditionId})";
|
public override string ToString() => $"OpenDutyFinder({ContentFinderConditionId})";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class OpenDutyWindowExecutor(
|
internal sealed class OpenDutyFinderExecutor(
|
||||||
GameFunctions gameFunctions,
|
GameFunctions gameFunctions,
|
||||||
ICondition condition) : TaskExecutor<Task>
|
ICondition condition) : TaskExecutor<OpenDutyFinderTask>
|
||||||
{
|
{
|
||||||
protected override bool Start()
|
protected override bool Start()
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@ using Dalamud.Plugin.Services;
|
|||||||
using Questionable.Controller.Steps.Common;
|
using Questionable.Controller.Steps.Common;
|
||||||
using Questionable.Controller.Utils;
|
using Questionable.Controller.Utils;
|
||||||
using Questionable.Data;
|
using Questionable.Data;
|
||||||
|
using Questionable.External;
|
||||||
using Questionable.Functions;
|
using Questionable.Functions;
|
||||||
using Questionable.Model;
|
using Questionable.Model;
|
||||||
using Questionable.Model.Questing;
|
using Questionable.Model.Questing;
|
||||||
@ -19,7 +20,8 @@ internal static class WaitAtEnd
|
|||||||
internal sealed class Factory(
|
internal sealed class Factory(
|
||||||
IClientState clientState,
|
IClientState clientState,
|
||||||
ICondition condition,
|
ICondition condition,
|
||||||
TerritoryData territoryData)
|
TerritoryData territoryData,
|
||||||
|
AutoDutyIpc autoDutyIpc)
|
||||||
: ITaskFactory
|
: ITaskFactory
|
||||||
{
|
{
|
||||||
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
||||||
@ -50,7 +52,7 @@ internal static class WaitAtEnd
|
|||||||
case EInteractionType.Snipe:
|
case EInteractionType.Snipe:
|
||||||
return [new WaitNextStepOrSequence()];
|
return [new WaitNextStepOrSequence()];
|
||||||
|
|
||||||
case EInteractionType.Duty:
|
case EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled):
|
||||||
case EInteractionType.SinglePlayerDuty:
|
case EInteractionType.SinglePlayerDuty:
|
||||||
return [new EndAutomation()];
|
return [new EndAutomation()];
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Dalamud.Game;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
using Dalamud.Utility;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
|
|
||||||
@ -15,6 +18,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, string> _contentFinderConditionNames;
|
private readonly ImmutableDictionary<uint, string> _contentFinderConditionNames;
|
||||||
|
private readonly ImmutableDictionary<uint, uint> _contentFinderConditionIds;
|
||||||
|
|
||||||
public TerritoryData(IDataManager dataManager)
|
public TerritoryData(IDataManager dataManager)
|
||||||
{
|
{
|
||||||
@ -40,11 +44,14 @@ internal sealed class TerritoryData
|
|||||||
|
|
||||||
_instanceNames = dataManager.GetExcelSheet<ContentFinderCondition>()
|
_instanceNames = dataManager.GetExcelSheet<ContentFinderCondition>()
|
||||||
.Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6)
|
.Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6)
|
||||||
.ToImmutableDictionary(x => x.Content.RowId, x => x.Name.ToString());
|
.ToImmutableDictionary(x => x.Content.RowId, x => x.Name.ToDalamudString().ToString());
|
||||||
|
|
||||||
_contentFinderConditionNames = dataManager.GetExcelSheet<ContentFinderCondition>()
|
_contentFinderConditionNames = dataManager.GetExcelSheet<ContentFinderCondition>()
|
||||||
.Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6)
|
.Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6)
|
||||||
.ToImmutableDictionary(x => x.RowId, x => x.Name.ToString());
|
.ToImmutableDictionary(x => x.RowId, x => FixName(x.Name.ToDalamudString().ToString(), dataManager.Language));
|
||||||
|
_contentFinderConditionIds = dataManager.GetExcelSheet<ContentFinderCondition>()
|
||||||
|
.Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6)
|
||||||
|
.ToImmutableDictionary(x => x.RowId, x => x.TerritoryType.RowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? GetName(ushort territoryId) => _territoryNames.GetValueOrDefault(territoryId);
|
public string? GetName(ushort territoryId) => _territoryNames.GetValueOrDefault(territoryId);
|
||||||
@ -68,4 +75,15 @@ internal sealed class TerritoryData
|
|||||||
public string? GetInstanceName(ushort instanceId) => _instanceNames.GetValueOrDefault(instanceId);
|
public string? GetInstanceName(ushort instanceId) => _instanceNames.GetValueOrDefault(instanceId);
|
||||||
|
|
||||||
public string? GetContentFinderConditionName(uint cfcId) => _contentFinderConditionNames.GetValueOrDefault(cfcId);
|
public string? GetContentFinderConditionName(uint cfcId) => _contentFinderConditionNames.GetValueOrDefault(cfcId);
|
||||||
|
|
||||||
|
public bool TryGetTerritoryIdForContentFinderCondition(uint cfcId, out uint territoryId) =>
|
||||||
|
_contentFinderConditionIds.TryGetValue(cfcId, out territoryId);
|
||||||
|
|
||||||
|
private static string FixName(string name, ClientLanguage language)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name) || language != ClientLanguage.English)
|
||||||
|
return name;
|
||||||
|
|
||||||
|
return string.Concat(name[0].ToString().ToUpper(CultureInfo.InvariantCulture), name.AsSpan(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
89
Questionable/External/AutoDutyIpc.cs
vendored
Normal file
89
Questionable/External/AutoDutyIpc.cs
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
using Dalamud.Plugin;
|
||||||
|
using Dalamud.Plugin.Ipc;
|
||||||
|
using Dalamud.Plugin.Ipc.Exceptions;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Questionable.Controller.Steps;
|
||||||
|
using Questionable.Data;
|
||||||
|
|
||||||
|
namespace Questionable.External;
|
||||||
|
|
||||||
|
internal sealed class AutoDutyIpc
|
||||||
|
{
|
||||||
|
private readonly Configuration _configuration;
|
||||||
|
private readonly TerritoryData _territoryData;
|
||||||
|
private readonly ILogger<AutoDutyIpc> _logger;
|
||||||
|
private readonly ICallGateSubscriber<uint,bool> _contentHasPath;
|
||||||
|
private readonly ICallGateSubscriber<uint,int,bool,object> _run;
|
||||||
|
private readonly ICallGateSubscriber<bool> _isStopped;
|
||||||
|
|
||||||
|
public AutoDutyIpc(IDalamudPluginInterface pluginInterface, Configuration configuration, TerritoryData territoryData, ILogger<AutoDutyIpc> logger)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
_territoryData = territoryData;
|
||||||
|
_logger = logger;
|
||||||
|
_contentHasPath = pluginInterface.GetIpcSubscriber<uint, bool>("AutoDuty.ContentHasPath");
|
||||||
|
_run = pluginInterface.GetIpcSubscriber<uint, int, bool, object>("AutoDuty.Run");
|
||||||
|
_isStopped = pluginInterface.GetIpcSubscriber<bool>("AutoDuty.IsStopped");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsConfiguredToRunContent(uint? cfcId, bool autoDutyEnabled)
|
||||||
|
{
|
||||||
|
if (cfcId == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_configuration.Duties.RunInstancedContentWithAutoDuty)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (_configuration.Duties.BlacklistedDutyCfcIds.Contains(cfcId.Value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (_configuration.Duties.WhitelistedDutyCfcIds.Contains(cfcId.Value) &&
|
||||||
|
_territoryData.TryGetTerritoryIdForContentFinderCondition(cfcId.Value, out _))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return autoDutyEnabled && HasPath(cfcId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasPath(uint cfcId)
|
||||||
|
{
|
||||||
|
if (!_territoryData.TryGetTerritoryIdForContentFinderCondition(cfcId, out uint territoryType))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _contentHasPath.InvokeFunc(territoryType);
|
||||||
|
}
|
||||||
|
catch (IpcError e)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Unable to query AutoDuty for path in territory {TerritoryType}: {Message}", territoryType, e.Message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartInstance(uint cfcId)
|
||||||
|
{
|
||||||
|
if (!_territoryData.TryGetTerritoryIdForContentFinderCondition(cfcId, out uint territoryType))
|
||||||
|
throw new TaskException($"Unknown ContentFinderConditionId {cfcId}");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_run.InvokeAction(territoryType, 0, true);
|
||||||
|
}
|
||||||
|
catch (IpcError e)
|
||||||
|
{
|
||||||
|
throw new TaskException($"Unable to run content with AutoDuty: {e.Message}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsStopped()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _isStopped.InvokeFunc();
|
||||||
|
}
|
||||||
|
catch (IpcError)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -129,6 +129,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
serviceCollection.AddSingleton<TextAdvanceIpc>();
|
serviceCollection.AddSingleton<TextAdvanceIpc>();
|
||||||
serviceCollection.AddSingleton<NotificationMasterIpc>();
|
serviceCollection.AddSingleton<NotificationMasterIpc>();
|
||||||
serviceCollection.AddSingleton<AutomatonIpc>();
|
serviceCollection.AddSingleton<AutomatonIpc>();
|
||||||
|
serviceCollection.AddSingleton<AutoDutyIpc>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddTaskFactories(ServiceCollection serviceCollection)
|
private static void AddTaskFactories(ServiceCollection serviceCollection)
|
||||||
@ -178,7 +179,9 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
.AddTaskFactoryAndExecutor<AethernetShard.Attune, AethernetShard.Factory, AethernetShard.DoAttune>();
|
.AddTaskFactoryAndExecutor<AethernetShard.Attune, AethernetShard.Factory, AethernetShard.DoAttune>();
|
||||||
serviceCollection.AddTaskFactoryAndExecutor<Aetheryte.Attune, Aetheryte.Factory, Aetheryte.DoAttune>();
|
serviceCollection.AddTaskFactoryAndExecutor<Aetheryte.Attune, Aetheryte.Factory, Aetheryte.DoAttune>();
|
||||||
serviceCollection.AddTaskFactoryAndExecutor<Combat.Task, Combat.Factory, Combat.HandleCombat>();
|
serviceCollection.AddTaskFactoryAndExecutor<Combat.Task, Combat.Factory, Combat.HandleCombat>();
|
||||||
serviceCollection.AddTaskFactoryAndExecutor<Duty.Task, Duty.Factory, Duty.OpenDutyWindowExecutor>();
|
serviceCollection.AddTaskFactoryAndExecutor<Duty.OpenDutyFinderTask, Duty.Factory, Duty.OpenDutyFinderExecutor>();
|
||||||
|
serviceCollection.AddTaskExecutor<Duty.StartAutoDutyTask, Duty.StartAutoDutyExecutor>();
|
||||||
|
serviceCollection.AddTaskExecutor<Duty.WaitAutoDutyTask, Duty.WaitAutoDutyExecutor>();
|
||||||
serviceCollection.AddTaskFactory<Emote.Factory>();
|
serviceCollection.AddTaskFactory<Emote.Factory>();
|
||||||
serviceCollection.AddTaskExecutor<Emote.UseOnObject, Emote.UseOnObjectExecutor>();
|
serviceCollection.AddTaskExecutor<Emote.UseOnObject, Emote.UseOnObjectExecutor>();
|
||||||
serviceCollection.AddTaskExecutor<Emote.UseOnSelf, Emote.UseOnSelfExecutor>();
|
serviceCollection.AddTaskExecutor<Emote.UseOnSelf, Emote.UseOnSelfExecutor>();
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Text;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
@ -12,19 +16,28 @@ using ImGuiNET;
|
|||||||
using LLib.ImGui;
|
using LLib.ImGui;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
using Questionable.Controller;
|
using Questionable.Controller;
|
||||||
|
using Questionable.Data;
|
||||||
using Questionable.External;
|
using Questionable.External;
|
||||||
|
using Questionable.Model;
|
||||||
using GrandCompany = FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany;
|
using GrandCompany = FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany;
|
||||||
|
|
||||||
namespace Questionable.Windows;
|
namespace Questionable.Windows;
|
||||||
|
|
||||||
internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
|
internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
|
||||||
{
|
{
|
||||||
|
private const string DutyClipboardPrefix = "qst:duty:";
|
||||||
|
private const string DutyClipboardSeparator = ";";
|
||||||
|
private const string DutyWhitelistPrefix = "+";
|
||||||
|
private const string DutyBlacklistPrefix = "-";
|
||||||
|
|
||||||
private static readonly List<(uint Id, string Name)> DefaultMounts = [(0, "Mount Roulette")];
|
private static readonly List<(uint Id, string Name)> DefaultMounts = [(0, "Mount Roulette")];
|
||||||
|
|
||||||
private readonly IDalamudPluginInterface _pluginInterface;
|
private readonly IDalamudPluginInterface _pluginInterface;
|
||||||
private readonly NotificationMasterIpc _notificationMasterIpc;
|
private readonly NotificationMasterIpc _notificationMasterIpc;
|
||||||
private readonly Configuration _configuration;
|
private readonly Configuration _configuration;
|
||||||
private readonly CombatController _combatController;
|
private readonly CombatController _combatController;
|
||||||
|
private readonly QuestRegistry _questRegistry;
|
||||||
|
private readonly AutoDutyIpc _autoDutyIpc;
|
||||||
|
|
||||||
private readonly uint[] _mountIds;
|
private readonly uint[] _mountIds;
|
||||||
private readonly string[] _mountNames;
|
private readonly string[] _mountNames;
|
||||||
@ -34,17 +47,38 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
|
|||||||
private readonly string[] _grandCompanyNames =
|
private readonly string[] _grandCompanyNames =
|
||||||
["None (manually pick quest)", "Maelstrom", "Twin Adder", "Immortal Flames"];
|
["None (manually pick quest)", "Maelstrom", "Twin Adder", "Immortal Flames"];
|
||||||
|
|
||||||
|
private readonly string[] _supportedCfcOptions =
|
||||||
|
[
|
||||||
|
$"{SeIconChar.Circle.ToIconChar()} Enabled (Default)",
|
||||||
|
$"{SeIconChar.Circle.ToIconChar()} Enabled",
|
||||||
|
$"{SeIconChar.Cross.ToIconChar()} Disabled"
|
||||||
|
];
|
||||||
|
|
||||||
|
private readonly string[] _unsupportedCfcOptions =
|
||||||
|
[
|
||||||
|
$"{SeIconChar.Cross.ToIconChar()} Disabled (Default)",
|
||||||
|
$"{SeIconChar.Circle.ToIconChar()} Enabled",
|
||||||
|
$"{SeIconChar.Cross.ToIconChar()} Disabled"
|
||||||
|
];
|
||||||
|
|
||||||
|
private readonly Dictionary<EExpansionVersion, List<DutyInfo>> _contentFinderConditionNames;
|
||||||
|
|
||||||
public ConfigWindow(IDalamudPluginInterface pluginInterface,
|
public ConfigWindow(IDalamudPluginInterface pluginInterface,
|
||||||
NotificationMasterIpc notificationMasterIpc,
|
NotificationMasterIpc notificationMasterIpc,
|
||||||
Configuration configuration,
|
Configuration configuration,
|
||||||
IDataManager dataManager,
|
IDataManager dataManager,
|
||||||
CombatController combatController)
|
CombatController combatController,
|
||||||
|
TerritoryData territoryData,
|
||||||
|
QuestRegistry questRegistry,
|
||||||
|
AutoDutyIpc autoDutyIpc)
|
||||||
: base("Config - Questionable###QuestionableConfig", ImGuiWindowFlags.AlwaysAutoResize)
|
: base("Config - Questionable###QuestionableConfig", ImGuiWindowFlags.AlwaysAutoResize)
|
||||||
{
|
{
|
||||||
_pluginInterface = pluginInterface;
|
_pluginInterface = pluginInterface;
|
||||||
_notificationMasterIpc = notificationMasterIpc;
|
_notificationMasterIpc = notificationMasterIpc;
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
_combatController = combatController;
|
_combatController = combatController;
|
||||||
|
_questRegistry = questRegistry;
|
||||||
|
_autoDutyIpc = autoDutyIpc;
|
||||||
|
|
||||||
var mounts = dataManager.GetExcelSheet<Mount>()
|
var mounts = dataManager.GetExcelSheet<Mount>()
|
||||||
.Where(x => x is { RowId: > 0, Icon: > 0 })
|
.Where(x => x is { RowId: > 0, Icon: > 0 })
|
||||||
@ -54,10 +88,41 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
|
|||||||
.ToList();
|
.ToList();
|
||||||
_mountIds = DefaultMounts.Select(x => x.Id).Concat(mounts.Select(x => x.MountId)).ToArray();
|
_mountIds = DefaultMounts.Select(x => x.Id).Concat(mounts.Select(x => x.MountId)).ToArray();
|
||||||
_mountNames = DefaultMounts.Select(x => x.Name).Concat(mounts.Select(x => x.Name)).ToArray();
|
_mountNames = DefaultMounts.Select(x => x.Name).Concat(mounts.Select(x => x.Name)).ToArray();
|
||||||
|
|
||||||
|
_contentFinderConditionNames = dataManager.GetExcelSheet<DawnContent>()
|
||||||
|
.Where(x => x.RowId > 0)
|
||||||
|
.Select(x => x.Content.ValueNullable)
|
||||||
|
.Where(x => x != null)
|
||||||
|
.Select(x => x!.Value)
|
||||||
|
.Select(x => new
|
||||||
|
{
|
||||||
|
Expansion = (EExpansionVersion)x.TerritoryType.Value.ExVersion.RowId,
|
||||||
|
CfcId = x.RowId,
|
||||||
|
Name = territoryData.GetContentFinderConditionName(x.RowId) ?? "?",
|
||||||
|
TerritoryId = x.TerritoryType.RowId,
|
||||||
|
ContentType = x.ContentType.RowId,
|
||||||
|
Level = x.ClassJobLevelRequired,
|
||||||
|
x.SortKey
|
||||||
|
})
|
||||||
|
.GroupBy(x => x.Expansion)
|
||||||
|
.ToDictionary(x => x.Key,
|
||||||
|
x => x.OrderBy(y => y.Level)
|
||||||
|
.ThenBy(y => y.ContentType)
|
||||||
|
.ThenBy(y => y.SortKey)
|
||||||
|
.Select(y => new DutyInfo(y.CfcId, y.TerritoryId, $"{SeIconChar.LevelEn.ToIconChar()}{FormatLevel(y.Level)} {y.Name}"))
|
||||||
|
.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public WindowConfig WindowConfig => _configuration.ConfigWindowConfig;
|
public WindowConfig WindowConfig => _configuration.ConfigWindowConfig;
|
||||||
|
|
||||||
|
private static string FormatLevel(int level)
|
||||||
|
{
|
||||||
|
if (level == 0)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
return $"{FormatLevel(level / 10)}{(SeIconChar.Number0 + level % 10).ToIconChar()}";
|
||||||
|
}
|
||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
using var tabBar = ImRaii.TabBar("QuestionableConfigTabs");
|
using var tabBar = ImRaii.TabBar("QuestionableConfigTabs");
|
||||||
@ -65,6 +130,7 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
DrawGeneralTab();
|
DrawGeneralTab();
|
||||||
|
DrawDutiesTab();
|
||||||
DrawNotificationsTab();
|
DrawNotificationsTab();
|
||||||
DrawAdvancedTab();
|
DrawAdvancedTab();
|
||||||
}
|
}
|
||||||
@ -138,6 +204,175 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawDutiesTab()
|
||||||
|
{
|
||||||
|
using var tab = ImRaii.TabItem("Duties");
|
||||||
|
if (!tab)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool runInstancedContentWithAutoDuty = _configuration.Duties.RunInstancedContentWithAutoDuty;
|
||||||
|
if (ImGui.Checkbox("Run instanced content with AutoDuty and BossMod", ref runInstancedContentWithAutoDuty))
|
||||||
|
{
|
||||||
|
_configuration.Duties.RunInstancedContentWithAutoDuty = runInstancedContentWithAutoDuty;
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGuiComponents.HelpMarker(
|
||||||
|
"The combat module used for this is configured by AutoDuty, ignoring whichever selection you've made in Questionable's \"General\" configuration.");
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
|
using (ImRaii.Disabled(!runInstancedContentWithAutoDuty))
|
||||||
|
{
|
||||||
|
ImGui.Text(
|
||||||
|
"Questionable includes a default list of duties that work if AutoDuty and BossMod are installed.");
|
||||||
|
|
||||||
|
ImGui.Text("The included list of duties can change with each update, and is based on the following spreadsheet:");
|
||||||
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.GlobeEurope, "Open AutoDuty spreadsheet"))
|
||||||
|
Util.OpenLink(
|
||||||
|
"https://docs.google.com/spreadsheets/d/151RlpqRcCpiD_VbQn6Duf-u-S71EP7d0mx3j1PDNoNA/edit?pli=1#gid=0");
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
ImGui.Text("You can override the dungeon settings for each individual dungeon/trial:");
|
||||||
|
|
||||||
|
using (var child = ImRaii.Child("DutyConfiguration", new Vector2(-1, 400), true))
|
||||||
|
{
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
foreach (EExpansionVersion expansion in Enum.GetValues<EExpansionVersion>())
|
||||||
|
{
|
||||||
|
if (ImGui.CollapsingHeader(expansion.ToString()))
|
||||||
|
{
|
||||||
|
using var table = ImRaii.Table($"Duties{expansion}", 2, ImGuiTableFlags.SizingFixedFit);
|
||||||
|
if (table)
|
||||||
|
{
|
||||||
|
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthStretch);
|
||||||
|
ImGui.TableSetupColumn("Options", ImGuiTableColumnFlags.WidthFixed, 200f);
|
||||||
|
|
||||||
|
if (_contentFinderConditionNames.TryGetValue(expansion, out var cfcNames))
|
||||||
|
{
|
||||||
|
foreach (var (cfcId, territoryId, name) in cfcNames)
|
||||||
|
{
|
||||||
|
if (_questRegistry.TryGetDutyByContentFinderConditionId(cfcId,
|
||||||
|
out bool autoDutyEnabledByDefault))
|
||||||
|
{
|
||||||
|
ImGui.TableNextRow();
|
||||||
|
|
||||||
|
string[] labels = autoDutyEnabledByDefault
|
||||||
|
? _supportedCfcOptions
|
||||||
|
: _unsupportedCfcOptions;
|
||||||
|
int value = 0;
|
||||||
|
if (_configuration.Duties.WhitelistedDutyCfcIds.Contains(cfcId))
|
||||||
|
value = 1;
|
||||||
|
if (_configuration.Duties.BlacklistedDutyCfcIds.Contains(cfcId))
|
||||||
|
value = 2;
|
||||||
|
|
||||||
|
if (ImGui.TableNextColumn())
|
||||||
|
{
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted(name);
|
||||||
|
if (ImGui.IsItemHovered() && _configuration.Advanced.AdditionalStatusInformation)
|
||||||
|
{
|
||||||
|
using var tooltip = ImRaii.Tooltip();
|
||||||
|
if (tooltip)
|
||||||
|
{
|
||||||
|
ImGui.TextUnformatted(name);
|
||||||
|
ImGui.Separator();
|
||||||
|
ImGui.BulletText($"TerritoryId: {territoryId}");
|
||||||
|
ImGui.BulletText($"ContentFinderConditionId: {cfcId}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runInstancedContentWithAutoDuty && !_autoDutyIpc.HasPath(cfcId))
|
||||||
|
ImGuiComponents.HelpMarker("This duty is not supported by AutoDuty", FontAwesomeIcon.Times, ImGuiColors.DalamudRed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.TableNextColumn())
|
||||||
|
{
|
||||||
|
using var _ = ImRaii.PushId($"##Dungeon{cfcId}");
|
||||||
|
ImGui.SetNextItemWidth(200);
|
||||||
|
if (ImGui.Combo(string.Empty, ref value, labels, labels.Length))
|
||||||
|
{
|
||||||
|
_configuration.Duties.WhitelistedDutyCfcIds.Remove(cfcId);
|
||||||
|
_configuration.Duties.BlacklistedDutyCfcIds.Remove(cfcId);
|
||||||
|
|
||||||
|
if (value == 1)
|
||||||
|
_configuration.Duties.WhitelistedDutyCfcIds.Add(cfcId);
|
||||||
|
else if (value == 2)
|
||||||
|
_configuration.Duties.BlacklistedDutyCfcIds.Add(cfcId);
|
||||||
|
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (ImRaii.Disabled(_configuration.Duties.WhitelistedDutyCfcIds.Count +
|
||||||
|
_configuration.Duties.BlacklistedDutyCfcIds.Count == 0))
|
||||||
|
{
|
||||||
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Copy, "Export to clipboard"))
|
||||||
|
{
|
||||||
|
var whitelisted =
|
||||||
|
_configuration.Duties.WhitelistedDutyCfcIds.Select(x => $"{DutyWhitelistPrefix}{x}");
|
||||||
|
var blacklisted =
|
||||||
|
_configuration.Duties.BlacklistedDutyCfcIds.Select(x => $"{DutyBlacklistPrefix}{x}");
|
||||||
|
string text = DutyClipboardPrefix + Convert.ToBase64String(Encoding.UTF8.GetBytes(
|
||||||
|
string.Join(DutyClipboardSeparator, whitelisted.Concat(blacklisted))));
|
||||||
|
ImGui.SetClipboardText(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
string? clipboardText = GetClipboardText();
|
||||||
|
using (ImRaii.Disabled(clipboardText == null || !clipboardText.StartsWith(DutyClipboardPrefix, StringComparison.InvariantCulture)))
|
||||||
|
{
|
||||||
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Paste, "Import from Clipboard"))
|
||||||
|
{
|
||||||
|
clipboardText = clipboardText!.Substring(DutyClipboardPrefix.Length);
|
||||||
|
string text = Encoding.UTF8.GetString(Convert.FromBase64String(clipboardText));
|
||||||
|
|
||||||
|
_configuration.Duties.WhitelistedDutyCfcIds.Clear();
|
||||||
|
_configuration.Duties.BlacklistedDutyCfcIds.Clear();
|
||||||
|
foreach (string part in text.Split(DutyClipboardSeparator))
|
||||||
|
{
|
||||||
|
if (part.StartsWith(DutyWhitelistPrefix, StringComparison.InvariantCulture) &&
|
||||||
|
uint.TryParse(part.AsSpan(DutyWhitelistPrefix.Length), CultureInfo.InvariantCulture,
|
||||||
|
out uint whitelistedCfcId))
|
||||||
|
_configuration.Duties.WhitelistedDutyCfcIds.Add(whitelistedCfcId);
|
||||||
|
|
||||||
|
if (part.StartsWith(DutyBlacklistPrefix, StringComparison.InvariantCulture) &&
|
||||||
|
uint.TryParse(part.AsSpan(DutyBlacklistPrefix.Length), CultureInfo.InvariantCulture,
|
||||||
|
out uint blacklistedCfcId))
|
||||||
|
_configuration.Duties.WhitelistedDutyCfcIds.Add(blacklistedCfcId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
using (var unused = ImRaii.Disabled(!ImGui.IsKeyDown(ImGuiKey.ModCtrl)))
|
||||||
|
{
|
||||||
|
if (ImGui.Button("Reset to default"))
|
||||||
|
{
|
||||||
|
_configuration.Duties.WhitelistedDutyCfcIds.Clear();
|
||||||
|
_configuration.Duties.BlacklistedDutyCfcIds.Clear();
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||||
|
ImGui.SetTooltip("Hold CTRL to enable this button.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawNotificationsTab()
|
private void DrawNotificationsTab()
|
||||||
{
|
{
|
||||||
using var tab = ImRaii.TabItem("Notifications");
|
using var tab = ImRaii.TabItem("Notifications");
|
||||||
@ -231,4 +466,21 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
|
|||||||
private void Save() => _pluginInterface.SavePluginConfig(_configuration);
|
private void Save() => _pluginInterface.SavePluginConfig(_configuration);
|
||||||
|
|
||||||
public void SaveWindowConfig() => Save();
|
public void SaveWindowConfig() => Save();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The default implementation for <see cref="ImGui.GetClipboardText"/> throws an NullReferenceException if the clipboard is empty, maybe also if it doesn't contain text.
|
||||||
|
/// </summary>
|
||||||
|
private unsafe string? GetClipboardText()
|
||||||
|
{
|
||||||
|
byte* ptr = ImGuiNative.igGetClipboardText();
|
||||||
|
if (ptr == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int byteCount = 0;
|
||||||
|
while (ptr[byteCount] != 0)
|
||||||
|
++byteCount;
|
||||||
|
return Encoding.UTF8.GetString(ptr, byteCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed record DutyInfo(uint CfcId, uint TerritoryId, string Name);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user