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 chaotic changes #536

Merged
merged 5 commits into from
Jan 1, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Break(BossModule module) : Components.GenericGaze(module)
{
public readonly List<Eye> Eyes = [];

public override IEnumerable<Eye> ActiveEyes(int slot, Actor actor) => Eyes;//_casters.Where(c => c.CastInfo?.TargetID != actor.InstanceID).Select(c => new Eye(EyePosition(c), Module.CastFinishAt(c.CastInfo), Range: range));
public override IEnumerable<Eye> ActiveEyes(int slot, Actor actor) => Eyes;

public override void OnCastStarted(Actor caster, ActorCastInfo spell)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ class Atomos(BossModule module) : Components.Adds(module, (uint)OID.Atomos);
class LoomingChaos(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.LoomingChaosAOE));

// TODO: tankswap hints component for phase1
// TODO: phase 2 squares, break timer, teleport zones
// TODO: phase 2 squares, break timer, teleport zones, outer ring safety
// TODO: grim embrace / curse of darkness prevent turning

[ModuleInfo(BossModuleInfo.Maturity.WIP, Contributors = "The Combat Reborn Team (Malediktus, LTS)", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 1010, NameID = 13624, PlanLevel = 100)]
[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "The Combat Reborn Team (Malediktus, LTS)", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 1010, NameID = 13624, PlanLevel = 100)]
public class Ch01CloudOfDarkness(WorldState ws, Actor primary) : BossModule(ws, primary, DefaultCenter, DefaultArena)
{
public static readonly WPos DefaultCenter = new(100, 100);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,17 @@ public enum AID : uint
public enum SID : uint
{
//_Gen_ArcaneDesign = 4180, // Boss->Boss, extra=0x0
//_Gen_VeilOfDarkness = 4179, // Boss->Boss, extra=0x0
//_Gen_LightningResistanceDown = 4386, // Helper/Boss->player, extra=0x1/0x2/0x3/0x4/0x5/0x6/0x7/0x8/0x9/0xA/0xB/0xC/0xD/0xE/0xF/0x10
DeadlyEmbrace = 4181, // none->player, extra=0x0
AbyssalEdge = 4182, // Boss->Boss, extra=0x0 (endeath/enaero stored)
//_Gen_VeilOfDarkness = 4179, // Boss->Boss, extra=0x0
//_Gen_CloyingCondensation = 2532, // none->player, extra=0x0
//_Gen_CloyingCondensation = 2532, // none->player, extra=0x0, prevent jumps?
//_Gen_ = 4388, // none->StygianShadow, extra=0x1052
//_Gen_ = 4387, // none->Boss, extra=0x1051
InnerDarkness = 4177, // none->player, extra=0x0, on main platform
OuterDarkness = 4178, // none->player, extra=0x0, on side platform
//_Gen_Rehabilitation = 4191, // none->Boss, extra=0x1/0x4/0x3/0x2
//_Gen_LifeDrain = 1377, // none->player, extra=0x0
//_Gen_CraftersGrace = 45, // player->player, extra=0x50
CurseOfDarkness = 2387, // none->player, extra=0x0
//_Gen_StabWound = 3061, // none->player, extra=0x0
//_Gen_StabWound = 3062, // none->player, extra=0x0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ private void Subphase2(uint id, float delay)
ThirdArtOfDarknessParticleConcentration(id + 0x20000, 4);
GhastlyGloom(id + 0x30000, 12.3f);
CurseOfDarkness(id + 0x40000, 8.3f);
EvilSeed(id + 0x50000, 9.9f);
ChaosCondensedDiffusiveForceParticleBeam(id + 0x60000, 8.1f);
EvilSeedChaosCondensedDiffusiveForceParticleBeam(id + 0x50000, 9.9f);
ActivePivotParticleBeam(id + 0x70000, 4.4f);
LoomingChaos(id + 0x80000, 6.2f);

Expand Down Expand Up @@ -240,7 +239,8 @@ private void ThirdArtOfDarknessParticleConcentration(uint id, float delay)
.DeactivateOnExit<ThirdArtOfDarknessHyperFocusedParticleBeam>()
.DeactivateOnExit<ThirdArtOfDarknessMultiProngedParticleBeam>()
.DeactivateOnExit<ThirdArtOfDarknessCleave>();
ComponentCondition<ParticleConcentration>(id + 0x50, 3.6f, comp => comp.NumCasts > 0, "Towers")
ComponentCondition<ParticleConcentration>(id + 0x50, 3.6f, comp => comp.Towers.Count == 0, "Towers")
.ExecOnEnter<ParticleConcentration>(comp => comp.ShowOuterTowers())
.DeactivateOnExit<ParticleConcentration>();
}

Expand Down Expand Up @@ -270,29 +270,29 @@ private State FloodOfDarknessAdds(uint id, float delay)
.DeactivateOnExit<FloodOfDarknessAdd>();
}

