This commit is contained in:
NotSoToothless
2026-06-19 18:47:44 -07:00
committed by GitHub
parent ac7c318899
commit 062a9e2bdf
+40 -22
View File
@@ -971,6 +971,42 @@ def _capture_tm_vectors(tm: list) -> tuple[np.ndarray, np.ndarray, np.ndarray, n
return a0, a1, a2, c
def _halve_outlier_capture_area(areas: list[dict]) -> list[dict]:
"""Halve a single capture area whose radius is a strong outlier.
Some definitions report one capture point at roughly double its true radius
(a known datamine quirk that also rides along in the replay's own zone
geometry). When exactly one area among at least three exceeds 2x the median
sibling radius, halve it — radius plus its tm X/Z basis so the rendered
outline matches. Applied to every capture-area source so the correction is
independent of whether geometry came from the mission .blk or the replay
zone data fallback.
"""
if len(areas) < 3:
return areas
radii = sorted(float(c["radius"]) for c in areas if float(c.get("radius", 0.0)) > 0.0)
if len(radii) < 3:
return areas
median_r = radii[len(radii) // 2]
if median_r <= 0.0:
return areas
outlier = [
i for i, c in enumerate(areas)
if float(c.get("radius", 0.0)) > (2.0 * median_r)
]
if len(outlier) != 1:
return areas
oi = outlier[0]
areas[oi]["radius"] = float(areas[oi]["radius"]) * 0.5
tm = areas[oi].get("tm")
if isinstance(tm, dict):
for key in ("a0", "a2"):
vec = tm.get(key)
if isinstance(vec, list) and len(vec) >= 3:
tm[key] = [float(vec[0]) * 0.5, float(vec[1]) * 0.5, float(vec[2]) * 0.5]
return areas
def resolve_capture_areas(mission_def: dict | None, mission_def_path: Path | None,
battle_type: str) -> list[dict]:
"""Resolve gameplay capture areas from mission imports (mode-specific)."""
@@ -1058,27 +1094,8 @@ def resolve_capture_areas(mission_def: dict | None, mission_def_path: Path | Non
"radius": _capture_radius_from_tm(tm),
"tm": tm_data,
})
# If exactly one cap is a strong outlier (>2x median sibling radius),
# halve only that cap (including tm X/Z basis so rendered outline matches).
if len(out) >= 3:
radii = sorted(float(c["radius"]) for c in out if float(c["radius"]) > 0.0)
if len(radii) >= 3:
median_r = radii[len(radii) // 2]
if median_r > 0.0:
outlier = [
i for i, c in enumerate(out)
if float(c.get("radius", 0.0)) > (2.0 * median_r)
]
if len(outlier) == 1:
oi = outlier[0]
out[oi]["radius"] = float(out[oi]["radius"]) * 0.5
tm = out[oi].get("tm")
if isinstance(tm, dict):
for key in ("a0", "a2"):
vec = tm.get(key)
if isinstance(vec, list) and len(vec) >= 3:
tm[key] = [float(vec[0]) * 0.5, float(vec[1]) * 0.5, float(vec[2]) * 0.5]
return out
# Correct a single oversized-outlier cap, regardless of geometry source.
return _halve_outlier_capture_area(out)
def _capture_areas_from_zone_geometry(zone_geometry: dict | None) -> list[dict]:
@@ -1107,7 +1124,7 @@ def _capture_areas_from_zone_geometry(zone_geometry: dict | None) -> list[dict]:
"radius": radius,
"tm": None,
})
return out
return _halve_outlier_capture_area(out)
def _world_to_map_px(x: float, z: float, x0: float, z0: float, xr: float, zr: float, canvas: int) -> tuple[int, int]:
@@ -3727,6 +3744,7 @@ def export_replay_json(replay_path: Path) -> dict:
map_coords = None
full_map_level = None
mc0 = mc1 = None
if level_data:
try:
mc0, mc1, _ = select_map_coords(level_data)