NEON-29: fix arrival check using actual capsule bottom for vert_err

The vertical arrival error was computed with CAPSULE_HALF_HEIGHT (0.5),
placing code-feet at body_y - 0.5 = 0.4 on a floor-level player.
Step surfaces at Y=0.3 are only 0.1 m away from that reference, and
Jolt can nudge the body down to ~0.8 when the bottom hemisphere contacts
the step edge, making code-feet = 0.3 and vert_err = 0 — triggering
immediate arrival while the player is still at floor level.

Fix: pass CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS (= 0.9) to
vertical_arrival_error so actual feet = body_y - 0.9 = 0.0 on the
floor. Step goals (Y=0.3) now give vert_err=0.3 >> VERT_ARRIVE_EPS,
preventing premature arrival. Arrival fires correctly once the step
assist lifts the player onto the surface (body_y=1.2, err=0).
Add two tests pinning the new pre/post-climb behaviour.
pull/41/head
VinPropane 2026-04-11 19:35:39 -04:00
parent 382e662f1d
commit ef211ab4ac
2 changed files with 33 additions and 1 deletions

View File

@ -491,8 +491,13 @@ func _physics_process(_delta: float) -> void:
var full_to_goal: Vector3 = _auth_walk_goal - global_position
var horiz_dist: float = Vector2(full_to_goal.x, full_to_goal.z).length()
# Use actual capsule bottom (CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS = 0.9) so that a
# step-surface goal (e.g. Y=0.3) is never considered "arrived" while the player is still at
# floor height. Using only CAPSULE_HALF_HEIGHT (0.5) gives code-feet at Y=0.4, which is too
# close to step surfaces and causes premature arrival when Jolt nudges the body down to ~0.8
# while the capsule hemisphere contacts the step edge.
var vert_err: float = vertical_arrival_error(
_auth_walk_goal.y, global_position.y, CAPSULE_HALF_HEIGHT
_auth_walk_goal.y, global_position.y, CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS
)
if horiz_dist <= ARRIVE_EPS and vert_err <= VERT_ARRIVE_EPS:
velocity = Vector3.ZERO

View File

@ -119,6 +119,33 @@ func test_vertical_arrival_error_stays_large_for_origin_height_only_match() -> v
assert_that(absf(err - 0.5)).is_less(0.000001)
func test_arrival_vert_err_large_for_step_goal_from_floor() -> void:
# Player at floor height (body Y=0.9). Goal at step surface (Y=0.3).
# Using actual capsule bottom (CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS) the error
# must exceed VERT_ARRIVE_EPS so the arrival check does NOT fire prematurely.
var goal_y := 0.3
var body_y := 0.9
var full_half: float = (
PLAYER_SCRIPT.get("CAPSULE_HALF_HEIGHT") as float
+ PLAYER_SCRIPT.get("PLAYER_CAPSULE_RADIUS") as float
)
var err: float = PLAYER_SCRIPT.vertical_arrival_error(goal_y, body_y, full_half)
assert_that(err).is_greater(PLAYER_SCRIPT.get("VERT_ARRIVE_EPS") as float)
func test_arrival_vert_err_zero_when_standing_on_step() -> void:
# Player body centred at goal_y + total_half_height (i.e. actually standing on the step).
# Error must be within VERT_ARRIVE_EPS so arrival fires correctly once the player is up.
var goal_y := 0.3
var full_half: float = (
PLAYER_SCRIPT.get("CAPSULE_HALF_HEIGHT") as float
+ PLAYER_SCRIPT.get("PLAYER_CAPSULE_RADIUS") as float
)
var body_y: float = goal_y + full_half
var err: float = PLAYER_SCRIPT.vertical_arrival_error(goal_y, body_y, full_half)
assert_that(err).is_less_equal(PLAYER_SCRIPT.get("VERT_ARRIVE_EPS") as float)
func test_flat_floor_goal_is_not_below_feet_height_margin() -> void:
var goal_y := 0.0
var body_origin_y := 0.4