fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
# fly_dynamic_collision_test —— 40250 FlyingInstance 动态 Actor 碰撞回归。
|
||||
#
|
||||
# 参考 FlyingInstance.cpp::Update:
|
||||
# collision sphere = max(move_distance * 2, configured radius)
|
||||
# hitonanothermonster -> HittedObjectSet 去重 -> OnExplodingAtAnotherTarget
|
||||
# pierce 后继续飞行,耗尽才爆炸。
|
||||
extends SceneTree
|
||||
|
||||
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
|
||||
_test_two_actors_and_pierce()
|
||||
_test_same_actor_is_deduplicated()
|
||||
if _failures == 0:
|
||||
print("PASS: fly_dynamic_collision_test")
|
||||
|
||||
func _new_manager() -> Array:
|
||||
var mount := Node3D.new()
|
||||
get_root().add_child(mount)
|
||||
var manager := FlyObject.new()
|
||||
manager.manual_step = true
|
||||
mount.add_child(manager)
|
||||
manager.setup(mount)
|
||||
return [manager, mount]
|
||||
|
||||
func _test_two_actors_and_pierce() -> void:
|
||||
var fixture := _new_manager()
|
||||
var manager: FlyObject = fixture[0]
|
||||
var mount: Node3D = fixture[1]
|
||||
var first := Node3D.new()
|
||||
first.position = Vector3(0.0, 1.0, 5.0)
|
||||
get_root().add_child(first)
|
||||
var second := Node3D.new()
|
||||
second.position = Vector3(0.0, 1.0, 10.0)
|
||||
get_root().add_child(second)
|
||||
manager.set_actor_provider(func() -> Array:
|
||||
return [
|
||||
{"vid": 200, "node": first, "center": first.position, "radius": 0.35},
|
||||
{"vid": 300, "node": second, "center": second.position, "radius": 0.35},
|
||||
]
|
||||
)
|
||||
|
||||
var events: Array[int] = []
|
||||
var data := FlyObject.FlyData.new()
|
||||
data.init_vel = 10.0
|
||||
data.flat_range = 30.0
|
||||
data.bomb_range = 0.05
|
||||
data.collision_sphere_radius = 0.05
|
||||
data.hit_on_another_monster = true
|
||||
data.pierce_count = 1
|
||||
var inst = manager.spawn(Vector3(0.0, 1.0, 0.0), Vector3(0.0, 1.0, 30.0), false, data)
|
||||
inst.handler = func(event: String, _pos: Vector3, vid: int) -> void:
|
||||
if event == "at_another":
|
||||
events.append(vid)
|
||||
|
||||
for _i in 100:
|
||||
if manager.active_count() == 0:
|
||||
break
|
||||
manager.step(0.1)
|
||||
_ck(events == [200, 300], "pierce projectile hits first and second Actor exactly once")
|
||||
_ck(manager.active_count() == 0, "non-piercing second Actor hit removes projectile")
|
||||
|
||||
manager.clear_for_map_change()
|
||||
first.free()
|
||||
second.free()
|
||||
manager.free()
|
||||
mount.free()
|
||||
|
||||
func _test_same_actor_is_deduplicated() -> void:
|
||||
var fixture := _new_manager()
|
||||
var manager: FlyObject = fixture[0]
|
||||
var mount: Node3D = fixture[1]
|
||||
var target := Node3D.new()
|
||||
target.position = Vector3(0.0, 1.0, 5.0)
|
||||
get_root().add_child(target)
|
||||
manager.set_actor_provider(func() -> Array:
|
||||
return [{"vid": 400, "node": target, "center": target.position, "radius": 0.35}]
|
||||
)
|
||||
|
||||
var events: Array[int] = []
|
||||
var data := FlyObject.FlyData.new()
|
||||
data.init_vel = 10.0
|
||||
data.flat_range = 12.0
|
||||
data.bomb_range = 0.05
|
||||
data.collision_sphere_radius = 0.05
|
||||
data.hit_on_another_monster = true
|
||||
data.pierce_count = 2
|
||||
var inst = manager.spawn(Vector3(0.0, 1.0, 0.0), Vector3(0.0, 1.0, 30.0), false, data)
|
||||
inst.handler = func(event: String, _pos: Vector3, vid: int) -> void:
|
||||
if event == "at_another":
|
||||
events.append(vid)
|
||||
|
||||
for _i in 100:
|
||||
if manager.active_count() == 0:
|
||||
break
|
||||
manager.step(0.1)
|
||||
_ck(events == [400], "same dynamic Actor is blocked by HittedObjectSet")
|
||||
_ck(manager.active_count() == 0, "deduplicated projectile eventually expires")
|
||||
|
||||
manager.clear_for_map_change()
|
||||
target.free()
|
||||
manager.free()
|
||||
mount.free()
|
||||
Reference in New Issue
Block a user