meow (#1344)
This commit is contained in:
+40
-22
@@ -999,6 +999,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.
|
||||
"""
|
||||
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)."""
|
||||
@@ -1086,27 +1122,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]:
|
||||
@@ -1144,7 +1161,7 @@ def _capture_areas_from_zone_geometry(zone_geometry: dict | None) -> list[dict]:
|
||||
"zone_letter": letter,
|
||||
"tm": tm,
|
||||
})
|
||||
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]:
|
||||
@@ -4165,6 +4182,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)
|
||||
|
||||
Reference in New Issue
Block a user