Skip to content

Commit

Permalink
Merge pull request #553 from FFXIV-CombatReborn/mergeWIP
Browse files Browse the repository at this point in the history
merge FRU stuff from vbm
  • Loading branch information
CarnifexOptimus authored Jan 13, 2025
2 parents 932a107 + 7145c92 commit bbf78f9
Show file tree
Hide file tree
Showing 16 changed files with 911 additions and 88 deletions.
6 changes: 3 additions & 3 deletions BossMod/Autorotation/Standard/StandardWAR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ public override void Execute(StrategyValues strategy, Actor? primaryTarget, floa
if (Player.InCombat && Unlocked(WAR.AID.Infuriate))
{
var stratInf = strategy.Option(Track.Infuriate);
var inf = ShouldUseInfuriate(stratInf.As<InfuriateStrategy>(), primaryTarget);
var inf = ShouldUseInfuriate(stratInf.As<InfuriateStrategy>(), primaryTarget, burstStrategy == BurstStrategy.IgnoreST);
if (inf.Use)
QueueOGCD(WAR.AID.Infuriate, Player, stratInf.Value.PriorityOverride, OGCDPriority.Infuriate, inf.Delayable ? ActionQueue.Priority.VeryLow : ActionQueue.Priority.Low);
}
Expand Down Expand Up @@ -837,7 +837,7 @@ private bool ShouldUseBerserk(OffensiveStrategy strategy, Actor? target, int aoe
}
}

private (bool Use, bool Delayable) ShouldUseInfuriate(InfuriateStrategy strategy, Actor? target)
private (bool Use, bool Delayable) ShouldUseInfuriate(InfuriateStrategy strategy, Actor? target, bool ignoreST)
{
if (strategy == InfuriateStrategy.Delay || CanFitGCD(NascentChaosLeft))
return (false, false); // explicitly forbidden or NC still active
Expand Down Expand Up @@ -915,7 +915,7 @@ private bool ShouldUseBerserk(OffensiveStrategy strategy, Actor? target, int aoe
_ => (30, 4)
};
// don't double infuriate during opener when NC is not yet unlocked (TODO: consider making it better)
if (Gauge + stRefreshGauge + 50 > 100 && !CanFitGCD(SurgingTempestLeft, stRefreshGCDs))
if (!ignoreST && Gauge + stRefreshGauge + 50 > 100 && !CanFitGCD(SurgingTempestLeft, stRefreshGCDs))
return (false, false);

// at this point, use under burst or delay outside (TODO: reconsider, we might want to be smarter here...)
Expand Down
6 changes: 4 additions & 2 deletions BossMod/Modules/Dawntrail/Ultimate/FRU/FRU.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
namespace BossMod.Dawntrail.Ultimate.FRU;

class P2QuadrupleSlap(BossModule module) : Components.TankSwap(module, ActionID.MakeSpell(AID.QuadrupleSlapFirst), ActionID.MakeSpell(AID.QuadrupleSlapFirst), ActionID.MakeSpell(AID.QuadrupleSlapSecond), 4.1f, null, true);
class P2CrystalOfLight(BossModule module) : Components.Adds(module, (uint)OID.CrystalOfLight);
class P3Junction(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.Junction));
class P3BlackHalo(BossModule module) : Components.CastSharedTankbuster(module, ActionID.MakeSpell(AID.BlackHalo), new AOEShapeCone(60, 45.Degrees())); // TODO: verify angle

