diff --git a/extension/deps/openvic-simulation b/extension/deps/openvic-simulation index d2af122e..8e639dca 160000 --- a/extension/deps/openvic-simulation +++ b/extension/deps/openvic-simulation @@ -1 +1 @@ -Subproject commit d2af122e1553791639074f0fd8bdd8c02c962cd0 +Subproject commit 8e639dca1477305e3cbebbdfe3358f85c6686050 diff --git a/extension/doc_classes/MenuSingleton.xml b/extension/doc_classes/MenuSingleton.xml index f72b1a65..4233b446 100644 --- a/extension/doc_classes/MenuSingleton.xml +++ b/extension/doc_classes/MenuSingleton.xml @@ -150,14 +150,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. diff --git a/extension/doc_classes/PlayerSingleton.xml b/extension/doc_classes/PlayerSingleton.xml index 74ddfdab..0e38316b 100644 --- a/extension/doc_classes/PlayerSingleton.xml +++ b/extension/doc_classes/PlayerSingleton.xml @@ -91,6 +91,12 @@ + + + + + + diff --git a/extension/src/openvic-extension/singletons/GameSingleton.cpp b/extension/src/openvic-extension/singletons/GameSingleton.cpp index 6a8cdf6e..b6bc270b 100644 --- a/extension/src/openvic-extension/singletons/GameSingleton.cpp +++ b/extension/src/openvic-extension/singletons/GameSingleton.cpp @@ -13,6 +13,7 @@ #include "openvic-extension/singletons/PlayerSingleton.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; @@ -159,17 +160,6 @@ Error GameSingleton::setup_game(int32_t bookmark_index) { player_singleton.set_player_country(starting_country); ERR_FAIL_NULL_V(player_singleton.get_player_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); } diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.cpp b/extension/src/openvic-extension/singletons/MenuSingleton.cpp index ac041cda..692d6b42 100644 --- a/extension/src/openvic-extension/singletons/MenuSingleton.cpp +++ b/extension/src/openvic-extension/singletons/MenuSingleton.cpp @@ -1,17 +1,28 @@ #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/singletons/PlayerSingleton.hpp" #include "openvic-extension/utility/ClassBindings.hpp" -#include "openvic-extension/utility/Utilities.hpp" using namespace godot; using namespace OpenVic; @@ -168,13 +179,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); } } @@ -314,6 +329,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" }); @@ -436,6 +454,11 @@ 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_identifier" }); } MenuSingleton* MenuSingleton::get_singleton() { @@ -460,6 +483,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 17cd40ee..6804e8d2 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; @@ -149,6 +151,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 @@ -173,6 +176,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; @@ -233,6 +239,11 @@ 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_identifier) const; + /* TRADE MENU */ godot::Dictionary get_trade_menu_good_categories_info() const; godot::Dictionary get_trade_menu_trade_details_info( diff --git a/extension/src/openvic-extension/singletons/PlayerSingleton.cpp b/extension/src/openvic-extension/singletons/PlayerSingleton.cpp index c78962f1..ced3c320 100644 --- a/extension/src/openvic-extension/singletons/PlayerSingleton.cpp +++ b/extension/src/openvic-extension/singletons/PlayerSingleton.cpp @@ -7,6 +7,7 @@ #include "openvic-extension/singletons/GameSingleton.hpp" #include "openvic-extension/singletons/MenuSingleton.hpp" #include "openvic-extension/utility/ClassBindings.hpp" +#include "openvic-extension/utility/Utilities.hpp" using namespace OpenVic; using namespace godot; @@ -39,6 +40,7 @@ void PlayerSingleton::_bind_methods() { // Budget // Technology + OV_BIND_METHOD(PlayerSingleton::start_research, { "technology_identifier" }); // Politics @@ -213,6 +215,25 @@ void PlayerSingleton::expand_selected_province_building(int32_t building_index) // Budget // Technology +void PlayerSingleton::start_research(String const& technology_identifier) const { + ERR_FAIL_NULL(player_country); + + GameSingleton& game_singleton = *GameSingleton::get_singleton(); + + Technology const* technology = + game_singleton.get_definition_manager().get_research_manager().get_technology_manager().get_technology_by_identifier( + Utilities::godot_to_std_string(technology_identifier) + ); + ERR_FAIL_NULL(technology); + + InstanceManager* instance_manager = game_singleton.get_instance_manager(); + ERR_FAIL_NULL(instance_manager); + + instance_manager->queue_game_action( + game_action_type_t::GAME_ACTION_START_RESEARCH, + std::pair { player_country->get_index(), technology->get_index() } + ); +} // Politics diff --git a/extension/src/openvic-extension/singletons/PlayerSingleton.hpp b/extension/src/openvic-extension/singletons/PlayerSingleton.hpp index 2a407d18..db620170 100644 --- a/extension/src/openvic-extension/singletons/PlayerSingleton.hpp +++ b/extension/src/openvic-extension/singletons/PlayerSingleton.hpp @@ -50,6 +50,7 @@ namespace OpenVic { // Budget // Technology + void start_research(godot::String const& technology_identifier) const; // Politics diff --git a/extension/src/openvic-extension/singletons/TechnologyMenu.cpp b/extension/src/openvic-extension/singletons/TechnologyMenu.cpp new file mode 100644 index 00000000..04bc64cc --- /dev/null +++ b/extension/src/openvic-extension/singletons/TechnologyMenu.cpp @@ -0,0 +1,178 @@ +#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/singletons/PlayerSingleton.hpp" +#include "openvic-extension/utility/Utilities.hpp" + +using namespace OpenVic; +using namespace godot; + +/* TECHNOLOGY MENU */ +Dictionary MenuSingleton::get_technology_menu_defines() const { + 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 = GameSingleton::get_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 {}; + TypedArray 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(); + DefinitionManager const& definition_manager = game_singleton.get_definition_manager(); + InstanceManager const* instance_manager = game_singleton.get_instance_manager(); + ERR_FAIL_NULL_V(instance_manager, {}); + + TechnologyManager const& tech_manager = definition_manager.get_research_manager().get_technology_manager(); + + static const StringName tech_school_key = "tech_school"; + static const StringName tech_school_mod_values_key = "tech_school_mod_values"; + static const StringName tech_school_mod_icons_key = "tech_school_mod_icons"; + static const StringName tech_school_mod_tt_key = "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_key = "current_research_tech"; + static const StringName current_research_cat_key = "current_research_cat"; + static const StringName current_research_finish_date_key = "current_research_finish_date"; + static const StringName current_research_invested_key = "current_research_invested"; + static const StringName current_research_cost_key = "current_research_cost"; + static const StringName current_research_effect_tt_key = "current_research_effect_tt"; + static const StringName current_research_progress_key = "current_research_progress"; + + Dictionary ret; + + CountryInstance const* country = PlayerSingleton::get_singleton()->get_player_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 [tech_folder, research_bonus_effect] : + 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_key] = std::move(school_modifier_values); + ret[tech_school_mod_icons_key] = std::move(school_modifier_icons); + ret[tech_school_mod_tt_key] = 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, 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_key] = Utilities::std_to_godot_string(current_research->get_identifier()); + ret[current_research_cat_key] = + 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_key] = Utilities::date_to_string(country->get_expected_research_completion_date()); + ret[current_research_invested_key] = country->get_invested_research_points().to_int32_t(); + ret[current_research_cost_key] = country->get_current_research_cost().to_int32_t(); + ret[current_research_effect_tt_key] = _make_modifier_effects_tooltip(*current_research).trim_prefix("\n"); + ret[current_research_progress_key] = country->get_research_progress().to_float(); + } + + return ret; +} + +Dictionary MenuSingleton::get_specific_technology_info(String technology_identifier) const { + DefinitionManager const& definition_manager = GameSingleton::get_singleton()->get_definition_manager(); + + static const StringName effect_tooltip_key = "effects_tooltip"; + 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 = + definition_manager.get_research_manager().get_technology_manager().get_technology_by_identifier( + Utilities::godot_to_std_string(technology_identifier) + ); + CountryInstance const* player_country = PlayerSingleton::get_singleton()->get_player_country(); + if (technology == nullptr || player_country == nullptr) { + return ret; + } + + ret[effect_tooltip_key] = _make_modifier_effects_tooltip(*technology).trim_prefix("\n"); + ret[research_points_key] = player_country->calculate_research_cost( + *technology, 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; +} diff --git a/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd b/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd index 8386fef3..24855d6c 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,154 @@ 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 + const tech_folders_key : StringName = &"tech_folders" + const tech_areas_key : StringName = &"tech_areas" + const technologies_key : StringName = &"technologies" + const folder_tech_count_key : StringName = &"folder_tech_count" + + _tech_folders = _tech_defines.get(tech_folders_key, [] as PackedStringArray) + _tech_areas = _tech_defines.get(tech_areas_key, [] as Array[PackedStringArray]) + _technologies = _tech_defines.get(technologies_key, []) + 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_key, [] as PackedInt32Array) + + var root_node : Node = get_node(^"./country_technology") + var tech_folder_pos : Vector2 = GUINode.get_gui_position("country_technology", "folder_offset") + var tech_group_pos_base : Vector2 = GUINode.get_gui_position("country_technology", "tech_group_offset") + var tech_pos_base : Vector2 = GUINode.get_gui_position("country_technology", "tech_offset") + + for i : int in _tech_folders.size(): + add_gui_element("country_technology", "folder_window") + + var folder_node : Node = get_node(^"./folder_window") + + if not folder_node: + continue + + folder_node.reparent(root_node) + folder_node.name = _tech_folders[i] + "_folder" + folder_node.set_position(tech_folder_pos) + tech_folder_pos.x += folder_node.get_size().x + + var icon : GUIIcon = GUINode.get_gui_icon_from_node_and_path(folder_node, ^"./folder_icon") + if icon: + icon.set_icon_index(i+1) + + var title : GUILabel = GUINode.get_gui_label_from_node_and_path(folder_node, ^"./folder_category") + if title: + title.set_text(_tech_folders[i]) + + var button : GUIIconButton = GUINode.get_gui_icon_button_from_node_and_path(folder_node, ^"./folder_button") + 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("TECHNOLOGYVIEW_SHOW_FOLDER_TOOLTIP", { "FOLDER" : _tech_folders[i] }) + _tech_folder_buttons.push_back(button) + + var progressbar : GUIProgressBar = GUINode.get_gui_progress_bar_from_node_and_path(folder_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_and_path(folder_node, ^"folder_number_discovered") + if discovered: + _tech_folder_number_discovered_labels.push_back(discovered) + + # areas + var folder_areas : PackedStringArray = _tech_areas[i] + var tech_group_pos : Vector2 = tech_group_pos_base + for area_index : int in 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) + + area_node.set_position(tech_group_pos) + tech_group_pos.x += area_node.get_size().x + + var area_title : GUILabel = GUINode.get_gui_label_from_node_and_path(area_node, ^"./group_name") + if area_title: + area_title.set_text(folder_areas[area_index]) + + # technologies + var area_technologies : PackedStringArray = _technologies[i][area_index] + var tech_pos : Vector2 = tech_pos_base + 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] + + tech_node.set_position(tech_pos) + tech_pos.y += tech_node.get_size().y + + var tech_name : GUILabel = GUINode.get_gui_label_from_node_and_path(tech_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_and_path(tech_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: + PlayerSingleton.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 +201,139 @@ 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() + + const tech_school_key : StringName = &"tech_school" + const tech_school_mod_values_key : StringName = &"tech_school_mod_values" + const tech_school_mod_icons_key : StringName = &"tech_school_mod_icons" + const tech_school_mod_tt_key : StringName = &"tech_school_mod_tt" + + if _tech_school: + _tech_school.set_text(info.get(tech_school_key, "")) + + if _tech_school_modifiers: + var mod_values : PackedFloat32Array = info.get(tech_school_mod_values_key, PackedFloat32Array()) + var mod_icons : PackedInt32Array = info.get(tech_school_mod_icons_key, PackedInt32Array()) + var mod_tooltips : PackedStringArray = info.get(tech_school_mod_tt_key, 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.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.set_tooltip_string(mod_tooltips[i]) + + const current_research_tech_key : StringName = &"current_research_tech" + const current_research_cat_key : StringName = &"current_research_cat" + const current_research_finish_date_key : StringName = &"current_research_finish_date" + const current_research_invested_key : StringName = &"current_research_invested" + const current_research_cost_key : StringName = &"current_research_cost" + const current_research_effect_tt_key : StringName = &"current_research_effect_tt" + const current_research_progress_key : StringName = &"current_research_progress" + + var current_research : String = info.get(current_research_tech_key, "") + 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_key, "")) + + if _current_research_progressbar: + if current_research != "": + _current_research_progressbar.value = info.get(current_research_progress_key, 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_key, ""), + { + "TECH": current_research, + "DATE": info.get(current_research_finish_date_key, "1836.1.1"), + "INVESTED": info.get(current_research_invested_key, 0), + "COST": info.get(current_research_cost_key, 0) + } + ) + else: + _current_research_progressbar.value = 0 + _current_research_progressbar.set_tooltip_string("TECHNOLOGYVIEW_NO_RESEARCH_TOOLTIP") + + const researched_technologies_key : StringName = &"researched_technologies" + const researchable_technologies_key : StringName = &"researchable_technologies" + + var researched_techs : PackedStringArray = info.get(researched_technologies_key, PackedStringArray()) + var avail_techs : PackedStringArray = info.get(researchable_technologies_key, PackedStringArray()) + + const effect_tooltip_key : StringName = &"effects_tooltip" + const research_points_key : StringName = &"research_points" + const start_year_key : StringName = &"start_year" + const prerequisite_key : StringName = &"prerequisite" + + 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(effect_tooltip_key, "") + 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(effect_tooltip_key, "")) + if _selected_tech_research_points: + _selected_tech_research_points.set_text(str(_selected_technology_info.get(research_points_key, 0))) + var start_year_string : String = str(_selected_technology_info.get(start_year_key, 0)) + if _selected_tech_unlock_year: + _selected_tech_unlock_year.set_text(start_year_string) + if _start_research_button: + if current_research == _selected_technology: + _start_research_button.disabled = true + _start_research_button.set_tooltip_string_and_substitution_dict("TECHNOLOGYVIEW_UNDER_RESEARCH_TOOLTIP", { "TECH": _selected_technology }) + elif researched_techs.has(_selected_technology): + _start_research_button.disabled = true + _start_research_button.set_tooltip_string_and_substitution_dict("TECHNOLOGYVIEW_ALREADY_RESEARCHED_TOOLTIP", { "TECH": _selected_technology }) + elif avail_techs.has(_selected_technology): + _start_research_button.disabled = false + _start_research_button.set_tooltip_string_and_substitution_dict("TECHNOLOGYVIEW_START_RESEARCH_TOOLTIP", { "TECH": _selected_technology }) + else: + var prerequisite : String = _selected_technology_info.get(prerequisite_key, "") + _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(prerequisite) else MenuSingleton.get_tooltip_condition_unmet()) + + " " + tr(&"TECHNOLOGYVIEW_HAVE_DISCOVERED_PREREQ_TOOLTIP").replace("$TECH$", "$PREREQ$"), + { + "TECH": _selected_technology, + "YEAR": start_year_string, + "PREREQ": prerequisite + } + ) + show() else: hide()