Skip to content

Commit

Permalink
Merge pull request #208 from FFXIV-CombatReborn/mergeWIP2
Browse files Browse the repository at this point in the history
M3 module updated
  • Loading branch information
CarnifexOptimus authored Jul 22, 2024
2 parents eacd064 + 293eac4 commit 4d84419
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 102 deletions.
16 changes: 10 additions & 6 deletions BossMod/Components/Towers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ public override void AddHints(int slot, Actor actor, TextHints hints)
hints.Add("Too few soakers in the tower!");
else if (count > Towers[soakedIndex].MaxSoakers)
hints.Add("Too many soakers in the tower!");
else
hints.Add("Soak the tower!", false);
}
else if (Towers.Any(t => !t.ForbiddenSoakers[slot] && !t.CorrectAmountInside(Module)))
else if (Towers.Any(t => !t.ForbiddenSoakers[slot] && t.NumInside(Module) < t.MaxSoakers))
{
hints.Add("Soak the tower!");
}
Expand All @@ -61,14 +63,16 @@ public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignme
var forbidden = new List<Func<WPos, float>>();
if (!Towers.Any(x => x.ForbiddenSoakers[slot]))
{
foreach (var t in Towers.Where(x => x.NumInside(Module) < x.MinSoakers || actor.Position.InCircle(x.Position, x.Radius) && x.CorrectAmountInside(Module)))
var inTower = Towers.Any(x => x.IsInside(actor) && x.CorrectAmountInside(Module));
var missingSoakers = !inTower && Towers.Any(x => x.NumInside(Module) < x.MaxSoakers);
foreach (var t in Towers.Where(x => x.NumInside(Module) < x.MinSoakers || x.IsInside(actor) && x.CorrectAmountInside(Module)))
forbiddenInverted.Add(ShapeDistance.InvertedCircle(t.Position, t.Radius));
foreach (var t in Towers.Where(x => x.NumInside(Module) > x.MaxSoakers || !actor.Position.InCircle(x.Position, x.Radius) && x.CorrectAmountInside(Module)))
foreach (var t in Towers.Where(x => x.NumInside(Module) > x.MaxSoakers || !x.IsInside(actor) && x.CorrectAmountInside(Module)))
forbidden.Add(ShapeDistance.Circle(t.Position, t.Radius));
if (forbidden.Count > 0)
hints.AddForbiddenZone(p => forbidden.Select(f => f(p)).Min(), Towers[0].Activation);
if (forbidden.Count == 0 && forbiddenInverted.Count > 0)
if (forbidden.Count == 0 || inTower || missingSoakers && forbiddenInverted.Count > 0)
hints.AddForbiddenZone(p => forbiddenInverted.Select(f => f(p)).Max(), Towers[0].Activation);
else if (forbidden.Count > 0 && !inTower)
hints.AddForbiddenZone(p => forbidden.Select(f => f(p)).Min(), Towers[0].Activation);
}
else if (Towers.Any(x => x.ForbiddenSoakers[slot]))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class LightOfDevotion(BossModule module) : Components.LineStack(module, ActionID
public override void Update()
{
// as soon as limit break phase ends the line stack gets cancelled
if (CurrentBaits.Count > 0 && Module.Enemies(OID.LightningGenerator).Count == 0)
if (CurrentBaits.Count > 0 && !Module.Enemies(OID.LightningGenerator).Any(x => !x.IsDead))
CurrentBaits.Clear();
}
}
Expand Down
11 changes: 8 additions & 3 deletions BossMod/Modules/Dawntrail/Raid/M1NBIackCat/Mouser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@ class ArenaChanges(BossModule module) : BossComponent(module)