Expand All @@ -19,13 +18,15 @@ public class FRU(WorldState ws, Actor primary) : BossModule(ws, primary, arena.C
private Actor? _bossP3;
private Actor? _bossP4Usurper;
private Actor? _bossP4Oracle;
private Actor? _bossP5;

public Actor? BossP1() => PrimaryActor;
public Actor? BossP2() => _bossP2;
public Actor? IceVeil() => _iceVeil;
public Actor? BossP3() => _bossP3;
public Actor? BossP4Usurper() => _bossP4Usurper;
public Actor? BossP4Oracle() => _bossP4Oracle;
public Actor? BossP5() => _bossP5;

protected override void UpdateModule()
{
Expand All @@ -36,15 +37,16 @@ protected override void UpdateModule()
_bossP3 ??= StateMachine.ActivePhaseIndex == 2 ? Enemies(OID.BossP3).FirstOrDefault() : null;
_bossP4Usurper ??= StateMachine.ActivePhaseIndex == 2 ? Enemies(OID.UsurperOfFrostP4).FirstOrDefault() : null;
_bossP4Oracle ??= StateMachine.ActivePhaseIndex == 2 ? Enemies(OID.OracleOfDarknessP4).FirstOrDefault() : null;
_bossP5 ??= StateMachine.ActivePhaseIndex == 3 ? Enemies(OID.BossP5).FirstOrDefault() : null;
}

protected override void DrawEnemies(int pcSlot, Actor pc)
{
Arena.Actor(PrimaryActor);
Arena.Actor(_bossP2);
Arena.Actor(_iceVeil);
Arena.Actor(_bossP3);
Arena.Actor(_bossP4Usurper);
Arena.Actor(_bossP4Oracle);
Arena.Actor(_bossP5);
}
}
9 changes: 9 additions & 0 deletions BossMod/Modules/Dawntrail/Ultimate/FRU/FRUConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,13 @@ public class FRUConfig() : ConfigNode()
[PropertyDisplay("P2 Banish after Light Rampant: direction to move to resolve pairs", tooltip: "Only used by AI")]
[PropertyCombo("CW", "CCW")]
public bool P2Banish2MoveCCWToStack = true;

[PropertyDisplay("P2 Intermission: clock spots (cardinals prioritize their crystals, intercardinals bait)", tooltip: "Only used by AI")]
[GroupDetails(["N", "NE", "E", "SE", "S", "SW", "W", "NW"])]
[GroupPreset("Default", [0, 2, 5, 3, 4, 6, 7, 1])]
public GroupAssignmentUnique P2IntermissionClockSpots = new() { Assignments = [0, 2, 5, 3, 4, 6, 7, 1] };

[PropertyDisplay("P3 Darkest Dance: baiter")]
[PropertyCombo("MT", "OT")]
public bool P3DarkestDanceOTBait;
}
30 changes: 30 additions & 0 deletions BossMod/Modules/Dawntrail/Ultimate/FRU/FRUEnums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public enum OID : uint
DragonPuddle = 0x1EBD41, // R0.500, x0 (spawn during fight), EventObj type, puddle appears when head is touched
GuardianOfEden = 0x45AE, // R115.380, x0 (spawn during fight), p5 failure state tree

BossP5 = 0x45AF, // R7.000, x0 (spawn during fight)
FulgentBladeLine = 0x1EBBF7, // R0.500, x0 (spawn during fight), EventObj type

Helper = 0x233C
}

Expand Down Expand Up @@ -249,6 +252,32 @@ public enum AID : uint
MemorysEndP4 = 40305, // OracleOfDarknessP4->self, 10.0s cast, range 100 circle, enrage
AbsoluteZeroP4 = 40245, // UsurperOfFrostP4->self, 10.0s cast, range 100 circle, enrage
ParadiseLost = 40263, // Helper->self, no cast, range 100 circle, wipe on p5 failure state
IntermissionP5Visual = 40231, // UsurperOfFrostP4->self, no cast, single-target, visual (intermission start)
IntermissionP5Start = 40232, // Helper->self, no cast, range 60 circle, stun + move players to a specific spot

// P5
AutoAttackP5 = 40114, // BossP5->self, no cast, single-target, visual (auto attack on both tanks)
AutoAttackP5AOE = 40115, // Helper->player, no cast, single-target, auto-attack

FulgentBlade = 40306, // BossP5->self, 6.0s cast, range 100 circle, raidwide + mechanic start
PathOfLightFirst = 40307, // Helper->self, 7.0s cast, range 5 width 80 rect
PathOfLightRest = 40308, // Helper->self, no cast, range 5 width 80 rect
PathOfDarknessFirst = 40118, // Helper->self, 7.0s cast, range 5 width 80 rect
PathOfDarknessRest = 40309, // Helper->self, no cast, range 5 width 80 rect

AkhMornPandora = 40310, // BossP5->self, 8.0s cast, single-target, visual (left/right stack)
AkhMornPandoraAOE1 = 40311, // Helper->players, no cast, range 4 circle, 4-man stack
AkhMornPandoraAOE2 = 40312, // Helper->players, no cast, range 4 circle, 4-man stack

