Skip to content

Commit

Permalink
Merge pull request #237 from CarnifexOptimus/slave_masked_carnivale
Browse files Browse the repository at this point in the history
masked carnivale 1-20
  • Loading branch information
awgil authored Jan 25, 2024
2 parents a3528c6 + 2a1595b commit f7dd747
Show file tree
Hide file tree
Showing 39 changed files with 3,384 additions and 1 deletion.
2 changes: 2 additions & 0 deletions BossMod/BossModule/StateMachineBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public Phase OnExit(Action action, bool condition = true)

// note: usually components are deactivated automatically on phase change - manual deactivate is needed only for components that opt out of this (useful for components that need to maintain state across multiple phases)
public Phase ActivateOnEnter<C>(bool condition = true) where C : BossComponent, new() => OnEnter(_module.ActivateComponent<C>, condition);
public Phase DeactivateOnEnter<C>(bool condition = true) where C : BossComponent, new() => OnEnter(_module.DeactivateComponent<C>, condition);
public Phase DeactivateOnExit<C>(bool condition = true) where C : BossComponent => OnExit(_module.DeactivateComponent<C>, condition);
}

Expand Down Expand Up @@ -72,6 +73,7 @@ public State OnExit(Action action, bool condition = true)
}

public State ActivateOnEnter<C>(bool condition = true) where C : BossComponent, new() => OnEnter(_module.ActivateComponent<C>, condition);
public State DeactivateOnEnter<C>(bool condition = true) where C : BossComponent, new() => OnEnter(_module.DeactivateComponent<C>, condition);
public State DeactivateOnExit<C>(bool condition = true) where C : BossComponent => OnExit(_module.DeactivateComponent<C>, condition);
public State ExecOnEnter<C>(Action<C> fn, bool condition = true) where C : BossComponent => OnEnter(() => { var c = _module.FindComponent<C>(); if (c != null) fn(c); }, condition);
public State ExecOnExit<C>(Action<C> fn, bool condition = true) where C : BossComponent => OnExit(() => { var c = _module.FindComponent<C>(); if (c != null) fn(c); }, condition);
Expand Down
2 changes: 1 addition & 1 deletion BossMod/Components/Knockback.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ public override IEnumerable<Source> Sources(BossModule module, int slot, Actor a
else
{
var origin = module.WorldState.Actors.Find(c.CastInfo.TargetID)?.Position ?? c.CastInfo.LocXZ;
yield return new(origin, Distance, c.CastInfo.FinishAt, Shape, c.CastInfo.Rotation, KnockbackKind); // TODO: not sure whether rotation should be this or Angle.FromDirection(origin - c.Position)...
yield return new(origin, Distance, c.CastInfo.FinishAt, Shape, Angle.FromDirection(origin - c.Position), KnockbackKind);
}
}
}
Expand Down
49 changes: 49 additions & 0 deletions BossMod/Modules/MaskedCarnivale/ObstacleLayouts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Collections.Generic;

