Skip to content

Commit

Permalink
Merge pull request #121 from FFXIV-CombatReborn/mergeWIP2
Browse files Browse the repository at this point in the history
verified Lapis Manalis and Leviathan hard
  • Loading branch information
CarnifexOptimus authored Jun 6, 2024
2 parents ee40802 + a843044 commit 14b5617
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public D110AlbusGriffinStates(D110AlbusGriffin module) : base(module)
}
}

[ModuleInfo(BossModuleInfo.Maturity.Contributed, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 896, NameID = 12245)]
[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 896, NameID = 12245)]
public class D110AlbusGriffin : BossModule
{
public readonly IReadOnlyList<Actor> Caladrius; // available from start
Expand Down
89 changes: 47 additions & 42 deletions BossMod/Modules/Endwalker/Dungeon/D11LapisManalis/D111Albion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,36 +44,29 @@ class WildlifeCrossing(BossModule module) : Components.GenericAOEs(module)
private static readonly Angle Rot90 = 90.Degrees();
private static readonly Angle RotM90 = -90.Degrees();

private (bool Active, WPos Position, Angle Rotation, int Count, DateTime Reset, List<Actor> Beasts) stampede1;
private (bool Active, WPos Position, Angle Rotation, int Count, DateTime Reset, List<Actor> Beasts) stampede2;

private readonly (bool, WPos, Angle, int, DateTime, List<Actor>)[] stampedePositions =
[
(true, new WPos(4, -759), Rot90, 0, default, []),
(true, new WPos(44, -759), RotM90, 0, default, []),
(true, new WPos(4, -749), Rot90, 0, default, []),
(true, new WPos(44, -749), RotM90, 0, default, []),
(true, new WPos(4, -739), Rot90, 0, default, []),
(true, new WPos(44, -739), RotM90, 0, default, []),
(true, new WPos(4, -729), Rot90, 0, default, []),
(true, new WPos(44, -729), RotM90, 0, default, [])
];

private bool IsNewStampede => stampede1 == default;
private Stampede stampede1 = Stampede.Default;
private Stampede stampede2 = Stampede.Default;

private static readonly (WPos, Angle)[] stampedePositions = [(new(4, -759), Rot90),
(new(44, -759), RotM90), (new(4, -749), Rot90), (new(44, -749), RotM90),
(new(4, -739), Rot90), (new(44, -739), RotM90), (new(4, -729), Rot90),
(new(44, -729), RotM90)];

private static Stampede NewStampede((WPos Position, Angle Rotation) stampede)
=> new(true, stampede.Position, stampede.Rotation);

private bool IsNewStampede => stampede1.Equals(Stampede.Default);

public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor)
{
if (stampede1.Active && stampede1.Beasts.Count > 0)
yield return CreateAOEInstance(stampede1);
if (stampede2.Active && stampede2.Beasts.Count > 0)
yield return CreateAOEInstance(stampede2);
if (stampede1.Active && stampede1.Beasts.Count == 0)
yield return new(rect, stampede1.Position, Rot90);
if (stampede2.Active && stampede2.Beasts.Count == 0)
yield return new(rect, stampede2.Position, Rot90);
foreach (var stampede in new[] { stampede1, stampede2 })
{
if (stampede.Active)
yield return stampede.Beasts.Count > 0 ? CreateAOEInstance(stampede) : new(rect, stampede.Position, Rot90);
}
}

