Files
mtgodot-poc/project/physics_push.gd
T
shenleiandClaude Opus 5 1933a5ceda fix(combat): 战斗逐项对齐 40250,修复移动 / 技能释放与武器挂点
- 连击类型由 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
2026-09-12 13:15:28 +09:00

130 lines
3.8 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PhysicsPush —— CLIENT-GAP §3.7:受击击退,逐行移植 GameLib/PhysicsObject.cpp `CPhysicsObject`
# + GameLib/MapUtil.cpp `CEaseOutInterpolation`。单位 = Metin2 cm(平面 x / y)。
# __PushCircle -> set_direction(normalize(victim - attacker))
# IncreaseExternalForce(base, fExternalForce) -> increase_external_force(force[, collides])
# PhysicsProcessupdate(dt) 后 AddMovement(get_movement())
extends RefCounted
const FRAME_TIME := 0.02 # c_fFrameTime
const EPSILON := 0.001
const LOOP_VALUE := 100
const FLT_EPSILON := 1.192092896e-07
class EaseOut:
var remaining := 0.0
var value := 0.0
var speed := 0.0
var acceleration := 0.0
var start_value := 0.0
var last_value := 0.0
func initialize() -> void:
remaining = 0.0
value = 0.0
speed = 0.0
acceleration = 0.0
start_value = 0.0
last_value = 0.0
func setup(f_start: float, f_end: float, f_time: float) -> void:
if absf(f_time) < FLT_EPSILON:
f_time = 0.01
value = f_start
start_value = f_start
last_value = f_start
speed = (2.0 * (f_end - f_start)) / f_time
acceleration = 2.0 * (f_end - f_start) / (f_time * f_time) - 2.0 * speed / f_time
remaining = f_time
func interpolate(dt: float) -> void:
last_value = value
remaining -= dt
speed += acceleration * dt
value += speed * dt
if not is_playing():
value = 0.0
last_value = 0.0
func is_playing() -> bool:
return remaining > 0.0
func changing_value() -> float:
return value - last_value
var mass := 1.0
var friction := 0.3
var direction := Vector3.ZERO
var acceleration := Vector3.ZERO
var velocity := Vector3.ZERO
var last_position := Vector3.ZERO
var _x := EaseOut.new()
var _y := EaseOut.new()
func initialize() -> void:
mass = 1.0
friction = 0.3
direction = Vector3.ZERO
acceleration = Vector3.ZERO
velocity = Vector3.ZERO
last_position = Vector3.ZERO
_x.initialize()
_y.initialize()
func set_direction(dir: Vector2) -> void:
direction = Vector3(dir.x, dir.y, 0.0)
func update(dt: float) -> void:
if _x.is_playing():
_x.interpolate(dt)
if _y.is_playing():
_y.interpolate(dt)
func _accumulate(pos: Vector3) -> Vector3:
var force := 0.0
if absf(velocity.x) < EPSILON or absf(velocity.y) < EPSILON or absf(velocity.z) < EPSILON:
force -= mass * friction
acceleration = direction * (force / mass)
velocity += acceleration
if velocity.x * direction.x < EPSILON:
velocity.x = 0.0
direction.x = 0.0
if velocity.y * direction.y < EPSILON:
velocity.y = 0.0
direction.y = 0.0
if velocity.z * direction.z < EPSILON:
velocity.z = 0.0
direction.z = 0.0
return pos + velocity
# collides(movement: Vector2) -> bool 对应 IPhysicsWorld::isPhysicalCollision(base + movement)
# 空 Callable = 没有物理世界(参考端 pWorld == NULL 分支)。
func increase_external_force(force: float, collides := Callable()) -> void:
acceleration = direction * (force / mass)
velocity = acceleration
var movement := Vector3.ZERO
for i in LOOP_VALUE:
movement = _accumulate(movement)
if collides.is_valid() and bool(collides.call(Vector2(movement.x, movement.y))):
initialize()
return
if absf(velocity.x) < EPSILON and absf(velocity.y) < EPSILON and absf(velocity.z) < EPSILON:
break
set_last_position(Vector2(movement.x, movement.y), float(LOOP_VALUE) * FRAME_TIME)
func set_last_position(p: Vector2, blending_time: float) -> void:
last_position = Vector3(p.x, p.y, 0.0)
_x.setup(0.0, p.x, blending_time)
_y.setup(0.0, p.y, blending_time)
func get_last_position() -> Vector2:
return Vector2(last_position.x, last_position.y)
# GetXMovement / GetYMovement:本帧 ease-out 增量。
func get_movement() -> Vector2:
return Vector2(_x.changing_value(), _y.changing_value())
func is_blending() -> bool:
if velocity.length() != 0.0:
return true
return _x.is_playing() or _y.is_playing()