diff --git a/BossMod/Modules/Dawntrail/Hunt/RankA/Heshuala.cs b/BossMod/Modules/Dawntrail/Hunt/RankA/Heshuala.cs index a6273e10ad..70f2b72bff 100644 --- a/BossMod/Modules/Dawntrail/Hunt/RankA/Heshuala.cs +++ b/BossMod/Modules/Dawntrail/Hunt/RankA/Heshuala.cs @@ -56,7 +56,7 @@ public override void OnCastStarted(Actor caster, ActorCastInfo spell) AddSequence(-90f.Degrees()); break; } - void AddSequence(Angle angle) => Sequences.Add(new(cone, WPos.ClampToGrid(caster.Position), spell.Rotation, angle, Module.CastFinishAt(spell), 2.7f, Spins)); + void AddSequence(Angle increment) => Sequences.Add(new(cone, WPos.ClampToGrid(caster.Position), spell.Rotation, increment, Module.CastFinishAt(spell), 2.7f, Spins)); } public override void OnCastFinished(Actor caster, ActorCastInfo spell) diff --git a/BossMod/Modules/Dawntrail/Quest/Job/Viper/VengeanceOfTheViper.cs b/BossMod/Modules/Dawntrail/Quest/Job/Viper/VengeanceOfTheViper.cs index 50a9ac2e70..dbaeb71e3d 100644 --- a/BossMod/Modules/Dawntrail/Quest/Job/Viper/VengeanceOfTheViper.cs +++ b/BossMod/Modules/Dawntrail/Quest/Job/Viper/VengeanceOfTheViper.cs @@ -73,10 +73,21 @@ public override IEnumerable ActiveAOEs(int slot, Actor actor) public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if (spell.Action.ID == (uint)AID.SwoopingFrenzy2 || spell.Action.ID == (uint)AID.SwoopingFrenzyTelegraph && !_aoes.Any(x => x.Origin.AlmostEqual(spell.LocXZ, 1f))) + if (spell.Action.ID == (uint)AID.SwoopingFrenzy2 || spell.Action.ID == (uint)AID.SwoopingFrenzyTelegraph && !HasMatchingAOE(spell.LocXZ)) _aoes.Add(new(circle, spell.LocXZ, default, Module.CastFinishAt(spell, 1.5f))); } + private bool HasMatchingAOE(WPos location) + { + var count = _aoes.Count; + for (var i = 0; i < count; ++i) + { + if (_aoes[i].Origin.AlmostEqual(location, 1f)) + return true; + } + return false; + } + public override void OnEventCast(Actor caster, ActorCastEvent spell) { if (_aoes.Count != 0 && spell.Action.ID is (uint)AID.SwoopingFrenzy2 or (uint)AID.SwoopingFrenzy3) diff --git a/BossMod/Modules/Dawntrail/Raid/M03NBruteBomber/Firespin.cs b/BossMod/Modules/Dawntrail/Raid/M03NBruteBomber/Firespin.cs index 957db5e797..6a38ff4cac 100644 --- a/BossMod/Modules/Dawntrail/Raid/M03NBruteBomber/Firespin.cs +++ b/BossMod/Modules/Dawntrail/Raid/M03NBruteBomber/Firespin.cs @@ -17,7 +17,7 @@ public override void OnCastStarted(Actor caster, ActorCastInfo spell) AddSequence(-45f.Degrees()); break; } - void AddSequence(Angle angle) => Sequences.Add(new(cone, spell.LocXZ, spell.Rotation, angle, Module.CastFinishAt(spell, 0.5f), 1f, 8)); + void AddSequence(Angle increment) => Sequences.Add(new(cone, spell.LocXZ, spell.Rotation, increment, Module.CastFinishAt(spell, 0.5f), 1f, 8)); } public override void OnCastFinished(Actor caster, ActorCastInfo spell) diff --git a/BossMod/Modules/Dawntrail/Savage/M03SBruteBomber/FuseOrFoe.cs b/BossMod/Modules/Dawntrail/Savage/M03SBruteBomber/FuseOrFoe.cs index 93e3c76b5b..7a5cd4ed13 100644 --- a/BossMod/Modules/Dawntrail/Savage/M03SBruteBomber/FuseOrFoe.cs +++ b/BossMod/Modules/Dawntrail/Savage/M03SBruteBomber/FuseOrFoe.cs @@ -2,46 +2,46 @@ class InfernalSpin(BossModule module) : Components.GenericRotatingAOE(module) { - private static readonly AOEShapeCone _shape = new(40, 30.Degrees()); + private static readonly AOEShapeCone _shape = new(40f, 30f.Degrees()); public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - var increment = (AID)spell.Action.ID switch + var increment = spell.Action.ID switch { - AID.InfernalSpinFirstCW => -45.Degrees(), - AID.InfernalSpinFirstCCW => 45.Degrees(), + (uint)AID.InfernalSpinFirstCW => -45f.Degrees(), + (uint)AID.InfernalSpinFirstCCW => 45f.Degrees(), _ => default }; if (increment != default) { - Sequences.Add(new(_shape, caster.Position, spell.Rotation, increment, Module.CastFinishAt(spell, 0.5f), 1.1f, 8)); + Sequences.Add(new(_shape, spell.LocXZ, spell.Rotation, increment, Module.CastFinishAt(spell, 0.5f), 1.1f, 8)); } } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID is AID.InfernalSpinFirstAOE or AID.InfernalSpinRestAOE) + if (spell.Action.ID is (uint)AID.InfernalSpinFirstAOE or (uint)AID.InfernalSpinRestAOE) AdvanceSequence(0, WorldState.CurrentTime); } } class ExplosiveRain(BossModule module) : Components.ConcentricAOEs(module, _shapes) { - private static readonly AOEShape[] _shapes = [new AOEShapeCircle(8), new AOEShapeDonut(8, 16), new AOEShapeDonut(16, 24)]; + private static readonly AOEShape[] _shapes = [new AOEShapeCircle(8f), new AOEShapeDonut(8f, 16f), new AOEShapeDonut(16f, 24f)]; public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID is AID.ExplosiveRain11 or AID.ExplosiveRain21) + if (spell.Action.ID is (uint)AID.ExplosiveRain11 or (uint)AID.ExplosiveRain21) AddSequence(spell.LocXZ, Module.CastFinishAt(spell)); } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - var order = (AID)spell.Action.ID switch + var order = spell.Action.ID switch { - AID.ExplosiveRain11 or AID.ExplosiveRain21 => 0, - AID.ExplosiveRain12 or AID.ExplosiveRain22 => 1, - AID.ExplosiveRain13 or AID.ExplosiveRain23 => 2, + (uint)AID.ExplosiveRain11 or (uint)AID.ExplosiveRain21 => 0, + (uint)AID.ExplosiveRain12 or (uint)AID.ExplosiveRain22 => 1, + (uint)AID.ExplosiveRain13 or (uint)AID.ExplosiveRain23 => 2, _ => -1 }; if (!AdvanceSequence(order, spell.LocXZ, WorldState.FutureTime(4))) diff --git a/BossMod/Modules/Endwalker/Hunt/RankA/Gurangatch.cs b/BossMod/Modules/Endwalker/Hunt/RankA/Gurangatch.cs index 3814387451..bdfce114a6 100644 --- a/BossMod/Modules/Endwalker/Hunt/RankA/Gurangatch.cs +++ b/BossMod/Modules/Endwalker/Hunt/RankA/Gurangatch.cs @@ -29,21 +29,22 @@ class Slammer(BossModule module) : Components.GenericRotatingAOE(module) public override void OnCastStarted(Actor caster, ActorCastInfo spell) { + void AddSequence(Angle increment, int casts = 8, int max = 2) => Sequences.Add(new(_shape, spell.LocXZ, spell.Rotation, increment, Module.CastFinishAt(spell), 3.6f, casts, max)); switch (spell.Action.ID) { case (uint)AID.OctupleSlammerLCW: case (uint)AID.OctupleSlammerRCW: - Sequences.Add(new(_shape, caster.Position, spell.Rotation, 90f.Degrees(), Module.CastFinishAt(spell), 3.7f, 8)); + AddSequence(90f.Degrees()); ImminentColor = Colors.Danger; break; case (uint)AID.OctupleSlammerLCCW: case (uint)AID.OctupleSlammerRCCW: - Sequences.Add(new(_shape, caster.Position, spell.Rotation, -90f.Degrees(), Module.CastFinishAt(spell), 3.7f, 8)); + AddSequence(-90f.Degrees()); ImminentColor = Colors.Danger; break; case (uint)AID.LeftHammerSlammer: case (uint)AID.RightHammerSlammer: - Sequences.Add(new(_shape, caster.Position, spell.Rotation, 180f.Degrees(), Module.CastFinishAt(spell), 3.6f, 2, 1)); + AddSequence(180f.Degrees()); ImminentColor = 0; break; } diff --git a/BossMod/Modules/Endwalker/Hunt/RankS/Armstrong.cs b/BossMod/Modules/Endwalker/Hunt/RankS/Armstrong.cs index 075a273a1f..7d5f5d7378 100644 --- a/BossMod/Modules/Endwalker/Hunt/RankS/Armstrong.cs +++ b/BossMod/Modules/Endwalker/Hunt/RankS/Armstrong.cs @@ -27,34 +27,34 @@ class MagitekCompressor(BossModule module) : Components.GenericRotatingAOE(modul public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID is AID.MagitekCompressorFirst) + if (spell.Action.ID == (uint)AID.MagitekCompressorFirst) { NumCasts = 0; - Sequences.Add(new(_shape, caster.Position, spell.Rotation, _increment, Module.CastFinishAt(spell), 2.1f, 10)); + Sequences.Add(new(_shape, spell.LocXZ, spell.Rotation, _increment, Module.CastFinishAt(spell), 2.1f, 10)); } } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - switch ((AID)spell.Action.ID) + switch (spell.Action.ID) { - case AID.RotateCW: - _increment = -30.Degrees(); + case (uint)AID.RotateCW: + _increment = -30f.Degrees(); break; - case AID.RotateCCW: - _increment = 30.Degrees(); + case (uint)AID.RotateCCW: + _increment = 30f.Degrees(); break; - case AID.MagitekCompressorFirst: - case AID.MagitekCompressorReverse: - case AID.MagitekCompressorNext: - if (Sequences.Count > 0) + case (uint)AID.MagitekCompressorFirst: + case (uint)AID.MagitekCompressorReverse: + case (uint)AID.MagitekCompressorNext: + if (Sequences.Count != 0) { AdvanceSequence(0, WorldState.CurrentTime); if (NumCasts == 5) { ref var s = ref Sequences.Ref(0); s.Increment = -s.Increment; - s.NextActivation = WorldState.FutureTime(3.6f); + s.NextActivation = WorldState.FutureTime(3.6d); } } break; @@ -62,10 +62,10 @@ public override void OnEventCast(Actor caster, ActorCastEvent spell) } } -class AcceleratedLanding(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.AcceleratedLanding), 6); +class AcceleratedLanding(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.AcceleratedLanding), 6f); class CalculatedCombustion(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.CalculatedCombustion)); class Pummel(BossModule module) : Components.SingleTargetCast(module, ActionID.MakeSpell(AID.Pummel)); -class SoporificGas(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.SoporificGas), 12); +class SoporificGas(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.SoporificGas), 12f); class ArmstrongStates : StateMachineBuilder { diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V021Yozakura/LevinblossomLance.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V021Yozakura/LevinblossomLance.cs index 95a7e988dc..a1e7d9fa2e 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V021Yozakura/LevinblossomLance.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V021Yozakura/LevinblossomLance.cs @@ -6,7 +6,7 @@ class LevinblossomLance(BossModule module) : Components.GenericRotatingAOE(modul public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - void AddSequence(Angle angle) => Sequences.Add(new(rect, spell.LocXZ, spell.Rotation, angle, Module.CastFinishAt(spell, 0.8f), 1, 5, 2)); + void AddSequence(Angle increment) => Sequences.Add(new(rect, spell.LocXZ, spell.Rotation, increment, Module.CastFinishAt(spell, 0.8f), 1, 5, 2)); switch (spell.Action.ID) { case (uint)AID.LevinblossomLanceCCW: diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/FlameAndSulphur.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/FlameAndSulphur.cs index 09a9e9ef77..0d2958d33e 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/FlameAndSulphur.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/FlameAndSulphur.cs @@ -2,42 +2,56 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V023Gorai; class FlameAndSulphur(BossModule module) : Components.GenericAOEs(module) { - private readonly List _aoes = []; - - private static readonly AOEShapeRect _shapeFlameExpand = new(46, 5); - private static readonly AOEShapeRect _shapeFlameSplit = new(46, 2.5f); - private static readonly AOEShapeCircle _shapeRockExpand = new(11); - private static readonly AOEShapeDonut _shapeRockSplit = new(5, 16); + private readonly List _aoes = new(4); + private static readonly AOEShapeRect _shapeFlameExpand = new(46f, 5f); + private static readonly AOEShapeRect _shapeFlameSplit = new(46f, 2.5f); + private static readonly AOEShapeCircle _shapeRockExpand = new(11f); + private static readonly AOEShapeDonut _shapeRockSplit = new(5f, 16f); public override IEnumerable ActiveAOEs(int slot, Actor actor) => _aoes; public override void OnCastStarted(Actor caster, ActorCastInfo spell) { var activation = Module.CastFinishAt(spell, 3.1f); - switch ((AID)spell.Action.ID) + switch (spell.Action.ID) { - case AID.BrazenBalladSplitting: - foreach (var a in Module.Enemies(OID.FlameAndSulphurFlame)) - _aoes.Add(new(_shapeFlameExpand, a.Position, a.Rotation, activation)); - foreach (var a in Module.Enemies(OID.FlameAndSulphurRock)) - _aoes.Add(new(_shapeRockExpand, a.Position, a.Rotation, activation)); + case (uint)AID.BrazenBalladSplitting: + AddAOEs(_shapeFlameExpand, (uint)OID.FlameAndSulphurFlame); + AddAOEs(_shapeRockExpand, (uint)OID.FlameAndSulphurRock); + break; + case (uint)AID.BrazenBalladExpanding: + AddAOEs(_shapeFlameSplit, (uint)OID.FlameAndSulphurFlame, true); + AddAOEs(_shapeRockSplit, (uint)OID.FlameAndSulphurRock); break; - case AID.BrazenBalladExpanding: - foreach (var a in Module.Enemies(OID.FlameAndSulphurFlame)) + + void AddAOEs(AOEShape shape, uint actors, bool twice = false) { - var offset = a.Rotation.ToDirection().OrthoL() * 7.5f; - _aoes.Add(new(_shapeFlameSplit, a.Position + offset, a.Rotation, activation)); - _aoes.Add(new(_shapeFlameSplit, a.Position - offset, a.Rotation, activation)); + var enemies = Module.Enemies(actors); + var count = enemies.Count; + + if (!twice) + for (var i = 0; i < count; ++i) + { + var enemy = enemies[i]; + AddAOE(shape, enemy.Position, enemy.Rotation); + } + else + for (var i = 0; i < count; ++i) + { + var enemy = enemies[i]; + var rot = enemy.Rotation; + var offset = rot.ToDirection().OrthoL() * 7.5f; + AddAOE(shape, enemy.Position + offset, rot); + AddAOE(shape, enemy.Position - offset, rot); + } + void AddAOE(AOEShape shape, WPos origin, Angle rotation) => _aoes.Add(new(shape, WPos.ClampToGrid(origin), rotation, activation)); } - foreach (var a in Module.Enemies(OID.FlameAndSulphurRock)) - _aoes.Add(new(_shapeRockSplit, a.Position, a.Rotation, activation)); - break; } } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if ((AID)spell.Action.ID is AID.FireSpreadExpand or AID.FireSpreadSplit or AID.FallingRockExpand or AID.FallingRockSplit) + if (spell.Action.ID is (uint)AID.FireSpreadExpand or (uint)AID.FireSpreadSplit or (uint)AID.FallingRockExpand or (uint)AID.FallingRockSplit) _aoes.Clear(); } } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/ImpurePurgation.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/ImpurePurgation.cs index eceb0eecb1..c1e182be54 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/ImpurePurgation.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/ImpurePurgation.cs @@ -1,33 +1,35 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V023Gorai; -class ImpurePurgation(BossModule module) : Components.GenericAOEs(module, ActionID.MakeSpell(AID.ImpurePurgation)) +class ImpurePurgation(BossModule module) : Components.GenericAOEs(module) { - private readonly List _castersPurgationFirst = []; - private readonly List _castersPurgationNext = []; - - private static readonly AOEShapeCone cone = new(60, 22.5f.Degrees()); + private static readonly AOEShapeCone cone = new(60f, 22.5f.Degrees()); + public readonly List AOEs = new(8); public override IEnumerable ActiveAOEs(int slot, Actor actor) { - return _castersPurgationFirst.Count > 0 - ? _castersPurgationFirst.Select(c => new AOEInstance(cone, c.Position, c.CastInfo!.Rotation, Module.CastFinishAt(c.CastInfo))) - : _castersPurgationNext.Select(c => new AOEInstance(cone, c.Position, c.CastInfo!.Rotation, Module.CastFinishAt(c.CastInfo))); + var count = AOEs.Count; + if (count == 0) + return []; + var max = count > 4 ? 4 : count; + var aoes = new AOEInstance[max]; + for (var i = 0; i < max; ++i) + aoes[i] = AOEs[i]; + return aoes; } public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - CastersForSpell(spell.Action)?.Add(caster); + if (spell.Action.ID is (uint)AID.ImpurePurgationFirst or (uint)AID.ImpurePurgationSecond) + { + AOEs.Add(new(cone, spell.LocXZ, spell.Rotation, Module.CastFinishAt(spell))); + if (AOEs.Count == 8) + AOEs.SortBy(x => x.Activation); + } } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - CastersForSpell(spell.Action)?.Remove(caster); + if (AOEs.Count != 0 && spell.Action.ID is (uint)AID.ImpurePurgationFirst or (uint)AID.ImpurePurgationFirst) + AOEs.RemoveAt(0); } - - private List? CastersForSpell(ActionID spell) => (AID)spell.ID switch - { - AID.ImpurePurgationFirst => _castersPurgationFirst, - AID.ImpurePurgationSecond => _castersPurgationNext, - _ => null - }; } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/MalformedPrayer.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/MalformedPrayer.cs index 595e4603d6..633b763717 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/MalformedPrayer.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/MalformedPrayer.cs @@ -4,38 +4,50 @@ class MalformedPrayer(BossModule module) : Components.GenericTowers(module) { private readonly ImpurePurgation _aoe = module.FindComponent()!; - private static readonly Dictionary towerSources = new() - { - {0x1F, new(741, -201)}, {0x23, new(741, -179)}, {0x25, new(730, -190)}, - {0x21, new(752, -190)}, {0x24, new(733.222f, -182.222f)}, - {0x26, new(733.222f, -197.778f)}, {0x20, new(748.778f, -197.778f)}, - {0x22, new(748.778f, -182.222f)}}; - public override void OnEventEnvControl(byte index, uint state) { - if (state == 0x00020001 && towerSources.TryGetValue(index, out var source)) - Towers.Add(new(source, 4, activation: WorldState.FutureTime(9))); + if (state != 0x00020001) + return; + WPos? pos = index switch + { + 0x1F => new(741f, -201f), + 0x20 => new(748.778f, -197.778f), + 0x21 => new(752f, -190f), + 0x22 => new(748.778f, -182.222f), + 0x23 => new(741f, -179f), + 0x24 => new(733.222f, -182.222f), + 0x25 => new(730f, -190f), + 0x26 => new(733.222f, -197.778f), + _ => null + }; + if (pos is WPos origin) + Towers.Add(new(WPos.ClampToGrid(origin), 4f, activation: WorldState.FutureTime(9d))); } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if (Towers.Count > 0 && (AID)spell.Action.ID == AID.Burst) + if (Towers.Count != 0 && spell.Action.ID == (uint)AID.Burst) Towers.RemoveAt(0); } public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { - if (_aoe.ActiveAOEs(slot, actor).Any() && !Towers.Any(x => x.IsInside(actor))) - hints.AddForbiddenZone(ShapeDistance.InvertedCircle(Module.PrimaryActor.Position, 1)); + if (_aoe.AOEs.Count != 0 && Towers.Count != 0 && !Towers[0].IsInside(actor)) + { + hints.AddForbiddenZone(ShapeDistance.InvertedCircle(Arena.Center, 3f)); + } else base.AddAIHints(slot, actor, assignment, hints); } public override void Update() { - if (Towers.Count == 0) + var count = Towers.Count; + if (count == 0) return; - for (var i = 0; i < Towers.Count; ++i) - Towers[i] = new(Towers[i].Position, Towers[i].Radius, i > 0 ? 0 : 1, i > 0 ? 0 : 4, default, Towers[i].Activation); + for (var i = 0; i < count; ++i) + { + Towers[i] = Towers[i] with { MinSoakers = i > 0 ? 0 : 1, MaxSoakers = i > 0 ? 0 : 4 }; + } } } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/Thundercall.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/Thundercall.cs index 178ec38bd5..13f066de29 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/Thundercall.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/Thundercall.cs @@ -2,36 +2,44 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V023Gorai; class Thundercall(BossModule module) : Components.GenericAOEs(module) { - private readonly List _aoes = []; + private readonly List _aoes = new(4); private int counter; - private static readonly AOEShapeCircle circleSmall = new(8); - private static readonly AOEShapeCircle circleBig = new(18); + private static readonly AOEShapeCircle circleSmall = new(8f), circleBig = new(18f); public override IEnumerable ActiveAOEs(int slot, Actor actor) => _aoes; public override void OnActorCreated(Actor actor) { - if (counter < 2 && (OID)actor.OID == OID.BallOfLevin) + if (counter < 2 && actor.OID == (uint)OID.BallOfLevin) { - _aoes.Add(new(circleBig, actor.Position, default, WorldState.FutureTime(10.8f))); + _aoes.Add(new(circleBig, actor.Position, default, WorldState.FutureTime(10.8d))); ++counter; } } public override void OnStatusGain(Actor actor, ActorStatus status) { - if ((OID)actor.OID == OID.BallOfLevin && (SID)status.ID == SID.SmallOrb) + + if (actor.OID == (uint)OID.BallOfLevin && status.ID == (uint)SID.SmallOrb) { - var activation = WorldState.FutureTime(10); - _aoes.Add(new(circleSmall, actor.Position, default, activation)); - foreach (var a in Module.Enemies(OID.BallOfLevin).Except([actor])) - _aoes.Add(new(circleBig, a.Position, default, activation)); + var activation = WorldState.FutureTime(10d); + AddAOE(circleSmall, actor.Position); + + var orbs = Module.Enemies((uint)OID.BallOfLevin); + var count = orbs.Count; + for (var i = 0; i < count; ++i) + { + var orb = orbs[i]; + if (orb != actor) + AddAOE(circleBig, orb.Position); + } + void AddAOE(AOEShape shape, WPos origin) => _aoes.Add(new(shape, WPos.ClampToGrid(origin), default, activation)); } } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if ((AID)spell.Action.ID is AID.ShockSmall or AID.ShockLarge) + if (spell.Action.ID is (uint)AID.ShockSmall or (uint)AID.ShockLarge) _aoes.Clear(); } } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/V023Gorai.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/V023Gorai.cs index a776d51a94..2f3d774b08 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/V023Gorai.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/V023Gorai.cs @@ -1,15 +1,15 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V023Gorai; class Unenlightenment(BossModule module) : Components.RaidwideCastDelay(module, ActionID.MakeSpell(AID.Unenlightenment), ActionID.MakeSpell(AID.UnenlightenmentAOE), 0.5f); -class SpikeOfFlameAOE(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.SpikeOfFlameAOE), 5); +class SpikeOfFlameAOE(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.SpikeOfFlameAOE), 5f); class StringSnap(BossModule module) : Components.ConcentricAOEs(module, _shapes) { - private static readonly AOEShape[] _shapes = [new AOEShapeCircle(10), new AOEShapeDonut(10, 20), new AOEShapeDonut(20, 30)]; + private static readonly AOEShape[] _shapes = [new AOEShapeCircle(10f), new AOEShapeDonut(10f, 20f), new AOEShapeDonut(20f, 30f)]; public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.StringSnap1) + if (spell.Action.ID == (uint)AID.StringSnap1) AddSequence(spell.LocXZ, Module.CastFinishAt(spell)); } @@ -17,29 +17,29 @@ public override void OnCastFinished(Actor caster, ActorCastInfo spell) { if (Sequences.Count != 0) { - var order = (AID)spell.Action.ID switch + var order = spell.Action.ID switch { - AID.StringSnap1 => 0, - AID.StringSnap2 => 1, - AID.StringSnap3 => 2, + (uint)AID.StringSnap1 => 0, + (uint)AID.StringSnap2 => 1, + (uint)AID.StringSnap3 => 2, _ => -1 }; - AdvanceSequence(order, spell.LocXZ, WorldState.FutureTime(2)); + AdvanceSequence(order, spell.LocXZ, WorldState.FutureTime(2d)); } } } -class TorchingTorment(BossModule module) : Components.BaitAwayIcon(module, new AOEShapeCircle(6), (uint)IconID.Tankbuster, ActionID.MakeSpell(AID.TorchingTorment), 5.9f, true) +class TorchingTorment(BossModule module) : Components.BaitAwayIcon(module, new AOEShapeCircle(6f), (uint)IconID.Tankbuster, ActionID.MakeSpell(AID.TorchingTorment), 5.9f, true) { public override void AddGlobalHints(GlobalHints hints) { - if (CurrentBaits.Count > 0) + if (CurrentBaits.Count != 0) hints.Add("Tankbuster cleave"); } } class PureShock(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.PureShock)); -class HumbleHammer(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.HumbleHammer), 3); +class HumbleHammer(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.HumbleHammer), 3f); class FightingSpirits(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.FightingSpirits)); class BiwaBreaker(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.BiwaBreakerFirst), "Raidwide x5"); @@ -49,17 +49,18 @@ public class V023Gorai(WorldState ws, Actor primary) : BossModule(ws, primary, A protected override void DrawEnemies(int pcSlot, Actor pc) { Arena.Actor(PrimaryActor); - Arena.Actors(Enemies(OID.ShishuWhiteBaboon)); + Arena.Actors(Enemies((uint)OID.ShishuWhiteBaboon)); } protected override void CalculateModuleAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { - foreach (var e in hints.PotentialTargets) + var count = hints.PotentialTargets.Count; + for (var i = 0; i < count; ++i) { - e.Priority = (OID)e.Actor.OID switch + var e = hints.PotentialTargets[i]; + e.Priority = e.Actor.OID switch { - OID.ShishuWhiteBaboon => 2, - OID.Boss => 1, + (uint)OID.ShishuWhiteBaboon => 1, _ => 0 }; } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/WordlyPursuit.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/WordlyPursuit.cs index 8cbef1964a..38dc7d8ce3 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/WordlyPursuit.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V023Gorai/WordlyPursuit.cs @@ -2,25 +2,26 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V023Gorai; class WorldlyPursuit(BossModule module) : Components.GenericRotatingAOE(module) { - private static readonly AOEShapeCross cross = new(60, 10); + private static readonly AOEShapeCross cross = new(60f, 10f); public override uint ImminentColor => Colors.AOE; public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - switch ((AID)spell.Action.ID) + void AddSequence(Angle increment) => Sequences.Add(new(cross, spell.LocXZ, spell.Rotation, increment, Module.CastFinishAt(spell), 3.7f, 5, 1)); + switch (spell.Action.ID) { - case AID.WorldlyPursuitFirstCCW: - Sequences.Add(new(cross, Module.PrimaryActor.Position, spell.Rotation, 22.5f.Degrees(), Module.CastFinishAt(spell), 3.7f, 5, 1)); + case (uint)AID.WorldlyPursuitFirstCCW: + AddSequence(22.5f.Degrees()); break; - case AID.WorldlyPursuitFirstCW: - Sequences.Add(new(cross, Module.PrimaryActor.Position, spell.Rotation, -22.5f.Degrees(), Module.CastFinishAt(spell), 3.7f, 5, 1)); + case (uint)AID.WorldlyPursuitFirstCW: + AddSequence(-22.5f.Degrees()); break; } } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID is AID.WorldlyPursuitFirstCCW or AID.WorldlyPursuitFirstCW or AID.WorldlyPursuitRest) + if (spell.Action.ID is (uint)AID.WorldlyPursuitFirstCCW or (uint)AID.WorldlyPursuitFirstCW or (uint)AID.WorldlyPursuitRest) AdvanceSequence(0, WorldState.CurrentTime); } } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/ArenaChange.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/ArenaChange.cs index b667726603..59bcc73f24 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/ArenaChange.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/ArenaChange.cs @@ -2,13 +2,13 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V024Shishio; class ArenaChange(BossModule module) : Components.GenericAOEs(module) { - private static readonly AOEShapeDonut donut = new(20, 28); + private static readonly AOEShapeDonut donut = new(20f, 28f); private AOEInstance? _aoe; public override IEnumerable ActiveAOEs(int slot, Actor actor) => Utils.ZeroOrOne(_aoe); public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.StormcloudSummons) + if (spell.Action.ID == (uint)AID.StormcloudSummons) _aoe = new(donut, Arena.Center, default, Module.CastFinishAt(spell, 0.7f)); } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/FocusedTremor.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/FocusedTremor.cs index 7a4d6d90fb..91b87e3e04 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/FocusedTremor.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/FocusedTremor.cs @@ -1,47 +1,39 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V024Shishio; -class YokiUzu(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.YokiUzu), 23); - -class FocusedTremor(BossModule module) : Components.GenericAOEs(module) +class FocusedTremorYokiUzu(BossModule module) : Components.GenericAOEs(module) { - private readonly YokiUzu _yokiUzu = module.FindComponent()!; - private static readonly AOEShapeRect rect = new(30, 20); - private AOEInstance _aoe; - private Circle? circle; + private static readonly AOEShapeRect rect = new(30f, 20f); + private static readonly AOEShapeDonut donut = new(23f, 40f, true); + private AOEInstance? _aoe; + private AOEInstance? _aoeCache; public override IEnumerable ActiveAOEs(int slot, Actor actor) { - if (_aoe == default) - yield break; - - var isCasterActive = _yokiUzu.ActiveCasters.Count != 0; - var firstAOEActivation = _yokiUzu.ActiveAOEs(slot, actor).FirstOrDefault().Activation; - var sixFulmsUnderStatus = actor.FindStatus(SID.SixFulmsUnder); - var expireAt = sixFulmsUnderStatus?.ExpireAt ?? DateTime.MaxValue; - var extra = circle != null ? 10 : 0; - RectangleSE[] rectShape = [new(_aoe.Origin, _aoe.Origin + (rect.LengthFront + extra) * _aoe.Rotation.ToDirection(), rect.HalfWidth)]; - Circle[] circleShape = circle != null ? [circle] : []; - var aoeInstance = _aoe with + if (_aoe == null) + return []; + else { - Origin = Arena.Center, - Shape = new AOEShapeCustom(rectShape, null, circleShape, false, circle != null ? OperandType.Xor : OperandType.Union) with { InvertForbiddenZone = isCasterActive }, - Color = isCasterActive ? Colors.SafeFromAOE : Colors.AOE, - Activation = !isCasterActive ? expireAt : firstAOEActivation - }; - - yield return aoeInstance; + var aoe = _aoe.Value; + return [aoe.Shape == rect ? aoe with { Activation = actor.FindStatus((uint)SID.SixFulmsUnder)?.ExpireAt ?? DateTime.MaxValue } : aoe]; + } } public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.YokiUzu) - circle = new(caster.Position, 23); + if (spell.Action.ID == (uint)AID.YokiUzu) + { + _aoeCache = _aoe; + _aoe = new(donut, spell.LocXZ, default, Module.CastFinishAt(spell), Colors.SafeFromAOE); + } } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.YokiUzu) - circle = null; + if (spell.Action.ID == (uint)AID.YokiUzu) + { + _aoe = _aoeCache; + _aoeCache = null; + } } public override void OnEventEnvControl(byte index, uint state) @@ -49,30 +41,32 @@ public override void OnEventEnvControl(byte index, uint state) if (state == 0x00020001) _aoe = index switch { - 0x67 => new(rect, Arena.Center - new WDir(20, 0), 90.Degrees()), - 0x65 => new(rect, Arena.Center - new WDir(-20, 0), -90.Degrees()), - 0x66 => new(rect, Arena.Center - new WDir(0, 20)), - 0x68 => new(rect, Arena.Center - new WDir(0, -20), 180.Degrees()), + 0x67 => new(rect, Arena.Center - new WDir(20f, default), 90f.Degrees()), + 0x65 => new(rect, Arena.Center - new WDir(-20f, default), -90f.Degrees()), + 0x66 => new(rect, Arena.Center - new WDir(default, 20f)), + 0x68 => new(rect, Arena.Center - new WDir(default, -20f), 180f.Degrees()), _ => default }; - if (state == 0x00080004 && index is 0x65 or 0x66 or 0x67 or 0x68) + else if (state == 0x00080004 && index is 0x65 or 0x66 or 0x67 or 0x68) _aoe = default; } public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { base.AddAIHints(slot, actor, assignment, hints); - var sixFulmsUnderStatus = actor.FindStatus(SID.SixFulmsUnder); - var expireAt = sixFulmsUnderStatus?.ExpireAt ?? DateTime.MaxValue; - if (circle != null && (expireAt - WorldState.CurrentTime).TotalSeconds <= 8) + var expireAt = actor.FindStatus((uint)SID.SixFulmsUnder)?.ExpireAt ?? DateTime.MaxValue; + if (_aoe is AOEInstance aoe && aoe.Shape == donut && (expireAt - WorldState.CurrentTime).TotalSeconds <= 8d) hints.ActionsToExecute.Push(ActionID.MakeSpell(ClassShared.AID.Sprint), actor, ActionQueue.Priority.High); } public override void AddHints(int slot, Actor actor, TextHints hints) { - if (ActiveAOEs(slot, actor).Any(c => c.Color == Colors.AOE)) - base.AddHints(slot, actor, hints); - else if (ActiveAOEs(slot, actor).Any(c => !c.Check(actor.Position))) - hints.Add("Go into quicksand to avoid AOE!"); + if (_aoe is AOEInstance aoe) + { + if (aoe.Shape == rect) + base.AddHints(slot, actor, hints); + else if (!aoe.Check(actor.Position)) + hints.Add("Go into quicksand to avoid AOE!"); + } } } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Levinburst.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Levinburst.cs index c020af16ae..1df72b5e5a 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Levinburst.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Levinburst.cs @@ -2,19 +2,19 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V024Shishio; class Levinburst(BossModule module) : Components.GenericAOEs(module) { - private static readonly AOEShapeRect rect = new(5, 20, 5); + private static readonly AOEShapeRect rect = new(5f, 20f, 5f); private readonly List _aoes = []; public override IEnumerable ActiveAOEs(int slot, Actor actor) => _aoes; public override void OnActorCreated(Actor actor) { - if ((OID)actor.OID == OID.Rairin) - _aoes.Add(new(rect, actor.Position, actor.Rotation, WorldState.FutureTime(6.9f))); + if (actor.OID == (uint)OID.Rairin) + _aoes.Add(new(rect, WPos.ClampToGrid(actor.Position), actor.Rotation, WorldState.FutureTime(6.9d))); } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if ((AID)spell.Action.ID == AID.Levinburst) + if (spell.Action.ID == (uint)AID.Levinburst) _aoes.Clear(); } } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Reisho.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Reisho.cs index 7e59cbb99d..7579e0b718 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Reisho.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Reisho.cs @@ -1,13 +1,15 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V024Shishio; -class Reisho1(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.ReishoFirst), 6); -class Reisho2(BossModule module) : Components.PersistentVoidzone(module, 6, m => m.Enemies(OID.HauntingThrall), 10) +class Reisho1(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.ReishoFirst), 6f); +class Reisho2(BossModule module) : Components.PersistentVoidzone(module, 6f, GetGhosts, 10f) { + private static List GetGhosts(BossModule module) => module.Enemies((uint)OID.HauntingThrall); + private bool started; public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.ReishoFirst) + if (spell.Action.ID == (uint)AID.ReishoFirst) started = true; } @@ -25,9 +27,9 @@ public override void DrawArenaBackground(int pcSlot, Actor pc) public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if ((AID)spell.Action.ID == AID.ReishoRest) + if (spell.Action.ID == (uint)AID.ReishoRest) ++NumCasts; - else if ((AID)spell.Action.ID == AID.ThunderVortex) // not sure if mechanic can repeat if fight takes long enough + else if (spell.Action.ID == (uint)AID.ThunderVortex) // not sure if mechanic can repeat if fight takes long enough { started = false; NumCasts = 0; diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Rokujo.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Rokujo.cs index d1bfd49c34..3cce221df9 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Rokujo.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/Rokujo.cs @@ -2,7 +2,7 @@ class Rokujos : Components.SimpleAOEs { - public Rokujos(BossModule module, AID aid) : base(module, ActionID.MakeSpell(aid), new AOEShapeRect(60, 7)) { MaxDangerColor = 1; } + public Rokujos(BossModule module, AID aid) : base(module, ActionID.MakeSpell(aid), new AOEShapeRect(60f, 7f)) { MaxDangerColor = 1; } } class OnceOnRokujo(BossModule module) : Rokujos(module, AID.OnceOnRokujo); class TwiceOnRokujo(BossModule module) : Rokujos(module, AID.TwiceOnRokujo); @@ -10,9 +10,9 @@ class ThriceOnRokujo(BossModule module) : Rokujos(module, AID.ThriceOnRokujo); class Rokujo(BossModule module) : Components.GenericAOEs(module) { - private static readonly AOEShapeCircle[] circles = [new(8), new(12), new(23)]; - private readonly List _aoes = []; - private readonly List _clouds = []; + private static readonly AOEShapeCircle[] circles = [new(8f), new(12f), new(23f)]; + private readonly List _aoes = new(12); + private readonly List _clouds = new(18); public override IEnumerable ActiveAOEs(int slot, Actor actor) { @@ -20,87 +20,106 @@ public override IEnumerable ActiveAOEs(int slot, Actor actor) if (count == 0) return []; var max = count > 6 ? 6 : count; - List aoes = new(max); + var aoes = new AOEInstance[max]; for (var i = 0; i < max; ++i) { var aoe = _aoes[i]; - if (i == 0) - aoes.Add(count > 2 ? aoe with { Color = Colors.Danger } : aoe); + if (i < 2) + aoes[i] = count > 2 ? aoe with { Color = Colors.Danger } : aoe; else - aoes.Add(aoe); + aoes[i] = aoe; } return aoes; } public override void OnActorDestroyed(Actor actor) { - if ((OID)actor.OID == OID.Raiun) + if (actor.OID == (uint)OID.Raiun) _clouds.Remove(actor); } public override void OnActorCreated(Actor actor) { - if ((OID)actor.OID == OID.Raiun) + if (actor.OID == (uint)OID.Raiun) _clouds.Add(actor); } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if ((AID)spell.Action.ID == AID.SmokeaterAbsorb) + if (spell.Action.ID == (uint)AID.SmokeaterAbsorb) _clouds.Remove(caster); } public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - switch ((AID)spell.Action.ID) + switch (spell.Action.ID) { - case AID.OnceOnRokujo: + case (uint)AID.OnceOnRokujo: RemoveCloudsAndAddAOEs(caster, spell, circles[0], circles[0].Radius, 1, aoeCount => 1 + MathF.Ceiling(aoeCount / 2)); break; - case AID.TwiceOnRokujo: + case (uint)AID.TwiceOnRokujo: RemoveCloudsAndAddAOEs(caster, spell, circles[1], circles[1].Radius, 1.6f, aoeCount => 3.1f); break; - case AID.ThriceOnRokujoVisual1: - foreach (var cloud in _clouds) - _aoes.Add(new(circles[2], cloud.Position, default, Module.CastFinishAt(spell, 7.1f))); + case (uint)AID.ThriceOnRokujoVisual1: + var count = _clouds.Count; + for (var i = 0; i < count; ++i) + _aoes.Add(new(circles[2], WPos.ClampToGrid(_clouds[i].Position), default, Module.CastFinishAt(spell, 7.1f))); break; } } private void RemoveCloudsAndAddAOEs(Actor caster, ActorCastInfo spell, AOEShapeCircle circle, float radius, float initialActivation, Func activation) { - var cloudsToRemove = _clouds.Where(c => c.Position.InRect(caster.Position, spell.Rotation, 30, 30, 7)); - foreach (var c in cloudsToRemove) - _aoes.Add(new(circle, c.Position, default, Module.CastFinishAt(spell, initialActivation))); - _clouds.RemoveAll(cloudsToRemove.Contains); + var countClouds = _clouds.Count; + var pos = caster.Position; + var rot = spell.Rotation; + for (var i = countClouds - 1; i >= 0; --i) + { + var cloud = _clouds[i].Position; + if (cloud.InRect(pos, rot, 30f, 30f, 7f)) + { + _aoes.Add(new(circle, WPos.ClampToGrid(cloud), default, Module.CastFinishAt(spell, initialActivation))); + _clouds.RemoveAt(i); + } + } while (_clouds.Count > 0) { List newAOEs = []; - List cloudsToRemoveInThisPass = []; - - foreach (var c in _clouds) - if (_aoes.Skip(_aoes.Count - 2).Any(a => a.Origin.InCircle(c.Position, radius))) + var removedAny = false; + var countClouds2 = _clouds.Count; + for (var i = countClouds2 - 1; i >= 0; --i) + { + var count = _aoes.Count; + var min = count - 2; + var max = min > 0 ? min : 0; + for (var j = max; j < count; ++j) { - newAOEs.Add(new(circle, c.Position, default, Module.CastFinishAt(spell, activation(_aoes.Count)))); - cloudsToRemoveInThisPass.Add(c); + var cloud = _clouds[i].Position; + if (_aoes[j].Origin.InCircle(cloud, radius)) + { + newAOEs.Add(new(circle, WPos.ClampToGrid(cloud), default, Module.CastFinishAt(spell, activation(count)))); + _clouds.RemoveAt(i); + removedAny = true; + break; + } } - if (cloudsToRemoveInThisPass.Count == 0) - break; // avoid infinite loop if no clouds are found for removal for whatever reason + } + if (!removedAny) + break; // Avoid infinite loop incase something goes wrong _aoes.AddRange(newAOEs); - _clouds.RemoveAll(cloudsToRemoveInThisPass.Contains); } } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { if (_aoes.Count != 0) - switch ((AID)spell.Action.ID) + switch (spell.Action.ID) { - case AID.LeapingLevin1: - case AID.LeapingLevin2: - case AID.LeapingLevin3: + case (uint)AID.LeapingLevin1: + case (uint)AID.LeapingLevin2: + case (uint)AID.LeapingLevin3: _aoes.RemoveAt(0); break; } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/V024Shishio.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/V024Shishio.cs index 18c71722ab..c84a4fc527 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/V024Shishio.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/V024Shishio.cs @@ -1,22 +1,22 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V024Shishio; -class NoblePursuit(BossModule module) : Components.ChargeAOEs(module, ActionID.MakeSpell(AID.NoblePursuit), 6); +class NoblePursuit(BossModule module) : Components.ChargeAOEs(module, ActionID.MakeSpell(AID.NoblePursuit), 6f); class Enkyo(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.Enkyo)); abstract class CloudToCloud : Components.SimpleAOEs { - protected CloudToCloud(BossModule module, AID aid, int halfWidth, int dangerCount) : base(module, ActionID.MakeSpell(aid), new AOEShapeRect(100, halfWidth)) { MaxDangerColor = dangerCount; } + protected CloudToCloud(BossModule module, AID aid, float halfWidth, int dangerCount) : base(module, ActionID.MakeSpell(aid), new AOEShapeRect(100f, halfWidth)) { MaxDangerColor = dangerCount; } } -class CloudToCloud1(BossModule module) : CloudToCloud(module, AID.CloudToCloud1, 1, 6); -class CloudToCloud2(BossModule module) : CloudToCloud(module, AID.CloudToCloud2, 3, 4); -class CloudToCloud3(BossModule module) : CloudToCloud(module, AID.CloudToCloud3, 6, 2); +class CloudToCloud1(BossModule module) : CloudToCloud(module, AID.CloudToCloud1, 1f, 6); +class CloudToCloud2(BossModule module) : CloudToCloud(module, AID.CloudToCloud2, 3f, 4); +class CloudToCloud3(BossModule module) : CloudToCloud(module, AID.CloudToCloud3, 6f, 2); -abstract class Thunder(BossModule module, AID aid) : Components.SimpleAOEs(module, ActionID.MakeSpell(aid), 6); +abstract class Thunder(BossModule module, AID aid) : Components.SimpleAOEs(module, ActionID.MakeSpell(aid), 6f); class ThunderOnefold(BossModule module) : Thunder(module, AID.ThunderOnefold); class ThunderTwofold(BossModule module) : Thunder(module, AID.ThunderTwofold); class ThunderThreefold(BossModule module) : Thunder(module, AID.ThunderThreefold); -class SplittingCry(BossModule module) : Components.BaitAwayIcon(module, new AOEShapeRect(60, 7), (uint)IconID.Tankbuster, ActionID.MakeSpell(AID.SplittingCry), 5) +class SplittingCry(BossModule module) : Components.BaitAwayIcon(module, new AOEShapeRect(60f, 7f), (uint)IconID.Tankbuster, ActionID.MakeSpell(AID.SplittingCry), 5f) { public override void AddGlobalHints(GlobalHints hints) { @@ -25,24 +25,24 @@ public override void AddGlobalHints(GlobalHints hints) } } -class ThunderVortex(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.ThunderVortex), new AOEShapeDonut(8, 30)); +class ThunderVortex(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.ThunderVortex), new AOEShapeDonut(8f, 30f)); -class Circles(BossModule module, AID aid) : Components.SimpleAOEs(module, ActionID.MakeSpell(aid), 6); +class Circles(BossModule module, AID aid) : Components.SimpleAOEs(module, ActionID.MakeSpell(aid), 6f); class UnsagelySpin(BossModule module) : Circles(module, AID.UnsagelySpin); class Yoki(BossModule module) : Circles(module, AID.Yoki); -class Rush(BossModule module) : Components.ChargeAOEs(module, ActionID.MakeSpell(AID.Rush), 4); -class Vasoconstrictor(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Vasoconstrictor), 5); +class Rush(BossModule module) : Components.ChargeAOEs(module, ActionID.MakeSpell(AID.Rush), 4f); +class Vasoconstrictor(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Vasoconstrictor), 5f); -class Swipe(BossModule module, AID aid) : Components.SimpleAOEs(module, ActionID.MakeSpell(aid), new AOEShapeCone(40, 90.Degrees())); +class Swipe(BossModule module, AID aid) : Components.SimpleAOEs(module, ActionID.MakeSpell(aid), new AOEShapeCone(40f, 90f.Degrees())); class RightSwipe(BossModule module) : Swipe(module, AID.RightSwipe); class LeftSwipe(BossModule module) : Swipe(module, AID.LeftSwipe); [ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "The Combat Reborn Team (Malediktus, LTS)", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 945, NameID = 12428, SortOrder = 5)] public class V024Shishio(WorldState ws, Actor primary) : BossModule(ws, primary, ArenaCenter, NormalBounds) { - public static readonly WPos ArenaCenter = new(-40, -300); + public static readonly WPos ArenaCenter = new(-40f, -300f); public static readonly ArenaBoundsSquare NormalBounds = new(19.5f); - public static readonly ArenaBoundsComplex CircleBounds = new([new Circle(ArenaCenter, 20)], [new Rectangle(ArenaCenter + new WDir(-20, 0), 0.5f, 20), - new Rectangle(ArenaCenter + new WDir(20, 0), 0.5f, 20), new Rectangle(ArenaCenter + new WDir(0, 20), 20, 0.5f), new Rectangle(ArenaCenter + new WDir(0, -20), 20, 0.5f)]); + public static readonly ArenaBoundsComplex CircleBounds = new([new Circle(ArenaCenter, 20f)], [new Rectangle(ArenaCenter + new WDir(-20f, default), 0.5f, 20f), + new Rectangle(ArenaCenter + new WDir(20f, default), 0.5f, 20f), new Rectangle(ArenaCenter + new WDir(default, 20f), 20f, 0.5f), new Rectangle(ArenaCenter + new WDir(default, -20f), 20f, 0.5f)]); } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/V024ShishioStates.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/V024ShishioStates.cs index ccb7d78147..b0511dc240 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/V024ShishioStates.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V024Shishio/V024ShishioStates.cs @@ -13,8 +13,7 @@ public V024ShishioStates(BossModule module) : base(module) .ActivateOnEnter() // Route 9 .ActivateOnEnter() - .ActivateOnEnter() - .ActivateOnEnter() + .ActivateOnEnter() // Route 10 .ActivateOnEnter() .ActivateOnEnter() diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/ArenaChange.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/ArenaChange.cs index 453b63563b..0a152460cd 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/ArenaChange.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/ArenaChange.cs @@ -2,13 +2,13 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V025Enenra; class ArenaChange(BossModule module) : Components.GenericAOEs(module) { - private static readonly AOEShapeDonut donut = new(20, 21); + private static readonly AOEShapeDonut donut = new(20f, 21f); private AOEInstance? _aoe; public override IEnumerable ActiveAOEs(int slot, Actor actor) => Utils.ZeroOrOne(_aoe); public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.FlagrantCombustion && Arena.Bounds == V025Enenra.StartingBounds) + if (spell.Action.ID == (uint)AID.FlagrantCombustion && Arena.Bounds == V025Enenra.StartingBounds) _aoe = new(donut, Arena.Center, default, Module.CastFinishAt(spell, 2.9f)); } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/IntoTheFire.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/IntoTheFire.cs index 8ca1d38930..f787bd50c2 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/IntoTheFire.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/IntoTheFire.cs @@ -2,16 +2,16 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V025Enenra; class IntoTheFire(BossModule module) : Components.GenericAOEs(module) { - private static readonly AOEShapeRect rect = new(50, 25); - private readonly List _aoes = []; - private static readonly float offset = 11 * MathF.Sqrt(2); + private static readonly AOEShapeRect rect = new(50f, 25f); + private readonly List _aoes = new(2); + private const float offset = 15.556349f; public override IEnumerable ActiveAOEs(int slot, Actor actor) => _aoes; public override void OnActorEAnim(Actor actor, uint state) { if (state == 0x00010002) - HandleSmokeVisuals(actor, WorldState.FutureTime(16.6f)); + HandleSmokeVisuals(actor, WorldState.FutureTime(16.6d)); } private void HandleSmokeVisuals(Actor actor, DateTime activation) @@ -21,38 +21,36 @@ private void HandleSmokeVisuals(Actor actor, DateTime activation) if (positionOffset != null && rotation != null) { - var roundedPosition = RoundPosition(actor.Position + positionOffset.Value); - _aoes.Add(new(rect, roundedPosition, rotation.Value, activation)); + var correctedPosition = WPos.ClampToGrid(RoundPosition(actor.Position + positionOffset.Value)); + _aoes.Add(new(rect, correctedPosition, rotation.Value, activation)); } } private static WDir? GetPositionOffsetForActor(Actor actor) { - var actorDirection = actor.Rotation.ToDirection(); - - return (OID)actor.OID switch + return actor.OID switch { - OID.SmokeVisual1 => offset * (actor.Rotation - 45.Degrees()).ToDirection(), - OID.SmokeVisual2 => offset * (actor.Rotation + 45.Degrees()).ToDirection(), - OID.SmokeVisual3 => 22 * actorDirection, + (uint)OID.SmokeVisual1 => offset * (actor.Rotation - 45f.Degrees()).ToDirection(), + (uint)OID.SmokeVisual2 => offset * (actor.Rotation + 45f.Degrees()).ToDirection(), + (uint)OID.SmokeVisual3 => 22f * actor.Rotation.ToDirection(), _ => null }; } private static Angle? GetRotationForActor(Actor actor) { - return (OID)actor.OID switch + return actor.OID switch { - OID.SmokeVisual1 => actor.Rotation + 90.Degrees(), - OID.SmokeVisual2 => actor.Rotation - 90.Degrees(), - OID.SmokeVisual3 => actor.Rotation + 180.Degrees(), + (uint)OID.SmokeVisual1 => actor.Rotation + 90f.Degrees(), + (uint)OID.SmokeVisual2 => actor.Rotation - 90f.Degrees(), + (uint)OID.SmokeVisual3 => actor.Rotation + 180f.Degrees(), _ => null }; } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - if (_aoes.Count > 0 && (AID)spell.Action.ID == AID.IntoTheFire) + if (_aoes.Count != 0 && spell.Action.ID == (uint)AID.IntoTheFire) _aoes.RemoveAt(0); } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/V025Enenra.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/V025Enenra.cs index a65103ac4c..120feb94b5 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/V025Enenra.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V025Enenra/V025Enenra.cs @@ -1,27 +1,28 @@ namespace BossMod.Endwalker.VariantCriterion.V02MR.V025Enenra; -class PipeCleaner(BossModule module) : Components.BaitAwayTethers(module, new AOEShapeRect(60, 5), (uint)TetherID.PipeCleaner); -class Uplift(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Uplift), 6); -class Snuff(BossModule module) : Components.BaitAwayCast(module, ActionID.MakeSpell(AID.Snuff), new AOEShapeCircle(6), true) +class PipeCleaner(BossModule module) : Components.BaitAwayTethers(module, new AOEShapeRect(60f, 5f), (uint)TetherID.PipeCleaner); +class Uplift(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Uplift), 6f); +class Snuff(BossModule module) : Components.BaitAwayCast(module, ActionID.MakeSpell(AID.Snuff), new AOEShapeCircle(6f), true) { public override void AddGlobalHints(GlobalHints hints) { - if (CurrentBaits.Count > 0) + if (CurrentBaits.Count != 0) hints.Add("Tankbuster cleave"); } } -class Smoldering(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Smoldering), 8, 8); +class Smoldering(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Smoldering), 8f, 8); class FlagrantCombustion(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.FlagrantCombustion)); -class SmokeRings(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.SmokeRings), 16); -class ClearingSmoke(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.ClearingSmoke), 16, stopAfterWall: true) +class SmokeRings(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.SmokeRings), 16f); +class ClearingSmoke(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.ClearingSmoke), 16f, stopAfterWall: true) { + private readonly Smoldering _aoe = module.FindComponent()!; + public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { - var source = Sources(slot, actor).FirstOrDefault(); - var component = Module.FindComponent()?.ActiveAOEs(slot, actor)?.ToList(); - if (component != null && source != default) - hints.AddForbiddenZone(ShapeDistance.InvertedCircle(Arena.Center, 4), source.Activation); + var source = Casters.Count != 0 ? Casters[0] : null; + if (_aoe.Casters.Count != 0 && source != null) + hints.AddForbiddenZone(ShapeDistance.InvertedCircle(Arena.Center, 4f), Module.CastFinishAt(source.CastInfo)); } } @@ -31,7 +32,7 @@ class StringRock(BossModule module) : Components.ConcentricAOEs(module, _shapes) public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.KiseruClamor) + if (spell.Action.ID == (uint)AID.KiseruClamor) AddSequence(spell.LocXZ, Module.CastFinishAt(spell)); } @@ -39,28 +40,28 @@ public override void OnCastFinished(Actor caster, ActorCastInfo spell) { if (Sequences.Count != 0) { - var order = (AID)spell.Action.ID switch + var order = spell.Action.ID switch { - AID.KiseruClamor => 0, - AID.BedrockUplift1 => 1, - AID.BedrockUplift2 => 2, - AID.BedrockUplift3 => 3, + (uint)AID.KiseruClamor => 0, + (uint)AID.BedrockUplift1 => 1, + (uint)AID.BedrockUplift2 => 2, + (uint)AID.BedrockUplift3 => 3, _ => -1 }; - AdvanceSequence(order, spell.LocXZ, WorldState.FutureTime(2)); + AdvanceSequence(order, spell.LocXZ, WorldState.FutureTime(2d)); } } } [ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "The Combat Reborn Team (Malediktus, LTS)", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 945, NameID = 12393, SortOrder = 7)] -public class V025Enenra(WorldState ws, Actor primary) : BossModule(ws, primary, new(900, -900), StartingBounds) +public class V025Enenra(WorldState ws, Actor primary) : BossModule(ws, primary, new(900f, -900f), StartingBounds) { public static readonly ArenaBoundsCircle StartingBounds = new(20.5f); - public static readonly ArenaBoundsCircle DefaultBounds = new(20); + public static readonly ArenaBoundsCircle DefaultBounds = new(20f); protected override void DrawEnemies(int pcSlot, Actor pc) { Arena.Actor(PrimaryActor); - Arena.Actors(Enemies(OID.EnenraClone)); + Arena.Actors(Enemies((uint)OID.EnenraClone)); } } diff --git a/BossMod/Modules/Endwalker/Variant/V02MR/V026ShishuChochin/V026ShishuChochin.cs b/BossMod/Modules/Endwalker/Variant/V02MR/V026ShishuChochin/V026ShishuChochin.cs index 346856c724..10920330e7 100644 --- a/BossMod/Modules/Endwalker/Variant/V02MR/V026ShishuChochin/V026ShishuChochin.cs +++ b/BossMod/Modules/Endwalker/Variant/V02MR/V026ShishuChochin/V026ShishuChochin.cs @@ -17,15 +17,11 @@ class Lanterns(BossModule module) : Components.GenericAOEs(module) { private readonly V026ShishuChochinConfig _config = Service.Config.Get(); - private static readonly Circle lantern1 = new(new(723.5f, 57.5f), 1); - private static readonly Circle lantern2 = new(new(690.5f, 57.5f), 1); - private static readonly Circle lantern3 = new(new(681.2f, 51.6f), 1); + private static readonly Circle lantern1 = new(new(723.5f, 57.5f), 1f), lantern2 = new(new(690.5f, 57.5f), 1f), lantern3 = new(new(681.2f, 51.6f), 1f); private readonly List lanterns = [lantern1, lantern2, lantern3]; - public override IEnumerable ActiveAOEs(int slot, Actor actor) - { - return [new(new AOEShapeCustom([.. lanterns], InvertForbiddenZone: true), Arena.Center, default, WorldState.FutureTime(99), Colors.SafeFromAOE)]; - } + private AOEInstance? _aoe; + public override IEnumerable ActiveAOEs(int slot, Actor actor) => Utils.ZeroOrOne(_aoe); public override void OnEventEnvControl(byte index, uint state) { if (state == 0x00020001) @@ -36,12 +32,13 @@ public override void OnEventEnvControl(byte index, uint state) lanterns.Remove(lantern2); else if (index == 0x46) lanterns.Remove(lantern3); + _aoe = new(new AOEShapeCustom([.. lanterns], InvertForbiddenZone: true), Arena.Center, default, WorldState.FutureTime(99d), Colors.SafeFromAOE); } } public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.Illume) + if (spell.Action.ID == (uint)AID.Illume) ++NumCasts; } @@ -53,26 +50,19 @@ public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignme if (count) base.AddAIHints(slot, actor, assignment, hints); var lanternPriorityCount = 0; - for (var i = 0; i < hints.PotentialTargets.Count; ++i) + + var countT = hints.PotentialTargets.Count; + for (var i = 0; i < countT; ++i) { var e = hints.PotentialTargets[i]; if (e.Actor.OID == (uint)OID.Boss) { - var hasActiveAOE = false; - foreach (var c in ActiveAOEs(slot, actor)) - { - if (c.Check(actor.Position)) - { - hasActiveAOE = true; - break; - } - } - - if (lanternPriorityCount == 0 && hasActiveAOE && count) + var inAOE = _aoe != null && _aoe.Value.Check(actor.Position); + if (lanternPriorityCount == 0 && inAOE && count) { Actor? closestBoss = null; var closestDistance = float.MaxValue; - var boss = Module.Enemies(OID.Boss); + var boss = Module.Enemies((uint)OID.Boss); var countBoss = boss.Count; for (var j = 0; j < countBoss; ++j) { @@ -106,12 +96,13 @@ public override void AddHints(int slot, Actor actor, TextHints hints) { } public override void DrawArenaForeground(int pcSlot, Actor pc) { - foreach (var l in lanterns) - Arena.AddCircle(l.Center, 5, Colors.Safe, 5); + var count = lanterns.Count; + for (var i = 0; i < count; ++i) + Arena.AddCircle(lanterns[i].Center, 5f, Colors.Safe, 5f); } } -class Illume(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Illume), new AOEShapeCone(6, 45.Degrees())); +class Illume(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Illume), new AOEShapeCone(6f, 45f.Degrees())); class V026ShishuChochinStates : StateMachineBuilder { @@ -120,8 +111,17 @@ public V026ShishuChochinStates(BossModule module) : base(module) TrivialPhase() .ActivateOnEnter() .ActivateOnEnter() - .Raw.Update = () => module.Enemies(OID.Boss).All(e => e.IsDeadOrDestroyed); - + .Raw.Update = () => + { + var enemies = module.Enemies((uint)OID.Boss); + var count = enemies.Count; + for (var i = 0; i < count; ++i) + { + if (!enemies[i].IsDeadOrDestroyed) + return false; + } + return true; + }; } } @@ -177,6 +177,6 @@ public class V026ShishuChochin(WorldState ws, Actor primary) : BossModule(ws, pr protected override void DrawEnemies(int pcSlot, Actor pc) { - Arena.Actors(Enemies(OID.Boss)); + Arena.Actors(Enemies((uint)OID.Boss)); } } diff --git a/BossMod/Modules/Global/PVP/HiddenGorge/GoblinMercenary.cs b/BossMod/Modules/Global/PVP/HiddenGorge/GoblinMercenary.cs index 56c54d768e..3b32b6e0f3 100644 --- a/BossMod/Modules/Global/PVP/HiddenGorge/GoblinMercenary.cs +++ b/BossMod/Modules/Global/PVP/HiddenGorge/GoblinMercenary.cs @@ -51,8 +51,8 @@ public override void OnEventCast(Actor caster, ActorCastEvent spell) class Knockbacks(BossModule module) : Components.Knockback(module) { - private static readonly AOEShapeCircle circle = new(8); - private static readonly AOEShapeDonut donut = new(5, 30); + private static readonly AOEShapeCircle circle = new(8f); + private static readonly AOEShapeDonut donut = new(5f, 30f); private Source? _knockback; public override IEnumerable Sources(int slot, Actor actor) => Utils.ZeroOrOne(_knockback); @@ -60,15 +60,15 @@ class Knockbacks(BossModule module) : Components.Knockback(module) public override void OnCastStarted(Actor caster, ActorCastInfo spell) { var activation = Module.CastFinishAt(spell, 4); - if ((AID)spell.Action.ID == AID.GobspinWhooshdropsTelegraph) - _knockback = new(Module.PrimaryActor.Position, 15, activation, circle); - if ((AID)spell.Action.ID == AID.GobswipeConklopsTelegraph) - _knockback = new(Module.PrimaryActor.Position, 15, activation, donut); + if (spell.Action.ID == (uint)AID.GobspinWhooshdropsTelegraph) + _knockback = new(Module.PrimaryActor.Position, 15f, activation, circle); + else if (spell.Action.ID == (uint)AID.GobswipeConklopsTelegraph) + _knockback = new(Module.PrimaryActor.Position, 15f, activation, donut); } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if ((AID)spell.Action.ID is AID.GobspinWhooshdrops or AID.GobswipeConklops) + if (spell.Action.ID is (uint)AID.GobspinWhooshdrops or (uint)AID.GobswipeConklops) _knockback = null; } } @@ -79,14 +79,14 @@ class GobfireShootypops(BossModule module) : Components.GenericRotatingAOE(modul private Angle _rotation; private DateTime _activation; - private static readonly AOEShapeRect _shape = new(32, 3); + private static readonly AOEShapeRect _shape = new(32f, 3f); public override void OnEventIcon(Actor actor, uint iconID, ulong targetID) { - var increment = (IconID)iconID switch + var increment = iconID switch { - IconID.RotateCW => -60.Degrees(), - IconID.RotateCCW => 60.Degrees(), + (uint)IconID.RotateCW => -60f.Degrees(), + (uint)IconID.RotateCCW => 60f.Degrees(), _ => default }; if (increment != default) @@ -98,18 +98,17 @@ public override void OnEventIcon(Actor actor, uint iconID, ulong targetID) public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.GobfireShootypopsStart) + if (spell.Action.ID == (uint)AID.GobfireShootypopsStart) { _rotation = spell.Rotation; _activation = Module.CastFinishAt(spell); - } - if (_rotation != default) InitIfReady(caster); + } } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if ((AID)spell.Action.ID is AID.GobfireShootypopsStart or AID.GobfireShootypops) + if (spell.Action.ID is (uint)AID.GobfireShootypopsStart or (uint)AID.GobfireShootypops) AdvanceSequence(0, WorldState.CurrentTime); } @@ -117,7 +116,7 @@ private void InitIfReady(Actor source) { if (_rotation != default && _increment != default) { - Sequences.Add(new(_shape, source.Position, _rotation, _increment, _activation, 1, 6)); + Sequences.Add(new(_shape, WPos.ClampToGrid(source.Position), _rotation, _increment, _activation, 1, 6)); _rotation = default; _increment = default; } diff --git a/BossMod/Modules/RealmReborn/Dungeon/D04Halatali/D041Firemane.cs b/BossMod/Modules/RealmReborn/Dungeon/D04Halatali/D041Firemane.cs index c07c7e1cb7..6f35643a4d 100644 --- a/BossMod/Modules/RealmReborn/Dungeon/D04Halatali/D041Firemane.cs +++ b/BossMod/Modules/RealmReborn/Dungeon/D04Halatali/D041Firemane.cs @@ -21,7 +21,7 @@ public enum AID : uint class Fireflow(BossModule module) : Components.GenericAOEs(module) { - private static readonly AOEShapeCone cone = new(60, 22.5f.Degrees()); + private static readonly AOEShapeCone cone = new(60f, 22.5f.Degrees()); private readonly List _aoes = new(8); public override IEnumerable ActiveAOEs(int slot, Actor actor) @@ -38,7 +38,7 @@ public override IEnumerable ActiveAOEs(int slot, Actor actor) public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID is AID.Fireflow1 or AID.Fireflow2) + if (spell.Action.ID is (uint)AID.Fireflow1 or (uint)AID.Fireflow2) { _aoes.Add(new(cone, spell.LocXZ, spell.Rotation, Module.CastFinishAt(spell))); if (_aoes.Count == 8) @@ -48,13 +48,13 @@ public override void OnCastStarted(Actor caster, ActorCastInfo spell) public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - if (_aoes.Count != 0 && (AID)spell.Action.ID is AID.Fireflow1 or AID.Fireflow2) + if (_aoes.Count != 0 && spell.Action.ID is (uint)AID.Fireflow1 or (uint)AID.Fireflow2) _aoes.RemoveAt(0); } } class BurningBolt(BossModule module) : Components.SingleTargetCast(module, ActionID.MakeSpell(AID.BurningBolt)); -class FireII(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.FireII), 5); +class FireII(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.FireII), 5f); class D041FiremaneStates : StateMachineBuilder { @@ -71,7 +71,7 @@ public D041FiremaneStates(BossModule module) : base(module) public class D041Firemane(WorldState ws, Actor primary) : BossModule(ws, primary, arena.Center, arena) { private static readonly WPos[] vertices = [new(18.77f, 105.52f), new(20.74f, 105.75f), new(21.4f, 106.03f), new(31.94f, 110.21f), new(32.51f, 110.54f), - new(34.44f, 112.19f), new(35, 112.58f), new(42.3f, 119.87f), new(44.11f, 121.45f), new(47.1f, 124.46f), + new(34.44f, 112.19f), new(35f, 112.58f), new(42.3f, 119.87f), new(44.11f, 121.45f), new(47.1f, 124.46f), new(47.65f, 124.87f), new(48.29f, 125.2f), new(51.14f, 127.53f), new(51.48f, 127.91f), new(52.34f, 129.13f), new(52.7f, 129.77f), new(52.99f, 130.44f), new(55.04f, 140.77f), new(55, 141.44f), new(54.86f, 142.09f), new(54.61f, 142.71f), new(50.46f, 148.48f), new(49.99f, 148.92f), new(40.54f, 154.16f), new(33.76f, 155.83f), diff --git a/BossMod/Modules/Shadowbringers/Dungeon/D01Holminster/D013Philia.cs b/BossMod/Modules/Shadowbringers/Dungeon/D01Holminster/D013Philia.cs index 1e84d97b2a..d37f09919d 100644 --- a/BossMod/Modules/Shadowbringers/Dungeon/D01Holminster/D013Philia.cs +++ b/BossMod/Modules/Shadowbringers/Dungeon/D01Holminster/D013Philia.cs @@ -210,7 +210,7 @@ class CatONineTails(BossModule module) : Components.GenericRotatingAOE(module) public override void OnCastStarted(Actor caster, ActorCastInfo spell) { if (spell.Action.ID == (uint)AID.FierceBeatingRotationVisual) - Sequences.Add(new(_shape, spell.LocXZ, spell.Rotation + 180f.Degrees(), -45f.Degrees(), Module.CastFinishAt(spell), 2, 8)); + Sequences.Add(new(_shape, spell.LocXZ, spell.Rotation + 180f.Degrees(), -45f.Degrees(), Module.CastFinishAt(spell), 2f, 8)); } public override void OnCastFinished(Actor caster, ActorCastInfo spell) diff --git a/BossMod/Modules/Shadowbringers/Dungeon/D04MalikahsWell/D042AmphibiousTalos.cs b/BossMod/Modules/Shadowbringers/Dungeon/D04MalikahsWell/D042AmphibiousTalos.cs index f36d460a26..0a0d6b712f 100644 --- a/BossMod/Modules/Shadowbringers/Dungeon/D04MalikahsWell/D042AmphibiousTalos.cs +++ b/BossMod/Modules/Shadowbringers/Dungeon/D04MalikahsWell/D042AmphibiousTalos.cs @@ -54,9 +54,8 @@ public override void OnCastStarted(Actor caster, ActorCastInfo spell) { _rotation = spell.Rotation; _activation = Module.CastFinishAt(spell); - } - if (_rotation != default) InitIfReady(caster); + } } public override void OnEventCast(Actor caster, ActorCastEvent spell) @@ -80,7 +79,7 @@ class Efface(BossModule module) : Components.SingleTargetCast(module, ActionID.M class HighPressureRaidwide(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.HighPressure)); class HighPressureKnockback(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.HighPressure), 20f, stopAtWall: true); class GeyserEruption(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.GeyserEruption), 8f); -class Geysers(BossModule module) : Components.PersistentVoidzone(module, 4, GetVoidzones) +class Geysers(BossModule module) : Components.PersistentVoidzone(module, 4f, GetVoidzones) { private static Actor[] GetVoidzones(BossModule module) { diff --git a/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeNormal/DRN2Dahu/FirebreatheRotating.cs b/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeNormal/DRN2Dahu/FirebreatheRotating.cs index 5ee730b1b8..d573a4bb7f 100644 --- a/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeNormal/DRN2Dahu/FirebreatheRotating.cs +++ b/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeNormal/DRN2Dahu/FirebreatheRotating.cs @@ -4,26 +4,26 @@ class FirebreatheRotating(BossModule module) : Components.GenericRotatingAOE(mod { private Angle _increment; - private static readonly AOEShapeCone _shape = new(60, 45.Degrees()); + private static readonly AOEShapeCone _shape = new(60f, 45f.Degrees()); public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.FirebreatheRotating) - Sequences.Add(new(_shape, spell.LocXZ, spell.Rotation, _increment, Module.CastFinishAt(spell, 0.7f), 2, 5)); + if (spell.Action.ID == (uint)AID.FirebreatheRotating) + Sequences.Add(new(_shape, spell.LocXZ, spell.Rotation, _increment, Module.CastFinishAt(spell, 0.7f), 2f, 5)); } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if ((AID)spell.Action.ID == AID.FirebreatheRotatingAOE && Sequences.Count > 0) + if (spell.Action.ID == (uint)AID.FirebreatheRotatingAOE) AdvanceSequence(0, WorldState.CurrentTime); } public override void OnEventIcon(Actor actor, uint iconID, ulong targetID) { - var angle = (IconID)iconID switch + var angle = iconID switch { - IconID.FirebreatheCW => -90.Degrees(), - IconID.FirebreatheCCW => 90.Degrees(), + (uint)IconID.FirebreatheCW => -90f.Degrees(), + (uint)IconID.FirebreatheCCW => 90f.Degrees(), _ => default }; if (angle != default) diff --git a/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/DRS2.cs b/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/DRS2.cs index c2a12791eb..7240a5fcc6 100644 --- a/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/DRS2.cs +++ b/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/DRS2.cs @@ -1,8 +1,8 @@ namespace BossMod.Shadowbringers.Foray.DelubrumReginae.DRS2StygimolochWarrior; -class ViciousSwipe(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.ViciousSwipe), 15); -class CrazedRampage(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.CrazedRampage), 13); +class ViciousSwipe(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.ViciousSwipe), 15f); +class CrazedRampage(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.CrazedRampage), 13f); class Coerce(BossModule module) : Components.StatusDrivenForcedMarch(module, 4, (uint)SID.ForwardMarch, (uint)SID.AboutFace, (uint)SID.LeftFace, (uint)SID.RightFace); [ModuleInfo(BossModuleInfo.Maturity.Verified, GroupType = BossModuleInfo.GroupType.CFC, GroupID = 761, NameID = 9754, PlanLevel = 80)] -public class DRS2(WorldState ws, Actor primary) : BossModule(ws, primary, new(-160, 78), new ArenaBoundsSquare(17.5f)); +public class DRS2(WorldState ws, Actor primary) : BossModule(ws, primary, new(-160f, 78f), new ArenaBoundsSquare(17.5f)); diff --git a/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/Entrapment.cs b/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/Entrapment.cs index b0ec7ad166..4ee5917d0f 100644 --- a/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/Entrapment.cs +++ b/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/Entrapment.cs @@ -6,7 +6,7 @@ class EntrapmentAttract(BossModule module) : Components.Knockback(module, Action public override IEnumerable Sources(int slot, Actor actor) { - yield return new(new(Arena.Center.X, Arena.Center.Z + Module.Bounds.Radius), 60, _activation, Kind: Kind.TowardsOrigin); + yield return new(new(Arena.Center.X, Arena.Center.Z + Module.Bounds.Radius), 60f, _activation, Kind: Kind.TowardsOrigin); } public override void OnCastStarted(Actor caster, ActorCastInfo spell) @@ -58,7 +58,7 @@ public override void Update() if (player != null) for (var z = 0; z < 7; ++z) for (var x = 0; x < 7; ++x) - if (player.Position.InCircle(Module.Center + CellOffset(x, z), 10)) + if (player.Position.InCircle(Arena.Center + CellOffset(x, z), 10f)) _uncovered.Set(IndexFromCell(x, z)); // remove all patterns that have difference with current state in uncovered areas @@ -248,6 +248,6 @@ public override void OnCastStarted(Actor caster, ActorCastInfo spell) } } -class LethalBlow(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.LethalBlow), new AOEShapeRect(44, 24)); +class LethalBlow(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.LethalBlow), new AOEShapeRect(44f, 24f)); class LeapingSpark(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.LeapingSparkAOE)); -class Devour(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Devour), new AOEShapeCone(6, 60.Degrees())); +class Devour(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Devour), new AOEShapeCone(6f, 60f.Degrees())); diff --git a/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/FocusedTremor.cs b/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/FocusedTremor.cs index fbf9bb5ffc..78155998bd 100644 --- a/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/FocusedTremor.cs +++ b/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS2StygimolochWarrior/FocusedTremor.cs @@ -1,12 +1,12 @@ namespace BossMod.Shadowbringers.Foray.DelubrumReginae.DRS2StygimolochWarrior; -class FocusedTremorLarge(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.FocusedTremorAOELarge), new AOEShapeRect(10, 10, 10), 2); -class ForcefulStrike(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.ForcefulStrike), new AOEShapeRect(44, 24)); +class FocusedTremorLarge(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.FocusedTremorAOELarge), new AOEShapeRect(20f, 10f), 2); +class ForcefulStrike(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.ForcefulStrike), new AOEShapeRect(44f, 24f)); // combined with flailing strike, first bait should be into first square class FocusedTremorSmall : Components.SimpleAOEs { - public FocusedTremorSmall(BossModule module) : base(module, ActionID.MakeSpell(AID.FocusedTremorAOESmall), new AOEShapeRect(5, 5, 5), 1) + public FocusedTremorSmall(BossModule module) : base(module, ActionID.MakeSpell(AID.FocusedTremorAOESmall), new AOEShapeRect(10f, 5f), 1) { Color = Colors.SafeFromAOE; Risky = false; @@ -20,23 +20,23 @@ public void Activate() } } -class FlailingStrikeBait(BossModule module) : Components.BaitAwayTethers(module, new AOEShapeCone(40, 30.Degrees()), (uint)TetherID.FlailingStrike); +class FlailingStrikeBait(BossModule module) : Components.BaitAwayTethers(module, new AOEShapeCone(40f, 30f.Degrees()), (uint)TetherID.FlailingStrike); class FlailingStrike(BossModule module) : Components.GenericRotatingAOE(module) { - private static readonly AOEShapeCone _shape = new(60, 30.Degrees()); + private static readonly AOEShapeCone _shape = new(60f, 30f.Degrees()); public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.FlailingStrikeFirst) + if (spell.Action.ID == (uint)AID.FlailingStrikeFirst) { - Sequences.Add(new(_shape, caster.Position, spell.Rotation, 60.Degrees(), Module.CastFinishAt(spell), 1.6f, 6, 3)); + Sequences.Add(new(_shape, spell.LocXZ, spell.Rotation, 60f.Degrees(), Module.CastFinishAt(spell), 1.6f, 6, 3)); } } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if ((AID)spell.Action.ID == AID.FlailingStrikeRest && Sequences.Count > 0) + if (spell.Action.ID == (uint)AID.FlailingStrikeRest) { AdvanceSequence(0, WorldState.CurrentTime); } diff --git a/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS3Dahu/FirebreatheRotating.cs b/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS3Dahu/FirebreatheRotating.cs index 94b4b7b10a..73dcf6219a 100644 --- a/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS3Dahu/FirebreatheRotating.cs +++ b/BossMod/Modules/Shadowbringers/Foray/DelubrumReginaeSavage/DRS3Dahu/FirebreatheRotating.cs @@ -4,19 +4,19 @@ class FirebreatheRotating(BossModule module) : Components.GenericRotatingAOE(mod { private Angle _increment; - private static readonly AOEShapeCone _shape = new(60, 45.Degrees()); + private static readonly AOEShapeCone _shape = new(60f, 45f.Degrees()); public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.FirebreatheRotating) + if (spell.Action.ID == (uint)AID.FirebreatheRotating) { - Sequences.Add(new(_shape, caster.Position, spell.Rotation, _increment, Module.CastFinishAt(spell, 0.7f), 2, 5)); + Sequences.Add(new(_shape, caster.Position, spell.Rotation, _increment, Module.CastFinishAt(spell, 0.7f), 2f, 5)); } } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if ((AID)spell.Action.ID == AID.FirebreatheRotatingAOE && Sequences.Count > 0) + if (spell.Action.ID == (uint)AID.FirebreatheRotatingAOE) { AdvanceSequence(0, WorldState.CurrentTime); } @@ -24,10 +24,10 @@ public override void OnEventCast(Actor caster, ActorCastEvent spell) public override void OnEventIcon(Actor actor, uint iconID, ulong targetID) { - var angle = (IconID)iconID switch + var angle = iconID switch { - IconID.FirebreatheCW => -90.Degrees(), - IconID.FirebreatheCCW => 90.Degrees(), + (uint)IconID.FirebreatheCW => -90f.Degrees(), + (uint)IconID.FirebreatheCCW => 90f.Degrees(), _ => default }; if (angle != default) diff --git a/BossMod/Modules/Shadowbringers/Hunt/RankA/Sugaar.cs b/BossMod/Modules/Shadowbringers/Hunt/RankA/Sugaar.cs index 78d4d482eb..b2da9ea18a 100644 --- a/BossMod/Modules/Shadowbringers/Hunt/RankA/Sugaar.cs +++ b/BossMod/Modules/Shadowbringers/Hunt/RankA/Sugaar.cs @@ -20,59 +20,70 @@ public enum AID : uint TailSnapRotationAOE = 18099 // Boss->self (behind), 0.5 cast, range 18, 120 degree cone } -class BodySlam(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.BodySlam), 11); -class NumbingNoise(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.NumbingNoise), new AOEShapeCone(13, 60.Degrees())); -class TailSnap(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.TailSnap), new AOEShapeCone(18, 60.Degrees())); +class BodySlam(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.BodySlam), 11f); +class NumbingNoise(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.NumbingNoise), NumbingNoiseTailSnapRotating.ShapeNumbingNoise); +class TailSnap(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.TailSnap), NumbingNoiseTailSnapRotating.ShapeTailSnap); class NumbingNoiseTailSnapRotating(BossModule module) : Components.GenericRotatingAOE(module) { - private static readonly AOEShapeCone _shapeNumbingNoise = new(13, 60.Degrees()); - private static readonly AOEShapeCone _shapeTailSnap = new(18, 60.Degrees()); + public static readonly AOEShapeCone ShapeNumbingNoise = new(13f, 60f.Degrees()); + public static readonly AOEShapeCone ShapeTailSnap = new(18f, 60f.Degrees()); public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - switch ((AID)spell.Action.ID) + switch (spell.Action.ID) { - case AID.NumbingNoiseRotation: // NN always seems to go CCW - Sequences.Add(new(_shapeNumbingNoise, spell.LocXZ, spell.Rotation, 120.Degrees(), Module.CastFinishAt(spell, 1.1f), 2.7f, 3)); + case (uint)AID.NumbingNoiseRotation: // NN always seems to go CCW + AddSequence(ShapeNumbingNoise, default, 120f.Degrees()); break; - case AID.TailSnapRotation: // TS always seems to go CW - Sequences.Add(new(_shapeTailSnap, spell.LocXZ, spell.Rotation + 180.Degrees(), -120.Degrees(), Module.CastFinishAt(spell, 1.1f), 2.7f, 3)); + case (uint)AID.TailSnapRotation: // TS always seems to go CW + AddSequence(ShapeTailSnap, 180f.Degrees(), -120f.Degrees()); break; } + void AddSequence(AOEShapeCone shape, Angle offset, Angle increment) => Sequences.Add(new(shape, spell.LocXZ, spell.Rotation + offset, increment, Module.CastFinishAt(spell, 1.1f), 2.7f, 3)); } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID is AID.NumbingNoiseRotationAOE or AID.TailSnapRotationAOE) + if (spell.Action.ID is (uint)AID.NumbingNoiseRotationAOE or (uint)AID.TailSnapRotationAOE) AdvanceSequence(0, WorldState.CurrentTime); } } class NumbingNoiseTailSnapAttract(BossModule module) : Components.Knockback(module) { - private readonly NumbingNoiseTailSnapRotating? _rotating = module.FindComponent(); + private readonly NumbingNoiseTailSnapRotating _rotating = module.FindComponent()!; private DateTime _activation; - private static readonly AOEShapeCircle _shape = new(30); + private static readonly AOEShapeCircle _shape = new(30f); public override IEnumerable Sources(int slot, Actor actor) { if (_activation != default) - yield return new(Module.PrimaryActor.Position, 25, _activation, _shape, default, Kind.TowardsOrigin, Module.PrimaryActor.HitboxRadius + actor.HitboxRadius); + return [new(Module.PrimaryActor.Position, 25f, _activation, _shape, default, Kind.TowardsOrigin, Module.PrimaryActor.HitboxRadius + actor.HitboxRadius)]; + else + return []; } - public override bool DestinationUnsafe(int slot, Actor actor, WPos pos) => _rotating?.ActiveAOEs(slot, actor).Any(aoe => aoe.Check(pos)) ?? false; + public override bool DestinationUnsafe(int slot, Actor actor, WPos pos) + { + foreach (var aoe in _rotating.ActiveAOEs(slot, actor)) + { + if (aoe.Check(pos)) + return true; + } + return false; + } public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID is AID.NumbingNoiseRotation or AID.TailSnapRotation) + if (spell.Action.ID is (uint)AID.NumbingNoiseRotation or (uint)AID.TailSnapRotation) _activation = Module.CastFinishAt(spell); } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID is AID.NumbingNoiseRotation or AID.TailSnapRotation) + if (spell.Action.ID is (uint)AID.NumbingNoiseRotation or (uint)AID.TailSnapRotation) _activation = default; } }