class_name MoveIntent
extends RefCounted

## Immutable player locomotion request expressed in character-local axes.
## Axis values are normalized to `[-1, 1]`: forward/right/up are positive.
## The intent contains no world coordinates, engine input events or presentation state.

var forward_axis: float:
	get:
		return _forward_axis

var strafe_axis: float:
	get:
		return _strafe_axis

var vertical_axis: float:
	get:
		return _vertical_axis

var is_sprint_requested: bool:
	get:
		return _is_sprint_requested

## Signed keyboard turn request: left is negative and right is positive.
var turn_axis: float:
	get:
		return _turn_axis

var _forward_axis: float
var _strafe_axis: float
var _vertical_axis: float
var _is_sprint_requested: bool
var _turn_axis: float


## Creates one frame's movement request without retaining mutable input state.
func _init(
		forward_axis_value: float = 0.0,
		strafe_axis_value: float = 0.0,
		vertical_axis_value: float = 0.0,
		sprint_requested: bool = false,
		turn_axis_value: float = 0.0
) -> void:
	_forward_axis = clampf(forward_axis_value, -1.0, 1.0)
	_strafe_axis = clampf(strafe_axis_value, -1.0, 1.0)
	_vertical_axis = clampf(vertical_axis_value, -1.0, 1.0)
	_is_sprint_requested = sprint_requested
	_turn_axis = clampf(turn_axis_value, -1.0, 1.0)


## Returns true when the intent requests planar or vertical translation.
func has_translation() -> bool:
	return not is_zero_approx(_forward_axis) \
		or not is_zero_approx(_strafe_axis) \
		or not is_zero_approx(_vertical_axis)
