Files
open-wc/src/gameplay/movement/local_player_movement_controller.gd
T
sindoring 742c415885 gmp(M02): gate debug movement capabilities
Work-Package: M02-GMP-SANDBOX-CAPABILITIES-001

Agent: sindo-main-codex

Tests: capability/input/movement/terrain/camera/presentation; coordinate/streaming/docs/coordination; renderer dry-run 7/7

Fidelity: proves debug sprint/free-flight exclusion in Blizzlike335; no positive movement parity claim
2026-07-14 23:55:27 +04:00

116 lines
4.3 KiB
GDScript

class_name LocalPlayerMovementController
extends RefCounted
## Scene-free state and velocity integrator for the current local sandbox player.
## Direction inputs use a Godot-world movement basis selected by the scene
## adapter. This class does not discover Nodes, query terrain or mutate transforms.
var godot_world_velocity_units_per_second: Vector3:
get:
return _godot_world_velocity_units_per_second
var is_flight_enabled: bool:
get:
return _is_flight_enabled
var movement_profile_id: StringName:
get:
return _movement_capabilities.profile_id
var _run_speed_units_per_second: float
var _backward_speed_units_per_second: float
var _strafe_speed_units_per_second: float
var _flight_vertical_speed_units_per_second: float
var _acceleration_units_per_second_squared: float
var _sandbox_sprint_multiplier: float
var _movement_capabilities: PlayerMovementCapabilities
var _godot_world_velocity_units_per_second := Vector3.ZERO
var _is_flight_enabled := false
## Creates a movement state with explicit Godot-unit speeds, acceleration and capabilities.
## The current compatibility renderer treats one Godot unit as one WoW yard.
## A null capability input fails closed to Blizzlike335 debug permissions.
func _init(
run_speed_units_per_second: float,
backward_speed_units_per_second: float,
strafe_speed_units_per_second: float,
flight_vertical_speed_units_per_second: float,
acceleration_units_per_second_squared: float,
sandbox_sprint_multiplier: float,
movement_capabilities: PlayerMovementCapabilities = null
) -> void:
_run_speed_units_per_second = run_speed_units_per_second
_backward_speed_units_per_second = backward_speed_units_per_second
_strafe_speed_units_per_second = strafe_speed_units_per_second
_flight_vertical_speed_units_per_second = flight_vertical_speed_units_per_second
_acceleration_units_per_second_squared = acceleration_units_per_second_squared
_sandbox_sprint_multiplier = sandbox_sprint_multiplier
_movement_capabilities = (
movement_capabilities
if movement_capabilities != null
else PlayerMovementCapabilities.blizzlike_335()
)
## Toggles sandbox free flight and clears velocity when the profile permits it.
## Returns the resulting state; rejected compatibility-profile requests return false.
func toggle_sandbox_flight() -> bool:
if not _movement_capabilities.allows_debug_free_flight:
return false
_is_flight_enabled = not _is_flight_enabled
_godot_world_velocity_units_per_second = Vector3.ZERO
return _is_flight_enabled
## Advances velocity by one physics step and returns local-world displacement.
## `godot_world_movement_basis` is the player basis on ground and camera-pivot basis in flight.
## Negative delta values are treated as zero and do not mutate velocity.
func advance(
move_intent: MoveIntent,
godot_world_movement_basis: Basis,
delta_seconds: float
) -> Vector3:
var safe_delta_seconds := maxf(delta_seconds, 0.0)
if is_zero_approx(safe_delta_seconds):
return Vector3.ZERO
var target_velocity := _calculate_target_velocity(move_intent, godot_world_movement_basis)
_godot_world_velocity_units_per_second = _godot_world_velocity_units_per_second.move_toward(
target_velocity,
_acceleration_units_per_second_squared * safe_delta_seconds
)
return _godot_world_velocity_units_per_second * safe_delta_seconds
func _calculate_target_velocity(move_intent: MoveIntent, godot_world_movement_basis: Basis) -> Vector3:
var forward_direction := -godot_world_movement_basis.z
var right_direction := godot_world_movement_basis.x
if not _is_flight_enabled:
forward_direction.y = 0.0
right_direction.y = 0.0
forward_direction = forward_direction.normalized()
right_direction = right_direction.normalized()
var forward_speed := (
_run_speed_units_per_second
if move_intent.forward_axis > 0.0
else _backward_speed_units_per_second
)
var speed_multiplier := (
_sandbox_sprint_multiplier
if move_intent.is_sprint_requested and _movement_capabilities.allows_debug_sprint
else 1.0
)
var target_velocity := (
forward_direction * move_intent.forward_axis * forward_speed
+ right_direction * move_intent.strafe_axis * _strafe_speed_units_per_second
) * speed_multiplier
if _is_flight_enabled:
target_velocity.y += (
move_intent.vertical_axis
* _flight_vertical_speed_units_per_second
* speed_multiplier
)
return target_velocity