Huge changes

Implemented spawn points correctly.
Added saving & loading (currently only implemented with the spawn_index).
You can now set spawn indicies in the DynamicAreaLoader to automatically load when the game is set to that value (on ready).
Added configuration warnings to DynamicAreaLoader & PlayerSpawnPoint

Added some generic translation (pot) files.
Added AudioManager autoload to play, stop, fade audio streams (and set the bus directly).
Added SceneFader autoload.
Added SaveManager autoload.
Added OptionsMenu with currently only volume sliders and a fullscreen toggle button.
Added PauseMenu
This commit is contained in:
SchimmelSpreu83 2025-03-01 13:28:21 +01:00
parent 7bd8e95c0d
commit c7f96c78c4
52 changed files with 1448 additions and 141 deletions

View File

@ -18,20 +18,21 @@ func _ready() -> void:
func _physics_process(delta: float) -> void:
# Don't process if it isn't necessary.
if not is_instance_valid(character):
return
if audio_player.is_empty():
# Don't process if it isn't necessary.
return
var on_floor: bool = character.is_on_floor()
if on_floor:
if _was_in_air:
# We landed. Play a footstep.
play_footstep()
_distance_traveled = 0.0
var velocity: Vector3 = abs(character.velocity) #+ (abs(character.get_platform_velocity()) if not character.velocity.is_zero_approx() else Vector3.ZERO)
var velocity: Vector3 = abs(character.velocity)
velocity.y = 0.0
if velocity.is_zero_approx():

View File

@ -17,6 +17,15 @@ var has_control: bool = true
func _ready() -> void:
GameGlobals.player = self
if not get_tree().root.is_node_ready():
await get_tree().root.ready
var spawn_point := PlayerSpawnPoint.get_spawn_point_by_index(GameGlobals.spawn_index)
if is_instance_valid(spawn_point):
global_position = spawn_point.global_position
head.global_rotation = spawn_point.global_rotation
func _physics_process(delta: float) -> void:
# Add the gravity.

View File

@ -1,3 +1,4 @@
@tool
@icon("dynamic_area_loader.svg")
class_name DynamicAreaLoader3D
extends Area3D
@ -16,7 +17,10 @@ signal load_finished(loaded_node: Node)
## The node to load and add.[br][br]
## [b]IMPORTANT:[/b] The node needs to be marked as [b]Load as Placeholder[/b], otherwise nothing
## happens when loading (see [InstancePlaceholder]).
@export var placeholder_node: Node
@export var placeholder_node: Node:
set(value):
placeholder_node = value
update_configuration_warnings()
## If [code]true[/code], the actual loading will be done separately in a thread.[br]
## This prevents the game from freezing for a moment when loading a large scene.[br]
## However, loading can be slower on lower-end hardware.
@ -25,22 +29,34 @@ signal load_finished(loaded_node: Node)
## when the [PlayerCharacter] exits this area.[br]This is to prevent the [PlayerCharacter]
## from keep re-loading the area by just walking back and fourth through the load zones.
@export_range(0.0, 10.0, 0.01, "or_greater", "suffix:s") var keep_loaded_duration: float = 3.0
## Automatically load the area when entering the scene tree, if the [member GameGlobals.spawn_point]
## is set to any of these values.
@export var loaded_if_spawnpoint: Array[int] = []
## The reference to the currently loaded node that was loaded.
var loaded_node: Node
func _ready() -> void:
if Engine.is_editor_hint():
return
if loaded_if_spawnpoint.has(GameGlobals.spawn_index):
load_area(null, true)
body_entered.connect(_on_body_entered)
body_exited.connect(_on_body_exited)
## Instances the area defined by [member placeholder_node].[br]
## See [method load_area_threaded] if you want to load the area in a thread instead
## of having a freeze during load.
func load_area(custom_scene: PackedScene = null) -> void:
if is_instance_valid(placeholder_node) and placeholder_node is InstancePlaceholder:
if is_instance_valid(loaded_node) or not overlaps_body(GameGlobals.get_player()):
## of having a freeze during load.[br][br]
## If [param forced] is [code]true[/code], don't check if the player is colliding when calling this function.
func load_area(custom_scene: PackedScene = null, forced: bool = false) -> void:
assert(is_instance_valid(placeholder_node), "[placeholder_node] needs to be set.")
assert(placeholder_node is InstancePlaceholder, "[placeholder_node] needs to be marked as 'Load As Placeholder'.")
if is_instance_valid(loaded_node) or (not forced and not overlaps_body(GameGlobals.get_player())):
return
loaded_node = placeholder_node.create_instance(false, custom_scene)
@ -49,13 +65,11 @@ func load_area(custom_scene: PackedScene = null) -> void:
## Loads the scene defined in
## [member placeholder_node] ([member InstancePlaceholder.get_instance_path]) threaded.[br]
## Calls [method load_area] with the [param custom_scene] set to the loaded scene.
func load_area_threaded() -> void:
if is_instance_valid(loaded_node):
return
if not is_instance_valid(placeholder_node) or placeholder_node is not InstancePlaceholder:
return
## Calls [method load_area] with the [param custom_scene] set to the loaded scene.[br][br]
## [param forced] does the same thing as in [method load_area].
func load_area_threaded(forced: bool = false) -> void:
assert(is_instance_valid(placeholder_node), "[placeholder_node] needs to be set.")
assert(placeholder_node is InstancePlaceholder, "[placeholder_node] needs to be marked as 'Load As Placeholder'.")
placeholder_node = placeholder_node as InstancePlaceholder
@ -70,7 +84,7 @@ func load_area_threaded() -> void:
var scene: PackedScene = ResourceLoader.load_threaded_get(path)
load_area(scene)
load_area(scene, forced)
## Unloads ([method Node.queue_free]) the [member loaded_node].[br]
@ -104,3 +118,14 @@ func _on_body_entered(body: Node3D) -> void:
func _on_body_exited(body: Node3D) -> void:
if body == GameGlobals.get_player():
unload_area()
func _get_configuration_warnings() -> PackedStringArray:
if not is_instance_valid(placeholder_node):
return ["'placeholder_node' is not set."]
# TODO: Find a way to detect that in the editor.
if placeholder_node is not InstancePlaceholder and false:
return ["'placeholder_node' needs to be marked as 'Load As Placeholder'"]
return []

View File

@ -1,6 +1,8 @@
class_name InteractiveLoader
extends Node
var load_progress: Array = []
func load_threaded(path: String) -> Resource:
if not is_inside_tree():
@ -14,7 +16,7 @@ func load_threaded(path: String) -> Resource:
ResourceLoader.load_threaded_request(path, "", false, ResourceLoader.CACHE_MODE_REUSE)
while ResourceLoader.load_threaded_get_status(path) != ResourceLoader.THREAD_LOAD_LOADED:
match ResourceLoader.load_threaded_get_status(path):
match ResourceLoader.load_threaded_get_status(path, load_progress):
ResourceLoader.THREAD_LOAD_FAILED || ResourceLoader.THREAD_LOAD_INVALID_RESOURCE:
Logger.print_msg("[Interactive Loader] load failed.", -1.0, Logger.ErrTypes.WARNING)
return null

View File

