From 1a82237da71c468f47e244b6f3913b2d74d361bc Mon Sep 17 00:00:00 2001 From: BrickPi Date: Mon, 4 Nov 2024 16:33:44 -0600 Subject: [PATCH] Implement the Technology Menu --- extension/deps/openvic-simulation | 2 +- extension/doc_classes/MenuSingleton.xml | 38 +++ .../singletons/GameSingleton.cpp | 16 +- .../singletons/GameSingleton.hpp | 4 +- .../singletons/MenuSingleton.cpp | 42 ++- .../singletons/MenuSingleton.hpp | 16 +- .../singletons/TechnologyMenu.cpp | 176 +++++++++++ .../NationManagementScreen/TechnologyMenu.gd | 275 +++++++++++++++++- 8 files changed, 546 insertions(+), 23 deletions(-) create mode 100644 extension/src/openvic-extension/singletons/TechnologyMenu.cpp diff --git a/extension/deps/openvic-simulation b/extension/deps/openvic-simulation index 91d7b0a9..668daa1e 160000 --- a/extension/deps/openvic-simulation +++ b/extension/deps/openvic-simulation @@ -1 +1 @@ -Subproject commit 91d7b0a9c7319a2d144efcec4d846bb5fdaa4c37 +Subproject commit 668daa1e4bea66cfba569c83fc5fe0f6e6abe4fe diff --git a/extension/doc_classes/MenuSingleton.xml b/extension/doc_classes/MenuSingleton.xml index b96d465d..8a290731 100644 --- a/extension/doc_classes/MenuSingleton.xml +++ b/extension/doc_classes/MenuSingleton.xml @@ -155,14 +155,46 @@ + + + + + Returns the effects, point cost, unlock year, and prerequisite tech of the given technology, in a [Dictionary]. + + + + + + Returns a [Dictionary] with static defines for the technology menu. + + + + + + Returns a [Dictionary] with the dynamic state of the technology menu. + + + + + + Returns the colored symbol used by met tooltip conditions "(*)" + + + + + + Returns the colored symbol used by unmet tooltip conditions "(X)" + + + Returns the symbol used to separate normal and extended tooltips. @@ -270,6 +302,12 @@ + + + + + + diff --git a/extension/src/openvic-extension/singletons/GameSingleton.cpp b/extension/src/openvic-extension/singletons/GameSingleton.cpp index 37418c3a..ec4cc038 100644 --- a/extension/src/openvic-extension/singletons/GameSingleton.cpp +++ b/extension/src/openvic-extension/singletons/GameSingleton.cpp @@ -12,6 +12,7 @@ #include "openvic-extension/singletons/MenuSingleton.hpp" #include "openvic-extension/utility/ClassBindings.hpp" #include "openvic-extension/utility/Utilities.hpp" +#include "openvic-simulation/country/CountryInstance.hpp" using namespace godot; using namespace OpenVic; @@ -179,17 +180,6 @@ Error GameSingleton::setup_game(int32_t bookmark_index) { set_viewed_country(starting_country); ERR_FAIL_NULL_V(viewed_country, FAILED); - // TODO - remove this test starting research - for ( - Technology const& technology : - get_definition_manager().get_research_manager().get_technology_manager().get_technologies() - ) { - if (starting_country->can_research_tech(technology, instance_manager->get_today())) { - starting_country->start_research(technology, *instance_manager); - break; - } - } - return ERR(ret); } @@ -425,7 +415,7 @@ void GameSingleton::unset_selected_province() { set_selected_province(ProvinceDefinition::NULL_INDEX); } -void GameSingleton::set_viewed_country(CountryInstance const* new_viewed_country) { +void GameSingleton::set_viewed_country(CountryInstance* new_viewed_country) { if (viewed_country != new_viewed_country) { viewed_country = new_viewed_country; @@ -439,7 +429,7 @@ void GameSingleton::set_viewed_country_by_province_index(int32_t province_index) InstanceManager* instance_manager = get_instance_manager(); ERR_FAIL_NULL(instance_manager); - ProvinceInstance const* province_instance = + ProvinceInstance* province_instance = instance_manager->get_map_instance().get_province_instance_by_index(province_index); ERR_FAIL_NULL(province_instance); diff --git a/extension/src/openvic-extension/singletons/GameSingleton.hpp b/extension/src/openvic-extension/singletons/GameSingleton.hpp index 653d712b..c08c3459 100644 --- a/extension/src/openvic-extension/singletons/GameSingleton.hpp +++ b/extension/src/openvic-extension/singletons/GameSingleton.hpp @@ -15,7 +15,7 @@ namespace OpenVic { GameManager game_manager; - CountryInstance const* PROPERTY(viewed_country, nullptr); + CountryInstance* PROPERTY_PTR(viewed_country, nullptr); godot::Vector2i image_subdivisions; godot::Ref province_shape_texture; @@ -133,7 +133,7 @@ namespace OpenVic { void set_selected_province(int32_t index); void unset_selected_province(); - void set_viewed_country(CountryInstance const* new_viewed_country); + void set_viewed_country(CountryInstance* new_viewed_country); void set_viewed_country_by_province_index(int32_t province_index); godot::Vector2 get_viewed_country_capital_position() const; diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.cpp b/extension/src/openvic-extension/singletons/MenuSingleton.cpp index 20460979..5539ebbf 100644 --- a/extension/src/openvic-extension/singletons/MenuSingleton.cpp +++ b/extension/src/openvic-extension/singletons/MenuSingleton.cpp @@ -1,16 +1,27 @@ #include "MenuSingleton.hpp" +#include +#include +#include +#include + #include +#include +#include -#include #include #include +#include +#include +#include +#include +#include "openvic-extension/classes/GUILabel.hpp" +#include "openvic-extension/utility/Utilities.hpp" #include "openvic-extension/classes/GFXPieChartTexture.hpp" #include "openvic-extension/classes/GUINode.hpp" #include "openvic-extension/singletons/GameSingleton.hpp" #include "openvic-extension/utility/ClassBindings.hpp" -#include "openvic-extension/utility/Utilities.hpp" using namespace godot; using namespace OpenVic; @@ -167,13 +178,17 @@ String MenuSingleton::_make_modifier_effect_value_coloured( return result; } +String MenuSingleton::_make_modifier_effect_tooltip(ModifierEffect const& effect, const fixed_point_t value) const { + return tr(Utilities::std_to_godot_string(effect.get_localisation_key())) + ": " + + _make_modifier_effect_value_coloured(effect, value, true); +} + String MenuSingleton::_make_modifier_effects_tooltip(ModifierValue const& modifier) const { String result; for (auto const& [effect, value] : modifier.get_values()) { if (value != fixed_point_t::_0()) { - result += "\n" + tr(Utilities::std_to_godot_string(effect->get_localisation_key())) + ": " + - _make_modifier_effect_value_coloured(*effect, value, true); + result += "\n" + _make_modifier_effect_tooltip(*effect, value); } } @@ -315,6 +330,9 @@ String MenuSingleton::_make_mobilisation_impact_tooltip() const { void MenuSingleton::_bind_methods() { OV_BIND_SMETHOD(get_tooltip_separator); + OV_BIND_SMETHOD(get_tooltip_condition_met); + OV_BIND_SMETHOD(get_tooltip_condition_unmet); + OV_BIND_METHOD(MenuSingleton::get_country_name_from_identifier, { "country_identifier" }); OV_BIND_METHOD(MenuSingleton::get_country_adjective_from_identifier, { "country_identifier" }); @@ -441,6 +459,12 @@ void MenuSingleton::_bind_methods() { OV_BIND_METHOD(MenuSingleton::get_search_result_position, { "result_index" }); ADD_SIGNAL(MethodInfo(_signal_search_cache_changed())); + + /* TECHNOLOGY MENU */ + OV_BIND_METHOD(MenuSingleton::get_technology_menu_defines); + OV_BIND_METHOD(MenuSingleton::get_technology_menu_info); + OV_BIND_METHOD(MenuSingleton::get_specific_technology_info, { "technology_id" }); + OV_BIND_METHOD(MenuSingleton::start_research, { "technology_id" }); } MenuSingleton* MenuSingleton::get_singleton() { @@ -465,6 +489,16 @@ String MenuSingleton::get_tooltip_separator() { return tooltip_separator; } +String MenuSingleton::get_tooltip_condition_met() { + static const String condition_met = String { "(" } + GUILabel::get_colour_marker() + String { "G*" } + GUILabel::get_colour_marker() + "W)"; + return condition_met; +} + +String MenuSingleton::get_tooltip_condition_unmet() { + static const String condition_unmet = String { "(" } + GUILabel::get_colour_marker() + String { "RX" } + GUILabel::get_colour_marker() + "W)"; + return condition_unmet; +} + String MenuSingleton::get_country_name_from_identifier(String const& country_identifier) const { if (country_identifier.is_empty()) { return {}; diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.hpp b/extension/src/openvic-extension/singletons/MenuSingleton.hpp index 2623b2e8..728a0ad7 100644 --- a/extension/src/openvic-extension/singletons/MenuSingleton.hpp +++ b/extension/src/openvic-extension/singletons/MenuSingleton.hpp @@ -1,14 +1,16 @@ #pragma once -#include - #include #include +#include #include #include #include #include +#include +#include +#include namespace OpenVic { struct CountryInstance; @@ -148,6 +150,7 @@ namespace OpenVic { ModifierEffect const& format_effect, fixed_point_t value, bool plus_for_non_negative ); + godot::String _make_modifier_effect_tooltip(ModifierEffect const& effect, const fixed_point_t value) const; godot::String _make_modifier_effects_tooltip(ModifierValue const& modifier) const; template @@ -172,6 +175,9 @@ namespace OpenVic { ~MenuSingleton(); static godot::String get_tooltip_separator(); + static godot::String get_tooltip_condition_met(); + static godot::String get_tooltip_condition_unmet(); + godot::String get_country_name_from_identifier(godot::String const& country_identifier) const; godot::String get_country_adjective_from_identifier(godot::String const& country_identifier) const; @@ -237,6 +243,12 @@ namespace OpenVic { /* Array of GFXPieChartTexture::godot_pie_chart_data_t. */ godot::TypedArray get_population_menu_distribution_info() const; + /* TECHNOLOGY MENU */ + godot::Dictionary get_technology_menu_defines() const; + godot::Dictionary get_technology_menu_info() const; + godot::Dictionary get_specific_technology_info(godot::String technology_id) const; + void start_research(godot::String technology_id); // TODO: move to PlayerSingleton + /* TRADE MENU */ godot::Dictionary get_trade_menu_good_categories_info() const; godot::Dictionary get_trade_menu_trade_details_info(int32_t trade_detail_good_index) const; diff --git a/extension/src/openvic-extension/singletons/TechnologyMenu.cpp b/extension/src/openvic-extension/singletons/TechnologyMenu.cpp new file mode 100644 index 00000000..919c22ac --- /dev/null +++ b/extension/src/openvic-extension/singletons/TechnologyMenu.cpp @@ -0,0 +1,176 @@ +#include "MenuSingleton.hpp" +#include "godot_cpp/variant/typed_array.hpp" +#include "openvic-simulation/research/Technology.hpp" + +#include +#include +#include + +#include + +#include "openvic-extension/singletons/GameSingleton.hpp" +#include "openvic-extension/utility/Utilities.hpp" + +using namespace OpenVic; +using namespace godot; + +/* TECHNOLOGY MENU */ +Dictionary MenuSingleton::get_technology_menu_defines() const { + GameSingleton const* game_singleton = GameSingleton::get_singleton(); + ERR_FAIL_NULL_V(game_singleton, {}); + + static const StringName tech_folders_key = "tech_folders"; + static const StringName tech_areas_key = "tech_areas"; + static const StringName technologies_key = "technologies"; + static const StringName folder_tech_count_key = "folder_tech_count"; + + Dictionary ret; + + std::vector const& tech_folders = game_singleton->get_definition_manager().get_research_manager().get_technology_manager().get_technology_folders(); + + PackedStringArray tech_folder_identifiers {}; + TypedArray tech_area_identifiers {}; + Array tech_identifiers {}; + PackedInt32Array folder_tech_count {}; + for (TechnologyFolder const& folder : tech_folders) { + tech_folder_identifiers.push_back(Utilities::std_to_godot_string(folder.get_identifier())); + int32_t num_in_folder = 0; + + PackedStringArray folder_areas {}; + Array tech_folder_nested_array {}; // tech_identifiers has three levels of nested arrays :P + for (TechnologyArea const* area : folder.get_technology_areas()) { + folder_areas.push_back(Utilities::std_to_godot_string(area->get_identifier())); + + PackedStringArray area_technologies {}; + for (Technology const* tech : area->get_technologies()) { + area_technologies.push_back(Utilities::std_to_godot_string(tech->get_identifier())); + num_in_folder++; + } + tech_folder_nested_array.push_back(std::move(area_technologies)); + } + tech_area_identifiers.push_back(std::move(folder_areas)); + tech_identifiers.push_back(std::move(tech_folder_nested_array)); + folder_tech_count.push_back(num_in_folder); + } + ret[tech_folders_key] = std::move(tech_folder_identifiers); + ret[tech_areas_key] = std::move(tech_area_identifiers); + ret[technologies_key] = std::move(tech_identifiers); + ret[folder_tech_count_key] = std::move(folder_tech_count); + + return ret; +} + +Dictionary MenuSingleton::get_technology_menu_info() const { + GameSingleton const* game_singleton = GameSingleton::get_singleton(); + ERR_FAIL_NULL_V(game_singleton, {}); + TechnologyManager const& tech_manager = game_singleton->get_definition_manager().get_research_manager().get_technology_manager(); + + static const StringName tech_school_key = "tech_school"; + static const StringName tech_school_mod_values = "tech_school_mod_values"; + static const StringName tech_school_mod_icons = "tech_school_mod_icons"; + static const StringName tech_school_mod_tt = "tech_school_mod_tt"; + + static const StringName researched_technologies_key = "researched_technologies"; + static const StringName researchable_technologies_key = "researchable_technologies"; + + static const StringName current_research_tech = "current_research_tech"; + static const StringName current_research_cat = "current_research_cat"; + static const StringName current_research_finish_date = "current_research_finish_date"; + static const StringName current_research_invested = "current_research_invested"; + static const StringName current_research_cost = "current_research_cost"; + static const StringName current_research_effect_tt = "current_research_effect_tt"; + static const StringName current_research_progress = "current_research_progress"; + + Dictionary ret; + + CountryInstance const* country = game_singleton->get_viewed_country(); + if (country == nullptr) { + return ret; + } + + TechnologySchool const* tech_school = country->get_tech_school(); + if (tech_school == nullptr) { + tech_school = tech_manager.get_technology_school_by_index(0); + } + if (tech_school != nullptr) { + ret[tech_school_key] = Utilities::std_to_godot_string(tech_school->get_identifier()); + PackedFloat32Array school_modifier_values; + PackedInt32Array school_modifier_icons; + PackedStringArray school_modifier_tt; + for (auto const& [tech_folder, research_bonus_effect] : game_singleton->get_definition_manager().get_modifier_manager().get_modifier_effect_cache().get_research_bonus_effects()) { + const fixed_point_t research_bonus_value = tech_school->get_effect(*research_bonus_effect); + if (research_bonus_value != fixed_point_t::_0()) { + school_modifier_values.push_back(research_bonus_value.to_float()); + school_modifier_icons.push_back(1 + tech_folder.get_index()); + school_modifier_tt.push_back(_make_modifier_effect_tooltip(*research_bonus_effect, research_bonus_value)); + } + } + ret[tech_school_mod_values] = std::move(school_modifier_values); + ret[tech_school_mod_icons] = std::move(school_modifier_icons); + ret[tech_school_mod_tt] = std::move(school_modifier_tt); + } + + PackedStringArray researched_technologies {}; + PackedStringArray researchable_technologies {}; + for (Technology const& tech : tech_manager.get_technologies()) { + if (country->is_technology_unlocked(tech)) { + researched_technologies.push_back(Utilities::std_to_godot_string(tech.get_identifier())); + } + if (country->can_research_tech(tech, game_singleton->get_instance_manager()->get_today())) { + researchable_technologies.push_back(Utilities::std_to_godot_string(tech.get_identifier())); + } + } + ret[researched_technologies_key] = std::move(researched_technologies); + ret[researchable_technologies_key] = std::move(researchable_technologies); + + Technology const* current_research = country->get_current_research(); + if (current_research != nullptr) { + ret[current_research_tech] = Utilities::std_to_godot_string(current_research->get_identifier()); + ret[current_research_cat] = tr(Utilities::std_to_godot_string(current_research->get_area().get_folder().get_identifier())) + ", " + tr(Utilities::std_to_godot_string(current_research->get_area().get_identifier())); + ret[current_research_finish_date] = Utilities::date_to_string(country->get_expected_research_completion_date()); + ret[current_research_invested] = country->get_invested_research_points().to_int32_t(); + ret[current_research_cost] = country->get_current_research_cost().to_int32_t(); + ret[current_research_effect_tt] = _make_modifier_effects_tooltip(*current_research).trim_prefix("\n"); + ret[current_research_progress] = country->get_research_progress().to_float(); + } + + return ret; +} + +Dictionary MenuSingleton::get_specific_technology_info(String technology_id) const { + GameSingleton const* game_singleton = GameSingleton::get_singleton(); + ERR_FAIL_NULL_V(game_singleton, {}); + + static const StringName effect_tooltip_key = "effects"; + static const StringName research_points_key = "research_points"; + static const StringName start_year_key = "start_year"; + static const StringName prerequisite_key = "prerequisite"; + + Dictionary ret; + + Technology const* technology = game_singleton->get_definition_manager().get_research_manager().get_technology_manager().get_technology_by_identifier(Utilities::godot_to_std_string(technology_id)); + CountryInstance const* viewed_country = game_singleton->get_viewed_country(); + if (technology == nullptr || viewed_country == nullptr) { + return ret; + } + + ret[effect_tooltip_key] = _make_modifier_effects_tooltip(*technology).trim_prefix("\n"); + ret[research_points_key] = viewed_country->calculate_research_cost(*technology, game_singleton->get_definition_manager().get_modifier_manager().get_modifier_effect_cache()).to_int32_t(); + ret[start_year_key] = technology->get_year(); + if (technology->get_index_in_area() > 0) { + ret[prerequisite_key] = Utilities::std_to_godot_string(technology->get_area().get_technologies()[technology->get_index_in_area() - 1]->get_identifier()); + } + + return ret; +} + +void MenuSingleton::start_research(String technology_id) { + GameSingleton* game_singleton = GameSingleton::get_singleton(); + ERR_FAIL_NULL(game_singleton); + + CountryInstance* viewed_country = game_singleton->get_viewed_country(); + Technology const* technology = game_singleton->get_definition_manager().get_research_manager().get_technology_manager().get_technology_by_identifier(Utilities::godot_to_std_string(technology_id)); + if (technology == nullptr || viewed_country == nullptr) { return; } + + viewed_country->start_research(*technology, *game_singleton->get_instance_manager()); +} \ No newline at end of file diff --git a/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd b/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd index 8386fef3..797dd5d5 100644 --- a/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd +++ b/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd @@ -4,6 +4,35 @@ var _active : bool = false const _screen : NationManagement.Screen = NationManagement.Screen.TECHNOLOGY +var _tech_defines : Dictionary = MenuSingleton.get_technology_menu_defines() + +var _tech_folders : PackedStringArray +var _tech_areas : Array[PackedStringArray] +var _technologies : Array +var _folder_tech_counts : PackedInt32Array + +var _tech_folder_buttons : Array[GUIIconButton] +var _tech_folder_progressbars : Array[GUIProgressBar] +var _tech_folder_number_discovered_labels : Array[GUILabel] + +var _tech_school : GUILabel +var _tech_school_modifiers : GUIOverlappingElementsBox +var _current_research_label : GUILabel +var _current_research_cat_label : GUILabel +var _current_research_progressbar : GUIProgressBar + +var _selected_tech_picture : GUIIcon +var _selected_tech_label : GUILabel +var _selected_tech_effects : GUILabel +var _selected_tech_research_points : GUILabel +var _selected_tech_unlock_year : GUILabel + +var _start_research_button : GUIIconButton + +var _selected_folder = 0 +var _selected_technology : String +var _selected_technology_info : Dictionary + func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) @@ -13,12 +42,145 @@ func _ready() -> void: set_click_mask_from_nodepaths([^"./country_technology/main_bg"]) + # TECHNOLOGY SCHOOLS + _tech_school = get_gui_label_from_nodepath(^"./country_technology/administration_type") + _tech_school_modifiers = get_gui_overlapping_elements_box_from_nodepath(^"./country_technology/school_bonus_icons") + if _tech_school_modifiers: + _tech_school_modifiers.set_gui_child_element_name("country_technology", "school_icon_window") + + # CURRENT RESEARCH PROGRESSBAR + _current_research_label = get_gui_label_from_nodepath(^"./country_technology/research_progress_name") + _current_research_cat_label = get_gui_label_from_nodepath(^"./country_technology/research_progress_category") + _current_research_progressbar = get_gui_progress_bar_from_nodepath(^"./country_technology/research_progress") + + # FOLDERS, AREAS, TECHNOLOGIES + _tech_folders = _tech_defines.get("tech_folders", [] as PackedStringArray) + _tech_areas = _tech_defines.get("tech_areas", [] as Array[PackedStringArray]) + _technologies = _tech_defines.get("technologies", []) + if _technologies.size() > 0 and _technologies[0].size() > 0 and _technologies[0][0].size() > 0 and _technologies[0][0][0]: + _selected_technology = _technologies[0][0][0] + _selected_technology_info = MenuSingleton.get_specific_technology_info(_selected_technology) + _folder_tech_counts = _tech_defines.get("folder_tech_count", 0) + for i : int in _tech_folders.size(): + add_gui_element("country_technology", "folder_window") + + var folder_node : Node = get_node(^"./folder_window") + var root_node : Node = get_node(^"./country_technology") + + folder_node.reparent(root_node) + folder_node.name = _tech_folders[i] + "_folder" + + var pos : Vector2 = GUINode.get_gui_position("country_technology", "folder_offset") + pos.x += folder_node.get_size().x * i + folder_node.set_position(pos) + + var icon : GUIIcon = GUINode.get_gui_icon_from_node(folder_node.get_node(^"./folder_icon")) + if icon: + icon.set_icon_index(i+1) + + var title : GUILabel = GUINode.get_gui_label_from_node(folder_node.get_node(^"./folder_category")) + if title: + title.set_text(_tech_folders[i]) + + var button : GUIIconButton = GUINode.get_gui_icon_button_from_node(folder_node.get_node(^"./folder_button")) + var button_tooltip : String = tr("TECHNOLOGYVIEW_SHOW_FOLDER_TOOLTIP") + var button_dict : Dictionary = { "FOLDER" : _tech_folders[i] } + if button: + if i == 0: + button.set_icon_index(2) + button.pressed.connect( # change selected technology area + func() -> void: + _tech_folder_buttons[_selected_folder].set_icon_index(1) + for x : int in range(_tech_areas[_selected_folder].size()): + root_node.get_node("./" + _tech_areas[_selected_folder][x]).visible = false + _selected_folder = i + button.set_icon_index(2) + for x : int in range(_tech_areas[_selected_folder].size()): + root_node.get_node("./" + _tech_areas[_selected_folder][x]).visible = true + ) + button.set_tooltip_string_and_substitution_dict(button_tooltip, button_dict) + _tech_folder_buttons.push_back(button) + + var progressbar : GUIProgressBar = GUINode.get_gui_progress_bar_from_node(folder_node.get_node(^"./folder_progress")) + if progressbar: + progressbar.mouse_filter = Control.MOUSE_FILTER_IGNORE + _tech_folder_progressbars.push_back(progressbar) + + var discovered : GUILabel = GUINode.get_gui_label_from_node(folder_node.get_node(^"folder_number_discovered")) + if discovered: + _tech_folder_number_discovered_labels.push_back(discovered) + + # areas + var folder_areas : PackedStringArray = _tech_areas[i] + for area_index : int in range(folder_areas.size()): + add_gui_element("country_technology", "tech_group") + + var area_node : Node = get_node(^"./tech_group") + + area_node.reparent(root_node) + area_node.name = folder_areas[area_index] + if i != 0: + area_node.set_visible(false) + + pos = GUINode.get_gui_position("country_technology", "tech_group_offset") + pos.x += area_node.get_size().x * area_index + area_node.set_position(pos) + + var area_title : GUILabel = GUINode.get_gui_label_from_node(area_node.get_node(^"./group_name")) + if area_title: + area_title.set_text(folder_areas[area_index]) + + # technologies + var area_technologies : PackedStringArray = _technologies[i][area_index] + for tech_index : int in range(area_technologies.size()): + add_gui_element("country_technology", "tech_window") + + var tech_node = get_node(^"./tech_window") + + tech_node.reparent(area_node) + tech_node.name = area_technologies[tech_index] + + pos = GUINode.get_gui_position("country_technology", "tech_offset") + pos.y += tech_node.get_size().y * tech_index + tech_node.set_position(pos) + + var tech_name : GUILabel = GUINode.get_gui_label_from_node(tech_node.get_node(^"./tech_name")) + if tech_name: + tech_name.set_text(area_technologies[tech_index]) + + var tech_button : GUIIconButton = GUINode.get_gui_icon_button_from_node(tech_node.get_node(^"./start_research")) + if tech_button: + tech_button.pressed.connect(_on_tech_selected.bind(area_technologies[tech_index])) + + # SELECTED TECH WINDOW + _selected_tech_picture = get_gui_icon_from_nodepath(^"./country_technology/selected_tech_window/picture") + _selected_tech_label = get_gui_label_from_nodepath(^"./country_technology/selected_tech_window/title") + _selected_tech_effects = get_gui_label_from_nodepath(^"./country_technology/selected_tech_window/effect") + _selected_tech_research_points = get_gui_label_from_nodepath(^"./country_technology/selected_tech_window/diff") + _selected_tech_unlock_year = get_gui_label_from_nodepath(^"./country_technology/selected_tech_window/year") + _start_research_button = get_gui_icon_button_from_nodepath(^"./country_technology/selected_tech_window/start") + if _start_research_button: + _start_research_button.pressed.connect( + func() -> void: + MenuSingleton.start_research(_selected_technology) + print("Started Research of " + _selected_technology) + _update_info() + get_parent()._update_info() + ) + + # CLOSE BUTTON var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_technology/close_button") if close_button: close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) _update_info() +func _on_tech_selected(technology_id : String) -> void: + if _selected_technology != technology_id: + _selected_technology = technology_id + _selected_technology_info = MenuSingleton.get_specific_technology_info(_selected_technology) + _update_info() + func _notification(what : int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: @@ -30,7 +192,118 @@ func _on_update_active_nation_management_screen(active_screen : NationManagement func _update_info() -> void: if _active: - # TODO - update UI state + var info : Dictionary = MenuSingleton.get_technology_menu_info() + + if _tech_school: + _tech_school.set_text(info.get("tech_school", "")) + + if _tech_school_modifiers: + var mod_values : PackedFloat32Array = info.get("tech_school_mod_values", PackedFloat32Array()) + var mod_icons : PackedInt32Array = info.get("tech_school_mod_icons", PackedInt32Array()) + var mod_tooltips : PackedStringArray = info.get("tech_school_mod_tt", PackedStringArray()) + var mod_count : int = mod_values.size() + _tech_school_modifiers.set_child_count(mod_count) + for i : int in range(mod_count): + var main_icon : GUIIcon = get_gui_icon_from_nodepath("./country_technology/school_bonus_icons/school_icon_window_{x}/main_icon".format({"x": i})) + main_icon.set_icon_index(mod_icons[i]) + main_icon.mouse_filter = Control.MOUSE_FILTER_PASS + main_icon.set_tooltip_string(mod_tooltips[i]) + var plusminus_icon : GUIIcon = get_gui_icon_from_nodepath("./country_technology/school_bonus_icons/school_icon_window_{x}/plusminus_icon".format({"x": i})) + plusminus_icon.set_icon_index(2 if mod_values[i] > 0 else 1) + plusminus_icon.mouse_filter = Control.MOUSE_FILTER_PASS + plusminus_icon.set_tooltip_string(mod_tooltips[i]) + + var current_research : String = info.get("current_research_tech", "") + if _current_research_label and _current_research_label.text != current_research: + _current_research_label.set_text(current_research if current_research else "TECHNOLOGYVIEW_NO_RESEARCH") + + if _current_research_cat_label: + _current_research_cat_label.set_text(info.get("current_research_cat", "")) + + if _current_research_progressbar: + if current_research != "": + _current_research_progressbar.value = info.get("current_research_progress", 0) + _current_research_progressbar.set_tooltip_string_and_substitution_dict( + tr("TECHNOLOGYVIEW_RESEARCH_TOOLTIP") + "\n" + + tr("TECHNOLOGYVIEW_RESEARCH_INVESTED_TOOLTIP") + + MenuSingleton.get_tooltip_separator() + + info.get("current_research_effect_tt", ""), + { + "TECH": tr(current_research), + "DATE": info.get("current_research_finish_date", "1836.1.1"), + "INVESTED": info.get("current_research_invested", 0), + "COST": info.get("current_research_cost", 0) + } + ) + else: + _current_research_progressbar.value = 0 + _current_research_progressbar.set_tooltip_string(tr("TECHNOLOGYVIEW_NO_RESEARCH_TOOLTIP")) + + var researched_techs : PackedStringArray = info.get("researched_technologies", PackedStringArray()) + var avail_techs : PackedStringArray = info.get("researchable_technologies", PackedStringArray()) + + for ix : int in range(_technologies.size()): + var folder_number_discovered = 0 + # spellchecker:off (iy is wrongly detected as misspelling of it) + for iy : int in range(_technologies[ix].size()): + for iz : int in range(_technologies[ix][iy].size()): + var tech_identifier : String = _technologies[ix][iy][iz] + var tech_info : Dictionary = MenuSingleton.get_specific_technology_info(tech_identifier) + var tech : GUIIconButton = get_gui_icon_button_from_nodepath("./country_technology/{y}/{z}/start_research".format({"y":_tech_areas[ix][iy], "z":tech_identifier})) + if tech: + if researched_techs.has(tech_identifier): + tech.set_icon_index(2) + folder_number_discovered += 1 + elif current_research == tech_identifier: + tech.set_icon_index(1) + elif avail_techs.has(tech_identifier): + tech.set_icon_index(3) + else: + tech.set_icon_index(4) + tech.set_tooltip_string("§Y{tech}§W\n".format({ "tech": tr(tech_identifier) }) + tech_info.get("effects", "") + MenuSingleton.get_tooltip_separator() + tr("TECH_INVENTIONS_TOOLTIP") + "\nTODO: Inventions") + # spellchecker:on + var label : GUILabel = _tech_folder_number_discovered_labels[ix] + if label: + label.set_text("{r}/{a}".format({"r":folder_number_discovered,"a":_folder_tech_counts[ix]})) + var progbar : GUIProgressBar = _tech_folder_progressbars[ix] + if progbar: + progbar.value = float(folder_number_discovered) / float(_folder_tech_counts[ix]) + + # SELECTED TECHNOLOGY PANEL + if _selected_tech_label: + _selected_tech_label.set_text(_selected_technology) + if _selected_tech_picture and _selected_technology: + _selected_tech_picture.set_texture(AssetManager.get_texture("gfx/pictures/tech/{a}.tga".format({ "a": _selected_technology }))) + if _selected_tech_effects: + _selected_tech_effects.set_text(_selected_technology_info.get("effects", "")) + if _selected_tech_research_points: + _selected_tech_research_points.set_text(str(_selected_technology_info.get("research_points", 0))) + if _selected_tech_unlock_year: + _selected_tech_unlock_year.set_text(str(_selected_technology_info.get("start_year", 1836))) + if _start_research_button: + if current_research == _selected_technology: + _start_research_button.disabled = true + _start_research_button.set_tooltip_string_and_substitution_dict(tr("TECHNOLOGYVIEW_UNDER_RESEARCH_TOOLTIP"), { "TECH": tr(_selected_technology) }) + elif researched_techs.has(_selected_technology): + _start_research_button.disabled = true + _start_research_button.set_tooltip_string_and_substitution_dict(tr("TECHNOLOGYVIEW_ALREADY_RESEARCHED_TOOLTIP"), { "TECH": tr(_selected_technology) }) + elif avail_techs.has(_selected_technology): + _start_research_button.disabled = false + _start_research_button.set_tooltip_string_and_substitution_dict(tr("TECHNOLOGYVIEW_START_RESEARCH_TOOLTIP"), { "TECH": tr(_selected_technology) }) + else: + _start_research_button.disabled = true + _start_research_button.set_tooltip_string_and_substitution_dict( + tr("TECHNOLOGYVIEW_CANNOT_RESEARCH_TOOLTIP") + "\n" + + tr("TECHNOLOGYVIEW_HAVE_NOT_YEAR") + "\n" + + (MenuSingleton.get_tooltip_condition_met() if researched_techs.has(_selected_technology_info.get("prerequisite", "")) else MenuSingleton.get_tooltip_condition_unmet()) + + " " + tr("TECHNOLOGYVIEW_HAVE_DISCOVERED_PREREQ_TOOLTIP").replace("$TECH$", "$PREREQ$"), + { + "TECH": tr(_selected_technology), + "YEAR": str(_selected_technology_info.get("start_year", 1836)), + "PREREQ": _selected_technology_info.get("prerequisite", "") + } + ) + show() else: hide()