NEON-29: Faster vertical descent — accel multiplier + peel until feet arrive

Apply PLAYER_VERTICAL_ACCEL_MULTIPLIER (~2.45×) to walk-airborne gravity,
ledge peel integration, and idle-airborne gravity for snappier falls.

Peel used to clear when goal.y >= feet_y - DESCEND_GOAL_Y_MARGIN, which
stopped peeling ~6 cm above the click surface while XZ was already at the
destination — use vertical_arrival_error <= VERT_ARRIVE_EPS instead, with
a small guard when the goal is clearly above the feet (climb).
pull/41/head
VinPropane 2026-04-12 18:44:51 -04:00
parent a78b44263c
commit b924707202
1 changed files with 17 additions and 4 deletions

View File

@ -87,6 +87,9 @@ const WALK_CONTINUATION_MAX_BELOW_FEET: float = 0.14
const WALK_DEEP_DESCENT_FEET_ABOVE_GOAL: float = 0.42
## [method get_gravity] can be ~0 with missing/odd project defaults; ledge peel + airborne walk still need a pull.
const WALK_FALLBACK_GRAVITY_Y: float = -9.81
## Multiplier on project gravity for walk ledge peel, walk-airborne, and idle-airborne — snappier than
## real-world 9.81 m/s² for prototype feel; also offsets move_and_collide step coarseness at 120 Hz.
const PLAYER_VERTICAL_ACCEL_MULTIPLIER: float = 2.45
## CapsuleShape3D in scene: height = 1.0 (cylinder portion), radius = 0.4.
## Total half-height from body origin to physical bottom = 0.5 + 0.4 = 0.9
## (`CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS`).
@ -456,7 +459,7 @@ func _walk_has_close_floor_probe_below(move_dir_xz: Vector2) -> bool:
## velocity does **not** move the body off a terrace lip; use [method _apply_walk_post_slide_ledge_peel].
func _apply_walk_air_gravity(delta: float, _feet_y: float, _move_dir_xz: Vector2 = Vector2.ZERO) -> void:
if not is_on_floor():
velocity += _effective_gravity(delta) * delta
velocity += _player_vertical_accel(delta) * delta
## After [method move_and_slide], peel the capsule down when the authoritative goal is below the feet
@ -471,7 +474,13 @@ func _apply_walk_post_slide_ledge_peel(
if not is_on_floor():
_walk_ledge_peel_vy = 0.0
return
if _auth_walk_goal.y >= feet_y - DESCEND_GOAL_Y_MARGIN:
# Do not use [member DESCEND_GOAL_Y_MARGIN] here: it stopped peel while feet were still ~6 cm above
# the goal surface → slow “float to rest” at XZ destination. Only stop once vertical arrival matches.
var cap_half: float = CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS
if vertical_arrival_error(_auth_walk_goal.y, global_position.y, cap_half) <= VERT_ARRIVE_EPS:
_walk_ledge_peel_vy = 0.0
return
if _auth_walk_goal.y > feet_y + 0.04:
_walk_ledge_peel_vy = 0.0
return
var peel: bool = (
@ -481,7 +490,7 @@ func _apply_walk_post_slide_ledge_peel(
if not peel:
_walk_ledge_peel_vy = 0.0
return
_walk_ledge_peel_vy += _effective_gravity(delta).y * delta
_walk_ledge_peel_vy += _player_vertical_accel(delta).y * delta
var dy: float = _walk_ledge_peel_vy * delta
if absf(dy) > 1e-9:
# Raw [code]global_position[/code] edits can be ignored/overwritten vs Jolt sync after [method move_and_slide].
@ -588,6 +597,10 @@ func _effective_gravity(_delta: float) -> Vector3:
return g
func _player_vertical_accel(_delta: float) -> Vector3:
return _effective_gravity(_delta) * PLAYER_VERTICAL_ACCEL_MULTIPLIER
static func capsule_feet_y(body_origin_y: float, capsule_half_height: float) -> float:
return body_origin_y - capsule_half_height
@ -607,7 +620,7 @@ func _physics_idle_tick(delta: float) -> void:
# cannot reach the lower floor — the capsule idles in mid-air until a new walk goal runs.
velocity.x = 0.0
velocity.z = 0.0
velocity += _effective_gravity(delta) * delta
velocity += _player_vertical_accel(delta) * delta
floor_snap_length = FLOOR_SNAP_MOVING
move_and_slide()