aboutsummaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/audio/play_random.gd48
-rw-r--r--client/global.gd140
-rw-r--r--client/map/items/item.gd6
-rw-r--r--client/menu/credits.gd10
-rw-r--r--client/menu/settings.gd18
-rw-r--r--client/menu/settings/dropdown_setting.gd40
-rw-r--r--client/menu/settings/game_setting.gd51
-rw-r--r--client/menu/settings/range_setting.gd42
-rw-r--r--client/menu/settings/settings_menu.gd40
-rw-r--r--client/menu/settings/settings_row.gd36
-rw-r--r--client/menu/settings/settings_row.tscn (renamed from client/menu/settings_row.tscn)12
-rw-r--r--client/menu/settings/text_setting.gd38
-rw-r--r--client/menu/settings/toggle_setting.gd34
-rw-r--r--client/menu/settings_row.gd91
-rw-r--r--client/menu/setup.gd2
-rw-r--r--client/menu/sounds/failure.oggbin0 -> 14740 bytes
-rw-r--r--client/menu/sounds/failure.ogg.import19
-rw-r--r--client/menu/sounds/success.oggbin26466 -> 10840 bytes
-rw-r--r--client/player/angry.svg.import37
-rw-r--r--client/player/angry.tscn37
-rw-r--r--client/player/angry.webpbin0 -> 5022 bytes
-rw-r--r--client/player/angry.webp.import35
-rw-r--r--client/player/character/character.gd14
-rw-r--r--client/player/character/character.tscn33
-rw-r--r--client/player/effect.gd13
-rw-r--r--client/player/effect.tscn25
-rw-r--r--client/player/player.gd2
-rw-r--r--client/player/sounds/angry1.oggbin0 -> 8491 bytes
-rw-r--r--client/player/sounds/angry1.ogg.import19
-rw-r--r--client/player/sounds/angry2.oggbin0 -> 6622 bytes
-rw-r--r--client/player/sounds/angry2.ogg.import19
-rw-r--r--client/player/sounds/step1.oggbin0 -> 4037 bytes
-rw-r--r--client/player/sounds/step1.ogg.import19
-rw-r--r--client/player/sounds/step2.oggbin0 -> 3840 bytes
-rw-r--r--client/player/sounds/step2.ogg.import19
-rw-r--r--client/player/sounds/step3.oggbin0 -> 3757 bytes
-rw-r--r--client/player/sounds/step3.ogg.import19
-rw-r--r--client/player/sounds/woosh1.oggbin0 -> 6730 bytes
-rw-r--r--client/player/sounds/woosh1.ogg.import19
-rw-r--r--client/player/sounds/woosh2.oggbin0 -> 6767 bytes
-rw-r--r--client/player/sounds/woosh2.ogg.import19
41 files changed, 736 insertions, 220 deletions
diff --git a/client/audio/play_random.gd b/client/audio/play_random.gd
new file mode 100644
index 00000000..afdf046f
--- /dev/null
+++ b/client/audio/play_random.gd
@@ -0,0 +1,48 @@
+# Undercooked - a game about cooking
+# Copyright 2024 tpart
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License only.
+#
+# 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+extends Node
+class_name PlayRandom
+
+@export var volume_db := 0.0
+@export var enable_attenuations := true
+
+var autoplay := false
+
+@onready var sounds = get_children()
+
+func _ready():
+ for s: AudioStreamPlayer3D in sounds:
+ s.connect("finished", sound_finished)
+ s.volume_db = volume_db
+
+ if not enable_attenuations:
+ s.attenuation_filter_cutoff_hz = 20500
+
+func play_random():
+ var s = sounds[randi_range(0, sounds.size() - 1)]
+ s.pitch_scale = randf_range(0.9, 1.1)
+ s.play()
+
+func start_autoplay():
+ autoplay = true
+ play_random()
+
+func stop_autoplay():
+ autoplay = false
+
+func sound_finished():
+ if autoplay:
+ play_random()
diff --git a/client/global.gd b/client/global.gd
index ca0a9603..fdb4df28 100644
--- a/client/global.gd
+++ b/client/global.gd
@@ -33,96 +33,21 @@ var default_profile := {
"last_server_url": ""
}
+var languages := [tr("System default"), "en", "de"]
+
var default_settings := {
- "language": {
- "type": "dropdown",
- "options": [tr("System default"), "en", "de"],
- "value": 0,
- "description": tr("Language"),
- },
- "fullscreen": {
- "type": "toggle",
- "value": false,
- "description": tr("Fullscreen")
- },
- "interpolate_camera_rotation": {
- "type": "toggle",
- "value": true,
- "description": tr("Interpolate the camera rotation")
- },
- "invert_camera": {
- "type": "toggle",
- "value": false,
- "description": tr("Invert camera movement")
- },
- "server_binary": {
- "type": "line",
- "value": "",
- "description": tr("Server binary (leave empty to search PATH)")
- },
- "server_data": {
- "type": "line",
- "value": "",
- "description": tr("Server data directory (leave empty to auto-detect)")
- },
- "graphics_preset": {
- "type": "dropdown_preset",
- "options": [tr("Low"), tr("Medium"), tr("High"), tr("Ultra")],
- "value": 1,
- "description": tr("Graphics preset"),
- "apply": "GRAPHICS_PRESETS"
- },
- "voxel_gi": {
- "type": "toggle",
- "value": false,
- "description": tr("Use VoxelGI (Blocks the game on map update, looks good)")
- },
- "sdfgi": {
- "type": "toggle",
- "value": false,
- "description": tr("Use SDFGI (Doesn't block the game, looks worse)")
- },
- "grass_amount": {
- "type": "range",
- "value": 16,
- "min": 0,
- "max": 32,
- "description": tr("3D grass amount per grass tile")
- },
- "setup_complete": {
- "type": "toggle",
- "value": false,
- "description": tr("Initial setup complete. (Uncheck and restart to reenter)")
- }
+ "language": DropdownSetting.new(tr("Language"), 0, languages),
+ "fullscreen": ToggleSetting.new(tr("Fullscreen"), false),
+ "interpolate_camera_rotation": ToggleSetting.new(tr("Interpolate the camera rotation"), true),
+ "invert_camera": ToggleSetting.new(tr("Invert camera movement"), false),
+ "server_binary": TextSetting.new(tr("Server binary (leave empty to search PATH)"), "", "Enter path"),
+ "server_data": TextSetting.new(tr("Server data directory (leave empty to auto-detect)"), "", "Enter path"),
+ "voxel_gi": ToggleSetting.new(tr("Use VoxelGI (Blocks the game on map update but is more accurate)"), false),
+ "sdfgi": ToggleSetting.new(tr("Use SDFGI (Doesn't block the game but produces more artifacts)"), false),
+ "grass_amount": RangeSetting.new(tr("3D grass amount per grass tile"), 16, 0, 32),
+ "setup_complete": ToggleSetting.new(tr("Initial setup complete. (Uncheck and restart to reenter)"), false)
}
-const GRAPHICS_PRESETS = [
- # Low:
- {
- "voxel_gi": false,
- "sdfgi": false,
- "grass_amount": 0
- },
- # Medium:
- {
- "voxel_gi": false,
- "sdfgi": false,
- "grass_amount": 16
- },
- # High:
- {
- "voxel_gi": false,
- "sdfgi": true,
- "grass_amount": 16
- },
- # Ultra:
- {
- "voxel_gi": true,
- "sdfgi": false,
- "grass_amount": 16
- }
-]
-
var profile: Dictionary
var settings: Dictionary
@@ -131,23 +56,23 @@ var error_message = ""
func _init():
profile = load_dict("user://profile", default_profile)
- settings = load_dict("user://settings", default_settings)
+ load_settings("user://settings")
update_fullscreen()
update_language()
func _ready():
get_viewport().gui_focus_changed.connect(Sound.play_hover_maybe)
-func _input(event):
+func _input(_event):
if Input.is_action_just_pressed("fullscreen"):
Global.set_setting("fullscreen", not Global.get_setting("fullscreen"))
save_settings()
update_fullscreen()
func update_language():
- var lang_idx = get_setting("language")
- var lang = settings["language"]["options"][lang_idx]
-
+ var lang_idx: int = get_setting("language")
+ var lang = languages[lang_idx]
+
if lang_idx != 0: # 0 is system language
TranslationServer.set_locale(lang)
else:
@@ -163,7 +88,13 @@ func save_profile():
save_dict("user://profile", profile)
func save_settings():
- save_dict("user://settings", settings)
+ for v in settings.values():
+ v.fetch_setting()
+ var dict := {}
+ for k in settings.keys():
+ var setting: GameSetting = settings[k]
+ dict[k] = setting.get_value()
+ save_dict("user://settings", dict)
func save_dict(path: String, dict: Dictionary):
var f = FileAccess.open(path, FileAccess.WRITE)
@@ -176,13 +107,28 @@ func load_dict(path: String, default: Dictionary) -> Dictionary:
return default
var f = FileAccess.open(path, FileAccess.READ)
var saved_dict = f.get_var()
-
+
if saved_dict != null and saved_dict is Dictionary:
add_missing_keys(saved_dict, default)
print("Loaded dict: ", saved_dict)
return saved_dict
+func load_settings(path: String):
+ settings = default_settings
+ if not FileAccess.file_exists(path):
+ print("Skip settings load")
+ return
+ var f = FileAccess.open(path, FileAccess.READ)
+ var saved_dict = f.get_var()
+
+ if saved_dict != null and saved_dict is Dictionary:
+ for k in default_settings.keys():
+ var setting: GameSetting = default_settings[k]
+ if saved_dict.has(k):
+ setting.set_value(saved_dict[k])
+ settings[k] = setting
+
func on_vulkan() -> bool:
return ProjectSettings.get_setting("rendering/rendering_device/driver") == "vulkan"
@@ -196,7 +142,7 @@ func add_missing_keys(dict: Dictionary, reference: Dictionary):
func get_setting(key: String):
if settings.has(key):
- return settings[key]["value"]
+ return settings[key].get_value()
else:
push_error("Tried to access setting \"%s\", which does not exist (missing key)" % key)
return null
@@ -204,5 +150,5 @@ func get_setting(key: String):
func set_setting(key: String, value):
if !settings.has(key):
push_error("Tried to set setting \"%s\", which does not yet exist (missing key)" % key)
- settings[key] = {}
- settings[key]["value"] = value
+ return
+ settings[key].set_value(value)
diff --git a/client/map/items/item.gd b/client/map/items/item.gd
index cd8fd75e..688308fe 100644
--- a/client/map/items/item.gd
+++ b/client/map/items/item.gd
@@ -42,5 +42,11 @@ func progress(p: float, warn: bool):
func finish(_warn: bool):
progress_instance.visible = false
+func take():
+ pass
+
+func put():
+ pass
+
static func base_position() -> Vector3:
return Vector3(0., 0., 0.)
diff --git a/client/menu/credits.gd b/client/menu/credits.gd
index 0ab94fd5..10ea910f 100644
--- a/client/menu/credits.gd
+++ b/client/menu/credits.gd
@@ -1,5 +1,5 @@
# Undercooked - a game about cooking
-# Copyright 2024 metamuffin
+# Copyright 2024 metamuffin, tpart
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
@@ -18,12 +18,16 @@ extends Menu
var contributors := ["sofviic", "metamuffin", "nokoe", "tpart"]
var cc_0 := ["kenney.nl", "Kay Lousberg"]
var cc_by_3 := {
+ "Game_over.wav": "deleted_user_877451",
"Glasses": "Jeremy Edelblut"
}
var cc_by_4 := {
- "Universal UI/Menu Soundpack": "Ellr",
+ "Footstep sounds": "Dryoma",
+ "Page_Turn_24.wav": "Koops",
"Pencil, Writing, Close, A.wav": "InspectorJ",
- "Page_Turn_24.wav": "Koops"
+ "Super Dialogue Audio Pack": "Dillon Becker",
+ "Universal UI/Menu Soundpack": "Ellr",
+ "Woosh Fleuret Escrime B.WAV": "toyoto"
}
@onready var label = $MarginContainer/Panel/MarginContainer/VBoxContainer/RichTextLabel
diff --git a/client/menu/settings.gd b/client/menu/settings.gd
index 66b53f64..efd462ca 100644
--- a/client/menu/settings.gd
+++ b/client/menu/settings.gd
@@ -17,11 +17,7 @@ extends Menu
@onready var options: VBoxContainer = $OuterGap/Panel/InnerGap/VBoxContainer/ScrollContainer/Options
-var settings: Dictionary
-
func _on_back_pressed():
- for k in settings.keys():
- Global.set_setting(k, settings[k].get_value())
Global.save_settings()
Global.update_language()
Global.update_fullscreen()
@@ -36,21 +32,9 @@ func update_rows(fix_focus = false):
c.queue_free()
for k in Global.settings.keys():
- var row: SettingsRow = preload("res://menu/settings_row.tscn").instantiate()
- row.setup(k, Global.settings, Global.default_settings)
- row.connect("apply_preset", apply_preset)
+ var row: SettingsRow = Global.settings[k].get_row()
options.add_child(row)
- settings[k] = row
if fix_focus:
await get_tree().process_frame
Global.focus_first_button(self)
-
-func apply_preset(preset: Dictionary):
- for k in settings.keys():
- Global.set_setting(k, settings[k].get_value())
-
- for k in preset.keys():
- Global.set_setting(k, preset[k])
-
- update_rows(true)
diff --git a/client/menu/settings/dropdown_setting.gd b/client/menu/settings/dropdown_setting.gd
new file mode 100644
index 00000000..47f7355b
--- /dev/null
+++ b/client/menu/settings/dropdown_setting.gd
@@ -0,0 +1,40 @@
+# Undercooked - a game about cooking
+# Copyright 2024 nokoe
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License only.
+#
+# 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+class_name DropdownSetting
+extends GameSetting
+
+var options: Array
+
+func _init(new_description: String, new_preset: int, new_options: Array):
+ assert(new_preset < new_options.size())
+ super(new_description, new_preset)
+ options = new_options
+
+func _update_row():
+ super()
+ row.value_node = OptionButton.new()
+ for i in options:
+ row.value_node.add_item(i)
+ row.value_node.select(_value)
+
+func fetch_setting():
+ if row != null:
+ _value = row.value_node.selected
+
+func set_value(v):
+ super(v)
+ if row != null:
+ row.value_node.selected = _value
diff --git a/client/menu/settings/game_setting.gd b/client/menu/settings/game_setting.gd
new file mode 100644
index 00000000..67dca232
--- /dev/null
+++ b/client/menu/settings/game_setting.gd
@@ -0,0 +1,51 @@
+# Undercooked - a game about cooking
+# Copyright 2024 nokoe
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License only.
+#
+# 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+class_name GameSetting
+extends Object
+
+var preset
+var _value
+var description: String
+
+var row: SettingsRow
+
+func _init(new_description: String, new_preset):
+ _value = new_preset
+ preset = new_preset
+ description = new_description
+
+func reset():
+ set_value(preset)
+
+func get_row() -> SettingsRow:
+ _update_row()
+ return row
+
+func _update_row():
+ if row != null:
+ row.queue_free()
+ row = preload("res://menu/settings/settings_row.tscn").instantiate()
+ row.description = description
+ row.reset.connect(reset)
+
+func fetch_setting():
+ pass
+
+func get_value():
+ return _value
+
+func set_value(v):
+ _value = v
diff --git a/client/menu/settings/range_setting.gd b/client/menu/settings/range_setting.gd
new file mode 100644
index 00000000..97229db9
--- /dev/null
+++ b/client/menu/settings/range_setting.gd
@@ -0,0 +1,42 @@
+# Undercooked - a game about cooking
+# Copyright 2024 nokoe
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License only.
+#
+# 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+class_name RangeSetting
+extends GameSetting
+
+var min_value: float
+var max_value: float
+
+func _init(new_description: String, new_preset: float, new_min_value: float, new_max_value: float):
+ super(new_description, new_preset)
+ min_value = new_min_value
+ max_value = new_max_value
+
+func _update_row():
+ super()
+ row.value_node = HSlider.new()
+ row.value_node.min_value = min_value
+ row.value_node.max_value = max_value
+ row.value_node.tick_count = abs(max_value - min_value)
+ row.value_node.value = _value
+
+func fetch_setting():
+ if row != null:
+ _value = row.value_node.value
+
+func set_value(v):
+ super(v)
+ if row != null:
+ row.value_node.value = _value
diff --git a/client/menu/settings/settings_menu.gd b/client/menu/settings/settings_menu.gd
new file mode 100644
index 00000000..efd462ca
--- /dev/null
+++ b/client/menu/settings/settings_menu.gd
@@ -0,0 +1,40 @@
+# Undercooked - a game about cooking
+# Copyright 2024 metamuffin
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License only.
+#
+# 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+extends Menu
+
+@onready var options: VBoxContainer = $OuterGap/Panel/InnerGap/VBoxContainer/ScrollContainer/Options
+
+func _on_back_pressed():
+ Global.save_settings()
+ Global.update_language()
+ Global.update_fullscreen()
+ exit()
+
+func _ready():
+ super()
+ update_rows()
+
+func update_rows(fix_focus = false):
+ for c in options.get_children():
+ c.queue_free()
+
+ for k in Global.settings.keys():
+ var row: SettingsRow = Global.settings[k].get_row()
+ options.add_child(row)
+
+ if fix_focus:
+ await get_tree().process_frame
+ Global.focus_first_button(self)
diff --git a/client/menu/settings/settings_row.gd b/client/menu/settings/settings_row.gd
new file mode 100644
index 00000000..8c71a8c5
--- /dev/null
+++ b/client/menu/settings/settings_row.gd
@@ -0,0 +1,36 @@
+# Undercooked - a game about cooking
+# Copyright 2024 nokoe
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License only.
+#
+# 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+class_name SettingsRow
+extends PanelContainer
+
+signal reset()
+
+@onready var value_parent = $HBoxContainer/BoxContainer
+@onready var label = $HBoxContainer/Label
+
+var value_node: Node
+var description = tr("no value was given to the row")
+
+func _ready():
+ if value_node != null:
+ var c: Control = value_node
+ c.size_flags_vertical = Control.SIZE_EXPAND_FILL
+ c.size_flags_horizontal = Control.SIZE_EXPAND_FILL
+ label.text = description
+ value_parent.add_child(c)
+
+func _on_reset_pressed():
+ reset.emit()
diff --git a/client/menu/settings_row.tscn b/client/menu/settings/settings_row.tscn
index d08963d6..d9c1f215 100644
--- a/client/menu/settings_row.tscn
+++ b/client/menu/settings/settings_row.tscn
@@ -1,21 +1,21 @@
[gd_scene load_steps=6 format=3 uid="uid://o5e5vpem8w0k"]
-[ext_resource type="Theme" uid="uid://b0qmvo504e457" path="res://menu/theme/theme.tres" id="1_fk0r2"]
-[ext_resource type="Script" path="res://menu/settings_row.gd" id="1_lxjnc"]
-[ext_resource type="FontFile" uid="uid://5ixo6b3bd3km" path="res://menu/theme/font-josefin-sans.woff2" id="3_qh45r"]
+[ext_resource type="Theme" uid="uid://b0qmvo504e457" path="res://menu/theme/theme.tres" id="1_iij3k"]
+[ext_resource type="Script" path="res://menu/settings/settings_row.gd" id="2_l8i7p"]
+[ext_resource type="FontFile" uid="uid://5ixo6b3bd3km" path="res://menu/theme/font-josefin-sans.woff2" id="3_7k5da"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_pk3rs"]
content_margin_left = 16.0
[sub_resource type="FontVariation" id="FontVariation_o6i7s"]
-base_font = ExtResource("3_qh45r")
+base_font = ExtResource("3_7k5da")
[node name="SettingsRow" type="PanelContainer"]
offset_right = 105.0
offset_bottom = 23.0
size_flags_horizontal = 3
-theme = ExtResource("1_fk0r2")
-script = ExtResource("1_lxjnc")
+theme = ExtResource("1_iij3k")
+script = ExtResource("2_l8i7p")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 2
diff --git a/client/menu/settings/text_setting.gd b/client/menu/settings/text_setting.gd
new file mode 100644
index 00000000..c8aa49d4
--- /dev/null
+++ b/client/menu/settings/text_setting.gd
@@ -0,0 +1,38 @@
+# Undercooked - a game about cooking
+# Copyright 2024 nokoe
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License only.
+#
+# 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+class_name TextSetting
+extends GameSetting
+
+var placeholder: String
+
+func _init(new_description: String, new_preset: String, new_placeholder: String = ""):
+ super(new_description, new_preset)
+ placeholder = new_placeholder
+
+func _update_row():
+ super()
+ row.value_node = LineEdit.new()
+ row.value_node.text = _value
+ row.value_node.placeholder_text = placeholder
+
+func fetch_setting():
+ if row != null:
+ _value = row.value_node.text
+
+func set_value(v):
+ super(v)
+ if row != null:
+ row.value_node.text = _value
diff --git a/client/menu/settings/toggle_setting.gd b/client/menu/settings/toggle_setting.gd
new file mode 100644
index 00000000..90e42264
--- /dev/null
+++ b/client/menu/settings/toggle_setting.gd
@@ -0,0 +1,34 @@
+# Undercooked - a game about cooking
+# Copyright 2024 nokoe
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License only.
+#
+# 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+class_name ToggleSetting
+extends GameSetting
+
+func _init(new_description: String, new_preset: bool):
+ super(new_description, new_preset)
+
+func fetch_setting():
+ if row != null:
+ _value = row.value_node.button_pressed
+
+func _update_row():
+ super()
+ row.value_node = CheckButton.new()
+ row.value_node.button_pressed = _value
+
+func set_value(v):
+ super(v)
+ if row != null:
+ row.value_node.button_pressed = _value
diff --git a/client/menu/settings_row.gd b/client/menu/settings_row.gd
deleted file mode 100644
index d57bbee0..00000000
--- a/client/menu/settings_row.gd
+++ /dev/null
@@ -1,91 +0,0 @@
-class_name SettingsRow
-extends PanelContainer
-
-signal apply_preset
-
-@onready var value_parent = $HBoxContainer/BoxContainer
-@onready var label = $HBoxContainer/Label
-
-var setting
-var default
-var value_node
-var description = tr("no value was given to the row")
-
-func setup(key: String, dict: Dictionary, defaults: Dictionary):
- setting = dict[key]
- description = setting["description"]
- var value = setting["value"]
- default = defaults[key]["value"]
- match setting["type"]:
- "toggle":
- value_node = CheckButton.new()
- value_node.button_pressed = value
- "line":
- value_node = LineEdit.new()
- value_node.text = value
- if default != "":
- value_node.placeholder_text = default
- else:
- value_node.placeholder_text = description
- "dropdown":
- value_node = OptionButton.new()
- for i in setting["options"]:
- value_node.add_item(i)
- value_node.select(value)
- "dropdown_preset":
- value_node = OptionButton.new()
- for i in setting["options"]:
- value_node.add_item(i)
- value_node.select(value)
- value_node.connect("item_selected", apply.bind(Global.get(setting["apply"])))
- "range":
- value_node = HSlider.new()
- value_node.min_value = setting["min"]
- value_node.max_value = setting["max"]
- value_node.tick_count = abs(setting["max"] - setting["min"])
- value_node.value = value
- _:
- push_error("Could not set up SettingsRow: Unknown setting type \"%s\"" % setting["type"])
-
-func _ready():
- if value_node != null:
- var c: Control = value_node
- c.size_flags_vertical = Control.SIZE_EXPAND_FILL
- c.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- label.text = description
- value_parent.add_child(c)
-
-func apply(idx: int, apply: Array):
- emit_signal("apply_preset", apply[idx])
-
-func get_value():
- if value_node != null:
- if value_node is CheckButton:
- return value_node.button_pressed
- elif value_node is LineEdit:
- return value_node.text
- elif value_node is OptionButton:
- return value_node.selected
- elif value_node is HSlider:
- return value_node.value
- else:
- push_error("get_value() failed for unknown node type: %s" % value_node)
- return null
- else:
- return null
-
-func _on_reset_pressed():
- match setting["type"]:
- "toggle":
- value_node.button_pressed = default
- "line":
- value_node.text = default
- "dropdown":
- value_node.select(default)
- "dropdown_preset":
- value_node.select(default)
- value_node.emit_signal("item_selected", value_node.selected)
- "range":
- value_node.value = default
- _:
- push_error("Could not reset setting: Unknown setting type \"%s\"" % setting["type"])
diff --git a/client/menu/setup.gd b/client/menu/setup.gd
index 565753d8..c5080920 100644
--- a/client/menu/setup.gd
+++ b/client/menu/setup.gd
@@ -43,7 +43,7 @@ func _on_sign_pressed():
Global.profile["username"] = username.text
Global.profile["character"] = character
- Global.settings["setup_complete"]["value"] = true
+ Global.set_setting("setup_complete", true)
Global.save_profile()
Global.save_settings()
$SceneTransition.transition_to("res://menu/menu_manager.tscn")
diff --git a/client/menu/sounds/failure.ogg b/client/menu/sounds/failure.ogg
new file mode 100644
index 00000000..cbe6db14
--- /dev/null
+++ b/client/menu/sounds/failure.ogg
Binary files differ
diff --git a/client/menu/sounds/failure.ogg.import b/client/menu/sounds/failure.ogg.import
new file mode 100644
index 00000000..78800693
--- /dev/null
+++ b/client/menu/sounds/failure.ogg.import
@@ -0,0 +1,19 @@
+[remap]
+
+importer="oggvorbisstr"
+type="AudioStreamOggVorbis"
+uid="uid://cv4isy6po6pqd"
+path="res://.godot/imported/failure.ogg-4b523df8a2a2485852fc3b46f038f1af.oggvorbisstr"
+
+[deps]
+
+source_file="res://menu/sounds/failure.ogg"
+dest_files=["res://.godot/imported/failure.ogg-4b523df8a2a2485852fc3b46f038f1af.oggvorbisstr"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/client/menu/sounds/success.ogg b/client/menu/sounds/success.ogg
index 590c7dab..37cd2bcd 100644
--- a/client/menu/sounds/success.ogg
+++ b/client/menu/sounds/success.ogg
Binary files differ
diff --git a/client/player/angry.svg.import b/client/player/angry.svg.import
new file mode 100644
index 00000000..4f1afd25
--- /dev/null
+++ b/client/player/angry.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dk36vvlrg0t15"
+path="res://.godot/imported/angry.svg-20686ccd97ba20a3d660573cae3108bc.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://player/angry.svg"
+dest_files=["res://.godot/imported/angry.svg-20686ccd97ba20a3d660573cae3108bc.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/client/player/angry.tscn b/client/player/angry.tscn
new file mode 100644
index 00000000..56fa4d05
--- /dev/null
+++ b/client/player/angry.tscn
@@ -0,0 +1,37 @@
+[gd_scene load_steps=6 format=3 uid="uid://cvty1rwt52anq"]
+
+[ext_resource type="Texture2D" uid="uid://unjbxplj845n" path="res://player/angry.webp" id="1_5op6v"]
+
+[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ysmnk"]
+transparency = 1
+shading_mode = 0
+vertex_color_use_as_albedo = true
+albedo_texture = ExtResource("1_5op6v")
+billboard_mode = 2
+billboard_keep_scale = true
+
+[sub_resource type="QuadMesh" id="QuadMesh_5nim7"]
+material = SubResource("StandardMaterial3D_ysmnk")
+
+[sub_resource type="Curve" id="Curve_0rju1"]
+_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.51927, 1), 0.0, 0.0, 0, 0]
+point_count = 2
+
+[sub_resource type="Gradient" id="Gradient_lmymu"]
+offsets = PackedFloat32Array(0, 0.711828, 1)
+colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
+
+[node name="Angry" type="CPUParticles3D"]
+emitting = false
+amount = 5
+lifetime = 2.0
+one_shot = true
+explosiveness = 1.0
+mesh = SubResource("QuadMesh_5nim7")
+direction = Vector3(0, 1, 0)
+spread = 30.0
+gravity = Vector3(0, 0, 0)
+initial_velocity_min = 1.0
+initial_velocity_max = 1.5
+scale_amount_curve = SubResource("Curve_0rju1")
+color_ramp = SubResource("Gradient_lmymu")
diff --git a/client/player/angry.webp b/client/player/angry.webp
new file mode 100644
index 00000000..866ba92c
--- /dev/null
+++ b/client/player/angry.webp
Binary files differ
diff --git a/client/player/angry.webp.import b/client/player/angry.webp.import
new file mode 100644
index 00000000..989ff542
--- /dev/null
+++ b/client/player/angry.webp.import
@@ -0,0 +1,35 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://unjbxplj845n"
+path.s3tc="res://.godot/imported/angry.webp-0f7d45c1cfc32a18650521cc19587d16.s3tc.ctex"
+metadata={
+"imported_formats": ["s3tc_bptc"],
+"vram_texture": true
+}
+
+[deps]
+
+source_file="res://player/angry.webp"
+dest_files=["res://.godot/imported/angry.webp-0f7d45c1cfc32a18650521cc19587d16.s3tc.ctex"]
+
+[params]
+
+compress/mode=2
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=true
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=0
diff --git a/client/player/character/character.gd b/client/player/character/character.gd
index 36ff1323..11db638f 100644
--- a/client/player/character/character.gd
+++ b/client/player/character/character.gd
@@ -39,6 +39,9 @@ var current_animation := "idle"
"E. Parsley": $Main/Head/Hair3
}
+@onready var step_sounds: PlayRandom = $Steps
+@onready var boost_sounds: PlayRandom = $Boosts
+
func _ready():
play_animation("idle")
@@ -61,7 +64,11 @@ func _process(delta):
next_animation = "idle"
walking_particles.emitting = walking
- boosting_particles.emitting = boosting and walking and not was_boosting
+ if boosting and walking and not was_boosting:
+ boosting_particles.emitting = true
+ boost_sounds.play_random()
+ else:
+ boosting_particles.emitting = false
was_boosting = boosting and walking
if current_animation != next_animation:
@@ -81,6 +88,11 @@ func select_hairstyle(id: int):
func play_animation(name_: String):
current_animation = name_
hand_animations.play(name_)
+
+ if name_ == "walk":
+ step_sounds.start_autoplay()
+ else:
+ step_sounds.stop_autoplay()
func _on_hand_animations_animation_finished(_name):
hand_animations.play(current_animation)
diff --git a/client/player/character/character.tscn b/client/player/character/character.tscn
index e4a2af66..f09ec2cf 100644
--- a/client/player/character/character.tscn
+++ b/client/player/character/character.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=18 format=3 uid="uid://b3hhir2fvnunu"]
+[gd_scene load_steps=24 format=3 uid="uid://b3hhir2fvnunu"]
[ext_resource type="Script" path="res://player/character/character.gd" id="1_12lbh"]
[ext_resource type="ArrayMesh" uid="uid://bnmm01yjwultj" path="res://player/character/main.res" id="2_lxdbd"]
@@ -9,6 +9,12 @@
[ext_resource type="ArrayMesh" uid="uid://dx7jswwaesok4" path="res://player/character/hair_2.res" id="7_0551e"]
[ext_resource type="ArrayMesh" uid="uid://c2qnwt44x8ujl" path="res://player/character/tie.res" id="7_knv6q"]
[ext_resource type="ArrayMesh" uid="uid://c5qsthvtf3cta" path="res://player/character/hair_3.res" id="8_2bc5u"]
+[ext_resource type="AudioStream" uid="uid://bxiorkb4xb8t1" path="res://player/sounds/step1.ogg" id="10_qpd6x"]
+[ext_resource type="AudioStream" uid="uid://l2fd8u7rq3cq" path="res://player/sounds/step2.ogg" id="11_2dmo8"]
+[ext_resource type="AudioStream" uid="uid://d353uwy83crca" path="res://player/sounds/step3.ogg" id="12_bj5ue"]
+[ext_resource type="Script" path="res://audio/play_random.gd" id="14_3rb6x"]
+[ext_resource type="AudioStream" uid="uid://1jsqpnk3igj3" path="res://player/sounds/woosh1.ogg" id="14_ikcec"]
+[ext_resource type="AudioStream" uid="uid://cwme7eatip0jc" path="res://player/sounds/woosh2.ogg" id="15_iv4wu"]
[sub_resource type="Animation" id="Animation_tdhvg"]
length = 0.001
@@ -655,4 +661,29 @@ scale_amount_min = 0.5
scale_amount_max = 0.75
scale_amount_curve = SubResource("Curve_7ml8g")
+[node name="Steps" type="Node3D" parent="."]
+script = ExtResource("14_3rb6x")
+volume_db = -12.0
+enable_attenuations = false
+
+[node name="Step1" type="AudioStreamPlayer3D" parent="Steps"]
+stream = ExtResource("10_qpd6x")
+
+[node name="Step2" type="AudioStreamPlayer3D" parent="Steps"]
+stream = ExtResource("11_2dmo8")
+
+[node name="Step3" type="AudioStreamPlayer3D" parent="Steps"]
+stream = ExtResource("12_bj5ue")
+
+[node name="Boosts" type="Node3D" parent="."]
+script = ExtResource("14_3rb6x")
+volume_db = -12.0
+enable_attenuations = false
+
+[node name="Woosh1" type="AudioStreamPlayer3D" parent="Boosts"]
+stream = ExtResource("14_ikcec")
+
+[node name="Woosh2" type="AudioStreamPlayer3D" parent="Boosts"]
+stream = ExtResource("15_iv4wu")
+
[connection signal="animation_finished" from="HandAnimations" to="." method="_on_hand_animations_animation_finished"]
diff --git a/client/player/effect.gd b/client/player/effect.gd
index ae6a6756..8371d99d 100644
--- a/client/player/effect.gd
+++ b/client/player/effect.gd
@@ -1,5 +1,5 @@
# Undercooked - a game about cooking
-# Copyright 2024 nokoe
+# Copyright 2024 nokoe, tpart
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
@@ -17,13 +17,22 @@ class_name Effect
extends Node3D
@onready var success = $Success
+@onready var failure = $Failure
+@onready var angry_grunt: PlayRandom = $AngryGrunt
+@onready var stars = $Stars
+@onready var angry = $Angry
+
func set_effect(e: String):
clear_effect()
match e:
"satisfied":
- $Stars.emitting = true
+ stars.emitting = true
success.play()
+ "angry":
+ angry.emitting = true
+ angry_grunt.play_random()
+ failure.play()
_:
push_warning("effect %s unknown" % e)
diff --git a/client/player/effect.tscn b/client/player/effect.tscn
index fec019c2..748aa20e 100644
--- a/client/player/effect.tscn
+++ b/client/player/effect.tscn
@@ -1,8 +1,13 @@
-[gd_scene load_steps=4 format=3 uid="uid://dn2ne30t81ame"]
+[gd_scene load_steps=9 format=3 uid="uid://dn2ne30t81ame"]
[ext_resource type="Script" path="res://player/effect.gd" id="1_aqsk6"]
[ext_resource type="PackedScene" uid="uid://yaed1vnhd0aa" path="res://player/stars.tscn" id="2_shb5l"]
[ext_resource type="AudioStream" uid="uid://camy77x26mmpv" path="res://menu/sounds/success.ogg" id="3_favyn"]
+[ext_resource type="AudioStream" uid="uid://cv4isy6po6pqd" path="res://menu/sounds/failure.ogg" id="4_j38qf"]
+[ext_resource type="PackedScene" uid="uid://cvty1rwt52anq" path="res://player/angry.tscn" id="4_uxxex"]
+[ext_resource type="Script" path="res://audio/play_random.gd" id="5_t2upj"]
+[ext_resource type="AudioStream" uid="uid://c3gatgrsb0npf" path="res://player/sounds/angry1.ogg" id="6_ou7uy"]
+[ext_resource type="AudioStream" uid="uid://cty282m6ckt62" path="res://player/sounds/angry2.ogg" id="7_r21iy"]
[node name="Effect" type="Node3D"]
script = ExtResource("1_aqsk6")
@@ -12,3 +17,21 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
[node name="Success" type="AudioStreamPlayer" parent="."]
stream = ExtResource("3_favyn")
+
+[node name="Failure" type="AudioStreamPlayer" parent="."]
+stream = ExtResource("4_j38qf")
+volume_db = -8.0
+
+[node name="Angry" parent="." instance=ExtResource("4_uxxex")]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
+
+[node name="AngryGrunt" type="Node3D" parent="."]
+script = ExtResource("5_t2upj")
+volume_db = -8.0
+enable_attenuations = false
+
+[node name="Angry1" type="AudioStreamPlayer3D" parent="AngryGrunt"]
+stream = ExtResource("6_ou7uy")
+
+[node name="Angry2" type="AudioStreamPlayer3D" parent="AngryGrunt"]
+stream = ExtResource("7_r21iy")
diff --git a/client/player/player.gd b/client/player/player.gd
index 33606bc4..1df80d94 100644
--- a/client/player/player.gd
+++ b/client/player/player.gd
@@ -91,10 +91,12 @@ func take_item(tile: Tile):
if hand != null:
push_error("already holding an item")
var i = tile.take_item()
+ i.take()
set_item(i)
func put_item(tile: Tile):
var i = remove_item()
+ i.put()
tile.put_item(i)
func _process(delta):
diff --git a/client/player/sounds/angry1.ogg b/client/player/sounds/angry1.ogg
new file mode 100644
index 00000000..9876f3da
--- /dev/null
+++ b/client/player/sounds/angry1.ogg
Binary files differ
diff --git a/client/player/sounds/angry1.ogg.import b/client/player/sounds/angry1.ogg.import
new file mode 100644
index 00000000..1fbbfb2e
--- /dev/null
+++ b/client/player/sounds/angry1.ogg.import
@@ -0,0 +1,19 @@
+[remap]
+
+importer="oggvorbisstr"
+type="AudioStreamOggVorbis"
+uid="uid://c3gatgrsb0npf"
+path="res://.godot/imported/angry1.ogg-89dfe7562e07a5f538e60fe56615fd53.oggvorbisstr"
+
+[deps]
+
+source_file="res://player/sounds/angry1.ogg"
+dest_files=["res://.godot/imported/angry1.ogg-89dfe7562e07a5f538e60fe56615fd53.oggvorbisstr"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/client/player/sounds/angry2.ogg b/client/player/sounds/angry2.ogg
new file mode 100644
index 00000000..805b6c48
--- /dev/null
+++ b/client/player/sounds/angry2.ogg
Binary files differ
diff --git a/client/player/sounds/angry2.ogg.import b/client/player/sounds/angry2.ogg.import
new file mode 100644
index 00000000..fb529c5c
--- /dev/null
+++ b/client/player/sounds/angry2.ogg.import
@@ -0,0 +1,19 @@
+[remap]
+
+importer="oggvorbisstr"
+type="AudioStreamOggVorbis"
+uid="uid://cty282m6ckt62"
+path="res://.godot/imported/angry2.ogg-cc281b5bbc23e0a935c56ccbfcbd60a0.oggvorbisstr"
+
+[deps]
+
+source_file="res://player/sounds/angry2.ogg"
+dest_files=["res://.godot/imported/angry2.ogg-cc281b5bbc23e0a935c56ccbfcbd60a0.oggvorbisstr"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/client/player/sounds/step1.ogg b/client/player/sounds/step1.ogg
new file mode 100644
index 00000000..563d6444
--- /dev/null
+++ b/client/player/sounds/step1.ogg
Binary files differ
diff --git a/client/player/sounds/step1.ogg.import b/client/player/sounds/step1.ogg.import
new file mode 100644
index 00000000..409919f6
--- /dev/null
+++ b/client/player/sounds/step1.ogg.import
@@ -0,0 +1,19 @@
+[remap]
+
+importer="oggvorbisstr"
+type="AudioStreamOggVorbis"
+uid="uid://bxiorkb4xb8t1"
+path="res://.godot/imported/step1.ogg-fb18c712af8c20437bc3716795beb323.oggvorbisstr"
+
+[deps]
+
+source_file="res://player/sounds/step1.ogg"
+dest_files=["res://.godot/imported/step1.ogg-fb18c712af8c20437bc3716795beb323.oggvorbisstr"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/client/player/sounds/step2.ogg b/client/player/sounds/step2.ogg
new file mode 100644
index 00000000..a6ec7103
--- /dev/null
+++ b/client/player/sounds/step2.ogg
Binary files differ
diff --git a/client/player/sounds/step2.ogg.import b/client/player/sounds/step2.ogg.import
new file mode 100644
index 00000000..2a6f9789
--- /dev/null
+++ b/client/player/sounds/step2.ogg.import
@@ -0,0 +1,19 @@
+[remap]
+
+importer="oggvorbisstr"
+type="AudioStreamOggVorbis"
+uid="uid://l2fd8u7rq3cq"
+path="res://.godot/imported/step2.ogg-cac7b3cbd2fc698c0ac3ca59fb818e5d.oggvorbisstr"
+
+[deps]
+
+source_file="res://player/sounds/step2.ogg"
+dest_files=["res://.godot/imported/step2.ogg-cac7b3cbd2fc698c0ac3ca59fb818e5d.oggvorbisstr"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/client/player/sounds/step3.ogg b/client/player/sounds/step3.ogg
new file mode 100644
index 00000000..27dfa368
--- /dev/null
+++ b/client/player/sounds/step3.ogg
Binary files differ
diff --git a/client/player/sounds/step3.ogg.import b/client/player/sounds/step3.ogg.import
new file mode 100644
index 00000000..c01a5b7d
--- /dev/null
+++ b/client/player/sounds/step3.ogg.import
@@ -0,0 +1,19 @@
+[remap]
+
+importer="oggvorbisstr"
+type="AudioStreamOggVorbis"
+uid="uid://d353uwy83crca"
+path="res://.godot/imported/step3.ogg-2d825d8675e6dad3253d34dfcabf3b0e.oggvorbisstr"
+
+[deps]
+
+source_file="res://player/sounds/step3.ogg"
+dest_files=["res://.godot/imported/step3.ogg-2d825d8675e6dad3253d34dfcabf3b0e.oggvorbisstr"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/client/player/sounds/woosh1.ogg b/client/player/sounds/woosh1.ogg
new file mode 100644
index 00000000..284fc480
--- /dev/null
+++ b/client/player/sounds/woosh1.ogg
Binary files differ
diff --git a/client/player/sounds/woosh1.ogg.import b/client/player/sounds/woosh1.ogg.import
new file mode 100644
index 00000000..38b1c435
--- /dev/null
+++ b/client/player/sounds/woosh1.ogg.import
@@ -0,0 +1,19 @@
+[remap]
+
+importer="oggvorbisstr"
+type="AudioStreamOggVorbis"
+uid="uid://1jsqpnk3igj3"
+path="res://.godot/imported/woosh1.ogg-1f4b2fe1be72c87cf944d6c0761e71c8.oggvorbisstr"
+
+[deps]
+
+source_file="res://player/sounds/woosh1.ogg"
+dest_files=["res://.godot/imported/woosh1.ogg-1f4b2fe1be72c87cf944d6c0761e71c8.oggvorbisstr"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/client/player/sounds/woosh2.ogg b/client/player/sounds/woosh2.ogg
new file mode 100644
index 00000000..0a94ec9a
--- /dev/null
+++ b/client/player/sounds/woosh2.ogg
Binary files differ
diff --git a/client/player/sounds/woosh2.ogg.import b/client/player/sounds/woosh2.ogg.import
new file mode 100644
index 00000000..c38bf1fe
--- /dev/null
+++ b/client/player/sounds/woosh2.ogg.import
@@ -0,0 +1,19 @@
+[remap]
+
+importer="oggvorbisstr"
+type="AudioStreamOggVorbis"
+uid="uid://cwme7eatip0jc"
+path="res://.godot/imported/woosh2.ogg-adc164c3f2035f82c8c508e981753d03.oggvorbisstr"
+
+[deps]
+
+source_file="res://player/sounds/woosh2.ogg"
+dest_files=["res://.godot/imported/woosh2.ogg-adc164c3f2035f82c8c508e981753d03.oggvorbisstr"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4