diff --git a/client/scripts/player.gd b/client/scripts/player.gd index a085809..cc09f8a 100644 --- a/client/scripts/player.gd +++ b/client/scripts/player.gd @@ -1,7 +1,7 @@ extends CharacterBody3D ## NS-23: Nav waypoints + stored server goal for arrival. -## NS-19: `ns19_bump` — skip nav waypoints when leaving (goal lower) or on flatish bump top. +## NS-19: any underfoot ray into `ns19_bump` → skip nav (waypoints); bumps are small vs obstacles. const MOVE_SPEED: float = 5.0 const ARRIVE_EPS: float = 0.35 @@ -11,11 +11,9 @@ const VERT_ARRIVE_EPS: float = 0.055 const MAX_CLIMB_SPEED: float = 2.6 const MAX_DESCENT_SPEED: float = 2.2 const DIRECT_APPROACH_RADIUS: float = 0.85 -## Plateau / near-rim: floor normal within ~15° of up still counts (0.992 missed convex edges). -const NS19_BUMP_FLAT_NORMAL_DOT: float = 0.964 const NS19_RAY_DOWN: float = 3.0 -## Second ray origin offset toward feet so a tall capsule still hits bump underfoot. -const NS19_FEET_RAY_Y_OFFSET: float = -0.45 +## Downward ray origins (Y offset from body origin) so we still detect bump under a tall capsule. +const NS19_UNDERFOOT_RAY_Y: Array[float] = [0.0, -0.45, -0.82] var _has_walk_goal: bool = false var _auth_walk_goal: Vector3 = Vector3.ZERO @@ -47,16 +45,9 @@ func snap_to_server(world_pos: Vector3) -> void: func _should_skip_nav_for_ns19_bump() -> bool: - var under_bump: bool = _ns19_bump_under_ray(global_position) - if not under_bump: - under_bump = _ns19_bump_under_ray(global_position + Vector3(0.0, NS19_FEET_RAY_Y_OFFSET, 0.0)) - if not under_bump: - return false - # Waypoints pick “down the mesh” first; horizontal steer to goal fixes departure. - if _auth_walk_goal.y < global_position.y - 0.02: - return true - if is_on_floor() and get_floor_normal().dot(Vector3.UP) >= NS19_BUMP_FLAT_NORMAL_DOT: - return true + for y_off: float in NS19_UNDERFOOT_RAY_Y: + if _ns19_bump_under_ray(global_position + Vector3(0.0, y_off, 0.0)): + return true return false @@ -96,8 +87,8 @@ func _steer_toward_world_point(point: Vector3) -> void: var desired: Vector3 = delta.normalized() * MOVE_SPEED desired.y = clampf(desired.y, -MAX_DESCENT_SPEED, MAX_CLIMB_SPEED) velocity = desired - elif dy < -0.04: - # Goal is lower and almost same xz (e.g. floor under the plateau): still need rim escape. + elif dy < 0.0: + # Same xz, goal slightly lower (e.g. -0.03): old threshold left velocity at zero (“hang”). var escape_h := Vector3(-global_transform.basis.z.x, 0.0, -global_transform.basis.z.z) if escape_h.length_squared() < 1e-8: escape_h = Vector3(1.0, 0.0, 0.0) @@ -131,7 +122,7 @@ func _physics_process(_delta: float) -> void: move_and_slide() return - # On bump + (goal lower or flat top): skip waypoints so we do not follow vertical “drop” legs. + # On bump: skip nav waypoints (drop-first paths); bump area is small vs the obstacle. if _should_skip_nav_for_ns19_bump(): _steer_toward_world_point(_auth_walk_goal) move_and_slide()