1717#include " openvic-extension/singletons/GameSingleton.hpp"
1818#include " openvic-extension/utility/ClassBindings.hpp"
1919#include " openvic-extension/utility/Utilities.hpp"
20+ #include " godot_cpp/core/error_macros.hpp"
2021#include " godot_cpp/variant/array.hpp"
2122#include " godot_cpp/variant/dictionary.hpp"
23+ #include " godot_cpp/variant/packed_float32_array.hpp"
24+ #include " godot_cpp/variant/packed_int32_array.hpp"
25+ #include " godot_cpp/variant/packed_string_array.hpp"
2226#include " godot_cpp/variant/string.hpp"
2327#include " openvic-simulation/country/CountryInstance.hpp"
2428#include " openvic-simulation/research/Technology.hpp"
@@ -132,47 +136,55 @@ String MenuSingleton::make_modifier_effects_tooltip(ModifierValue const& modifie
132136 result += " \n " ;
133137 }
134138
135- result += tr (Utilities::std_to_godot_string (effect->get_localisation_key ()));
139+ make_modifier_effect_tooltip (*effect, value);
140+ }
136141
137- static const String post_name_text = " : " + GUILabel::get_colour_marker () ;
138- result += post_name_text;
142+ return result ;
143+ }
139144
140- if (value == 0 ) {
141- result += " Y" ;
142- } else if (effect->is_positive_good () == value > 0 ) {
143- result += " G" ;
144- } else {
145- result += " R" ;
146- }
145+ String MenuSingleton::make_modifier_effect_tooltip (ModifierEffect const & effect, fixed_point_t value) const {
146+ String result;
147147
148- if (value >= 0 ) {
149- result += " +" ;
150- }
148+ result += tr (Utilities::std_to_godot_string (effect.get_localisation_key ()));
151149
152- static constexpr int32_t DECIMAL_PLACES = 2 ;
153-
154- using enum ModifierEffect::format_t ;
155-
156- switch (effect->get_format ()) {
157- case PROPORTION_DECIMAL:
158- result += GUINode::float_to_string_dp ((value * 100 ).to_float (), DECIMAL_PLACES) + " %" ;
159- break ;
160- case PERCENTAGE_DECIMAL:
161- result += GUINode::float_to_string_dp (value.to_float (), DECIMAL_PLACES) + " %" ;
162- break ;
163- case INT:
164- result += String::num_int64 (value.to_int64_t ());
165- break ;
166- case RAW_DECIMAL: [[fallthrough]];
167- default : // Use raw decimal as fallback format
168- result += GUINode::float_to_string_dp (value.to_float (), DECIMAL_PLACES);
169- break ;
170- }
150+ static const String post_name_text = " : " + GUILabel::get_colour_marker ();
151+ result += post_name_text;
152+
153+ if (value == 0 ) {
154+ result += " Y" ;
155+ } else if (effect.is_positive_good () == value > 0 ) {
156+ result += " G" ;
157+ } else {
158+ result += " R" ;
159+ }
171160
172- static const String end_text = GUILabel::get_colour_marker () + String { " ! " };
173- result += end_text ;
161+ if (value >= 0 ) {
162+ result += " + " ;
174163 }
175164
165+ static constexpr int32_t DECIMAL_PLACES = 2 ;
166+
167+ using enum ModifierEffect::format_t ;
168+
169+ switch (effect.get_format ()) {
170+ case PROPORTION_DECIMAL:
171+ result += GUINode::float_to_string_dp ((value * 100 ).to_float (), DECIMAL_PLACES) + " %" ;
172+ break ;
173+ case PERCENTAGE_DECIMAL:
174+ result += GUINode::float_to_string_dp (value.to_float (), DECIMAL_PLACES) + " %" ;
175+ break ;
176+ case INT:
177+ result += String::num_int64 (value.to_int64_t ());
178+ break ;
179+ case RAW_DECIMAL: [[fallthrough]];
180+ default : // Use raw decimal as fallback format
181+ result += GUINode::float_to_string_dp (value.to_float (), DECIMAL_PLACES);
182+ break ;
183+ }
184+
185+ static const String end_text = GUILabel::get_colour_marker () + String { " !" };
186+ result += end_text;
187+
176188 return result;
177189}
178190
@@ -307,6 +319,7 @@ void MenuSingleton::_bind_methods() {
307319 ADD_SIGNAL (MethodInfo (_signal_search_cache_changed ()));
308320
309321 /* TECHNOLOGY MENU */
322+ OV_BIND_METHOD (MenuSingleton::get_technology_menu_defines);
310323 OV_BIND_METHOD (MenuSingleton::get_technology_menu_info);
311324}
312325
@@ -1027,32 +1040,81 @@ Vector2 MenuSingleton::get_search_result_position(int32_t result_index) const {
10271040}
10281041
10291042/* TECHNOLOGY MENU */
1030- godot::Dictionary MenuSingleton::get_technology_menu_info () const {
1043+ godot::Dictionary MenuSingleton::get_technology_menu_defines () const {
10311044 GameSingleton const * game_singleton = GameSingleton::get_singleton ();
10321045 ERR_FAIL_NULL_V (game_singleton, {});
10331046
10341047 static const StringName tech_folders_key = " tech_folders" ;
1048+ static const StringName tech_areas_key = " tech_areas" ;
1049+ static const StringName technologies_key = " technologies" ;
1050+ static const StringName folder_tech_count_key = " folder_tech_count" ;
1051+
1052+ Dictionary ret;
1053+
1054+ std::vector<OpenVic::TechnologyFolder> const & tech_folders = game_singleton->get_definition_manager ().get_research_manager ().get_technology_manager ().get_technology_folders ();
1055+
1056+ PackedStringArray tech_folder_identifiers {};
1057+ Array tech_area_identifiers {};
1058+ Array tech_identifiers {};
1059+ PackedInt32Array folder_tech_count {};
1060+ for (TechnologyFolder const & folder : tech_folders) {
1061+ tech_folder_identifiers.push_back (Utilities::std_to_godot_string (folder.get_identifier ()));
1062+ int32_t num_in_folder = 0 ;
1063+
1064+ PackedStringArray folder_areas {};
1065+ Array tech_folder_nested_array {}; // tech_identifiers has three levels of nested arrays :P
1066+ for (TechnologyArea const * area : folder.get_technology_areas ()) {
1067+ folder_areas.push_back (Utilities::std_to_godot_string (area->get_identifier ()));
1068+
1069+ PackedStringArray area_technologies {};
1070+ for (Technology const * tech : area->get_technologies ()) {
1071+ area_technologies.push_back (Utilities::std_to_godot_string (tech->get_identifier ()));
1072+ num_in_folder++;
1073+ }
1074+ tech_folder_nested_array.push_back (std::move (area_technologies));
1075+ }
1076+ tech_area_identifiers.push_back (std::move (folder_areas));
1077+ tech_identifiers.push_back (std::move (tech_folder_nested_array));
1078+ folder_tech_count.push_back (num_in_folder);
1079+ }
1080+ ret[tech_folders_key] = std::move (tech_folder_identifiers);
1081+ ret[tech_areas_key] = std::move (tech_area_identifiers);
1082+ ret[technologies_key] = std::move (tech_identifiers);
1083+ ret[folder_tech_count_key] = std::move (folder_tech_count);
1084+
1085+ return ret;
1086+ }
1087+
1088+ godot::Dictionary MenuSingleton::get_technology_menu_info () const {
1089+ GameSingleton const * game_singleton = GameSingleton::get_singleton ();
1090+ ERR_FAIL_NULL_V (game_singleton, {});
1091+
10351092 static const StringName tech_school_key = " tech_school" ;
1036- static const StringName tech_school_mod_names = " tech_school_mod_names" ;
10371093 static const StringName tech_school_mod_values = " tech_school_mod_values" ;
10381094 static const StringName tech_school_mod_icons = " tech_school_mod_icons" ;
1095+ static const StringName tech_school_mod_tt = " tech_school_mod_tt" ;
10391096
1040- Dictionary ret;
1097+ static const StringName current_research_tech = " current_research_tech" ;
1098+ static const StringName current_research_cat = " current_research_cat" ;
10411099
1042- std::vector<std::string_view> tech_folder_identifiers = game_singleton->get_definition_manager ().get_research_manager ().get_technology_manager ().get_technology_folder_identifiers ();
1043- Array tech_folders {};
1044- for (auto folder : tech_folder_identifiers) {
1045- tech_folders.push_back (Utilities::std_to_godot_string (folder));
1046- }
1047- ret[tech_folders_key] = tech_folders;
1100+ static const StringName researched_technologies_key = " researched_technologies" ;
1101+
1102+ Dictionary ret;
10481103
10491104 const CountryInstance* country = game_singleton->get_viewed_country ();
10501105 if (country == nullptr ) {
10511106 ret[tech_school_key] = String (" traditional_academic" );
1052- ret[tech_school_mod_names] = Array {};
1053- ret[tech_school_mod_values] = Array {};
1107+ ret[tech_school_mod_values] = PackedFloat32Array {};
1108+ ret[tech_school_mod_icons] = PackedInt32Array {};
1109+ ret[tech_school_mod_tt] = PackedStringArray {};
1110+ ret[current_research_tech] = " " ;
1111+ ret[current_research_cat] = " " ;
1112+ ret[researched_technologies_key] = PackedStringArray {};
10541113 return ret;
10551114 }
1115+
1116+ std::vector<std::string_view> tech_folder_identifiers = game_singleton->get_definition_manager ().get_research_manager ().get_technology_manager ().get_technology_folder_identifiers ();
1117+
10561118 ret[tech_school_key] = Utilities::std_to_godot_string (country->get_tech_school () == nullptr ? " traditional_academic" : country->get_tech_school ()->get_identifier ());
10571119
10581120 static const auto bonus_suffix = " _research_bonus" ;
@@ -1062,7 +1124,7 @@ godot::Dictionary MenuSingleton::get_technology_menu_info() const {
10621124 return std::find (tech_folder_identifiers.begin (), tech_folder_identifiers.end (), tempA) < std::find (tech_folder_identifiers.begin (), tech_folder_identifiers.end (), tempB);
10631125 };
10641126
1065- std::vector<std::pair<std::string_view, fixed_point_t >> school_modifiers;
1127+ std::vector<std::pair<std::string_view, fixed_point_t >> school_modifiers {} ;
10661128 if (country->get_tech_school () != nullptr ) {
10671129 for (auto effect : country->get_tech_school ()->get_values ()) {
10681130 if (!effect.first ->get_identifier ().starts_with (" unciv" )) {
@@ -1071,22 +1133,42 @@ godot::Dictionary MenuSingleton::get_technology_menu_info() const {
10711133 }
10721134 }
10731135 }
1136+ if (country->get_tech_school ()->get_effect_count () > 0 ) {
1137+ std::sort (school_modifiers.begin (), school_modifiers.end (), compareFolders);
1138+ }
10741139 }
1075- std::sort (school_modifiers.begin (), school_modifiers.end (), compareFolders);
10761140
1077- Array school_modifier_names {};
1078- Array school_modifier_values {};
1079- Array school_modifier_icons {};
1141+ PackedFloat32Array school_modifier_values {};
1142+ PackedInt32Array school_modifier_icons {};
1143+ PackedStringArray school_modifier_tt {};
10801144
10811145 for (auto modifier : school_modifiers) {
1082- school_modifier_names.push_back (Utilities::std_to_godot_string (modifier.first ));
1146+ int32_t folder_id = std::find (tech_folder_identifiers.begin (), tech_folder_identifiers.end (), modifier.first .substr (0 , modifier.first .find (bonus_suffix))) - tech_folder_identifiers.begin ();
1147+
10831148 school_modifier_values.push_back (modifier.second .to_float ());
1084- school_modifier_icons.push_back (1 + std::find (tech_folder_identifiers.begin (), tech_folder_identifiers.end (), modifier.first .substr (0 , modifier.first .find (bonus_suffix))) - tech_folder_identifiers.begin ());
1149+ school_modifier_icons.push_back (1 + folder_id);
1150+ school_modifier_tt.push_back (make_modifier_effect_tooltip (**game_singleton->get_definition_manager ().get_modifier_manager ().get_modifier_effect_cache ().get_research_bonus_effects ().get_item_by_key (*game_singleton->get_definition_manager ().get_research_manager ().get_technology_manager ().get_technology_folder_by_index (folder_id)), modifier.second ));
10851151 }
10861152
1087- ret[tech_school_mod_names] = school_modifier_names;
1088- ret[tech_school_mod_values] = school_modifier_values;
1089- ret[tech_school_mod_icons] = school_modifier_icons;
1153+ ret[tech_school_mod_values] = std::move (school_modifier_values);
1154+ ret[tech_school_mod_icons] = std::move (school_modifier_icons);
1155+ ret[tech_school_mod_tt] = std::move (school_modifier_tt);
1156+
1157+ Technology const * current_research = country->get_current_research ();
1158+ if (current_research != nullptr ) {
1159+ ret[current_research_tech] = Utilities::std_to_godot_string (current_research->get_identifier ());
1160+ 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 ()));
1161+ } else {
1162+ ret[current_research_tech] = String (" " );
1163+ ret[current_research_cat] = String (" " );
1164+ }
1165+
1166+ PackedStringArray researched_technologies {};
1167+ for (Technology const & tech : game_singleton->get_definition_manager ().get_research_manager ().get_technology_manager ().get_technologies ()) {
1168+ if (country->is_technology_unlocked (tech))
1169+ researched_technologies.push_back (Utilities::std_to_godot_string (tech.get_identifier ()));
1170+ }
1171+ ret[researched_technologies_key] = std::move (researched_technologies);
10901172
10911173 return ret;
10921174}
0 commit comments