Chained loading of save states

This commit is contained in:
Rob Kelly 2025-04-22 22:10:08 -06:00
parent bc9e928c3b
commit 4bfa1c88a6
10 changed files with 314 additions and 303 deletions

View File

@ -1,7 +1,8 @@
[gd_scene load_steps=21 format=3 uid="uid://bov4ok76woyc"] [gd_scene load_steps=22 format=3 uid="uid://bov4ok76woyc"]
[ext_resource type="PackedScene" uid="uid://crydi5cjgfwe5" path="res://levels/ghost_ship/ghost_ship_level.tscn" id="1_aj2m7"] [ext_resource type="PackedScene" uid="uid://crydi5cjgfwe5" path="res://levels/ghost_ship/ghost_ship_level.tscn" id="1_aj2m7"]
[ext_resource type="Environment" uid="uid://bkvij3ljl5ox3" path="res://levels/ghost_ship/environment_3.tres" id="1_h081y"] [ext_resource type="Environment" uid="uid://bkvij3ljl5ox3" path="res://levels/ghost_ship/environment_3.tres" id="1_h081y"]
[ext_resource type="Script" uid="uid://68r4ht5ut1ct" path="res://src/game/level.gd" id="1_law5k"]
[ext_resource type="PackedScene" uid="uid://bwe2jdmvinhqd" path="res://src/player/player.tscn" id="2_0ef5p"] [ext_resource type="PackedScene" uid="uid://bwe2jdmvinhqd" path="res://src/player/player.tscn" id="2_0ef5p"]
[ext_resource type="PackedScene" uid="uid://d1kacn4b60ucy" path="res://src/ui/post_processing.tscn" id="3_o7mxe"] [ext_resource type="PackedScene" uid="uid://d1kacn4b60ucy" path="res://src/ui/post_processing.tscn" id="3_o7mxe"]
[ext_resource type="AudioStream" uid="uid://dx4d8a3mgpws" path="res://assets/sfx/ambient/drone_loop.wav" id="5_ejh2c"] [ext_resource type="AudioStream" uid="uid://dx4d8a3mgpws" path="res://assets/sfx/ambient/drone_loop.wav" id="5_ejh2c"]
@ -42,6 +43,9 @@ stream_10/stream = ExtResource("10_h081y")
stream_10/weight = 0.2 stream_10/weight = 0.2
[node name="GhostShip" type="Node3D"] [node name="GhostShip" type="Node3D"]
script = ExtResource("1_law5k")
id = "ghost_ship"
pretty_name = "The HFCS Gnurk"
[node name="WorldEnvironment" type="WorldEnvironment" parent="."] [node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = ExtResource("1_h081y") environment = ExtResource("1_h081y")

View File

@ -1,4 +1,4 @@
extends Node3D extends Level
## Game mechanic testing level ## Game mechanic testing level
@onready var gunk_hall: GunkBody = %GunkHallBody @onready var gunk_hall: GunkBody = %GunkHallBody

View File

@ -1,16 +1,16 @@
[gd_scene load_steps=31 format=4 uid="uid://b8rv6dg4tgaeb"] [gd_scene load_steps=31 format=4 uid="uid://b8rv6dg4tgaeb"]
[ext_resource type="Script" uid="uid://bvua1l2hb3an6" path="res://levels/mechanic_test/mechanic_test.gd" id="1_umjw2"] [ext_resource type="Script" uid="uid://bvua1l2hb3an6" path="res://levels/mechanic_test/mechanic_test.gd" id="1_iyuyb"]
[ext_resource type="PackedScene" uid="uid://bwe2jdmvinhqd" path="res://src/player/player.tscn" id="2_gut8u"] [ext_resource type="PackedScene" uid="uid://bwe2jdmvinhqd" path="res://src/player/player.tscn" id="2_qjnj2"]
[ext_resource type="PackedScene" uid="uid://b6eg8t04rkh0c" path="res://src/props/wall_switch/wall_switch.tscn" id="3_4okgx"] [ext_resource type="PackedScene" uid="uid://b6eg8t04rkh0c" path="res://src/props/wall_switch/wall_switch.tscn" id="3_awnx0"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="4_7v7un"] [ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="4_cgmn0"]
[ext_resource type="Texture2D" uid="uid://8cm835h4gxwe" path="res://assets/debug_mask.png" id="5_llot1"] [ext_resource type="Texture2D" uid="uid://8cm835h4gxwe" path="res://assets/debug_mask.png" id="5_aix42"]
[ext_resource type="Shader" uid="uid://ckxc0ngd37rtk" path="res://src/shaders/gunk.gdshader" id="6_6agnv"] [ext_resource type="Shader" uid="uid://ckxc0ngd37rtk" path="res://src/shaders/gunk.gdshader" id="6_6frcc"]
[ext_resource type="FastNoiseLite" uid="uid://cnlvdtx68giv6" path="res://assets/materials/gunk_noise.tres" id="7_aqwgb"] [ext_resource type="FastNoiseLite" uid="uid://cnlvdtx68giv6" path="res://assets/materials/gunk_noise.tres" id="7_7cbja"]
[ext_resource type="PackedScene" uid="uid://cubwniraol1qn" path="res://src/props/bulkhead/bulkhead.tscn" id="8_ny31q"] [ext_resource type="PackedScene" uid="uid://cubwniraol1qn" path="res://src/props/bulkhead/bulkhead.tscn" id="8_ujrcv"]
[ext_resource type="PackedScene" uid="uid://b5jubpjj3d277" path="res://levels/mechanic_test/signal_test.tscn" id="9_dub8r"] [ext_resource type="PackedScene" uid="uid://b5jubpjj3d277" path="res://levels/mechanic_test/signal_test.tscn" id="9_ix0jw"]
[ext_resource type="PackedScene" uid="uid://cfqirm2o3uo4k" path="res://levels/mechanic_test/prop_test.tscn" id="10_ovu60"] [ext_resource type="PackedScene" uid="uid://cfqirm2o3uo4k" path="res://levels/mechanic_test/prop_test.tscn" id="10_xrfi2"]
[ext_resource type="PackedScene" uid="uid://dbabcsp38wmid" path="res://levels/mechanic_test/item_test.tscn" id="11_crh2u"] [ext_resource type="PackedScene" uid="uid://dbabcsp38wmid" path="res://levels/mechanic_test/item_test.tscn" id="11_8natv"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_goufh"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_goufh"]
@ -93,7 +93,7 @@ height = 256
depth = 32 depth = 32
seamless = true seamless = true
seamless_blend_skirt = 0.5 seamless_blend_skirt = 0.5
noise = ExtResource("7_aqwgb") noise = ExtResource("7_7cbja")
[sub_resource type="NoiseTexture3D" id="NoiseTexture3D_2pd8h"] [sub_resource type="NoiseTexture3D" id="NoiseTexture3D_2pd8h"]
width = 256 width = 256
@ -101,12 +101,12 @@ height = 256
depth = 32 depth = 32
seamless = true seamless = true
seamless_blend_skirt = 0.5 seamless_blend_skirt = 0.5
noise = ExtResource("7_aqwgb") noise = ExtResource("7_7cbja")
[sub_resource type="ShaderMaterial" id="ShaderMaterial_umjw2"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_iyuyb"]
resource_local_to_scene = true resource_local_to_scene = true
render_priority = 0 render_priority = 0
shader = ExtResource("6_6agnv") shader = ExtResource("6_6frcc")
shader_parameter/color_1 = Color(0, 0.03, 0.1, 1) shader_parameter/color_1 = Color(0, 0.03, 0.1, 1)
shader_parameter/color_2 = Color(0, 0.1, 0.3, 1) shader_parameter/color_2 = Color(0, 0.1, 0.3, 1)
shader_parameter/emission_color = Color(0.25, 0.88, 1, 1) shader_parameter/emission_color = Color(0.25, 0.88, 1, 1)
@ -132,9 +132,11 @@ shader_parameter/overlay_emission_scale = 1.0
data = PackedVector3Array(-1.5, 0, -6, -1.5, 0, 6, -1.5, 3, -6, -1.5, 3, -6, -1.5, 0, 6, -1.5, 3, 6, 1.5, 0, 6, 1.5, 0, -6, 1.5, 3, 6, 1.5, 3, 6, 1.5, 0, -6, 1.5, 3, -6, -1.5, 0, 6, -1.5, 0, -6, 1.5, 0, 6, 1.5, 0, 6, -1.5, 0, -6, 1.5, 0, -6, 1.5, 3, 6, 1.5, 3, -6, -1.5, 3, 6, -1.5, 3, 6, 1.5, 3, -6, -1.5, 3, -6) data = PackedVector3Array(-1.5, 0, -6, -1.5, 0, 6, -1.5, 3, -6, -1.5, 3, -6, -1.5, 0, 6, -1.5, 3, 6, 1.5, 0, 6, 1.5, 0, -6, 1.5, 3, 6, 1.5, 3, 6, 1.5, 0, -6, 1.5, 3, -6, -1.5, 0, 6, -1.5, 0, -6, 1.5, 0, 6, 1.5, 0, 6, -1.5, 0, -6, 1.5, 0, -6, 1.5, 3, 6, 1.5, 3, -6, -1.5, 3, 6, -1.5, 3, 6, 1.5, 3, -6, -1.5, 3, -6)
[node name="MechanicTest" type="Node3D"] [node name="MechanicTest" type="Node3D"]
script = ExtResource("1_umjw2") script = ExtResource("1_iyuyb")
id = "mechanic_test"
pretty_name = "Mechanics Test Sandbox"
[node name="Player" parent="." instance=ExtResource("2_gut8u")] [node name="Player" parent="." instance=ExtResource("2_qjnj2")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.65, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.65, 0)
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
@ -161,7 +163,7 @@ mesh = SubResource("BoxMesh_goufh")
[node name="CollisionShape3D" type="CollisionShape3D" parent="ResetPodium"] [node name="CollisionShape3D" type="CollisionShape3D" parent="ResetPodium"]
shape = SubResource("ConcavePolygonShape3D_bg05n") shape = SubResource("ConcavePolygonShape3D_bg05n")
[node name="ResetSwitch" parent="ResetPodium" instance=ExtResource("3_4okgx")] [node name="ResetSwitch" parent="ResetPodium" instance=ExtResource("3_awnx0")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35)
clean = true clean = true
@ -178,7 +180,7 @@ mesh = SubResource("BoxMesh_goufh")
[node name="CollisionShape3D" type="CollisionShape3D" parent="NoduleSpawner"] [node name="CollisionShape3D" type="CollisionShape3D" parent="NoduleSpawner"]
shape = SubResource("ConcavePolygonShape3D_bg05n") shape = SubResource("ConcavePolygonShape3D_bg05n")
[node name="WallSwitch" parent="NoduleSpawner" instance=ExtResource("3_4okgx")] [node name="WallSwitch" parent="NoduleSpawner" instance=ExtResource("3_awnx0")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35)
clean = true clean = true
@ -200,7 +202,7 @@ mesh = SubResource("BoxMesh_goufh")
[node name="CollisionShape3D" type="CollisionShape3D" parent="AlarmSpawner"] [node name="CollisionShape3D" type="CollisionShape3D" parent="AlarmSpawner"]
shape = SubResource("ConcavePolygonShape3D_bg05n") shape = SubResource("ConcavePolygonShape3D_bg05n")
[node name="WallSwitch" parent="AlarmSpawner" instance=ExtResource("3_4okgx")] [node name="WallSwitch" parent="AlarmSpawner" instance=ExtResource("3_awnx0")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35)
clean = true clean = true
@ -222,7 +224,7 @@ mesh = SubResource("BoxMesh_goufh")
[node name="CollisionShape3D" type="CollisionShape3D" parent="AlarmTrigger"] [node name="CollisionShape3D" type="CollisionShape3D" parent="AlarmTrigger"]
shape = SubResource("ConcavePolygonShape3D_bg05n") shape = SubResource("ConcavePolygonShape3D_bg05n")
[node name="AlarmTriggerSwitch" parent="AlarmTrigger" instance=ExtResource("3_4okgx")] [node name="AlarmTriggerSwitch" parent="AlarmTrigger" instance=ExtResource("3_awnx0")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35)
clean = true clean = true
@ -235,15 +237,15 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.5, 0, -31)
mesh = SubResource("ArrayMesh_x2vho") mesh = SubResource("ArrayMesh_x2vho")
skeleton = NodePath("GunkHallBody") skeleton = NodePath("GunkHallBody")
[node name="GunkHallBody" parent="GunkHall" instance=ExtResource("4_7v7un")] [node name="GunkHallBody" parent="GunkHall" instance=ExtResource("4_cgmn0")]
unique_name_in_owner = true unique_name_in_owner = true
initial_mask = ExtResource("5_llot1") initial_mask = ExtResource("5_aix42")
source_gunk_material = SubResource("ShaderMaterial_umjw2") source_gunk_material = SubResource("ShaderMaterial_iyuyb")
[node name="CollisionShape3D" type="CollisionShape3D" parent="GunkHall/GunkHallBody"] [node name="CollisionShape3D" type="CollisionShape3D" parent="GunkHall/GunkHallBody"]
shape = SubResource("ConcavePolygonShape3D_qjnj2") shape = SubResource("ConcavePolygonShape3D_qjnj2")
[node name="Bulkhead" parent="." instance=ExtResource("8_ny31q")] [node name="Bulkhead" parent="." instance=ExtResource("8_ujrcv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6.5, 0, -2) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6.5, 0, -2)
[node name="Podium" type="StaticBody3D" parent="Bulkhead"] [node name="Podium" type="StaticBody3D" parent="Bulkhead"]
@ -255,7 +257,7 @@ mesh = SubResource("BoxMesh_goufh")
[node name="CollisionShape3D" type="CollisionShape3D" parent="Bulkhead/Podium"] [node name="CollisionShape3D" type="CollisionShape3D" parent="Bulkhead/Podium"]
shape = SubResource("ConcavePolygonShape3D_bg05n") shape = SubResource("ConcavePolygonShape3D_bg05n")
[node name="OpenSwitch" parent="Bulkhead/Podium" instance=ExtResource("3_4okgx")] [node name="OpenSwitch" parent="Bulkhead/Podium" instance=ExtResource("3_awnx0")]
unique_name_in_owner = true unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35)
clean = true clean = true
@ -273,7 +275,7 @@ mesh = SubResource("BoxMesh_goufh")
[node name="CollisionShape3D" type="CollisionShape3D" parent="Bulkhead/Podium2"] [node name="CollisionShape3D" type="CollisionShape3D" parent="Bulkhead/Podium2"]
shape = SubResource("ConcavePolygonShape3D_bg05n") shape = SubResource("ConcavePolygonShape3D_bg05n")
[node name="CloseSwitch" parent="Bulkhead/Podium2" instance=ExtResource("3_4okgx")] [node name="CloseSwitch" parent="Bulkhead/Podium2" instance=ExtResource("3_awnx0")]
unique_name_in_owner = true unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0.35)
clean = true clean = true
@ -287,19 +289,19 @@ text = "Close"
unique_name_in_owner = true unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.5, 0, -6) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.5, 0, -6)
[node name="SignalTest" parent="SignalTestSpawnPoint" instance=ExtResource("9_dub8r")] [node name="SignalTest" parent="SignalTestSpawnPoint" instance=ExtResource("9_ix0jw")]
[node name="PropTestSpawnPoint" type="Marker3D" parent="."] [node name="PropTestSpawnPoint" type="Marker3D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.5, 0, 4.5) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.5, 0, 4.5)
[node name="PropTest" parent="PropTestSpawnPoint" instance=ExtResource("10_ovu60")] [node name="PropTest" parent="PropTestSpawnPoint" instance=ExtResource("10_xrfi2")]
[node name="ItemTestSpawnPoint" type="Marker3D" parent="."] [node name="ItemTestSpawnPoint" type="Marker3D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -13, 0, -2) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -13, 0, -2)
[node name="ItemTest" parent="ItemTestSpawnPoint" instance=ExtResource("11_crh2u")] [node name="ItemTest" parent="ItemTestSpawnPoint" instance=ExtResource("11_8natv")]
[connection signal="activated" from="ResetPodium/ResetSwitch" to="." method="reset"] [connection signal="activated" from="ResetPodium/ResetSwitch" to="." method="reset"]
[connection signal="activated" from="NoduleSpawner/WallSwitch" to="." method="spawn_nodule"] [connection signal="activated" from="NoduleSpawner/WallSwitch" to="." method="spawn_nodule"]

14
src/game/level.gd Normal file
View File

@ -0,0 +1,14 @@
class_name Level extends Node3D
## A level with associated metadata
const SAVE_PATH_FMT := "user://{0}.state.res"
## Internal ID string
@export var id: String
## Human-readable name
@export var pretty_name: String
func get_save_path() -> String:
return SAVE_PATH_FMT.format([id])

1
src/game/level.gd.uid Normal file
View File

@ -0,0 +1 @@
uid://68r4ht5ut1ct

View File

@ -1,6 +1,9 @@
extends Control extends Control
## Title screen! ## Title screen!
# TODO is there a way to get this path without loading the level scene?
@export var save_path: String
@export_category("Game Scenes") @export_category("Game Scenes")
# TODO is there a way to get the appropriate level scene path here without loading the world scene? # TODO is there a way to get the appropriate level scene path here without loading the world scene?
@export_file("*.tscn") var level_scene: String @export_file("*.tscn") var level_scene: String
@ -14,17 +17,12 @@ extends Control
func _ready() -> void: func _ready() -> void:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
var save_path := _get_save_path()
if FileAccess.file_exists(save_path): if FileAccess.file_exists(save_path):
continue_button.disabled = false continue_button.disabled = false
func _get_save_path() -> String:
return World.get_save_path(level_scene)
func continue_game() -> void: func continue_game() -> void:
LoadingTools.load_save(_get_save_path()) LoadingTools.load_save(save_path)
func new_game() -> void: func new_game() -> void:

View File

@ -52,6 +52,249 @@ shader_parameter/gunk_normal_map = SubResource("NoiseTexture3D_d72jk")
shader_parameter/mask_progress = 0.0 shader_parameter/mask_progress = 0.0
shader_parameter/mask_noise = SubResource("NoiseTexture2D_pgbvb") shader_parameter/mask_noise = SubResource("NoiseTexture2D_pgbvb")
[sub_resource type="Animation" id="Animation_iv5x5"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("VBoxContainer/Loader/Done:visible_ratio")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("VBoxContainer/TitleContainer:custom_minimum_size")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(800, 0)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("VBoxContainer/WarningMessage/LogoContainer:custom_minimum_size")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(128, 0)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Warning:visible_ratio")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Warning2:visible_ratio")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2/Warning3:visible_ratio")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Blinker:visible")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/7/type = "value"
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2/Blinker2:visible")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/8/type = "value"
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1:visible")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/9/type = "value"
tracks/9/imported = false
tracks/9/enabled = true
tracks/9/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2:visible")
tracks/9/interp = 1
tracks/9/loop_wrap = true
tracks/9/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/10/type = "value"
tracks/10/imported = false
tracks/10/enabled = true
tracks/10/path = NodePath("VBoxContainer/BufferSpace:custom_minimum_size")
tracks/10/interp = 1
tracks/10/loop_wrap = true
tracks/10/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(1024, 0)]
}
tracks/11/type = "value"
tracks/11/imported = false
tracks/11/enabled = true
tracks/11/path = NodePath("../Grunk2D:material:shader_parameter/mask_progress")
tracks/11/interp = 1
tracks/11/loop_wrap = true
tracks/11/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/12/type = "value"
tracks/12/imported = false
tracks/12/enabled = true
tracks/12/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Continue:visible")
tracks/12/interp = 1
tracks/12/loop_wrap = true
tracks/12/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/13/type = "value"
tracks/13/imported = false
tracks/13/enabled = true
tracks/13/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/NewGame:visible")
tracks/13/interp = 1
tracks/13/loop_wrap = true
tracks/13/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/14/type = "value"
tracks/14/imported = false
tracks/14/enabled = true
tracks/14/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Settings:visible")
tracks/14/interp = 1
tracks/14/loop_wrap = true
tracks/14/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/15/type = "value"
tracks/15/imported = false
tracks/15/enabled = true
tracks/15/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Quit:visible")
tracks/15/interp = 1
tracks/15/loop_wrap = true
tracks/15/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/16/type = "value"
tracks/16/imported = false
tracks/16/enabled = true
tracks/16/path = NodePath("VBoxContainer/MarginContainer:visible")
tracks/16/interp = 1
tracks/16/loop_wrap = true
tracks/16/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/17/type = "value"
tracks/17/imported = false
tracks/17/enabled = true
tracks/17/path = NodePath("VBoxContainer/TitleContainer:visible")
tracks/17/interp = 1
tracks/17/loop_wrap = true
tracks/17/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/18/type = "value"
tracks/18/imported = false
tracks/18/enabled = true
tracks/18/path = NodePath("VBoxContainer/BufferSpace:visible")
tracks/18/interp = 1
tracks/18/loop_wrap = true
tracks/18/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/19/type = "value"
tracks/19/imported = false
tracks/19/enabled = true
tracks/19/path = NodePath("VBoxContainer/WarningMessage:visible")
tracks/19/interp = 1
tracks/19/loop_wrap = true
tracks/19/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_uxv0r"] [sub_resource type="Animation" id="Animation_uxv0r"]
resource_name = "display" resource_name = "display"
length = 10.0 length = 10.0
@ -297,249 +540,6 @@ tracks/19/keys = {
"values": [false, true] "values": [false, true]
} }
[sub_resource type="Animation" id="Animation_iv5x5"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("VBoxContainer/Loader/Done:visible_ratio")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("VBoxContainer/TitleContainer:custom_minimum_size")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(800, 0)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("VBoxContainer/WarningMessage/LogoContainer:custom_minimum_size")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(128, 0)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Warning:visible_ratio")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Warning2:visible_ratio")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2/Warning3:visible_ratio")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Blinker:visible")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/7/type = "value"
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2/Blinker2:visible")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/8/type = "value"
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1:visible")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/9/type = "value"
tracks/9/imported = false
tracks/9/enabled = true
tracks/9/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2:visible")
tracks/9/interp = 1
tracks/9/loop_wrap = true
tracks/9/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/10/type = "value"
tracks/10/imported = false
tracks/10/enabled = true
tracks/10/path = NodePath("VBoxContainer/BufferSpace:custom_minimum_size")
tracks/10/interp = 1
tracks/10/loop_wrap = true
tracks/10/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(1024, 0)]
}
tracks/11/type = "value"
tracks/11/imported = false
tracks/11/enabled = true
tracks/11/path = NodePath("../Grunk2D:material:shader_parameter/mask_progress")
tracks/11/interp = 1
tracks/11/loop_wrap = true
tracks/11/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/12/type = "value"
tracks/12/imported = false
tracks/12/enabled = true
tracks/12/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Continue:visible")
tracks/12/interp = 1
tracks/12/loop_wrap = true
tracks/12/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/13/type = "value"
tracks/13/imported = false
tracks/13/enabled = true
tracks/13/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/NewGame:visible")
tracks/13/interp = 1
tracks/13/loop_wrap = true
tracks/13/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/14/type = "value"
tracks/14/imported = false
tracks/14/enabled = true
tracks/14/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Settings:visible")
tracks/14/interp = 1
tracks/14/loop_wrap = true
tracks/14/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/15/type = "value"
tracks/15/imported = false
tracks/15/enabled = true
tracks/15/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Quit:visible")
tracks/15/interp = 1
tracks/15/loop_wrap = true
tracks/15/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/16/type = "value"
tracks/16/imported = false
tracks/16/enabled = true
tracks/16/path = NodePath("VBoxContainer/MarginContainer:visible")
tracks/16/interp = 1
tracks/16/loop_wrap = true
tracks/16/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/17/type = "value"
tracks/17/imported = false
tracks/17/enabled = true
tracks/17/path = NodePath("VBoxContainer/TitleContainer:visible")
tracks/17/interp = 1
tracks/17/loop_wrap = true
tracks/17/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/18/type = "value"
tracks/18/imported = false
tracks/18/enabled = true
tracks/18/path = NodePath("VBoxContainer/BufferSpace:visible")
tracks/18/interp = 1
tracks/18/loop_wrap = true
tracks/18/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/19/type = "value"
tracks/19/imported = false
tracks/19/enabled = true
tracks/19/path = NodePath("VBoxContainer/WarningMessage:visible")
tracks/19/interp = 1
tracks/19/loop_wrap = true
tracks/19/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_3qdtd"] [sub_resource type="AnimationLibrary" id="AnimationLibrary_3qdtd"]
_data = { _data = {
&"RESET": SubResource("Animation_iv5x5"), &"RESET": SubResource("Animation_iv5x5"),
@ -555,6 +555,7 @@ grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
theme = ExtResource("1_3lcvc") theme = ExtResource("1_3lcvc")
script = ExtResource("2_rjwhj") script = ExtResource("2_rjwhj")
save_path = "user://ghost_ship.state.res"
level_scene = "uid://bov4ok76woyc" level_scene = "uid://bov4ok76woyc"
world_scene = "uid://884jqafhtrv0" world_scene = "uid://884jqafhtrv0"
settings_scene = ExtResource("3_wqn52") settings_scene = ExtResource("3_wqn52")

View File

@ -28,12 +28,12 @@ static func node_key(node: Node, world: World) -> String:
func load_to_world(world: World) -> void: func load_to_world(world: World) -> void:
if level_path != world.current_level.resource_path: if level_path != world.current_level_scene.resource_path:
push_warning( push_warning(
"This save is for ", "This save is for ",
level_path, level_path,
" but the loaded level is for ", " but the loaded level is for ",
world.current_level.resource_path world.current_level_scene.resource_path
) )
world.manager.grunk_tank_limit = grunk_tank_limit world.manager.grunk_tank_limit = grunk_tank_limit
@ -59,7 +59,7 @@ func load_to_world(world: World) -> void:
static func serialize(world: World) -> SaveState: static func serialize(world: World) -> SaveState:
var save := SaveState.new() var save := SaveState.new()
save.level_path = world.current_level.resource_path save.level_path = world.current_level_scene.resource_path
save.grunk_tank_limit = world.manager.grunk_tank_limit save.grunk_tank_limit = world.manager.grunk_tank_limit
save.mp3_player_unlocked = world.manager.mp3_player_unlocked save.mp3_player_unlocked = world.manager.mp3_player_unlocked

View File

@ -1,8 +1,6 @@
class_name World extends Node class_name World extends Node
## Access and flow control for the game world. ## Access and flow control for the game world.
const SAVE_PATH_FMT := "user://{0}.state.res"
@export var pause_enabled := true @export var pause_enabled := true
@export var save_state: SaveState @export var save_state: SaveState
@ -17,7 +15,8 @@ const SAVE_PATH_FMT := "user://{0}.state.res"
@export var kill_screen_scene: PackedScene @export var kill_screen_scene: PackedScene
var current_level: PackedScene var current_level_scene: PackedScene
var current_level: Level
@onready var level_root: Node3D = %LevelRoot @onready var level_root: Node3D = %LevelRoot
@onready var ui_root: Control = %UIRoot @onready var ui_root: Control = %UIRoot
@ -55,10 +54,10 @@ func load_level(level: PackedScene) -> void:
for c: Node in level_root.get_children(): for c: Node in level_root.get_children():
c.queue_free() c.queue_free()
level_root.remove_child(c) level_root.remove_child(c)
current_level = level current_level_scene = level
print("Instantiating level from ", level.resource_path) print("Instantiating level from ", level.resource_path)
var level_instance := level.instantiate() current_level = level.instantiate()
level_root.add_child(level_instance) level_root.add_child(current_level)
if save_state: if save_state:
save_state.load_to_world(self) save_state.load_to_world(self)
print("Done!") print("Done!")
@ -73,32 +72,24 @@ func on_player_death() -> void:
func _reload_saved(save: SaveState) -> void: func _reload_saved(save: SaveState) -> void:
save_state = save save_state = save
load_level(current_level) load_level(current_level_scene)
func on_game_over() -> void: func on_game_over() -> void:
# reload the level from the last save # reload the level from the last save
var save_path := World.get_level_save_path(current_level) var save_path := current_level.get_save_path()
if FileAccess.file_exists(save_path): if FileAccess.file_exists(save_path):
Game.instance.queue_load(save_path).finally(_reload_saved) Game.instance.queue_load(save_path).finally(_reload_saved)
else: else:
load_level(current_level) load_level(current_level_scene)
func save_progress() -> void: func save_progress() -> void:
print("Preparing save state...") print("Preparing save state...")
save_icon.show() save_icon.show()
var save := SaveState.serialize(self) var save := SaveState.serialize(self)
var save_path := World.get_level_save_path(current_level) var save_path := current_level.get_save_path()
print("Writing save to ", save_path) print("Writing save to ", save_path)
ResourceSaver.save(save, save_path) ResourceSaver.save(save, save_path)
save_icon.hide() save_icon.hide()
print("Done!") print("Done!")
static func get_save_path(level_path: String) -> String:
return SAVE_PATH_FMT.format([level_path.get_basename().get_file()])
static func get_level_save_path(level: PackedScene) -> String:
return World.get_save_path(level.resource_path)

View File

@ -4,7 +4,7 @@
[ext_resource type="Resource" uid="uid://tgac5tnfx56r" path="res://src/world/world_manager.tres" id="2_5kmgb"] [ext_resource type="Resource" uid="uid://tgac5tnfx56r" path="res://src/world/world_manager.tres" id="2_5kmgb"]
[ext_resource type="PackedScene" uid="uid://byvjsvavbg5xe" path="res://src/ui/menus/pause_menu/pause_menu.tscn" id="2_6fy3g"] [ext_resource type="PackedScene" uid="uid://byvjsvavbg5xe" path="res://src/ui/menus/pause_menu/pause_menu.tscn" id="2_6fy3g"]
[ext_resource type="Resource" uid="uid://0i72bf8ip1lx" path="res://src/world/spook_manager.tres" id="3_l0av5"] [ext_resource type="Resource" uid="uid://0i72bf8ip1lx" path="res://src/world/spook_manager.tres" id="3_l0av5"]
[ext_resource type="PackedScene" uid="uid://bov4ok76woyc" path="res://levels/ghost_ship/ghost_ship.tscn" id="4_5kmgb"] [ext_resource type="PackedScene" uid="uid://b8rv6dg4tgaeb" path="res://levels/mechanic_test/mechanic_test.tscn" id="4_5kmgb"]
[ext_resource type="PackedScene" uid="uid://c0uitm5cg88h1" path="res://src/ui/menus/kill_screen/kill_screen.tscn" id="6_l0av5"] [ext_resource type="PackedScene" uid="uid://c0uitm5cg88h1" path="res://src/ui/menus/kill_screen/kill_screen.tscn" id="6_l0av5"]
[ext_resource type="PackedScene" uid="uid://brknr57xc2cp0" path="res://src/ui/elements/save_icon/save_icon.tscn" id="7_5kmgb"] [ext_resource type="PackedScene" uid="uid://brknr57xc2cp0" path="res://src/ui/elements/save_icon/save_icon.tscn" id="7_5kmgb"]