Skip to content

Commit

Permalink
ArenaBoundsDifference, AOE caching, hydaelyn improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
CarnifexOptimus committed Apr 21, 2024
1 parent 9c95c82 commit 319ad6a
Show file tree
Hide file tree
Showing 13 changed files with 572 additions and 328 deletions.
444 changes: 391 additions & 53 deletions BossMod/BossModule/ArenaBounds.cs

Large diffs are not rendered by default.

55 changes: 37 additions & 18 deletions BossMod/BossModule/MiniArena.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void Begin(float cameraAzimuthRadians)
ImGui.GetWindowDrawList().PushClipRect(Vector2.Max(cursor, wmin), Vector2.Min(cursor + fullSize, wmax));
if (Config.OpaqueArenaBackground)
{
if (Bounds is ArenaBoundsPolygon or ArenaBoundsDonut or ArenaBoundsUnion) //only use the more expensive fill algorithm if needed, draw time is 0.05 to 0.1ms higher
if (Bounds is ArenaBoundsPolygon or ArenaBoundsDonut or ArenaBoundsUnion or ArenaBoundsDifference) //only use the more expensive fill algorithm if needed, draw time is 0.05 to 0.1ms higher
{
var clipPoly = Bounds.BuildClipPoly();
var triangles = Bounds.ClipAndTriangulate(clipPoly);
Expand Down Expand Up @@ -202,27 +202,38 @@ public void TextWorld(WPos center, string text, uint color, float fontSize = 17)
// draw arena border
public void Border(uint color)
{
if (Bounds is ArenaBoundsUnion union)
{
var polygons = union.BuildClipPoly().ToList();
var groupedPolygons = GroupPolygons(polygons);
foreach (var polygon in groupedPolygons)
DrawPolygon(polygon, color);
}
else if (Bounds is ArenaBoundsDonut donut)
{
AddCircle(Bounds.Center, donut.OuterRadius, color, 2);
AddCircle(Bounds.Center, donut.InnerRadius, color, 2);
}
else
ProcessBounds(Bounds, color);
}

private void ProcessBounds(ArenaBounds bounds, uint color)
{
switch (bounds)
{
foreach (var p in Bounds.ClipPoly)
PathLineTo(p);
PathStroke(true, color, 2);
case ArenaBoundsUnion union:
DrawPolygons(union, color);
break;
case ArenaBoundsDifference difference:
DrawPolygons(difference, color);
break;
case ArenaBoundsDonut donut:
AddCircle(bounds.Center, donut.OuterRadius, color, 2);
AddCircle(bounds.Center, donut.InnerRadius, color, 2);
break;
default:
DefaultHandling(bounds, color);
break;
}
}

private void DrawPolygon(IEnumerable<WPos> vertices, uint color)
private void DrawPolygons(ArenaBounds bounds, uint color)
{
var polygons = bounds.BuildClipPoly().ToList();
var groupedPolygons = GroupPolygons(polygons);
foreach (var polygon in groupedPolygons)
DrawPolygons2(polygon, color);
}

private void DrawPolygons2(IEnumerable<WPos> vertices, uint color)
{
var lastPoint = vertices.First();
PathLineTo(lastPoint);
Expand All @@ -235,6 +246,14 @@ private void DrawPolygon(IEnumerable<WPos> vertices, uint color)
PathStroke(true, color, 2);
}

private void DefaultHandling(ArenaBounds bounds, uint color)
{
foreach (var p in bounds.ClipPoly)
PathLineTo(p);
PathStroke(true, color, 2);
}


private static IEnumerable<IEnumerable<WPos>> GroupPolygons(IEnumerable<WPos> vertices)
{
List<WPos> currentPolygon = [];
Expand Down
11 changes: 9 additions & 2 deletions BossMod/Modules/DemoModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public override void AddGlobalHints(GlobalHints hints)

public override void DrawArenaBackground(int pcSlot, Actor pc)
{
Arena.ZoneCircle(Module.Bounds.Center, 12, ArenaColor.AOE);
Arena.ZoneCircle(Module.Bounds.Center, 10, ArenaColor.AOE);
}

public override void DrawArenaForeground(int pcSlot, Actor pc)
Expand All @@ -32,7 +32,7 @@ public override void DrawArenaForeground(int pcSlot, Actor pc)
}
}

//for testing ray intersections with new arena shapes
// for testing ray intersections with new arena shapes
// class RayIntersectionTest(BossModule module) : Components.Knockback(module)
// {

Expand All @@ -48,10 +48,17 @@ public override void DrawArenaForeground(int pcSlot, Actor pc)
// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsUnion([new ArenaBoundsDonut(new(80, 100), 20,30), new ArenaBoundsDonut(new(120, 120), 20,30), new ArenaBoundsDonut(new(100, 100), 20,30)]))
// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsUnion([new ArenaBoundsCircle(new(105, 115), 15), new ArenaBoundsCircle(new(120, 120), 15), new ArenaBoundsCircle(new(120, 100), 15)]))
// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsUnion([new ArenaBoundsDonut(new(100, 100), 20,30), new ArenaBoundsRect(new(120, 120), 5,20,240.Degrees()), new ArenaBoundsRect(new(80, 80), 5,20,-120.Degrees()), new ArenaBoundsRect(new(80, 120), 5,20,120.Degrees())]))
// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsUnion([new ArenaBoundsDonut(new(100, 100), 20, 30), new ArenaBoundsRect(new(100, 75), 5, 20), new ArenaBoundsRect(Helpers.RotateAroundOrigin(-120, new(100, 100),new(100, 75)), 5, 20, 120.Degrees()), new ArenaBoundsRect(Helpers.RotateAroundOrigin(120, new(100, 100),new(100, 75)), 5, 20, -120.Degrees())]))

// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsDonut(new(100, 100), 20, 30))
// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsUnion([new ArenaBoundsCircle(new(105, 115), 10), new ArenaBoundsCircle(new(140, 100), 10), new ArenaBoundsCircle(new(120, 95), 10)]))
// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsUnion([new ArenaBoundsDonut(new(105, 115), 5,10), new ArenaBoundsDonut(new(120, 100), 5,10)]))
// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsUnion([new ArenaBoundsDonut(new(80, 100), 10,20), new ArenaBoundsDonut(new(120, 120), 10,20), new ArenaBoundsCircle(new(100, 100), 30)]))
// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsDifference(new ArenaBoundsSquare(new(100, 100), 30), [new ArenaBoundsCircle(new(80, 100), 10), new ArenaBoundsCircle(new(120, 120), 10)]))
// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsDifference(new ArenaBoundsDonut(new(100, 100), 20,30), [new ArenaBoundsCircle(new(80, 100), 25), new ArenaBoundsCircle(new(120, 120), 25)]))
// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsDifference(new ArenaBoundsSquare(new(100, 100), 20), [new ArenaBoundsDonut(new(80, 100), 15,25), new ArenaBoundsCircle(new(120, 120), 25)]))
// public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsDifference(new ArenaBoundsSquare(new(100, 100), 20), [new ArenaBoundsDonut(new(80, 100), 15,25),new ArenaBoundsDonut(new(80, 100), 26,28)]))

public DemoModule(WorldState ws, Actor primary) : base(ws, primary, new ArenaBoundsSquare(new(100, 100), 20))
{
ActivateComponent<DemoComponent>();
Expand Down
15 changes: 1 addition & 14 deletions BossMod/Modules/Endwalker/Extreme/Ex2Hydaelyn/Aureole.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,9 @@
namespace BossMod.Endwalker.Extreme.Ex2Hydaelyn;

// component tracking [lateral] aureole mechanic
// component tracking [lateral] aureole mechanic, only exists for the timeline anymore
class Aureole(BossModule module) : BossComponent(module)
{
public bool Done { get; private set; }
private AOEShapeCone _aoe = new(40, 75.Degrees(), (AID)(module.PrimaryActor.CastInfo?.Action.ID ?? 0) is AID.LateralAureole1 or AID.LateralAureole2 ? -90.Degrees() : 0.Degrees());

public override void AddHints(int slot, Actor actor, TextHints hints)
{
if (_aoe.Check(actor.Position, Module.PrimaryActor) || _aoe.Check(actor.Position, Module.PrimaryActor.Position, Module.PrimaryActor.Rotation + 180.Degrees()))
hints.Add("GTFO from aoe!");
}

public override void DrawArenaBackground(int pcSlot, Actor pc)
{
_aoe.Draw(Arena, Module.PrimaryActor);
_aoe.Draw(Arena, Module.PrimaryActor.Position, Module.PrimaryActor.Rotation + 180.Degrees());
}

public override void OnEventCast(Actor caster, ActorCastEvent spell)
{
Expand Down
5 changes: 5 additions & 0 deletions BossMod/Modules/Endwalker/Extreme/Ex2Hydaelyn/Ex2Hydaelyn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ class PureCrystal(BossModule module) : Components.CastCounter(module, ActionID.M

// cast counter for post-intermission AOE
class Exodus(BossModule module) : Components.CastCounter(module, ActionID.MakeSpell(AID.Exodus));
class LateralAureole1(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.LateralAureole1AOE), new AOEShapeCone(40, 75.Degrees()));
class LateralAureole2(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.LateralAureole2AOE), new AOEShapeCone(40, 75.Degrees()));
class Aureole1(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.Aureole1AOE), new AOEShapeCone(40, 75.Degrees()));
class Aureole2(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.Aureole2AOE), new AOEShapeCone(40, 75.Degrees()));
class HerosSundering(BossModule module) : Components.BaitAwayCast(module, ActionID.MakeSpell(AID.HerosSundering), new AOEShapeCone(40, 45.Degrees()));

[ConfigDisplay(Order = 0x020, Parent = typeof(EndwalkerConfig))]
public class Ex2HydaelynConfig() : CooldownPlanningConfigNode(90);
Expand Down
111 changes: 58 additions & 53 deletions BossMod/Modules/Endwalker/Extreme/Ex2Hydaelyn/Ex2HydaelynEnums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,58 @@ public enum OID : uint

public enum AID : uint
{
AutoAttackSword = 870,
Enrage = 24571, // Boss->self
WeaponChangeAOEChakram = 26004, // Boss->self, no cast, chakram aoe
WeaponChangeAOEStaff = 26008, // Boss->self, no cast, staff aoe
ShiningSaberAOE = 26006, // Boss->target, no cast, shared damage
CrystallizeSwordStaffWater = 26010, // Boss->self: (1) water+blue->red/green, (6) ?
CrystallizeStaffEarth = 26011, // Boss->self: (3) earth+green->blue
CrystallizeStaffIce = 26012, // Boss->self: (2) ice+green->red, (4) ice+green->green
CrystallizeChakramIce = 26013, // Boss->self: (2) ice+red->green
CrystallizeChakramEarth = 26014, // Boss->self: (3) earth+red->blue
CrystallizeTriggerEarth = 26015, // Boss->self, no cast, removes buff and triggers aoe
CrystallizeTriggerIce = 26016, // Boss->self, no cast, removes buff and triggers aoe
CrystallizeTriggerWater = 26017, // Boss->self, no cast, removes buff and triggers aoe
CrystallineWater = 26018, // Helper->healer, no cast
CrystallineStone = 26019, // Helper->target, no cast
CrystallineBlizzard = 26020, // Helper->target, no cast
Halo = 26021, // Boss->self
LightOfTheCrystal = 26022, // Helper->self, no cast, aoe when lightwave hits crystal
RayOfLight = 26023, // Helper->self, no cast, aoe inside lightwave
HerosGlory = 26024, // Boss->self
TeleportToCenter = 26025, // Boss->n/a
InfralateralArcAOE = 26026, // Boss->self, no cast
ParhelicCircle = 26028, // Boss->self
Incandescence = 26031, // MysticRefulgence->self, no cast, aoe
AutoAttackSword = 870, // Boss/Echo->player, no cast, single-target
HerosRadiance = 26049, // Boss->self, 5,0s cast, range 40 circle
ShiningSaber = 26824, // Boss->self, 4,9s cast, single-target, stack
ShiningSaberAOE = 26006, // Boss->players, no cast, range 6 circle
CrystallizeSwordStaffWater = 26010, // Boss->self, 4,0s cast, single-target, (1) water+blue->red/green, (6) ?
WeaponChangeAOEStaff = 26008, // Boss->self, no cast, range 10 circle
CrystallizeTriggerIce = 26016, // Boss->self, no cast, single-target
CrystallineWater = 26018, // Helper->players, no cast, range 6 circle, healer light party stack
MagosRadiance = 26050, // Boss->self, 5,0s cast, range 40 circle
AutoAttackStaff = 27732, // Boss->player, no cast, single-target
LateralAureole2 = 28435, // Boss->self, 5,0s cast, single-target
LateralAureole2AOE = 28436, // Helper->self, 5,5s cast, range 40 150-degree cone
CrystallizeStaffIce = 26012, // Boss->self, 4,0s cast, single-target, (2) ice+green->red, (4) ice+green->green
WeaponChangeAOEChakram = 26004, // Boss->self, no cast, range 5-40 donut
CrystallizeTriggerWater = 26017, // Boss->self, no cast, single-target
CrystallineBlizzard = 26020, // Helper->players, no cast, range 5 circle
AutoAttackChakram = 27733, // Boss->player, no cast, single-target
MousaScorn = 26048, // Boss->players, 5,0s cast, range 4 circle
LateralAureole1 = 26053, // Boss->self, 5,0s cast, single-target
LateralAureole1AOE = 26256, // Helper->self, 5,5s cast, range 40 150-degree cone
CrystallizeChakramEarth = 26014, // Boss->self, 4,0s cast, single-target, (3) earth+red->blue
WeaponChangeVisualSword = 26051, // Boss->self, no cast, single-target
WeaponChangeAOESword = 28338, // Helper->self, no cast, range 40 width 10 cross
CrystallizeTriggerEarth = 26015, // Boss->self, no cast, single-target
CrystallineStone = 26019, // Helper->players, no cast, range 6 circle
CrystalPhase = 26044, // Boss->self, no cast, single-target, trigger for crystal phase
PureCrystal = 26045, // Helper->self, no cast, range 40 circle
IncreaseConviction = 26046, // CrystalOfLight->Boss, no cast, single-target, performed every 1s by glowing crystals to increase conviction
CrystalOfLightDeath = 26732, // Helper->Echo, no cast, single-target, 1 cast per echo after each crystal dies
ExodusVisual = 26043, // Boss->self, no cast, single-target, happens after all echoes die
Exodus = 26155, // Helper->self, no cast, range 40 circle
ExodusEnrage = 27911, // Helper->self, no cast, range 40 circle, enrage if crystal phase takes too long
Halo = 26021, // Boss->self, 5,0s cast, range 40 circle
LightwaveSword = 26259, // Boss->self, 4,0s cast, single-target
RayOfLight = 26023, // Helper->self, no cast, range 15 width 16 rect, aoe inside lightwave
LightOfTheCrystal = 26022, // Helper->self, 1,0s cast, range 40 circle, aoe when lightwave hits crystal
TeleportToCenter = 26025, // Boss->location, no cast, single-target
InfralateralArc = 26217, // Boss->self, 4,9s cast, single-target
InfralateralArcAOE = 26026, // Boss->self, no cast, range 40 90-degree cone
HerosGlory = 26024, // Boss->self, 5,0s cast, range 40 180-degree cone
HerosSundering = 26047, // Boss->self/players, 5,0s cast, range 40 90-degree cone
ParhelicCircle = 26028, // Boss->self, 6,0s cast, single-target
MysticRefulgenceTeleport = 26030, // MysticRefulgence->location, no cast, single-target
IncandescenceTrigger = 26029, // MysticRefulgence2->self, no cast, single-target
Incandescence = 26031, // MysticRefulgence->self, no cast, range 6 circle
Aureole1 = 27793, // Boss->self, 5,0s cast, single-target
Aureole1AOE = 27794, // Helper->self, 5,5s cast, range 40 150-degree cone
Aureole2 = 28433, // Boss->self, 5,0s cast, single-target
Aureole2AOE = 28434, // Helper->self, 5,5s cast, range 40 150-degree cone
CrystallizeChakramWater = 28373, // Boss->self, 4,0s cast, single-target, (5) water+red->red
CrystallizeChakramIce = 26013, // Boss->self, 4,0s cast, single-target, (2) ice+red->green
CrystallizeStaffEarth = 26011, // Boss->self, 4,0s cast, single-target, (3) earth+green->blue
Parhelion = 26032, // Boss->self
ParhelionNext = 26033, // Boss->self, no cast
BeaconParhelion = 26034, // Parhelion->location
Expand All @@ -52,42 +80,19 @@ public enum AID : uint
DichroicSpectrum = 26040, // Helper->mt
BrightSpectrum = 26041, // Helper->non-tank
EchoesAOE = 26042, // Helper->target, no cast
ExodusVisual = 26043, // Boss->self, no cast, ??? (happens after all echoes die)
PureCrystal = 26045, // Helper->self, no cast, raidwide
IncreaseConviction = 26046, // CrystalOfLight->Boss, no cast, performed every 1s by glowing crystals to increase conviction
HerosSundering = 26047, // Boss->mt
MousaScorn = 26048, // Boss->mt
HerosRadiance = 26049, // Boss->self
MagosRadiance = 26050, // Boss->self
WeaponChangeVisualSword = 26051, // Boss->self, no cast, sword visual
LateralAureole1 = 26053, // Boss->self
Exodus = 26155, // Helper->self, no cast, raidwide
InfralateralArc = 26217, // Boss->self
LateralAureole1AOE = 26256, // Helper->self
LightwaveSword = 26259, // Boss->self
LightwaveStaff = 26260, // Boss->self
LightwaveChakram = 26261, // Boss->self
CrystalOfLightDeath = 26732, // Helper->Echo, no cast, 1 cast per echo after each crystal dies
ShiningSaber = 26824, // Boss->self
AutoAttackStaff = 27732,
AutoAttackChakram = 27733,
Subparhelion = 27734, // Boss->self
Aureole1 = 27793, // Boss->self
Aureole1AOE = 27794, // Helper->self
WeaponChangeAOESword = 28338, // Helper->self, no cast, sword aoe
CrystallizeChakramWater = 28373, // Boss->self: (5) water+red->red
Aureole2 = 28433, // Boss->self
Aureole2AOE = 28434, // Helper->self
LateralAureole2 = 28435, // Boss->self
LateralAureole2AOE = 28436, // Helper->self
HerosRadianceEnrage = 24571, // Boss->self
}

public enum SID : uint
{
CrystallizeElement = 2056, // invisible in ui, extra determines element type
HerosMantle = 2876, // sword stance
MagosMantle = 2877, // staff stance
MousaMantle = 2878, // chakram stance
CrystallizeElement = 2056, // Boss->Boss, extra=0x151/0x153/0x152, invisible in ui, extra determines element type
HydaelynsWeapon = 2273, // Boss->Boss, extra=0x1B4/0x1B5, (n/a for sword, 1B4 for staff, 1B5 for chakram)
MagosMantle = 2877, // none->Boss, extra=0x0
MousaMantle = 2878, // none->Boss, extra=0x0
HerosMantle = 2876, // none->Boss/Echo, extra=0x0
}

public enum IconID : uint
Expand Down
14 changes: 10 additions & 4 deletions BossMod/Modules/Endwalker/Extreme/Ex2Hydaelyn/Ex2HydaelynStates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ private void ForkSecondMerge(uint id, float delay)
SwitchWeapon(id + 0x160000, 1.3f, false);
CrystallizeAureole(id + 0x170000, 7.3f, false);
SwitchWeapon(id + 0x180000, 1.3f, true);
Cast(id + 0x190000, AID.Enrage, 9.5f, 10, "Enrage");
Cast(id + 0x190000, AID.HerosRadianceEnrage, 9.5f, 10, "Enrage");
}

