- 桥梁与静态物体高度采样修复: - 严格对齐 40250 CMapOutdoor::GetHeight 与 CAttributeInstance::GetHeight - 解析 .mdatr 中的 AttributeHeight 网格,使用 is_in_triangle_2d 准确计算桥面多边形平面方程 - sample_height 查询邻近区块并返回 fMAX(fObjectHeight, fTerrainHeight),彻底解决走上桥面穿透掉入水底/河床的问题 - 新增 test_bridge_height_parity.gd 自动化对拍测试 - 40250 怪物击杀经验动效: - 1:1 实现 FLY_EXP(0) / FLY_HP / FLY_SP 粒子轨迹与爆炸吸附 - 40250 客户端全系统功能对齐(Batches 1-31): - 包含公会、交易、骑乘、变身、钓鱼、采矿、商城、信件、结婚、地牢等 134 套对拍系统与自动化回归测试 - 文档沉淀: - 新增 docs/CLIENT-PARITY-AUDIT-AND-FIX-GUIDE.md 客户端对拍缺陷发现与修复工程指南
106 lines
2.9 KiB
GDScript
106 lines
2.9 KiB
GDScript
# test_minimap_radar_parity.gd —— 小地图雷达与坐标系统 1:1 回归测试套件
|
|
# 运行方式:
|
|
# /opt/homebrew/bin/godot --headless --path metin2-client/project --script test_minimap_radar_parity.gd
|
|
extends SceneTree
|
|
|
|
const Minimap = preload("res://ui/minimap.gd")
|
|
|
|
class MockPlayer extends Node3D:
|
|
pass
|
|
|
|
class MockClient extends Node:
|
|
signal channel_changed(c: int)
|
|
signal observer_event(ev: Dictionary)
|
|
signal world_reset
|
|
|
|
var _passed := 0
|
|
var _failed := 0
|
|
|
|
func _assert(cond: bool, msg: String) -> void:
|
|
if cond:
|
|
_passed += 1
|
|
print(" [PASS] %s" % msg)
|
|
else:
|
|
_failed += 1
|
|
printerr(" [FAIL] %s" % msg)
|
|
|
|
func _init() -> void:
|
|
print("\n=== Running test_minimap_radar_parity (Direction 3: Minimap & Coordinates 1:1) ===")
|
|
_test_minimap_coordinates()
|
|
_test_zoom_buttons()
|
|
_test_atlas_button()
|
|
_finish()
|
|
|
|
func _test_minimap_coordinates() -> void:
|
|
print("\n--- Test 1: Real-time (X, Y) Coordinates Display ---")
|
|
var client := MockClient.new()
|
|
get_root().add_child(client)
|
|
|
|
var player := MockPlayer.new()
|
|
get_root().add_child(player)
|
|
player.position = Vector3(150.8, 5.0, -320.4)
|
|
|
|
var mm := Minimap.new()
|
|
get_root().add_child(mm)
|
|
mm.setup(client, get_root(), func(): return player)
|
|
|
|
# Trigger process update
|
|
mm._process(0.016)
|
|
_assert(mm._coord_label != null, "_coord_label exists")
|
|
_assert(mm._coord_label.text == "(150, 320)", "Coordinates label correctly displays (150, 320)")
|
|
|
|
# Move player to (500, -800)
|
|
player.position = Vector3(500.0, 0.0, -800.0)
|
|
mm._process(0.016)
|
|
_assert(mm._coord_label.text == "(500, 800)", "Coordinates updated to (500, 800)")
|
|
|
|
mm.queue_free()
|
|
player.queue_free()
|
|
client.queue_free()
|
|
|
|
func _test_zoom_buttons() -> void:
|
|
print("\n--- Test 2: ScaleUp / ScaleDown Buttons ---")
|
|
var client := MockClient.new()
|
|
get_root().add_child(client)
|
|
|
|
var mm := Minimap.new()
|
|
get_root().add_child(mm)
|
|
mm.setup(client, get_root(), func(): return null)
|
|
|
|
var initial_scale := mm.get_scale()
|
|
mm._btn_zoom_in.pressed.emit()
|
|
_assert(mm.get_scale() > initial_scale, "Zoom in button increases scale")
|
|
|
|
mm._btn_zoom_out.pressed.emit()
|
|
_assert(absf(mm.get_scale() - initial_scale) < 0.001, "Zoom out button decreases scale back")
|
|
|
|
mm.queue_free()
|
|
client.queue_free()
|
|
|
|
func _test_atlas_button() -> void:
|
|
print("\n--- Test 3: Atlas (M) Button ---")
|
|
var client := MockClient.new()
|
|
get_root().add_child(client)
|
|
|
|
var mm := Minimap.new()
|
|
get_root().add_child(mm)
|
|
mm.setup(client, get_root(), func(): return null)
|
|
|
|
var state := {"clicked": false}
|
|
mm.map_pressed.connect(func(): state["clicked"] = true)
|
|
|
|
mm._btn_atlas.pressed.emit()
|
|
_assert(state["clicked"] == true, "Atlas button click emits map_pressed signal")
|
|
|
|
mm.queue_free()
|
|
client.queue_free()
|
|
|
|
func _finish() -> void:
|
|
print("\n=== SUMMARY: %d passed, %d failed ===" % [_passed, _failed])
|
|
if _failed == 0:
|
|
print("ALL TESTS PASSED!\n")
|
|
quit(0)
|
|
else:
|
|
printerr("SOME TESTS FAILED!\n")
|
|
quit(1)
|