]> Untitled Git - wolf-seeking-sheep.git/blob - classes/gameplay/Player.gd
Squashed commit of the following:
[wolf-seeking-sheep.git] / classes / gameplay / Player.gd
1 class_name Player
2 extends CharacterBody3D
3
4 ###########
5
6 signal foundActionableNode
7 signal noActionableNode
8
9 ###########
10
11 @export_category("Movement")
12 @export var movement_enabled := true
13 @export var walk_speed := 5.0
14 @export var acceleration := 30.0
15 @export var gravity := 10.0
16
17 @export_category("Camera")
18 @export var camera_movement_enabled := true
19 @export_range(0.0, 1.0) var mouse_sensitivity := 0.2
20 @export_range(0.0, 1.0) var mouse_sensitivity_x := 1.0
21 @export_range(0.0, 1.0) var mouse_sensitivity_y := 0.5
22 @export var look_at_rotation_speed := 3.0
23
24 enum {CAMERA_MOUSE_INPUT, CAMERA_JOYSTICK_INPUT}
25 var _camera_input_method := CAMERA_MOUSE_INPUT
26 var _camera_input_direction := Vector2.ZERO
27
28 const _camera_highest_x_angle := PI / 2
29 const _camera_lowest_x_angle := -PI / 2
30
31 @onready var _camera: Camera3D = %Camera3D
32 @onready var _phone = %Phone
33
34 var actionable_node: Actionable = null
35 var look_at_pos: Vector3 = Vector3.ZERO
36
37 ###########
38
39 func _physics_process(delta: float) -> void:
40         if camera_movement_enabled:
41                 _camera.rotation.y -= _camera_input_direction.x * mouse_sensitivity_x * delta
42                 _camera.rotation.x -= _camera_input_direction.y * mouse_sensitivity_y * delta
43                 _camera.rotation.x = clamp(
44                         _camera.rotation.x, _camera_lowest_x_angle, _camera_highest_x_angle
45                         )
46                 
47                 # reset mouse movement vector if mouse input
48                 if _camera_input_method == CAMERA_MOUSE_INPUT:
49                         _camera_input_direction = Vector2.ZERO
50         elif look_at_pos != Vector3.ZERO:
51                 var target_vector: Vector3 = look_at_pos - _camera.global_position
52                 var target_angle_y = Vector3.FORWARD.signed_angle_to(target_vector, Vector3.UP)
53                 _camera.global_rotation.y = lerp_angle(
54                         _camera.global_rotation.y,
55                         target_angle_y,
56                         delta * look_at_rotation_speed
57                 )
58                 var target_angle_x = atan2(target_vector.y, target_vector.length())
59                 _camera.rotation.x = lerp_angle(
60                         _camera.rotation.x,
61                         target_angle_x,
62                         delta * look_at_rotation_speed
63                 )
64         
65         if movement_enabled:
66                 if is_on_floor():
67                         var move_direction := _get_player_move_direction()
68                         velocity = velocity.move_toward(move_direction * walk_speed, acceleration * delta)
69                 else:
70                         velocity += Vector3.DOWN * gravity * delta
71         
72         move_and_slide()
73
74
75 func _unhandled_input(event: InputEvent) -> void:
76         if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
77                 return
78
79         if event is InputEventMouseMotion:
80                 _camera_input_method = CAMERA_MOUSE_INPUT
81                 _camera_input_direction = event.screen_relative * mouse_sensitivity
82
83 ###########
84
85
86 func phone_out(b: bool) -> void:
87         _phone.visible = b
88
89
90 func toggle_phone_out() -> void:
91         if movement_enabled:
92                 _phone.visible = !_phone.visible
93
94
95 func camera_look_at(pos: Vector3, snapTo: bool = false) -> void:
96         if snapTo:
97                 _camera.look_at(pos, Vector3.UP)
98         look_at_pos = pos
99
100
101 func _get_player_move_direction() -> Vector3:
102         var input_dir := Input.get_vector("player-left", "player-right", "player-up", "player-down")
103         var forward := _camera.global_basis.z
104         var right := _camera.global_basis.x
105         var move_direction := (forward * input_dir.y + right * input_dir.x).normalized()
106         move_direction.y = 0
107         return move_direction
108
109
110 func _on_talking_area_body_entered(body: Node3D) -> void:
111         if body is Actionable:
112                 print("Hello " + str(body) + ": " + body.get("prompt"))
113                 actionable_node = body
114                 foundActionableNode.emit(body)
115
116
117 func _on_talking_area_body_exited(body: Node3D) -> void:
118         if body is Actionable:
119                 if actionable_node == body:
120                         print("Goodbye " + str(body))
121                         actionable_node = null
122                         noActionableNode.emit()