TinyAdventure/scenes/game.gd

129 lines
4.6 KiB
GDScript

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)