Skip to content

Commit

Permalink
Merge pull request #454 from FFXIV-CombatReborn/mergeWIP
Browse files Browse the repository at this point in the history
code analyzer fix
  • Loading branch information
CarnifexOptimus authored Nov 21, 2024
2 parents f7cb18e + 6a38fa7 commit ea1bf20
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 58 deletions.
32 changes: 18 additions & 14 deletions BossMod/Autorotation/RotationModuleManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
// the manager contains a set of rotation module instances corresponding to the selected preset/plan
public sealed class RotationModuleManager : IDisposable
{
#pragma warning disable IDE0032
private Preset? _preset; // if non-null, this preset overrides the configuration
#pragma warning restore IDE0032
public Preset? Preset
{
get;
get => _preset;
set
{
DirtyActiveModules(field != value);
field = value;
DirtyActiveModules(_preset != value);
_preset = value;
}
}

Expand Down Expand Up @@ -81,14 +84,14 @@ public void Update(float estimatedAnimLockDelay, bool isMoving)
{
Service.Log($"[RMM] Changing active plan: '{Planner?.Plan?.Guid}' -> '{expectedPlan?.Guid}'");
Planner = Bossmods.ActiveModule != null ? new(Bossmods.ActiveModule, expectedPlan) : null;
DirtyActiveModules(Preset == null);
DirtyActiveModules(_preset == null);
}

// rebuild modules if needed
ActiveModules ??= Preset != null ? RebuildActiveModules(Preset.Modules.Keys) : Planner?.Plan != null ? RebuildActiveModules(Planner.Plan.Modules.Keys) : [];
ActiveModules ??= _preset != null ? RebuildActiveModules(_preset.Modules.Keys) : Planner?.Plan != null ? RebuildActiveModules(Planner.Plan.Modules.Keys) : [];

// forced target update
if (Hints.ForcedTarget == null && Preset == null && Planner?.ActiveForcedTarget() is var forced && forced != null)
if (Hints.ForcedTarget == null && _preset == null && Planner?.ActiveForcedTarget() is var forced && forced != null)
{
Hints.ForcedTarget = forced.Value.Target != StrategyTarget.Automatic
? ResolveTargetOverride(forced.Value.Target, forced.Value.TargetParam)
Expand All @@ -97,10 +100,11 @@ public void Update(float estimatedAnimLockDelay, bool isMoving)

// auto actions
var target = Hints.ForcedTarget ?? WorldState.Actors.Find(Player?.TargetID ?? 0);
foreach (var m in ActiveModules)
for (var i = 0; i < ActiveModules.Count; ++i)
{
var m = ActiveModules[i];
var mt = m.Module.GetType();
var values = Preset?.ActiveStrategyOverrides(mt) ?? Planner?.ActiveStrategyOverrides(mt) ?? throw new InvalidOperationException("Both preset and plan are null, but there are active modules");
var values = _preset?.ActiveStrategyOverrides(mt) ?? Planner?.ActiveStrategyOverrides(mt) ?? throw new InvalidOperationException("Both preset and plan are null, but there are active modules");
m.Module.Execute(values, target, estimatedAnimLockDelay, isMoving);
}
}
Expand Down Expand Up @@ -163,16 +167,16 @@ private void OnCombatChanged(Actor actor)

CombatStart = actor.InCombat ? WorldState.CurrentTime : default; // keep track of combat time in case rotation modules want to do something special in openers

if (!actor.InCombat && (Preset == ForceDisable || Config.ClearPresetOnCombatEnd))
if (!actor.InCombat && (_preset == ForceDisable || Config.ClearPresetOnCombatEnd))
{
// player exits combat => clear manual overrides
Service.Log($"[RMM] Player exits combat => clear preset '{Preset?.Name ?? "<n/a>"}'");
Service.Log($"[RMM] Player exits combat => clear preset '{_preset?.Name ?? "<n/a>"}'");
Preset = null;
}
else if (actor.InCombat && WorldState.Client.CountdownRemaining > Config.EarlyPullThreshold)
{
// player enters combat while countdown is in progress => force disable
Service.Log($"[RMM] Player ninja pulled => force-disabling from '{Preset?.Name ?? "<n/a>"}'");
Service.Log($"[RMM] Player ninja pulled => force-disabling from '{_preset?.Name ?? "<n/a>"}'");
Preset = ForceDisable;
}
// if player enters combat when countdown is either not active or around zero, proceed normally - if override is queued, let it run, otherwise let plan run
Expand All @@ -187,7 +191,7 @@ private void OnDeadChanged(Actor actor)
if (actor.IsDead && actor.InCombat)
{
// player died in combat => force disable (otherwise there's a risk of dying immediately after rez)
Service.Log($"[RMM] Player died in combat => force-disabling from '{Preset?.Name ?? "<n/a>"}'");
Service.Log($"[RMM] Player died in combat => force-disabling from '{_preset?.Name ?? "<n/a>"}'");
Preset = ForceDisable;
}
// else: player either died outside combat (no need to touch anything) or rez'd (unless player cleared override, we stay in force disable mode)
Expand All @@ -199,14 +203,14 @@ private void OnCountdownChanged(ClientState.OpCountdownChange op)
{
// countdown ended and player is not in combat - so either it was cancelled, or pull didn't happen => clear manual overrides
// note that if pull will happen regardless after this, we'll start executing plan normally (without prepull part)
Service.Log($"[RMM] Countdown expired or aborted => clear preset '{Preset?.Name ?? "<n/a>"}'");
Service.Log($"[RMM] Countdown expired or aborted => clear preset '{_preset?.Name ?? "<n/a>"}'");
Preset = null;
}
}

