class_name Game extends Node3D # Takes care of game state including # * player state # * current level # * player-world state (i.e. which items were picked up in the level) signal item_picked_up(node_path:NodePath) @onready var camera = %Camera @onready var player:Player = %Player @onready var build_system:BuildSystem = %BuildSystem var picked_up_level_items:Array[NodePath] = [] var level = null var _player_camera_offset:Vector3 = Vector3.ZERO # Called when the node enters the scene tree for the first time. func _ready(): _player_camera_offset = camera.global_position - player.global_position + Vector3.UP * 1 picked_up_level_items.clear() level = get_node("Level") register_item_pickups() # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(_delta): if build_system.is_active: player.process_mode = Node.PROCESS_MODE_DISABLED else: player.process_mode = Node.PROCESS_MODE_ALWAYS camera.global_position = player.global_position + _player_camera_offset camera.look_at(player.global_position) func register_item_pickups() -> void: # When saving a game we need to know which items were picked up. for pickup_item in get_tree().get_nodes_in_group("pickup_item"): pickup_item.connect("item_picked_up", on_item_pickup) func on_item_pickup(node_path:NodePath): picked_up_level_items.append(node_path) item_picked_up.emit(node_path) func load_level(level_resource_path:String) -> void: var level_resource = load(level_resource_path) as PackedScene var level_node = get_node("Level") as Node3D assert(level_node != null) level_node.queue_free() remove_child(level_node) level = level_resource.instantiate() name = "Level" add_child(level) register_item_pickups() func save_game(game_profile_path:String): var save_data:SaveGameResource = SaveGameResource.new() save_data.level = level.scene_file_path save_data.level_pickup_items = picked_up_level_items save_data.player_transform = player.global_transform for node:Node in get_tree().get_nodes_in_group("quest_state"): save_data.quest_states[node.name] = {} for property in node.get_property_list(): if (property.usage & PROPERTY_USAGE_STORAGE != 0) and (property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE) != 0: save_data.quest_states[node.name][property.name] = node.get(property.name) for item_stack in player.inventory.get_item_stacks(): save_data.inventory.append({"item": item_stack.item, "count": item_stack.count}) for structure:BuiltStructure in get_tree().get_nodes_in_group("built_structure"): var built_structure_resource = BuiltStructureResource.new() built_structure_resource.global_transform = structure.global_transform built_structure_resource.item = structure.item var item_array = save_data.built_structures.get_or_add(structure.item, []) item_array.append(structure.global_transform) print("Saving game: " + game_profile_path + "/savegame.tres") ResourceSaver.save(save_data, game_profile_path + "/savegame.tres") func load_game(game_profile_path:String) -> void: print("Loading game: " + game_profile_path + "/savegame.tres") var save_data:SaveGameResource = load(game_profile_path + "/savegame.tres") as SaveGameResource load_level(save_data.level) player.global_transform = save_data.player_transform player.init_look_target_direction() # Quest state for quest_state:Node in get_tree().get_nodes_in_group("quest_state"): for property in quest_state.get_property_list(): if (property.usage & PROPERTY_USAGE_STORAGE != 0) and (property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE) != 0 and (save_data.quest_states.has(quest_state.name)) and (save_data.quest_states[quest_state.name].has(property.name)): quest_state.set(property.name, save_data.quest_states[quest_state.name][property.name]) # Inventory player.inventory.clear() var inventory_item_stacks:Array[ItemStack] = player.inventory.get_item_stacks() assert(inventory_item_stacks.size() >= save_data.inventory.size()) for i in range(save_data.inventory.size()): inventory_item_stacks[i].item = save_data.inventory[i]["item"] inventory_item_stacks[i].count = save_data.inventory[i]["count"] # Picked up items for item_path in save_data.level_pickup_items: if get_tree().root.has_node(item_path): var item_node = get_tree().root.get_node(item_path) picked_up_level_items.append(item_path) item_node.queue_free() # Built structures for item:ItemResource in save_data.built_structures.keys(): var item_transform_array = save_data.built_structures[item] as Array[Transform3D] for structure_transform in item_transform_array: build_system.build_structure(item, structure_transform)