namespace BossMod.MaskedCarnivale
{
public class Layout2Corners : BossComponent
{
public static IEnumerable<WPos> Wall1()
{
yield return new WPos(85,95);
yield return new WPos(95,95);
yield return new WPos(95,89);
yield return new WPos(94.5f,89);
yield return new WPos(94.5f,94.5f);
yield return new WPos(85,94.5f);
}
public static IEnumerable<WPos> Wall2()
{
yield return new WPos(105,95);
yield return new WPos(115,95);
yield return new WPos(115,94.5f);
yield return new WPos(105.5f,94.5f);
yield return new WPos(105.5f,89);
yield return new WPos(105,89);
}
public override void DrawArenaForeground(BossModule module, int pcSlot, Actor pc, MiniArena arena)
{
arena.AddPolygon(Wall1(),ArenaColor.Border);
arena.AddPolygon(Wall2(),ArenaColor.Border);
}
}
public class Layout4Quads : BossComponent
{
public override void DrawArenaForeground(BossModule module, int pcSlot, Actor pc, MiniArena arena)
{
arena.AddQuad(new(107,110),new(110,113),new(113,110),new(110,107), ArenaColor.Border, 2);
arena.AddQuad(new(93,110),new(90,107),new(87,110),new(90,113), ArenaColor.Border, 2);
arena.AddQuad(new(90,93),new(93,90),new(90,87),new(87,90), ArenaColor.Border, 2);
arena.AddQuad(new(110,93),new(113,90),new(110,87),new(107,90), ArenaColor.Border, 2);
}
}

public class LayoutBigQuad : BossComponent
{
public override void DrawArenaForeground(BossModule module, int pcSlot, Actor pc, MiniArena arena)
{
arena.AddQuad(new(100,107),new(107,100),new(100,93),new(93,100), ArenaColor.Border, 2);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Linq;

namespace BossMod.MaskedCarnivale.Stage01
{
public enum OID : uint
{
Boss = 0x25BE, //R=1.5
Slime = 0x25BD, //R=1.5
};

public enum AID : uint
{
AutoAttack = 6499, // 25BD->player, no cast, single-target
FluidSpread = 14198, // 25BD->player, no cast, single-target
AutoAttack2 = 6497, // 25BE->player, no cast, single-target
IronJustice = 14199, // 25BE->self, 2,5s cast, range 8+R 120-degree cone
};
class IronJustice : Components.SelfTargetedAOEs
{
public IronJustice() : base(ActionID.MakeSpell(AID.IronJustice), new AOEShapeCone(9.5f,60.Degrees())) { }
}
class Hints : BossComponent
{
public override void AddGlobalHints(BossModule module, GlobalHints hints)
{
hints.Add("This stage is trivial.\nUse whatever skills you have to defeat these opponents.");
}
}
class Stage01States : StateMachineBuilder
{
public Stage01States(BossModule module) : base(module)
{
TrivialPhase()
.ActivateOnEnter<IronJustice>()
.DeactivateOnEnter<Hints>()
.Raw.Update = () => module.Enemies(OID.Boss).All(e => e.IsDead) && module.Enemies(OID.Slime).All(e => e.IsDead);
}
}
[ModuleInfo(CFCID = 611, NameID = 8077)]
public class Stage01 : BossModule
{
public Stage01(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsCircle(new(100, 100), 25))
{
ActivateComponent<Hints>();
}
protected override bool CheckPull() { return PrimaryActor.IsTargetable && PrimaryActor.InCombat || Enemies(OID.Slime).Any(e => e.InCombat); }
protected override void DrawEnemies(int pcSlot, Actor pc)
{
foreach (var s in Enemies(OID.Boss))
Arena.Actor(s, ArenaColor.Enemy, false);
foreach (var s in Enemies(OID.Slime))
Arena.Actor(s, ArenaColor.Enemy, false);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System.Linq;

namespace BossMod.MaskedCarnivale.Stage02.Act1
{
public enum OID : uint
{
Boss = 0x25C0, //R=1.8
Marshmallow = 0x25C2, //R1.8
Bavarois = 0x25C4, //R1.8
};

public enum AID : uint
{
Fire = 14266, // 25C0->player, 1,0s cast, single-target
Aero = 14269, // 25C2->player, 1,0s cast, single-target
Thunder = 14268, // 25C4->player, 1,0s cast, single-target
GoldenTongue = 14265, // 25C0/25C2/25C4->self, 5,0s cast, single-target
};

class GoldenTongue : Components.CastHint
{
public GoldenTongue() : base(ActionID.MakeSpell(AID.GoldenTongue), "Can be interrupted, increase its magic damage") { }
}
class Hints : BossComponent
{
public override void AddGlobalHints(BossModule module, GlobalHints hints)
{
hints.Add("To beat this stage in a timely manner,\nyou should have at least one spell of each element.\n(Water, Fire, Ice, Lightning, Earth and Wind)");
}
}
class Hints2 : BossComponent
{
public override void AddGlobalHints(BossModule module, GlobalHints hints)
{
hints.Add("Pudding is weak to wind spells.\nMarshmallow is weak to ice spells.\nBavarois is weak to earth spells.");
}
}
class Stage02Act1States : StateMachineBuilder
{
public Stage02Act1States(BossModule module) : base(module)
{
TrivialPhase()
.ActivateOnEnter<GoldenTongue>()
.ActivateOnEnter<Hints2>()
.DeactivateOnEnter<Hints>()
.Raw.Update = () => module.Enemies(OID.Boss).All(e => e.IsDead) && module.Enemies(OID.Marshmallow).All(e => e.IsDead) && module.Enemies(OID.Bavarois).All(e => e.IsDead);
}
}
[ModuleInfo(CFCID = 612, NameID = 8078)]
public class Stage02Act1 : BossModule
{
public Stage02Act1(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsCircle(new(100, 100), 25))
{
ActivateComponent<Hints>();
}
protected override bool CheckPull() { return PrimaryActor.IsTargetable && PrimaryActor.InCombat || Enemies(OID.Marshmallow).Any(e => e.InCombat) || Enemies(OID.Bavarois).Any(e => e.InCombat); }
protected override void DrawEnemies(int pcSlot, Actor pc)
{
foreach (var s in Enemies(OID.Boss))
Arena.Actor(s, ArenaColor.Enemy, false);
foreach (var s in Enemies(OID.Marshmallow))
Arena.Actor(s, ArenaColor.Enemy, false);
foreach (var s in Enemies(OID.Bavarois))
Arena.Actor(s, ArenaColor.Enemy, false);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.Linq;

namespace BossMod.MaskedCarnivale.Stage02.Act2
{
public enum OID : uint
{
Boss = 0x25C1, //R1.8
Flan = 0x25C5, //R1.8
Licorice = 0x25C3, //R=1.8

};

public enum AID : uint
{
Water = 14271, // 25C5->player, 1,0s cast, single-target
Stone = 14270, // 25C3->player, 1,0s cast, single-target
Blizzard = 14267, // 25C1->player, 1,0s cast, single-target
GoldenTongue = 14265, // 25C5/25C3/25C1->self, 5,0s cast, single-target
};

class GoldenTongue : Components.CastHint
{
public GoldenTongue() : base(ActionID.MakeSpell(AID.GoldenTongue), "Can be interrupted, increases its magic damage.") { }
}
class Hints : BossComponent
{
public override void AddGlobalHints(BossModule module, GlobalHints hints)
{
hints.Add("Gelato is weak to fire spells.\nFlan is weak to lightning spells.\nLicorice is weak to water spells.");
}
}

class Stage02Act2States : StateMachineBuilder
{
public Stage02Act2States(BossModule module) : base(module)
{
TrivialPhase()
.ActivateOnEnter<GoldenTongue>()
.ActivateOnEnter<Hints>()
.Raw.Update = () => module.Enemies(OID.Boss).All(e => e.IsDead) && module.Enemies(OID.Flan).All(e => e.IsDead) && module.Enemies(OID.Licorice).All(e => e.IsDead);
}
}
[ModuleInfo(CFCID = 612, NameID = 8079)]
public class Stage02Act2(WorldState ws, Actor primary) : BossModule(ws, primary, new ArenaBoundsCircle(new(100, 100), 25))
{
protected override bool CheckPull() { return PrimaryActor.IsTargetable && PrimaryActor.InCombat || Enemies(OID.Flan).Any(e => e.InCombat) || Enemies(OID.Licorice).Any(e => e.InCombat); }
protected override void DrawEnemies(int pcSlot, Actor pc)
{
foreach (var s in Enemies(OID.Boss))
Arena.Actor(s, ArenaColor.Enemy, false);
foreach (var s in Enemies(OID.Flan))
Arena.Actor(s, ArenaColor.Enemy, false);
foreach (var s in Enemies(OID.Licorice))
Arena.Actor(s, ArenaColor.Enemy, false);
}
}
}
72 changes: 72 additions & 0 deletions BossMod/Modules/MaskedCarnivale/Stage03WaitingForGolem/Stage03.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using BossMod.Components;

namespace BossMod.MaskedCarnivale.Stage03
{
public enum OID : uint
{
Boss = 0x25D4, //R=2.2
voidzone = 0x1E8FEA,
};

public enum AID : uint
{
Attack = 6499, // 25D4->player, no cast, single-target
BoulderClap = 14363, // 25D4->self, 3,0s cast, range 14 120-degree cone
EarthenHeart = 14364, // 25D4->location, 3,0s cast, range 6 circle
Obliterate = 14365, // 25D4->self, 6,0s cast, range 60 circle
};

class BoulderClap : SelfTargetedAOEs
{
public BoulderClap() : base(ActionID.MakeSpell(AID.BoulderClap), new AOEShapeCone(14,60.Degrees())) { }
}

class Dreadstorm : PersistentVoidzoneAtCastTarget
{
public Dreadstorm() : base(6, ActionID.MakeSpell(AID.EarthenHeart), m => m.Enemies(OID.voidzone), 0) { }
}
class Obliterate : RaidwideCast
{
public Obliterate() : base(ActionID.MakeSpell(AID.Obliterate), "Interruptible raidwide") { }
}
class Hints : BossComponent
{
public override void AddGlobalHints(BossModule module, GlobalHints hints)
{
hints.Add("Zipacna is weak against water based spells.\nFlying Sardine is recommended to interrupt raidwide.");
}
}
class Hints2 : BossComponent
{
public override void AddGlobalHints(BossModule module, GlobalHints hints)
{
hints.Add("Zipacna is weak against water based spells.\nEarth based spells are useless against Zipacna.");
}
}

class Stage03States : StateMachineBuilder
{
public Stage03States(BossModule module) : base(module)
{
TrivialPhase()
.ActivateOnEnter<BoulderClap>()
.ActivateOnEnter<Dreadstorm>()
.ActivateOnEnter<Obliterate>()
.ActivateOnEnter<Hints2>()
.DeactivateOnEnter<Hints>();
}
}
[ModuleInfo(CFCID = 613, NameID = 8084)]
public class Stage03 : BossModule
{
public Stage03(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsCircle(new(100, 100), 25))
{
ActivateComponent<Hints>();
}

protected override void DrawEnemies(int pcSlot, Actor pc)
{
Arena.Actor(PrimaryActor, ArenaColor.Enemy, true);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System.Linq;

namespace BossMod.MaskedCarnivale.Stage04.Act1
{
public enum OID : uint
{
Boss = 0x25C8, //R=1.65
Bat = 0x25D2, //R=0.4
};

public enum AID : uint
{
AutoAttack = 6497, // 25C8->player, no cast, single-target
AutoAttack2 = 6499, // 25D2->player, no cast, single-target
BloodDrain = 14360, // 25D2->player, no cast, single-target
SanguineBite = 14361, // 25C8->self, no cast, range 3+R width 2 rect
};

class Hints : BossComponent
{
public override void AddGlobalHints(BossModule module, GlobalHints hints)
{
hints.Add("Trivial stage. Enemies here are weak to lightning and fire.\nIn Act 2 the Ram's Voice and Ultravibration combo can be useful.\nFlying Sardine for interrupts can be beneficial.");
}
}
class Hints2 : BossComponent
{
public override void AddGlobalHints(BossModule module, GlobalHints hints)
{
hints.Add("Bats are weak to lightning.\nThe wolf is weak to fire.");
}
}
class Stage04Act1States : StateMachineBuilder
{
public Stage04Act1States(BossModule module) : base(module)
{
TrivialPhase()
.ActivateOnEnter<Hints2>()
.DeactivateOnEnter<Hints>()
.Raw.Update = () => module.Enemies(OID.Boss).All(e => e.IsDead) && module.Enemies(OID.Bat).All(e => e.IsDead);
}
}
[ModuleInfo(CFCID = 614, NameID = 8086)]
public class Stage04Act1 : BossModule
{
public Stage04Act1(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsCircle(new(100, 100), 25))
{
ActivateComponent<Hints>();
}
protected override bool CheckPull() { return PrimaryActor.IsTargetable && PrimaryActor.InCombat || Enemies(OID.Bat).Any(e => e.InCombat); }
protected override void DrawEnemies(int pcSlot, Actor pc)
{
foreach (var s in Enemies(OID.Boss))
Arena.Actor(s, ArenaColor.Enemy, false);
foreach (var s in Enemies(OID.Bat))
Arena.Actor(s, ArenaColor.Enemy, false);
}
}
}
Loading

0 comments on commit f7dd747

Please sign in to comment.