ParadiseRegained = 40319, // BossP5->self, 4.0s cast, single-target, visual (mechanic start)
WingsDarkAndLightDL = 40233, // BossP5->self, 6.9+0.1s cast, single-target, visual (dark > light)
WingsDarkAndLightLD = 40313, // BossP5->self, 6.9+0.1s cast, single-target, visual (light > dark)
WingsDarkAndLightExplosion = 40320, // Helper->self, no cast, range 3 circle, tower
WingsDarkAndLightUnmitigatedExplosion = 40321, // Helper->self, no cast, range 100 circle, tower fail
WingsDarkAndLightCleaveLight = 40314, // BossP5->self, no cast, range 100 240?-degree cone on target
WingsDarkAndLightCleaveDark = 40315, // BossP5->self, no cast, range 100 240?-degree cone on target
WingsDarkAndLightTetherLight = 39879, // Helper->players, no cast, range 4 circle on farthest
WingsDarkAndLightTetherDark = 39880, // Helper->player, no cast, range 4 circle on closest
}

public enum SID : uint
Expand Down Expand Up @@ -308,4 +337,5 @@ public enum TetherID : uint
UltimateRelativitySlow = 133, // DelightsHourglass->BossP3
UltimateRelativityQuicken = 134, // DelightsHourglass->BossP3
MornAfahHPCheck = 1, // UsurperOfFrostP4->OracleOfDarknessP4
MornAfahHPFail = 2, // UsurperOfFrostP4->OracleOfDarknessP4
}
102 changes: 80 additions & 22 deletions BossMod/Modules/Dawntrail/Ultimate/FRU/FRUStates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@ class FRUStates : StateMachineBuilder
{
private readonly FRU _module;

private static bool IsActorDead(Actor? a, bool valueIfNull) => a == null ? valueIfNull : (a.IsDeadOrDestroyed || a.HPMP.CurHP <= 1);

public FRUStates(FRU module) : base(module)
{
_module = module;
SimplePhase(0, Phase1, "P1: Fatebreaker")
.Raw.Update = () => Module.PrimaryActor.IsDeadOrDestroyed;
SimplePhase(1, Phase2, "P2: Usurper of Frost")
.SetHint(StateMachine.PhaseHint.StartWithDowntime)
.Raw.Update = () => !Module.PrimaryActor.IsDead || (_module.BossP2()?.IsDeadOrDestroyed ?? false) || (_module.IceVeil()?.IsDeadOrDestroyed ?? false);
.Raw.Update = () => !Module.PrimaryActor.IsDead || (_module.BossP2()?.IsDestroyed ?? false) || (_module.IceVeil()?.IsDeadOrDestroyed ?? false);
SimplePhase(2, Phase34, "P3/4: Oracle of Darkness & Both")
.SetHint(StateMachine.PhaseHint.StartWithDowntime)
.Raw.Update = () => !Module.PrimaryActor.IsDead || (_module.BossP2()?.IsDeadOrDestroyed ?? false) && (_module.BossP3()?.IsDeadOrDestroyed ?? true) && (_module.BossP4Oracle()?.IsDeadOrDestroyed ?? true);
.Raw.Update = () => !Module.PrimaryActor.IsDead || (_module.BossP2()?.IsDestroyed ?? false) && (_module.BossP3()?.IsDestroyed ?? true) && IsActorDead(_module.BossP4Oracle(), true) && IsActorDead(_module.BossP4Usurper(), true);
SimplePhase(3, Phase5, "P5: Pandora")
.SetHint(StateMachine.PhaseHint.StartWithDowntime)
.Raw.Update = () => !Module.PrimaryActor.IsDead || (_module.BossP4Oracle()?.IsDeadOrDestroyed ?? true) && (_module.BossP5()?.IsDeadOrDestroyed ?? true);
}

private void Phase1(uint id)
Expand Down Expand Up @@ -56,6 +61,13 @@ private void Phase34(uint id)
P4CrystallizeTime(id + 0x130000, 4.6f);
P4AkhMornMornAfah(id + 0x140000, 0.1f);
P4Enrage(id + 0x150000, 2.3f);
}

private void Phase5(uint id)
{
P5Start(id, 77);
P5FulgentBlade(id + 0x10000, 5.3f);
P5ParadiseRegained(id + 0x20000, 4.2f);

SimpleState(id + 0xFF0000, 100, "???");
}
Expand Down Expand Up @@ -367,14 +379,14 @@ private void P2AbsoluteZero(uint id, float delay)
ComponentCondition<P2SwellingFrost>(id + 3, 2.3f, comp => comp.NumCasts > 0, "Knockback")
.DeactivateOnExit<P2SwellingFrost>();