@ -3,8 +3,22 @@ class_name PlayerSpawnPoint
extends Marker3D
@export var spawn_index: int = 0: set = set_spawn_index
@export_tool_button("Set unique index") var set_unique_index: Callable = func() -> void:
for spawn_point: PlayerSpawnPoint in spawn_points:
if spawn_point == self:
continue
if spawn_point.spawn_index == spawn_index:
set_spawn_index(spawn_index + 1)
set_unique_index.call()
return
update_configuration_warnings()
@export var editor_auto_assign_unique_id: bool = true
static var spawn_points: Array[PlayerSpawnPoint] = []
var idx_label: Label3D
var config_warnings_hint: Label3D
func _init() -> void:
@ -12,17 +26,78 @@ func _init() -> void:
var player_scene: PackedScene = load("res://components/characters/player/player_character.tscn")
add_child(player_scene.instantiate(), false, Node.INTERNAL_MODE_FRONT)
# Setup label.
# Setup labels.
idx_label = Label3D.new()
idx_label.billboard = BaseMaterial3D.BILLBOARD_ENABLED
idx_label.shaded = false
idx_label.font_size = 64
add_child(idx_label, false, Node.INTERNAL_MODE_FRONT)
idx_label.position.y = 1.8
set_spawn_index(spawn_index)
config_warnings_hint = Label3D.new()
config_warnings_hint.billboard = BaseMaterial3D.BILLBOARD_ENABLED
config_warnings_hint.shaded = false
config_warnings_hint.no_depth_test = true
config_warnings_hint.fixed_size = true
config_warnings_hint.text = "!"
config_warnings_hint.modulate = Color.RED
add_child(config_warnings_hint, false, Node.INTERNAL_MODE_FRONT)
config_warnings_hint.position.y = 1.0
var tween: Tween = create_tween().set_loops()
tween.tween_property(config_warnings_hint, ^"scale", Vector3.ONE * 1.5, 0.075)
tween.tween_property(config_warnings_hint, ^"scale", Vector3.ONE * 1.0, 0.075)
update_configuration_warnings()
func _enter_tree() -> void:
if not spawn_points.has(self):
spawn_points.append(self)
if editor_auto_assign_unique_id and Engine.is_editor_hint():
set_unique_index.call_deferred()
func _exit_tree() -> void:
spawn_points.erase(self)
func set_spawn_index(index: int) -> void:
spawn_index = index
update_configuration_warnings()
if is_instance_valid(idx_label):
idx_label.text = str(spawn_index)
func make_current(do_autosave: bool = true) -> void:
GameGlobals.spawn_index = spawn_index
if do_autosave:
SaveManager.save_game()
static func get_spawn_point_by_index(index: int) -> PlayerSpawnPoint:
for spawn_point: PlayerSpawnPoint in PlayerSpawnPoint.spawn_points:
if spawn_point.spawn_index == index:
return spawn_point
return null
func _get_configuration_warnings() -> PackedStringArray:
var warnings: PackedStringArray = []
for spawn_point: PlayerSpawnPoint in spawn_points:
if spawn_point.spawn_index == spawn_index and spawn_point != self:
warnings.append(str(spawn_point, " has the same spawn index as us."))
spawn_point.config_warnings_hint.show()
spawn_point.update_configuration_warnings()
if warnings.is_empty():
config_warnings_hint.hide()
return warnings

View File

@ -5,6 +5,10 @@ extends Node3D
@onready var saw_skin: Node3D = $SawSkin
func _ready() -> void:
saw_skin.rotation.z = randf() * TAU
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _physics_process(delta: float) -> void:
saw_skin.rotate_z(spin_speed * delta)

View File

@ -3,5 +3,15 @@ extends Control
@onready var shader_precompiler: Node = $ShaderPrecompiler
func _ready() -> void:
if SettingsManager.get_setting(&"game", &"has_compiled_shaders"):
shader_precompiler.canvas_layer.hide()
_on_shader_precompiler_finished_compilation()
else:
await get_tree().create_timer(1.0).timeout
shader_precompiler.precompile_shaders()
func _on_shader_precompiler_finished_compilation() -> void:
get_tree().quit()
SettingsManager.set_setting(&"game", &"has_compiled_shaders", true)
SceneFader.load_to_path(GameGlobals.MAIN_MENU_PATH)

View File

@ -4,18 +4,13 @@ signal finished_compilation
const EXCLUDED_DIRECTORIES: Array[String] = [
"res://addons",
"res://.godot"
"res://.godot",
]
#const SIMUTANEOUS_SCENES: int = 5
@onready var progress_bar: ProgressBar = %ProgressBar
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
await get_tree().create_timer(1.0).timeout
precompile_shaders()
@onready var canvas_layer: CanvasLayer = $CanvasLayer
func precompile_shaders() -> void:

View File

@ -0,0 +1,19 @@
class_name LoadingScreen
extends MenuBase
var _interactive_loader: InteractiveLoader
@onready var progress_bar: ProgressBar = %ProgressBar
func _process(_delta: float) -> void:
if is_instance_valid(_interactive_loader) and not _interactive_loader.load_progress.is_empty():
progress_bar.value = _interactive_loader.load_progress.front()
func load_scene(path: String) -> PackedScene:
_interactive_loader = InteractiveLoader.new()
add_child(_interactive_loader)
var resource: Object = await _interactive_loader.load_threaded(path)
_interactive_loader.queue_free()
return resource

View File

@ -0,0 +1 @@
uid://tmo4wscguj62

View File