// TODO: this one needs a lot of thought
private void EvilSeed(uint id, float delay)
private void EvilSeedChaosCondensedDiffusiveForceParticleBeam(uint id, float delay)
{
ComponentCondition<EvilSeedBait>(id, delay, comp => comp.Baiters.Any())
.ActivateOnEnter<EvilSeedBait>();
ComponentCondition<EvilSeedAOE>(id + 0x10, 8.1f, comp => comp.Casters.Count > 0, "Seed plant")
.ActivateOnEnter<EvilSeedAOE>()
.ActivateOnEnter<EvilSeedVoidzone>()
.DeactivateOnExit<EvilSeedBait>();

GhastlyGloom(id + 0x1000, 2.8f)
.DeactivateOnExit<EvilSeedAOE>();

ComponentCondition<ThornyVine>(id + 0x2000, 14, comp => comp.Targets.Any())
.ActivateOnEnter<ThornyVine>();
ComponentCondition<ThornyVine>(id + 0x2010, 3, comp => comp.HaveTethers);
FloodOfDarknessAdds(id + 0x2020, 2.2f)
.DeactivateOnExit<ThornyVine>();
}
ComponentCondition<ThornyVine>(id + 0x2010, 3, comp => comp.TethersAssigned, "Tethers");
FloodOfDarknessAdds(id + 0x2020, 2.2f);

private void ChaosCondensedDiffusiveForceParticleBeam(uint id, float delay)
{
CastMulti(id, [AID.ChaosCondensedParticleBeam, AID.DiffusiveForceParticleBeam], delay, 8)
CastMulti(id + 0x3000, [AID.ChaosCondensedParticleBeam, AID.DiffusiveForceParticleBeam], 8.1f, 8)
.ActivateOnEnter<ChaosCondensedParticleBeam>()
.ActivateOnEnter<DiffusiveForceParticleBeam>();
Condition(id + 0x10, 0.7f, () => Module.FindComponent<ChaosCondensedParticleBeam>()?.NumCasts > 0 || Module.FindComponent<DiffusiveForceParticleBeam>()?.Spreads.Count == 0, "Spread/line stacks")
.ActivateOnEnter<DiffusiveForceParticleBeam>()
.DeactivateOnExit<EvilSeedVoidzone>()
.DeactivateOnExit<ThornyVine>();
Condition(id + 0x3010, 0.7f, () => Module.FindComponent<ChaosCondensedParticleBeam>()?.NumCasts > 0 || Module.FindComponent<DiffusiveForceParticleBeam>()?.Spreads.Count == 0, "Spread/line stacks")
.DeactivateOnExit<ChaosCondensedParticleBeam>()
.DeactivateOnExit<DiffusiveForceParticleBeam>(); // TODO: show second wave ...
}
Expand Down Expand Up @@ -335,7 +335,8 @@ private void ParticleConcentrationPhaser(uint id, float delay)
.ActivateOnEnter<ParticleConcentration>(); // TODO: towers appear 1s after cast end
ComponentCondition<Phaser>(id + 0x11, 1.5f, comp => comp.NumCasts >= 6, "Adds sides/front")
.DeactivateOnExit<Phaser>();
ComponentCondition<ParticleConcentration>(id + 0x20, 6.6f, comp => comp.NumCasts > 0, "Towers")
ComponentCondition<ParticleConcentration>(id + 0x20, 6.6f, comp => comp.Towers.Count == 0, "Towers")
.ExecOnEnter<ParticleConcentration>(comp => comp.ShowOuterTowers())
.DeactivateOnExit<ParticleConcentration>();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
namespace BossMod.Dawntrail.Chaotic.Ch01CloudOfDarkness;

