From 43fbfa9196af8f279eb74febfc70b5af0c64ef00 Mon Sep 17 00:00:00 2001 From: CarnifexOptimus <156172553+CarnifexOptimus@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:01:41 +0200 Subject: [PATCH] Seiryu nm verified --- BossMod/Components/BaitAway.cs | 9 +- BossMod/Components/Towers.cs | 3 +- .../Stormblood/Trial/T09Seiryu/BlueBolt.cs | 43 ++++++++ .../Trial/T09Seiryu/ForbiddenArts.cs | 49 +++++++++ .../Trial/T09Seiryu/OnmyoSerpentEyeSigil.cs | 25 +++++ .../Trial/T09Seiryu/SerpentsAscending.cs | 25 +++++ .../Stormblood/Trial/T09Seiryu/T09Seiryu.cs | 96 +++++++++++++---- .../Trial/T09Seiryu/T09SeiryuEnums.cs | 101 ++++++++---------- .../Trial/T09Seiryu/T09SeiryuStates.cs | 25 +++-- BossMod/Pathfinding/NavigationDecision.cs | 2 +- 10 files changed, 282 insertions(+), 96 deletions(-) create mode 100644 BossMod/Modules/Stormblood/Trial/T09Seiryu/BlueBolt.cs create mode 100644 BossMod/Modules/Stormblood/Trial/T09Seiryu/ForbiddenArts.cs create mode 100644 BossMod/Modules/Stormblood/Trial/T09Seiryu/OnmyoSerpentEyeSigil.cs create mode 100644 BossMod/Modules/Stormblood/Trial/T09Seiryu/SerpentsAscending.cs diff --git a/BossMod/Components/BaitAway.cs b/BossMod/Components/BaitAway.cs index 4ab6aca34a..35043ad280 100644 --- a/BossMod/Components/BaitAway.cs +++ b/BossMod/Components/BaitAway.cs @@ -84,11 +84,13 @@ public BaitAwayEveryone(BossModule module, Actor? source, AOEShape shape, Action } // component for mechanics requiring tether targets to bait their aoe away from raid -public class BaitAwayTethers(BossModule module, AOEShape shape, uint tetherID, ActionID aid = default) : GenericBaitAway(module, aid) +public class BaitAwayTethers(BossModule module, AOEShape shape, uint tetherID, ActionID aid = default, uint enemyOID = default, float activationDelay = default) : GenericBaitAway(module, aid) { public AOEShape Shape = shape; public uint TID = tetherID; public bool DrawTethers = true; + public readonly IReadOnlyList _enemies = module.Enemies(enemyOID); + public float ActivationDelay = activationDelay; public override void DrawArenaForeground(int pcSlot, Actor pc) { @@ -108,9 +110,8 @@ public override void OnTethered(Actor source, ActorTetherInfo tether) { var (player, enemy) = DetermineTetherSides(source, tether); if (player != null && enemy != null) - { - CurrentBaits.Add(new(enemy, player, Shape)); - } + if (enemyOID == default || _enemies.Contains(source)) + CurrentBaits.Add(new(enemy, player, Shape, WorldState.FutureTime(ActivationDelay))); } public override void OnUntethered(Actor source, ActorTetherInfo tether) diff --git a/BossMod/Components/Towers.cs b/BossMod/Components/Towers.cs index f066108ff1..01baaa6460 100644 --- a/BossMod/Components/Towers.cs +++ b/BossMod/Components/Towers.cs @@ -2,13 +2,14 @@ public class GenericTowers(BossModule module, ActionID aid = default) : CastCounter(module, aid) { - public struct Tower(WPos position, float radius, int minSoakers = 1, int maxSoakers = 1, BitMask forbiddenSoakers = default) + public struct Tower(WPos position, float radius, int minSoakers = 1, int maxSoakers = 1, BitMask forbiddenSoakers = default, DateTime activation = default) { public WPos Position = position; public float Radius = radius; public int MinSoakers = minSoakers; public int MaxSoakers = maxSoakers; public BitMask ForbiddenSoakers = forbiddenSoakers; + public DateTime Activation = activation; public readonly bool IsInside(WPos pos) => pos.InCircle(Position, Radius); public readonly bool IsInside(Actor actor) => IsInside(actor.Position); diff --git a/BossMod/Modules/Stormblood/Trial/T09Seiryu/BlueBolt.cs b/BossMod/Modules/Stormblood/Trial/T09Seiryu/BlueBolt.cs new file mode 100644 index 0000000000..6a00753360 --- /dev/null +++ b/BossMod/Modules/Stormblood/Trial/T09Seiryu/BlueBolt.cs @@ -0,0 +1,43 @@ +namespace BossMod.Stormblood.Trial.T09Seiryu; + +// TODO: create and use generic 'line stack' component +class BlueBolt(BossModule module) : Components.GenericBaitAway(module) +{ + private Actor? target; + + public override void OnEventCast(Actor caster, ActorCastEvent spell) + { + if ((AID)spell.Action.ID == AID.BlueBoltMarker) + { + target = WorldState.Actors.Find(spell.MainTargetID); + CurrentBaits.Add(new(Module.PrimaryActor, target!, new AOEShapeRect(83, 2.5f), Module.WorldState.FutureTime(5.9f))); + } + if ((AID)spell.Action.ID == AID.BlueBolt) + CurrentBaits.Clear(); + } + + public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + if (CurrentBaits.Count > 0 && actor != target && !Module.FindComponent()!.CurrentBaits.Any(x => x.Target == actor)) + hints.AddForbiddenZone(ShapeDistance.InvertedRect(Module.PrimaryActor.Position, (target!.Position - Module.PrimaryActor.Position).Normalized(), 83, default, 2.5f)); + } + + public override void AddHints(int slot, Actor actor, TextHints hints) + { + if (CurrentBaits.Count > 0 && !Module.FindComponent()!.CurrentBaits.Any(x => x.Target == actor)) + { + if (!actor.Position.InRect(Module.PrimaryActor.Position, (target!.Position - Module.PrimaryActor.Position).Normalized(), 83, default, 2.5f)) + hints.Add("Stack!"); + else + hints.Add("Stack!", false); + } + } + + public override void DrawArenaBackground(int pcSlot, Actor pc) + { + foreach (var bait in CurrentBaits) + bait.Shape.Draw(Arena, BaitOrigin(bait), bait.Rotation, ArenaColor.SafeFromAOE); + } + + public override void DrawArenaForeground(int pcSlot, Actor pc) { } +} diff --git a/BossMod/Modules/Stormblood/Trial/T09Seiryu/ForbiddenArts.cs b/BossMod/Modules/Stormblood/Trial/T09Seiryu/ForbiddenArts.cs new file mode 100644 index 0000000000..ffb293d7bf --- /dev/null +++ b/BossMod/Modules/Stormblood/Trial/T09Seiryu/ForbiddenArts.cs @@ -0,0 +1,49 @@ +namespace BossMod.Stormblood.Trial.T09Seiryu; + +// TODO: create and use generic 'line stack' component +class ForbiddenArts(BossModule module) : Components.GenericBaitAway(module) +{ + private Actor? target; + + public override void OnEventCast(Actor caster, ActorCastEvent spell) + { + if ((AID)spell.Action.ID == AID.ForbiddenArtsMarker) + { + target = WorldState.Actors.Find(spell.MainTargetID); + CurrentBaits.Add(new(Module.PrimaryActor, target!, new AOEShapeRect(84.4f, 4), Module.WorldState.FutureTime(5.2f))); + } + if ((AID)spell.Action.ID is AID.ForbiddenArts1 or AID.ForbiddenArts2) + { + if (++NumCasts == 2) + { + NumCasts = 0; + CurrentBaits.Clear(); + } + } + } + + public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + if (CurrentBaits.Count > 0 && actor != target) + hints.AddForbiddenZone(ShapeDistance.InvertedRect(Module.PrimaryActor.Position, (target!.Position - Module.PrimaryActor.Position).Normalized(), 84.4f, default, 4)); + } + + public override void AddHints(int slot, Actor actor, TextHints hints) + { + if (CurrentBaits.Count > 0) + { + if (!actor.Position.InRect(Module.PrimaryActor.Position, (target!.Position - Module.PrimaryActor.Position).Normalized(), 84.4f, default, 4)) + hints.Add("Stack!"); + else + hints.Add("Stack!", false); + } + } + + public override void DrawArenaBackground(int pcSlot, Actor pc) + { + foreach (var bait in CurrentBaits) + bait.Shape.Draw(Arena, BaitOrigin(bait), bait.Rotation, ArenaColor.SafeFromAOE); + } + + public override void DrawArenaForeground(int pcSlot, Actor pc) { } +} diff --git a/BossMod/Modules/Stormblood/Trial/T09Seiryu/OnmyoSerpentEyeSigil.cs b/BossMod/Modules/Stormblood/Trial/T09Seiryu/OnmyoSerpentEyeSigil.cs new file mode 100644 index 0000000000..776926cc3e --- /dev/null +++ b/BossMod/Modules/Stormblood/Trial/T09Seiryu/OnmyoSerpentEyeSigil.cs @@ -0,0 +1,25 @@ +namespace BossMod.Stormblood.Trial.T09Seiryu; + +class OnmyoSerpentEyeSigil(BossModule module) : Components.GenericAOEs(module) +{ + private AOEInstance? _aoe; + private static readonly AOEShapeDonut donut = new(6.95f, 30.05f); //adjusted sizes slightly since cast is done by helper with non identical position + private static readonly AOEShapeCircle circle = new(12.05f); + + public override IEnumerable ActiveAOEs(int slot, Actor actor) => Utils.ZeroOrOne(_aoe); + + public override void OnActorModelStateChange(Actor actor, byte modelState, byte animState1, byte animState2) + { + var activation = Module.WorldState.FutureTime(5.6f); + if (modelState == 32) + _aoe = new(circle, Module.PrimaryActor.Position, default, activation); + if (modelState == 33) + _aoe = new(donut, Module.PrimaryActor.Position, default, activation); + } + + public override void OnCastFinished(Actor caster, ActorCastInfo spell) + { + if ((AID)spell.Action.ID is AID.OnmyoSigil2 or AID.SerpentEyeSigil2) + _aoe = null; + } +} diff --git a/BossMod/Modules/Stormblood/Trial/T09Seiryu/SerpentsAscending.cs b/BossMod/Modules/Stormblood/Trial/T09Seiryu/SerpentsAscending.cs new file mode 100644 index 0000000000..591dc289ac --- /dev/null +++ b/BossMod/Modules/Stormblood/Trial/T09Seiryu/SerpentsAscending.cs @@ -0,0 +1,25 @@ +namespace BossMod.Stormblood.Trial.T09Seiryu; + +class SerpentAscending(BossModule module) : Components.GenericTowers(module) +{ + public override void OnActorCreated(Actor actor) + { + if ((OID)actor.OID == OID.Towers) + Towers.Add(new(actor.Position, 3, 1, 1, activation: Module.WorldState.FutureTime(7.8f))); + } + + public override void OnEventCast(Actor caster, ActorCastEvent spell) + { + if ((AID)spell.Action.ID is AID.SerpentsFang or AID.SerpentsJaws) + Towers.Clear(); + } + + public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + var forbidden = new List>(); + foreach (var t in Towers.Where(x => !Raid.WithoutSlot().InRadius(x.Position, 3).Any() || actor.Position.InCircle(x.Position, 3))) + forbidden.Add(ShapeDistance.InvertedCircle(t.Position, 3)); + if (forbidden.Count > 0) + hints.AddForbiddenZone(p => forbidden.Select(f => f(p)).Max(), Towers[0].Activation); + } +} diff --git a/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09Seiryu.cs b/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09Seiryu.cs index a13212e140..ab41b0289a 100644 --- a/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09Seiryu.cs +++ b/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09Seiryu.cs @@ -1,35 +1,89 @@ namespace BossMod.Stormblood.Trial.T09Seiryu; class HundredTonzeSwing(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.HundredTonzeSwing), new AOEShapeCircle(16)); -class CoursingRiverCircleAOE(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.CoursingRiverCircleAOE), 25, kind: Kind.DirForward); -class CoursingRiverRectAOE(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.CoursingRiverRectAOE)); -class DragonsWake2(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.DragonsWake2)); +class CoursingRiver(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.CoursingRiverAOE), 25, true, kind: Kind.DirForward) +{ + public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + if (!Module.FindComponent()!.ActiveAOEs(slot, actor).Any()) + foreach (var c in Casters) + hints.AddForbiddenZone(ShapeDistance.Rect(c.CastInfo!.Rotation.AlmostEqual(90.Degrees(), Helpers.RadianConversion) ? c.Position - new WDir(12.5f, 0) : c.Position - new WDir(-12.5f, 0), c.Rotation, 50, default, 20), c.CastInfo!.NPCFinishAt); + } +} + +class DragonsWake(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.DragonsWake2)); class FifthElement(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.FifthElement)); class FortuneBladeSigil(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.FortuneBladeSigil), new AOEShapeRect(50, 2, 50)); -class GreatTyphoon28(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.GreatTyphoon28), new AOEShapeDonut(20, 28)); -class GreatTyphoon34(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.GreatTyphoon34), new AOEShapeDonut(20, 34)); -class GreatTyphoon40(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.GreatTyphoon40), new AOEShapeDonut(20, 40)); - -class InfirmSoul(BossModule module) : Components.SingleTargetCast(module, ActionID.MakeSpell(AID.InfirmSoul)); -class InfirmSoulSpread(BossModule module) : Components.SpreadFromCastTargets(module, ActionID.MakeSpell(AID.InfirmSoul), 4); +class InfirmSoul(BossModule module) : Components.BaitAwayCast(module, ActionID.MakeSpell(AID.InfirmSoul), new AOEShapeCircle(4), true) +{ + public override void AddGlobalHints(GlobalHints hints) + { + if (CurrentBaits.Count > 0) + hints.Add("Tankbuster cleave"); + } +} -class Kanabo1(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.Kanabo1), new AOEShapeCone(45, 30.Degrees())); -class OnmyoSigil2(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.OnmyoSigil2), new AOEShapeCircle(12)); +class SerpentDescending(BossModule module) : Components.SpreadFromIcon(module, (uint)IconID.Spreadmarker, ActionID.MakeSpell(AID.SerpentDescending), 5, 6); +class YamaKagura(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.YamaKagura), new AOEShapeRect(60, 3)); +class Handprint(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.Handprint4), new AOEShapeCone(40, 90.Degrees())); -class SerpentDescending(BossModule module) : Components.SpreadFromCastTargets(module, ActionID.MakeSpell(AID.SerpentDescending), 5); +class ForceOfNature1(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.ForceOfNature1), 10) +{ + public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + if (Sources(slot, actor).Any()) + hints.AddForbiddenZone(ShapeDistance.InvertedCircle(Module.Center, 10), Sources(slot, actor).FirstOrDefault().Activation); + } +} +class ForceOfNature2(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.ForceOfNature2), new AOEShapeCircle(5)); +class KanaboBait(BossModule module) : Components.BaitAwayTethers(module, new AOEShapeCone(45, 30.Degrees()), (uint)TetherID.BaitAway, ActionID.MakeSpell(AID.Kanabo1), (uint)OID.IwaNoShiki, 5.9f) +{ + public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + base.AddAIHints(slot, actor, assignment, hints); + if (CurrentBaits.Any(x => x.Target == actor)) + hints.AddForbiddenZone(ShapeDistance.Circle(Module.Center, 19), Module.WorldState.FutureTime(ActivationDelay)); + } +} -class SerpentEyeSigil2(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.SerpentEyeSigil2), new AOEShapeDonut(6, 30)); +class KanaboAOE(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.Kanabo1), new AOEShapeCone(45, 30.Degrees())); -class YamaKagura(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.YamaKagura), new AOEShapeRect(60, 3)); +class RedRush(BossModule module) : Components.BaitAwayTethers(module, new AOEShapeRect(82.6f, 2.5f), (uint)TetherID.BaitAway, ActionID.MakeSpell(AID.RedRush), (uint)OID.AkaNoShiki, 6) +{ + public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + base.AddAIHints(slot, actor, assignment, hints); + var activation = Module.WorldState.FutureTime(ActivationDelay); + if (CurrentBaits.Any(x => x.Target == actor) && Module.Bounds == T09Seiryu.phase2Bounds) + hints.AddForbiddenZone(ShapeDistance.InvertedCircle(Module.Center, 5), activation); + else if (CurrentBaits.Any(x => x.Target == actor) && Module.Bounds == T09Seiryu.phase1Bounds) + hints.AddForbiddenZone(ShapeDistance.Circle(Module.Center, 18.5f), activation); + } +} -class Handprint3(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.Handprint3), new AOEShapeCone(20, 90.Degrees())); -class Handprint4(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.Handprint4), new AOEShapeCone(40, 90.Degrees())); +class ArenaChange(BossModule module) : BossComponent(module) +{ -class ForceOfNature1(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.ForceOfNature1), 10, stopAtWall: true, kind: Kind.AwayFromOrigin); -class ForceOfNature2(BossModule module) : Components.SelfTargetedAOEs(module, ActionID.MakeSpell(AID.ForceOfNature2), new AOEShapeCircle(5)); + public override void OnCastFinished(Actor caster, ActorCastInfo spell) + { + if ((AID)spell.Action.ID == AID.StrengthOfSpirit) // in phase 2 the arena no longer got a wall and we need to add back the player hitboxradius + Module.Arena.Bounds = T09Seiryu.phase2Bounds; + } +} -class KanaboTether(BossModule module) : Components.BaitAwayTethers(module, new AOEShapeCone(45, 30.Degrees()), (uint)TetherID.BaitAway, ActionID.MakeSpell(AID.Kanabo1)); +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)); + } +} -[ModuleInfo(BossModuleInfo.Maturity.WIP, Contributors = "The Combat Reborn Team", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 637, NameID = 7922)] -public class T09Seiryu(WorldState ws, Actor primary) : BossModule(ws, primary, new(100, 100), new ArenaBoundsCircle(20)); +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "The Combat Reborn Team (Malediktus, LTS)", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 637, NameID = 7922)] +public class T09Seiryu(WorldState ws, Actor primary) : BossModule(ws, primary, new(100, 100), phase1Bounds) +{ + public static readonly ArenaBounds phase1Bounds = new ArenaBoundsCircle(19.5f); + public static readonly ArenaBounds phase2Bounds = new ArenaBoundsCircle(20); +} diff --git a/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09SeiryuEnums.cs b/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09SeiryuEnums.cs index 533d2fe6e7..336e73ef71 100644 --- a/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09SeiryuEnums.cs +++ b/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09SeiryuEnums.cs @@ -2,33 +2,36 @@ public enum OID : uint { - Boss = 0x25F4, // R4.400, x1 - Helper = 0x233C, // R0.500, x30, 523 type - AkaNoShiki = 0x2786, // R2.600, x0 (spawn during fight) - AoNoShiki = 0x2787, // R3.000, x0 (spawn during fight) - IwaNoShiki = 0x2788, // R4.000, x0 (spawn during fight) - BlueOrochi = 0x2672, // R1.000, x0 (spawn during fight) - TenNoShiki = 0x25F8, // R2.700, x0 (spawn during fight) - NumaNoShiki = 0x25F6, // R2.400, x0 (spawn during fight) - DoroNoShiki = 0x25F7, // R1.440, x0 (spawn during fight) - BlueOrochi1 = 0x25F5, // R1.000, x0 (spawn during fight) - BlueOrochi2 = 0x2658, // R1.000, x0 (spawn during fight) - BlueOrochi3 = 0x2659, // R1.000, x0 (spawn during fight) - YamaNoShiki = 0x25F9, // R12.000, x0 (spawn during fight) + Boss = 0x25F4, // R4.4 + Helper = 0x233C, + AkaNoShiki = 0x2786, // R2.6 + AoNoShiki = 0x2787, // R3.0 + IwaNoShiki = 0x2788, // R4.0 + BlueOrochi = 0x2672, // R1.0 + TenNoShiki = 0x25F8, // R2.7 + NumaNoShiki = 0x25F6, // R2.4 + DoroNoShiki = 0x25F7, // R1.44 + BlueOrochi1 = 0x25F5, // R1.0 + BlueOrochi2 = 0x2658, // R1.0 + BlueOrochi3 = 0x2659, // R1.0 + YamaNoShiki = 0x25F9, // R12.0 + Towers = 0x1EAA3C // R0.5 } public enum AID : uint { AutoAttack = 870, // Boss->player, no cast, single-target - MobAutoAttack = 872, // NumaNoShiki/DoroNoShiki->player, no cast, single-target + AutoAttack2 = 872, // NumaNoShiki/DoroNoShiki->player, no cast, single-target - HundredTonzeSwing = 15390, // IwaNoShiki->self, 4.0s cast, range 16 circle// + HundredTonzeSwing = 15390, // IwaNoShiki->self, 4.0s cast, range 16 circle - BlueBolt = 15388, // AoNoShiki->self, no cast, range 80+R width 5 rect + BlueBoltMarker = 14319, // Helper->player, no cast, single-target, applies linestack marker + BlueBolt = 15388, // AoNoShiki->self, no cast, range 80+R width 5 rect, line stack + RedRush = 15389, // AkaNoShiki->self, no cast, range 80+R width 5 rect, knockback bait, 15 awayfromsource CoursingRiver1 = 14325, // BlueOrochi1->self, 5.0s cast, single-target - CoursingRiverCircleAOE = 14349, // Helper->self, 7.5s cast, range 21 circle // knockback dirforward 25 - CoursingRiverRectAOE = 14350, // Helper->self, 7.5s cast, range 90+R width 90 rect + CoursingRiverAOE = 14349, // Helper->self, 7.5s cast, range 21 circle, knockback dirforward 25 + CoursingRiver = 14350, // Helper->self, 7.5s cast, range 90+R width 90 rect, visual?, doesn't seem to do anything CoursingRiver4 = 14626, // BlueOrochi2->self, 5.0s cast, single-target CoursingRiver5 = 14627, // BlueOrochi3->self, 5.0s cast, single-target @@ -40,79 +43,65 @@ public enum AID : uint FifthElement = 14334, // Boss->self, 4.0s cast, range 100 circle - ForbiddenArts1 = 14277, // Helper->player, no cast, single-target - ForbiddenArts2 = 15474, // Boss->self, no cast, range 80+R width 8 rect - ForbiddenArts3 = 15490, // Boss->self, no cast, range 80+R width 8 rect + ForbiddenArtsMarker = 14277, // Helper->player, no cast, single-target, applies linestack marker + ForbiddenArts1 = 15474, // Boss->self, no cast, range 80+R width 8 rect + ForbiddenArts2 = 15490, // Boss->self, no cast, range 80+R width 8 rect FortuneBladeSigil = 14342, // Helper->self, 6.5s cast, range 50+R width 4 rect - GreatTyphoon28 = 14352, // Helper->self, 3.0s cast, range ?-28 donut - GreatTyphoon34 = 14353, // Helper->self, 3.0s cast, range ?-34 donut - GreatTyphoon40 = 14354, // Helper->self, 3.0s cast, range ?-40 donut + GreatTyphoon28 = 14352, // Helper->self, 3.0s cast, range ?-28 donut, outside of arena + GreatTyphoon34 = 14353, // Helper->self, 3.0s cast, range ?-34 donut, outside of arena + GreatTyphoon40 = 14354, // Helper->self, 3.0s cast, range ?-40 donut, outside of arena + InfirmSoul = 14333, // Boss->player, 5.0s cast, range 4 circle, tankbuster - InfirmSoul = 14333, // Boss->player, 5.0s cast, range 4 circle //tankbuster - - Kanabo1 = 15391, // IwaNoShiki->self, 3.0s cast, range 40+R 60-degree cone - Kanabo2 = 15392, // IwaNoShiki->self, 6.0s cast, single-target + KanaboVisual = 14316, // IwaNoShiki->location, no cast, ??? + Kanabo1 = 15392, // IwaNoShiki->self, 6.0s cast, single-target + Kanabo2 = 15391, // IwaNoShiki->self, 3.0s cast, range 40+R 60-degree cone KujiKiri = 14305, // Boss->self, 4.0s cast, single-target OnmyoSigil1 = 14338, // Boss->self, no cast, single-target OnmyoSigil2 = 14855, // Helper->self, 3.0s cast, range 12 circle - RedRush = 15389, // AkaNoShiki->self, no cast, range 80+R width 5 rect - - SerpentAscending1 = 14300, // Boss->self, no cast, single-target - SerpentAscending2 = 15397, // Boss->self, 4.0s cast, single-target - + SerpentAscending = 14300, // Boss->self, no cast, single-target SerpentDescending = 14340, // Helper->player, 6.0s cast, range 5 circle + SerpentAscendingTowers = 15397, // Boss->self, 4.0s cast, single-target + SerpentsFang = 14988, // Helper->self, no cast, range 3 circle + SerpentsJaws = 14989, // Helper->self, no cast, range 80 circle, tower fail + SerpentEyeSigil1 = 14339, // Boss->self, no cast, single-target - SerpentEyeSigil2 = 14856, // Helper->self, 3.0s cast, range ?-30 donut + SerpentEyeSigil2 = 14856, // Helper->self, 3.0s cast, range 7-30 donut - StrengthOfSpirit = 14281, // Boss->self, 5.0s cast, range 80 circle // Transitions fight to Phase 2 + StrengthOfSpirit = 14281, // Boss->self, 5.0s cast, range 80 circle, knockback 24, awayfromsource, Transitions fight to Phase 2 SummonShiki1 = 14286, // Boss->self, 3.0s cast, single-target SummonShiki2 = 14287, // Boss->self, 3.0s cast, single-target SummonShiki3 = 14288, // Boss->self, 5.0s cast, single-target - UnknownAbility1 = 14276, // Boss->location, no cast, ??? - UnknownAbility2 = 14293, // Boss->location, no cast, ??? - UnknownAbility3 = 14316, // IwaNoShiki->location, no cast, ??? - UnknownAbility4 = 14319, // Helper->player, no cast, single-target + Teleport1 = 14276, // Boss->location, no cast, ??? + Teleport2 = 14293, // Boss->location, no cast, ??? YamaKagura = 14355, // TenNoShiki->self, 5.0s cast, range 60+R width 6 rect Handprint1 = 14309, // YamaNoShiki->self, no cast, single-target Handprint2 = 14310, // YamaNoShiki->self, no cast, single-target - Handprint3 = 14343, // Helper->self, 4.5s cast, range 20 ?-degree cone - Handprint4 = 14344, // Helper->self, 4.5s cast, range 40 ?-degree cone + Handprint3 = 14343, // Helper->self, 4.5s cast, range 20 180-degree cone, handprint 3 and 4 happen at exactly the same time and spot + Handprint4 = 14344, // Helper->self, 4.5s cast, range 40 180-degree cone - ForceOfNature1 = 14346, // Helper->self, 5.0s cast, range 21 circle // knockback 10 AwayFromOrigin + ForceOfNature1 = 14346, // Helper->self, 5.0s cast, range 21 circle, knockback 10 AwayFromOrigin ForceOfNature2 = 14345, // Helper->self, 5.0s cast, range 5 circle ForceOfNature3 = 14313, // YamaNoShiki->self, no cast, single-target SummonShiki = 14285, // Boss->self, 3.0s cast, single-target } -public enum SID : uint -{ - Fetters = 1726, // Boss->player, extra=0xEC7 - VulnerabilityUp1 = 1054, // none->player, extra=0x0 - Drowning = 1696, // none->player, extra=0x1818 - VulnerabilityUp2 = 1597, // Helper->player, extra=0x1/0x2 - BluntResistanceDown = 1776, // Helper->player, extra=0x0 - Swiftcast = 167, // none->player, extra=0x0 - Weakness = 43, // none->player, extra=0x0 - Transcendent = 418, // none->player, extra=0x0 -} - public enum IconID : uint { - Icon169 = 169, // player + Spreadmarker = 169, // player } public enum TetherID : uint { BaitAway = 17, // AkaNoShiki/AoNoShiki/IwaNoShiki->player -} \ No newline at end of file +} diff --git a/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09SeiryuStates.cs b/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09SeiryuStates.cs index 14813bec51..f1aeaa28c8 100644 --- a/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09SeiryuStates.cs +++ b/BossMod/Modules/Stormblood/Trial/T09Seiryu/T09SeiryuStates.cs @@ -5,25 +5,24 @@ class T09SeiryuStates : StateMachineBuilder public T09SeiryuStates(BossModule module) : base(module) { TrivialPhase() + .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter() .ActivateOnEnter() - .ActivateOnEnter() - .ActivateOnEnter() - .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter() - .ActivateOnEnter() - .ActivateOnEnter() - .ActivateOnEnter() .ActivateOnEnter() - .ActivateOnEnter() - .ActivateOnEnter() - //.ActivateOnEnter() tether is not implemented yet, one iconid shared with multple tethered AIDs, multiple shapes simultaneously - .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter() .ActivateOnEnter() - .ActivateOnEnter() .ActivateOnEnter() - .ActivateOnEnter() - .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter(); } diff --git a/BossMod/Pathfinding/NavigationDecision.cs b/BossMod/Pathfinding/NavigationDecision.cs index 50b9ada423..e12badcbee 100644 --- a/BossMod/Pathfinding/NavigationDecision.cs +++ b/BossMod/Pathfinding/NavigationDecision.cs @@ -31,7 +31,7 @@ public enum Decision public int MapGoal; public Decision DecisionType; - public const float DefaultForbiddenZoneCushion = 0.12f; + public const float DefaultForbiddenZoneCushion = 0.15f; public static NavigationDecision Build(WorldState ws, AIHints hints, Actor player, WPos? targetPos, float targetRadius, Angle targetRot, Positional positional, float playerSpeed = 6, float forbiddenZoneCushion = DefaultForbiddenZoneCushion) {