NEON-29: Freeze horizontal velocity on column tread wobble band.

When vlat&&ncol, XZ within ~0.92*ARRIVE_EPS, and vert_sep in a narrow band
above vertical-arrival noise, zero XZ velocity so nav slide cannot drive ~6 cm
Y oscillation on violet stairs. Descending fallback when column latch is off;
skip when goal is above feet (climb still needs XZ).
pull/41/head
VinPropane 2026-04-12 19:41:39 -04:00
parent ec903d9c11
commit ea3903d8ab
1 changed files with 28 additions and 0 deletions

View File

@ -38,6 +38,13 @@ const WALK_PEEL_SUSPEND_VERT_SEP: float = 0.48
## so shallow lips (~0.48 m) still peel; widened from 0.34 to cover ~0.350.47 m stair/goal gaps.
const WALK_PEEL_SUSPEND_HORIZ_VERT_SEP: float = 0.46
const WALK_PEEL_SUSPEND_HORIZ_DIST: float = 5.0
## In [code]vlat && ncol[/code], when XZ is almost at arrival but [code]vert_sep[/code] sits in a tread
## wobble band (~4.513 cm), full [member MOVE_SPEED] slide keeps pumping Y (NEON-16 ~0.890.95). Zero
## horizontal [member velocity] for that tick so only floor snap settles height — narrow gates avoid
## freezing open-floor approaches or long vertical offsets.
const WALK_TREAD_FREEZE_HORIZ_FRAC: float = 0.92
const WALK_TREAD_FREEZE_VERT_SEP_MIN: float = 0.045
const WALK_TREAD_FREEZE_VERT_SEP_MAX: float = 0.13
## [method _walk_has_close_floor_probe_below] often flips on stairs: next tread is ~0.104 m down but
## [member WALK_CONTINUATION_MAX_BELOW_FEET] is 0.078 m, so rays reject the hit → peel + zero snap
## alternate with full snap each tick (~y≈1.0 jitter). Require this many consecutive probe-fail frames
@ -495,6 +502,23 @@ func _walk_peel_suspend_near_goal(feet_y: float, horiz_dist: float) -> bool:
return vsep <= WALK_PEEL_SUSPEND_HORIZ_VERT_SEP and horiz_dist <= WALK_PEEL_SUSPEND_HORIZ_DIST
func _walk_tread_freeze_horizontal_active(feet_y: float, horiz_dist: float) -> bool:
if not is_on_floor() or not _has_walk_goal:
return false
# Step-up / climb still needs XZ motion along the face.
if _auth_walk_goal.y > feet_y + 0.04:
return false
if horiz_dist > ARRIVE_EPS * WALK_TREAD_FREEZE_HORIZ_FRAC:
return false
var vsep: float = absf(_auth_walk_goal.y - feet_y)
if vsep <= WALK_TREAD_FREEZE_VERT_SEP_MIN or vsep > WALK_TREAD_FREEZE_VERT_SEP_MAX:
return false
if _walk_vert_route_latched and _walk_nav_column_steering:
return true
# [code]vlat[/code] can unlatch on long descents; keep freeze only when clearly dropping.
return _auth_walk_goal.y < feet_y - DESCEND_GOAL_Y_MARGIN
func _walk_refresh_ledge_peel_debounce(feet_y: float, move_dir_xz: Vector2) -> void:
var probe_ok: bool = _walk_has_close_floor_probe_below(move_dir_xz)
var deep: bool = feet_y > _auth_walk_goal.y + WALK_DEEP_DESCENT_FEET_ABOVE_GOAL
@ -1098,6 +1122,10 @@ func _physics_process(delta: float) -> void:
else:
_set_horizontal_velocity_toward(_auth_walk_goal, want_goal_h)
if _walk_tread_freeze_horizontal_active(feet_y, horiz_dist):
velocity.x = 0.0
velocity.z = 0.0
var walk_move_dir_xz: Vector2 = _resolve_walk_probe_dir_xz(feet_y, want_goal_h)
_walk_refresh_ledge_peel_debounce(feet_y, walk_move_dir_xz)