Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
namespace BossMod.Dawntrail.Dungeon.D08TenderValley.D080YokHuyAttestant;

public enum OID : uint
{
Boss = 0x4253,
YokHuyOrb = 0x424F,
YokHuyAltar = 0x4251,
YokHuyAltar2 = 0x448D
}

public enum AID : uint
{
AutoAttack = 872,

SunToss = 38539,
BoulderToss = 38540,
TectonicShift = 39221
}

class SunToss(BossModule module) : Components.StandardAOEs(module, AID.SunToss, 6);
class BoulderToss(BossModule module) : Components.SingleTargetDelayableCast(module, AID.BoulderToss);
class TectonicShift(BossModule module) : Components.StandardAOEs(module, AID.TectonicShift, 8);

class D080YokHuyAttestantStates : StateMachineBuilder
{
public D080YokHuyAttestantStates(BossModule module) : base(module)
{
TrivialPhase()
.ActivateOnEnter<SunToss>()
.ActivateOnEnter<BoulderToss>()
.ActivateOnEnter<TectonicShift>();
}
}

[ModuleInfo(BossModuleInfo.Maturity.WIP, Contributors = "CerQ", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 834, NameID = 12801, SortOrder = -1)]
public class D080YokHuyAttestant(WorldState ws, Actor primary) : BossModule(ws, primary, new(-130, -475.25f), new ArenaBoundsRect(17.5f, 24.5f))
{
protected override void DrawEnemies(int pcSlot, Actor pc)
{
Arena.Actor(PrimaryActor, ArenaColor.Enemy);
Arena.Actors(Enemies(OID.YokHuyOrb), ArenaColor.Object);
Arena.Actors(Enemies(OID.YokHuyAltar), ArenaColor.Object);
Arena.Actors(Enemies(OID.YokHuyAltar2), ArenaColor.Object);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
namespace BossMod.Dawntrail.Dungeon.D08TenderValley.D081Barreltender;

public enum OID : uint
{
Boss = 0x4234,
SmallTenderDrop = 0x1EBBF0,
LargeTenderDrop = 0x1EBBF1,
Helper = 0x233C
}

public enum AID : uint
{
AutoAttack = 872,

HeavyweightNeedlesVisual = 37384,
HeavyweightNeedles = 37386,
TenderDrop = 37387,
NeedleStorm = 37388,
NeedleSuperstorm = 37389,
BarrelBreaker = 37390,
SucculentStomp = 37391,
BarbedBellow = 37392,
BarrelBreakerAOE = 37393,
PricklyRight = 39154,
PricklyLeft = 39155,
TenderFury = 39242
}

class BarbedBellow(BossModule module) : Components.RaidwideCast(module, AID.BarbedBellow);
class NeedleStorm(BossModule module) : Components.StandardAOEs(module, AID.NeedleStorm, 6);
class NeedleSuperstorm(BossModule module) : Components.StandardAOEs(module, AID.NeedleSuperstorm, 11);
class SucculentStomp(BossModule module) : Components.StackWithCastTargets(module, AID.SucculentStomp, 6, 4);
class TenderFury(BossModule module) : Components.SingleTargetCast(module, AID.TenderFury);

class HeavyweightNeedles(BossModule module) : Components.StandardAOEs(module, AID.HeavyweightNeedles, new AOEShapeCone(36, 25.Degrees()));
class PricklyRight(BossModule module) : Components.StandardAOEs(module, AID.PricklyRight, new AOEShapeCone(36, 165.Degrees()));
class PricklyLeft(BossModule module) : Components.StandardAOEs(module, AID.PricklyLeft, new AOEShapeCone(36, 165.Degrees()));

class BarrelBreaker(BossModule module) : Components.Knockback(module)
{
private readonly List<Source> _sources = [];

public override IEnumerable<Source> Sources(int slot, Actor actor) => _sources;

public override void OnCastStarted(Actor caster, ActorCastInfo spell)
{
if ((AID)spell.Action.ID == AID.BarrelBreaker)
_sources.Add(new(Module.Center, 15, Module.CastFinishAt(spell)));
}

public override void OnCastFinished(Actor caster, ActorCastInfo spell)
{
if ((AID)spell.Action.ID == AID.BarrelBreaker)
_sources.Clear();
}
}

class D081BarreltenderStates : StateMachineBuilder
{
public D081BarreltenderStates(BossModule module) : base(module)
{
TrivialPhase()
.ActivateOnEnter<BarbedBellow>()
.ActivateOnEnter<HeavyweightNeedles>()
.ActivateOnEnter<NeedleStorm>()
.ActivateOnEnter<NeedleSuperstorm>()
.ActivateOnEnter<BarrelBreaker>()
.ActivateOnEnter<SucculentStomp>()
.ActivateOnEnter<PricklyRight>()
.ActivateOnEnter<PricklyLeft>()
.ActivateOnEnter<TenderFury>();
}
}

[ModuleInfo(BossModuleInfo.Maturity.Contributed, Contributors = "CerQ", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 834, NameID = 12889)]
public class D081Barreltender(WorldState ws, Actor primary) : BossModule(ws, primary, new(-65, 470), new ArenaBoundsRect(17, 15.5f));
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
namespace BossMod.Dawntrail.Dungeon.D08TenderValley.D082Anthracite;

public enum OID : uint
{
Boss = 0x41BE,
Helper = 0x233C
}

public enum AID : uint
{
AutoAttack = 872,

AnthrabombLong = 36401,
AnthrabombShort = 36402,
AnthrabombSetup = 36542,
AnthrabombMid = 36543,
AnthrabombMidResolve = 36544,
HotBlastLong = 36545,
HotBlastLongResolve = 36546,
Carniflagration = 36547,
CarniflagrationVisual = 36548,
AnthrabombFast = 36549,
AnthrabombFastResolve = 36550,
HotBlastShort = 36551,
HotBlastShortResolve = 36552,
AnthrabombSpread = 36553,
BurningCoalsVisual = 36554,
BurningCoals = 36555,
CarbonaceousCombustion = 36556,
CarbonaceousCombustionAOE = 36557,
ChimneySmack = 38467,
ChimneySmackTarget = 38468
}

class CarbonaceousCombustion(BossModule module) : Components.RaidwideCastDelay(module, AID.CarbonaceousCombustion, AID.CarbonaceousCombustionAOE, 0.5f);
class BurningCoals(BossModule module) : Components.StackWithCastTargets(module, AID.BurningCoals, 6, 4);
class ChimneySmack(BossModule module) : Components.SingleTargetCast(module, AID.ChimneySmackTarget);
class AnthrabombSpread(BossModule module) : Components.SpreadFromCastTargets(module, AID.AnthrabombSpread, 6);
class CarniflagrationHint(BossModule module) : Components.CastHint(module, AID.Carniflagration, "Bomb sequence + spreads");

class Anthrabombs(BossModule module) : Components.GenericAOEs(module)
{
private static readonly AOEShapeCircle _circle = new(10);
private static readonly AOEShapeRect _line = new(40, 3);
private readonly List<(AID aid, ulong caster, AOEInstance aoe)> _aoes = [];

public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor) => _aoes.Select(e => e.aoe);

public override void OnCastStarted(Actor caster, ActorCastInfo spell)
{
switch ((AID)spell.Action.ID)
{
case AID.AnthrabombLong:
case AID.AnthrabombShort:
case AID.AnthrabombMid:
case AID.AnthrabombFast:
_aoes.Add(((AID)spell.Action.ID, caster.InstanceID, new(_circle, caster.Position, Activation: Module.CastFinishAt(spell))));
break;
case AID.HotBlastLong:
case AID.HotBlastShort:
_aoes.Add(((AID)spell.Action.ID, caster.InstanceID, new(_line, caster.Position, spell.Rotation, Module.CastFinishAt(spell))));
break;
}
}

public override void OnCastFinished(Actor caster, ActorCastInfo spell)
{
var aid = (AID)spell.Action.ID;
var index = _aoes.FindIndex(e => e.aid == aid && e.caster == caster.InstanceID);
if (index >= 0)
_aoes.RemoveAt(index);
}
}

class D082AnthraciteStates : StateMachineBuilder
{
public D082AnthraciteStates(BossModule module) : base(module)
{
TrivialPhase()
.ActivateOnEnter<CarbonaceousCombustion>()
.ActivateOnEnter<Anthrabombs>()
.ActivateOnEnter<CarniflagrationHint>()
.ActivateOnEnter<AnthrabombSpread>()
.ActivateOnEnter<BurningCoals>()
.ActivateOnEnter<ChimneySmack>();
}
}

[ModuleInfo(BossModuleInfo.Maturity.Contributed, Contributors = "CerQ", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 834, NameID = 12853)]
public class D082Anthracite(WorldState ws, Actor primary) : BossModule(ws, primary, new(-130, -57), new ArenaBoundsRect(15, 20));
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
namespace BossMod.Dawntrail.Dungeon.D08TenderValley.D083GreatestSerpentOfTural;

public enum OID : uint
{
Boss = 0x4164,
LesserSerpentOfTural = 0x41DE,
GreatSerpentOfTural = 0x41E0,
MightyBlorpPuddle1 = 0x1EBA86,
MightyBlorpPuddle2 = 0x1EBA87,
MightyBlorpPuddle3 = 0x1EBA88,
Helper = 0x233C
}

public enum SID : uint
{
Bind = 2518,
GreatestCurse = 3825
}

public enum AID : uint
{
AutoAttack = 872,

GreatTorrentVisual = 36741,
GreatestFloodVisual = 36742,
MoistSummoning = 36743,
ScreesOfFuryVisual = 36744,
GreatestLabyrinth = 36745,
BouncyCouncil = 36746,
BouncyCouncilResolve = 36747,
DubiousTulidisaster = 36748,
ExaltedWobble = 36749,
MisplacedMystery = 36750,
MightyBlorpVisual1 = 36751,
MightyBlorpVisual2 = 36752,
MightyBlorpVisual3 = 36753,
GreatTorrentAOE = 36754,
GreatTorrentSpread = 36755,
GreatestFloodAOE = 36756,
ScreesOfFury = 36757,
MightyBlorp1 = 39981,
MightyBlorp2 = 39982,
MightyBlorp3 = 39983
}

class DubiousTulidisaster(BossModule module) : Components.RaidwideCast(module, AID.DubiousTulidisaster);
class GreatestLabyrinth(BossModule module) : BossComponent(module)
{
private static readonly Dictionary<uint, WPos> _tiles = new()
{
[0x04000200] = new(-128.0483f, -560.11017f),
[0x10000800] = new(-131.8944f, -547.8202f),
[0x01000080] = new(-124.125694f, -551.9294f),
[0x00020001] = new(-135.9524f, -560.0384f),
};

private BitMask _cursed;
private WPos? _tile;

public override void AddHints(int slot, Actor actor, TextHints hints)
{
if (_tile is { } tile && _cursed[slot] && !actor.Position.InRect(tile, default(Angle), 2, 2, 2))
hints.Add("Go to marked tile!");
}

public override void AddMovementHints(int slot, Actor actor, MovementHints movementHints)
{
if (_tile is { } tile && _cursed[slot])
movementHints.Add(actor.Position, tile, ArenaColor.Safe);
}

public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints)
{
if (_tile is { } tile && _cursed[slot])
hints.GoalZones.Add(p => p.InRect(tile, default(Angle), 2, 2, 2) ? 10 : 0);
}

public override void DrawArenaBackground(int pcSlot, Actor pc)
{
if (_tile is { } tile && _cursed[pcSlot])
Arena.ZoneRect(tile, default(Angle), 2, 2, 2, ArenaColor.SafeFromAOE);
}

public override void DrawArenaForeground(int pcSlot, Actor pc)
{
if (_tile is { } tile && _cursed[pcSlot])
{
Arena.AddRect(tile, new WDir(1, 0), 2, 2, 2, ArenaColor.Safe, 2);
Arena.AddLine(pc.Position, tile, ArenaColor.Safe);
}
}

public override void OnStatusGain(Actor actor, ActorStatus status)
{
if ((SID)status.ID == SID.GreatestCurse && Raid.TryFindSlot(actor, out var slot))
_cursed.Set(slot);
}

public override void OnStatusLose(Actor actor, ActorStatus status)
{
if ((SID)status.ID == SID.GreatestCurse && Raid.TryFindSlot(actor, out var slot))
{
_cursed.Clear(slot);
if (_cursed.None())
_tile = null;
}
}

public override void OnMapEffect(byte index, uint state)
{
if (index == 0x01 && _tiles.TryGetValue(state, out var tile))
_tile = tile;
}
}
class MoistSummoning(BossModule module) : Components.CastHint(module, AID.MoistSummoning, "Summon jumps + puddles");
class ScreesOfFury(BossModule module) : Components.SingleTargetCastDelay(module, AID.ScreesOfFuryVisual, AID.ScreesOfFury, 0.6f);
class GreatTorrentAOEs(BossModule module) : Components.StandardAOEs(module, AID.GreatTorrentAOE, 6);
class GreatTorrentSpread(BossModule module) : Components.UniformStackSpread(module, 0, 6, alwaysShowSpreads: true)
{
private int _numAOEs;

public override void OnCastStarted(Actor caster, ActorCastInfo spell)
{
if ((AID)spell.Action.ID == AID.GreatTorrentVisual)
{
_numAOEs = 0;
Spreads.Clear();
}
}

public override void OnEventCast(Actor caster, ActorCastEvent spell)
{
switch ((AID)spell.Action.ID)
{
case AID.GreatTorrentAOE:
if (++_numAOEs == 12)
AddSpreads(Raid.WithoutSlot(true), WorldState.FutureTime(2.8f));
break;
case AID.GreatTorrentSpread:
Spreads.Clear();
break;
}
}
}
class ExaltedWobble(BossModule module) : Components.StandardAOEs(module, AID.ExaltedWobble, 9);
class MisplacedMystery(BossModule module) : Components.StandardAOEs(module, AID.MisplacedMystery, new AOEShapeRect(52, 2.5f));
class GreatestFlood(BossModule module) : Components.KnockbackFromCastTarget(module, AID.GreatestFloodAOE, 20, shape: new AOEShapeCircle(40));
class MightyBlorpPuddles(BossModule module) : Components.PersistentVoidzone(module, 6, m => m.Enemies(OID.MightyBlorpPuddle1).Concat(m.Enemies(OID.MightyBlorpPuddle2)).Concat(m.Enemies(OID.MightyBlorpPuddle3)));

class D083GreatestSerpentOfTuralStates : StateMachineBuilder
{
public D083GreatestSerpentOfTuralStates(BossModule module) : base(module)
{
TrivialPhase()
.ActivateOnEnter<DubiousTulidisaster>()
.ActivateOnEnter<GreatestLabyrinth>()
.ActivateOnEnter<MoistSummoning>()
.ActivateOnEnter<ScreesOfFury>()
.ActivateOnEnter<GreatTorrentAOEs>()
.ActivateOnEnter<GreatTorrentSpread>()
.ActivateOnEnter<ExaltedWobble>()
.ActivateOnEnter<MisplacedMystery>()
.ActivateOnEnter<GreatestFlood>()
.ActivateOnEnter<MightyBlorpPuddles>();
}
}

[ModuleInfo(BossModuleInfo.Maturity.Contributed, Contributors = "CerQ", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 834, NameID = 12709)]
public class D083GreatestSerpentOfTural(WorldState ws, Actor primary) : BossModule(ws, primary, new(-130, -554), new ArenaBoundsSquare(12));