NEON-29: Deep-descent walk gravity bypass for violet deck vs floor goal

Rays and is_on_floor() can still agree the capsule is supported while the
authoritative click is on the main floor far below (TerracePlatformB lip).

When feet are >0.42 m above the goal surface Y, always add walk gravity and
zero moving floor snap. Shorter drops (e.g. gold step to floor) still use
the probe heuristic only.
pull/41/head
VinPropane 2026-04-12 18:31:01 -04:00
parent 91b802c679
commit 55ce6f3e3b
1 changed files with 24 additions and 3 deletions

View File

@ -80,6 +80,11 @@ const WALK_SUPPORT_PROBE_MIN_UP_DOT: float = 0.42
## and reads as “forward support”, so snap + lip [code]is_on_floor()[/code] keep the capsule skating
## at deck height until XZ arrival.
const WALK_CONTINUATION_MAX_BELOW_FEET: float = 0.14
## If capsule feet are farther above the clicks surface Y than this, always use walk gravity + zero
## moving snap (rays can still read “support” while [method CharacterBody3D.is_on_floor] hugs a lip).
## ~0.42 m: **TerracePlatformB** top (~0.6 m) → floor (0) qualifies; **TerraceStepB** (~0.3 m) → floor does
## not — shallow drops still rely on [method _walk_has_close_floor_probe_below].
const WALK_DEEP_DESCENT_FEET_ABOVE_GOAL: float = 0.42
## 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`).
@ -438,8 +443,11 @@ func _walk_has_close_floor_probe_below(move_dir_xz: Vector2) -> bool:
## toward a floor click and poisons horizontal motion / slide resolution.
## Do apply gravity when [code]is_on_floor()[/code] is still true but there is no walkable surface
## within [member WALK_SUPPORT_PROBE_DEPTH] under the foot disk (ledge / void while moving).
## [param feet_y] is [method capsule_feet_y] for the current body origin (see [member CAPSULE_HALF_HEIGHT]).
## [param move_dir_xz] steers multi-sample rays (see [method _walk_probe_xz_offsets]).
func _apply_walk_air_gravity(delta: float, move_dir_xz: Vector2 = Vector2.ZERO) -> void:
func _apply_walk_air_gravity(
delta: float, feet_y: float, move_dir_xz: Vector2 = Vector2.ZERO
) -> void:
var apply_gravity: bool = not is_on_floor()
if (
not apply_gravity
@ -448,6 +456,13 @@ func _apply_walk_air_gravity(delta: float, move_dir_xz: Vector2 = Vector2.ZERO)
and not _walk_has_close_floor_probe_below(move_dir_xz)
):
apply_gravity = true
if (
not apply_gravity
and _has_walk_goal
and is_on_floor()
and feet_y > _auth_walk_goal.y + WALK_DEEP_DESCENT_FEET_ABOVE_GOAL
):
apply_gravity = true
if apply_gravity:
velocity += get_gravity() * delta
@ -459,7 +474,13 @@ func _walk_floor_snap_length(
return WALK_STEP_ASSIST_SNAP
if _has_walk_goal:
# Strong moving snap + lip [code]is_on_floor()[/code] otherwise cancels gravity every tick.
if is_on_floor() and not _walk_has_close_floor_probe_below(move_dir_xz):
if (
is_on_floor()
and (
not _walk_has_close_floor_probe_below(move_dir_xz)
or feet_y > _auth_walk_goal.y + WALK_DEEP_DESCENT_FEET_ABOVE_GOAL
)
):
return 0.0
if want_goal_h.length_squared() > 1e-10:
var want: Vector3 = want_goal_h.normalized()
@ -979,7 +1000,7 @@ func _physics_process(delta: float) -> void:
var walk_move_dir_xz: Vector2 = _resolve_walk_probe_dir_xz(feet_y, want_goal_h)
_apply_walk_air_gravity(delta, walk_move_dir_xz)
_apply_walk_air_gravity(delta, feet_y, walk_move_dir_xz)
floor_snap_length = _walk_floor_snap_length(feet_y, want_goal_h, walk_move_dir_xz)
move_and_slide()
_after_walk_move_and_slide()