stick-the-quick/characters/thinkers/RunnerController.gd

136 lines
4.0 KiB
GDScript

class_name RunnerController extends RunnerObserver
const BASE_ZOOM_SPEED: float = 0.125
const MOUSE_WHEEL_BIAS: float = 8.0
const MAX_VERTICAL_ALIGNMENT: float = 0.75
const LOOK_IMPETUS_LERP_WEIGHT: float = 0.125
var control_enabled: bool
var look_impetus := Vector3.ZERO
var look_impetus_target := Vector3.ZERO
func _ready() -> void:
super()
control_enabled = true
func switch_runner(whom: Runner, distance: float = DEFAULT_DISTANCE) -> void:
if runner:
runner.remove_from_group(&'player')
super(whom, distance)
if runner:
runner.add_to_group(&'player')
func _would_be_responsive_if_current() -> bool:
return runner and control_enabled and not target_override
func _is_responsive() -> bool:
return current and _would_be_responsive_if_current()
func _unhandled_input(event: InputEvent) -> void:
if _is_responsive():
var iemm := event as InputEventMouseMotion
var iemb := event as InputEventMouseButton
if iemm and Options.mouselook:
var dy: float = iemm.relative.y
if Options.invert_mouselook:
dy = -dy
var align: float = maintain_direction.dot(up_normal)
if (
(dy > 0.0 and align < -MAX_VERTICAL_ALIGNMENT) or
(dy < 0.0 and align > MAX_VERTICAL_ALIGNMENT/2.0)
):
dy = 0.0
var dx: float = iemm.relative.x
look_impetus_target += (
basis.y*dy - basis.x*dx
).limit_length()*Options.mouse_sensitivity*(
maintain_distance/FX.DEFAULT_CAMERA_DISTANCE
)
if iemb and Options.mouselook:
match iemb.button_index:
MOUSE_BUTTON_WHEEL_UP:
maintain_distance = max(
maintain_distance - (
BASE_ZOOM_SPEED *
MOUSE_WHEEL_BIAS *
Options.mouse_wheel_sensitivity
)*(
-1.0 if Options.invert_mouse_wheel
else 1.0
),
0.0
)
MOUSE_BUTTON_WHEEL_DOWN:
maintain_distance = max(
maintain_distance + (
BASE_ZOOM_SPEED *
MOUSE_WHEEL_BIAS *
Options.mouse_wheel_sensitivity
)*(
-1.0 if Options.invert_mouse_wheel
else 1.0
),
0.0
)
_: pass
if event.is_action_released(&'pause'):
UI.Call(load("res://ui/OptionsMenu/OptionsMenu.tscn"))
get_viewport().set_input_as_handled()
elif runner.state != &'knockback' and runner.state != &'taunt':
if event.is_action_pressed(&'jump'):
runner.jump()
get_viewport().set_input_as_handled()
elif event.is_action_released(&'jump'):
runner.cancel_jump()
get_viewport().set_input_as_handled()
elif event.is_action_pressed(&'ability'):
runner.do_ability()
get_viewport().set_input_as_handled()
func _accept_analog_input() -> void:
if _is_responsive():
var dy: float = Input.get_axis(&'look_down', &'look_up')
if Options.invert_right_stick:
dy = -dy
var align: float = maintain_direction.dot(up_normal)
if (
(dy > 0.0 and align < -MAX_VERTICAL_ALIGNMENT) or
(dy < 0.0 and align > MAX_VERTICAL_ALIGNMENT/2.0)
):
dy = 0.0
var dx: float = Input.get_axis(&'look_left', &'look_right')
look_impetus_target += (
basis.y*dy - basis.x*dx
).limit_length()*Options.right_stick_sensitivity*(
maintain_distance/FX.DEFAULT_CAMERA_DISTANCE
)
look_impetus = look_impetus.lerp(
look_impetus_target, LOOK_IMPETUS_LERP_WEIGHT
)
_try_go(global_position + look_impetus)
if Input.is_action_pressed(&'zoom_in'):
maintain_distance = max(maintain_distance - BASE_ZOOM_SPEED, 0.0)
if Input.is_action_pressed(&'zoom_out'):
maintain_distance += BASE_ZOOM_SPEED
if runner.state != &'knockback' and runner.state != &'taunt':
var raw_impetus := Vector3(
Input.get_axis(&'move_left', &'move_right'),
0.0,
Input.get_axis(&'move_forward', &'move_back')
).limit_length()
if not raw_impetus.is_zero_approx():
runner.impetus = (
(basis*raw_impetus).slide(runner.up_normal).normalized()
)*raw_impetus.length()
look_impetus_target = Vector3.ZERO
func _update_mouselook_requested() -> void:
if current:
Options.mouselook_requested = _would_be_responsive_if_current()
func _physics_process(delta: float) -> void:
_update_mouselook_requested()
_accept_analog_input()
super(delta)