class_name GM extends Node @export var level_scenes: Array[PackedScene] @export var player_state := { "coins": 0, "lives": 3, "unlocked_skills": [], "current_level": 0, "unlocked_levels": [0], "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) func on_node_added(node: Node) -> void: nodes_in_scene.append(node) func on_node_removed(node: Node) -> void: if node in nodes_in_scene: nodes_in_scene.erase(node) func get_colllectable_nodes() -> Array[CollectableComponent]: var collectable_nodes: Array[CollectableComponent] = [] for node in nodes_in_scene: var collectable_component: CollectableComponent = node.get_node_or_null("Collectable") if not collectable_component: collectable_component = node.get_node_or_null("CollectableComponent") if not collectable_component: continue collectable_nodes.append(collectable_component) return collectable_nodes func get_coin_nodes() -> Array[CollectableComponent]: var coin_nodes := [] for node in nodes_in_scene: var collectable_component: CollectableComponent = node.get_node_or_null("Collectable") if not collectable_component: continue if collectable_component.collectable_data.type == CollectableResource.CollectableType.COIN: coin_nodes.append(collectable_component) return coin_nodes func get_kid_nodes() -> Array[CollectableComponent]: var kid_nodes := [] for node in nodes_in_scene: var collectable_component: CollectableComponent = node.get_node_or_null("Collectable") if not collectable_component: continue if collectable_component.collectable_data.type == CollectableResource.CollectableType.KID: kid_nodes.append(collectable_component) return kid_nodes func get_player_node() -> Node: for node in nodes_in_scene: if node is PlayerController: return node return null func add_coins(amount: int) -> void: player_state["coins"] += amount player_state["coins"] = max(0, player_state["coins"]) func set_coins(amount: int) -> void: player_state["coins"] = amount func get_coins() -> int: return player_state["coins"] + current_session_state["coins_collected"] func remove_coins(amount: int) -> void: 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: player_state["lives"] += amount func remove_lives(amount: int) -> void: player_state["lives"] -= amount func set_lives(amount: int) -> void: player_state["lives"] = amount func get_lives() -> int: return player_state["lives"] func is_skill_unlocked(skill: SkillData) -> bool: return skill in player_state["unlocked_skills"] or skill in current_session_state["skills_unlocked"] func unlock_skill(skill: SkillData) -> void: if not is_skill_unlocked(skill): player_state["unlocked_skills"].append(skill) func remove_skill(skill: SkillData) -> void: if is_skill_unlocked(skill): player_state["unlocked_skills"].erase(skill) func unlock_skills(skills: Array[SkillData]) -> void: for skill in skills: unlock_skill(skill) func reset_player_state() -> void: player_state = { "coins": 0, "lives": 3, "unlocked_skills": [], "current_level": 0, "unlocked_levels": [0], "completed_levels": [], } func unlock_level(level_index: int) -> void: if level_index not in player_state["unlocked_levels"]: player_state["unlocked_levels"].append(level_index) func try_to_go_to_next_level() -> void: var next_level = player_state["current_level"] + 1 if next_level < level_scenes.size() and next_level in player_state["unlocked_levels"]: player_state["current_level"] += 1 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 restart_game() -> void: reset_player_state() reset_current_session_state() get_tree().change_scene_to_packed(level_scenes[0]) SaveSystem.save_game() func quit_game() -> void: get_tree().quit() func pause_game() -> void: Engine.time_scale = 0 func resume_game() -> void: Engine.time_scale = 1 func start_new_game() -> void: reset_player_state() reset_current_session_state() get_tree().change_scene_to_packed(level_scenes[0]) SaveSystem.save_game() func continue_game() -> void: 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 in current_session_state["skills_unlocked"]: unlock_skill(skill) reset_current_session_state() try_to_go_to_next_level() SaveSystem.save_game() func get_unlocked_skills() -> Array: var skills_unlocked = player_state.get("unlocked_skills", []) var skills_current_session = current_session_state.get("skills_unlocked", []) if not skills_current_session: return skills_unlocked if not skills_unlocked: return skills_current_session return skills_unlocked + skills_current_session