Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
LTS-FFXIV committed Apr 3, 2024
1 parent 8230662 commit 4f79126
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 72 deletions.
38 changes: 31 additions & 7 deletions BossMod/Components/CastHint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,16 @@ public class CastInterruptHint : CastHint
{
public bool CanBeInterrupted { get; init; }
public bool CanBeStunned { get; init; }
public bool ShowNameInHint { get ; init; } // important if there are several targets
public string HintExtra { get; init; }

public CastInterruptHint(ActionID aid, bool canBeInterrupted = true, bool canBeStunned = false, string hint = "") : base(aid, "")
public CastInterruptHint(ActionID aid, bool canBeInterrupted = true, bool canBeStunned = false, string hintExtra = "", bool showNameInHint = false) : base(aid, "")
{
CanBeInterrupted = canBeInterrupted;
CanBeStunned = canBeStunned;
if (canBeInterrupted || canBeStunned)
{
Hint = !canBeStunned ? "Interrupt" : !canBeInterrupted ? "Stun" : "Interrupt/stun";
if (hint.Length > 0)
Hint += $" {hint}";
}
ShowNameInHint = showNameInHint;
HintExtra = hintExtra;
UpdateHint();
}

public override void AddAIHints(BossModule module, int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints)
Expand All @@ -63,4 +62,29 @@ public override void AddAIHints(BossModule module, int slot, Actor actor, PartyR
}
}
}

public override void OnCastStarted(BossModule module, Actor caster, ActorCastInfo spell)
{
base.OnCastStarted(module, caster, spell);
if (ShowNameInHint && spell.Action == WatchedAction)
UpdateHint();
}

public override void OnCastFinished(BossModule module, Actor caster, ActorCastInfo spell)
{
base.OnCastFinished(module, caster, spell);
if (ShowNameInHint && spell.Action == WatchedAction)
UpdateHint();
}

private void UpdateHint()
{
if (!CanBeInterrupted && !CanBeStunned)
return;
var actionStr = !CanBeStunned ? "Interrupt" : !CanBeInterrupted ? "Stun" : "Interrupt/stun";
var nameStr = ShowNameInHint && Casters.Count == 1 ? " " + Casters[0].Name : "";
Hint = $"{actionStr}{nameStr}!";
if (HintExtra.Length > 0)
Hint += $" ({HintExtra})";
}
}
2 changes: 1 addition & 1 deletion BossMod/Modules/Endwalker/Hunt/RankA/Petalodus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public enum AID : uint

class MarineMayhem : Components.CastInterruptHint
{
public MarineMayhem() : base(ActionID.MakeSpell(AID.MarineMayhem), hint: "(Raidwide x3)") { }
public MarineMayhem() : base(ActionID.MakeSpell(AID.MarineMayhem), hintExtra: "Raidwide x3") { }
}

class Waterga : Components.SpreadFromCastTargets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class SanctifiedAero : Components.SelfTargetedAOEs

class PunitiveLight : Components.CastInterruptHint
{ //Note: this attack is a r20 circle, not drawing it because it is too big and the damage not all that high even if interrupt/stun fails
public PunitiveLight() : base(ActionID.MakeSpell(AID.PunitiveLight), true, true, "(Raidwide)") { }
public PunitiveLight() : base(ActionID.MakeSpell(AID.PunitiveLight), true, true, "Raidwide", true) { }
}

class Sanctification : Components.SelfTargetedAOEs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public enum AID : uint

class PunitiveLight : Components.CastInterruptHint
{ //Note: this attack is a r20 circle, not drawing it because it is too big and the damage not all that high even if interrupt/stun fails
public PunitiveLight() : base(ActionID.MakeSpell(AID.PunitiveLight), true, true, "(Raidwide)") { }
public PunitiveLight() : base(ActionID.MakeSpell(AID.PunitiveLight), true, true, "Raidwide", true) { }
}

class Sanctification : Components.SelfTargetedAOEs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,40 +47,19 @@ class PerfectContrition : Components.SelfTargetedAOEs

