From 53917132a760095393579ea7a30a2d8d948b8f04 Mon Sep 17 00:00:00 2001 From: CarnifexOptimus <156172553+CarnifexOptimus@users.noreply.github.com> Date: Mon, 28 Oct 2024 02:11:28 +0100 Subject: [PATCH] some arena fixes --- .../Dungeon/D02WorqorZormor/D023Gurfurlur.cs | 12 ++-- .../Dungeon/D03SkydeepCenote/D033Maulskull.cs | 8 +++ .../T03QueenEternal/DownburstPowerfulGust.cs | 8 ++- .../T03QueenEternal/WaltzOfTheRegalia.cs | 2 +- .../D13CastrumMeridianum/D131BlackEft.cs | 61 +++++++++++++---- .../D132MagitekVanguardF1.cs | 11 ++-- .../Dungeon/D13CastrumMeridianum/D133Livia.cs | 12 ++-- .../Dungeon/D14Praetorium/D141Colossus.cs | 17 +++-- .../Dungeon/D14Praetorium/D142Nero.cs | 65 +++++++++++++++++-- .../Dungeon/D14Praetorium/D143Gaius.cs | 46 +++++++++---- BossMod/Replay/Analysis/ArenaBounds.cs | 39 +++++++---- 11 files changed, 217 insertions(+), 64 deletions(-) diff --git a/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D023Gurfurlur.cs b/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D023Gurfurlur.cs index a34bb2772e..df764da787 100644 --- a/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D023Gurfurlur.cs +++ b/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D023Gurfurlur.cs @@ -79,7 +79,6 @@ public override void AddGlobalHints(GlobalHints hints) public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { - var orb = ActiveOrbs.FirstOrDefault(); var orbs = new List>(); if (ActiveOrbs.Any()) { @@ -130,15 +129,17 @@ public override IEnumerable ActiveAOEs(int slot, Actor actor) var source = Module.FindComponent()!.Sources(slot, actor).FirstOrDefault(); if (source == default) { + var count1 = _aoesWave1.Count; + var count2 = _aoesWave2.Count; if (_aoesWave1.Count > 0) foreach (var a in _aoesWave1) yield return a with { Color = Colors.Danger }; if (_aoesWave2.Count > 0) foreach (var a in _aoesWave2) - yield return a with { Color = _aoesWave1.Count > 0 ? Colors.AOE : Colors.Danger, Risky = _aoesWave1.Count == 0 }; + yield return a with { Color = count1 > 0 ? Colors.AOE : Colors.Danger, Risky = count1 == 0 }; if (_aoesWave1.Count == 0 && _aoesWave3.Count > 0) foreach (var a in _aoesWave3) - yield return a with { Color = _aoesWave2.Count > 0 ? Colors.AOE : Colors.Danger, Risky = _aoesWave2.Count == 0 }; + yield return a with { Color = count2 > 0 ? Colors.AOE : Colors.Danger, Risky = count2 == 0 }; } else if ((_aoesWave3.Count > 0 || _aoesWave1.Count > 0) && source != default) yield return new(safespot, source.Origin, source.Direction, source.Activation, Colors.SafeFromAOE); @@ -220,6 +221,7 @@ private enum Pattern { None, EWEW, WEWE } private static readonly Angle a165 = 165.Degrees(); private static readonly Angle a105 = 105.Degrees(); private static readonly Angle a75 = 75.Degrees(); + private static readonly WDir offset = new(0, 1); public override void OnActorCreated(Actor actor) { @@ -246,8 +248,8 @@ public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignme if (timespan <= 3) { var patternWEWE = CurrentPattern == Pattern.WEWE; - forbidden.Add(ShapeDistance.InvertedCone(sources.Origin - (patternWEWE ? new WDir(0, 1) : new(0, 1)), 5, patternWEWE ? a15 : -a15, a15)); - forbidden.Add(ShapeDistance.InvertedCone(sources.Origin - (patternWEWE ? new WDir(0, -1) : new(0, -1)), 5, patternWEWE ? -a165 : a165, a15)); + forbidden.Add(ShapeDistance.InvertedCone(sources.Origin - offset, 5, patternWEWE ? a15 : -a15, a15)); + forbidden.Add(ShapeDistance.InvertedCone(sources.Origin + offset, 5, patternWEWE ? -a165 : a165, a15)); forbidden.Add(ShapeDistance.InvertedCone(sources.Origin, 5, patternWEWE ? a105 : -a105, a15)); forbidden.Add(ShapeDistance.InvertedCone(sources.Origin, 5, patternWEWE ? -a75 : a75, a15)); } diff --git a/BossMod/Modules/Dawntrail/Dungeon/D03SkydeepCenote/D033Maulskull.cs b/BossMod/Modules/Dawntrail/Dungeon/D03SkydeepCenote/D033Maulskull.cs index 7853f79c8b..6a65a868ed 100644 --- a/BossMod/Modules/Dawntrail/Dungeon/D03SkydeepCenote/D033Maulskull.cs +++ b/BossMod/Modules/Dawntrail/Dungeon/D03SkydeepCenote/D033Maulskull.cs @@ -81,6 +81,7 @@ class Stonecarver(BossModule module) : Components.GenericAOEs(module) private readonly List _aoes = []; private static readonly AOEShapeRect rect = new(40, 10); private static readonly HashSet aids = [AID.Stonecarver1, AID.Stonecarver2, AID.Stonecarver3, AID.Stonecarver4]; + private static readonly WDir offset = new(0, 20); public override IEnumerable ActiveAOEs(int slot, Actor actor) { @@ -104,6 +105,13 @@ public override void OnCastFinished(Actor caster, ActorCastInfo spell) if (_aoes.Count > 0 && aids.Contains((AID)spell.Action.ID)) _aoes.RemoveAt(0); } + + public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + base.AddAIHints(slot, actor, assignment, hints); + if (_aoes.Count > 0) + hints.AddForbiddenZone(ShapeDistance.InvertedRect(Arena.Center + offset, Arena.Center - offset, 2), _aoes[0].Activation); + } } class Shatter(BossModule module) : Components.GenericAOEs(module) diff --git a/BossMod/Modules/Dawntrail/Trial/T03QueenEternal/DownburstPowerfulGust.cs b/BossMod/Modules/Dawntrail/Trial/T03QueenEternal/DownburstPowerfulGust.cs index 61354de4a7..e972ba91da 100644 --- a/BossMod/Modules/Dawntrail/Trial/T03QueenEternal/DownburstPowerfulGust.cs +++ b/BossMod/Modules/Dawntrail/Trial/T03QueenEternal/DownburstPowerfulGust.cs @@ -27,7 +27,13 @@ public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignme hints.AddForbiddenZone(ShapeDistance.InvertedCone(source.Origin, 5, source.Direction + offset, 10.Degrees()), source.Activation); } else - hints.AddForbiddenZone(ShapeDistance.InvertedCross(source.Origin, source.Direction, 5, 0.5f), source.Activation); + { + var forbidden = new List>(); + foreach (var a in Helpers.AnglesCardinals) + forbidden.Add(ShapeDistance.InvertedCone(source.Origin, 5, source.Direction + a, 10.Degrees())); + if (forbidden.Count > 0) + hints.AddForbiddenZone(p => forbidden.Select(f => f(p)).Max(), source.Activation); + } } } } diff --git a/BossMod/Modules/Dawntrail/Trial/T03QueenEternal/WaltzOfTheRegalia.cs b/BossMod/Modules/Dawntrail/Trial/T03QueenEternal/WaltzOfTheRegalia.cs index 8f02c426e1..7110500861 100644 --- a/BossMod/Modules/Dawntrail/Trial/T03QueenEternal/WaltzOfTheRegalia.cs +++ b/BossMod/Modules/Dawntrail/Trial/T03QueenEternal/WaltzOfTheRegalia.cs @@ -36,4 +36,4 @@ public override void OnActorDestroyed(Actor actor) } } -class WaltzOfTheRegalia(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.WaltzOfTheRegalia), new AOEShapeRect(7, 2, 7)); \ No newline at end of file +class WaltzOfTheRegalia(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.WaltzOfTheRegalia), new AOEShapeRect(7, 2, 7)); diff --git a/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D131BlackEft.cs b/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D131BlackEft.cs index 1aa257d918..5900df3b6c 100644 --- a/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D131BlackEft.cs +++ b/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D131BlackEft.cs @@ -2,24 +2,28 @@ public enum OID : uint { - Boss = 0x38CA, // x1 - Helper = 0x233C, // x3 - AddSignifer = 0x38CC, // x2, and more spawn during fight - AddLaquearius = 0x38CB, // x2, and more spawn during fight - AddMagitekColossus = 0x394C, // spawn during fight + Boss = 0x38CA, // R3.0 + EigthCohortSignifer = 0x38CC, // R0.5, x2, and more spawn during fight + EigthCohortLaquearius = 0x38CB, // R0.5, x2, and more spawn during fight + MagitekColossus = 0x394C, // R2.5, spawn during fight + Helper = 0x233C } public enum AID : uint { + AutoAttack = 870, // EigthCohortLaquearius/MagitekColossus->player, no cast, single-target + + Fire = 966, // EigthCohortSignifer->player, 1.0s cast, single-target + Fortis = 28777, // EigthCohortLaquearius/EigthCohortSignifer->self, 6.0s cast, single-target PhotonStream = 28776, // Boss->player, no cast, single-target, auto-attack - IncendiarySupport = 29268, // Boss->self, 3.0s cast, single-target, visual - IncendiarySupportAOE = 29269, // Helper->self, no cast, range 60 circle, raidwide + IncendiarySupportVisual = 29268, // Boss->self, 3.0s cast, single-target, visual + IncendiarySupport = 29269, // Helper->self, no cast, range 60 circle, raidwide HighPoweredMagitekRay = 28773, // Boss->self, 5.0s cast, range 60 width 4 rect aoe RequestAssistance = 28774, // Boss->self, 4.0s cast, single-target, summon adds - MagitekCannon = 28775, // Boss->location, 3.0s cast, range 6 circle aoe + MagitekCannon = 28775 // Boss->location, 3.0s cast, range 6 circle aoe } -class IncendiarySupport(BossModule module) : Components.CastHint(module, ActionID.MakeSpell(AID.IncendiarySupport), "Raidwide x3"); +class IncendiarySupport(BossModule module) : Components.RaidwideCastDelay(module, ActionID.MakeSpell(AID.IncendiarySupportVisual), ActionID.MakeSpell(AID.IncendiarySupport), 1, "Raidwide x3"); class HighPoweredMagitekRay(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.HighPoweredMagitekRay), new AOEShapeRect(50, 2)); class MagitekCannon(BossModule module) : Components.LocationTargetedAOEs(module, ActionID.MakeSpell(AID.MagitekCannon), 6); @@ -39,5 +43,40 @@ public D131BlackEftStates(BossModule module) : base(module) // first wave = 3x signifier + 3x laquearius // second wave = 2x colossus // third wave = 2x colossus + 2x signifier + 2x laquearius -[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 15, NameID = 557)] -public class D131BlackEft(WorldState ws, Actor primary) : BossModule(ws, primary, new(10, -40), new ArenaBoundsSquare(20)); +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn, Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 15, NameID = 557)] +public class D131BlackEft(WorldState ws, Actor primary) : BossModule(ws, primary, arena.Center, arena) +{ + private static readonly WPos[] vertices = [new(12.14f, -73.48f), new(12.44f, -73), new(12.44f, -71.9f), new(12.74f, -71.3f), new(13.13f, -70.8f), + new(14.31f, -70.32f), new(14.92f, -70.35f), new(15.56f, -70.61f), new(16.13f, -70.92f), new(16.46f, -71.45f), + new(16.68f, -71.98f), new(16.68f, -72.5f), new(17.4f, -72.64f), new(18.91f, -72.52f), new(19.53f, -72.62f), + new(21.04f, -72.53f), new(21.62f, -72.63f), new(23.79f, -72.52f), new(24.31f, -72.74f), new(25.82f, -72.9f), + new(26.5f, -72.76f), new(26.9f, -71.49f), new(27.15f, -71.02f), new(30.92f, -68.56f), new(32.19f, -67.16f), + new(32.23f, -66.49f), new(32.15f, -65.2f), new(31.38f, -61.39f), new(31.59f, -51.28f), new(31.72f, -50.07f), + new(32.17f, -49.85f), new(32.84f, -49.87f), new(32.96f, -49.35f), new(33.1f, -43.09f), new(32.8f, -42.43f), + new(32.34f, -41.87f), new(32.26f, -41.19f), new(32.39f, -30.8f), new(32.34f, -30.14f), new(32.44f, -29.65f), + new(32.82f, -29.25f), new(34.14f, -29.04f), new(34.56f, -28.75f), new(34.51f, -26.78f), new(34.67f, -26.17f), + new(34.91f, -25.53f), new(35.3f, -25.1f), new(36.22f, -24.24f), new(36.7f, -23.91f), new(37.36f, -23.78f), + new(37.93f, -23.44f), new(39.51f, -19.31f), new(38.94f, -19.25f), new(38.45f, -18.85f), new(38.13f, -18.26f), + new(38.9f, -15.76f), new(39.17f, -15.22f), new(41.47f, -13.7f), new(39.97f, -10.11f), new(39.6f, -9.75f), + new(38.28f, -9.88f), new(37, -9.59f), new(36.52f, -9.32f), new(35.07f, -7.95f), new(34.68f, -7.49f), + new(34.85f, -5.75f), new(34.3f, -5.68f), new(33.65f, -5.66f), new(33.05f, -5.48f), new(32.34f, -5.33f), + new(31.71f, -5.34f), new(31.07f, -5.21f), new(30.46f, -4.98f), new(29.74f, -4.98f), new(29.21f, -5.43f), + new(28.76f, -5.9f), new(27.55f, -6.21f), new(26.91f, -6.13f), new(26.3f, -5.8f), new(25.81f, -5.45f), + new(25.52f, -4.82f), new(25.36f, -4.21f), new(25.58f, -2.94f), new(25.56f, -2.18f), new(14.1f, -0.16f), + new(13.75f, -0.74f), new(13.56f, -2.05f), new(13.21f, -2.58f), new(12.8f, -3.06f), new(12.15f, -3.27f), + new(11.54f, -3.55f), new(10.92f, -3.32f), new(9.78f, -2.59f), new(9.22f, -1.36f), new(8.57f, -1.1f), + new(7.87f, -1.1f), new(7.24f, -1.01f), new(6.62f, -0.76f), new(6.41f, -1.27f), new(6.58f, -1.92f), + new(7.01f, -2.45f), new(7.26f, -3.78f), new(6.97f, -4.3f), new(4.51f, -4.9f), new(3.83f, -5.02f), + new(3.41f, -4.73f), new(2.79f, -3.67f), new(2.47f, -3.23f), new(0.05f, -6.12f), new(-10.46f, -65.92f), + new(-10.32f, -66.6f), new(-9.43f, -69.1f), new(-9.18f, -69.62f), new(-7.8f, -68.49f), new(-7.31f, -68.23f), + new(-6.85f, -68.53f), new(-4.91f, -70.35f), new(-4.89f, -70.86f), new(-5.72f, -71.82f), new(-5.86f, -72.3f), + new(-5.22f, -72.55f), new(-4.3f, -72.65f), new(-3.72f, -72.47f), new(-3.82f, -71.92f), new(-3.07f, -70.9f), + new(-1.82f, -70.34f), new(-1.22f, -70.34f), new(0.02f, -70.85f), new(0.34f, -71.37f), new(0.61f, -71.94f), + new(0.61f, -73.48f), new(12.14f, -73.48f)]; + private static readonly ArenaBoundsComplex arena = new([new PolygonCustom(vertices)]); + + protected override void DrawEnemies(int pcSlot, Actor pc) + { + Arena.Actors(Enemies(OID.EigthCohortLaquearius).Concat([PrimaryActor]).Concat(Enemies(OID.EigthCohortSignifer)).Concat(Enemies(OID.MagitekColossus))); + } +} diff --git a/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D132MagitekVanguardF1.cs b/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D132MagitekVanguardF1.cs index 08ee6a32b7..a86e76b4b9 100644 --- a/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D132MagitekVanguardF1.cs +++ b/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D132MagitekVanguardF1.cs @@ -2,13 +2,14 @@ public enum OID : uint { - Boss = 0x38CD, // x1 - Helper = 0x233C, // x7 + Boss = 0x38CD, // R4.4 + Helper = 0x233C } public enum AID : uint { AutoAttack = 870, // Boss->player, no cast, single-target + ThermobaricStrike = 28778, // Boss->self, 4.0s cast, single-target, visual ThermobaricCharge = 28779, // Helper->self, 7.0s cast, range 60 circle aoe with ? falloff Hypercharge = 28780, // Boss->self, 4.1s cast, single-target, visual @@ -17,7 +18,7 @@ public enum AID : uint TargetedSupport = 28783, // Boss->self, 4.0s cast, single-target, visual TargetedSupportAOE = 28784, // Helper->self, 3.0s cast, range 5 circle aoe CermetDrill = 28785, // Boss->player, 5.0s cast, single-target tankbuster - Overcharge = 29146, // Boss->self, 3.0s cast, range 11 120-degree cone aoe + Overcharge = 29146 // Boss->self, 3.0s cast, range 11 120-degree cone aoe } class ThermobaricCharge(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.ThermobaricCharge), new AOEShapeCircle(20)); @@ -41,5 +42,5 @@ public D132MagitekVanguardF1States(BossModule module) : base(module) } } -[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 15, NameID = 2116)] -public class D132MagitekVanguardF1(WorldState ws, Actor primary) : BossModule(ws, primary, new(-13, 31), new ArenaBoundsRect(20, 20, 20.Degrees())); +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn, Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 15, NameID = 2116)] +public class D132MagitekVanguardF1(WorldState ws, Actor primary) : BossModule(ws, primary, new(-13, 31), new ArenaBoundsSquare(19.5f, 11.Degrees())); diff --git a/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D133Livia.cs b/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D133Livia.cs index e96a3e8338..5a917a7e13 100644 --- a/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D133Livia.cs +++ b/BossMod/Modules/RealmReborn/Dungeon/D13CastrumMeridianum/D133Livia.cs @@ -2,8 +2,8 @@ public enum OID : uint { - Boss = 0x38CE, // x1 - Helper = 0x233C, // x50 + Boss = 0x38CE, // R1.507 + Helper = 0x233C } public enum AID : uint @@ -215,5 +215,9 @@ public D133LiviaStates(BossModule module) : base(module) } } -[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 15, NameID = 2118)] -public class D133Livia(WorldState ws, Actor primary) : BossModule(ws, primary, new(-98, -33), new ArenaBoundsCircle(20)); +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn, Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 15, NameID = 2118)] +public class D133Livia(WorldState ws, Actor primary) : BossModule(ws, primary, arena.Center, arena) +{ + private static readonly ArenaBoundsComplex arena = new([new Polygon(new(-98, -33), 19.5f / MathF.Cos(MathF.PI / 36), 36)], + [new Rectangle(new(-78.187f, -36.886f), 20, 1.25f, 79.Degrees())]); +} diff --git a/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D141Colossus.cs b/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D141Colossus.cs index 49f6423e1b..e97581434c 100644 --- a/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D141Colossus.cs +++ b/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D141Colossus.cs @@ -2,13 +2,14 @@ public enum OID : uint { - Boss = 0x3872, // x1 - Helper = 0x233C, // x8 + Boss = 0x3872, // R3.5 + Helper = 0x233C } public enum AID : uint { AutoAttack = 870, // Boss->player, no cast, single-target + CeruleumVent = 28474, // Boss->self, 5.0s cast, raidwide Teleport = 28467, // Boss->location, no cast, single-target, teleport PrototypeLaserAlpha = 28468, // Boss->self, 5.0s cast, single-target, visual @@ -16,13 +17,13 @@ public enum AID : uint IronKissAlpha2 = 28470, // Helper->location, 9.0s cast, range 6 circle aoe (outer set) PrototypeLaserBeta = 28471, // Boss->self, 5.0s cast, single-target, visual IronKissBeta = 28472, // Helper->player, 5.0s cast, range 5 circle spread - GrandSword = 28473, // Boss->self, 5.0s cast, range 25 90-degree cone aoe + GrandSword = 28473 // Boss->self, 5.0s cast, range 25 90-degree cone aoe } class CeruleumVent(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.CeruleumVent)); class PrototypeLaserAlpha1(BossModule module) : Components.LocationTargetedAOEs(module, ActionID.MakeSpell(AID.IronKissAlpha1), 6); class PrototypeLaserAlpha2(BossModule module) : Components.LocationTargetedAOEs(module, ActionID.MakeSpell(AID.IronKissAlpha2), 6); -class PrototypeLaserBeta(BossModule module) : Components.SpreadFromCastTargets(module, ActionID.MakeSpell(AID.IronKissBeta), 5, false); +class PrototypeLaserBeta(BossModule module) : Components.SpreadFromCastTargets(module, ActionID.MakeSpell(AID.IronKissBeta), 5); class GrandSword(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.GrandSword), new AOEShapeCone(25, 45.Degrees())); class D141ColossusStates : StateMachineBuilder @@ -38,5 +39,9 @@ public D141ColossusStates(BossModule module) : base(module) } } -[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 16, NameID = 2134)] -public class D141Colossus(WorldState ws, Actor primary) : BossModule(ws, primary, new(192, 0), new ArenaBoundsCircle(15)); +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn, Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 16, NameID = 2134)] +public class D141Colossus(WorldState ws, Actor primary) : BossModule(ws, primary, arena.Center, arena) +{ + private static readonly ArenaBoundsComplex arena = new([new Polygon(new(192, 0), 14.5f / MathF.Cos(MathF.PI / 48), 48)], + [new Rectangle(new(207, 0), 20, 1.25f, 90.Degrees()), new Rectangle(new(177, 0), 20, 1.8f, 90.Degrees())]); +} diff --git a/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D142Nero.cs b/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D142Nero.cs index e56645dd95..ae118ca97d 100644 --- a/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D142Nero.cs +++ b/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D142Nero.cs @@ -2,14 +2,15 @@ public enum OID : uint { - Boss = 0x3873, // x1 - MagitekDeathClaw = 0x3874, // spawn during fight - Helper = 0x233C, // x8 + Boss = 0x3873, // R1.65 + MagitekDeathClaw = 0x3874, // R1.0 + Helper = 0x233 } public enum AID : uint { AutoAttack = 872, // Boss->player, no cast, single-target + IronUprising = 28482, // Boss->self, 3.0s cast, range 7 120-degree cone aoe (knockback 12) SpineShatter = 28483, // Boss->player, 5.0s cast, single-target tankbuster Teleport = 28475, // Boss->location, no cast, single-target @@ -18,7 +19,7 @@ public enum AID : uint AugmentedUprising = 28478, // Boss->self, 7.0s cast, range 45 90-degree cone aoe Activate = 28479, // Boss->self, 3.0s cast, single-target, visual (spawn claw) TheHand = 28480, // MagitekDeathClaw->player, no cast, single-target (autoattack with knockback 20) - WheelOfSuffering = 28481, // Boss->self, 3.5s cast, range 7 circle aoe (knockback 12) + WheelOfSuffering = 28481 // Boss->self, 3.5s cast, range 7 circle aoe (knockback 12) } class IronUprising(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.IronUprising), new AOEShapeCone(7, 60.Degrees())); @@ -37,11 +38,38 @@ class AugmentedShatter(BossModule module) : Components.StackWithCastTargets(modu class AugmentedUprising(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.AugmentedUprising), new AOEShapeCone(45, 45.Degrees())); class WheelOfSuffering(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.WheelOfSuffering), new AOEShapeCircle(7)); +class ArenaChange(BossModule module) : Components.GenericAOEs(module) +{ + private static readonly AOEShapeDonut donut = new(20, 35); + private AOEInstance? _aoe; + private bool begin; + + public override IEnumerable ActiveAOEs(int slot, Actor actor) => Utils.ZeroOrOne(_aoe); + + public override void OnEventEnvControl(byte index, uint state) + { + if (index == 0x00 && state == 0x00020001) + { + Arena.Bounds = D142Nero.DefaultBounds; + _aoe = null; + begin = true; + } + } + + public override void Update() + { + if (!begin && _aoe == null) + _aoe = new(donut, Arena.Center, default, WorldState.FutureTime(3.6f)); + } +} + class D142NeroStates : StateMachineBuilder { public D142NeroStates(BossModule module) : base(module) { TrivialPhase() + .ActivateOnEnter() + .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter() @@ -51,9 +79,34 @@ public D142NeroStates(BossModule module) : base(module) } } -[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 16, NameID = 2135)] -public class D142Nero(WorldState ws, Actor primary) : BossModule(ws, primary, new(-164, 0), new ArenaBoundsCircle(20)) +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn, Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 16, NameID = 2135)] +public class D142Nero(WorldState ws, Actor primary) : BossModule(ws, primary, startingBounds.Center, startingBounds) { + private static readonly WPos[] vertices = [new(-158.27f, -29.04f), new(-156.76f, -28.7f), new(-155.3f, -28.29f), new(-151.86f, -26.99f), new(-151.47f, -25.48f), + new(-151.27f, -25), new(-151.02f, -24.52f), new(-150.27f, -23.82f), new(-149.28f, -23.51f), new(-148.21f, -23.58f), + new(-146.71f, -23.99f), new(-146.3f, -23.69f), new(-143.17f, -21), new(-142.44f, -20.24f), new(-142.05f, -19.86f), + new(-138.63f, -15.25f), new(-137.84f, -13.83f), new(-136.14f, -9.99f), new(-135.65f, -8.51f), new(-135.24f, -6.99f), + new(-135.23f, -5.44f), new(-135.02f, -3.03f), new(-135.02f, 5.01f), new(-135.21f, 5.48f), new(-135.23f, 6.75f), + new(-135.3f, 7.25f), new(-135.59f, 8.27f), new(-136.19f, 10.1f), new(-136.64f, 11.25f), new(-137.33f, 12.82f), + new(-137.79f, 13.74f), new(-138.22f, 14.49f), new(-138.46f, 14.95f), new(-139.28f, 16.26f), new(-143.03f, 20.88f), + new(-144.14f, 21.95f), new(-145.29f, 22.94f), new(-146.52f, 23.88f), new(-147.03f, 23.91f), new(-148.03f, 23.64f), + new(-149.05f, 23.46f), new(-150.04f, 23.74f), new(-150.49f, 24.03f), new(-150.86f, 24.38f), new(-151.21f, 24.77f), + new(-151.41f, 25.27f), new(-151.82f, 26.76f), new(-152.2f, 27.12f), new(-152.69f, 27.35f), new(-158.17f, 29.02f), + new(-159.72f, 29.29f), new(-163.96f, 29.6f), new(-165.52f, 29.56f), new(-171.11f, 28.73f), new(-172.65f, 28.31f), + new(-176.05f, 27.03f), new(-176.24f, 26.55f), new(-176.51f, 25.56f), new(-176.74f, 25.1f), new(-176.88f, 24.62f), + new(-177.64f, 23.9f), new(-178.12f, 23.7f), new(-178.6f, 23.55f), new(-179.11f, 23.49f), new(-179.66f, 23.55f), + new(-181.16f, 23.95f), new(-181.64f, 23.77f), new(-182.85f, 22.81f), new(-185.85f, 19.96f), new(-186.89f, 18.76f), + new(-190.05f, 14.05f), new(-190.77f, 12.63f), new(-192.29f, 8.69f), new(-192.71f, 7.2f), new(-192.78f, 5.42f), + new(-192.98f, 4.88f), new(-192.98f, -5.06f), new(-192.78f, -5.53f), new(-192.76f, -6.86f), new(-191.36f, -11.23f), + new(-190.74f, -12.63f), new(-189.82f, -14.46f), new(-187.83f, -17.56f), new(-186.86f, -18.79f), new(-182.78f, -22.87f), + new(-181.55f, -23.83f), new(-181.03f, -23.92f), new(-179.56f, -23.52f), new(-179.06f, -23.44f), new(-178.55f, -23.56f), + new(-178.06f, -23.71f), new(-177.57f, -23.95f), new(-176.84f, -24.65f), new(-176.48f, -25.61f), new(-176.22f, -26.59f), + new(-175.97f, -27.03f), new(-174.56f, -27.62f), new(-174.07f, -27.83f), new(-172.59f, -28.32f), new(-171.11f, -28.73f), + new(-166.99f, -29.45f), new(-165.38f, -29.56f)]; + + private static readonly ArenaBoundsComplex startingBounds = new([new PolygonCustom(vertices)]); + public static readonly ArenaBoundsCircle DefaultBounds = new(20); + protected override void CalculateModuleAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { foreach (var e in hints.PotentialTargets) diff --git a/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D143Gaius.cs b/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D143Gaius.cs index b12d0426cd..937e109f06 100644 --- a/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D143Gaius.cs +++ b/BossMod/Modules/RealmReborn/Dungeon/D14Praetorium/D143Gaius.cs @@ -3,10 +3,11 @@ public enum OID : uint { Boss = 0x3875, // x1 - Helper = 0x233C, // x16 - PhantomGaiusSide = 0x3876, // x5, untargetable - PhantomGaiusAdd = 0x3877, // x4, adds that become targetable on low hp - TerminusEst = 0x3878, // spawn during fight + + PhantomGaiusSide = 0x3876, // R1.65, untargetable + PhantomGaiusAdd = 0x3877, // R1.65, adds that become targetable on low hp + TerminusEst = 0x3878, // R=1.0 + Helper = 0x233C } public enum AID : uint @@ -33,12 +34,31 @@ public enum AID : uint AddPhaseStart = 28497, // Boss->self, no cast, single-target, visual (enemy 'lb' gauge starts filling over 90 secs) Heirsbane = 28498, // PhantomGaiusAdd->player, 5.0s cast, single-target damage VeniVidiVici = 28499, // Boss->self, no cast, raidwide on last add death - VeniVidiViciEnrage = 28500, // Boss->self, no cast, enrage (if adds aren't killed in 90s) + VeniVidiViciEnrage = 28500 // Boss->self, no cast, enrage (if adds aren't killed in 90s) +} + +class TerminusEst(BossModule module) : Components.GenericAOEs(module) +{ + private readonly List _aoes = []; + + private static readonly AOEShapeRect rect = new(40, 2); + + public override IEnumerable ActiveAOEs(int slot, Actor actor) => _aoes; + + public override void OnActorCreated(Actor actor) + { + if ((OID)actor.OID == OID.TerminusEst) + _aoes.Add(new(rect, actor.Position, actor.Rotation, WorldState.FutureTime(6))); + } + + public override void OnEventCast(Actor caster, ActorCastEvent spell) + { + if ((AID)spell.Action.ID is AID.TerminusEstTriple or AID.TerminusEstQuintuple) + _aoes.Clear(); + } } -class TerminusEstTriple(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.TerminusEstTriple), new AOEShapeRect(40, 2)); -class TerminusEstQuintuple(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.TerminusEstQuintuple), new AOEShapeRect(40, 2)); -class HandOfTheEmpire(BossModule module) : Components.SpreadFromCastTargets(module, ActionID.MakeSpell(AID.HandOfTheEmpireAOE), 5, false); +class HandOfTheEmpire(BossModule module) : Components.SpreadFromCastTargets(module, ActionID.MakeSpell(AID.HandOfTheEmpireAOE), 5); class FestinaLente(BossModule module) : Components.StackWithCastTargets(module, ActionID.MakeSpell(AID.FestinaLente), 6, 4, 4); class Innocence(BossModule module) : Components.SingleTargetCast(module, ActionID.MakeSpell(AID.Innocence)); class HorridaBella(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.HorridaBella)); @@ -68,8 +88,7 @@ class D143GaiusStates : StateMachineBuilder public D143GaiusStates(BossModule module) : base(module) { TrivialPhase() - .ActivateOnEnter() - .ActivateOnEnter() + .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter() @@ -80,12 +99,11 @@ public D143GaiusStates(BossModule module) : base(module) } } -[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 16, NameID = 2136)] -public class D143Gaius(WorldState ws, Actor primary) : BossModule(ws, primary, new(-562, 220), new ArenaBoundsRect(15, 20)) +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn, Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 16, NameID = 2136)] +public class D143Gaius(WorldState ws, Actor primary) : BossModule(ws, primary, new(-562, 220), new ArenaBoundsRect(14.5f, 19.5f)) { protected override void DrawEnemies(int pcSlot, Actor pc) { - Arena.Actor(PrimaryActor); - Arena.Actors(Enemies(OID.PhantomGaiusAdd)); + Arena.Actors(Enemies(OID.PhantomGaiusAdd).Concat([PrimaryActor])); } } diff --git a/BossMod/Replay/Analysis/ArenaBounds.cs b/BossMod/Replay/Analysis/ArenaBounds.cs index 803c76bfae..6efffa6d13 100644 --- a/BossMod/Replay/Analysis/ArenaBounds.cs +++ b/BossMod/Replay/Analysis/ArenaBounds.cs @@ -63,8 +63,12 @@ public void DrawContextMenu() { Task.Run(() => { - var playerPoints = _points.Where(p => p.Item2.OID == 0).Select(x => new WPos(x.Item4.XZ())).ToList(); - var points = ConcaveHull.GenerateConcaveHull(playerPoints, 0.5f, 0); + var playerPoints = _points + .Where(p => p.Item2.OID == 0) + .Select(x => new WPos(RoundToNearestHundredth(x.Item4.X), RoundToNearestHundredth(x.Item4.Z))) + .ToList(); + + var points = ConcaveHull.GenerateConcaveHull(playerPoints, 0.5f, 0.2f); var center = CalculateCentroid(points); var sb = new StringBuilder("private static readonly WPos[] vertices = ["); @@ -89,6 +93,7 @@ public void DrawContextMenu() } } + private static float RoundToNearestHundredth(float value) => MathF.Round(value, 3); private static WPos CalculateCentroid(List points) { if (points == null || points.Count < 3) @@ -185,15 +190,16 @@ private static List ApplyAlphaFilter(List hull, double alpha) private static List RemoveCollinearPoints(List points) { - if (points.Count < 3) + var count = points.Count; + if (count < 3) return points; List filteredPoints = []; for (var i = 0; i < points.Count; i++) { - var prev = points[(i - 1 + points.Count) % points.Count]; + var prev = points[(i - 1 + count) % count]; var curr = points[i]; - var next = points[(i + 1) % points.Count]; + var next = points[(i + 1) % count]; if (!AreCollinear(prev, curr, next)) filteredPoints.Add(curr); @@ -201,12 +207,23 @@ private static List RemoveCollinearPoints(List points) return filteredPoints; } - private static bool AreCollinear(WPos a, WPos b, WPos c) + private static bool AreCollinear(WPos a, WPos b, WPos c, float toleranceDegrees = 4) { - var ab = b - a; - var bc = c - b; - var crossProduct = ab.X * bc.Z - ab.Z * bc.X; - return Math.Abs(crossProduct) < 0.015f; + var ab = new Vector2(b.X - a.X, b.Z - a.Z); + var bc = new Vector2(c.X - b.X, c.Z - b.Z); + + var magnitudeAB = ab.Length(); + var magnitudeBC = bc.Length(); + + if (magnitudeAB == 0 || magnitudeBC == 0) + return false; + + var dotProduct = ab.X * bc.X + ab.Y * bc.Y; + + var cosTheta = dotProduct / (magnitudeAB * magnitudeBC); + cosTheta = Math.Clamp(cosTheta, -1, 1); + var angle = MathF.Acos(cosTheta) * Angle.RadToDeg; + + return Math.Abs(angle) < toleranceDegrees || Math.Abs(angle - 180) < toleranceDegrees; } } -