NEON-29: fix step assist guard and lift for flat-faced terrace steps

_try_walk_step_assist compared goal surface Y to the capsule centre
(~0.9 m above floor) instead of the actual capsule bottom, disabling
the assist for any surface below ~0.925 m — every terrace we added.
The lift formula used offsets 0.45/0.55 instead of the full capsule
total half-height (CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS = 0.9),
producing zero/negative lift.

Fix: guard uses actual_feet_y = pos.y - CAPSULE_HALF_HEIGHT - PLAYER_CAPSULE_RADIUS;
lift targets goal.y + total_half_height via clampf. Flat floor clicks
and cylinder bumps are unaffected (guard still disabled when goal.y is
at or below true feet level).
pull/41/head
VinPropane 2026-04-11 19:21:37 -04:00
parent 5d91ea4e17
commit 382e662f1d
2 changed files with 11 additions and 3 deletions

View File

@ -154,7 +154,13 @@ func _step_assist_can_raise_by(dy: float) -> bool:
func _try_walk_step_assist() -> bool:
if not _has_walk_goal or _auth_walk_goal.y < global_position.y + 0.025:
if not _has_walk_goal:
return false
# Use actual capsule bottom (cylindrical half-height + hemisphere radius) so the guard
# triggers whenever the goal surface is meaningfully above the player's feet — not the
# capsule centre, which sits ~0.9 m above the floor.
var actual_feet_y: float = global_position.y - CAPSULE_HALF_HEIGHT - PLAYER_CAPSULE_RADIUS
if _auth_walk_goal.y < actual_feet_y + 0.025:
return false
if not _step_assist_has_support():
return false
@ -166,8 +172,9 @@ func _try_walk_step_assist() -> bool:
var vel_h: Vector3 = Vector3(velocity.x, 0.0, velocity.z)
if not _step_assist_wallish_blocks(want) or vel_h.dot(want) > WALK_STEP_ASSIST_MAX_FORWARD_DOT:
return false
var lift: float = minf(WALK_STEP_ASSIST_DELTA, _auth_walk_goal.y - global_position.y + 0.45)
lift = minf(lift, maxf(0.0, _auth_walk_goal.y + 0.55 - global_position.y))
# Target capsule centre once standing on the goal surface.
var target_center_y: float = _auth_walk_goal.y + CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS
var lift: float = clampf(target_center_y - global_position.y, 0.0, WALK_STEP_ASSIST_DELTA)
if lift <= 0.002 or not _step_assist_can_raise_by(lift):
return false
global_position.y += lift

View File

@ -105,6 +105,7 @@ No new automated GDScript tests are added for this story — there is no new GDS
## Decisions
- **No horizontal step limit (resolved):** The server's `MaxHorizontalStep = 18 m` was too restrictive for the expanded 45 × 45 m floor (diagonal ≈ 63 m). Added `HorizontalStepEnabled` bool to `MovementValidationOptions` (defaults `false`), matching the `DistrictBoundsEnabled` pattern. The horizontal check is now skipped by default; the property remains available to opt back in via config. `MoveRejectFarPad` no longer exercises a horizontal range reject; it retains its walkable surface for vertical-step regression only.
- **Step assist guard/lift bug fixed (resolved):** `_try_walk_step_assist` in `player.gd` compared the goal's surface Y against the **capsule centre** (`global_position.y ≈ 0.9`) instead of the actual capsule bottom (`global_position.y CAPSULE_HALF_HEIGHT PLAYER_CAPSULE_RADIUS = 0.0`). This disabled the assist for any surface below ≈ 0.925 m — including all three terrace platforms. The lift formula used offsets of 0.45/0.55 instead of the full total half-height (0.9), giving zero or negative lift. Fixed: guard now uses `actual_feet_y`; lift targets `goal.y + CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS` via `clampf`.
## Open questions / risks