66 lines
2.2 KiB
Python
66 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Render every classic dungeon's webp with AtlasLoot boss coords overlaid as
|
|
red rings, side-by-side with the bare texture. Output to /tmp/alignment/ for
|
|
human review.
|
|
"""
|
|
from __future__ import annotations
|
|
import json
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
from PIL import Image, ImageDraw
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
WEB_MAPS = ROOT / "web" / "assets" / "maps"
|
|
DUNGEONS_JSON = ROOT / "web" / "assets" / "dungeons.json"
|
|
OUT_DIR = Path("/tmp/alignment")
|
|
|
|
|
|
def main() -> int:
|
|
if not DUNGEONS_JSON.exists():
|
|
print("dungeons.json missing, run build_data.py first", file=sys.stderr)
|
|
return 1
|
|
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
|
|
|
data = json.loads(DUNGEONS_JSON.read_text())
|
|
rendered = []
|
|
for d in data["dungeons"]:
|
|
if d.get("expansion") != "OriginalWoW":
|
|
continue
|
|
# Use bosses from the first map (single-floor) or unassignedBosses (multi)
|
|
bosses = d["maps"][0]["bosses"] if d["maps"] and d["maps"][0]["bosses"] else d.get("unassignedBosses", [])
|
|
if not d["maps"]:
|
|
continue
|
|
# Pick the first map for the alignment check
|
|
m = d["maps"][0]
|
|
src = WEB_MAPS / Path(m["image"]).name
|
|
if not src.exists():
|
|
continue
|
|
|
|
with Image.open(src) as im:
|
|
im = im.convert("RGBA")
|
|
W, H = im.size
|
|
draw = ImageDraw.Draw(im)
|
|
for b in bosses:
|
|
px = int((b["x"] / 100) * W)
|
|
py = int((b["y"] / 100) * H)
|
|
r = 80
|
|
draw.ellipse([px - r, py - r, px + r, py + r], outline="red", width=14)
|
|
draw.ellipse([px - 4, py - 4, px + 4, py + 4], fill="red")
|
|
# Scale down for review
|
|
scale = 1024 / W
|
|
im_small = im.resize((1024, int(H * scale)), Image.LANCZOS)
|
|
out = OUT_DIR / f"{d['id']}.png"
|
|
im_small.save(out)
|
|
rendered.append((d["id"], d["name"], len(bosses), out))
|
|
|
|
print(f"Rendered {len(rendered)} dungeons → {OUT_DIR}")
|
|
for did, name, n, p in rendered:
|
|
print(f" {did:30s} {n:>2d} bosses → {p.name}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|