- 连击类型由 combo_changed 驱动(SetComboSkillFlag,技能 122 等级) - 命中判定改为 .msa 刀尖 Z 圆柱 vs .msm 防御球(hit_collision.gd 逐行移植) - _register_hit 改为 map::insert 语义,修正命中上限 - 攻速同时缩放 GetAttackingElapsedTime 与攻击动作速率;按武器动作模式目录绑定攻击段 - 去掉本地连击超时,motion_bound 清命中表 / 连击段号 - __ProcessDataAttackSuccess:InsertDelay 硬直、physics_push.gd 击退 + GetBlendingPosition 同步、 命中特效、__HitGood / __HitGreate / __HitStone 受击动作链与抖动(ui/hit_reaction.gd) - ClassicSession::send_use_skill 不再夹带 CG_FLY_TARGETING - mac 前进 / 后退方向与技能释放修复;武器按职业骨骼挂到手上 - 新增 hit_collision / physics_push / hit_view / net_world_push / weapon_attach 测试; gpu_pose_bounds / race_motion_assembly 适配 damage 随机变体 - 文档:CLIENT-GAP.md、CLIENT-GAP-FIX.md §3.5 / §3.7 与 C.5 增量 130 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ft3kXpNdLbKEfg5uDLfqVF
73 lines
3.0 KiB
GDScript
73 lines
3.0 KiB
GDScript
# physics_push_test —— §3.7:受击击退物理(GameLib/PhysicsObject.cpp CPhysicsObject +
|
||
# MapUtil.cpp CEaseOutInterpolation)headless 自检。
|
||
# godot --headless --path project --script physics_push_test.gd
|
||
extends SceneTree
|
||
|
||
const PhysicsPush = preload("res://physics_push.gd")
|
||
|
||
var _fail := 0
|
||
func _ck(c: bool, m: String) -> void:
|
||
if not c:
|
||
_fail += 1
|
||
printerr("FAIL: " + m)
|
||
|
||
func _init() -> void:
|
||
_run()
|
||
if _fail == 0:
|
||
print("PASS: physics_push_test (external force / friction / ease-out blend)")
|
||
quit(0)
|
||
else:
|
||
printerr("%d check(s) failed" % _fail)
|
||
quit(1)
|
||
|
||
func _run() -> void:
|
||
# 初始:不在 blending,每帧位移 0
|
||
var p := PhysicsPush.new()
|
||
_ck(not p.is_blending(), "fresh object -> not blending")
|
||
p.update(0.02)
|
||
_ck(p.get_movement() == Vector2.ZERO, "fresh object -> zero movement")
|
||
|
||
# IncreaseExternalForce(F=3, dir +X):vel 3 -> 每步摩擦 0.3,累计 2.7+2.4+…+0.3 = 13.5 cm
|
||
p.set_direction(Vector2(1, 0))
|
||
p.increase_external_force(3.0)
|
||
_ck(absf(p.get_last_position().x - 13.5) < 0.001 and absf(p.get_last_position().y) < 0.001,
|
||
"F=3 along +X -> last position (13.5, 0), got %s" % p.get_last_position())
|
||
_ck(p.is_blending(), "after push -> blending (ease-out playing)")
|
||
|
||
# 逐帧 AddMovement(GetXMovement, GetYMovement):2 秒 ease-out 累计 ≈ 13.5(离散 Euler 少 1/N)
|
||
var sum := Vector2.ZERO
|
||
var frames := 0
|
||
while p.is_blending() and frames < 1000:
|
||
p.update(0.02)
|
||
sum += p.get_movement()
|
||
frames += 1
|
||
_ck(frames >= 99 and frames <= 101, "blend lasts LoopValue*c_fFrameTime = 2s, got %d frames" % frames)
|
||
_ck(absf(sum.x - 13.5) < 0.3 and absf(sum.y) < 0.001, "ease-out total movement ≈ 13.5, got %s" % sum)
|
||
p.update(0.02)
|
||
_ck(p.get_movement() == Vector2.ZERO, "blend done -> movement 0")
|
||
|
||
# 斜向:分量各自摩擦,13.5 * cos45
|
||
var q := PhysicsPush.new()
|
||
q.set_direction(Vector2(1, 1).normalized())
|
||
q.increase_external_force(3.0)
|
||
_ck(absf(q.get_last_position().x - 13.5 * 0.70710678) < 0.01 and absf(q.get_last_position().y - 13.5 * 0.70710678) < 0.01,
|
||
"diagonal push -> per-axis 9.546, got %s" % q.get_last_position())
|
||
|
||
# 分量 vel*dir < EPSILON(0.001) 当步清零(3*0.01*0.01 = 3e-4)
|
||
var w := PhysicsPush.new()
|
||
w.set_direction(Vector2(0.99995, 0.01))
|
||
w.increase_external_force(3.0)
|
||
_ck(w.get_last_position().y == 0.0, "tiny axis component zeroed on first step, got %s" % w.get_last_position())
|
||
|
||
# 力为 0:没有位移,也不 blending(Setup(0,0,2) 仍在播放 -> isBlending 为真,与参考端一致)
|
||
var z := PhysicsPush.new()
|
||
z.set_direction(Vector2(1, 0))
|
||
z.increase_external_force(0.0)
|
||
_ck(z.get_last_position() == Vector2.ZERO, "zero force -> no movement")
|
||
|
||
# 撞墙(IPhysicsWorld::isPhysicalCollision 为真)-> Initialize(),不推
|
||
var c := PhysicsPush.new()
|
||
c.set_direction(Vector2(1, 0))
|
||
c.increase_external_force(3.0, func(_moved: Vector2) -> bool: return true)
|
||
_ck(c.get_last_position() == Vector2.ZERO and not c.is_blending(), "world collision -> Initialize, no push")
|