# -*- coding: utf-8 -*- # 맵마다 새 소품(FRProp_)이 모인 자리를 골라 촬영 자리 목록을 만든다 — 빌더가 남긴 소품 기록(_props.json)을 읽는다. # python shot_spots.py <맵 이름> [자리 수] → 한 줄에 "번호 x z 가까운 새 소품들" # 숲(로비) 맵은 이름을 Forest 로 주면 Logs/bt_forest_props.txt 에서 읽는다. import io, json, math, os, re, sys root = r"C:\BurningTimes\FirstRising" name = sys.argv[1] want = int(sys.argv[2]) if len(sys.argv) > 2 else 5 pts = [] if name == "Forest": for line in io.open(os.path.join(root, "Logs", "bt_forest_props.txt"), encoding="utf-8"): m = re.match(r"\s+(\w+) \((-?[\d.]+), (-?[\d.]+)\) 높이", line) if m: pts.append((m.group(1), float(m.group(2)), float(m.group(3)))) else: rec = json.loads(io.open(os.path.join(root, "Logs", "bt_map_%s_props.json" % name.lower()), encoding="utf-8-sig").read()) items = (rec.get("props") or rec.get("items")) if isinstance(rec, dict) else rec for it in items: if it["name"].startswith("FRProp_"): pts.append((it["name"].split("_", 2)[2], it["x"], it["z"])) left = list(pts) out = [] while left and len(out) < want: # 둘레 9 m 안에 새 소품이 가장 많은 것을 고른다 best, score = None, -1 for p in left: near = [q for q in left if math.hypot(q[1] - p[1], q[2] - p[2]) < 9.0] kinds = len({q[0] for q in near}) s = len(near) + kinds * 1.5 if s > score: best, score = p, s near = [q for q in left if math.hypot(q[1] - best[1], q[2] - best[2]) < 9.0] cx = sum(q[1] for q in near) / len(near) cz = sum(q[2] for q in near) / len(near) # 카메라는 +z 쪽에서 내려다본다 — 소품이 화면 가운데보다 조금 위에 오게 선 자리를 +z 로 2.5 m 당긴다 out.append((cx, cz + 2.5, sorted({q[0] for q in near}))) left = [q for q in left if math.hypot(q[1] - cx, q[2] - cz) >= 16.0] for i, (x, z, names) in enumerate(out): print("%d %.1f %.1f %s" % (i + 1, x, z, ",".join(names)))