ComponentCondition<P2CrystalOfLight>(id + 0x1000, 18.9f, comp => comp.ActiveActors.Any(), "Crystals appear")
.ActivateOnEnter<P2CrystalOfLight>()
ComponentCondition<P2Intermission>(id + 0x1000, 18.9f, comp => comp.CrystalsActive, "Crystals appear")
.ActivateOnEnter<P2SinboundBlizzard>()
.ActivateOnEnter<P2Intermission>()
.SetHint(StateMachine.StateHint.DowntimeEnd);
ActorCast(id + 0x1010, _module.IceVeil, AID.EndlessIceAge, 4.7f, 40, true, "Enrage")
.ActivateOnEnter<P2SinboundBlizzard>()
.ActivateOnEnter<P2HiemalStorm>()
.ActivateOnEnter<P2HiemalRay>()
.DeactivateOnExit<P2CrystalOfLight>()
.DeactivateOnExit<P2Intermission>()
.DeactivateOnExit<P2SinboundBlizzard>()
.DeactivateOnExit<P2HiemalStorm>()
.DeactivateOnExit<P2HiemalRay>();
Expand Down Expand Up @@ -454,40 +466,46 @@ private void P3Apocalypse(uint id, float delay)
ComponentCondition<P3ApocalypseDarkWater>(id + 0x12, 0.6f, comp => comp.NumStatuses >= 6)
.ActivateOnEnter<P3Apocalypse>()
.ActivateOnEnter<P3ApocalypseDarkWater>()
.ActivateOnEnter<P3ApocalypseAIWater1>()
.ExecOnExit<P3ApocalypseDarkWater>(comp => comp.ShowOrder(1));
ActorCast(id + 0x20, _module.BossP3, AID.Apocalypse, 2.6f, 4, true);
ActorCastStart(id + 0x30, _module.BossP3, AID.SpiritTaker, 2.2f, true);
ComponentCondition<P3ApocalypseDarkWater>(id + 0x31, 1.3f, comp => comp.Stacks.Count == 0, "Stack 1");
ComponentCondition<P3ApocalypseDarkWater>(id + 0x31, 1.3f, comp => comp.Stacks.Count == 0, "Stack 1")
.DeactivateOnExit<P3ApocalypseAIWater1>();
ActorCastEnd(id + 0x32, _module.BossP3, 1.7f, true)
.ActivateOnEnter<P3SpiritTaker>();
ComponentCondition<P3SpiritTaker>(id + 0x33, 0.3f, comp => comp.Spreads.Count == 0, "Jump")
.DeactivateOnExit<P3SpiritTaker>();
.ActivateOnEnter<P3ApocalypseSpiritTaker>();
ComponentCondition<SpiritTaker>(id + 0x33, 0.3f, comp => comp.Spreads.Count == 0, "Jump")
.DeactivateOnExit<SpiritTaker>();
ActorCastStart(id + 0x40, _module.BossP3, AID.ApocalypseDarkEruption, 6.2f, true)
.ExecOnEnter<P3Apocalypse>(comp => comp.Show(8.5f))
.ActivateOnEnter<P3ApocalypseDarkEruption>();
ComponentCondition<P3Apocalypse>(id + 0x41, 2.4f, comp => comp.NumCasts > 0, "Apocalypse start");
ComponentCondition<P3Apocalypse>(id + 0x41, 2.4f, comp => comp.NumCasts >= 4, "Apocalypse start");
ActorCastEnd(id + 0x42, _module.BossP3, 1.6f, true);
ComponentCondition<P3Apocalypse>(id + 0x43, 0.4f, comp => comp.NumCasts > 4);
ComponentCondition<P3Apocalypse>(id + 0x43, 0.4f, comp => comp.NumCasts >= 10);
ComponentCondition<P3ApocalypseDarkEruption>(id + 0x44, 0.7f, comp => comp.NumFinishedSpreads > 0, "Spread")
.DeactivateOnExit<P3ApocalypseDarkEruption>()
.ExecOnExit<P3ApocalypseDarkWater>(comp => comp.ShowOrder(2));
ComponentCondition<P3Apocalypse>(id + 0x45, 1.3f, comp => comp.NumCasts > 10);
ComponentCondition<P3Apocalypse>(id + 0x45, 1.3f, comp => comp.NumCasts >= 16)
.ActivateOnEnter<P3ApocalypseAIWater2>();
ActorCastStart(id + 0x50, _module.BossP3, AID.DarkestDance, 1.3f, true);
ComponentCondition<P3Apocalypse>(id + 0x51, 0.7f, comp => comp.NumCasts > 16);
ComponentCondition<P3Apocalypse>(id + 0x52, 2.0f, comp => comp.NumCasts > 22);
ComponentCondition<P3Apocalypse>(id + 0x51, 0.7f, comp => comp.NumCasts >= 22);
ComponentCondition<P3Apocalypse>(id + 0x52, 2.0f, comp => comp.NumCasts >= 28);
ComponentCondition<P3ApocalypseDarkWater>(id + 0x53, 0.5f, comp => comp.Stacks.Count == 0, "Stack 2");
ComponentCondition<P3Apocalypse>(id + 0x54, 1.5f, comp => comp.NumCasts > 28)
ComponentCondition<P3Apocalypse>(id + 0x54, 1.5f, comp => comp.NumCasts >= 34)
.ActivateOnEnter<P3DarkestDanceBait>()
.DeactivateOnExit<P3Apocalypse>();
ActorCastEnd(id + 0x55, _module.BossP3, 0.3f, true);
ComponentCondition<P3DarkestDanceBait>(id + 0x56, 0.4f, comp => comp.NumCasts > 0, "Tankbuster")
.ActivateOnEnter<P3DarkestDanceKnockback>()
.DeactivateOnExit<P3ApocalypseAIWater2>()
.DeactivateOnExit<P3DarkestDanceBait>()
.ExecOnExit<P3ApocalypseDarkWater>(comp => comp.ShowOrder(3))
.SetHint(StateMachine.StateHint.Tankbuster);
ComponentCondition<P3DarkestDanceKnockback>(id + 0x57, 2.8f, comp => comp.NumCasts > 0, "Knockback")
.ActivateOnEnter<P3ApocalypseAIWater3>()
.DeactivateOnExit<P3DarkestDanceKnockback>();
ComponentCondition<P3ApocalypseDarkWater>(id + 0x60, 4.1f, comp => comp.Stacks.Count == 0, "Stack 3")
.DeactivateOnExit<P3ApocalypseAIWater3>()
.DeactivateOnExit<P3ApocalypseDarkWater>();