private static AOEInstance CreateAOEInstance((bool Active, WPos Position, Angle Rotation, int Count, DateTime Reset, List<Actor> Beasts) stampede)
private static AOEInstance CreateAOEInstance(Stampede stampede)
{
var length = CalculateStampedeLength(stampede.Beasts) + 30;
var position = new WPos(stampede.Beasts[^1].Position.X, stampede.Position.Z);
Expand All @@ -86,16 +79,18 @@ public override void OnEventEnvControl(byte index, uint state)
{
if (state != 0x00020001)
return;

var stampedePosition = GetStampedePosition(index);
if (stampedePosition == null)
return;

if (IsNewStampede)
stampede1 = stampedePosition.Value;
stampede1 = NewStampede(stampedePosition.Value);
else
stampede2 = stampedePosition.Value;
stampede2 = NewStampede(stampedePosition.Value);
}

private (bool, WPos, Angle, int, DateTime, List<Actor>)? GetStampedePosition(byte index)
private (WPos, Angle)? GetStampedePosition(byte index)
{
return index switch
{
Expand All @@ -113,27 +108,25 @@ public override void OnEventEnvControl(byte index, uint state)

public override void Update()
{
UpdateStampede(ref stampede1, new WPos(24, stampede1.Position.Z));
UpdateStampede(ref stampede2, new WPos(24, stampede2.Position.Z));
UpdateStampede(ref stampede1);
UpdateStampede(ref stampede2);

ResetStampedeIfNeeded(ref stampede1);
ResetStampedeIfNeeded(ref stampede2);
ResetStampede(ref stampede1);
ResetStampede(ref stampede2);
}

private void UpdateStampede(ref (bool Active, WPos Position, Angle Rotation, int Count, DateTime Reset, List<Actor> Beasts) stampede, WPos position)
private void UpdateStampede(ref Stampede stampede)
{
foreach (var oid in new[] { OID.WildBeasts4, OID.WildBeasts3, OID.WildBeasts2, OID.WildBeasts1 })
{
var beasts = Module.Enemies(oid);
foreach (var b in beasts)
{
if (b.Position.InRect(position, stampede.Rotation, 33, 33, 5) && !stampede.Beasts.Contains(b))
if (b.Position.InRect(stampede.Position, stampede.Rotation, 0, 10, 5) && !stampede.Beasts.Contains(b) && stampede.Active)
stampede.Beasts.Add(b);
}
}
}

private void ResetStampedeIfNeeded(ref (bool Active, WPos Position, Angle Rotation, int Count, DateTime Reset, List<Actor> Beasts) stampede)
private void ResetStampede(ref Stampede stampede)
{
if (stampede.Reset != default && WorldState.CurrentTime > stampede.Reset)
stampede = default;
Expand All @@ -143,20 +136,32 @@ public override void OnEventCast(Actor caster, ActorCastEvent spell)
{
if ((AID)spell.Action.ID != AID.WildlifeCrossing)
return;

UpdateStampedeCount(ref stampede1, caster.Position.Z);
UpdateStampedeCount(ref stampede2, caster.Position.Z);
}

private void UpdateStampedeCount(ref (bool Active, WPos Position, Angle Rotation, int Count, DateTime Reset, List<Actor> Beasts) stampede, float casterZ)
private void UpdateStampedeCount(ref Stampede stampede, float casterZ)
{
if (MathF.Abs(casterZ - stampede.Position.Z) < 1)
++stampede.Count;
if (stampede.Count != 30)
return;
stampede.Reset = WorldState.FutureTime(0.5f);

if (stampede.Count == 30)
stampede.Reset = WorldState.FutureTime(0.5f);
}
}

struct Stampede(bool active, WPos position, Angle rotation)
{
public bool Active = active;
public WPos Position = position;
public Angle Rotation = rotation;
public int Count = 0;
public DateTime Reset = default;
public List<Actor> Beasts = [];
public static readonly Stampede Default = new(false, new WPos(), new Angle());
}

class IcyThroes(BossModule module) : Components.GenericBaitAway(module)
{
private readonly List<Actor> _targets = [];
Expand Down Expand Up @@ -252,5 +257,5 @@ public D111AlbionStates(BossModule module) : base(module)
}
}

[ModuleInfo(BossModuleInfo.Maturity.Contributed, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 896, NameID = 11992)]
[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 896, NameID = 11992)]
public class D111Albion(WorldState ws, Actor primary) : BossModule(ws, primary, new(24, -744), new ArenaBoundsSquare(19.5f));
Original file line number Diff line number Diff line change
Expand Up @@ -264,5 +264,11 @@ public D112GalateaMagnaStates(BossModule module) : base(module)
}
}

