diff --git a/BossMod/Data/ActorEnumeration.cs b/BossMod/Data/ActorEnumeration.cs index 4ea3b6ce78..79dfe54599 100644 --- a/BossMod/Data/ActorEnumeration.cs +++ b/BossMod/Data/ActorEnumeration.cs @@ -136,18 +136,39 @@ public static IEnumerable Tethered(this IEnumerable range, ID // sort range by distance from point public static IEnumerable SortedByRange(this IEnumerable range, WPos origin) { - return range - .Select(actor => (actor, (actor.Position - origin).LengthSq())) - .OrderBy(actorDist => actorDist.Item2) - .Select(actorDist => actorDist.actor); + var actors = new List<(Actor actor, float distanceSq)>(); + + foreach (var a in range) + { + var distanceSq = (a.Position - origin).LengthSq(); + actors.Add((a, distanceSq)); + } + + actors.Sort((a, b) => a.distanceSq.CompareTo(b.distanceSq)); + + for (var i = 0; i < actors.Count; ++i) + { + yield return actors[i].actor; + } } public static IEnumerable<(int, Actor)> SortedByRange(this IEnumerable<(int, Actor)> range, WPos origin) { - return range - .Select(indexPlayer => (indexPlayer.Item1, indexPlayer.Item2, (indexPlayer.Item2.Position - origin).LengthSq())) - .OrderBy(indexPlayerDist => indexPlayerDist.Item3) - .Select(indexPlayerDist => (indexPlayerDist.Item1, indexPlayerDist.Item2)); + var actors = new List<(int index, Actor actor, float distanceSq)>(); + + foreach (var a in range) + { + var distanceSq = (a.Item2.Position - origin).LengthSq(); + actors.Add((a.Item1, a.Item2, distanceSq)); + } + + actors.Sort((a, b) => a.distanceSq.CompareTo(b.distanceSq)); + + for (var i = 0; i < actors.Count; ++i) + { + var actor = actors[i]; + yield return (actor.index, actor.actor); + } } // find closest actor to point diff --git a/BossMod/Framework/Utils.cs b/BossMod/Framework/Utils.cs index 52f41b5800..585dc26ce6 100644 --- a/BossMod/Framework/Utils.cs +++ b/BossMod/Framework/Utils.cs @@ -176,10 +176,9 @@ public static int UpperBound(this SortedList list, T public static void SortByReverse(this TValue[] arr, Func proj) where TKey : notnull, IComparable => Array.Sort(arr, (l, r) => proj(r).CompareTo(proj(l))); // get enumerable of zero or one elements, depending on whether argument is null - public static IEnumerable ZeroOrOne(T? value) where T : struct + public static List ZeroOrOne(T? value) where T : struct { - if (value != null) - yield return value.Value; + return value != null ? [value.Value] : []; } // enumerate pairs of neighbouring elements diff --git a/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/DiffusiveForceParticleBeam.cs b/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/DiffusiveForceParticleBeam.cs index 2735f5b39e..3da2d39ed0 100644 --- a/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/DiffusiveForceParticleBeam.cs +++ b/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/DiffusiveForceParticleBeam.cs @@ -12,7 +12,7 @@ class DiffusiveForceParticleBeam(BossModule module) : Components.UniformStackSpr public override void OnCastStarted(Actor caster, ActorCastInfo spell) { if ((AID)spell.Action.ID == AID.DiffusiveForceParticleBeam) - AddSpreads(Raid.WithoutSlot(true, true, true), Module.CastFinishAt(spell, 0.7f)); + AddSpreads(Raid.WithoutSlot(true, false, true), Module.CastFinishAt(spell, 0.7f)); } public override void OnEventCast(Actor caster, ActorCastEvent spell) diff --git a/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/EnaeroEndeath.cs b/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/EnaeroEndeath.cs index a20b6214a4..455cd74c9b 100644 --- a/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/EnaeroEndeath.cs +++ b/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/EnaeroEndeath.cs @@ -136,7 +136,7 @@ class EndeathAOE(BossModule module) : Components.GenericAOEs(module) private static readonly AOEShapeCircle _shapeOut = new(6); private static readonly AOEShapeDonut _shapeIn = new(6, 40); - public override IEnumerable ActiveAOEs(int slot, Actor actor) => _aoes.Take(1); + public override IEnumerable ActiveAOEs(int slot, Actor actor) => _aoes.Count != 0 ? [_aoes[0]] : []; public override void OnCastStarted(Actor caster, ActorCastInfo spell) { diff --git a/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/ParticleConcentration.cs b/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/ParticleConcentration.cs index 9ec6f53e61..02f96a7647 100644 --- a/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/ParticleConcentration.cs +++ b/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/ParticleConcentration.cs @@ -52,8 +52,12 @@ class ParticleConcentration(BossModule module) : Components.GenericTowers(module public void ShowOuterTowers() { - var activation = Towers.Count > 0 ? Towers[0].Activation : default; - Towers.AddRange(_outerTowers.Select(p => new Tower(p, 3, 3, 3, _innerPlayers, activation))); + var activation = Towers.Count != 0 ? Towers[0].Activation : default; + for (var i = 0; i < _outerTowers.Count; ++i) + { + var newTower = new Tower(_outerTowers[i], 3, 3, 3, _innerPlayers, activation); + Towers.Add(newTower); + } } public override void OnStatusGain(Actor actor, ActorStatus status) @@ -133,9 +137,9 @@ public override void OnEventEnvControl(byte index, uint state) }; if (count == 3) - _outerTowers.Add(Module.Center + offset); + _outerTowers.Add(Arena.Center + offset); else if (count > 0) - Towers.Add(new(Module.Center + offset, 3, count, count, _outerPlayers, WorldState.FutureTime(10.1f))); + Towers.Add(new(Arena.Center + offset, 3, count, count, _outerPlayers, WorldState.FutureTime(10.1f))); } public override void OnEventCast(Actor caster, ActorCastEvent spell) @@ -143,8 +147,15 @@ public override void OnEventCast(Actor caster, ActorCastEvent spell) if ((AID)spell.Action.ID is AID.ParticleBeam1 or AID.ParticleBeam2 or AID.ParticleBeam3) { ++NumCasts; - if (Towers.RemoveAll(t => t.Position == caster.Position) != 1) - ReportError($"Unexpected tower position @ {caster.Position}"); + for (var i = 0; i < Towers.Count; ++i) + { + var tower = Towers[i]; + if (tower.Position == caster.Position) + { + Towers.Remove(tower); + break; + } + } } } } diff --git a/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/ThirdArtOfDarkness.cs b/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/ThirdArtOfDarkness.cs index b7313a0c0a..a1c733a685 100644 --- a/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/ThirdArtOfDarkness.cs +++ b/BossMod/Modules/Dawntrail/Chaotic/Ch01CloudOfDarkness/ThirdArtOfDarkness.cs @@ -28,11 +28,35 @@ public override void AddHints(int slot, Actor actor, TextHints hints) { if (PlatformPlayers[slot]) { - var playerSide = actor.Position.X - Module.Center.X; - var (a, m) = Mechanics.FirstOrDefault(kv => (kv.Key.Position.X - Module.Center.X) * playerSide > 0); - if (a != null && m.Count > 0) - hints.Add($"Order: {string.Join(" > ", m.Select(m => m.mechanic))}", false); + var playerSide = actor.Position.X - Arena.Center.X; + + Actor? matchingActor = null; + List<(Mechanic mechanic, DateTime activation)>? matchingMechanics = null; + + foreach (var kv in Mechanics) + { + var actorSide = kv.Key.Position.X - Arena.Center.X; + if (actorSide * playerSide > 0) + { + matchingActor = kv.Key; + matchingMechanics = kv.Value; + break; + } + } + + if (matchingActor != null && matchingMechanics != null && matchingMechanics.Count > 0) + { + var order = ""; + for (var i = 0; i < matchingMechanics.Count; ++i) + { + if (i > 0) + order += " > "; + order += matchingMechanics[i].mechanic.ToString(); + } + hints.Add($"Order: {order}", false); + } } + base.AddHints(slot, actor, hints); } @@ -101,7 +125,7 @@ public override void Update() if (_main != null) foreach (var (a, m) in _main.Mechanics) if (m.Count > 0 && m[0].mechanic == ThirdArtOfDarknessCleave.Mechanic.Spread) - foreach (var p in Raid.WithoutSlot(false, true, true).SortedByRange(a.Position).Take(6)) + foreach (var p in Raid.WithoutSlot(false, false, true).SortedByRange(a.Position).Take(6)) CurrentBaits.Add(new(a, p, _shape, m[0].activation)); } } @@ -116,7 +140,7 @@ public override void Update() if (_main != null) foreach (var (a, m) in _main.Mechanics) if (m.Count > 0 && m[0].mechanic == ThirdArtOfDarknessCleave.Mechanic.Stack) - foreach (var p in Raid.WithoutSlot(false, true, true).SortedByRange(a.Position).Take(3)) + foreach (var p in Raid.WithoutSlot(false, false, true).SortedByRange(a.Position).Take(3)) AddStack(p, m[0].activation, ~_main.PlatformPlayers); base.Update(); } diff --git a/BossMod/Modules/Endwalker/Dungeon/D11LapisManalis/D112GalateaMagna.cs b/BossMod/Modules/Endwalker/Dungeon/D11LapisManalis/D112GalateaMagna.cs index c875863f74..2efbe91848 100644 --- a/BossMod/Modules/Endwalker/Dungeon/D11LapisManalis/D112GalateaMagna.cs +++ b/BossMod/Modules/Endwalker/Dungeon/D11LapisManalis/D112GalateaMagna.cs @@ -36,7 +36,7 @@ public enum IconID : uint Icon1 = 336, // Helper2 Icon2 = 337, // Helper2 Icon3 = 338, // Helper2 - Icon4 = 339, // Helper2 + Icon4 = 339 // Helper2 } public enum SID : uint