public class JudgmentDay : Components.GenericTowers
{
private bool tower1;
private bool tower2;
private Actor? Tower1;

public override void OnActorEState(BossModule module, Actor actor, ushort state)
{
if (state is 0x01C or 0x02C)
{
if (!tower1)
{
tower1 = true;
Towers.Add(new(actor.Position, 5, 1, 1));
Tower1 = actor;
}
if (tower1 && !tower2 && actor != Tower1)
{
tower2 = true;
if (!Towers.Any(t => t.Position.AlmostEqual(actor.Position, 1)))
Towers.Add(new(actor.Position, 5, 1, 1));
}
}
}

public override void OnEventCast(BossModule module, Actor caster, ActorCastEvent spell)
{
if ((AID)spell.Action.ID is AID.Judged or AID.FoundWanting)
{
Towers.RemoveAll(t => t.Position.AlmostEqual(caster.Position, 1));
if (Towers.Count == 0) //Note: I don't think towers can repeat, this is just a safety precaution
{
tower1 = default;
tower2 = default;
Tower1 = default;
}
}
if ((AID)spell.Action.ID is AID.Judged or AID.FoundWanting && Towers.Count > 0)
Towers.RemoveAt(0);
}

public override void AddAIHints(BossModule module, int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints)
Expand All @@ -95,33 +74,31 @@ public override void AddAIHints(BossModule module, int slot, Actor actor, PartyR
class Exegesis : Components.GenericAOEs
{
private DateTime _activation;
private bool ExegesisA;
private bool ExegesisB;
private bool ExegesisC;
private bool ExegesisD;
public enum Patterns { None, Diagonal, Cross, EastWest, NorthSouth }
public Patterns Pattern { get; private set; }
private static readonly AOEShapeRect rect = new(5, 5, 5);

public override IEnumerable<AOEInstance> ActiveAOEs(BossModule module, int slot, Actor actor)
{
if (ExegesisA) //diagonal squares
if (Pattern == Patterns.Diagonal)
{
yield return new(rect, new(-240, -50), default, _activation);
yield return new(rect, new(-250, -40), default, _activation);
yield return new(rect, new(-230, -40), default, _activation);
yield return new(rect, new(-250, -60), default, _activation);
yield return new(rect, new(-230, -60), default, _activation);
}
if (ExegesisB) //West+East Square
if (Pattern == Patterns.EastWest)
{
yield return new(rect, new(-250, -50), default, _activation);
yield return new(rect, new(-230, -50), default, _activation);
}
if (ExegesisC) //North+South Square
if (Pattern == Patterns.NorthSouth)
{
yield return new(rect, new(-240, -60), default, _activation);
yield return new(rect, new(-240, -40), default, _activation);
}
if (ExegesisD) //cross pattern
if (Pattern == Patterns.Cross)
{
yield return new(rect, new(-230, -50), default, _activation);
yield return new(rect, new(-240, -60), default, _activation);
Expand All @@ -136,44 +113,28 @@ public override void OnCastStarted(BossModule module, Actor caster, ActorCastInf
switch ((AID)spell.Action.ID)
{
case AID.ExegesisA:
ExegesisA = true;
Pattern = Patterns.Diagonal;
_activation = spell.NPCFinishAt;
break;
case AID.ExegesisB:
ExegesisB = true;
Pattern = Patterns.EastWest;
_activation = spell.NPCFinishAt;
break;
case AID.ExegesisC:
ExegesisC = true;
Pattern = Patterns.NorthSouth;
_activation = spell.NPCFinishAt;
break;
case AID.ExegesisD:
ExegesisD = true;
Pattern = Patterns.Cross;
_activation = spell.NPCFinishAt;
break;
}
}

public override void OnCastFinished(BossModule module, Actor caster, ActorCastInfo spell)
{
if ((AID)spell.Action.ID is AID.ExegesisA or AID.ExegesisB or AID.ExegesisC or AID.ExegesisD)
{
ExegesisA = false;
ExegesisB = false;
ExegesisC = false;
ExegesisD = false;
}
}

public override void DrawArenaForeground(BossModule module, int pcSlot, Actor pc, MiniArena arena)
public override void OnEventCast(BossModule module, Actor caster, ActorCastEvent spell)
{
if (ExegesisA || ExegesisB || ExegesisC || ExegesisD)
{
arena.AddLine(new(-235, -65), new(-235, -35), ArenaColor.Border, 2);
arena.AddLine(new(-245, -65), new(-245, -35), ArenaColor.Border, 2);
arena.AddLine(new(-225, -55), new(-255, -55), ArenaColor.Border, 2);
arena.AddLine(new(-225, -45), new(-255, -45), ArenaColor.Border, 2);
}
if ((AID)spell.Action.ID == AID.Exegesis)
Pattern = Patterns.None;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ public Aethertide() : base(ActionID.MakeSpell(AID.AethertideAOE), 8) { }

class MarchingBreath : Components.CastInterruptHint //heals all allies by 20% of max health (raidwide)
{
public MarchingBreath() : base(ActionID.MakeSpell(AID.MarchingBreath), hint: "(20% HP AOE heal)") { }
public MarchingBreath() : base(ActionID.MakeSpell(AID.MarchingBreath), showNameInHint: true) { }
}

class TacticalAero : Components.SelfTargetedAOEs
Expand All @@ -171,7 +171,7 @@ public DarkFlare() : base(ActionID.MakeSpell(AID.DarkFlare), 8) { }

class SoulSacrifice : Components.CastInterruptHint //WarWraith sacrifices itself to give boss a damage buff
{
public SoulSacrifice() : base(ActionID.MakeSpell(AID.SoulSacrifice), hint: "(Dmg buff on boss)") { }
public SoulSacrifice() : base(ActionID.MakeSpell(AID.SoulSacrifice), showNameInHint: true) { }
}

class PurifyingLight : Components.LocationTargetedAOEs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,14 @@ class EntrapmentInescapable : Entrapment
{
// TODO: don't think these patterns are actually correct...
private readonly static Pattern[] _allowedPatterns = [
new() { Normal = BuildMask(3, 8, 20, 25, 38, 43, 46, 49, 52), Toad = BuildMask(10, 50, 53), Ice = BuildMask(40), Mini = BuildMask(29) },
new() { Normal = BuildMask(2, 8, 11, 16, 25, 29, 38, 46), Toad = BuildMask(0, 4, 44), Ice = BuildMask(49), Mini = BuildMask(34) },
new() { Normal = BuildMask(3, 4, 5, 8, 20, 25, 38, 43, 46, 49, 52), Toad = BuildMask(10, 50, 54), Ice = BuildMask(40), Mini = BuildMask(29) },
//new() { Normal = BuildMask(3, 8, 20, 25, 38, 43, 46, 49, 52), Toad = BuildMask(10, 50, 53), Ice = BuildMask(40), Mini = BuildMask(29) },
new() { Normal = BuildMask(2, 5, 8, 11, 14, 16, 25, 29, 46, 49, 51), Toad = BuildMask(0, 4, 44), Ice = BuildMask(50), Mini = BuildMask(34) },
//new() { Normal = BuildMask(2, 8, 11, 16, 25, 29, 38, 46), Toad = BuildMask(0, 4, 44), Ice = BuildMask(49), Mini = BuildMask(34) },
new() { Normal = BuildMask(5, 8, 11, 16, 18, 22, 24, 29, 43, 49, 53), Toad = BuildMask(6, 33, 38), Ice = BuildMask(4), Mini = BuildMask(48) },
new() { Normal = BuildMask(5, 8, 11, 25, 30, 32, 38, 43, 50), Toad = BuildMask(16, 21, 48), Ice = BuildMask(36), Mini = BuildMask(1) },
//new() { Normal = BuildMask(5, 8, 11, 16, 18, 22, 24, 29, 43, 49, 53), Toad = BuildMask(6, 33, 38), Ice = BuildMask(4), Mini = BuildMask(48) },
new() { Normal = BuildMask(5, 6, 8, 11, 25, 30, 32, 38, 43, 46, 50), Toad = BuildMask(16, 21, 48), Ice = BuildMask(36), Mini = BuildMask(1) },
//new() { Normal = BuildMask(5, 8, 11, 25, 30, 32, 38, 43, 50), Toad = BuildMask(16, 21, 48), Ice = BuildMask(36), Mini = BuildMask(1) },
];

public EntrapmentInescapable() : base(_allowedPatterns) { }
Expand Down
2 changes: 1 addition & 1 deletion BossMod/Modules/Shadowbringers/Hunt/RankS/Aglaope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public enum SID : uint

class SongOfTorment : Components.CastInterruptHint
{
public SongOfTorment() : base(ActionID.MakeSpell(AID.SongOfTorment), hint: "(Raidwide + Bleed)") { }
public SongOfTorment() : base(ActionID.MakeSpell(AID.SongOfTorment), hintExtra: "Raidwide + Bleed") { }
}

//TODO: ideally this AOE should just wait for Effect Results, since they can be delayed by over 2.1s, which would cause unknowning players and AI to run back into the death zone,
Expand Down
2 changes: 1 addition & 1 deletion BossMod/Modules/Shadowbringers/Hunt/RankS/Tyger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class TheDragonsVoice : Components.SelfTargetedAOEs

class TheDragonsVoiceHint : Components.CastInterruptHint
{
public TheDragonsVoiceHint() : base(ActionID.MakeSpell(AID.TheDragonsVoice), hint: "(Donut Raidwide)") { }
public TheDragonsVoiceHint() : base(ActionID.MakeSpell(AID.TheDragonsVoice), hintExtra: "Donut Raidwide") { }
}

class TygerStates : StateMachineBuilder
Expand Down

0 comments on commit 4f79126

Please sign in to comment.