Skip to content

Commit 62007ab

Browse files
committed
Add Technology Folders and Areas
1 parent 60e2ba2 commit 62007ab

File tree

3 files changed

+303
-65
lines changed

3 files changed

+303
-65
lines changed

extension/src/openvic-extension/singletons/MenuSingleton.cpp

Lines changed: 137 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@
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
}

extension/src/openvic-extension/singletons/MenuSingleton.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
#pragma once
22

3-
<<<<<<< HEAD
4-
=======
5-
>>>>>>> 05f564d (tech schools)
63
#include <godot_cpp/classes/control.hpp>
74
#include <godot_cpp/classes/image.hpp>
5+
#include <godot_cpp/variant/dictionary.hpp>
86

97
#include <openvic-simulation/types/IndexedMap.hpp>
108
#include <openvic-simulation/types/PopSize.hpp>
119
#include <openvic-simulation/types/OrderedContainers.hpp>
12-
#include "godot_cpp/variant/dictionary.hpp"
10+
#include <openvic-simulation/types/fixed_point/FixedPoint.hpp>
11+
#include <openvic-simulation/modifier/ModifierEffect.hpp>
12+
#include <openvic-simulation/pop/Pop.hpp>
1313

1414
namespace OpenVic {
1515
struct CountryInstance;
@@ -127,6 +127,7 @@ namespace OpenVic {
127127
godot::String get_country_adjective(CountryInstance const& country) const;
128128

129129
godot::String make_modifier_effects_tooltip(ModifierValue const& modifier) const;
130+
godot::String make_modifier_effect_tooltip(ModifierEffect const& effect, fixed_point_t value) const;
130131
godot::String make_rules_tooltip(RuleSet const& rules) const;
131132

132133
protected:
@@ -206,6 +207,7 @@ namespace OpenVic {
206207
godot::TypedArray<godot::Array> get_population_menu_distribution_info() const;
207208

208209
/* TECHNOLOGY MENU */
210+
godot::Dictionary get_technology_menu_defines() const;
209211
godot::Dictionary get_technology_menu_info() const;
210212

211213
/* Find/Search Panel */

0 commit comments

Comments
 (0)