Files
mtgodot-poc/project/test_all_map_height_probe.gd
T

123 lines
5.6 KiB
GDScript

# test_all_map_height_probe.gd
# 严格按照《CLIENT-PARITY-AUDIT-AND-FIX-GUIDE.md》手段 1(全图几何与阻挡坐标探针):
# 自动化探针遍历多个核心地图(OutdoorA1、OutdoorC1 等),全面巡检跨河桥梁、高架栈道与悬索吊桥:
# 1. 验证物体中心及行进跨度内 sample_height 稳定采样到表面高度,不跌入河床裸地形;
# 2. 验证桥面行走通道未被 is_blocked 错误拦截;
# 3. 验证侧向偏离点正确回退到裸地形标高;
# 4. 验证高度数据不存在 NaN / Inf 异常。
extends SceneTree
const ASSETS_PATH := "res://../assets"
func _init() -> void:
call_deferred("_run")
func _run() -> void:
print("=== Starting test_all_map_height_probe (Headless Coordinate Probe Suite) ===")
var fails := [0]
var check = func(cond: bool, msg: String):
if not cond:
fails[0] += 1
printerr("FAIL: ", msg)
else:
print("PASS: ", msg)
if not ClassDB.class_exists("Metin2World"):
printerr("FAIL: Metin2World class not found")
quit(1)
return
var world: Node = ClassDB.instantiate("Metin2World")
get_root().add_child(world)
var assets_abs := ProjectSettings.globalize_path(ASSETS_PATH)
world.set("assets_root", assets_abs)
world.set("objects_enabled", true)
world.set("water_enabled", true)
world.set("load_radius_tiles", -1)
# -------------------------------------------------------------
# 巡检 1: OutdoorA1/metin2_map_a1 跨河石桥与悬索吊桥
# -------------------------------------------------------------
print("\n--- Probing Map 1: OutdoorA1/metin2_map_a1 ---")
world.set("map_path", "OutdoorA1/metin2_map_a1")
var ok: bool = bool(world.call("load_map"))
check.call(ok, "OutdoorA1 load_map succeeded")
if ok:
# 桥梁 1: a1-024-10m-bridge (Chunk 002002)
var b1_x := 761.57
var b1_z := 594.55
var h1: float = float(world.call("sample_height", b1_x, b1_z))
var bl1: bool = bool(world.call("is_blocked", b1_x, b1_z))
print(" A1 Bridge 1 (a1-024-10m-bridge) at (%f, %f): height=%f m, blocked=%s" % [b1_x, b1_z, h1, bl1])
check.call(h1 >= 204.0 and h1 <= 208.0, "Bridge 1 deck elevation in expected range (204m~208m), got %f" % h1)
check.call(not bl1, "Bridge 1 walking lane is NOT blocked (is_blocked == false)")
# 跨桥连续性巡检 (沿 x 轴跨度从 751 到 771)
var span_continuous := true
for dx in range(-10, 11, 2):
var step_x := b1_x + float(dx)
var step_h: float = float(world.call("sample_height", step_x, b1_z))
var step_bl: bool = bool(world.call("is_blocked", step_x, b1_z))
if step_h < 203.0 or step_bl:
span_continuous = false
printerr(" Span defect at x=%f: height=%f (expected >= 203), blocked=%s" % [step_x, step_h, step_bl])
break
check.call(span_continuous, "Bridge 1 walking span maintains elevated deck and walkable status across entire length")
# 桥侧河床自然回退验证
var off_h: float = float(world.call("sample_height", b1_x, 570.0))
check.call(off_h < 200.0, "Off-bridge point correctly samples riverbed terrain (%f m < 200m)" % off_h)
# 桥梁 2: 悬索吊桥 (general_obj_suspension bridge01)
var b2_x := 213.91
var b2_z := 700.45
var h2: float = float(world.call("sample_height", b2_x, b2_z))
var bl2: bool = bool(world.call("is_blocked", b2_x, b2_z))
print(" A1 Bridge 2 (suspension bridge) at (%f, %f): height=%f m, blocked=%s" % [b2_x, b2_z, h2, bl2])
check.call(h2 >= 130.0 and h2 <= 140.0, "Suspension bridge deck in expected range (130m~140m), got %f" % h2)
check.call(not bl2, "Suspension bridge walking deck is NOT blocked")
# -------------------------------------------------------------
# 巡检 2: OutdoorC1/metin2_map_c1 跨河石桥
# -------------------------------------------------------------
print("\n--- Probing Map 2: OutdoorC1/metin2_map_c1 ---")
world.call("unload_map")
world.set("map_path", "OutdoorC1/metin2_map_c1")
var ok_c1: bool = bool(world.call("load_map"))
check.call(ok_c1, "OutdoorC1 load_map succeeded")
if ok_c1:
# C1 跨河石桥: c1-022-10m-bridge (位于 Chunk 001001, areadata pos: 35755.88, -50457.72, 16555.45, bias=-705.0)
var c1_x := 357.56
var c1_z := 504.58
var c1_h: float = float(world.call("sample_height", c1_x, c1_z))
var c1_bl: bool = bool(world.call("is_blocked", c1_x, c1_z))
print(" C1 Bridge (c1-022-10m-bridge) at (%f, %f): height=%f m, blocked=%s" % [c1_x, c1_z, c1_h, c1_bl])
check.call(c1_h >= 170.0 and c1_h <= 180.0, "C1 Bridge deck elevation in expected range (170m~180m), got %f" % c1_h)
check.call(not c1_bl, "C1 Bridge walking lane is NOT blocked")
# 跨桥连续性巡检 (沿 z 轴方向,因为 rot=90度,桥面沿南北走向展开)
var c1_span_continuous := true
for dz in range(-12, 13, 3):
var step_z := c1_z + float(dz)
var step_h: float = float(world.call("sample_height", c1_x, step_z))
var step_bl: bool = bool(world.call("is_blocked", c1_x, step_z))
if step_h < 172.0 or step_bl:
c1_span_continuous = false
printerr(" C1 Span defect at z=%f: height=%f (expected >= 172), blocked=%s" % [step_z, step_h, step_bl])
break
check.call(c1_span_continuous, "C1 Bridge walking span maintains elevated deck across entire span")
# 侧向远离桥梁 15m 的点 (河道): (357.56 - 15.0, 504.58)
var c1_off_x := c1_x - 15.0
var c1_off_h: float = float(world.call("sample_height", c1_off_x, c1_z))
print(" C1 Off-bridge river at (%f, %f): height=%f m (< bridge %f m)" % [c1_off_x, c1_z, c1_off_h, c1_h])
check.call(c1_off_h < c1_h - 1.0, "C1 Off-bridge point drops below bridge deck (%f m < %f m)" % [c1_off_h, c1_h])
world.call("unload_map")
world.queue_free()
print("\n=== All Map Height Probes finished with %d failures ===" % fails[0])
quit(fails[0])