diff --git a/BossMod/Modules/Stormblood/Foray/Hydatos/Ceto.cs b/BossMod/Modules/Stormblood/Foray/Hydatos/Ceto.cs index 6f783b9c7..4b73033ab 100644 --- a/BossMod/Modules/Stormblood/Foray/Hydatos/Ceto.cs +++ b/BossMod/Modules/Stormblood/Foray/Hydatos/Ceto.cs @@ -90,7 +90,7 @@ public CetoStates(BossModule module) : base(module) } [ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "xan, Malediktus", GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1421, SortOrder = 9)] -public class Ceto(WorldState ws, Actor primary) : BossModule(ws, primary, new(747.8959f, -878.8765f), new ArenaBoundsCircle(80f, 1f, true)) +public class Ceto(WorldState ws, Actor primary) : BossModule(ws, primary, new(747.8959f, -878.8765f), SharedBounds.Circle) { private static readonly uint[] trash = [(uint)OID.FaithlessGuard, (uint)OID.HydatosDelphyne, (uint)OID.DarkGargoyle]; protected override void DrawEnemies(int pcSlot, Actor pc) diff --git a/BossMod/Modules/Stormblood/Foray/Hydatos/Daphne.cs b/BossMod/Modules/Stormblood/Foray/Hydatos/Daphne.cs index 1813efc49..9b58a0c7e 100644 --- a/BossMod/Modules/Stormblood/Foray/Hydatos/Daphne.cs +++ b/BossMod/Modules/Stormblood/Foray/Hydatos/Daphne.cs @@ -59,7 +59,7 @@ public DaphneStates(BossModule module) : base(module) } [ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "xan, Malediktus", GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1417, SortOrder = 5)] -public class Daphne(WorldState ws, Actor primary) : BossModule(ws, primary, new(207.8475f, -736.8179f), new ArenaBoundsCircle(80f, 1f, true)) +public class Daphne(WorldState ws, Actor primary) : BossModule(ws, primary, new(207.8475f, -736.8179f), SharedBounds.Circle) { protected override void DrawEnemies(int pcSlot, Actor pc) { diff --git a/BossMod/Modules/Stormblood/Foray/Hydatos/Molech.cs b/BossMod/Modules/Stormblood/Foray/Hydatos/Molech.cs index a901a6ecd..8cc22b2c5 100644 --- a/BossMod/Modules/Stormblood/Foray/Hydatos/Molech.cs +++ b/BossMod/Modules/Stormblood/Foray/Hydatos/Molech.cs @@ -2,23 +2,24 @@ namespace BossMod.Stormblood.Foray.Hydatos.Molech; public enum OID : uint { - Boss = 0x275D, // R6.000, x1 - Adulator = 0x275E // R2.800, x3 + Boss = 0x275D, // R6.0 + Adulator = 0x275E // R2.8 } public enum AID : uint { + AutoAttack = 15492, // Boss->player, no cast, single-target + W11TonzeSwipeAdds = 14978, // Adulator->player, no cast, single-target W11TonzeSwipe = 14972, // Boss->self, 3.0s cast, range 9 ?-degree cone W111TonzeSwing = 14973, // Boss->self, 4.0s cast, range 13 circle - OrderToStandFast = 14976, // Boss->self, 3.0s cast, range 100 circle + OrderToAssault = 14975, // Boss->self, 3.0s cast, range 100 circle, buffs Adulators + OrderToStandFast = 14976, // Boss->self, 3.0s cast, range 100 circle, buffs Adulators W111TonzeSwingAdds = 14979, // Adulator->self, 3.0s cast, range 13 circle W111TonzeSwingBig = 14974, // Boss->self, 4.0s cast, range 20 circle - OrderToAssault = 14975, // Boss->self, 3.0s cast, range 100 circle ZoomIn = 14980 // Adulator->location, 3.0s cast, width 8 rect charge } -class Adds(BossModule module) : Components.AddsPointless(module, (uint)OID.Adulator); class W11TonzeSwipe(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.W11TonzeSwipe), new AOEShapeCone(9f, 75f.Degrees())); class W111TonzeSwing(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.W111TonzeSwing), 13f); class W111TonzeSwingAdds(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.W111TonzeSwingAdds), 13f); @@ -30,7 +31,6 @@ class MolechStates : StateMachineBuilder public MolechStates(BossModule module) : base(module) { TrivialPhase() - .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter() @@ -39,6 +39,28 @@ public MolechStates(BossModule module) : base(module) } } -[ModuleInfo(BossModuleInfo.Maturity.Contributed, GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1414, Contributors = "xan", SortOrder = 3)] -public class Molech(WorldState ws, Actor primary) : BossModule(ws, primary, new(-676.8632f, -441.8009f), new ArenaBoundsCircle(80f, 1f, true)); +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "xan, Malediktus", GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1414, SortOrder = 3)] +public class Molech(WorldState ws, Actor primary) : BossModule(ws, primary, new(-676.8632f, -441.8009f), SharedBounds.Circle) +{ + protected override void DrawEnemies(int pcSlot, Actor pc) + { + Arena.Actor(PrimaryActor); + Arena.Actors(Enemies((uint)OID.Adulator)); + } + protected override void CalculateModuleAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + var count = hints.PotentialTargets.Count; + for (var i = 0; i < count; ++i) + { + var e = hints.PotentialTargets[i]; + e.Priority = e.Actor.OID switch + { + (uint)OID.Boss => 1, + (uint)OID.Adulator => AIHints.Enemy.PriorityPointless, + _ when e.Actor.InCombat => 0, + _ => AIHints.Enemy.PriorityUndesirable + }; + } + } +} diff --git a/BossMod/Modules/Stormblood/Foray/Hydatos/Ovni.cs b/BossMod/Modules/Stormblood/Foray/Hydatos/Ovni.cs index c2adfe1fd..f9b2886ed 100644 --- a/BossMod/Modules/Stormblood/Foray/Hydatos/Ovni.cs +++ b/BossMod/Modules/Stormblood/Foray/Hydatos/Ovni.cs @@ -2,11 +2,15 @@ public enum OID : uint { - Boss = 0x2685, // R16.000, x1 + Boss = 0x2685, // R16.0 + UnfoundOgre = 0x26BF, // R1.3 } public enum AID : uint { + AutoAttack1 = 14781, // Boss->player, no cast, single-target + AutoAttack2 = 15228, // UnfoundOgre->player, no cast, single-target + RockHard = 14786, // Boss->location, 3.0s cast, range 8 circle TorrentialTorment = 14785, // Boss->self, 5.0s cast, range 40+R 45-degree cone Fluorescence = 14789, // Boss->self, 3.0s cast, single-target @@ -16,11 +20,13 @@ public enum AID : uint IonStorm = 14788, // Boss->players, no cast, range 20 circle VitriolicBarrage = 14790, // Boss->self, 4.0s cast, range 25+R circle ConcussiveOscillation = 14783, // Boss->self, 5.0s cast, range 24 circle + StraightPunch = 15430, // UnfoundOgre->player, no cast, single-target + PlainPound = 15431 // UnfoundOgre->self, 3.0s cast, range 6 circle } public enum IconID : uint { - IonShower = 111, // player->self + IonShower = 111 // player->self } class PullOfTheVoid(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.PullOfTheVoid), 30f, kind: Kind.TowardsOrigin, minDistanceBetweenHitboxes: true); @@ -29,6 +35,7 @@ class ConcussiveOscillation(BossModule module) : Components.SimpleAOEs(module, A class VitriolicBarrage(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.VitriolicBarrage)); class RockHard(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.RockHard), 8); class TorrentialTorment(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.TorrentialTorment), new AOEShapeCone(56f, 22.5f.Degrees())); + class IonShower(BossModule module) : Components.GenericStackSpread(module, alwaysShowSpreads: true, raidwideOnResolve: false) { private int _numCasts; @@ -38,7 +45,7 @@ public override void OnEventIcon(Actor actor, uint iconID, ulong targetID) if (iconID == (uint)IconID.IonShower && WorldState.Actors.Find(targetID) is { } target) { _numCasts = 0; - Spreads.Add(new(target, 20, WorldState.FutureTime(5d))); + Spreads.Add(new(target, 20f, WorldState.FutureTime(5d))); } } @@ -67,6 +74,8 @@ public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignme } } +class PlainPound(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.PlainPound), 6); + class OvniStates : StateMachineBuilder { public OvniStates(BossModule module) : base(module) @@ -78,10 +87,32 @@ public OvniStates(BossModule module) : base(module) .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter() - .ActivateOnEnter(); + .ActivateOnEnter() + .ActivateOnEnter(); } } -[ModuleInfo(BossModuleInfo.Maturity.Contributed, GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1424, Contributors = "xan", SortOrder = 11)] -public class Ovni(WorldState ws, Actor primary) : BossModule(ws, primary, new(266.1068f, -97.09414f), new ArenaBoundsCircle(80f, 1f, true)); +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "xan, Malediktus", GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1424, SortOrder = 11)] +public class Ovni(WorldState ws, Actor primary) : BossModule(ws, primary, new(266.1068f, -97.09414f), SharedBounds.Circle) +{ + protected override void DrawEnemies(int pcSlot, Actor pc) + { + Arena.Actor(PrimaryActor); + Arena.Actors(Enemies((uint)OID.UnfoundOgre)); + } + protected override void CalculateModuleAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + var count = hints.PotentialTargets.Count; + for (var i = 0; i < count; ++i) + { + var e = hints.PotentialTargets[i]; + e.Priority = e.Actor.OID switch + { + (uint)OID.Boss => 1, + _ when e.Actor.InCombat => 0, + _ => AIHints.Enemy.PriorityUndesirable + }; + } + } +} diff --git a/BossMod/Modules/Stormblood/Foray/Hydatos/SharedBounds.cs b/BossMod/Modules/Stormblood/Foray/Hydatos/SharedBounds.cs new file mode 100644 index 000000000..b536e0f0a --- /dev/null +++ b/BossMod/Modules/Stormblood/Foray/Hydatos/SharedBounds.cs @@ -0,0 +1,6 @@ +namespace BossMod.Stormblood.Foray.Hydatos; + +public static class SharedBounds +{ + public static readonly ArenaBoundsCircle Circle = new(80f, 1f, true); +} \ No newline at end of file diff --git a/BossMod/Modules/Stormblood/Foray/Hydatos/Tristitia.cs b/BossMod/Modules/Stormblood/Foray/Hydatos/Tristitia.cs new file mode 100644 index 000000000..a816b1aef --- /dev/null +++ b/BossMod/Modules/Stormblood/Foray/Hydatos/Tristitia.cs @@ -0,0 +1,172 @@ +using BossMod.Shadowbringers.Hunt.RankS.Ixtab; + +namespace BossMod.Stormblood.Foray.Hydatos.Tristitia; + +public enum OID : uint +{ + Boss = 0x2741, // R4.0 + Tristitia = 0x2740, // R6.0 +} + +public enum AID : uint +{ + AutoAttack1 = 14923, // Boss->player, no cast, single-target + AutoAttack2 = 14919, // Tristitia->player, no cast, single-target + + WatergaIII = 14922, // Tristitia->location, 3.0s cast, range 8 circle + SpineLash1 = 14924, // Boss->self, 3.0s cast, range 5+R 90-degree cone + SpineLash2 = 14921, // Tristitia->self, 3.0s cast, range 5+R 90-degree cone + ShockSpikes = 14920, // Tristitia->self, 5.0s cast, single-target, applies shock spike buff + TornadoII1 = 15914, // Tristitia->self, 5.0s cast, range 5-40 donut + TornadoII2 = 15915, // Tristitia->self, no cast, range 5-40 donut + AerogaIV1 = 15912, // Tristitia->self, 3.5s cast, range 10 circle + AerogaIV2 = 15913, // Tristitia->self, no cast, range 10 circle + MightyStrikes = 15910, // Tristitia->self, 3.0s cast, single-target, applies critical strikes buff + Meteor = 15911, // Tristitia->self, 5.0s cast, range 40 circle + Dualcast = 15909 // Tristitia->self, 2.0s cast, single-target +} + +class WatergaIII(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.WatergaIII), 8f); +class SpineLash1(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.SpineLash1), new AOEShapeCone(9f, 45f.Degrees())); +class SpineLash2(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.SpineLash2), new AOEShapeCone(11f, 45f.Degrees())); +class Meteor(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.Meteor)); + +class TornadoIIAerogaIVDualCast(BossModule module) : Components.GenericAOEs(module) +{ + private static readonly AOEShapeCircle circle = new(10f); + private static readonly AOEShapeDonut donut = new(5f, 40f); + private bool dualCast; + public readonly List _aoes = new(2); + + public override IEnumerable ActiveAOEs(int slot, Actor actor) + { + var count = _aoes.Count; + if (count == 0) + return []; + var aoes = new AOEInstance[count]; + for (var i = 0; i < count; ++i) + { + var aoe = _aoes[i]; + if (i == 0) + aoes[i] = count > 1 ? aoe with { Color = Colors.Danger } : aoe; + else + aoes[i] = aoe with { Risky = false }; + } + return aoes; + } + + public override void OnCastStarted(Actor caster, ActorCastInfo spell) + { + void AddAOE(AOEShape shape, float delay = 0f) => _aoes.Add(new(shape, spell.LocXZ, default, Module.CastFinishAt(spell, delay))); + void AddAOEs(AOEShape shape1, AOEShape shape2) + { + AddAOE(shape1); + AddAOE(shape2, 3.1f); + dualCast = false; + } + switch (spell.Action.ID) + { + case (uint)AID.Dualcast: + dualCast = true; + break; + case (uint)AID.TornadoII1: + if (!dualCast) + AddAOE(donut); + else + AddAOEs(donut, circle); + break; + case (uint)AID.AerogaIV1: + if (!dualCast) + AddAOE(circle); + else + AddAOEs(circle, donut); + break; + } + } + + public override void OnEventCast(Actor caster, ActorCastEvent spell) + { + if (_aoes.Count != 0) + switch (spell.Action.ID) + { + case (uint)AID.TornadoII1: + case (uint)AID.TornadoII2: + case (uint)AID.AerogaIV1: + case (uint)AID.AerogaIV2: + _aoes.RemoveAt(0); + break; + } + } +} + +class PhuaboStates : StateMachineBuilder +{ + public PhuaboStates(BossModule module) : base(module) + { + TrivialPhase() + .ActivateOnEnter() + .Raw.Update = () => + { + var adds = module.Enemies((uint)OID.Boss); + var countadds = adds.Count; + var areAddsDestroyed = true; + for (var i = 0; i < countadds; ++i) + { + if (!adds[i].IsDestroyed) + areAddsDestroyed = false; + } + var boss = module.Enemies((uint)OID.Tristitia); + var countBoss = boss.Count; + var isBossTargetable = false; + for (var i = 0; i < countBoss; ++i) + { + if (boss[i].IsTargetable) + isBossTargetable = true; + } + return areAddsDestroyed || isBossTargetable; + }; + } +} + +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1422, SortOrder = 12)] +public class Phuabo(WorldState ws, Actor primary) : BASupportFate(ws, primary); + +class TristitiaStates : StateMachineBuilder +{ + public TristitiaStates(BossModule module) : base(module) + { + TrivialPhase() + .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter(); + } +} + +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1422, PrimaryActorOID = (uint)OID.Tristitia, SortOrder = 13)] +public class Tristitia(WorldState ws, Actor primary) : BASupportFate(ws, primary); + +public abstract class BASupportFate(WorldState ws, Actor primary) : BossModule(ws, primary, new(-123.4f, -128.283f), SharedBounds.Circle) +{ + public static readonly uint[] All = [(uint)OID.Boss, (uint)OID.Tristitia]; + protected override void DrawEnemies(int pcSlot, Actor pc) + { + Arena.Actor(PrimaryActor); + Arena.Actors(Enemies(All)); + } + + protected override void CalculateModuleAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + var count = hints.PotentialTargets.Count; + for (var i = 0; i < count; ++i) + { + var e = hints.PotentialTargets[i]; + e.Priority = e.Actor.OID switch + { + (uint)OID.Boss or (uint)OID.Tristitia => 1, + _ when e.Actor.InCombat => 0, + _ => AIHints.Enemy.PriorityUndesirable + }; + } + } +}