- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
67 lines
2.8 KiB
GDScript
67 lines
2.8 KiB
GDScript
# motion_event_payload_test —— native .msa event dictionary parity.
|
|
# 40250 RaceMotionDataEvent payloads must survive the native parser all the
|
|
# way to motion_event_detailed/get_events before any visual routing is added.
|
|
extends SceneTree
|
|
|
|
const AssetRoot = preload("res://asset_root.gd")
|
|
var failures := 0
|
|
|
|
func check(ok: bool, label: String) -> void:
|
|
if not ok:
|
|
failures += 1
|
|
printerr("FAIL: " + label)
|
|
|
|
func _init() -> void:
|
|
call_deferred("run")
|
|
|
|
func run() -> void:
|
|
if not ClassDB.class_exists("Metin2AnimPlayer"):
|
|
print("motion_event_payload_test: skipped (native extension unavailable)")
|
|
quit(0)
|
|
return
|
|
var assets := AssetRoot.path()
|
|
await _test_asset(assets.path_join("PC/ymir work/pc/warrior/skill/daejin_2.msa"), 2, 2.0)
|
|
await _test_asset(assets.path_join("PC/ymir work/pc/warrior/skill/gihyeol.msa"), 4, 2.0)
|
|
await _test_asset(assets.path_join("PC/ymir work/pc/warrior/skill/geompung.msa"), 6, 1.4)
|
|
await _test_asset(assets.path_join("PC/ymir work/pc/assassin/skill/gungsin_3.msa"), 7, 1.5)
|
|
if failures == 0:
|
|
print("PASS: motion_event_payload_test")
|
|
else:
|
|
printerr("motion_event_payload_test: %d failure(s)" % failures)
|
|
quit(1 if failures else 0)
|
|
|
|
func _test_asset(path: String, expected_type: int, expected_duration: float) -> void:
|
|
if not FileAccess.file_exists(path):
|
|
check(false, "reference asset exists: %s" % path)
|
|
return
|
|
var anim: Node = ClassDB.instantiate("Metin2AnimPlayer")
|
|
get_root().add_child(anim)
|
|
anim.set("anim_path", path)
|
|
await process_frame
|
|
var events: Array = anim.call("get_events")
|
|
var motion_data: Dictionary = anim.call("get_motion_data")
|
|
check(is_equal_approx(float(motion_data.get("duration", 0.0)), expected_duration),
|
|
"%s uses MSA MotionDuration %.3f as motion timing" % [path.get_file(), expected_duration])
|
|
var found: Dictionary = {}
|
|
for event in events:
|
|
if event is Dictionary:
|
|
found[int(event.get("type", -1))] = event
|
|
check(found.has(expected_type), "%s exposes type %d" % [path.get_file(), expected_type])
|
|
if found.has(2):
|
|
var wave: Dictionary = found[2]
|
|
check(wave.has("duration_time") and wave.has("power") and wave.has("affecting_range"),
|
|
"SCREEN_WAVING keeps DuringTime/Power/AffectingRange")
|
|
if found.has(4):
|
|
var attack: Dictionary = found[4]
|
|
check(attack.has("enable_hit_process") and attack.has("collision_spheres") and
|
|
attack.collision_spheres.size() > 0, "SPECIAL_ATTACKING keeps collision spheres")
|
|
if found.has(6):
|
|
var fly: Dictionary = found[6]
|
|
check(String(fly.get("fly_file", "")).to_lower().ends_with(".msf") and
|
|
fly.has("fly_pos") and fly.has("fly_bone"),
|
|
"FLY keeps FlyFileName/FlyPosition/bone")
|
|
if found.has(7):
|
|
check(found[7].has("duration_time") and found[7].has("collision_spheres"),
|
|
"no-payload event types retain a stable detailed dictionary")
|
|
anim.free()
|