private void OnPresetModified(Preset? prev, Preset? curr)
{
if (prev != null && prev == Preset)
if (prev != null && prev == _preset)
Preset = curr;
}

Expand Down
9 changes: 6 additions & 3 deletions BossMod/BossModule/ArenaBounds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ public abstract record class ArenaBounds(float Radius, float MapResolution, floa
private readonly PolygonClipper.Operand _clipOperand = new();
public readonly Dictionary<object, object> Cache = [];

#pragma warning disable IDE0032
private float _screenHalfSize;
#pragma warning restore IDE0032
public float ScreenHalfSize
{
get;
get => _screenHalfSize;
set
{
if (field != value)
if (_screenHalfSize != value)
{
field = value;
_screenHalfSize = value;
MaxApproxError = CurveApprox.ScreenError / value * Radius;
ShapeSimplified = Clipper.Simplify(BuildClipPoly());
ShapeTriangulation = ShapeSimplified.Triangulate();
Expand Down
74 changes: 39 additions & 35 deletions BossMod/BossModule/MiniArena.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ public sealed class MiniArena(BossModuleConfig config, WPos center, ArenaBounds
{
public readonly BossModuleConfig Config = config;
private WPos _center = center;
#pragma warning disable IDE0032
private ArenaBounds _bounds = bounds;
#pragma warning restore IDE0032
private readonly TriangulationCache _triCache = new();

public WPos Center
Expand All @@ -28,16 +31,16 @@ public WPos Center

public ArenaBounds Bounds
{
get;
get => _bounds;
set
{
if (!ReferenceEquals(field, value))
if (!ReferenceEquals(_bounds, value))
{
field = value;
_bounds = value;
_triCache.Invalidate();
}
}
} = bounds;
}

public float ScreenHalfSize => 150 * Config.ArenaScale;
public float ScreenMarginSize => 20 * Config.ArenaScale;
Expand All @@ -48,9 +51,9 @@ public ArenaBounds Bounds
private float _cameraSinAzimuth;
private float _cameraCosAzimuth = 1;

public bool InBounds(WPos position) => Bounds.Contains(position - Center);
public WPos ClampToBounds(WPos position) => Center + Bounds.ClampToBounds(position - Center);
public float IntersectRayBounds(WPos rayOrigin, WDir rayDir) => Bounds.IntersectRay(rayOrigin - Center, rayDir);
public bool InBounds(WPos position) => _bounds.Contains(position - _center);
public WPos ClampToBounds(WPos position) => _center + _bounds.ClampToBounds(position - _center);
public float IntersectRayBounds(WPos rayOrigin, WDir rayDir) => _bounds.IntersectRay(rayOrigin - _center, rayDir);

// prepare for drawing - set up internal state, clip rect etc.
public async Task Begin(Angle cameraAzimuth)
Expand All @@ -63,7 +66,7 @@ public async Task Begin(Angle cameraAzimuth)
var cursor = ImGui.GetCursorScreenPos();
ImGui.Dummy(fullSize);

if (Bounds.ScreenHalfSize != ScreenHalfSize)
if (_bounds.ScreenHalfSize != ScreenHalfSize)
{
Bounds.ScreenHalfSize = ScreenHalfSize;
_triCache.Invalidate();
Expand All @@ -88,7 +91,7 @@ public async Task Begin(Angle cameraAzimuth)
}
private Task GenerateBackgroundAsync()
{
Zone(Bounds.ShapeTriangulation, Colors.Background);
Zone(_bounds.ShapeTriangulation, Colors.Background);
return Task.CompletedTask;
}

Expand All @@ -112,7 +115,7 @@ public Vector2 RotatedCoords(Vector2 coords)

private Vector2 WorldOffsetToScreenOffset(WDir worldOffset)
{
return ScreenHalfSize * RotatedCoords(worldOffset.ToVec2()) / Bounds.Radius;
return ScreenHalfSize * RotatedCoords(worldOffset.ToVec2()) / _bounds.Radius;
}

// unclipped primitive rendering that accept world-space positions; thin convenience wrappers around drawlist api
Expand Down Expand Up @@ -153,14 +156,15 @@ public void AddRect(WPos origin, WDir direction, float lenFront, float lenBack,

public void AddCircle(WPos center, float radius, uint color = 0, float thickness = 1)
{
var radiusscreenhalfsize = radius / _bounds.Radius * ScreenHalfSize;
if (Config.ShowOutlinesAndShadows)
ImGui.GetWindowDrawList().AddCircle(WorldPositionToScreenPosition(center), radius / Bounds.Radius * ScreenHalfSize, Colors.Shadows, 0, thickness + 1);
ImGui.GetWindowDrawList().AddCircle(WorldPositionToScreenPosition(center), radius / Bounds.Radius * ScreenHalfSize, color != 0 ? color : Colors.Danger, 0, thickness);
ImGui.GetWindowDrawList().AddCircle(WorldPositionToScreenPosition(center), radiusscreenhalfsize, Colors.Shadows, 0, thickness + 1);
ImGui.GetWindowDrawList().AddCircle(WorldPositionToScreenPosition(center), radiusscreenhalfsize, color != 0 ? color : Colors.Danger, 0, thickness);
}

public void AddCircleFilled(WPos center, float radius, uint color = 0)
{
ImGui.GetWindowDrawList().AddCircleFilled(WorldPositionToScreenPosition(center), radius / Bounds.Radius * ScreenHalfSize, color != 0 ? color : Colors.Danger);
ImGui.GetWindowDrawList().AddCircleFilled(WorldPositionToScreenPosition(center), radius / _bounds.Radius * ScreenHalfSize, color != 0 ? color : Colors.Danger);
}

public void AddCone(WPos center, float radius, Angle centerDirection, Angle halfAngle, uint color = 0, float thickness = 1)
Expand All @@ -169,7 +173,7 @@ public void AddCone(WPos center, float radius, Angle centerDirection, Angle half
var sDir = Angle.HalfPi - centerDirection.Rad + _cameraAzimuth.Rad;
var drawlist = ImGui.GetWindowDrawList();
drawlist.PathLineTo(sCenter);
drawlist.PathArcTo(sCenter, radius / Bounds.Radius * ScreenHalfSize, sDir - halfAngle.Rad, sDir + halfAngle.Rad);
drawlist.PathArcTo(sCenter, radius / _bounds.Radius * ScreenHalfSize, sDir - halfAngle.Rad, sDir + halfAngle.Rad);
drawlist.PathStroke(color != 0 ? color : Colors.Danger, ImDrawFlags.Closed, thickness);
}

Expand All @@ -178,7 +182,7 @@ public void AddDonutCone(WPos center, float innerRadius, float outerRadius, Angl
var sCenter = WorldPositionToScreenPosition(center);
var sDir = Angle.HalfPi - centerDirection.Rad + _cameraAzimuth.Rad;
var drawlist = ImGui.GetWindowDrawList();
var invRadius = 1 / Bounds.Radius * ScreenHalfSize;
var invRadius = 1 / _bounds.Radius * ScreenHalfSize;
var sDirP = sDir + halfAngle.Rad;
var sDirN = sDir - halfAngle.Rad;
drawlist.PathArcTo(sCenter, innerRadius * invRadius, sDirP, sDirN);
Expand All @@ -196,7 +200,7 @@ public void AddCapsule(WPos start, WDir direction, float radius, float length, u

var drawList = ImGui.GetWindowDrawList();

var screenRadius = radius / Bounds.Radius * ScreenHalfSize;
var screenRadius = radius / _bounds.Radius * ScreenHalfSize;
var screenCapsuleStart = WorldPositionToScreenPosition(capsuleStart);
var screenCapsuleEnd = WorldPositionToScreenPosition(capsuleEnd);

Expand Down Expand Up @@ -226,8 +230,8 @@ public void AddCapsule(WPos start, WDir direction, float radius, float length, u

public void AddPolygon(ReadOnlySpan<WPos> vertices, uint color = 0, float thickness = 1)
{
foreach (var p in vertices)
PathLineTo(p);
for (var i = 0; i < vertices.Length; ++i)
PathLineTo(vertices[i]);
PathStroke(true, color != 0 ? color : Colors.Danger, thickness);
}

Expand All @@ -247,7 +251,7 @@ public void PathLineTo(WPos p)
// adds a bunch of points corresponding to arc - if path is non empty, this adds an edge from last point to first arc point
public void PathArcTo(WPos center, float radius, float amin, float amax)
{
ImGui.GetWindowDrawList().PathArcTo(WorldPositionToScreenPosition(center), radius / Bounds.Radius * ScreenHalfSize, Angle.HalfPi - amin + _cameraAzimuth.Rad, Angle.HalfPi - amax + _cameraAzimuth.Rad);
ImGui.GetWindowDrawList().PathArcTo(WorldPositionToScreenPosition(center), radius / _bounds.Radius * ScreenHalfSize, Angle.HalfPi - amin + _cameraAzimuth.Rad, Angle.HalfPi - amax + _cameraAzimuth.Rad);
}

public static void PathStroke(bool closed, uint color = 0, float thickness = 1)
Expand Down Expand Up @@ -276,31 +280,31 @@ public void Zone(List<RelTriangle> triangulation, uint color = 0)

// draw zones - these are filled primitives clipped to arena border; note that triangulation is cached
public void ZoneCone(WPos center, float innerRadius, float outerRadius, Angle centerDirection, Angle halfAngle, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(1, center, innerRadius, outerRadius, centerDirection, halfAngle)] ??= Bounds.ClipAndTriangulateCone(center - Center, innerRadius, outerRadius, centerDirection, halfAngle), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(1, center, innerRadius, outerRadius, centerDirection, halfAngle)] ??= _bounds.ClipAndTriangulateCone(center - Center, innerRadius, outerRadius, centerDirection, halfAngle), color);
public void ZoneCircle(WPos center, float radius, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(2, center, radius)] ??= Bounds.ClipAndTriangulateCircle(center - Center, radius), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(2, center, radius)] ??= _bounds.ClipAndTriangulateCircle(center - Center, radius), color);
public void ZoneDonut(WPos center, float innerRadius, float outerRadius, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(3, center, innerRadius, outerRadius)] ??= Bounds.ClipAndTriangulateDonut(center - Center, innerRadius, outerRadius), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(3, center, innerRadius, outerRadius)] ??= _bounds.ClipAndTriangulateDonut(center - Center, innerRadius, outerRadius), color);
public void ZoneTri(WPos a, WPos b, WPos c, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(4, a, b, c)] ??= Bounds.ClipAndTriangulateTri(a - Center, b - Center, c - Center), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(4, a, b, c)] ??= _bounds.ClipAndTriangulateTri(a - Center, b - Center, c - Center), color);
public void ZoneIsoscelesTri(WPos apex, WDir height, WDir halfBase, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(5, apex, height, halfBase)] ??= Bounds.ClipAndTriangulateIsoscelesTri(apex - Center, height, halfBase), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(5, apex, height, halfBase)] ??= _bounds.ClipAndTriangulateIsoscelesTri(apex - Center, height, halfBase), color);
public void ZoneIsoscelesTri(WPos apex, Angle direction, Angle halfAngle, float height, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(6, apex, direction, halfAngle, height)] ??= Bounds.ClipAndTriangulateIsoscelesTri(apex - Center, direction, halfAngle, height), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(6, apex, direction, halfAngle, height)] ??= _bounds.ClipAndTriangulateIsoscelesTri(apex - Center, direction, halfAngle, height), color);
public void ZoneRect(WPos origin, WDir direction, float lenFront, float lenBack, float halfWidth, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(7, origin, direction, lenFront, lenBack, halfWidth)] ??= Bounds.ClipAndTriangulateRect(origin - Center, direction, lenFront, lenBack, halfWidth), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(7, origin, direction, lenFront, lenBack, halfWidth)] ??= _bounds.ClipAndTriangulateRect(origin - Center, direction, lenFront, lenBack, halfWidth), color);
public void ZoneRect(WPos origin, Angle direction, float lenFront, float lenBack, float halfWidth, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(8, origin, direction, lenFront, lenBack, halfWidth)] ??= Bounds.ClipAndTriangulateRect(origin - Center, direction, lenFront, lenBack, halfWidth), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(8, origin, direction, lenFront, lenBack, halfWidth)] ??= _bounds.ClipAndTriangulateRect(origin - Center, direction, lenFront, lenBack, halfWidth), color);
public void ZoneRect(WPos start, WPos end, float halfWidth, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(9, start, end, halfWidth)] ??= Bounds.ClipAndTriangulateRect(start - Center, end - Center, halfWidth), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(9, start, end, halfWidth)] ??= _bounds.ClipAndTriangulateRect(start - Center, end - Center, halfWidth), color);
public void ZonePoly(object key, IEnumerable<WPos> contour, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(10, key)] ??= Bounds.ClipAndTriangulate(contour.Select(p => p - Center)), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(10, key)] ??= _bounds.ClipAndTriangulate(contour.Select(p => p - Center)), color);
public void ZoneRelPoly(object key, IEnumerable<WDir> relContour, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(11, key)] ??= Bounds.ClipAndTriangulate(relContour), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(11, key)] ??= _bounds.ClipAndTriangulate(relContour), color);
public void ZoneRelPoly(int key, RelSimplifiedComplexPolygon poly, uint color)
=> Zone(_triCache[key] ??= Bounds.ClipAndTriangulate(poly), color);
=> Zone(_triCache[key] ??= _bounds.ClipAndTriangulate(poly), color);
public void ZoneCapsule(WPos start, WDir direction, float radius, float length, uint color)
=> Zone(_triCache[TriangulationCache.GetKeyHash(12, start, direction, radius, length)] ??= Bounds.ClipAndTriangulateCapsule(start - Center, direction, radius, length), color);
=> Zone(_triCache[TriangulationCache.GetKeyHash(12, start, direction, radius, length)] ??= _bounds.ClipAndTriangulateCapsule(start - Center, direction, radius, length), color);

public void TextScreen(Vector2 center, string text, uint color, float fontSize = 17)
{
Expand All @@ -319,9 +323,9 @@ public void Border(uint color)
{
var dl = ImGui.GetWindowDrawList();

for (var i = 0; i < Bounds.ShapeSimplified.Parts.Count; ++i)
for (var i = 0; i < _bounds.ShapeSimplified.Parts.Count; ++i)
{
var part = Bounds.ShapeSimplified.Parts[i];
var part = _bounds.ShapeSimplified.Parts[i];
Vector2? lastPoint = null;

for (var j = 0; j < part.Exterior.Length; ++j)
Expand Down Expand Up @@ -356,7 +360,7 @@ public void Border(uint color)

public void CardinalNames()
{
var offCenter = (ScreenHalfSize + ScreenMarginSize * 0.5f) * Bounds.ScaleFactor;
var offCenter = (ScreenHalfSize + ScreenMarginSize * 0.5f) * _bounds.ScaleFactor;
var fontSetting = Config.CardinalsFontSize;
var sizeoffset = fontSetting - 17;
var offS = RotatedCoords(new(0, offCenter + sizeoffset));
Expand Down
Loading

0 comments on commit ea1bf20

Please sign in to comment.