public override void OnEventEnvControl(byte index, uint state)
{
if (state == 0x00020001)
// index per tile, starting north
// 0x00, 0x01, 0x02, 0x03
// 0x04, 0x05, 0x06, 0x07
// 0x08, 0x09, 0x0A, 0x0B
// 0x0C, 0x0D, 0x0E, 0x0F
if (state == 0x00020001) // tile gets damaged
AddTileToList(DamagedTiles, index);
else if (state == 0x00200010)
else if (state == 0x00200010) // tile gets broken
MoveTileBetweenLists(DamagedTiles, brokenTiles, index);
else if (state is 0x01000004 or 0x00800004)
else if (state is 0x01000004 or 0x00800004) // tile gets repaired
RemoveTileFromLists(index);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public override IEnumerable<Source> Sources(int slot, Actor actor)
public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints)
{
var towers = Module.FindComponent<BarbarousBarrageTower>()!.Towers;
var isDelayDeltaLow = (towers.First().Activation - Module.WorldState.CurrentTime).TotalSeconds < 6;
var isDelayDeltaLow = (towers.FirstOrDefault().Activation - Module.WorldState.CurrentTime).TotalSeconds < 5;
var isActorInsideTower = towers.Any(x => x.IsInside(actor));
if (towers.Count > 0 && isDelayDeltaLow && isActorInsideTower)
{
Expand Down
27 changes: 27 additions & 0 deletions BossMod/Modules/Dawntrail/Raid/M3NBruteBomber/Firespin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace BossMod.Dawntrail.Raid.M3NBruteBomber;

class FireSpin(BossModule module) : Components.GenericRotatingAOE(module)
{
private static readonly AOEShapeCone cone = new(40, 30.Degrees());

public override void OnCastStarted(Actor caster, ActorCastInfo spell)
{
switch ((AID)spell.Action.ID)
{
case AID.FireSpinCCW:
case AID.InfernalSpinCCW:
Sequences.Add(new(cone, Module.PrimaryActor.Position, spell.Rotation, 45.Degrees(), Module.CastFinishAt(spell, 0.5f), 1, 8));
break;
case AID.FireSpinCW:
case AID.InfernalSpinCW:
Sequences.Add(new(cone, Module.PrimaryActor.Position, spell.Rotation, -45.Degrees(), Module.CastFinishAt(spell, 0.5f), 1, 8));
break;
}
}

public override void OnCastFinished(Actor caster, ActorCastInfo spell)
{
if ((AID)spell.Action.ID is AID.FireSpinFirst or AID.FireSpinRest or AID.InfernalSpinFirst or AID.InfernalSpinRest)
AdvanceSequence(0, WorldState.CurrentTime);
}
}
8 changes: 1 addition & 7 deletions BossMod/Modules/Dawntrail/Raid/M3NBruteBomber/LariatCombo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,7 @@ class LariatCombo(BossModule module) : Components.GenericAOEs(module)
private static readonly AOEShapeRect rect1 = new(20, 30, 5, -90.Degrees());
private static readonly AOEShapeRect rect2 = new(20, 30, 5, 90.Degrees());

public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor)
{
if (_aoes.Count > 0)
yield return _aoes[0] with { Color = ArenaColor.Danger };
if (_aoes.Count > 1)
yield return _aoes[1] with { Risky = false };
}
public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor) => _aoes.Take(1);

