-
Notifications
You must be signed in to change notification settings - Fork 116
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
1,097 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
142 changes: 142 additions & 0 deletions
142
BossMod/Modules/Dawntrail/Savage/RM03SBruteBomber/BarbarousBarrage.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
namespace BossMod.Dawntrail.Savage.RM03SBruteBomber; | ||
|
||
class BarbarousBarrageTowers(BossModule module) : Components.GenericTowers(module) | ||
{ | ||
public enum State { None, NextNS, NextEW, NextCorners, NextCenter, Done } | ||
|
||
public State CurState; | ||
|
||
public override void DrawArenaForeground(int pcSlot, Actor pc) | ||
{ | ||
base.DrawArenaForeground(pcSlot, pc); | ||
// draw next towers to aim knockback | ||
if (CurState != State.None) | ||
foreach (var p in TowerPositions(CurState == State.NextNS ? State.NextCorners : CurState + 1)) | ||
Arena.AddCircle(p, 4, ArenaColor.Object); | ||
} | ||
|
||
public override void OnEventEnvControl(byte index, uint state) | ||
{ | ||
if (CurState == State.None && index is 14 or 15) | ||
SetState(index == 14 ? State.NextNS : State.NextEW, 4); | ||
} | ||
|
||
public override void OnEventCast(Actor caster, ActorCastEvent spell) | ||
{ | ||
switch ((AID)spell.Action.ID) | ||
{ | ||
case AID.BarbarousBarrageExplosion4: | ||
SetState(State.NextCorners, 2); | ||
break; | ||
case AID.BarbarousBarrageExplosion2: | ||
SetState(State.NextCenter, 8); | ||
break; | ||
case AID.BarbarousBarrageExplosion8: | ||
SetState(State.Done, 1); | ||
break; | ||
} | ||
} | ||
|
||
private void SetState(State state, int soakers) | ||
{ | ||
if (CurState != state) | ||
{ | ||
CurState = state; | ||
Towers.Clear(); | ||
foreach (var p in TowerPositions(state)) | ||
Towers.Add(new(p, 4, soakers, soakers)); | ||
} | ||
} | ||
|
||
private IEnumerable<WPos> TowerPositions(State state) | ||
{ | ||
switch (state) | ||
{ | ||
case State.NextNS: | ||
yield return Module.Center + new WDir(0, -11); | ||
yield return Module.Center + new WDir(0, +11); | ||
break; | ||
case State.NextEW: | ||
yield return Module.Center + new WDir(-11, 0); | ||
yield return Module.Center + new WDir(+11, 0); | ||
break; | ||
case State.NextCorners: | ||
yield return Module.Center + new WDir(-11, -11); | ||
yield return Module.Center + new WDir(-11, +11); | ||
yield return Module.Center + new WDir(+11, -11); | ||
yield return Module.Center + new WDir(+11, +11); | ||
break; | ||
case State.NextCenter: | ||
yield return Module.Center; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
class BarbarousBarrageKnockback(BossModule module) : Components.Knockback(module) | ||
{ | ||
private readonly BarbarousBarrageTowers? _towers = module.FindComponent<BarbarousBarrageTowers>(); | ||
|
||
private static readonly AOEShapeCircle _shape = new(4); | ||
|
||
public override IEnumerable<Source> Sources(int slot, Actor actor) | ||
{ | ||
if (_towers != null) | ||
{ | ||
foreach (var t in _towers.Towers) | ||
{ | ||
var dist = t.MinSoakers switch | ||
{ | ||
4 => 23, | ||
2 => 19, | ||
8 => 15, | ||
_ => 0 | ||
}; | ||
yield return new(t.Position, dist, default, _shape); | ||
} | ||
} | ||
} | ||
} | ||
|
||
class BarbarousBarrageMurderousMist(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.BarbarousBarrageMurderousMist), new AOEShapeCone(40, 135.Degrees())); | ||
|
||
class BarbarousBarrageLariatCombo(BossModule module) : Components.GenericAOEs(module) | ||
{ | ||
public readonly List<AOEInstance> AOEs = []; | ||
|
||
private static readonly AOEShapeRect _shape = new(70, 17); | ||
|
||
public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor) => AOEs.Skip(NumCasts).Take(1); | ||
|
||
public override void OnCastStarted(Actor caster, ActorCastInfo spell) | ||
{ | ||
var (off1, off2) = (AID)spell.Action.ID switch | ||
{ | ||
AID.BarbarousBarrageLariatComboFirstRR => (-90.Degrees(), -90.Degrees()), | ||
AID.BarbarousBarrageLariatComboFirstRL => (-90.Degrees(), 90.Degrees()), | ||
AID.BarbarousBarrageLariatComboFirstLR => (90.Degrees(), -90.Degrees()), | ||
AID.BarbarousBarrageLariatComboFirstLL => (90.Degrees(), 90.Degrees()), | ||
_ => default | ||
}; | ||
if (off1 != default) | ||
{ | ||
var from = caster.Position; | ||
var to = spell.LocXZ; | ||
var offset = 0.6667f * (to - from); | ||
var dir1 = Angle.FromDirection(offset); | ||
var dir2 = dir1 + 180.Degrees(); | ||
AOEs.Add(new(_shape, from - offset + 12 * (dir1 + off1).ToDirection(), dir1, Module.CastFinishAt(spell, 1.2f))); | ||
AOEs.Add(new(_shape, to + offset + 12 * (dir2 + off2).ToDirection(), dir2, Module.CastFinishAt(spell, 5.6f))); | ||
} | ||
} | ||
|
||
public override void OnCastFinished(Actor caster, ActorCastInfo spell) | ||
{ | ||
if ((AID)spell.Action.ID is AID.BarbarousBarrageLariatComboFirstRAOE or AID.BarbarousBarrageLariatComboFirstLAOE or AID.BarbarousBarrageLariatComboSecondRAOE or AID.BarbarousBarrageLariatComboSecondLAOE) | ||
{ | ||
if (NumCasts < AOEs.Count && !spell.LocXZ.AlmostEqual(AOEs[NumCasts].Origin, 2)) | ||
ReportError($"Unexpected AOE: {spell.Location} vs {AOEs[NumCasts].Origin}"); | ||
++NumCasts; | ||
} | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
BossMod/Modules/Dawntrail/Savage/RM03SBruteBomber/BombarianSpecial.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
namespace BossMod.Dawntrail.Savage.RM03SBruteBomber; | ||
|
||
class BombarianSpecial(BossModule module) : Components.UniformStackSpread(module, 5, 5, alwaysShowSpreads: true) | ||
{ | ||
public enum Mechanic { None, Spread, Pairs } | ||
|
||
public Mechanic CurMechanic; | ||
|
||
public void Show(float delay) | ||
{ | ||
switch (CurMechanic) | ||
{ | ||
case Mechanic.Spread: | ||
AddSpreads(Raid.WithoutSlot(true), WorldState.FutureTime(delay)); | ||
break; | ||
case Mechanic.Pairs: | ||
// TODO: can target any role | ||
AddStacks(Raid.WithoutSlot(true).Where(p => p.Class.IsSupport()), WorldState.FutureTime(delay)); | ||
break; | ||
} | ||
} | ||
|
||
public override void AddGlobalHints(GlobalHints hints) | ||
{ | ||
if (CurMechanic != Mechanic.None) | ||
hints.Add(CurMechanic.ToString()); | ||
} | ||
|
||
public override void OnCastStarted(Actor caster, ActorCastInfo spell) | ||
{ | ||
var mechanic = (AID)spell.Action.ID switch | ||
{ | ||
AID.OctoboomBombarianSpecial => Mechanic.Spread, | ||
AID.QuadroboomBombarianSpecial => Mechanic.Pairs, | ||
_ => Mechanic.None | ||
}; | ||
if (mechanic != Mechanic.None) | ||
CurMechanic = mechanic; | ||
} | ||
|
||
public override void OnEventCast(Actor caster, ActorCastEvent spell) | ||
{ | ||
if ((AID)spell.Action.ID is AID.BombariboomSpread or AID.BombariboomPair) | ||
{ | ||
Spreads.Clear(); | ||
Stacks.Clear(); | ||
CurMechanic = Mechanic.None; | ||
} | ||
} | ||
} | ||
|
||
class BombarianSpecialRaidwide(BossModule module) : Components.CastCounter(module, default) | ||
{ | ||
public override void OnEventCast(Actor caster, ActorCastEvent spell) | ||
{ | ||
if ((AID)spell.Action.ID is AID.BombarianSpecialRaidwide1 or AID.BombarianSpecialRaidwide2 or AID.BombarianSpecialRaidwide3 or AID.BombarianSpecialRaidwide4 or AID.BombarianSpecialRaidwide5 or AID.BombarianSpecialRaidwide6 | ||
or AID.SpecialBombarianSpecialRaidwide1 or AID.SpecialBombarianSpecialRaidwide2 or AID.SpecialBombarianSpecialRaidwide3 or AID.SpecialBombarianSpecialRaidwide4 or AID.SpecialBombarianSpecialRaidwide5 or AID.SpecialBombarianSpecialRaidwide6) | ||
{ | ||
++NumCasts; | ||
} | ||
} | ||
} | ||
|
||
class BombarianSpecialOut(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.BombarianSpecialOut), new AOEShapeCircle(10)); | ||
class BombarianSpecialIn(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.BombarianSpecialIn), new AOEShapeDonut(6, 40)); | ||
class BombarianSpecialAOE(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.BombarianSpecialAOE), new AOEShapeCircle(8)); | ||
class BombarianSpecialKnockback(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.BombarianSpecialKnockback), 10); | ||
class SpecialBombarianSpecialOut(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.SpecialBombarianSpecialOut), new AOEShapeCircle(10)); | ||
class SpecialBombarianSpecialIn(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.SpecialBombarianSpecialIn), new AOEShapeDonut(6, 40)); |
34 changes: 34 additions & 0 deletions
34
BossMod/Modules/Dawntrail/Savage/RM03SBruteBomber/Diveboom.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
namespace BossMod.Dawntrail.Savage.RM03SBruteBomber; | ||
|
||
class OctoboomDiveProximity(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.OctoboomDiveProximityAOE), new AOEShapeCircle(20)); // TODO: verify falloff | ||
class OctoboomDiveKnockback(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.OctoboomDiveKnockbackAOE), 25); | ||
class QuadroboomDiveProximity(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.QuadroboomDiveProximityAOE), new AOEShapeCircle(20)); // TODO: verify falloff | ||
class QuadroboomDiveKnockback(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.QuadroboomDiveKnockbackAOE), 25); | ||
|
||
class Diveboom(BossModule module) : Components.UniformStackSpread(module, 5, 5, alwaysShowSpreads: true) | ||
{ | ||
public override void OnCastStarted(Actor caster, ActorCastInfo spell) | ||
{ | ||
switch ((AID)spell.Action.ID) | ||
{ | ||
case AID.OctoboomDiveProximityAOE: | ||
case AID.OctoboomDiveKnockbackAOE: | ||
AddSpreads(Raid.WithoutSlot(true), Module.CastFinishAt(spell)); | ||
break; | ||
case AID.QuadroboomDiveProximityAOE: | ||
case AID.QuadroboomDiveKnockbackAOE: | ||
// TODO: can target any role | ||
AddStacks(Raid.WithoutSlot(true).Where(p => p.Class.IsSupport()), Module.CastFinishAt(spell)); | ||
break; | ||
} | ||
} | ||
|
||
public override void OnEventCast(Actor caster, ActorCastEvent spell) | ||
{ | ||
if ((AID)spell.Action.ID is AID.DiveboomSpread or AID.DiveboomPair) | ||
{ | ||
Spreads.Clear(); | ||
Stacks.Clear(); | ||
} | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
BossMod/Modules/Dawntrail/Savage/RM03SBruteBomber/FinalFusedown.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
namespace BossMod.Dawntrail.Savage.RM03SBruteBomber; | ||
|
||
class FinalFusedownSelfDestruct(BossModule module) : Components.GenericAOEs(module) | ||
{ | ||
private readonly List<AOEInstance> _aoes = []; | ||
|
||
private static readonly AOEShapeCircle _shape = new(8); | ||
|
||
public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor) => _aoes.Skip(NumCasts).Take(4); | ||
|
||
public override void OnStatusGain(Actor actor, ActorStatus status) | ||
{ | ||
var delay = (SID)status.ID switch | ||
{ | ||
SID.FinalFusedownFutureSelfDestructShort => 12.2f, | ||
SID.FinalFusedownFutureSelfDestructLong => 17.2f, | ||
_ => 0 | ||
}; | ||
if (delay > 0) | ||
{ | ||
_aoes.Add(new(_shape, actor.Position, default, WorldState.FutureTime(delay))); | ||
_aoes.SortBy(aoe => aoe.Activation); | ||
} | ||
} | ||
|
||
public override void OnEventCast(Actor caster, ActorCastEvent spell) | ||
{ | ||
if ((AID)spell.Action.ID is AID.FinalFusedownSelfDestructShort or AID.FinalFusedownSelfDestructLong) | ||
++NumCasts; | ||
} | ||
} | ||
|
||
class FinalFusedownExplosion(BossModule module) : Components.GenericStackSpread(module, true) | ||
{ | ||
public int NumCasts; | ||
private readonly List<Spread> _spreads1 = []; | ||
private readonly List<Spread> _spreads2 = []; | ||
|
||
public void Show() => Spreads = _spreads1; | ||
|
||
public override void OnStatusGain(Actor actor, ActorStatus status) | ||
{ | ||
(List<Spread>? list, float delay) = (SID)status.ID switch | ||
{ | ||
SID.FinalFusedownFutureExplosionShort => (_spreads1, 12.2f), | ||
SID.FinalFusedownFutureExplosionLong => (_spreads2, 17.2f), | ||
_ => (null, 0) | ||
}; | ||
list?.Add(new(actor, 6, WorldState.FutureTime(delay))); | ||
} | ||
|
||
public override void OnEventCast(Actor caster, ActorCastEvent spell) | ||
{ | ||
switch ((AID)spell.Action.ID) | ||
{ | ||
case AID.FinalFusedownExplosionShort: | ||
++NumCasts; | ||
Spreads = _spreads2; | ||
break; | ||
case AID.FinalFusedownExplosionLong: | ||
++NumCasts; | ||
Spreads.Clear(); | ||
break; | ||
} | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
BossMod/Modules/Dawntrail/Savage/RM03SBruteBomber/FuseOrFoe.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
namespace BossMod.Dawntrail.Savage.RM03SBruteBomber; | ||
|
||
class InfernalSpin(BossModule module) : Components.GenericRotatingAOE(module) | ||
{ | ||
private static readonly AOEShapeCone _shape = new(40, 30.Degrees()); | ||
|
||
public override void OnCastStarted(Actor caster, ActorCastInfo spell) | ||
{ | ||
var increment = (AID)spell.Action.ID switch | ||
{ | ||
AID.InfernalSpinFirstCW => -45.Degrees(), | ||
AID.InfernalSpinFirstCCW => 45.Degrees(), | ||
_ => default | ||
}; | ||
if (increment != default) | ||
{ | ||
Sequences.Add(new(_shape, caster.Position, spell.Rotation, increment, Module.CastFinishAt(spell, 0.5f), 1.1f, 8)); | ||
} | ||
} | ||
|
||
public override void OnCastFinished(Actor caster, ActorCastInfo spell) | ||
{ | ||
if (Sequences.Count > 0 && (AID)spell.Action.ID is AID.InfernalSpinFirstAOE or AID.InfernalSpinRestAOE) | ||
{ | ||
AdvanceSequence(0, WorldState.CurrentTime); | ||
} | ||
} | ||
} | ||
|
||
class ExplosiveRain(BossModule module) : Components.ConcentricAOEs(module, _shapes) | ||
{ | ||
private static readonly AOEShape[] _shapes = [new AOEShapeCircle(8), new AOEShapeDonut(8, 16), new AOEShapeDonut(16, 24)]; | ||
|
||
public override void OnCastStarted(Actor caster, ActorCastInfo spell) | ||
{ | ||
if ((AID)spell.Action.ID is AID.ExplosiveRain11 or AID.ExplosiveRain21) | ||
AddSequence(caster.Position, Module.CastFinishAt(spell)); | ||
} | ||
|
||
public override void OnEventCast(Actor caster, ActorCastEvent spell) | ||
{ | ||
var order = (AID)spell.Action.ID switch | ||
{ | ||
AID.ExplosiveRain11 or AID.ExplosiveRain21 => 0, | ||
AID.ExplosiveRain12 or AID.ExplosiveRain22 => 1, | ||
AID.ExplosiveRain13 or AID.ExplosiveRain23 => 2, | ||
_ => -1 | ||
}; | ||
if (!AdvanceSequence(order, caster.Position, WorldState.FutureTime(4))) | ||
ReportError($"Unexpected ring {order}"); | ||
} | ||
} |
Oops, something went wrong.