NS-19: ignore vertical walkable surfaces in ground ray pick

pull/21/head
VinPropane 2026-04-04 23:45:54 -04:00
parent 32d2153acb
commit 7ac6b66b51
2 changed files with 12 additions and 1 deletions

View File

@ -1,10 +1,15 @@
extends Node3D
## NS-16: walkable ground ray pick. Emits world target for MoveCommand; camera wired from main.
## NS-19: ignores hits on **steep** surfaces (e.g. pedestal **walls**) so players cannot chain small
## vertical steps up a vertical face; only **floor-like** normals (high dot with UP) count.
## (No `class_name` so headless/CI can load the project before `.godot` import exists.)
signal target_chosen(world: Vector3)
## Minimum `hit_normal.dot(Vector3.UP)` to accept a pick (0 = vertical wall, 1 = flat floor).
const MIN_WALKABLE_NORMAL_DOT_UP: float = 0.82
## Fallback when `Viewport.get_camera_3d()` is null (e.g. some editor setups). Set from `main.gd`
## in `_ready`.
var fallback_camera: Camera3D
@ -36,6 +41,12 @@ func _try_pick(screen_pos: Vector2) -> void:
var collider: Variant = hit.get("collider")
if not _collider_is_walkable(collider):
return
var hit_normal: Variant = hit.get("normal", Vector3.ZERO)
if hit_normal is not Vector3:
return
var nrm: Vector3 = (hit_normal as Vector3).normalized()
if nrm.dot(Vector3.UP) < MIN_WALKABLE_NORMAL_DOT_UP:
return
var hit_pos: Variant = hit.get("position")
if hit_pos is Vector3:
target_chosen.emit(hit_pos as Vector3)

View File

@ -72,7 +72,7 @@ Unknown player ids return **404**. Full zone sync / replication is still out of
| `Game:MovementValidation:DistrictBoundsEnabled` | Axis-aligned box on **target** (inclusive min/max) | `false` |
| `Game:MovementValidation:DistrictMinX``DistrictMaxZ` | District extents when enabled | ±12 / Y 2…24 |
**Manual QA (Godot `main.tscn`):** **Green bumps** (~0.15 m rise) stay under default `MaxVerticalStep` from the dev spawn; **orange reject pedestal** top is ~2.5 m above floor so a floor-level click yields **`vertical_step_exceeded`**; **far pad** is beyond default horizontal reach for **`horizontal_step_exceeded`**.
**Manual QA (Godot `main.tscn`):** **Green bumps** (~0.15 m rise) stay under default `MaxVerticalStep` from the dev spawn; **orange reject pedestal** top is ~2.5 m above floor so a floor-level click yields **`vertical_step_exceeded`**; **far pad** is beyond default horizontal reach for **`horizontal_step_exceeded`**. The clients **`ground_pick.gd`** only accepts ray hits whose surface **normal** is mostly **upward** (`MIN_WALKABLE_NORMAL_DOT_UP`), so **vertical faces** on the pedestal do not emit move targets—this complements server per-step limits and prevents “stair-stepping” up walls.
Request body (example):