From 6f0f02fa1227d25b47f4ec8711a8b21e2af3fa03 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Mon, 10 Mar 2025 21:19:10 +0100 Subject: [PATCH] Add quest battle for 'It's Probably a Trap' --- .../A2-Kugane/2474_It's Probably a Trap.json | 6 ++- .../Steps/Interactions/SinglePlayerDuty.cs | 40 +++++++++++++++---- Questionable/External/BossModIpc.cs | 4 +- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/QuestPaths/4.x - Stormblood/MSQ/A2-Kugane/2474_It's Probably a Trap.json b/QuestPaths/4.x - Stormblood/MSQ/A2-Kugane/2474_It's Probably a Trap.json index a5a7d30c..67e65dd8 100644 --- a/QuestPaths/4.x - Stormblood/MSQ/A2-Kugane/2474_It's Probably a Trap.json +++ b/QuestPaths/4.x - Stormblood/MSQ/A2-Kugane/2474_It's Probably a Trap.json @@ -106,6 +106,10 @@ }, "TerritoryId": 628, "InteractionType": "SinglePlayerDuty", + "SinglePlayerDutyOptions": { + "Enabled": true, + "TestedBossModVersion": "0.1.0.1" + }, "AethernetShortcut": [ "[Kugane] The Ruby Bazaar", "[Kugane] Kogane Dori Markets" @@ -129,4 +133,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/Questionable/Controller/Steps/Interactions/SinglePlayerDuty.cs b/Questionable/Controller/Steps/Interactions/SinglePlayerDuty.cs index ef61cb46..264d8128 100644 --- a/Questionable/Controller/Steps/Interactions/SinglePlayerDuty.cs +++ b/Questionable/Controller/Steps/Interactions/SinglePlayerDuty.cs @@ -6,6 +6,8 @@ using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.Game.Event; +using FFXIVClientStructs.FFXIV.Client.Game.InstanceContent; using Questionable.Controller.Steps.Common; using Questionable.Controller.Steps.Shared; using Questionable.Data; @@ -17,7 +19,11 @@ namespace Questionable.Controller.Steps.Interactions; internal static class SinglePlayerDuty { - public const int LahabreaTerritoryId = 1052; + private static class SpecialTerritories + { + public const ushort Lahabrea = 1052; + public const ushort ItsProbablyATrap = 665; + } internal sealed class Factory( BossModIpc bossModIpc, @@ -32,24 +38,42 @@ internal static class SinglePlayerDuty 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"); yield return new StartSinglePlayerDuty(cfcData.ContentFinderConditionId); yield return new EnableAi(); - if (cfcData.TerritoryId == LahabreaTerritoryId) + if (cfcData.TerritoryId == SpecialTerritories.Lahabrea) { yield return new SetTarget(14643); - yield return new WaitCondition.Task(() => condition[ConditionFlag.Unconscious] || clientState.TerritoryType != LahabreaTerritoryId, "Wait(death)"); + yield return new WaitCondition.Task( + () => condition[ConditionFlag.Unconscious] || clientState.TerritoryType != SpecialTerritories.Lahabrea, + "Wait(death)"); yield return new DisableAi(); - yield return new WaitCondition.Task(() => !condition[ConditionFlag.Unconscious] || clientState.TerritoryType != LahabreaTerritoryId, "Wait(resurrection)"); + yield return new WaitCondition.Task( + () => !condition[ConditionFlag.Unconscious] || clientState.TerritoryType != SpecialTerritories.Lahabrea, + "Wait(resurrection)"); yield return new EnableAi(); } + else if (cfcData.TerritoryId == SpecialTerritories.ItsProbablyATrap) + { + yield return new WaitCondition.Task(() => DutyActionsAvailable() || clientState.TerritoryType != SpecialTerritories.ItsProbablyATrap, + "Wait(Phase 2)"); + yield return new EnableAi(true); + } + yield return new WaitSinglePlayerDuty(cfcData.ContentFinderConditionId); yield return new DisableAi(); yield return new WaitAtEnd.WaitNextStepOrSequence(); } } + + private unsafe bool DutyActionsAvailable() + { + ContentDirector* contentDirector = EventFramework.Instance()->GetContentDirector(); + return contentDirector != null && contentDirector->DutyActionManager.ActionsPresent; + } } internal sealed record StartSinglePlayerDuty(uint ContentFinderConditionId) : ITask @@ -71,9 +95,9 @@ internal static class SinglePlayerDuty public override bool ShouldInterruptOnDamage() => false; } - internal sealed record EnableAi : ITask + internal sealed record EnableAi(bool Passive = false) : ITask { - public override string ToString() => "BossMod.EnableAi"; + public override string ToString() => $"BossMod.EnableAi({(Passive ? "Passive" : "AutoPull")})"; } internal sealed class EnableAiExecutor( @@ -81,7 +105,7 @@ internal static class SinglePlayerDuty { protected override bool Start() { - bossModIpc.EnableAi(); + bossModIpc.EnableAi(Task.Passive); return true; } diff --git a/Questionable/External/BossModIpc.cs b/Questionable/External/BossModIpc.cs index ca732105..05e8257c 100644 --- a/Questionable/External/BossModIpc.cs +++ b/Questionable/External/BossModIpc.cs @@ -72,11 +72,11 @@ internal sealed class BossModIpc } // TODO this should use your actual rotation plugin, not always vbm - public void EnableAi() + public void EnableAi(bool passive) { _commandManager.ProcessCommand("/vbmai on"); _commandManager.ProcessCommand("/vbm cfg ZoneModuleConfig EnableQuestBattles true"); - SetPreset(EPreset.QuestBattle); + SetPreset(passive ? EPreset.Overworld : EPreset.QuestBattle); } public void DisableAi() -- 2.30.2