From 190751b6b5834f040fc04f395e150daac221f6c5 Mon Sep 17 00:00:00 2001 From: theludovyc Date: Sun, 15 Dec 2024 17:07:04 +0100 Subject: [PATCH] [ench] handle save system Use RGT to save into a json in user data Save buildings placement, money, production lines, storage and orders --- Scene/Menu/MainMenu.tscn | 39 ++++++++- Scene/RGT/loadSaveMenu.tscn | 21 +++++ Scene/RGT/savePanelContainer.tscn | 49 +++++++++++ Script/Gui/Menu/MainMenu.gd | 18 ++++ Script/RGT/LoadSaveMenu/load_save_menu.gd | 2 +- Script/RGT/MainMenu.gd | 46 +++++----- Script/RGT/load_save_menu.gd | 85 ++++++++++++++++++ Script/RGT/save_panel_container.gd | 22 +++++ Script/TheBuilder.gd | 75 ++++++++++++++++ theLudovyc/EventBus.gd | 1 + theLudovyc/GUI/MarketContainer.gd | 12 +++ theLudovyc/GUI/ResourceOrder.gd | 3 + theLudovyc/Game2D.gd | 100 ++++++++++++---------- theLudovyc/Game2D.tscn | 9 +- theLudovyc/TheBank.gd | 17 ++++ theLudovyc/TheFactory.gd | 34 +++++++- theLudovyc/TheMarket.gd | 51 ++++++++++- theLudovyc/TheStorage.gd | 19 +++- theLudovyc/TileMap.gd | 7 +- 19 files changed, 529 insertions(+), 81 deletions(-) create mode 100644 Scene/RGT/loadSaveMenu.tscn create mode 100644 Scene/RGT/savePanelContainer.tscn create mode 100644 Script/RGT/load_save_menu.gd create mode 100644 Script/RGT/save_panel_container.gd create mode 100644 Script/TheBuilder.gd diff --git a/Scene/Menu/MainMenu.tscn b/Scene/Menu/MainMenu.tscn index 6bc6f495..528c3a8b 100644 --- a/Scene/Menu/MainMenu.tscn +++ b/Scene/Menu/MainMenu.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=18 format=3 uid="uid://dytw0n3b07ux4"] +[gd_scene load_steps=19 format=3 uid="uid://dytw0n3b07ux4"] [ext_resource type="Script" path="res://Script/Gui/Menu/MainMenu.gd" id="1"] [ext_resource type="Theme" uid="uid://lyx8kydf373j" path="res://Art/Theme/MenuTheme.tres" id="1_i4hjr"] @@ -14,6 +14,7 @@ [ext_resource type="Texture2D" uid="uid://fnwe2ccpoxu7" path="res://Art/Image/Gui/Icons/MainMenu/multiplayer_bw.png" id="11_ulff8"] [ext_resource type="Texture2D" uid="uid://dx3wfk7nhepo7" path="res://Art/Image/Gui/Logos/uh_no_text.svg" id="12_q4rhy"] [ext_resource type="Texture2D" uid="uid://lxvd4qr8d35m" path="res://Art/Image/Gui/Logos/uh_only_text.svg" id="13_yw4on"] +[ext_resource type="PackedScene" uid="uid://choevp6ilq78t" path="res://Scene/RGT/loadSaveMenu.tscn" id="15_fufc5"] [sub_resource type="Animation" id="Animation_ft716"] length = 0.001 @@ -202,7 +203,6 @@ offset_left = -158.0 offset_top = -160.0 offset_right = -58.0 offset_bottom = -60.0 -disabled = true text = "Load Game" texture = ExtResource("6_6uh4k") @@ -347,6 +347,39 @@ texture = ExtResource("13_yw4on") expand_mode = 1 stretch_mode = 4 +[node name="PanelMenu" type="Panel" parent="."] +unique_name_in_owner = true +visible = false +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.1 +anchor_top = 0.1 +anchor_right = 0.9 +anchor_bottom = 0.9 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="LoadSaveMenu" parent="PanelMenu" instance=ExtResource("15_fufc5")] +unique_name_in_owner = true +visible = false +layout_mode = 1 +metadata/_edit_use_anchors_ = true + +[node name="BackButton" type="Button" parent="PanelMenu"] +layout_mode = 1 +anchors_preset = 7 +anchor_left = 0.5 +anchor_top = 1.0 +anchor_right = 0.5 +anchor_bottom = 1.0 +offset_left = -34.0 +offset_top = 16.0 +offset_right = 37.0 +offset_bottom = 61.0 +grow_horizontal = 2 +grow_vertical = 0 +text = "Back" + [node name="VersionNumber" type="Label" parent="."] unique_name_in_owner = true layout_mode = 1 @@ -371,4 +404,6 @@ unique_name_in_owner = true dialog_text = "Are you sure you want to quit ?" [connection signal="pressed" from="Decoration/MenuItems/PlayButton" to="." method="_on_play_button_pressed"] +[connection signal="pressed" from="Decoration/MenuItems/LoadButton" to="." method="_on_load_button_pressed"] [connection signal="pressed" from="Decoration/MenuItems/ExitButton" to="." method="_on_exit_button_pressed"] +[connection signal="pressed" from="PanelMenu/BackButton" to="." method="_on_back_button_pressed"] diff --git a/Scene/RGT/loadSaveMenu.tscn b/Scene/RGT/loadSaveMenu.tscn new file mode 100644 index 00000000..7f418df5 --- /dev/null +++ b/Scene/RGT/loadSaveMenu.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=2 format=3 uid="uid://choevp6ilq78t"] + +[ext_resource type="Script" path="res://Script/RGT/LoadSaveMenu/load_save_menu.gd" id="1_nyk5l"] + +[node name="LoadSaveMenu" type="ScrollContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +horizontal_scroll_mode = 0 +script = ExtResource("1_nyk5l") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ConfirmationDialog" type="ConfirmationDialog" parent="."] +unique_name_in_owner = true + +[connection signal="confirmed" from="ConfirmationDialog" to="." method="_on_confirmation_dialog_confirmed"] diff --git a/Scene/RGT/savePanelContainer.tscn b/Scene/RGT/savePanelContainer.tscn new file mode 100644 index 00000000..fcbd1f8f --- /dev/null +++ b/Scene/RGT/savePanelContainer.tscn @@ -0,0 +1,49 @@ +[gd_scene load_steps=2 format=3 uid="uid://wal8k0gos06y"] + +[ext_resource type="Script" path="res://Script/RGT/LoadSaveMenu/save_panel_container.gd" id="1_np60c"] + +[node name="SavePanelContainer" type="PanelContainer"] +script = ExtResource("1_np60c") + +[node name="MarginContainer" type="MarginContainer" parent="."] +layout_mode = 2 +theme_override_constants/margin_left = 12 +theme_override_constants/margin_top = 12 +theme_override_constants/margin_right = 12 +theme_override_constants/margin_bottom = 12 + +[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"] +layout_mode = 2 +theme_override_constants/separation = 8 + +[node name="SaveTextureRect" type="TextureRect" parent="MarginContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 4 +expand_mode = 5 +stretch_mode = 5 + +[node name="NameLabel" type="Label" parent="MarginContainer/HBoxContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(8, 8) +layout_mode = 2 +size_flags_horizontal = 3 +horizontal_alignment = 1 +vertical_alignment = 1 +autowrap_mode = 1 + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/HBoxContainer"] +layout_mode = 2 +size_flags_vertical = 4 +alignment = 1 + +[node name="LoadButton" type="Button" parent="MarginContainer/HBoxContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Load" + +[node name="DeleteButton" type="Button" parent="MarginContainer/HBoxContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Delete" diff --git a/Script/Gui/Menu/MainMenu.gd b/Script/Gui/Menu/MainMenu.gd index 8425abf4..fffffefe 100644 --- a/Script/Gui/Menu/MainMenu.gd +++ b/Script/Gui/Menu/MainMenu.gd @@ -1,5 +1,7 @@ extends MainMenu +@onready var panel_menu = %PanelMenu + # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(_delta): if Input.is_anything_pressed(): @@ -8,3 +10,19 @@ func _process(_delta): animation_player.seek(animation_player.current_animation_length) set_process(false) + + +func _open_sub_menu(menu : Control): + panel_menu.visible = true + + sub_menu = menu + sub_menu.show() + +func _close_sub_menu(): + if sub_menu == null: + return + + panel_menu.visible = false + + sub_menu.hide() + sub_menu = null diff --git a/Script/RGT/LoadSaveMenu/load_save_menu.gd b/Script/RGT/LoadSaveMenu/load_save_menu.gd index 46aa67ad..abf2f73c 100644 --- a/Script/RGT/LoadSaveMenu/load_save_menu.gd +++ b/Script/RGT/LoadSaveMenu/load_save_menu.gd @@ -5,7 +5,7 @@ signal no_save_to_load const confirm_load = "Are you sure you want to load this save?\n" const confirm_delete = "Are you sure you want to delete this save ?\n" -var SavePanel = preload("res://scenes/LoadSaveMenu/savePanelContainer.tscn") +var SavePanel = preload("res://Scene/RGT/savePanelContainer.tscn") @onready var vbox_container = $VBoxContainer diff --git a/Script/RGT/MainMenu.gd b/Script/RGT/MainMenu.gd index 02361678..c217cb98 100644 --- a/Script/RGT/MainMenu.gd +++ b/Script/RGT/MainMenu.gd @@ -1,7 +1,7 @@ class_name MainMenu extends Control -#var sub_menu +var sub_menu #@onready var continue_button = %ContinueButton @onready var play_button = %PlayButton @@ -18,27 +18,27 @@ extends Control exit_button ] -#@onready var load_save_menu = %LoadSaveMenu +@onready var load_save_menu = %LoadSaveMenu #@onready var option_menu = %OptionsMenu #@onready var credit_menu = %CreditsContainer @onready var confirm_popup = %ConfirmationDialog -#func _open_sub_menu(menu : Control): - #if sub_menu == menu: - #sub_menu.visible = !sub_menu.visible - #return - #if sub_menu != null: - #sub_menu.hide() - #sub_menu = menu - #sub_menu.show() +func _open_sub_menu(menu : Control): + if sub_menu == menu: + sub_menu.visible = !sub_menu.visible + return + if sub_menu != null: + sub_menu.hide() + sub_menu = menu + sub_menu.show() -#func _close_sub_menu(): - #if sub_menu == null: - #return - #sub_menu.hide() - #sub_menu = null +func _close_sub_menu(): + if sub_menu == null: + return + sub_menu.hide() + sub_menu = null #func _event_is_mouse_button_released(event : InputEvent): @@ -86,8 +86,8 @@ func _on_play_button_pressed(): SceneLoader.change_scene(RGT_Globals.first_game_scene_setting) -#func _on_load_button_pressed() -> void: - #_open_sub_menu(load_save_menu) +func _on_load_button_pressed() -> void: + _open_sub_menu(load_save_menu) # #func _on_options_button_pressed(): #_open_sub_menu(option_menu) @@ -101,11 +101,11 @@ func _on_exit_button_pressed(): func _on_exit_confirmed(): get_tree().quit() -#func _on_back_button_pressed(): - #_close_sub_menu() +func _on_back_button_pressed(): + _close_sub_menu() -#func _on_load_save_menu_no_save_to_load() -> void: +func _on_load_save_menu_no_save_to_load() -> void: #continue_button.hide() - #load_button.hide() - # - #_close_sub_menu() + load_button.hide() + + _close_sub_menu() diff --git a/Script/RGT/load_save_menu.gd b/Script/RGT/load_save_menu.gd new file mode 100644 index 00000000..46aa67ad --- /dev/null +++ b/Script/RGT/load_save_menu.gd @@ -0,0 +1,85 @@ +extends ScrollContainer + +signal no_save_to_load + +const confirm_load = "Are you sure you want to load this save?\n" +const confirm_delete = "Are you sure you want to delete this save ?\n" + +var SavePanel = preload("res://scenes/LoadSaveMenu/savePanelContainer.tscn") + +@onready var vbox_container = $VBoxContainer + +@onready var confirm_dialog = %ConfirmationDialog + +enum Modes{ + Loading, + Deleting +} + +var popup_mode = Modes.Loading +var current_save_file_name:String = "" +var current_save_panel:Node = null + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + if SaveHelper.save_file_names.is_empty(): + SaveHelper.update_save_file_names() + + if SaveHelper.save_file_names.is_empty(): + push_warning("No save to load") + pass + + for save_file_name in SaveHelper.save_file_names: + var save_panel = SavePanel.instantiate() + + vbox_container.add_child(save_panel) + + save_panel.init(save_file_name) + + save_panel.load_button.pressed.connect(_on_load_button_pressed.bind(save_file_name)) + save_panel.delete_button.pressed.connect( + _on_delete_button_pressed.bind(save_panel, save_file_name)) + +func _on_load_button_pressed(save_file_name:String): + popup_mode = Modes.Loading + + current_save_file_name = save_file_name + + confirm_dialog.dialog_text = confirm_load + save_file_name + + confirm_dialog.popup_centered() + +func _on_delete_button_pressed(save_panel:Node, save_file_name:String): + popup_mode = Modes.Deleting + + current_save_file_name = save_file_name + + current_save_panel = save_panel + + confirm_dialog.dialog_text = confirm_delete + save_file_name + + confirm_dialog.popup_centered() + +func _on_confirmation_dialog_confirmed() -> void: + match(popup_mode): + Modes.Loading: + SaveHelper.save_file_name_to_load = current_save_file_name + + SceneLoader.change_scene(RGT_Globals.first_game_scene_setting) + + Modes.Deleting: + SaveHelper.delete(current_save_file_name) + + # move to trash the screenshot + OS.move_to_trash( + ProjectSettings.globalize_path( + SaveHelper.get_save_file_path_without_extension(current_save_file_name) + ".png" + )) + + SaveHelper.update_save_file_names() + + if SaveHelper.save_file_names.is_empty(): + no_save_to_load.emit() + + current_save_panel.queue_free() + diff --git a/Script/RGT/save_panel_container.gd b/Script/RGT/save_panel_container.gd new file mode 100644 index 00000000..4dc6ae59 --- /dev/null +++ b/Script/RGT/save_panel_container.gd @@ -0,0 +1,22 @@ +extends PanelContainer + +@onready var name_label = %NameLabel +@onready var save_texture = %SaveTextureRect +@onready var load_button = %LoadButton +@onready var delete_button = %DeleteButton + +func init(save_name:String): + name_label.text = save_name + + var image_path := SaveHelper.save_dir_path + "/" + save_name + ".png" + + if not FileAccess.file_exists(image_path): + return + + var image := Image.load_from_file(image_path) + + if image == null: + return + + save_texture.texture = ImageTexture.create_from_image(image) + diff --git a/Script/TheBuilder.gd b/Script/TheBuilder.gd new file mode 100644 index 00000000..80b9c369 --- /dev/null +++ b/Script/TheBuilder.gd @@ -0,0 +1,75 @@ +extends Node + +const Buildings_Scenes = { + Buildings.Ids.Warehouse: preload("res://theLudovyc/Building/Warehouse.tscn"), + Buildings.Ids.Tent: preload("res://theLudovyc/Building/Residential.tscn"), + Buildings.Ids.Lumberjack: preload("res://theLudovyc/Building/Lumberjack.tscn") +} + +var warehouse: Building2D + +@onready var node_buildings:Node = %Buildings + +@onready var tilemap:TileMap = %TileMap + +func instantiate_building(building_id: Buildings.Ids) -> Building2D: + if not Buildings_Scenes.has(building_id): + push_error("Cannot instanciate a building with this Id: " + str(building_id)) + + return null + + var instance = Buildings_Scenes[building_id].instantiate() as Building2D + + node_buildings.add_child(instance) + + return instance + +func build(building_id:Buildings.Ids, pos:Vector2) -> Building2D: + var building = instantiate_building(building_id) + + if building == null: + push_error("Cannot create a building from null instance") + + return null + + building.position = pos + + tilemap.conclude_building_construction(building) + + building.build() + return building + +func build_warehouse(pos:Vector2): + warehouse = build(Buildings.Ids.Warehouse, pos) + +func get_buildings_save() -> Dictionary: + var datas:Array + + for child:Building2D in node_buildings.get_children(): + datas.append([child.building_id, child.position.x, child.position.y]) + + return {"Buildings":datas} + +func load_buildings_save() -> Error: + if SaveHelper.last_loaded_data.is_empty(): + return FAILED + + var buildings_data:Array = SaveHelper.last_loaded_data.get("Buildings", []) + + if buildings_data.is_empty(): + return FAILED + + for building_data in SaveHelper.last_loaded_data["Buildings"]: + var building = build(building_data[0], + Vector2(building_data[1], building_data[2])) + + if build(building_data[0], + Vector2(building_data[1], building_data[2])) == null: + # TODO handle error with a popup and return to MainMenu + + pass + + if building_data[0] == 0: + warehouse = building + + return OK diff --git a/theLudovyc/EventBus.gd b/theLudovyc/EventBus.gd index 1316c5e0..2539cdfc 100644 --- a/theLudovyc/EventBus.gd +++ b/theLudovyc/EventBus.gd @@ -32,6 +32,7 @@ signal money_production_rate_updated(money_production_rate) ## ORDER signal ask_create_new_order(resource_type) signal send_create_new_order(resource_type) +signal send_create_new_order_with_values(resource_type, buy_amount, sell_amount) signal ask_remove_order(resource_type) signal send_remove_order(resource_type) diff --git a/theLudovyc/GUI/MarketContainer.gd b/theLudovyc/GUI/MarketContainer.gd index ee6627fe..c73233be 100644 --- a/theLudovyc/GUI/MarketContainer.gd +++ b/theLudovyc/GUI/MarketContainer.gd @@ -20,6 +20,7 @@ func _ready(): event_bus = current_scene.get_node("EventBus") as EventBus event_bus.send_create_new_order.connect(_on_receive_create_new_order) + event_bus.send_create_new_order_with_values.connect(_on_receive_create_new_order_with_values) event_bus.send_remove_order.connect(_on_receive_remove_order) event_bus.send_update_order_buy.connect(_on_receive_update_order_buy) event_bus.money_production_rate_updated.connect(_on_receive_money_production_rate_updated) @@ -44,6 +45,17 @@ func _on_receive_create_new_order(resource_type: Resources.Types): order_nodes[resource_type] = resource_order +func _on_receive_create_new_order_with_values(resource_type: Resources.Types, + buy_amount:int, sell_amount:int): + var resource_order = resource_order_scene.instantiate() + + order_container.add_child(resource_order) + + resource_order._resource_type = resource_type + resource_order.force_buy_value(buy_amount) + resource_order.force_sell_value(sell_amount) + + order_nodes[resource_type] = resource_order func _on_receive_remove_order(resource_type: Resources.Types): order_nodes[resource_type].queue_free() diff --git a/theLudovyc/GUI/ResourceOrder.gd b/theLudovyc/GUI/ResourceOrder.gd index 9e7befa2..92333bd0 100644 --- a/theLudovyc/GUI/ResourceOrder.gd +++ b/theLudovyc/GUI/ResourceOrder.gd @@ -5,6 +5,7 @@ var event_bus: EventBus = null @onready var _resource_texture = $VBoxContainer/TextureRect @onready var buy_spin_box = $BuySpinBox +@onready var sell_spin_box = $SellSpinBox @onready var delete_button = $VBoxContainer/DeleteButton @@ -41,6 +42,8 @@ func _on_SellSpinBox_value_changed(value): if event_bus != null: event_bus.ask_update_order_sell.emit(_resource_type, value) +func force_sell_value(sell_amount:int): + sell_spin_box.set_value_no_signal(sell_amount) func _on_DeleteButton_pressed(): delete_button.disabled = true diff --git a/theLudovyc/Game2D.gd b/theLudovyc/Game2D.gd index e0d77173..c6a0feb0 100644 --- a/theLudovyc/Game2D.gd +++ b/theLudovyc/Game2D.gd @@ -7,23 +7,19 @@ class_name Game2D @onready var cam := $Camera2D -@onready var node_entities := %Entities +@onready var node_buildings := %Buildings -@onready var the_storage := $TheStorage -@onready var the_bank := $TheBank @onready var event_bus := $EventBus +@onready var the_storage := $TheStorage +@onready var the_bank := $TheBank @onready var the_factory := $TheFactory +@onready var the_market := $TheMarket +@onready var the_builder := $TheBuilder @onready var gui := $GUI @onready var pause_menu := %PauseMenu -const Buildings_Scenes = { - Buildings.Ids.Warehouse: preload("res://theLudovyc/Building/Warehouse.tscn"), - Buildings.Ids.Tent: preload("res://theLudovyc/Building/Residential.tscn"), - Buildings.Ids.Lumberjack: preload("res://theLudovyc/Building/Lumberjack.tscn") -} - const Trees_Destroy_Cost = 1 # if not null follow the cursor @@ -37,42 +33,55 @@ var population := 0: event_bus.population_updated.emit(value) event_bus.available_workers_updated.emit(population - the_factory.workers) -var warehouse: Building2D - var current_selected_building: Building2D = null # Called when the node enters the scene tree for the first time. func _ready(): tm.create_island("res://theLudovyc/singularity_40.json") - - # spawn the warehouse - warehouse = instantiate_building(Buildings.Ids.Warehouse) - - var warehouse_center_tile = Vector2i(1, 20) - - warehouse.position = tm.ground_layer.map_to_local(warehouse_center_tile) - - tm.build_entityStatic(warehouse, warehouse_center_tile) - - warehouse.build() - + # set camera limits var pos_limits = tm.get_pos_limits() cam.pos_limit_top_left = pos_limits[0] cam.pos_limit_bot_right = pos_limits[1] + + var warehouse_pos = Vector2.ZERO + + if SaveHelper.save_file_name_to_load.is_empty(): + the_builder.build_warehouse(Vector2(704, 320)) + + # add some initial resources + the_bank.money = 100 + the_storage.add_resource(Resources.Types.Wood, 2) + the_storage.add_resource(Resources.Types.Textile, 16) + + elif SaveHelper.load_saved_file_name() == OK: + if SaveHelper.last_loaded_data.is_empty(): + return + + var game_data:Dictionary = SaveHelper.last_loaded_data.get("Game", {}) + + if game_data.is_empty(): + return + + population = game_data["population"] + + the_storage.load_storage_save() + the_bank.load_bank_save() + the_factory.load_factory_save() + the_market.load_market_save() + the_builder.load_buildings_save() + else: + # save cannot be loaded + # TODO show popup and return to main menu + return + # force camera initial pos on warehouse - cam.position = warehouse.global_position + cam.position = the_builder.warehouse.global_position cam.reset_smoothing() - # add some initial resources - the_bank.money = 100 - - the_storage.add_resource(Resources.Types.Wood, 2) - the_storage.add_resource(Resources.Types.Textile, 16) - pass # Replace with function body. @@ -200,20 +209,8 @@ func _process(delta): cursor_entity = null -func instantiate_building(building_id: Buildings.Ids) -> Building2D: - var instance = Buildings_Scenes[building_id].instantiate() as Building2D - - node_entities.add_child(instance) - - # TODO - #instance.selected.connect(_on_building_selected) - - return instance - - func _on_EventBus_ask_create_building(building_id: Buildings.Ids): - var entity := instantiate_building(building_id) - cursor_entity = entity + cursor_entity = the_builder.instantiate_building(building_id) cursor_entity_wait_release = true cursor_entity.modulate = Color(Color.RED, 0.6) @@ -229,9 +226,9 @@ func _on_EventBus_ask_deselect_building(): func _on_EventBus_ask_select_warehouse(): - current_selected_building = warehouse + current_selected_building = the_builder.warehouse - warehouse.select() + the_builder.warehouse.select() func _on_EventBus_ask_demolish_current_building(): @@ -260,3 +257,16 @@ func _on_EventBus_ask_demolish_current_building(): current_selected_building = null event_bus.send_current_building_demolished.emit() + +func _on_PauseMenu_ask_to_save() -> void: + var dicoToSave := { + "Game": {"population":population} + } + + dicoToSave.merge(the_storage.get_storage_save()) + dicoToSave.merge(the_bank.get_bank_save()) + dicoToSave.merge(the_factory.get_factory_save()) + dicoToSave.merge(the_market.get_market_save()) + dicoToSave.merge(the_builder.get_buildings_save()) + + pause_menu.save_this_please(dicoToSave) diff --git a/theLudovyc/Game2D.tscn b/theLudovyc/Game2D.tscn index b5291613..bb130f43 100644 --- a/theLudovyc/Game2D.tscn +++ b/theLudovyc/Game2D.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=17 format=3 uid="uid://bbbuj3ne5rupv"] +[gd_scene load_steps=18 format=3 uid="uid://bbbuj3ne5rupv"] [ext_resource type="Script" path="res://theLudovyc/Game2D.gd" id="1_i3wk0"] [ext_resource type="Script" path="res://theLudovyc/EventBus.gd" id="2_jbfdl"] @@ -11,6 +11,7 @@ [ext_resource type="Script" path="res://theLudovyc/Camera2D.gd" id="5_7hgfn"] [ext_resource type="PackedScene" uid="uid://b3s7eqy0blp6g" path="res://theLudovyc/GUI/GUI.tscn" id="6_lovin"] [ext_resource type="Script" path="res://theLudovyc/TheTicker.gd" id="7_41bva"] +[ext_resource type="Script" path="res://Script/TheBuilder.gd" id="7_gnc51"] [ext_resource type="TileSet" uid="uid://bhin7dsw4tvvl" path="res://theLudovyc/new_tile_set.tres" id="11_gqnmu"] [ext_resource type="TileSet" uid="uid://dprvpcto8mhgv" path="res://theLudovyc/tile_set_trees.tres" id="12_25naw"] [ext_resource type="Script" path="res://Script/World/GroundLayer.gd" id="12_dmqkb"] @@ -35,6 +36,9 @@ script = ExtResource("3_6uk0m") [node name="TheMarket" type="Node" parent="."] script = ExtResource("4_gvgis") +[node name="TheBuilder" type="Node" parent="."] +script = ExtResource("7_gnc51") + [node name="TheTicker" type="Timer" parent="."] wait_time = 2.0 autostart = true @@ -70,7 +74,7 @@ y_sort_enabled = true tile_set = ExtResource("12_25naw") script = ExtResource("14_wtd65") -[node name="Entities" type="Node2D" parent="ZSorter"] +[node name="Buildings" type="Node2D" parent="ZSorter"] unique_name_in_owner = true z_index = 1 y_sort_enabled = true @@ -100,3 +104,4 @@ unique_name_in_owner = true [connection signal="cycle" from="TheTicker" to="TheMarket" method="_on_TheTicker_cycle"] [connection signal="tick" from="TheTicker" to="TheFactory" method="_on_TheTicker_tick"] [connection signal="timeout" from="TheTicker" to="TheTicker" method="_on_timeout"] +[connection signal="ask_to_save" from="GUI/PauseMenu" to="." method="_on_PauseMenu_ask_to_save"] diff --git a/theLudovyc/TheBank.gd b/theLudovyc/TheBank.gd index 1da2df8b..e1874114 100644 --- a/theLudovyc/TheBank.gd +++ b/theLudovyc/TheBank.gd @@ -81,3 +81,20 @@ func recalculate_orders_cost(): tmp_orders_cost += resource_cost * order.sell_amount orders_cost = tmp_orders_cost + +func get_bank_save() -> Dictionary: + return {"Money": [money, money_production_rate]} + +func load_bank_save() -> Error: + if SaveHelper.last_loaded_data.is_empty(): + return FAILED + + var bank_data:Array = SaveHelper.last_loaded_data.get("Money", []) + + if bank_data.is_empty(): + return FAILED + + money = bank_data[0] + money_production_rate = bank_data[1] + + return OK diff --git a/theLudovyc/TheFactory.gd b/theLudovyc/TheFactory.gd index ed039513..5a8b0346 100644 --- a/theLudovyc/TheFactory.gd +++ b/theLudovyc/TheFactory.gd @@ -6,7 +6,7 @@ class_name TheFactory @onready var event_bus = $"../EventBus" enum Production_Line { current_workers, production_rate, current_ticks } -var production_lines = {} +var production_lines := {} var workers := 0: set(value): @@ -14,7 +14,7 @@ var workers := 0: event_bus.available_workers_updated.emit(game.population - workers) enum Waiting_Lines { resource_type, needed_workers } -var waiting_lines = [] +var waiting_lines := [] func get_production_rate_per_tick(resource_type: Resources.Types) -> int: @@ -158,3 +158,33 @@ func _on_TheTicker_tick(): line[Production_Line.current_ticks] = 0 storage.add_resource(resource_type, line[Production_Line.production_rate]) + +func get_factory_save() -> Dictionary: + return {"Factory":[workers, production_lines, waiting_lines]} + +func load_factory_save() -> Error: + if SaveHelper.last_loaded_data.is_empty(): + return FAILED + + var factory_data:Array = SaveHelper.last_loaded_data.get("Factory", []) + + if factory_data.is_empty(): + return FAILED + + workers = factory_data[0] + + waiting_lines = factory_data[2] + + for line:String in factory_data[1]: + var resource_type:int = line.to_int() + + if not Resources.Types.values().has(resource_type): + push_error("Cannot create a production line from an unknow resource type: " + line) + + continue + + production_lines[resource_type] = factory_data[1][line] + + storage.update_global_production_rate(resource_type) + + return OK diff --git a/theLudovyc/TheMarket.gd b/theLudovyc/TheMarket.gd index 0311ba23..77c2c156 100644 --- a/theLudovyc/TheMarket.gd +++ b/theLudovyc/TheMarket.gd @@ -9,8 +9,14 @@ class Order: var buy_amount := 0 var sell_amount := 0 + func _to_json() -> Array: + return [buy_amount, sell_amount] + + func _from_json(data:Array): + buy_amount = data[0] + sell_amount = data[1] -var orders = {} +var orders := {} func _ready(): @@ -99,3 +105,46 @@ func _on_TheTicker_cycle(): if the_storage.try_to_sell_resource(order_key, order.sell_amount): the_bank.conclude_sale(order_key, order.sell_amount) + +func get_market_save() -> Dictionary: + var data_to_save := {} + + for resource_type in orders: + var order = orders[resource_type] + + data_to_save[resource_type] = order._to_json() + + return {"Market": data_to_save} + +func load_market_save() -> Error: + if SaveHelper.last_loaded_data.is_empty(): + return FAILED + + var market_data:Dictionary = SaveHelper.last_loaded_data.get("Market", {}) + + if market_data.is_empty(): + return FAILED + + for resource_type_str in market_data: + var resource_type:int = resource_type_str.to_int() + + if not Resources.Types.values().has(resource_type): + push_error("Cannot create a production line \ + from an unknow resource type: " + resource_type_str) + + continue + + var order = Order.new() + order._from_json(market_data[resource_type_str]) + + orders[resource_type] = order + + if event_bus != null: + event_bus.send_create_new_order_with_values.emit( + resource_type, order.buy_amount, order.sell_amount) + + the_storage.update_global_production_rate(resource_type) + + the_bank.recalculate_orders_cost() + + return OK diff --git a/theLudovyc/TheStorage.gd b/theLudovyc/TheStorage.gd index c4845ebd..6522576c 100644 --- a/theLudovyc/TheStorage.gd +++ b/theLudovyc/TheStorage.gd @@ -1,7 +1,7 @@ extends Node class_name TheStorage -var storage = {} +var storage := {} @onready var event_bus = $"../EventBus" @@ -91,3 +91,20 @@ func recover_building_construction(building_id: Buildings.Ids): for cost in building_cost: add_resource(cost[0], cost[1]) + +func get_storage_save() -> Dictionary: + return {"Storage":storage} + +func load_storage_save() -> Error: + if SaveHelper.last_loaded_data.is_empty(): + return FAILED + + var storage_data:Dictionary = SaveHelper.last_loaded_data.get("Storage", {}) + + if storage_data.is_empty(): + return FAILED + + for resource_type_str:String in storage_data: + add_resource(resource_type_str.to_int(), storage_data[resource_type_str]) + + return OK diff --git a/theLudovyc/TileMap.gd b/theLudovyc/TileMap.gd index 78820305..b5307ff9 100644 --- a/theLudovyc/TileMap.gd +++ b/theLudovyc/TileMap.gd @@ -66,6 +66,9 @@ func build_entityStatic(entity:EntityStatic, tile_center:Vector2i): trees_layer.erase_cell(tile_coord) minimap_set_cell_vec(tile_coord, Minimap_Cell_Type.Building) + +func conclude_building_construction(building:Building2D): + build_entityStatic(building, ground_layer.local_to_map(building.position)) func demolish_building(building:Building2D): var top_left_tile = entityStatic_get_top_left_tile(building, @@ -138,7 +141,3 @@ func get_pos_limits() -> PackedVector2Array: func local_to_map_to_local(position:Vector2) -> Vector2: return map_to_local(local_to_map(position)) - -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): - pass