-
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
10 changed files
with
800 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
66 changes: 66 additions & 0 deletions
66
BossMod/Modules/Dawntrail/Savage/RM02SHoneyBLovely/DropSplashOfVenom.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.RM02SHoneyBLovely; | ||
|
||
class DropSplashOfVenom(BossModule module) : Components.UniformStackSpread(module, 6, 6, 2, 2, alwaysShowSpreads: true) | ||
{ | ||
public enum Mechanic { None, Pairs, Spread } | ||
|
||
private Mechanic NextMechanic; | ||
|
||
public override void AddGlobalHints(GlobalHints hints) | ||
{ | ||
if (NextMechanic != Mechanic.None) | ||
hints.Add(NextMechanic.ToString()); | ||
} | ||
|
||
public override void OnCastStarted(Actor caster, ActorCastInfo spell) | ||
{ | ||
switch ((AID)spell.Action.ID) | ||
{ | ||
case AID.SplashOfVenom: | ||
case AID.SpreadLove: | ||
NextMechanic = Mechanic.Spread; | ||
break; | ||
case AID.DropOfVenom: | ||
case AID.DropOfLove: | ||
NextMechanic = Mechanic.Pairs; | ||
break; | ||
} | ||
} | ||
|
||
public override void OnEventCast(Actor caster, ActorCastEvent spell) | ||
{ | ||
switch ((AID)spell.Action.ID) | ||
{ | ||
case AID.TemptingTwistAOE: | ||
case AID.HoneyBeelineAOE: | ||
case AID.TemptingTwistBeatAOE: | ||
case AID.HoneyBeelineBeatAOE: | ||
switch (NextMechanic) | ||
{ | ||
case Mechanic.Pairs: | ||
// note: it's random whether dd or supports are hit, select supports arbitrarily | ||
AddStacks(Raid.WithoutSlot(true).Where(p => p.Class.IsSupport()), WorldState.FutureTime(4.5f)); | ||
break; | ||
case Mechanic.Spread: | ||
AddSpreads(Raid.WithoutSlot(true), WorldState.FutureTime(4.5f)); | ||
break; | ||
} | ||
break; | ||
case AID.SplashOfVenomAOE: | ||
case AID.DropOfVenomAOE: | ||
case AID.SpreadLoveAOE: | ||
case AID.DropOfLoveAOE: | ||
Spreads.Clear(); | ||
Stacks.Clear(); | ||
NextMechanic = Mechanic.None; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
class TemptingTwist(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.TemptingTwistAOE), new AOEShapeDonut(6, 30)); // TODO: verify inner radius | ||
class TemptingTwistBeat(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.TemptingTwistBeatAOE), new AOEShapeDonut(6, 30)); // TODO: verify inner radius | ||
class HoneyBeeline(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.HoneyBeelineAOE), new AOEShapeRect(30, 7, 30)); | ||
class HoneyBeelineBeat(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.HoneyBeelineBeatAOE), new AOEShapeRect(30, 7, 30)); | ||
class PoisonCloudSplinter(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.PoisonCloudSplinter), new AOEShapeCircle(8)); | ||
class SweetheartSplinter(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.SweetheartSplinter), new AOEShapeCircle(8)); |
187 changes: 187 additions & 0 deletions
187
BossMod/Modules/Dawntrail/Savage/RM02SHoneyBLovely/HoneyBLiveBeat.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,187 @@ | ||
namespace BossMod.Dawntrail.Savage.RM02SHoneyBLovely; | ||
|
||
class HoneyBLiveBeat1(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.HoneyBLiveBeat1AOE)); | ||
class HoneyBLiveBeat2(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.HoneyBLiveBeat2AOE)); | ||
class HoneyBLiveBeat3(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.HoneyBLiveBeat3AOE)); | ||
|
||
class HoneyBLiveHearts(BossModule module) : BossComponent(module) | ||
{ | ||
public int[] Hearts = new int[PartyState.MaxPartySize]; | ||
|
||
public override void OnStatusGain(Actor actor, ActorStatus status) | ||
{ | ||
var hearts = NumHearts((SID)status.ID); | ||
if (hearts >= 0 && Raid.FindSlot(actor.InstanceID) is var slot && slot >= 0) | ||
Hearts[slot] = hearts; | ||
} | ||
|
||
public override void OnStatusLose(Actor actor, ActorStatus status) | ||
{ | ||
var hearts = NumHearts((SID)status.ID); | ||
if (hearts >= 0 && Raid.FindSlot(actor.InstanceID) is var slot && slot >= 0 && Hearts[slot] == hearts) | ||
Hearts[slot] = 0; | ||
} | ||
|
||
private int NumHearts(SID sid) => sid switch | ||
{ | ||
SID.Hearts0 => 0, | ||
SID.Hearts1 => 1, | ||
SID.Hearts2 => 2, | ||
SID.Hearts3 => 3, | ||
SID.Hearts4 => 4, | ||
_ => -1 | ||
}; | ||
} | ||
|
||
abstract class Fracture(BossModule module) : Components.CastTowers(module, ActionID.MakeSpell(AID.Fracture), 4) | ||
{ | ||
protected abstract BitMask UpdateForbidden(); | ||
|
||
public override void Update() | ||
{ | ||
var forbidden = UpdateForbidden(); | ||
foreach (ref var t in Towers.AsSpan()) | ||
t.ForbiddenSoakers = forbidden; | ||
} | ||
} | ||
|
||
class Fracture1(BossModule module) : Fracture(module) | ||
{ | ||
private readonly HoneyBLiveHearts? _hearts = module.FindComponent<HoneyBLiveHearts>(); | ||
|
||
protected override BitMask UpdateForbidden() | ||
{ | ||
var forbidden = new BitMask(); | ||
if (_hearts != null) | ||
for (int i = 0; i < _hearts.Hearts.Length; ++i) | ||
if (_hearts.Hearts[i] == 3) | ||
forbidden.Set(i); | ||
return forbidden; | ||
} | ||
} | ||
|
||
class Fracture2(BossModule module) : Fracture(module) | ||
{ | ||
private BitMask _spreads; | ||
private readonly HoneyBLiveHearts? _hearts = module.FindComponent<HoneyBLiveHearts>(); | ||
|
||
protected override BitMask UpdateForbidden() | ||
{ | ||
var forbidden = _spreads; | ||
if (_hearts != null) | ||
for (int i = 0; i < _hearts.Hearts.Length; ++i) | ||
if (_hearts.Hearts[i] > 1) | ||
forbidden.Set(i); | ||
return forbidden; | ||
} | ||
|
||
public override void OnEventIcon(Actor actor, uint iconID) | ||
{ | ||
// spread targets should never take towers | ||
if (iconID == (uint)IconID.Heartsore) | ||
_spreads.Set(Raid.FindSlot(actor.InstanceID)); | ||
} | ||
} | ||
|
||
class Fracture3 : Fracture | ||
{ | ||
private BitMask _defamations; | ||
|
||
public Fracture3(BossModule module) : base(module) | ||
{ | ||
var bigBurst = module.FindComponent<HoneyBLiveBeat3BigBurst>(); | ||
if (bigBurst != null) | ||
{ | ||
var order = bigBurst.NumCasts == 0 ? 1 : 2; | ||
_defamations = Raid.WithSlot(true).WhereSlot(i => bigBurst.Order[i] == order).Mask(); | ||
} | ||
} | ||
|
||
protected override BitMask UpdateForbidden() => _defamations; | ||
} | ||
|
||
class Loveseeker(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.LoveseekerAOE), new AOEShapeCircle(10)); | ||
class HeartStruck(BossModule module) : Components.LocationTargetedAOEs(module, ActionID.MakeSpell(AID.HeartStruck), 6); | ||
class Heartsore(BossModule module) : Components.SpreadFromIcon(module, (uint)IconID.Heartsore, ActionID.MakeSpell(AID.Heartsore), 6, 7.1f); | ||
|
||
class Sweetheart(BossModule module) : Components.GenericAOEs(module) | ||
{ | ||
private readonly List<Actor> _adds = []; | ||
|
||
private static readonly AOEShapeCircle _shape = new(2); | ||
|
||
public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor) => _adds.Where(a => !a.IsDestroyed).Select(a => new AOEInstance(_shape, a.Position)); | ||
|
||
public override void OnActorPlayActionTimelineEvent(Actor actor, ushort id) | ||
{ | ||
if ((OID)actor.OID == OID.Sweetheart && id == 0x11D3) | ||
_adds.Add(actor); | ||
} | ||
} | ||
|
||
abstract class Heartsick(BossModule module, bool roles) : Components.StackWithIcon(module, (uint)IconID.Heartsick, ActionID.MakeSpell(AID.Heartsick), 6, 7, roles ? 2 : 4) | ||
{ | ||
private readonly HoneyBLiveHearts? _hearts = module.FindComponent<HoneyBLiveHearts>(); | ||
|
||
public override void Update() | ||
{ | ||
if (_hearts != null) | ||
{ | ||
foreach (ref var stack in Stacks.AsSpan()) | ||
{ | ||
for (int i = 0; i < _hearts.Hearts.Length; ++i) | ||
{ | ||
stack.ForbiddenPlayers[i] = roles | ||
? (_hearts.Hearts[i] > 0 || stack.Target.Class.IsSupport() != Raid[i]?.Class.IsSupport()) | ||
: _hearts.Hearts[i] == 3; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
class Heartsick1(BossModule module) : Heartsick(module, false); | ||
class Heartsick2(BossModule module) : Heartsick(module, true); | ||
|
||
class HoneyBLiveBeat3BigBurst(BossModule module) : Components.UniformStackSpread(module, 0, 14, alwaysShowSpreads: true) | ||
{ | ||
public int NumCasts; | ||
public int[] Order = new int[PartyState.MaxPartySize]; | ||
private readonly DateTime[] _activation = new DateTime[2]; | ||
|
||
public override void AddHints(int slot, Actor actor, TextHints hints) | ||
{ | ||
if (Order[slot] != 0) | ||
hints.Add($"Order: {Order[slot]}", false); | ||
base.AddHints(slot, actor, hints); | ||
} | ||
|
||
public override void OnStatusGain(Actor actor, ActorStatus status) | ||
{ | ||
if ((SID)status.ID == SID.PoisonNPop) | ||
{ | ||
var order = (status.ExpireAt - WorldState.CurrentTime).TotalSeconds > 30 ? 1 : 0; | ||
_activation[order] = status.ExpireAt; | ||
var slot = Raid.FindSlot(actor.InstanceID); | ||
if (slot >= 0) | ||
Order[slot] = order + 1; | ||
} | ||
} | ||
|
||
public override void OnCastStarted(Actor caster, ActorCastInfo spell) | ||
{ | ||
if ((AID)spell.Action.ID == AID.Fracture && Spreads.Count == 0) | ||
{ | ||
var order = NumCasts == 0 ? 1 : 2; | ||
AddSpreads(Raid.WithSlot(true).WhereSlot(i => Order[i] == order).Actors(), _activation[order - 1]); | ||
} | ||
} | ||
|
||
public override void OnEventCast(Actor caster, ActorCastEvent spell) | ||
{ | ||
if ((AID)spell.Action.ID == AID.HoneyBLiveBeat3BigBurst) | ||
{ | ||
++NumCasts; | ||
Spreads.Clear(); | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
BossMod/Modules/Dawntrail/Savage/RM02SHoneyBLovely/RM02SHoneyBLovely.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,12 @@ | ||
namespace BossMod.Dawntrail.Savage.RM02SHoneyBLovely; | ||
|
||
class StingingSlash(BossModule module) : Components.BaitAwayIcon(module, new AOEShapeCone(50, 45.Degrees()), (uint)IconID.StingingSlash, ActionID.MakeSpell(AID.StingingSlashAOE)); | ||
class KillerSting(BossModule module) : Components.IconSharedTankbuster(module, (uint)IconID.KillerSting, ActionID.MakeSpell(AID.KillerStingAOE), 6); | ||
class BlindingLoveBait(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.BlindingLoveBaitAOE), new AOEShapeRect(50, 4)); | ||
class BlindingLoveCharge1(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.BlindingLoveCharge1AOE), new AOEShapeRect(45, 5)); | ||
class BlindingLoveCharge2(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.BlindingLoveCharge2AOE), new AOEShapeRect(45, 5)); | ||
class PoisonStingBait(BossModule module) : Components.BaitAwayCast(module, ActionID.MakeSpell(AID.PoisonStingAOE), new AOEShapeCircle(6), true); | ||
class PoisonStingVoidzone(BossModule module) : Components.PersistentVoidzone(module, 6, m => m.Enemies(OID.PoisonStingVoidzone).Where(z => z.EventState != 7)); | ||
class BeeSting(BossModule module) : Components.StackWithCastTargets(module, ActionID.MakeSpell(AID.BeeStingAOE), 6, 4); | ||
|
||
public class RM02SHoneyBLovely(WorldState ws, Actor primary) : BossModule(ws, primary, new(100, 100), new ArenaBoundsCircle(20)); |
Oops, something went wrong.