aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/modifier/ModifierManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation/modifier/ModifierManager.cpp')
-rw-r--r--src/openvic-simulation/modifier/ModifierManager.cpp194
1 files changed, 127 insertions, 67 deletions
diff --git a/src/openvic-simulation/modifier/ModifierManager.cpp b/src/openvic-simulation/modifier/ModifierManager.cpp
index daf186f..a426f23 100644
--- a/src/openvic-simulation/modifier/ModifierManager.cpp
+++ b/src/openvic-simulation/modifier/ModifierManager.cpp
@@ -5,7 +5,7 @@ using namespace OpenVic::NodeTools;
bool ModifierManager::add_modifier_effect(
ModifierEffect const*& effect_cache, std::string_view identifier, bool positive_good, ModifierEffect::format_t format,
- ModifierEffect::target_t targets, std::string_view localisation_key
+ ModifierEffect::target_t targets, std::string_view localisation_key, std::string_view mapping_key
) {
using enum ModifierEffect::target_t;
@@ -35,7 +35,7 @@ bool ModifierManager::add_modifier_effect(
return false;
}
- const bool ret = modifier_effects.add_item({ std::move(identifier), positive_good, format, targets, localisation_key });
+ const bool ret = modifier_effects.add_item({ identifier, positive_good, format, targets, mapping_key, localisation_key });
if (ret) {
effect_cache = &modifier_effects.get_items().back();
@@ -44,6 +44,53 @@ bool ModifierManager::add_modifier_effect(
return ret;
}
+bool ModifierManager::setup_modifier_effect_mappings() {
+ if (!modifier_effect_mappings.empty()) {
+ Logger::error("Modifier effect mappings have already been initialised!");
+ return false;
+ }
+
+ using enum ModifierEffectMapping::modifier_effect_mapping_type_t;
+
+ modifier_effect_mappings.reserve(static_cast<size_t>(MODIFIER_EFFECT_MAPPING_COUNT));
+
+ bool ret = true;
+
+ const auto add_modifier_effect_mapping = [this, &ret](
+ ModifierEffectMapping::modifier_effect_mapping_type_t type,
+ // MODIFIER_EFFECT_MAPPING_COUNT is used as an invalid/unset value here
+ ModifierEffectMapping::modifier_effect_mapping_type_t fallback_type = MODIFIER_EFFECT_MAPPING_COUNT
+ ) -> void {
+ if (static_cast<size_t>(type) != modifier_effect_mappings.size()) {
+ Logger::error(
+ "Trying to place modifier effect mapping type \"",
+ ModifierEffectMapping::modifier_effect_mapping_type_to_string(type), "\" with index ",
+ static_cast<size_t>(type), " in position ", modifier_effect_mappings.size(), "!"
+ );
+ ret = false;
+ return;
+ }
+
+ // The fallback pointer will be valid even if its map hasn't yet been initialised as we have reserved the space
+ // (further emplacements won't invalidate the pointer for the same reason).
+
+ modifier_effect_mappings.emplace_back(
+ type, fallback_type < MODIFIER_EFFECT_MAPPING_COUNT ?
+ &modifier_effect_mappings[static_cast<size_t>(fallback_type)] : nullptr
+ );
+ };
+
+ add_modifier_effect_mapping(LEADER_MAPPING);
+ add_modifier_effect_mapping(TECHNOLOGY_MAPPING);
+ add_modifier_effect_mapping(UNIT_TERRAIN_MAPPING);
+ add_modifier_effect_mapping(BASE_COUNTRY_MAPPING);
+ add_modifier_effect_mapping(BASE_PROVINCE_MAPPING, BASE_COUNTRY_MAPPING);
+ add_modifier_effect_mapping(EVENT_MAPPING, BASE_PROVINCE_MAPPING);
+ add_modifier_effect_mapping(TERRAIN_MAPPING, BASE_PROVINCE_MAPPING);
+
+ return ret;
+}
+
bool ModifierManager::setup_modifier_effects() {
// Variant Modifier Effeects
static const std::string combat_width = "combat_width";
@@ -686,36 +733,59 @@ bool ModifierManager::parse_scripts(DefinitionManager const& definition_manager)
return ret;
}
+static constexpr ModifierEffectMapping::modifier_effect_mapping_type_t modifier_type_to_modifier_effect_mapping_type(
+ Modifier::modifier_type_t type
+) {
+ using enum Modifier::modifier_type_t;
+ using enum ModifierEffectMapping::modifier_effect_mapping_type_t;
+
+ switch (type) {
+ case EVENT: return EVENT_MAPPING;
+ case STATIC: return BASE_COUNTRY_MAPPING; // shouldn't this be BASE_PROVINCE_MAPPING or EVENT_MAPPING?
+ case TRIGGERED: return BASE_COUNTRY_MAPPING; // maybe should be BASE_PROVINCE_MAPPING or EVENT_MAPPING, but less likely
+ case CRIME: return BASE_PROVINCE_MAPPING;
+ case TERRAIN: return TERRAIN_MAPPING;
+ case CLIMATE: return BASE_PROVINCE_MAPPING;
+ case CONTINENT: return BASE_PROVINCE_MAPPING;
+ case BUILDING: return BASE_PROVINCE_MAPPING;
+ case LEADER: return LEADER_MAPPING;
+ case UNIT_TERRAIN: return UNIT_TERRAIN_MAPPING;
+ case NATIONAL_VALUE: return BASE_COUNTRY_MAPPING;
+ case NATIONAL_FOCUS: return BASE_PROVINCE_MAPPING;
+ case ISSUE: return BASE_COUNTRY_MAPPING;
+ case REFORM: return BASE_COUNTRY_MAPPING;
+ case TECHNOLOGY: return TECHNOLOGY_MAPPING;
+ case INVENTION: return BASE_COUNTRY_MAPPING;
+ case INVENTION_EFFECT: return TECHNOLOGY_MAPPING;
+ case TECH_SCHOOL: return BASE_COUNTRY_MAPPING;
+ default: return MODIFIER_EFFECT_MAPPING_COUNT; // Used as an invalid valid
+ }
+}
+
key_value_callback_t ModifierManager::_modifier_effect_callback(
- ModifierValue& modifier, Modifier::modifier_type_t type, key_value_callback_t default_callback,
- ModifierEffectValidator auto effect_validator
+ ModifierValue& modifier, Modifier::modifier_type_t type, key_value_callback_t default_callback
) const {
- const auto add_modifier_cb = [this, &modifier, effect_validator](
+ const auto add_modifier_cb = [this, &modifier](
ModifierEffect const* effect, ast::NodeCPtr value
) -> bool {
- if (effect_validator(*effect)) {
- static const case_insensitive_string_set_t no_effect_modifiers {
- "boost_strongest_party", "poor_savings_modifier", "local_artisan_input", "local_artisan_throughput",
- "local_artisan_output", "artisan_input", "artisan_throughput", "artisan_output",
- "import_cost", "unciv_economic_modifier", "unciv_military_modifier"
- };
-
- if (no_effect_modifiers.contains(effect->get_identifier())) {
- Logger::warning("This modifier does nothing: ", effect->get_identifier());
- }
-
- return expect_fixed_point(map_callback(modifier.values, effect))(value);
- } else {
- Logger::error("Failed to validate modifier effect: ", effect->get_identifier());
- return false;
+ static const case_insensitive_string_set_t no_effect_modifiers {
+ "boost_strongest_party", "poor_savings_modifier", "local_artisan_input", "local_artisan_throughput",
+ "local_artisan_output", "artisan_input", "artisan_throughput", "artisan_output",
+ "import_cost", "unciv_economic_modifier", "unciv_military_modifier"
+ };
+
+ if (no_effect_modifiers.contains(effect->get_identifier())) {
+ Logger::warning("This modifier does nothing: ", effect->get_identifier());
}
+
+ return expect_fixed_point(map_callback(modifier.values, effect))(value);
};
const auto add_flattened_modifier_cb = [this, add_modifier_cb](
- std::string_view prefix, std::string_view key, ast::NodeCPtr value
+ ModifierEffectMapping const& modifier_effect_mapping, std::string_view prefix, std::string_view key, ast::NodeCPtr value
) -> bool {
const std::string flat_identifier = get_flat_identifier(prefix, key);
- ModifierEffect const* effect = get_modifier_effect_by_identifier(flat_identifier);
+ ModifierEffect const* effect = modifier_effect_mapping.lookup_modifier_effect(flat_identifier);
if (effect != nullptr) {
return add_modifier_cb(effect, value);
} else {
@@ -727,13 +797,33 @@ key_value_callback_t ModifierManager::_modifier_effect_callback(
return [this, type, default_callback, add_modifier_cb, add_flattened_modifier_cb](
std::string_view key, ast::NodeCPtr value
) -> bool {
+ using enum ModifierEffectMapping::modifier_effect_mapping_type_t;
+
+ // TODO - template-ise the modifier type argument so getting the ModifierEffectMapping pointer can be made constexpr
+ const ModifierEffectMapping::modifier_effect_mapping_type_t mapping_type =
+ modifier_type_to_modifier_effect_mapping_type(type);
+
+ if (mapping_type >= MODIFIER_EFFECT_MAPPING_COUNT) {
+ Logger::error(
+ "Modifier type \"", Modifier::modifier_type_to_string(type),
+ "\" has produced an invalid modifier effect mapping type \"",
+ ModifierEffectMapping::modifier_effect_mapping_type_to_string(mapping_type), "\"!"
+ );
+ return false;
+ }
+
+ ModifierEffectMapping const& modifier_effect_mapping = modifier_effect_mappings[static_cast<size_t>(mapping_type)];
if (dryad::node_has_kind<ast::IdentifierValue>(value)) {
- ModifierEffect const* effect = get_modifier_effect_by_identifier(key);
+ ModifierEffect const* effect = modifier_effect_mapping.lookup_modifier_effect(key);
if (effect != nullptr) {
return add_modifier_cb(effect, value);
- } else if (key == "war_exhaustion_effect") {
+ }
+
+ // This will all be unnecessary when using modifier effect mappings
+
+ /* else if (key == "war_exhaustion_effect") {
Logger::warning("war_exhaustion_effect does nothing (vanilla issues have it).");
return true;
} else {
@@ -758,7 +848,7 @@ key_value_callback_t ModifierManager::_modifier_effect_callback(
);
return false;
}
- }
+ }*/
} else if (dryad::node_has_kind<ast::ListValue>(value) && complex_modifiers.contains(key)) {
if (key == "rebel_org_gain") { // because of course there's a special one
std::string_view faction_identifier;
@@ -769,11 +859,17 @@ key_value_callback_t ModifierManager::_modifier_effect_callback(
"value", ONE_EXACTLY, assign_variable_callback(value_node)
)(value);
- ret &= add_flattened_modifier_cb(key, faction_identifier, value_node);
+ ret &= add_flattened_modifier_cb(modifier_effect_mapping, key, faction_identifier, value_node);
return ret;
} else {
- return expect_dictionary(std::bind_front(add_flattened_modifier_cb, key))(value);
+ return expect_dictionary(
+ [add_flattened_modifier_cb, &modifier_effect_mapping, key](
+ std::string_view dict_key, ast::NodeCPtr dict_value
+ ) -> bool {
+ return add_flattened_modifier_cb(modifier_effect_mapping, key, dict_key, dict_value);
+ }
+ )(value);
}
}
@@ -781,16 +877,15 @@ key_value_callback_t ModifierManager::_modifier_effect_callback(
};
}
-node_callback_t ModifierManager::expect_validated_modifier_value_and_default(
- callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type, key_value_callback_t default_callback,
- ModifierEffectValidator auto effect_validator
+node_callback_t ModifierManager::expect_modifier_value_and_default(
+ callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type, key_value_callback_t default_callback
) const {
- return [this, modifier_callback, type, default_callback, effect_validator](ast::NodeCPtr root) -> bool {
+ return [this, modifier_callback, type, default_callback](ast::NodeCPtr root) -> bool {
ModifierValue modifier;
bool ret = expect_dictionary_reserve_length(
modifier.values,
- _modifier_effect_callback(modifier, type, default_callback, effect_validator)
+ _modifier_effect_callback(modifier, type, default_callback)
)(root);
ret &= modifier_callback(std::move(modifier));
@@ -799,47 +894,12 @@ node_callback_t ModifierManager::expect_validated_modifier_value_and_default(
};
}
-node_callback_t ModifierManager::expect_validated_modifier_value(
- callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type,
- ModifierEffectValidator auto effect_validator
-) const {
- return expect_validated_modifier_value_and_default(modifier_callback, type, key_value_invalid_callback, effect_validator);
-}
-
-node_callback_t ModifierManager::expect_modifier_value_and_default(
- callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type, key_value_callback_t default_callback
-) const {
- return expect_validated_modifier_value_and_default(
- modifier_callback, type, default_callback, [](ModifierEffect const&) -> bool {
- return true;
- }
- );
-}
-
node_callback_t ModifierManager::expect_modifier_value(
callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type
) const {
return expect_modifier_value_and_default(modifier_callback, type, key_value_invalid_callback);
}
-node_callback_t ModifierManager::expect_whitelisted_modifier_value_and_default(
- callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type, string_set_t const& whitelist,
- key_value_callback_t default_callback
-) const {
- return expect_validated_modifier_value_and_default(
- modifier_callback, type, default_callback,
- [&whitelist](ModifierEffect const& effect) -> bool {
- return whitelist.contains(effect.get_identifier());
- }
- );
-}
-
-node_callback_t ModifierManager::expect_whitelisted_modifier_value(
- callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type, string_set_t const& whitelist
-) const {
- return expect_whitelisted_modifier_value_and_default(modifier_callback, type, whitelist, key_value_invalid_callback);
-}
-
node_callback_t ModifierManager::expect_modifier_value_and_key_map_and_default(
callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type, key_value_callback_t default_callback,
key_map_t&& key_map