435e1c95d2
Work-Package: M02-GMP-MOVEMENT-001 Agent: sindo-main-codex Tests: local movement and player input regressions; asset-free scene; renderer dry-run; coordinate, streaming, documentation and coordination gates Fidelity: preserves current sandbox speed, acceleration, sprint and camera-relative flight behavior; build-12340 parity remains unverified
98 lines
3.7 KiB
GDScript
98 lines
3.7 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 _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 _godot_world_velocity_units_per_second := Vector3.ZERO
|
|
var _is_flight_enabled := false
|
|
|
|
|
|
## Creates a movement state with explicit Godot-unit speeds and acceleration.
|
|
## The current compatibility renderer treats one Godot unit as one WoW yard.
|
|
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
|
|
) -> 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
|
|
|
|
|
|
## Toggles sandbox free flight and clears velocity exactly like the pre-M02 controller.
|
|
## Returns the new flight state.
|
|
func toggle_sandbox_flight() -> bool:
|
|
_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 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
|