Refactored Interaction and Save System

- Added a save override confirmation in main menu.
- Added Interaction types.
- Added some test interactions.
- Also added a ViewRollEffect for the player camera.
- Also also added a cubemap generator (CubeMapGeneratorCamera).
This commit is contained in:
SchimmelSpreu83 2026-01-03 12:45:39 +01:00
parent 9da3ddcf35
commit 9dc31a11f6
91 changed files with 4249 additions and 171 deletions

View File

@ -1,27 +1,32 @@
[gd_scene load_steps=12 format=3 uid="uid://btjepmbw1mq6j"]
[gd_scene load_steps=14 format=3 uid="uid://btjepmbw1mq6j"]
[ext_resource type="PackedScene" uid="uid://8y3swwnmxwg2" path="res://src/core/world/world.tscn" id="1_7hw7e"]
[ext_resource type="Script" uid="uid://dfnb036hysorj" path="res://src/core/world/level/level_loader.gd" id="2_5eifk"]
[ext_resource type="Resource" uid="uid://d0y8d244covqn" path="res://_development/ayuroo/levels/_chase_test/_chase_world_info.tres" id="2_gynur"]
[ext_resource type="Script" uid="uid://3hlvt5k34xva" path="res://src/core/spawnpoint/player_spawn_point.gd" id="3_5eifk"]
[ext_resource type="PackedScene" uid="uid://drr80goa61wrx" path="res://src/core/world/level/level_area.tscn" id="4_clslv"]
[ext_resource type="Script" uid="uid://u2s0spt1rud4" path="res://src/core/game_state_overrider.gd" id="6_gynur"]
[ext_resource type="Script" uid="uid://bfv3de7iqflhv" path="res://src/core/damage/death_area.gd" id="6_tys81"]
[sub_resource type="BoxShape3D" id="BoxShape3D_77q0j"]
size = Vector3(29, 14, 149)
size = Vector3(29, 14, 1582)
[sub_resource type="BoxShape3D" id="BoxShape3D_clslv"]
size = Vector3(29, 14, 1175)
[sub_resource type="BoxShape3D" id="BoxShape3D_gynur"]
size = Vector3(29, 14, 1762)
size = Vector3(29, 14, 1550)
[sub_resource type="BoxShape3D" id="BoxShape3D_vcy7h"]
size = Vector3(14, 14, 17)
[sub_resource type="BoxShape3D" id="BoxShape3D_tys81"]
size = Vector3(1, 2, 0.5)
size = Vector3(1.3000001, 2, 0.5)
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_gynur"]
[node name="ChaseTestWorld" instance=ExtResource("1_7hw7e")]
world_info = ExtResource("2_gynur")
initial_spawn_id = &"Staircase"
debug_spawn_point = &"ChaseInfrontBeginning"
@ -33,13 +38,13 @@ spawn_id = &"Staircase"
metadata/_custom_type_script = "uid://3hlvt5k34xva"
[node name="SpawnInfrontChase" type="Marker3D" parent="Spawnpoints" index="1"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, -26)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1, 4, -26)
script = ExtResource("3_5eifk")
spawn_id = &"ChaseInfrontBeginning"
metadata/_custom_type_script = "uid://3hlvt5k34xva"
[node name="SpawnChaseBeginning" type="Marker3D" parent="Spawnpoints" index="2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, -28)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1, 4, -28)
script = ExtResource("3_5eifk")
spawn_id = &"ChaseBeginning"
metadata/_custom_type_script = "uid://3hlvt5k34xva"
@ -54,6 +59,16 @@ override_level_id = false
level_id = &"LayoutTest"
metadata/_custom_type_script = "uid://dfnb036hysorj"
[node name="LevelArea" parent="LevelLoaders/LoaderLayoutTest" index="1" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("4_clslv")]
level_loader = NodePath("..")
loaded_if_spawnpoint = [NodePath("../../../Spawnpoints/SpawnStaircase"), NodePath("../../../Spawnpoints/SpawnChaseBeginning"), NodePath("../../../Spawnpoints/SpawnInfrontChase")]
keep_loaded_duration = 2.0
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelLoaders/LoaderLayoutTest/LevelArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6.5, -785.5)
shape = SubResource("BoxShape3D_77q0j")
debug_color = Color(1, 1, 0, 0.41960785)
[node name="LoaderChaseLGTest" type="Marker3D" parent="LevelLoaders" index="1"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -14.5, 3.5, -37.5)
script = ExtResource("2_5eifk")
@ -62,6 +77,16 @@ override_level_id = false
level_id = &"ChaseTest"
metadata/_custom_type_script = "uid://dfnb036hysorj"
[node name="LevelArea" parent="LevelLoaders/LoaderChaseLGTest" index="1" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("4_clslv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -3.5, 37.5)
level_loader = NodePath("..")
loaded_if_spawnpoint = [NodePath("../../../Spawnpoints/SpawnChaseBeginning")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelLoaders/LoaderChaseLGTest/LevelArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6.5, -613.54346)
shape = SubResource("BoxShape3D_clslv")
debug_color = Color(1, 1, 0, 0.41960785)
[node name="LoaderChaseEFTest" type="Marker3D" parent="LevelLoaders" index="2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 14.5, 3.5, -37.5)
script = ExtResource("2_5eifk")
@ -70,39 +95,71 @@ override_level_id = false
level_id = &"ChaseTest"
metadata/_custom_type_script = "uid://dfnb036hysorj"
[node name="LevelAreas" type="Node" parent="." index="2"]
[node name="LevelArea" parent="LevelLoaders/LoaderChaseEFTest" index="1" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("4_clslv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -3.5, 37.5)
level_loader = NodePath("..")
loaded_if_spawnpoint = [NodePath("../../../Spawnpoints/SpawnChaseBeginning")]
[node name="LayoutTestArea" parent="LevelAreas" index="0" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("4_clslv")]
level_loader = NodePath("../../LevelLoaders/LoaderLayoutTest")
loaded_if_spawnpoint = [NodePath("../../Spawnpoints/SpawnStaircase"), NodePath("../../Spawnpoints/SpawnChaseBeginning"), NodePath("../../Spawnpoints/SpawnInfrontChase")]
keep_loaded_duration = 20.0
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelAreas/LayoutTestArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6.5, -69)
shape = SubResource("BoxShape3D_77q0j")
debug_color = Color(1, 1, 0, 0.41960785)
[node name="ChaseLGArea" parent="LevelAreas" index="1" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("4_clslv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -14.5, 0, 0)
level_loader = NodePath("../../LevelLoaders/LoaderChaseLGTest")
loaded_if_spawnpoint = [NodePath("../../Spawnpoints/SpawnChaseBeginning")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelAreas/ChaseLGArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6.5, -613.54346)
shape = SubResource("BoxShape3D_clslv")
debug_color = Color(1, 1, 0, 0.41960785)
[node name="ChaseEFArea" parent="LevelAreas" index="2" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("4_clslv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 14.5, 0, 0)
level_loader = NodePath("../../LevelLoaders/LoaderChaseEFTest")
loaded_if_spawnpoint = [NodePath("../../Spawnpoints/SpawnChaseBeginning")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelAreas/ChaseEFArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6.5, -907.04346)
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelLoaders/LoaderChaseEFTest/LevelArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6.5, -801.04346)
shape = SubResource("BoxShape3D_gynur")
debug_color = Color(1, 1, 0, 0.41960785)
[node name="Checkpoints" type="Node" parent="." index="3"]
[node name="LoaderChaseGNTest" type="Marker3D" parent="LevelLoaders" index="3"]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -12.5, 3.5, -28.5)
script = ExtResource("2_5eifk")
scene_path = "uid://buftkff6aaq04"
override_level_id = false
level_id = &"ChaseTest"
metadata/_custom_type_script = "uid://dfnb036hysorj"
[node name="LevelArea" parent="LevelLoaders/LoaderChaseGNTest" index="1" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("4_clslv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -3.5, 37.5)
level_loader = NodePath("..")
loaded_if_spawnpoint = [NodePath("../../../Spawnpoints/SpawnChaseBeginning")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelLoaders/LoaderChaseGNTest/LevelArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6.5, -801.04346)
shape = SubResource("BoxShape3D_gynur")
debug_color = Color(1, 1, 0, 0.41960785)
[node name="LoaderChaseMOTest" type="Marker3D" parent="LevelLoaders" index="4"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.5, -37.5)
script = ExtResource("2_5eifk")
scene_path = "uid://lyl5v6s6waw"
override_level_id = false
level_id = &"ChaseTest"
metadata/_custom_type_script = "uid://dfnb036hysorj"
[node name="LevelArea" parent="LevelLoaders/LoaderChaseMOTest" index="1" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("4_clslv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -3.5, 37.5)
level_loader = NodePath("..")
loaded_if_spawnpoint = [NodePath("../../../Spawnpoints/SpawnChaseBeginning")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelLoaders/LoaderChaseMOTest/LevelArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6.5, -801.04346)
shape = SubResource("BoxShape3D_gynur")
debug_color = Color(1, 1, 0, 0.41960785)
[node name="LoaderRhythmTest" type="Marker3D" parent="LevelLoaders" index="5"]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 12.5, 3.5, -29.5)
script = ExtResource("2_5eifk")
scene_path = "uid://7se2e0m4ivcn"
override_level_id = false
level_id = &"ChaseTest"
metadata/_custom_type_script = "uid://dfnb036hysorj"
[node name="LevelArea" parent="LevelLoaders/LoaderRhythmTest" index="1" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("4_clslv")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 29.5, -3.5, -2.000001)
level_loader = NodePath("..")
loaded_if_spawnpoint = [NodePath("../../../Spawnpoints/SpawnChaseBeginning")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelLoaders/LoaderRhythmTest/LevelArea" index="0"]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 3, 6.5, -29.543457)
shape = SubResource("BoxShape3D_vcy7h")
debug_color = Color(1, 1, 0, 0.41960785)
[node name="Checkpoints" type="Node" parent="." index="2"]
[node name="GameStateOverrider" type="Area3D" parent="Checkpoints" index="0" node_paths=PackedStringArray("level_loader", "spawnpoint")]
collision_layer = 0
@ -112,14 +169,13 @@ do_save = false
override_chapter_index = false
level_loader = NodePath("../../LevelLoaders/LoaderLayoutTest")
spawnpoint = NodePath("../../Spawnpoints/SpawnInfrontChase")
use_player_transform = false
metadata/_custom_type_script = "uid://u2s0spt1rud4"
[node name="CollisionShape3D" type="CollisionShape3D" parent="Checkpoints/GameStateOverrider" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5, -23.751904)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1, 5, -28.251904)
shape = SubResource("BoxShape3D_tys81")
[node name="DeathArea" type="Area3D" parent="." index="4"]
[node name="DeathArea" type="Area3D" parent="." index="3"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -7, 0)
collision_layer = 0
collision_mask = 2

View File

@ -0,0 +1,19 @@
[remap]
importer="mp3"
type="AudioStreamMP3"
uid="uid://du3mds6gp7awe"
path="res://.godot/imported/Maestro.mp3-84933deddf14ac0571897a97f8b07420.mp3str"
[deps]
source_file="res://_development/ayuroo/levels/_chase_test/maestro/Maestro.mp3"
dest_files=["res://.godot/imported/Maestro.mp3-84933deddf14ac0571897a97f8b07420.mp3str"]
[params]
loop=true
loop_offset=0.0
bpm=160.0
beat_count=0
bar_beats=4

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,142 @@
[gd_scene load_steps=14 format=3 uid="uid://lyl5v6s6waw"]
[ext_resource type="Script" uid="uid://cdgei0ihcem0n" path="res://_development/ayuroo/levels/_chase_test/_chase_test.gd" id="1_ce4yl"]
[ext_resource type="AudioStream" uid="uid://bxka3egn4m01r" path="res://_development/ayuroo/levels/_chase_test/tick.ogg" id="2_v5aaa"]
[ext_resource type="AudioStream" uid="uid://bji7bb0rrangg" path="res://_development/ayuroo/levels/_chase_test/tack.ogg" id="3_kbj6i"]
[ext_resource type="AnimationLibrary" uid="uid://dhcvtj55pdbi0" path="res://_development/ayuroo/levels/_chase_test/maestro/_mo_anim.tres" id="4_q2x38"]
[ext_resource type="Script" uid="uid://jahmwrxb2siw" path="res://tools/timed_music_animationplayer.gd" id="5_5dvgd"]
[ext_resource type="Script" uid="uid://dp6jy00a6xuhk" path="res://tools/beat_measurer.gd" id="6_hltqc"]
[ext_resource type="Material" uid="uid://c38215ysnknyk" path="res://assets/materials/dev/dark/dark_01.tres" id="7_6lemm"]
[ext_resource type="PackedScene" uid="uid://c0jearfhlqcvr" path="res://src/gameplay/hazards/saw/saw.tscn" id="8_lca1p"]
[ext_resource type="Script" uid="uid://bbwtct3hoxwws" path="res://src/core/vibration_component.gd" id="9_yut28"]
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_2frp2"]
playback_mode = 2
streams_count = 2
stream_0/stream = ExtResource("2_v5aaa")
stream_1/stream = ExtResource("3_kbj6i")
[sub_resource type="Curve3D" id="Curve3D_tqtrq"]
_data = {
"points": PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -897),
"tilts": PackedFloat32Array(0, 0)
}
point_count = 2
[sub_resource type="SphereMesh" id="SphereMesh_tqtrq"]
radius = 0.15
height = 0.3
[sub_resource type="BoxShape3D" id="BoxShape3D_gsfaw"]
size = Vector3(14, 5, 1)
[node name="ChaseTest" type="Node3D"]
script = ExtResource("1_ce4yl")
chase_anim = &"maestro"
metadata/_custom_type_script = "uid://cigop0ivp5vvu"
[node name="Music" type="AudioStreamPlayer" parent="."]
volume_db = -4.5
[node name="Beat" type="AudioStreamPlayer" parent="."]
stream = SubResource("AudioStreamRandomizer_2frp2")
volume_db = -3.0
max_polyphony = 4
[node name="Bar" type="AudioStreamPlayer" parent="."]
stream = ExtResource("3_kbj6i")
volume_db = -6.0
[node name="MusicAnimation" type="AnimationPlayer" parent="."]
audio_max_polyphony = 1
callback_mode_process = 0
callback_mode_method = 1
libraries = {
&"": ExtResource("4_q2x38")
}
script = ExtResource("5_5dvgd")
audio_player = NodePath("../Music")
metadata/_custom_type_script = "uid://jahmwrxb2siw"
[node name="CameraRoot" type="Node3D" parent="."]
transform = Transform3D(0.99999887, 0, 0, 0, 0.99999887, 0, 0, 0, 0.99999887, 0, 1, -897)
[node name="Camera3D" type="Camera3D" parent="CameraRoot"]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 2, 0, 0)
fov = 37.38998
[node name="ProgressTrack" type="Path3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
curve = SubResource("Curve3D_tqtrq")
[node name="PlayerDesiredProgress" type="PathFollow3D" parent="ProgressTrack"]
rotation_mode = 0
loop = false
[node name="DebugVisualizer" type="MeshInstance3D" parent="ProgressTrack/PlayerDesiredProgress"]
mesh = SubResource("SphereMesh_tqtrq")
[node name="RemoteTransform3D" type="RemoteTransform3D" parent="ProgressTrack/PlayerDesiredProgress/DebugVisualizer"]
remote_path = NodePath("../../../../CameraRoot")
update_scale = false
[node name="BeatMeasurer" type="Node" parent="ProgressTrack" node_paths=PackedStringArray("path")]
script = ExtResource("6_hltqc")
path = NodePath("..")
track_duration = 290.06
track_bpm = 176
metadata/_custom_type_script = "uid://dp6jy00a6xuhk"
[node name="CSGCombiner3D" type="CSGCombiner3D" parent="."]
use_collision = true
[node name="CSGBox3D" type="CSGBox3D" parent="CSGCombiner3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -450)
size = Vector3(14, 1, 901)
material = ExtResource("7_6lemm")
[node name="Saws" type="Node3D" parent="."]
[node name="ResetSaw" parent="Saws" instance=ExtResource("8_lca1p")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 1, -896.19434)
[node name="Saw" parent="Saws" instance=ExtResource("8_lca1p")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, -46)
[node name="Saw2" parent="Saws" instance=ExtResource("8_lca1p")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, -53)
[node name="HeavyBeatVibration" type="Node" parent="."]
script = ExtResource("9_yut28")
duration = 0.1
sync_to_audio = true
weak_magnitude = 0.575
strong_magnitude = 0.75
weak_controller_magnitude_multiplier = 1.5
weak_controller_duration_multiplier = 1.25
metadata/_custom_type_script = "uid://bbwtct3hoxwws"
[node name="LightBeatVibration" type="Node" parent="."]
script = ExtResource("9_yut28")
duration = 0.175
sync_to_audio = true
weak_magnitude = 0.375
strong_magnitude = 0.0
weak_controller_magnitude_multiplier = 1.75
metadata/_custom_type_script = "uid://bbwtct3hoxwws"
[node name="StartChaseArea" type="Area3D" parent="."]
collision_layer = 0
collision_mask = 2
[node name="CollisionShape3D" type="CollisionShape3D" parent="StartChaseArea"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0)
shape = SubResource("BoxShape3D_gsfaw")
[node name="_DEV_LABEL" type="Label3D" parent="."]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 6, 2, -3)
text = "If the audio and anim desync and cause the player to slow down,
set the follower up, so that it always stays at a certain
distance from the PlayerDesiredProgress ball/point/marker."
[connection signal="body_entered" from="StartChaseArea" to="." method="_on_start_chase_area_body_entered"]

View File

@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://cwpx80o5yaauf"
path="res://.godot/imported/120bpm_beat.ogg-0962ec5100a97c7393d43714eea8b62e.oggvorbisstr"
[deps]
source_file="res://_development/ayuroo/levels/_chase_test/rhythm_test/120bpm_beat.ogg"
dest_files=["res://.godot/imported/120bpm_beat.ogg-0962ec5100a97c7393d43714eea8b62e.oggvorbisstr"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4

View File

@ -0,0 +1,647 @@
[gd_scene load_steps=21 format=3 uid="uid://7se2e0m4ivcn"]
[ext_resource type="Script" uid="uid://cdgei0ihcem0n" path="res://_development/ayuroo/levels/_chase_test/_chase_test.gd" id="1_td1ny"]
[ext_resource type="AudioStream" uid="uid://bxka3egn4m01r" path="res://_development/ayuroo/levels/_chase_test/tick.ogg" id="2_hqvl2"]
[ext_resource type="AudioStream" uid="uid://bji7bb0rrangg" path="res://_development/ayuroo/levels/_chase_test/tack.ogg" id="3_gkp73"]
[ext_resource type="AudioStream" uid="uid://cwpx80o5yaauf" path="res://_development/ayuroo/levels/_chase_test/rhythm_test/120bpm_beat.ogg" id="4_rv68v"]
[ext_resource type="Script" uid="uid://jahmwrxb2siw" path="res://tools/timed_music_animationplayer.gd" id="5_qnmws"]
[ext_resource type="Script" uid="uid://dp6jy00a6xuhk" path="res://tools/beat_measurer.gd" id="6_6tlon"]
[ext_resource type="Material" uid="uid://c38215ysnknyk" path="res://assets/materials/dev/dark/dark_01.tres" id="7_xcut5"]
[ext_resource type="PackedScene" uid="uid://c0jearfhlqcvr" path="res://src/gameplay/hazards/saw/saw.tscn" id="8_burxb"]
[ext_resource type="Script" uid="uid://bbwtct3hoxwws" path="res://src/core/vibration_component.gd" id="9_k4kf7"]
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_2frp2"]
playback_mode = 2
streams_count = 2
stream_0/stream = ExtResource("2_hqvl2")
stream_1/stream = ExtResource("3_gkp73")
[sub_resource type="Animation" id="Animation_lx33g"]
resource_name = "RESET"
step = 0.0427
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("ProgressTrack/PlayerDesiredProgress:progress_ratio")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
[sub_resource type="Animation" id="Animation_uxiet"]
resource_name = "rhythm_test"
length = 60.0
loop_mode = 1
step = 0.5
markers = [{
"color": Color(1, 1, 1, 1),
"name": &"Intro",
"time": 0.0
}, {
"color": Color(1, 1, 1, 1),
"name": &"HalfTime",
"time": 30.120914
}]
tracks/0/type = "audio"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Music")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"clips": [{
"end_offset": 0.0,
"start_offset": 0.0,
"stream": ExtResource("4_rv68v")
}],
"times": PackedFloat32Array(0)
}
tracks/0/use_blend = true
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("ProgressTrack/PlayerDesiredProgress:progress_ratio")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 60),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [0.0, 1.0]
}
tracks/2/type = "method"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("LightBeatVibration")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0.5, 1, 1.5, 2.5, 3, 3.5, 4.5, 5, 5.5, 6.5, 7, 7.5, 8.5, 9, 9.5, 10.5, 11, 11.5, 12.5, 13, 13.5, 14.5, 15, 15.5, 16.5, 17, 17.5, 18.5, 19, 19.5, 20.5, 21, 21.5, 22.5, 23, 23.5, 24.5, 25, 25.5, 26.5, 27, 27.5, 28.5, 29, 29.5, 30.5, 31, 31.5, 32.5, 33, 33.5, 34.5, 35, 35.5, 36.5, 37, 37.5, 38.5, 39, 39.5, 40.5, 41, 41.5, 42.5, 43, 43.5, 44.5, 45, 45.5, 46.5, 47, 47.5, 48.5, 49, 49.5, 50.5, 51, 51.5, 52.5, 53, 53.5, 54.5, 55, 55.5, 56.5, 57, 57.5, 58.5, 59, 59.5),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"values": [{
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}]
}
tracks/3/type = "method"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("HeavyBeatVibration")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"values": [{
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}, {
"args": [],
"method": &"vibrate"
}]
}
tracks/4/type = "animation"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("Saws/Saw/SawAnimation")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"clips": PackedStringArray("saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in", "saw_out", "saw_in"),
"times": PackedFloat32Array(0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15, 15.5, 16, 16.5, 17, 17.5, 18, 18.5, 19, 19.5, 20, 20.5, 21, 21.5, 22, 22.5, 23, 23.5, 24, 24.5, 25, 25.5, 26, 26.5, 27, 27.5, 28, 28.5, 29, 29.5, 30, 30.5, 31, 31.5, 32, 32.5, 33, 33.5, 34, 34.5, 35, 35.5, 36, 36.5, 37, 37.5, 38, 38.5, 39, 39.5, 40, 40.5, 41, 41.5, 42, 42.5, 43, 43.5, 44, 44.5, 45, 45.5, 46, 46.5, 47, 47.5, 48, 48.5, 49, 49.5, 50, 50.5, 51, 51.5, 52, 52.5, 53, 53.5, 54, 54.5, 55, 55.5, 56, 56.5, 57, 57.5, 58, 58.5, 59, 59.5, 60)
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_4gsqv"]
_data = {
&"RESET": SubResource("Animation_lx33g"),
&"rhythm_test": SubResource("Animation_uxiet")
}
[sub_resource type="Curve3D" id="Curve3D_tqtrq"]
_data = {
"points": PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -13),
"tilts": PackedFloat32Array(0, 0)
}
point_count = 2
[sub_resource type="SphereMesh" id="SphereMesh_tqtrq"]
radius = 0.15
height = 0.3
[sub_resource type="Animation" id="Animation_4gsqv"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Saws/Saw:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector3(3, 0.5, -11)]
}
[sub_resource type="Animation" id="Animation_rv68v"]
resource_name = "saw_in"
length = 0.15
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Saws/Saw:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.15),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector3(3, 0.5, -11), Vector3(3, -0.75, -11)]
}
[sub_resource type="Animation" id="Animation_t4ew6"]
resource_name = "saw_out"
length = 0.15
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Saws/Saw:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.15),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector3(3, -0.75, -11), Vector3(3, 0.5, -11)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_f8t6g"]
_data = {
&"RESET": SubResource("Animation_4gsqv"),
&"saw_in": SubResource("Animation_rv68v"),
&"saw_out": SubResource("Animation_t4ew6")
}
[sub_resource type="BoxShape3D" id="BoxShape3D_gsfaw"]
size = Vector3(14, 5, 1)
[node name="ChaseTest" type="Node3D"]
script = ExtResource("1_td1ny")
chase_anim = &"rhythm_test"
bpm = 120.0
metadata/_custom_type_script = "uid://cigop0ivp5vvu"
[node name="Music" type="AudioStreamPlayer" parent="."]
volume_db = -6.0
[node name="Beat" type="AudioStreamPlayer" parent="."]
stream = SubResource("AudioStreamRandomizer_2frp2")
volume_db = -3.0
max_polyphony = 4
[node name="Bar" type="AudioStreamPlayer" parent="."]
stream = ExtResource("3_gkp73")
volume_db = -6.0
[node name="MusicAnimation" type="AnimationPlayer" parent="."]
audio_max_polyphony = 1
callback_mode_process = 0
callback_mode_method = 1
libraries = {
&"": SubResource("AnimationLibrary_4gsqv")
}
script = ExtResource("5_qnmws")
audio_player = NodePath("../Music")
metadata/_custom_type_script = "uid://jahmwrxb2siw"
[node name="CameraRoot" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
[node name="Camera3D" type="Camera3D" parent="CameraRoot"]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 2, 0, 0)
fov = 37.38998
[node name="ProgressTrack" type="Path3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
curve = SubResource("Curve3D_tqtrq")
[node name="PlayerDesiredProgress" type="PathFollow3D" parent="ProgressTrack"]
rotation_mode = 0
loop = false
[node name="DebugVisualizer" type="MeshInstance3D" parent="ProgressTrack/PlayerDesiredProgress"]
mesh = SubResource("SphereMesh_tqtrq")
[node name="RemoteTransform3D" type="RemoteTransform3D" parent="ProgressTrack/PlayerDesiredProgress/DebugVisualizer"]
remote_path = NodePath("../../../../CameraRoot")
update_scale = false
[node name="BeatMeasurer" type="Node" parent="ProgressTrack" node_paths=PackedStringArray("path")]
script = ExtResource("6_6tlon")
path = NodePath("..")
track_duration = 290.06
track_bpm = 176
metadata/_custom_type_script = "uid://dp6jy00a6xuhk"
[node name="CSGCombiner3D" type="CSGCombiner3D" parent="."]
use_collision = true
[node name="CSGBox3D" type="CSGBox3D" parent="CSGCombiner3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -6.5)
size = Vector3(14, 1, 14)
material = ExtResource("7_xcut5")
[node name="Saws" type="Node3D" parent="."]
[node name="Saw" parent="Saws" instance=ExtResource("8_burxb")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0.5, -11)
[node name="SawAnimation" type="AnimationPlayer" parent="Saws/Saw"]
root_node = NodePath("../../..")
audio_max_polyphony = 1
callback_mode_process = 0
callback_mode_method = 1
libraries = {
&"": SubResource("AnimationLibrary_f8t6g")
}
[node name="HeavyBeatVibration" type="Node" parent="."]
script = ExtResource("9_k4kf7")
duration = 0.1
sync_to_audio = true
weak_magnitude = 0.25
strong_magnitude = 0.5
weak_controller_duration_multiplier = 1.5
metadata/_custom_type_script = "uid://bbwtct3hoxwws"
[node name="LightBeatVibration" type="Node" parent="."]
script = ExtResource("9_k4kf7")
duration = 0.1
sync_to_audio = true
strong_magnitude = 0.125
metadata/_custom_type_script = "uid://bbwtct3hoxwws"
[node name="StartChaseArea" type="Area3D" parent="."]
collision_layer = 0
collision_mask = 2
[node name="CollisionShape3D" type="CollisionShape3D" parent="StartChaseArea"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0)
shape = SubResource("BoxShape3D_gsfaw")
[connection signal="body_entered" from="StartChaseArea" to="." method="_on_start_chase_area_body_entered"]

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=13 format=3 uid="uid://srvm3v1grugk"]
[gd_scene load_steps=22 format=3 uid="uid://srvm3v1grugk"]
[ext_resource type="Script" uid="uid://cigop0ivp5vvu" path="res://src/core/world/level/level.gd" id="1_0kdur"]
[ext_resource type="Material" uid="uid://c38215ysnknyk" path="res://assets/materials/dev/dark/dark_01.tres" id="2_cxrf3"]
@ -10,6 +10,9 @@
[ext_resource type="LightmapGIData" uid="uid://c0mcaeg0ikvmo" path="res://_development/ayuroo/levels/_experimental/_layout_test.lmbake" id="7_cv3fe"]
[ext_resource type="Script" uid="uid://dbcy7qdq4hqlg" path="res://addons/lightmap_probe_grid/lightmap_probe_grid.gd" id="9_p8lkr"]
[ext_resource type="Material" uid="uid://c4uudb0m5p048" path="res://tools/lightbeam/lightbeam_material.tres" id="10_283a8"]
[ext_resource type="PackedScene" uid="uid://bn6ylrp7gn2mq" path="res://src/gameplay/interactables/test_collectible.tscn" id="10_vl7nw"]
[ext_resource type="Script" uid="uid://bouybbg0o60d4" path="res://tools/cubemap_generator.gd" id="11_161yw"]
[ext_resource type="PackedScene" uid="uid://c6r5kuxoootli" path="res://src/gameplay/interactables/test_button.tscn" id="13_5yihs"]
[sub_resource type="Environment" id="Environment_cv3fe"]
tonemap_mode = 2
@ -18,6 +21,56 @@ glow_bloom = 1.0
[sub_resource type="PlaneMesh" id="PlaneMesh_vl7nw"]
[sub_resource type="Curve3D" id="Curve3D_161yw"]
_data = {
"points": PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8.384, 0, -0.259, 0, 0, 0, 0, 0, 0, 9.189121, 0.1175164, -4.7231674, 0, 0, 0, 0, 0, 0, 8.732193, 3.8047876, -13.381323, 0, 0, 0, 0, 0, 0, 9.587055, 3.3351002, -17.84987, 0, 0, 0, 0, 0, 0, 17.448553, 3.413024, -19.285408, 0, 0, 0, 0, 0, 0, 17.055298, 3.6111283, -24.103613, 0, 0, 0, 0, 0, 0, 7.709808, 3.834219, -25.328993, 0, 0, 0, 0, 0, 0, 7.1683526, 3.5565443, -29.338982, 0, 0, 0, 0, 0, 0, 8.131235, 2.7369313, -37.82245),
"tilts": PackedFloat32Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
}
point_count = 10
[sub_resource type="Animation" id="Animation_p23v4"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("..:progress_ratio")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
[sub_resource type="Animation" id="Animation_5yihs"]
resource_name = "new_animation"
loop_mode = 2
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("..:progress_ratio")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [0.0, 1.0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_pm2x5"]
_data = {
&"RESET": SubResource("Animation_p23v4"),
&"new_animation": SubResource("Animation_5yihs")
}
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_161yw"]
metallic = 1.0
roughness = 0.0
[sub_resource type="SphereMesh" id="SphereMesh_5yihs"]
[node name="LayoutTest" type="Node3D"]
script = ExtResource("1_0kdur")
metadata/_custom_type_script = "uid://cigop0ivp5vvu"
@ -309,6 +362,9 @@ visible = false
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0)
metadata/_edit_lock_ = true
[node name="TestCollectible" parent="LightmapGI" instance=ExtResource("10_vl7nw")]
transform = Transform3D(0.8660254, 0, 0.5, 0, 1, 0, -0.5, 0, 0.8660254, 2, 2.9999993, -29)
[node name="Lighting" type="Node3D" parent="LightmapGI"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0)
@ -1090,6 +1146,14 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -11.042128, -1.8584228, -1.41
[node name="LightmapProbe 3, 2, 3" type="LightmapProbe" parent="LightmapGI/LightmapProbes/LightmapProbeGrid4"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -11.042128, -1.8584228, -4.244747)
[node name="CubeMapGeneratorCamera" type="Camera3D" parent="LightmapGI"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5, -51.4)
visible = false
fov = 90.0
script = ExtResource("11_161yw")
resolution = 12
metadata/_custom_type_script = "uid://bouybbg0o60d4"
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_cv3fe")
@ -1097,3 +1161,26 @@ environment = SubResource("Environment_cv3fe")
transform = Transform3D(44, 0, 0, 0, -4.371139e-08, -31, 0, 1, -1.3550531e-06, 0, 48, -51.4)
material_override = ExtResource("10_283a8")
mesh = SubResource("PlaneMesh_vl7nw")
[node name="Path3D" type="Path3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.596221, 1.5, 3.6047435)
curve = SubResource("Curve3D_161yw")
[node name="PathFollow3D" type="PathFollow3D" parent="Path3D"]
rotation_mode = 0
[node name="AnimationPlayer" type="AnimationPlayer" parent="Path3D/PathFollow3D"]
root_node = NodePath("../MeshInstance3D2")
libraries = {
&"": SubResource("AnimationLibrary_pm2x5")
}
autoplay = "new_animation"
speed_scale = 0.02
[node name="MeshInstance3D2" type="MeshInstance3D" parent="Path3D/PathFollow3D"]
material_override = SubResource("StandardMaterial3D_161yw")
mesh = SubResource("SphereMesh_5yihs")
skeleton = NodePath("../../..")
[node name="CommonButton" parent="." instance=ExtResource("13_5yihs")]
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, -2, 5.8, -28.2)

Binary file not shown.

View File

@ -0,0 +1,42 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://b1ax1psf37ets"
path="res://.godot/imported/godot_plush_sitting.glb-0976f26961774533aed945988fb919e5.scn"
[deps]
source_file="res://assets/models/plush/godot_plush_sitting.glb"
dest_files=["res://.godot/imported/godot_plush_sitting.glb-0976f26961774533aed945988fb919e5.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=0
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=true
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 MiB

View File

@ -0,0 +1,44 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://byxam2d0pahu0"
path.s3tc="res://.godot/imported/godot_plush_sitting_godot_plush_basecolor.png-19716d1f5e2e4071807f25506ccd05d8.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={
"md5": "6aa88ad35f2cb7798263bd4925888e7b"
}
[deps]
source_file="res://assets/models/plush/godot_plush_sitting_godot_plush_basecolor.png"
dest_files=["res://.godot/imported/godot_plush_sitting_godot_plush_basecolor.png-19716d1f5e2e4071807f25506ccd05d8.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

View File

@ -0,0 +1,44 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://6e6jhxo8507x"
path.s3tc="res://.godot/imported/godot_plush_sitting_godot_plush_normal.png-29b0a51fe8f67cea2d5bc3d37b9885e9.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={
"md5": "33ac1a9f1eac7545987cebf825968bea"
}
[deps]
source_file="res://assets/models/plush/godot_plush_sitting_godot_plush_normal.png"
dest_files=["res://.godot/imported/godot_plush_sitting_godot_plush_normal.png-29b0a51fe8f67cea2d5bc3d37b9885e9.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://assets/models/plush/godot_plush_sitting_godot_plush_normal.png"
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

View File

@ -0,0 +1,44 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dx8dnt87dovdm"
path.s3tc="res://.godot/imported/godot_plush_sitting_godot_plush_roughness.png-c986f129af18223c92dbf964e18255cb.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={
"md5": "53e8d52887ded32d898767cc245cc96a"
}
[deps]
source_file="res://assets/models/plush/godot_plush_sitting_godot_plush_roughness.png"
dest_files=["res://.godot/imported/godot_plush_sitting_godot_plush_roughness.png-c986f129af18223c92dbf964e18255cb.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

BIN
source/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

3
source/icon.png.import Normal file
View File

@ -0,0 +1,3 @@
[remap]
importer="skip"

View File

@ -22,7 +22,7 @@ SettingsManager="*res://src/globals/autoloads/settings/settings_manager.gd"
SceneFader="*res://src/globals/autoloads/scene_fader/scene_fader.tscn"
GameGlobals="*res://src/globals/autoloads/game_globals.gd"
InputManager="*res://src/globals/autoloads/input_manager.gd"
SaveManager="*res://src/globals/autoloads/save_manager/save_manager.gd"
SaveManager="*res://src/globals/autoloads/save_manager/save_manager.tscn"
AudioManager="*res://src/globals/autoloads/audio/audio_manager.tscn"
Logger="*res://addons/logger/logger.tscn"
VersionDisplay="*res://addons/version_display/version_display.tscn"
@ -203,6 +203,7 @@ locale/translations_pot_files=PackedStringArray("res://src/ui/menus/main_menu/ma
3d_render/layer_1="Static"
3d_render/layer_2="Dynamic"
3d_physics/layer_2="Characters"
3d_physics/layer_3="Interaction"
3d_physics/layer_11="World"
[physics]
@ -214,6 +215,7 @@ jolt_physics_3d/collisions/collision_margin_fraction=0.0
anti_aliasing/quality/screen_space_aa=2
occlusion_culling/use_occlusion_culling=true
environment/defaults/default_environment="uid://cujlm5u722ot7"
[run_configs]

View File

@ -0,0 +1,14 @@
[gd_resource type="Environment" load_steps=4 format=3 uid="uid://cujlm5u722ot7"]
[ext_resource type="Texture2D" uid="uid://bxxamjotmlubu" path="res://resources/editor_panorama.png" id="1_2oonr"]
[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_huhbn"]
panorama = ExtResource("1_2oonr")
[sub_resource type="Sky" id="Sky_xdwe2"]
sky_material = SubResource("PanoramaSkyMaterial_huhbn")
[resource]
background_mode = 2
sky = SubResource("Sky_xdwe2")
glow_enabled = true

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 MiB

View File

@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bxxamjotmlubu"
path.s3tc="res://.godot/imported/editor_panorama.png-de50614a5c3fcd56125b400a1893f3ae.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://resources/editor_panorama.png"
dest_files=["res://.godot/imported/editor_panorama.png-de50614a5c3fcd56125b400a1893f3ae.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -1,12 +1,11 @@
[gd_resource type="Resource" script_class="GameState" load_steps=3 format=3 uid="uid://dpgfu1y1cqhvk"]
[gd_resource type="Resource" script_class="GameState" load_steps=5 format=3 uid="uid://dpgfu1y1cqhvk"]
[ext_resource type="Script" uid="uid://fc1y4sr6ofvq" path="res://src/core/game_state.gd" id="1_0ugyj"]
[ext_resource type="Script" uid="uid://dq4pwtwhxusxc" path="res://src/core/world/world_state.gd" id="2_k3cva"]
[ext_resource type="Resource" uid="uid://d2qpu70epn5rs" path="res://src/worlds/expo_combined_info.tres" id="2_s8hvi"]
[ext_resource type="Script" uid="uid://dlf1vq0qej6bs" path="res://src/core/world/world_info.gd" id="4_k3cva"]
[resource]
script = ExtResource("1_0ugyj")
world_info = ExtResource("2_s8hvi")
level_id = &"OutsideArea"
spawnpoint_id = &"OutsideSpawn"
use_player_transform = false
initial_world = ExtResource("2_s8hvi")
metadata/_custom_type_script = "uid://fc1y4sr6ofvq"

View File

@ -0,0 +1,28 @@
class_name ViewRollEffect
extends CameraEffect
@export var character: Character3D
@export var smoothing_speed: float = 10.0
@export_range(-25.0, 25.0, 0.01, "or_greater", "or_less", "suffix:deg")
var roll_max_angle: float = 2.5
var _previous_rotation := Vector3.ZERO
func _process_effect(delta: float) -> void:
if not is_instance_valid(character):
return
var velocity: Vector3 = character.velocity.rotated(Vector3.UP, -root_node.rotation.y)
rotation.z = deg_to_rad(clampf(-velocity.x, -roll_max_angle, roll_max_angle))
rotation.x = deg_to_rad(clampf(velocity.z, -roll_max_angle, roll_max_angle))
var weight: float = 1.0 - pow(0.5, delta * smoothing_speed)
rotation.z = lerp_angle(_previous_rotation.z, rotation.z, weight)
rotation.x = lerp_angle(_previous_rotation.x, rotation.x, weight)
_previous_rotation = rotation
func _effect_disabled() -> void:
_previous_rotation = Vector3.ZERO

View File

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

View File

@ -1,11 +1,64 @@
class_name GameState
extends Resource
@export var world_info: WorldInfo
@export var level_id: StringName = &""
@export var spawnpoint_id: StringName = &""
@export var initial_world: WorldInfo
@export var current_world_state: WorldState
@export var chapter_index: int = 0
@export var level_data: Dictionary = {}
@export var use_player_transform: bool = true
@export var player_transform: Transform3D
@export var world_states: Dictionary[WorldInfo, WorldState] = {}
@export var unlocked_collectibles: Array[StringName] = []
var current_world_info: WorldInfo
var current_world: World
func create_duplicate() -> GameState:
var game_state := GameState.new()
game_state.initial_world = initial_world
game_state.chapter_index = chapter_index
game_state.unlocked_collectibles = unlocked_collectibles.duplicate()
game_state.world_states = world_states.duplicate_deep(DeepDuplicateMode.DEEP_DUPLICATE_INTERNAL)
return game_state
func initialize_world_state(world_info: WorldInfo, set_as_active: bool = false, reset_if_exists: bool = false) -> WorldState:
if world_states.has(world_info):
if reset_if_exists:
current_world_state = world_states.get(
world_info,
WorldState.create_from_world_info(world_info)
)
return world_states.get(world_info)
var world_state := WorldState.create_from_world_info(world_info)
world_states.set(world_info, world_state)
if set_as_active:
current_world_state = world_state
return world_state
func store_world_state(world_info: WorldInfo, world_state: WorldState) -> void:
world_states.set(world_info, world_state)
func get_level_id(world_info: WorldInfo = null) -> StringName:
var world_state: WorldState = get_world_state(world_info)
if not is_instance_valid(world_state):
return &""
return world_state.level_id if not world_state.level_id.is_empty() else world_state.world_info.initial_level
func get_world_info(world_info: WorldInfo = null) -> WorldInfo:
var world_state: WorldState = get_world_state(world_info)
return world_state.world_info if is_instance_valid(world_state) else initial_world
func get_world_state(world_info: WorldInfo = null) -> WorldState:
return world_states.get(
world_info
if is_instance_valid(world_info)
else current_world_state.world_info
)

View File

@ -39,19 +39,22 @@ func override_game_state() -> void:
if not cooldown_timer.is_stopped():
return
var world: World = GameGlobals.game.world
var world_state: WorldState = world.get_world_state()
if override_chapter_index:
if not chapter_override_if_higher or chapter_index > GameGlobals.game_state.chapter_index:
GameGlobals.game_state.chapter_index = chapter_index
if override_spawnpoint_id:
GameGlobals.game_state.spawnpoint_id = spawnpoint.spawn_id
world_state.spawnpoint_id = spawnpoint.spawn_id
if override_player:
GameGlobals.game.store_player_transform()
GameGlobals.game_state.use_player_transform = use_player_transform
world_state.use_player_transform = use_player_transform
if override_level:
GameGlobals.game_state.level_id = level_loader.level_id
world_state.level_id = level_loader.level_id
if do_save:
GameGlobals.request_save()

View File

@ -0,0 +1,96 @@
class_name InstancePersister
var watched_node: Node: set = set_watched_node
var watched_properties: Array[NodePath] = []
var update_on_child_order_change: bool = false
var _instance_path: String = ""
static func get_owner_nodes(node: Node) -> Array[Node]:
if not is_instance_valid(node):
return [node]
var owners: Array[Node] = []
var owner: Node = node.owner
if is_instance_valid(owner):
owners.append(owner)
owners.append_array(get_owner_nodes(owner))
elif is_instance_valid(node.get_parent()):
if is_instance_valid(node.get_parent().owner):
owners.append_array(get_owner_nodes(node.get_parent()))
else:
owners.append(node.get_parent())
return owners
func _init(bound_node: Node, properties: Array[NodePath] = []) -> void:
SaveManager.pre_save.connect(_on_pre_save)
set_watched_node(bound_node)
for property: NodePath in properties:
persist_property(property, false)
func set_watched_node(node: Node) -> void:
if is_instance_valid(watched_node):
watched_node.child_order_changed.disconnect(_update_instance_path)
if not node.is_inside_tree():
await node.tree_entered
watched_node = node
if update_on_child_order_change and is_instance_valid(watched_node):
watched_node.child_order_changed.connect(_update_instance_path)
_update_instance_path()
func persist_property(property: NodePath, do_save: bool = false) -> void:
if not watched_properties.has(property):
watched_properties.append(property)
if do_save:
GameGlobals.request_save()
func has_entry(property: NodePath) -> bool:
var world_state: WorldState = GameGlobals.game.world.get_world_state()
if not is_instance_valid(world_state):
return false
return world_state.instance_data.has(_get_property_path(property))
func get_entry(property: NodePath, default: Variant = null) -> Variant:
var world_state: WorldState = GameGlobals.game.world.get_world_state()
if not is_instance_valid(world_state):
return default
return world_state.instance_data.get(_get_property_path(property), default)
func _get_property_path(property: NodePath) -> String:
return str(_instance_path, ":", property)
func _update_instance_path() -> void:
var path: String = ""
var owner_nodes: Array[Node] = get_owner_nodes(watched_node)
owner_nodes.reverse()
for owner: Node in owner_nodes:
path += owner.name + "/"
_instance_path = str(path, watched_node.name)
func _on_pre_save(game_state: GameState) -> void:
for property: NodePath in watched_properties:
var value: Variant = watched_node.get_indexed(property)
game_state.current_world.get_world_state().instance_data[_get_property_path(property)] = value

View File

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

View File

@ -0,0 +1,56 @@
class_name InteractionArea
extends Area3D
signal focused
signal unfocused
signal hint_prompts_changed
@export var interaction_types: Array[InteractionType] = []: set = set_interaction_types
var is_focused: bool = false
func _ready() -> void:
set_interaction_types(interaction_types)
func set_interaction_types(types: Array[InteractionType]) -> void:
for type: InteractionType in interaction_types:
if type.hint_prompt_changed.is_connected(hint_prompts_changed.emit):
type.hint_prompt_changed.disconnect(hint_prompts_changed.emit)
interaction_types = types
for type: InteractionType in interaction_types:
if not type.hint_prompt_changed.is_connected(hint_prompts_changed.emit):
type.hint_prompt_changed.connect(hint_prompts_changed.emit)
func set_area_focused(value: bool) -> void:
is_focused = value
(focused if is_focused else unfocused).emit()
for type: InteractionType in interaction_types:
type.set_focused(is_focused)
func get_interaction_strings() -> Array[Array]:
var strings: Array[Array] = []
for interaction_type: InteractionType in interaction_types:
if interaction_type.enabled:
var pre: String = interaction_type.get_hint(0)
var prompt: Texture2D = interaction_type.button_prompt
var post: String = interaction_type.get_hint(1)
strings.append([pre, prompt, post])
print("Interaction Strings: ", strings)
return strings
func _interaction_started(_interaction_ray: InteractionRay) -> void:
pass
func _interaction_ended(_interaction_ray: InteractionRay) -> void:
pass

View File

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

View File

@ -0,0 +1,9 @@
[gd_scene load_steps=2 format=3 uid="uid://2dre1e56emw6"]
[ext_resource type="Script" uid="uid://c4lc0ubqo7gmp" path="res://src/core/interaction/interaction_area.gd" id="1_mhac1"]
[node name="InteractionArea" type="Area3D"]
collision_layer = 4
collision_mask = 0
script = ExtResource("1_mhac1")
metadata/_custom_type_script = "uid://c4lc0ubqo7gmp"

View File

@ -0,0 +1,41 @@
class_name InteractionRay
extends RayCast3D
signal focused_gained(interaction_area: InteractionArea)
signal focus_lost(interaction_area: InteractionArea)
var is_interacting: bool = false
var focused_area: InteractionArea
func _physics_process(_delta: float) -> void:
var collider: Object = get_collider()
#if is_colliding() and collider is InteractionArea and focused_area != collider:
#focused_area = collider
#focused_gained.emit(focused_area)
#elif not collider is InteractionArea and is_instance_valid(focused_area):
#focused_area = null
#focused_gained.emit(null)
if collider == focused_area:
return
if is_instance_valid(focused_area):
focused_area.set_area_focused(false)
focus_lost.emit(focused_area)
focused_area = collider if collider is InteractionArea else null
focused_gained.emit(focused_area)
if is_instance_valid(focused_area):
focused_area.set_area_focused(true)
func get_interaction() -> InteractionArea:
var collider: Object = get_collider()
if collider is InteractionArea:
return collider
return null

View File

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

View File

@ -0,0 +1,9 @@
[gd_scene load_steps=2 format=3 uid="uid://ck2rokdyvqvwg"]
[ext_resource type="Script" uid="uid://dw2afgad5q6hs" path="res://src/core/interaction/interaction_ray.gd" id="1_46xqa"]
[node name="InteractionRay" type="RayCast3D"]
collision_mask = 5
collide_with_areas = true
script = ExtResource("1_46xqa")
metadata/_custom_type_script = "uid://dw2afgad5q6hs"

View File

@ -0,0 +1,74 @@
@abstract
class_name InteractionType
extends Node
signal hint_prompt_changed
@export var enabled: bool = true
@export var hover_hint: String = "Press {prompt} to interact": set = set_hover_hint
@export var button_prompt: Texture2D
#@export var additional_prompts: Dictionary[String, Texture2D] = {}
@export_custom(PROPERTY_HINT_INPUT_NAME, "") var action: StringName = &"interact"
var is_focused: bool = false
var is_interacting: bool = false
func start_interaction() -> void:
if enabled:
is_interacting = true
_interaction_started()
func stop_interaction() -> void:
if enabled:
is_interacting = false
_interaction_ended()
func get_hint(slice_idx: int) -> String:
return hover_hint.get_slice("{prompt}", slice_idx)
#return hover_hint.format({"prompt": str("[img]", button_prompt, "[/img]]")})
# TODO: Convert from string to array.
# "Press {prompt} to {interact} interact{exclamation}"
# ["Press ", Texture, " to ", Texture, " interact", Texture]
func get_full_hint() -> Array:
var prompts: Dictionary[String, Texture2D] = {}#additional_prompts.duplicate()
prompts.set("{prompt}", button_prompt)
var entries: Array = []
var strings: Array[String] = []
for key: String in prompts.keys():
strings.append(hover_hint.split(key))
return entries
func set_focused(value: bool) -> void:
is_focused = value
if enabled:
(_focused if is_focused else _unfocused).call()
func set_hover_hint(text: String) -> void:
hover_hint = text
if is_focused:
hint_prompt_changed.emit()
@abstract func _interaction_started() -> void
@abstract func _interaction_ended() -> void
@abstract func _focused() -> void
@abstract func _unfocused() -> void

View File

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

View File

@ -0,0 +1,62 @@
class_name ButtonInteraction
extends InteractionType
signal turned_on
signal turned_off
@export_range(0.0, 2.0, 0.001, "or_greater", "suffix:s") var interact_cooldown: float = 0.375
@export var can_be_held: bool = false
@export_group("Animation")
@export var animation_player: AnimationPlayer
@export var press_in_animation: StringName = &""
@export var press_out_animation: StringName = &""
var state: bool = false
var _cooldown_timer := Timer.new()
func _ready() -> void:
_cooldown_timer.one_shot = true
_cooldown_timer.timeout.connect(_on_cooldown_timer_timeout)
add_child(_cooldown_timer)
func _unhandled_input(event: InputEvent) -> void:
if not is_focused:
return
if event.is_action_pressed(action):
start_interaction()
elif event.is_action_released(action) and is_interacting:
stop_interaction()
func _interaction_started() -> void:
if not _cooldown_timer.is_stopped():
return
_cooldown_timer.start(interact_cooldown)
enabled = false
state = true
turned_on.emit()
if not can_be_held:
stop_interaction()
func _interaction_ended() -> void:
state = false
turned_off.emit()
func _focused() -> void:
pass
func _unfocused() -> void:
pass
func _on_cooldown_timer_timeout() -> void:
enabled = true

View File

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

View File

@ -0,0 +1,42 @@
class_name CollectibleInteraction
extends InteractionType
@export var collectible_id: StringName = &""
@export var leave_in_world: bool = true
@export var save_game: bool = true
func _ready() -> void:
if not leave_in_world and GameGlobals.game_state.unlocked_collectibles.has(collectible_id):
get_parent().queue_free()
func _unhandled_input(event: InputEvent) -> void:
if not is_focused:
return
if event.is_action_pressed(action):
start_interaction()
elif event.is_action_released(action):
stop_interaction()
func _interaction_started() -> void:
if not GameGlobals.game_state.unlocked_collectibles.has(collectible_id):
GameGlobals.game_state.unlocked_collectibles.append(collectible_id)
if save_game:
GameGlobals.request_save()
func _interaction_ended() -> void:
if not leave_in_world:
get_parent().queue_free()
func _focused() -> void:
pass
func _unfocused() -> void:
pass

View File

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

View File

@ -0,0 +1,18 @@
class_name PickupInteraction
extends InteractionType
# TODO: Figure out, how and if we do pickup interactions.
func _interaction_started() -> void:
pass
func _interaction_ended() -> void:
pass
func _focused() -> void:
pass
func _unfocused() -> void:
pass

View File

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

View File

@ -0,0 +1,68 @@
class_name SwitchInteraction
extends InteractionType
signal toggled_on
signal toggled_off
@export var start_activated: bool = false
@export var hover_hint_on: String = ""
@export var hover_hint_off: String = ""
@export_range(0.0, 2.0, 0.001, "or_greater", "suffix:s") var interact_cooldown: float = 2.0
var state: bool = false
var _cooldown_timer := Timer.new()
var _instance_persister := InstancePersister.new(self, [^"state"])
func _ready() -> void:
state = _instance_persister.get_entry(^"state", start_activated)
_update_prompt()
_cooldown_timer.one_shot = true
_cooldown_timer.timeout.connect(_on_cooldown_timer_timeout)
add_child(_cooldown_timer)
func _unhandled_input(event: InputEvent) -> void:
if not is_focused:
return
if event.is_action_pressed(action):
start_interaction()
func _interaction_started() -> void:
if not _cooldown_timer.is_stopped():
return
state = not state
hover_hint = ""
if interact_cooldown > 0.0:
_cooldown_timer.start(interact_cooldown)
else:
_update_prompt()
stop_interaction()
(toggled_on if state else toggled_off).emit()
func _interaction_ended() -> void:
pass
func _focused() -> void:
pass
func _unfocused() -> void:
pass
func _update_prompt() -> void:
hover_hint = hover_hint_on if state else hover_hint_off
func _on_cooldown_timer_timeout() -> void:
_update_prompt()

View File

@ -0,0 +1 @@
uid://5y74uiijaxrx

View File

@ -150,7 +150,7 @@ func make_current(do_autosave: bool = true) -> void:
GameGlobals.spawn_id = spawn_id
if do_autosave:
SaveManager.save_game()
GameGlobals.request_save()
func generate_unique_identifier() -> StringName:

View File

@ -11,7 +11,7 @@ extends Area3D
func _ready() -> void:
for spawnpoint: PlayerSpawnPoint in loaded_if_spawnpoint:
if GameGlobals.game_state.spawnpoint_id == spawnpoint.spawn_id:
if GameGlobals.game_state.current_world_state.spawnpoint_id == spawnpoint.spawn_id:
var was_threaded: bool = level_loader.load_threaded
level_loader.load_threaded = false
load_level()

View File

@ -9,7 +9,7 @@ signal level_unloaded
static var level_loaders: Array[LevelLoader]
@export_file("*.tscn", "*.scn") var scene_path: String
@export_tool_button("Edit Level", "Load") var editor_edit: Callable = ed_edit_level
@export_tool_button("Edit Level", "Load") var editor_edit: Callable = _editor_edit_level
@export var load_threaded: bool = true
@export_tool_button("Load Level", "Slot") var editor_load: Callable = load_level
@export_tool_button("Unload Level", "Clear") var editor_unload: Callable = unload_level
@ -62,6 +62,8 @@ func _init() -> void:
if Engine.is_editor_hint():
# Setup labels.
_id_label = Label3D.new()
_id_label.ignore_occlusion_culling = true
_id_label.no_depth_test = true
_id_label.billboard = BaseMaterial3D.BILLBOARD_ENABLED
_id_label.shaded = false
_id_label.font_size = 64
@ -80,7 +82,7 @@ func load_level() -> void:
return
if not Engine.is_editor_hint() and override_level_id:
GameGlobals.game_state.level_id = level_id
GameGlobals.game_state.get_world_state().level_id = level_id
if is_instance_valid(level):
if Utils.get_uid(level.scene_file_path) == Utils.get_uid(scene_path):
@ -101,10 +103,10 @@ func load_level() -> void:
assert(is_instance_valid(scene), "Scene is not valid.")
level = scene.instantiate()
add_child(level)
add_child.call_deferred(level)
is_loading = false
level_loaded.emit()
@ -120,7 +122,7 @@ func unload_level() -> void:
level_unloaded.emit()
func ed_edit_level() -> void:
func _editor_edit_level() -> void:
#EditorInterface.open_scene_from_path(scene_path)
Engine.get_singleton(&"EditorInterface").open_scene_from_path.call_deferred(scene_path)

View File

@ -2,6 +2,7 @@
class_name World
extends Node
@export var world_info: WorldInfo
@export var player_scene: PackedScene = preload(GameGlobals.PLAYER_PATH)
@export var capture_mouse_on_ready: bool = true
@export var initial_spawn_id: StringName = &""#:
@ -33,7 +34,7 @@ func _ready() -> void:
_update_spawnpoint()
LevelLoader.load_initial_levels()
#LevelLoader.load_initial_levels()
player_character = _create_player()
_spawn_player()
@ -42,6 +43,11 @@ func _ready() -> void:
InputManager.set_mouse_captured(true)
func _exit_tree() -> void:
if not Engine.is_editor_hint() and GameGlobals.game_state.current_world == self:
GameGlobals.game_state.current_world = null
func spawn_at_spawnpoint(spawnpoint_id: StringName) -> void:
var spawnpoint := PlayerSpawnPoint.get_spawnpoint_by_identifier(spawnpoint_id)
@ -77,22 +83,35 @@ func get_player_transform() -> Transform3D:
return transform
func restore_player_transform() -> void:
var transform: Transform3D = GameGlobals.game_state.player_transform
func set_player_transform(transform: Transform3D) -> void:
player_character.head.global_basis = transform.basis
player_character.global_position = transform.origin
func create_instance_path_to(node: Node) -> NodePath:
#if node.is_ancestor_of(self):
return NodePath(get_path_to(node, true))
func get_world_state() -> WorldState:
var world_state: WorldState = GameGlobals.game_state.get_world_state(world_info)
if not is_instance_valid(world_state):
return GameGlobals.game_state.initialize_world_state(world_info)
return GameGlobals.game_state.get_world_state(world_info)
func _update_spawnpoint() -> void:
if not is_instance_valid(PlayerSpawnPoint.get_spawnpoint_by_identifier(GameGlobals.game_state.spawnpoint_id)):
GameGlobals.game_state.spawnpoint_id = initial_spawn_id
var world_state: WorldState = get_world_state()
if not is_instance_valid(PlayerSpawnPoint.get_spawnpoint_by_identifier(world_state.spawnpoint_id)):
world_state.spawnpoint_id = initial_spawn_id
if OS.has_feature("editor") and debug_enabled:
if not debug_spawn_point.is_empty():
GameGlobals.game_state.spawnpoint_id = debug_spawn_point
world_state.spawnpoint_id = debug_spawn_point
if debug_chapter_idx >= 0:
GameGlobals.game_state.chapter_index = debug_chapter_idx
world_state.chapter_index = debug_chapter_idx
func _create_player() -> PlayerCharacter:
@ -102,10 +121,12 @@ func _create_player() -> PlayerCharacter:
func _spawn_player() -> void:
var world_state: WorldState = get_world_state()
if (
not (OS.has_feature("editor") and debug_enabled)
and GameGlobals.game_state.use_player_transform
and world_state.use_player_transform
):
restore_player_transform()
set_player_transform(world_state.player_transform)
else:
spawn_at_spawnpoint(GameGlobals.game_state.spawnpoint_id)
spawn_at_spawnpoint(world_state.spawnpoint_id)

View File

@ -11,14 +11,16 @@ func get_initial_level_paths() -> PackedStringArray:
func get_level_paths_from_id(level_id: StringName) -> PackedStringArray:
var matching_level_ids: PackedStringArray = []
var level_paths: PackedStringArray = []
for level: LevelInfo in levels:
if level.level_id == level_id:
matching_level_ids.append(level.level_path)
level_paths.append(level.level_path)
if not matching_level_ids.is_empty():
return matching_level_ids
if level_paths.is_empty():
push_warning(
"No level_id's found for level id '%s' in '%s'."
% [level_id, Utils.uid_to_res_path(resource_path)]
)
push_warning("No level_id found for initial level id '%s' in '%s'." % [level_id, resource_path])
return []
return level_paths

View File

@ -0,0 +1,17 @@
class_name WorldState
extends Resource
@export var world_info: WorldInfo
@export var level_id: StringName = &""
@export var spawnpoint_id: StringName = &""
@export var use_player_transform: bool = false
@export var player_transform: Transform3D
@export var instance_data: Dictionary = {}
static func create_from_world_info(info: WorldInfo) -> WorldState:
var world_state := WorldState.new()
world_state.world_info = info
world_state.level_id = info.initial_level
return world_state

View File

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

View File

@ -14,7 +14,7 @@ func _ready() -> void:
AudioManager.play_audio(preload("uid://vft8mjglpa2u"), AudioManager.AMBIENCE)
if load_to_world_info:
load_to_world(GameGlobals.game_state.world_info)
load_to_world(GameGlobals.game_state.current_world_info)
elif SceneFader.is_fading:
SceneFader.fade_out()
@ -35,11 +35,10 @@ func load_to_world(world_info: WorldInfo) -> void:
var new_world: Node = loaded_world.instantiate()
assert(new_world is World, "Loaded scene is not of type [World].")
add_child(new_world)
SceneFader.fade_out()
set_world(new_world)
SceneFader.fade_out.call_deferred()
func get_world() -> World:
return world
@ -47,6 +46,7 @@ func get_world() -> World:
func set_world(new_world: World) -> void:
world = new_world
GameGlobals.game_state.current_world = world
func reload_world() -> void:
@ -58,5 +58,8 @@ func reload_world() -> void:
add_child(world)
func store_player_transform() -> void:
GameGlobals.game_state.player_transform = get_world().get_player_transform()
func store_player_transform(force: bool = false) -> void:
if is_instance_valid(world):
world.get_world_state().player_transform = world.get_player_transform()
elif force:
GameGlobals.game_state.get_world_state().player_transform = world.get_player_transform()

View File

@ -0,0 +1,64 @@
class_name Hud
extends CanvasLayer
@export var interaction_ray: InteractionRay: set = set_interaction_ray
@onready var interaction_prompt: RichTextLabel = $InteractionPrompt
@onready var crosshair: AnimatedSprite2D = %Crosshair
func _ready() -> void:
crosshair.play(&"to_dot", 1.0, true)
func set_interaction_ray(ray: InteractionRay) -> void:
if is_instance_valid(interaction_ray):
interaction_ray.focused_gained.disconnect(_on_interaction_ray_focused)
interaction_ray.focus_lost.disconnect(_on_interaction_ray_focus_lost)
interaction_ray = ray
if is_instance_valid(interaction_ray):
interaction_ray.focused_gained.connect(_on_interaction_ray_focused)
interaction_ray.focus_lost.connect(_on_interaction_ray_focus_lost)
func _on_interaction_ray_focused(area: InteractionArea) -> void:
if is_instance_valid(area):
area.hint_prompts_changed.connect(_populate_focused_hints.bind(area))
_populate_focused_hints(area)
_play_crosshair_anim(&"to_hollow")
else:
interaction_prompt.clear()
_play_crosshair_anim(&"to_dot")
func _on_interaction_ray_focus_lost(area: InteractionArea) -> void:
area.hint_prompts_changed.disconnect(_populate_focused_hints)
func _play_crosshair_anim(anim_name: StringName) -> void:
if crosshair.animation != anim_name:
crosshair.play(anim_name)
func _populate_focused_hints(area: InteractionArea) -> void:
interaction_prompt.clear()
interaction_prompt.push_paragraph(HORIZONTAL_ALIGNMENT_CENTER)
#for hint: Array in area.get_interaction_strings():
#for entry: Variant in hint:
#if typeof(entry) == TYPE_STRING:
#interaction_prompt.append_text(entry)
#elif entry is Texture2D:
#interaction_prompt.add_image(entry, 42, 42)
#
#interaction_prompt.add_text("\n")
for string: Array in area.get_interaction_strings():
if not string[0].is_empty() or not string[2].is_empty():
interaction_prompt.append_text(string[0])
interaction_prompt.add_image(string[1], 42, 42)
interaction_prompt.append_text(string[2] + "\n")
interaction_prompt.pop_all()

View File

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

View File

@ -8,6 +8,7 @@ const ACTION_MOVE_LEFT: StringName = &"move_left"
const ACTION_MOVE_RIGHT: StringName = &"move_right"
const ACTION_MOVE_FORWARD: StringName = &"move_forward"
const ACTION_MOVE_BACKWARD: StringName = &"move_backward"
const ACTION_INTERACT: StringName = &"interact"
@export_group("Crouching")
@export_subgroup("Speed")
@ -30,6 +31,7 @@ var crouch_speed_affection: float = 0.0
@onready var head: PlayerHead = $Head
@onready var collision_shape: CollisionShape3D = $CylinderCollider
@onready var standup_checker: Area3D = $StandupChecker
@onready var interaction_ray: InteractionRay = %InteractionRay
#@onready var stair_stepper: StairStepper = $StairStepper

View File

@ -1,14 +1,18 @@
[gd_scene load_steps=15 format=3 uid="uid://clhy3kiceqf2o"]
[gd_scene load_steps=34 format=3 uid="uid://clhy3kiceqf2o"]
[ext_resource type="Script" uid="uid://day6rhxicaxqf" path="res://src/gameplay/characters/player/player_character.gd" id="1_hqu6r"]
[ext_resource type="Script" uid="uid://dsjlv8midt2g2" path="res://src/gameplay/characters/character_movement.gd" id="2_1ixuj"]
[ext_resource type="Script" uid="uid://2y3gnaqtrfnx" path="res://src/gameplay/characters/player/head.gd" id="2_fjt7c"]
[ext_resource type="Script" uid="uid://44s0v8mukxk4" path="res://src/core/camera/camera_shaker/shaking_camera.gd" id="4_ci1ud"]
[ext_resource type="PackedScene" uid="uid://ck2rokdyvqvwg" path="res://src/core/interaction/interaction_ray.tscn" id="4_de0uv"]
[ext_resource type="Script" uid="uid://nuwb55sbveaf" path="res://src/gameplay/characters/common/footstep_component.gd" id="4_vq0uu"]
[ext_resource type="Script" uid="uid://ss6nj3fn2n77" path="res://src/core/camera/effects/headbobbing_effect.gd" id="4_xn4sk"]
[ext_resource type="Script" uid="uid://xfpktxhb2i7t" path="res://src/core/camera/effects/impact_effect.gd" id="5_ghuot"]
[ext_resource type="Script" uid="uid://ds461t4g8nlnh" path="res://src/core/camera/effects/step_smoothing_effect.gd" id="6_de0uv"]
[ext_resource type="Script" uid="uid://dd0i7xqjwgc6r" path="res://src/core/camera/effects/view_roll_effect.gd" id="7_3mv4n"]
[ext_resource type="Script" uid="uid://dyoa3tnirv7wh" path="res://src/core/camera/camera_effect_target.gd" id="7_ghuot"]
[ext_resource type="Script" uid="uid://gvuvxikepb2r" path="res://src/gameplay/characters/player/hud.gd" id="11_y2ktv"]
[ext_resource type="Texture2D" uid="uid://cwvfdx2v41k0h" path="res://src/ui/hud/crosshair.png" id="13_qx1cj"]
[sub_resource type="Resource" id="Resource_vq0uu"]
script = ExtResource("2_1ixuj")
@ -31,10 +35,116 @@ radius = 0.46
_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.2, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
point_count = 3
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_qx1cj"]
use_z_clip_scale = true
z_clip_scale = 0.01
[sub_resource type="CylinderMesh" id="CylinderMesh_vxew7"]
top_radius = 0.125
bottom_radius = 0.125
height = 0.25
[sub_resource type="CylinderShape3D" id="CylinderShape3D_ntkcp"]
height = 1.59
radius = 0.45
[sub_resource type="AtlasTexture" id="AtlasTexture_qx1cj"]
atlas = ExtResource("13_qx1cj")
region = Rect2(0, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_vxew7"]
atlas = ExtResource("13_qx1cj")
region = Rect2(64, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_hqe5n"]
atlas = ExtResource("13_qx1cj")
region = Rect2(128, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_ateho"]
atlas = ExtResource("13_qx1cj")
region = Rect2(0, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_ybhcy"]
atlas = ExtResource("13_qx1cj")
region = Rect2(64, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_oc077"]
atlas = ExtResource("13_qx1cj")
region = Rect2(128, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_vb64c"]
atlas = ExtResource("13_qx1cj")
region = Rect2(128, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_gfn7w"]
atlas = ExtResource("13_qx1cj")
region = Rect2(64, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_p81y6"]
atlas = ExtResource("13_qx1cj")
region = Rect2(0, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_de76s"]
atlas = ExtResource("13_qx1cj")
region = Rect2(128, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_a3abn"]
atlas = ExtResource("13_qx1cj")
region = Rect2(64, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_5yj12"]
atlas = ExtResource("13_qx1cj")
region = Rect2(0, 0, 64, 64)
[sub_resource type="SpriteFrames" id="SpriteFrames_p81y6"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_qx1cj")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_vxew7")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_hqe5n")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ateho")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ybhcy")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_oc077")
}],
"loop": false,
"name": &"to_dot",
"speed": 16.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_vb64c")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_gfn7w")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_p81y6")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_de76s")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_a3abn")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_5yj12")
}],
"loop": false,
"name": &"to_hollow",
"speed": 16.0
}]
[node name="PlayerCharacter" type="StairsCharacter3D"]
collider = NodePath("CylinderCollider")
step_height_up = 0.7
@ -62,8 +172,10 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0)
script = ExtResource("2_fjt7c")
camera = NodePath("EffectsRoot/ShakingCamera")
character = NodePath("..")
headbob_range = 0.05
headbob_frequency = 2.0
[node name="InteractionRay" parent="Head" instance=ExtResource("4_de0uv")]
unique_name_in_owner = true
target_position = Vector3(0, 0, -1.75)
[node name="HeadbobbingEffect" type="Node" parent="Head" node_paths=PackedStringArray("character", "root_node", "target")]
script = ExtResource("4_xn4sk")
@ -80,6 +192,13 @@ root_node = NodePath("..")
target = NodePath("../EffectsRoot")
metadata/_custom_type_script = "uid://xfpktxhb2i7t"
[node name="ViewRollEffect" type="Node" parent="Head" node_paths=PackedStringArray("character", "root_node", "target")]
script = ExtResource("7_3mv4n")
character = NodePath("../..")
root_node = NodePath("..")
target = NodePath("../EffectsRoot")
metadata/_custom_type_script = "uid://dd0i7xqjwgc6r"
[node name="StepSmoothingEffect" type="Node" parent="Head" node_paths=PackedStringArray("character", "root_node", "target")]
script = ExtResource("6_de0uv")
character = NodePath("../..")
@ -98,6 +217,14 @@ fov = 85.0
script = ExtResource("4_ci1ud")
metadata/_custom_type_script = "uid://44s0v8mukxk4"
[node name="Viewmodel" type="Node3D" parent="Head/EffectsRoot/ShakingCamera"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Head/EffectsRoot/ShakingCamera/Viewmodel"]
transform = Transform3D(0.7728222, -0.5495994, 0.31731132, -2.8930426e-08, 0.49999997, 0.86602557, -0.6346227, -0.6692837, 0.3864111, 0.23610628, -0.23588216, -0.26444602)
visible = false
material_override = SubResource("StandardMaterial3D_qx1cj")
mesh = SubResource("CylinderMesh_vxew7")
[node name="StandupChecker" type="Area3D" parent="."]
collision_layer = 0
input_ray_pickable = false
@ -108,3 +235,42 @@ shape = SubResource("CylinderShape3D_ntkcp")
[node name="FootstepComponent" type="Node" parent="."]
script = ExtResource("4_vq0uu")
[node name="Hud" type="CanvasLayer" parent="." node_paths=PackedStringArray("interaction_ray")]
layer = 0
script = ExtResource("11_y2ktv")
interaction_ray = NodePath("../Head/InteractionRay")
[node name="InteractionPrompt" type="RichTextLabel" parent="Hud"]
anchors_preset = -1
anchor_left = 0.5
anchor_top = 0.675
anchor_right = 0.5
anchor_bottom = 0.675
offset_left = -5.0
offset_top = -4.5
offset_right = 5.0
offset_bottom = 4.5
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
bbcode_enabled = true
fit_content = true
autowrap_mode = 0
[node name="CenterContainer" type="CenterContainer" parent="Hud"]
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
grow_horizontal = 2
grow_vertical = 2
[node name="Crosshair" type="AnimatedSprite2D" parent="Hud/CenterContainer"]
unique_name_in_owner = true
scale = Vector2(0.25, 0.25)
sprite_frames = SubResource("SpriteFrames_p81y6")
animation = &"to_hollow"
frame = 5
frame_progress = 1.0

View File

@ -33,7 +33,7 @@ extends Node3D
func _ready() -> void:
force_update()
force_update.call_deferred()
func set_locked(value: bool) -> void:

View File

@ -0,0 +1,53 @@
[gd_scene load_steps=9 format=3 uid="uid://c6r5kuxoootli"]
[ext_resource type="PackedScene" uid="uid://2dre1e56emw6" path="res://src/core/interaction/interaction_area.tscn" id="1_8b67t"]
[ext_resource type="Script" uid="uid://bvwy23eskb8d" path="res://src/core/interaction/interaction_types/button.gd" id="2_sgaqf"]
[ext_resource type="Script" uid="uid://c2w177bb5r70x" path="res://addons/controller_icons/objects/ControllerIconTexture.gd" id="3_aoew6"]
[ext_resource type="Script" uid="uid://caxr8dg3iundb" path="res://src/core/interaction/interaction_types/collectible.gd" id="4_ueeyx"]
[sub_resource type="BoxMesh" id="BoxMesh_sgaqf"]
size = Vector3(0.4, 0.5, 0.2)
[sub_resource type="BoxShape3D" id="BoxShape3D_sgaqf"]
size = Vector3(0.4, 0.5, 0.2)
[sub_resource type="Texture2D" id="Texture2D_ueeyx"]
resource_local_to_scene = false
resource_name = ""
script = ExtResource("3_aoew6")
path = "interact"
metadata/_custom_type_script = "uid://c2w177bb5r70x"
[sub_resource type="Texture2D" id="Texture2D_0njmr"]
resource_local_to_scene = false
resource_name = ""
script = ExtResource("3_aoew6")
path = "toggle_console"
metadata/_custom_type_script = "uid://c2w177bb5r70x"
[node name="CommonButton" type="Node3D"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.1)
mesh = SubResource("BoxMesh_sgaqf")
skeleton = NodePath("")
[node name="InteractionArea" parent="." node_paths=PackedStringArray("interaction_types") instance=ExtResource("1_8b67t")]
interaction_types = [NodePath("ButtonInteraction"), NodePath("CollectibleInteraction")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="InteractionArea"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.1)
shape = SubResource("BoxShape3D_sgaqf")
[node name="ButtonInteraction" type="Node" parent="InteractionArea"]
script = ExtResource("2_sgaqf")
button_prompt = SubResource("Texture2D_ueeyx")
metadata/_custom_type_script = "uid://bvwy23eskb8d"
[node name="CollectibleInteraction" type="Node" parent="InteractionArea"]
script = ExtResource("4_ueeyx")
collectible_id = &"btn"
hover_hint = "Press {prompt} to collect"
button_prompt = SubResource("Texture2D_0njmr")
action = &"toggle_console"
metadata/_custom_type_script = "uid://caxr8dg3iundb"

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=7 format=3 uid="uid://bn6ylrp7gn2mq"]
[ext_resource type="PackedScene" uid="uid://2dre1e56emw6" path="res://src/core/interaction/interaction_area.tscn" id="1_krjhc"]
[ext_resource type="Script" uid="uid://caxr8dg3iundb" path="res://src/core/interaction/interaction_types/collectible.gd" id="2_ivfai"]
[ext_resource type="Script" uid="uid://c2w177bb5r70x" path="res://addons/controller_icons/objects/ControllerIconTexture.gd" id="3_1djg4"]
[ext_resource type="PackedScene" uid="uid://b1ax1psf37ets" path="res://assets/models/plush/godot_plush_sitting.glb" id="3_gmwxi"]
[sub_resource type="Texture2D" id="Texture2D_eeujq"]
resource_local_to_scene = false
resource_name = ""
script = ExtResource("3_1djg4")
path = "interact"
metadata/_custom_type_script = "uid://c2w177bb5r70x"
[sub_resource type="CylinderShape3D" id="CylinderShape3D_1djg4"]
height = 0.3
radius = 0.2
[node name="TestCollectible" type="Node3D"]
[node name="godot_plush_sitting" parent="." instance=ExtResource("3_gmwxi")]
transform = Transform3D(3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0)
[node name="InteractionArea" parent="." node_paths=PackedStringArray("interaction_types") instance=ExtResource("1_krjhc")]
interaction_types = [NodePath("CollectibleInteraction")]
[node name="CollectibleInteraction" type="Node" parent="InteractionArea"]
script = ExtResource("2_ivfai")
collectible_id = &"gdplush"
hover_hint = "Press {prompt} to collect."
button_prompt = SubResource("Texture2D_eeujq")
metadata/_custom_type_script = "uid://caxr8dg3iundb"
[node name="CollisionShape3D" type="CollisionShape3D" parent="InteractionArea"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.15, 0)
shape = SubResource("CylinderShape3D_1djg4")

View File

@ -0,0 +1,13 @@
[gd_scene load_steps=3 format=3 uid="uid://u6qs7lfgku2e"]
[ext_resource type="PackedScene" uid="uid://2dre1e56emw6" path="res://src/core/interaction/interaction_area.tscn" id="1_f3310"]
[ext_resource type="Script" uid="uid://ckdo7huqoleoi" path="res://src/core/interaction/interaction_types/pickup.gd" id="2_d6xtc"]
[node name="Node3D" type="Node3D"]
[node name="InteractionArea" parent="." node_paths=PackedStringArray("interaction_types") instance=ExtResource("1_f3310")]
interaction_types = [NodePath("PickupInteraction")]
[node name="PickupInteraction" type="Node" parent="InteractionArea"]
script = ExtResource("2_d6xtc")
metadata/_custom_type_script = "uid://ckdo7huqoleoi"

View File

@ -0,0 +1,39 @@
[gd_scene load_steps=7 format=3 uid="uid://cyiprnsiwhul3"]
[ext_resource type="PackedScene" uid="uid://2dre1e56emw6" path="res://src/core/interaction/interaction_area.tscn" id="1_8awim"]
[ext_resource type="Script" uid="uid://5y74uiijaxrx" path="res://src/core/interaction/interaction_types/switch.gd" id="3_0vrdy"]
[ext_resource type="Script" uid="uid://c2w177bb5r70x" path="res://addons/controller_icons/objects/ControllerIconTexture.gd" id="3_7cmb6"]
[sub_resource type="BoxMesh" id="BoxMesh_0vrdy"]
size = Vector3(0.4, 0.5, 0.2)
[sub_resource type="Texture2D" id="Texture2D_i1632"]
resource_local_to_scene = false
resource_name = ""
script = ExtResource("3_7cmb6")
path = "interact"
metadata/_custom_type_script = "uid://c2w177bb5r70x"
[sub_resource type="BoxShape3D" id="BoxShape3D_6cn7s"]
size = Vector3(0.4, 0.5, 0.2)
[node name="CommonSwitch" type="Node3D"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.1)
mesh = SubResource("BoxMesh_0vrdy")
skeleton = NodePath("")
[node name="InteractionArea" parent="." node_paths=PackedStringArray("interaction_types") instance=ExtResource("1_8awim")]
interaction_types = [NodePath("SwitchInteraction")]
[node name="SwitchInteraction" type="Node" parent="InteractionArea"]
script = ExtResource("3_0vrdy")
hover_hint_on = "Press {prompt} to turn off"
hover_hint_off = "Press {prompt} to turn on"
button_prompt = SubResource("Texture2D_i1632")
metadata/_custom_type_script = "uid://5y74uiijaxrx"
[node name="CollisionShape3D" type="CollisionShape3D" parent="InteractionArea"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.1)
shape = SubResource("BoxShape3D_6cn7s")

View File

@ -19,18 +19,19 @@ enum DeathTypes {
}
var game: Game
var player: PlayerCharacter
var game_state: GameState: set = set_game_state
var player: PlayerCharacter: get = get_player
func _ready() -> void:
game_state = BASE_GAME_STATE.duplicate()
reset_game()
# Ensure that if we load a world directly that we make the Game the current scene.
# Ensure that if we load a world directly, we make the Game the current scene.
await get_tree().root.ready
if get_tree().current_scene is World:
load_from_save()
player.free()
var world_path: String = get_tree().current_scene.scene_file_path
# Can't do this. Would also duplicate already loaded levels, adding them a second time.
@ -49,27 +50,27 @@ func get_player() -> PlayerCharacter:
func set_game_state(new_game_state: GameState) -> void:
game_state = new_game_state
SaveManager.save_data.game_state = game_state
func reset_game() -> void:
game_state = BASE_GAME_STATE.duplicate()
game_state = BASE_GAME_STATE.create_duplicate()
load_world_info(game_state.initial_world, true)
func load_from_save() -> void:
game_state = null
SaveManager.save_data = null
game_state = SaveManager.load_game()
if not SaveManager.load_game():
SaveManager.save_data = SaveData.new()
SaveManager.save_data.game_state = BASE_GAME_STATE.duplicate()
if not is_instance_valid(game_state):
reset_game()
var data: SaveData = SaveManager.save_data
game_state = data.game_state
func load_world_info(world_info: WorldInfo, set_active_world_state: bool = false, reset_world_state_if_exists: bool = false) -> void:
game_state.current_world_info = world_info
game_state.initialize_world_state(world_info, set_active_world_state, reset_world_state_if_exists)
func request_save() -> void:
SaveManager.save_game()
SaveManager.save_game(game_state)
func kill_player(death_type: DeathTypes) -> void:

View File

@ -1,12 +0,0 @@
class_name SaveData
extends Resource
@export var game_state: GameState
func get_level_id() -> StringName:
return game_state.level_id if not game_state.level_id.is_empty() else get_world_info().initial_level
func get_world_info() -> WorldInfo:
return game_state.world_info

View File

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

View File

@ -1,15 +1,12 @@
extends Node
const SAVE_PATH: String = "user://saves/"
signal pre_save(game_state: GameState)
signal post_save(game_state: GameState)
const SAVE_DIRECTORY: String = "user://saves/"
const SAVE_FILENAME: String = "saved_game.tres"
const SAVE_FILE: String = SAVE_PATH + SAVE_FILENAME
const SAVE_PATH: String = SAVE_DIRECTORY + SAVE_FILENAME
var save_data := SaveData.new():
set(value):
save_data = value
if not is_instance_valid(save_data):
save_data = SaveData.new()
#var persistent_data: Dictionary[StringName, Variant] = {
#&"spawn_id": &"",
#&"sequence_index": 0,
@ -21,29 +18,53 @@ var save_data := SaveData.new():
#}
#}
func save_game() -> void:
DirAccess.make_dir_recursive_absolute(SAVE_PATH)
ResourceSaver.save(save_data, SAVE_FILE, ResourceSaver.FLAG_CHANGE_PATH)
@onready var save_indicator: TextureRect = $SaveIndicator
func load_game() -> bool:
func _ready() -> void:
save_indicator.hide()
func save_game(game_state: GameState) -> void:
pre_save.emit(game_state)
save_indicator.show()
var thread := Thread.new()
var result: Error = thread.start(_save_game.bind(game_state))
if result == OK:
result = await thread.wait_to_finish()
else:
push_error("Saving progress failed! Running on main thread now. Error: %s" % result)
result = _save_game(game_state)
if not result == OK:
OS.alert("Saving progress failed!\nError-Code: %s" % result, "Unable to save game.")
save_indicator.hide()
post_save.emit(game_state)
func load_game() -> GameState:
if not save_exists():
return false
return null
var save: Resource = ResourceLoader.load(SAVE_FILE, "SaveData")
var save: Resource = ResourceLoader.load(SAVE_PATH, "GameState")
if not is_instance_valid(save) or save is not SaveData:
return false
if not is_instance_valid(save) or save is not GameState:
return null
save_data = save
return true
return save
func delete_save() -> void:
DirAccess.remove_absolute(SAVE_FILE)
save_data = SaveData.new()
DirAccess.remove_absolute(SAVE_PATH)
func save_exists() -> bool:
return ResourceLoader.exists(SAVE_FILE, "SaveGame") #FileAccess.file_exists(SAVE_FILE)
return ResourceLoader.exists(SAVE_PATH, "GameState") #FileAccess.file_exists(SAVE_PATH)
func _save_game(game_state: GameState) -> Error:
DirAccess.make_dir_recursive_absolute(SAVE_DIRECTORY)
return ResourceSaver.save(game_state, SAVE_PATH, ResourceSaver.FLAG_CHANGE_PATH)

View File

@ -0,0 +1,12 @@
[gd_scene load_steps=3 format=3 uid="uid://bkl3havyol8y7"]
[ext_resource type="Script" uid="uid://iadl2o6wkphx" path="res://src/globals/autoloads/save_manager/save_manager.gd" id="1_c13sc"]
[ext_resource type="Texture2D" uid="uid://bovb32x4x3ps5" path="res://icon.svg" id="2_r2845"]
[node name="SaveManager" type="Node"]
script = ExtResource("1_c13sc")
[node name="SaveIndicator" type="TextureRect" parent="."]
offset_right = 40.0
offset_bottom = 40.0
texture = ExtResource("2_r2845")

View File

@ -65,6 +65,9 @@ func load_to_path(path: String, additional_paths: PackedStringArray = [], do_fad
func fade_in() -> void:
if color_rect.is_visible():
return
color_rect.show()
is_fading = true

View File

@ -0,0 +1,70 @@
class_name SignalGroup
## @tutorial(Small Modified Version from ShaggyDev): https://shaggydev.com/2025/06/12/godot-awaiting-signals/
signal _all_complete
var _counter: int = 0
#var _watched_signals: Array[Signal] = []
var _signals_in_order: Array[Signal] = []
## Awaits for all - or a specific number of signals to emit. Returns the order in which they were emitted.[br]
## You can limit the amount on how many signals you wanna await with [param custom_count].[br][br]
## [b]Note[/b]: If [param custom_count] is below [code]0[/code] it will be automatically
## set the size of the [param signals] array.
# TODO: Add a bound node parameter, similar to the tween node binding.
static func await_signals(signals: Array[Signal], custom_count: int = -1) -> Array[Signal]:
var group := SignalGroup.new()
return await group.all(signals, custom_count)
func _notification(what: int) -> void:
if what == NOTIFICATION_PREDELETE:
print(self, " freeing [SignalGroup]")
func all(signals: Array[Signal], custom_count: int = -1) -> Array[Signal]:
_counter = signals.size() if custom_count < 0 else custom_count
if _counter == 0:
return []
for sig: Signal in signals:
#_add_probe(sig.get_object(), sig)
sig.connect(
(
# I can't remove any parameters that where defined in a signal,
# so I just discard them here.
func(..._args: Array) -> void:
_on_signal_complete(sig)
), CONNECT_ONE_SHOT)
await _all_complete
return _signals_in_order
#func _add_probe(obj: Object, sig: Signal) -> void:
#var probe := Probe.new()
#probe.callable = func(..._args: Array) -> void:
#_on_signal_complete(sig)
#obj.set_meta("__probe", probe)
func _on_signal_complete(sig: Signal) -> void:
_counter -= 1
_signals_in_order.append(sig)
if _counter == 0:
_all_complete.emit()
#class Probe extends RefCounted:
### @tutorial: https://github.com/godotengine/godot-proposals/issues/7441
#var callable: Callable
#
#func _notification(what: int) -> void:
#if what == NOTIFICATION_PREDELETE:
#if callable.is_valid():
#callable.call()

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cwvfdx2v41k0h"
path="res://.godot/imported/crosshair.png-a963137264e1979651851d3e816bf3fa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://src/ui/hud/crosshair.png"
dest_files=["res://.godot/imported/crosshair.png-a963137264e1979651851d3e816bf3fa.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -0,0 +1,8 @@
class_name CollectibleData
extends Resource
@export var name: String
@export_multiline var description: String
@export var thumbnail: Texture2D
@export var generate_thumbnail: bool = false
@export var inspect_scene: PackedScene

View File

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

View File

@ -0,0 +1,67 @@
class_name CollectibleInventoryMenu
extends Control
@export var collectibles: Dictionary[StringName, CollectibleData]
@export_group("Thumbnail Generation")
@export var thumbnail_resolution := Vector2i(64, 64)
@export var msaa := SubViewport.MSAA.MSAA_8X
@export var ssaa := SubViewport.ScreenSpaceAA.SCREEN_SPACE_AA_SMAA
@onready var grid_container: GridContainer = $GridContainer
@onready var entry_template: PanelContainer = $GridContainer/EntryTemplate
func _ready() -> void:
populate_menu()
func populate_menu() -> void:
entry_template.hide()
for id: StringName in collectibles.keys():
var collectible: CollectibleData = collectibles[id]
var thumbnail: Texture2D = collectible.thumbnail
if collectible.generate_thumbnail:
thumbnail = await _generate_thumbnail(collectible.inspect_scene)
var entry: PanelContainer = entry_template.duplicate()
grid_container.add_child(entry)
entry.name = id
entry.find_children("", "TextureRect", true, false)[0].texture = thumbnail
entry.show()
func _generate_thumbnail(inspect_scene: PackedScene) -> Texture2D:
var viewport := SubViewport.new()
viewport.world_3d = World3D.new()
viewport.own_world_3d = true
viewport.msaa_3d = msaa
viewport.screen_space_aa = ssaa
viewport.size = thumbnail_resolution
viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
add_child(viewport)
viewport.owner = get_owner()
assert(is_instance_valid(inspect_scene), "Inspect scene is null")
var inspect_node: Node3D = inspect_scene.instantiate()
viewport.add_child(inspect_node)
var camera := Camera3D.new()
camera.fov = 90.0
viewport.add_child(camera)
camera.owner = get_owner()
camera.make_current()
var visual_instance: VisualInstance3D = inspect_node.find_children("", "VisualInstance3D", true, false)[0]
camera.look_at_from_position(Vector3.ZERO, visual_instance.get_aabb().get_longest_axis())
await RenderingServer.frame_post_draw
var texture: Texture2D = viewport.get_texture()
viewport.queue_free()
return texture

View File

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

View File

@ -0,0 +1,52 @@
[gd_scene load_steps=6 format=3 uid="uid://bu73s32mjv6hp"]
[ext_resource type="Script" uid="uid://bw2rslcsio77p" path="res://src/ui/menus/collectible_inventory/collectible_inventory_menu.gd" id="1_ityjr"]
[ext_resource type="Script" uid="uid://dwdhbftfi3ay1" path="res://src/ui/menus/collectible_inventory/collectible_data.gd" id="2_klcvd"]
[ext_resource type="Texture2D" uid="uid://pmp6awa0j0sl" path="res://src/ui/menus/collectible_inventory/datas/gdplush.png" id="2_wtv45"]
[ext_resource type="Resource" uid="uid://dyq7da37u66cm" path="res://src/ui/menus/collectible_inventory/datas/gdplush.tres" id="3_y3gh6"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_u414w"]
bg_color = Color(0.15294118, 0.15294118, 0.15294118, 0.5882353)
corner_radius_top_left = 8
corner_radius_top_right = 8
corner_radius_bottom_right = 8
corner_radius_bottom_left = 8
[node name="CollectibleInventoryMenu" 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_ityjr")
collectibles = Dictionary[StringName, ExtResource("2_klcvd")]({
&"gdplush": ExtResource("3_y3gh6")
})
metadata/_custom_type_script = "uid://bw2rslcsio77p"
[node name="GridContainer" type="GridContainer" parent="."]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -32.0
offset_top = -32.0
offset_right = 32.0
offset_bottom = 32.0
grow_horizontal = 2
grow_vertical = 2
columns = 3
[node name="EntryTemplate" type="PanelContainer" parent="GridContainer"]
custom_minimum_size = Vector2(64, 64)
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_u414w")
[node name="TextureRect" type="TextureRect" parent="GridContainer/EntryTemplate"]
layout_mode = 2
texture = ExtResource("2_wtv45")
expand_mode = 5
stretch_mode = 5

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://pmp6awa0j0sl"
path="res://.godot/imported/gdplush.png-8a8640616725d1c18a5be5745caf3695.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://src/ui/menus/collectible_inventory/datas/gdplush.png"
dest_files=["res://.godot/imported/gdplush.png-8a8640616725d1c18a5be5745caf3695.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -0,0 +1,13 @@
[gd_resource type="Resource" script_class="CollectibleData" load_steps=4 format=3 uid="uid://dyq7da37u66cm"]
[ext_resource type="Script" uid="uid://dwdhbftfi3ay1" path="res://src/ui/menus/collectible_inventory/collectible_data.gd" id="1_8d2qu"]
[ext_resource type="PackedScene" uid="uid://b1ax1psf37ets" path="res://assets/models/plush/godot_plush_sitting.glb" id="1_lioxv"]
[ext_resource type="Texture2D" uid="uid://pmp6awa0j0sl" path="res://src/ui/menus/collectible_inventory/datas/gdplush.png" id="3_mfb76"]
[resource]
script = ExtResource("1_8d2qu")
name = "Godot Plush"
description = "It's a plush, representing the mascot of the Godot Engine!"
thumbnail = ExtResource("3_mfb76")
inspect_scene = ExtResource("1_lioxv")
metadata/_custom_type_script = "uid://dwdhbftfi3ay1"

View File

@ -30,24 +30,34 @@ func _unhandled_input(event: InputEvent) -> void:
func load_game() -> void:
AudioManager.fade_audio(AMBIENCE_STREAM, -80.0, SceneFader.fade_in_duration, AudioManager.AMBIENCE, true)
var save_data: SaveData = SaveManager.save_data
var world_info: WorldInfo = save_data.get_world_info()
var paths: PackedStringArray = world_info.get_level_paths_from_id(save_data.get_level_id())
GameGlobals.game_state.world_info = world_info
var game_state: GameState = GameGlobals.game_state
GameGlobals.load_world_info(game_state.get_world_info(), true)
var world_state: WorldState = game_state.get_world_state()
GameGlobals.game_state.current_world_state = world_state
GameGlobals.game_state.current_world_info = world_state.world_info
# Also try to load the levels the player currently is in.
var paths: PackedStringArray = world_state.world_info.get_level_paths_from_id(game_state.get_level_id())
SceneFader.load_to_path(GameGlobals.GAME_PATH, paths, false)
func ask_for_save_confirmation() -> bool:
save_confirmation.show()
return await save_confirmation.interacted
func _on_new_game_button_pressed() -> void:
if SceneFader.is_fading:
return
# TODO: Ask for confirmiation when a save already exists.
#if not await _ask_for_new_game_confirmation():
#return
if SaveManager.save_exists() and not await ask_for_save_confirmation():
new_game_button.grab_focus()
return
SaveManager.delete_save()
GameGlobals.reset_game()
SaveManager.save_game()
load_game()
@ -84,5 +94,6 @@ func _on_chase_button_pressed() -> void:
var world_info: WorldInfo = load("uid://d0y8d244covqn")
var paths: PackedStringArray = world_info.get_initial_level_paths()
GameGlobals.game_state.world_info = world_info
GameGlobals.load_from_save()
GameGlobals.load_world_info(world_info, false, false)
SceneFader.load_to_path(GameGlobals.GAME_PATH, paths, false)

View File

@ -1,6 +1,7 @@
[gd_scene load_steps=4 format=3 uid="uid://dwd8wf02j2epn"]
[gd_scene load_steps=5 format=3 uid="uid://dwd8wf02j2epn"]
[ext_resource type="Script" uid="uid://bmsx3h2kunhb0" path="res://src/ui/menus/main_menu/main_menu.gd" id="1_6xfbl"]
[ext_resource type="PackedScene" uid="uid://b20anjeolijf6" path="res://src/ui/menus/main_menu/save_confirmation.tscn" id="2_hjh2c"]
[ext_resource type="PackedScene" uid="uid://4s2nskkco0a2" path="res://src/ui/menus/options_menu/options_menu.tscn" id="2_i2wwg"]
[sub_resource type="Environment" id="Environment_6xfbl"]
@ -70,6 +71,15 @@ unique_name_in_owner = true
layout_mode = 2
text = "QUIT"
[node name="SaveConfirmation" parent="MainMenuUI" instance=ExtResource("2_hjh2c")]
unique_name_in_owner = true
visible = false
layout_mode = 1
offset_left = -195.0
offset_top = -109.5
offset_right = 195.0
offset_bottom = 109.5
[node name="OptionsMenu" parent="." instance=ExtResource("2_i2wwg")]
unique_name_in_owner = true
visible = false

View File

@ -0,0 +1,24 @@
class_name SaveConfirmation
extends PanelContainer
signal interacted(has_confirmed: bool)
@onready var confirm_button: Button = %ConfirmButton
@onready var cancel_button: Button = %CancelButton
func _ready() -> void:
confirm_button.pressed.connect(set_confimed.bind(true))
cancel_button.pressed.connect(set_confimed.bind(false))
visibility_changed.connect(_on_visibility_changed)
func set_confimed(is_confirmed: bool) -> void:
hide()
interacted.emit(is_confirmed)
func _on_visibility_changed() -> void:
if is_visible_in_tree():
cancel_button.grab_focus()

View File

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

View File

@ -0,0 +1,59 @@
[gd_scene load_steps=2 format=3 uid="uid://b20anjeolijf6"]
[ext_resource type="Script" uid="uid://dteft3r4ijvwa" path="res://src/ui/menus/main_menu/save_confirmation.gd" id="1_o21f4"]
[node name="SaveConfirmation" type="PanelContainer"]
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -188.0
offset_top = -56.5
offset_right = 188.0
offset_bottom = 56.5
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_o21f4")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 2
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 8
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 23
[node name="Title" type="Label" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 36
text = "A Save Already Exists!"
horizontal_alignment = 1
[node name="HSeparator" type="HSeparator" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="HintLabel" type="Label" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Do you really want to start a new game?
This will erase your previous save!"
horizontal_alignment = 1
autowrap_mode = 3
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 46
alignment = 1
[node name="ConfirmButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Yes - New Game"
[node name="CancelButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "No - Go Back"

View File

@ -1,20 +1,54 @@
[gd_scene load_steps=16 format=3 uid="uid://dspysc2bld6eu"]
[gd_scene load_steps=26 format=3 uid="uid://dspysc2bld6eu"]
[ext_resource type="Script" uid="uid://dfnb036hysorj" path="res://src/core/world/level/level_loader.gd" id="1_kntr3"]
[ext_resource type="PackedScene" uid="uid://8y3swwnmxwg2" path="res://src/core/world/world.tscn" id="1_ls3dg"]
[ext_resource type="PackedScene" uid="uid://drr80goa61wrx" path="res://src/core/world/level/level_area.tscn" id="2_5mqkb"]
[ext_resource type="Resource" uid="uid://d2qpu70epn5rs" path="res://src/worlds/expo_combined_info.tres" id="2_p35h1"]
[ext_resource type="Script" uid="uid://3hlvt5k34xva" path="res://src/core/spawnpoint/player_spawn_point.gd" id="3_aoi14"]
[ext_resource type="Script" uid="uid://dhrqjudaignuc" path="res://src/core/world/level/load_threshold_area.gd" id="3_mcc85"]
[ext_resource type="Script" uid="uid://dgsfc4i6bovwa" path="res://src/core/chapter/chapter_area.gd" id="4_sujqt"]
[ext_resource type="Script" uid="uid://cy2248x8tuoj4" path="res://src/gameplay/illusionary/illusionary_wall.gd" id="5_a2dpg"]
[ext_resource type="Shader" uid="uid://dvpk3m7f8x5pc" path="res://src/vfx/shaders/dissolving_wall/dissolving_wall.gdshader" id="6_estl1"]
[ext_resource type="Script" uid="uid://u2s0spt1rud4" path="res://src/core/game_state_overrider.gd" id="7_b5v2q"]
[ext_resource type="Texture2D" uid="uid://jpmuawwwmwci" path="res://src/vfx/shaders/dissolving_wall/dissolving_wall_noise.tres" id="7_lqjcs"]
[ext_resource type="Script" uid="uid://bfv3de7iqflhv" path="res://src/core/damage/death_area.gd" id="8_wjjd2"]
[sub_resource type="BoxShape3D" id="BoxShape3D_b5v2q"]
size = Vector3(17, 9, 84)
size = Vector3(17, 9, 87)
[sub_resource type="BoxShape3D" id="BoxShape3D_wjjd2"]
size = Vector3(31, 19, 37)
[sub_resource type="Gradient" id="Gradient_n6nl5"]
[sub_resource type="GradientTexture2D" id="GradientTexture2D_215e1"]
gradient = SubResource("Gradient_n6nl5")
fill_to = Vector2(0.66453, 0.262821)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_7gqwp"]
render_priority = 0
shader = ExtResource("6_estl1")
shader_parameter/albedo = Color(1, 1, 1, 1)
shader_parameter/texture_albedo = SubResource("GradientTexture2D_215e1")
shader_parameter/texture_dissolve = ExtResource("7_lqjcs")
shader_parameter/alpha_scissor_threshold = 0.0
shader_parameter/roughness = 0.0
shader_parameter/metallic_texture_channel = Vector4(0, 0, 0, 0)
shader_parameter/specular = 0.0
shader_parameter/metallic = 0.0
shader_parameter/uv1_blend_sharpness = 1.0
shader_parameter/uv1_scale = Vector3(1, 1, 1)
shader_parameter/uv1_offset = Vector3(0, 0, 0)
[sub_resource type="BoxMesh" id="BoxMesh_nam8p"]
size = Vector3(4, 3, 1)
[sub_resource type="BoxShape3D" id="BoxShape3D_xlfme"]
size = Vector3(4, 3, 5)
[sub_resource type="BoxShape3D" id="BoxShape3D_tiv74"]
size = Vector3(4, 3, 1)
[sub_resource type="BoxShape3D" id="BoxShape3D_p35h1"]
size = Vector3(4, 3, 0.5)
@ -30,6 +64,7 @@ size = Vector3(33, 14, 31)
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_p35h1"]
[node name="ExpoCombined" instance=ExtResource("1_ls3dg")]
world_info = ExtResource("2_p35h1")
initial_spawn_id = &"OutsideSpawn"
debug_spawn_point = &"NoKnows"
@ -41,6 +76,15 @@ scene_path = "uid://lraild3yetsh"
level_id = &"OutsideArea"
metadata/_custom_type_script = "uid://dfnb036hysorj"
[node name="LevelArea" parent="LevelLoaders/LoaderOutsideArea" index="1" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("2_5mqkb")]
level_loader = NodePath("..")
loaded_if_spawnpoint = [NodePath("../../../Spawnpoints/OutsideSpawnPoint")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelLoaders/LoaderOutsideArea/LevelArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 4, -5)
shape = SubResource("BoxShape3D_b5v2q")
debug_color = Color(1, 1, 0, 0.41960785)
[node name="LoaderEntranceHall" type="Marker3D" parent="LevelLoaders" index="1"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.3, 3.5, 33)
script = ExtResource("1_kntr3")
@ -48,27 +92,47 @@ scene_path = "uid://cmdy6f6kesmbj"
level_id = &"EntranceHall"
metadata/_custom_type_script = "uid://dfnb036hysorj"
[node name="LevelAreas" type="Node" parent="." index="1"]
[node name="LevelArea" parent="LevelLoaders/LoaderEntranceHall" index="1" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("2_5mqkb")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.3, -3.5, -33)
level_loader = NodePath("..")
loaded_if_spawnpoint = [NodePath("../../../Spawnpoints/EntranceHallSpawnPoint")]
[node name="OutsideArea" parent="LevelAreas" index="0" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("2_5mqkb")]
level_loader = NodePath("../../LevelLoaders/LoaderOutsideArea")
loaded_if_spawnpoint = [NodePath("../../Spawnpoints/OutsideSpawnPoint")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelAreas/OutsideArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 4, -6.5)
shape = SubResource("BoxShape3D_b5v2q")
debug_color = Color(1, 1, 0, 0.41960785)
[node name="EntranceHall" parent="LevelAreas" index="1" node_paths=PackedStringArray("level_loader", "loaded_if_spawnpoint") instance=ExtResource("2_5mqkb")]
level_loader = NodePath("../../LevelLoaders/LoaderEntranceHall")
loaded_if_spawnpoint = [NodePath("../../Spawnpoints/EntranceHallSpawnPoint")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelAreas/EntranceHall" index="0"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelLoaders/LoaderEntranceHall/LevelArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 9, 53)
shape = SubResource("BoxShape3D_wjjd2")
debug_color = Color(1, 1, 0, 0.41960785)
[node name="LevelLoadThresholds" type="Node" parent="." index="2"]
[node name="IllusionaryWall" type="Node3D" parent="LevelLoaders/LoaderEntranceHall" index="3" node_paths=PackedStringArray("static_body", "mesh", "appear_area", "disappear_area")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 1, 3.5)
script = ExtResource("5_a2dpg")
static_body = NodePath("BlockingWall")
mesh = NodePath("DissolvingMesh")
appear_area = NodePath("AppearArea")
disappear_area = NodePath("AppearArea")
metadata/_custom_type_script = "uid://cy2248x8tuoj4"
[node name="DissolvingMesh" type="MeshInstance3D" parent="LevelLoaders/LoaderEntranceHall/IllusionaryWall" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0.00292015)
material_override = SubResource("ShaderMaterial_7gqwp")
mesh = SubResource("BoxMesh_nam8p")
[node name="AppearArea" type="Area3D" parent="LevelLoaders/LoaderEntranceHall/IllusionaryWall" index="1"]
process_mode = 1
collision_layer = 0
collision_mask = 3
[node name="CollisionShape3D2" type="CollisionShape3D" parent="LevelLoaders/LoaderEntranceHall/IllusionaryWall/AppearArea" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
shape = SubResource("BoxShape3D_xlfme")
debug_color = Color(0.933125, 2.06e-05, 0.645944, 0.42)
[node name="BlockingWall" type="StaticBody3D" parent="LevelLoaders/LoaderEntranceHall/IllusionaryWall" index="2"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelLoaders/LoaderEntranceHall/IllusionaryWall/BlockingWall" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
shape = SubResource("BoxShape3D_tiv74")
[node name="LevelLoadThresholds" type="Node" parent="." index="1"]
[node name="LevelThresholdArea" type="Area3D" parent="LevelLoadThresholds" index="0" node_paths=PackedStringArray("level_loaders")]
collision_layer = 0
@ -87,7 +151,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.8, 5, 33)
shape = SubResource("BoxShape3D_p35h1")
debug_color = Color(1, 0.5176471, 0, 0.41960785)
[node name="Spawnpoints" type="Node" parent="." index="3"]
[node name="Spawnpoints" type="Node" parent="." index="2"]
[node name="OutsideSpawnPoint" type="Marker3D" parent="Spawnpoints" index="0"]
transform = Transform3D(-1, 0, 8.742278e-08, 0, 1, 0, -8.742278e-08, 0, -1, 1, 1, 1)
@ -101,7 +165,7 @@ script = ExtResource("3_aoi14")
spawn_id = &"NoKnows"
metadata/_custom_type_script = "uid://3hlvt5k34xva"
[node name="Checkpoints" type="Node" parent="." index="4"]
[node name="Checkpoints" type="Node" parent="." index="3"]
[node name="CheckpointEntranceHall" type="Area3D" parent="Checkpoints" index="0"]
collision_layer = 0
@ -118,7 +182,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.8, 5, 37)
shape = SubResource("BoxShape3D_tpfae")
debug_color = Color(0.970704, 0, 0.45613372, 0.41960785)
[node name="GameStateOverriders" type="Node" parent="." index="5"]
[node name="GameStateOverriders" type="Node" parent="." index="4"]
[node name="OutsideArea" type="Area3D" parent="GameStateOverriders" index="0" node_paths=PackedStringArray("level_loader", "spawnpoint")]
collision_layer = 0
@ -149,7 +213,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.3000002, 10.5, 52)
shape = SubResource("BoxShape3D_0a1wn")
debug_color = Color(0.970704, 0, 0.45613372, 0.41960785)
[node name="DeathArea" type="Area3D" parent="." index="6"]
[node name="DeathArea" type="Area3D" parent="." index="5"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -7, 0)
collision_layer = 0
collision_mask = 2

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=15 format=3 uid="uid://cmdy6f6kesmbj"]
[gd_scene load_steps=17 format=3 uid="uid://cmdy6f6kesmbj"]
[ext_resource type="Script" uid="uid://cigop0ivp5vvu" path="res://src/core/world/level/level.gd" id="1_s41bt"]
[ext_resource type="Script" uid="uid://dk4pqgs08xphi" path="res://src/core/camera/camera_shaker/camera_trauma_causer.gd" id="2_ht7mm"]
@ -11,6 +11,8 @@
[ext_resource type="PackedScene" uid="uid://pvll6bliout1" path="res://assets/models/electrics/spot_light/studio_spot_light.glb" id="9_1itxg"]
[ext_resource type="PackedScene" uid="uid://bwejp67rw5erj" path="res://assets/models/electrics/spot_light/studio_spot_light_framing_01.glb" id="10_3r78c"]
[ext_resource type="PackedScene" uid="uid://boxc0e6to4083" path="res://assets/models/electrics/spot_light/studio_light_framing_02.glb" id="11_84j0j"]
[ext_resource type="PackedScene" uid="uid://bn6ylrp7gn2mq" path="res://src/gameplay/interactables/test_collectible.tscn" id="12_3r78c"]
[ext_resource type="PackedScene" uid="uid://cyiprnsiwhul3" path="res://src/gameplay/interactables/test_switch.tscn" id="13_84j0j"]
[sub_resource type="Environment" id="Environment_ht7mm"]
ambient_light_source = 2
@ -196,7 +198,7 @@ transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -5, 0.
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1, 0.5, 23)
[node name="SawSkin" parent="Gameplay/Hazards/Saw7" index="0"]
transform = Transform3D(0.9064751, 0.18482661, 0, -0.18482661, 0.9064751, 0, 0, 0, 1, 0, 0, 0)
transform = Transform3D(0.2685029, 0.884415, 0, -0.884415, 0.2685029, 0, 0, 0, 1, 0, 0, 0)
[node name="SawSkin" parent="Gameplay/Hazards/Saw7/SawSkin" index="1" instance=ExtResource("7_hd5mq")]
transform = Transform3D(0.90769696, -0.41963005, 0, 0.41963005, 0.90769696, 1.7763568e-15, 5.3290705e-15, -1.0658141e-14, 0.99999994, 0, 0, 0.099999845)
@ -315,5 +317,11 @@ transform = Transform3D(0.22414383, 0.12940954, 0.96592575, -0.5, 0.8660254, 1.2
[node name="StudioSpotLightFraming02" parent="StudioSpotLight2" instance=ExtResource("11_84j0j")]
visible = false
[node name="TestCollectible" parent="." instance=ExtResource("12_3r78c")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.9131215, 0.007685883, 27.544394)
[node name="CommonSwitch" parent="." instance=ExtResource("13_84j0j")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.019445956, 1.25, 28.841022)
[editable path="Gameplay/Hazards/Saw7"]
[editable path="Gameplay/Hazards/Saw7/SawSkin"]

View File

@ -0,0 +1,108 @@
@tool
class_name CubeMapGeneratorCamera
extends Camera3D
## https://danilw.github.io/GLSL-howto/cubemap_to_panorama_js/cubemap_to_panorama.html
const RESOLUTIONS: PackedInt32Array = [
2,
4,
8,
16,
32,
64,
128,
256,
512,
1024,
2048,
4096,
8192,
]
const AXIS_NAMES: Dictionary[int, String] = {
0: "Front", 1: "Left", 2: "Back", 3: "Right", 4: "Up", 5: "Down"
}
const CAMERA_ALIGNMENTS: Dictionary[int, Vector3] = {
0: Vector3.ZERO, # Forward
1: Vector3(0.0, -90.0, 0.0), # Left
2: Vector3(0.0, 180.0, 0.0), # Back
3: Vector3(0.0, 90.0, 0.0), # Right
4: Vector3(90.0, 90.0, 0.0), # Up
5: Vector3(-90.0, 90.0, 0.0),# Down
}
@warning_ignore("unused_private_class_variable")
@export_tool_button("Generate Cubemaps", "Cubemap") var _gen: Callable = generate_cubemaps
@export var resolution: int = 8
@export var msaa := SubViewport.MSAA.MSAA_8X
@export var ssaa := SubViewport.ScreenSpaceAA.SCREEN_SPACE_AA_SMAA
@export_global_dir var output_directory: String = "user://cubemaps/"
func _validate_property(property: Dictionary) -> void:
if property.name == "resolution":
var enums: String = str(RESOLUTIONS).replace("[", "").replace("]", "").replace(" ", "")
property.type = TYPE_INT
property.hint = PROPERTY_HINT_ENUM
property.hint_string = enums
func generate_cubemaps() -> void:
if not DirAccess.dir_exists_absolute(output_directory):
push_error("Directory '%s' does not exist. Please create it." % output_directory)
return
var camera: Camera3D = duplicate()
camera.fov = 90.0
for child: Node in camera.get_children():
child.queue_free()
var viewport := SubViewport.new()
viewport.msaa_3d = msaa
viewport.screen_space_aa = ssaa
viewport.size = get_resolution()
viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
add_child(viewport)
viewport.owner = get_owner()
viewport.add_child(camera)
camera.owner = get_owner()
camera.global_position = global_position
camera.make_current()
for axis: int in range(6):
camera.rotation_degrees = CAMERA_ALIGNMENTS[axis]
await take_screenshot(viewport, axis)
#await get_tree().create_timer(3.0).timeout
#await get_tree().create_timer(15.0).timeout
viewport.queue_free()
func take_screenshot(viewport: SubViewport, axis_index: int) -> void:
await RenderingServer.frame_post_draw
var image: Image = viewport.get_texture().get_image()
var file: String = str(_get_scene_name(), "_", AXIS_NAMES[axis_index], ".png")
var filepath: String = output_directory.path_join(file)
image.save_png(filepath)
func get_resolution() -> Vector2i:
@warning_ignore("narrowing_conversion")
var _resolution: int = pow(2.0, 1 + resolution)
return Vector2i.ONE * _resolution
func _get_scene_name() -> String:
if Engine.is_editor_hint():
return Engine.get_singleton(&"EditorInterface").get_edited_scene_root().name
return owner.name

View File

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