diff --git a/client/scripts/player.gd b/client/scripts/player.gd index 3912d82..1449e61 100644 --- a/client/scripts/player.gd +++ b/client/scripts/player.gd @@ -6,12 +6,15 @@ extends CharacterBody3D ## and steps comes from `move_and_slide` + floor_* on CharacterBody3D. Move **legality** (step, ## distance, bounds) is server MoveCommand only — not reimplemented here. ## -## NavigationAgent3D detours obstacles; steering uses target **xz** only. +## Nav detours except when goal Y is below us: then xz toward goal (waypoints sit under bump rims). const MOVE_SPEED: float = 5.0 const ARRIVE_EPS: float = 0.35 const VERT_ARRIVE_EPS: float = 0.055 const DIRECT_APPROACH_RADIUS: float = 0.85 +## Server goal clearly below us (descending). Nav mesh waypoints are often under the rim first; +## steering at next gives almost no horizontal speed — walk out on xz toward the authorized goal. +const DESCEND_GOAL_Y_MARGIN: float = 0.06 var _has_walk_goal: bool = false var _auth_walk_goal: Vector3 = Vector3.ZERO @@ -73,6 +76,11 @@ func _physics_process(_delta: float) -> void: move_and_slide() return + if _auth_walk_goal.y < global_position.y - DESCEND_GOAL_Y_MARGIN: + _set_horizontal_velocity_toward(_auth_walk_goal) + move_and_slide() + return + if horiz_dist <= DIRECT_APPROACH_RADIUS: _set_horizontal_velocity_toward(_auth_walk_goal) else: diff --git a/server/NeonSprawl.Server/Game/PositionState/MoveCommandValidation.cs b/server/NeonSprawl.Server/Game/PositionState/MoveCommandValidation.cs index 0dc1c86..ef75be9 100644 --- a/server/NeonSprawl.Server/Game/PositionState/MoveCommandValidation.cs +++ b/server/NeonSprawl.Server/Game/PositionState/MoveCommandValidation.cs @@ -4,6 +4,8 @@ namespace NeonSprawl.Server.Game.PositionState; /// /// Precedence when multiple rules fail: , /// then , then . +/// Vertical uses abs(ΔY), so descending (target Y lower than current) is allowed when the +/// drop is within — same as climbing. /// public static class MoveCommandValidation {