Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge Byakko unreal #442

Merged
merged 6 commits into from
Nov 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion BossMod/Framework/ActionManagerEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
19 changes: 19 additions & 0 deletions BossMod/Modules/Dawntrail/Unreal/Un1Byakko/AratamaPuddle.cs
Original file line number Diff line number Diff line change
@@ -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));
30 changes: 30 additions & 0 deletions BossMod/Modules/Dawntrail/Unreal/Un1Byakko/HundredfoldHavoc.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
42 changes: 42 additions & 0 deletions BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Intermission.cs
Original file line number Diff line number Diff line change
@@ -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 orbs!");
}
}

class IntermissionOrbAratama(BossModule module) : Components.GenericAOEs(module, ActionID.MakeSpell(AID.IntermissionOrbAratama), "GTFO from puddle!")
{
public readonly List<AOEInstance> AOEs = [];

private static readonly AOEShapeCircle _shape = new(2);

public override IEnumerable<AOEInstance> 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));
42 changes: 42 additions & 0 deletions BossMod/Modules/Dawntrail/Unreal/Un1Byakko/StateOfShock.cs
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
31 changes: 31 additions & 0 deletions BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1Byakko.cs
Original file line number Diff line number Diff line change
@@ -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, 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;
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);
Arena.Actor(_hakutei);
}
}
84 changes: 84 additions & 0 deletions BossMod/Modules/Dawntrail/Unreal/Un1Byakko/Un1ByakkoEnums.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
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
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)
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
}
Loading