public override void OnCastStarted(Actor caster, ActorCastInfo spell)
{
Expand Down
81 changes: 81 additions & 0 deletions BossMod/Modules/Dawntrail/Raid/M3NBruteBomber/LitFuse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
namespace BossMod.Dawntrail.Raid.M3NBruteBomber;

public class LitFuse(BossModule module) : Components.GenericAOEs(module)
{
private List<AOEInstance> _aoes = [];
private static readonly AOEShapeCircle circle = new(8);
private bool sorted;
private bool fusesOfFury;

public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor)
{
var towers = Module.FindComponent<BarbarousBarrageTower>()!.Towers;
if (_aoes.Count > 3)
for (var i = 0; i < 4; i++)
yield return _aoes[i] with { Color = ArenaColor.Danger, Risky = towers.Count == 0 };
if (_aoes.Count > 7)
for (var i = 4; i < 8; i++)
yield return _aoes[i] with { Risky = false };
}

public override void OnCastStarted(Actor caster, ActorCastInfo spell)
{
if ((AID)spell.Action.ID == AID.FusesOfFury)
fusesOfFury = true;
}

public override void Update()
{
var towers = Module.FindComponent<BarbarousBarrageTower>()!.Towers;
if (towers.Count > 0 && fusesOfFury && _aoes.Count == 8)
{
var updatedAOEs = new List<AOEInstance>();
foreach (var a in _aoes)
{
var updatedAOE = new AOEInstance(a.Shape, a.Origin, default, a.Activation.AddSeconds(3));
updatedAOEs.Add(updatedAOE);
}
_aoes = updatedAOEs;
fusesOfFury = false;
}
}

public override void OnStatusGain(Actor actor, ActorStatus status)
{
switch ((SID)status.ID)
{
case SID.LitFuseLong:
_aoes.Add(new(circle, actor.Position, default, Module.WorldState.FutureTime(10.4f)));
break;
case SID.LitFuseShort:
_aoes.Add(new(circle, actor.Position, default, Module.WorldState.FutureTime(7.4f)));
break;
}
if (_aoes.Count == 8 && !sorted)
{
_aoes.Sort((x, y) => x.Activation.CompareTo(y.Activation));
sorted = true;
}
}

public override void OnCastFinished(Actor caster, ActorCastInfo spell)
{
if (_aoes.Count > 0)
switch ((AID)spell.Action.ID)
{
case AID.SelfDestruct1:
case AID.SelfDestruct2:
_aoes.RemoveAt(0);
sorted = false;
fusesOfFury = false;
break;
}
}

public override void AddGlobalHints(GlobalHints hints)
{
var towers = Module.FindComponent<BarbarousBarrageTower>()!.Towers;
if (_aoes.Count > 0 && towers.Count > 0)
hints.Add("Don't panic! AOEs start resolving 3.8s after towers.");
}
}
38 changes: 1 addition & 37 deletions BossMod/Modules/Dawntrail/Raid/M3NBruteBomber/M3NBruteBomber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,8 @@ class BrutalImpact(BossModule module) : Components.RaidwideCast(module, ActionID
class KnuckleSandwich(BossModule module) : Components.CastSharedTankbuster(module, ActionID.MakeSpell(AID.KnuckleSandwich), 6);
class BrutalLariat1(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.BrutalLariat1), new AOEShapeRect(20, 30, 5, -90.Degrees()));
class BrutalLariat2(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.BrutalLariat2), new AOEShapeRect(20, 30, 5, 90.Degrees()));

class MurderousMist(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.MurderousMist), new AOEShapeCone(40, 135.Degrees()));

class SelfDestruct(BossModule module) : Components.GenericAOEs(module)
{
private readonly List<AOEInstance> _aoes = [];

private static readonly AOEShapeCircle circle = new(8);

public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor)
{
if (_aoes.Count > 0)
yield return _aoes[0] with { Color = ArenaColor.Danger };
if (_aoes.Count > 1)
yield return _aoes[1] with { Risky = false };
}

public override void OnCastStarted(Actor caster, ActorCastInfo spell)
{
if ((AID)spell.Action.ID is AID.SelfDestruct1 or AID.SelfDestruct2)
{
_aoes.Add(new(circle, caster.Position, spell.Rotation, Module.CastFinishAt(spell)));
_aoes.Sort((x, y) => x.Activation.CompareTo(y.Activation));
}
}

public override void OnCastFinished(Actor caster, ActorCastInfo spell)
{
if (_aoes.Count > 0 && (AID)spell.Action.ID is AID.SelfDestruct1 or AID.SelfDestruct2)
_aoes.RemoveAt(0);
}
}

class FireSpin4(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.FireSpin4), new AOEShapeCone(40, 30.Degrees()));
class FireSpin5(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.FireSpin5), new AOEShapeCone(40, 30.Degrees()));
class InfernalSpin4(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.InfernalSpin4), new AOEShapeCone(40, 30.Degrees()));
class InfernalSpin5(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.InfernalSpin5), new AOEShapeCone(40, 30.Degrees()));
class BrutalBurn(BossModule module) : Components.StackWithCastTargets(module, ActionID.MakeSpell(AID.BrutalBurn), 6, 8);

