220 lines
7.1 KiB
GDScript
220 lines
7.1 KiB
GDScript
class_name RootUI
|
|
extends CanvasLayer
|
|
|
|
const GAME_PROFILE_FOLDER:String = "game_profiles"
|
|
|
|
@export var startup_scene:PackedScene
|
|
@export var game_scene:PackedScene
|
|
@export var autostart_game_profile:String = ""
|
|
|
|
@onready var scene = %Scene
|
|
@onready var ui_panels:Array = [ %MainMenuUI, %StartGameMenuUI, %CreateGameUI, %GameUI ]
|
|
@onready var active_ui_panel:Control = null
|
|
|
|
enum ROOT_UI_STATE { UNDEFINED, MENU, GAME }
|
|
var _root_ui_state:ROOT_UI_STATE = ROOT_UI_STATE.UNDEFINED
|
|
|
|
var current_level_resource:String
|
|
var current_game_profile:GameProfileResource = null
|
|
var current_game_profile_directory:String = ""
|
|
|
|
var _game_build_system:BuildSystem = null
|
|
|
|
func _ready():
|
|
var autostart_load_success = false
|
|
if not autostart_game_profile.is_empty():
|
|
autostart_load_success = _on_start_game_profile("user://" + GAME_PROFILE_FOLDER + "/" + autostart_game_profile + "/game.tres")
|
|
|
|
if not autostart_load_success:
|
|
set_root_ui_state(ROOT_UI_STATE.MENU)
|
|
|
|
%CreateGameUI.start_game.connect(_on_start_game_profile)
|
|
%StartGameMenuUI.start_game.connect(_on_start_game_profile)
|
|
|
|
func activate_ui_panel(ui_panel:Control):
|
|
for control in ui_panels:
|
|
if control == ui_panel:
|
|
control.visible = true
|
|
else:
|
|
control.visible = false
|
|
|
|
active_ui_panel = ui_panel
|
|
|
|
|
|
func load_scene(scene_resource:PackedScene):
|
|
for scene_child in scene.get_children():
|
|
scene_child.queue_free()
|
|
scene_child.get_parent().remove_child(scene_child)
|
|
|
|
print("Loading level '" + scene_resource.resource_path + "'")
|
|
scene.add_child(scene_resource .instantiate())
|
|
current_level_resource = scene_resource.resource_path
|
|
|
|
_game_build_system = scene.find_child("BuildSystem", true, false) as BuildSystem
|
|
|
|
var player:Player = scene.find_child("Player", true, false)
|
|
InteractionSystem.player = player
|
|
|
|
func save_game():
|
|
var player:Player = scene.find_child("Player", true, false)
|
|
|
|
if player == null:
|
|
push_error("Cannot load game: no player found!")
|
|
return
|
|
|
|
var save_data:SaveGameResource = SaveGameResource.new()
|
|
|
|
save_data.level = current_level_resource
|
|
save_data.level_pickup_items = %GameUI.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.find_key(structure.item)
|
|
|
|
if item_array == null:
|
|
item_array = []
|
|
save_data.built_structures[structure.item] = item_array
|
|
|
|
item_array.append(structure.global_transform)
|
|
|
|
print("Saving game: " + current_game_profile_directory + "/savegame.tres")
|
|
ResourceSaver.save(save_data, current_game_profile_directory + "/savegame.tres")
|
|
activate_ui_panel(%GameUI)
|
|
|
|
func load_game():
|
|
set_root_ui_state(RootUI.ROOT_UI_STATE.UNDEFINED)
|
|
|
|
%GameUI.picked_up_level_items.clear()
|
|
|
|
print("Loading game: " + current_game_profile_directory + "/savegame.tres")
|
|
var save_data:SaveGameResource = load(current_game_profile_directory + "/savegame.tres") as SaveGameResource
|
|
|
|
var level_resource:PackedScene = load(save_data.level)
|
|
load_scene(level_resource)
|
|
|
|
var player:Player = scene.find_child("Player", true, false)
|
|
|
|
if player == null:
|
|
push_error("Cannot load game: no player found!")
|
|
return
|
|
|
|
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)
|
|
%GameUI.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:
|
|
_game_build_system.build_structure(item, structure_transform)
|
|
|
|
set_root_ui_state(RootUI.ROOT_UI_STATE.GAME)
|
|
|
|
|
|
func set_root_ui_state(state:ROOT_UI_STATE):
|
|
if _root_ui_state == state:
|
|
return
|
|
|
|
if state == ROOT_UI_STATE.GAME:
|
|
%GameUI.activate_game_scene(scene.get_child(0))
|
|
activate_ui_panel(%GameUI)
|
|
elif state == ROOT_UI_STATE.MENU:
|
|
load_scene(startup_scene)
|
|
%GameUI.activate_game_scene(null)
|
|
activate_ui_panel(%MainMenuUI)
|
|
|
|
_root_ui_state = state
|
|
|
|
func _on_start_game_profile(profile_path:String) -> bool:
|
|
current_game_profile = null
|
|
current_game_profile_directory = ""
|
|
|
|
print ("Root UI: Starting game from profile path " + profile_path)
|
|
current_game_profile = ResourceLoader.load(profile_path)
|
|
if current_game_profile == null:
|
|
push_error("Error loading game profile " + profile_path)
|
|
return false
|
|
|
|
# Update last_played timestamp
|
|
current_game_profile.last_played = Time.get_datetime_string_from_system()
|
|
ResourceSaver.save(current_game_profile, profile_path)
|
|
|
|
current_game_profile_directory = profile_path.get_base_dir()
|
|
|
|
if not _is_savegame_available():
|
|
var level_resource:PackedScene = game_scene
|
|
load_scene(level_resource)
|
|
save_game()
|
|
|
|
load_game()
|
|
|
|
activate_ui_panel(%GameUI)
|
|
|
|
return true
|
|
|
|
func _is_savegame_available() -> bool:
|
|
if current_game_profile_directory == "":
|
|
return false
|
|
|
|
var game_profile_directory = DirAccess.open(current_game_profile_directory)
|
|
return game_profile_directory.file_exists("savegame.tres")
|
|
|
|
func _on_start_game_button_pressed():
|
|
load_scene(game_scene)
|
|
set_root_ui_state(ROOT_UI_STATE.GAME)
|
|
|
|
func _on_quit_game_scene():
|
|
save_game()
|
|
set_root_ui_state(ROOT_UI_STATE.MENU)
|
|
|
|
func _on_quit_button_pressed():
|
|
get_tree().quit()
|
|
|
|
func _activate_main_menu_ui():
|
|
activate_ui_panel(%MainMenuUI)
|
|
|
|
func _activate_start_game_menu_ui():
|
|
activate_ui_panel(%StartGameMenuUI)
|
|
|
|
func _activate_create_game_ui():
|
|
%CreateGameUI.game_name_edit.text = ""
|
|
activate_ui_panel(%CreateGameUI)
|
|
|
|
func _activate_game_ui():
|
|
activate_ui_panel(%GameUI)
|