[ModuleInfo(BossModuleInfo.Maturity.Contributed, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 896, NameID = 10308)]
public class D112GalateaMagna(WorldState ws, Actor primary) : BossModule(ws, primary, new(350, -394), new ArenaBoundsCircle(19.5f));
[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 896, NameID = 10308)]
public class D112GalateaMagna(WorldState ws, Actor primary) : BossModule(ws, primary, arena.Center, arena)
{
private static readonly List<Shape> union = [new Circle(new(350, -394), 19.5f)];
private static readonly List<Shape> difference = [new Rectangle(new(350, -373), 20, 2.25f), new Rectangle(new(350, -414), 20, 1.25f)];
public static readonly ArenaBounds arena = new ArenaBoundsComplex(union, difference);

}
22 changes: 20 additions & 2 deletions BossMod/Modules/Endwalker/Dungeon/D11LapisManalis/D113Cagnazzo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public enum AID : uint
Hydrovent = 31136, // Helper->location, 5.0s cast, range 6 circle
SpringTide = 31135, // Helper->players, no cast, range 6 circle
Tsunami = 31137, // Helper->self, no cast, range 80 width 60 rect
TsunamiEnrage = 31138, // Helper->self, no cast, range 80 width 60 rect
Voidcleaver = 31110, // Boss->self, 4.0s cast, single-target
Voidcleaver2 = 31111, // Helper->self, no cast, range 100 circle
VoidMiasma = 32691, // Helper->self, 3.0s cast, range 50 30-degree cone
Expand Down Expand Up @@ -67,7 +68,14 @@ class Tsunami(BossModule module) : Components.RaidwideAfterNPCYell(module, Actio
class StygianDeluge(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.StygianDeluge));
class Antediluvian(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.Antediluvian2), new AOEShapeCircle(15));
class BodySlam(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.BodySlam3), new AOEShapeCircle(8));
class BodySlamKB(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.BodySlam2), 10);
class BodySlamKB(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.BodySlam2), 10)
{
public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints)
{
if (Sources(slot, actor).Any() && Module.FindComponent<Antediluvian>()!.NumCasts >= 4)
hints.AddForbiddenZone(ShapeDistance.InvertedCircle(Module.Center, 10), Sources(slot, actor).FirstOrDefault().Activation);
}
}

class HydraulicRam(BossModule module) : Components.GenericAOEs(module)
{
Expand Down Expand Up @@ -162,11 +170,21 @@ public override void OnEventCast(Actor caster, ActorCastEvent spell)
}
}

class StayInBounds(BossModule module) : BossComponent(module)
{
public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints)
{
if (!Module.InBounds(actor.Position))
hints.AddForbiddenZone(ShapeDistance.InvertedCircle(Module.Center, 3));
}
}

class D113CagnazzoStates : StateMachineBuilder
{
public D113CagnazzoStates(BossModule module) : base(module)
{
TrivialPhase()
.ActivateOnEnter<StayInBounds>()
.ActivateOnEnter<Voidcleaver>()
.ActivateOnEnter<Lifescleaver>()
.ActivateOnEnter<VoidMiasma>()
Expand All @@ -186,7 +204,7 @@ public D113CagnazzoStates(BossModule module) : base(module)
}
}

[ModuleInfo(BossModuleInfo.Maturity.Contributed, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 896, NameID = 11995)]
[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 896, NameID = 11995)]
public class D113Cagnazzo(WorldState ws, Actor primary) : BossModule(ws, primary, new(-250, 130), new ArenaBoundsSquare(20))
{
protected override void DrawEnemies(int pcSlot, Actor pc)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public T09WhorleaterHStates(BossModule module) : base(module)
}
}

[ModuleInfo(BossModuleInfo.Maturity.Contributed, Contributors = "taurenkey, Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 72, NameID = 2505)]
[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "taurenkey, Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 72, NameID = 2505)]
public class T09WhorleaterH(WorldState ws, Actor primary) : BossModule(ws, primary, new(-0, 0), new ArenaBoundsRect(14.5f, 20))
{
protected override void DrawEnemies(int pcSlot, Actor pc)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public override void AddHints(int slot, Actor actor, TextHints hints)
var TankMimikry = actor.FindStatus(2124); //Bluemage Tank Mimikry
if (tail != null)
{
if ((actor.Class.GetClassCategory() is ClassCategory.Caster or ClassCategory.Healer || (actor.Class is Class.BLU && TankMimikry == null)) && actor.TargetID == Module.Enemies(OID.Tail).FirstOrDefault()?.InstanceID)
if ((actor.Class.GetClassCategory() is ClassCategory.Caster or ClassCategory.Healer || actor.Class is Class.BLU && TankMimikry == null) && actor.TargetID == Module.Enemies(OID.Tail).FirstOrDefault()?.InstanceID)
hints.Add("Attack the head! (Attacking the tail will reflect damage onto you)");
if (actor.Class.GetClassCategory() is ClassCategory.PhysRanged && actor.TargetID == Module.PrimaryActor.InstanceID)
hints.Add("Attack the tail! (Attacking the head will reflect damage onto you)");
Expand Down

0 comments on commit 14b5617

Please sign in to comment.