[ModuleInfo(BossModuleInfo.Maturity.WIP, Contributors = "The Combat Reborn Team", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 989, NameID = 13356)]
[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "The Combat Reborn Team (Malediktus, LTS)", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 989, NameID = 13356)]
public class M3NBruteBomber(WorldState ws, Actor primary) : BossModule(ws, primary, new(100, 100), new ArenaBoundsSquare(15));
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

public enum OID : uint
{
Boss = 0x42C2, // R5.016, x1

LitFuse = 0x42C3, // R1.200, x8
Refbot = 0x42C4, // R3.360, x0 (spawn during fight)
UnknownActor = 0x42C5, // R1.000, x4
Boss = 0x42C2, // R5.016
LitFuse = 0x42C3, // R1.2
Refbot = 0x42C4, // R3.36
LariatHelper = 0x42C5, // R1.0
Helper = 0x233C
}

Expand All @@ -21,12 +20,12 @@ public enum AID : uint
BrutalImpactFirst = 37846, // Boss->self, 5.0s cast, range 60 circle
BrutalImpactRest = 37847, // Boss->self, no cast, range 60 circle

BrutalLariatVisual1 = 39670, // UnknownActor->self, 4.9s cast, single-target
BrutalLariatVisual1 = 39670, // LariatHelper->self, 4.9s cast, single-target
BrutalLariatVisual2 = 39636, // Boss->location, 4.9+1.2s cast, single-target
BrutalLariatVisual3 = 39637, // Boss->location, 4.9+1.2s cast, single-target
BrutalLariatVisual4 = 39808, // UnknownActor->self, 4.9s cast, single-target
BrutalLariatVisual5 = 39670, // UnknownActor->self, 4.9s cast, single-target
BrutalLariatVisual6 = 39671, // UnknownActor->self, no cast, single-target
BrutalLariatVisual4 = 39808, // LariatHelper->self, 4.9s cast, single-target
BrutalLariatVisual5 = 39670, // LariatHelper->self, 4.9s cast, single-target
BrutalLariatVisual6 = 39671, // LariatHelper->self, no cast, single-target
BrutalLariat1 = 39638, // Helper->self, 6.1s cast, range 50 width 34 rect
BrutalLariat2 = 39639, // Helper->self, 6.1s cast, range 50 width 34 rect

Expand All @@ -47,54 +46,39 @@ public enum AID : uint

BarbarousBarrage = 37810, // Boss->self, 4.0s cast, single-target, spawns towers
Explosion = 37811, // Helper->self, no cast, range 4 circle, knockback 22, away from source
UnmitigatedExplosion = 37812, // Helper->self, no cast, range 60 circle, tower fail

ExplosiveRain1 = 37837, // Helper->self, 5.0s cast, range 8 circle
ExplosiveRain2 = 37838, // Helper->self, 7.0s cast, range 8-16 donut
ExplosiveRain3 = 37839, // Helper->self, 9.0s cast, range 16-24 donut
ExplosiveRain4 = 38541, // Helper->self, 3.0s cast, range 6 circle

FireSpin1 = 37840, // Boss->self, 4.5+0.5s cast, single-target
FireSpin2 = 37841, // Boss->self, 4.5+0.5s cast, single-target
FireSpin3 = 37842, // Boss->self, no cast, single-target
FireSpin4 = 39768, // Helper->self, 5.0s cast, range 40 60-degree cone, 8 casts
FireSpin5 = 39769, // Helper->self, 0.5s cast, range 40 60-degree cone
FireSpinCW = 37840, // Boss->self, 4.5+0.5s cast, single-target
FireSpinCCW = 37841, // Boss->self, 4.5+0.5s cast, single-target
FireSpinVisual = 37842, // Boss->self, no cast, single-target
FireSpinFirst = 39768, // Helper->self, 5.0s cast, range 40 60-degree cone, 8 casts
FireSpinRest = 39769, // Helper->self, 0.5s cast, range 40 60-degree cone

