Enhance save system functionality; improve game state management and session tracking
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
class_name SaveSystem
|
||||
extends Node
|
||||
|
||||
@export var save_path: String = "user://savegame.save"
|
||||
@@ -15,18 +14,32 @@ func save_game():
|
||||
var file := FileAccess.open(save_path, FileAccess.WRITE)
|
||||
file.store_var(save_data)
|
||||
file.close()
|
||||
print("Game saved to: ", save_path)
|
||||
|
||||
|
||||
func load_game():
|
||||
func load_game() -> bool:
|
||||
if not FileAccess.file_exists(save_path):
|
||||
return
|
||||
return false
|
||||
var file := FileAccess.open(save_path, FileAccess.READ)
|
||||
var save_data: Dictionary = file.get_var()
|
||||
file.close()
|
||||
|
||||
if save_data.has("version") and save_data["version"] != version:
|
||||
print("Save file version mismatch. Expected: ", version, ", Found: ", save_data["version"])
|
||||
return
|
||||
return false
|
||||
|
||||
print("save data: ", save_data)
|
||||
gm.player_state = save_data["player_state"]
|
||||
gm.unlock_skills(gm.player_state["unlocked_skills"])
|
||||
print("Player state loaded: ", gm.player_state)
|
||||
var skills: Array[String] = []
|
||||
for skill_name in gm.player_state["unlocked_skills"]:
|
||||
skills.append(skill_name)
|
||||
|
||||
print("Newly unlocked skills: ", skills)
|
||||
gm.unlock_skills(skills)
|
||||
print("Game loaded from: ", save_path)
|
||||
return true
|
||||
|
||||
|
||||
func check_save_exists() -> bool:
|
||||
return FileAccess.file_exists(save_path)
|
@@ -36,6 +36,7 @@ Console="*res://addons/console/console.gd"
|
||||
AchievementsManager="*res://objects/achievements.tscn"
|
||||
ConfigFileHandler="*res://autoloads/config_file_handler.gd"
|
||||
UiManager="*res://autoloads/ui_manager.gd"
|
||||
SaveSystem="*res://autoloads/save_system.gd"
|
||||
|
||||
[debug]
|
||||
|
||||
|
@@ -75,8 +75,9 @@ player_health = NodePath("../../Brick Player/HealthComponent")
|
||||
current_level = SubResource("Resource_bqjcg")
|
||||
nodes_to_disable = [NodePath("../../Brick Player")]
|
||||
|
||||
[node name="Marketplace" parent="UI Layer" index="3" node_paths=PackedStringArray("skill_unlocker")]
|
||||
[node name="Marketplace" parent="UI Layer" index="3" node_paths=PackedStringArray("skill_unlocker", "components_to_disable")]
|
||||
skill_unlocker = NodePath("../../Brick Player/SkillUnlockerComponent")
|
||||
components_to_disable = [NodePath("../../Brick Player")]
|
||||
|
||||
[node name="Global Light" parent="." instance=ExtResource("4_wykfl")]
|
||||
|
||||
|
@@ -36,4 +36,4 @@ func on_exit_area_body_entered(_body: Node2D) -> void:
|
||||
|
||||
|
||||
func go_to_next_level() -> void:
|
||||
gm.try_to_go_to_next_level()
|
||||
gm.on_level_complete()
|
@@ -17,5 +17,5 @@ func _on_health_component_on_death() -> void:
|
||||
effect.scale = Vector2(1.5, 1.5)
|
||||
|
||||
gm.remove_lives(1)
|
||||
gm.set_coins(0)
|
||||
gm.reset_current_session_state()
|
||||
|
||||
|
@@ -6,10 +6,10 @@ extends Node
|
||||
|
||||
func _ready():
|
||||
await get_tree().process_frame
|
||||
var coins = get_tree().get_nodes_in_group("coins")
|
||||
var coins := get_tree().get_nodes_in_group("coins")
|
||||
|
||||
for coin in coins:
|
||||
coin.connect("collected", on_collected)
|
||||
coin.collected.connect(on_collected)
|
||||
|
||||
|
||||
func on_collected(amount: int, type: CollectableResource.CollectableType) -> void:
|
||||
@@ -17,4 +17,4 @@ func on_collected(amount: int, type: CollectableResource.CollectableType) -> voi
|
||||
return
|
||||
if type != CollectableResource.CollectableType.COIN:
|
||||
return
|
||||
game_manager.add_coins(amount)
|
||||
game_manager.current_session_state["coins_collected"] += amount
|
||||
|
@@ -6,6 +6,11 @@ extends Node
|
||||
@onready var game_manager: GM = $"/root/GameManager"
|
||||
|
||||
|
||||
|
||||
func has_enough_coins(amount: int) -> bool:
|
||||
return game_manager and game_manager.get_coins() >= amount
|
||||
|
||||
|
||||
func try_unlock_skill(skill_data: SkillData) -> bool:
|
||||
if not game_manager:
|
||||
return false
|
||||
@@ -13,11 +18,11 @@ func try_unlock_skill(skill_data: SkillData) -> bool:
|
||||
if game_manager.is_skill_unlocked(skill_data.name):
|
||||
return false
|
||||
|
||||
if game_manager.get_coins() < skill_data.cost:
|
||||
if not has_enough_coins(skill_data.cost):
|
||||
return false
|
||||
|
||||
game_manager.remove_coins(skill_data.cost)
|
||||
game_manager.unlock_skill(skill_data.name)
|
||||
game_manager.current_session_state["unlocked_skills"].append(skill_data.name)
|
||||
skill_manager.add_skill(skill_data)
|
||||
return true
|
||||
|
||||
@@ -31,8 +36,3 @@ func unlock_all_skills() -> void:
|
||||
|
||||
game_manager.unlock_skills(skills)
|
||||
skill_manager.apply_unlocked_skills()
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("unlock_skills"):
|
||||
unlock_all_skills()
|
@@ -9,11 +9,18 @@ extends Node
|
||||
"unlocked_skills": [],
|
||||
"current_level": 0,
|
||||
"unlocked_levels": [],
|
||||
"completed_levels": [],
|
||||
}
|
||||
|
||||
var nodes_in_scene := []
|
||||
|
||||
|
||||
var current_session_state := {
|
||||
"coins_collected": 0,
|
||||
"skills_unlocked": [],
|
||||
}
|
||||
|
||||
|
||||
func _enter_tree() -> void:
|
||||
get_tree().node_added.connect(on_node_added)
|
||||
get_tree().node_removed.connect(on_node_removed)
|
||||
@@ -64,6 +71,7 @@ func get_kid_nodes() -> Array[CollectableComponent]:
|
||||
|
||||
func add_coins(amount: int) -> void:
|
||||
player_state["coins"] += amount
|
||||
player_state["coins"] = max(0, player_state["coins"])
|
||||
|
||||
|
||||
func set_coins(amount: int) -> void:
|
||||
@@ -71,11 +79,20 @@ func set_coins(amount: int) -> void:
|
||||
|
||||
|
||||
func get_coins() -> int:
|
||||
return player_state["coins"]
|
||||
return player_state["coins"] + current_session_state["coins_collected"]
|
||||
|
||||
|
||||
func remove_coins(amount: int) -> void:
|
||||
player_state["coins"] -= amount
|
||||
var session_coins = current_session_state["coins_collected"]
|
||||
|
||||
if amount <= session_coins:
|
||||
current_session_state["coins_collected"] -= amount
|
||||
else:
|
||||
var remaining_amount = amount - session_coins
|
||||
current_session_state["coins_collected"] = 0
|
||||
player_state["coins"] = max(0, player_state["coins"] - remaining_amount)
|
||||
|
||||
player_state["coins"] = max(0, player_state["coins"])
|
||||
|
||||
|
||||
func add_lives(amount: int) -> void:
|
||||
@@ -95,7 +112,7 @@ func get_lives() -> int:
|
||||
|
||||
|
||||
func is_skill_unlocked(skill_name: String) -> bool:
|
||||
return skill_name in player_state["unlocked_skills"]
|
||||
return skill_name in player_state["unlocked_skills"] or skill_name in current_session_state["skills_unlocked"]
|
||||
|
||||
|
||||
func unlock_skill(skill_name: String) -> void:
|
||||
@@ -118,6 +135,7 @@ func reset_player_state() -> void:
|
||||
"coins": 0,
|
||||
"lives": 3,
|
||||
"unlocked_skills": [],
|
||||
"completed_levels": [],
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +150,19 @@ func try_to_go_to_next_level() -> void:
|
||||
get_tree().change_scene_to_packed(level_scenes[next_level])
|
||||
|
||||
|
||||
|
||||
func mark_level_complete(level_index: int) -> void:
|
||||
unlock_level(level_index + 1)
|
||||
if level_index not in player_state["completed_levels"]: player_state["completed_levels"].append(level_index)
|
||||
|
||||
|
||||
func reset_current_session_state() -> void:
|
||||
current_session_state = {
|
||||
"coins_collected": 0,
|
||||
"skills_unlocked": [],
|
||||
}
|
||||
|
||||
|
||||
func quit_game() -> void:
|
||||
get_tree().quit()
|
||||
|
||||
@@ -152,9 +183,24 @@ func start_new_game() -> void:
|
||||
|
||||
|
||||
func continue_game() -> void:
|
||||
# todo: load player state from save file
|
||||
if not SaveSystem.load_game():
|
||||
printerr("Failed to load game. Starting a new game instead.")
|
||||
start_new_game()
|
||||
return
|
||||
|
||||
if player_state["current_level"] < level_scenes.size():
|
||||
get_tree().change_scene_to_packed(level_scenes[player_state["current_level"]])
|
||||
else:
|
||||
printerr("No levels unlocked to continue.")
|
||||
|
||||
|
||||
func on_level_complete() -> void:
|
||||
var level_index = player_state["current_level"]
|
||||
mark_level_complete(level_index)
|
||||
add_coins(current_session_state["coins_collected"])
|
||||
for skill_name in current_session_state["skills_unlocked"]:
|
||||
unlock_skill(skill_name)
|
||||
|
||||
reset_current_session_state()
|
||||
try_to_go_to_next_level()
|
||||
SaveSystem.save_game()
|
||||
|
@@ -23,6 +23,7 @@ func on_restart_button_pressed() -> void:
|
||||
return
|
||||
|
||||
gm.reset_player_state()
|
||||
gm.reset_current_session_state()
|
||||
get_tree().reload_current_scene()
|
||||
|
||||
|
||||
|
@@ -27,6 +27,11 @@ func _ready() -> void:
|
||||
if version_label:
|
||||
version_label.text = "v. " + ProjectSettings.get_setting("application/config/version")
|
||||
|
||||
if not SaveSystem.check_save_exists() and continue_button:
|
||||
continue_button.disabled = true
|
||||
else:
|
||||
continue_button.disabled = false
|
||||
|
||||
|
||||
func _on_new_game_button_pressed() -> void:
|
||||
if gm:
|
||||
|
Reference in New Issue
Block a user