diff --git a/BossMod/ActionQueue/Casters/PCT.cs b/BossMod/ActionQueue/Casters/PCT.cs index f4249aa0e3..ba99080fda 100644 --- a/BossMod/ActionQueue/Casters/PCT.cs +++ b/BossMod/ActionQueue/Casters/PCT.cs @@ -167,7 +167,8 @@ public void Dispose() { } private void Customize(ActionDefinitions d) { d.RegisterChargeIncreaseTrait(AID.StrikingMuse, TraitID.EnhancedPictomancyII); - d.RegisterChargeIncreaseTrait(AID.LivingMuse, TraitID.EnhancedPictomancyIV); + foreach (var creature in new AID[] { AID.LivingMuse, AID.PomMuse, AID.WingedMuse, AID.ClawedMuse, AID.FangedMuse }) + d.RegisterChargeIncreaseTrait(creature, TraitID.EnhancedPictomancyIV); d.Spell(AID.Smudge)!.TransformAngle = (ws, _, _, _) => _config.AlignDashToCamera ? ws.Client.CameraAzimuth + 180.Degrees() diff --git a/BossMod/Autorotation/MiscAI/AutoPull.cs b/BossMod/Autorotation/MiscAI/AutoPull.cs index 643e28e253..e8a34d7b80 100644 --- a/BossMod/Autorotation/MiscAI/AutoPull.cs +++ b/BossMod/Autorotation/MiscAI/AutoPull.cs @@ -38,7 +38,7 @@ public override void Execute(StrategyValues strategy, Actor? primaryTarget, floa if (strategy.Enabled(Track.Hunt) && Bossmods.ActiveModule?.Info?.Category == BossModuleInfo.Category.Hunt && Bossmods.ActiveModule?.PrimaryActor is Actor p && p.InCombat && p.HPRatio < 0.95f) { Hints.SetPriority(p, 0); - primaryTarget = p; + primaryTarget = Hints.ForcedTarget = p; return; } @@ -48,7 +48,7 @@ public override void Execute(StrategyValues strategy, Actor? primaryTarget, floa if (bestEnemy != null) { bestEnemy.Priority = 0; - primaryTarget = bestEnemy.Actor; + primaryTarget = Hints.ForcedTarget = bestEnemy.Actor; } } } diff --git a/BossMod/Data/PartyState.cs b/BossMod/Data/PartyState.cs index ae95b9700b..e706fa4684 100644 --- a/BossMod/Data/PartyState.cs +++ b/BossMod/Data/PartyState.cs @@ -135,7 +135,8 @@ public Actor[] WithoutSlot(bool includeDead = false, bool excludeAlliance = fals // find a slot index containing specified player (by name); returns -1 if not found public int FindSlot(ReadOnlySpan name, StringComparison cmp = StringComparison.CurrentCultureIgnoreCase) { - for (var i = 0; i < Members.Length; ++i) + var length = Members.Length; + for (var i = 0; i < length; ++i) if (name.Equals(Members[i].Name, cmp)) return i; return -1; diff --git a/BossMod/Debug/DebugCollision.cs b/BossMod/Debug/DebugCollision.cs index 838524da14..53ebcd2b4d 100644 --- a/BossMod/Debug/DebugCollision.cs +++ b/BossMod/Debug/DebugCollision.cs @@ -366,10 +366,10 @@ private void DrawColliderMesh(ColliderMesh* coll) return; var mesh = (MeshPCB*)coll->Mesh; - DrawColliderMeshPCBNode("Root", mesh->RootNode, ref coll->World, coll->Collider.ObjectMaterialValue & coll->Collider.ObjectMaterialMask, ~coll->Collider.ObjectMaterialMask); + DrawColliderMeshPCBNode("Root", mesh->RootNode, ref coll->World, coll->Collider.ObjectMaterialValue & coll->Collider.ObjectMaterialMask, ~coll->Collider.ObjectMaterialMask, coll); } - private void DrawColliderMeshPCBNode(string tag, MeshPCB.FileNode* node, ref Matrix4x3 world, ulong objMatId, ulong objMatInvMask) + private void DrawColliderMeshPCBNode(string tag, MeshPCB.FileNode* node, ref Matrix4x3 world, ulong objMatId, ulong objMatInvMask, ColliderMesh* coll) { if (node == null) return; @@ -381,18 +381,57 @@ private void DrawColliderMeshPCBNode(string tag, MeshPCB.FileNode* node, ref Mat return; _tree.LeafNode2($"Header: {node->Header:X16}"); + if (_tree.LeafNode2($"AABB: {AABBStr(node->LocalBounds)}").SelectedOrHovered) VisualizeOBB(ref node->LocalBounds, ref world, Colors.CollisionColor1); + using var nv = _tree.Node2($"Vertices: {node->NumVertsRaw}+{node->NumVertsCompressed}", node->NumVertsRaw + node->NumVertsCompressed == 0); + if (nv.Opened) { - using var nv = _tree.Node2($"Vertices: {node->NumVertsRaw}+{node->NumVertsCompressed}", node->NumVertsRaw + node->NumVertsCompressed == 0); - if (nv.Opened) + // Collect all vertices + Vector3 translation = coll->Translation; + Vector3 rotation = coll->Rotation; + + List<(Vector3 vertex, int index, char type)> vertices = []; + + for (var i = 0; i < node->NumVertsRaw + node->NumVertsCompressed; ++i) + { + var v = node->Vertex(i); + var transformedVertex = ApplyTransformation(v, translation, rotation); + vertices.Add((transformedVertex, i, i < node->NumVertsRaw ? 'r' : 'c')); + } + + var playerPos = Service.ClientState.LocalPlayer!.Position; + // Sort vertices by distance to player position, ignore height + + vertices.Sort((a, b) => { - for (int i = 0; i < node->NumVertsRaw + node->NumVertsCompressed; ++i) + var distA = (playerPos.X - a.vertex.X) * (playerPos.X - a.vertex.X) + + (playerPos.Z - a.vertex.Z) * (playerPos.Z - a.vertex.Z); + + var distB = (playerPos.X - b.vertex.X) * (playerPos.X - b.vertex.X) + + (playerPos.Z - b.vertex.Z) * (playerPos.Z - b.vertex.Z); + + return distA.CompareTo(distB); + }); + + // Render vertices in sorted order + foreach (var (vertex, index, type) in vertices) + { + var vertexStr = $"new({vertex.X.ToString("F3", System.Globalization.CultureInfo.InvariantCulture)}f, {vertex.Z.ToString("F3", System.Globalization.CultureInfo.InvariantCulture)}f)"; + using var node2 = _tree.Node2($"[{index}] ({type}): {Vec3Str(vertex)}"); + if (node2.SelectedOrHovered) { - var v = node->Vertex(i); - if (_tree.LeafNode2($"[{i}] ({(i < node->NumVertsRaw ? 'r' : 'c')}): {Vec3Str(v)}").SelectedOrHovered) - VisualizeVertex(world.TransformCoordinate(v), Colors.CollisionColor2); + VisualizeVertex(vertex, Colors.CollisionColor2); + } + + if (ImGui.BeginPopupContextItem()) + { + if (ImGui.MenuItem("Copy to Clipboard")) + { + ImGui.SetClipboardText(vertexStr); + } + ImGui.EndPopup(); } } } @@ -406,8 +445,8 @@ private void DrawColliderMeshPCBNode(string tag, MeshPCB.FileNode* node, ref Mat VisualizeTriangle(node, ref prim, ref world, Colors.CollisionColor2); } } - DrawColliderMeshPCBNode($"Child 1 (+{node->Child1Offset})", node->Child1, ref world, objMatId, objMatId); - DrawColliderMeshPCBNode($"Child 2 (+{node->Child2Offset})", node->Child2, ref world, objMatId, objMatId); + DrawColliderMeshPCBNode($"Child 1 (+{node->Child1Offset})", node->Child1, ref world, objMatId, objMatId, coll); + DrawColliderMeshPCBNode($"Child 2 (+{node->Child2Offset})", node->Child2, ref world, objMatId, objMatId, coll); } private void DrawResource(Resource* res) @@ -615,4 +654,14 @@ private void ContextCollider(Collider* coll) if (ImGui.Checkbox("Flag: global visit", ref globalVisit)) coll->VisibilityFlags ^= 2; } + + static Vector3 ApplyTransformation(Vector3 vertex, Vector3 translation, Vector3 rotation) + { + var rotX = rotation.X; + var rotY = rotation.Y; + var rotZ = rotation.Z; + var rotMatrix = Matrix4x4.CreateRotationX(rotX) * Matrix4x4.CreateRotationY(rotY) * Matrix4x4.CreateRotationZ(rotZ); + var rotatedVertex = Vector3.Transform(vertex, rotMatrix); + return rotatedVertex + translation; + } } diff --git a/BossMod/Framework/MovementOverride.cs b/BossMod/Framework/MovementOverride.cs index 0bf23fed2c..f29a7a19c2 100644 --- a/BossMod/Framework/MovementOverride.cs +++ b/BossMod/Framework/MovementOverride.cs @@ -102,7 +102,7 @@ public void Dispose() _rmiFlyHook.Dispose(); } - private bool NavmeshActive() + private bool FollowpathActive() { if (_navmeshPathIsRunning == null && _dalamud.TryGetData("vnav.PathIsRunning", out var data)) _navmeshPathIsRunning = data; @@ -116,7 +116,7 @@ private void RMIWalkDetour(void* self, float* sumLeft, float* sumForward, float* _rmiWalkHook.Original(self, sumLeft, sumForward, sumTurnLeft, haveBackwardOrStrafe, a6, bAdditiveUnk); // TODO: we really need to introduce some extra checks that PlayerMoveController::readInput does - sometimes it skips reading input, and returning something non-zero breaks stuff... - var movementAllowed = bAdditiveUnk == 0 && _rmiWalkIsInputEnabled1(self) && _rmiWalkIsInputEnabled2(self) && !NavmeshActive(); + var movementAllowed = bAdditiveUnk == 0 && _rmiWalkIsInputEnabled1(self) && _rmiWalkIsInputEnabled2(self) && !FollowpathActive(); var misdirectionMode = PlayerHasMisdirection(); if (!movementAllowed && misdirectionMode) { @@ -169,6 +169,11 @@ private void RMIFlyDetour(void* self, PlayerMoveControllerFlyInput* result) { _forcedControlState = null; _rmiFlyHook.Original(self, result); + + // do nothing while followpath is running + if (FollowpathActive()) + return; + // TODO: we really need to introduce some extra checks that PlayerMoveController::readInput does - sometimes it skips reading input, and returning something non-zero breaks stuff... if (result->Forward == 0 && result->Left == 0 && result->Up == 0 && DirectionToDestination(true) is var relDir && relDir != null) { diff --git a/BossMod/Framework/Plugin.cs b/BossMod/Framework/Plugin.cs index 589006d59d..b6e8a6c5d9 100644 --- a/BossMod/Framework/Plugin.cs +++ b/BossMod/Framework/Plugin.cs @@ -58,7 +58,8 @@ public unsafe Plugin(IDalamudPluginInterface dalamud, ICommandManager commandMan InteropGenerator.Runtime.Resolver.GetInstance.Resolve(); dalamud.Create(); - Service.LogHandler = (string msg) => Service.Logger.Debug(msg); + Service.LogHandlerDebug = (string msg) => Service.Logger.Debug(msg); + Service.LogHandlerVerbose = (string msg) => Service.Logger.Verbose(msg); Service.LuminaGameData = dataManager.GameData; Service.WindowSystem = new("bmr"); //Service.Device = pluginInterface.UiBuilder.Device; diff --git a/BossMod/Framework/Service.cs b/BossMod/Framework/Service.cs index 1d1ae7ec7a..2725b3d348 100644 --- a/BossMod/Framework/Service.cs +++ b/BossMod/Framework/Service.cs @@ -32,8 +32,10 @@ public sealed class Service #pragma warning restore CS8618 #pragma warning disable CA2211 - public static Action? LogHandler; - public static void Log(string msg) => LogHandler?.Invoke(msg); + public static Action? LogHandlerDebug; + public static Action? LogHandlerVerbose; + public static void Log(string msg) => LogHandlerDebug?.Invoke(msg); + public static void LogVerbose(string msg) => LogHandlerVerbose?.Invoke(msg); public static Lumina.GameData? LuminaGameData; public static Lumina.Excel.ExcelSheet? LuminaSheet() where T : struct, Lumina.Excel.IExcelRow => LuminaGameData?.GetExcelSheet(Lumina.Data.Language.English); diff --git a/BossMod/Framework/WorldStateGameSync.cs b/BossMod/Framework/WorldStateGameSync.cs index d26fb58d75..26a6095ae1 100644 --- a/BossMod/Framework/WorldStateGameSync.cs +++ b/BossMod/Framework/WorldStateGameSync.cs @@ -221,7 +221,7 @@ private unsafe void UpdateActors() if (obj != null && (obj->EntityId & 0xFF000000) == 0xFF000000) { - // Service.Log($"[WorldState] Skipping bad object #{i} with id {obj->EntityId:X}"); + Service.LogVerbose($"[WorldState] Skipping bad object #{i} with id {obj->EntityId:X}"); obj = null; } diff --git a/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D023Gurfurlur.cs b/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D023Gurfurlur.cs index eac48ad0a4..ebe096b071 100644 --- a/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D023Gurfurlur.cs +++ b/BossMod/Modules/Dawntrail/Dungeon/D02WorqorZormor/D023Gurfurlur.cs @@ -248,9 +248,9 @@ public override void OnActorCreated(Actor actor) { if (actor.OID == (uint)OID.BitingWind) { - if (actor.Position == new WPos(-74f, -180f)) + if (actor.Position.Z == -180f) CurrentPattern = Pattern.EWEW; - else if (actor.Position == new WPos(-74f, -210f)) + else if (actor.Position.Z == -210f) CurrentPattern = Pattern.WEWE; } } diff --git a/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD70Aeturna.cs b/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD70Aeturna.cs index f87a657f73..95ef896944 100644 --- a/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD70Aeturna.cs +++ b/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD70Aeturna.cs @@ -47,7 +47,10 @@ void AddAOEs(AOEShape shape) var crystals = Module.Enemies((uint)OID.AllaganCrystal); var count = crystals.Count; for (var i = 0; i < count; ++i) - _aoes.Add(new(shape, WPos.ClampToGrid(crystals[i].Position), default, Module.CastFinishAt(spell, 0.5f))); + { + var crystal = crystals[i]; + _aoes.Add(new(shape, WPos.ClampToGrid(crystal.Position), crystal.Rotation, Module.CastFinishAt(spell, 0.5f))); + } } switch (spell.Action.ID) { diff --git a/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD80ProtoKaliya.cs b/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD80ProtoKaliya.cs index 0b7a9e500e..de3f00e4df 100644 --- a/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD80ProtoKaliya.cs +++ b/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD80ProtoKaliya.cs @@ -10,6 +10,7 @@ public enum OID : uint public enum AID : uint { AutoAttack = 31421, // Boss->players, no cast, range 6+R 90-degree cone + AetheromagnetismKB = 31431, // Helper->player, no cast, single-target, knockback 10, away from source AetheromagnetismPull = 31430, // Helper->player, no cast, single-target, pull 10, between centers AutoCannons = 31432, // WeaponsDrone->self, 4.0s cast, range 41+R width 5 rect @@ -44,20 +45,20 @@ public enum TetherID : uint class Magnetism(BossModule module) : Components.Knockback(module, ignoreImmunes: true) { - private readonly HashSet<(Actor, uint)> statusOnActor = []; - public readonly HashSet<(Actor, Source)> sourceByActor = []; + public readonly Source?[] _sources = new Source?[4]; private readonly NerveGasRingAndAutoCannons _aoe1 = module.FindComponent()!; private readonly Barofield _aoe2 = module.FindComponent()!; public override IEnumerable Sources(int slot, Actor actor) { - if (sourceByActor.Count != 0 && _aoe1.AOEs.Any(z => z.Shape == NerveGasRingAndAutoCannons.donut)) + if (_sources[slot] is Source source) { - var x = sourceByActor.FirstOrDefault(x => x.Item1 == actor); - return [new(x.Item2.Origin, x.Item2.Distance, x.Item2.Activation, Kind: x.Item2.Kind)]; + var count = _aoe1.AOEs.Count; + for (var i = 0; i < count; ++i) + if (_aoe1.AOEs[i].Shape == NerveGasRingAndAutoCannons.donut) + return [source]; } - else - return []; + return []; } public override bool DestinationUnsafe(int slot, Actor actor, WPos pos) @@ -73,28 +74,25 @@ public override bool DestinationUnsafe(int slot, Actor actor, WPos pos) return _aoe2.AOE != null && _aoe2.AOE.Value.Check(pos) || !Module.InBounds(pos); } - private bool IsPull(Actor source, Actor target) + public override void OnTethered(Actor source, ActorTetherInfo tether) { - return statusOnActor.Contains((source, (uint)SID.NegativeChargeDrone)) && statusOnActor.Contains((target, (uint)SID.PositiveChargePlayer)) || - statusOnActor.Contains((source, (uint)SID.PositiveChargeDrone)) && statusOnActor.Contains((target, (uint)SID.NegativeChargePlayer)); - } + bool IsPull(ref Actor target) + => source.FindStatus((uint)SID.NegativeChargeDrone) != null && target.FindStatus((uint)SID.PositiveChargePlayer) != null || + source.FindStatus((uint)SID.PositiveChargeDrone) != null && target.FindStatus((uint)SID.NegativeChargePlayer) != null; - private bool IsKnockback(Actor source, Actor target) - { - return statusOnActor.Contains((source, (uint)SID.NegativeChargeDrone)) && statusOnActor.Contains((target, (uint)SID.NegativeChargePlayer)) || - statusOnActor.Contains((source, (uint)SID.PositiveChargeDrone)) && statusOnActor.Contains((target, (uint)SID.PositiveChargePlayer)); - } + bool IsKnockback(ref Actor target) + => source.FindStatus((uint)SID.NegativeChargeDrone) != null && target.FindStatus((uint)SID.NegativeChargePlayer) != null || + source.FindStatus((uint)SID.PositiveChargeDrone) != null && target.FindStatus((uint)SID.PositiveChargePlayer) != null; - public override void OnTethered(Actor source, ActorTetherInfo tether) - { if (tether.ID == (uint)TetherID.Magnetism) { var target = WorldState.Actors.Find(tether.Target)!; - var activation = WorldState.FutureTime(10d); - if (IsPull(source, target)) - sourceByActor.Add((target, new(source.Position, 10f, activation, Kind: Kind.TowardsOrigin))); - else if (IsKnockback(source, target)) - sourceByActor.Add((target, new(source.Position, 10f, activation))); + if (IsPull(ref target)) + AddSource(false); + else if (IsKnockback(ref target)) + AddSource(true); + + void AddSource(bool isKnockback) => _sources[Raid.FindSlot(target.InstanceID)] = new(source.Position, 10f, WorldState.FutureTime(10d), Kind: isKnockback ? Kind.AwayFromOrigin : Kind.TowardsOrigin); } } @@ -103,26 +101,39 @@ public override void OnUntethered(Actor source, ActorTetherInfo tether) if (tether.ID == (uint)TetherID.Magnetism) { var target = WorldState.Actors.Find(tether.Target)!; - sourceByActor.RemoveWhere(x => x.Item1 == target); - } - } - - public override void OnStatusGain(Actor actor, ActorStatus status) - { - if (status.ID is (uint)SID.NegativeChargeDrone or (uint)SID.PositiveChargeDrone or (uint)SID.PositiveChargePlayer or (uint)SID.NegativeChargePlayer) - { - statusOnActor.RemoveWhere(x => x.Item1 == actor); - statusOnActor.Add((actor, status.ID)); + _sources[Raid.FindSlot(target.InstanceID)] = null; } } public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { - if (sourceByActor.Count > 0) + if (_sources[slot] is Source source) { - var target = sourceByActor.FirstOrDefault(x => x.Item1 == actor); - var offset = target.Item2.Kind == Kind.TowardsOrigin ? 180f.Degrees() : default; - hints.AddForbiddenZone(ShapeDistance.InvertedDonutSector(Arena.Center, 15f, 18f, Angle.FromDirection(target.Item2.Origin - Arena.Center) + offset, 35f.Degrees())); + var attract = source.Kind == Kind.TowardsOrigin; + var pos = Module.PrimaryActor.Position; + var barofield = ShapeDistance.Circle(pos, 5f); + var arena = ShapeDistance.InvertedCircle(pos, 8f); + var cannons = Module.Enemies((uint)OID.WeaponsDrone); + var count = cannons.Count; + var forbiddenRects = new Func[count]; + for (var i = 0; i < count; ++i) + { + var c = cannons[i]; + forbiddenRects[i] = ShapeDistance.Rect(c.Position, c.Rotation, 43f, default, 2.5f); + } + var all = ShapeDistance.Union((Func[])[barofield, arena, .. forbiddenRects]); + + hints.AddForbiddenZone(p => + { + var dir = (p - source.Origin).Normalized(); + var kb = attract ? -dir : dir; + + // prevent KB through death zone in center + if (Intersect.RayCircle(p, kb, pos, 5f) < 99f) + return 0; + + return all(p + kb * 10f); + }, source.Activation); } } } @@ -150,40 +161,58 @@ public override void OnStatusLose(Actor actor, ActorStatus status) class NerveGasRingAndAutoCannons(BossModule module) : Components.GenericAOEs(module) { public readonly List AOEs = new(2); - private static readonly AOEShapeCross cross = new(43f, 2.5f); + private static readonly AOEShapeCross cross = new(20f, 2.5f); + private static readonly AOEShapeCross rect = new(43f, 2.5f); public static readonly AOEShapeDonut donut = new(8f, 30f); public override IEnumerable ActiveAOEs(int slot, Actor actor) => AOEs; public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - void AddAOE(AOEShape shape, bool risky = true) => AOEs.Add(new(shape, spell.LocXZ, default, Module.CastFinishAt(spell), Risky: risky)); + void AddAOE(AOEShape shape) => AOEs.Add(new(shape, spell.LocXZ, shape == rect ? spell.Rotation : default, Module.CastFinishAt(spell), ActorID: caster.InstanceID)); if (spell.Action.ID == (uint)AID.NerveGasRing) { - AddAOE(donut, false); + AddAOE(donut); AddAOE(cross); } else if (spell.Action.ID == (uint)AID.AutoCannons) - AddAOE(cross); - else if (AOEs.Count == 2 && spell.Action.ID == (uint)AID.AutoCannons) { - AOEs.RemoveAt(1); - AddAOE(cross); + AddAOE(rect); + var count = AOEs.Count; + for (var i = 0; i < count; ++i) + { + if (AOEs[i].Shape == cross) + { + AOEs.RemoveAt(i); + break; + } + } } } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { if (AOEs.Count != 0 && spell.Action.ID is (uint)AID.NerveGasRing or (uint)AID.AutoCannons) - AOEs.RemoveAt(0); + { + var count = AOEs.Count; + var id = caster.InstanceID; + for (var i = 0; i < count; ++i) + { + if (AOEs[i].ActorID == id) + { + AOEs.RemoveAt(i); + break; + } + } + } } } -class NerveGas(BossModule module, AID aid) : Components.SimpleAOEs(module, ActionID.MakeSpell(aid), new AOEShapeCone(30f, 90f.Degrees())); +class NerveGas(BossModule module, AID aid) : Components.SimpleAOEs(module, ActionID.MakeSpell(aid), new AOEShapeCone(25.5f, 90f.Degrees())); class LeftNerveGas(BossModule module) : NerveGas(module, AID.LeftwardNerveGas); class RightNerveGas(BossModule module) : NerveGas(module, AID.RightwardNerveGas); -class CentralizedNerveGas(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.CentralizedNerveGas), new AOEShapeCone(30f, 60f.Degrees())); +class CentralizedNerveGas(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.CentralizedNerveGas), new AOEShapeCone(25.5f, 60f.Degrees())); class AutoAttack(BossModule module) : Components.Cleave(module, ActionID.MakeSpell(AID.AutoAttack), new AOEShapeCone(11f, 45f.Degrees())) { @@ -191,13 +220,13 @@ class RightNerveGas(BossModule module) : NerveGas(module, AID.RightwardNerveGas) public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { - if (_aoe.AOE != null) + if (_aoe.AOE == null) base.AddAIHints(slot, actor, assignment, hints); } public override void DrawArenaForeground(int pcSlot, Actor pc) { - if (_aoe.AOE != null) + if (_aoe.AOE == null) base.DrawArenaForeground(pcSlot, pc); } } diff --git a/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD90Administrator.cs b/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD90Administrator.cs index 83625ab468..4c8be1e699 100644 --- a/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD90Administrator.cs +++ b/BossMod/Modules/Endwalker/DeepDungeon/EurekaOrthos/DD90Administrator.cs @@ -49,32 +49,28 @@ class AetheroChemicalLaserCombo(BossModule module) : Components.GenericAOEs(modu { private static readonly AOEShape[] _shapes = [new AOEShapeCone(50f, 60f.Degrees()), new AOEShapeDonut(8f, 60f), new AOEShapeRect(40f, 2.5f), new AOEShapeCross(60f, 5f), new AOEShapeDonut(5f, 60f)]; - private readonly Dictionary> _icons = new() { - { (uint)IconID.Icon1, [] }, - { (uint)IconID.Icon2, [] }, - { (uint)IconID.Icon3, [] } - }; - private AOEInstance _boss; + public readonly List AOEs = new(6); public override IEnumerable ActiveAOEs(int slot, Actor actor) { - foreach (var icon in _icons) + var count = AOEs.Count; + if (count == 0) + return []; + var aoes = new AOEInstance[count]; + var act0 = AOEs[0].Activation; + var color = Colors.Danger; + var index = 0; + for (var i = 0; i < count; ++i) { - if (icon.Value != null && icon.Value.Count > 0) - { - foreach (var c in icon.Value) - yield return new(c.Shape, c.Origin, c.Rotation, c.Activation, Colors.Danger); - var nextIcon = _icons.FirstOrDefault(x => x.Key == icon.Key + 1).Value; - if (nextIcon != null) - foreach (var c in nextIcon) - yield return new(c.Shape, c.Origin, c.Rotation, c.Activation, Risky: false); - if (_boss != default) - yield return new(_boss.Shape, _boss.Origin, _boss.Rotation, _boss.Activation, Risky: false); - yield break; - } + var aoe = AOEs[i]; + var act = aoe.Activation; + var total = (act - act0).TotalSeconds; + var comp = total < 1d; + if (total > 5d) + break; + aoes[index++] = aoe with { Color = comp ? color : 0, Risky = comp }; } - if (_boss != default) - yield return new(_boss.Shape, _boss.Origin, _boss.Rotation, _boss.Activation, Colors.Danger); + return aoes[..index]; } public override void OnEventIcon(Actor actor, uint iconID, ulong targetID) @@ -84,9 +80,12 @@ public override void OnEventIcon(Actor actor, uint iconID, ulong targetID) (uint)OID.SquareInterceptor => 2, (uint)OID.OrbInterceptor => 1, (uint)OID.EggInterceptor => 0, - _ => default + _ => -1 }; + if (shapeIndex == -1) + return; + var activation = iconID switch { (uint)IconID.Icon1 => WorldState.FutureTime(7d), @@ -95,65 +94,52 @@ public override void OnEventIcon(Actor actor, uint iconID, ulong targetID) _ => default }; - _icons[iconID].Add(new(_shapes[shapeIndex], WPos.ClampToGrid(actor.Position), actor.OID == (uint)OID.OrbInterceptor ? default : actor.Rotation, activation)); + AOEs.Add(new(_shapes[shapeIndex], WPos.ClampToGrid(actor.Position), actor.OID == (uint)OID.OrbInterceptor ? default : actor.Rotation, activation)); + if (AOEs.Count == 6) + AOEs.SortBy(x => x.Activation); } public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - _boss = spell.Action.ID switch + AOEInstance? aoe = spell.Action.ID switch { (uint)AID.PeripheralLasers => new(_shapes[4], spell.LocXZ, default, Module.CastFinishAt(spell)), (uint)AID.CrossLaser => new(_shapes[3], spell.LocXZ, spell.Rotation, Module.CastFinishAt(spell)), - _ => _boss + _ => null }; + + if (aoe != null) + AOEs.Add(aoe.Value); } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - if (spell.Action.ID is (uint)AID.AetherochemicalLaserCone or (uint)AID.AetherochemicalLaserLine or (uint)AID.AetherochemicalLaserDonut) + switch (spell.Action.ID) { - foreach (var icon in _icons) - if (icon.Value.Count != 0) - { - icon.Value.RemoveAt(0); - break; - } + case (uint)AID.AetherochemicalLaserCone: + case (uint)AID.AetherochemicalLaserLine: + case (uint)AID.AetherochemicalLaserDonut: + case (uint)AID.PeripheralLasers: + case (uint)AID.CrossLaser: + if (AOEs.Count != 0) + AOEs.RemoveAt(0); + break; } - else if (spell.Action.ID is (uint)AID.PeripheralLasers or (uint)AID.CrossLaser) - _boss = default; } } -class AetherLaserLine(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.AetherochemicalLaserLine), new AOEShapeRect(40f, 2.5f), 4) +class AetherLaserLine : Components.SimpleAOEs { - private readonly AetheroChemicalLaserCombo _aoe = module.FindComponent()!; - public override IEnumerable ActiveAOEs(int slot, Actor actor) - { - var count = Casters.Count; + private readonly AetheroChemicalLaserCombo _aoe; - if (count == 0) - return []; - - var hasActiveAOEs = false; - { - foreach (var aoe in _aoe.ActiveAOEs(slot, actor)) - { - hasActiveAOEs = true; - break; - } - } - if (hasActiveAOEs) - return []; - - var max = count > 4 ? 4 : count; - var aoes = new AOEInstance[max]; - for (var i = 0; i < max; ++i) - { - var caster = Casters[i]; - aoes[i] = caster with { Color = i < 2 && count > i ? Colors.Danger : 0 }; - } - return aoes; + public AetherLaserLine(BossModule module) : base(module, ActionID.MakeSpell(AID.AetherochemicalLaserLine), new AOEShapeRect(40f, 2.5f), 4) + { + MaxDangerColor = 2; + MaxRisky = 2; + _aoe = module.FindComponent()!; } + + public override IEnumerable ActiveAOEs(int slot, Actor actor) => Casters.Count != 0 && _aoe.AOEs.Count == 0 ? base.ActiveAOEs(slot, actor) : []; } class AetherLaserLine2(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.AetherochemicalLaserLine2), new AOEShapeRect(40f, 2.5f)); diff --git a/BossMod/Modules/Endwalker/FATE/Chi.cs b/BossMod/Modules/Endwalker/FATE/Chi.cs index 46ea472931..e81b359bce 100644 --- a/BossMod/Modules/Endwalker/FATE/Chi.cs +++ b/BossMod/Modules/Endwalker/FATE/Chi.cs @@ -112,7 +112,7 @@ public override IEnumerable ActiveAOEs(int slot, Actor actor) { var aoe = _aoes[i]; if ((aoe.Activation - firstact).TotalSeconds < 1d) - aoes[i] = (lastact - aoe.Activation).TotalSeconds > 1 ? aoe with { Color = Colors.Danger } : aoe; + aoes[i] = (lastact - aoe.Activation).TotalSeconds > 1d ? aoe with { Color = Colors.Danger } : aoe; else aoes[i] = aoe with { Risky = false }; } diff --git a/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D121Locksmith.cs b/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D121Locksmith.cs index 2bbe73c753..df441c306c 100644 --- a/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D121Locksmith.cs +++ b/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D121Locksmith.cs @@ -13,17 +13,8 @@ public enum AID : uint GoldDust = 1033 // Boss->location, 3.5s cast, range 8 circle } -class HundredLashings(BossModule module) : Components.Cleave(module, ActionID.MakeSpell(AID.HundredLashings), new AOEShapeCone(12, 45.Degrees())); // TODO: verify angle -class GoldDust(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.GoldDust), 8); - -// arena has multiple weirdly-shaped puddles, so just prefer standing in large safe zone -class AIPosition(BossModule module) : BossComponent(module) -{ - public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) - { - hints.AddForbiddenZone(ShapeDistance.InvertedCircle(new(30, 0), 5)); - } -} +class HundredLashings(BossModule module) : Components.Cleave(module, ActionID.MakeSpell(AID.HundredLashings), new AOEShapeCone(12f, 45f.Degrees())); // TODO: verify angle +class GoldDust(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.GoldDust), 8f); class D121LocksmithStates : StateMachineBuilder { @@ -31,10 +22,86 @@ public D121LocksmithStates(BossModule module) : base(module) { TrivialPhase() .ActivateOnEnter() - .ActivateOnEnter() - .ActivateOnEnter(); + .ActivateOnEnter(); } } -[ModuleInfo(BossModuleInfo.Maturity.Verified, GroupType = BossModuleInfo.GroupType.CFC, GroupID = 5, NameID = 1534)] -public class D121Locksmith(WorldState ws, Actor primary) : BossModule(ws, primary, new(35, 0), new ArenaBoundsRect(15, 25)); +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 5, NameID = 1534)] +public class D121Locksmith(WorldState ws, Actor primary) : BossModule(ws, primary, arena.Center, arena) +{ + private static readonly WPos[] vertices = [new(26.26f, -26.39f), new(27.55f, -26.38f), new(28.27f, -26.26f), new(38.31f, -26.38f), new(38.83f, -25.95f), + new(39.62f, -24.91f), new(40.05f, -24.44f), new(41.3f, -24.3f), new(41.91f, -24.3f), new(43.22f, -24.45f), + new(43.81f, -24.13f), new(44.35f, -23.91f), new(45.64f, -23.63f), new(46.27f, -23.35f), new(46.41f, -22.75f), + new(46.71f, -22.15f), new(46.89f, -21.56f), new(47.66f, -20.54f), new(47.9f, -19.91f), new(48.2f, -19.39f), + new(48.76f, -19.25f), new(49.1f, -18.72f), new(49.6f, -18.31f), new(50.2f, -17.93f), new(50.76f, -17.5f), + new(51.19f, -16.98f), new(51.58f, -16.42f), new(52.04f, -16.1f), new(52.63f, -15.93f), new(53.21f, -15.66f), + new(53.75f, -15.35f), new(54.31f, -15.25f), new(54.74f, -14.76f), new(55.08f, -14.24f), new(55.54f, -13.75f), + new(56.01f, -13.42f), new(56.6f, -13.25f), new(57.1f, -12.75f), new(57.5f, -12.22f), new(58.13f, -11f), + new(58.55f, -10.58f), new(59.07f, -10.26f), new(59.18f, -9.64f), new(57.84f, -5.86f), new(57.71f, -5.26f), + new(57.99f, -2.69f), new(58.13f, -2.16f), new(58.94f, -1.21f), new(59.21f, 6.58f), new(58.89f, 6.97f), + new(58.34f, 7.29f), new(56.92f, 9.24f), new(56.63f, 11.9f), new(55.45f, 12.34f), new(55.09f, 12.85f), + new(54.47f, 14.17f), new(54.19f, 14.6f), new(53.53f, 14.91f), new(53.01f, 15.3f), new(52.39f, 15.67f), + new(51.72f, 15.97f), new(50.82f, 16.87f), new(50.4f, 18.1f), new(49.95f, 18.6f), new(47.64f, 20.06f), + new(47.26f, 21.47f), new(47.27f, 22.16f), new(46.84f, 22.47f), new(46.17f, 22.71f), new(45.58f, 23.02f), + new(45.2f, 23.54f), new(45.02f, 24.17f), new(44.91f, 24.84f), new(43.99f, 25.67f), new(43.67f, 26.2f), + new(43.5f, 26.77f), new(43.66f, 27.35f), new(44.86f, 28.8f), new(44.05f, 29.68f), new(43.92f, 30.17f), + new(44.2f, 30.71f), new(44.4f, 31.32f), new(44.31f, 32.63f), new(43.84f, 33.17f), new(42.6f, 33.54f), + new(42.03f, 33.85f), new(40.95f, 34.27f), new(40.38f, 33.85f), new(39.74f, 33.62f), new(39.11f, 33.61f), + new(38.58f, 33.92f), new(37.16f, 35.53f), new(36.38f, 36.76f), new(35.96f, 37.33f), new(35.58f, 37.65f), + new(35.16f, 37.93f), new(34.51f, 38.19f), new(33.84f, 38.39f), new(31.16f, 38.17f), new(28.52f, 37.45f), + new(27.99f, 36.96f), new(27.2f, 35.84f), new(26.88f, 35.2f), new(26.4f, 33.98f), new(25.91f, 33.67f), + new(25.25f, 33.65f), new(21.89f, 34.06f), new(21.67f, 34.56f), new(21.16f, 34.8f), new(20.47f, 34.64f), + new(19.77f, 34.33f), new(19.98f, 33.88f), new(20.04f, 33.32f), new(19.82f, 32.75f), new(19.32f, 32.32f), + new(19.41f, 31.6f), new(19.89f, 31.14f), new(20.6f, 30.01f), new(21.63f, 29.21f), new(21.42f, 28.61f), + new(19.93f, 27.34f), new(18.85f, 26.68f), new(18.26f, 26.64f), new(17.6f, 26.39f), new(17.05f, 26.11f), + new(15.13f, 26.04f), new(14.65f, 25.52f), new(14.24f, 24.94f), new(14.34f, 24.45f), new(15.14f, 23.38f), + new(14.73f, 20.06f), new(14.2f, 19.84f), new(14.17f, 19.31f), new(14.86f, 16.15f), new(15.33f, 15.63f), + new(16.45f, 14.87f), new(16.65f, 14.32f), new(16.45f, 13.79f), new(16.03f, 13.32f), new(15.43f, 13.19f), + new(15.21f, 12.52f), new(15.3f, 9.89f), new(16.42f, 7.26f), new(16.47f, 6.65f), new(16.4f, 6f), + new(16.46f, 5.3f), new(16.89f, 5.01f), new(17.54f, 4.77f), new(17.82f, 4.29f), new(18.28f, 3.78f), + new(19.59f, 3.6f), new(19.92f, 2.99f), new(19.9f, 2.41f), new(19.5f, 1.92f), new(19.59f, 1.22f), + new(20.88f, 1.09f), new(21.28f, 0.7f), new(21.32f, 0.11f), new(21.62f, -0.55f), new(22.31f, -1.59f), + new(22.3f, -2.82f), new(22.35f, -3.47f), new(22.6f, -4.15f), new(22.73f, -4.84f), new(22.7f, -5.53f), + new(22.55f, -6.22f), new(22.31f, -6.9f), new(21.36f, -8.65f), new(20.74f, -8.93f), new(21.24f, -9.17f), + new(21.78f, -9.5f), new(22.18f, -10.85f), new(22f, -12.9f), new(21.89f, -13.52f), new(19.19f, -15.18f), + new(18.58f, -15.29f), new(17.91f, -15.53f), new(17.75f, -16.73f), new(17.59f, -17.36f), new(17.76f, -17.84f), + new(18.16f, -18.36f), new(18.16f, -18.99f), new(18.66f, -19.51f), new(19.05f, -20.04f), new(19.37f, -20.62f), + new(19.53f, -21.2f), new(19.33f, -21.8f), new(17.78f, -22.87f), new(17.02f, -23.05f), new(17.25f, -23.65f), + new(17.23f, -24.95f), new(17.37f, -25.45f), new(17.89f, -25.38f), new(18.49f, -25.47f), new(20.38f, -26.29f), + new(26.26f, -26.39f)]; + private static readonly WPos[] verticesPuddle1 = [new(39.41f, 19f), new(39.886f, 18f), new(40.276f, 17.209f), new(39.282f, 16.743f), + new(38.956f, 16f), new(38f, 15.436f), new(37f, 15.613f), new(36f, 16f), new(35.229f, 15.511f), new(34.487f, 15.369f), new(34.068f, 14.691f), + new(34.066f, 14f), new(33.884f, 13f), new(34.319f, 12f), new(34.25f, 11.267f), new(34.44f, 10.534f), new(35.22f, 10.088f), + new(35.162f, 9.044f), new(34f, 8f), new(33.5f, 7.693f), new(33f, 7.142f), new(32.5f, 7f), new(31.5f, 7f), new(31.5f, 7f), + new(31f, 7.174f), new(30.577f, 7.654f), new(30f, 8f), new(29.094f, 8.78f), new(28f, 9f), new(27.303f, 8.86f), + new(26.606f, 8.489f), new(26f, 8.427f), new(25.35f, 8.581f), new(24.7f, 8.977f), new(24.414f, 10f), new(24.657f, 10.911f), + new(23.951f, 12f), new(23.292f, 12.378f), new(22.976f, 12.954f), new(22f, 13.321f), new(21.246f, 13.645f), new(20.769f, 14f), + new(20.272f, 15f), new(20.094f, 16f), new(20.185f, 16.5f), new(20.643f, 17f), new(21.066f, 17.097f), new(21.458f, 17.359f), + new(22.127f, 17.235f), new(23f, 16.58f), new(24f, 16.369f), new(25f, 15.602f), new(26f, 16.054f), new(26.951f, 16.082f), + new(27.726f, 16.852f), new(28.104f, 18f), new(27.648f, 19f), new(27.506f, 20f), new(27.735f, 20.456f), new(27.81f, 20.912f), + new(28.266f, 21.133f), new(28.722f, 21.111f), new(29.228f, 21.701f), new(29.897f, 22f), new(30.18f, 22.596f), new(29.992f, 23.298f), + new(30f, 24f), new(30.354f, 24.888f), new(31f, 25.168f), new(31.5f, 25f), new(32.5f, 25f), new(33f, 25.153f), new(33.5f, 25.473f), + new(34f, 25.627f), new(35f, 25.677f), new(35.735f, 25f), new(36f, 24f), new(36.564f, 23.442f), new(37.254f, 23.159f), new(38f, 22.92f), + new(38.996f, 22f), new(38.783f, 21f), new(39.035f, 20.165f), new(39.501f, 19.642f)]; + private static readonly WPos[] verticesPuddle2 = [new(30.5f, -8f), new(31f, -7.205f), new(31.5f, -7f), new(32.5f, -7f), new(33f, -7.177f), + new(33.346f, -7.679f), new(33.779f, -8f), new(34f, -9f), new(34.381f, -10f), new(34.418f, -11f), new(34f, -12f), new(34f, -13f), + new(33.5f, -14f), new(34f, -15f), new(34.747f, -15.41f), new(35.178f, -16f), new(35.035f, -17f), new(35.423f, -17.569f), + new(36f, -18f), new(36f, -19f), new(35.665f, -20f), new(34.891f, -20.5f), new(34.404f, -21.141f), new(34f, -22f), new(34.117f, -22.633f), + new(34f, -23.265f), new(33.194f, -24f), new(33.101f, -24.479f), new(32.5f, -25f), new(31.5f, -25f), new(31f, -24.814f), + new(30.79f, -24.5f), new(30.756f, -24f), new(31.041f, -23f), new(30.871f, -22f), new(30.204f, -21f), new(30f, -20f), new(30f, -19.417f), + new(29.56f, -18.709f), new(29f, -18f), new(29f, -17.142f), new(29.337f, -16.57f), new(30f, -16f), new(29.924f, -15.368f), new(30.166f, -14.724f), + new(30.278f, -14f), new(30f, -13.236f), new(29.28f, -13.008f), new(28.561f, -13.103f), new(28f, -13.426f), new(27.177f, -13.074f), + new(26.895f, -12f), new(26.311f, -11.51f), new(26.1f, -10.77f), new(26.601f, -9.867f), new(27.341f, -9.787f), new(28f, -9.591f), + new(28.652f, -9.901f), new(29.304f, -9.984f), new(30, -10.445f), new(30.297f, -10.269f), new(30.5f, -10f), new(30.306f, -9f)]; + private static readonly WPos[] verticesPuddle3 = [new(57f, -0.5f), new(57.153f, -1f), new(57.473f, -1.5f), new(57.627f, -2f), + new(57.677f, -3f), new(57f, -3.735f), new(56f, -4f), new(55.442f, -4.564f), new(55.159f, -5.254f), new(54.92f, -6f), new(54f, -6.484f), + new(53f, -6.324f), new(52.165f, -6.577f), new(51.642f, -6.76f), new(51f, -6.94f), new(50f, -7.009f), new(49.209f, -7.509f), new(48.743f, -7.282f), + new(48f, -6.956f), new(47.436f, -6f), new(47.613f, -5f), new(48f, -4f), new(47.511f, -3.229f), new(47.369f, -2.488f), new(46.691f, -2.068f), + new(46f, -2.067f), new(45f, -1.885f), new(44f, -2.319f), new(43.267f, -2.25f), new(42.534f, -2.44f), new(42.089f, -3.22f), new(41.044f, -3.163f), + new(40f, -2f), new(39.693f, -1.5f), new(39.142f, -1f), new(39f, -0.5f), new(39f, 0.5f), new(39.177f, 1f), new(39.679f, 1.346f), + new(40f, 1.779f), new(41f, 2f), new(42f, 2.381f), new(43f, 2.418f), new(44f, 2f), new(45f, 2f), new(46f, 1.5f), new(47f, 2f), + new(47.41f, 2.747f), new(48f, 3.178f), new(49f, 3.035f), new(49.569f, 3.424f), new(50f, 4f), new(51f, 4f), new(52f, 3.665f), new(52.5f, 2.891f), + new(53.141f, 2.404f), new(54f, 2f), new(54.633f, 2.117f), new(55.265f, 2f), new(56f, 1.317f), new(56.479f, 1.101f), new(57f, 0.5f)]; + private static readonly ArenaBoundsComplex arena = new([new PolygonCustom(vertices)], [new PolygonCustom(verticesPuddle1), + new PolygonCustom(verticesPuddle2), new PolygonCustom(verticesPuddle3)]); +} diff --git a/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D122Coincounter.cs b/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D122Coincounter.cs index cb893ed306..c816180076 100644 --- a/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D122Coincounter.cs +++ b/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D122Coincounter.cs @@ -35,5 +35,75 @@ public D122CoincounterStates(BossModule module) : base(module) } } -[ModuleInfo(BossModuleInfo.Maturity.Verified, GroupType = BossModuleInfo.GroupType.CFC, GroupID = 5, NameID = 1533)] -public class D122Coincounter(WorldState ws, Actor primary) : BossModule(ws, primary, new(-150, -150), new ArenaBoundsSquare(20)); +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 5, NameID = 1533)] +public class D122Coincounter(WorldState ws, Actor primary) : BossModule(ws, primary, arena.Center, arena) +{ + private static readonly WPos[] vertices = [new(-139.18f, -177.68f), new(-138.68f, -177.28f), new(-138.39f, -176.65f), new(-138.6f, -176.02f), new(-138.38f, -175.49f), + new(-138.46f, -174.96f), new(-139.64f, -175.02f), new(-140.22f, -174.91f), new(-140.77f, -174.53f), new(-141.72f, -173.62f), + new(-141.96f, -173.12f), new(-141.49f, -171.96f), new(-140.81f, -170.8f), new(-140.64f, -169.4f), new(-140.46f, -168.69f), + new(-140.11f, -168.23f), new(-139.51f, -168.35f), new(-139.01f, -168.66f), new(-137.99f, -169.54f), new(-137.59f, -169.94f), + new(-136.93f, -171.75f), new(-136.6f, -172.3f), new(-136.14f, -172.76f), new(-135.59f, -173f), new(-135.07f, -173.32f), + new(-134.91f, -173.88f), new(-134.93f, -174.54f), new(-134.53f, -175.08f), new(-133.99f, -175.49f), new(-133.34f, -175.58f), + new(-132.7f, -175.31f), new(-132.26f, -174.76f), new(-132.05f, -173.6f), new(-131.81f, -173.07f), new(-130.27f, -171.13f), + new(-129.68f, -170.96f), new(-129.08f, -170.64f), new(-128.73f, -170.1f), new(-128.18f, -169.89f), new(-127.54f, -169.59f), + new(-126.62f, -168.58f), new(-124.77f, -168.17f), new(-124.18f, -168.12f), new(-122.91f, -168.26f), new(-122.32f, -167.93f), + new(-121.94f, -167.36f), new(-121.39f, -166.94f), new(-121.01f, -166.56f), new(-122.2f, -164.92f), new(-122.37f, -164.35f), + new(-122.46f, -163.68f), new(-122.75f, -163.09f), new(-125.1f, -162.06f), new(-125.62f, -161.73f), new(-126.6f, -160.85f), + new(-126.95f, -160.34f), new(-127.56f, -159.24f), new(-127.39f, -158f), new(-127.37f, -157.34f), new(-127.74f, -156.73f), + new(-128.03f, -156.11f), new(-128.25f, -155.46f), new(-128.26f, -154.89f), new(-127.64f, -153.68f), new(-127.05f, -153.66f), + new(-126.58f, -153.48f), new(-126.68f, -152.32f), new(-126.49f, -151.72f), new(-126.25f, -151.17f), new(-125.74f, -150.84f), + new(-125.54f, -150.19f), new(-125.87f, -148.91f), new(-125.61f, -147.57f), new(-126.22f, -145.87f), new(-126.35f, -145.18f), + new(-126.35f, -144.57f), new(-126.25f, -143.91f), new(-126.01f, -143.34f), new(-125.07f, -141.57f), new(-124.9f, -140.86f), + new(-125.15f, -139.61f), new(-124.85f, -139.2f), new(-123.91f, -138.33f), new(-123.81f, -130.92f), new(-124.27f, -130.37f), + new(-124.78f, -129.96f), new(-125.46f, -129.65f), new(-126.1f, -129.47f), new(-127.16f, -128.7f), new(-127.61f, -128.27f), + new(-128.26f, -127.08f), new(-128.59f, -125.75f), new(-128.6f, -125.19f), new(-128.24f, -123.86f), new(-128.75f, -123.39f), + new(-130.05f, -123.03f), new(-130.56f, -122.68f), new(-130.84f, -122.13f), new(-130.7f, -120.76f), new(-131.26f, -120.77f), + new(-131.9f, -120.62f), new(-132.58f, -120.56f), new(-133.03f, -120.14f), new(-133.47f, -118.89f), new(-133.95f, -118.7f), + new(-134.58f, -118.61f), new(-136.27f, -117.8f), new(-137.69f, -117.53f), new(-137.55f, -117f), new(-136.43f, -114.6f), + new(-135.55f, -112.07f), new(-135.21f, -111.59f), new(-134.13f, -110.91f), new(-133.83f, -110.47f), new(-134.64f, -109.85f), + new(-136.31f, -110.7f), new(-136.95f, -110.92f), new(-137.62f, -111.04f), new(-138.21f, -111.02f), new(-140.03f, -109.16f), + new(-141.27f, -108.65f), new(-142.68f, -107.24f), new(-143.36f, -107.06f), new(-144.01f, -106.99f), new(-145.18f, -106.6f), + new(-145.94f, -105.62f), new(-147.26f, -105.32f), new(-147.85f, -105f), new(-148.53f, -104.88f), new(-149.47f, -105.76f), + new(-150f, -106.08f), new(-150.54f, -106.26f), new(-151.14f, -106.08f), new(-151.8f, -106f), new(-152.38f, -106.27f), + new(-153.59f, -106.99f), new(-154.19f, -107.16f), new(-154.86f, -107.11f), new(-155.4f, -106.91f), new(-156.05f, -106.6f), + new(-156.64f, -107.03f), new(-156.81f, -107.69f), new(-156.37f, -108.19f), new(-155.78f, -108.47f), new(-154.5f, -108.73f), + new(-153.93f, -109f), new(-153.44f, -109.39f), new(-153.02f, -109.87f), new(-152.02f, -111.49f), new(-151.9f, -112.05f), + new(-153.87f, -114.71f), new(-154.3f, -115.12f), new(-156.5f, -116.36f), new(-159f, -116.17f), new(-159.56f, -115.96f), + new(-160.23f, -116.16f), new(-161.4f, -116.91f), new(-161.98f, -117.14f), new(-162.55f, -116.98f), new(-164.3f, -116.29f), + new(-165.82f, -115.13f), new(-166.13f, -114.69f), new(-166.2f, -113.45f), new(-166.46f, -112.84f), new(-167.09f, -113.14f), + new(-167.56f, -113.6f), new(-168.09f, -113.87f), new(-168.77f, -113.93f), new(-169.33f, -114.26f), new(-169.92f, -114.49f), + new(-170.47f, -114.35f), new(-171.06f, -114.12f), new(-171.57f, -113.86f), new(-171.95f, -113.34f), new(-172.31f, -112.99f), + new(-173.03f, -113f), new(-174.21f, -112.62f), new(-174.63f, -112.22f), new(-175.28f, -111.86f), new(-175.6f, -112.3f), + new(-175.89f, -112.92f), new(-176.06f, -113.56f), new(-176.47f, -113.92f), new(-176.8f, -114.44f), new(-177.3f, -114.82f), + new(-178.72f, -116.94f), new(-178.76f, -117.45f), new(-178.37f, -118.77f), new(-177.79f, -120.03f), new(-178.11f, -120.51f), + new(-178.45f, -120.88f), new(-178.16f, -121.31f), new(-177.71f, -121.74f), new(-177.42f, -122.28f), new(-176.8f, -122.48f), + new(-174.94f, -122.23f), new(-173.81f, -122.78f), new(-172.53f, -122.66f), new(-172.09f, -122.89f), new(-171.4f, -122.87f), + new(-170.9f, -123.11f), new(-170.42f, -123.52f), new(-169.27f, -124.21f), new(-169.14f, -124.87f), new(-168.49f, -125.95f), + new(-168.59f, -127.26f), new(-168.72f, -127.87f), new(-169.1f, -129.07f), new(-169.45f, -129.55f), new(-170.38f, -130.65f), + new(-169.89f, -130.85f), new(-169.32f, -132.06f), new(-169.13f, -132.73f), new(-169.1f, -133.35f), new(-169.98f, -134.35f), + new(-170.32f, -135.01f), new(-170.52f, -136.37f), new(-170.73f, -136.97f), new(-171.66f, -137.77f), new(-173.5f, -137.99f), + new(-174.13f, -138.14f), new(-174.56f, -138.67f), new(-174.78f, -139.28f), new(-175.64f, -140.13f), new(-176.18f, -140.42f), + new(-176.49f, -141f), new(-176.67f, -141.56f), new(-177.13f, -141.92f), new(-177.16f, -142.59f), new(-176.89f, -143.25f), + new(-176.34f, -145.23f), new(-176.36f, -145.83f), new(-176.62f, -146.36f), new(-177.11f, -146.76f), new(-177.46f, -147.25f), + new(-177.53f, -148.97f), new(-177.08f, -149.52f), new(-176.57f, -149.58f), new(-175.94f, -149.39f), new(-175.38f, -149.69f), + new(-174.96f, -149.38f), new(-175f, -148.17f), new(-174.78f, -147.6f), new(-174.4f, -147.05f), new(-173.85f, -146.66f), + new(-173.48f, -146.17f), new(-172.99f, -146.08f), new(-172.41f, -146.37f), new(-171.79f, -146.57f), new(-171.25f, -146.94f), + new(-170.6f, -147.15f), new(-169.99f, -147.15f), new(-169.39f, -147.26f), new(-168.81f, -147.45f), new(-168.31f, -147.74f), + new(-168.25f, -148.27f), new(-168.5f, -148.8f), new(-168.89f, -149.27f), new(-169.39f, -149.75f), new(-169.7f, -150.27f), + new(-170.22f, -150.52f), new(-170.8f, -150.73f), new(-171.44f, -150.84f), new(-172.11f, -151.01f), new(-172.71f, -151.33f), + new(-173.4f, -152.41f), new(-173.92f, -152.75f), new(-174.53f, -153.07f), new(-175.1f, -153.48f), new(-175.49f, -154.02f), + new(-175.21f, -154.61f), new(-170.62f, -157.06f), new(-170.43f, -157.63f), new(-170.55f, -158.2f), new(-171.06f, -158.51f), + new(-171.18f, -159.17f), new(-170.97f, -160.44f), new(-171.82f, -161.66f), new(-172.38f, -162.02f), new(-172.99f, -162.24f), + new(-173.44f, -162.7f), new(-173.57f, -163.35f), new(-173.8f, -164.02f), new(-174.93f, -165.55f), new(-175.25f, -166.16f), + new(-175.21f, -166.81f), new(-175.83f, -168f), new(-175.96f, -168.49f), new(-170.9f, -173.54f), new(-169.63f, -173.54f), + new(-168.99f, -173.28f), new(-168.5f, -172.79f), new(-167.31f, -172.29f), new(-166.81f, -171.8f), new(-166.1f, -170.81f), + new(-165.06f, -170.09f), new(-163.84f, -169.66f), new(-163.15f, -169.51f), new(-162.6f, -169.48f), new(-162.02f, -169.79f), + new(-160.77f, -170.09f), new(-160.34f, -170.61f), new(-159.97f, -170.95f), new(-158.38f, -170.07f), new(-155.83f, -170.1f), + new(-155.35f, -170.37f), new(-154.77f, -170.59f), new(-153.18f, -172.01f), new(-152.79f, -172.44f), new(-152.69f, -173.09f), + new(-152.33f, -173.66f), new(-152.1f, -174.17f), new(-151.93f, -174.78f), new(-151.56f, -175.43f), new(-151.1f, -175.18f), + new(-150.17f, -174.37f), new(-149.62f, -174.45f), new(-149.03f, -174.66f), new(-148.51f, -174.97f), new(-147.29f, -176.41f), + new(-146.65f, -176.59f), new(-146.21f, -176.95f), new(-145.81f, -177.54f), new(-145.32f, -177.31f), new(-144.8f, -176.9f), + new(-144.21f, -176.74f), new(-143.58f, -176.73f), new(-142.97f, -176.41f), new(-142.38f, -176.29f), new(-141.8f, -176.49f), + new(-140.92f, -177.39f), new(-139.18f, -177.68f)]; + private static readonly ArenaBoundsComplex arena = new([new PolygonCustom(vertices)]); +} diff --git a/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D123MisersMistress.cs b/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D123MisersMistress.cs index 3e5b0ded6d..c2e20734fc 100644 --- a/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D123MisersMistress.cs +++ b/BossMod/Modules/RealmReborn/Dungeon/D12AurumVale/D123MisersMistress.cs @@ -2,32 +2,47 @@ public enum OID : uint { - Boss = 0x3AF, // x1 - MorbolFruit = 0x5BC // spawn during fight + Boss = 0x3AF, // R3.85 + MorbolFruit = 0x5BC, // R0.6-1.8 + Plume1 = 0x5CA, // R0.5 + Plume2 = 0x603, // R1.5 + MorbolSeedling = 0x5BB, // R0.9 } public enum AID : uint { - AutoAttack = 1350, // Boss->player, no cast, single-target + AutoAttack1 = 1350, // Boss->player, no cast, single-target + AutoAttack2 = 1041, // MorbolSeedling->player, no cast, single-target - VineProbe = 1037, // Boss->self, 1.0s cast, range 6+R width 8 rect cleave (due to short cast time...) + VineProbe = 1037, // Boss->self, 1.0s cast, range 6+R width 8 rect BadBreath = 1036, // Boss->self, 2.5s cast, range 12+R 120-degree cone aoe - BurrBurrow = 1038, // Boss->self, 3.0s cast, raidwide? + BurrBurrow = 1038, // Boss->self, 3.0s cast, raidwide, apply burrs stack HookedBurrs = 1039, // Boss->player, 1.5s cast, single-target - Sow = 1081 // Boss->player, 3.0s cast, single-target, spawns adds + Sow = 1081, // Boss->player, 3.0s cast, single-target, spawns adds + GoldBilePlume1 = 1042, // Plume1->self, no cast, range 2 circle, knockback 5, away from source + GoldBilePlume2 = 1043, // Plume2->self, no cast, range 3+R width 2 rect + Germinate = 1040 // MorbolFruit->self, 15.0s cast, single-target } -class VineProbe(BossModule module) : Components.Cleave(module, ActionID.MakeSpell(AID.VineProbe), new AOEShapeRect(10, 4)); -class BadBreath(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.BadBreath), new AOEShapeCone(16, 60.Degrees())); +class VineProbeCleave(BossModule module) : Components.Cleave(module, ActionID.MakeSpell(AID.VineProbe), new AOEShapeRect(9.85f, 4), activeWhileCasting: false); +class VineProbe(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.VineProbe), new AOEShapeRect(9.85f, 4)); +class BadBreath(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.BadBreath), new AOEShapeCone(16f, 60f.Degrees())); -// arena has multiple weirdly-shaped puddles, so just prefer standing in large safe zone -class AIPosition(BossModule module) : BossComponent(module) +class GoldBilePlume(BossModule module) : Components.GenericAOEs(module) { - private readonly WPos[] _centers = [new(-395, -130), new(-402, -114)]; + private static readonly AOEShapeCircle circle = new(2f); + private static readonly AOEShapeRect rect = new(4.5f, 1f); + private readonly List _aoes = new(7); - public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + public override IEnumerable ActiveAOEs(int slot, Actor actor) => _aoes; + + public override void OnActorCreated(Actor actor) { - hints.AddForbiddenZone(ShapeDistance.InvertedCircle(_centers.MinBy(p => (p - Module.PrimaryActor.Position).LengthSq()), 5)); + void AddAOE(AOEShape shape) => _aoes.Add(new(shape, WPos.ClampToGrid(actor.Position), actor.Rotation)); + if (actor.OID == (uint)OID.Plume1) + AddAOE(circle); + else if (actor.OID == (uint)OID.Plume2) + AddAOE(rect); } } @@ -36,25 +51,155 @@ class D123MisersMistressStates : StateMachineBuilder public D123MisersMistressStates(BossModule module) : base(module) { TrivialPhase() + .ActivateOnEnter() .ActivateOnEnter() - .ActivateOnEnter() - .ActivateOnEnter(); + .ActivateOnEnter() + .ActivateOnEnter(); } } -[ModuleInfo(BossModuleInfo.Maturity.Verified, GroupType = BossModuleInfo.GroupType.CFC, GroupID = 5, NameID = 1532)] -public class D123MisersMistress(WorldState ws, Actor primary) : BossModule(ws, primary, new(-400, -130), new ArenaBoundsSquare(25)) +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "Malediktus", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 5, NameID = 1532)] +public class D123MisersMistress(WorldState ws, Actor primary) : BossModule(ws, primary, arena.Center, arena) { + private static readonly WPos[] vertices = [new(-390.6f, -142.52f), new(-390.05f, -142.12f), new(-389.51f, -141.84f), new(-388.26f, -141.72f), new(-387.03f, -141.22f), + new(-386.41f, -141.16f), new(-385.89f, -140.77f), new(-385.31f, -140.56f), new(-384.72f, -140.55f), new(-383.84f, -140.67f), + new(-383.32f, -140.25f), new(-382.26f, -139.66f), new(-381.04f, -139.47f), new(-379.84f, -139.63f), new(-378.07f, -140.6f), + new(-370.65f, -137.12f), new(-369.7f, -136.22f), new(-369.82f, -135.61f), new(-370.69f, -134.65f), new(-370.98f, -134.05f), + new(-371.18f, -133.4f), new(-371.47f, -132.8f), new(-372.21f, -131.71f), new(-372.03f, -131.13f), new(-371.75f, -130.51f), + new(-371.98f, -129.82f), new(-372.41f, -129.26f), new(-372.56f, -128.68f), new(-372.47f, -127.96f), new(-372.19f, -127.4f), + new(-372.47f, -126.91f), new(-376.18f, -125.2f), new(-376.63f, -124.67f), new(-376.99f, -124.15f), new(-377.24f, -123.58f), + new(-377.05f, -123f), new(-376.7f, -122.42f), new(-376.48f, -121.81f), new(-375.99f, -121.44f), new(-374.84f, -120.73f), + new(-374.65f, -120.14f), new(-377.79f, -120.89f), new(-378.35f, -120.81f), new(-378.94f, -120.49f), new(-379.63f, -120.34f), + new(-380.21f, -120.08f), new(-380.64f, -119.68f), new(-380.68f, -119.05f), new(-380.86f, -118.41f), new(-381.19f, -117.85f), + new(-381.34f, -117.33f), new(-381.54f, -116.85f), new(-383.29f, -115.8f), new(-383.78f, -115.32f), new(-384.48f, -115.36f), + new(-385.07f, -115.63f), new(-385.53f, -116.17f), new(-385.48f, -116.83f), new(-385.66f, -117.37f), new(-386.88f, -118.89f), + new(-387.42f, -119.23f), new(-387.97f, -119.47f), new(-389.22f, -119.13f), new(-390.12f, -118.26f), new(-390.58f, -117.04f), + new(-391.03f, -116.56f), new(-391.33f, -116.02f), new(-391.58f, -115.43f), new(-392.06f, -114.98f), new(-392.58f, -114.85f), + new(-392.95f, -114.38f), new(-393.22f, -113.77f), new(-393.78f, -113.31f), new(-394.38f, -113.15f), new(-394.9f, -112.79f), + new(-395.39f, -112.37f), new(-396.08f, -112.11f), new(-396.58f, -111.81f), new(-396.73f, -111.22f), new(-397f, -110.6f), + new(-397.98f, -109.71f), new(-398.5f, -109.43f), new(-399.86f, -108.11f), new(-400.04f, -107.47f), new(-400.34f, -106.81f), + new(-400.69f, -106.21f), new(-400.75f, -105.59f), new(-401.32f, -105.25f), new(-401.78f, -104.91f), new(-402.76f, -103.94f), + new(-403.81f, -104.36f), new(-404.43f, -104.17f), new(-406.34f, -104.5f), new(-408.24f, -104.23f), new(-408.97f, -104.22f), + new(-409.11f, -106.11f), new(-409.25f, -106.76f), new(-410.16f, -107.68f), new(-411.67f, -108.74f), new(-412.19f, -108.56f), + new(-412.83f, -108.47f), new(-413.51f, -108.55f), new(-414.12f, -108.69f), new(-414.71f, -108.7f), new(-415.36f, -108.79f), + new(-421.12f, -108.45f), new(-421.78f, -108.65f), new(-422.91f, -109.34f), new(-423.49f, -109.27f), new(-424.13f, -108.97f), + new(-425.7f, -110.28f), new(-426.15f, -110.82f), new(-426.23f, -111.48f), new(-426.46f, -112.09f), new(-426.79f, -112.69f), + new(-426.42f, -113.9f), new(-426.67f, -114.48f), new(-426.88f, -115.18f), new(-426.88f, -115.7f), new(-427.45f, -116.8f), + new(-427.91f, -117.1f), new(-428.55f, -117.32f), new(-428.95f, -117.62f), new(-429.41f, -118.13f), new(-429.77f, -118.69f), + new(-429.97f, -119.33f), new(-429.6f, -119.69f), new(-429.35f, -120.27f), new(-428.91f, -120.85f), new(-428f, -121.65f), + new(-427.73f, -122.24f), new(-427.53f, -122.87f), new(-427.71f, -123.41f), new(-428.51f, -124.37f), new(-428.38f, -125.04f), + new(-428.06f, -125.59f), new(-427.89f, -126.11f), new(-428.47f, -127.25f), new(-428.68f, -128.32f), new(-428.16f, -128.76f), + new(-427.67f, -129.25f), new(-427.01f, -129.37f), new(-426.43f, -129.62f), new(-425.89f, -129.92f), new(-425.26f, -130.13f), + new(-424.83f, -130.53f), new(-424.14f, -130.72f), new(-423.62f, -130.97f), new(-423.25f, -131.49f), new(-422.9f, -132.1f), + new(-422.8f, -132.68f), new(-423.4f, -133.8f), new(-423.65f, -134.36f), new(-424.81f, -135.07f), new(-425.26f, -135.58f), + new(-425.25f, -136.27f), new(-424.76f, -136.8f), new(-424.07f, -136.73f), new(-423.35f, -135.77f), new(-422.78f, -135.41f), + new(-422.23f, -135.13f), new(-421.69f, -135.18f), new(-421.08f, -135.49f), new(-420.46f, -135.64f), new(-419.88f, -135.88f), + new(-419.39f, -136.28f), new(-419.34f, -136.85f), new(-419.68f, -138.11f), new(-420.04f, -138.61f), new(-420.45f, -139.06f), + new(-420.94f, -139.5f), new(-421.08f, -140.17f), new(-420.6f, -140.67f), new(-419.89f, -140.76f), new(-419.24f, -140.71f), + new(-417.97f, -140.26f), new(-416.6f, -140.05f), new(-416.14f, -139.6f), new(-415.63f, -139.27f), new(-413.86f, -138.71f), + new(-413.25f, -138.77f), new(-412.66f, -138.58f), new(-412.12f, -138.82f), new(-411.64f, -139.14f), new(-411.16f, -139.65f), + new(-410.65f, -139.89f), new(-410.12f, -140.34f), new(-409.43f, -140.34f), new(-409.21f, -141.03f), new(-408.07f, -141.58f), + new(-407.37f, -141.49f), new(-406.52f, -138.39f), new(-406.06f, -138.07f), new(-405.43f, -137.9f), new(-404.78f, -137.83f), + new(-404.09f, -137.92f), new(-403.58f, -137.93f), new(-403.03f, -137.86f), new(-402.46f, -138.13f), new(-400.99f, -140.5f), + new(-400.77f, -141.06f), new(-400.67f, -141.67f), new(-400.34f, -142.29f), new(-399.77f, -142.76f), new(-399.14f, -143.04f), + new(-398.71f, -143.54f), new(-398.07f, -143.6f), new(-397.61f, -143.12f), new(-396.57f, -141.51f), new(-396.16f, -141.07f), + new(-395.61f, -140.73f), new(-395.07f, -140.5f), new(-394.48f, -140.59f), new(-394.04f, -140.86f), new(-393.27f, -141.99f), + new(-393.1f, -142.76f), new(-392.83f, -143.4f), new(-392.4f, -143.93f), new(-391.8f, -144.32f)]; + private static readonly WPos[] verticesPuddle1 = [new(-374f, -135f), new(-375.682f, -136.176f), new(-376.432f, -136.279f), + new(-377.182f, -135.75f), new(-377.932f, -135.588f), new(-378.682f, -135.456f), new(-379.432f, -135.702f), new(-380.182f, -135.75f), + new(-380.932f, -135f), new(-381f, -134f), new(-381.23f, -133f), new(-382f, -132f), new(-383f, -131.148f), new(-383.25f, -131f), + new(-384f, -131f), new(-385f, -130.708f), new(-385.493f, -130.5f), new(-386f, -130f), new(-385.774f, -129f), new(-385f, -128f), + new(-384f, -127.5f), new(-383.182f, -127.443f), new(-381.682f, -128f), new(-380.188f, -128.998f), new(-379.433f, -129.220f), + new(-378.68f, -128.62f), new(-377.935f, -128.337f), new(-377.182f, -128.53f), new(-376.432f, -129f), new(-376f, -130f), + new(-374f, -131f), new(-373f, -132f), new(-372.699f, -133f), new(-373f, -134f)]; + private static readonly WPos[] verticesPuddle2 = [new(-386.148f, -136.269f), new(-386.268f, -136.969f), new(-386.5f, -138f), + new(-387.159f, -138.378f), new(-387.074f, -138.634f), new(-386.958f, -139.252f), new(-387.019f, -140f),new(-387f, -141.623f), + new(-389f, -142.363f), new(-388.953f, -140.002f), new(-389.211f, -139.147f), new(-388.935f, -138.276f), new(-388.823f, -137.791f), + new(-389.255f, -137.375f), new(-389.565f, -136.625f), new(-389.567f, -136.031f), new(-389.369f, -135.319f), new(-389.291f, -134.94f), + new(-389.389f, -134.768f), new(-389.531f, -134.692f), new(-389.512f, -134.117f), new(-389.624f, -133.733f), new(-389.775f, -133.036f), + new(-389.361f, -132.469f), new(-388.836f, -132.209f), new(-388.232f, -132.331f), new(-387.954f, -133.036f), new(-388.033f, -133.347f), + new(-388f, -134f), new(-387.695f, -134.608f), new(-387.551f, -135.086f), new(-387.138f, -135.501f),new(-386.523f, -135.754f), + new(-386.272f, -136.099f)]; + private static readonly WPos[] verticesPuddle3 = [new(-395.063f, -136f), new(-394.544f, -135.806f), new(-394.011f, -136f), new(-393.538f, -137.115f), + new(-393.411f, -138f), new(-393.225f, -138.5f), new(-392.851f, -139f), new(-392.839f, -140f), new(-393.331f, -141.167f), new(-396.475f, -141.502f), + new(-396.883f, -140.706f), new(-396.992f, -140f), new(-396.761f, -139.093f), new(-396.57f, -138f), new(-396.305f, -137f), new(-395.966f, -136.712f), + new(-395.532f, -136.559f)]; + private static readonly WPos[] verticesPuddle4 = [new(-376f, -124.844f), new(-376.405f, -125.716f), new(-377f, -126f), new(-377.571f, -125.636f), + new(-377.919f, -125.5f), new(-378.148f, -125f), new(-378.382f, -124.299f), new(-379f, -124f), new(-379.422f, -123.5f), new(-379.5f, -123f), + new(-379.4f, -122.5f),new(-379.5f, -122f), new(-380f, -121.5f), new(-380.5f, -121.572f), new(-381f, -121.5f), new(-381.5f, -121.346f), + new(-382f, -121f), new(-382.702f, -121f), new(-384f, -121.378f), new(-385f, -122f), new(-385.5f, -122.288f), new(-386f, -122.505f), + new(-386.372f, -122.870f), new(-386.768f, -123.2f), new(-387f, -123.5f), new(-387.31f, -124f), new(-388f, -124.5f), new(-388.5f, -124.661f), + new(-389f, -124.5f), new(-389.5f, -124f), new(-389.745f, -123.5f), new(-389.835f, -123f), new(-389.745f, -122.5f), new(-389.5f, -122f), + new(-389.232f, -121.5f), new(-388.685f, -121f), new(-388.185f, -120.5f), new(-387.917f, -120.25f), new(-387.5f, -120f), new(-386.903f, -119.725f), + new(-386.306f, -119.668f), new(-385.742f, -119.435f), new(-385f, -119.234f), new(-384f, -119.266f), new(-383f, -119.128f), new(-382f, -118.786f), + new(-381.5f, -118.5f), new(-381f, -118f), new(-374.803f, -118.826f), new(-374.134f, -120f)]; + private static readonly WPos[] verticesPuddle5 = [new(-392f, -120f), new(-392.571f, -120.247f), new(-393.236f, -120.38f), new(-394f, -120.611f), + new(-395f, -119.935f), new(-395.254f, -119.353f), new(-395.986f, -119f), new(-396.467f, -118f), new(-396.484f, -117f), new(-396f, -116.316f), + new(-395.5f, -116.276f), new(-395f, -116.37f), new(-394.5f, -116.651f), new(-394f, -116.767f), new(-393.5f, -116.343f), new(-393f, -116.179f), + new(-392.488f, -116.331f), new(-391.966f, -117f), new(-391.542f, -118f), new(-391.455f, -119f)]; + private static readonly WPos[] verticesPuddle6 = [new(-401.265f, -128f), new(-402.135f, -129.441f), new(-402.764f, -130f), new(-402.992f, -130.719f), + new(-402.897f, -131.439f),new(-402.574f, -132f), new(-402.926f, -132.823f), new(-404f, -133.106f), new(-404.503f, -133.622f), new(-405.23f, -133.9f), + new(-406.133f, -133.4f), new(-406.293f, -132.694f), new(-406.409f, -132f), new(-406.099f, -131.348f), new(-406.016f, -130.696f), new(-405.555f, -130f), + new(-405.731f, -129.703f), new(-406f, -129.5f), new(-407f, -129.694f), new(-408f, -129.5f), new(-408.795f, -129f), new(-409f, -128.5f), new(-409f, -127.5f), + new(-408.823f, -127f), new(-408.321f, -126.654f), new(-408f, -126.221f), new(-407f, -126f), new(-406f, -125.619f), new(-405f, -125.582f), + new(-404f, -126f), new(-403f, -126f), new(-401.895f, -126.5f), new(-401.383f, -127.431f)]; + private static readonly WPos[] verticesPuddle7 = [new(-404.284f, -119.023f), new(-403.794f, -119.454f), new(-403.575f, -120.129f), new(-403.619f, -120.735f), + new(-403.886f, -121.163f), new(-404.310f, -121.591f), new(-404.474f, -122f), new(-404.553f, -122.428f), new(-404.907f, -122.856f), new(-405.454f, -123.05f), + new(-406, -122.853f), new(-406.587f, -122.881f), new(-407.294f, -123.334f), new(-408f, -123.506f), new(-409f, -123.33f), new(-410f, -122.997f), + new(-410.459f, -122.943f), new(-410.988f, -122.464f), new(-411.115f, -122f), new(-411.115f, -121.364f), new(-410.875f, -120.964f), new(-410.45f, -120.785f), + new(-409.9f, -120.449f), new(-409.246f, -120.213f), new(-408.593f, -120.159f), new(-408f, -120.19f), new(-407.318f, -119.826f), new(-407.075f, -119.175f), + new(-406.678f, -118.641f), new(-406, -118.45f), new(-405.47f, -118.701f), new(-404.89f, -118.911f)]; + private static readonly WPos[] verticesPuddle8 = [new(-411.374f, -130.476f), new(-410.843f, -130.781f), new(-410.56f, -131.536f), new(-410.222f, -132.124f), + new(-409.772f, -132.562f), new(-409.495f, -133f), new(-409.308f, -134f), new(-409.52f, -134.408f), new(-409.843f, -134.816f), new(-410.185f, -135.536f), + new(-411f, -135.802f), new(-412f, -135.631f), new(-412.632f, -135.178f),new(-413.052f, -134.482f), new(-413.692f, -134f), new(-414.12f, -133.056f), + new(-413.692f, -132.112f), new(-413.043f, -131.714f), new(-412.687f, -131.01f), new(-412f, -130.369f)]; + private static readonly WPos[] verticesPuddle9 = [new(-417.5f, -124f), new(-417.866f, -124.5f), new(-418f, -125f), new(-418.558f, -125.595f), + new(-419.279f, -125.483f), new(-420f, -125f), new(-420.154f, -124.5f), new(-420f, -124f),new(-419.454f, -123.654f), new(-419f, -122.999f), + new(-418.501f, -122.854f), new(-418f, -123.003f), new(-417.564f, -123.441f)]; + private static readonly WPos[] verticesPuddle10 = [new(-409.676f, -107f), new(-409.423f, -107.835f), new(-409.241f, -108.358f), new(-409.061f, -109f), + new(-408.991f, -110f), new(-408.491f, -110.791f), new(-409.002f, -111.257f), new(-409.317f, -112f), new(-409.771f, -112.564f), new(-411f, -112.387f), + new(-412f, -112f), new(-412.771f, -112.489f), new(-413.513f, -112.631f), new(-413.932f, -113.309f), new(-413.933f, -114f), new(-414.116f, -115f), + new(-413.681f, -116f), new(-413.75f, -116.733f), new(-413.56f, -117.467f), new(-412.78f, -117.912f), new(-412.838f, -118.956f), new(-414f, -120f), + new(-414.5f, -120.307f), new(-415f, -120.858f), new(-415.5f, -121f), new(-416.5f, -121f), new(-417f, -121.154f), new(-417.5f, -121.473f), + new(-418f, -121.627f), new(-419f, -121.677f), new(-419.735f, -121f), new(-420f, -120f), new(-420.564f, -119.442f), new(-421.254f, -119.159f), + new(-422f, -118.92f), new(-422.484f, -118f), new(-422.324f, -117f), new(-422.577f, -116.165f), new(-422.76f, -115.642f), new(-422.94f, -115f), + new(-423.009f, -114f), new(-423.509f, -113.210f), new(-422.998f, -112.743f), new(-422.683f, -112f), new(-422.229f, -111.436f), new(-421f, -111.613f), + new(-421f, -111.613f), new(-420f, -112f), new(-418.3f, -111.504f), new(-418.068f, -110.691f), new(-418.067f, -110f), new(-417.884f, -109f), + new(-418.502f, -108f)]; + private static readonly WPos[] verticesPuddle11 = [new(-428.683f, -124f), new(-428f, -124f), new(-427f, -123.764f), new(-426.05f, -123f), + new(-425.331f, -123f), new(-424.837f, -122f), new(-424.908f, -121.285f), new(-424.537f, -120.868f), new(-424f, -120.59f), new(-423.325f, -120.582f), + new(-422.651f, -120.65f), new(-422f, -121.126f), new(-421.396f, -121.389f), new(-421f, -122f), new(-420.702f, -123f), new(-421f, -124f), + new(-421.568f, -124.416f), new(-422f, -125f), new(-422.697f, -125.237f), new(-423.394f, -125.336f), new(-424f, -125.87f), new(-424.791f, -126f), + new(-425.173f, -125.499f), new(-425.365f, -125f), new(-427f, -125f), new(-428.291f, -126f)]; + private static readonly WPos[] verticesPuddle12 = [new(-424f, -131.156f), new(-423.595f, -130.285f), new(-423f, -130f), new(-422.429f, -130.364f), + new(-422.081f, -130.5f), new(-421.852f, -131f), new(-421.618f, -131.701f), new(-421f, -132f), new(-420.578f, -132.5f), new(-420.5f, -133f), + new(-420.6f, -133.5f), new(-420.5f, -134f), new(-420f, -134.5f), new(-419.5f, -134.428f), new(-419f, -134.5f), new(-418.5f, -134.654f), + new(-418f, -135f), new(-417.892f, -135.5f), new(-418f, -136f), new(-418.5f, -136.5f), new(-418.627f, -137f), new(-418.5f, -137.5f), + new(-419f, -138f), new(-419.288f, -138.487f), new(-419.422f, -138.973f), new(-419.346f, -139.488f), new(-419.305f, -140.003f), new(-419.414f, -140.418f), + new(-419.414f, -140.418f), new(-419.524f, -140.833f), new(-419.661f, -143.331f), new(-430f, -133f)]; + private static readonly ArenaBoundsComplex arena = new([new PolygonCustom(vertices)], [new PolygonCustom(verticesPuddle1), + new PolygonCustom(verticesPuddle2), new PolygonCustom(verticesPuddle3), new PolygonCustom(verticesPuddle4), new PolygonCustom(verticesPuddle5), + new PolygonCustom(verticesPuddle6), new PolygonCustom(verticesPuddle7), new PolygonCustom(verticesPuddle8), new PolygonCustom(verticesPuddle9), + new PolygonCustom(verticesPuddle10), new PolygonCustom(verticesPuddle11), new PolygonCustom(verticesPuddle12)]); + protected override void CalculateModuleAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { - foreach (var e in hints.PotentialTargets) + var count = hints.PotentialTargets.Count; + for (var i = 0; i < count; ++i) { - e.Priority = (OID)e.Actor.OID switch + var e = hints.PotentialTargets[i]; + e.Priority = e.Actor.OID switch { - OID.MorbolFruit => 2, - OID.Boss => 1, + (uint)OID.MorbolFruit or (uint)OID.MorbolSeedling => 1, _ => 0 }; } } + + protected override void DrawEnemies(int pcSlot, Actor pc) + { + Arena.Actor(PrimaryActor); + Arena.Actors(Enemies((uint)OID.MorbolFruit)); + Arena.Actors(Enemies((uint)OID.MorbolSeedling)); + } } diff --git a/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D021AencThon.cs b/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D021AencThon.cs index 74988e6573..d9ec1d96a8 100644 --- a/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D021AencThon.cs +++ b/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D021AencThon.cs @@ -35,44 +35,21 @@ class LaughingLeapStack(BossModule module) : Components.StackWithIcon(module, (u class Geyser(BossModule module) : Components.GenericAOEs(module) { private static readonly AOEShapeCircle circle = new(6f); - - private static readonly Dictionary> GeyserPositions = new() - { - { - (uint)OID.GeyserHelper1, new Dictionary - { - { 0.Degrees(), [new(0f, 14.16f), new(-9f, 45.16f)] }, - { 180.Degrees(), [new(9f, 15.16f), new(0f, 46.16f)] }, - { -90.Degrees(), [new(-15f, 21.16f), new(16f, 30.16f)] }, - { 90.Degrees(), [new(-16f, 30.16f), new(15f, 39.16f)] } - } - }, - { - (uint)OID.GeyserHelper2, new Dictionary - { - { 0.Degrees(), [new(0f, 35.16f), new(-9f, 15.16f), new(7f, 23.16f)] }, - { 90.Degrees(), [new(-15f, 39.16f), new(-7f, 23.16f), new(5f, 30.16f)] }, - { 180.Degrees(), [new(9f, 45.16f), new(-7f, 37.16f), new(0f, 25.16f)] }, - { -90.Degrees(), [new(7f, 37.16f), new(15f, 21.16f), new(-5f, 30.16f)] } - } - } - }; - - private readonly List _aoes = []; + private readonly List _aoes = new(14); public override IEnumerable ActiveAOEs(int slot, Actor actor) { var count = _aoes.Count; if (count == 0) return []; - var aoes = new AOEInstance[count]; var act0 = _aoes[0].Activation; + var compareFL = (_aoes[count - 1].Activation - act0).TotalSeconds > 1d; + var aoes = new AOEInstance[count]; var color = Colors.Danger; for (var i = 0; i < count; ++i) { var aoe = _aoes[i]; - var act = aoe.Activation; - aoes[i] = aoe with { Color = act != _aoes[count - 1].Activation ? color : 0, Risky = act == act0 }; + aoes[i] = (aoe.Activation - act0).TotalSeconds < 1d ? aoe with { Color = compareFL ? color : 0 } : aoe with { Risky = false }; } return aoes; } @@ -81,16 +58,37 @@ public override void OnActorEAnim(Actor actor, uint state) { if (state == 0x00100020) { - if (GeyserPositions.TryGetValue(actor.OID, out var positionsByRotation)) + var rotation = (int)actor.Rotation.Deg; + if (actor.OID == (uint)OID.GeyserHelper1) + { + WPos[] positions = rotation switch + { + 0 => [new(default, 14.16f), new(-9f, 45.16f)], + -180 => [new(9f, 15.16f), new(default, 46.16f)], + -90 => [new(-15f, 21.16f), new(16f, 30.16f)], + 89 => [new(-16f, 30.16f), new(15f, 39.16f)], + _ => [] + }; + AddAOEs(positions); + } + else if (actor.OID == (uint)OID.GeyserHelper2) + { + WPos[] positions = rotation switch + { + 0 => [new(default, 35.16f), new(-9f, 15.16f), new(7f, 23.16f)], + -180 => [new(-15f, 39.16f), new(-7f, 23.16f), new(5f, 30.16f)], + -90 => [new(9f, 45.16f), new(-7f, 37.16f), new(default, 25.16f)], + 89 => [new(7f, 37.16f), new(15f, 21.16f), new(-5f, 30.16f)], + _ => [] + }; + AddAOEs(positions); + } + void AddAOEs(WPos[] positions) { - var activation = WorldState.FutureTime(5.1f); - foreach (var (rotation, positions) in positionsByRotation) - if (actor.Rotation.AlmostEqual(rotation, Angle.DegToRad)) - { - for (var i = 0; i < positions.Length; ++i) - _aoes.Add(new(circle, WPos.ClampToGrid(positions[i]), default, activation)); - break; - } + var len = positions.Length; + var activation = WorldState.FutureTime(5.1d); + for (var i = 0; i < len; ++i) + _aoes.Add(new(circle, WPos.ClampToGrid(positions[i]), default, activation)); } } } @@ -119,5 +117,5 @@ public D021AencThonStates(BossModule module) : base(module) [ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "The Combat Reborn Team (Malediktus)", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 649, NameID = 8141)] public class D021AencThon(WorldState ws, Actor primary) : BossModule(ws, primary, arena.Center, arena) { - private static readonly ArenaBoundsComplex arena = new([new Polygon(new(0f, 30f), 19.5f * CosPI.Pi32th, 32)], [new Rectangle(new(0f, 50f), 20f, 1f), new Rectangle(new(0f, 10f), 20f, 1.4f)]); + private static readonly ArenaBoundsComplex arena = new([new Polygon(new(default, 30f), 19.5f * CosPI.Pi32th, 32)], [new Rectangle(new(default, 50f), 20f, 1f), new Rectangle(new(default, 10f), 20f, 1.4f)]); } diff --git a/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D022Griaule.cs b/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D022Griaule.cs index c752caf7f4..b8614261e3 100644 --- a/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D022Griaule.cs +++ b/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D022Griaule.cs @@ -24,15 +24,15 @@ class FeedingTime(BossModule module) : Components.InterceptTether(module, Action private DateTime _activation; public override void OnActorCreated(Actor actor) { - if ((OID)actor.OID == OID.PaintedSapling) - _activation = WorldState.FutureTime(10.9f); + if (actor.OID == (uint)OID.PaintedSapling) + _activation = WorldState.FutureTime(10.9d); } public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { if (Active) { - var source = Module.Enemies(OID.PaintedSapling)[slot]; + var source = Module.Enemies((uint)OID.PaintedSapling)[slot]; var target = Module.PrimaryActor; hints.AddForbiddenZone(ShapeDistance.InvertedRect(target.Position + (target.HitboxRadius + 0.1f) * target.DirectionTo(source), source.Position, 0.5f), _activation); } @@ -48,13 +48,13 @@ class Swinge(BossModule module) : Components.GenericAOEs(module) public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.Swinge) + if (spell.Action.ID == (uint)AID.Swinge) _aoe = new(new AOEShapeCone(50f + caster.HitboxRadius, 30.Degrees()), caster.Position, spell.Rotation, Module.CastFinishAt(spell)); } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.Swinge) + if (spell.Action.ID == (uint)AID.Swinge) _aoe = null; } } @@ -73,17 +73,18 @@ public D022GriauleStates(BossModule module) : base(module) [ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "The Combat Reborn Team (Malediktus)", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 649, NameID = 8143)] public class D022Griaule(WorldState ws, Actor primary) : BossModule(ws, primary, arena.Center, arena) { - private static readonly ArenaBoundsComplex arena = new([new Polygon(new(7.156f, -339.132f), 24.5f * CosPI.Pi32th, 32)], [new Rectangle(new(7, -363.5f), 20f, 1.1f), new Rectangle(new(7, -315), 20f, 0.75f)]); + private static readonly ArenaBoundsComplex arena = new([new Polygon(new(7.156f, -339.132f), 24.5f * CosPI.Pi32th, 32)], [new Rectangle(new(7f, -363.5f), 20f, 1.1f), new Rectangle(new(7f, -315), 20f, 0.75f)]); protected override void DrawEnemies(int pcSlot, Actor pc) { Arena.Actor(PrimaryActor); - Arena.Actors(Enemies(OID.PaintedRoot)); + Arena.Actors(Enemies((uint)OID.PaintedRoot)); } protected override void CalculateModuleAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { - for (var i = 0; i < hints.PotentialTargets.Count; ++i) + var count = hints.PotentialTargets.Count; + for (var i = 0; i < count; ++i) { var e = hints.PotentialTargets[i]; e.Priority = e.Actor.OID switch diff --git a/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D023AencThon.cs b/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D023AencThon.cs index 60073a867a..953f6b6589 100644 --- a/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D023AencThon.cs +++ b/BossMod/Modules/Shadowbringers/Dungeon/D02DohnMheg/D023AencThon.cs @@ -165,6 +165,6 @@ protected override void CalculateModuleAIHints(int slot, Actor actor, PartyRoles protected override void DrawEnemies(int pcSlot, Actor pc) { Arena.Actor(PrimaryActor); - Arena.Actors(Enemies(OID.LiarsLyre), Colors.Object); + Arena.Actors(Enemies((uint)OID.LiarsLyre), Colors.Object); } } diff --git a/BossMod/Modules/Stormblood/Dungeon/D02ShisuiOfTheVioletTides/D022RubyPrincess.cs b/BossMod/Modules/Stormblood/Dungeon/D02ShisuiOfTheVioletTides/D022RubyPrincess.cs index ff5a7d5f5c..b79ed34471 100644 --- a/BossMod/Modules/Stormblood/Dungeon/D02ShisuiOfTheVioletTides/D022RubyPrincess.cs +++ b/BossMod/Modules/Stormblood/Dungeon/D02ShisuiOfTheVioletTides/D022RubyPrincess.cs @@ -36,11 +36,11 @@ class SeduceOld(BossModule module) : Components.GenericAOEs(module) private static readonly AOEShapeCircle circle = new(2.5f); private bool active; private bool addedCircles; - private readonly HashSet chests = [.. module.Enemies(OID.Helper).Where(x => x.NameID == 6274)]; - private readonly HashSet closedChests = []; - private readonly HashSet openChests = []; + private readonly List chests = [.. module.Enemies((uint)OID.Helper).Where(x => x.NameID == 6274)]; + private readonly List closedChests = []; + private readonly List openChests = []; - public static bool IsOld(Actor actor) => actor.FindStatus(SID.Old) != null; + public static bool IsOld(Actor actor) => actor.FindStatus((uint)SID.Old) != null; public override IEnumerable ActiveAOEs(int slot, Actor actor) { @@ -61,31 +61,31 @@ public override void Update() public override void OnActorEAnim(Actor actor, uint state) { - var chest = chests.FirstOrDefault(x => x.Position.AlmostEqual(actor.Position, 5)); + var chest = chests.FirstOrDefault(x => x.Position.AlmostEqual(actor.Position, 5f)); if (chest != null) { if (state == 0x00040008) { - closedChests.RemoveWhere(x => x.Center == chest.Position); + closedChests.RemoveAll(x => x.Center == chest.Position); openChests.Add(new(chest.Position, 2.5f)); } else if (state == 0x00100020) { closedChests.Add(new(chest.Position, 2.5f)); - openChests.RemoveWhere(x => x.Center == chest.Position); + openChests.RemoveAll(x => x.Center == chest.Position); } } } public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.Seduce) + if (spell.Action.ID == (uint)AID.Seduce) active = true; } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.Seduce) + if (spell.Action.ID == (uint)AID.Seduce) active = false; } @@ -101,59 +101,57 @@ public override void AddHints(int slot, Actor actor, TextHints hints) class SeduceCoriolisKick(BossModule module) : Components.GenericAOEs(module) { private static readonly AOEShapeCircle circle = new(13); - private AOEInstance _aoe; + public AOEInstance? AOE; - public override IEnumerable ActiveAOEs(int slot, Actor actor) - { - if (_aoe != default) - yield return _aoe with { Origin = Module.PrimaryActor.Position }; - } + public override IEnumerable ActiveAOEs(int slot, Actor actor) => Utils.ZeroOrOne(AOE); public override void OnCastStarted(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.Seduce) - _aoe = new(circle, default, default, Module.CastFinishAt(spell, 8)); + if (spell.Action.ID == (uint)AID.Seduce) + AOE = new(circle, D022RubyPrincess.ArenaCenter, default, Module.CastFinishAt(spell, 8f)); + else if (spell.Action.ID == (uint)AID.CoriolisKick) + AOE = new(circle, spell.LocXZ, default, Module.CastFinishAt(spell)); } public override void OnCastFinished(Actor caster, ActorCastInfo spell) { - if ((AID)spell.Action.ID == AID.CoriolisKick) - _aoe = default; + if (spell.Action.ID == (uint)AID.CoriolisKick) + AOE = null; } } -class AbyssalVolcano(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.AbyssalVolcano), 7); +class AbyssalVolcano(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.AbyssalVolcano), 7f); -class GeothermalFlatulence(BossModule module) : Components.StandardChasingAOEs(module, new AOEShapeCircle(4), ActionID.MakeSpell(AID.GeothermalFlatulenceFirst), ActionID.MakeSpell(AID.GeothermalFlatulenceRest), 3, 0.8f, 10, true, (uint)IconID.ChasingAOE) +class GeothermalFlatulence(BossModule module) : Components.StandardChasingAOEs(module, new AOEShapeCircle(4f), ActionID.MakeSpell(AID.GeothermalFlatulenceFirst), ActionID.MakeSpell(AID.GeothermalFlatulenceRest), 3, 0.8f, 10, true, (uint)IconID.ChasingAOE) { public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { base.AddAIHints(slot, actor, assignment, hints); if (Actors.Contains(actor)) - hints.AddForbiddenZone(ShapeDistance.Circle(Arena.Center, 18), Activation); + hints.AddForbiddenZone(ShapeDistance.Circle(Arena.Center, 18f), Activation); } } -class Tornadogenesis(BossModule module) : Components.Cleave(module, ActionID.MakeSpell(AID.Tornadogenesis), new AOEShapeCone(9.6f, 60.Degrees())) +class Tornadogenesis(BossModule module) : Components.Cleave(module, ActionID.MakeSpell(AID.Tornadogenesis), new AOEShapeCone(9.6f, 60f.Degrees())) { private readonly SeduceCoriolisKick _aoe = module.FindComponent()!; private readonly GeothermalFlatulence _aoes = module.FindComponent()!; public override void AddHints(int slot, Actor actor, TextHints hints) { - if (!_aoe.ActiveAOEs(slot, actor).Any() && _aoes.Chasers.Count == 0) + if (_aoe.AOE == null && _aoes.Chasers.Count == 0) base.AddHints(slot, actor, hints); } public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) { - if (!_aoe.ActiveAOEs(slot, actor).Any() && _aoes.Chasers.Count == 0) + if (_aoe.AOE == null && _aoes.Chasers.Count == 0) base.AddAIHints(slot, actor, assignment, hints); } public override void DrawArenaForeground(int pcSlot, Actor pc) { - if (!_aoe.ActiveAOEs(pcSlot, pc).Any() && _aoes.Chasers.Count == 0) + if (_aoe.AOE == null && _aoes.Chasers.Count == 0) base.DrawArenaForeground(pcSlot, pc); } } @@ -174,5 +172,6 @@ public D022RubyPrincessStates(BossModule module) : base(module) [ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "The Combat Reborn Team (Malediktus)", GroupType = BossModuleInfo.GroupType.CFC, GroupID = 235, NameID = 6241)] public class D022RubyPrincess(WorldState ws, Actor primary) : BossModule(ws, primary, arena.Center, arena) { - private static readonly ArenaBoundsComplex arena = new([new Circle(new(-0.046f, -208.362f), 20)], [new Rectangle(new(-0.4f, -187.4f), 20, 2.5f), new Rectangle(new(-20, -208), 20, 1.5f, 90.Degrees())]); + public static readonly WPos ArenaCenter = new(-0.046f, -208.362f); + private static readonly ArenaBoundsComplex arena = new([new Circle(ArenaCenter, 20)], [new Rectangle(new(-0.4f, -187.4f), 20, 2.5f), new Rectangle(new(-20, -208), 20, 1.5f, 90.Degrees())]); } diff --git a/BossMod/Modules/Stormblood/Foray/Hydatos/Ceto.cs b/BossMod/Modules/Stormblood/Foray/Hydatos/Ceto.cs index c8ba2ff276..6f783b9c71 100644 --- a/BossMod/Modules/Stormblood/Foray/Hydatos/Ceto.cs +++ b/BossMod/Modules/Stormblood/Foray/Hydatos/Ceto.cs @@ -2,23 +2,37 @@ public enum OID : uint { - Boss = 0x2765, // R5.000, x1 - FaithlessGuard = 0x2767, // R2.000, x0 (spawn during fight) - LifelessSlave1 = 0x2766, // R2.700, x1 - LifelessSlave2 = 0x2785, // R2.700, x1 - LifelessSlave3 = 0x2784, // R2.700, x1 + Boss = 0x2765, // R5.0 + FaithlessGuard = 0x2767, // R2.0 + LifelessSlave1 = 0x2766, // R2.7 + LifelessSlave2 = 0x2785, // R2.7 + LifelessSlave3 = 0x2784, // R2.7 + HydatosDelphyne = 0x26C5, // R1.2 + DarkGargoyle = 0x26C6, // R2.3-4.14 + Helper = 0x2783 } public enum AID : uint { + AutoAttack1 = 15496, // Boss->player, no cast, single-target + AutoAttack2 = 15234, // HydatosDelphyne->player, no cast, single-target + AutoAttack3 = 15235, // DarkGargoyle->player, no cast, single-target + + BuffSlaves = 16171, // Boss->self, no cast, range 50 circle, applies Magic Infusion buff to slaves SickleStrike = 15466, // Boss->player, 3.5s cast, single-target PetrifactionBoss = 15469, // Boss->self, 450 circle AbyssalReaper = 15468, // Boss->self, 4.0s cast, range 18 circle PetrifactionAdds = 15475, // LifelessSlave1/LifelessSlave2/LifelessSlave3->self, 4.0s cast, range 50 circle CircleOfFlames = 15472, // FaithlessGuard->location, 3.0s cast, range 5 circle TailSlap = 15471, // FaithlessGuard->self, 3.0s cast, range 12 120-degree cone - Petrattraction = 15473, // FaithlessGuard->2783, 3.0s cast, single-target - CircleBlade = 15470, // FaithlessGuard->self, 3.0s cast, range 7 circle + PetrattractionVisual = 15473, // FaithlessGuard->Helper, 3.0s cast, single-target + Petrattraction = 15476, // Helper->self, no cast, range 50 circle, pull 50, between hitboxes + GrimFate = 15451, // DarkGargoyle->self, 3.0s cast, range 8 120-degree cone + Desolation = 15453, // DarkGargoyle->self, 3.0s cast, range 12 width 8 rect + + CircleBlade1 = 15470, // FaithlessGuard->self, 3.0s cast, range 7 circle + CircleBlade2 = 15448, // HydatosDelphyne->self, 3.0s cast, range 7 circle + FireToss = 15449, // HydatosDelphyne->players, 3.0s cast, range 5 circle } class SickleStrike(BossModule module) : Components.SingleTargetCast(module, ActionID.MakeSpell(AID.SickleStrike)); @@ -27,9 +41,33 @@ class PetrifactionAdds(BossModule module) : Components.CastGaze(module, ActionID class AbyssalReaper(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.AbyssalReaper), 18f); class CircleOfFlames(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.CircleOfFlames), 5f); class TailSlap(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.TailSlap), new AOEShapeCone(12f, 60f.Degrees())); -class Petrattraction(BossModule module) : Components.KnockbackFromCastTarget(module, ActionID.MakeSpell(AID.Petrattraction), 50f, kind: Kind.TowardsOrigin); -class CircleBlade(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.CircleBlade), 7); -class Adds(BossModule module) : Components.AddsPointless(module, (uint)OID.FaithlessGuard); +class GrimFate(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.GrimFate), new AOEShapeCone(8f, 60f.Degrees())); +class Desolation(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Desolation), new AOEShapeRect(12f, 4f)); + +class Petrattraction(BossModule module) : Components.Knockback(module) +{ + public Source? _source; + + private static readonly AOEShapeCircle circle = new(50f); + + public override IEnumerable Sources(int slot, Actor actor) => Utils.ZeroOrOne(_source); + + public override void OnCastStarted(Actor caster, ActorCastInfo spell) + { + if (spell.Action.ID == (uint)AID.PetrattractionVisual) + _source = new(caster.Position, 50f, Module.CastFinishAt(spell, 1.4f), circle, Kind: Kind.TowardsOrigin); + } + + public override void OnEventCast(Actor caster, ActorCastEvent spell) + { + if (spell.Action.ID == (uint)AID.Petrattraction) + _source = null; + } +} + +class CircleBlade1(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.CircleBlade1), 7); +class CircleBlade2(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.CircleBlade2), 7); +class FireToss(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.FireToss), 5f); class CetoStates : StateMachineBuilder { @@ -43,11 +81,37 @@ public CetoStates(BossModule module) : base(module) .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter() - .ActivateOnEnter() - .ActivateOnEnter(); + .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter(); } } -[ModuleInfo(BossModuleInfo.Maturity.Contributed, GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1421, Contributors = "xan", SortOrder = 9)] -public class Ceto(WorldState ws, Actor primary) : BossModule(ws, primary, new(747.8959f, -878.8765f), new ArenaBoundsCircle(80f, 1f, true)); +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "xan, Malediktus", GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1421, SortOrder = 9)] +public class Ceto(WorldState ws, Actor primary) : BossModule(ws, primary, new(747.8959f, -878.8765f), new ArenaBoundsCircle(80f, 1f, true)) +{ + private static readonly uint[] trash = [(uint)OID.FaithlessGuard, (uint)OID.HydatosDelphyne, (uint)OID.DarkGargoyle]; + protected override void DrawEnemies(int pcSlot, Actor pc) + { + Arena.Actor(PrimaryActor); + Arena.Actors(Enemies(trash)); + } + protected override void CalculateModuleAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + var count = hints.PotentialTargets.Count; + for (var i = 0; i < count; ++i) + { + var e = hints.PotentialTargets[i]; + e.Priority = e.Actor.OID switch + { + (uint)OID.Boss => 1, + (uint)OID.FaithlessGuard => AIHints.Enemy.PriorityPointless, + _ when e.Actor.InCombat => 0, + _ => AIHints.Enemy.PriorityUndesirable + }; + } + } +} diff --git a/BossMod/Modules/Stormblood/Foray/Hydatos/Daphne.cs b/BossMod/Modules/Stormblood/Foray/Hydatos/Daphne.cs index a00865e192..1813efc49f 100644 --- a/BossMod/Modules/Stormblood/Foray/Hydatos/Daphne.cs +++ b/BossMod/Modules/Stormblood/Foray/Hydatos/Daphne.cs @@ -3,26 +3,45 @@ public enum OID : uint { Boss = 0x2744, // R6.875, x1 - Tentacle = 0x276E, // R7.200, x0 (spawn during fight) - Helper1 = 0x276A, // R0.500, x0 (spawn during fight) - Helper2 = 0x276B, // R0.500, x0 (spawn during fight) + Tentacle = 0x276E, // R7.2 + Gorpokkur = 0x26BA, // R1.0-3.0 + Helper1 = 0x276A, + Helper2 = 0x276B } public enum AID : uint { + AutoAttack1 = 14926, // Boss->player, no cast, single-target + AutoAttack2 = 15223, // Gorpokkur->player, no cast, single-target + SpellwindCast = 15031, // Boss->self, 4.0s cast, single-target SpellwindAOE = 15032, // Helper1->location, no cast, range 40 circle Upburst = 15025, // Tentacle->self, 3.5s cast, range 8 circle RoilingReach = 15029, // Boss->self, 4.5s cast, range 32 width 7 cross Wallop = 15027, // Tentacle->self, 4.0s cast, range 50 width 7 rect ChillingGlare = 15030, // Boss->self, 4.0s cast, range 40 circle + NetherwaterVisual = 15037, // Boss->self, 6.0s cast, single-target + Netherwater = 15033, // Helper2->player, no cast, range 6 circle + + Tentacle = 15034, // Boss->self, no cast, single-target + TentacleFinish = 15044, // Tentacle->self, no cast, single-target + + Mutation = 15142, // Gorpokkur->self, 5.0s cast, single-target + Spiritus = 15417 // Gorpokkur->self, 3.0s cast, range 5 60-degree cone +} + +public enum IconID : uint +{ + Stackmarker = 62 // player->self } class Spellwind(BossModule module) : Components.RaidwideCast(module, ActionID.MakeSpell(AID.SpellwindCast)); -class Upburst(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Upburst), 8); +class Upburst(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Upburst), 8f); class RoilingReach(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.RoilingReach), new AOEShapeCross(32f, 3.5f)); class Wallop(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Wallop), new AOEShapeRect(50f, 3.5f)); class ChillingGlare(BossModule module) : Components.CastGaze(module, ActionID.MakeSpell(AID.ChillingGlare)); +class Netherwater(BossModule module) : Components.StackWithIcon(module, (uint)IconID.Stackmarker, ActionID.MakeSpell(AID.Netherwater), 6, 4.9f, 4, 24); +class Spiritus(BossModule module) : Components.SimpleAOEs(module, ActionID.MakeSpell(AID.Spiritus), new AOEShapeCone(5, 30f.Degrees())); class DaphneStates : StateMachineBuilder { @@ -33,10 +52,33 @@ public DaphneStates(BossModule module) : base(module) .ActivateOnEnter() .ActivateOnEnter() .ActivateOnEnter() - .ActivateOnEnter(); + .ActivateOnEnter() + .ActivateOnEnter() + .ActivateOnEnter(); } } -[ModuleInfo(BossModuleInfo.Maturity.Contributed, GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1417, Contributors = "xan", SortOrder = 5)] -public class Daphne(WorldState ws, Actor primary) : BossModule(ws, primary, new(207.8475f, -736.8179f), new ArenaBoundsCircle(80f, 1f, true)); +[ModuleInfo(BossModuleInfo.Maturity.Verified, Contributors = "xan, Malediktus", GroupType = BossModuleInfo.GroupType.EurekaNM, GroupID = 639, NameID = 1417, SortOrder = 5)] +public class Daphne(WorldState ws, Actor primary) : BossModule(ws, primary, new(207.8475f, -736.8179f), new ArenaBoundsCircle(80f, 1f, true)) +{ + protected override void DrawEnemies(int pcSlot, Actor pc) + { + Arena.Actor(PrimaryActor); + Arena.Actors(Enemies((uint)OID.Gorpokkur)); + } + protected override void CalculateModuleAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints) + { + var count = hints.PotentialTargets.Count; + for (var i = 0; i < count; ++i) + { + var e = hints.PotentialTargets[i]; + e.Priority = e.Actor.OID switch + { + (uint)OID.Boss => 1, + _ when e.Actor.InCombat => 0, + _ => AIHints.Enemy.PriorityUndesirable + }; + } + } +} diff --git a/BossMod/Pathfinding/ObstacleMaps/1193.824.1.bmp b/BossMod/Pathfinding/ObstacleMaps/1193.824.1.bmp index a5831ab34b..4c5195e017 100644 Binary files a/BossMod/Pathfinding/ObstacleMaps/1193.824.1.bmp and b/BossMod/Pathfinding/ObstacleMaps/1193.824.1.bmp differ diff --git a/BossMod/Pathfinding/ObstacleMaps/1193.824.2.bmp b/BossMod/Pathfinding/ObstacleMaps/1193.824.2.bmp index 50d9bd2098..d094ee15f5 100644 Binary files a/BossMod/Pathfinding/ObstacleMaps/1193.824.2.bmp and b/BossMod/Pathfinding/ObstacleMaps/1193.824.2.bmp differ diff --git a/BossMod/Pathfinding/ObstacleMaps/1193.824.3.bmp b/BossMod/Pathfinding/ObstacleMaps/1193.824.3.bmp index d094ee15f5..77e43bd127 100644 Binary files a/BossMod/Pathfinding/ObstacleMaps/1193.824.3.bmp and b/BossMod/Pathfinding/ObstacleMaps/1193.824.3.bmp differ diff --git a/BossMod/Pathfinding/ObstacleMaps/1193.824.4.bmp b/BossMod/Pathfinding/ObstacleMaps/1193.824.4.bmp deleted file mode 100644 index 77e43bd127..0000000000 Binary files a/BossMod/Pathfinding/ObstacleMaps/1193.824.4.bmp and /dev/null differ diff --git a/BossMod/Pathfinding/ObstacleMaps/1193.824.5.bmp b/BossMod/Pathfinding/ObstacleMaps/1193.824.5.bmp deleted file mode 100644 index 9193376a16..0000000000 Binary files a/BossMod/Pathfinding/ObstacleMaps/1193.824.5.bmp and /dev/null differ diff --git a/BossMod/Pathfinding/ObstacleMaps/1242.1008.1.bmp b/BossMod/Pathfinding/ObstacleMaps/1242.1008.1.bmp new file mode 100644 index 0000000000..ce18feb908 Binary files /dev/null and b/BossMod/Pathfinding/ObstacleMaps/1242.1008.1.bmp differ diff --git a/BossMod/Pathfinding/ObstacleMaps/maplist.json b/BossMod/Pathfinding/ObstacleMaps/maplist.json index 1eafba39e2..46310c9608 100644 --- a/BossMod/Pathfinding/ObstacleMaps/maplist.json +++ b/BossMod/Pathfinding/ObstacleMaps/maplist.json @@ -1545,31 +1545,18 @@ } ], "1193.824": [ - { - "MinBoundsX": 9, - "MinBoundsY": -25, - "MinBoundsZ": 157, - "MaxBoundsX": 222.5, - "MaxBoundsY": 2, - "MaxBoundsZ": 212.5, - "OriginX": 9, - "OriginZ": 157, - "ViewWidth": 60, - "ViewHeight": 60, - "Filename": "1193.824.1.bmp" - }, { "MinBoundsX": -155.5, - "MinBoundsY": 9.5, + "MinBoundsY": -25, "MinBoundsZ": 49, - "MaxBoundsX": -63, + "MaxBoundsX": 222.5, "MaxBoundsY": 51.5, - "MaxBoundsZ": 154, + "MaxBoundsZ": 212.5, "OriginX": -155.5, "OriginZ": 49, "ViewWidth": 60, "ViewHeight": 60, - "Filename": "1193.824.2.bmp" + "Filename": "1193.824.1.bmp" }, { "MinBoundsX": -167.5, @@ -1582,7 +1569,7 @@ "OriginZ": -22.5, "ViewWidth": 60, "ViewHeight": 60, - "Filename": "1193.824.3.bmp" + "Filename": "1193.824.2.bmp" }, { "MinBoundsX": -173, @@ -1595,20 +1582,7 @@ "OriginZ": -219.5, "ViewWidth": 60, "ViewHeight": 60, - "Filename": "1193.824.4.bmp" - }, - { - "MinBoundsX": -111, - "MinBoundsY": -8.5, - "MinBoundsZ": 158, - "MaxBoundsX": 4, - "MaxBoundsY": 21.5, - "MaxBoundsZ": 211, - "OriginX": -111, - "OriginZ": 158, - "ViewWidth": 60, - "ViewHeight": 60, - "Filename": "1193.824.5.bmp" + "Filename": "1193.824.3.bmp" } ], "1194.829": [ diff --git a/BossMod/QuestBattle/ARealmReborn/MSQ/LurkersInTheGrotto.cs b/BossMod/QuestBattle/ARealmReborn/MSQ/LurkersInTheGrotto.cs new file mode 100644 index 0000000000..957aa70363 --- /dev/null +++ b/BossMod/QuestBattle/ARealmReborn/MSQ/LurkersInTheGrotto.cs @@ -0,0 +1,11 @@ +namespace BossMod.QuestBattle.ARealmReborn.MSQ; + +[ZoneModuleInfo(BossModuleInfo.Maturity.Contributed, 332)] +public class LurkersInTheGrotto(WorldState ws) : QuestBattle(ws) +{ + public override void CalculateAIHints(int playerSlot, Actor player, AIHints hints) + { + foreach (var p in hints.PotentialTargets) + p.Priority = p.Actor.OID == 0x386 ? 0 : 1; + } +} diff --git a/BossMod/Replay/Analysis/ArenaBounds.cs b/BossMod/Replay/Analysis/ArenaBounds.cs index e46841a1ab..3da18e910f 100644 --- a/BossMod/Replay/Analysis/ArenaBounds.cs +++ b/BossMod/Replay/Analysis/ArenaBounds.cs @@ -173,17 +173,17 @@ private static Path64 MergePaths(Paths64 paths) private static List ApplyAlphaFilter(List hull, double alpha) { List filteredHull = [hull[0]]; - - for (var i = 1; i < hull.Count; ++i) + var count = hull.Count; + for (var i = 1; i < count; ++i) { var currentPoint = hull[i]; - var lastAddedPoint = filteredHull.Last(); + var lastAddedPoint = filteredHull[^1]; if (Distance(currentPoint, lastAddedPoint) > alpha) filteredHull.Add(currentPoint); } - if (Distance(filteredHull.Last(), filteredHull.First()) > alpha) - filteredHull.Add(filteredHull.First()); + if (Distance(filteredHull[^1], filteredHull[0]) > alpha) + filteredHull.Add(filteredHull[0]); return filteredHull; } @@ -206,7 +206,7 @@ private static List RemoveCollinearPoints(List points) return filteredPoints; } - private static bool AreCollinear(WPos a, WPos b, WPos c, float toleranceDegrees = 1) + private static bool AreCollinear(WPos a, WPos b, WPos c, float toleranceDegrees = 5) { var ab = new Vector2(b.X - a.X, b.Z - a.Z); var bc = new Vector2(c.X - b.X, c.Z - b.Z); diff --git a/UIDev/UITest.cs b/UIDev/UITest.cs index b413aa6e4a..909f62dd8f 100644 --- a/UIDev/UITest.cs +++ b/UIDev/UITest.cs @@ -47,7 +47,8 @@ public static void Main(string[] args) InitializeDalamudStyle(); - Service.LogHandler = msg => Debug.WriteLine(msg); + Service.LogHandlerDebug = msg => Debug.WriteLine(msg); + Service.LogHandlerVerbose = msg => Debug.WriteLine(msg); Service.LuminaGameData = new(FindGameDataPath()); //Service.LuminaGameData.Options.PanicOnSheetChecksumMismatch = false; // TODO: remove - temporary workaround until lumina is updated Service.LuminaGameData.Options.RsvResolver = Service.LuminaRSV.TryGetValue;