P3ShockwavePulsar(id + 0x1000, 0.3f);
Expand Down Expand Up @@ -530,10 +548,10 @@ private void P4DarklitDragonsong(uint id, float delay)
ComponentCondition<P4DarklitDragonsongPathOfLight>(id + 0x21, 0.8f, comp => comp.NumCasts > 0, "Proteans")
.DeactivateOnExit<P4DarklitDragonsongPathOfLight>();
ActorCastEnd(id + 0x22, _module.BossP4Oracle, 2.2f, true)
.ActivateOnEnter<P3SpiritTaker>();
.ActivateOnEnter<DefaultSpiritTaker>();
ActorCastStartMulti(id + 0x23, _module.BossP4Usurper, [AID.HallowedWingsL, AID.HallowedWingsR], 0.1f, true);
ComponentCondition<P3SpiritTaker>(id + 0x24, 0.3f, comp => comp.Spreads.Count == 0, "Jump")
.DeactivateOnExit<P3SpiritTaker>();
ComponentCondition<SpiritTaker>(id + 0x24, 0.3f, comp => comp.Spreads.Count == 0, "Jump")
.DeactivateOnExit<SpiritTaker>();
ActorCastStart(id + 0x25, _module.BossP4Oracle, AID.SomberDance, 2.8f)
.ActivateOnEnter<P4HallowedWingsL>()
.ActivateOnEnter<P4HallowedWingsR>()
Expand Down Expand Up @@ -614,10 +632,10 @@ private void P4CrystallizeTime(uint id, float delay)
.DeactivateOnExit<P4CrystallizeTime>();
ActorCastStart(id + 0x90, _module.BossP4Oracle, AID.SpiritTaker, 0.4f);
ActorCastStart(id + 0x91, _module.BossP4Usurper, AID.CrystallizeTimeHallowedWings1, 2.2f)
.ActivateOnEnter<P3SpiritTaker>();
.ActivateOnEnter<DefaultSpiritTaker>();
ActorCastEnd(id + 0x92, _module.BossP4Oracle, 0.8f);
ComponentCondition<P3SpiritTaker>(id + 0x93, 0.3f, comp => comp.Spreads.Count == 0, "Jump")
.DeactivateOnExit<P3SpiritTaker>();
ComponentCondition<SpiritTaker>(id + 0x93, 0.3f, comp => comp.Spreads.Count == 0, "Jump")
.DeactivateOnExit<SpiritTaker>();
ComponentCondition<P4CrystallizeTimeRewind>(id + 0x94, 3.3f, comp => comp.ReturnDone, "Rewind return")
.DeactivateOnExit<P4CrystallizeTimeRewind>();
ActorCastEnd(id + 0x95, _module.BossP4Usurper, 0.3f);
Expand All @@ -632,4 +650,44 @@ private void P4Enrage(uint id, float delay)
{
ActorCast(id, _module.BossP4Usurper, AID.AbsoluteZeroP4, delay, 10, true, "Enrage");
}