// TODO: who gets radius 7 and who gets radius 5?
// TODO: show for second wave too...
// note: it seems that normally first wave (radius 7) hits people inside, and second wave (radius 5) hits people outside
// however, if some of the players in the mid are dead, some players on the outside will be hit by first wave (up to a total of 12 hits)
// if there are <= 12 players alive, everyone will be hit by the first wave, and the second wave will never happen
// so for safety we just show larger radius around everyone
// TODO: show second wave for players not hit by first wave
class DiffusiveForceParticleBeam(BossModule module) : Components.UniformStackSpread(module, 0, 7)
{
public override void OnCastStarted(Actor caster, ActorCastInfo spell)
{
if ((AID)spell.Action.ID == AID.DiffusiveForceParticleBeam)
AddSpreads(Raid.WithoutSlot(), Module.CastFinishAt(spell, 0.7f));
AddSpreads(Raid.WithoutSlot(true), Module.CastFinishAt(spell, 0.7f));
}

public override void OnEventCast(Actor caster, ActorCastEvent spell)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,15 @@ public override void OnEventIcon(Actor actor, uint iconID, ulong targetID)

class EvilSeedAOE(BossModule module) : Components.LocationTargetedAOEs(module, ActionID.MakeSpell(AID.EvilSeedAOE), 5);

// todo: should be chains...
class ThornyVine(BossModule module) : BossComponent(module)
class EvilSeedVoidzone(BossModule module) : Components.PersistentVoidzone(module, 5, module => module.Enemies(OID.EvilSeed).Where(z => z.EventState != 7));

class ThornyVine(BossModule module) : Components.Chains(module, (uint)TetherID.ThornyVine, default, 25)
{
public BitMask Targets;
public bool HaveTethers;

public override void OnEventIcon(Actor actor, uint iconID, ulong targetID)
{
if (iconID == (uint)IconID.ThornyVineBait)
Targets.Set(Raid.FindSlot(actor.InstanceID));
}

public override void OnTethered(Actor source, ActorTetherInfo tether)
{
if (tether.ID == (uint)TetherID.ThornyVine)
HaveTethers = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,107 @@
// 47-56 = 1-man tower falling orb
// 57-66 = 2-man tower falling orb
// 67-6E = 3-man tower falling orb
class ParticleConcentration(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.ParticleBeam1)) { }
class ParticleConcentration(BossModule module) : Components.GenericTowers(module)
{
private BitMask _innerPlayers;
private BitMask _outerPlayers;
private readonly List<WPos> _outerTowers = []; // note: initially we don't show outer towers, as players resolve different mechanics first

public void ShowOuterTowers()
{
var activation = Towers.Count > 0 ? Towers[0].Activation : default;
Towers.AddRange(_outerTowers.Select(p => new Tower(p, 3, 3, 3, _innerPlayers, activation)));
}

public override void OnStatusGain(Actor actor, ActorStatus status)
{
switch ((SID)status.ID)
{
case SID.InnerDarkness:
_innerPlayers.Set(Raid.FindSlot(actor.InstanceID));
break;
case SID.OuterDarkness:
_outerPlayers.Set(Raid.FindSlot(actor.InstanceID));
break;
}
}

public override void OnStatusLose(Actor actor, ActorStatus status)
{
switch ((SID)status.ID)
{
case SID.InnerDarkness:
_innerPlayers.Clear(Raid.FindSlot(actor.InstanceID));
break;
case SID.OuterDarkness:
_outerPlayers.Clear(Raid.FindSlot(actor.InstanceID));
break;
}
}

public override void OnEventEnvControl(byte index, uint state)
{
if (state != 0x00020001) // appear
return;

var (offset, count) = index switch
{
0x1F => (new(-9, -15), 1),
0x20 => (new(+9, -15), 1),
0x21 => (new(-21, -15), 1),
0x22 => (new(+21, -15), 1),
0x23 => (new(-15, -9), 1),
0x24 => (new(+15, -9), 1),
0x25 => (new(-15, -21), 1),
0x26 => (new(+15, -21), 1),
0x27 => (new(-9, +15), 1),
0x28 => (new(+9, +15), 1),
0x29 => (new(-21, +15), 1),
0x2A => (new(+21, +15), 1),
0x2B => (new(-15, +9), 1),
0x2C => (new(+15, +9), 1),
0x2D => (new(-15, +21), 1),
0x2E => (new(+15, +21), 1),
0x2F => (new(-12, -15), 2),
0x30 => (new(+12, -15), 2),
0x31 => (new(-18, -15), 2),
0x32 => (new(+18, -15), 2),
0x33 => (new(-15, -12), 2),
0x34 => (new(+15, -12), 2),
0x35 => (new(-15, -18), 2),
0x36 => (new(+15, -18), 2),
0x37 => (new(-12, +15), 2),
0x38 => (new(+12, +15), 2),
0x39 => (new(-18, +15), 2),
0x3A => (new(+18, +15), 2),
0x3B => (new(-15, +12), 2),
0x3C => (new(+15, +12), 2),
0x3D => (new(-15, +18), 2),
0x3E => (new(+15, +18), 2),
0x3F => (new(-26.5f, -4.5f), 3),
0x40 => (new(-22, 0), 3),
0x41 => (new(-26.5f, +4.5f), 3),
0x42 => (new(-31, 0), 3),
0x43 => (new(+26.5f, -4.5f), 3),
0x44 => (new(+22, 0), 3),
0x45 => (new(+26.5f, +4.5f), 3),
0x46 => (new(+31, 0), 3),
_ => (default(WDir), 0)
};

if (count == 3)
_outerTowers.Add(Module.Center + offset);
else if (count > 0)
Towers.Add(new(Module.Center + offset, 3, count, count, _outerPlayers, WorldState.FutureTime(10.1f)));
}

public override void OnEventCast(Actor caster, ActorCastEvent spell)
{
if ((AID)spell.Action.ID is AID.ParticleBeam1 or AID.ParticleBeam2 or AID.ParticleBeam3)
{
++NumCasts;
if (Towers.RemoveAll(t => t.Position.AlmostEqual(caster.Position, 1)) != 1)
ReportError($"Unexpected tower position @ {caster.Position}");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class ThirdArtOfDarknessCleave(BossModule module) : Components.GenericAOEs(modul
public enum Mechanic { None, Left, Right, Stack, Spread }

public readonly Dictionary<Actor, List<(Mechanic mechanic, DateTime activation)>> Mechanics = [];
public BitMask PlatformPlayers;

private static readonly AOEShapeCone _shape = new(15, 90.Degrees());

Expand All @@ -25,12 +26,28 @@ public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor)

public override void AddHints(int slot, Actor actor, TextHints hints)
{
var (a, m) = Mechanics.FirstOrDefault(kv => kv.Key.InstanceID == actor.TargetID);
if (a != null && m.Count > 0)
hints.Add($"Order: {string.Join(" > ", m.Select(m => m.mechanic))}", false);
if (PlatformPlayers[slot])
{
var playerSide = actor.Position.X - Module.Center.X;
var (a, m) = Mechanics.FirstOrDefault(kv => (kv.Key.Position.X - Module.Center.X) * playerSide > 0);
if (a != null && m.Count > 0)
hints.Add($"Order: {string.Join(" > ", m.Select(m => m.mechanic))}", false);
}
base.AddHints(slot, actor, hints);
}

public override void OnStatusGain(Actor actor, ActorStatus status)
{
if ((SID)status.ID == SID.OuterDarkness)
PlatformPlayers.Set(Raid.FindSlot(actor.InstanceID));
}

public override void OnStatusLose(Actor actor, ActorStatus status)
{
if ((SID)status.ID == SID.OuterDarkness)
PlatformPlayers.Clear(Raid.FindSlot(actor.InstanceID));
}

public override void OnEventIcon(Actor actor, uint iconID, ulong targetID)
{
if ((OID)actor.OID == OID.StygianShadow)
Expand Down Expand Up @@ -100,7 +117,7 @@ public override void Update()
foreach (var (a, m) in _main.Mechanics)
if (m.Count > 0 && m[0].mechanic == ThirdArtOfDarknessCleave.Mechanic.Stack)
foreach (var p in Raid.WithoutSlot().SortedByRange(a.Position).Take(3))
AddStack(p, m[0].activation);
AddStack(p, m[0].activation, ~_main.PlatformPlayers);
base.Update();
}
}
Loading