diff --git a/BossMod/AI/AIBehaviour.cs b/BossMod/AI/AIBehaviour.cs index 3ccd43ec6..7f1cc5b92 100644 --- a/BossMod/AI/AIBehaviour.cs +++ b/BossMod/AI/AIBehaviour.cs @@ -180,7 +180,7 @@ private void UpdateMovement(Actor player, Actor master, Targeting target, Action var toDest = _naviDecision.Destination != null ? _naviDecision.Destination.Value - player.Position : new(); var distSq = toDest.LengthSq(); ctrl.NaviTargetPos = _naviDecision.Destination; - //_ctrl.NaviTargetRot = distSq >= 0.01f ? toDest.Normalized() : null; + ctrl.NaviTargetRot = null; ctrl.NaviTargetVertical = master != player ? master.PosRot.Y : null; ctrl.AllowInterruptingCastByMovement = player.CastInfo != null && _naviDecision.LeewaySeconds <= (player.CastInfo.FinishAt - WorldState.CurrentTime).TotalSeconds - 0.5; ctrl.ForceCancelCast = player.CastInfo != null && TargetIsForbidden(player.CastInfo.TargetID); diff --git a/BossMod/Modules/Dawntrail/Dungeon/D01Ihuykatumu/D013Apollyon.cs b/BossMod/Modules/Dawntrail/Dungeon/D01Ihuykatumu/D013Apollyon.cs index 6ca552b32..e53d06d27 100644 --- a/BossMod/Modules/Dawntrail/Dungeon/D01Ihuykatumu/D013Apollyon.cs +++ b/BossMod/Modules/Dawntrail/Dungeon/D01Ihuykatumu/D013Apollyon.cs @@ -30,78 +30,57 @@ class Blade(BossModule module) : Components.SingleTargetCast(module, ActionID.Ma class HighWind(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.HighWind)); class BladesOfFamine(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.BladesOfFamine), new AOEShapeRect(50, 6)); class WingOfLightning(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.WingOfLightning), new AOEShapeCone(40, 22.5f.Degrees()), maxCasts: 8); -class LightningHelper(BossModule module) : Components.PersistentVoidzone(module, 4, m => m.Enemies(OID.LightningAOE)); +class LightningHelper(BossModule module) : Components.PersistentVoidzone(module, 4, m => m.Enemies(OID.LightningAOE).Where(x => x.EventState != 7)); class ThunderIII(BossModule module) : Components.SpreadFromCastTargets(module, ActionID.MakeSpell(AID.ThunderIII), 6); class BladeAOE(BossModule module) : Components.BaitAwayCast(module, ActionID.MakeSpell(AID.BladeAOE), new AOEShapeCircle(6), centerAtTarget: true); -class WindSickle(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.WindSickle), new AOEShapeDonut(6, 60)); +class WindSickle(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.WindSickle), new AOEShapeDonut(5, 60)); class RazorStorm(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.RazorStorm), new AOEShapeRect(40, 20)); class Levinsickle(BossModule module) : Components.LocationTargetedAOEs(module, ActionID.MakeSpell(AID.Levinsickle), 4); class LevinsickleSpark(BossModule module) : Components.LocationTargetedAOEs(module, ActionID.MakeSpell(AID.LevinsickleSpark), 4); -// first aoe is 10 seconds after windwhistle -// rest are 8 seconds after previous -class Whirlwind(BossModule module) : Components.GenericAOEs(module) +class CuttingWind(BossModule module) : Components.GenericAOEs(module) { - private int _activations; - private DateTime _nextActivation; + private readonly List _aoes = []; + private static readonly AOEShapeRect Shape = new(36, 4, 36); + public override IEnumerable ActiveAOEs(int slot, Actor actor) => _aoes.Take(4); + + private readonly List _northPositions = [new(-111.69f, 253.94f), new(-102.28f, 264.31f), new(-108.92f, 276.53f)]; + private readonly List _southPositions = [new(-102.93f, 274.36f), new(-108.68f, 262.22f), new(-105.73f, 252.34f)]; + + private static readonly float[] CastTimers = [8.9f, 16.9f, 24.9f]; private static readonly List Rotations = [0.Degrees(), 45.Degrees(), 90.Degrees(), 135.Degrees()]; - public override void OnCastFinished(Actor caster, ActorCastInfo spell) + private void AddAOEs(WPos pos, float delay) { - if ((AID)spell.Action.ID == AID.Windwhistle) - _nextActivation = WorldState.FutureTime(10); + foreach (var angle in Rotations) + _aoes.Add(new(Shape, pos, angle, Module.WorldState.FutureTime(delay))); } - public override void DrawArenaBackground(int pcSlot, Actor pc) + public override void OnActorCreated(Actor actor) { - foreach (var c in ActiveAOEs(pcSlot, pc)) + if ((OID)actor.OID == OID.Whirlwind) { - c.Shape.Draw(Arena, c.Origin, c.Rotation, c.Color); - c.Shape.Outline(Arena, c.Origin, c.Rotation, ArenaColor.AOE); + var coords = actor.Position.Z < 265 ? _northPositions : _southPositions; + foreach (var (c, d) in coords.Zip(CastTimers)) + AddAOEs(c, d); } } public override void OnEventCast(Actor caster, ActorCastEvent spell) { - if ((AID)spell.Action.ID == AID.Cuttingwind) - { - _activations += 1; - _nextActivation = WorldState.FutureTime(8); - } - } - - public override void OnActorDestroyed(Actor actor) - { - _activations = 0; - _nextActivation = default; - } - - public override IEnumerable ActiveAOEs(int slot, Actor actor) - { - if (_activations >= 12) - yield break; - - var whirlwind = Module.Enemies(OID.Whirlwind).FirstOrDefault(); - if (whirlwind == null) - yield break; - - var whirlyHelper = Module.Enemies(OID.Helper).FirstOrDefault(x => x.NameID == 12715); - if (whirlyHelper == null) - yield break; - - foreach (var angle in Rotations) - { - yield return new AOEInstance(new AOEShapeRect(72, 4, 72), whirlwind.Position, angle, _nextActivation, Shade(_nextActivation), _nextActivation < WorldState.FutureTime(4)); - } + if (_aoes.Count > 0 && (AID)spell.Action.ID == AID.Cuttingwind) + _aoes.RemoveAt(0); } +} - private uint Shade(DateTime activation) +class Whirlwind(BossModule module) : Components.PersistentVoidzone(module, 4, m => m.Enemies(OID.Whirlwind)) +{ + public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { - var clampedETA = Math.Clamp((activation - WorldState.CurrentTime).TotalSeconds, 0, 4); - var opacity = 1 - clampedETA / 4; - var alpha = (uint)(opacity * 96) + 32; - return 0x008080 + alpha * 0x1000000; + base.AddAIHints(slot, actor, assignment, hints); + if (Sources(Module).FirstOrDefault() is Actor w) + hints.AddForbiddenZone(new AOEShapeRect(6, 4, 4), w.Position, w.Rotation); } } @@ -122,7 +101,9 @@ public D013ApollyonStates(BossModule module) : base(module) .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter() - .ActivateOnEnter(); + .ActivateOnEnter() + .ActivateOnEnter() + ; } } diff --git a/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D021RyoqorTerteh.cs b/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D021RyoqorTerteh.cs index 650889a04..ccb121731 100644 --- a/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D021RyoqorTerteh.cs +++ b/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D021RyoqorTerteh.cs @@ -17,8 +17,8 @@ public enum AID : uint public enum SID : uint { - // frozen adds always get both 3944 and 3445, no idea what the difference is. i just picked my favorite Frozen = 3944, // none->_Gen_RorrlohTeh/_Gen_QorrlohTeh1, extra=0x0 + Frozen2 = 3445 } class FrostingFracas(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.FrostingFracas)); @@ -64,7 +64,7 @@ public override void OnCastFinished(Actor caster, ActorCastInfo spell) public override void OnStatusGain(Actor actor, ActorStatus status) { - if ((SID)status.ID is SID.Frozen && _casters.ContainsKey(actor)) + if ((SID)status.ID is SID.Frozen or SID.Frozen2 && _casters.ContainsKey(actor)) { _casters[actor] = true; _numFrozen += 1; diff --git a/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D022Kahderyor.cs b/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D022Kahderyor.cs index 014c549a2..dd3940aed 100644 --- a/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D022Kahderyor.cs +++ b/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D022Kahderyor.cs @@ -154,7 +154,7 @@ public override void AddHints(int slot, Actor actor, TextHints hints) } } class SeedCrystals(BossModule module) : Components.SpreadFromCastTargets(module, ActionID.MakeSpell(AID.SeedCrystals), 6); -class CyclonicRing(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.CyclonicRing), new AOEShapeDonut(15, 40)); +class CyclonicRing(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.CyclonicRing), new AOEShapeDonut(7.5f, 40)); class StalagmiteCircle(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.StalagmiteCircle), new AOEShapeCircle(15)); class EyeOfTheFierce(BossModule module) : Components.CastGaze(module, ActionID.MakeSpell(AID.EyeOfTheFierce));