aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp4
-rw-r--r--src/openvic-simulation/military/LeaderTrait.cpp9
-rw-r--r--src/openvic-simulation/modifier/Modifier.hpp2
-rw-r--r--src/openvic-simulation/modifier/ModifierEffect.cpp15
-rw-r--r--src/openvic-simulation/modifier/ModifierEffect.hpp5
-rw-r--r--src/openvic-simulation/modifier/ModifierEffectMapping.cpp80
-rw-r--r--src/openvic-simulation/modifier/ModifierEffectMapping.hpp45
-rw-r--r--src/openvic-simulation/modifier/ModifierManager.cpp194
-rw-r--r--src/openvic-simulation/modifier/ModifierManager.hpp32
-rw-r--r--src/openvic-simulation/research/Invention.cpp11
10 files changed, 286 insertions, 111 deletions
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index 99a8d68..0c029f7 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -898,6 +898,10 @@ bool Dataloader::load_defines(DefinitionManager& definition_manager) {
Logger::error("Failed to load interface files!");
ret = false;
}
+ if (!definition_manager.get_modifier_manager().setup_modifier_effect_mappings()) {
+ Logger::error("Failed to set up modifier effect mappings!");
+ ret = false;
+ }
if (!definition_manager.get_modifier_manager().setup_modifier_effects()) {
Logger::error("Failed to set up modifier effects!");
ret = false;
diff --git a/src/openvic-simulation/military/LeaderTrait.cpp b/src/openvic-simulation/military/LeaderTrait.cpp
index 7835636..1694828 100644
--- a/src/openvic-simulation/military/LeaderTrait.cpp
+++ b/src/openvic-simulation/military/LeaderTrait.cpp
@@ -34,15 +34,10 @@ bool LeaderTraitManager::load_leader_traits_file(ModifierManager const& modifier
[this, &modifier_manager, type](std::string_view trait_identifier, ast::NodeCPtr value) -> bool {
using enum Modifier::modifier_type_t;
- static const string_set_t allowed_modifiers = {
- "attack", "defence leader", "morale", "organisation", "reconnaissance",
- "speed", "attrition", "experience", "reliability"
- };
-
ModifierValue modifiers;
- bool ret = modifier_manager.expect_whitelisted_modifier_value(
- move_variable_callback(modifiers), LEADER, allowed_modifiers
+ bool ret = modifier_manager.expect_modifier_value(
+ move_variable_callback(modifiers), LEADER
)(value);
ret &= add_leader_trait(trait_identifier, type, std::move(modifiers));
diff --git a/src/openvic-simulation/modifier/Modifier.hpp b/src/openvic-simulation/modifier/Modifier.hpp
index 1277c76..ebd54a7 100644
--- a/src/openvic-simulation/modifier/Modifier.hpp
+++ b/src/openvic-simulation/modifier/Modifier.hpp
@@ -16,7 +16,7 @@ namespace OpenVic {
enum struct modifier_type_t : uint8_t {
EVENT, STATIC, TRIGGERED, CRIME, TERRAIN, CLIMATE, CONTINENT, BUILDING, LEADER, UNIT_TERRAIN,
- NATIONAL_VALUE, NATIONAL_FOCUS, ISSUE, REFORM, TECHNOLOGY, INVENTION, TECH_SCHOOL
+ NATIONAL_VALUE, NATIONAL_FOCUS, ISSUE, REFORM, TECHNOLOGY, INVENTION, INVENTION_EFFECT, TECH_SCHOOL
};
static std::string_view modifier_type_to_string(modifier_type_t type);
diff --git a/src/openvic-simulation/modifier/ModifierEffect.cpp b/src/openvic-simulation/modifier/ModifierEffect.cpp
index 2ffb9a5..37822c3 100644
--- a/src/openvic-simulation/modifier/ModifierEffect.cpp
+++ b/src/openvic-simulation/modifier/ModifierEffect.cpp
@@ -41,9 +41,18 @@ std::string ModifierEffect::make_default_modifier_effect_localisation_key(std::s
}
ModifierEffect::ModifierEffect(
- std::string_view new_identifier, bool new_positive_good, format_t new_format, target_t new_targets,
+ std::string_view new_identifier,
+ bool new_positive_good,
+ format_t new_format,
+ target_t new_targets,
+ std::string_view new_mapping_key,
std::string_view new_localisation_key
-) : HasIdentifier { new_identifier }, positive_good { new_positive_good }, format { new_format }, targets { new_targets },
+) : HasIdentifier { new_identifier },
+ positive_good { new_positive_good },
+ format { new_format },
+ targets { new_targets },
+ mapping_key { new_mapping_key.empty() ? new_identifier : new_mapping_key },
localisation_key {
- new_localisation_key.empty() ? make_default_modifier_effect_localisation_key(new_identifier) : new_localisation_key
+ // mapping_key will have been initialised by this point as it's before localisation_key in the struct's declaration
+ new_localisation_key.empty() ? make_default_modifier_effect_localisation_key(mapping_key) : new_localisation_key
} {}
diff --git a/src/openvic-simulation/modifier/ModifierEffect.hpp b/src/openvic-simulation/modifier/ModifierEffect.hpp
index ff82acf..1ba9f63 100644
--- a/src/openvic-simulation/modifier/ModifierEffect.hpp
+++ b/src/openvic-simulation/modifier/ModifierEffect.hpp
@@ -40,13 +40,12 @@ namespace OpenVic {
const bool PROPERTY_CUSTOM_PREFIX(positive_good, is);
const format_t PROPERTY(format);
const target_t PROPERTY(targets);
+ std::string PROPERTY(mapping_key); // The identifier in the text defines that maps to this effect
std::string PROPERTY(localisation_key);
- // TODO - format/precision, e.g. 80% vs 0.8 vs 0.800, 2 vs 2.0 vs 200%
-
ModifierEffect(
std::string_view new_identifier, bool new_positive_good, format_t new_format, target_t mew_targets,
- std::string_view new_localisation_key
+ std::string_view new_mapping_key, std::string_view new_localisation_key
);
public:
diff --git a/src/openvic-simulation/modifier/ModifierEffectMapping.cpp b/src/openvic-simulation/modifier/ModifierEffectMapping.cpp
new file mode 100644
index 0000000..388c47f
--- /dev/null
+++ b/src/openvic-simulation/modifier/ModifierEffectMapping.cpp
@@ -0,0 +1,80 @@
+#include "ModifierEffectMapping.hpp"
+
+#include "openvic-simulation/modifier/ModifierEffect.hpp"
+#include "openvic-simulation/utility/Logger.hpp"
+
+using namespace OpenVic;
+
+std::string_view ModifierEffectMapping::modifier_effect_mapping_type_to_string(modifier_effect_mapping_type_t type) {
+ using enum ModifierEffectMapping::modifier_effect_mapping_type_t;
+
+ switch (type) {
+#define _CASE(X) case X: return #X;
+ _CASE(LEADER_MAPPING)
+ _CASE(TECHNOLOGY_MAPPING)
+ _CASE(UNIT_TERRAIN_MAPPING)
+ _CASE(BASE_COUNTRY_MAPPING)
+ _CASE(BASE_PROVINCE_MAPPING)
+ _CASE(EVENT_MAPPING)
+ _CASE(TERRAIN_MAPPING)
+#undef _CASE
+ default: return "INVALID MODIFIER TYPE";
+ }
+}
+
+ModifierEffectMapping::ModifierEffectMapping(
+ modifier_effect_mapping_type_t new_type, ModifierEffectMapping const* new_fallback_mapping
+) : type { new_type }, locked { false }, fallback_mapping { new_fallback_mapping }, effect_map {} {}
+
+std::string_view ModifierEffectMapping::get_type_name() const {
+ return modifier_effect_mapping_type_to_string(type);
+}
+
+bool ModifierEffectMapping::add_modifier_effect(ModifierEffect const& effect) {
+ if (locked) {
+ Logger::error("Cannot add modifier effect to modifier effect mapping \"", get_type_name(), "\" - locked!");
+ return false;
+ }
+
+ const auto [effect_it, effect_was_added] = effect_map.emplace(effect.get_mapping_key(), &effect);
+
+ if (!effect_was_added) {
+ Logger::error(
+ "Cannot add modifier effect \"", effect.get_identifier(), "\" to modifier effect mapping \"", get_type_name(),
+ "\" - the key \"", effect.get_mapping_key(), "\" is already mapped to modifier effect \"",
+ effect_it->second->get_identifier(), "\"!"
+ );
+ }
+
+ return effect_was_added;
+}
+
+void ModifierEffectMapping::lock() {
+ if (locked) {
+ Logger::error("Cannot lock modifier effect mapping \"", get_type_name(), "\" - already locked!");
+ } else {
+ locked = true;
+ }
+}
+
+ModifierEffect const* ModifierEffectMapping::lookup_modifier_effect(std::string_view identifier) const {
+ if (!locked) {
+ Logger::error(
+ "Cannot lookup modifier effect \"", identifier, "\" in modifier effect mapping \"", get_type_name(),
+ "\" - not locked!"
+ );
+ return nullptr;
+ }
+
+ const decltype(effect_map)::const_iterator it = effect_map.find(identifier);
+
+ if (it != effect_map.end()) {
+ return it->second;
+ }
+
+ if (fallback_mapping != nullptr) {
+ return fallback_mapping->lookup_modifier_effect(identifier);
+ }
+
+ return nullptr;
+}
diff --git a/src/openvic-simulation/modifier/ModifierEffectMapping.hpp b/src/openvic-simulation/modifier/ModifierEffectMapping.hpp
new file mode 100644
index 0000000..1042bb2
--- /dev/null
+++ b/src/openvic-simulation/modifier/ModifierEffectMapping.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <string_view>
+
+#include "openvic-simulation/types/OrderedContainers.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ struct ModifierManager;
+ struct ModifierEffect;
+
+ struct ModifierEffectMapping {
+ enum struct modifier_effect_mapping_type_t : uint8_t {
+ LEADER_MAPPING, // Isolated
+ TECHNOLOGY_MAPPING, // Isolated
+ UNIT_TERRAIN_MAPPING, // Isolated
+ BASE_COUNTRY_MAPPING, // Fallen back to by BASE_PROVINCE_MAPPING, and in turn by EVENT_MAPPING and TERRAIN_MAPPING
+ BASE_PROVINCE_MAPPING, // Falls back to BASE_COUNTRY_MAPPING, fallen back to by EVENT_MAPPING and TERRAIN_MAPPING
+ EVENT_MAPPING, // Falls back to BASE_PROVINCE_MAPPING
+ TERRAIN_MAPPING, // Falls back to BASE_PROVINCE_MAPPING
+ MODIFIER_EFFECT_MAPPING_COUNT
+ };
+
+ static std::string_view modifier_effect_mapping_type_to_string(modifier_effect_mapping_type_t type);
+
+ private:
+ const modifier_effect_mapping_type_t PROPERTY(type);
+ bool PROPERTY_CUSTOM_PREFIX(locked, is);
+ ModifierEffectMapping const* const PROPERTY(fallback_mapping);
+ string_map_t<ModifierEffect const*> PROPERTY(effect_map);
+
+ public:
+ ModifierEffectMapping(
+ modifier_effect_mapping_type_t new_type, ModifierEffectMapping const* new_fallback_mapping = nullptr
+ );
+ ModifierEffectMapping(ModifierEffectMapping&&) = default;
+
+ std::string_view get_type_name() const;
+
+ bool add_modifier_effect(ModifierEffect const& effect);
+ void lock();
+
+ ModifierEffect const* lookup_modifier_effect(std::string_view identifier) const;
+ };
+}
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
diff --git a/src/openvic-simulation/modifier/ModifierManager.hpp b/src/openvic-simulation/modifier/ModifierManager.hpp
index 51f89ae..bb946a7 100644
--- a/src/openvic-simulation/modifier/ModifierManager.hpp
+++ b/src/openvic-simulation/modifier/ModifierManager.hpp
@@ -2,14 +2,12 @@
#include "openvic-simulation/modifier/Modifier.hpp"
#include "openvic-simulation/modifier/ModifierEffectCache.hpp"
+#include "openvic-simulation/modifier/ModifierEffectMapping.hpp"
#include "openvic-simulation/modifier/StaticModifierCache.hpp"
#include "openvic-simulation/types/IdentifierRegistry.hpp"
namespace OpenVic {
- template<typename Fn>
- concept ModifierEffectValidator = std::predicate<Fn, ModifierEffect const&>;
-
struct ModifierManager {
friend struct StaticModifierCache;
friend struct BuildingTypeManager;
@@ -37,10 +35,11 @@ namespace OpenVic {
ModifierEffectCache PROPERTY(modifier_effect_cache);
StaticModifierCache PROPERTY(static_modifier_cache);
+ std::vector<ModifierEffectMapping> PROPERTY(modifier_effect_mappings);
+
/* effect_validator takes in ModifierEffect const& */
NodeTools::key_value_callback_t _modifier_effect_callback(
- ModifierValue& modifier, Modifier::modifier_type_t type, NodeTools::key_value_callback_t default_callback,
- ModifierEffectValidator auto effect_validator
+ ModifierValue& modifier, Modifier::modifier_type_t type, NodeTools::key_value_callback_t default_callback
) const;
public:
@@ -50,7 +49,9 @@ namespace OpenVic {
bool positive_good,
ModifierEffect::format_t format,
ModifierEffect::target_t targets,
- std::string_view localisation_key = {}
+ std::string_view localisation_key = {},
+ // mapping_key is placed after localisation_key as it's less likely to be set explicitly
+ std::string_view mapping_key = {}
);
bool register_complex_modifier(std::string_view identifier);
@@ -62,6 +63,7 @@ namespace OpenVic {
std::string const& identifier, ModifierEffect const* effect, std::vector<Modifier::modifier_type_t> const& types
);
+ bool setup_modifier_effect_mappings();
bool setup_modifier_effects();
bool add_event_modifier(std::string_view identifier, ModifierValue&& values, IconModifier::icon_t icon);
@@ -77,15 +79,6 @@ namespace OpenVic {
bool parse_scripts(DefinitionManager const& definition_manager);
- NodeTools::node_callback_t expect_validated_modifier_value_and_default(
- NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type,
- NodeTools::key_value_callback_t default_callback, ModifierEffectValidator auto effect_validator
- ) const;
- NodeTools::node_callback_t expect_validated_modifier_value(
- NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type,
- ModifierEffectValidator auto effect_validator
- ) const;
-
NodeTools::node_callback_t expect_modifier_value_and_default(
NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type,
NodeTools::key_value_callback_t default_callback
@@ -94,15 +87,6 @@ namespace OpenVic {
NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type
) const;
- NodeTools::node_callback_t expect_whitelisted_modifier_value_and_default(
- NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type,
- string_set_t const& whitelist, NodeTools::key_value_callback_t default_callback
- ) const;
- NodeTools::node_callback_t expect_whitelisted_modifier_value(
- NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type,
- string_set_t const& whitelist
- ) const;
-
// In the functions below, key_map refers to a map from identifier strings to NodeTools::dictionary_entry_t,
// allowing any non-modifier effect keys found to be parsed in a custom way, similar to expect_dictionary_keys.
NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default(
diff --git a/src/openvic-simulation/research/Invention.cpp b/src/openvic-simulation/research/Invention.cpp
index 808dad4..d39a4b8 100644
--- a/src/openvic-simulation/research/Invention.cpp
+++ b/src/openvic-simulation/research/Invention.cpp
@@ -64,9 +64,8 @@ bool InventionManager::load_inventions_file(
) -> bool {
using enum Modifier::modifier_type_t;
- // TODO - use the same variable for all modifiers rather than combining them at the end?
ModifierValue loose_modifiers;
- ModifierValue modifiers;
+ ModifierValue effect_modifiers;
Invention::unit_set_t activated_units;
Invention::building_set_t activated_buildings;
@@ -86,8 +85,8 @@ bool InventionManager::load_inventions_file(
"limit", ONE_EXACTLY, limit.expect_script(),
"chance", ONE_EXACTLY, chance.expect_conditional_weight(ConditionalWeight::BASE),
"effect", ZERO_OR_ONE, modifier_manager.expect_modifier_value_and_keys(
- move_variable_callback(modifiers),
- INVENTION,
+ move_variable_callback(effect_modifiers),
+ INVENTION_EFFECT,
"gas_attack", ZERO_OR_ONE, expect_bool(assign_variable_callback(unlock_gas_attack)),
"gas_defence", ZERO_OR_ONE, expect_bool(assign_variable_callback(unlock_gas_defence)),
"activate_unit", ZERO_OR_MORE,
@@ -101,10 +100,10 @@ bool InventionManager::load_inventions_file(
)
)(value);
- modifiers += loose_modifiers;
+ loose_modifiers += effect_modifiers;
ret &= add_invention(
- identifier, std::move(modifiers), news, std::move(activated_units), std::move(activated_buildings),
+ identifier, std::move(loose_modifiers), news, std::move(activated_units), std::move(activated_buildings),
std::move(enabled_crimes), unlock_gas_attack, unlock_gas_defence, std::move(limit), std::move(chance)
);