- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
91 lines
3.3 KiB
GDScript
91 lines
3.3 KiB
GDScript
# fly_attachment_effect_test —— 40250 BuildAttachInstance/UpdateAttachInstance/
|
|
# __Bomb 的资源消费和 FlyTrace 回归。
|
|
extends SceneTree
|
|
|
|
const AssetRoot = preload("res://asset_root.gd")
|
|
const EffectRegistry = preload("res://fx/effect_registry.gd")
|
|
const FlyObject = preload("res://fly_object.gd")
|
|
|
|
var _failures := 0
|
|
|
|
func _ck(condition: bool, message: String) -> void:
|
|
if condition:
|
|
return
|
|
_failures += 1
|
|
printerr("FAIL: ", message)
|
|
|
|
func _init() -> void:
|
|
await _run()
|
|
quit(1 if _failures else 0)
|
|
|
|
func _run() -> void:
|
|
await process_frame
|
|
var assets := AssetRoot.path()
|
|
var registry = EffectRegistry.new()
|
|
registry.setup(assets)
|
|
var spawned_effects: Array[String] = []
|
|
registry.fx_spawned.connect(func(name: String, _id: int, _lifetime: int): spawned_effects.append(name))
|
|
|
|
var mount := Node3D.new()
|
|
get_root().add_child(mount)
|
|
var geometry_probe = FlyObject.FlyInstance.new()
|
|
geometry_probe.pos = Vector3.ZERO
|
|
geometry_probe.vel = Vector3(0.0, -1.0, 0.0)
|
|
var multi_line := {"fly_type": 2, "distance": 1.0, "roll": 0.0}
|
|
_ck(is_equal_approx(geometry_probe._attachment_position(multi_line).z, -1.0),
|
|
"AttachData MULTI_LINE keeps 40250's negative local Z offset")
|
|
var manager := FlyObject.new()
|
|
manager.manual_step = true
|
|
mount.add_child(manager)
|
|
manager.setup(mount, null, assets)
|
|
manager.set_effect_registry(registry)
|
|
|
|
var target := Node3D.new()
|
|
target.position = Vector3(5.0, 0.0, 0.0)
|
|
mount.add_child(target)
|
|
await process_frame
|
|
|
|
var data = FlyObject.FlyData.load_msf(
|
|
"d:/ymir work/pc/assassin/effect/arrow_01_fast.msf", assets)
|
|
_ck(data != null, "arrow_01_fast.msf loads")
|
|
if data != null:
|
|
_ck(data.attach_data.size() == 1, "arrow resource keeps one AttachData group")
|
|
var inst = manager.spawn(Vector3.ZERO, target, false, data)
|
|
_ck(inst.attachments.size() == 1, "BuildAttachInstance creates one attachment")
|
|
if inst.attachments.size() == 1:
|
|
var attachment: Dictionary = inst.attachments[0]
|
|
_ck(is_instance_valid(attachment.get("effect", null)),
|
|
"AttachFile is instantiated through EffectRegistry")
|
|
_ck(is_instance_valid(attachment.get("tail", null)),
|
|
"TailFlag creates a FlyTrace mesh")
|
|
_ck(manager._visuals.get(inst, null) == null,
|
|
"resource-driven projectile does not duplicate a generic SphereMesh")
|
|
manager.step(0.01)
|
|
if inst.attachments.size() == 1:
|
|
var trail_history: Array = inst.attachments[0].get("history", [])
|
|
_ck(trail_history.size() >= 2, "UpdateAttachInstance records moving tail positions")
|
|
|
|
# Arrow reaches the target and must use BombEffect instead of only the
|
|
# generic placeholder flash when EffectRegistry has the source resource.
|
|
for _i in 20:
|
|
if manager.active_count() == 0:
|
|
break
|
|
manager.step(0.05)
|
|
var found_bomb := false
|
|
for effect_name in spawned_effects:
|
|
if String(effect_name).get_file().get_basename() == "blow_1_low_center":
|
|
found_bomb = true
|
|
_ck(found_bomb, "__Bomb consumes arrow BombEffect resource")
|
|
_ck(manager._flash_nodes.is_empty(),
|
|
"resource BombEffect does not receive a duplicate pre-hit flash")
|
|
|
|
manager.clear_for_map_change()
|
|
_ck(manager.active_count() == 0 and manager._effect_nodes.is_empty(),
|
|
"map reset releases resource-driven bomb effects")
|
|
manager.free()
|
|
target.free()
|
|
mount.free()
|
|
await process_frame
|
|
if _failures == 0:
|
|
print("PASS: fly_attachment_effect_test")
|