@ -0,0 +1,30 @@
[gd_scene load_steps=2 format=3 uid="uid://buvus4ym83wa8"]
[ext_resource type="Script" uid="uid://tmo4wscguj62" path="res://components/ui/menus/loading_screen/loading_screen.gd" id="1_1gk3q"]
[node name="LoadingScreen" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_1gk3q")
metadata/_custom_type_script = "uid://crdgxvb8i0cif"
[node name="ProgressBar" type="ProgressBar" parent="."]
unique_name_in_owner = true
custom_minimum_size = Vector2(512, 0)
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -2.0
offset_top = -13.5
offset_right = 2.0
offset_bottom = 13.5
grow_horizontal = 2
grow_vertical = 2
max_value = 1.0

View File

@ -1,10 +1,61 @@
extends MenuBase
class_name MainMenu
extends Node
const AMBIENCE_STREAM: AudioStream = preload("res://Dark House.wav")
@onready var continue_button: Button = %ContinueButton
@onready var new_game_button: Button = %NewGameButton
@onready var quit_button: Button = %QuitButton
@onready var options_menu: Control = $OptionsMenu
@onready var main_menu_ui: Control = $MainMenuUI
func _ready() -> void:
continue_button.disabled = not SaveManager.save_exists()
func _on_play_button_pressed() -> void:
pass # Replace with function body.
AudioManager.play_audio(AMBIENCE_STREAM, AudioManager.MUSIC)
func _unhandled_input(event: InputEvent) -> void:
if options_menu.is_visible_in_tree() and event.is_action_pressed(&"pause"):
main_menu_ui.show()
options_menu.hide()
func load_game() -> void:
AudioManager.fade_audio(AMBIENCE_STREAM, -80.0, SceneFader.fade_in_duration, AudioManager.MUSIC, true)
SceneFader.load_to_path(GameGlobals.GAME_PATH)
func _on_new_game_button_pressed() -> void:
if SceneFader.is_fading:
return
GameGlobals.reset_game()
SaveManager.delete_save()
SaveManager.save_game()
load_game()
func _on_continue_button_pressed() -> void:
if SceneFader.is_fading:
return
GameGlobals.reset_game()
SaveManager.load_game()
load_game()
func _on_quit_button_pressed() -> void:
if SceneFader.is_fading:
return
get_tree().quit()
func _on_settings_button_pressed() -> void:
if SceneFader.is_fading:
return
main_menu_ui.hide()
options_menu.show()

View File

@ -1,27 +1,34 @@
[gd_scene load_steps=2 format=3 uid="uid://dwd8wf02j2epn"]
[gd_scene load_steps=4 format=3 uid="uid://dwd8wf02j2epn"]
[ext_resource type="Script" uid="uid://bmsx3h2kunhb0" path="res://components/ui/menus/main_menu/main_menu.gd" id="1_6xfbl"]
[ext_resource type="PackedScene" uid="uid://4s2nskkco0a2" path="res://components/ui/menus/options_menu/options_menu.tscn" id="2_i2wwg"]
[node name="MainMenu" type="Control"]
[sub_resource type="Environment" id="Environment_6xfbl"]
ambient_light_source = 2
ambient_light_color = Color(0.177136, 0.177136, 0.177136, 1)
[node name="MainMenu" type="Node"]
script = ExtResource("1_6xfbl")
[node name="MainMenuUI" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_6xfbl")
[node name="Label" type="Label" parent="."]
[node name="TitleLabel" type="Label" parent="MainMenuUI"]
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 23.0
offset_bottom = 88.0
grow_horizontal = 2
theme_override_font_sizes/font_size = 64
text = "Untitled Maskot Horror Game"
text = "Magic N' Stuff"
horizontal_alignment = 1
[node name="ButtonContainer" type="VBoxContainer" parent="."]
[node name="ButtonContainer" type="VBoxContainer" parent="MainMenuUI"]
custom_minimum_size = Vector2(128, 0)
layout_mode = 1
anchors_preset = 8
@ -29,21 +36,64 @@ anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -21.0
offset_top = -33.0
offset_right = 21.0
offset_bottom = 33.0
offset_left = -64.0
offset_top = -68.0
offset_right = 64.0
offset_bottom = 68.0
grow_horizontal = 2
grow_vertical = 2
alignment = 1
[node name="PlayButton" type="Button" parent="ButtonContainer"]
[node name="ContinueButton" type="Button" parent="MainMenuUI/ButtonContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Play"
text = "CONTINUE"
[node name="QuitButton" type="Button" parent="ButtonContainer"]
[node name="NewGameButton" type="Button" parent="MainMenuUI/ButtonContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Quit"
text = "NEW_GAME"
[connection signal="pressed" from="ButtonContainer/PlayButton" to="." method="_on_play_button_pressed"]
[connection signal="pressed" from="ButtonContainer/QuitButton" to="." method="_on_quit_button_pressed"]
[node name="SettingsButton" type="Button" parent="MainMenuUI/ButtonContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "SETTINGS"
[node name="QuitButton" type="Button" parent="MainMenuUI/ButtonContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "QUIT"
[node name="OptionsMenu" parent="." instance=ExtResource("2_i2wwg")]
visible = false
[node name="Background" type="Node3D" parent="."]
[node name="WorldEnvironment" type="WorldEnvironment" parent="Background"]
environment = SubResource("Environment_6xfbl")
[node name="TVLight" type="OmniLight3D" parent="Background"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.6, -1)
light_energy = 0.135
omni_range = 3.0
omni_attenuation = 2.15
[node name="CSGGeometry" type="CSGCombiner3D" parent="Background"]
[node name="CSGBox3D" type="CSGBox3D" parent="Background/CSGGeometry"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
size = Vector3(10, 4, 7)
[node name="CSGBox3D2" type="CSGBox3D" parent="Background/CSGGeometry/CSGBox3D"]
operation = 2
size = Vector3(9, 3, 6)
[node name="Camera3D" type="Camera3D" parent="Background"]
transform = Transform3D(1, 0, 0, 0, 0.996195, -0.0871557, 0, 0.0871557, 0.996195, 0, 0.4, 1)
current = true
fov = 55.0
[connection signal="pressed" from="MainMenuUI/ButtonContainer/ContinueButton" to="." method="_on_continue_button_pressed"]
[connection signal="pressed" from="MainMenuUI/ButtonContainer/NewGameButton" to="." method="_on_new_game_button_pressed"]
[connection signal="pressed" from="MainMenuUI/ButtonContainer/SettingsButton" to="." method="_on_settings_button_pressed"]
[connection signal="pressed" from="MainMenuUI/ButtonContainer/QuitButton" to="." method="_on_quit_button_pressed"]

View File

@ -12,6 +12,7 @@ func open_menu(last_menu: MenuBase = previous_menu) -> void:
if is_instance_valid(last_menu):
previous_menu = last_menu
last_menu.hide()
menu_opened.emit()

View File

@ -0,0 +1,10 @@
class_name MenuButtonOpener
extends Button
@export var open_menu: MenuBase
@export var previous_menu: MenuBase
func _pressed() -> void:
if is_instance_valid(open_menu):
open_menu.open_menu(previous_menu)

View File

@ -0,0 +1 @@
uid://dtgap28ru5dt0

View File

@ -0,0 +1,10 @@
extends CheckBox
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
button_pressed = SettingsManager.get_setting(&"video", &"fullscreen")
func _toggled(toggled_on: bool) -> void:
SettingsManager.set_fullscreen(toggled_on)

View File

@ -0,0 +1 @@
uid://dlkewd0xr6ytq

View File

@ -0,0 +1,40 @@
class_name SliderLabel
extends Label
@export var slider: Slider: set = set_slider
@export var pad_zeros: int = 1
@export var pad_decimals: int = 2
@export var prefix: String = ""
@export var suffix: String = ""
@export_group("Remap Value")
@export var do_remap: bool = false
@export var remap_initial_min: float = 0.0
@export var remap_initial_max: float = 1.0
@export var remap_output_min: float = 0.0
@export var remap_output_max: float = 1.0
func set_slider(new_slider: Slider) -> void:
if new_slider == slider:
return
if is_instance_valid(slider):
slider.value_changed.disconnect(_on_value_changed)
if is_instance_valid(new_slider):
new_slider.value_changed.connect(_on_value_changed)
if not new_slider.is_node_ready():
await new_slider.ready
_on_value_changed(new_slider.get_value()) # Apply the value of the new slider.
slider = new_slider
func _on_value_changed(new_value: float) -> void:
var value: float = new_value
if do_remap:
value = remap(value, remap_initial_min, remap_initial_max, remap_output_min, remap_output_max)
var new_text: String = str(value).pad_zeros(pad_zeros).pad_decimals(pad_decimals)
set_text(str(prefix, new_text, suffix))

View File

@ -0,0 +1 @@
uid://dg2s0gww8q6jh

View File

@ -0,0 +1,51 @@
class_name VolumeSlider
extends HSlider
## A normal slider that automatically changes the volume of the given [param bus] in
## the given [param bus_layout].
## This slider will automatically load and save it's value when it enters the tree
## or changes it's value.[br]
## INFO: You don't need to change [param min_value] and [param max_value], the calculations
## towards [param volume_db] are automatically being done.
## The bus that get's it's volume changed.
@export var bus: StringName = &"Master"
@export var auto_set_muted: bool = false
@export var min_volume: float = 0.0
@export var max_volume: float = 1.0
@export var default_volume: float = 1.0
## The audio bus layout that get's affected.
#@export var bus_layout: AudioBusLayout = preload("res://resources/default_bus_layout.tres")
func _ready() -> void:
value_changed.connect(func(_value_changed: bool) -> void:
SettingsManager.set_setting(&"audio", bus, remap(value, min_value, max_value, 0.0, 1.0), true)
)
if not value_changed.is_connected(set_volume):
value_changed.connect(set_volume)
var err: float = SettingsManager.get_setting(&"audio", bus)
var new_value: float = remap(err, 0.0, 1.0, min_value, max_value)
set_value_no_signal(new_value)
set_volume(new_value)
value_changed.emit(value)
## Set's the volume on the audio bus given by [param bus] to the volume_range (Range from 0 to 100).[br]
## Note that this won't change [param value].
func set_volume(volume_range: float) -> void:
volume_range = remap(volume_range, min_value, max_value, min_volume, max_volume)
var new_volume: float = linear_to_db(volume_range)
var bus_idx: int = AudioServer.get_bus_index(bus)
AudioServer.set_bus_volume_db(bus_idx, new_volume)
if auto_set_muted:
AudioServer.set_bus_mute(bus_idx, is_zero_approx(volume_range))
#func save_volume(volume_range: float) -> void:
#OptionSaver.save_option("audio", bus, (volume_range / max_value))

View File

@ -0,0 +1 @@
uid://d2j5jmj08o7f5

View File

@ -0,0 +1,2 @@
class_name OptionsMenu
extends Control

View File

@ -0,0 +1 @@
uid://dl8uyh4kcvgl4

View File

@ -0,0 +1,177 @@
[gd_scene load_steps=4 format=3 uid="uid://4s2nskkco0a2"]
[ext_resource type="Script" uid="uid://dg2s0gww8q6jh" path="res://components/ui/menus/options_menu/elements/slider_label.gd" id="2_gjkvu"]
[ext_resource type="Script" uid="uid://d2j5jmj08o7f5" path="res://components/ui/menus/options_menu/elements/volume_slider.gd" id="2_hj0r6"]
[ext_resource type="Script" uid="uid://dlkewd0xr6ytq" path="res://components/ui/menus/options_menu/elements/fullscreen_button.gd" id="3_hj0r6"]
[node name="OptionsMenu" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="TabContainer" type="TabContainer" parent="."]
custom_minimum_size = Vector2(256, 256)
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -20.0
offset_top = -20.0
offset_right = 20.0
offset_bottom = 20.0
grow_horizontal = 2
grow_vertical = 2
tab_alignment = 1
current_tab = 0
[node name="Audio" type="Control" parent="TabContainer"]
layout_mode = 2
metadata/_tab_index = 0
[node name="MarginContainer" type="MarginContainer" parent="TabContainer/Audio"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 4
theme_override_constants/margin_top = 4
theme_override_constants/margin_right = 4
theme_override_constants/margin_bottom = 4
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/Audio/MarginContainer"]
layout_mode = 2
[node name="MasterLabel" type="Label" parent="TabContainer/Audio/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Master"
[node name="MasterContainer" type="HBoxContainer" parent="TabContainer/Audio/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="VolumeSlider" type="HSlider" parent="TabContainer/Audio/MarginContainer/VBoxContainer/MasterContainer"]
layout_mode = 2
size_flags_horizontal = 3
value = 100.0
tick_count = 10
ticks_on_borders = true
script = ExtResource("2_hj0r6")
metadata/_custom_type_script = "uid://d2j5jmj08o7f5"
[node name="SliderLabel" type="Label" parent="TabContainer/Audio/MarginContainer/VBoxContainer/MasterContainer" node_paths=PackedStringArray("slider")]
custom_minimum_size = Vector2(30, 0)
layout_mode = 2
text = "1.0"
script = ExtResource("2_gjkvu")
slider = NodePath("../VolumeSlider")
pad_decimals = 0
metadata/_custom_type_script = "uid://dg2s0gww8q6jh"
[node name="SFXLabel" type="Label" parent="TabContainer/Audio/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "SFX"
[node name="SFXContainer" type="HBoxContainer" parent="TabContainer/Audio/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="VolumeSlider" type="HSlider" parent="TabContainer/Audio/MarginContainer/VBoxContainer/SFXContainer"]
layout_mode = 2
size_flags_horizontal = 3
value = 100.0
tick_count = 10
ticks_on_borders = true
script = ExtResource("2_hj0r6")
bus = &"SFX"
metadata/_custom_type_script = "uid://d2j5jmj08o7f5"
[node name="SliderLabel" type="Label" parent="TabContainer/Audio/MarginContainer/VBoxContainer/SFXContainer" node_paths=PackedStringArray("slider")]
custom_minimum_size = Vector2(30, 0)
layout_mode = 2
text = "1.0"
script = ExtResource("2_gjkvu")
slider = NodePath("../VolumeSlider")
pad_decimals = 0
metadata/_custom_type_script = "uid://dg2s0gww8q6jh"
[node name="MusicLabel" type="Label" parent="TabContainer/Audio/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Music"
[node name="MusicContainer" type="HBoxContainer" parent="TabContainer/Audio/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="VolumeSlider" type="HSlider" parent="TabContainer/Audio/MarginContainer/VBoxContainer/MusicContainer"]
layout_mode = 2
size_flags_horizontal = 3
value = 100.0
tick_count = 10
ticks_on_borders = true
script = ExtResource("2_hj0r6")
bus = &"Music"
metadata/_custom_type_script = "uid://d2j5jmj08o7f5"
[node name="SliderLabel" type="Label" parent="TabContainer/Audio/MarginContainer/VBoxContainer/MusicContainer" node_paths=PackedStringArray("slider")]
custom_minimum_size = Vector2(30, 0)
layout_mode = 2
text = "1.0"
script = ExtResource("2_gjkvu")
slider = NodePath("../VolumeSlider")
pad_decimals = 0
metadata/_custom_type_script = "uid://dg2s0gww8q6jh"
[node name="AmbientLabel" type="Label" parent="TabContainer/Audio/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Ambient"
[node name="AmbientContainer" type="HBoxContainer" parent="TabContainer/Audio/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="VolumeSlider" type="HSlider" parent="TabContainer/Audio/MarginContainer/VBoxContainer/AmbientContainer"]
layout_mode = 2
size_flags_horizontal = 3
value = 100.0
tick_count = 10
ticks_on_borders = true
script = ExtResource("2_hj0r6")
bus = &"Ambient"
metadata/_custom_type_script = "uid://d2j5jmj08o7f5"
[node name="SliderLabel" type="Label" parent="TabContainer/Audio/MarginContainer/VBoxContainer/AmbientContainer" node_paths=PackedStringArray("slider")]
custom_minimum_size = Vector2(30, 0)
layout_mode = 2
text = "1.0"
script = ExtResource("2_gjkvu")
slider = NodePath("../VolumeSlider")
pad_decimals = 0
metadata/_custom_type_script = "uid://dg2s0gww8q6jh"
[node name="Graphics" type="Control" parent="TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 1
[node name="MarginContainer" type="MarginContainer" parent="TabContainer/Graphics"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 4
theme_override_constants/margin_top = 4
theme_override_constants/margin_right = 4
theme_override_constants/margin_bottom = 4
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/Graphics/MarginContainer"]
layout_mode = 2
[node name="FullscreenButton" type="CheckBox" parent="TabContainer/Graphics/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Fullscreen"
script = ExtResource("3_hj0r6")

View File

@ -0,0 +1,49 @@
class_name PauseMenu
extends Node
const ACTION_PAUSE: StringName = &"pause"
var can_pause: bool = true
@onready var pause_menu: MenuBase = $PauseMenu
@onready var options_menu: Control = $OptionsMenu
func _input(event: InputEvent) -> void:
if event.is_action_pressed(ACTION_PAUSE):
if options_menu.is_visible_in_tree():
options_menu.hide()
pause_menu.show()
else:
toggle_pause()
func set_paused(value: bool) -> void:
if SceneFader.is_fading:
return
get_tree().paused = value
pause_menu.visible = value
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE if value else Input.MOUSE_MODE_CAPTURED
func toggle_pause() -> void:
if not can_pause or options_menu.is_visible():
return
set_paused(not get_tree().paused)
func _on_continue_button_pressed() -> void:
set_paused(false)
func _on_main_menu_button_pressed() -> void:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
await SceneFader.load_to_path(GameGlobals.MAIN_MENU_PATH, true)
func _on_settings_button_pressed() -> void:
pause_menu.hide()
options_menu.show()

View File

@ -0,0 +1 @@
uid://cx3lpgmhrra8v

View File

@ -0,0 +1,63 @@
[gd_scene load_steps=4 format=3 uid="uid://dawmen0hlfaaq"]
[ext_resource type="Script" uid="uid://cx3lpgmhrra8v" path="res://components/ui/menus/pause_menu/pause_menu.gd" id="1_43sid"]
[ext_resource type="Script" uid="uid://crdgxvb8i0cif" path="res://components/ui/menus/menu_base.gd" id="1_hcnxh"]
[ext_resource type="PackedScene" uid="uid://4s2nskkco0a2" path="res://components/ui/menus/options_menu/options_menu.tscn" id="3_hcnxh"]
[node name="PauseMenu" type="Node"]
process_mode = 3
script = ExtResource("1_43sid")
[node name="PauseMenu" type="Control" parent="."]
visible = false
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_hcnxh")
metadata/_custom_type_script = "uid://crdgxvb8i0cif"
[node name="Label" type="Label" parent="PauseMenu"]
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 23.0
grow_horizontal = 2
theme_override_font_sizes/font_size = 128
text = "Paused"
horizontal_alignment = 1
[node name="VBoxContainer" type="VBoxContainer" parent="PauseMenu"]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -20.0
offset_top = -20.0
offset_right = 20.0
offset_bottom = 20.0
grow_horizontal = 2
grow_vertical = 2
[node name="ContinueButton" type="Button" parent="PauseMenu/VBoxContainer"]
layout_mode = 2
text = "Continue"
[node name="SettingsButton" type="Button" parent="PauseMenu/VBoxContainer"]
layout_mode = 2
text = "Settings"
[node name="MainMenuButton" type="Button" parent="PauseMenu/VBoxContainer"]
layout_mode = 2
text = "Main Menu"
[node name="OptionsMenu" parent="." instance=ExtResource("3_hcnxh")]
visible = false
[connection signal="pressed" from="PauseMenu/VBoxContainer/ContinueButton" to="." method="_on_continue_button_pressed"]
[connection signal="pressed" from="PauseMenu/VBoxContainer/SettingsButton" to="." method="_on_settings_button_pressed"]
[connection signal="pressed" from="PauseMenu/VBoxContainer/MainMenuButton" to="." method="_on_main_menu_button_pressed"]

8
source/game.gd Normal file
View File

@ -0,0 +1,8 @@
extends Node
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
AudioManager.play_audio(preload("res://Dark House.wav"), AudioManager.AMBIENCE)

1
source/game.gd.uid Normal file
View File

@ -0,0 +1 @@
uid://dbsjg3o61vuji

83
source/game.tscn Normal file
View File

@ -0,0 +1,83 @@
[gd_scene load_steps=7 format=3 uid="uid://s7cw6ulb7kh7"]
[ext_resource type="PackedScene" uid="uid://clhy3kiceqf2o" path="res://components/characters/player/player_character.tscn" id="1_80nbo"]
[ext_resource type="Script" uid="uid://dbsjg3o61vuji" path="res://game.gd" id="1_fc0e3"]
[ext_resource type="Environment" uid="uid://xe70va0pjc6c" path="res://resources/game_environment.tres" id="2_7jktm"]
[ext_resource type="Script" uid="uid://3hlvt5k34xva" path="res://components/general/player_spawn_point.gd" id="2_e2o6t"]
[ext_resource type="PackedScene" uid="uid://dawmen0hlfaaq" path="res://components/ui/menus/pause_menu/pause_menu.tscn" id="3_feb5d"]
[ext_resource type="PackedScene" uid="uid://c0jearfhlqcvr" path="res://components/hazards/saw/saw.tscn" id="5_ryrav"]
[node name="Game" type="Node"]
script = ExtResource("1_fc0e3")
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = ExtResource("2_7jktm")
[node name="PlayerCharacter" parent="." instance=ExtResource("1_80nbo")]
[node name="Menus" type="CanvasLayer" parent="."]
[node name="PauseMenu" parent="Menus" instance=ExtResource("3_feb5d")]
[node name="Areas" type="Node" parent="."]
[node name="IntroArea" type="Node3D" parent="Areas"]
[node name="Blockout" type="CSGCombiner3D" parent="Areas/IntroArea"]
use_collision = true
[node name="CSGBox3D" type="CSGBox3D" parent="Areas/IntroArea/Blockout"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, -4.5)
size = Vector3(5, 4, 12)
[node name="CSGBox3D3" type="CSGBox3D" parent="Areas/IntroArea/Blockout/CSGBox3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.5)
operation = 2
size = Vector3(4, 3, 12)
[node name="CSGBox3D2" type="CSGBox3D" parent="Areas/IntroArea/Blockout"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, -22)
size = Vector3(32, 15, 27)
[node name="CSGBox3D3" type="CSGBox3D" parent="Areas/IntroArea/Blockout/CSGBox3D2"]
operation = 2
size = Vector3(31, 14, 25)
[node name="CSGBox3D4" type="CSGBox3D" parent="Areas/IntroArea/Blockout/CSGBox3D2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -5.5, 12.25)
operation = 2
size = Vector3(4, 3, 2.5)
[node name="OmniLight3D" type="OmniLight3D" parent="Areas/IntroArea"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6, -24)
omni_range = 20.0
[node name="Saw" parent="Areas/IntroArea" instance=ExtResource("5_ryrav")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 0.5, -25)
[node name="Saw2" parent="Areas/IntroArea" instance=ExtResource("5_ryrav")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0.2, 0.5, -25)
[node name="Saw3" parent="Areas/IntroArea" instance=ExtResource("5_ryrav")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0.4, 0.5, -25)
[node name="Saw4" parent="Areas/IntroArea" instance=ExtResource("5_ryrav")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0.6, 0.5, -25)
[node name="Saw5" parent="Areas/IntroArea" instance=ExtResource("5_ryrav")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0.8, 0.5, -25)
[node name="Saw6" parent="Areas/IntroArea" instance=ExtResource("5_ryrav")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1, 0.5, -25)
[node name="SpawnPoints" type="Node" parent="."]
[node name="PlayerSpawnPoint" type="Marker3D" parent="SpawnPoints"]
script = ExtResource("2_e2o6t")
metadata/_custom_type_script = "uid://3hlvt5k34xva"
[node name="PlayerSpawnPoint2" type="Marker3D" parent="SpawnPoints"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -15)
script = ExtResource("2_e2o6t")
spawn_index = 1
metadata/_custom_type_script = "uid://3hlvt5k34xva"

View File

@ -0,0 +1,67 @@
extends Node
const MASTER: StringName = &"Master"
const MUSIC: StringName = &"Music"
const SFX: StringName = &"SFX"
const AMBIENCE: StringName = &"Ambient"
func play_audio(stream: AudioStream, bus: StringName, force_restart: bool = false) -> void:
if is_playing_audio(stream, bus):
if force_restart:
var existing_player: AudioStreamPlayer = get_audio_player_for_stream(stream, bus)
existing_player.stop()
existing_player.play()
return
var player: AudioStreamPlayer = _create_audio_player(stream, bus)
player.finished.connect(stop_audio.bind(stream, bus))
add_child(player)
player.play()
func stop_audio(stream: AudioStream, bus: StringName) -> void:
var player: AudioStreamPlayer = get_audio_player_for_stream(stream, bus)
if is_instance_valid(player):
player.queue_free()
func fade_audio(stream: AudioStream, volume_db: float, duration: float, bus: StringName, stop_on_finish: bool = false) -> void:
var player: AudioStreamPlayer = get_audio_player_for_stream(stream, bus)
if not is_instance_valid(player):
return
var tween: Tween = create_tween()
tween.tween_property(player, ^"volume_db", volume_db, duration)
await tween.finished
if stop_on_finish and is_instance_valid(player):
stop_audio(stream, bus)
func fade_audio_linear(stream: AudioStream, volume_linear: float, bus: StringName, duration: float, stop_on_finish: bool = false) -> void:
await fade_audio(stream, linear_to_db(volume_linear), duration, bus, stop_on_finish)
func get_audio_player_for_stream(stream: AudioStream, bus: StringName) -> AudioStreamPlayer:
for player: AudioStreamPlayer in get_children():
if player.stream == stream and player.bus == bus:
return player
return null
func is_playing_audio(stream: AudioStream, bus: StringName) -> bool:
return is_instance_valid(get_audio_player_for_stream(stream, bus))
func _create_audio_player(stream: AudioStream, bus: StringName) -> AudioStreamPlayer:
var player := AudioStreamPlayer.new()
player.bus = bus
player.stream = stream
return player

View File

@ -0,0 +1 @@
uid://chwfg6slvsay8

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://diduaxhewgjwa"]
[ext_resource type="Script" uid="uid://chwfg6slvsay8" path="res://globals/autoloads/audio/audio_manager.gd" id="1_pjc45"]
[node name="AudioManager" type="Node"]
script = ExtResource("1_pjc45")

View File

@ -1,8 +1,19 @@
extends Node
const MAIN_MENU_PATH: String = "res://components/ui/menus/main_menu/main_menu.tscn"
const GAME_PATH: String = "res://game.tscn"
var player: PlayerCharacter
var spawn_index: int = 0
func get_player() -> PlayerCharacter:
return player
func reset_game() -> void:
spawn_index = 0
func set_spawn_index(index: int) -> void:
spawn_index = index

View File

@ -18,8 +18,12 @@ func _input(event: InputEvent) -> void:
using_controller = true
if event.is_action_pressed(TOGGLE_MOUSE_BUTTON):
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED if Input.mouse_mode == Input.MOUSE_MODE_VISIBLE else Input.MOUSE_MODE_VISIBLE)
toggle_mouse()
func window_focused() -> bool:
return DisplayServer.window_is_focused()
func toggle_mouse() -> void:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED if Input.mouse_mode == Input.MOUSE_MODE_VISIBLE else Input.MOUSE_MODE_VISIBLE)

View File

@ -0,0 +1,32 @@
extends Node
const SAVE_PATH: String = "user://saves/"
const SAVE_FILENAME: String = "saved_game.dat"
func save_game() -> void:
DirAccess.make_dir_recursive_absolute(SAVE_PATH)
var file := FileAccess.open(str(SAVE_PATH, SAVE_FILENAME), FileAccess.WRITE)
# Store the variables.
file.store_var(GameGlobals.spawn_index)
func load_game() -> bool:
if not save_exists():
return false
var file := FileAccess.open(str(SAVE_PATH, SAVE_FILENAME), FileAccess.READ)
# Load the variables.
GameGlobals.spawn_index = file.get_var()
return true
func delete_save() -> void:
DirAccess.remove_absolute(str(SAVE_PATH, SAVE_FILENAME))
func save_exists() -> bool:
return FileAccess.file_exists(str(SAVE_PATH, SAVE_FILENAME))

View File

@ -0,0 +1 @@
uid://iadl2o6wkphx

View File

@ -0,0 +1,67 @@
extends CanvasLayer
var fade_in_duration: float = 2.0
var fade_out_duration: float = 2.0
var is_fading: bool = false
var is_loading: bool = false
@onready var interactive_loader: InteractiveLoader = $InteractiveLoader
@onready var color_rect: ColorRect = $ColorRect
@onready var loading_hint_animations: AnimationPlayer = $HintMargin/Control/LoadingHint/LoadingHintAnimations
@onready var loading_hint: TextureRect = $HintMargin/Control/LoadingHint
func _ready() -> void:
color_rect.hide()
func load_to_path(path: String, unpause_game: bool = false) -> void:
if is_loading:
return
is_loading = true
await fade_in()
var scene: PackedScene = await interactive_loader.load_threaded(path)
assert(is_instance_valid(scene))
get_tree().change_scene_to_packed(scene)
if unpause_game:
get_tree().paused = false
fade_out()
is_loading = false
func fade_in() -> void:
color_rect.show()
is_fading = true
var tween: Tween = create_tween()
tween.tween_property(color_rect, ^"color:a", 1.0, fade_in_duration)
await tween.finished
is_fading = false
loading_hint_animations.play(&"hover")
loading_hint.show()
func fade_out() -> void:
loading_hint_animations.stop()
loading_hint.hide()
is_fading = true
var tween: Tween = create_tween()
tween.tween_property(color_rect, ^"color:a", 0.0, fade_out_duration)
await tween.finished
color_rect.hide()
is_fading = false

View File

@ -0,0 +1 @@
uid://cynllcoh2smgv

View File

@ -0,0 +1,125 @@
[gd_scene load_steps=7 format=3 uid="uid://dis4efdm5s2fc"]
[ext_resource type="Script" uid="uid://cynllcoh2smgv" path="res://globals/autoloads/scene_fader/scene_fader.gd" id="1_7tt87"]
[ext_resource type="Script" uid="uid://d0k03wk1s7cw0" path="res://components/general/interactive_loader.gd" id="2_dwqb8"]
[ext_resource type="Texture2D" uid="uid://dhw8y2oqxvgwu" path="res://godot_icon.svg" id="3_dwqb8"]
[sub_resource type="Animation" id="Animation_t3447"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [-0.261799]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(1112, 608)]
}
[sub_resource type="Animation" id="Animation_dwqb8"]
resource_name = "hover"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:rotation")
tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.5),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [0.174533, -0.174533]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:position")
tracks/1/interp = 2
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0.25, 0.75),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(0, 5)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_e571n"]
_data = {
&"RESET": SubResource("Animation_t3447"),
&"hover": SubResource("Animation_dwqb8")
}
[node name="SceneFader" type="CanvasLayer"]
process_mode = 3
layer = 10
script = ExtResource("1_7tt87")
[node name="InteractiveLoader" type="Node" parent="."]
script = ExtResource("2_dwqb8")
metadata/_custom_type_script = "uid://d0k03wk1s7cw0"
[node name="ColorRect" type="ColorRect" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
color = Color(0, 0, 0, 1)
[node name="HintMargin" type="MarginContainer" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
theme_override_constants/margin_left = 16
theme_override_constants/margin_top = 16
theme_override_constants/margin_right = 16
theme_override_constants/margin_bottom = 16
[node name="Control" type="Control" parent="HintMargin"]
custom_minimum_size = Vector2(64, 64)
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 8
mouse_filter = 2
[node name="LoadingHint" type="TextureRect" parent="HintMargin/Control"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 1112.0
offset_top = 608.0
offset_right = 1112.0
offset_bottom = 608.0
grow_horizontal = 2
grow_vertical = 2
rotation = -0.261799
pivot_offset = Vector2(20, 32)
mouse_filter = 2
texture = ExtResource("3_dwqb8")
expand_mode = 5
[node name="LoadingHintAnimations" type="AnimationPlayer" parent="HintMargin/Control/LoadingHint"]
libraries = {
&"": SubResource("AnimationLibrary_e571n")
}

View File

@ -0,0 +1,71 @@
extends Node
const SETTINGS_PATH: String = "user://settings.cfg"
var settings: Dictionary[String, Dictionary] = {
&"game": {
&"has_compiled_shaders": false,
},
&"audio": {
&"Master": 1.0,
&"SFX": 1.0,
&"Music": 1.0,
&"Ambient": 1.0,
},
&"video": {
&"fullscreen": true
}
}
func _ready() -> void:
load_settings()
func load_settings() -> void:
if not FileAccess.file_exists(SETTINGS_PATH):
save_settings()
return
var config := ConfigFile.new()
config.load(SETTINGS_PATH)
for section: String in settings.keys():
for key: String in settings[section].keys():
var default: Variant = get_setting(section, key)
set_setting(section, key, config.get_value(section, key, default), false)
func save_settings() -> void:
var config := ConfigFile.new()
for section: String in settings.keys():
for key: String in settings[section].keys():
config.set_value(section, key, settings[section][key])
config.save(SETTINGS_PATH)
func set_setting(section: String, key: String, value: Variant, do_save: bool = true) -> void:
settings[section][key] = value
if do_save:
save_settings()
func get_setting(section: String, key: String) -> Variant:
return settings[section][key]
func adjust_volume(bus: StringName, volume: float) -> void:
set_setting(&"audio", bus, volume, false)
return
var fmod_bus: FmodBus = FmodServer.get_bus(str("res://components/fmod/Build/Desktop/", bus, ".bank"))
if is_instance_valid(fmod_bus):
fmod_bus.volume = volume
func set_fullscreen(fullscreened: bool) -> void:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN if fullscreened else DisplayServer.WINDOW_MODE_WINDOWED)
set_setting(&"video", &"fullscreen", fullscreened)

View File

@ -0,0 +1 @@
uid://py4o5sbsljq4

BIN
source/localization/de.mo Normal file

Binary file not shown.

38
source/localization/de.po Normal file
View File

@ -0,0 +1,38 @@
# LANGUAGE translation for MagicNStuff for the following files:
# res://components/ui/menus/main_menu/main_menu.tscn
#
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: MagicNStuff\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.4.2\n"
#: components/ui/menus/main_menu/main_menu.tscn
msgid "Magic N' Stuff"
msgstr ""
#: components/ui/menus/main_menu/main_menu.tscn
msgid "CONTINUE"
msgstr "Weiterspielen"
#: components/ui/menus/main_menu/main_menu.tscn
msgid "NEW_GAME"
msgstr "Neues Spiel"
#: components/ui/menus/main_menu/main_menu.tscn
msgid "SETTINGS"
msgstr "Einstellungen"
#: components/ui/menus/main_menu/main_menu.tscn
msgid "QUIT"
msgstr "Beenden"

BIN
source/localization/en.mo Normal file

Binary file not shown.

38
source/localization/en.po Normal file
View File

@ -0,0 +1,38 @@
# LANGUAGE translation for MagicNStuff for the following files:
# res://components/ui/menus/main_menu/main_menu.tscn
#
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: MagicNStuff\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.4.2\n"
#: components/ui/menus/main_menu/main_menu.tscn
msgid "Magic N' Stuff"
msgstr ""
#: components/ui/menus/main_menu/main_menu.tscn
msgid "CONTINUE"
msgstr "Continue"
#: components/ui/menus/main_menu/main_menu.tscn
msgid "NEW_GAME"
msgstr "New Game"
#: components/ui/menus/main_menu/main_menu.tscn
msgid "SETTINGS"
msgstr "Settings"
#: components/ui/menus/main_menu/main_menu.tscn
msgid "QUIT"
msgstr "Quit"

View File

@ -0,0 +1,32 @@
# LANGUAGE translation for MagicNStuff for the following files:
# res://components/ui/menus/main_menu/main_menu.tscn
#
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: MagicNStuff\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
#: components/ui/menus/main_menu/main_menu.tscn
msgid "Magic N' Stuff"
msgstr ""
#: components/ui/menus/main_menu/main_menu.tscn
msgid "CONTINUE"
msgstr ""
#: components/ui/menus/main_menu/main_menu.tscn
msgid "NEW_GAME"
msgstr ""
#: components/ui/menus/main_menu/main_menu.tscn
msgid "SETTINGS"
msgstr ""
#: components/ui/menus/main_menu/main_menu.tscn
msgid "QUIT"
msgstr ""

View File

@ -1,3 +0,0 @@
[gd_scene format=3 uid="uid://cvj5b6ygk8u02"]
[node name="Main" type="Node"]

View File

@ -18,7 +18,8 @@ sky = SubResource("Sky_yaqeo")
tonemap_mode = 2
glow_enabled = true
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_g60qb"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_g60qb"]
albedo_color = Color(1, 0.426083, 0.0827108, 1)
[sub_resource type="BoxShape3D" id="BoxShape3D_g60qb"]
size = Vector3(9, 4, 9)
@ -44,8 +45,7 @@ size = Vector3(22, 4, 7)
[sub_resource type="BoxShape3D" id="BoxShape3D_0qpgw"]
size = Vector3(9, 4, 25)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_g60qb"]
albedo_color = Color(1, 0.426083, 0.0827108, 1)
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_g60qb"]
[sub_resource type="CylinderMesh" id="CylinderMesh_g60qb"]
@ -61,6 +61,94 @@ shadow_enabled = true
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_4rgsp")
[node name="Areas" type="Node" parent="."]
[node name="AlwaysLoaded" type="CSGCombiner3D" parent="Areas"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 9)
use_collision = true
[node name="CSGBox3D" type="CSGBox3D" parent="Areas/AlwaysLoaded"]
size = Vector3(8, 1, 7)
material = SubResource("StandardMaterial3D_g60qb")
[node name="PerformanceTestPlatform1" type="Area3D" parent="Areas" node_paths=PackedStringArray("placeholder_node")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 0)
script = ExtResource("1_q4yy4")
placeholder_node = NodePath("Area1")
loaded_if_spawnpoint = Array[int]([0])
metadata/_custom_type_script = "uid://bj2bhtdul8xct"
[node name="Area1" parent="Areas/PerformanceTestPlatform1" instance_placeholder="res://maps/_dynamic_load_test/area_1.tscn"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, -2, 2)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Areas/PerformanceTestPlatform1"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0.5, 2)
shape = SubResource("BoxShape3D_g60qb")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="PerformanceTestPlatform2" type="Area3D" parent="Areas" node_paths=PackedStringArray("placeholder_node")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, -7)
script = ExtResource("1_q4yy4")
placeholder_node = NodePath("Area2")
loaded_if_spawnpoint = Array[int]([1])
metadata/_custom_type_script = "uid://bj2bhtdul8xct"
[node name="Area2" parent="Areas/PerformanceTestPlatform2" instance_placeholder="res://maps/_dynamic_load_test/area_2.tscn"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, -2, 2)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Areas/PerformanceTestPlatform2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0.5, 2)
shape = SubResource("BoxShape3D_yaqeo")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="CollisionShape3D2" type="CollisionShape3D" parent="Areas/PerformanceTestPlatform2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -12.5, 0.5, 3.67773)
shape = SubResource("BoxShape3D_4rgsp")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="CollisionShape3D3" type="CollisionShape3D" parent="Areas/PerformanceTestPlatform2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -16.5, 0.5, 5.67773)
shape = SubResource("BoxShape3D_m4fap")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="Hallway1Loader" type="Area3D" parent="Areas" node_paths=PackedStringArray("placeholder_node")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, -7)
script = ExtResource("1_q4yy4")
placeholder_node = NodePath("Hallway1")
metadata/_custom_type_script = "uid://bj2bhtdul8xct"
[node name="Hallway1" parent="Areas/Hallway1Loader" instance_placeholder="res://maps/_dynamic_load_test/hallway_1.tscn"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, -2, 16)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Areas/Hallway1Loader"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0.5, 17.85)
shape = SubResource("BoxShape3D_k1ge7")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="Hallway2Loader" type="Area3D" parent="Areas" node_paths=PackedStringArray("placeholder_node")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, -7)
script = ExtResource("1_q4yy4")
placeholder_node = NodePath("Hallway2")
metadata/_custom_type_script = "uid://bj2bhtdul8xct"
[node name="Hallway2" parent="Areas/Hallway2Loader" instance_placeholder="res://maps/_dynamic_load_test/hallway_2.tscn"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, -2, 16)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Areas/Hallway2Loader"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0.5, 25.5)
shape = SubResource("BoxShape3D_ka7nb")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="CollisionShape3D2" type="CollisionShape3D" parent="Areas/Hallway2Loader"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7.5, 0.5, 3.67773)
shape = SubResource("BoxShape3D_kaxur")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="CollisionShape3D3" type="CollisionShape3D" parent="Areas/Hallway2Loader"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -14, 0.5, 12.6777)
shape = SubResource("BoxShape3D_0qpgw")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="WorldFloor" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
metadata/_edit_lock_ = true
@ -69,90 +157,6 @@ metadata/_edit_group_ = true
[node name="CollisionShape3D" type="CollisionShape3D" parent="WorldFloor"]
shape = SubResource("WorldBoundaryShape3D_g60qb")
[node name="DynamicAreaLoader3D" type="Area3D" parent="." node_paths=PackedStringArray("placeholder_node")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 0)
script = ExtResource("1_q4yy4")
placeholder_node = NodePath("Area1")
metadata/_custom_type_script = "uid://bj2bhtdul8xct"
[node name="Area1" parent="DynamicAreaLoader3D" instance_placeholder="res://maps/_dynamic_load_test/area_1.tscn"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, -2, 2)
[node name="CollisionShape3D" type="CollisionShape3D" parent="DynamicAreaLoader3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0.5, 2)
shape = SubResource("BoxShape3D_g60qb")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="DynamicAreaLoader3D2" type="Area3D" parent="." node_paths=PackedStringArray("placeholder_node")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, -7)
script = ExtResource("1_q4yy4")
placeholder_node = NodePath("Area2")
metadata/_custom_type_script = "uid://bj2bhtdul8xct"
[node name="Area2" parent="DynamicAreaLoader3D2" instance_placeholder="res://maps/_dynamic_load_test/area_2.tscn"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, -2, 2)
[node name="CollisionShape3D" type="CollisionShape3D" parent="DynamicAreaLoader3D2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0.5, 2)
shape = SubResource("BoxShape3D_yaqeo")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="CollisionShape3D2" type="CollisionShape3D" parent="DynamicAreaLoader3D2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -12.5, 0.5, 3.67773)
shape = SubResource("BoxShape3D_4rgsp")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="CollisionShape3D3" type="CollisionShape3D" parent="DynamicAreaLoader3D2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -16.5, 0.5, 5.67773)
shape = SubResource("BoxShape3D_m4fap")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="Hallway1Loader" type="Area3D" parent="." node_paths=PackedStringArray("placeholder_node")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, -7)
script = ExtResource("1_q4yy4")
placeholder_node = NodePath("Hallway1")
metadata/_custom_type_script = "uid://bj2bhtdul8xct"
[node name="Hallway1" parent="Hallway1Loader" instance_placeholder="res://maps/_dynamic_load_test/hallway_1.tscn"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, -2, 16)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Hallway1Loader"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0.5, 17.85)
shape = SubResource("BoxShape3D_k1ge7")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="Hallway2Loader" type="Area3D" parent="." node_paths=PackedStringArray("placeholder_node")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, -7)
script = ExtResource("1_q4yy4")
placeholder_node = NodePath("Hallway2")
metadata/_custom_type_script = "uid://bj2bhtdul8xct"
[node name="Hallway2" parent="Hallway2Loader" instance_placeholder="res://maps/_dynamic_load_test/hallway_2.tscn"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, -2, 16)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Hallway2Loader"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0.5, 25.5)
shape = SubResource("BoxShape3D_ka7nb")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="CollisionShape3D2" type="CollisionShape3D" parent="Hallway2Loader"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7.5, 0.5, 3.67773)
shape = SubResource("BoxShape3D_kaxur")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="CollisionShape3D3" type="CollisionShape3D" parent="Hallway2Loader"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -14, 0.5, 12.6777)
shape = SubResource("BoxShape3D_0qpgw")
debug_color = Color(0.678973, 0.504376, 0, 0.42)
[node name="AlwaysLoaded" type="CSGCombiner3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 9)
use_collision = true
[node name="CSGBox3D" type="CSGBox3D" parent="AlwaysLoaded"]
size = Vector3(8, 1, 7)
material = SubResource("StandardMaterial3D_g60qb")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
transform = Transform3D(5.58473, 6.33307, 0, -6.33307, 5.58473, 0, 0, 0, 8.44375, -13.6652, 0, -15.4998)
mesh = SubResource("CylinderMesh_g60qb")
@ -162,5 +166,17 @@ transform = Transform3D(0.330597, 0, 0.943772, 0, 1, 0, -0.943772, 0, 0.330597,
script = ExtResource("3_yaqeo")
metadata/_custom_type_script = "uid://3hlvt5k34xva"
[node name="PlayerSpawnPoint2" type="Marker3D" parent="."]
transform = Transform3D(0.330597, 0, 0.943772, 0, 1, 0, -0.943772, 0, 0.330597, 2.60837, 0.5, -2.6832)
script = ExtResource("3_yaqeo")
spawn_index = 1
metadata/_custom_type_script = "uid://3hlvt5k34xva"
[node name="PlayerSpawnPoint3" type="Marker3D" parent="."]
transform = Transform3D(0.43358, 0, -0.901115, 0, 1, 0, 0.901115, 0, 0.43358, -14.3916, 0.5, -2.6832)
script = ExtResource("3_yaqeo")
spawn_index = 2
metadata/_custom_type_script = "uid://3hlvt5k34xva"
[node name="Saw" parent="." instance=ExtResource("4_4rgsp")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.31477, 1.59362, 6.44809)

View File

@ -11,13 +11,18 @@ config_version=5
[application]
config/name="MagicNStuff"
run/main_scene="uid://coga3ke4xw3a0"
config/features=PackedStringArray("4.4", "Forward Plus")
config/icon="uid://bovb32x4x3ps5"
[autoload]
SettingsManager="*res://globals/autoloads/settings/settings_manager.gd"
SceneFader="*res://globals/autoloads/scene_fader/scene_fader.tscn"
GameGlobals="*res://globals/autoloads/game_globals.gd"
InputManager="*res://globals/autoloads/input_manager.gd"
SaveManager="*res://globals/autoloads/save_manager.gd"
AudioManager="*res://globals/autoloads/audio/audio_manager.tscn"
Logger="*res://addons/logger/logger.tscn"
RunConfigManager="*res://addons/run-configs/run-config-manager.gd"
VersionDisplay="*res://addons/version_display/version_display.tscn"
@ -33,7 +38,9 @@ folder_colors={
"res://addons/": "gray",
"res://components/": "green",
"res://globals/": "orange",
"res://maps/": "yellow"
"res://localization/": "teal",
"res://maps/": "yellow",
"res://resources/": "purple"
}
[input]
@ -99,6 +106,12 @@ camera_right={
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":1.0,"script":null)
]
}
pause={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":6,"pressure":0.0,"pressed":false,"script":null)
]
}
toggle_console={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194341,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
@ -129,3 +142,8 @@ bbcode_edit/editor/open_current_file_documentation={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194332,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
[internationalization]
locale/translations=PackedStringArray("res://localization/de.mo", "res://localization/de.po", "res://localization/en.mo", "res://localization/en.po")
locale/translations_pot_files=PackedStringArray("res://components/ui/menus/main_menu/main_menu.tscn")

View File

@ -0,0 +1,8 @@
[gd_resource type="Environment" format=3 uid="uid://xe70va0pjc6c"]
[resource]
tonemap_mode = 3
ssao_enabled = true
ssao_radius = 0.7
ssao_intensity = 1.0
glow_enabled = true