FusesOfFury = 37814, // Boss->self, 4.0s cast, single-target

InfernalSpin1 = 39746, // Boss->self, 4.5+0.5s cast, single-target
InfernalSpin2 = 39747, // Boss->self, 4.5+0.5s cast, single-target
InfernalSpin3 = 39748, // Boss->self, no cast, single-target
InfernalSpin4 = 39770, // Helper->self, 5.0s cast, range 40 60-degree cone
InfernalSpin5 = 39771, // Helper->self, 0.5s cast, range 40 60-degree cone
InfernalSpinCW = 39746, // Boss->self, 4.5+0.5s cast, single-target
InfernalSpinCCW = 39747, // Boss->self, 4.5+0.5s cast, single-target
InfernalSpinVisual = 39748, // Boss->self, no cast, single-target
InfernalSpinFirst = 39770, // Helper->self, 5.0s cast, range 40 60-degree cone
InfernalSpinRest = 39771, // Helper->self, 0.5s cast, range 40 60-degree cone

KnuckleSandwich = 37845, // Boss->players, 5.0s cast, range 6 circle
KnuckleSandwich = 37845, // Boss->players, 5.0s cast, range 6 circle, shared tankbuster

MurderousMist = 37813, // Boss->self, 5.0s cast, range 40 270-degree cone

SelfDestruct1 = 37816, // LitFuse->self, 5.0s cast, range 8 circle
SelfDestruct2 = 37817, // LitFuse->self, 8.0s cast, range 8 circle
SelfDestruct2 = 37817 // LitFuse->self, 8.0s cast, range 8 circle
}

public enum SID : uint
{
Burns1 = 3065, // none->player, extra=0x0
Burns2 = 3066, // none->player, extra=0x0
Concussion = 997, // Helper->player, extra=0xF43
Doped = 4021, // Boss->Boss, extra=0x0
Poison = 2104, // Boss->player, extra=0x0
SustainedDamage = 2935, // Helper->player, extra=0x0
Trauma = 3796, // Helper->player, extra=0x1
Unknown1 = 4015, // none->LitFuse, extra=0x2DF
Unknown2 = 4016, // none->LitFuse, extra=0x2E0
Unknown3 = 4017, // none->LitFuse, extra=0x2E1
Unknown4 = 4018, // none->LitFuse, extra=0x2E2
VulnerabilityUp = 1789, // Boss/LitFuse/Helper->player, extra=0x1/0x2
}

public enum IconID : uint
{
Icon161 = 161, // player
Icon167 = 167, // Boss
Icon168 = 168, // Boss
Icon259 = 259, // player
LitFuseShort = 4015, // none->LitFuse, extra=0x2DF
LitFuseLong = 4016, // none->LitFuse, extra=0x2E0
LitFuseShortBurning = 4017, // none->LitFuse, extra=0x2E1
LitFuseLongBurning = 4018, // none->LitFuse, extra=0x2E2
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@ public M3NBruteBomberStates(BossModule module) : base(module)
.ActivateOnEnter<BrutalLariat2>()
.ActivateOnEnter<ExplosiveRainCircle>()
.ActivateOnEnter<ExplosiveRainConcentric>()
.ActivateOnEnter<InfernalSpin4>()
.ActivateOnEnter<SelfDestruct>()
.ActivateOnEnter<FireSpin4>()
.ActivateOnEnter<FireSpin5>()
.ActivateOnEnter<InfernalSpin4>()
.ActivateOnEnter<InfernalSpin5>()
.ActivateOnEnter<FireSpin>()
.ActivateOnEnter<LitFuse>()
.ActivateOnEnter<LariatCombo>()
.ActivateOnEnter<BrutalBurn>()
.ActivateOnEnter<MurderousMist>();
}
}

0 comments on commit 4d84419

Please sign in to comment.