forked from awgil/ffxiv_bossmod
-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from LeontopodiumNivale14/POTD-Dungeons
Potd dungeons
- Loading branch information
Showing
14 changed files
with
569 additions
and
28 deletions.
There are no files selected for viewing
103 changes: 103 additions & 0 deletions
103
BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD20CloningNode.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
namespace BossMod.Endwalker.DeepDungeon.EurekaOrthos.DD20CloningNode; | ||
|
||
public enum OID : uint | ||
{ | ||
Boss = 0x3E77, // R6.0 | ||
ClonedShieldDragon = 0x3E78, // R3.445 | ||
Helper = 0x233C | ||
} | ||
|
||
public enum AID : uint | ||
{ | ||
AutoAttack = 32817, // Boss->player, no cast, single-target | ||
Teleport = 32554, // ClonedShieldDragon->location, no cast, single-target | ||
|
||
FlameBreath = 32864, // Helper->self, 3.5s cast, range 50 30-degree cone | ||
FlameBreathVisual1 = 32544, // ClonedShieldDragon->self, 2.0+1,5s cast, single-target | ||
FlameBreathVisual2 = 32553, // ClonedShieldDragon->self, no cast, single-target | ||
FlameBreathVisual3 = 32552, // ClonedShieldDragon->self, no cast, single-target | ||
OffensiveCommand = 32543, // Boss->self, 5.0s cast, single-target | ||
OrderRelay = 32545, // Boss->self, 8.0s cast, single-target // problematic child | ||
PiercingLaser = 32547, // Boss->self, 2.5s cast, range 40 width 5 rect | ||
} | ||
class PiercingLaser(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.PiercingLaser), new AOEShapeRect(40, 2.5f)); | ||
class FlameBreath(BossModule module) : Components.GenericAOEs(module) | ||
{ | ||
private readonly List<AOEInstance> _aoes = []; | ||
private static readonly AOEShapeCone cone = new(50, 15.Degrees()); | ||
private static readonly float intercardinalDistance = 16 * MathF.Sqrt(2); | ||
private static readonly Angle[] AnglesIntercardinals = [-45.003f.Degrees(), 44.998f.Degrees(), 134.999f.Degrees(), -135.005f.Degrees()]; | ||
|
||
public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor) | ||
{ | ||
if (_aoes.Count > 0) | ||
foreach (var a in _aoes) | ||
if ((a.Activation - _aoes[0].Activation).TotalSeconds <= 1) | ||
yield return a; | ||
} | ||
|
||
public override void OnEventCast(Actor caster, ActorCastEvent spell) | ||
{ | ||
if ((AID)spell.Action.ID == AID.FlameBreathVisual3) | ||
{ | ||
var activation = WorldState.FutureTime(9.6f); | ||
|
||
if ((caster.Position - Arena.Center).LengthSq() > 625) | ||
_aoes.Add(new(cone, CalculatePosition(caster), caster.Rotation, activation)); | ||
else | ||
_aoes.Add(new(cone, RoundPosition(caster.Position), caster.Rotation, activation)); | ||
} | ||
} | ||
|
||
public override void OnCastFinished(Actor caster, ActorCastInfo spell) | ||
{ | ||
if (_aoes.Count > 0 && (AID)spell.Action.ID == AID.FlameBreath) | ||
_aoes.RemoveAt(0); | ||
} | ||
|
||
private static WPos CalculatePosition(Actor caster) | ||
{ | ||
var isIntercardinal = IsCasterIntercardinal(caster); | ||
var distance = isIntercardinal ? intercardinalDistance : 22; | ||
var position = caster.Position + distance * caster.Rotation.ToDirection(); | ||
return RoundPosition(position); | ||
} | ||
|
||
private static bool IsCasterIntercardinal(Actor caster) | ||
{ | ||
foreach (var angle in AnglesIntercardinals) | ||
if (caster.Rotation.AlmostEqual(angle, Angle.DegToRad)) | ||
return true; | ||
return false; | ||
} | ||
|
||
private static WPos RoundPosition(WPos position) => new(MathF.Round(position.X * 2) / 2, MathF.Round(position.Z * 2) / 2); | ||
} | ||
|
||
class EncounterHints(BossModule module) : BossComponent(module) | ||
{ | ||
public override void AddGlobalHints(GlobalHints hints) | ||
{ | ||
hints.Add($"{Module.PrimaryActor.Name} will tether to the clones on the edge of the arena. Those are the dragons that will be casting a cone.\nAfter a certain point, the boss will tether x2 sets of adds, find the first safe spot, rotate into the next."); | ||
} | ||
} | ||
|
||
class DD20CloningNodeStates : StateMachineBuilder | ||
{ | ||
public DD20CloningNodeStates(BossModule module) : base(module) | ||
{ | ||
TrivialPhase() | ||
.ActivateOnEnter<FlameBreath>() | ||
.ActivateOnEnter<PiercingLaser>() | ||
.DeactivateOnEnter<EncounterHints>(); | ||
} | ||
} | ||
|
||
[ModuleInfo(BossModuleInfo.Maturity.Contributed, Contributors = "LegendofIceman, Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 898, NameID = 12261)] | ||
public class DD20CloningNode : BossModule | ||
{ | ||
public DD20CloningNode(WorldState ws, Actor primary) : base(ws, primary, new(-300, -300), new ArenaBoundsCircle(19.5f)) | ||
{ | ||
ActivateComponent<EncounterHints>(); | ||
} | ||
} |
97 changes: 97 additions & 0 deletions
97
BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD40TwintaniasClone.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
namespace BossMod.Endwalker.DeepDungeon.EurekaOrthos.DD40TwintaniasClone; | ||
|
||
public enum OID : uint | ||
{ | ||
Boss = 0x3D1D, // R6.0 | ||
Twister = 0x1E8910, // R0.5 | ||
BitingWind = 0x3D1E, // R1.0 | ||
Helper = 0x233C | ||
} | ||
|
||
public enum AID : uint | ||
{ | ||
AutoAttack = 6497, // Boss->player, no cast, single-target | ||
|
||
BitingWind = 31464, // BitingWind->self, no cast, range 5 circle | ||
Gust = 31463, // Helper->location, 4.0s cast, range 5 circle | ||
MeracydianCyclone = 31462, // Boss->self, 3.0s cast, single-target | ||
MeracydianSquall = 31466, // Helper->location, 5.0s cast, range 5 circle | ||
MeracydianSquallVisual = 31465, // Boss->self, 3.0s cast, single-target | ||
Turbine = 31467, // Boss->self, 6.0s cast, range 60 circle, knockback 15, away from source | ||
TwisterTouch = 31470, // Helper->player, no cast, single-target, player got hit by twister | ||
TwisterVisual = 31468, // Boss->self, 5.0s cast, single-target | ||
TwistingDive = 31471 // Boss->self, 5.0s cast, range 50 width 15 rect | ||
} | ||
|
||
class Twister(BossModule module) : Components.CastTwister(module, 1, (uint)OID.Twister, ActionID.MakeSpell(AID.TwisterVisual), 0.4f, 0.25f); | ||
class BitingWind(BossModule module) : Components.PersistentVoidzoneAtCastTarget(module, 5, ActionID.MakeSpell(AID.BitingWind), m => m.Enemies(OID.BitingWind).Where(z => z.EventState != 7), 0.9f); | ||
class MeracydianSquall(BossModule module) : Components.LocationTargetedAOEs(module, ActionID.MakeSpell(AID.MeracydianSquall), 5); | ||
class TwistersHint(BossModule module, AID aid) : Components.CastHint(module, ActionID.MakeSpell(aid), "Twisters spawning, keep moving!"); | ||
class Twisters1(BossModule module) : TwistersHint(module, AID.TwisterVisual); | ||
class Twisters2(BossModule module) : TwistersHint(module, AID.TwistingDive); | ||
|
||
class TwistingDive(BossModule module) : Components.GenericAOEs(module) | ||
{ | ||
private AOEInstance? _aoe; | ||
private static readonly AOEShapeRect rect = new(50, 7.5f); | ||
private bool preparing; | ||
|
||
public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor) => Utils.ZeroOrOne(_aoe); | ||
|
||
public override void OnActorPlayActionTimelineEvent(Actor actor, ushort id) | ||
{ | ||
if (actor == Module.PrimaryActor) | ||
{ | ||
if (id == 0x1E3A) | ||
preparing = true; | ||
else if (preparing && id == 0x1E43) | ||
_aoe = new(rect, actor.Position, actor.Rotation, WorldState.FutureTime(6.9f)); | ||
} | ||
} | ||
|
||
public override void OnCastFinished(Actor caster, ActorCastInfo spell) | ||
{ | ||
if ((AID)spell.Action.ID == AID.TwistingDive) | ||
{ | ||
_aoe = null; | ||
preparing = false; | ||
} | ||
} | ||
} | ||
|
||
class Turbine(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.Turbine), 15) | ||
{ | ||
public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) | ||
{ | ||
var forbidden = new List<Func<WPos, float>>(); | ||
var component = Module.FindComponent<BitingWind>()?.ActiveAOEs(slot, actor)?.ToList(); | ||
var source = Sources(slot, actor).FirstOrDefault(); | ||
if (source != default && component != null) | ||
{ | ||
forbidden.Add(ShapeDistance.InvertedCircle(Arena.Center, 5)); | ||
forbidden.AddRange(component.Select(c => ShapeDistance.Cone(Arena.Center, 20, Angle.FromDirection(c.Origin - Arena.Center), 20.Degrees()))); | ||
if (forbidden.Count > 0) | ||
hints.AddForbiddenZone(p => forbidden.Select(f => f(p)).Min(), source.Activation); | ||
} | ||
} | ||
|
||
public override bool DestinationUnsafe(int slot, Actor actor, WPos pos) => (Module.FindComponent<BitingWind>()?.ActiveAOEs(slot, actor).Any(z => z.Shape.Check(pos, z.Origin, z.Rotation)) ?? false) || !Module.InBounds(pos); | ||
} | ||
|
||
class DD40TwintaniasCloneStates : StateMachineBuilder | ||
{ | ||
public DD40TwintaniasCloneStates(BossModule module) : base(module) | ||
{ | ||
TrivialPhase() | ||
.ActivateOnEnter<Twister>() | ||
.ActivateOnEnter<Twisters1>() | ||
.ActivateOnEnter<Twisters2>() | ||
.ActivateOnEnter<BitingWind>() | ||
.ActivateOnEnter<MeracydianSquall>() | ||
.ActivateOnEnter<Turbine>() | ||
.ActivateOnEnter<TwistingDive>(); | ||
} | ||
} | ||
|
||
[ModuleInfo(BossModuleInfo.Maturity.Contributed, Contributors = "LegendofIceman, Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 900, NameID = 12263)] | ||
public class DD40TwintaniasClone(WorldState ws, Actor primary) : BossModule(ws, primary, new(-600, -300), new ArenaBoundsCircle(20)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.