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()