From eb77495ba874d474bbbbc950a65e8f496b13f285 Mon Sep 17 00:00:00 2001 From: hop311 Date: Sun, 29 Sep 2024 21:37:11 +0100 Subject: Calculate country and province resultant modifier sums --- src/openvic-simulation/country/CountryInstance.cpp | 184 ++++++++++++++++----- 1 file changed, 146 insertions(+), 38 deletions(-) (limited to 'src/openvic-simulation/country/CountryInstance.cpp') diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index 55ceb23..b3df096 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -17,16 +17,16 @@ static constexpr colour_t ERROR_COLOUR = colour_t::from_integer(0xFF0000); CountryInstance::CountryInstance( CountryDefinition const* new_country_definition, - decltype(unlocked_building_types)::keys_t const& building_type_keys, - decltype(unlocked_technologies)::keys_t const& technology_keys, - decltype(unlocked_inventions)::keys_t const& invention_keys, + decltype(building_type_unlock_levels)::keys_t const& building_type_keys, + decltype(technology_unlock_levels)::keys_t const& technology_keys, + decltype(invention_unlock_levels)::keys_t const& invention_keys, decltype(upper_house)::keys_t const& ideology_keys, decltype(reforms)::keys_t const& reform_keys, decltype(government_flag_overrides)::keys_t const& government_type_keys, - decltype(unlocked_crimes)::keys_t const& crime_keys, + decltype(crime_unlock_levels)::keys_t const& crime_keys, decltype(pop_type_distribution)::keys_t const& pop_type_keys, - decltype(unlocked_regiment_types)::keys_t const& unlocked_regiment_types_keys, - decltype(unlocked_ship_types)::keys_t const& unlocked_ship_types_keys + decltype(regiment_type_unlock_levels)::keys_t const& regiment_type_unlock_levels_keys, + decltype(ship_type_unlock_levels)::keys_t const& ship_type_unlock_levels_keys ) : /* Main attributes */ country_definition { new_country_definition }, colour { ERROR_COLOUR }, @@ -41,6 +41,8 @@ CountryInstance::CountryInstance( controlled_provinces {}, core_provinces {}, states {}, + modifier_sum {}, + event_modifiers {}, /* Production */ industrial_power { 0 }, @@ -48,14 +50,14 @@ CountryInstance::CountryInstance( industrial_power_from_investments {}, industrial_rank { 0 }, foreign_investments {}, - unlocked_building_types { &building_type_keys }, + building_type_unlock_levels { &building_type_keys }, /* Budget */ cash_stockpile { 0 }, /* Technology */ - unlocked_technologies { &technology_keys }, - unlocked_inventions { &invention_keys }, + technology_unlock_levels { &technology_keys }, + invention_unlock_levels { &invention_keys }, current_research { nullptr }, invested_research_points { 0 }, expected_completion_date {}, @@ -79,7 +81,7 @@ CountryInstance::CountryInstance( infamy { 0 }, plurality { 0 }, revanchism { 0 }, - unlocked_crimes { &crime_keys }, + crime_unlock_levels { &crime_keys }, /* Population */ primary_culture { nullptr }, @@ -121,32 +123,32 @@ CountryInstance::CountryInstance( war_exhaustion { 0 }, mobilised { false }, disarmed { false }, - unlocked_regiment_types { &unlocked_regiment_types_keys }, + regiment_type_unlock_levels { ®iment_type_unlock_levels_keys }, allowed_regiment_cultures { RegimentType::allowed_cultures_t::NO_CULTURES }, - unlocked_ship_types { &unlocked_ship_types_keys }, + ship_type_unlock_levels { &ship_type_unlock_levels_keys }, gas_attack_unlock_level { 0 }, gas_defence_unlock_level { 0 }, unit_variant_unlock_levels {} { - for (BuildingType const& building_type : *unlocked_building_types.get_keys()) { + for (BuildingType const& building_type : *building_type_unlock_levels.get_keys()) { if (building_type.is_default_enabled()) { unlock_building_type(building_type); } } - for (Crime const& crime : *unlocked_crimes.get_keys()) { + for (Crime const& crime : *crime_unlock_levels.get_keys()) { if (crime.is_default_active()) { unlock_crime(crime); } } - for (RegimentType const& regiment_type : *unlocked_regiment_types.get_keys()) { + for (RegimentType const& regiment_type : *regiment_type_unlock_levels.get_keys()) { if (regiment_type.is_active()) { unlock_unit_type(regiment_type); } } - for (ShipType const& ship_type : *unlocked_ship_types.get_keys()) { + for (ShipType const& ship_type : *ship_type_unlock_levels.get_keys()) { if (ship_type.is_active()) { unlock_unit_type(ship_type); } @@ -335,7 +337,7 @@ template bool CountryInstance::remove_leader(LeaderBranched bool CountryInstance::modify_unit_type_unlock(UnitTypeBranched const& unit_type, unlock_level_t unlock_level_change) { - IndexedMap, unlock_level_t>& unlocked_unit_types = get_unlocked_unit_types(); + IndexedMap, unlock_level_t>& unlocked_unit_types = get_unit_type_unlock_levels(); typename IndexedMap, unlock_level_t>::value_ref_t unlock_level = unlocked_unit_types[unit_type]; @@ -384,9 +386,9 @@ bool CountryInstance::is_unit_type_unlocked(UnitType const& unit_type) const { switch (unit_type.get_branch()) { case LAND: - return unlocked_regiment_types[static_cast const&>(unit_type)] > 0; + return regiment_type_unlock_levels[static_cast const&>(unit_type)] > 0; case NAVAL: - return unlocked_ship_types[static_cast const&>(unit_type)] > 0; + return ship_type_unlock_levels[static_cast const&>(unit_type)] > 0; default: Logger::error( "Attempted to check if unit type \"", unit_type.get_identifier(), "\" with invalid branch ", @@ -397,7 +399,7 @@ bool CountryInstance::is_unit_type_unlocked(UnitType const& unit_type) const { } bool CountryInstance::modify_building_type_unlock(BuildingType const& building_type, unlock_level_t unlock_level_change) { - decltype(unlocked_building_types)::value_ref_t unlock_level = unlocked_building_types[building_type]; + decltype(building_type_unlock_levels)::value_ref_t unlock_level = building_type_unlock_levels[building_type]; // This catches subtracting below 0 or adding above the int types maximum value if (unlock_level + unlock_level_change < 0) { @@ -420,11 +422,11 @@ bool CountryInstance::unlock_building_type(BuildingType const& building_type) { } bool CountryInstance::is_building_type_unlocked(BuildingType const& building_type) const { - return unlocked_building_types[building_type] > 0; + return building_type_unlock_levels[building_type] > 0; } bool CountryInstance::modify_crime_unlock(Crime const& crime, unlock_level_t unlock_level_change) { - decltype(unlocked_crimes)::value_ref_t unlock_level = unlocked_crimes[crime]; + decltype(crime_unlock_levels)::value_ref_t unlock_level = crime_unlock_levels[crime]; // This catches subtracting below 0 or adding above the int types maximum value if (unlock_level + unlock_level_change < 0) { @@ -447,7 +449,7 @@ bool CountryInstance::unlock_crime(Crime const& crime) { } bool CountryInstance::is_crime_unlocked(Crime const& crime) const { - return unlocked_crimes[crime] > 0; + return crime_unlock_levels[crime] > 0; } bool CountryInstance::modify_gas_attack_unlock(unlock_level_t unlock_level_change) { @@ -543,7 +545,7 @@ CountryInstance::unit_variant_t CountryInstance::get_max_unlocked_unit_variant() } bool CountryInstance::modify_technology_unlock(Technology const& technology, unlock_level_t unlock_level_change) { - decltype(unlocked_technologies)::value_ref_t unlock_level = unlocked_technologies[technology]; + decltype(technology_unlock_levels)::value_ref_t unlock_level = technology_unlock_levels[technology]; // This catches subtracting below 0 or adding above the int types maximum value if (unlock_level + unlock_level_change < 0) { @@ -576,7 +578,7 @@ bool CountryInstance::modify_technology_unlock(Technology const& technology, unl } bool CountryInstance::set_technology_unlock_level(Technology const& technology, unlock_level_t unlock_level) { - const unlock_level_t unlock_level_change = unlock_level - unlocked_technologies[technology]; + const unlock_level_t unlock_level_change = unlock_level - technology_unlock_levels[technology]; return unlock_level_change != 0 ? modify_technology_unlock(technology, unlock_level_change) : true; } @@ -585,11 +587,11 @@ bool CountryInstance::unlock_technology(Technology const& technology) { } bool CountryInstance::is_technology_unlocked(Technology const& technology) const { - return unlocked_technologies[technology] > 0; + return technology_unlock_levels[technology] > 0; } bool CountryInstance::modify_invention_unlock(Invention const& invention, unlock_level_t unlock_level_change) { - decltype(unlocked_inventions)::value_ref_t unlock_level = unlocked_inventions[invention]; + decltype(invention_unlock_levels)::value_ref_t unlock_level = invention_unlock_levels[invention]; // This catches subtracting below 0 or adding above the int types maximum value if (unlock_level + unlock_level_change < 0) { @@ -628,7 +630,7 @@ bool CountryInstance::modify_invention_unlock(Invention const& invention, unlock } bool CountryInstance::set_invention_unlock_level(Invention const& invention, unlock_level_t unlock_level) { - const unlock_level_t unlock_level_change = unlock_level - unlocked_inventions[invention]; + const unlock_level_t unlock_level_change = unlock_level - invention_unlock_levels[invention]; return unlock_level_change != 0 ? modify_invention_unlock(invention, unlock_level_change) : true; } @@ -637,7 +639,7 @@ bool CountryInstance::unlock_invention(Invention const& invention) { } bool CountryInstance::is_invention_unlocked(Invention const& invention) const { - return unlocked_inventions[invention] > 0; + return invention_unlock_levels[invention] > 0; } bool CountryInstance::is_primary_culture(Culture const& culture) const { @@ -671,7 +673,7 @@ bool CountryInstance::apply_history_to_country( bool ret = true; - set_optional(primary_culture, entry.get_primary_culture()); + set_optional(primary_culture, entry.get_primary_culture()); for (auto const& [culture, add] : entry.get_accepted_cultures()) { if (add) { ret &= add_accepted_culture(*culture); @@ -927,6 +929,106 @@ bool CountryInstance::update_rule_set() { return rule_set.trim_and_resolve_conflicts(true); } +void CountryInstance::update_modifier_sum(Date today, StaticModifierCache const& static_modifier_cache) { + // Update sum of national modifiers + modifier_sum.clear(); + + const ModifierSum::modifier_source_t country_source { this }; + + // Erase expired event modifiers and add non-expired ones to the sum + std::erase_if(event_modifiers, [this, today, &country_source](ModifierInstance const& modifier) -> bool { + if (today <= modifier.get_expiry_date()) { + modifier_sum.add_modifier(*modifier.get_modifier(), country_source); + return false; + } else { + return true; + } + }); + + // Add static modifiers + modifier_sum.add_modifier_nullcheck(static_modifier_cache.get_base_modifier(), country_source); + + switch (country_status) { + using enum country_status_t; + case COUNTRY_STATUS_GREAT_POWER: + modifier_sum.add_modifier_nullcheck(static_modifier_cache.get_great_power(), country_source); + break; + case COUNTRY_STATUS_SECONDARY_POWER: + modifier_sum.add_modifier_nullcheck(static_modifier_cache.get_secondary_power(), country_source); + break; + case COUNTRY_STATUS_CIVILISED: + modifier_sum.add_modifier_nullcheck(static_modifier_cache.get_civilised(), country_source); + break; + default: + modifier_sum.add_modifier_nullcheck(static_modifier_cache.get_uncivilised(), country_source); + } + if (is_disarmed()) { + modifier_sum.add_modifier_nullcheck(static_modifier_cache.get_disarming(), country_source); + } + modifier_sum.add_modifier_nullcheck(static_modifier_cache.get_war_exhaustion(), country_source, war_exhaustion); + modifier_sum.add_modifier_nullcheck(static_modifier_cache.get_infamy(), country_source, infamy); + modifier_sum.add_modifier_nullcheck(static_modifier_cache.get_literacy(), country_source, national_literacy); + modifier_sum.add_modifier_nullcheck(static_modifier_cache.get_plurality(), country_source, plurality); + // TODO - difficulty modifiers, war, peace, debt_default_to, bad_debter, generalised_debt_default, + // total_occupation, total_blockaded, in_bankrupcy + + // TODO - handle triggered modifiers + + if (ruling_party != nullptr) { + for (Issue const* issue : ruling_party->get_policies()) { + // The ruling party's issues here could be null as they're stored in an IndexedMap which has + // values for every IssueGroup regardless of whether or not they have a policy set. + modifier_sum.add_modifier_nullcheck(issue, country_source); + } + } + + for (Reform const* reform : reforms) { + // The country's reforms here could be null as they're stored in an IndexedMap which has + // values for every ReformGroup regardless of whether or not they have a reform set. + modifier_sum.add_modifier_nullcheck(reform, country_source); + } + + modifier_sum.add_modifier_nullcheck(national_value, country_source); + + modifier_sum.add_modifier_nullcheck(tech_school, country_source); + + for (Technology const& technology : *technology_unlock_levels.get_keys()) { + if (is_technology_unlocked(technology)) { + modifier_sum.add_modifier(technology, country_source); + } + } + + for (Invention const& invention : *invention_unlock_levels.get_keys()) { + if (is_invention_unlocked(invention)) { + modifier_sum.add_modifier(invention, country_source); + } + } + + // Add province base modifiers (with local province modifier effects removed) + using enum ModifierEffect::target_t; + static constexpr ModifierEffect::target_t NOT_PROVINCE = ALL_TARGETS & ~PROVINCE; + + for (ProvinceInstance const* province : owned_provinces) { + modifier_sum.add_modifier_sum_filter_targets(province->get_modifier_sum(), NOT_PROVINCE); + } + + // This has to be done after adding all province modifiers to the country's sum, otherwise provinces earlier in the list + // wouldn't be affected by modifiers from provinces later in the list. + for (ProvinceInstance* province : owned_provinces) { + province->contribute_country_modifier_sum(modifier_sum); + } + + // TODO - calculate stats for each unit type (locked and unlocked) +} + +fixed_point_t CountryInstance::get_modifier_effect_value(ModifierEffect const& effect) const { + return modifier_sum.get_effect(effect); +} + +fixed_point_t CountryInstance::get_modifier_effect_value_nullcheck(ModifierEffect const* effect) const { + return modifier_sum.get_effect_nullcheck(effect); +} + void CountryInstance::update_gamestate(DefineManager const& define_manager, UnitTypeManager const& unit_type_manager) { // Order of updates might need to be changed/functions split up to account for dependencies _update_production(define_manager); @@ -1095,16 +1197,16 @@ CountryInstance const& CountryInstanceManager::get_country_instance_from_definit bool CountryInstanceManager::generate_country_instances( CountryDefinitionManager const& country_definition_manager, - decltype(CountryInstance::unlocked_building_types)::keys_t const& building_type_keys, - decltype(CountryInstance::unlocked_technologies)::keys_t const& technology_keys, - decltype(CountryInstance::unlocked_inventions)::keys_t const& invention_keys, + decltype(CountryInstance::building_type_unlock_levels)::keys_t const& building_type_keys, + decltype(CountryInstance::technology_unlock_levels)::keys_t const& technology_keys, + decltype(CountryInstance::invention_unlock_levels)::keys_t const& invention_keys, decltype(CountryInstance::upper_house)::keys_t const& ideology_keys, decltype(CountryInstance::reforms)::keys_t const& reform_keys, decltype(CountryInstance::government_flag_overrides)::keys_t const& government_type_keys, - decltype(CountryInstance::unlocked_crimes)::keys_t const& crime_keys, + decltype(CountryInstance::crime_unlock_levels)::keys_t const& crime_keys, decltype(CountryInstance::pop_type_distribution)::keys_t const& pop_type_keys, - decltype(CountryInstance::unlocked_regiment_types)::keys_t const& unlocked_regiment_types_keys, - decltype(CountryInstance::unlocked_ship_types)::keys_t const& unlocked_ship_types_keys + decltype(CountryInstance::regiment_type_unlock_levels)::keys_t const& regiment_type_unlock_levels_keys, + decltype(CountryInstance::ship_type_unlock_levels)::keys_t const& ship_type_unlock_levels_keys ) { reserve_more(country_instances, country_definition_manager.get_country_definition_count()); @@ -1121,8 +1223,8 @@ bool CountryInstanceManager::generate_country_instances( government_type_keys, crime_keys, pop_type_keys, - unlocked_regiment_types_keys, - unlocked_ship_types_keys + regiment_type_unlock_levels_keys, + ship_type_unlock_levels_keys }); } @@ -1171,6 +1273,12 @@ bool CountryInstanceManager::apply_history_to_countries( return ret; } +void CountryInstanceManager::update_modifier_sums(Date today, StaticModifierCache const& static_modifier_cache) { + for (CountryInstance& country : country_instances.get_items()) { + country.update_modifier_sum(today, static_modifier_cache); + } +} + void CountryInstanceManager::update_gamestate( Date today, DefineManager const& define_manager, UnitTypeManager const& unit_type_manager ) { -- cgit v1.2.3-56-ga3b1 From 3713393682c16fd5d3bed3e12fef68a1559c0cc5 Mon Sep 17 00:00:00 2001 From: hop311 Date: Mon, 30 Sep 2024 23:35:13 +0100 Subject: Add supply_consumption and mobilization_impact modifier effect check examples --- src/openvic-simulation/InstanceManager.cpp | 3 ++- src/openvic-simulation/country/CountryInstance.cpp | 23 ++++++++++++++-------- src/openvic-simulation/country/CountryInstance.hpp | 15 +++++++++++--- 3 files changed, 29 insertions(+), 12 deletions(-) (limited to 'src/openvic-simulation/country/CountryInstance.cpp') diff --git a/src/openvic-simulation/InstanceManager.cpp b/src/openvic-simulation/InstanceManager.cpp index 7f8a804..9c7804c 100644 --- a/src/openvic-simulation/InstanceManager.cpp +++ b/src/openvic-simulation/InstanceManager.cpp @@ -47,7 +47,8 @@ void InstanceManager::update_gamestate() { // Update gamestate... map_instance.update_gamestate(today, definition_manager.get_define_manager()); country_instance_manager.update_gamestate( - today, definition_manager.get_define_manager(), definition_manager.get_military_manager().get_unit_type_manager() + today, definition_manager.get_define_manager(), definition_manager.get_military_manager().get_unit_type_manager(), + definition_manager.get_modifier_manager().get_modifier_effect_cache() ); gamestate_updated(); diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index b3df096..be62fda 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -822,7 +822,10 @@ void CountryInstance::_update_diplomacy() { // TODO - update diplomatic points and colonial power } -void CountryInstance::_update_military(DefineManager const& define_manager, UnitTypeManager const& unit_type_manager) { +void CountryInstance::_update_military( + DefineManager const& define_manager, UnitTypeManager const& unit_type_manager, + ModifierEffectCache const& modifier_effect_cache +) { regiment_count = 0; for (ArmyInstance const* army : armies) { @@ -853,8 +856,8 @@ void CountryInstance::_update_military(DefineManager const& define_manager, Unit max_supported_regiment_count += state->get_max_supported_regiments(); } - // TODO - apply country/tech modifiers to supply consumption - supply_consumption = 1; + supply_consumption = + fixed_point_t::_1() + get_modifier_effect_value_nullcheck(modifier_effect_cache.get_supply_consumption()); const size_t regular_army_size = std::min(4 * deployed_non_mobilised_regiments, max_supported_regiment_count); @@ -896,7 +899,7 @@ void CountryInstance::_update_military(DefineManager const& define_manager, Unit military_power = military_power_from_land + military_power_from_sea + military_power_from_leaders; // Mobilisation calculations - mobilisation_impact = 0; // TODO - apply ruling party's war policy + mobilisation_impact = get_modifier_effect_value_nullcheck(modifier_effect_cache.get_mobilization_impact()); mobilisation_max_regiment_count = ((fixed_point_t::_1() + mobilisation_impact) * fixed_point_t::parse(regiment_count)).to_int64_t(); @@ -1029,7 +1032,10 @@ fixed_point_t CountryInstance::get_modifier_effect_value_nullcheck(ModifierEffec return modifier_sum.get_effect_nullcheck(effect); } -void CountryInstance::update_gamestate(DefineManager const& define_manager, UnitTypeManager const& unit_type_manager) { +void CountryInstance::update_gamestate( + DefineManager const& define_manager, UnitTypeManager const& unit_type_manager, + ModifierEffectCache const& modifier_effect_cache +) { // Order of updates might need to be changed/functions split up to account for dependencies _update_production(define_manager); _update_budget(); @@ -1038,7 +1044,7 @@ void CountryInstance::update_gamestate(DefineManager const& define_manager, Unit _update_population(); _update_trade(); _update_diplomacy(); - _update_military(define_manager, unit_type_manager); + _update_military(define_manager, unit_type_manager, modifier_effect_cache); total_score = prestige + industrial_power + military_power; @@ -1280,10 +1286,11 @@ void CountryInstanceManager::update_modifier_sums(Date today, StaticModifierCach } void CountryInstanceManager::update_gamestate( - Date today, DefineManager const& define_manager, UnitTypeManager const& unit_type_manager + Date today, DefineManager const& define_manager, UnitTypeManager const& unit_type_manager, + ModifierEffectCache const& modifier_effect_cache ) { for (CountryInstance& country : country_instances.get_items()) { - country.update_gamestate(define_manager, unit_type_manager); + country.update_gamestate(define_manager, unit_type_manager, modifier_effect_cache); } update_rankings(today, define_manager); diff --git a/src/openvic-simulation/country/CountryInstance.hpp b/src/openvic-simulation/country/CountryInstance.hpp index c9b61e3..8a5d234 100644 --- a/src/openvic-simulation/country/CountryInstance.hpp +++ b/src/openvic-simulation/country/CountryInstance.hpp @@ -295,7 +295,10 @@ namespace OpenVic { void _update_population(); void _update_trade(); void _update_diplomacy(); - void _update_military(DefineManager const& define_manager, UnitTypeManager const& unit_type_manager); + void _update_military( + DefineManager const& define_manager, UnitTypeManager const& unit_type_manager, + ModifierEffectCache const& modifier_effect_cache + ); bool update_rule_set(); @@ -305,7 +308,10 @@ namespace OpenVic { fixed_point_t get_modifier_effect_value(ModifierEffect const& effect) const; fixed_point_t get_modifier_effect_value_nullcheck(ModifierEffect const* effect) const; - void update_gamestate(DefineManager const& define_manager, UnitTypeManager const& unit_type_manager); + void update_gamestate( + DefineManager const& define_manager, UnitTypeManager const& unit_type_manager, + ModifierEffectCache const& modifier_effect_cache + ); void tick(); }; @@ -351,7 +357,10 @@ namespace OpenVic { ); void update_modifier_sums(Date today, StaticModifierCache const& static_modifier_cache); - void update_gamestate(Date today, DefineManager const& define_manager, UnitTypeManager const& unit_type_manager); + void update_gamestate( + Date today, DefineManager const& define_manager, UnitTypeManager const& unit_type_manager, + ModifierEffectCache const& modifier_effect_cache + ); void tick(); }; } -- cgit v1.2.3-56-ga3b1 From 6181851281876730d7db4bed18791fdbbe3cfbbc Mon Sep 17 00:00:00 2001 From: hop311 Date: Sun, 6 Oct 2024 00:08:44 +0100 Subject: Add alternative modifier calculation (keeping country modifiers out of their owned provinces' modifier sums) --- src/openvic-simulation/InstanceManager.cpp | 28 ++++++++-- src/openvic-simulation/country/CountryInstance.cpp | 39 +++++++++---- src/openvic-simulation/country/CountryInstance.hpp | 5 ++ src/openvic-simulation/map/ProvinceInstance.cpp | 65 +++++++++++++++++++++- src/openvic-simulation/map/ProvinceInstance.hpp | 11 +++- src/openvic-simulation/modifier/ModifierSum.cpp | 17 ++++-- src/openvic-simulation/modifier/ModifierSum.hpp | 1 + 7 files changed, 142 insertions(+), 24 deletions(-) (limited to 'src/openvic-simulation/country/CountryInstance.cpp') diff --git a/src/openvic-simulation/InstanceManager.cpp b/src/openvic-simulation/InstanceManager.cpp index 9c7804c..a33acdb 100644 --- a/src/openvic-simulation/InstanceManager.cpp +++ b/src/openvic-simulation/InstanceManager.cpp @@ -39,10 +39,30 @@ void InstanceManager::update_gamestate() { Logger::info("Update: ", today); - map_instance.update_modifier_sums(today, definition_manager.get_modifier_manager().get_static_modifier_cache()); - country_instance_manager.update_modifier_sums( - today, definition_manager.get_modifier_manager().get_static_modifier_cache() - ); + if constexpr (ProvinceInstance::ADD_OWNER_CONTRIBUTION) { + // Calculate local province modifier sums first, then national country modifier sums, then loop over owned provinces + // adding their contributions to the owner country's modifier sum and loop over them again to add the country's total + // (including province contributions) to the provinces' modifier sum. This results in every country and province + // having a full copy of all the modifiers affecting them in their modifier sum. + map_instance.update_modifier_sums( + today, definition_manager.get_modifier_manager().get_static_modifier_cache() + ); + country_instance_manager.update_modifier_sums( + today, definition_manager.get_modifier_manager().get_static_modifier_cache() + ); + } else { + // Calculate national country modifier sums first, then local province modifier sums, adding province contributions + // to owner countries' modifier sums if each province has an owner. This results in every country having a full copy + // of all the modifiers affecting them in their modifier sum, but provinces only having their directly/locally applied + // modifiers in their modifier sum, hence requiring both province and owner country modifier effect values to be looked + // up and added together to get the full effect on the province. + country_instance_manager.update_modifier_sums( + today, definition_manager.get_modifier_manager().get_static_modifier_cache() + ); + map_instance.update_modifier_sums( + today, definition_manager.get_modifier_manager().get_static_modifier_cache() + ); + } // Update gamestate... map_instance.update_gamestate(today, definition_manager.get_define_manager()); diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index be62fda..f04dfc6 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -1007,23 +1007,30 @@ void CountryInstance::update_modifier_sum(Date today, StaticModifierCache const& } } - // Add province base modifiers (with local province modifier effects removed) - using enum ModifierEffect::target_t; - static constexpr ModifierEffect::target_t NOT_PROVINCE = ALL_TARGETS & ~PROVINCE; - - for (ProvinceInstance const* province : owned_provinces) { - modifier_sum.add_modifier_sum_filter_targets(province->get_modifier_sum(), NOT_PROVINCE); - } + if constexpr (ProvinceInstance::ADD_OWNER_CONTRIBUTION) { + // Add province base modifiers (with local province modifier effects removed) + for (ProvinceInstance const* province : owned_provinces) { + contribute_province_modifier_sum(province->get_modifier_sum()); + } - // This has to be done after adding all province modifiers to the country's sum, otherwise provinces earlier in the list - // wouldn't be affected by modifiers from provinces later in the list. - for (ProvinceInstance* province : owned_provinces) { - province->contribute_country_modifier_sum(modifier_sum); + // This has to be done after adding all province modifiers to the country's sum, otherwise provinces + // earlier in the list wouldn't be affected by modifiers from provinces later in the list. + for (ProvinceInstance* province : owned_provinces) { + province->contribute_country_modifier_sum(modifier_sum); + } } // TODO - calculate stats for each unit type (locked and unlocked) } +void CountryInstance::contribute_province_modifier_sum(ModifierSum const& province_modifier_sum) { + using enum ModifierEffect::target_t; + + static constexpr ModifierEffect::target_t NOT_PROVINCE = ALL_TARGETS & ~PROVINCE; + + modifier_sum.add_modifier_sum_filter_targets(province_modifier_sum, NOT_PROVINCE); +} + fixed_point_t CountryInstance::get_modifier_effect_value(ModifierEffect const& effect) const { return modifier_sum.get_effect(effect); } @@ -1032,6 +1039,16 @@ fixed_point_t CountryInstance::get_modifier_effect_value_nullcheck(ModifierEffec return modifier_sum.get_effect_nullcheck(effect); } +void CountryInstance::push_contributing_modifiers( + ModifierEffect const& effect, std::vector& contributions +) const { + modifier_sum.push_contributing_modifiers(effect, contributions); +} + +std::vector CountryInstance::get_contributing_modifiers(ModifierEffect const& effect) const { + return modifier_sum.get_contributing_modifiers(effect); +} + void CountryInstance::update_gamestate( DefineManager const& define_manager, UnitTypeManager const& unit_type_manager, ModifierEffectCache const& modifier_effect_cache diff --git a/src/openvic-simulation/country/CountryInstance.hpp b/src/openvic-simulation/country/CountryInstance.hpp index 8a5d234..5e42f1d 100644 --- a/src/openvic-simulation/country/CountryInstance.hpp +++ b/src/openvic-simulation/country/CountryInstance.hpp @@ -305,8 +305,13 @@ namespace OpenVic { public: void update_modifier_sum(Date today, StaticModifierCache const& static_modifier_cache); + void contribute_province_modifier_sum(ModifierSum const& province_modifier_sum); fixed_point_t get_modifier_effect_value(ModifierEffect const& effect) const; fixed_point_t get_modifier_effect_value_nullcheck(ModifierEffect const* effect) const; + void push_contributing_modifiers( + ModifierEffect const& effect, std::vector& contributions + ) const; + std::vector get_contributing_modifiers(ModifierEffect const& effect) const; void update_gamestate( DefineManager const& define_manager, UnitTypeManager const& unit_type_manager, diff --git a/src/openvic-simulation/map/ProvinceInstance.cpp b/src/openvic-simulation/map/ProvinceInstance.cpp index e85c576..949a2a3 100644 --- a/src/openvic-simulation/map/ProvinceInstance.cpp +++ b/src/openvic-simulation/map/ProvinceInstance.cpp @@ -235,6 +235,12 @@ void ProvinceInstance::update_modifier_sum(Date today, StaticModifierCache const modifier_sum.add_modifier_nullcheck(province_definition.get_climate(), province_source); modifier_sum.add_modifier_nullcheck(terrain_type, province_source); + + if constexpr (!ADD_OWNER_CONTRIBUTION) { + if (owner != nullptr) { + owner->contribute_province_modifier_sum(modifier_sum); + } + } } void ProvinceInstance::contribute_country_modifier_sum(ModifierSum const& owner_modifier_sum) { @@ -242,11 +248,66 @@ void ProvinceInstance::contribute_country_modifier_sum(ModifierSum const& owner_ } fixed_point_t ProvinceInstance::get_modifier_effect_value(ModifierEffect const& effect) const { - return modifier_sum.get_effect(effect); + if constexpr (ADD_OWNER_CONTRIBUTION) { + return modifier_sum.get_effect(effect); + } else { + using enum ModifierEffect::target_t; + + if (owner != nullptr) { + if ((effect.get_targets() & PROVINCE) == NO_TARGETS) { + // Non-province targeted effects are already added to the country modifier sum + return owner->get_modifier_effect_value(effect); + } else { + // Province-targeted effects aren't passed to the country modifier sum + return owner->get_modifier_effect_value(effect) + modifier_sum.get_effect(effect); + } + } else { + return modifier_sum.get_effect(effect); + } + } } fixed_point_t ProvinceInstance::get_modifier_effect_value_nullcheck(ModifierEffect const* effect) const { - return modifier_sum.get_effect_nullcheck(effect); + if (effect != nullptr) { + return get_modifier_effect_value(*effect); + } else { + return fixed_point_t::_0(); + } +} + +void ProvinceInstance::push_contributing_modifiers( + ModifierEffect const& effect, std::vector& contributions +) const { + if constexpr (ADD_OWNER_CONTRIBUTION) { + modifier_sum.push_contributing_modifiers(effect, contributions); + } else { + using enum ModifierEffect::target_t; + + if (owner != nullptr) { + if ((effect.get_targets() & PROVINCE) == NO_TARGETS) { + // Non-province targeted effects are already added to the country modifier sum + owner->push_contributing_modifiers(effect, contributions); + } else { + // Province-targeted effects aren't passed to the country modifier sum + modifier_sum.push_contributing_modifiers(effect, contributions); + owner->push_contributing_modifiers(effect, contributions); + } + } else { + modifier_sum.push_contributing_modifiers(effect, contributions); + } + } +} + +std::vector ProvinceInstance::get_contributing_modifiers(ModifierEffect const& effect) const { + if constexpr (ADD_OWNER_CONTRIBUTION) { + return modifier_sum.get_contributing_modifiers(effect); + } else { + std::vector contributions; + + push_contributing_modifiers(effect, contributions); + + return contributions; + } } void ProvinceInstance::update_gamestate(Date today, DefineManager const& define_manager) { diff --git a/src/openvic-simulation/map/ProvinceInstance.hpp b/src/openvic-simulation/map/ProvinceInstance.hpp index 0b02c41..91e8ee1 100644 --- a/src/openvic-simulation/map/ProvinceInstance.hpp +++ b/src/openvic-simulation/map/ProvinceInstance.hpp @@ -69,7 +69,12 @@ namespace OpenVic { CountryInstance* PROPERTY(controller); ordered_set PROPERTY(cores); - // The total/resultant modifier affecting this province, including owner country contributions. + public: + static constexpr bool ADD_OWNER_CONTRIBUTION = true; + + private: + // The total/resultant modifier affecting this province, including owner country contributions if + // ADD_OWNER_CONTRIBUTION is true. ModifierSum PROPERTY(modifier_sum); std::vector PROPERTY(event_modifiers); @@ -133,6 +138,10 @@ namespace OpenVic { void contribute_country_modifier_sum(ModifierSum const& owner_modifier_sum); fixed_point_t get_modifier_effect_value(ModifierEffect const& effect) const; fixed_point_t get_modifier_effect_value_nullcheck(ModifierEffect const* effect) const; + void push_contributing_modifiers( + ModifierEffect const& effect, std::vector& contributions + ) const; + std::vector get_contributing_modifiers(ModifierEffect const& effect) const; void update_gamestate(Date today, DefineManager const& define_manager); void tick(Date today); diff --git a/src/openvic-simulation/modifier/ModifierSum.cpp b/src/openvic-simulation/modifier/ModifierSum.cpp index 09cb36d..a3b8cd5 100644 --- a/src/openvic-simulation/modifier/ModifierSum.cpp +++ b/src/openvic-simulation/modifier/ModifierSum.cpp @@ -70,23 +70,28 @@ void ModifierSum::add_modifier_sum_exclude_source(ModifierSum const& modifier_su } // TODO - include value_sum[effect] in result? Early return if lookup in value_sum fails? -std::vector ModifierSum::get_contributing_modifiers( - ModifierEffect const& effect + +void ModifierSum::push_contributing_modifiers( + ModifierEffect const& effect, std::vector& contributions ) const { using enum ModifierEffect::target_t; - std::vector ret; - for (modifier_entry_t const& modifier_entry : modifiers) { if ((modifier_entry.targets & effect.get_targets()) != NO_TARGETS) { bool effect_found = false; const fixed_point_t value = modifier_entry.modifier->get_effect(effect, &effect_found); if (effect_found) { - ret.push_back(modifier_entry); + contributions.push_back(modifier_entry); } } } +} + +std::vector ModifierSum::get_contributing_modifiers(ModifierEffect const& effect) const { + std::vector contributions; + + push_contributing_modifiers(effect, contributions); - return ret; + return contributions; } diff --git a/src/openvic-simulation/modifier/ModifierSum.hpp b/src/openvic-simulation/modifier/ModifierSum.hpp index 0ca8caa..7c1b238 100644 --- a/src/openvic-simulation/modifier/ModifierSum.hpp +++ b/src/openvic-simulation/modifier/ModifierSum.hpp @@ -55,6 +55,7 @@ namespace OpenVic { void add_modifier_sum_filter_targets(ModifierSum const& modifier_sum, ModifierEffect::target_t targets); void add_modifier_sum_exclude_source(ModifierSum const& modifier_sum, modifier_source_t const& excluded_source); + void push_contributing_modifiers(ModifierEffect const& effect, std::vector& contributions) const; std::vector get_contributing_modifiers(ModifierEffect const& effect) const; }; } -- cgit v1.2.3-56-ga3b1 From 18ab144ec4ecf1efca68a26bc79b9d54e28e54f8 Mon Sep 17 00:00:00 2001 From: hop311 Date: Fri, 18 Oct 2024 23:53:32 +0100 Subject: Move ModifierManager to its own files --- src/openvic-simulation/DefinitionManager.hpp | 2 +- src/openvic-simulation/country/CountryInstance.cpp | 2 + src/openvic-simulation/country/CountryInstance.hpp | 2 + src/openvic-simulation/economy/BuildingType.cpp | 2 + src/openvic-simulation/economy/GoodDefinition.cpp | 2 +- src/openvic-simulation/map/Crime.cpp | 2 + src/openvic-simulation/map/MapDefinition.cpp | 1 + src/openvic-simulation/map/ProvinceInstance.cpp | 1 + src/openvic-simulation/map/ProvinceInstance.hpp | 1 + src/openvic-simulation/map/TerrainType.cpp | 1 + src/openvic-simulation/military/LeaderTrait.cpp | 2 + src/openvic-simulation/military/UnitType.cpp | 1 + src/openvic-simulation/modifier/Modifier.cpp | 706 --------------------- src/openvic-simulation/modifier/Modifier.hpp | 126 +--- .../modifier/ModifierManager.cpp | 692 ++++++++++++++++++++ .../modifier/ModifierManager.hpp | 127 ++++ src/openvic-simulation/modifier/ModifierValue.cpp | 9 + .../modifier/StaticModifierCache.cpp | 2 +- src/openvic-simulation/politics/Issue.cpp | 2 + src/openvic-simulation/politics/NationalFocus.cpp | 1 + src/openvic-simulation/politics/NationalValue.cpp | 2 + src/openvic-simulation/politics/Rebel.cpp | 2 +- src/openvic-simulation/pop/Pop.cpp | 1 + src/openvic-simulation/research/Invention.cpp | 8 +- src/openvic-simulation/research/Technology.cpp | 2 + 25 files changed, 864 insertions(+), 835 deletions(-) create mode 100644 src/openvic-simulation/modifier/ModifierManager.cpp create mode 100644 src/openvic-simulation/modifier/ModifierManager.hpp (limited to 'src/openvic-simulation/country/CountryInstance.cpp') diff --git a/src/openvic-simulation/DefinitionManager.hpp b/src/openvic-simulation/DefinitionManager.hpp index 887cc1b..b5df507 100644 --- a/src/openvic-simulation/DefinitionManager.hpp +++ b/src/openvic-simulation/DefinitionManager.hpp @@ -14,7 +14,7 @@ #include "openvic-simulation/misc/Event.hpp" #include "openvic-simulation/misc/SongChance.hpp" #include "openvic-simulation/misc/SoundEffect.hpp" -#include "openvic-simulation/modifier/Modifier.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/politics/PoliticsManager.hpp" #include "openvic-simulation/pop/Pop.hpp" #include "openvic-simulation/research/ResearchManager.hpp" diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index f04dfc6..aceae11 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -5,6 +5,8 @@ #include "openvic-simulation/map/Crime.hpp" #include "openvic-simulation/map/MapInstance.hpp" #include "openvic-simulation/misc/Define.hpp" +#include "openvic-simulation/modifier/ModifierEffectCache.hpp" +#include "openvic-simulation/modifier/StaticModifierCache.hpp" #include "openvic-simulation/politics/Ideology.hpp" #include "openvic-simulation/research/Invention.hpp" #include "openvic-simulation/research/Technology.hpp" diff --git a/src/openvic-simulation/country/CountryInstance.hpp b/src/openvic-simulation/country/CountryInstance.hpp index 5e42f1d..ea30c0d 100644 --- a/src/openvic-simulation/country/CountryInstance.hpp +++ b/src/openvic-simulation/country/CountryInstance.hpp @@ -35,6 +35,8 @@ namespace OpenVic { struct CountryHistoryEntry; struct MapInstance; struct DefineManager; + struct ModifierEffectCache; + struct StaticModifierCache; /* Representation of a country's mutable attributes, with a CountryDefinition that is unique at any single time * but can be swapped with other CountryInstance's CountryDefinition when switching tags. */ diff --git a/src/openvic-simulation/economy/BuildingType.cpp b/src/openvic-simulation/economy/BuildingType.cpp index 3733a5f..278cde4 100644 --- a/src/openvic-simulation/economy/BuildingType.cpp +++ b/src/openvic-simulation/economy/BuildingType.cpp @@ -1,5 +1,7 @@ #include "BuildingType.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" + using namespace OpenVic; using namespace OpenVic::NodeTools; diff --git a/src/openvic-simulation/economy/GoodDefinition.cpp b/src/openvic-simulation/economy/GoodDefinition.cpp index 25281bb..f8bd9b7 100644 --- a/src/openvic-simulation/economy/GoodDefinition.cpp +++ b/src/openvic-simulation/economy/GoodDefinition.cpp @@ -1,6 +1,6 @@ #include "GoodDefinition.hpp" -#include "openvic-simulation/modifier/Modifier.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; diff --git a/src/openvic-simulation/map/Crime.cpp b/src/openvic-simulation/map/Crime.cpp index fb521ad..532be9d 100644 --- a/src/openvic-simulation/map/Crime.cpp +++ b/src/openvic-simulation/map/Crime.cpp @@ -1,5 +1,7 @@ #include "Crime.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" + using namespace OpenVic; using namespace OpenVic::NodeTools; diff --git a/src/openvic-simulation/map/MapDefinition.cpp b/src/openvic-simulation/map/MapDefinition.cpp index 828a679..50fba7d 100644 --- a/src/openvic-simulation/map/MapDefinition.cpp +++ b/src/openvic-simulation/map/MapDefinition.cpp @@ -3,6 +3,7 @@ #include #include +#include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/types/Vector.hpp" diff --git a/src/openvic-simulation/map/ProvinceInstance.cpp b/src/openvic-simulation/map/ProvinceInstance.cpp index 949a2a3..57a33a4 100644 --- a/src/openvic-simulation/map/ProvinceInstance.cpp +++ b/src/openvic-simulation/map/ProvinceInstance.cpp @@ -8,6 +8,7 @@ #include "openvic-simulation/map/TerrainType.hpp" #include "openvic-simulation/military/UnitInstanceGroup.hpp" #include "openvic-simulation/misc/Define.hpp" +#include "openvic-simulation/modifier/StaticModifierCache.hpp" #include "openvic-simulation/politics/Ideology.hpp" using namespace OpenVic; diff --git a/src/openvic-simulation/map/ProvinceInstance.hpp b/src/openvic-simulation/map/ProvinceInstance.hpp index 91e8ee1..e7c0326 100644 --- a/src/openvic-simulation/map/ProvinceInstance.hpp +++ b/src/openvic-simulation/map/ProvinceInstance.hpp @@ -22,6 +22,7 @@ namespace OpenVic { struct Ideology; struct Culture; struct Religion; + struct StaticModifierCache; struct BuildingTypeManager; struct ProvinceHistoryEntry; struct IssueManager; diff --git a/src/openvic-simulation/map/TerrainType.cpp b/src/openvic-simulation/map/TerrainType.cpp index b4cc430..2f8423d 100644 --- a/src/openvic-simulation/map/TerrainType.cpp +++ b/src/openvic-simulation/map/TerrainType.cpp @@ -1,5 +1,6 @@ #include "TerrainType.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/types/Colour.hpp" using namespace OpenVic; diff --git a/src/openvic-simulation/military/LeaderTrait.cpp b/src/openvic-simulation/military/LeaderTrait.cpp index da7331a..4378a67 100644 --- a/src/openvic-simulation/military/LeaderTrait.cpp +++ b/src/openvic-simulation/military/LeaderTrait.cpp @@ -1,5 +1,7 @@ #include "LeaderTrait.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" + using namespace OpenVic; using namespace OpenVic::NodeTools; diff --git a/src/openvic-simulation/military/UnitType.cpp b/src/openvic-simulation/military/UnitType.cpp index 004f766..815025a 100644 --- a/src/openvic-simulation/military/UnitType.cpp +++ b/src/openvic-simulation/military/UnitType.cpp @@ -2,6 +2,7 @@ #include "openvic-simulation/country/CountryInstance.hpp" #include "openvic-simulation/map/TerrainType.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; diff --git a/src/openvic-simulation/modifier/Modifier.cpp b/src/openvic-simulation/modifier/Modifier.cpp index 4e10c76..962d2d4 100644 --- a/src/openvic-simulation/modifier/Modifier.cpp +++ b/src/openvic-simulation/modifier/Modifier.cpp @@ -1,15 +1,6 @@ #include "Modifier.hpp" -#include - -#include - -#include - -#include "openvic-simulation/types/OrderedContainers.hpp" - using namespace OpenVic; -using namespace OpenVic::NodeTools; Modifier::Modifier(std::string_view new_identifier, ModifierValue&& new_values, modifier_type_t new_type) : HasIdentifier { new_identifier }, ModifierValue { std::move(new_values) }, type { new_type } {} @@ -29,700 +20,3 @@ bool TriggeredModifier::parse_scripts(DefinitionManager const& definition_manage ModifierInstance::ModifierInstance(Modifier const& new_modifier, Date new_expiry_date) : modifier { &new_modifier }, expiry_date { new_expiry_date } {} - -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 -) { - if (identifier.empty()) { - Logger::error("Invalid modifier effect identifier - empty!"); - return false; - } - - if (effect_cache != nullptr) { - Logger::error( - "Cache variable for modifier effect \"", identifier, "\" is already filled with modifier effect \"", - effect_cache->get_identifier(), "\"" - ); - return false; - } - - const bool ret = modifier_effects.add_item({ std::move(identifier), positive_good, format, targets, localisation_key }); - - if (ret) { - effect_cache = &modifier_effects.get_items().back(); - } - - return ret; -} - -bool ModifierManager::setup_modifier_effects() { - bool ret = true; - - using enum ModifierEffect::format_t; - using enum ModifierEffect::target_t; - - /* Tech/inventions only */ - ret &= add_modifier_effect( - modifier_effect_cache.cb_creation_speed, "cb_creation_speed", true, PROPORTION_DECIMAL, COUNTRY, "CB_MANUFACTURE_TECH" - ); - ret &= add_modifier_effect(modifier_effect_cache.combat_width, "combat_width", false, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.plurality, "plurality", true, PERCENTAGE_DECIMAL, COUNTRY, "TECH_PLURALITY" - ); - ret &= add_modifier_effect( - modifier_effect_cache.pop_growth, "pop_growth", true, PROPORTION_DECIMAL, COUNTRY, "TECH_POP_GROWTH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.regular_experience_level, "regular_experience_level", true, RAW_DECIMAL, COUNTRY, - "REGULAR_EXP_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.reinforce_rate, "reinforce_rate", true, PROPORTION_DECIMAL, COUNTRY, "REINFORCE_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.separatism, "seperatism", // paradox typo - false, PROPORTION_DECIMAL, COUNTRY, "SEPARATISM_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.shared_prestige, "shared_prestige", true, RAW_DECIMAL, COUNTRY, "SHARED_PRESTIGE_TECH" - ); - ret &= add_modifier_effect(modifier_effect_cache.tax_eff, "tax_eff", true, PERCENTAGE_DECIMAL, COUNTRY, "TECH_TAX_EFF"); - - /* Country Modifier Effects */ - ret &= add_modifier_effect( - modifier_effect_cache.administrative_efficiency, "administrative_efficiency", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.administrative_efficiency_modifier, "administrative_efficiency_modifier", true, - PROPORTION_DECIMAL, COUNTRY, ModifierEffect::make_default_modifier_effect_localisation_key("administrative_efficiency") - ); - ret &= add_modifier_effect(modifier_effect_cache.artisan_input, "artisan_input", false, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect(modifier_effect_cache.artisan_output, "artisan_output", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.artisan_throughput, "artisan_throughput", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect(modifier_effect_cache.badboy, "badboy", false, RAW_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.cb_generation_speed_modifier, "cb_generation_speed_modifier", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.civilization_progress_modifier, "civilization_progress_modifier", true, PROPORTION_DECIMAL, - COUNTRY, ModifierEffect::make_default_modifier_effect_localisation_key("civilization_progress") - ); - ret &= add_modifier_effect( - modifier_effect_cache.colonial_life_rating, "colonial_life_rating", false, INT, COUNTRY, "COLONIAL_LIFE_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.colonial_migration, "colonial_migration", true, PROPORTION_DECIMAL, COUNTRY, - "COLONIAL_MIGRATION_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.colonial_points, "colonial_points", true, INT, COUNTRY, "COLONIAL_POINTS_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.colonial_prestige, "colonial_prestige", true, PROPORTION_DECIMAL, COUNTRY, - "COLONIAL_PRESTIGE_MODIFIER_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.core_pop_consciousness_modifier, "core_pop_consciousness_modifier", false, RAW_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.core_pop_militancy_modifier, "core_pop_militancy_modifier", false, RAW_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect(modifier_effect_cache.dig_in_cap, "dig_in_cap", true, INT, COUNTRY, "DIGIN_FROM_TECH"); - ret &= add_modifier_effect( - modifier_effect_cache.diplomatic_points, "diplomatic_points", true, PROPORTION_DECIMAL, COUNTRY, - "DIPLOMATIC_POINTS_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.diplomatic_points_modifier, "diplomatic_points_modifier", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("diplopoints_gain") - ); - ret &= add_modifier_effect( - modifier_effect_cache.education_efficiency, "education_efficiency", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.education_efficiency_modifier, "education_efficiency_modifier", true, PROPORTION_DECIMAL, - COUNTRY, ModifierEffect::make_default_modifier_effect_localisation_key("education_efficiency") - ); - ret &= add_modifier_effect(modifier_effect_cache.factory_cost, "factory_cost", false, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect(modifier_effect_cache.factory_input, "factory_input", false, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.factory_maintenance, "factory_maintenance", false, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect(modifier_effect_cache.factory_output, "factory_output", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.factory_owner_cost, "factory_owner_cost", false, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.factory_throughput, "factory_throughput", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.global_assimilation_rate, "global_assimilation_rate", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("assimilation_rate") - ); - ret &= add_modifier_effect( - modifier_effect_cache.global_immigrant_attract, "global_immigrant_attract", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("immigant_attract") - ); - ret &= add_modifier_effect( - modifier_effect_cache.global_pop_consciousness_modifier, "global_pop_consciousness_modifier", false, RAW_DECIMAL, - COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.global_pop_militancy_modifier, "global_pop_militancy_modifier", false, RAW_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.global_population_growth, "global_population_growth", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("population_growth") - ); - ret &= add_modifier_effect(modifier_effect_cache.goods_demand, "goods_demand", false, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect(modifier_effect_cache.import_cost, "import_cost", false, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.increase_research, "increase_research", true, PROPORTION_DECIMAL, COUNTRY, "INC_RES_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.influence, "influence", true, PROPORTION_DECIMAL, COUNTRY, "TECH_GP_INFLUENCE" - ); - ret &= add_modifier_effect( - modifier_effect_cache.influence_modifier, "influence_modifier", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("greatpower_influence_gain") - ); - ret &= add_modifier_effect( - modifier_effect_cache.issue_change_speed, "issue_change_speed", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.land_attack_modifier, "land_attack_modifier", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("land_attack") - ); - ret &= add_modifier_effect( - modifier_effect_cache.land_attrition, "land_attrition", false, PROPORTION_DECIMAL, COUNTRY, "LAND_ATTRITION_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.land_defense_modifier, "land_defense_modifier", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("land_defense") - ); - ret &= add_modifier_effect( - modifier_effect_cache.land_organisation, "land_organisation", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.land_unit_start_experience, "land_unit_start_experience", true, RAW_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect(modifier_effect_cache.leadership, "leadership", true, RAW_DECIMAL, COUNTRY, "LEADERSHIP"); - ret &= add_modifier_effect( - modifier_effect_cache.leadership_modifier, "leadership_modifier", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("global_leadership_modifier") - ); - ret &= add_modifier_effect( - modifier_effect_cache.literacy_con_impact, "literacy_con_impact", false, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect(modifier_effect_cache.loan_interest, "loan_interest", false, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.max_loan_modifier, "max_loan_modifier", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("max_loan_amount") - ); - ret &= add_modifier_effect( - modifier_effect_cache.max_military_spending, "max_military_spending", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.max_national_focus, "max_national_focus", true, INT, COUNTRY, "TECH_MAX_FOCUS" - ); - ret &= add_modifier_effect( - modifier_effect_cache.max_social_spending, "max_social_spending", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect(modifier_effect_cache.max_tariff, "max_tariff", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect(modifier_effect_cache.max_tax, "max_tax", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.max_war_exhaustion, "max_war_exhaustion", true, PERCENTAGE_DECIMAL, COUNTRY, "MAX_WAR_EXHAUSTION" - ); - ret &= add_modifier_effect( - modifier_effect_cache.military_tactics, "military_tactics", true, PROPORTION_DECIMAL, COUNTRY, "MIL_TACTICS_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.min_military_spending, "min_military_spending", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.min_social_spending, "min_social_spending", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect(modifier_effect_cache.min_tariff, "min_tariff", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect(modifier_effect_cache.min_tax, "min_tax", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.minimum_wage, "minimum_wage", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("minimun_wage") - ); - ret &= add_modifier_effect( - modifier_effect_cache.mobilisation_economy_impact, "mobilisation_economy_impact", false, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.mobilisation_size, "mobilisation_size", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.mobilization_impact, "mobilization_impact", false, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.naval_attack_modifier, "naval_attack_modifier", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("naval_attack") - ); - ret &= add_modifier_effect( - modifier_effect_cache.naval_attrition, "naval_attrition", false, PROPORTION_DECIMAL, COUNTRY, "NAVAL_ATTRITION_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.naval_defense_modifier, "naval_defense_modifier", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("naval_defense") - ); - ret &= add_modifier_effect( - modifier_effect_cache.naval_organisation, "naval_organisation", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.naval_unit_start_experience, "naval_unit_start_experience", true, RAW_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.non_accepted_pop_consciousness_modifier, "non_accepted_pop_consciousness_modifier", false, - RAW_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.non_accepted_pop_militancy_modifier, "non_accepted_pop_militancy_modifier", false, RAW_DECIMAL, - COUNTRY - ); - ret &= add_modifier_effect(modifier_effect_cache.org_regain, "org_regain", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect(modifier_effect_cache.pension_level, "pension_level", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.permanent_prestige, "permanent_prestige", true, RAW_DECIMAL, COUNTRY, "PERMANENT_PRESTIGE_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.political_reform_desire, "political_reform_desire", false, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.poor_savings_modifier, "poor_savings_modifier", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect(modifier_effect_cache.prestige, "prestige", true, RAW_DECIMAL, COUNTRY); - ret &= add_modifier_effect(modifier_effect_cache.reinforce_speed, "reinforce_speed", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect(modifier_effect_cache.research_points, "research_points", true, RAW_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.research_points_modifier, "research_points_modifier", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.research_points_on_conquer, "research_points_on_conquer", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect(modifier_effect_cache.rgo_output, "rgo_output", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect(modifier_effect_cache.rgo_throughput, "rgo_throughput", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.ruling_party_support, "ruling_party_support", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.self_unciv_economic_modifier, "self_unciv_economic_modifier", false, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("self_unciv_economic") - ); - ret &= add_modifier_effect( - modifier_effect_cache.self_unciv_military_modifier, "self_unciv_military_modifier", false, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("self_unciv_military") - ); - ret &= add_modifier_effect( - modifier_effect_cache.social_reform_desire, "social_reform_desire", false, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.soldier_to_pop_loss, "soldier_to_pop_loss", true, PROPORTION_DECIMAL, COUNTRY, - "SOLDIER_TO_POP_LOSS_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.supply_consumption, "supply_consumption", false, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.supply_range, "supply_range", true, PROPORTION_DECIMAL, COUNTRY, "SUPPLY_RANGE_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.suppression_points_modifier, "suppression_points_modifier", true, PROPORTION_DECIMAL, COUNTRY, - "SUPPRESSION_TECH" - ); - ret &= add_modifier_effect( - modifier_effect_cache.tariff_efficiency_modifier, "tariff_efficiency_modifier", true, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("tariff_efficiency") - ); - ret &= add_modifier_effect(modifier_effect_cache.tax_efficiency, "tax_efficiency", true, PROPORTION_DECIMAL, COUNTRY); - ret &= add_modifier_effect( - modifier_effect_cache.unemployment_benefit, "unemployment_benefit", true, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.unciv_economic_modifier, "unciv_economic_modifier", false, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("unciv_economic") - ); - ret &= add_modifier_effect( - modifier_effect_cache.unciv_military_modifier, "unciv_military_modifier", false, PROPORTION_DECIMAL, COUNTRY, - ModifierEffect::make_default_modifier_effect_localisation_key("unciv_military") - ); - ret &= add_modifier_effect( - modifier_effect_cache.unit_recruitment_time, "unit_recruitment_time", false, PROPORTION_DECIMAL, COUNTRY - ); - ret &= add_modifier_effect( - modifier_effect_cache.war_exhaustion, "war_exhaustion", false, PROPORTION_DECIMAL, COUNTRY, "WAR_EXHAUST_BATTLES" - ); - - /* Province Modifier Effects */ - ret &= add_modifier_effect( - modifier_effect_cache.assimilation_rate, "assimilation_rate", true, PROPORTION_DECIMAL, PROVINCE - ); - ret &= add_modifier_effect( - modifier_effect_cache.boost_strongest_party, "boost_strongest_party", false, PROPORTION_DECIMAL, PROVINCE - ); - ret &= add_modifier_effect( - modifier_effect_cache.farm_rgo_eff, "farm_rgo_eff", true, PROPORTION_DECIMAL, PROVINCE, "TECH_FARM_OUTPUT" - ); - ret &= add_modifier_effect( - modifier_effect_cache.farm_rgo_size, "farm_rgo_size", true, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("farm_size") - ); - ret &= add_modifier_effect( - modifier_effect_cache.immigrant_attract, "immigrant_attract", true, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("immigant_attract") - ); - ret &= add_modifier_effect( - modifier_effect_cache.immigrant_push, "immigrant_push", false, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("immigant_push") - ); - ret &= add_modifier_effect(modifier_effect_cache.life_rating, "life_rating", true, PROPORTION_DECIMAL, PROVINCE); - ret &= add_modifier_effect( - modifier_effect_cache.local_artisan_input, "local_artisan_input", false, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("artisan_input") - ); - ret &= add_modifier_effect( - modifier_effect_cache.local_artisan_output, "local_artisan_output", true, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("artisan_output") - ); - ret &= add_modifier_effect( - modifier_effect_cache.local_artisan_throughput, "local_artisan_throughput", true, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("artisan_throughput") - ); - ret &= add_modifier_effect( - modifier_effect_cache.local_factory_input, "local_factory_input", false, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("factory_input") - ); - ret &= add_modifier_effect( - modifier_effect_cache.local_factory_output, "local_factory_output", true, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("factory_output") - ); - ret &= add_modifier_effect( - modifier_effect_cache.local_factory_throughput, "local_factory_throughput", true, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("factory_throughput") - ); - ret &= add_modifier_effect(modifier_effect_cache.local_repair, "local_repair", true, PROPORTION_DECIMAL, PROVINCE); - ret &= add_modifier_effect( - modifier_effect_cache.local_rgo_output, "local_rgo_output", true, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("rgo_output") - ); - ret &= add_modifier_effect( - modifier_effect_cache.local_rgo_throughput, "local_rgo_throughput", true, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("rgo_throughput") - ); - ret &= add_modifier_effect( - modifier_effect_cache.local_ruling_party_support, "local_ruling_party_support", true, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("ruling_party_support") - ); - ret &= add_modifier_effect( - modifier_effect_cache.local_ship_build, "local_ship_build", false, PROPORTION_DECIMAL, PROVINCE - ); - ret &= add_modifier_effect(modifier_effect_cache.max_attrition, "max_attrition", false, RAW_DECIMAL, PROVINCE); - ret &= add_modifier_effect( - modifier_effect_cache.mine_rgo_eff, "mine_rgo_eff", true, PROPORTION_DECIMAL, PROVINCE, "TECH_MINE_OUTPUT" - ); - ret &= add_modifier_effect( - modifier_effect_cache.mine_rgo_size, "mine_rgo_size", true, PROPORTION_DECIMAL, PROVINCE, - ModifierEffect::make_default_modifier_effect_localisation_key("mine_size") - ); - ret &= add_modifier_effect(modifier_effect_cache.movement_cost, "movement_cost", false, PROPORTION_DECIMAL, PROVINCE); - ret &= add_modifier_effect( - modifier_effect_cache.number_of_voters, "number_of_voters", false, PROPORTION_DECIMAL, PROVINCE - ); - ret &= add_modifier_effect( - modifier_effect_cache.pop_consciousness_modifier, "pop_consciousness_modifier", false, RAW_DECIMAL, PROVINCE - ); - ret &= add_modifier_effect( - modifier_effect_cache.pop_militancy_modifier, "pop_militancy_modifier", false, RAW_DECIMAL, PROVINCE - ); - ret &= add_modifier_effect( - modifier_effect_cache.population_growth, "population_growth", true, PROPORTION_DECIMAL, PROVINCE - ); - ret &= add_modifier_effect(modifier_effect_cache.supply_limit, "supply_limit", true, RAW_DECIMAL, PROVINCE); - - /* Military Modifier Effects */ - ret &= add_modifier_effect(modifier_effect_cache.attack, "attack", true, INT, UNIT, "TRAIT_ATTACK"); - ret &= add_modifier_effect(modifier_effect_cache.attrition, "attrition", false, RAW_DECIMAL, UNIT, "ATTRITION"); - ret &= add_modifier_effect(modifier_effect_cache.defence, "defence", true, INT, UNIT, "TRAIT_DEFEND"); - ret &= add_modifier_effect( - modifier_effect_cache.experience, "experience", true, PROPORTION_DECIMAL, UNIT, "TRAIT_EXPERIENCE" - ); - ret &= add_modifier_effect(modifier_effect_cache.morale, "morale", true, PROPORTION_DECIMAL, UNIT, "TRAIT_MORALE"); - ret &= add_modifier_effect( - modifier_effect_cache.organisation, "organisation", true, PROPORTION_DECIMAL, UNIT, "TRAIT_ORGANISATION" - ); - ret &= add_modifier_effect( - modifier_effect_cache.reconnaissance, "reconnaissance", true, PROPORTION_DECIMAL, UNIT, "TRAIT_RECONAISSANCE" - ); - ret &= add_modifier_effect(modifier_effect_cache.reliability, "reliability", true, RAW_DECIMAL, UNIT, "TRAIT_RELIABILITY"); - ret &= add_modifier_effect(modifier_effect_cache.speed, "speed", true, PROPORTION_DECIMAL, UNIT, "TRAIT_SPEED"); - - return ret; -} - -bool ModifierManager::register_complex_modifier(std::string_view identifier) { - if (complex_modifiers.emplace(identifier).second) { - return true; - } else { - Logger::error("Duplicate complex modifier: ", identifier); - return false; - } -} - -std::string ModifierManager::get_flat_identifier( - std::string_view complex_modifier_identifier, std::string_view variant_identifier -) { - return StringUtils::append_string_views(complex_modifier_identifier, " ", variant_identifier); -} - -bool ModifierManager::add_event_modifier(std::string_view identifier, ModifierValue&& values, IconModifier::icon_t icon) { - if (identifier.empty()) { - Logger::error("Invalid event modifier effect identifier - empty!"); - return false; - } - - return event_modifiers.add_item( - { identifier, std::move(values), Modifier::modifier_type_t::EVENT, icon }, duplicate_warning_callback - ); -} - -bool ModifierManager::load_event_modifiers(ast::NodeCPtr root) { - const bool ret = expect_dictionary_reserve_length( - event_modifiers, - [this](std::string_view key, ast::NodeCPtr value) -> bool { - ModifierValue modifier_value; - IconModifier::icon_t icon = 0; - bool ret = expect_modifier_value_and_keys( - move_variable_callback(modifier_value), - "icon", ZERO_OR_ONE, expect_uint(assign_variable_callback(icon)) - )(value); - ret &= add_event_modifier(key, std::move(modifier_value), icon); - return ret; - } - )(root); - - lock_event_modifiers(); - - return ret; -} - -bool ModifierManager::add_static_modifier(std::string_view identifier, ModifierValue&& values) { - if (identifier.empty()) { - Logger::error("Invalid static modifier effect identifier - empty!"); - return false; - } - - return static_modifiers.add_item( - { identifier, std::move(values), Modifier::modifier_type_t::STATIC }, duplicate_warning_callback - ); -} - -bool ModifierManager::load_static_modifiers(ast::NodeCPtr root) { - bool ret = expect_dictionary_reserve_length( - static_modifiers, - [this](std::string_view key, ast::NodeCPtr value) -> bool { - ModifierValue modifier_value; - bool ret = expect_modifier_value(move_variable_callback(modifier_value))(value); - ret &= add_static_modifier(key, std::move(modifier_value)); - return ret; - } - )(root); - - lock_static_modifiers(); - - ret &= static_modifier_cache.load_static_modifiers(*this); - - return ret; -} - -bool ModifierManager::add_triggered_modifier( - std::string_view identifier, ModifierValue&& values, IconModifier::icon_t icon, ConditionScript&& trigger -) { - if (identifier.empty()) { - Logger::error("Invalid triggered modifier effect identifier - empty!"); - return false; - } - - return triggered_modifiers.add_item( - { identifier, std::move(values), Modifier::modifier_type_t::TRIGGERED, icon, std::move(trigger) }, - duplicate_warning_callback - ); -} - -bool ModifierManager::load_triggered_modifiers(ast::NodeCPtr root) { - const bool ret = expect_dictionary_reserve_length( - triggered_modifiers, - [this](std::string_view key, ast::NodeCPtr value) -> bool { - ModifierValue modifier_value; - IconModifier::icon_t icon = 0; - ConditionScript trigger { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE }; - - bool ret = expect_modifier_value_and_keys( - move_variable_callback(modifier_value), - "icon", ZERO_OR_ONE, expect_uint(assign_variable_callback(icon)), - "trigger", ONE_EXACTLY, trigger.expect_script() - )(value); - ret &= add_triggered_modifier(key, std::move(modifier_value), icon, std::move(trigger)); - return ret; - } - )(root); - - lock_triggered_modifiers(); - - return ret; -} - -bool ModifierManager::parse_scripts(DefinitionManager const& definition_manager) { - bool ret = true; - - for (TriggeredModifier& modifier : triggered_modifiers.get_items()) { - ret &= modifier.parse_scripts(definition_manager); - } - - return ret; -} - -key_value_callback_t ModifierManager::_modifier_effect_callback( - ModifierValue& modifier, key_value_callback_t default_callback, ModifierEffectValidator auto effect_validator -) const { - const auto add_modifier_cb = [this, &modifier, effect_validator]( - 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; - } - }; - - const auto add_flattened_modifier_cb = [this, add_modifier_cb]( - 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); - if (effect != nullptr) { - return add_modifier_cb(effect, value); - } else { - Logger::error("Could not find flattened modifier: ", flat_identifier); - return false; - } - }; - - return [this, default_callback, add_modifier_cb, add_flattened_modifier_cb]( - std::string_view key, ast::NodeCPtr value - ) -> bool { - ModifierEffect const* effect = get_modifier_effect_by_identifier(key); - if (effect != nullptr && dryad::node_has_kind(value)) { - return add_modifier_cb(effect, value); - } else if (complex_modifiers.contains(key) && dryad::node_has_kind(value)) { - if (key == "rebel_org_gain") { //because of course there's a special one - std::string_view faction_identifier; - ast::NodeCPtr value_node = nullptr; - bool ret = expect_dictionary_keys( - "faction", ONE_EXACTLY, expect_identifier(assign_variable_callback(faction_identifier)), - "value", ONE_EXACTLY, assign_variable_callback(value_node) - )(value); - ret &= add_flattened_modifier_cb(key, faction_identifier, value_node); - return ret; - } else { - return expect_dictionary(std::bind_front(add_flattened_modifier_cb, key))(value); - } - } else if (key == "war_exhaustion_effect") { - Logger::warning("war_exhaustion_effect does nothing (vanilla issues have it)."); - return true; - } else { - return default_callback(key, value); - } - }; -} - -node_callback_t ModifierManager::expect_validated_modifier_value_and_default( - callback_t modifier_callback, key_value_callback_t default_callback, - ModifierEffectValidator auto effect_validator -) const { - return [this, modifier_callback, default_callback, effect_validator](ast::NodeCPtr root) -> bool { - ModifierValue modifier; - bool ret = expect_dictionary_reserve_length( - modifier.values, - _modifier_effect_callback(modifier, default_callback, effect_validator) - )(root); - ret &= modifier_callback(std::move(modifier)); - return ret; - }; -} - -node_callback_t ModifierManager::expect_validated_modifier_value( - callback_t modifier_callback, ModifierEffectValidator auto effect_validator -) const { - return expect_validated_modifier_value_and_default(modifier_callback, key_value_invalid_callback, effect_validator); -} - -node_callback_t ModifierManager::expect_modifier_value_and_default( - callback_t modifier_callback, key_value_callback_t default_callback -) const { - return expect_validated_modifier_value_and_default(modifier_callback, default_callback, [](ModifierEffect const&) -> bool { - return true; - }); -} - -node_callback_t ModifierManager::expect_modifier_value(callback_t modifier_callback) const { - return expect_modifier_value_and_default(modifier_callback, key_value_invalid_callback); -} - -node_callback_t ModifierManager::expect_whitelisted_modifier_value_and_default( - callback_t modifier_callback, string_set_t const& whitelist, key_value_callback_t default_callback -) const { - return expect_validated_modifier_value_and_default( - modifier_callback, default_callback, - [&whitelist](ModifierEffect const& effect) -> bool { - return whitelist.contains(effect.get_identifier()); - } - ); -} - -node_callback_t ModifierManager::expect_whitelisted_modifier_value( - callback_t modifier_callback, string_set_t const& whitelist -) const { - return expect_whitelisted_modifier_value_and_default(modifier_callback, whitelist, key_value_invalid_callback); -} - -node_callback_t ModifierManager::expect_modifier_value_and_key_map_and_default( - callback_t modifier_callback, key_value_callback_t default_callback, key_map_t&& key_map -) const { - return [this, modifier_callback, default_callback, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool { - bool ret = expect_modifier_value_and_default( - modifier_callback, - dictionary_keys_callback(key_map, default_callback) - )(node); - ret &= check_key_map_counts(key_map); - return ret; - }; -} - -node_callback_t ModifierManager::expect_modifier_value_and_key_map( - callback_t modifier_callback, key_map_t&& key_map -) const { - return expect_modifier_value_and_key_map_and_default(modifier_callback, key_value_invalid_callback, std::move(key_map)); -} - -namespace OpenVic { // so the compiler shuts up - std::ostream& operator<<(std::ostream& stream, ModifierValue const& value) { - for (ModifierValue::effect_map_t::value_type const& effect : value.values) { - stream << effect.first << ": " << effect.second << "\n"; - } - return stream; - } -} diff --git a/src/openvic-simulation/modifier/Modifier.hpp b/src/openvic-simulation/modifier/Modifier.hpp index 49194cd..16ccd21 100644 --- a/src/openvic-simulation/modifier/Modifier.hpp +++ b/src/openvic-simulation/modifier/Modifier.hpp @@ -1,11 +1,11 @@ #pragma once -#include "openvic-simulation/modifier/ModifierEffect.hpp" -#include "openvic-simulation/modifier/ModifierEffectCache.hpp" +#include + #include "openvic-simulation/modifier/ModifierValue.hpp" -#include "openvic-simulation/modifier/StaticModifierCache.hpp" #include "openvic-simulation/scripts/ConditionScript.hpp" -#include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/Date.hpp" +#include "openvic-simulation/utility/Getters.hpp" namespace OpenVic { struct Modifier : HasIdentifier, ModifierValue { @@ -69,122 +69,4 @@ namespace OpenVic { public: ModifierInstance(Modifier const& new_modifier, Date new_expiry_date); }; - - template - concept ModifierEffectValidator = std::predicate; - - struct ModifierManager { - friend struct StaticModifierCache; - friend struct BuildingTypeManager; - friend struct GoodDefinitionManager; - friend struct UnitTypeManager; - friend struct RebelManager; - friend struct PopManager; - friend struct TechnologyManager; - - /* Some ModifierEffects are generated mid-load, such as max/min count modifiers for each building, so - * we can't lock it until loading is over. This means we can't rely on locking for pointer stability, - * so instead we store the effects in a deque which doesn't invalidate pointers on insert. - */ - private: - CaseInsensitiveIdentifierRegistry IDENTIFIER_REGISTRY(modifier_effect); - case_insensitive_string_set_t complex_modifiers; - - IdentifierRegistry IDENTIFIER_REGISTRY(event_modifier); - IdentifierRegistry IDENTIFIER_REGISTRY(static_modifier); - IdentifierRegistry IDENTIFIER_REGISTRY(triggered_modifier); - - ModifierEffectCache PROPERTY(modifier_effect_cache); - StaticModifierCache PROPERTY(static_modifier_cache); - - /* effect_validator takes in ModifierEffect const& */ - NodeTools::key_value_callback_t _modifier_effect_callback( - ModifierValue& modifier, NodeTools::key_value_callback_t default_callback, - ModifierEffectValidator auto effect_validator - ) const; - - public: - bool 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 = {} - ); - - bool register_complex_modifier(std::string_view identifier); - static std::string get_flat_identifier( - std::string_view complex_modifier_identifier, std::string_view variant_identifier - ); - - bool setup_modifier_effects(); - - bool add_event_modifier(std::string_view identifier, ModifierValue&& values, IconModifier::icon_t icon); - bool load_event_modifiers(ast::NodeCPtr root); - - bool add_static_modifier(std::string_view identifier, ModifierValue&& values); - bool load_static_modifiers(ast::NodeCPtr root); - - bool add_triggered_modifier( - std::string_view identifier, ModifierValue&& values, IconModifier::icon_t icon, ConditionScript&& trigger - ); - bool load_triggered_modifiers(ast::NodeCPtr root); - - bool parse_scripts(DefinitionManager const& definition_manager); - - NodeTools::node_callback_t expect_validated_modifier_value_and_default( - NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback, - ModifierEffectValidator auto effect_validator - ) const; - NodeTools::node_callback_t expect_validated_modifier_value( - NodeTools::callback_t modifier_callback, ModifierEffectValidator auto effect_validator - ) const; - - NodeTools::node_callback_t expect_modifier_value_and_default( - NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback - ) const; - NodeTools::node_callback_t expect_modifier_value(NodeTools::callback_t modifier_callback) const; - - NodeTools::node_callback_t expect_whitelisted_modifier_value_and_default( - NodeTools::callback_t modifier_callback, string_set_t const& whitelist, - NodeTools::key_value_callback_t default_callback - ) const; - NodeTools::node_callback_t expect_whitelisted_modifier_value( - NodeTools::callback_t modifier_callback, string_set_t const& whitelist - ) const; - - NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default( - NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback, - NodeTools::key_map_t&& key_map - ) const; - NodeTools::node_callback_t expect_modifier_value_and_key_map( - NodeTools::callback_t modifier_callback, NodeTools::key_map_t&& key_map - ) const; - - template - NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default( - NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback, - NodeTools::key_map_t&& key_map, Args... args - ) const { - NodeTools::add_key_map_entries(key_map, args...); - return expect_modifier_value_and_key_map_and_default(modifier_callback, default_callback, std::move(key_map)); - } - - template - NodeTools::node_callback_t expect_modifier_value_and_keys_and_default( - NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback, - Args... args - ) const { - return expect_modifier_value_and_key_map_and_default(modifier_callback, default_callback, {}, args...); - } - template - NodeTools::node_callback_t expect_modifier_value_and_keys( - NodeTools::callback_t modifier_callback, Args... args - ) const { - return expect_modifier_value_and_key_map_and_default( - modifier_callback, NodeTools::key_value_invalid_callback, {}, args... - ); - } - }; } diff --git a/src/openvic-simulation/modifier/ModifierManager.cpp b/src/openvic-simulation/modifier/ModifierManager.cpp new file mode 100644 index 0000000..c9072c8 --- /dev/null +++ b/src/openvic-simulation/modifier/ModifierManager.cpp @@ -0,0 +1,692 @@ +#include "ModifierManager.hpp" + +using namespace OpenVic; +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 +) { + if (identifier.empty()) { + Logger::error("Invalid modifier effect identifier - empty!"); + return false; + } + + if (effect_cache != nullptr) { + Logger::error( + "Cache variable for modifier effect \"", identifier, "\" is already filled with modifier effect \"", + effect_cache->get_identifier(), "\"" + ); + return false; + } + + const bool ret = modifier_effects.add_item({ std::move(identifier), positive_good, format, targets, localisation_key }); + + if (ret) { + effect_cache = &modifier_effects.get_items().back(); + } + + return ret; +} + +bool ModifierManager::setup_modifier_effects() { + bool ret = true; + + using enum ModifierEffect::format_t; + using enum ModifierEffect::target_t; + + /* Tech/inventions only */ + ret &= add_modifier_effect( + modifier_effect_cache.cb_creation_speed, "cb_creation_speed", true, PROPORTION_DECIMAL, COUNTRY, "CB_MANUFACTURE_TECH" + ); + ret &= add_modifier_effect(modifier_effect_cache.combat_width, "combat_width", false, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.plurality, "plurality", true, PERCENTAGE_DECIMAL, COUNTRY, "TECH_PLURALITY" + ); + ret &= add_modifier_effect( + modifier_effect_cache.pop_growth, "pop_growth", true, PROPORTION_DECIMAL, COUNTRY, "TECH_POP_GROWTH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.regular_experience_level, "regular_experience_level", true, RAW_DECIMAL, COUNTRY, + "REGULAR_EXP_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.reinforce_rate, "reinforce_rate", true, PROPORTION_DECIMAL, COUNTRY, "REINFORCE_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.separatism, "seperatism", // paradox typo + false, PROPORTION_DECIMAL, COUNTRY, "SEPARATISM_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.shared_prestige, "shared_prestige", true, RAW_DECIMAL, COUNTRY, "SHARED_PRESTIGE_TECH" + ); + ret &= add_modifier_effect(modifier_effect_cache.tax_eff, "tax_eff", true, PERCENTAGE_DECIMAL, COUNTRY, "TECH_TAX_EFF"); + + /* Country Modifier Effects */ + ret &= add_modifier_effect( + modifier_effect_cache.administrative_efficiency, "administrative_efficiency", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.administrative_efficiency_modifier, "administrative_efficiency_modifier", true, + PROPORTION_DECIMAL, COUNTRY, ModifierEffect::make_default_modifier_effect_localisation_key("administrative_efficiency") + ); + ret &= add_modifier_effect(modifier_effect_cache.artisan_input, "artisan_input", false, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect(modifier_effect_cache.artisan_output, "artisan_output", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.artisan_throughput, "artisan_throughput", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect(modifier_effect_cache.badboy, "badboy", false, RAW_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.cb_generation_speed_modifier, "cb_generation_speed_modifier", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.civilization_progress_modifier, "civilization_progress_modifier", true, PROPORTION_DECIMAL, + COUNTRY, ModifierEffect::make_default_modifier_effect_localisation_key("civilization_progress") + ); + ret &= add_modifier_effect( + modifier_effect_cache.colonial_life_rating, "colonial_life_rating", false, INT, COUNTRY, "COLONIAL_LIFE_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.colonial_migration, "colonial_migration", true, PROPORTION_DECIMAL, COUNTRY, + "COLONIAL_MIGRATION_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.colonial_points, "colonial_points", true, INT, COUNTRY, "COLONIAL_POINTS_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.colonial_prestige, "colonial_prestige", true, PROPORTION_DECIMAL, COUNTRY, + "COLONIAL_PRESTIGE_MODIFIER_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.core_pop_consciousness_modifier, "core_pop_consciousness_modifier", false, RAW_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.core_pop_militancy_modifier, "core_pop_militancy_modifier", false, RAW_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect(modifier_effect_cache.dig_in_cap, "dig_in_cap", true, INT, COUNTRY, "DIGIN_FROM_TECH"); + ret &= add_modifier_effect( + modifier_effect_cache.diplomatic_points, "diplomatic_points", true, PROPORTION_DECIMAL, COUNTRY, + "DIPLOMATIC_POINTS_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.diplomatic_points_modifier, "diplomatic_points_modifier", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("diplopoints_gain") + ); + ret &= add_modifier_effect( + modifier_effect_cache.education_efficiency, "education_efficiency", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.education_efficiency_modifier, "education_efficiency_modifier", true, PROPORTION_DECIMAL, + COUNTRY, ModifierEffect::make_default_modifier_effect_localisation_key("education_efficiency") + ); + ret &= add_modifier_effect(modifier_effect_cache.factory_cost, "factory_cost", false, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect(modifier_effect_cache.factory_input, "factory_input", false, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.factory_maintenance, "factory_maintenance", false, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect(modifier_effect_cache.factory_output, "factory_output", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.factory_owner_cost, "factory_owner_cost", false, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.factory_throughput, "factory_throughput", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.global_assimilation_rate, "global_assimilation_rate", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("assimilation_rate") + ); + ret &= add_modifier_effect( + modifier_effect_cache.global_immigrant_attract, "global_immigrant_attract", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("immigant_attract") + ); + ret &= add_modifier_effect( + modifier_effect_cache.global_pop_consciousness_modifier, "global_pop_consciousness_modifier", false, RAW_DECIMAL, + COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.global_pop_militancy_modifier, "global_pop_militancy_modifier", false, RAW_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.global_population_growth, "global_population_growth", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("population_growth") + ); + ret &= add_modifier_effect(modifier_effect_cache.goods_demand, "goods_demand", false, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect(modifier_effect_cache.import_cost, "import_cost", false, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.increase_research, "increase_research", true, PROPORTION_DECIMAL, COUNTRY, "INC_RES_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.influence, "influence", true, PROPORTION_DECIMAL, COUNTRY, "TECH_GP_INFLUENCE" + ); + ret &= add_modifier_effect( + modifier_effect_cache.influence_modifier, "influence_modifier", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("greatpower_influence_gain") + ); + ret &= add_modifier_effect( + modifier_effect_cache.issue_change_speed, "issue_change_speed", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.land_attack_modifier, "land_attack_modifier", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("land_attack") + ); + ret &= add_modifier_effect( + modifier_effect_cache.land_attrition, "land_attrition", false, PROPORTION_DECIMAL, COUNTRY, "LAND_ATTRITION_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.land_defense_modifier, "land_defense_modifier", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("land_defense") + ); + ret &= add_modifier_effect( + modifier_effect_cache.land_organisation, "land_organisation", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.land_unit_start_experience, "land_unit_start_experience", true, RAW_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect(modifier_effect_cache.leadership, "leadership", true, RAW_DECIMAL, COUNTRY, "LEADERSHIP"); + ret &= add_modifier_effect( + modifier_effect_cache.leadership_modifier, "leadership_modifier", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("global_leadership_modifier") + ); + ret &= add_modifier_effect( + modifier_effect_cache.literacy_con_impact, "literacy_con_impact", false, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect(modifier_effect_cache.loan_interest, "loan_interest", false, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.max_loan_modifier, "max_loan_modifier", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("max_loan_amount") + ); + ret &= add_modifier_effect( + modifier_effect_cache.max_military_spending, "max_military_spending", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.max_national_focus, "max_national_focus", true, INT, COUNTRY, "TECH_MAX_FOCUS" + ); + ret &= add_modifier_effect( + modifier_effect_cache.max_social_spending, "max_social_spending", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect(modifier_effect_cache.max_tariff, "max_tariff", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect(modifier_effect_cache.max_tax, "max_tax", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.max_war_exhaustion, "max_war_exhaustion", true, PERCENTAGE_DECIMAL, COUNTRY, "MAX_WAR_EXHAUSTION" + ); + ret &= add_modifier_effect( + modifier_effect_cache.military_tactics, "military_tactics", true, PROPORTION_DECIMAL, COUNTRY, "MIL_TACTICS_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.min_military_spending, "min_military_spending", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.min_social_spending, "min_social_spending", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect(modifier_effect_cache.min_tariff, "min_tariff", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect(modifier_effect_cache.min_tax, "min_tax", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.minimum_wage, "minimum_wage", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("minimun_wage") + ); + ret &= add_modifier_effect( + modifier_effect_cache.mobilisation_economy_impact, "mobilisation_economy_impact", false, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.mobilisation_size, "mobilisation_size", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.mobilization_impact, "mobilization_impact", false, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.naval_attack_modifier, "naval_attack_modifier", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("naval_attack") + ); + ret &= add_modifier_effect( + modifier_effect_cache.naval_attrition, "naval_attrition", false, PROPORTION_DECIMAL, COUNTRY, "NAVAL_ATTRITION_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.naval_defense_modifier, "naval_defense_modifier", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("naval_defense") + ); + ret &= add_modifier_effect( + modifier_effect_cache.naval_organisation, "naval_organisation", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.naval_unit_start_experience, "naval_unit_start_experience", true, RAW_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.non_accepted_pop_consciousness_modifier, "non_accepted_pop_consciousness_modifier", false, + RAW_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.non_accepted_pop_militancy_modifier, "non_accepted_pop_militancy_modifier", false, RAW_DECIMAL, + COUNTRY + ); + ret &= add_modifier_effect(modifier_effect_cache.org_regain, "org_regain", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect(modifier_effect_cache.pension_level, "pension_level", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.permanent_prestige, "permanent_prestige", true, RAW_DECIMAL, COUNTRY, "PERMANENT_PRESTIGE_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.political_reform_desire, "political_reform_desire", false, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.poor_savings_modifier, "poor_savings_modifier", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect(modifier_effect_cache.prestige, "prestige", true, RAW_DECIMAL, COUNTRY); + ret &= add_modifier_effect(modifier_effect_cache.reinforce_speed, "reinforce_speed", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect(modifier_effect_cache.research_points, "research_points", true, RAW_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.research_points_modifier, "research_points_modifier", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.research_points_on_conquer, "research_points_on_conquer", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect(modifier_effect_cache.rgo_output, "rgo_output", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect(modifier_effect_cache.rgo_throughput, "rgo_throughput", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.ruling_party_support, "ruling_party_support", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.self_unciv_economic_modifier, "self_unciv_economic_modifier", false, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("self_unciv_economic") + ); + ret &= add_modifier_effect( + modifier_effect_cache.self_unciv_military_modifier, "self_unciv_military_modifier", false, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("self_unciv_military") + ); + ret &= add_modifier_effect( + modifier_effect_cache.social_reform_desire, "social_reform_desire", false, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.soldier_to_pop_loss, "soldier_to_pop_loss", true, PROPORTION_DECIMAL, COUNTRY, + "SOLDIER_TO_POP_LOSS_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.supply_consumption, "supply_consumption", false, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.supply_range, "supply_range", true, PROPORTION_DECIMAL, COUNTRY, "SUPPLY_RANGE_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.suppression_points_modifier, "suppression_points_modifier", true, PROPORTION_DECIMAL, COUNTRY, + "SUPPRESSION_TECH" + ); + ret &= add_modifier_effect( + modifier_effect_cache.tariff_efficiency_modifier, "tariff_efficiency_modifier", true, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("tariff_efficiency") + ); + ret &= add_modifier_effect(modifier_effect_cache.tax_efficiency, "tax_efficiency", true, PROPORTION_DECIMAL, COUNTRY); + ret &= add_modifier_effect( + modifier_effect_cache.unemployment_benefit, "unemployment_benefit", true, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.unciv_economic_modifier, "unciv_economic_modifier", false, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("unciv_economic") + ); + ret &= add_modifier_effect( + modifier_effect_cache.unciv_military_modifier, "unciv_military_modifier", false, PROPORTION_DECIMAL, COUNTRY, + ModifierEffect::make_default_modifier_effect_localisation_key("unciv_military") + ); + ret &= add_modifier_effect( + modifier_effect_cache.unit_recruitment_time, "unit_recruitment_time", false, PROPORTION_DECIMAL, COUNTRY + ); + ret &= add_modifier_effect( + modifier_effect_cache.war_exhaustion, "war_exhaustion", false, PROPORTION_DECIMAL, COUNTRY, "WAR_EXHAUST_BATTLES" + ); + + /* Province Modifier Effects */ + ret &= add_modifier_effect( + modifier_effect_cache.assimilation_rate, "assimilation_rate", true, PROPORTION_DECIMAL, PROVINCE + ); + ret &= add_modifier_effect( + modifier_effect_cache.boost_strongest_party, "boost_strongest_party", false, PROPORTION_DECIMAL, PROVINCE + ); + ret &= add_modifier_effect( + modifier_effect_cache.farm_rgo_eff, "farm_rgo_eff", true, PROPORTION_DECIMAL, PROVINCE, "TECH_FARM_OUTPUT" + ); + ret &= add_modifier_effect( + modifier_effect_cache.farm_rgo_size, "farm_rgo_size", true, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("farm_size") + ); + ret &= add_modifier_effect( + modifier_effect_cache.immigrant_attract, "immigrant_attract", true, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("immigant_attract") + ); + ret &= add_modifier_effect( + modifier_effect_cache.immigrant_push, "immigrant_push", false, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("immigant_push") + ); + ret &= add_modifier_effect(modifier_effect_cache.life_rating, "life_rating", true, PROPORTION_DECIMAL, PROVINCE); + ret &= add_modifier_effect( + modifier_effect_cache.local_artisan_input, "local_artisan_input", false, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("artisan_input") + ); + ret &= add_modifier_effect( + modifier_effect_cache.local_artisan_output, "local_artisan_output", true, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("artisan_output") + ); + ret &= add_modifier_effect( + modifier_effect_cache.local_artisan_throughput, "local_artisan_throughput", true, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("artisan_throughput") + ); + ret &= add_modifier_effect( + modifier_effect_cache.local_factory_input, "local_factory_input", false, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("factory_input") + ); + ret &= add_modifier_effect( + modifier_effect_cache.local_factory_output, "local_factory_output", true, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("factory_output") + ); + ret &= add_modifier_effect( + modifier_effect_cache.local_factory_throughput, "local_factory_throughput", true, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("factory_throughput") + ); + ret &= add_modifier_effect(modifier_effect_cache.local_repair, "local_repair", true, PROPORTION_DECIMAL, PROVINCE); + ret &= add_modifier_effect( + modifier_effect_cache.local_rgo_output, "local_rgo_output", true, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("rgo_output") + ); + ret &= add_modifier_effect( + modifier_effect_cache.local_rgo_throughput, "local_rgo_throughput", true, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("rgo_throughput") + ); + ret &= add_modifier_effect( + modifier_effect_cache.local_ruling_party_support, "local_ruling_party_support", true, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("ruling_party_support") + ); + ret &= add_modifier_effect( + modifier_effect_cache.local_ship_build, "local_ship_build", false, PROPORTION_DECIMAL, PROVINCE + ); + ret &= add_modifier_effect(modifier_effect_cache.max_attrition, "max_attrition", false, RAW_DECIMAL, PROVINCE); + ret &= add_modifier_effect( + modifier_effect_cache.mine_rgo_eff, "mine_rgo_eff", true, PROPORTION_DECIMAL, PROVINCE, "TECH_MINE_OUTPUT" + ); + ret &= add_modifier_effect( + modifier_effect_cache.mine_rgo_size, "mine_rgo_size", true, PROPORTION_DECIMAL, PROVINCE, + ModifierEffect::make_default_modifier_effect_localisation_key("mine_size") + ); + ret &= add_modifier_effect(modifier_effect_cache.movement_cost, "movement_cost", false, PROPORTION_DECIMAL, PROVINCE); + ret &= add_modifier_effect( + modifier_effect_cache.number_of_voters, "number_of_voters", false, PROPORTION_DECIMAL, PROVINCE + ); + ret &= add_modifier_effect( + modifier_effect_cache.pop_consciousness_modifier, "pop_consciousness_modifier", false, RAW_DECIMAL, PROVINCE + ); + ret &= add_modifier_effect( + modifier_effect_cache.pop_militancy_modifier, "pop_militancy_modifier", false, RAW_DECIMAL, PROVINCE + ); + ret &= add_modifier_effect( + modifier_effect_cache.population_growth, "population_growth", true, PROPORTION_DECIMAL, PROVINCE + ); + ret &= add_modifier_effect(modifier_effect_cache.supply_limit, "supply_limit", true, RAW_DECIMAL, PROVINCE); + + /* Military Modifier Effects */ + ret &= add_modifier_effect(modifier_effect_cache.attack, "attack", true, INT, UNIT, "TRAIT_ATTACK"); + ret &= add_modifier_effect(modifier_effect_cache.attrition, "attrition", false, RAW_DECIMAL, UNIT, "ATTRITION"); + ret &= add_modifier_effect(modifier_effect_cache.defence, "defence", true, INT, UNIT, "TRAIT_DEFEND"); + ret &= add_modifier_effect( + modifier_effect_cache.experience, "experience", true, PROPORTION_DECIMAL, UNIT, "TRAIT_EXPERIENCE" + ); + ret &= add_modifier_effect(modifier_effect_cache.morale, "morale", true, PROPORTION_DECIMAL, UNIT, "TRAIT_MORALE"); + ret &= add_modifier_effect( + modifier_effect_cache.organisation, "organisation", true, PROPORTION_DECIMAL, UNIT, "TRAIT_ORGANISATION" + ); + ret &= add_modifier_effect( + modifier_effect_cache.reconnaissance, "reconnaissance", true, PROPORTION_DECIMAL, UNIT, "TRAIT_RECONAISSANCE" + ); + ret &= add_modifier_effect(modifier_effect_cache.reliability, "reliability", true, RAW_DECIMAL, UNIT, "TRAIT_RELIABILITY"); + ret &= add_modifier_effect(modifier_effect_cache.speed, "speed", true, PROPORTION_DECIMAL, UNIT, "TRAIT_SPEED"); + + return ret; +} + +bool ModifierManager::register_complex_modifier(std::string_view identifier) { + if (complex_modifiers.emplace(identifier).second) { + return true; + } else { + Logger::error("Duplicate complex modifier: ", identifier); + return false; + } +} + +std::string ModifierManager::get_flat_identifier( + std::string_view complex_modifier_identifier, std::string_view variant_identifier +) { + return StringUtils::append_string_views(complex_modifier_identifier, " ", variant_identifier); +} + +bool ModifierManager::add_event_modifier(std::string_view identifier, ModifierValue&& values, IconModifier::icon_t icon) { + if (identifier.empty()) { + Logger::error("Invalid event modifier effect identifier - empty!"); + return false; + } + + return event_modifiers.add_item( + { identifier, std::move(values), Modifier::modifier_type_t::EVENT, icon }, duplicate_warning_callback + ); +} + +bool ModifierManager::load_event_modifiers(ast::NodeCPtr root) { + const bool ret = expect_dictionary_reserve_length( + event_modifiers, + [this](std::string_view key, ast::NodeCPtr value) -> bool { + ModifierValue modifier_value; + IconModifier::icon_t icon = 0; + bool ret = expect_modifier_value_and_keys( + move_variable_callback(modifier_value), + "icon", ZERO_OR_ONE, expect_uint(assign_variable_callback(icon)) + )(value); + ret &= add_event_modifier(key, std::move(modifier_value), icon); + return ret; + } + )(root); + + lock_event_modifiers(); + + return ret; +} + +bool ModifierManager::add_static_modifier(std::string_view identifier, ModifierValue&& values) { + if (identifier.empty()) { + Logger::error("Invalid static modifier effect identifier - empty!"); + return false; + } + + return static_modifiers.add_item( + { identifier, std::move(values), Modifier::modifier_type_t::STATIC }, duplicate_warning_callback + ); +} + +bool ModifierManager::load_static_modifiers(ast::NodeCPtr root) { + bool ret = expect_dictionary_reserve_length( + static_modifiers, + [this](std::string_view key, ast::NodeCPtr value) -> bool { + ModifierValue modifier_value; + bool ret = expect_modifier_value(move_variable_callback(modifier_value))(value); + ret &= add_static_modifier(key, std::move(modifier_value)); + return ret; + } + )(root); + + lock_static_modifiers(); + + ret &= static_modifier_cache.load_static_modifiers(*this); + + return ret; +} + +bool ModifierManager::add_triggered_modifier( + std::string_view identifier, ModifierValue&& values, IconModifier::icon_t icon, ConditionScript&& trigger +) { + if (identifier.empty()) { + Logger::error("Invalid triggered modifier effect identifier - empty!"); + return false; + } + + return triggered_modifiers.add_item( + { identifier, std::move(values), Modifier::modifier_type_t::TRIGGERED, icon, std::move(trigger) }, + duplicate_warning_callback + ); +} + +bool ModifierManager::load_triggered_modifiers(ast::NodeCPtr root) { + const bool ret = expect_dictionary_reserve_length( + triggered_modifiers, + [this](std::string_view key, ast::NodeCPtr value) -> bool { + ModifierValue modifier_value; + IconModifier::icon_t icon = 0; + ConditionScript trigger { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE }; + + bool ret = expect_modifier_value_and_keys( + move_variable_callback(modifier_value), + "icon", ZERO_OR_ONE, expect_uint(assign_variable_callback(icon)), + "trigger", ONE_EXACTLY, trigger.expect_script() + )(value); + ret &= add_triggered_modifier(key, std::move(modifier_value), icon, std::move(trigger)); + return ret; + } + )(root); + + lock_triggered_modifiers(); + + return ret; +} + +bool ModifierManager::parse_scripts(DefinitionManager const& definition_manager) { + bool ret = true; + + for (TriggeredModifier& modifier : triggered_modifiers.get_items()) { + ret &= modifier.parse_scripts(definition_manager); + } + + return ret; +} + +key_value_callback_t ModifierManager::_modifier_effect_callback( + ModifierValue& modifier, key_value_callback_t default_callback, ModifierEffectValidator auto effect_validator +) const { + const auto add_modifier_cb = [this, &modifier, effect_validator]( + 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; + } + }; + + const auto add_flattened_modifier_cb = [this, add_modifier_cb]( + 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); + if (effect != nullptr) { + return add_modifier_cb(effect, value); + } else { + Logger::error("Could not find flattened modifier: ", flat_identifier); + return false; + } + }; + + return [this, default_callback, add_modifier_cb, add_flattened_modifier_cb]( + std::string_view key, ast::NodeCPtr value + ) -> bool { + ModifierEffect const* effect = get_modifier_effect_by_identifier(key); + if (effect != nullptr && dryad::node_has_kind(value)) { + return add_modifier_cb(effect, value); + } else if (complex_modifiers.contains(key) && dryad::node_has_kind(value)) { + if (key == "rebel_org_gain") { //because of course there's a special one + std::string_view faction_identifier; + ast::NodeCPtr value_node = nullptr; + bool ret = expect_dictionary_keys( + "faction", ONE_EXACTLY, expect_identifier(assign_variable_callback(faction_identifier)), + "value", ONE_EXACTLY, assign_variable_callback(value_node) + )(value); + ret &= add_flattened_modifier_cb(key, faction_identifier, value_node); + return ret; + } else { + return expect_dictionary(std::bind_front(add_flattened_modifier_cb, key))(value); + } + } else if (key == "war_exhaustion_effect") { + Logger::warning("war_exhaustion_effect does nothing (vanilla issues have it)."); + return true; + } else { + return default_callback(key, value); + } + }; +} + +node_callback_t ModifierManager::expect_validated_modifier_value_and_default( + callback_t modifier_callback, key_value_callback_t default_callback, + ModifierEffectValidator auto effect_validator +) const { + return [this, modifier_callback, default_callback, effect_validator](ast::NodeCPtr root) -> bool { + ModifierValue modifier; + bool ret = expect_dictionary_reserve_length( + modifier.values, + _modifier_effect_callback(modifier, default_callback, effect_validator) + )(root); + ret &= modifier_callback(std::move(modifier)); + return ret; + }; +} + +node_callback_t ModifierManager::expect_validated_modifier_value( + callback_t modifier_callback, ModifierEffectValidator auto effect_validator +) const { + return expect_validated_modifier_value_and_default(modifier_callback, key_value_invalid_callback, effect_validator); +} + +node_callback_t ModifierManager::expect_modifier_value_and_default( + callback_t modifier_callback, key_value_callback_t default_callback +) const { + return expect_validated_modifier_value_and_default(modifier_callback, default_callback, [](ModifierEffect const&) -> bool { + return true; + }); +} + +node_callback_t ModifierManager::expect_modifier_value(callback_t modifier_callback) const { + return expect_modifier_value_and_default(modifier_callback, key_value_invalid_callback); +} + +node_callback_t ModifierManager::expect_whitelisted_modifier_value_and_default( + callback_t modifier_callback, string_set_t const& whitelist, key_value_callback_t default_callback +) const { + return expect_validated_modifier_value_and_default( + modifier_callback, default_callback, + [&whitelist](ModifierEffect const& effect) -> bool { + return whitelist.contains(effect.get_identifier()); + } + ); +} + +node_callback_t ModifierManager::expect_whitelisted_modifier_value( + callback_t modifier_callback, string_set_t const& whitelist +) const { + return expect_whitelisted_modifier_value_and_default(modifier_callback, whitelist, key_value_invalid_callback); +} + +node_callback_t ModifierManager::expect_modifier_value_and_key_map_and_default( + callback_t modifier_callback, key_value_callback_t default_callback, key_map_t&& key_map +) const { + return [this, modifier_callback, default_callback, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool { + bool ret = expect_modifier_value_and_default( + modifier_callback, + dictionary_keys_callback(key_map, default_callback) + )(node); + ret &= check_key_map_counts(key_map); + return ret; + }; +} + +node_callback_t ModifierManager::expect_modifier_value_and_key_map( + callback_t modifier_callback, key_map_t&& key_map +) const { + return expect_modifier_value_and_key_map_and_default(modifier_callback, key_value_invalid_callback, std::move(key_map)); +} diff --git a/src/openvic-simulation/modifier/ModifierManager.hpp b/src/openvic-simulation/modifier/ModifierManager.hpp new file mode 100644 index 0000000..73d974d --- /dev/null +++ b/src/openvic-simulation/modifier/ModifierManager.hpp @@ -0,0 +1,127 @@ +#pragma once + +#include "openvic-simulation/modifier/Modifier.hpp" +#include "openvic-simulation/modifier/ModifierEffectCache.hpp" +#include "openvic-simulation/modifier/StaticModifierCache.hpp" +#include "openvic-simulation/types/IdentifierRegistry.hpp" + +namespace OpenVic { + + template + concept ModifierEffectValidator = std::predicate; + + struct ModifierManager { + friend struct StaticModifierCache; + friend struct BuildingTypeManager; + friend struct GoodDefinitionManager; + friend struct UnitTypeManager; + friend struct RebelManager; + friend struct PopManager; + friend struct TechnologyManager; + + /* Some ModifierEffects are generated mid-load, such as max/min count modifiers for each building, so + * we can't lock it until loading is over. This means we can't rely on locking for pointer stability, + * so instead we store the effects in a deque which doesn't invalidate pointers on insert. + */ + private: + CaseInsensitiveIdentifierRegistry IDENTIFIER_REGISTRY(modifier_effect); + case_insensitive_string_set_t complex_modifiers; + + IdentifierRegistry IDENTIFIER_REGISTRY(event_modifier); + IdentifierRegistry IDENTIFIER_REGISTRY(static_modifier); + IdentifierRegistry IDENTIFIER_REGISTRY(triggered_modifier); + + ModifierEffectCache PROPERTY(modifier_effect_cache); + StaticModifierCache PROPERTY(static_modifier_cache); + + /* effect_validator takes in ModifierEffect const& */ + NodeTools::key_value_callback_t _modifier_effect_callback( + ModifierValue& modifier, NodeTools::key_value_callback_t default_callback, + ModifierEffectValidator auto effect_validator + ) const; + + public: + bool 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 = {} + ); + + bool register_complex_modifier(std::string_view identifier); + static std::string get_flat_identifier( + std::string_view complex_modifier_identifier, std::string_view variant_identifier + ); + + bool setup_modifier_effects(); + + bool add_event_modifier(std::string_view identifier, ModifierValue&& values, IconModifier::icon_t icon); + bool load_event_modifiers(ast::NodeCPtr root); + + bool add_static_modifier(std::string_view identifier, ModifierValue&& values); + bool load_static_modifiers(ast::NodeCPtr root); + + bool add_triggered_modifier( + std::string_view identifier, ModifierValue&& values, IconModifier::icon_t icon, ConditionScript&& trigger + ); + bool load_triggered_modifiers(ast::NodeCPtr root); + + bool parse_scripts(DefinitionManager const& definition_manager); + + NodeTools::node_callback_t expect_validated_modifier_value_and_default( + NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback, + ModifierEffectValidator auto effect_validator + ) const; + NodeTools::node_callback_t expect_validated_modifier_value( + NodeTools::callback_t modifier_callback, ModifierEffectValidator auto effect_validator + ) const; + + NodeTools::node_callback_t expect_modifier_value_and_default( + NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback + ) const; + NodeTools::node_callback_t expect_modifier_value(NodeTools::callback_t modifier_callback) const; + + NodeTools::node_callback_t expect_whitelisted_modifier_value_and_default( + NodeTools::callback_t modifier_callback, string_set_t const& whitelist, + NodeTools::key_value_callback_t default_callback + ) const; + NodeTools::node_callback_t expect_whitelisted_modifier_value( + NodeTools::callback_t modifier_callback, string_set_t const& whitelist + ) const; + + NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default( + NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback, + NodeTools::key_map_t&& key_map + ) const; + NodeTools::node_callback_t expect_modifier_value_and_key_map( + NodeTools::callback_t modifier_callback, NodeTools::key_map_t&& key_map + ) const; + + template + NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default( + NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback, + NodeTools::key_map_t&& key_map, Args... args + ) const { + NodeTools::add_key_map_entries(key_map, args...); + return expect_modifier_value_and_key_map_and_default(modifier_callback, default_callback, std::move(key_map)); + } + + template + NodeTools::node_callback_t expect_modifier_value_and_keys_and_default( + NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback, + Args... args + ) const { + return expect_modifier_value_and_key_map_and_default(modifier_callback, default_callback, {}, args...); + } + template + NodeTools::node_callback_t expect_modifier_value_and_keys( + NodeTools::callback_t modifier_callback, Args... args + ) const { + return expect_modifier_value_and_key_map_and_default( + modifier_callback, NodeTools::key_value_invalid_callback, {}, args... + ); + } + }; +} diff --git a/src/openvic-simulation/modifier/ModifierValue.cpp b/src/openvic-simulation/modifier/ModifierValue.cpp index 51d41bc..eec34bb 100644 --- a/src/openvic-simulation/modifier/ModifierValue.cpp +++ b/src/openvic-simulation/modifier/ModifierValue.cpp @@ -134,3 +134,12 @@ void ModifierValue::multiply_add_filter( } } } + +namespace OpenVic { // so the compiler shuts up + std::ostream& operator<<(std::ostream& stream, ModifierValue const& value) { + for (ModifierValue::effect_map_t::value_type const& effect : value.values) { + stream << effect.first << ": " << effect.second << "\n"; + } + return stream; + } +} diff --git a/src/openvic-simulation/modifier/StaticModifierCache.cpp b/src/openvic-simulation/modifier/StaticModifierCache.cpp index 32ef10a..b03d827 100644 --- a/src/openvic-simulation/modifier/StaticModifierCache.cpp +++ b/src/openvic-simulation/modifier/StaticModifierCache.cpp @@ -1,6 +1,6 @@ #include "StaticModifierCache.hpp" -#include "openvic-simulation/modifier/Modifier.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" using namespace OpenVic; diff --git a/src/openvic-simulation/politics/Issue.cpp b/src/openvic-simulation/politics/Issue.cpp index 3174e23..aa7fd60 100644 --- a/src/openvic-simulation/politics/Issue.cpp +++ b/src/openvic-simulation/politics/Issue.cpp @@ -1,5 +1,7 @@ #include "Issue.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" + using namespace OpenVic; using namespace OpenVic::NodeTools; diff --git a/src/openvic-simulation/politics/NationalFocus.cpp b/src/openvic-simulation/politics/NationalFocus.cpp index 4887ed6..81e6336 100644 --- a/src/openvic-simulation/politics/NationalFocus.cpp +++ b/src/openvic-simulation/politics/NationalFocus.cpp @@ -1,6 +1,7 @@ #include "NationalFocus.hpp" #include "openvic-simulation/economy/GoodDefinition.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/politics/Ideology.hpp" #include "openvic-simulation/pop/Pop.hpp" diff --git a/src/openvic-simulation/politics/NationalValue.cpp b/src/openvic-simulation/politics/NationalValue.cpp index e9f7f2a..6dd4678 100644 --- a/src/openvic-simulation/politics/NationalValue.cpp +++ b/src/openvic-simulation/politics/NationalValue.cpp @@ -1,5 +1,7 @@ #include "NationalValue.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" + using namespace OpenVic; using namespace OpenVic::NodeTools; diff --git a/src/openvic-simulation/politics/Rebel.cpp b/src/openvic-simulation/politics/Rebel.cpp index 219a47b..9bba1b9 100644 --- a/src/openvic-simulation/politics/Rebel.cpp +++ b/src/openvic-simulation/politics/Rebel.cpp @@ -2,7 +2,7 @@ #include -#include "openvic-simulation/modifier/Modifier.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; diff --git a/src/openvic-simulation/pop/Pop.cpp b/src/openvic-simulation/pop/Pop.cpp index 54765d0..885903a 100644 --- a/src/openvic-simulation/pop/Pop.cpp +++ b/src/openvic-simulation/pop/Pop.cpp @@ -5,6 +5,7 @@ #include "openvic-simulation/map/ProvinceInstance.hpp" #include "openvic-simulation/military/UnitType.hpp" #include "openvic-simulation/misc/Define.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/politics/Ideology.hpp" #include "openvic-simulation/politics/Issue.hpp" #include "openvic-simulation/politics/Rebel.hpp" diff --git a/src/openvic-simulation/research/Invention.cpp b/src/openvic-simulation/research/Invention.cpp index 299cefb..d8696a8 100644 --- a/src/openvic-simulation/research/Invention.cpp +++ b/src/openvic-simulation/research/Invention.cpp @@ -3,6 +3,7 @@ #include "openvic-simulation/economy/BuildingType.hpp" #include "openvic-simulation/map/Crime.hpp" #include "openvic-simulation/military/UnitType.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -54,8 +55,8 @@ bool InventionManager::add_invention( } bool InventionManager::load_inventions_file( - ModifierManager const& modifier_manager, UnitTypeManager const& unit_type_manager, BuildingTypeManager const& building_type_manager, - CrimeManager const& crime_manager, ast::NodeCPtr root + ModifierManager const& modifier_manager, UnitTypeManager const& unit_type_manager, + BuildingTypeManager const& building_type_manager, CrimeManager const& crime_manager, ast::NodeCPtr root ) { return expect_dictionary_reserve_length( inventions, [this, &modifier_manager, &unit_type_manager, &building_type_manager, &crime_manager]( @@ -82,7 +83,8 @@ bool InventionManager::load_inventions_file( move_variable_callback(modifiers), "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, unit_type_manager.expect_unit_type_identifier(set_callback_pointer(activated_units)), + "activate_unit", ZERO_OR_MORE, + unit_type_manager.expect_unit_type_identifier(set_callback_pointer(activated_units)), "activate_building", ZERO_OR_MORE, building_type_manager.expect_building_type_identifier( set_callback_pointer(activated_buildings) ), diff --git a/src/openvic-simulation/research/Technology.cpp b/src/openvic-simulation/research/Technology.cpp index 27bb4ca..773b3c6 100644 --- a/src/openvic-simulation/research/Technology.cpp +++ b/src/openvic-simulation/research/Technology.cpp @@ -1,5 +1,7 @@ #include "Technology.hpp" +#include "openvic-simulation/modifier/ModifierManager.hpp" + using namespace OpenVic; using namespace OpenVic::NodeTools; -- cgit v1.2.3-56-ga3b1 From 35909d6e79d524f19f9b69dffd02fcf162be5093 Mon Sep 17 00:00:00 2001 From: hop311 Date: Sat, 19 Oct 2024 11:31:40 +0100 Subject: Switch to excluding given modifier effect targets rather than using a positive filter --- src/openvic-simulation/country/CountryInstance.cpp | 4 +- src/openvic-simulation/map/ProvinceInstance.cpp | 4 +- src/openvic-simulation/modifier/ModifierEffect.cpp | 32 ++++++++++++ src/openvic-simulation/modifier/ModifierEffect.hpp | 10 ++++ .../modifier/ModifierManager.cpp | 7 +++ src/openvic-simulation/modifier/ModifierSum.cpp | 58 ++++++++++++++++------ src/openvic-simulation/modifier/ModifierSum.hpp | 30 ++++++++--- src/openvic-simulation/modifier/ModifierValue.cpp | 20 +++++--- src/openvic-simulation/modifier/ModifierValue.hpp | 6 ++- 9 files changed, 133 insertions(+), 38 deletions(-) (limited to 'src/openvic-simulation/country/CountryInstance.cpp') diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index aceae11..417ca0a 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -1028,9 +1028,7 @@ void CountryInstance::update_modifier_sum(Date today, StaticModifierCache const& void CountryInstance::contribute_province_modifier_sum(ModifierSum const& province_modifier_sum) { using enum ModifierEffect::target_t; - static constexpr ModifierEffect::target_t NOT_PROVINCE = ALL_TARGETS & ~PROVINCE; - - modifier_sum.add_modifier_sum_filter_targets(province_modifier_sum, NOT_PROVINCE); + modifier_sum.add_modifier_sum_exclude_targets(province_modifier_sum, PROVINCE); } fixed_point_t CountryInstance::get_modifier_effect_value(ModifierEffect const& effect) const { diff --git a/src/openvic-simulation/map/ProvinceInstance.cpp b/src/openvic-simulation/map/ProvinceInstance.cpp index 57a33a4..236efd2 100644 --- a/src/openvic-simulation/map/ProvinceInstance.cpp +++ b/src/openvic-simulation/map/ProvinceInstance.cpp @@ -255,7 +255,7 @@ fixed_point_t ProvinceInstance::get_modifier_effect_value(ModifierEffect const& using enum ModifierEffect::target_t; if (owner != nullptr) { - if ((effect.get_targets() & PROVINCE) == NO_TARGETS) { + if (ModifierEffect::excludes_targets(effect.get_targets(), PROVINCE)) { // Non-province targeted effects are already added to the country modifier sum return owner->get_modifier_effect_value(effect); } else { @@ -285,7 +285,7 @@ void ProvinceInstance::push_contributing_modifiers( using enum ModifierEffect::target_t; if (owner != nullptr) { - if ((effect.get_targets() & PROVINCE) == NO_TARGETS) { + if (ModifierEffect::excludes_targets(effect.get_targets(), PROVINCE)) { // Non-province targeted effects are already added to the country modifier sum owner->push_contributing_modifiers(effect, contributions); } else { diff --git a/src/openvic-simulation/modifier/ModifierEffect.cpp b/src/openvic-simulation/modifier/ModifierEffect.cpp index 8daf563..2ffb9a5 100644 --- a/src/openvic-simulation/modifier/ModifierEffect.cpp +++ b/src/openvic-simulation/modifier/ModifierEffect.cpp @@ -4,6 +4,38 @@ using namespace OpenVic; +std::string ModifierEffect::target_to_string(target_t target) { + using enum target_t; + + if (target == NO_TARGETS) { + return "NO TARGETS"; + } + + if (target == ALL_TARGETS) { + return "ALL TARGETS"; + } + + static constexpr std::string_view SEPARATOR = " | "; + + std::string ret; + + const auto append_target = [target, &ret](target_t check_target, std::string_view target_str) -> void { + if (!ModifierEffect::excludes_targets(target, check_target)) { + if (!ret.empty()) { + ret += SEPARATOR; + } + ret += target_str; + } + }; + + append_target(COUNTRY, "COUNTRY"); + append_target(PROVINCE, "PROVINCE"); + append_target(UNIT, "UNIT"); + append_target(~ALL_TARGETS, "INVALID TARGET"); + + return ret; +} + std::string ModifierEffect::make_default_modifier_effect_localisation_key(std::string_view identifier) { return "MODIFIER_" + StringUtils::string_toupper(identifier); } diff --git a/src/openvic-simulation/modifier/ModifierEffect.hpp b/src/openvic-simulation/modifier/ModifierEffect.hpp index 8eac65b..ff82acf 100644 --- a/src/openvic-simulation/modifier/ModifierEffect.hpp +++ b/src/openvic-simulation/modifier/ModifierEffect.hpp @@ -27,6 +27,10 @@ namespace OpenVic { ALL_TARGETS = (1 << 3) - 1 }; + static constexpr bool excludes_targets(target_t targets, target_t excluded_target); + + static std::string target_to_string(target_t target); + static std::string make_default_modifier_effect_localisation_key(std::string_view identifier); private: @@ -50,4 +54,10 @@ namespace OpenVic { }; template<> struct enable_bitfield : std::true_type {}; + + constexpr bool ModifierEffect::excludes_targets(target_t targets, target_t excluded_targets) { + using enum target_t; + + return (targets & excluded_targets) == NO_TARGETS; + } } diff --git a/src/openvic-simulation/modifier/ModifierManager.cpp b/src/openvic-simulation/modifier/ModifierManager.cpp index c9072c8..f21712d 100644 --- a/src/openvic-simulation/modifier/ModifierManager.cpp +++ b/src/openvic-simulation/modifier/ModifierManager.cpp @@ -7,11 +7,18 @@ 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 ) { + using enum ModifierEffect::target_t; + if (identifier.empty()) { Logger::error("Invalid modifier effect identifier - empty!"); return false; } + if (targets == NO_TARGETS) { + Logger::error("Invalid targets for modifier effect \"", identifier, "\" - none!"); + return false; + } + if (effect_cache != nullptr) { Logger::error( "Cache variable for modifier effect \"", identifier, "\" is already filled with modifier effect \"", diff --git a/src/openvic-simulation/modifier/ModifierSum.cpp b/src/openvic-simulation/modifier/ModifierSum.cpp index a3b8cd5..676e872 100644 --- a/src/openvic-simulation/modifier/ModifierSum.cpp +++ b/src/openvic-simulation/modifier/ModifierSum.cpp @@ -2,8 +2,27 @@ #include "openvic-simulation/modifier/Modifier.hpp" +#include "openvic-simulation/country/CountryInstance.hpp" +#include "openvic-simulation/map/ProvinceInstance.hpp" + using namespace OpenVic; +std::string_view ModifierSum::source_to_string(modifier_source_t const& source) { + return std::visit( + [](HasGetIdentifier auto const* has_identifier) -> std::string_view { + return has_identifier->get_identifier(); + }, + source + ); +} + +std::string ModifierSum::modifier_entry_t::to_string() const { + return StringUtils::append_string_views( + "[", modifier->get_identifier(), ", ", multiplier.to_string(), ", ", source_to_string(source), ", ", + ModifierEffect::target_to_string(excluded_targets), "]" + ); +} + void ModifierSum::clear() { modifiers.clear(); value_sum.clear(); @@ -26,21 +45,25 @@ bool ModifierSum::has_effect(ModifierEffect const& effect) const { } void ModifierSum::add_modifier( - Modifier const& modifier, modifier_source_t const& source, fixed_point_t multiplier, ModifierEffect::target_t targets + Modifier const& modifier, modifier_source_t const& source, fixed_point_t multiplier, + ModifierEffect::target_t excluded_targets ) { using enum ModifierEffect::target_t; - if (multiplier != fixed_point_t::_0() && targets != NO_TARGETS) { - modifiers.emplace_back(&modifier, multiplier, source, targets); - value_sum.multiply_add_filter(modifier, multiplier, targets); + // We could test that excluded_targets != ALL_TARGETS, but in practice it's always + // called with an explcit/hardcoded value and so won't ever exclude everything. + if (multiplier != fixed_point_t::_0()) { + modifiers.emplace_back(&modifier, multiplier, source, excluded_targets); + value_sum.multiply_add_exclude_targets(modifier, multiplier, excluded_targets); } } void ModifierSum::add_modifier_nullcheck( - Modifier const* modifier, modifier_source_t const& source, fixed_point_t multiplier, ModifierEffect::target_t targets + Modifier const* modifier, modifier_source_t const& source, fixed_point_t multiplier, + ModifierEffect::target_t excluded_targets ) { if (modifier != nullptr) { - add_modifier(*modifier, source, multiplier, targets); + add_modifier(*modifier, source, multiplier, excluded_targets); } } @@ -49,22 +72,25 @@ void ModifierSum::add_modifier_sum(ModifierSum const& modifier_sum) { value_sum += modifier_sum.value_sum; } -void ModifierSum::add_modifier_sum_filter_targets(ModifierSum const& modifier_sum, ModifierEffect::target_t targets) { - using enum ModifierEffect::target_t; - +void ModifierSum::add_modifier_sum_exclude_targets( + ModifierSum const& modifier_sum, ModifierEffect::target_t excluded_targets +) { + // We could test that excluded_targets != ALL_TARGETS, but in practice it's always + // called with an explcit/hardcoded value and so won't ever exclude everything. for (modifier_entry_t const& modifier_entry : modifier_sum.modifiers) { - ModifierEffect::target_t new_targets = modifier_entry.targets & targets; - - if (new_targets != NO_TARGETS) { - add_modifier(*modifier_entry.modifier, modifier_entry.source, modifier_entry.multiplier, new_targets); - } + add_modifier( + *modifier_entry.modifier, modifier_entry.source, modifier_entry.multiplier, + modifier_entry.excluded_targets | excluded_targets + ); } } void ModifierSum::add_modifier_sum_exclude_source(ModifierSum const& modifier_sum, modifier_source_t const& excluded_source) { for (modifier_entry_t const& modifier_entry : modifier_sum.modifiers) { if (modifier_entry.source != excluded_source) { - add_modifier(*modifier_entry.modifier, modifier_entry.source, modifier_entry.multiplier, modifier_entry.targets); + add_modifier( + *modifier_entry.modifier, modifier_entry.source, modifier_entry.multiplier, modifier_entry.excluded_targets + ); } } } @@ -77,7 +103,7 @@ void ModifierSum::push_contributing_modifiers( using enum ModifierEffect::target_t; for (modifier_entry_t const& modifier_entry : modifiers) { - if ((modifier_entry.targets & effect.get_targets()) != NO_TARGETS) { + if (ModifierEffect::excludes_targets(effect.get_targets(), modifier_entry.excluded_targets)) { bool effect_found = false; const fixed_point_t value = modifier_entry.modifier->get_effect(effect, &effect_found); diff --git a/src/openvic-simulation/modifier/ModifierSum.hpp b/src/openvic-simulation/modifier/ModifierSum.hpp index 7c1b238..858ca71 100644 --- a/src/openvic-simulation/modifier/ModifierSum.hpp +++ b/src/openvic-simulation/modifier/ModifierSum.hpp @@ -13,16 +13,32 @@ namespace OpenVic { struct ModifierSum { using modifier_source_t = std::variant; + static std::string_view source_to_string(modifier_source_t const& source); + struct modifier_entry_t { Modifier const* modifier; fixed_point_t multiplier; modifier_source_t source; - ModifierEffect::target_t targets; + ModifierEffect::target_t excluded_targets; constexpr modifier_entry_t( - Modifier const* new_modifier, fixed_point_t new_multiplier, modifier_source_t const& new_source, - ModifierEffect::target_t new_targets - ) : modifier { new_modifier }, multiplier { new_multiplier }, source { new_source }, targets { new_targets } {} + Modifier const* new_modifier, + fixed_point_t new_multiplier, + modifier_source_t const& new_source, + ModifierEffect::target_t new_excluded_targets + ) : modifier { new_modifier }, + multiplier { new_multiplier }, + source { new_source }, + excluded_targets { new_excluded_targets } {} + + constexpr bool operator==(modifier_entry_t const& other) const { + return modifier == other.modifier + && multiplier == other.multiplier + && source_to_string(source) == source_to_string(other.source) + && excluded_targets == other.excluded_targets; + } + + std::string to_string() const; }; private: @@ -45,14 +61,14 @@ namespace OpenVic { void add_modifier( Modifier const& modifier, modifier_source_t const& source, fixed_point_t multiplier = fixed_point_t::_1(), - ModifierEffect::target_t targets = ModifierEffect::target_t::ALL_TARGETS + ModifierEffect::target_t excluded_targets = ModifierEffect::target_t::ALL_TARGETS ); void add_modifier_nullcheck( Modifier const* modifier, modifier_source_t const& source, fixed_point_t multiplier = fixed_point_t::_1(), - ModifierEffect::target_t targets = ModifierEffect::target_t::ALL_TARGETS + ModifierEffect::target_t excluded_targets = ModifierEffect::target_t::ALL_TARGETS ); void add_modifier_sum(ModifierSum const& modifier_sum); - void add_modifier_sum_filter_targets(ModifierSum const& modifier_sum, ModifierEffect::target_t targets); + void add_modifier_sum_exclude_targets(ModifierSum const& modifier_sum, ModifierEffect::target_t excluded_targets); void add_modifier_sum_exclude_source(ModifierSum const& modifier_sum, modifier_source_t const& excluded_source); void push_contributing_modifiers(ModifierEffect const& effect, std::vector& contributions) const; diff --git a/src/openvic-simulation/modifier/ModifierValue.cpp b/src/openvic-simulation/modifier/ModifierValue.cpp index eec34bb..e3e7b0b 100644 --- a/src/openvic-simulation/modifier/ModifierValue.cpp +++ b/src/openvic-simulation/modifier/ModifierValue.cpp @@ -108,27 +108,31 @@ ModifierValue ModifierValue::operator*(fixed_point_t const& right) const { return copy *= right; } -void ModifierValue::apply_target_filter(ModifierEffect::target_t targets) { +void ModifierValue::apply_exclude_targets(ModifierEffect::target_t excluded_targets) { using enum ModifierEffect::target_t; + // We could test if excluded_targets is NO_TARGETS (and so we do nothing) or ALL_TARGETS (and so we clear everything), + // but so long as this is always called with an explicit/hardcoded value then we'll never have either of those cases. erase_if( values, - [targets](effect_map_t::value_type const& value) -> bool { - return (value.first->get_targets() & targets) == NO_TARGETS; + [excluded_targets](effect_map_t::value_type const& value) -> bool { + return !ModifierEffect::excludes_targets(value.first->get_targets(), excluded_targets); } ); } -void ModifierValue::multiply_add_filter( - ModifierValue const& other, fixed_point_t multiplier, ModifierEffect::target_t targets +void ModifierValue::multiply_add_exclude_targets( + ModifierValue const& other, fixed_point_t multiplier, ModifierEffect::target_t excluded_targets ) { using enum ModifierEffect::target_t; - if (multiplier == fixed_point_t::_1() && targets == ALL_TARGETS) { + if (multiplier == fixed_point_t::_1() && excluded_targets == NO_TARGETS) { *this += other; - } else if (multiplier != fixed_point_t::_0() && targets != NO_TARGETS) { + } else if (multiplier != fixed_point_t::_0()) { + // We could test that excluded_targets != ALL_TARGETS, but in practice it's always + // called with an explcit/hardcoded value and so won't ever exclude everything. for (effect_map_t::value_type const& value : other.values) { - if ((value.first->get_targets() & targets) != NO_TARGETS) { + if (ModifierEffect::excludes_targets(value.first->get_targets(), excluded_targets)) { values[value.first] += value.second * multiplier; } } diff --git a/src/openvic-simulation/modifier/ModifierValue.hpp b/src/openvic-simulation/modifier/ModifierValue.hpp index 23c0ba5..6e6a29b 100644 --- a/src/openvic-simulation/modifier/ModifierValue.hpp +++ b/src/openvic-simulation/modifier/ModifierValue.hpp @@ -40,8 +40,10 @@ namespace OpenVic { ModifierValue& operator*=(fixed_point_t const& right); ModifierValue operator*(fixed_point_t const& right) const; - void apply_target_filter(ModifierEffect::target_t targets); - void multiply_add_filter(ModifierValue const& other, fixed_point_t multiplier, ModifierEffect::target_t targets); + void apply_exclude_targets(ModifierEffect::target_t excluded_targets); + void multiply_add_exclude_targets( + ModifierValue const& other, fixed_point_t multiplier, ModifierEffect::target_t excluded_targets + ); friend std::ostream& operator<<(std::ostream& stream, ModifierValue const& value); }; -- cgit v1.2.3-56-ga3b1