private void P5Start(uint id, float delay)
{
ActorTargetable(id, _module.BossP5, true, delay, "Boss appears")
.SetHint(StateMachine.StateHint.DowntimeEnd);
}

private void P5FulgentBlade(uint id, float delay)
{
ActorCast(id, _module.BossP5, AID.FulgentBlade, delay, 6, true, "Raidwide")
.ActivateOnEnter<P5FulgentBlade>()
.SetHint(StateMachine.StateHint.Raidwide);
ComponentCondition<P5FulgentBlade>(id + 0x10, 4.1f, comp => comp.Active);
ComponentCondition<P5FulgentBlade>(id + 0x20, 7, comp => comp.NumCasts > 0, "Exaline 1");
ComponentCondition<P5FulgentBlade>(id + 0x21, 2, comp => comp.NumCasts > 1, "Exaline 2");
ComponentCondition<P5FulgentBlade>(id + 0x22, 2, comp => comp.NumCasts > 2, "Exaline 3");
ComponentCondition<P5FulgentBlade>(id + 0x23, 2, comp => comp.NumCasts > 3, "Exaline 4");
ActorCastStart(id + 0x30, _module.BossP5, AID.AkhMornPandora, 1.8f, true);
ComponentCondition<P5FulgentBlade>(id + 0x31, 0.2f, comp => comp.NumCasts > 4, "Exaline 5")
.ActivateOnEnter<P5AkhMorn>();
ComponentCondition<P5FulgentBlade>(id + 0x32, 2, comp => comp.NumCasts > 5, "Exaline 6");
ActorCastEnd(id + 0x33, _module.BossP5, 5.8f, true);
ComponentCondition<P5AkhMorn>(id + 0x34, 0.1f, comp => comp.Source == null, "Left/right stack")
.DeactivateOnExit<P5AkhMorn>()
.DeactivateOnExit<P5FulgentBlade>(); // TODO: there are still lines going, but they are far...
}

private void P5ParadiseRegained(uint id, float delay)
{
ActorCast(id, _module.BossP5, AID.ParadiseRegained, delay, 4, true)
.ActivateOnEnter<P5ParadiseRegainedTowers>(); // first tower appears ~0.9s after cast end, then every 3.5s
ActorCastMulti(id + 0x10, _module.BossP5, [AID.WingsDarkAndLightDL, AID.WingsDarkAndLightLD], 3.2f, 6.9f, true)
.ActivateOnEnter<P5ParadiseRegainedBaits>();
ComponentCondition<P5ParadiseRegainedBaits>(id + 0x20, 0.5f, comp => comp.NumCasts > 0, "Light/dark"); // first tower resolve ~0.1s earlier
ComponentCondition<P5ParadiseRegainedBaits>(id + 0x30, 3.7f, comp => comp.NumCasts > 1, "Dark/light") // second tower resolves ~1s earlier
.DeactivateOnExit<P5ParadiseRegainedBaits>();
// note: tethers resolve ~0.7s after cleave, but they won't happen if tether target dies to cleave
ComponentCondition<P5ParadiseRegainedTowers>(id + 0x40, 2.4f, comp => comp.NumCasts > 2, "Towers resolve")
.DeactivateOnExit<P5ParadiseRegainedTowers>();
}
}
Loading

0 comments on commit bbf78f9

Please sign in to comment.