From a5c8ba10cceb9ba25808cd66be66491de393da7f Mon Sep 17 00:00:00 2001 From: Andrew Gilewsky Date: Sat, 16 Nov 2024 17:38:07 +0000 Subject: [PATCH 1/5] Unreal module. --- .../Dawntrail/Extreme/Ex3Sphene/Ex3Sphene.cs | 2 +- .../Unreal/Un1Byakko/AratamaPuddle.cs | 19 ++ .../Unreal/Un1Byakko/HundredfoldHavoc.cs | 30 ++ .../Unreal/Un1Byakko/Intermission.cs | 42 +++ .../Unreal/Un1Byakko/StateOfShock.cs | 42 +++ .../Dawntrail/Unreal/Un1Byakko/Un1Byakko.cs | 31 ++ .../Unreal/Un1Byakko/Un1ByakkoEnums.cs | 83 +++++ .../Unreal/Un1Byakko/Un1ByakkoStates.cs | 301 ++++++++++++++++++ .../Unreal/Un1Byakko/UnrelentingAnguish.cs | 34 ++ 9 files changed, 583 insertions(+), 1 deletion(-) create mode 100644 BossMod/Modules/Dawntrail/Unreal/Un1Byakko/AratamaPuddle.cs create mode 100644 BossMod/Modules/Dawntrail/Unreal/Un1Byakko/HundredfoldHavoc.cs create mode 100644 BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs create mode 100644 BossMod/Modules/Dawntrail/Unreal/Un1Byakko/StateOfShock.cs create mode 100644 BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1Byakko.cs create mode 100644 BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoEnums.cs create mode 100644 BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoStates.cs create mode 100644 BossMod/Modules/Dawntrail/Unreal/Un1Byakko/UnrelentingAnguish.cs diff --git a/BossMod/Modules/Dawntrail/Extreme/Ex3Sphene/Ex3Sphene.cs b/BossMod/Modules/Dawntrail/Extreme/Ex3Sphene/Ex3Sphene.cs index 1108054833..4a978bc0de 100644 --- a/BossMod/Modules/Dawntrail/Extreme/Ex3Sphene/Ex3Sphene.cs +++ b/BossMod/Modules/Dawntrail/Extreme/Ex3Sphene/Ex3Sphene.cs @@ -4,7 +4,7 @@ class ProsecutionOfWar(BossModule module) : Components.TankSwap(module, ActionID class DyingMemory(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.DyingMemory)); class DyingMemoryLast(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.DyingMemoryLast)); -[ModuleInfo(BossModuleInfo.Maturity.Verified, PlanLevel = 100, PrimaryActorOID = (uint)OID.BossP1, GroupType = BossModuleInfo.GroupType.CFC, GroupID = 1017, NameID = 13029)] +[ModuleInfo(BossModuleInfo.Maturity.Verified, PrimaryActorOID = (uint)OID.BossP1, GroupType = BossModuleInfo.GroupType.CFC, GroupID = 1017, NameID = 13029, PlanLevel = 100)] public class Ex3Sphene(WorldState ws, Actor primary) : BossModule(ws, primary, new(100, 100), NormalBounds) { public static readonly ArenaBoundsSquare NormalBounds = new(20); diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/AratamaPuddle.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/AratamaPuddle.cs new file mode 100644 index 0000000000..470e520e4c --- /dev/null +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/AratamaPuddle.cs @@ -0,0 +1,19 @@ +namespace BossMod.Dawntrail.Unreal.Un1Byakko; + +class AratamaPuddleBait(BossModule module) : Components.SpreadFromIcon(module, (uint)IconID.AratamaPuddle, ActionID.MakeSpell(AID.AratamaPuddle), 4, 5.1f) +{ + private DateTime _nextSpread; + + public override void OnEventCast(Actor caster, ActorCastEvent spell) + { + if (spell.Action == SpreadAction && WorldState.CurrentTime > _nextSpread) + { + if (++NumFinishedSpreads >= 3) + Spreads.Clear(); + else + _nextSpread = WorldState.FutureTime(0.5f); // protection in case one target dies + } + } +} + +class AratamaPuddleVoidzone(BossModule module) : Components.PersistentVoidzone(module, 4, m => m.Enemies(OID.AratamaPuddle).Where(z => z.EventState != 7)); diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/HundredfoldHavoc.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/HundredfoldHavoc.cs new file mode 100644 index 0000000000..e0a7d765ca --- /dev/null +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/HundredfoldHavoc.cs @@ -0,0 +1,30 @@ +namespace BossMod.Dawntrail.Unreal.Un1Byakko; + +class HundredfoldHavoc(BossModule module) : Components.Exaflare(module, 5) +{ + public override void OnCastStarted(Actor caster, ActorCastInfo spell) + { + if ((AID)spell.Action.ID is AID.HundredfoldHavocFirst) + { + Lines.Add(new() { Next = caster.Position, Advance = 5 * spell.Rotation.ToDirection(), NextExplosion = Module.CastFinishAt(spell), TimeToMove = 1.1f, ExplosionsLeft = 4, MaxShownExplosions = 2 }); + } + } + + public override void OnEventCast(Actor caster, ActorCastEvent spell) + { + if ((AID)spell.Action.ID is AID.HundredfoldHavocFirst or AID.HundredfoldHavocRest) + { + ++NumCasts; + int index = Lines.FindIndex(item => item.Next.AlmostEqual(caster.Position, 1)); + if (index == -1) + { + ReportError($"Failed to find entry for {caster.InstanceID:X}"); + return; + } + + AdvanceLine(Lines[index], caster.Position); + if (Lines[index].ExplosionsLeft == 0) + Lines.RemoveAt(index); + } + } +} diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs new file mode 100644 index 0000000000..d8a72a1b8d --- /dev/null +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs @@ -0,0 +1,42 @@ +namespace BossMod.Dawntrail.Unreal.Un1Byakko; + +class VoiceOfThunder : Components.PersistentInvertibleVoidzone +{ + public VoiceOfThunder(BossModule module) : base(module, 2, m => m.Enemies(OID.AramitamaSoul).Where(x => !x.IsDead)) + { + InvertResolveAt = WorldState.CurrentTime; + } + + public override void AddHints(int slot, Actor actor, TextHints hints) + { + if (Sources(Module).Any(x => !Shape.Check(actor.Position, x))) + hints.Add("Touch the balls!"); + } +} + +class IntermissionOrbAratama(BossModule module) : Components.GenericAOEs(module, ActionID.MakeSpell(AID.IntermissionOrbAratama), "GTFO from puddle!") +{ + public readonly List AOEs = []; + + public static readonly AOEShapeCircle _shape = new(2); + + public override IEnumerable ActiveAOEs(int slot, Actor actor) => AOEs; + + public override void OnEventCast(Actor caster, ActorCastEvent spell) + { + switch ((AID)spell.Action.ID) + { + case AID.IntermissionOrbSpawn: + AOEs.Add(new(_shape, spell.TargetXZ, default, WorldState.FutureTime(5.1f))); + break; + case AID.IntermissionOrbAratama: + ++NumCasts; + AOEs.RemoveAll(aoe => aoe.Origin.AlmostEqual(spell.TargetXZ, 1)); + break; + } + } +} + +class IntermissionSweepTheLeg(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.IntermissionSweepTheLeg), new AOEShapeDonut(5, 25)); +class ImperialGuard(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.ImperialGuard), new AOEShapeRect(44.75f, 2.5f)); +class FellSwoop(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.FellSwoop)); diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/StateOfShock.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/StateOfShock.cs new file mode 100644 index 0000000000..7e06794944 --- /dev/null +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/StateOfShock.cs @@ -0,0 +1,42 @@ +namespace BossMod.Dawntrail.Unreal.Un1Byakko; + +class StateOfShock(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.StateOfShockSecond)) +{ + public int NumStuns; + + public override void OnStatusGain(Actor actor, ActorStatus status) + { + if ((SID)status.ID == SID.Stun) + ++NumStuns; + } + + public override void OnStatusLose(Actor actor, ActorStatus status) + { + if ((SID)status.ID == SID.Stun) + --NumStuns; + } +} + +class HighestStakes(BossModule module) : Components.GenericTowers(module, ActionID.MakeSpell(AID.HighestStakesAOE)) +{ + private BitMask _forbidden; + + public override void OnEventIcon(Actor actor, uint iconID, ulong targetID) + { + if (iconID == (uint)IconID.HighestStakes) + { + Towers.Add(new(actor.Position, 6, 3, 3, _forbidden, WorldState.FutureTime(6.1f))); + } + } + + public override void OnEventCast(Actor caster, ActorCastEvent spell) + { + if (spell.Action == WatchedAction) + { + ++NumCasts; + Towers.Clear(); + foreach (var t in spell.Targets) + _forbidden.Set(Raid.FindSlot(t.ID)); + } + } +} diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1Byakko.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1Byakko.cs new file mode 100644 index 0000000000..94620b9296 --- /dev/null +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1Byakko.cs @@ -0,0 +1,31 @@ +namespace BossMod.Dawntrail.Unreal.Un1Byakko; + +class StormPulseRepeat(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.StormPulseRepeat)); +class HeavenlyStrike(BossModule module) : Components.BaitAwayCast(module, ActionID.MakeSpell(AID.HeavenlyStrike), new AOEShapeCircle(3), true); +class FireAndLightningBoss(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.FireAndLightningBoss), new AOEShapeRect(54.3f, 10)); +class FireAndLightningAdd(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.FireAndLightningAdd), new AOEShapeRect(54.75f, 10)); +class SteelClaw(BossModule module) : Components.Cleave(module, ActionID.MakeSpell(AID.SteelClaw), new AOEShapeCone(17.75f, 30.Degrees()), (uint)OID.Hakutei); // TODO: verify angle +class WhiteHerald(BossModule module) : Components.SpreadFromIcon(module, (uint)IconID.WhiteHerald, ActionID.MakeSpell(AID.WhiteHerald), 15, 5.1f); // TODO: verify falloff +class DistantClap(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.DistantClap), new AOEShapeDonut(4, 25)); +class SweepTheLegBoss(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.SweepTheLegBoss), new AOEShapeCone(28.3f, 135.Degrees())); + +[ModuleInfo(BossModuleInfo.Maturity.Verified, GroupType = BossModuleInfo.GroupType.CFC, GroupID = 1007, NameID = 7092, PlanLevel = 100)] +public class Un1Byakko(WorldState ws, Actor primary) : BossModule(ws, primary, new(0, 0), new ArenaBoundsCircle(20)) +{ + private Actor? _hakutei; + public Actor? Boss() => PrimaryActor; + public Actor? Hakutei() => _hakutei; + + protected override void UpdateModule() + { + // TODO: this is an ugly hack, think how multi-actor fights can be implemented without it... + // the problem is that on wipe, any actor can be deleted and recreated in the same frame + _hakutei ??= StateMachine.ActivePhaseIndex >= 0 ? Enemies(OID.Hakutei).FirstOrDefault() : null; + } + + protected override void DrawEnemies(int pcSlot, Actor pc) + { + Arena.Actor(PrimaryActor, ArenaColor.Enemy); + Arena.Actor(_hakutei, ArenaColor.Enemy); + } +} diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoEnums.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoEnums.cs new file mode 100644 index 0000000000..8281c4c2bb --- /dev/null +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoEnums.cs @@ -0,0 +1,83 @@ +namespace BossMod.Dawntrail.Unreal.Un1Byakko; + +public enum OID : uint +{ + Boss = 0x4579, // R4.300, x1 + Hakutei = 0x4581, // R4.750, x1 - tiger + Helper = 0x464D, // R0.500, x29, mixed types + AratamaForce = 0x4589, // R0.700, x0 (spawn during fight) - orbs from center + IntermissionHakutei = 0x458B, // R4.750, x0 (spawn during fight) + AramitamaSoul = 0x458A, // R1.000, x0 (spawn during fight) - orbs from edge + AratamaPuddle = 0x1E8EA9, // R0.500, x0 (spawn during fight), EventObj type + IntermissionHelper = 0x1EA87E, // R0.500, x0 (spawn during fight), EventObj type + VacuumClaw = 0x1EA957, // R0.500, x0 (spawn during fight), EventObj type +} + +public enum AID : uint +{ + AutoAttackBoss = 39987, // Boss->player, no cast, single-target + AutoAttackAdd = 39988, // Hakutei->player, no cast, single-target + TeleportBoss = 39929, // Boss->location, no cast, single-target + TeleportAdd = 39927, // Hakutei->location, no cast, single-target + StormPulse = 39933, // Boss->self, 4.0s cast, range 100 circle, raidwide + StormPulseRepeat = 39964, // Boss->self, no cast, range 100 circle, raidwide + HeavenlyStrike = 39931, // Boss->players, 4.0s cast, range 3 circle tankbuster + + StateOfShock = 39937, // Boss->player, 4.0s cast, single-target, stun target to grab & throw it + StateOfShockSecond = 39928, // Boss->player, no cast, single-target, stun second target to grab & throw it + Clutch = 39938, // Boss->player, no cast, single-target, grab target + HighestStakes = 39939, // Boss->location, 5.0s cast, single-target, jump + HighestStakesAOE = 39940, // Helper->location, no cast, range 6 circle tower + + UnrelentingAnguish = 39950, // Boss->self, 3.0s cast, single-target, visual (orbs) + UnrelentingAnguishAratama = 39958, // AratamaForce->self, no cast, range 2 circle, orb explosion + OminousWind = 39948, // Boss->self, no cast, single-target, apply bubbles + FireAndLightningBoss = 39930, // Boss->self, 4.0s cast, range 50+R width 20 rect + + DanceOfTheIncomplete = 39924, // Boss->self, no cast, single-target, visual (split off tiger) + AddAppear = 39923, // Hakutei->self, no cast, single-target, visual (start appear animation) + AratamaPuddle = 39926, // Helper->location, no cast, range 4 circle, puddle drop + SteelClaw = 39936, // Hakutei->self, no cast, range 13+R ?-degree cone, cleave + WhiteHerald = 39962, // Hakutei->self, no cast, range 50 circle with ? falloff + DistantClap = 39934, // Boss->self, 5.0s cast, range 4-25 donut + FireAndLightningAdd = 39935, // Hakutei->self, 4.0s cast, range 50+R width 20 rect + + VoiceOfThunder = 39959, // Hakutei->self, no cast, single-target, visual (physical damage down orbs) + VoiceOfThunderAratama = 39965, // AramitamaSoul->self, no cast, range 2 circle, orb explosion if soaked + VoiceOfThunderAratamaFail = 39960, // AramitamaSoul->Hakutei, no cast, single-target, orb explosion if it reaches the tiger, heals + RoarOfThunder = 39961, // Hakutei->self, 20.0s cast, range 100 circle, raidwide scaled by remaining hp + RoarOfThunderEnd1 = 39968, // Hakutei->Boss, no cast, single-target, visual (???) + RoarOfThunderEnd2 = 39967, // Boss->self, no cast, single-target, visual (???) + IntermissionOrbVisual = 39951, // Boss->self, no cast, single-target, visual (start next set of orbs) + IntermissionOrbSpawn = 39952, // Helper->location, no cast, single-target, visual (location of next orb) + IntermissionOrbAratama = 39953, // Helper->location, no cast, range 2 circle + ImperialGuard = 39954, // IntermissionHakutei->self, 3.0s cast, range 40+R width 5 rect + IntermissionSweepTheLegVisual = 39956, // Boss->self, no cast, single-target, visual (start donut) + IntermissionSweepTheLeg = 39957, // Helper->self, 5.1s cast, range 5-25 donut + IntermissionEnd = 39970, // Boss->self, no cast, single-target, visual (intermission end) + FellSwoop = 39963, // Helper->self, no cast, range 100 circle, raidwide + + AnswerOnHigh = 39941, // Boss->self, no cast, single-target, visual (exaflare start) + HundredfoldHavocFirst = 39942, // Helper->self, 5.0s cast, range 5 circle exaflare + HundredfoldHavocRest = 39943, // Helper->self, no cast, range 5 circle exaflare + SweepTheLegBoss = 39932, // Boss->self, 4.0s cast, range 24+R 270-degree cone + + Bombogenesis = 39944, // Boss->self, no cast, single-target, visual (3 baited puddle icons) + GaleForce = 39945, // Helper->self, no cast, range 6 circle, baited puddle + VacuumClaw = 39946, // Helper->self, no cast, range ? circle, growing voidzone aoe + VacuumBlade = 39947, // Helper->self, no cast, range 100 circle, raidwide +} + +public enum SID : uint +{ + Stun = 201, // Boss->player, extra=0x0 + OminousWind = 1481, // none->player, extra=0x0 +} + +public enum IconID : uint +{ + HighestStakes = 62, // Helper->self + AratamaPuddle = 4, // player->self + WhiteHerald = 87, // player->self + Bombogenesis = 101, // player->self +} diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoStates.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoStates.cs new file mode 100644 index 0000000000..6401963f60 --- /dev/null +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoStates.cs @@ -0,0 +1,301 @@ +namespace BossMod.Dawntrail.Unreal.Un1Byakko; + +class Un1ByakkoStates : StateMachineBuilder +{ + private readonly Un1Byakko _module; + + public Un1ByakkoStates(Un1Byakko module) : base(module) + { + _module = module; + DeathPhase(0, SinglePhase) + .ActivateOnEnter(); // these orbs linger after mechanic ends + } + + private void SinglePhase(uint id) + { + StormPulse(id, 6.2f); + HeavenlyStrike(id + 0x10000, 2.1f); + StateOfShock(id + 0x20000, 6.1f); + UnrelentingAnguish1(id + 0x30000, 11.1f); + Hakutei1(id + 0x40000, 13.4f); + Intermission(id + 0x50000, 2.1f); + HeavenlyStrike(id + 0x60000, 7.2f); + HundredfoldHavoc1(id + 0x70000, 6.2f); + UnrelentingAnguish2(id + 0x80000, 11.6f); + Hakutei2(id + 0x90000, 8.9f); // TODO: variance is quite large? + StormPulseDouble(id + 0xA0000, 11.2f); + HundredfoldHavoc2(id + 0xB0000, 8); + HeavenlyStrike(id + 0xC0000, 10.2f); + StormPulseDouble(id + 0xD0000, 6.2f); + DistantClap(id + 0xE0000, 6.1f); + HeavenlyStrike(id + 0xF0000, 2.1f); + UnrelentingAnguish2(id + 0x100000, 9.5f); + StormPulseDouble(id + 0x110000, 10.5f); + HundredfoldHavoc1(id + 0x120000, 6.1f); + // TODO: ??? + SimpleState(id + 0xFF0000, 10000, "???"); + } + + private State StormPulse(uint id, float delay, string name = "Raidwide") + { + return Cast(id, AID.StormPulse, delay, 4, name) + .SetHint(StateMachine.StateHint.Raidwide); + } + + private void StormPulseDouble(uint id, float delay) + { + StormPulse(id, delay, "Raidwide 1"); + ComponentCondition(id + 2, 2.2f, comp => comp.NumCasts > 0, "Raidwide 2") + .ActivateOnEnter() + .DeactivateOnExit() + .SetHint(StateMachine.StateHint.Raidwide); + } + + private State HeavenlyStrike(uint id, float delay) + { + return Cast(id, AID.HeavenlyStrike, delay, 4, "Tankbuster") + .ActivateOnEnter() + .DeactivateOnExit() + .SetHint(StateMachine.StateHint.Tankbuster); + } + + private void DistantClap(uint id, float delay) + { + Cast(id, AID.DistantClap, delay, 5, "Donut") + .ActivateOnEnter() + .DeactivateOnExit(); + } + + private void StateOfShock(uint id, float delay) + { + Cast(id, AID.StateOfShock, delay, 4); + ComponentCondition(id + 0x10, 0.9f, comp => comp.NumStuns > 0, "Grab tank") + .ActivateOnEnter() + .ActivateOnEnter(); + Cast(id + 0x20, AID.HighestStakes, 1.5f, 5); + ComponentCondition(id + 0x30, 0.8f, comp => comp.NumCasts > 0, "Tower 1") + .DeactivateOnExit(); + ComponentCondition(id + 0x40, 2, comp => comp.NumCasts > 0) + .ActivateOnEnter(); + ComponentCondition(id + 0x41, 0.9f, comp => comp.NumStuns > 0, "Grab tank"); + Cast(id + 0x50, AID.HighestStakes, 1.2f, 5); + ComponentCondition(id + 0x60, 0.8f, comp => comp.NumCasts > 1, "Tower 2") + .DeactivateOnExit() + .DeactivateOnExit(); + } + + private void UnrelentingAnguish1(uint id, float delay) + { + Cast(id, AID.UnrelentingAnguish, delay, 3, "Orbs start"); + StormPulse(id + 0x10, 2.2f); + ComponentCondition(id + 0x20, 2.9f, comp => comp.Targets.Any()) + .ActivateOnEnter(); + Cast(id + 0x30, AID.FireAndLightningBoss, 4.5f, 4, "Line") + .ActivateOnEnter() + .DeactivateOnExit(); + ComponentCondition(id + 0x40, 1.5f, comp => comp.Targets.None(), "Orbs end") + .DeactivateOnExit(); + } + + private void Hakutei1(uint id, float delay) + { + ActorTargetable(id, _module.Hakutei, true, delay, "Tiger appears") + .ActivateOnEnter(); // icons appear ~2s before tiger + ComponentCondition(id + 0x10, 3.1f, comp => comp.NumFinishedSpreads > 0, "Puddle baits start") + .ActivateOnEnter(); + StormPulse(id + 0x20, 4) + .ActivateOnEnter() + .DeactivateOnExit(); + ComponentCondition(id + 0x30, 0.1f, comp => comp.NumCasts > 0, "Cleave 1"); + CastStart(id + 0x40, AID.HeavenlyStrike, 6); + ComponentCondition(id + 0x41, 0.1f, comp => comp.NumCasts > 1, "Cleave 2") + .ActivateOnEnter() + .DeactivateOnExit(); + CastEnd(id + 0x42, 3.9f, "Tankbuster") + .DeactivateOnExit() + .SetHint(StateMachine.StateHint.Tankbuster); + ActorTargetable(id + 0x50, _module.Hakutei, false, 3.1f, "Tiger disappears"); + + ComponentCondition(id + 0x60, 0.7f, comp => comp.Active) + .ActivateOnEnter(); + CastStart(id + 0x61, AID.DistantClap, 2.4f); + ComponentCondition(id + 0x62, 2.7f, comp => comp.NumFinishedSpreads > 0, "Flare") + .ActivateOnEnter() + .DeactivateOnExit(); + ActorTargetable(id + 0x63, _module.Hakutei, true, 2, "Tiger reappears"); + CastEnd(id + 0x64, 0.3f, "Donut") + .DeactivateOnExit(); + ComponentCondition(id + 0x65, 3.9f, comp => comp.NumCasts > 0, "Line") + .ActivateOnEnter() + .DeactivateOnExit(); + StormPulse(id + 0x70, 0.2f) + .DeactivateOnExit(); + } + + private void Intermission(uint id, float delay) + { + ActorTargetable(id, _module.Boss, false, delay, "Boss disappears"); + ActorCast(id + 0x10, _module.Hakutei, AID.RoarOfThunder, 4.4f, 20, true, "Add enrage") + .ActivateOnEnter() + .DeactivateOnExit() + .SetHint(StateMachine.StateHint.Raidwide | StateMachine.StateHint.DowntimeStart); + ComponentCondition(id + 0x20, 42.2f, comp => comp.NumCasts > 0, "Donut 1") + .ActivateOnEnter() + .ActivateOnEnter(); + ComponentCondition(id + 0x21, 5.7f, comp => comp.NumCasts > 0, "Line 1") + .ActivateOnEnter(); + ComponentCondition(id + 0x22, 12, comp => comp.NumCasts > 1, "Line 2"); + ComponentCondition(id + 0x23, 13.6f, comp => comp.NumCasts > 1, "Donut 2") + .DeactivateOnExit() + .DeactivateOnExit(); + ComponentCondition(id + 0x24, 3.4f, comp => comp.NumCasts > 2, "Line 3") + .DeactivateOnExit(); + ComponentCondition(id + 0x25, 27.7f, comp => comp.NumCasts > 0, "Raidwide") + .ActivateOnEnter() + .DeactivateOnExit() + .SetHint(StateMachine.StateHint.Raidwide); + ActorTargetable(id + 0x30, _module.Boss, true, 7.9f, "Boss reappears") + .SetHint(StateMachine.StateHint.DowntimeEnd); + } + + private void HundredfoldHavoc1(uint id, float delay) + { + ComponentCondition(id, delay, comp => comp.Active) + .ActivateOnEnter(); + CastStart(id + 1, AID.StateOfShock, 2.1f); + ComponentCondition(id + 2, 2.9f, comp => comp.NumCasts > 0, "Exaflares start"); + CastEnd(id + 3, 1.1f); + + ComponentCondition(id + 0x10, 0.9f, comp => comp.NumStuns > 0, "Grab tank") + .ActivateOnEnter() + .ActivateOnEnter(); + Cast(id + 0x20, AID.HighestStakes, 1.5f, 5) + .DeactivateOnExit(); + ComponentCondition(id + 0x30, 0.8f, comp => comp.NumCasts > 0, "Tower 1") + .DeactivateOnExit(); + ComponentCondition(id + 0x40, 2, comp => comp.NumCasts > 0) + .ActivateOnEnter(); + ComponentCondition(id + 0x41, 0.9f, comp => comp.NumStuns > 0, "Grab tank"); + Cast(id + 0x50, AID.HighestStakes, 1.2f, 5); + ComponentCondition(id + 0x60, 0.8f, comp => comp.NumCasts > 1, "Tower 2") + .DeactivateOnExit() + .DeactivateOnExit(); + + Cast(id + 0x1000, AID.SweepTheLegBoss, 1.9f, 4, "Wide cone") + .ActivateOnEnter() + .DeactivateOnExit(); + } + + private void UnrelentingAnguish2(uint id, float delay) + { + Cast(id, AID.UnrelentingAnguish, delay, 3, "Orbs start"); + StormPulseDouble(id + 0x10, 2.1f); + + ComponentCondition(id + 0x20, 2, comp => comp.CurrentBaits.Count > 0) + .ActivateOnEnter(); + ComponentCondition(id + 0x21, 6.9f, comp => comp.Targets.Any()) + .ActivateOnEnter() + .ActivateOnEnter(); + ComponentCondition(id + 0x22, 1.2f, comp => comp.NumCasts > 0, "Baits") + .DeactivateOnExit(); + + Cast(id + 0x30, AID.FireAndLightningBoss, 3.4f, 4, "Line") + .ActivateOnEnter() + .DeactivateOnExit(); + ComponentCondition(id + 0x40, 1.5f, comp => comp.Targets.None(), "Orbs end") + .DeactivateOnExit(); + + Cast(id + 0x50, AID.FireAndLightningBoss, 3.4f, 4, "Line") + .ActivateOnEnter() + .DeactivateOnExit(); + ComponentCondition(id + 0x60, 0.7f, comp => comp.NumCasts >= 39, "Voidzones end") + .DeactivateOnExit(); + } + + private void Hakutei2(uint id, float delay) + { + ActorTargetable(id, _module.Hakutei, true, delay, "Tiger appears") + .ActivateOnEnter(); // icons appear ~2s before tiger + + ComponentCondition(id + 0x10, 3.1f, comp => comp.NumFinishedSpreads > 0, "Puddle baits start") + .ActivateOnEnter(); + ActorTargetable(id + 0x20, _module.Hakutei, false, 6, "Tiger disappears"); + + ComponentCondition(id + 0x30, 0.7f, comp => comp.Active) + .ActivateOnEnter(); + CastStart(id + 0x31, AID.DistantClap, 2.4f); + ComponentCondition(id + 0x32, 2.7f, comp => comp.NumFinishedSpreads > 0, "Flare") + .ActivateOnEnter() + .DeactivateOnExit(); + ActorTargetable(id + 0x33, _module.Hakutei, true, 2, "Tiger reappears"); + CastEnd(id + 0x34, 0.3f, "Donut 1") + .DeactivateOnExit(); + + CastStart(id + 0x40, AID.DistantClap, 3.2f) + .ActivateOnEnter(); + ComponentCondition(id + 0x41, 0.8f, comp => comp.NumCasts > 0, "Line 1") + .ActivateOnEnter() + .DeactivateOnExit(); + CastEnd(id + 0x42, 4.2f, "Donut 2") + .DeactivateOnExit(); + ComponentCondition(id + 0x50, 4, comp => comp.NumCasts > 0, "Line 2") + .ActivateOnEnter() + .DeactivateOnExit(); + + HeavenlyStrike(id + 0x100, 3.2f) + .ActivateOnEnter() + .DeactivateOnExit(); + + ActorCastStart(id + 0x200, _module.Hakutei, AID.RoarOfThunder, 10.6f, false) + .ActivateOnEnter() + .DeactivateOnExit(); + StormPulseDouble(id + 0x210, 5.7f); + ActorCastEnd(id + 0x220, _module.Hakutei, 8.1f, false, "Add enrage") + .DeactivateOnExit() + .SetHint(StateMachine.StateHint.Raidwide); + + Cast(id + 0x300, AID.FireAndLightningBoss, 8.3f, 4, "Line") + .ActivateOnEnter() + .DeactivateOnExit(); + } + + private void HundredfoldHavoc2(uint id, float delay) + { + ComponentCondition(id, delay, comp => comp.CurrentBaits.Count > 0) + .ActivateOnEnter(); + + ComponentCondition(id + 0x10, 2.2f, comp => comp.Active) + .ActivateOnEnter(); + CastStart(id + 0x11, AID.StateOfShock, 4.6f); + ComponentCondition(id + 0x12, 0.4f, comp => comp.NumCasts > 0, "Exaflares start"); + ComponentCondition(id + 0x13, 0.9f, comp => comp.NumCasts > 0, "Baits") + .ActivateOnEnter() + .DeactivateOnExit(); + CastEnd(id + 0x14, 2.7f); + + ComponentCondition(id + 0x20, 0.9f, comp => comp.NumStuns > 0, "Grab tank") + .ActivateOnEnter() + .ActivateOnEnter(); + Cast(id + 0x30, AID.HighestStakes, 1.3f, 5) + .DeactivateOnExit(); + ComponentCondition(id + 0x40, 0.8f, comp => comp.NumCasts > 0, "Tower 1") + .DeactivateOnExit(); + ComponentCondition(id + 0x50, 2, comp => comp.NumCasts > 0) + .ActivateOnEnter(); + ComponentCondition(id + 0x51, 0.9f, comp => comp.NumStuns > 0, "Grab tank"); + CastStart(id + 0x60, AID.HighestStakes, 1.2f); + ComponentCondition(id + 0x61, 3, comp => comp.NumCasts > 0, "Raidwide") + .ActivateOnEnter() + .DeactivateOnExit() + .DeactivateOnExit() + .SetHint(StateMachine.StateHint.Raidwide); + CastEnd(id + 0x62, 2); + ComponentCondition(id + 0x70, 0.8f, comp => comp.NumCasts > 1, "Tower 2") + .DeactivateOnExit() + .DeactivateOnExit(); + + Cast(id + 0x1000, AID.SweepTheLegBoss, 1.9f, 4, "Wide cone") + .ActivateOnEnter() + .DeactivateOnExit(); + } +} diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/UnrelentingAnguish.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/UnrelentingAnguish.cs new file mode 100644 index 0000000000..c207a4faa5 --- /dev/null +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/UnrelentingAnguish.cs @@ -0,0 +1,34 @@ +namespace BossMod.Dawntrail.Unreal.Un1Byakko; + +class UnrelentingAnguish(BossModule module) : Components.PersistentVoidzone(module, 2, m => m.Enemies(OID.AratamaForce).Where(z => !z.IsDead), 1); + +// TODO: show something +class OminousWind(BossModule module) : BossComponent(module) +{ + public BitMask Targets; + + public override void OnStatusGain(Actor actor, ActorStatus status) + { + if ((SID)status.ID == SID.OminousWind) + Targets.Set(Raid.FindSlot(actor.InstanceID)); + } + + public override void OnStatusLose(Actor actor, ActorStatus status) + { + if ((SID)status.ID == SID.OminousWind) + Targets.Clear(Raid.FindSlot(actor.InstanceID)); + } +} + +class GaleForce(BossModule module) : Components.BaitAwayIcon(module, new AOEShapeCircle(6), (uint)IconID.Bombogenesis, ActionID.MakeSpell(AID.GaleForce), 8.1f, true); + +class VacuumClaw(BossModule module) : Components.GenericAOEs(module, ActionID.MakeSpell(AID.VacuumClaw), "GTFO from voidzone!") +{ + private readonly IReadOnlyList _sources = module.Enemies(OID.VacuumClaw); + + private static readonly AOEShapeCircle _shape = new(10); // TODO: verify radius; initial voidzone is 6, but spell radius is 1 in sheets; after 5th hit we get 4 stacks of area-of-influence increase + + public override IEnumerable ActiveAOEs(int slot, Actor actor) => _sources.Select(s => new AOEInstance(_shape, s.Position)); +} + +class VacuumBlade(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.VacuumBlade)); From 7b5e38959b3e1a2c7043f5f93dc3e129659c8ee3 Mon Sep 17 00:00:00 2001 From: Andrew Gilewsky Date: Sat, 16 Nov 2024 17:47:21 +0000 Subject: [PATCH 2/5] Prepare to publish... --- .github/workflows/publish.yml | 6 +++--- BossMod/BossMod.csproj | 2 +- BossMod/Framework/ActionManagerEx.cs | 2 +- BossMod/Replay/ReplayParserLog.cs | 23 ++--------------------- FFXIVClientStructs | 2 +- TODO | 4 ---- UIDev/UIDev.csproj | 2 +- 7 files changed, 9 insertions(+), 32 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e12ee4452c..cc0f9451c6 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,9 +24,9 @@ jobs: with: dotnet-version: 8.0.x - - name: Download Dalamud Latest + - name: Download Dalamud Latest (TODO: revert back to master!) run: | - wget https://goatcorp.github.io/dalamud-distrib/latest.zip -O ${{ env.DALAMUD_HOME }}.zip + wget https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -O ${{ env.DALAMUD_HOME }}.zip unzip ${{ env.DALAMUD_HOME }}.zip -d ${{ env.DALAMUD_HOME }} - name: Restore Project @@ -44,6 +44,6 @@ jobs: version_number: ${{ env.tag }} path: "BossMod/bin/Release/BossMod/latest.zip" type: "latest" - dalamud_version: "10" + dalamud_version: "11" env: PUBLISHER_KEY: ${{ secrets.PUBLISHER_KEY }} diff --git a/BossMod/BossMod.csproj b/BossMod/BossMod.csproj index 323c897fa4..a997780a7a 100644 --- a/BossMod/BossMod.csproj +++ b/BossMod/BossMod.csproj @@ -38,7 +38,7 @@ - E:\sources\ff14\dalamud\Dalamud\bin\Debug\ + $(appdata)\XIVLauncher\addon\Hooks\dev\ diff --git a/BossMod/Framework/ActionManagerEx.cs b/BossMod/Framework/ActionManagerEx.cs index fd220224d0..bcee751d1e 100644 --- a/BossMod/Framework/ActionManagerEx.cs +++ b/BossMod/Framework/ActionManagerEx.cs @@ -338,7 +338,7 @@ private void UpdateDetour(ActionManager* self) var desiredRotation = CalculateDesiredOrientation(actionImminent); // execute rotation, if needed - var autoRotateConfig = fwk->SystemConfig.GetConfigOption(/*(uint)ConfigOption.AutoFaceTargetOnAction*/225); // TODO: 7.1: update config option + var autoRotateConfig = fwk->SystemConfig.GetConfigOption((uint)ConfigOption.AutoFaceTargetOnAction); var autoRotateOriginal = autoRotateConfig->Value.UInt; if (desiredRotation != null) { diff --git a/BossMod/Replay/ReplayParserLog.cs b/BossMod/Replay/ReplayParserLog.cs index dc17e5606b..aac9f76c8d 100644 --- a/BossMod/Replay/ReplayParserLog.cs +++ b/BossMod/Replay/ReplayParserLog.cs @@ -267,7 +267,6 @@ public static Replay Parse(string path, ref float progress, CancellationToken ca private ulong _qpcStart; private uint _legacyFrameIndex; private DateTime _legacyPrevTS; - private readonly Dictionary _legacyIcons = []; // TODO: remove private double _invQPF = 1.0 / TimeSpan.TicksPerSecond; private ReplayParserLog(Input input, ReplayBuilder builder) @@ -583,11 +582,7 @@ private ActorState.OpCastEvent ParseActorCastEvent() private ActorState.OpEffectResult ParseActorEffectResult() => new(_input.ReadActorID(), _input.ReadUInt(false), _input.ReadInt()); private ActorState.OpStatus ParseActorStatus(bool gainOrUpdate) => new(_input.ReadActorID(), _input.ReadInt(), gainOrUpdate ? _input.ReadStatus() : default); - private ActorState.OpIcon ParseActorIcon() - { - var source = _input.ReadActorID(); - return new(source, _input.ReadUInt(false), _version >= 22 ? _input.ReadActorID() : _legacyIcons.Remove(source, out var target) ? target : 0); - } + private ActorState.OpIcon ParseActorIcon() => new(_input.ReadActorID(), _input.ReadUInt(false), _version >= 22 ? _input.ReadActorID() : 0); private ActorState.OpEventObjectStateChange ParseActorEventObjectStateChange() => new(_input.ReadActorID(), _input.ReadUShort(true)); private ActorState.OpEventObjectAnimation ParseActorEventObjectAnimation() => new(_input.ReadActorID(), _input.ReadUShort(true), _input.ReadUShort(true)); private ActorState.OpPlayActionTimelineEvent ParseActorPlayActionTimelineEvent() => new(_input.ReadActorID(), _input.ReadUShort(true)); @@ -679,21 +674,7 @@ private ClientState.OpClassJobLevelsChange ParseClientClassJobLevels() private ClientState.OpFocusTargetChange ParseClientFocusTarget() => new(_input.ReadULong(true)); private NetworkState.OpIDScramble ParseNetworkIDScramble() => new(_input.ReadUInt(false)); - private NetworkState.OpServerIPC ParseNetworkServerIPC() - { - var packet = new NetworkState.ServerIPC((Network.ServerIPC.PacketID)_input.ReadInt(), _input.ReadUShort(false), _input.ReadUInt(false), _input.ReadUInt(true), new(_input.ReadLong()), _input.ReadBytes()); - if (_version < 22 && packet.ID == Network.ServerIPC.PacketID.ActorControl && packet.Payload[0] == (byte)Network.ServerIPC.ActorControlCategory.TargetIcon) - { - unsafe - { - fixed (byte* p = &packet.Payload[8]) - { - _legacyIcons[packet.SourceServerActor] = *(uint*)p; - } - } - } - return new(packet); - } + private NetworkState.OpServerIPC ParseNetworkServerIPC() => new(new((Network.ServerIPC.PacketID)_input.ReadInt(), _input.ReadUShort(false), _input.ReadUInt(false), _input.ReadUInt(true), new(_input.ReadLong()), _input.ReadBytes())); private ActorHPMP ReadActorHPMP() { diff --git a/FFXIVClientStructs b/FFXIVClientStructs index 028dd87ddb..31a434115b 160000 --- a/FFXIVClientStructs +++ b/FFXIVClientStructs @@ -1 +1 @@ -Subproject commit 028dd87ddbbc5c7851db8202b9d41676fa11d92f +Subproject commit 31a434115b617d94b239979f71fc48a60af68a43 diff --git a/TODO b/TODO index 5626bf276b..56c2f6786e 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,4 @@ immediate plans -- 7.1 --- revert csproj changes --- bump api version in workflow --- remove icontarget hack - nechuciho - seen incorrect rotations... - questbattles - collisions for pathfinding diff --git a/UIDev/UIDev.csproj b/UIDev/UIDev.csproj index 61d6968729..aec60ee2af 100644 --- a/UIDev/UIDev.csproj +++ b/UIDev/UIDev.csproj @@ -10,7 +10,7 @@ - E:\sources\ff14\dalamud\Dalamud\bin\Debug\ + $(appdata)\XIVLauncher\addon\Hooks\dev\ From ada1ef1c2765f6b6af5620f60fb1df2ae100f3ee Mon Sep 17 00:00:00 2001 From: Andrew Gilewsky Date: Sat, 16 Nov 2024 17:51:08 +0000 Subject: [PATCH 3/5] Ok github... --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index cc0f9451c6..1180a3349d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,7 +24,7 @@ jobs: with: dotnet-version: 8.0.x - - name: Download Dalamud Latest (TODO: revert back to master!) + - name: Download Dalamud Latest run: | wget https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -O ${{ env.DALAMUD_HOME }}.zip unzip ${{ env.DALAMUD_HOME }}.zip -d ${{ env.DALAMUD_HOME }} From 39a8d3d55251109eb04d1bb07641e236abcf135c Mon Sep 17 00:00:00 2001 From: Andrew Gilewsky Date: Sat, 16 Nov 2024 17:55:18 +0000 Subject: [PATCH 4/5] Fix CA errors. --- BossMod/AI/AIManager.cs | 65 ++----------------- .../Unreal/Un1Byakko/Intermission.cs | 2 +- 2 files changed, 6 insertions(+), 61 deletions(-) diff --git a/BossMod/AI/AIManager.cs b/BossMod/AI/AIManager.cs index eda32e28d5..cb00d29377 100644 --- a/BossMod/AI/AIManager.cs +++ b/BossMod/AI/AIManager.cs @@ -6,10 +6,9 @@ namespace BossMod.AI; -sealed class AIManager : IDisposable +sealed class AIManager(RotationModuleManager autorot, ActionManagerEx amex, MovementOverride movement) : IDisposable { - private readonly RotationModuleManager _autorot; - private readonly AIController _controller; + private readonly AIController _controller = new(autorot.WorldState, amex, movement); public readonly AIConfig Config = Service.Config.Get(); public AIBehaviour? Behaviour { get; private set; } @@ -17,7 +16,7 @@ sealed class AIManager : IDisposable public string NaviStatus { get; private set; } = ""; public int MasterSlot => (int)Config.FollowSlot; // non-zero means corresponding player is master - public WorldState WorldState => _autorot.Bossmods.WorldState; + public WorldState WorldState => autorot.Bossmods.WorldState; public float ForceMovementIn => Behaviour?.ForceMovementIn ?? float.MaxValue; // TODO: this is not good, callers should use SwitchToXXX directly @@ -36,17 +35,9 @@ public bool Enabled } } - public AIManager(RotationModuleManager autorot, ActionManagerEx amex, MovementOverride movement) - { - _autorot = autorot; - _controller = new(autorot.WorldState, amex, movement); - //Service.ChatGui.ChatMessage += OnChatMessage; - } - public void Dispose() { SwitchToIdle(); - //Service.ChatGui.ChatMessage -= OnChatMessage; } public void Update() @@ -71,7 +62,7 @@ public void Update() _controller.Clear(); } - _controller.Update(player, _autorot.Hints, WorldState.CurrentTime); + _controller.Update(player, autorot.Hints, WorldState.CurrentTime); AIStatus = $"AI: {(Behaviour != null ? $"on, {$"master={master?.Name}[{(int)Config.FollowSlot + 1}]"}" : "off")}"; var dist = _controller.NaviTargetPos != null && player != null ? (_controller.NaviTargetPos.Value - player.Position).Length() : 0; NaviStatus = $"Navi={_controller.NaviTargetPos?.ToString() ?? ""} (d={dist:f3}, max-cast={MathF.Min(Behaviour?.ForceMovementIn ?? float.MaxValue, 1000):f3})"; @@ -92,52 +83,6 @@ public void SwitchToFollow(int masterSlot) SwitchToIdle(); Config.FollowSlot = (AIConfig.Slot)masterSlot; Config.Modified.Fire(); - Behaviour = new AIBehaviour(_controller, _autorot); + Behaviour = new AIBehaviour(_controller, autorot); } - - //private unsafe int FindPartyMemberSlotFromSender(SeString sender) - //{ - // if (sender.Payloads.FirstOrDefault() is not PlayerPayload source) - // return -1; - // var group = GroupManager.Instance()->GetGroup(); - // var slot = -1; - // for (int i = 0; i < group->MemberCount; ++i) - // { - // if (group->PartyMembers[i].HomeWorld == source.World.RowId && group->PartyMembers[i].NameString == source.PlayerName) - // { - // slot = i; - // break; - // } - // } - // return slot >= 0 ? Array.FindIndex(WorldState.Party.Members, m => m.ContentId == group->PartyMembers[slot].ContentId) : -1; - //} - - //private void OnChatMessage(XivChatType type, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled) - //{ - // if (!Config.Enabled || type != XivChatType.Party) - // return; - - // var messagePrefix = message.Payloads.FirstOrDefault() as TextPayload; - // if (messagePrefix?.Text == null || !messagePrefix.Text.StartsWith("vbmai ", StringComparison.Ordinal)) - // return; - - // var messageData = messagePrefix.Text.Split(' '); - // if (messageData.Length < 2) - // return; - - // switch (messageData[1]) - // { - // case "follow": - // var master = FindPartyMemberSlotFromSender(sender); - // if (master >= 0) - // SwitchToFollow(master); - // break; - // case "cancel": - // SwitchToIdle(); - // break; - // default: - // Service.Log($"[AI] Unknown command: {messageData[1]}"); - // break; - // } - //} } diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs index d8a72a1b8d..91358214c4 100644 --- a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs @@ -18,7 +18,7 @@ class IntermissionOrbAratama(BossModule module) : Components.GenericAOEs(module, { public readonly List AOEs = []; - public static readonly AOEShapeCircle _shape = new(2); + private static readonly AOEShapeCircle _shape = new(2); public override IEnumerable ActiveAOEs(int slot, Actor actor) => AOEs; From 6f2eb18df460da2494033c0f15c0529d3c6af02f Mon Sep 17 00:00:00 2001 From: CarnifexOptimus <156172553+CarnifexOptimus@users.noreply.github.com> Date: Sat, 16 Nov 2024 19:38:42 +0100 Subject: [PATCH 5/5] merge fixes --- BossMod/AI/AIManager.cs | 2 +- .../Dawntrail/Extreme/Ex3QueenEternal/Ex3QueenEternal.cs | 2 +- .../Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs | 2 +- BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1Byakko.cs | 8 ++++---- .../Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoEnums.cs | 1 + .../Dawntrail/Unreal/Un1Byakko/UnrelentingAnguish.cs | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/BossMod/AI/AIManager.cs b/BossMod/AI/AIManager.cs index a837847d4d..1bc3226c64 100644 --- a/BossMod/AI/AIManager.cs +++ b/BossMod/AI/AIManager.cs @@ -6,7 +6,7 @@ namespace BossMod.AI; -sealed class AIManager(RotationModuleManager autorot, ActionManagerEx amex, MovementOverride movement) : IDisposable +sealed class AIManager : IDisposable { public static AIManager? Instance; public readonly RotationModuleManager Autorot; diff --git a/BossMod/Modules/Dawntrail/Extreme/Ex3QueenEternal/Ex3QueenEternal.cs b/BossMod/Modules/Dawntrail/Extreme/Ex3QueenEternal/Ex3QueenEternal.cs index 5be14eb56f..fca44a7e0d 100644 --- a/BossMod/Modules/Dawntrail/Extreme/Ex3QueenEternal/Ex3QueenEternal.cs +++ b/BossMod/Modules/Dawntrail/Extreme/Ex3QueenEternal/Ex3QueenEternal.cs @@ -4,7 +4,7 @@ class ProsecutionOfWar(BossModule module) : Components.TankSwap(module, ActionID class DyingMemory(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.DyingMemory)); class DyingMemoryLast(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.DyingMemoryLast)); -[ModuleInfo(BossModuleInfo.Maturity.Contributed, Contributors = "veyn, Malediktus", PlanLevel = 100, PrimaryActorOID = (uint)OID.BossP1, GroupType = BossModuleInfo.GroupType.CFC, GroupID = 1017, NameID = 13029)] +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn, Malediktus", PrimaryActorOID = (uint)OID.BossP1, GroupType = BossModuleInfo.GroupType.CFC, GroupID = 1017, NameID = 13029, PlanLevel = 100)] public class Ex3QueenEternal(WorldState ws, Actor primary) : BossModule(ws, primary, ArenaCenter, NormalBounds) { public static readonly WPos ArenaCenter = Trial.T03QueenEternal.T03QueenEternal.ArenaCenter; diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs index 91358214c4..3fdbb0a5d7 100644 --- a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs @@ -10,7 +10,7 @@ public VoiceOfThunder(BossModule module) : base(module, 2, m => m.Enemies(OID.Ar public override void AddHints(int slot, Actor actor, TextHints hints) { if (Sources(Module).Any(x => !Shape.Check(actor.Position, x))) - hints.Add("Touch the balls!"); + hints.Add("Touch the orbs!"); } } diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1Byakko.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1Byakko.cs index 94620b9296..67ce2bf71f 100644 --- a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1Byakko.cs +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1Byakko.cs @@ -9,8 +9,8 @@ class WhiteHerald(BossModule module) : Components.SpreadFromIcon(module, (uint)I class DistantClap(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.DistantClap), new AOEShapeDonut(4, 25)); class SweepTheLegBoss(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.SweepTheLegBoss), new AOEShapeCone(28.3f, 135.Degrees())); -[ModuleInfo(BossModuleInfo.Maturity.Verified, GroupType = BossModuleInfo.GroupType.CFC, GroupID = 1007, NameID = 7092, PlanLevel = 100)] -public class Un1Byakko(WorldState ws, Actor primary) : BossModule(ws, primary, new(0, 0), new ArenaBoundsCircle(20)) +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "veyn", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 1007, NameID = 7092, PlanLevel = 100)] +public class Un1Byakko(WorldState ws, Actor primary) : BossModule(ws, primary, default, new ArenaBoundsCircle(20)) { private Actor? _hakutei; public Actor? Boss() => PrimaryActor; @@ -25,7 +25,7 @@ protected override void UpdateModule() protected override void DrawEnemies(int pcSlot, Actor pc) { - Arena.Actor(PrimaryActor, ArenaColor.Enemy); - Arena.Actor(_hakutei, ArenaColor.Enemy); + Arena.Actor(PrimaryActor); + Arena.Actor(_hakutei); } } diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoEnums.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoEnums.cs index 8281c4c2bb..fd54d1cd8d 100644 --- a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoEnums.cs +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoEnums.cs @@ -32,6 +32,7 @@ public enum AID : uint UnrelentingAnguish = 39950, // Boss->self, 3.0s cast, single-target, visual (orbs) UnrelentingAnguishAratama = 39958, // AratamaForce->self, no cast, range 2 circle, orb explosion OminousWind = 39948, // Boss->self, no cast, single-target, apply bubbles + OminousWindAOE = 39949, // Helper->self, no cast, range 6 circle FireAndLightningBoss = 39930, // Boss->self, 4.0s cast, range 50+R width 20 rect DanceOfTheIncomplete = 39924, // Boss->self, no cast, single-target, visual (split off tiger) diff --git a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/UnrelentingAnguish.cs b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/UnrelentingAnguish.cs index c207a4faa5..93552400fa 100644 --- a/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/UnrelentingAnguish.cs +++ b/BossMod/Modules/Dawntrail/Unreal/Un1Byakko/UnrelentingAnguish.cs @@ -1,6 +1,6 @@ namespace BossMod.Dawntrail.Unreal.Un1Byakko; -class UnrelentingAnguish(BossModule module) : Components.PersistentVoidzone(module, 2, m => m.Enemies(OID.AratamaForce).Where(z => !z.IsDead), 1); +class UnrelentingAnguish(BossModule module) : Components.PersistentVoidzone(module, 2, m => m.Enemies(OID.AratamaForce).Where(z => !z.IsDead), 2); // TODO: show something class OminousWind(BossModule module) : BossComponent(module)