open-fpsz/entities/player/inputs_sync.gd

93 lines
3.4 KiB
GDScript

# This file is part of open-fpsz.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
class_name PlayerInputController extends Node
@export var jetting:bool = false
@export var skiing:bool = false
@export var direction:Vector2
@export var camera_rotation:Vector2
signal jump
signal primary(pressed: bool)
signal throw(pressed: bool)
var _mouse_sensitivity:float = .0
func _enter_tree() -> void:
# @NOTE: This is a workaround for player node being too integrated with the
# multiplayer layer and blocks player inputs in singleplayer if not set.
set_multiplayer_authority(1)
func _unhandled_input(event: InputEvent) -> void:
if is_multiplayer_authority() and owner.is_alive():
var mouse_mode: Input.MouseMode = Input.get_mouse_mode()
direction = Input.get_vector("left", "right", "forward", "backward")
jetting = Input.is_action_pressed("secondary")
skiing = Input.is_action_pressed("ski")
# isolate mouse events
if event is InputEventMouseMotion:
if mouse_mode == Input.MOUSE_MODE_CAPTURED:
# update camera with mouse position relative to last frame
_update_camera(event.relative)
elif event is InputEventMouseButton:
# @NOTE: there could be a control setting for direction
if event.button_index == MOUSE_BUTTON_WHEEL_UP and event.pressed:
_cycle.rpc(1)
elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN and event.pressed:
_cycle.rpc(-1)
elif event is InputEventKey:
match event.keycode:
KEY_1: _select.rpc(0)
KEY_2: _select.rpc(1)
KEY_3: _select.rpc(2)
if event.is_action("primary"):
_primary.rpc(event.pressed)
if Input.is_action_just_pressed("secondary"):
_jump.rpc()
if event.is_action("throw") and not event.echo:
_throw.rpc(event.pressed)
func _update_camera(relative_motion:Vector2) -> void:
# reverse y axis
if Settings.get_value("controls", "inverted_y_axis"):
relative_motion.y *= -1.0
_mouse_sensitivity = Settings.get_value("controls", "mouse_sensitivity")
# clamp vertical rotation (head motion)
camera_rotation.x -= relative_motion.y * _mouse_sensitivity / 100
camera_rotation.x = clamp(camera_rotation.x, deg_to_rad(-90.0), deg_to_rad(90.0))
# wrap horizontal rotation (to prevent accumulation)
camera_rotation.y -= relative_motion.x * _mouse_sensitivity / 100
camera_rotation.y = wrapf(camera_rotation.y, deg_to_rad(0.0), deg_to_rad(360.0))
@rpc("authority", "call_local", "reliable")
func _jump() -> void:
jump.emit()
@rpc("authority", "call_local", "reliable")
func _primary(pressed: bool) -> void:
primary.emit(pressed)
@rpc("authority", "call_local", "reliable")
func _cycle(shift:int) -> void:
%Inventory.cycle(shift)
@rpc("authority", "call_local", "reliable")
func _select(index:int) -> void:
%Inventory.select(index)
@rpc("authority", "call_local", "reliable")
func _throw(pressed: bool) -> void:
throw.emit(pressed)