private void Intermission(uint id, float delay)
Expand Down Expand Up @@ -219,9 +219,15 @@ private State Aureole(uint id, float delay)
{
// note: what is the difference between aureole spells? seems to be determined by weapon?..
CastMulti(id, new AID[] { AID.Aureole1, AID.Aureole2, AID.LateralAureole1, AID.LateralAureole2 }, delay, 5)
.ActivateOnEnter<Aureole>();
.ActivateOnEnter<Aureole1>()
.ActivateOnEnter<Aureole2>()
.ActivateOnEnter<LateralAureole1>()
.ActivateOnEnter<LateralAureole2>();
return ComponentCondition<Aureole>(id + 2, 0.5f, comp => comp.Done, "Aureole")
.DeactivateOnExit<Aureole>();
.DeactivateOnExit<Aureole1>()
.DeactivateOnExit<Aureole2>()
.DeactivateOnExit<LateralAureole1>()
.DeactivateOnExit<LateralAureole2>();
}

private void ParhelicCircle(uint id, float delay)
Expand All @@ -235,7 +241,7 @@ private void ParhelicCircle(uint id, float delay)
private void SwitchWeapon(uint id, float delay, bool toSword)
{
ComponentCondition<WeaponTracker>(id, delay, comp => comp.AOEImminent, "Select weapon");
ComponentCondition<WeaponTracker>(id + 0x10, toSword ? 4.5f : 3.7f, comp => !comp.AOEImminent, "Weapon AOE");
ComponentCondition<WeaponTracker>(id + 0x10, toSword ? 6.9f : 6, comp => !comp.AOEImminent, "Weapon AOE");
}

// note: activates Crystallize component and sets positioning flag
Expand Down
Loading

0 comments on commit 319ad6a

Please sign in to comment.