-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathplayer.gd
More file actions
327 lines (269 loc) · 8.78 KB
/
Copy pathplayer.gd
File metadata and controls
327 lines (269 loc) · 8.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
extends CharacterBody3D
const BASE_SPEED = 3.3
const JUMP_VELOCITY = 4.5
const SPRINT_MULTIPLIER = 1.8
@onready var footsteps_sound = $FootstepsSound
@onready var background_sound = $BackgroundSound
@onready var air_brake_sound = $AirBrakeSound
@onready var hand_washing_sound = $HandWashingSound
@onready var camera_pivot = $"Camera Pivot"
@onready var pee_sound = $PeeSound
@onready var game_over_label = $UI/GameOverLabel
@onready var message_label = $UI/MessageLabel
@onready var game_over_background = $UI/GameOverBackground
@onready var the_end_label = $UI/TheEndLabel
@onready var menu = $UI/Menu
@onready var sensitivity_slider = $UI/Menu/SensitivitySlider
var rotation_x = 0.0
var rotation_y := 0.0
var can_move := true
var can_look := true
var footsteps_playing := true
var in_pee_area := false
var in_hand_wash_area := false
var in_bathroom_exit_area := false
var in_bus_area := false
var has_peed := false
var has_washed_hands := false
var showed_station_message := false
var active_messages := {}
var paused := false
@export var vertical_look_range := Vector2(-60.0, 75.0)
@export var horizontal_look_range := Vector2(-INF, INF)
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
menu.process_mode = Node.PROCESS_MODE_ALWAYS
begin_footsteps()
sensitivity_slider.value = Settings.mouse_sensitivity
func begin_footsteps():
var prev_max_volume = footsteps_sound.max_db
footsteps_sound.max_db = -1000.0
await get_tree().create_timer(0.1).timeout
footsteps_sound.play()
await get_tree().create_timer(0.1).timeout
footsteps_sound.max_db = prev_max_volume
footsteps_sound.stream_paused = true
func _notification(what):
if what == NOTIFICATION_WM_WINDOW_FOCUS_OUT:
if not paused:
toggle_pause()
func _input(event):
if event is InputEventKey:
if event.keycode == Key.KEY_ESCAPE and event.pressed:
toggle_pause()
func _unhandled_input(event):
if event is InputEventMouseMotion:
handle_mouse_motion(event)
func _physics_process(delta: float) -> void:
if not can_move:
return
if not is_on_floor():
velocity += get_gravity() * delta
if Input.is_action_just_pressed("player_jump") and is_on_floor():
velocity.y = JUMP_VELOCITY
if in_pee_area and not has_peed:
showMessage("pee_prompt", "Press 'E' to pee")
if Input.is_action_just_pressed("player_action"):
pee()
else:
hideMessage("pee_prompt")
if in_hand_wash_area and has_peed and not has_washed_hands:
showMessage("hand_wash_prompt", "Press 'E' to wash your hands")
if Input.is_action_just_pressed("player_action"):
wash_hands()
else:
hideMessage("hand_wash_prompt")
if in_bus_area and has_peed and has_washed_hands:
showMessage("bus_prompt", "Press 'E' to return to the bus")
if Input.is_action_just_pressed("player_action"):
run_end_cutscene()
hideMessage("bus_prompt")
else:
hideMessage("bus_prompt")
if in_bathroom_exit_area and has_peed:
bathroom_after_pee_exit()
var speed = BASE_SPEED
if Input.is_action_pressed("player_sprint"):
speed *= SPRINT_MULTIPLIER
var input_dir := Input.get_vector("player_left", "player_right", "player_up", "player_down")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction:
velocity.x = direction.x * speed
velocity.z = direction.z * speed
else:
velocity.x = move_toward(velocity.x, 0, speed)
velocity.z = move_toward(velocity.z, 0, speed)
var is_moving := velocity.length() > 0.1
var should_play_footsteps = is_on_floor() and is_moving and can_move
if should_play_footsteps != footsteps_playing:
footsteps_sound.stream_paused = not should_play_footsteps
footsteps_playing = should_play_footsteps
move_and_slide()
func handle_mouse_motion(event: InputEventMouseMotion) -> void:
if not can_look:
return
rotate_camera_y(-event.relative.x * Settings.mouse_sensitivity)
rotate_camera_x(-event.relative.y * Settings.mouse_sensitivity)
func rotate_camera_x(angle: float) -> void:
var new_rotation_x = clamp(
rotation_x + angle,
vertical_look_range[0],
vertical_look_range[1]
)
set_camera_x(new_rotation_x)
func set_camera_y(angle: float) -> void:
rotation_y = angle
rotation_degrees.y = angle
func set_camera_x(angle: float) -> void:
rotation_x = angle
camera_pivot.rotation_degrees.x = angle
func rotate_camera_y(angle: float) -> void:
var new_rotation_y = clamp(
rotation_y + angle,
horizontal_look_range[0],
horizontal_look_range[1]
)
set_camera_y(new_rotation_y)
func _on_pee_area_body_entered(body: Node3D) -> void:
if body != self:
return
in_pee_area = true
func _on_pee_area_body_exited(body: Node3D) -> void:
if body != self:
return
in_pee_area = false
func _on_bathroom_exit_area_body_entered(body: Node3D) -> void:
if body != self:
return
in_bathroom_exit_area = true
func _on_bathroom_exit_area_body_exited(body: Node3D) -> void:
if body != self:
return
in_bathroom_exit_area = false
func _on_hand_wash_area_body_entered(body: Node3D) -> void:
if body != self:
return
in_hand_wash_area = true
func _on_hand_wash_area_body_exited(body: Node3D) -> void:
if body != self:
return
in_hand_wash_area = false
func _on_bus_area_body_entered(body: Node3D) -> void:
if body != self:
return
in_bus_area = true
func _on_bus_area_body_exited(body: Node3D) -> void:
if body != self:
return
in_bus_area = false
func _on_station_area_body_entered(body: Node3D) -> void:
if body != self:
return
if showed_station_message:
return
showed_station_message = true
showMessage("station_empty", "This place is deserted... Where is everyone?")
await get_tree().create_timer(3.0).timeout
hideMessage("station_empty")
func run_end_cutscene() -> void:
get_tree().current_scene.start_cutscene()
showMessage("final_thanks", "Thank you Mr Driver, I feel much better now.")
await get_tree().create_timer(5.0).timeout
hideMessage("final_thanks")
await get_tree().create_timer(10.0).timeout
game_over_background.modulate.a = 0.0
game_over_background.visible = true
var tween = create_tween()
tween.tween_property(game_over_background, "modulate:a", 1.0, 2.0)
await tween.finished
the_end_label.visible = true
await get_tree().create_timer(5.0).timeout
go_to_menu()
func pee() -> void:
hideMessage("pee_prompt")
in_pee_area = false
pee_sound.play()
can_move = false
can_look = false
await get_tree().create_timer(7.0).timeout
can_move = true
can_look = true
has_peed = true
showMessage("pee_done", "You have peed!")
await get_tree().create_timer(2.0).timeout
hideMessage("pee_done")
func bathroom_after_pee_exit() -> void:
if not has_washed_hands:
game_over("You left without washing your hands!")
return
showMessage("bathroom_exit", "I really should go back to the bus.")
await get_tree().create_timer(3.0).timeout
hideMessage("bathroom_exit")
func wash_hands() -> void:
has_washed_hands = true
hideMessage("hand_wash_prompt")
hand_washing_sound.play()
can_move = false
can_look = false
await get_tree().create_timer(3.0).timeout
can_move = true
can_look = true
showMessage("hand_wash_done", "You have washed your hands!")
await get_tree().create_timer(2.0).timeout
hideMessage("hand_wash_done")
func play_background_sound() -> void:
if not background_sound.playing:
background_sound.play()
func stop_background_sound() -> void:
if background_sound.playing:
background_sound.stop()
func game_over(reason: String) -> void:
game_over_background.visible = true
showMessage("game_over", reason)
game_over_label.visible = true
can_move = false
can_look = false
await get_tree().create_timer(5.0).timeout
go_to_menu()
func go_to_menu() -> void:
get_tree().change_scene_to_file("res://menu.tscn")
func showMessage(id: String, text: String) -> void:
if active_messages.has(id):
var existing_label = active_messages[id]
existing_label.text = text
existing_label.visible = true
return
var new_label = message_label.duplicate()
new_label.text = text
new_label.visible = true
message_label.get_parent().add_child(new_label)
var offset = active_messages.size() * 20
new_label.position.y = message_label.position.y + offset
active_messages[id] = new_label
func hideMessage(id: String) -> void:
if active_messages.has(id):
var label = active_messages[id]
label.queue_free()
active_messages.erase(id)
var index = 0
for msg_id in active_messages:
var label_node = active_messages[msg_id]
label_node.position.y = message_label.position.y + (index * 20)
index += 1
func toggle_pause() -> void:
paused = not paused
get_tree().paused = paused
if paused:
menu.visible = true
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
else:
menu.visible = false
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _on_resume_game_pressed() -> void:
toggle_pause()
func _on_back_to_menu_pressed() -> void:
toggle_pause()
go_to_menu()
func _on_sensitivity_slider_value_changed(value: float) -> void:
Settings.mouse_sensitivity = value
Settings.save_settings()