forked from liza/Questionable
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
fe63319b56 | |||
5757a73b22 | |||
b213e872da | |||
c7f4865201 | |||
59793d19dc | |||
2ada2fa9dc | |||
fe1d86bf5b | |||
71b40496fb | |||
224825b071 | |||
ed797143b3 | |||
22aa81cf75 | |||
dcdc288b08 | |||
a70e195a93 |
@ -1,5 +1,5 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup Condition="$(MSBuildProjectName) != 'GatheringPathRenderer'">
|
<PropertyGroup Condition="$(MSBuildProjectName) != 'GatheringPathRenderer'">
|
||||||
<Version>4.19</Version>
|
<Version>4.20</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -108,7 +108,7 @@ internal static class QuestStepExtensions
|
|||||||
AssignmentList(nameof(QuestStep.ComplexCombatData), step.ComplexCombatData)
|
AssignmentList(nameof(QuestStep.ComplexCombatData), step.ComplexCombatData)
|
||||||
.AsSyntaxNodeOrToken(),
|
.AsSyntaxNodeOrToken(),
|
||||||
Assignment(nameof(QuestStep.CombatItemUse), step.CombatItemUse,
|
Assignment(nameof(QuestStep.CombatItemUse), step.CombatItemUse,
|
||||||
emptyStep.CombatItemUse)
|
emptyStep.CombatItemUse)
|
||||||
.AsSyntaxNodeOrToken(),
|
.AsSyntaxNodeOrToken(),
|
||||||
Assignment(nameof(QuestStep.CombatDelaySecondsAtStart),
|
Assignment(nameof(QuestStep.CombatDelaySecondsAtStart),
|
||||||
step.CombatDelaySecondsAtStart,
|
step.CombatDelaySecondsAtStart,
|
||||||
@ -123,14 +123,8 @@ internal static class QuestStepExtensions
|
|||||||
Assignment(nameof(QuestStep.AutoDutyEnabled),
|
Assignment(nameof(QuestStep.AutoDutyEnabled),
|
||||||
step.AutoDutyEnabled, emptyStep.AutoDutyEnabled)
|
step.AutoDutyEnabled, emptyStep.AutoDutyEnabled)
|
||||||
.AsSyntaxNodeOrToken(),
|
.AsSyntaxNodeOrToken(),
|
||||||
Assignment(nameof(QuestStep.BossModEnabled),
|
Assignment(nameof(QuestStep.SinglePlayerDutyOptions), step.SinglePlayerDutyOptions,
|
||||||
step.BossModEnabled, emptyStep.BossModEnabled)
|
emptyStep.SinglePlayerDutyOptions)
|
||||||
.AsSyntaxNodeOrToken(),
|
|
||||||
Assignment(nameof(QuestStep.BossModNotes),
|
|
||||||
step.BossModNotes, emptyStep.BossModNotes)
|
|
||||||
.AsSyntaxNodeOrToken(),
|
|
||||||
Assignment(nameof(QuestStep.SinglePlayerDutyIndex),
|
|
||||||
step.SinglePlayerDutyIndex, emptyStep.SinglePlayerDutyIndex)
|
|
||||||
.AsSyntaxNodeOrToken(),
|
.AsSyntaxNodeOrToken(),
|
||||||
Assignment(nameof(QuestStep.SkipConditions), step.SkipConditions,
|
Assignment(nameof(QuestStep.SkipConditions), step.SkipConditions,
|
||||||
emptyStep.SkipConditions)
|
emptyStep.SkipConditions)
|
||||||
|
@ -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 SinglePlayerDutyOptionsExtensions
|
||||||
|
{
|
||||||
|
public static ExpressionSyntax ToExpressionSyntax(this SinglePlayerDutyOptions dutyOptions)
|
||||||
|
{
|
||||||
|
var emptyOptions = new SinglePlayerDutyOptions();
|
||||||
|
return ObjectCreationExpression(
|
||||||
|
IdentifierName(nameof(SinglePlayerDutyOptions)))
|
||||||
|
.WithInitializer(
|
||||||
|
InitializerExpression(
|
||||||
|
SyntaxKind.ObjectInitializerExpression,
|
||||||
|
SeparatedList<ExpressionSyntax>(
|
||||||
|
SyntaxNodeList(
|
||||||
|
Assignment(nameof(SinglePlayerDutyOptions.Enabled),
|
||||||
|
dutyOptions.Enabled, emptyOptions.Enabled)
|
||||||
|
.AsSyntaxNodeOrToken(),
|
||||||
|
AssignmentList(nameof(SinglePlayerDutyOptions.Notes), dutyOptions.Notes)
|
||||||
|
.AsSyntaxNodeOrToken(),
|
||||||
|
Assignment(nameof(SinglePlayerDutyOptions.Index),
|
||||||
|
dutyOptions.Index, emptyOptions.Index)
|
||||||
|
.AsSyntaxNodeOrToken()))));
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
SinglePlayerDutyOptions dutyOptions => dutyOptions.ToExpressionSyntax(),
|
||||||
SkipConditions skipConditions => skipConditions.ToExpressionSyntax(),
|
SkipConditions skipConditions => skipConditions.ToExpressionSyntax(),
|
||||||
SkipStepConditions skipStepConditions => skipStepConditions.ToExpressionSyntax(),
|
SkipStepConditions skipStepConditions => skipStepConditions.ToExpressionSyntax(),
|
||||||
SkipItemConditions skipItemCondition => skipItemCondition.ToExpressionSyntax(),
|
SkipItemConditions skipItemCondition => skipItemCondition.ToExpressionSyntax(),
|
||||||
|
@ -57,7 +57,9 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 153,
|
"TerritoryId": 153,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"SinglePlayerDutyIndex": 1,
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Index": 1
|
||||||
|
},
|
||||||
"Fly": true
|
"Fly": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -62,7 +62,9 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 154,
|
"TerritoryId": 154,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"SinglePlayerDutyIndex": 1,
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Index": 1
|
||||||
|
},
|
||||||
"AetheryteShortcut": "North Shroud - Fallgourd Float",
|
"AetheryteShortcut": "North Shroud - Fallgourd Float",
|
||||||
"Fly": true
|
"Fly": true
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,9 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 152,
|
"TerritoryId": 152,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"SinglePlayerDutyIndex": 1
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Index": 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -140,6 +140,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 141,
|
"TerritoryId": 141,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
},
|
||||||
"Fly": true
|
"Fly": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -92,7 +92,9 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 130,
|
"TerritoryId": 130,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"SinglePlayerDutyIndex": 1,
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Index": 1
|
||||||
|
},
|
||||||
"AetheryteShortcut": "Ul'dah"
|
"AetheryteShortcut": "Ul'dah"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -29,13 +29,7 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 129,
|
"TerritoryId": 129,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"DialogueChoices": [
|
"TargetTerritoryId": 129
|
||||||
{
|
|
||||||
"Type": "YesNo",
|
|
||||||
"Prompt": "TEXT_CLSROG011_00102_Q9_000_901",
|
|
||||||
"Yes": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1009943,
|
"DataId": 1009943,
|
||||||
|
@ -5,6 +5,26 @@
|
|||||||
{
|
{
|
||||||
"Sequence": 0,
|
"Sequence": 0,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
{
|
||||||
|
"TerritoryId": 129,
|
||||||
|
"InteractionType": "EquipItem",
|
||||||
|
"ItemId": 7952,
|
||||||
|
"AetheryteShortcut": "Limsa Lominsa",
|
||||||
|
"SkipConditions": {
|
||||||
|
"AetheryteShortcutIf": {
|
||||||
|
"InSameTerritory": true
|
||||||
|
},
|
||||||
|
"StepIf": {
|
||||||
|
"Item": {
|
||||||
|
"NotInInventory": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TerritoryId": 129,
|
||||||
|
"InteractionType": "EquipRecommended"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1009944,
|
"DataId": 1009944,
|
||||||
"Position": {
|
"Position": {
|
||||||
@ -14,16 +34,12 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 129,
|
"TerritoryId": 129,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"AetheryteShortcut": "Limsa Lominsa",
|
|
||||||
"TargetTerritoryId": 129,
|
"TargetTerritoryId": 129,
|
||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Limsa Lominsa] Aetheryte Plaza",
|
"[Limsa Lominsa] Aetheryte Plaza",
|
||||||
"[Limsa Lominsa] Fishermens' Guild"
|
"[Limsa Lominsa] Fishermens' Guild"
|
||||||
],
|
],
|
||||||
"SkipConditions": {
|
"SkipConditions": {
|
||||||
"AetheryteShortcutIf": {
|
|
||||||
"InSameTerritory": true
|
|
||||||
},
|
|
||||||
"StepIf": {
|
"StepIf": {
|
||||||
"ExtraCondition": "RoguesGuild"
|
"ExtraCondition": "RoguesGuild"
|
||||||
}
|
}
|
||||||
@ -45,6 +61,25 @@
|
|||||||
{
|
{
|
||||||
"Sequence": 1,
|
"Sequence": 1,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
{
|
||||||
|
"DataId": 2004936,
|
||||||
|
"Position": {
|
||||||
|
"X": -151.90363,
|
||||||
|
"Y": -128.16058,
|
||||||
|
"Z": 256.8551
|
||||||
|
},
|
||||||
|
"TerritoryId": 129,
|
||||||
|
"InteractionType": "Interact",
|
||||||
|
"TargetTerritoryId": 129,
|
||||||
|
"SkipConditions": {
|
||||||
|
"StepIf": {
|
||||||
|
"InTerritory": [
|
||||||
|
134
|
||||||
|
],
|
||||||
|
"ExtraCondition": "NotRoguesGuild"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Position": {
|
"Position": {
|
||||||
"X": 31.662792,
|
"X": 31.662792,
|
||||||
|
@ -152,15 +152,9 @@
|
|||||||
"TerritoryId": 129,
|
"TerritoryId": 129,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"TargetTerritoryId": 129,
|
"TargetTerritoryId": 129,
|
||||||
"AethernetShortcut": [
|
|
||||||
"[Limsa Lominsa] Fishermens' Guild",
|
|
||||||
"[Limsa Lominsa] The Aftcastle"
|
|
||||||
],
|
|
||||||
"SkipConditions": {
|
"SkipConditions": {
|
||||||
"StepIf": {
|
"StepIf": {
|
||||||
"InTerritory": [
|
"ExtraCondition": "NotRoguesGuild"
|
||||||
128
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -173,6 +167,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 128,
|
"TerritoryId": 128,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
|
"AethernetShortcut": [
|
||||||
|
"[Limsa Lominsa] Fishermens' Guild",
|
||||||
|
"[Limsa Lominsa] The Aftcastle"
|
||||||
|
],
|
||||||
"DialogueChoices": [
|
"DialogueChoices": [
|
||||||
{
|
{
|
||||||
"Type": "List",
|
"Type": "List",
|
||||||
|
@ -291,7 +291,17 @@
|
|||||||
"Z": 239.30713
|
"Z": 239.30713
|
||||||
},
|
},
|
||||||
"TerritoryId": 129,
|
"TerritoryId": 129,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": false,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"(phase 1) AI doesn't move or pick up the stolen firearms",
|
||||||
|
"(phase 1 + 2) AI automatically removes Hidden status",
|
||||||
|
"(phase 2) AI only moves while targeted enemies are in range + gets stuck on corners while trying to get to irrelevant enemies",
|
||||||
|
"(phase 2) AI doesn't even attempt to navigate to the end of the quest"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -35,6 +35,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 137,
|
"TerritoryId": 137,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
},
|
||||||
"AetheryteShortcut": "Eastern La Noscea - Wineport",
|
"AetheryteShortcut": "Eastern La Noscea - Wineport",
|
||||||
"Fly": true
|
"Fly": true
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 152,
|
"TerritoryId": 152,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
},
|
||||||
"Fly": true
|
"Fly": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -65,7 +65,8 @@
|
|||||||
"AetheryteShortcut": "East Shroud - Hawthorne Hut",
|
"AetheryteShortcut": "East Shroud - Hawthorne Hut",
|
||||||
"SkipConditions": {
|
"SkipConditions": {
|
||||||
"AetheryteShortcutIf": {
|
"AetheryteShortcutIf": {
|
||||||
"InSameTerritory": true
|
"InSameTerritory": true,
|
||||||
|
"AetheryteLocked": "East Shroud - Hawthorne Hut"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,7 +117,11 @@
|
|||||||
"Z": 35.568726
|
"Z": 35.568726
|
||||||
},
|
},
|
||||||
"TerritoryId": 152,
|
"TerritoryId": 152,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -33,6 +33,39 @@
|
|||||||
{
|
{
|
||||||
"Sequence": 1,
|
"Sequence": 1,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
{
|
||||||
|
"DataId": 1001263,
|
||||||
|
"Position": {
|
||||||
|
"X": 181.41443,
|
||||||
|
"Y": -2.3519497,
|
||||||
|
"Z": -240.40594
|
||||||
|
},
|
||||||
|
"TerritoryId": 133,
|
||||||
|
"InteractionType": "Interact",
|
||||||
|
"TargetTerritoryId": 152,
|
||||||
|
"AethernetShortcut": [
|
||||||
|
"[Gridania] Conjurers' Guild",
|
||||||
|
"[Gridania] Lancers' Guild"
|
||||||
|
],
|
||||||
|
"SkipConditions": {
|
||||||
|
"StepIf": {
|
||||||
|
"AetheryteUnlocked": "East Shroud - Hawthorne Hut",
|
||||||
|
"InTerritory": [
|
||||||
|
152
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TerritoryId": 152,
|
||||||
|
"InteractionType": "AttuneAetheryte",
|
||||||
|
"Aetheryte": "East Shroud - Hawthorne Hut",
|
||||||
|
"SkipConditions": {
|
||||||
|
"StepIf": {
|
||||||
|
"AetheryteUnlocked": "East Shroud - Hawthorne Hut"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Position": {
|
"Position": {
|
||||||
"X": -276.804,
|
"X": -276.804,
|
||||||
@ -42,7 +75,12 @@
|
|||||||
"TerritoryId": 152,
|
"TerritoryId": 152,
|
||||||
"InteractionType": "WalkTo",
|
"InteractionType": "WalkTo",
|
||||||
"AetheryteShortcut": "East Shroud - Hawthorne Hut",
|
"AetheryteShortcut": "East Shroud - Hawthorne Hut",
|
||||||
"Fly": true
|
"Fly": true,
|
||||||
|
"SkipConditions": {
|
||||||
|
"AetheryteShortcutIf": {
|
||||||
|
"AetheryteLocked": "East Shroud - Hawthorne Hut"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 2000889,
|
"DataId": 2000889,
|
||||||
@ -212,6 +250,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 152,
|
"TerritoryId": 152,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
},
|
||||||
"Fly": true
|
"Fly": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -138,7 +138,11 @@
|
|||||||
"Z": 192.2179
|
"Z": 192.2179
|
||||||
},
|
},
|
||||||
"TerritoryId": 148,
|
"TerritoryId": 148,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -111,7 +111,14 @@
|
|||||||
"Z": 295.52136
|
"Z": 295.52136
|
||||||
},
|
},
|
||||||
"TerritoryId": 148,
|
"TerritoryId": 148,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"Healer NPC is only killed after the boss dies; all NPCs need to be killed for the duty to complete"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -29,10 +29,13 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 148,
|
"TerritoryId": 148,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"BossModEnabled": false,
|
"SinglePlayerDutyOptions": {
|
||||||
"BossModNotes": [
|
"Enabled": false,
|
||||||
"AI doesn't automatically target newly spawning adds and dies until after the boss died (tested on CNJ)"
|
"TestedBossModVersion": 292,
|
||||||
]
|
"Notes": [
|
||||||
|
"AI doesn't automatically target newly spawning adds until after the boss died, and dies (tested on CNJ)"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -77,6 +77,13 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 148,
|
"TerritoryId": 148,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"(Phase 1) Healer NPCs are only killed after the boss dies - allied NPCs will kill them eventually; all NPCs need to be killed for the duty to complete"
|
||||||
|
]
|
||||||
|
},
|
||||||
"AetheryteShortcut": "Central Shroud - Bentbranch Meadows"
|
"AetheryteShortcut": "Central Shroud - Bentbranch Meadows"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -69,6 +69,13 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 135,
|
"TerritoryId": 135,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": false,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"(Phase 1, second enemy group) Stuck with enemy being out of sight -- but still able to attack you (tested on ACN)"
|
||||||
|
]
|
||||||
|
},
|
||||||
"AetheryteShortcut": "Lower La Noscea - Moraby Drydocks"
|
"AetheryteShortcut": "Lower La Noscea - Moraby Drydocks"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -45,8 +45,11 @@
|
|||||||
"TerritoryId": 134,
|
"TerritoryId": 134,
|
||||||
"InteractionType": "Combat",
|
"InteractionType": "Combat",
|
||||||
"EnemySpawnType": "AutoOnEnterArea",
|
"EnemySpawnType": "AutoOnEnterArea",
|
||||||
"KillEnemyDataIds": [
|
"ComplexCombatData": [
|
||||||
52
|
{
|
||||||
|
"DataId": 52,
|
||||||
|
"IgnoreQuestMarker": true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -73,7 +73,11 @@
|
|||||||
"Z": -432.15082
|
"Z": -432.15082
|
||||||
},
|
},
|
||||||
"TerritoryId": 134,
|
"TerritoryId": 134,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -28,7 +28,14 @@
|
|||||||
"Z": -141.7716
|
"Z": -141.7716
|
||||||
},
|
},
|
||||||
"TerritoryId": 134,
|
"TerritoryId": 134,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": false,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"AI doesn't automatically target newly spawning adds until after the boss died (requires healing luck on ACN)"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -58,6 +58,13 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 138,
|
"TerritoryId": 138,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"(Phase 1) Kills PGL NPCs and then the boss - allied NPCs will kill most other NPCs eventually; all NPCs need to be killed for the duty to complete"
|
||||||
|
]
|
||||||
|
},
|
||||||
"AetheryteShortcut": "Western La Noscea - Swiftperch"
|
"AetheryteShortcut": "Western La Noscea - Swiftperch"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -44,7 +44,11 @@
|
|||||||
"Z": -242.51166
|
"Z": -242.51166
|
||||||
},
|
},
|
||||||
"TerritoryId": 145,
|
"TerritoryId": 145,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -79,6 +79,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 130,
|
"TerritoryId": 130,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
},
|
||||||
"AetheryteShortcut": "Ul'dah",
|
"AetheryteShortcut": "Ul'dah",
|
||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Ul'dah] Aetheryte Plaza",
|
"[Ul'dah] Aetheryte Plaza",
|
||||||
@ -87,6 +91,9 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Sequence": 5
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Sequence": 255,
|
"Sequence": 255,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
@ -63,12 +63,22 @@
|
|||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Gridania] Aetheryte Plaza",
|
"[Gridania] Aetheryte Plaza",
|
||||||
"[Gridania] Lancers' Guild"
|
"[Gridania] Lancers' Guild"
|
||||||
]
|
],
|
||||||
|
"SkipConditions": {
|
||||||
|
"StepIf": {
|
||||||
|
"AetheryteUnlocked": "East Shroud - Hawthorne Hut"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"TerritoryId": 152,
|
"TerritoryId": 152,
|
||||||
"InteractionType": "AttuneAetheryte",
|
"InteractionType": "AttuneAetheryte",
|
||||||
"Aetheryte": "East Shroud - Hawthorne Hut"
|
"Aetheryte": "East Shroud - Hawthorne Hut",
|
||||||
|
"SkipConditions": {
|
||||||
|
"StepIf": {
|
||||||
|
"AetheryteUnlocked": "East Shroud - Hawthorne Hut"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1004886,
|
"DataId": 1004886,
|
||||||
@ -78,7 +88,17 @@
|
|||||||
"Z": 475.30322
|
"Z": 475.30322
|
||||||
},
|
},
|
||||||
"TerritoryId": 152,
|
"TerritoryId": 152,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
},
|
||||||
|
"AetheryteShortcut": "East Shroud - Hawthorne Hut",
|
||||||
|
"SkipConditions": {
|
||||||
|
"AetheryteShortcutIf": {
|
||||||
|
"InSameTerritory": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -64,6 +64,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 135,
|
"TerritoryId": 135,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
},
|
||||||
"AethernetShortcut": [
|
"AethernetShortcut": [
|
||||||
"[Limsa Lominsa] The Aftcastle",
|
"[Limsa Lominsa] The Aftcastle",
|
||||||
"[Limsa Lominsa] Tempest Gate (Lower La Noscea)"
|
"[Limsa Lominsa] Tempest Gate (Lower La Noscea)"
|
||||||
|
@ -59,6 +59,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 140,
|
"TerritoryId": 140,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
},
|
||||||
"AetheryteShortcut": "Western Thanalan - Horizon"
|
"AetheryteShortcut": "Western Thanalan - Horizon"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -46,7 +46,8 @@
|
|||||||
},
|
},
|
||||||
"StopDistance": 7,
|
"StopDistance": 7,
|
||||||
"TerritoryId": 141,
|
"TerritoryId": 141,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact",
|
||||||
|
"DelaySecondsAtStart": 2
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -158,7 +158,11 @@
|
|||||||
"Z": 117.29602
|
"Z": 117.29602
|
||||||
},
|
},
|
||||||
"TerritoryId": 141,
|
"TerritoryId": 141,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -21,6 +21,15 @@
|
|||||||
{
|
{
|
||||||
"Sequence": 255,
|
"Sequence": 255,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": -174.73444,
|
||||||
|
"Y": 15.450659,
|
||||||
|
"Z": -266.76144
|
||||||
|
},
|
||||||
|
"TerritoryId": 140,
|
||||||
|
"InteractionType": "WalkTo"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Position": {
|
"Position": {
|
||||||
"X": -289.1099,
|
"X": -289.1099,
|
||||||
|
@ -37,7 +37,11 @@
|
|||||||
"Z": -293.1411
|
"Z": -293.1411
|
||||||
},
|
},
|
||||||
"TerritoryId": 140,
|
"TerritoryId": 140,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 141,
|
"TerritoryId": 141,
|
||||||
"InteractionType": "Combat",
|
"InteractionType": "Combat",
|
||||||
"EnemySpawnType": "OverworldEnemies",
|
"EnemySpawnType": "FinishCombatIfAny",
|
||||||
"KillEnemyDataIds": [
|
"KillEnemyDataIds": [
|
||||||
352,
|
352,
|
||||||
353
|
353
|
||||||
@ -53,6 +53,25 @@
|
|||||||
{
|
{
|
||||||
"Sequence": 255,
|
"Sequence": 255,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": 131.78122,
|
||||||
|
"Y": 20.119337,
|
||||||
|
"Z": -115.27284
|
||||||
|
},
|
||||||
|
"TerritoryId": 141,
|
||||||
|
"InteractionType": "WalkTo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": 127.7017,
|
||||||
|
"Y": -0.15994573,
|
||||||
|
"Z": -161.89238
|
||||||
|
},
|
||||||
|
"TerritoryId": 141,
|
||||||
|
"InteractionType": "WalkTo",
|
||||||
|
"DisableNavmesh": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1001605,
|
"DataId": 1001605,
|
||||||
"Position": {
|
"Position": {
|
||||||
|
@ -28,7 +28,11 @@
|
|||||||
"Z": 536.88855
|
"Z": 536.88855
|
||||||
},
|
},
|
||||||
"TerritoryId": 141,
|
"TerritoryId": 141,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -64,7 +64,14 @@
|
|||||||
"Z": -131.48706
|
"Z": -131.48706
|
||||||
},
|
},
|
||||||
"TerritoryId": 141,
|
"TerritoryId": 141,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"(Phase 1) Healer NPCs are only killed after the boss dies - allied NPCs will kill them eventually; all NPCs need to be killed for the duty to complete"
|
||||||
|
]
|
||||||
|
},
|
||||||
"AetheryteShortcut": "Central Thanalan - Black Brush Station"
|
"AetheryteShortcut": "Central Thanalan - Black Brush Station"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -73,13 +73,23 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 133,
|
"TerritoryId": 133,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"TargetTerritoryId": 152
|
"TargetTerritoryId": 152,
|
||||||
|
"SkipConditions": {
|
||||||
|
"StepIf": {
|
||||||
|
"AetheryteUnlocked": "East Shroud - Hawthorne Hut"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"TerritoryId": 152,
|
"TerritoryId": 152,
|
||||||
"InteractionType": "AttuneAetheryte",
|
"InteractionType": "AttuneAetheryte",
|
||||||
"Aetheryte": "East Shroud - Hawthorne Hut",
|
"Aetheryte": "East Shroud - Hawthorne Hut",
|
||||||
"StopDistance": 5
|
"StopDistance": 5,
|
||||||
|
"SkipConditions": {
|
||||||
|
"StepIf": {
|
||||||
|
"AetheryteUnlocked": "East Shroud - Hawthorne Hut"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1006188,
|
"DataId": 1006188,
|
||||||
@ -89,7 +99,13 @@
|
|||||||
"Z": 283.4973
|
"Z": 283.4973
|
||||||
},
|
},
|
||||||
"TerritoryId": 152,
|
"TerritoryId": 152,
|
||||||
"InteractionType": "CompleteQuest"
|
"InteractionType": "CompleteQuest",
|
||||||
|
"AetheryteShortcut": "East Shroud - Hawthorne Hut",
|
||||||
|
"SkipConditions": {
|
||||||
|
"AetheryteShortcutIf": {
|
||||||
|
"InSameTerritory": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,11 @@
|
|||||||
"Z": -39.383606
|
"Z": -39.383606
|
||||||
},
|
},
|
||||||
"TerritoryId": 152,
|
"TerritoryId": 152,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -83,7 +83,14 @@
|
|||||||
"Z": -12.985474
|
"Z": -12.985474
|
||||||
},
|
},
|
||||||
"TerritoryId": 153,
|
"TerritoryId": 153,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"AI will kill initial adds before the boss, but not switch target whenever new enemies spawn; all NPCs need to be killed for the duty to complete"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -159,7 +159,11 @@
|
|||||||
"Z": -805.478
|
"Z": -805.478
|
||||||
},
|
},
|
||||||
"TerritoryId": 140,
|
"TerritoryId": 140,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -104,10 +104,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 1053,
|
"TerritoryId": 1053,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"BossModEnabled": false,
|
"SinglePlayerDutyOptions": {
|
||||||
"BossModNotes": [
|
"Enabled": true,
|
||||||
"Doesn't handle death properly"
|
"TestedBossModVersion": 292
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -68,6 +68,15 @@
|
|||||||
{
|
{
|
||||||
"Sequence": 3,
|
"Sequence": 3,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": -561.9863,
|
||||||
|
"Y": 9.919454,
|
||||||
|
"Z": 66.29564
|
||||||
|
},
|
||||||
|
"TerritoryId": 152,
|
||||||
|
"InteractionType": "WalkTo"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1008276,
|
"DataId": 1008276,
|
||||||
"Position": {
|
"Position": {
|
||||||
|
@ -78,6 +78,10 @@
|
|||||||
"StopDistance": 1,
|
"StopDistance": 1,
|
||||||
"TerritoryId": 156,
|
"TerritoryId": 156,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
},
|
||||||
"Fly": true
|
"Fly": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -100,6 +100,28 @@
|
|||||||
2
|
2
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Position": {
|
||||||
|
"X": 86.662384,
|
||||||
|
"Y": 28.34813,
|
||||||
|
"Z": -627.5218
|
||||||
|
},
|
||||||
|
"TerritoryId": 156,
|
||||||
|
"InteractionType": "WalkTo",
|
||||||
|
"Fly": true,
|
||||||
|
"SkipConditions": {
|
||||||
|
"StepIf": {
|
||||||
|
"CompletionQuestVariablesFlags": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
32
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"DataId": 1009143,
|
"DataId": 1009143,
|
||||||
"Position": {
|
"Position": {
|
||||||
@ -109,7 +131,6 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 156,
|
"TerritoryId": 156,
|
||||||
"InteractionType": "Interact",
|
"InteractionType": "Interact",
|
||||||
"Fly": true,
|
|
||||||
"$": "1 112 0 0 0 2 -> 2 96 0 0 0 34",
|
"$": "1 112 0 0 0 2 -> 2 96 0 0 0 34",
|
||||||
"CompletionQuestVariablesFlags": [
|
"CompletionQuestVariablesFlags": [
|
||||||
null,
|
null,
|
||||||
|
@ -71,6 +71,14 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 147,
|
"TerritoryId": 147,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"Will target Eline first (other NPCs later), and move to some -other- group of NPCs; only re-targets once they're at 1 HP (for Eline) or die",
|
||||||
|
"If the target isn't in melee range but other NPCs are, whether any AOEs are used for nearby enemies seems random"
|
||||||
|
]
|
||||||
|
},
|
||||||
"Fly": true,
|
"Fly": true,
|
||||||
"AetheryteShortcut": "Northern Thanalan - Ceruleum Processing Plant"
|
"AetheryteShortcut": "Northern Thanalan - Ceruleum Processing Plant"
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,16 @@
|
|||||||
"Z": -328.66406
|
"Z": -328.66406
|
||||||
},
|
},
|
||||||
"TerritoryId": 155,
|
"TerritoryId": 155,
|
||||||
"InteractionType": "SinglePlayerDuty"
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": false,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"WIP: Needs to be re-tested",
|
||||||
|
"AI doesn't move after starting the instance, so enemies won't be triggered",
|
||||||
|
"(First Barrier) If the player is too far south, after being stunned by Vishap's roar, AI doesn't move out of the AOE and dies to the Cauterize"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -46,6 +46,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 155,
|
"TerritoryId": 155,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
},
|
||||||
"Fly": true
|
"Fly": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -96,7 +96,10 @@
|
|||||||
"TerritoryId": 138,
|
"TerritoryId": 138,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"Fly": true,
|
"Fly": true,
|
||||||
"BossModEnabled": true
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -30,7 +30,11 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 397,
|
"TerritoryId": 397,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"Comment": "Walk straight to Gorgagne Mills basement, ignore footprints"
|
"Comment": "Walk straight to Gorgagne Mills basement, ignore footprints",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -59,7 +59,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 401,
|
"TerritoryId": 401,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"BossModEnabled": true
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -79,7 +79,10 @@
|
|||||||
"[Ishgard] The Forgotten Knight",
|
"[Ishgard] The Forgotten Knight",
|
||||||
"[Ishgard] The Tribunal"
|
"[Ishgard] The Tribunal"
|
||||||
],
|
],
|
||||||
"BossModEnabled": true
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -29,7 +29,13 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 145,
|
"TerritoryId": 145,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"BossModEnabled": true
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"Will not move into melee range to kill the gate; Alphinaud will kill it after a while"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -79,7 +79,10 @@
|
|||||||
"TerritoryId": 397,
|
"TerritoryId": 397,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"DisableNavmesh": true,
|
"DisableNavmesh": true,
|
||||||
"BossModEnabled": true
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -75,7 +75,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 418,
|
"TerritoryId": 418,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"BossModEnabled": true
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -57,7 +57,10 @@
|
|||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"Emote": "lookout",
|
"Emote": "lookout",
|
||||||
"StopDistance": 0.25,
|
"StopDistance": 0.25,
|
||||||
"BossModEnabled": true
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -48,7 +48,10 @@
|
|||||||
"[Idyllshire] Aetheryte Plaza",
|
"[Idyllshire] Aetheryte Plaza",
|
||||||
"[Idyllshire] Epilogue Gate (Eastern Hinterlands)"
|
"[Idyllshire] Epilogue Gate (Eastern Hinterlands)"
|
||||||
],
|
],
|
||||||
"BossModEnabled": true
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -69,7 +69,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 402,
|
"TerritoryId": 402,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"BossModEnabled": true
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -85,14 +85,17 @@
|
|||||||
"TerritoryId": 351,
|
"TerritoryId": 351,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"Comment": "Estinien vs. Arch Ultima",
|
"Comment": "Estinien vs. Arch Ultima",
|
||||||
"BossModEnabled": false,
|
"SinglePlayerDutyOptions": {
|
||||||
"BossModNotes": [
|
"Enabled": false,
|
||||||
"AI doesn't move automatically for the first boss",
|
"TestedBossModVersion": 292,
|
||||||
"AI doesn't move automatically for the dialogue with gaius on the bridge",
|
"Notes": [
|
||||||
"After walking downstairs automatically, AI tries to run back towards the stairs (ignoring the arena boudnary)",
|
"AI doesn't move automatically for the first boss",
|
||||||
"After moving from the arena boundary, AI doesn't move into melee range and stops too far away when initially attacking"
|
"AI doesn't move automatically for the dialogue with gaius on the bridge",
|
||||||
],
|
"After walking downstairs automatically, AI tries to run back towards the stairs (ignoring the arena boudnary)",
|
||||||
"$.1": "This doesn't have a duty confirmation dialog, so we're treating TEXT_LUCKMG110_03682_Q1_100_125 as one"
|
"After moving from the arena boundary, AI doesn't move into melee range and stops too far away when initially attacking"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"$": "This doesn't have a duty confirmation dialog, so we're treating TEXT_LUCKMG110_03682_Q1_100_125 as one"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -46,10 +46,13 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 817,
|
"TerritoryId": 817,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"BossModEnabled": false,
|
"SinglePlayerDutyOptions": {
|
||||||
"BossModNotes": [
|
"Enabled": false,
|
||||||
"Doesn't walk to the teleporter to finish the duty"
|
"TestedBossModVersion": 292,
|
||||||
],
|
"Notes": [
|
||||||
|
"Doesn't walk to the teleporter to finish the duty"
|
||||||
|
]
|
||||||
|
},
|
||||||
"Fly": true,
|
"Fly": true,
|
||||||
"Comment": "A Sleep Disturbed (Opo-Opo, Wolf, Serpent)",
|
"Comment": "A Sleep Disturbed (Opo-Opo, Wolf, Serpent)",
|
||||||
"$": "The dialogue choices and data ids here are recycled",
|
"$": "The dialogue choices and data ids here are recycled",
|
||||||
|
@ -78,6 +78,14 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 918,
|
"TerritoryId": 918,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": false,
|
||||||
|
"TestedBossModVersion": 292,
|
||||||
|
"Notes": [
|
||||||
|
"(phase 2) AI doesn't target Ardbert to start combat",
|
||||||
|
"(phase 2) VBM module: Elidibus' line cleave only covers half the length of the actual line (survivable)"
|
||||||
|
]
|
||||||
|
},
|
||||||
"Comment": "Fight NPCs, then Elidibus",
|
"Comment": "Fight NPCs, then Elidibus",
|
||||||
"DialogueChoices": [
|
"DialogueChoices": [
|
||||||
{
|
{
|
||||||
|
@ -84,7 +84,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 180,
|
"TerritoryId": 180,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"Comment": "Great Ship Vylbrand"
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 292
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -46,6 +46,15 @@
|
|||||||
"StopDistance": 7,
|
"StopDistance": 7,
|
||||||
"TerritoryId": 132,
|
"TerritoryId": 132,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": false,
|
||||||
|
"TestedBossModVersion": 293,
|
||||||
|
"Notes": [
|
||||||
|
"(Lunar Odin) AI doesn't pull Odin to start combat",
|
||||||
|
"(Lunar Ravana) AI doesn't pull Ravana to start combat",
|
||||||
|
"(Lunar Ravana) AI doesn't move out of directional parry directions"
|
||||||
|
]
|
||||||
|
},
|
||||||
"Comment": "Death Unto Dawn"
|
"Comment": "Death Unto Dawn"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -99,6 +99,9 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Sequence": 5
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Sequence": 255,
|
"Sequence": 255,
|
||||||
"Steps": [
|
"Steps": [
|
||||||
|
@ -54,6 +54,11 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 816,
|
"TerritoryId": 816,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 293,
|
||||||
|
"$": "test: Redacted"
|
||||||
|
},
|
||||||
"ItemId": 2002569
|
"ItemId": 2002569
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -104,7 +104,9 @@
|
|||||||
"StopDistance": 5,
|
"StopDistance": 5,
|
||||||
"TerritoryId": 829,
|
"TerritoryId": 829,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"SinglePlayerDutyIndex": 1,
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Index": 1
|
||||||
|
},
|
||||||
"DialogueChoices": [
|
"DialogueChoices": [
|
||||||
{
|
{
|
||||||
"Type": "List",
|
"Type": "List",
|
||||||
|
@ -153,7 +153,7 @@
|
|||||||
"Y": -14.169313,
|
"Y": -14.169313,
|
||||||
"Z": 114.76306
|
"Z": 114.76306
|
||||||
},
|
},
|
||||||
"StopDistance": 7,
|
"StopDistance": 6.9,
|
||||||
"TerritoryId": 962,
|
"TerritoryId": 962,
|
||||||
"InteractionType": "Interact"
|
"InteractionType": "Interact"
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,8 @@
|
|||||||
"TerritoryId": 956,
|
"TerritoryId": 956,
|
||||||
"InteractionType": "UseItem",
|
"InteractionType": "UseItem",
|
||||||
"ItemId": 2003129,
|
"ItemId": 2003129,
|
||||||
"Mount": false
|
"Mount": false,
|
||||||
|
"DelaySecondsAtStart": 2
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -30,6 +30,13 @@
|
|||||||
"TerritoryId": 621,
|
"TerritoryId": 621,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"Comment": "A Frosty Reception",
|
"Comment": "A Frosty Reception",
|
||||||
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": false,
|
||||||
|
"TestedBossModVersion": 293,
|
||||||
|
"Notes": [
|
||||||
|
"(Thancred) How many enemies get pulled during the stealth section is random; if you pull multiple you can die here. Can probably be fixed by retrying on very easy."
|
||||||
|
]
|
||||||
|
},
|
||||||
"DialogueChoices": [
|
"DialogueChoices": [
|
||||||
{
|
{
|
||||||
"Type": "List",
|
"Type": "List",
|
||||||
|
@ -59,7 +59,15 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 958,
|
"TerritoryId": 958,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"Comment": "In from the Cold",
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": false,
|
||||||
|
"Notes": [
|
||||||
|
"Instance probably only works on very easy difficulty",
|
||||||
|
"AI doesn't move to first enemy",
|
||||||
|
"AI doesn't unmount from the Magitek Reaper",
|
||||||
|
"Navmesh takes 5+ minutes to build"
|
||||||
|
]
|
||||||
|
},
|
||||||
"DialogueChoices": [
|
"DialogueChoices": [
|
||||||
{
|
{
|
||||||
"Type": "YesNo",
|
"Type": "YesNo",
|
||||||
|
@ -54,7 +54,10 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 961,
|
"TerritoryId": 961,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"Comment": "Venat"
|
"SinglePlayerDutyOptions": {
|
||||||
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 294
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -29,8 +29,11 @@
|
|||||||
},
|
},
|
||||||
"TerritoryId": 958,
|
"TerritoryId": 958,
|
||||||
"InteractionType": "SinglePlayerDuty",
|
"InteractionType": "SinglePlayerDuty",
|
||||||
"AetheryteShortcut": "Garlemald - Camp Broken Glass",
|
"SinglePlayerDutyOptions": {
|
||||||
"Comment": "As the Heavens Burn"
|
"Enabled": true,
|
||||||
|
"TestedBossModVersion": 294
|
||||||
|
},
|
||||||
|
"AetheryteShortcut": "Garlemald - Camp Broken Glass"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -302,6 +302,7 @@
|
|||||||
"WakingSandsSolar",
|
"WakingSandsSolar",
|
||||||
"RisingStonesSolar",
|
"RisingStonesSolar",
|
||||||
"RoguesGuild",
|
"RoguesGuild",
|
||||||
|
"NotRoguesGuild",
|
||||||
"DockStorehouse"
|
"DockStorehouse"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1267,20 +1268,36 @@
|
|||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"BossModEnabled": {
|
"SinglePlayerDutyOptions": {
|
||||||
"type": "boolean"
|
"type": "object",
|
||||||
},
|
"properties": {
|
||||||
"BossModNotes": {
|
"Enabled": {
|
||||||
"type": "array",
|
"type": "boolean"
|
||||||
"items": {
|
},
|
||||||
"type": "string"
|
"Notes": {
|
||||||
}
|
"type": "array",
|
||||||
},
|
"items": {
|
||||||
"SinglePlayerDutyIndex": {
|
"type": "string"
|
||||||
"type": "integer",
|
}
|
||||||
"minimum": 0,
|
},
|
||||||
"maximum": 1,
|
"Index": {
|
||||||
"description": "If a quest has multiple solo instances (which affects 5 quests total), indicates which one this is"
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 1,
|
||||||
|
"description": "If a quest has multiple solo instances (which affects 5 quests total), indicates which one this is"
|
||||||
|
},
|
||||||
|
"TestedBossModVersion": {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 292
|
||||||
|
},
|
||||||
|
"$": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TODO_required": [
|
||||||
|
"Enabled"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ public sealed class SkipConditionConverter() : EnumConverter<EExtraSkipCondition
|
|||||||
{ EExtraSkipCondition.WakingSandsSolar, "WakingSandsSolar" },
|
{ EExtraSkipCondition.WakingSandsSolar, "WakingSandsSolar" },
|
||||||
{ EExtraSkipCondition.RisingStonesSolar, "RisingStonesSolar"},
|
{ EExtraSkipCondition.RisingStonesSolar, "RisingStonesSolar"},
|
||||||
{ EExtraSkipCondition.RoguesGuild, "RoguesGuild"},
|
{ EExtraSkipCondition.RoguesGuild, "RoguesGuild"},
|
||||||
|
{ EExtraSkipCondition.NotRoguesGuild, "NotRoguesGuild"},
|
||||||
{ EExtraSkipCondition.DockStorehouse, "DockStorehouse"},
|
{ EExtraSkipCondition.DockStorehouse, "DockStorehouse"},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ public enum EExtraSkipCondition
|
|||||||
/// Location for ROG quests in Limsa Lominsa; located far underneath the actual lower decks.
|
/// Location for ROG quests in Limsa Lominsa; located far underneath the actual lower decks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
RoguesGuild,
|
RoguesGuild,
|
||||||
|
NotRoguesGuild,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Location for NIN quests in Eastern La Noscea; located far underneath the actual zone.
|
/// Location for NIN quests in Eastern La Noscea; located far underneath the actual zone.
|
||||||
|
@ -75,9 +75,8 @@ 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 bool AutoDutyEnabled { get; set; }
|
||||||
public bool BossModEnabled { get; set; }
|
public SinglePlayerDutyOptions? SinglePlayerDutyOptions { get; set; }
|
||||||
public List<string> BossModNotes { get; set; } = [];
|
public byte SinglePlayerDutyIndex => SinglePlayerDutyOptions?.Index ?? 0;
|
||||||
public byte SinglePlayerDutyIndex { 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();
|
||||||
@ -114,12 +113,15 @@ public sealed class QuestStep
|
|||||||
|
|
||||||
public float CalculateActualStopDistance()
|
public float CalculateActualStopDistance()
|
||||||
{
|
{
|
||||||
if (InteractionType == EInteractionType.WalkTo)
|
if (StopDistance is { } stopDistance)
|
||||||
return StopDistance ?? 0.25f;
|
return stopDistance;
|
||||||
if (InteractionType == EInteractionType.AttuneAetheryte)
|
|
||||||
return StopDistance ?? 10f;
|
return InteractionType switch
|
||||||
else
|
{
|
||||||
return StopDistance ?? DefaultStopDistance;
|
EInteractionType.WalkTo => 0.25f,
|
||||||
|
EInteractionType.AttuneAetheryte => 10f,
|
||||||
|
_ => DefaultStopDistance
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
10
Questionable.Model/Questing/SinglePlayerDutyOptions.cs
Normal file
10
Questionable.Model/Questing/SinglePlayerDutyOptions.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Questionable.Model.Questing;
|
||||||
|
|
||||||
|
public sealed class SinglePlayerDutyOptions
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
public List<string> Notes { get; set; } = [];
|
||||||
|
public byte Index { get; set; }
|
||||||
|
}
|
@ -37,6 +37,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=tertium/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=tertium/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=tural/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=tural/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=urqopacha/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=urqopacha/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=vnavmesh/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=wachumeqimeqi/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=wachumeqimeqi/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=wachunpelo/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=wachunpelo/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=wolekdorf/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=wolekdorf/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Dalamud.Configuration;
|
using Dalamud.Configuration;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||||
@ -45,7 +46,10 @@ internal sealed class Configuration : IPluginConfiguration
|
|||||||
internal sealed class SinglePlayerDutyConfiguration
|
internal sealed class SinglePlayerDutyConfiguration
|
||||||
{
|
{
|
||||||
public bool RunSoloInstancesWithBossMod { get; set; }
|
public bool RunSoloInstancesWithBossMod { get; set; }
|
||||||
public byte RetryDifficulty { get; set; } = 2;
|
|
||||||
|
[SuppressMessage("Performance", "CA1822", Justification = "Will be fixed when no longer WIP")]
|
||||||
|
public byte RetryDifficulty => 0;
|
||||||
|
|
||||||
public HashSet<uint> WhitelistedSinglePlayerDutyCfcIds { get; set; } = [];
|
public HashSet<uint> WhitelistedSinglePlayerDutyCfcIds { get; set; } = [];
|
||||||
public HashSet<uint> BlacklistedSinglePlayerDutyCfcIds { get; set; } = [];
|
public HashSet<uint> BlacklistedSinglePlayerDutyCfcIds { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,7 @@
|
|||||||
using Dalamud.Game.ClientState.Objects.Types;
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
using Dalamud.Plugin;
|
|
||||||
using Dalamud.Plugin.Ipc;
|
|
||||||
using Dalamud.Plugin.Ipc.Exceptions;
|
using Dalamud.Plugin.Ipc.Exceptions;
|
||||||
using Dalamud.Plugin.Services;
|
|
||||||
using Json.Schema;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Questionable.Model;
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Numerics;
|
|
||||||
using Questionable.External;
|
using Questionable.External;
|
||||||
|
|
||||||
namespace Questionable.Controller.CombatModules;
|
namespace Questionable.Controller.CombatModules;
|
||||||
@ -19,8 +12,6 @@ internal sealed class BossModModule : ICombatModule, IDisposable
|
|||||||
private readonly BossModIpc _bossModIpc;
|
private readonly BossModIpc _bossModIpc;
|
||||||
private readonly Configuration _configuration;
|
private readonly Configuration _configuration;
|
||||||
|
|
||||||
private static Stream Preset => typeof(BossModModule).Assembly.GetManifestResourceStream("Questionable.Controller.CombatModules.BossModPreset")!;
|
|
||||||
|
|
||||||
public BossModModule(
|
public BossModModule(
|
||||||
ILogger<BossModModule> logger,
|
ILogger<BossModModule> logger,
|
||||||
BossModIpc bossModIpc,
|
BossModIpc bossModIpc,
|
||||||
@ -43,12 +34,7 @@ internal sealed class BossModModule : ICombatModule, IDisposable
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_bossModIpc.GetPreset("Questionable") == null)
|
_bossModIpc.SetPreset(BossModIpc.EPreset.Overworld);
|
||||||
{
|
|
||||||
using var reader = new StreamReader(Preset);
|
|
||||||
_logger.LogInformation("Loading Questionable BossMod Preset: {LoadedState}", _bossModIpc.CreatePreset(reader.ReadToEnd(), true));
|
|
||||||
}
|
|
||||||
_bossModIpc.SetPreset("Questionable");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (IpcError e)
|
catch (IpcError e)
|
||||||
|
@ -0,0 +1,293 @@
|
|||||||
|
{
|
||||||
|
"Name": "Questionable",
|
||||||
|
"Modules": {
|
||||||
|
"BossMod.Autorotation.xan.DNC": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.MCH": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.MNK": [
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.PCT": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Motifs",
|
||||||
|
"Option": "Downtime"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.PLD": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.SAM": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.SGE": [
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.VPR": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.NIN": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.GNB": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.SMN": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.DRK": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.RPR": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.WHM": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.AST": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.BRD": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.SCH": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.BLM": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.RDM": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.xan.DRG": [
|
||||||
|
{
|
||||||
|
"Track": "Buffs",
|
||||||
|
"Option": "Auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Track": "Targeting",
|
||||||
|
"Option": "Manual"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.VeynWAR": [
|
||||||
|
{
|
||||||
|
"Track": "AOE",
|
||||||
|
"Option": "AutoFinishCombo"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BossMod.Autorotation.MiscAI.NormalMovement": [
|
||||||
|
{
|
||||||
|
"Track": "Destination",
|
||||||
|
"Option": "Pathfind"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"Name": "Questionable",
|
"Name": "Questionable - Quest Battles",
|
||||||
"Modules": {
|
"Modules": {
|
||||||
"BossMod.Autorotation.MiscAI.AutoFarm": [],
|
"BossMod.Autorotation.MiscAI.AutoFarm": [],
|
||||||
"BossMod.Autorotation.MiscAI.AutoPull": [
|
"BossMod.Autorotation.MiscAI.AutoPull": [
|
@ -691,7 +691,7 @@ internal sealed class InteractionUiController : IDisposable
|
|||||||
private bool CheckSinglePlayerDutyYesNo(ElementId questId, QuestStep? step)
|
private bool CheckSinglePlayerDutyYesNo(ElementId questId, QuestStep? step)
|
||||||
{
|
{
|
||||||
if (step is { InteractionType: EInteractionType.SinglePlayerDuty } &&
|
if (step is { InteractionType: EInteractionType.SinglePlayerDuty } &&
|
||||||
_bossModIpc.IsConfiguredToRunSoloInstance(questId, step.SinglePlayerDutyIndex, step.BossModEnabled))
|
_bossModIpc.IsConfiguredToRunSoloInstance(questId, step.SinglePlayerDutyOptions))
|
||||||
{
|
{
|
||||||
// Most of these are yes/no dialogs "Duty calls, ...".
|
// Most of these are yes/no dialogs "Duty calls, ...".
|
||||||
//
|
//
|
||||||
|
@ -89,6 +89,7 @@ internal sealed class MovementController : IDisposable
|
|||||||
public bool IsPathfinding => _pathfindTask is { IsCompleted: false };
|
public bool IsPathfinding => _pathfindTask is { IsCompleted: false };
|
||||||
public DestinationData? Destination { get; set; }
|
public DestinationData? Destination { get; set; }
|
||||||
public DateTime MovementStartedAt { get; private set; } = DateTime.Now;
|
public DateTime MovementStartedAt { get; private set; } = DateTime.Now;
|
||||||
|
public int BuiltNavmeshPercent => _navmeshIpc.GetBuildProgress();
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,7 @@ using Dalamud.Plugin.Services;
|
|||||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Questionable.Controller.Steps;
|
using Questionable.Controller.Steps;
|
||||||
|
using Questionable.Controller.Steps.Interactions;
|
||||||
using Questionable.Controller.Steps.Shared;
|
using Questionable.Controller.Steps.Shared;
|
||||||
using Questionable.External;
|
using Questionable.External;
|
||||||
using Questionable.Functions;
|
using Questionable.Functions;
|
||||||
@ -200,7 +201,13 @@ internal sealed class QuestController : MiniTaskController<QuestController>
|
|||||||
|
|
||||||
if (!_clientState.IsLoggedIn || _condition[ConditionFlag.Unconscious])
|
if (!_clientState.IsLoggedIn || _condition[ConditionFlag.Unconscious])
|
||||||
{
|
{
|
||||||
if (!_taskQueue.AllTasksComplete)
|
if (_condition[ConditionFlag.Unconscious] &&
|
||||||
|
_condition[ConditionFlag.SufferingStatusAffliction63] &&
|
||||||
|
_clientState.TerritoryType == SinglePlayerDuty.LahabreaTerritoryId)
|
||||||
|
{
|
||||||
|
// ignore, we're in the lahabrea fight
|
||||||
|
}
|
||||||
|
else if (!_taskQueue.AllTasksComplete)
|
||||||
{
|
{
|
||||||
Stop("HP = 0");
|
Stop("HP = 0");
|
||||||
_movementController.Stop();
|
_movementController.Stop();
|
||||||
@ -680,6 +687,17 @@ internal sealed class QuestController : MiniTaskController<QuestController>
|
|||||||
public bool IsRunning => !_taskQueue.AllTasksComplete;
|
public bool IsRunning => !_taskQueue.AllTasksComplete;
|
||||||
public TaskQueue TaskQueue => _taskQueue;
|
public TaskQueue TaskQueue => _taskQueue;
|
||||||
|
|
||||||
|
public string? CurrentTaskState
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_taskQueue.CurrentTaskExecutor is IDebugStateProvider debugStateProvider)
|
||||||
|
return debugStateProvider.GetDebugState();
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class QuestProgress
|
public sealed class QuestProgress
|
||||||
{
|
{
|
||||||
public Quest Quest { get; }
|
public Quest Quest { get; }
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Questionable.Data;
|
||||||
using Questionable.Functions;
|
using Questionable.Functions;
|
||||||
using Questionable.Model;
|
using Questionable.Model;
|
||||||
using Questionable.Model.Questing;
|
using Questionable.Model.Questing;
|
||||||
@ -21,7 +23,7 @@ internal static class NextQuest
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
// probably irrelevant, since pick up is handled elsewhere (and, in particular, checks for aetherytes and stuff)
|
// probably irrelevant, since pick up is handled elsewhere (and, in particular, checks for aetherytes and stuff)
|
||||||
if (questFunctions.GetPriorityQuests().Contains(step.NextQuestId))
|
if (questFunctions.GetPriorityQuests(onlyClassAndRoleQuests: true).Contains(step.NextQuestId))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new SetQuestTask(step.NextQuestId, quest.Id);
|
return new SetQuestTask(step.NextQuestId, quest.Id);
|
||||||
|
@ -27,7 +27,7 @@ internal static class SendNotification
|
|||||||
new Task(step.InteractionType, step.ContentFinderConditionId.HasValue
|
new Task(step.InteractionType, step.ContentFinderConditionId.HasValue
|
||||||
? territoryData.GetContentFinderCondition(step.ContentFinderConditionId.Value)?.Name
|
? territoryData.GetContentFinderCondition(step.ContentFinderConditionId.Value)?.Name
|
||||||
: step.Comment),
|
: step.Comment),
|
||||||
EInteractionType.SinglePlayerDuty when !bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyIndex, step.BossModEnabled) =>
|
EInteractionType.SinglePlayerDuty when !bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyOptions) =>
|
||||||
new Task(step.InteractionType, quest.Info.Name),
|
new Task(step.InteractionType, quest.Info.Name),
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
|
27
Questionable/Controller/Steps/Common/WaitNavmesh.cs
Normal file
27
Questionable/Controller/Steps/Common/WaitNavmesh.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
namespace Questionable.Controller.Steps.Common;
|
||||||
|
|
||||||
|
internal sealed class WaitNavmesh
|
||||||
|
{
|
||||||
|
internal sealed record Task : ITask
|
||||||
|
{
|
||||||
|
public override string ToString() => "Wait(navmesh)";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class Executor(MovementController movementController) : TaskExecutor<Task>, IDebugStateProvider
|
||||||
|
{
|
||||||
|
protected override bool Start() => true;
|
||||||
|
|
||||||
|
public override ETaskResult Update() =>
|
||||||
|
movementController.IsNavmeshReady ? ETaskResult.TaskComplete : ETaskResult.StillRunning;
|
||||||
|
|
||||||
|
public override bool ShouldInterruptOnDamage() => false;
|
||||||
|
|
||||||
|
public string? GetDebugState()
|
||||||
|
{
|
||||||
|
if (!movementController.IsNavmeshReady)
|
||||||
|
return $"Navmesh: {movementController.BuiltNavmeshPercent}%";
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -96,6 +96,12 @@ internal static class Interact
|
|||||||
private EInteractionState _interactionState = EInteractionState.None;
|
private EInteractionState _interactionState = EInteractionState.None;
|
||||||
private DateTime _continueAt = DateTime.MinValue;
|
private DateTime _continueAt = DateTime.MinValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A slight delay when we think an interaction has ended, to make sure that we're processing "Action cancelled"
|
||||||
|
/// prior to the next step (in case we're attacked).
|
||||||
|
/// </summary>
|
||||||
|
private bool delayedFinalCheck;
|
||||||
|
|
||||||
public Quest? Quest => Task.Quest;
|
public Quest? Quest => Task.Quest;
|
||||||
public EInteractionType InteractionType { get; set; }
|
public EInteractionType InteractionType { get; set; }
|
||||||
|
|
||||||
@ -179,7 +185,14 @@ internal static class Interact
|
|||||||
return ETaskResult.StillRunning;
|
return ETaskResult.StillRunning;
|
||||||
else if (ProgressContext.WasSuccessful() ||
|
else if (ProgressContext.WasSuccessful() ||
|
||||||
_interactionState == EInteractionState.InteractionConfirmed)
|
_interactionState == EInteractionState.InteractionConfirmed)
|
||||||
return ETaskResult.TaskComplete;
|
{
|
||||||
|
if (delayedFinalCheck)
|
||||||
|
return ETaskResult.TaskComplete;
|
||||||
|
|
||||||
|
_continueAt = DateTime.Now.AddSeconds(0.2);
|
||||||
|
delayedFinalCheck = true;
|
||||||
|
return ETaskResult.StillRunning;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IGameObject? gameObject = gameFunctions.FindObjectByDataId(Task.DataId);
|
IGameObject? gameObject = gameFunctions.FindObjectByDataId(Task.DataId);
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Dalamud.Game.ClientState.Conditions;
|
||||||
|
using Dalamud.Game.ClientState.Objects;
|
||||||
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
|
using Questionable.Controller.Steps.Common;
|
||||||
using Questionable.Controller.Steps.Shared;
|
using Questionable.Controller.Steps.Shared;
|
||||||
using Questionable.Data;
|
using Questionable.Data;
|
||||||
using Questionable.External;
|
using Questionable.External;
|
||||||
@ -12,22 +17,34 @@ namespace Questionable.Controller.Steps.Interactions;
|
|||||||
|
|
||||||
internal static class SinglePlayerDuty
|
internal static class SinglePlayerDuty
|
||||||
{
|
{
|
||||||
|
public const int LahabreaTerritoryId = 1052;
|
||||||
|
|
||||||
internal sealed class Factory(
|
internal sealed class Factory(
|
||||||
BossModIpc bossModIpc,
|
BossModIpc bossModIpc,
|
||||||
TerritoryData territoryData) : ITaskFactory
|
TerritoryData territoryData,
|
||||||
|
ICondition condition,
|
||||||
|
IClientState clientState) : ITaskFactory
|
||||||
{
|
{
|
||||||
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
||||||
{
|
{
|
||||||
if (step.InteractionType != EInteractionType.SinglePlayerDuty)
|
if (step.InteractionType != EInteractionType.SinglePlayerDuty)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
if (bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyIndex, step.BossModEnabled))
|
if (bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyOptions))
|
||||||
{
|
{
|
||||||
if (!territoryData.TryGetContentFinderConditionForSoloInstance(quest.Id, step.SinglePlayerDutyIndex, out var cfcData))
|
if (!territoryData.TryGetContentFinderConditionForSoloInstance(quest.Id, step.SinglePlayerDutyIndex, out var cfcData))
|
||||||
throw new TaskException("Failed to get content finder condition for solo instance");
|
throw new TaskException("Failed to get content finder condition for solo instance");
|
||||||
|
|
||||||
yield return new StartSinglePlayerDuty(cfcData.ContentFinderConditionId);
|
yield return new StartSinglePlayerDuty(cfcData.ContentFinderConditionId);
|
||||||
yield return new EnableAi();
|
yield return new EnableAi();
|
||||||
|
if (cfcData.TerritoryId == LahabreaTerritoryId)
|
||||||
|
{
|
||||||
|
yield return new SetTarget(14643);
|
||||||
|
yield return new WaitCondition.Task(() => condition[ConditionFlag.Unconscious] || clientState.TerritoryType != LahabreaTerritoryId, "Wait(death)");
|
||||||
|
yield return new DisableAi();
|
||||||
|
yield return new WaitCondition.Task(() => !condition[ConditionFlag.Unconscious] || clientState.TerritoryType != LahabreaTerritoryId, "Wait(resurrection)");
|
||||||
|
yield return new EnableAi();
|
||||||
|
}
|
||||||
yield return new WaitSinglePlayerDuty(cfcData.ContentFinderConditionId);
|
yield return new WaitSinglePlayerDuty(cfcData.ContentFinderConditionId);
|
||||||
yield return new DisableAi();
|
yield return new DisableAi();
|
||||||
yield return new WaitAtEnd.WaitNextStepOrSequence();
|
yield return new WaitAtEnd.WaitNextStepOrSequence();
|
||||||
@ -79,7 +96,9 @@ internal static class SinglePlayerDuty
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class WaitSinglePlayerDutyExecutor(
|
internal sealed class WaitSinglePlayerDutyExecutor(
|
||||||
BossModIpc bossModIpc) : TaskExecutor<WaitSinglePlayerDuty>, IStoppableTaskExecutor
|
BossModIpc bossModIpc,
|
||||||
|
MovementController movementController)
|
||||||
|
: TaskExecutor<WaitSinglePlayerDuty>, IStoppableTaskExecutor, IDebugStateProvider
|
||||||
{
|
{
|
||||||
protected override bool Start() => true;
|
protected override bool Start() => true;
|
||||||
|
|
||||||
@ -93,6 +112,14 @@ internal static class SinglePlayerDuty
|
|||||||
public void StopNow() => bossModIpc.DisableAi();
|
public void StopNow() => bossModIpc.DisableAi();
|
||||||
|
|
||||||
public override bool ShouldInterruptOnDamage() => false;
|
public override bool ShouldInterruptOnDamage() => false;
|
||||||
|
|
||||||
|
public string? GetDebugState()
|
||||||
|
{
|
||||||
|
if (!movementController.IsNavmeshReady)
|
||||||
|
return $"Navmesh: {movementController.BuiltNavmeshPercent}%";
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed record DisableAi : ITask
|
internal sealed record DisableAi : ITask
|
||||||
@ -113,4 +140,32 @@ internal static class SinglePlayerDuty
|
|||||||
|
|
||||||
public override bool ShouldInterruptOnDamage() => false;
|
public override bool ShouldInterruptOnDamage() => false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO this should be handled in VBM
|
||||||
|
internal sealed record SetTarget(uint DataId) : ITask
|
||||||
|
{
|
||||||
|
public override string ToString() => $"SetTarget({DataId})";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class SetTargetExecutor(
|
||||||
|
ITargetManager targetManager,
|
||||||
|
IObjectTable objectTable) : TaskExecutor<SetTarget>
|
||||||
|
{
|
||||||
|
protected override bool Start() => true;
|
||||||
|
|
||||||
|
public override ETaskResult Update()
|
||||||
|
{
|
||||||
|
if (targetManager.Target?.DataId == Task.DataId)
|
||||||
|
return ETaskResult.TaskComplete;
|
||||||
|
|
||||||
|
IGameObject? gameObject = objectTable.FirstOrDefault(x => x.DataId == Task.DataId);
|
||||||
|
if (gameObject == null)
|
||||||
|
return ETaskResult.StillRunning;
|
||||||
|
|
||||||
|
targetManager.Target = gameObject;
|
||||||
|
return ETaskResult.StillRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ShouldInterruptOnDamage() => false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,12 +45,13 @@ internal static class QuestCleanUp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// have any of the previous sequences interacted with the issuer?
|
// have any of the previous sequences interacted with the issuer?
|
||||||
var previousSequences =
|
var previousSteps =
|
||||||
quest.AllSequences()
|
quest.AllSequences()
|
||||||
.Where(x => x.Sequence > 0 // quest accept doesn't ever put us into a mount
|
.Where(x => x.Sequence > 0 // quest accept doesn't ever put us into a mount
|
||||||
&& x.Sequence < sequence.Sequence)
|
&& x.Sequence < sequence.Sequence)
|
||||||
|
.SelectMany(x => x.Steps)
|
||||||
.ToList();
|
.ToList();
|
||||||
if (previousSequences.SelectMany(x => x.Steps).All(x => x.DataId != mountConfiguration.IssuerDataId))
|
if (!previousSteps.Any(x => x.DataId != null && mountConfiguration.IssuerDataIds.Contains(x.DataId.Value)))
|
||||||
{
|
{
|
||||||
// this quest hasn't given us a mount yet
|
// this quest hasn't given us a mount yet
|
||||||
logger.LogInformation("Haven't talked to mount NPC for this allied society quest; {Aetheryte}", mountConfiguration.ClosestAetheryte);
|
logger.LogInformation("Haven't talked to mount NPC for this allied society quest; {Aetheryte}", mountConfiguration.ClosestAetheryte);
|
||||||
|
@ -20,7 +20,6 @@ namespace Questionable.Controller.Steps.Shared;
|
|||||||
internal static class AethernetShortcut
|
internal static class AethernetShortcut
|
||||||
{
|
{
|
||||||
internal sealed class Factory(
|
internal sealed class Factory(
|
||||||
MovementController movementController,
|
|
||||||
AetheryteData aetheryteData,
|
AetheryteData aetheryteData,
|
||||||
TerritoryData territoryData,
|
TerritoryData territoryData,
|
||||||
IClientState clientState)
|
IClientState clientState)
|
||||||
@ -31,8 +30,7 @@ internal static class AethernetShortcut
|
|||||||
if (step.AethernetShortcut == null)
|
if (step.AethernetShortcut == null)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
yield return new WaitCondition.Task(() => movementController.IsNavmeshReady,
|
yield return new WaitNavmesh.Task();
|
||||||
"Wait(navmesh ready)");
|
|
||||||
yield return new Task(step.AethernetShortcut.From, step.AethernetShortcut.To,
|
yield return new Task(step.AethernetShortcut.From, step.AethernetShortcut.To,
|
||||||
step.SkipConditions?.AethernetShortcutIf ?? new());
|
step.SkipConditions?.AethernetShortcutIf ?? new());
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ internal static class Gather
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class DelayedGatheringExecutor(
|
internal sealed class DelayedGatheringExecutor(
|
||||||
MovementController movementController,
|
|
||||||
GatheringData gatheringData,
|
GatheringData gatheringData,
|
||||||
GatheringPointRegistry gatheringPointRegistry,
|
GatheringPointRegistry gatheringPointRegistry,
|
||||||
TerritoryData territoryData,
|
TerritoryData territoryData,
|
||||||
@ -85,8 +84,7 @@ internal static class Gather
|
|||||||
yield return new WaitCondition.Task(() => clientState.TerritoryType == territoryId,
|
yield return new WaitCondition.Task(() => clientState.TerritoryType == territoryId,
|
||||||
$"Wait(territory: {territoryData.GetNameAndId(territoryId)})");
|
$"Wait(territory: {territoryData.GetNameAndId(territoryId)})");
|
||||||
|
|
||||||
yield return new WaitCondition.Task(() => movementController.IsNavmeshReady,
|
yield return new WaitNavmesh.Task();
|
||||||
"Wait(navmesh ready)");
|
|
||||||
|
|
||||||
yield return new GatheringTask(gatheringPointId, Task.GatheredItem);
|
yield return new GatheringTask(gatheringPointId, Task.GatheredItem);
|
||||||
yield return new WaitAtEnd.WaitDelay();
|
yield return new WaitAtEnd.WaitDelay();
|
||||||
|
@ -25,7 +25,6 @@ namespace Questionable.Controller.Steps.Shared;
|
|||||||
internal static class MoveTo
|
internal static class MoveTo
|
||||||
{
|
{
|
||||||
internal sealed class Factory(
|
internal sealed class Factory(
|
||||||
MovementController movementController,
|
|
||||||
IClientState clientState,
|
IClientState clientState,
|
||||||
AetheryteData aetheryteData,
|
AetheryteData aetheryteData,
|
||||||
TerritoryData territoryData,
|
TerritoryData territoryData,
|
||||||
@ -67,10 +66,7 @@ internal static class MoveTo
|
|||||||
$"Wait(territory: {territoryData.GetNameAndId(step.TerritoryId)})");
|
$"Wait(territory: {territoryData.GetNameAndId(step.TerritoryId)})");
|
||||||
|
|
||||||
if (!step.DisableNavmesh)
|
if (!step.DisableNavmesh)
|
||||||
{
|
yield return new WaitNavmesh.Task();
|
||||||
yield return new WaitCondition.Task(() => movementController.IsNavmeshReady,
|
|
||||||
"Wait(navmesh ready)");
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return new MoveTask(step, destination);
|
yield return new MoveTask(step, destination);
|
||||||
|
|
||||||
|
@ -310,6 +310,7 @@ internal static class SkipCondition
|
|||||||
EExtraSkipCondition.WakingSandsSolar => territoryType == 212 && position.X >= 24,
|
EExtraSkipCondition.WakingSandsSolar => territoryType == 212 && position.X >= 24,
|
||||||
EExtraSkipCondition.RisingStonesSolar => territoryType == 351 && position.Z <= -28,
|
EExtraSkipCondition.RisingStonesSolar => territoryType == 351 && position.Z <= -28,
|
||||||
EExtraSkipCondition.RoguesGuild => territoryType == 129 && position.Y <= -115,
|
EExtraSkipCondition.RoguesGuild => territoryType == 129 && position.Y <= -115,
|
||||||
|
EExtraSkipCondition.NotRoguesGuild => territoryType == 129 && position.Y > -115,
|
||||||
EExtraSkipCondition.DockStorehouse => territoryType == 137 && position.Y <= -20,
|
EExtraSkipCondition.DockStorehouse => territoryType == 137 && position.Y <= -20,
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(condition), condition, null)
|
_ => throw new ArgumentOutOfRangeException(nameof(condition), condition, null)
|
||||||
};
|
};
|
||||||
|
@ -54,7 +54,7 @@ internal static class WaitAtEnd
|
|||||||
return [new WaitNextStepOrSequence()];
|
return [new WaitNextStepOrSequence()];
|
||||||
|
|
||||||
case EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled):
|
case EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled):
|
||||||
case EInteractionType.SinglePlayerDuty when !bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyIndex, step.BossModEnabled):
|
case EInteractionType.SinglePlayerDuty when !bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyOptions):
|
||||||
return [new EndAutomation()];
|
return [new EndAutomation()];
|
||||||
|
|
||||||
case EInteractionType.WalkTo:
|
case EInteractionType.WalkTo:
|
||||||
|
@ -30,6 +30,11 @@ internal interface IStoppableTaskExecutor : ITaskExecutor
|
|||||||
void StopNow();
|
void StopNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal interface IDebugStateProvider : ITaskExecutor
|
||||||
|
{
|
||||||
|
string? GetDebugState();
|
||||||
|
}
|
||||||
|
|
||||||
internal abstract class TaskExecutor<T> : ITaskExecutor
|
internal abstract class TaskExecutor<T> : ITaskExecutor
|
||||||
where T : class, ITask
|
where T : class, ITask
|
||||||
{
|
{
|
||||||
|
169
Questionable/Controller/Utils/PartyWatchDog.cs
Normal file
169
Questionable/Controller/Utils/PartyWatchDog.cs
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
using System;
|
||||||
|
using Dalamud.Plugin.Services;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Game.Group;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Questionable.Controller.Utils;
|
||||||
|
|
||||||
|
internal sealed class PartyWatchDog : IDisposable
|
||||||
|
{
|
||||||
|
private readonly QuestController _questController;
|
||||||
|
private readonly IClientState _clientState;
|
||||||
|
private readonly IChatGui _chatGui;
|
||||||
|
private readonly ILogger<PartyWatchDog> _logger;
|
||||||
|
|
||||||
|
private ushort? _uncheckedTeritoryId;
|
||||||
|
|
||||||
|
public PartyWatchDog(QuestController questController, IClientState clientState, IChatGui chatGui,
|
||||||
|
ILogger<PartyWatchDog> logger)
|
||||||
|
{
|
||||||
|
_questController = questController;
|
||||||
|
_clientState = clientState;
|
||||||
|
_chatGui = chatGui;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
|
_clientState.TerritoryChanged += TerritoryChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void TerritoryChanged(ushort newTerritoryId)
|
||||||
|
{
|
||||||
|
var intendedUse = (ETerritoryIntendedUseEnum)GameMain.Instance()->CurrentTerritoryIntendedUseId;
|
||||||
|
switch (intendedUse)
|
||||||
|
{
|
||||||
|
case ETerritoryIntendedUseEnum.Gaol:
|
||||||
|
case ETerritoryIntendedUseEnum.Frontline:
|
||||||
|
case ETerritoryIntendedUseEnum.LordOfVerminion:
|
||||||
|
case ETerritoryIntendedUseEnum.Diadem:
|
||||||
|
case ETerritoryIntendedUseEnum.CrystallineConflict:
|
||||||
|
case ETerritoryIntendedUseEnum.Battlehall:
|
||||||
|
case ETerritoryIntendedUseEnum.CrystallineConflict2:
|
||||||
|
case ETerritoryIntendedUseEnum.DeepDungeon:
|
||||||
|
case ETerritoryIntendedUseEnum.TreasureMapDuty:
|
||||||
|
case ETerritoryIntendedUseEnum.Diadem2:
|
||||||
|
case ETerritoryIntendedUseEnum.RivalWings:
|
||||||
|
case ETerritoryIntendedUseEnum.Eureka:
|
||||||
|
case ETerritoryIntendedUseEnum.LeapOfFaith:
|
||||||
|
case ETerritoryIntendedUseEnum.OceanFishing:
|
||||||
|
case ETerritoryIntendedUseEnum.Diadem3:
|
||||||
|
case ETerritoryIntendedUseEnum.Bozja:
|
||||||
|
case ETerritoryIntendedUseEnum.Battlehall2:
|
||||||
|
case ETerritoryIntendedUseEnum.Battlehall3:
|
||||||
|
case ETerritoryIntendedUseEnum.LargeScaleRaid:
|
||||||
|
case ETerritoryIntendedUseEnum.LargeScaleSavageRaid:
|
||||||
|
case ETerritoryIntendedUseEnum.Blunderville:
|
||||||
|
StopIfRunning($"Unsupported Area entered ({newTerritoryId})");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ETerritoryIntendedUseEnum.Dungeon:
|
||||||
|
case ETerritoryIntendedUseEnum.VariantDungeon:
|
||||||
|
case ETerritoryIntendedUseEnum.AllianceRaid:
|
||||||
|
case ETerritoryIntendedUseEnum.Trial:
|
||||||
|
case ETerritoryIntendedUseEnum.Raid:
|
||||||
|
case ETerritoryIntendedUseEnum.Raid2:
|
||||||
|
case ETerritoryIntendedUseEnum.SeasonalEvent:
|
||||||
|
case ETerritoryIntendedUseEnum.SeasonalEvent2:
|
||||||
|
case ETerritoryIntendedUseEnum.CriterionDuty:
|
||||||
|
case ETerritoryIntendedUseEnum.CriterionSavageDuty:
|
||||||
|
_uncheckedTeritoryId = newTerritoryId;
|
||||||
|
_logger.LogInformation("Will check territory {TerritoryId} after loading", newTerritoryId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void Update()
|
||||||
|
{
|
||||||
|
if (_uncheckedTeritoryId == _clientState.TerritoryType && GameMain.Instance()->TerritoryLoadState == 2)
|
||||||
|
{
|
||||||
|
var groupManager = GroupManager.Instance();
|
||||||
|
if (groupManager == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
byte memberCount = groupManager->MainGroup.MemberCount;
|
||||||
|
bool isInAlliance = groupManager->MainGroup.IsAlliance;
|
||||||
|
_logger.LogDebug("Territory {TerritoryId} with {MemberCount} members, alliance: {IsInAlliance}",
|
||||||
|
_uncheckedTeritoryId, memberCount, isInAlliance);
|
||||||
|
if (memberCount > 1 || isInAlliance)
|
||||||
|
StopIfRunning("Other party members present");
|
||||||
|
|
||||||
|
_uncheckedTeritoryId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopIfRunning(string reason)
|
||||||
|
{
|
||||||
|
if (_questController.IsRunning || _questController.AutomationType != QuestController.EAutomationType.Manual)
|
||||||
|
{
|
||||||
|
_chatGui.PrintError(
|
||||||
|
$"Stopping Questionable: {reason}. If you believe this to be correct, please restart Questionable manually.",
|
||||||
|
CommandHandler.MessageTag, CommandHandler.TagColor);
|
||||||
|
_questController.Stop(reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_clientState.TerritoryChanged -= TerritoryChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
// from https://github.com/NightmareXIV/ECommons/blob/f69e460e95134c72592654059843b138b4c01a9e/ECommons/ExcelServices/TerritoryIntendedUseEnum.cs#L5
|
||||||
|
[UsedImplicitly(ImplicitUseTargetFlags.Members, Reason = "game data")]
|
||||||
|
private enum ETerritoryIntendedUseEnum : byte
|
||||||
|
{
|
||||||
|
CityArea = 0,
|
||||||
|
OpenWorld = 1,
|
||||||
|
Inn = 2,
|
||||||
|
Dungeon = 3,
|
||||||
|
VariantDungeon = 4,
|
||||||
|
Gaol = 5,
|
||||||
|
StartingArea = 6,
|
||||||
|
QuestArea = 7,
|
||||||
|
AllianceRaid = 8,
|
||||||
|
QuestBattle = 9,
|
||||||
|
Trial = 10,
|
||||||
|
QuestArea2 = 12,
|
||||||
|
ResidentialArea = 13,
|
||||||
|
HousingInstances = 14,
|
||||||
|
QuestArea3 = 15,
|
||||||
|
Raid = 16,
|
||||||
|
Raid2 = 17,
|
||||||
|
Frontline = 18,
|
||||||
|
ChocoboSquare = 20,
|
||||||
|
RestorationEvent = 21,
|
||||||
|
Sanctum = 22,
|
||||||
|
GoldSaucer = 23,
|
||||||
|
LordOfVerminion = 25,
|
||||||
|
Diadem = 26,
|
||||||
|
HallOfTheNovice = 27,
|
||||||
|
CrystallineConflict = 28,
|
||||||
|
QuestBattle2 = 29,
|
||||||
|
Barracks = 30,
|
||||||
|
DeepDungeon = 31,
|
||||||
|
SeasonalEvent = 32,
|
||||||
|
TreasureMapDuty = 33,
|
||||||
|
SeasonalEventDuty = 34,
|
||||||
|
Battlehall = 35,
|
||||||
|
CrystallineConflict2 = 37,
|
||||||
|
Diadem2 = 38,
|
||||||
|
RivalWings = 39,
|
||||||
|
Unknown1 = 40,
|
||||||
|
Eureka = 41,
|
||||||
|
SeasonalEvent2 = 43,
|
||||||
|
LeapOfFaith = 44,
|
||||||
|
MaskedCarnivale = 45,
|
||||||
|
OceanFishing = 46,
|
||||||
|
Diadem3 = 47,
|
||||||
|
Bozja = 48,
|
||||||
|
IslandSanctuary = 49,
|
||||||
|
Battlehall2 = 50,
|
||||||
|
Battlehall3 = 51,
|
||||||
|
LargeScaleRaid = 52,
|
||||||
|
LargeScaleSavageRaid = 53,
|
||||||
|
QuestArea4 = 54,
|
||||||
|
TribalInstance = 56,
|
||||||
|
CriterionDuty = 57,
|
||||||
|
CriterionSavageDuty = 58,
|
||||||
|
Blunderville = 59,
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ using Dalamud.Plugin.Services;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Questionable.Controller;
|
using Questionable.Controller;
|
||||||
using Questionable.Controller.GameUi;
|
using Questionable.Controller.GameUi;
|
||||||
|
using Questionable.Controller.Utils;
|
||||||
using Questionable.Windows;
|
using Questionable.Windows;
|
||||||
|
|
||||||
namespace Questionable;
|
namespace Questionable;
|
||||||
@ -23,6 +24,7 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
private readonly ConfigWindow _configWindow;
|
private readonly ConfigWindow _configWindow;
|
||||||
private readonly IToastGui _toastGui;
|
private readonly IToastGui _toastGui;
|
||||||
private readonly Configuration _configuration;
|
private readonly Configuration _configuration;
|
||||||
|
private readonly PartyWatchDog _partyWatchDog;
|
||||||
private readonly ILogger<DalamudInitializer> _logger;
|
private readonly ILogger<DalamudInitializer> _logger;
|
||||||
|
|
||||||
public DalamudInitializer(
|
public DalamudInitializer(
|
||||||
@ -42,6 +44,7 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
PriorityWindow priorityWindow,
|
PriorityWindow priorityWindow,
|
||||||
IToastGui toastGui,
|
IToastGui toastGui,
|
||||||
Configuration configuration,
|
Configuration configuration,
|
||||||
|
PartyWatchDog partyWatchDog,
|
||||||
ILogger<DalamudInitializer> logger)
|
ILogger<DalamudInitializer> logger)
|
||||||
{
|
{
|
||||||
_pluginInterface = pluginInterface;
|
_pluginInterface = pluginInterface;
|
||||||
@ -54,6 +57,7 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
_configWindow = configWindow;
|
_configWindow = configWindow;
|
||||||
_toastGui = toastGui;
|
_toastGui = toastGui;
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
|
_partyWatchDog = partyWatchDog;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
_windowSystem.AddWindow(oneTimeSetupWindow);
|
_windowSystem.AddWindow(oneTimeSetupWindow);
|
||||||
@ -77,6 +81,7 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
|
|
||||||
private void FrameworkUpdate(IFramework framework)
|
private void FrameworkUpdate(IFramework framework)
|
||||||
{
|
{
|
||||||
|
_partyWatchDog.Update();
|
||||||
_questController.Update();
|
_questController.Update();
|
||||||
|
|
||||||
try
|
try
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user