aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--src/headless/main.cpp55
-rw-r--r--src/openvic-simulation/DefinitionManager.hpp4
-rw-r--r--src/openvic-simulation/InstanceManager.cpp39
-rw-r--r--src/openvic-simulation/InstanceManager.hpp1
-rw-r--r--src/openvic-simulation/country/CountryInstance.cpp244
-rw-r--r--src/openvic-simulation/country/CountryInstance.hpp78
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp15
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.cpp6
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.hpp27
-rw-r--r--src/openvic-simulation/dataloader/Vic2PathSearch.cpp2
-rw-r--r--src/openvic-simulation/defines/AIDefines.cpp100
-rw-r--r--src/openvic-simulation/defines/AIDefines.hpp60
-rw-r--r--src/openvic-simulation/defines/CountryDefines.cpp228
-rw-r--r--src/openvic-simulation/defines/CountryDefines.hpp109
-rw-r--r--src/openvic-simulation/defines/Define.cpp25
-rw-r--r--src/openvic-simulation/defines/Define.hpp38
-rw-r--r--src/openvic-simulation/defines/DiplomacyDefines.cpp914
-rw-r--r--src/openvic-simulation/defines/DiplomacyDefines.hpp368
-rw-r--r--src/openvic-simulation/defines/EconomyDefines.cpp92
-rw-r--r--src/openvic-simulation/defines/EconomyDefines.hpp53
-rw-r--r--src/openvic-simulation/defines/GraphicsDefines.cpp41
-rw-r--r--src/openvic-simulation/defines/GraphicsDefines.hpp30
-rw-r--r--src/openvic-simulation/defines/MilitaryDefines.cpp168
-rw-r--r--src/openvic-simulation/defines/MilitaryDefines.hpp86
-rw-r--r--src/openvic-simulation/defines/PopsDefines.cpp142
-rw-r--r--src/openvic-simulation/defines/PopsDefines.hpp82
-rw-r--r--src/openvic-simulation/economy/BuildingType.cpp26
-rw-r--r--src/openvic-simulation/economy/GoodDefinition.cpp134
-rw-r--r--src/openvic-simulation/economy/GoodDefinition.hpp17
-rw-r--r--src/openvic-simulation/economy/GoodInstance.cpp2
-rw-r--r--src/openvic-simulation/economy/GoodInstance.hpp2
-rw-r--r--src/openvic-simulation/economy/production/ArtisanalProducer.hpp2
-rw-r--r--src/openvic-simulation/economy/production/Employee.cpp8
-rw-r--r--src/openvic-simulation/economy/production/Employee.hpp13
-rw-r--r--src/openvic-simulation/economy/production/FactoryProducer.hpp2
-rw-r--r--src/openvic-simulation/economy/production/ProductionType.cpp79
-rw-r--r--src/openvic-simulation/economy/production/ProductionType.hpp43
-rw-r--r--src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp344
-rw-r--r--src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp55
-rw-r--r--src/openvic-simulation/history/CountryHistory.cpp30
-rw-r--r--src/openvic-simulation/history/CountryHistory.hpp2
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.cpp22
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.hpp2
-rw-r--r--src/openvic-simulation/map/Crime.cpp14
-rw-r--r--src/openvic-simulation/map/MapDefinition.cpp240
-rw-r--r--src/openvic-simulation/map/MapDefinition.hpp18
-rw-r--r--src/openvic-simulation/map/MapInstance.cpp34
-rw-r--r--src/openvic-simulation/map/MapInstance.hpp2
-rw-r--r--src/openvic-simulation/map/Mapmode.cpp2
-rw-r--r--src/openvic-simulation/map/ProvinceDefinition.cpp2
-rw-r--r--src/openvic-simulation/map/ProvinceInstance.cpp191
-rw-r--r--src/openvic-simulation/map/ProvinceInstance.hpp35
-rw-r--r--src/openvic-simulation/map/State.cpp18
-rw-r--r--src/openvic-simulation/map/State.hpp2
-rw-r--r--src/openvic-simulation/map/TerrainType.cpp41
-rw-r--r--src/openvic-simulation/map/TerrainType.hpp1
-rw-r--r--src/openvic-simulation/military/Deployment.cpp2
-rw-r--r--src/openvic-simulation/military/LeaderTrait.cpp14
-rw-r--r--src/openvic-simulation/military/UnitType.cpp115
-rw-r--r--src/openvic-simulation/military/UnitType.hpp6
-rw-r--r--src/openvic-simulation/military/Wargoal.cpp13
-rw-r--r--src/openvic-simulation/misc/Decision.cpp11
-rw-r--r--src/openvic-simulation/misc/Define.cpp270
-rw-r--r--src/openvic-simulation/misc/Define.hpp88
-rw-r--r--src/openvic-simulation/misc/Event.cpp16
-rw-r--r--src/openvic-simulation/misc/SongChance.cpp4
-rw-r--r--src/openvic-simulation/misc/SoundEffect.cpp4
-rw-r--r--src/openvic-simulation/modifier/Modifier.cpp655
-rw-r--r--src/openvic-simulation/modifier/Modifier.hpp190
-rw-r--r--src/openvic-simulation/modifier/ModifierEffect.cpp49
-rw-r--r--src/openvic-simulation/modifier/ModifierEffect.hpp64
-rw-r--r--src/openvic-simulation/modifier/ModifierEffectCache.cpp251
-rw-r--r--src/openvic-simulation/modifier/ModifierEffectCache.hpp341
-rw-r--r--src/openvic-simulation/modifier/ModifierManager.cpp800
-rw-r--r--src/openvic-simulation/modifier/ModifierManager.hpp136
-rw-r--r--src/openvic-simulation/modifier/ModifierSum.cpp103
-rw-r--r--src/openvic-simulation/modifier/ModifierSum.hpp63
-rw-r--r--src/openvic-simulation/modifier/ModifierValue.cpp149
-rw-r--r--src/openvic-simulation/modifier/ModifierValue.hpp50
-rw-r--r--src/openvic-simulation/modifier/StaticModifierCache.cpp171
-rw-r--r--src/openvic-simulation/modifier/StaticModifierCache.hpp67
-rw-r--r--src/openvic-simulation/politics/Ideology.cpp20
-rw-r--r--src/openvic-simulation/politics/Issue.cpp22
-rw-r--r--src/openvic-simulation/politics/NationalFocus.cpp13
-rw-r--r--src/openvic-simulation/politics/NationalValue.cpp8
-rw-r--r--src/openvic-simulation/politics/Rebel.cpp30
-rw-r--r--src/openvic-simulation/politics/Rebel.hpp3
-rw-r--r--src/openvic-simulation/pop/Pop.cpp91
-rw-r--r--src/openvic-simulation/pop/Pop.hpp8
-rw-r--r--src/openvic-simulation/research/Invention.cpp25
-rw-r--r--src/openvic-simulation/research/Technology.cpp25
-rw-r--r--src/openvic-simulation/scripts/Condition.cpp66
-rw-r--r--src/openvic-simulation/scripts/Condition.hpp54
-rw-r--r--src/openvic-simulation/scripts/ConditionScript.cpp2
-rw-r--r--src/openvic-simulation/scripts/ConditionScript.hpp8
-rw-r--r--src/openvic-simulation/scripts/ConditionalWeight.cpp81
-rw-r--r--src/openvic-simulation/scripts/ConditionalWeight.hpp19
-rw-r--r--src/openvic-simulation/types/IndexedMap.hpp1
-rw-r--r--src/openvic-simulation/types/fixed_point/FixedPoint.hpp100
-rw-r--r--src/openvic-simulation/utility/NumberUtils.hpp4
101 files changed, 6814 insertions, 1789 deletions
diff --git a/.gitignore b/.gitignore
index e02298a..6040d4b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,7 +36,6 @@
# VSCode
.vscode/*
-!.vscode/launch.json
!.vscode/tasks.json
# Visual Studio
diff --git a/src/headless/main.cpp b/src/headless/main.cpp
index 21e9f7c..a50b4ba 100644
--- a/src/headless/main.cpp
+++ b/src/headless/main.cpp
@@ -1,7 +1,10 @@
-#include <cstring>
-
+#include <openvic-simulation/country/CountryInstance.hpp>
#include <openvic-simulation/dataloader/Dataloader.hpp>
+#include <openvic-simulation/economy/GoodDefinition.hpp>
+#include <openvic-simulation/economy/production/ProductionType.hpp>
+#include <openvic-simulation/economy/production/ResourceGatheringOperation.hpp>
#include <openvic-simulation/GameManager.hpp>
+#include <openvic-simulation/pop/Pop.hpp>
#include <openvic-simulation/testing/Testing.hpp>
#include <openvic-simulation/utility/Logger.hpp>
@@ -18,6 +21,40 @@ static void print_help(std::ostream& stream, char const* program_name) {
<< "(Paths with spaces need to be enclosed in \"quotes\").\n";
}
+static void print_rgo(ProvinceInstance const& province) {
+ ResourceGatheringOperation const& rgo = province.get_rgo();
+ ProductionType const* const production_type_nullable = rgo.get_production_type_nullable();
+ if (production_type_nullable == nullptr) {
+ Logger::error(
+ "\n ", province.get_identifier(),
+ " - production_type: nullptr"
+ );
+ } else {
+ ProductionType const& production_type = *production_type_nullable;
+ GoodDefinition const& output_good = production_type.get_output_good();
+ std::string text = StringUtils::append_string_views(
+ "\n\t", province.get_identifier(),
+ " - good: ", output_good.get_identifier(),
+ ", production_type: ", production_type.get_identifier(),
+ ", size_multiplier: ", rgo.get_size_multiplier().to_string(3),
+ ", output_quantity_yesterday: ", rgo.get_output_quantity_yesterday().to_string(3),
+ ", revenue_yesterday: ", rgo.get_revenue_yesterday().to_string(3),
+ ", total owner income: ", rgo.get_total_owner_income_cache().to_string(3),
+ ", total employee income: ", rgo.get_total_employee_income_cache().to_string(3),
+ "\n\temployees:"
+ );
+
+ auto const& employee_count_per_type_cache=rgo.get_employee_count_per_type_cache();
+ for (PopType const& pop_type : *employee_count_per_type_cache.get_keys()) {
+ const Pop::pop_size_t employees_of_type = employee_count_per_type_cache[pop_type];
+ if (employees_of_type > 0) {
+ text += StringUtils::append_string_views("\n\t\t", std::to_string(employees_of_type), " ", pop_type.get_identifier());
+ }
+ }
+ Logger::info("", text);
+ }
+}
+
static bool run_headless(Dataloader::path_vector_t const& roots, bool run_tests) {
bool ret = true;
@@ -72,9 +109,21 @@ static bool run_headless(Dataloader::path_vector_t const& roots, bool run_tests)
CountryInstanceManager const& country_instance_manager =
game_manager.get_instance_manager()->get_country_instance_manager();
- print_ranking_list("Great Powers", country_instance_manager.get_great_powers());
+ std::vector<CountryInstance*> const& great_powers = country_instance_manager.get_great_powers();
+ print_ranking_list("Great Powers", great_powers);
print_ranking_list("Secondary Powers", country_instance_manager.get_secondary_powers());
print_ranking_list("All countries", country_instance_manager.get_total_ranking());
+
+ Logger::info("===== RGO test... =====");
+ for (size_t i = 0; i < std::min<size_t>(3, great_powers.size()); ++i) {
+ CountryInstance const& great_power = *great_powers[i];
+ ProvinceInstance const* const capital_province = great_power.get_capital();
+ if (capital_province == nullptr) {
+ Logger::warning(great_power.get_identifier(), " has no capital ProvinceInstance set.");
+ } else {
+ print_rgo(*capital_province);
+ }
+ }
} else {
Logger::error("Instance manager not available!");
ret = false;
diff --git a/src/openvic-simulation/DefinitionManager.hpp b/src/openvic-simulation/DefinitionManager.hpp
index 887cc1b..02de2a3 100644
--- a/src/openvic-simulation/DefinitionManager.hpp
+++ b/src/openvic-simulation/DefinitionManager.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "openvic-simulation/country/CountryDefinition.hpp"
+#include "openvic-simulation/defines/Define.hpp"
#include "openvic-simulation/diplomacy/DiplomaticAction.hpp"
#include "openvic-simulation/economy/EconomyManager.hpp"
#include "openvic-simulation/history/HistoryManager.hpp"
@@ -10,11 +11,10 @@
#include "openvic-simulation/map/Mapmode.hpp"
#include "openvic-simulation/military/MilitaryManager.hpp"
#include "openvic-simulation/misc/Decision.hpp"
-#include "openvic-simulation/misc/Define.hpp"
#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/InstanceManager.cpp b/src/openvic-simulation/InstanceManager.cpp
index c9ce24a..670cbfc 100644
--- a/src/openvic-simulation/InstanceManager.cpp
+++ b/src/openvic-simulation/InstanceManager.cpp
@@ -12,7 +12,7 @@ InstanceManager::InstanceManager(
map_instance { new_definition_manager.get_map_definition() },
simulation_clock {
std::bind(&InstanceManager::tick, this), std::bind(&InstanceManager::update_gamestate, this),
- clock_state_changed_callback ? std::move(clock_state_changed_callback) : []() {}
+ clock_state_changed_callback ? std::move(clock_state_changed_callback) : []() {}
},
game_instance_setup { false },
game_session_started { false },
@@ -38,11 +38,12 @@ void InstanceManager::update_gamestate() {
currently_updating_gamestate = true;
Logger::info("Update: ", today);
-
+ update_modifier_sums();
// 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();
@@ -137,6 +138,11 @@ bool InstanceManager::load_bookmark(Bookmark const* new_bookmark) {
map_instance, definition_manager.get_pop_manager().get_pop_types()
);
+ if (ret) {
+ update_modifier_sums();
+ map_instance.initialise_for_new_game(definition_manager.get_modifier_manager().get_modifier_effect_cache());
+ }
+
return ret;
}
@@ -178,3 +184,30 @@ bool InstanceManager::expand_selected_province_building(size_t building_index) {
}
return province->expand_building(building_index);
}
+
+void InstanceManager::update_modifier_sums() {
+ 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()
+ );
+ }
+} \ No newline at end of file
diff --git a/src/openvic-simulation/InstanceManager.hpp b/src/openvic-simulation/InstanceManager.hpp
index cfb5447..05ae412 100644
--- a/src/openvic-simulation/InstanceManager.hpp
+++ b/src/openvic-simulation/InstanceManager.hpp
@@ -33,6 +33,7 @@ namespace OpenVic {
bool PROPERTY_CUSTOM_PREFIX(game_instance_setup, is);
bool PROPERTY_CUSTOM_PREFIX(game_session_started, is);
+ void update_modifier_sums();
public:
inline constexpr bool is_bookmark_loaded() const {
return bookmark != nullptr;
diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp
index 183b0c8..4ecb902 100644
--- a/src/openvic-simulation/country/CountryInstance.cpp
+++ b/src/openvic-simulation/country/CountryInstance.cpp
@@ -1,10 +1,12 @@
#include "CountryInstance.hpp"
#include "openvic-simulation/country/CountryDefinition.hpp"
+#include "openvic-simulation/defines/Define.hpp"
#include "openvic-simulation/history/CountryHistory.hpp"
#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"
@@ -17,16 +19,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 +43,8 @@ CountryInstance::CountryInstance(
controlled_provinces {},
core_provinces {},
states {},
+ modifier_sum {},
+ event_modifiers {},
/* Production */
industrial_power { 0 },
@@ -48,14 +52,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 +83,7 @@ CountryInstance::CountryInstance(
infamy { 0 },
plurality { 0 },
revanchism { 0 },
- unlocked_crimes { &crime_keys },
+ crime_unlock_levels { &crime_keys },
/* Population */
primary_culture { nullptr },
@@ -121,32 +125,32 @@ CountryInstance::CountryInstance(
war_exhaustion { 0 },
mobilised { false },
disarmed { false },
- unlocked_regiment_types { &unlocked_regiment_types_keys },
+ regiment_type_unlock_levels { &regiment_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 +339,7 @@ template bool CountryInstance::remove_leader(LeaderBranched<UnitType::branch_t::
template<UnitType::branch_t Branch>
bool CountryInstance::modify_unit_type_unlock(UnitTypeBranched<Branch> const& unit_type, unlock_level_t unlock_level_change) {
- IndexedMap<UnitTypeBranched<Branch>, unlock_level_t>& unlocked_unit_types = get_unlocked_unit_types<Branch>();
+ IndexedMap<UnitTypeBranched<Branch>, unlock_level_t>& unlocked_unit_types = get_unit_type_unlock_levels<Branch>();
typename IndexedMap<UnitTypeBranched<Branch>, unlock_level_t>::value_ref_t unlock_level = unlocked_unit_types[unit_type];
@@ -384,9 +388,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<UnitTypeBranched<LAND> const&>(unit_type)] > 0;
+ return regiment_type_unlock_levels[static_cast<UnitTypeBranched<LAND> const&>(unit_type)] > 0;
case NAVAL:
- return unlocked_ship_types[static_cast<UnitTypeBranched<NAVAL> const&>(unit_type)] > 0;
+ return ship_type_unlock_levels[static_cast<UnitTypeBranched<NAVAL> const&>(unit_type)] > 0;
default:
Logger::error(
"Attempted to check if unit type \"", unit_type.get_identifier(), "\" with invalid branch ",
@@ -397,7 +401,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 +424,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 +451,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 +547,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 +580,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 +589,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 +632,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 +641,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 {
@@ -672,8 +676,12 @@ bool CountryInstance::apply_history_to_country(
bool ret = true;
set_optional(primary_culture, entry.get_primary_culture());
- for (Culture const* culture : entry.get_accepted_cultures()) {
- ret &= add_accepted_culture(*culture);
+ for (auto const& [culture, add] : entry.get_accepted_cultures()) {
+ if (add) {
+ ret &= add_accepted_culture(*culture);
+ } else {
+ ret &= remove_accepted_culture(*culture);
+ }
}
set_optional(religion, entry.get_religion());
if (entry.get_ruling_party()) {
@@ -748,7 +756,7 @@ void CountryInstance::_update_production(DefineManager const& define_manager) {
for (auto const& [country, money_invested] : foreign_investments) {
if (country->exists()) {
const fixed_point_t investment_industrial_power =
- money_invested * define_manager.get_country_investment_industrial_score_factor() / 100;
+ money_invested * define_manager.get_country_defines().get_country_investment_industrial_score_factor() / 100;
if (investment_industrial_power != 0) {
industrial_power += investment_industrial_power;
@@ -816,7 +824,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) {
@@ -847,8 +858,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);
@@ -864,7 +875,7 @@ void CountryInstance::_update_military(DefineManager const& define_manager, Unit
/ fixed_point_t::parse(7 * (1 + unit_type_manager.get_regiment_type_count()));
if (disarmed) {
- military_power_from_land *= define_manager.get_disarmed_penalty();
+ military_power_from_land *= define_manager.get_diplomacy_defines().get_disarmed_penalty();
}
military_power_from_sea = 0;
@@ -890,7 +901,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();
@@ -923,7 +934,125 @@ bool CountryInstance::update_rule_set() {
return rule_set.trim_and_resolve_conflicts(true);
}
-void CountryInstance::update_gamestate(DefineManager const& define_manager, UnitTypeManager const& unit_type_manager) {
+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(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(static_modifier_cache.get_great_power(), country_source);
+ break;
+ case COUNTRY_STATUS_SECONDARY_POWER:
+ modifier_sum.add_modifier(static_modifier_cache.get_secondary_power(), country_source);
+ break;
+ case COUNTRY_STATUS_CIVILISED:
+ modifier_sum.add_modifier(static_modifier_cache.get_civilised(), country_source);
+ break;
+ default:
+ modifier_sum.add_modifier(static_modifier_cache.get_uncivilised(), country_source);
+ }
+ if (is_disarmed()) {
+ modifier_sum.add_modifier(static_modifier_cache.get_disarming(), country_source);
+ }
+ modifier_sum.add_modifier(static_modifier_cache.get_war_exhaustion(), country_source, war_exhaustion);
+ modifier_sum.add_modifier(static_modifier_cache.get_infamy(), country_source, infamy);
+ modifier_sum.add_modifier(static_modifier_cache.get_literacy(), country_source, national_literacy);
+ modifier_sum.add_modifier(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);
+ }
+ }
+
+ if constexpr (ProvinceInstance::ADD_OWNER_CONTRIBUTION) {
+ // Add province base modifiers (with local province modifier effects removed)
+ for (ProvinceInstance const* province : controlled_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);
+ }
+ }
+
+ // 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;
+
+ modifier_sum.add_modifier_sum_exclude_targets(province_modifier_sum, PROVINCE);
+}
+
+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::push_contributing_modifiers(
+ ModifierEffect const& effect, std::vector<ModifierSum::modifier_entry_t>& contributions
+) const {
+ modifier_sum.push_contributing_modifiers(effect, contributions);
+}
+
+std::vector<ModifierSum::modifier_entry_t> 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
+) {
// Order of updates might need to be changed/functions split up to account for dependencies
_update_production(define_manager);
_update_budget();
@@ -932,7 +1061,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;
@@ -1012,9 +1141,11 @@ void CountryInstanceManager::update_rankings(Date today, DefineManager const& de
military_power_ranking[index]->military_rank = rank;
}
- const size_t max_great_power_rank = define_manager.get_great_power_rank();
- const size_t max_secondary_power_rank = define_manager.get_secondary_power_rank();
- const Timespan lose_great_power_grace_days = define_manager.get_lose_great_power_grace_days();
+ CountryDefines const& country_defines = define_manager.get_country_defines();
+
+ const size_t max_great_power_rank = country_defines.get_great_power_rank();
+ const size_t max_secondary_power_rank = country_defines.get_secondary_power_rank();
+ const Timespan lose_great_power_grace_days = country_defines.get_lose_great_power_grace_days();
// Demote great powers who have been below the max great power rank for longer than the demotion grace period and
// remove them from the list. We don't just demote them all and clear the list as when rebuilding we'd need to look
@@ -1091,16 +1222,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());
@@ -1117,8 +1248,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
});
}
@@ -1167,11 +1298,18 @@ 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
+ 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 a7128aa..6e01649 100644
--- a/src/openvic-simulation/country/CountryInstance.hpp
+++ b/src/openvic-simulation/country/CountryInstance.hpp
@@ -6,6 +6,7 @@
#include "openvic-simulation/military/Leader.hpp"
#include "openvic-simulation/military/UnitInstanceGroup.hpp"
+#include "openvic-simulation/modifier/ModifierSum.hpp"
#include "openvic-simulation/politics/Rule.hpp"
#include "openvic-simulation/pop/Pop.hpp"
#include "openvic-simulation/types/Date.hpp"
@@ -34,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. */
@@ -80,13 +83,17 @@ namespace OpenVic {
ordered_set<ProvinceInstance*> PROPERTY(core_provinces);
ordered_set<State*> PROPERTY(states);
+ // The total/resultant modifier affecting this country, including owned province contributions.
+ ModifierSum PROPERTY(modifier_sum);
+ std::vector<ModifierInstance> PROPERTY(event_modifiers);
+
/* Production */
fixed_point_t PROPERTY(industrial_power);
std::vector<std::pair<State const*, fixed_point_t>> PROPERTY(industrial_power_from_states);
std::vector<std::pair<CountryInstance const*, fixed_point_t>> PROPERTY(industrial_power_from_investments);
size_t PROPERTY(industrial_rank);
fixed_point_map_t<CountryInstance const*> PROPERTY(foreign_investments);
- IndexedMap<BuildingType, unlock_level_t> PROPERTY(unlocked_building_types);
+ IndexedMap<BuildingType, unlock_level_t> PROPERTY(building_type_unlock_levels);
// TODO - total amount of each good produced
/* Budget */
@@ -94,8 +101,8 @@ namespace OpenVic {
// TODO - cash stockpile change over last 30 days
/* Technology */
- IndexedMap<Technology, unlock_level_t> PROPERTY(unlocked_technologies);
- IndexedMap<Invention, unlock_level_t> PROPERTY(unlocked_inventions);
+ IndexedMap<Technology, unlock_level_t> PROPERTY(technology_unlock_levels);
+ IndexedMap<Invention, unlock_level_t> PROPERTY(invention_unlock_levels);
Technology const* PROPERTY(current_research);
fixed_point_t PROPERTY(invested_research_points);
Date PROPERTY(expected_completion_date);
@@ -118,10 +125,10 @@ namespace OpenVic {
IndexedMap<GovernmentType, GovernmentType const*> PROPERTY(government_flag_overrides);
GovernmentType const* PROPERTY(flag_government_type);
fixed_point_t PROPERTY(suppression_points);
- fixed_point_t PROPERTY(infamy);
- fixed_point_t PROPERTY(plurality);
+ fixed_point_t PROPERTY(infamy); // in 0-25+ range
+ fixed_point_t PROPERTY(plurality); // in 0-100 range
fixed_point_t PROPERTY(revanchism);
- IndexedMap<Crime, unlock_level_t> PROPERTY(unlocked_crimes);
+ IndexedMap<Crime, unlock_level_t> PROPERTY(crime_unlock_levels);
// TODO - rebel movements
/* Population */
@@ -132,7 +139,7 @@ namespace OpenVic {
// TODO - population change over last 30 days
fixed_point_t PROPERTY(national_consciousness);
fixed_point_t PROPERTY(national_militancy);
- IndexedMap<PopType, fixed_point_t> PROPERTY(pop_type_distribution);
+ IndexedMap<PopType, Pop::pop_size_t> PROPERTY(pop_type_distribution);
size_t PROPERTY(national_focus_capacity)
// TODO - national foci
@@ -165,32 +172,32 @@ namespace OpenVic {
fixed_point_t PROPERTY(total_consumed_ship_supply);
fixed_point_t PROPERTY(max_ship_supply);
fixed_point_t PROPERTY(leadership_points);
- fixed_point_t PROPERTY(war_exhaustion);
+ fixed_point_t PROPERTY(war_exhaustion); // in 0-100 range
bool PROPERTY_CUSTOM_PREFIX(mobilised, is);
bool PROPERTY_CUSTOM_PREFIX(disarmed, is);
- IndexedMap<RegimentType, unlock_level_t> PROPERTY(unlocked_regiment_types);
+ IndexedMap<RegimentType, unlock_level_t> PROPERTY(regiment_type_unlock_levels);
RegimentType::allowed_cultures_t PROPERTY(allowed_regiment_cultures);
- IndexedMap<ShipType, unlock_level_t> PROPERTY(unlocked_ship_types);
+ IndexedMap<ShipType, unlock_level_t> PROPERTY(ship_type_unlock_levels);
unlock_level_t PROPERTY(gas_attack_unlock_level);
unlock_level_t PROPERTY(gas_defence_unlock_level);
std::vector<unlock_level_t> PROPERTY(unit_variant_unlock_levels);
UNIT_BRANCHED_GETTER(get_unit_instance_groups, armies, navies);
UNIT_BRANCHED_GETTER(get_leaders, generals, admirals);
- UNIT_BRANCHED_GETTER(get_unlocked_unit_types, unlocked_regiment_types, unlocked_ship_types);
+ UNIT_BRANCHED_GETTER(get_unit_type_unlock_levels, regiment_type_unlock_levels, ship_type_unlock_levels);
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
);
public:
@@ -290,13 +297,28 @@ 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();
public:
- void update_gamestate(DefineManager const& define_manager, UnitTypeManager const& unit_type_manager);
+ 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<ModifierSum::modifier_entry_t>& contributions
+ ) const;
+ std::vector<ModifierSum::modifier_entry_t> get_contributing_modifiers(ModifierEffect const& effect) const;
+
+ void update_gamestate(
+ DefineManager const& define_manager, UnitTypeManager const& unit_type_manager,
+ ModifierEffectCache const& modifier_effect_cache
+ );
void tick();
};
@@ -324,16 +346,16 @@ namespace OpenVic {
bool 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
);
bool apply_history_to_countries(
@@ -341,7 +363,11 @@ namespace OpenVic {
MapInstance& map_instance
);
- void update_gamestate(Date today, DefineManager const& define_manager, UnitTypeManager const& unit_type_manager);
+ 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,
+ ModifierEffectCache const& modifier_effect_cache
+ );
void tick();
};
}
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index 1be040f..2b438c7 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -683,7 +683,7 @@ bool Dataloader::_load_map_dir(DefinitionManager& definition_manager) const {
static constexpr std::string_view default_provinces = "provinces.bmp";
static constexpr std::string_view default_positions = "positions.txt";
static constexpr std::string_view default_terrain = "terrain.bmp";
- static constexpr std::string_view default_rivers = "rivers.bmp"; // TODO - load rivers into map pixel data
+ static constexpr std::string_view default_rivers = "rivers.bmp";
static constexpr std::string_view default_terrain_definition = "terrain.txt";
static constexpr std::string_view default_tree_definition = "trees.txt"; /* Tree textures and density values (unused). */
static constexpr std::string_view default_continent = "continent.txt";
@@ -778,10 +778,15 @@ bool Dataloader::_load_map_dir(DefinitionManager& definition_manager) const {
Logger::error("Failed to load terrain types!");
ret = false;
}
+ if (!map_definition.get_terrain_type_manager().generate_modifiers(definition_manager.get_modifier_manager())) {
+ Logger::error("Failed to generate terrain-based modifiers!");
+ ret = false;
+ }
if (!map_definition.load_map_images(
lookup_file(append_string_views(map_directory, provinces)),
- lookup_file(append_string_views(map_directory, terrain)), false
+ lookup_file(append_string_views(map_directory, terrain)),
+ lookup_file(append_string_views(map_directory, rivers)), false
)) {
Logger::error("Failed to load map images!");
ret = false;
@@ -963,11 +968,12 @@ bool Dataloader::load_defines(DefinitionManager& definition_manager) {
Logger::error("Failed to load rebel types!");
ret = false;
}
+ definition_manager.get_modifier_manager().lock_all_modifier_except_base_country_effects();
if (!_load_technologies(definition_manager)) {
Logger::error("Failed to load technologies!");
ret = false;
}
- definition_manager.get_modifier_manager().lock_modifier_effects();
+ definition_manager.get_modifier_manager().lock_base_country_modifier_effects();
if (!definition_manager.get_politics_manager().get_rule_manager().setup_rules(
definition_manager.get_economy_manager().get_building_type_manager()
)) {
@@ -1007,6 +1013,7 @@ bool Dataloader::load_defines(DefinitionManager& definition_manager) {
Logger::error("Failed to load crime modifiers!");
ret = false;
}
+
if (!definition_manager.get_modifier_manager().load_event_modifiers(
parse_defines(lookup_file(event_modifiers_file)).get_file_node()
)) {
@@ -1019,6 +1026,8 @@ bool Dataloader::load_defines(DefinitionManager& definition_manager) {
Logger::error("Failed to load static modifiers!");
ret = false;
}
+ definition_manager.get_modifier_manager().lock_event_modifiers();
+
if (!definition_manager.get_modifier_manager().load_triggered_modifiers(
parse_defines_cached(lookup_file(triggered_modifiers_file)).get_file_node()
)) {
diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp
index ad130ad..b7b3e34 100644
--- a/src/openvic-simulation/dataloader/NodeTools.cpp
+++ b/src/openvic-simulation/dataloader/NodeTools.cpp
@@ -234,19 +234,19 @@ node_callback_t NodeTools::expect_date_identifier_or_string(callback_t<Date> cal
}
node_callback_t NodeTools::expect_years(callback_t<Timespan> callback) {
- return expect_uint<Timespan::day_t>([callback](Timespan::day_t val) -> bool {
+ return expect_int<Timespan::day_t>([callback](Timespan::day_t val) -> bool {
return callback(Timespan::from_years(val));
});
}
node_callback_t NodeTools::expect_months(callback_t<Timespan> callback) {
- return expect_uint<Timespan::day_t>([callback](Timespan::day_t val) -> bool {
+ return expect_int<Timespan::day_t>([callback](Timespan::day_t val) -> bool {
return callback(Timespan::from_months(val));
});
}
node_callback_t NodeTools::expect_days(callback_t<Timespan> callback) {
- return expect_uint<Timespan::day_t>([callback](Timespan::day_t val) -> bool {
+ return expect_int<Timespan::day_t>([callback](Timespan::day_t val) -> bool {
return callback(Timespan::from_days(val));
});
}
diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp
index 51e3e82..43c5092 100644
--- a/src/openvic-simulation/dataloader/NodeTools.hpp
+++ b/src/openvic-simulation/dataloader/NodeTools.hpp
@@ -287,11 +287,14 @@ namespace OpenVic {
ret &= add_key_map_entries(FWD(key_map), FWD(args)...);
return ret;
}
+
template<IsOrderedMap Map>
NodeCallback auto expect_dictionary_key_map_and_length_and_default(
Map&& key_map, LengthCallback auto&& length_callback, KeyValueCallback auto&& default_callback
) {
- return [length_callback = FWD(length_callback), default_callback = FWD(default_callback), key_map = MOV(key_map)](ast::NodeCPtr node) mutable -> bool {
+ return [length_callback = FWD(length_callback), default_callback = FWD(default_callback), key_map = MOV(key_map)](
+ ast::NodeCPtr node
+ ) mutable -> bool {
bool ret = expect_dictionary_and_length(
FWD(length_callback), dictionary_keys_callback(key_map, FWD(default_callback))
)(node);
@@ -335,6 +338,28 @@ namespace OpenVic {
return expect_dictionary_key_map_and_length_and_default(FWD(key_map), FWD(length_callback), FWD(default_callback));
}
+ template<IsOrderedMap Map, typename... Args>
+ NodeCallback auto expect_dictionary_key_map_and_length(
+ Map&& key_map, LengthCallback auto&& length_callback, Args&&... args
+ ) {
+ add_key_map_entries(FWD(key_map), FWD(args)...);
+ return expect_dictionary_key_map_and_length(FWD(key_map), FWD(length_callback));
+ }
+
+ template<IsOrderedMap Map, typename... Args>
+ NodeCallback auto expect_dictionary_key_map_and_default(
+ Map&& key_map, KeyValueCallback auto&& default_callback, Args&&... args
+ ) {
+ add_key_map_entries(FWD(key_map), FWD(args)...);
+ return expect_dictionary_key_map_and_default(FWD(key_map), FWD(default_callback));
+ }
+
+ template<IsOrderedMap Map, typename... Args>
+ NodeCallback auto expect_dictionary_key_map(Map&& key_map, Args&&... args) {
+ add_key_map_entries(FWD(key_map), FWD(args)...);
+ return expect_dictionary_key_map(FWD(key_map));
+ }
+
template<StringMapCase Case = StringMapCaseSensitive, typename... Args>
NodeCallback auto expect_dictionary_keys_and_length_and_default(
LengthCallback auto&& length_callback, KeyValueCallback auto&& default_callback, Args&&... args
diff --git a/src/openvic-simulation/dataloader/Vic2PathSearch.cpp b/src/openvic-simulation/dataloader/Vic2PathSearch.cpp
index a23d0ce..a1a125d 100644
--- a/src/openvic-simulation/dataloader/Vic2PathSearch.cpp
+++ b/src/openvic-simulation/dataloader/Vic2PathSearch.cpp
@@ -206,7 +206,7 @@ static fs::path _search_for_game_path(fs::path hint_path = {}) {
}
return empty_fail_result_callback("Could not parse VDF at '", current_path, "'.");
}
- std::optional current_node = *(parser.get_key_values());
+ std::optional current_node = *parser.get_key_values();
// check "libraryfolders" list
auto it = current_node.value().find("libraryfolders");
diff --git a/src/openvic-simulation/defines/AIDefines.cpp b/src/openvic-simulation/defines/AIDefines.cpp
new file mode 100644
index 0000000..1229daa
--- /dev/null
+++ b/src/openvic-simulation/defines/AIDefines.cpp
@@ -0,0 +1,100 @@
+#include "AIDefines.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+AIDefines::AIDefines()
+ : colony_weight {},
+ administrator_weight {},
+ industryworker_weight {},
+ educator_weight {},
+ soldier_weight {},
+ soldier_fraction {},
+ capitalist_fraction {},
+ production_weight {},
+ spam_penalty {},
+ one_side_max_warscore {},
+ pop_project_investment_max_budget_factor {},
+ relation_limit_no_alliance_offer {},
+ naval_supply_penalty_limit {},
+ chance_build_railroad {},
+ chance_build_naval_base {},
+ chance_build_fort {},
+ chance_invest_pop_proj {},
+ chance_foreign_invest {},
+ tws_awareness_score_low_cap {},
+ tws_awareness_score_aspect {},
+ peace_base_reluctance {},
+ peace_time_duration {},
+ peace_time_factor {},
+ peace_time_factor_no_goals {},
+ peace_war_exhaustion_factor {},
+ peace_war_direction_factor {},
+ peace_war_direction_winning_mult {},
+ peace_force_balance_factor {},
+ peace_ally_base_reluctance_mult {},
+ peace_ally_time_mult {},
+ peace_ally_war_exhaustion_mult {},
+ peace_ally_war_direction_mult {},
+ peace_ally_force_balance_mult {},
+ aggression_base {},
+ aggression_unciv_bonus {},
+ fleet_size {},
+ min_fleets {},
+ max_fleets {},
+ time_before_disband {} {}
+
+std::string_view AIDefines::get_name() const {
+ return "ai";
+}
+
+node_callback_t AIDefines::expect_defines() {
+ return expect_dictionary_keys(
+ "COLONY_WEIGHT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(colony_weight)),
+ "ADMINISTRATOR_WEIGHT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(administrator_weight)),
+ "INDUSTRYWORKER_WEIGHT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(industryworker_weight)),
+ "EDUCATOR_WEIGHT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(educator_weight)),
+ "SOLDIER_WEIGHT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(soldier_weight)),
+ "SOLDIER_FRACTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(soldier_fraction)),
+ "CAPITALIST_FRACTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(capitalist_fraction)),
+ "PRODUCTION_WEIGHT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(production_weight)),
+ "SPAM_PENALTY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(spam_penalty)),
+ "ONE_SIDE_MAX_WARSCORE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(one_side_max_warscore)),
+ "POP_PROJECT_INVESTMENT_MAX_BUDGET_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(pop_project_investment_max_budget_factor)),
+ "RELATION_LIMIT_NO_ALLIANCE_OFFER", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(relation_limit_no_alliance_offer)),
+ "NAVAL_SUPPLY_PENALTY_LIMIT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(naval_supply_penalty_limit)),
+ "CHANCE_BUILD_RAILROAD", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(chance_build_railroad)),
+ "CHANCE_BUILD_NAVAL_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(chance_build_naval_base)),
+ "CHANCE_BUILD_FORT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(chance_build_fort)),
+ "CHANCE_INVEST_POP_PROJ", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(chance_invest_pop_proj)),
+ "CHANCE_FOREIGN_INVEST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(chance_foreign_invest)),
+ "TWS_AWARENESS_SCORE_LOW_CAP", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tws_awareness_score_low_cap)),
+ "TWS_AWARENESS_SCORE_ASPECT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tws_awareness_score_aspect)),
+ "PEACE_BASE_RELUCTANCE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_base_reluctance)),
+ "PEACE_TIME_MONTHS", ONE_EXACTLY, expect_months(assign_variable_callback(peace_time_duration)),
+ "PEACE_TIME_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_time_factor)),
+ "PEACE_TIME_FACTOR_NO_GOALS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_time_factor_no_goals)),
+ "PEACE_WAR_EXHAUSTION_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_war_exhaustion_factor)),
+ "PEACE_WAR_DIRECTION_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_war_direction_factor)),
+ "PEACE_WAR_DIRECTION_WINNING_MULT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(peace_war_direction_winning_mult)),
+ "PEACE_FORCE_BALANCE_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_force_balance_factor)),
+ "PEACE_ALLY_BASE_RELUCTANCE_MULT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(peace_ally_base_reluctance_mult)),
+ "PEACE_ALLY_TIME_MULT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_ally_time_mult)),
+ "PEACE_ALLY_WAR_EXHAUSTION_MULT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(peace_ally_war_exhaustion_mult)),
+ "PEACE_ALLY_WAR_DIRECTION_MULT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(peace_ally_war_direction_mult)),
+ "PEACE_ALLY_FORCE_BALANCE_MULT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(peace_ally_force_balance_mult)),
+ "AGGRESSION_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(aggression_base)),
+ "AGGRESSION_UNCIV_BONUS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(aggression_unciv_bonus)),
+ "FLEET_SIZE", ONE_EXACTLY, expect_uint(assign_variable_callback(fleet_size)),
+ "MIN_FLEETS", ONE_EXACTLY, expect_uint(assign_variable_callback(min_fleets)),
+ "MAX_FLEETS", ONE_EXACTLY, expect_uint(assign_variable_callback(max_fleets)),
+ "MONTHS_BEFORE_DISBAND", ONE_EXACTLY, expect_months(assign_variable_callback(time_before_disband))
+ );
+}
diff --git a/src/openvic-simulation/defines/AIDefines.hpp b/src/openvic-simulation/defines/AIDefines.hpp
new file mode 100644
index 0000000..c69e9af
--- /dev/null
+++ b/src/openvic-simulation/defines/AIDefines.hpp
@@ -0,0 +1,60 @@
+#pragma once
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ struct DefineManager;
+
+ struct AIDefines {
+ friend struct DefineManager;
+
+ private:
+ fixed_point_t PROPERTY(colony_weight);
+ fixed_point_t PROPERTY(administrator_weight);
+ fixed_point_t PROPERTY(industryworker_weight);
+ fixed_point_t PROPERTY(educator_weight);
+ fixed_point_t PROPERTY(soldier_weight);
+ fixed_point_t PROPERTY(soldier_fraction);
+ fixed_point_t PROPERTY(capitalist_fraction);
+ fixed_point_t PROPERTY(production_weight);
+ fixed_point_t PROPERTY(spam_penalty);
+ fixed_point_t PROPERTY(one_side_max_warscore);
+ fixed_point_t PROPERTY(pop_project_investment_max_budget_factor);
+ fixed_point_t PROPERTY(relation_limit_no_alliance_offer);
+ fixed_point_t PROPERTY(naval_supply_penalty_limit);
+ fixed_point_t PROPERTY(chance_build_railroad);
+ fixed_point_t PROPERTY(chance_build_naval_base);
+ fixed_point_t PROPERTY(chance_build_fort);
+ fixed_point_t PROPERTY(chance_invest_pop_proj);
+ fixed_point_t PROPERTY(chance_foreign_invest);
+ fixed_point_t PROPERTY(tws_awareness_score_low_cap);
+ fixed_point_t PROPERTY(tws_awareness_score_aspect);
+ fixed_point_t PROPERTY(peace_base_reluctance);
+ Timespan PROPERTY(peace_time_duration);
+ fixed_point_t PROPERTY(peace_time_factor);
+ fixed_point_t PROPERTY(peace_time_factor_no_goals);
+ fixed_point_t PROPERTY(peace_war_exhaustion_factor);
+ fixed_point_t PROPERTY(peace_war_direction_factor);
+ fixed_point_t PROPERTY(peace_war_direction_winning_mult);
+ fixed_point_t PROPERTY(peace_force_balance_factor);
+ fixed_point_t PROPERTY(peace_ally_base_reluctance_mult);
+ fixed_point_t PROPERTY(peace_ally_time_mult);
+ fixed_point_t PROPERTY(peace_ally_war_exhaustion_mult);
+ fixed_point_t PROPERTY(peace_ally_war_direction_mult);
+ fixed_point_t PROPERTY(peace_ally_force_balance_mult);
+ fixed_point_t PROPERTY(aggression_base);
+ fixed_point_t PROPERTY(aggression_unciv_bonus);
+ size_t PROPERTY(fleet_size);
+ size_t PROPERTY(min_fleets);
+ size_t PROPERTY(max_fleets);
+ Timespan PROPERTY(time_before_disband);
+
+ AIDefines();
+
+ std::string_view get_name() const;
+ NodeTools::node_callback_t expect_defines();
+ };
+}
diff --git a/src/openvic-simulation/defines/CountryDefines.cpp b/src/openvic-simulation/defines/CountryDefines.cpp
new file mode 100644
index 0000000..686f209
--- /dev/null
+++ b/src/openvic-simulation/defines/CountryDefines.cpp
@@ -0,0 +1,228 @@
+#include "CountryDefines.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+CountryDefines::CountryDefines()
+ : nationalism_duration {},
+ rebels_hold_capital_success_duration {}, // NOT USED
+ rebel_success_duration {},
+ base_country_tax_efficiency {},
+ base_country_admin_efficiency {},
+ gold_to_cash_rate {},
+ gold_to_worker_pay_rate {},
+ great_power_rank {},
+ lose_great_power_grace_days {},
+ infamy_containment_limit {},
+ max_bureaucracy_percentage {},
+ bureaucracy_percentage_increment {},
+ min_crimefight_percent {},
+ max_crimefight_percent {},
+ admin_efficiency_crimefight_percent {},
+ conservative_increase_after_reform {},
+ campaign_event_base_duration {},
+ campaign_event_min_duration {}, // NOT USED
+ campaign_event_state_duration_modifier {}, // NOT USED
+ campaign_duration {},
+ secondary_power_rank {},
+ colony_to_state_prestige_gain {},
+ colonial_liferating {},
+ base_greatpower_daily_influence {},
+ ai_support_reform {},
+ base_monthly_diplopoints {},
+ diplomat_travel_duration {},
+ province_overseas_penalty {},
+ noncore_tax_penalty {},
+ base_tariff_efficiency {},
+ colony_formed_prestige {},
+ created_cb_valid_time {},
+ loyalty_boost_on_party_win {},
+ movement_radicalism_base {},
+ movement_radicalism_passed_reform_effect {},
+ movement_radicalism_nationalism_factor {},
+ suppression_points_gain_base {},
+ suppress_bureaucrat_factor {},
+ wrong_reform_militancy_impact {},
+ suppression_radicalisation_hit {},
+ country_investment_industrial_score_factor {},
+ unciv_tech_spread_max {},
+ unciv_tech_spread_min {},
+ min_delay_duration_between_reforms {},
+ economic_reform_uh_factor {},
+ military_reform_uh_factor {},
+ wrong_reform_radical_impact {},
+ tech_year_span {},
+ tech_factor_vassal {},
+ max_suppression {},
+ prestige_hit_on_break_country {},
+ min_mobilize_limit {},
+ pop_growth_country_cache_days {},
+ newspaper_printing_frequency {},
+ newspaper_timeout_period {},
+ newspaper_max_tension {},
+ naval_base_supply_score_base {},
+ naval_base_supply_score_empty {},
+ naval_base_non_core_supply_score {},
+ colonial_points_from_supply_factor {},
+ colonial_points_for_non_core_base {},
+ mobilization_speed_base {},
+ mobilization_speed_rails_mult {},
+ colonization_interest_lead {},
+ colonization_influence_lead {},
+ colonization_duration {},
+ colonization_days_between_investment {},
+ colonization_days_for_initial_investment {},
+ colonization_protectorate_province_maintainance {},
+ colonization_colony_province_maintainance {},
+ colonization_colony_industry_maintainance {},
+ colonization_colony_railway_maintainance {},
+ colonization_interest_cost_initial {},
+ colonization_interest_cost_neighbor_modifier {},
+ colonization_interest_cost {},
+ colonization_influence_cost {},
+ colonization_extra_guard_cost {},
+ colonization_release_dominion_cost {},
+ colonization_create_state_cost {},
+ colonization_create_protectorate_cost {},
+ colonization_create_colony_cost {},
+ colonization_colony_state_distance {},
+ colonization_influence_temperature_per_day {},
+ colonization_influence_temperature_per_level {},
+ party_loyalty_hit_on_war_loss {},
+ research_points_on_conquer_mult {},
+ max_research_points {} {}
+
+std::string_view CountryDefines::get_name() const {
+ return "country";
+}
+
+node_callback_t CountryDefines::expect_defines() {
+ return expect_dictionary_keys(
+ "YEARS_OF_NATIONALISM", ONE_EXACTLY, expect_years(assign_variable_callback(nationalism_duration)),
+ "MONTHS_UNTIL_BROKEN", ZERO_OR_ONE, // NOT USED
+ expect_months(assign_variable_callback(rebels_hold_capital_success_duration)),
+ "REBEL_ACCEPTANCE_MONTHS", ONE_EXACTLY, expect_months(assign_variable_callback(rebel_success_duration)),
+ "BASE_COUNTRY_TAX_EFFICIENCY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base_country_tax_efficiency)),
+ "BASE_COUNTRY_ADMIN_EFFICIENCY", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(base_country_admin_efficiency)),
+ "GOLD_TO_CASH_RATE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gold_to_cash_rate)),
+ "GOLD_TO_WORKER_PAY_RATE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gold_to_worker_pay_rate)),
+ "GREAT_NATIONS_COUNT", ONE_EXACTLY, expect_uint(assign_variable_callback(great_power_rank)),
+ "GREATNESS_DAYS", ONE_EXACTLY, expect_days(assign_variable_callback(lose_great_power_grace_days)),
+ "BADBOY_LIMIT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_containment_limit)),
+ "MAX_BUREAUCRACY_PERCENTAGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_bureaucracy_percentage)),
+ "BUREAUCRACY_PERCENTAGE_INCREMENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(bureaucracy_percentage_increment)),
+ "MIN_CRIMEFIGHT_PERCENT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(min_crimefight_percent)),
+ "MAX_CRIMEFIGHT_PERCENT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_crimefight_percent)),
+ "ADMIN_EFFICIENCY_CRIMEFIGHT_PERCENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(admin_efficiency_crimefight_percent)),
+ "CONSERVATIVE_INCREASE_AFTER_REFORM", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(conservative_increase_after_reform)),
+ "CAMPAIGN_EVENT_BASE_TIME", ONE_EXACTLY, expect_days(assign_variable_callback(campaign_event_base_duration)),
+ "CAMPAIGN_EVENT_MIN_TIME", ZERO_OR_ONE, expect_days(assign_variable_callback(campaign_event_min_duration)), // NOT USED
+ "CAMPAIGN_EVENT_STATE_SCALE", ZERO_OR_ONE, // NOT USED
+ expect_days(assign_variable_callback(campaign_event_state_duration_modifier)),
+ "CAMPAIGN_DURATION", ONE_EXACTLY, expect_months(assign_variable_callback(campaign_duration)),
+ "COLONIAL_RANK", ONE_EXACTLY, expect_uint(assign_variable_callback(secondary_power_rank)),
+ "COLONY_TO_STATE_PRESTIGE_GAIN", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colony_to_state_prestige_gain)),
+ "COLONIAL_LIFERATING", ONE_EXACTLY, expect_uint(assign_variable_callback(colonial_liferating)),
+ "BASE_GREATPOWER_DAILY_INFLUENCE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(base_greatpower_daily_influence)),
+ "AI_SUPPORT_REFORM", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ai_support_reform)),
+ "BASE_MONTHLY_DIPLOPOINTS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base_monthly_diplopoints)),
+ "DIPLOMAT_TRAVEL_TIME", ONE_EXACTLY, expect_days(assign_variable_callback(diplomat_travel_duration)),
+ "PROVINCE_OVERSEAS_PENALTY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(province_overseas_penalty)),
+ "NONCORE_TAX_PENALTY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(noncore_tax_penalty)),
+ "BASE_TARIFF_EFFICIENCY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base_tariff_efficiency)),
+ "COLONY_FORMED_PRESTIGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(colony_formed_prestige)),
+ "CREATED_CB_VALID_TIME", ONE_EXACTLY, expect_months(assign_variable_callback(created_cb_valid_time)),
+ "LOYALTY_BOOST_ON_PARTY_WIN", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(loyalty_boost_on_party_win)),
+ "MOVEMENT_RADICALISM_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(movement_radicalism_base)),
+ "MOVEMENT_RADICALISM_PASSED_REFORM_EFFECT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(movement_radicalism_passed_reform_effect)),
+ "MOVEMENT_RADICALISM_NATIONALISM_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(movement_radicalism_nationalism_factor)),
+ "SUPPRESSION_POINTS_GAIN_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(suppression_points_gain_base)),
+ "SUPPRESS_BUREAUCRAT_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(suppress_bureaucrat_factor)),
+ "WRONG_REFORM_MILITANCY_IMPACT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(wrong_reform_militancy_impact)),
+ "SUPPRESSION_RADICALISATION_HIT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(suppression_radicalisation_hit)),
+ "INVESTMENT_SCORE_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(country_investment_industrial_score_factor)),
+ "UNCIV_TECH_SPREAD_MAX", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(unciv_tech_spread_max)),
+ "UNCIV_TECH_SPREAD_MIN", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(unciv_tech_spread_min)),
+ "MIN_DELAY_BETWEEN_REFORMS", ONE_EXACTLY, expect_months(assign_variable_callback(min_delay_duration_between_reforms)),
+ "ECONOMIC_REFORM_UH_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(economic_reform_uh_factor)),
+ "MILITARY_REFORM_UH_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(military_reform_uh_factor)),
+ "WRONG_REFORM_RADICAL_IMPACT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(wrong_reform_radical_impact)),
+ "TECH_YEAR_SPAN", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tech_year_span)),
+ "TECH_FACTOR_VASSAL", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tech_factor_vassal)),
+ "MAX_SUPPRESSION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_suppression)),
+ "PRESTIGE_HIT_ON_BREAK_COUNTRY", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(prestige_hit_on_break_country)),
+ "MIN_MOBILIZE_LIMIT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(min_mobilize_limit)),
+ "POP_GROWTH_COUNTRY_CACHE_DAYS", ONE_EXACTLY, expect_days(assign_variable_callback(pop_growth_country_cache_days)),
+ "NEWSPAPER_PRINTING_FREQUENCY", ONE_EXACTLY, expect_days(assign_variable_callback(newspaper_printing_frequency)),
+ "NEWSPAPER_TIMEOUT_PERIOD", ONE_EXACTLY, expect_days(assign_variable_callback(newspaper_timeout_period)),
+ "NEWSPAPER_MAX_TENSION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(newspaper_max_tension)),
+ "NAVAL_BASE_SUPPLY_SCORE_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_base_supply_score_base)),
+ "NAVAL_BASE_SUPPLY_SCORE_EMPTY", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_base_supply_score_empty)),
+ "NAVAL_BASE_NON_CORE_SUPPLY_SCORE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_base_non_core_supply_score)),
+ "COLONIAL_POINTS_FROM_SUPPLY_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonial_points_from_supply_factor)),
+ "COLONIAL_POINTS_FOR_NON_CORE_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonial_points_for_non_core_base)),
+ "MOBILIZATION_SPEED_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mobilization_speed_base)),
+ "MOBILIZATION_SPEED_RAILS_MULT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(mobilization_speed_rails_mult)),
+ "COLONIZATION_INTEREST_LEAD", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(colonization_interest_lead)),
+ "COLONIZATION_INFLUENCE_LEAD", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(colonization_influence_lead)),
+ "COLONIZATION_MONTHS_TO_COLONIZE", ONE_EXACTLY, expect_months(assign_variable_callback(colonization_duration)),
+ "COLONIZATION_DAYS_BETWEEN_INVESTMENT", ONE_EXACTLY,
+ expect_days(assign_variable_callback(colonization_days_between_investment)),
+ "COLONIZATION_DAYS_FOR_INITIAL_INVESTMENT", ONE_EXACTLY,
+ expect_days(assign_variable_callback(colonization_days_for_initial_investment)),
+ "COLONIZATION_PROTECTORATE_PROVINCE_MAINTAINANCE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_protectorate_province_maintainance)),
+ "COLONIZATION_COLONY_PROVINCE_MAINTAINANCE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_colony_province_maintainance)),
+ "COLONIZATION_COLONY_INDUSTRY_MAINTAINANCE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_colony_industry_maintainance)),
+ "COLONIZATION_COLONY_RAILWAY_MAINTAINANCE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_colony_railway_maintainance)),
+ "COLONIZATION_INTEREST_COST_INITIAL", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_interest_cost_initial)),
+ "COLONIZATION_INTEREST_COST_NEIGHBOR_MODIFIER", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_interest_cost_neighbor_modifier)),
+ "COLONIZATION_INTEREST_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(colonization_interest_cost)),
+ "COLONIZATION_INFLUENCE_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(colonization_influence_cost)),
+ "COLONIZATION_EXTRA_GUARD_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_extra_guard_cost)),
+ "COLONIZATION_RELEASE_DOMINION_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_release_dominion_cost)),
+ "COLONIZATION_CREATE_STATE_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_create_state_cost)),
+ "COLONIZATION_CREATE_PROTECTORATE_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_create_protectorate_cost)),
+ "COLONIZATION_CREATE_COLONY_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_create_colony_cost)),
+ "COLONIZATION_COLONY_STATE_DISTANCE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_colony_state_distance)),
+ "COLONIZATION_INFLUENCE_TEMPERATURE_PER_DAY", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_influence_temperature_per_day)),
+ "COLONIZATION_INFLUENCE_TEMPERATURE_PER_LEVEL", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(colonization_influence_temperature_per_level)),
+ "PARTY_LOYALTY_HIT_ON_WAR_LOSS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(party_loyalty_hit_on_war_loss)),
+ "RESEARCH_POINTS_ON_CONQUER_MULT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(research_points_on_conquer_mult)),
+ "MAX_RESEARCH_POINTS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_research_points))
+ );
+}
diff --git a/src/openvic-simulation/defines/CountryDefines.hpp b/src/openvic-simulation/defines/CountryDefines.hpp
new file mode 100644
index 0000000..b97f6f3
--- /dev/null
+++ b/src/openvic-simulation/defines/CountryDefines.hpp
@@ -0,0 +1,109 @@
+#pragma once
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/map/ProvinceInstance.hpp"
+#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ struct DefineManager;
+
+ struct CountryDefines {
+ friend struct DefineManager;
+
+ private:
+ Timespan PROPERTY(nationalism_duration);
+ Timespan PROPERTY(rebels_hold_capital_success_duration); // NOT USED
+ Timespan PROPERTY(rebel_success_duration);
+ fixed_point_t PROPERTY(base_country_tax_efficiency);
+ fixed_point_t PROPERTY(base_country_admin_efficiency);
+ fixed_point_t PROPERTY(gold_to_cash_rate);
+ fixed_point_t PROPERTY(gold_to_worker_pay_rate);
+ size_t PROPERTY(great_power_rank);
+ Timespan PROPERTY(lose_great_power_grace_days);
+ fixed_point_t PROPERTY(infamy_containment_limit);
+ fixed_point_t PROPERTY(max_bureaucracy_percentage);
+ fixed_point_t PROPERTY(bureaucracy_percentage_increment);
+ fixed_point_t PROPERTY(min_crimefight_percent);
+ fixed_point_t PROPERTY(max_crimefight_percent);
+ fixed_point_t PROPERTY(admin_efficiency_crimefight_percent);
+ fixed_point_t PROPERTY(conservative_increase_after_reform);
+ Timespan PROPERTY(campaign_event_base_duration);
+ Timespan PROPERTY(campaign_event_min_duration); // NOT USED
+ Timespan PROPERTY(campaign_event_state_duration_modifier); // NOT USED
+ Timespan PROPERTY(campaign_duration);
+ size_t PROPERTY(secondary_power_rank);
+ fixed_point_t PROPERTY(colony_to_state_prestige_gain);
+ ProvinceInstance::life_rating_t PROPERTY(colonial_liferating);
+ fixed_point_t PROPERTY(base_greatpower_daily_influence);
+ fixed_point_t PROPERTY(ai_support_reform);
+ fixed_point_t PROPERTY(base_monthly_diplopoints);
+ Timespan PROPERTY(diplomat_travel_duration);
+ fixed_point_t PROPERTY(province_overseas_penalty);
+ fixed_point_t PROPERTY(noncore_tax_penalty);
+ fixed_point_t PROPERTY(base_tariff_efficiency);
+ fixed_point_t PROPERTY(colony_formed_prestige);
+ Timespan PROPERTY(created_cb_valid_time);
+ fixed_point_t PROPERTY(loyalty_boost_on_party_win);
+ fixed_point_t PROPERTY(movement_radicalism_base);
+ fixed_point_t PROPERTY(movement_radicalism_passed_reform_effect);
+ fixed_point_t PROPERTY(movement_radicalism_nationalism_factor);
+ fixed_point_t PROPERTY(suppression_points_gain_base);
+ fixed_point_t PROPERTY(suppress_bureaucrat_factor);
+ fixed_point_t PROPERTY(wrong_reform_militancy_impact);
+ fixed_point_t PROPERTY(suppression_radicalisation_hit);
+ fixed_point_t PROPERTY(country_investment_industrial_score_factor);
+ fixed_point_t PROPERTY(unciv_tech_spread_max);
+ fixed_point_t PROPERTY(unciv_tech_spread_min);
+ Timespan PROPERTY(min_delay_duration_between_reforms);
+ fixed_point_t PROPERTY(economic_reform_uh_factor);
+ fixed_point_t PROPERTY(military_reform_uh_factor);
+ fixed_point_t PROPERTY(wrong_reform_radical_impact);
+ fixed_point_t PROPERTY(tech_year_span);
+ fixed_point_t PROPERTY(tech_factor_vassal);
+ fixed_point_t PROPERTY(max_suppression);
+ fixed_point_t PROPERTY(prestige_hit_on_break_country);
+ fixed_point_t PROPERTY(min_mobilize_limit);
+ Timespan PROPERTY(pop_growth_country_cache_days);
+ Timespan PROPERTY(newspaper_printing_frequency);
+ Timespan PROPERTY(newspaper_timeout_period);
+ fixed_point_t PROPERTY(newspaper_max_tension);
+ fixed_point_t PROPERTY(naval_base_supply_score_base);
+ fixed_point_t PROPERTY(naval_base_supply_score_empty);
+ fixed_point_t PROPERTY(naval_base_non_core_supply_score);
+ fixed_point_t PROPERTY(colonial_points_from_supply_factor);
+ fixed_point_t PROPERTY(colonial_points_for_non_core_base);
+ fixed_point_t PROPERTY(mobilization_speed_base);
+ fixed_point_t PROPERTY(mobilization_speed_rails_mult);
+ fixed_point_t PROPERTY(colonization_interest_lead);
+ fixed_point_t PROPERTY(colonization_influence_lead);
+ Timespan PROPERTY(colonization_duration);
+ Timespan PROPERTY(colonization_days_between_investment);
+ Timespan PROPERTY(colonization_days_for_initial_investment);
+ fixed_point_t PROPERTY(colonization_protectorate_province_maintainance);
+ fixed_point_t PROPERTY(colonization_colony_province_maintainance);
+ fixed_point_t PROPERTY(colonization_colony_industry_maintainance);
+ fixed_point_t PROPERTY(colonization_colony_railway_maintainance);
+ fixed_point_t PROPERTY(colonization_interest_cost_initial);
+ fixed_point_t PROPERTY(colonization_interest_cost_neighbor_modifier);
+ fixed_point_t PROPERTY(colonization_interest_cost);
+ fixed_point_t PROPERTY(colonization_influence_cost);
+ fixed_point_t PROPERTY(colonization_extra_guard_cost);
+ fixed_point_t PROPERTY(colonization_release_dominion_cost);
+ fixed_point_t PROPERTY(colonization_create_state_cost);
+ fixed_point_t PROPERTY(colonization_create_protectorate_cost);
+ fixed_point_t PROPERTY(colonization_create_colony_cost);
+ fixed_point_t PROPERTY(colonization_colony_state_distance);
+ fixed_point_t PROPERTY(colonization_influence_temperature_per_day);
+ fixed_point_t PROPERTY(colonization_influence_temperature_per_level);
+ fixed_point_t PROPERTY(party_loyalty_hit_on_war_loss);
+ fixed_point_t PROPERTY(research_points_on_conquer_mult);
+ fixed_point_t PROPERTY(max_research_points);
+
+ CountryDefines();
+
+ std::string_view get_name() const;
+ NodeTools::node_callback_t expect_defines();
+ };
+}
diff --git a/src/openvic-simulation/defines/Define.cpp b/src/openvic-simulation/defines/Define.cpp
new file mode 100644
index 0000000..8d910cb
--- /dev/null
+++ b/src/openvic-simulation/defines/Define.cpp
@@ -0,0 +1,25 @@
+#include "Define.hpp"
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+DefineManager::DefineManager() : start_date {}, end_date {} {}
+
+bool DefineManager::load_defines_file(ast::NodeCPtr root) {
+ return expect_dictionary_keys(
+ "defines", ONE_EXACTLY, expect_dictionary_keys(
+ "start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start_date)),
+ "end_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(end_date)),
+
+ ai_defines.get_name(), ONE_EXACTLY, ai_defines.expect_defines(),
+ country_defines.get_name(), ONE_EXACTLY, country_defines.expect_defines(),
+ diplomacy_defines.get_name(), ONE_EXACTLY, diplomacy_defines.expect_defines(),
+ economy_defines.get_name(), ONE_EXACTLY, economy_defines.expect_defines(),
+ graphics_defines.get_name(), ONE_EXACTLY, graphics_defines.expect_defines(),
+ military_defines.get_name(), ONE_EXACTLY, military_defines.expect_defines(),
+ pops_defines.get_name(), ONE_EXACTLY, pops_defines.expect_defines()
+ )
+ )(root);
+}
diff --git a/src/openvic-simulation/defines/Define.hpp b/src/openvic-simulation/defines/Define.hpp
new file mode 100644
index 0000000..e1b2bc2
--- /dev/null
+++ b/src/openvic-simulation/defines/Define.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "openvic-simulation/defines/AIDefines.hpp"
+#include "openvic-simulation/defines/CountryDefines.hpp"
+#include "openvic-simulation/defines/DiplomacyDefines.hpp"
+#include "openvic-simulation/defines/EconomyDefines.hpp"
+#include "openvic-simulation/defines/GraphicsDefines.hpp"
+#include "openvic-simulation/defines/MilitaryDefines.hpp"
+#include "openvic-simulation/defines/PopsDefines.hpp"
+#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ struct DefineManager {
+ private:
+ // Date
+ Date PROPERTY(start_date);
+ Date PROPERTY(end_date);
+
+ // Other define groups
+ AIDefines PROPERTY(ai_defines);
+ CountryDefines PROPERTY(country_defines);
+ DiplomacyDefines PROPERTY(diplomacy_defines);
+ EconomyDefines PROPERTY(economy_defines);
+ GraphicsDefines PROPERTY(graphics_defines);
+ MilitaryDefines PROPERTY(military_defines);
+ PopsDefines PROPERTY(pops_defines);
+
+ public:
+ DefineManager();
+
+ constexpr bool in_game_period(Date date) const {
+ return date.in_range(start_date, end_date);
+ }
+
+ bool load_defines_file(ast::NodeCPtr root);
+ };
+}
diff --git a/src/openvic-simulation/defines/DiplomacyDefines.cpp b/src/openvic-simulation/defines/DiplomacyDefines.cpp
new file mode 100644
index 0000000..5facbe4
--- /dev/null
+++ b/src/openvic-simulation/defines/DiplomacyDefines.cpp
@@ -0,0 +1,914 @@
+#include "DiplomacyDefines.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+DiplomacyDefines::DiplomacyDefines()
+ : peace_cost_add_to_sphere {},
+ peace_cost_release_puppet {},
+ peace_cost_make_puppet {},
+ peace_cost_disarmament {},
+ peace_cost_destroy_forts {},
+ peace_cost_destroy_naval_bases {},
+ peace_cost_reparations {},
+ peace_cost_transfer_provinces {},
+ peace_cost_remove_cores {},
+ peace_cost_prestige {},
+ peace_cost_concede {},
+ peace_cost_status_quo {},
+ peace_cost_annex {},
+ peace_cost_demand_state {},
+ peace_cost_install_communist_gov_type {},
+ peace_cost_uninstall_communist_gov_type {},
+ peace_cost_colony {},
+ infamy_add_to_sphere {},
+ infamy_release_puppet {},
+ infamy_make_puppet {},
+ infamy_disarmament {},
+ infamy_destroy_forts {},
+ infamy_destroy_naval_bases {},
+ infamy_reparations {},
+ infamy_transfer_provinces {},
+ infamy_remove_cores {},
+ infamy_prestige {},
+ infamy_concede {},
+ infamy_status_quo {},
+ infamy_annex {},
+ infamy_demand_state {},
+ infamy_install_communist_gov_type {},
+ infamy_uninstall_communist_gov_type {},
+ infamy_colony {},
+ prestige_add_to_sphere_base {},
+ prestige_release_puppet_base {},
+ prestige_make_puppet_base {},
+ prestige_disarmament_base {},
+ prestige_destroy_forts_base {},
+ prestige_destroy_naval_bases_base {},
+ prestige_reparations_base {},
+ prestige_transfer_provinces_base {},
+ prestige_remove_cores_base {},
+ prestige_prestige_base {},
+ prestige_concede_base {},
+ prestige_status_quo_base {},
+ prestige_annex_base {},
+ prestige_demand_state_base {},
+ prestige_clear_union_sphere_base {},
+ prestige_gunboat_base {},
+ prestige_install_communist_gov_type_base {},
+ prestige_uninstall_communist_gov_type_base {},
+ prestige_colony_base {},
+ prestige_add_to_sphere {},
+ prestige_release_puppet {},
+ prestige_make_puppet {},
+ prestige_disarmament {},
+ prestige_destroy_forts {},
+ prestige_destroy_naval_bases {},
+ prestige_reparations {},
+ prestige_transfer_provinces {},
+ prestige_remove_cores {},
+ prestige_prestige {},
+ prestige_concede {},
+ prestige_status_quo {},
+ prestige_annex {},
+ prestige_demand_state {},
+ prestige_clear_union_sphere {},
+ prestige_gunboat {},
+ prestige_install_communist_gov_type {},
+ prestige_uninstall_communist_gov_type {},
+ prestige_colony {},
+ breaktruce_infamy_add_to_sphere {},
+ breaktruce_infamy_release_puppet {},
+ breaktruce_infamy_make_puppet {},
+ breaktruce_infamy_disarmament {},
+ breaktruce_infamy_destroy_forts {},
+ breaktruce_infamy_destroy_naval_bases {},
+ breaktruce_infamy_reparations {},
+ breaktruce_infamy_transfer_provinces {},
+ breaktruce_infamy_remove_cores {},
+ breaktruce_infamy_prestige {},
+ breaktruce_infamy_concede {},
+ breaktruce_infamy_status_quo {},
+ breaktruce_infamy_annex {},
+ breaktruce_infamy_demand_state {},
+ breaktruce_infamy_install_communist_gov_type {},
+ breaktruce_infamy_uninstall_communist_gov_type {},
+ breaktruce_infamy_colony {},
+ breaktruce_prestige_add_to_sphere {},
+ breaktruce_prestige_release_puppet {},
+ breaktruce_prestige_make_puppet {},
+ breaktruce_prestige_disarmament {},
+ breaktruce_prestige_destroy_forts {},
+ breaktruce_prestige_destroy_naval_bases {},
+ breaktruce_prestige_reparations {},
+ breaktruce_prestige_transfer_provinces {},
+ breaktruce_prestige_remove_cores {},
+ breaktruce_prestige_prestige {},
+ breaktruce_prestige_concede {},
+ breaktruce_prestige_status_quo {},
+ breaktruce_prestige_annex {},
+ breaktruce_prestige_demand_state {},
+ breaktruce_prestige_install_communist_gov_type {},
+ breaktruce_prestige_uninstall_communist_gov_type {},
+ breaktruce_prestige_colony {},
+ breaktruce_militancy_add_to_sphere {},
+ breaktruce_militancy_release_puppet {},
+ breaktruce_militancy_make_puppet {},
+ breaktruce_militancy_disarmament {},
+ breaktruce_militancy_destroy_forts {},
+ breaktruce_militancy_destroy_naval_bases {},
+ breaktruce_militancy_reparations {},
+ breaktruce_militancy_transfer_provinces {},
+ breaktruce_militancy_remove_cores {},
+ breaktruce_militancy_prestige {},
+ breaktruce_militancy_concede {},
+ breaktruce_militancy_status_quo {},
+ breaktruce_militancy_annex {},
+ breaktruce_militancy_demand_state {},
+ breaktruce_militancy_install_communist_gov_type {},
+ breaktruce_militancy_uninstall_communist_gov_type {},
+ breaktruce_militancy_colony {},
+ goodrelation_infamy_add_to_sphere {},
+ goodrelation_infamy_release_puppet {},
+ goodrelation_infamy_make_puppet {},
+ goodrelation_infamy_disarmament {},
+ goodrelation_infamy_destroy_forts {},
+ goodrelation_infamy_destroy_naval_bases {},
+ goodrelation_infamy_reparations {},
+ goodrelation_infamy_transfer_provinces {},
+ goodrelation_infamy_remove_cores {},
+ goodrelation_infamy_prestige {},
+ goodrelation_infamy_concede {},
+ goodrelation_infamy_status_quo {},
+ goodrelation_infamy_annex {},
+ goodrelation_infamy_demand_state {},
+ goodrelation_infamy_install_communist_gov_type {},
+ goodrelation_infamy_uninstall_communist_gov_type {},
+ goodrelation_infamy_colony {},
+ goodrelation_prestige_add_to_sphere {},
+ goodrelation_prestige_release_puppet {},
+ goodrelation_prestige_make_puppet {},
+ goodrelation_prestige_disarmament {},
+ goodrelation_prestige_destroy_forts {},
+ goodrelation_prestige_destroy_naval_bases {},
+ goodrelation_prestige_reparations {},
+ goodrelation_prestige_transfer_provinces {},
+ goodrelation_prestige_remove_cores {},
+ goodrelation_prestige_prestige {},
+ goodrelation_prestige_concede {},
+ goodrelation_prestige_status_quo {},
+ goodrelation_prestige_annex {},
+ goodrelation_prestige_demand_state {},
+ goodrelation_prestige_install_communist_gov_type {},
+ goodrelation_prestige_uninstall_communist_gov_type {},
+ goodrelation_prestige_colony {},
+ goodrelation_militancy_add_to_sphere {},
+ goodrelation_militancy_release_puppet {},
+ goodrelation_militancy_make_puppet {},
+ goodrelation_militancy_disarmament {},
+ goodrelation_militancy_destroy_forts {},
+ goodrelation_militancy_destroy_naval_bases {},
+ goodrelation_militancy_reparations {},
+ goodrelation_militancy_transfer_provinces {},
+ goodrelation_militancy_remove_cores {},
+ goodrelation_militancy_prestige {},
+ goodrelation_militancy_concede {},
+ goodrelation_militancy_status_quo {},
+ goodrelation_militancy_annex {},
+ goodrelation_militancy_demand_state {},
+ goodrelation_militancy_install_communist_gov_type {},
+ goodrelation_militancy_uninstall_communist_gov_type {},
+ goodrelation_militancy_colony {},
+ war_prestige_cost_base {},
+ war_prestige_cost_high_prestige {},
+ war_prestige_cost_neg_prestige {},
+ war_prestige_cost_truce {},
+ war_prestige_cost_honor_alliance {},
+ war_prestige_cost_honor_guarnatee {},
+ war_prestige_cost_uncivilized {},
+ war_prestige_cost_core {},
+ war_failed_goal_militancy {},
+ war_failed_goal_prestige_base {},
+ war_failed_goal_prestige {},
+ discredit_days {},
+ discredit_influence_cost_factor {},
+ discredit_influence_gain_factor {},
+ banembassy_days {},
+ declarewar_relation_on_accept {},
+ declarewar_diplomatic_cost {},
+ addwargoal_relation_on_accept {},
+ addwargoal_diplomatic_cost {},
+ add_unjustified_goal_badboy {},
+ peace_relation_on_accept {},
+ peace_relation_on_decline {},
+ peace_diplomatic_cost {},
+ alliance_relation_on_accept {},
+ alliance_relation_on_decline {},
+ alliance_diplomatic_cost {},
+ cancelalliance_relation_on_accept {},
+ cancelalliance_diplomatic_cost {},
+ callally_relation_on_accept {},
+ callally_relation_on_decline {},
+ callally_diplomatic_cost {},
+ askmilaccess_relation_on_accept {},
+ askmilaccess_relation_on_decline {},
+ askmilaccess_diplomatic_cost {},
+ cancelaskmilaccess_relation_on_accept {},
+ cancelaskmilaccess_diplomatic_cost {},
+ givemilaccess_relation_on_accept {},
+ givemilaccess_relation_on_decline {},
+ givemilaccess_diplomatic_cost {},
+ cancelgivemilaccess_relation_on_accept {},
+ cancelgivemilaccess_diplomatic_cost {},
+ warsubsidy_relation_on_accept {},
+ warsubsidy_diplomatic_cost {},
+ cancelwarsubsidy_relation_on_accept {},
+ cancelwarsubsidy_diplomatic_cost {},
+ discredit_relation_on_accept {},
+ discredit_influence_cost {},
+ expeladvisors_relation_on_accept {},
+ expeladvisors_influence_cost {},
+ ceasecolonization_relation_on_accept {},
+ ceasecolonization_relation_on_decline {},
+ ceasecolonization_diplomatic_cost {},
+ banembassy_relation_on_accept {},
+ banembassy_influence_cost {},
+ increaserelation_relation_on_accept {},
+ increaserelation_relation_on_decline {},
+ increaserelation_diplomatic_cost {},
+ decreaserelation_relation_on_accept {},
+ decreaserelation_diplomatic_cost {},
+ addtosphere_relation_on_accept {},
+ addtosphere_influence_cost {},
+ removefromsphere_relation_on_accept {},
+ removefromsphere_influence_cost {},
+ removefromsphere_prestige_cost {},
+ removefromsphere_infamy_cost {},
+ increaseopinion_relation_on_accept {},
+ increaseopinion_influence_cost {},
+ decreaseopinion_relation_on_accept {},
+ decreaseopinion_influence_cost {},
+ make_cb_diplomatic_cost {},
+ make_cb_relation_on_accept {},
+ disarmed_penalty {},
+ reparations_tax_hit {},
+ prestige_reduction_base {},
+ prestige_reduction {},
+ reparations_duration {},
+ min_warscore_to_intervene {},
+ min_time_to_intervene {},
+ max_warscore_from_battles {},
+ gunboat_diplomatic_cost {},
+ gunboat_relation_on_accept {},
+ wargoal_jingoism_requirement {},
+ liberate_state_relation_increase {},
+ dishonored_callally_prestige_penalty {},
+ base_truce_duration {},
+ max_influence {},
+ warsubsidies_percent {},
+ neighbour_bonus_influence_percent {},
+ sphere_neighbour_bonus_influence_percent {},
+ other_continent_bonus_influence_percent {},
+ puppet_bonus_influence_percent {},
+ release_nation_prestige {},
+ release_nation_infamy {},
+ infamy_clear_union_sphere {},
+ breaktruce_infamy_clear_union_sphere {},
+ breaktruce_prestige_clear_union_sphere {},
+ breaktruce_militancy_clear_union_sphere {},
+ goodrelation_infamy_clear_union_sphere {},
+ goodrelation_prestige_clear_union_sphere {},
+ goodrelation_militancy_clear_union_sphere {},
+ peace_cost_clear_union_sphere {},
+ good_peace_refusal_militancy {},
+ good_peace_refusal_warexh {},
+ peace_cost_gunboat {},
+ infamy_gunboat {},
+ breaktruce_infamy_gunboat {},
+ breaktruce_prestige_gunboat {},
+ breaktruce_militancy_gunboat {},
+ goodrelation_infamy_gunboat {},
+ goodrelation_prestige_gunboat {},
+ goodrelation_militancy_gunboat {},
+ cb_generation_base_speed {},
+ cb_generation_speed_bonus_on_colony_competition {},
+ cb_generation_speed_bonus_on_colony_competition_troops_presence {},
+ make_cb_relation_limit {},
+ cb_detection_chance_base {},
+ investment_influence_defense {},
+ relation_influence_modifier {},
+ on_cb_detected_relation_change {},
+ gw_intervene_min_relations {},
+ gw_intervene_max_exhaustion {},
+ gw_justify_cb_badboy_impact {},
+ gw_cb_construction_speed {},
+ gw_wargoal_jingoism_requirement_mod {},
+ gw_warscore_cost_mod {},
+ gw_warscore_cost_mod_2 {},
+ gw_warscore_2_threshold {},
+ tension_decay {},
+ tension_from_cb {},
+ tension_from_movement {},
+ tension_from_movement_max {},
+ at_war_tension_decay {},
+ tension_on_cb_discovered {},
+ tension_on_revolt {},
+ tension_while_crisis {},
+ crisis_cooldown_duration {},
+ crisis_base_chance {},
+ crisis_temperature_increase {},
+ crisis_offer_diplomatic_cost {},
+ crisis_offer_relation_on_accept {},
+ crisis_offer_relation_on_decline {},
+ crisis_did_not_take_side_prestige_factor_base {},
+ crisis_did_not_take_side_prestige_factor_year {},
+ crisis_winner_prestige_factor_base {},
+ crisis_winner_prestige_factor_year {},
+ crisis_winner_relations_impact {},
+ back_crisis_diplomatic_cost {},
+ back_crisis_relation_on_accept {},
+ back_crisis_relation_on_decline {},
+ crisis_temperature_on_offer_decline {},
+ crisis_temperature_participant_factor {},
+ crisis_temperature_on_mobilize {},
+ crisis_wargoal_infamy_mult {},
+ crisis_wargoal_prestige_mult {},
+ crisis_wargoal_militancy_mult {},
+ crisis_interest_war_exhaustion_limit {},
+ rank_1_tension_decay {},
+ rank_2_tension_decay {},
+ rank_3_tension_decay {},
+ rank_4_tension_decay {},
+ rank_5_tension_decay {},
+ rank_6_tension_decay {},
+ rank_7_tension_decay {},
+ rank_8_tension_decay {},
+ tws_fulfilled_speed {},
+ tws_not_fulfilled_speed {},
+ tws_grace_period_days {},
+ tws_cb_limit_default {},
+ tws_fulfilled_idle_space {},
+ tws_battle_min_count {},
+ tws_battle_max_aspect {},
+ large_population_influence_penalty {},
+ lone_backer_prestige_factor {} {}
+
+std::string_view DiplomacyDefines::get_name() const {
+ return "diplomacy";
+}
+
+node_callback_t DiplomacyDefines::expect_defines() {
+ // The key map entries are added in two separate function calls, half each time, as adding them all at once causes a
+ // runtime crash, presumably due to a limit on the number of loose lambda functions that can exist at the same time.
+
+ key_map_t key_map;
+
+ add_key_map_entries(
+ key_map,
+ "PEACE_COST_ADD_TO_SPHERE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_add_to_sphere)),
+ "PEACE_COST_RELEASE_PUPPET", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_release_puppet)),
+ "PEACE_COST_MAKE_PUPPET", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_make_puppet)),
+ "PEACE_COST_DISARMAMENT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_disarmament)),
+ "PEACE_COST_DESTROY_FORTS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_destroy_forts)),
+ "PEACE_COST_DESTROY_NAVAL_BASES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(peace_cost_destroy_naval_bases)),
+ "PEACE_COST_REPARATIONS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_reparations)),
+ "PEACE_COST_TRANSFER_PROVINCES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(peace_cost_transfer_provinces)),
+ "PEACE_COST_REMOVE_CORES", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_remove_cores)),
+ "PEACE_COST_PRESTIGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_prestige)),
+ "PEACE_COST_CONCEDE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_concede)),
+ "PEACE_COST_STATUS_QUO", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_status_quo)),
+ "PEACE_COST_ANNEX", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_annex)),
+ "PEACE_COST_DEMAND_STATE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_demand_state)),
+ "PEACE_COST_INSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(peace_cost_install_communist_gov_type)),
+ "PEACE_COST_UNINSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(peace_cost_uninstall_communist_gov_type)),
+ "PEACE_COST_COLONY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_colony)),
+ "INFAMY_ADD_TO_SPHERE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_add_to_sphere)),
+ "INFAMY_RELEASE_PUPPET", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_release_puppet)),
+ "INFAMY_MAKE_PUPPET", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_make_puppet)),
+ "INFAMY_DISARMAMENT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_disarmament)),
+ "INFAMY_DESTROY_FORTS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_destroy_forts)),
+ "INFAMY_DESTROY_NAVAL_BASES", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_destroy_naval_bases)),
+ "INFAMY_REPARATIONS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_reparations)),
+ "INFAMY_TRANSFER_PROVINCES", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_transfer_provinces)),
+ "INFAMY_REMOVE_CORES", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_remove_cores)),
+ "INFAMY_PRESTIGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_prestige)),
+ "INFAMY_CONCEDE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_concede)),
+ "INFAMY_STATUS_QUO", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_status_quo)),
+ "INFAMY_ANNEX", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_annex)),
+ "INFAMY_DEMAND_STATE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_demand_state)),
+ "INFAMY_INSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(infamy_install_communist_gov_type)),
+ "INFAMY_UNINSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(infamy_uninstall_communist_gov_type)),
+ "INFAMY_COLONY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_colony)),
+ "PRESTIGE_ADD_TO_SPHERE_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_add_to_sphere_base)),
+ "PRESTIGE_RELEASE_PUPPET_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(prestige_release_puppet_base)),
+ "PRESTIGE_MAKE_PUPPET_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_make_puppet_base)),
+ "PRESTIGE_DISARMAMENT_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_disarmament_base)),
+ "PRESTIGE_DESTROY_FORTS_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_destroy_forts_base)),
+ "PRESTIGE_DESTROY_NAVAL_BASES_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(prestige_destroy_naval_bases_base)),
+ "PRESTIGE_REPARATIONS_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_reparations_base)),
+ "PRESTIGE_TRANSFER_PROVINCES_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(prestige_transfer_provinces_base)),
+ "PRESTIGE_REMOVE_CORES_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_remove_cores_base)),
+ "PRESTIGE_PRESTIGE_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_prestige_base)),
+ "PRESTIGE_CONCEDE_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_concede_base)),
+ "PRESTIGE_STATUS_QUO_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_status_quo_base)),
+ "PRESTIGE_ANNEX_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_annex_base)),
+ "PRESTIGE_DEMAND_STATE_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_demand_state_base)),
+ "PRESTIGE_CLEAR_UNION_SPHERE_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(prestige_clear_union_sphere_base)),
+ "PRESTIGE_GUNBOAT_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_gunboat_base)),
+ "PRESTIGE_INSTALL_COMMUNIST_GOV_TYPE_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(prestige_install_communist_gov_type_base)),
+ "PRESTIGE_UNINSTALL_COMMUNIST_GOV_TYPE_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(prestige_uninstall_communist_gov_type_base)),
+ "PRESTIGE_COLONY_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_colony_base)),
+ "PRESTIGE_ADD_TO_SPHERE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_add_to_sphere)),
+ "PRESTIGE_RELEASE_PUPPET", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_release_puppet)),
+ "PRESTIGE_MAKE_PUPPET", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_make_puppet)),
+ "PRESTIGE_DISARMAMENT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_disarmament)),
+ "PRESTIGE_DESTROY_FORTS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_destroy_forts)),
+ "PRESTIGE_DESTROY_NAVAL_BASES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(prestige_destroy_naval_bases)),
+ "PRESTIGE_REPARATIONS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_reparations)),
+ "PRESTIGE_TRANSFER_PROVINCES", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_transfer_provinces)),
+ "PRESTIGE_REMOVE_CORES", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_remove_cores)),
+ "PRESTIGE_PRESTIGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_prestige)),
+ "PRESTIGE_CONCEDE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_concede)),
+ "PRESTIGE_STATUS_QUO", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_status_quo)),
+ "PRESTIGE_ANNEX", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_annex)),
+ "PRESTIGE_DEMAND_STATE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_demand_state)),
+ "PRESTIGE_CLEAR_UNION_SPHERE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_clear_union_sphere)),
+ "PRESTIGE_GUNBOAT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_gunboat)),
+ "PRESTIGE_INSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(prestige_install_communist_gov_type)),
+ "PRESTIGE_UNINSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(prestige_uninstall_communist_gov_type)),
+ "PRESTIGE_COLONY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_colony)),
+ "BREAKTRUCE_INFAMY_ADD_TO_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_add_to_sphere)),
+ "BREAKTRUCE_INFAMY_RELEASE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_release_puppet)),
+ "BREAKTRUCE_INFAMY_MAKE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_make_puppet)),
+ "BREAKTRUCE_INFAMY_DISARMAMENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_disarmament)),
+ "BREAKTRUCE_INFAMY_DESTROY_FORTS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_destroy_forts)),
+ "BREAKTRUCE_INFAMY_DESTROY_NAVAL_BASES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_destroy_naval_bases)),
+ "BREAKTRUCE_INFAMY_REPARATIONS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_reparations)),
+ "BREAKTRUCE_INFAMY_TRANSFER_PROVINCES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_transfer_provinces)),
+ "BREAKTRUCE_INFAMY_REMOVE_CORES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_remove_cores)),
+ "BREAKTRUCE_INFAMY_PRESTIGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(breaktruce_infamy_prestige)),
+ "BREAKTRUCE_INFAMY_CONCEDE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(breaktruce_infamy_concede)),
+ "BREAKTRUCE_INFAMY_STATUS_QUO", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_status_quo)),
+ "BREAKTRUCE_INFAMY_ANNEX", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(breaktruce_infamy_annex)),
+ "BREAKTRUCE_INFAMY_DEMAND_STATE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_demand_state)),
+ "BREAKTRUCE_INFAMY_INSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_install_communist_gov_type)),
+ "BREAKTRUCE_INFAMY_UNINSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_uninstall_communist_gov_type)),
+ "BREAKTRUCE_INFAMY_COLONY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(breaktruce_infamy_colony)),
+ "BREAKTRUCE_PRESTIGE_ADD_TO_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_add_to_sphere)),
+ "BREAKTRUCE_PRESTIGE_RELEASE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_release_puppet)),
+ "BREAKTRUCE_PRESTIGE_MAKE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_make_puppet)),
+ "BREAKTRUCE_PRESTIGE_DISARMAMENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_disarmament)),
+ "BREAKTRUCE_PRESTIGE_DESTROY_FORTS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_destroy_forts)),
+ "BREAKTRUCE_PRESTIGE_DESTROY_NAVAL_BASES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_destroy_naval_bases)),
+ "BREAKTRUCE_PRESTIGE_REPARATIONS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_reparations)),
+ "BREAKTRUCE_PRESTIGE_TRANSFER_PROVINCES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_transfer_provinces)),
+ "BREAKTRUCE_PRESTIGE_REMOVE_CORES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_remove_cores)),
+ "BREAKTRUCE_PRESTIGE_PRESTIGE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_prestige)),
+ "BREAKTRUCE_PRESTIGE_CONCEDE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(breaktruce_prestige_concede)),
+ "BREAKTRUCE_PRESTIGE_STATUS_QUO", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_status_quo)),
+ "BREAKTRUCE_PRESTIGE_ANNEX", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(breaktruce_prestige_annex)),
+ "BREAKTRUCE_PRESTIGE_DEMAND_STATE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_demand_state)),
+ "BREAKTRUCE_PRESTIGE_INSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_install_communist_gov_type)),
+ "BREAKTRUCE_PRESTIGE_UNINSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_uninstall_communist_gov_type)),
+ "BREAKTRUCE_PRESTIGE_COLONY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(breaktruce_prestige_colony)),
+ "BREAKTRUCE_MILITANCY_ADD_TO_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_add_to_sphere)),
+ "BREAKTRUCE_MILITANCY_RELEASE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_release_puppet)),
+ "BREAKTRUCE_MILITANCY_MAKE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_make_puppet)),
+ "BREAKTRUCE_MILITANCY_DISARMAMENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_disarmament)),
+ "BREAKTRUCE_MILITANCY_DESTROY_FORTS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_destroy_forts)),
+ "BREAKTRUCE_MILITANCY_DESTROY_NAVAL_BASES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_destroy_naval_bases)),
+ "BREAKTRUCE_MILITANCY_REPARATIONS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_reparations)),
+ "BREAKTRUCE_MILITANCY_TRANSFER_PROVINCES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_transfer_provinces)),
+ "BREAKTRUCE_MILITANCY_REMOVE_CORES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_remove_cores)),
+ "BREAKTRUCE_MILITANCY_PRESTIGE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_prestige)),
+ "BREAKTRUCE_MILITANCY_CONCEDE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_concede)),
+ "BREAKTRUCE_MILITANCY_STATUS_QUO", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_status_quo)),
+ "BREAKTRUCE_MILITANCY_ANNEX", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(breaktruce_militancy_annex)),
+ "BREAKTRUCE_MILITANCY_DEMAND_STATE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_demand_state)),
+ "BREAKTRUCE_MILITANCY_INSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_install_communist_gov_type)),
+ "BREAKTRUCE_MILITANCY_UNINSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_uninstall_communist_gov_type)),
+ "BREAKTRUCE_MILITANCY_COLONY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(breaktruce_militancy_colony)),
+ "GOODRELATION_INFAMY_ADD_TO_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_add_to_sphere)),
+ "GOODRELATION_INFAMY_RELEASE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_release_puppet)),
+ "GOODRELATION_INFAMY_MAKE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_make_puppet)),
+ "GOODRELATION_INFAMY_DISARMAMENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_disarmament)),
+ "GOODRELATION_INFAMY_DESTROY_FORTS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_destroy_forts)),
+ "GOODRELATION_INFAMY_DESTROY_NAVAL_BASES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_destroy_naval_bases)),
+ "GOODRELATION_INFAMY_REPARATIONS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_reparations)),
+ "GOODRELATION_INFAMY_TRANSFER_PROVINCES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_transfer_provinces)),
+ "GOODRELATION_INFAMY_REMOVE_CORES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_remove_cores)),
+ "GOODRELATION_INFAMY_PRESTIGE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_prestige)),
+ "GOODRELATION_INFAMY_CONCEDE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(goodrelation_infamy_concede)),
+ "GOODRELATION_INFAMY_STATUS_QUO", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_status_quo)),
+ "GOODRELATION_INFAMY_ANNEX", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(goodrelation_infamy_annex)),
+ "GOODRELATION_INFAMY_DEMAND_STATE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_demand_state)),
+ "GOODRELATION_INFAMY_INSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_install_communist_gov_type)),
+ "GOODRELATION_INFAMY_UNINSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_uninstall_communist_gov_type)),
+ "GOODRELATION_INFAMY_COLONY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(goodrelation_infamy_colony)),
+ "GOODRELATION_PRESTIGE_ADD_TO_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_add_to_sphere)),
+ "GOODRELATION_PRESTIGE_RELEASE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_release_puppet)),
+ "GOODRELATION_PRESTIGE_MAKE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_make_puppet)),
+ "GOODRELATION_PRESTIGE_DISARMAMENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_disarmament)),
+ "GOODRELATION_PRESTIGE_DESTROY_FORTS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_destroy_forts)),
+ "GOODRELATION_PRESTIGE_DESTROY_NAVAL_BASES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_destroy_naval_bases)),
+ "GOODRELATION_PRESTIGE_REPARATIONS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_reparations)),
+ "GOODRELATION_PRESTIGE_TRANSFER_PROVINCES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_transfer_provinces)),
+ "GOODRELATION_PRESTIGE_REMOVE_CORES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_remove_cores)),
+ "GOODRELATION_PRESTIGE_PRESTIGE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_prestige)),
+ "GOODRELATION_PRESTIGE_CONCEDE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_concede)),
+ "GOODRELATION_PRESTIGE_STATUS_QUO", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_status_quo)),
+ "GOODRELATION_PRESTIGE_ANNEX", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(goodrelation_prestige_annex)),
+ "GOODRELATION_PRESTIGE_DEMAND_STATE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_demand_state)),
+ "GOODRELATION_PRESTIGE_INSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_install_communist_gov_type)),
+ "GOODRELATION_PRESTIGE_UNINSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_uninstall_communist_gov_type)),
+ "GOODRELATION_PRESTIGE_COLONY", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_colony)),
+ "GOODRELATION_MILITANCY_ADD_TO_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_add_to_sphere)),
+ "GOODRELATION_MILITANCY_RELEASE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_release_puppet)),
+ "GOODRELATION_MILITANCY_MAKE_PUPPET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_make_puppet)),
+ "GOODRELATION_MILITANCY_DISARMAMENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_disarmament)),
+ "GOODRELATION_MILITANCY_DESTROY_FORTS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_destroy_forts)),
+ "GOODRELATION_MILITANCY_DESTROY_NAVAL_BASES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_destroy_naval_bases)),
+ "GOODRELATION_MILITANCY_REPARATIONS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_reparations)),
+ "GOODRELATION_MILITANCY_TRANSFER_PROVINCES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_transfer_provinces)),
+ "GOODRELATION_MILITANCY_REMOVE_CORES", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_remove_cores)),
+ "GOODRELATION_MILITANCY_PRESTIGE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_prestige)),
+ "GOODRELATION_MILITANCY_CONCEDE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_concede)),
+ "GOODRELATION_MILITANCY_STATUS_QUO", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_status_quo)),
+ "GOODRELATION_MILITANCY_ANNEX", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_annex)),
+ "GOODRELATION_MILITANCY_DEMAND_STATE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_demand_state)),
+ "GOODRELATION_MILITANCY_INSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_install_communist_gov_type)),
+ "GOODRELATION_MILITANCY_UNINSTALL_COMMUNIST_GOV_TYPE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_uninstall_communist_gov_type)),
+ "GOODRELATION_MILITANCY_COLONY", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_colony))
+ );
+
+ add_key_map_entries(
+ key_map,
+ "WAR_PRESTIGE_COST_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(war_prestige_cost_base)),
+ "WAR_PRESTIGE_COST_HIGH_PRESTIGE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(war_prestige_cost_high_prestige)),
+ "WAR_PRESTIGE_COST_NEG_PRESTIGE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(war_prestige_cost_neg_prestige)),
+ "WAR_PRESTIGE_COST_TRUCE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(war_prestige_cost_truce)),
+ "WAR_PRESTIGE_COST_HONOR_ALLIANCE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(war_prestige_cost_honor_alliance)),
+ "WAR_PRESTIGE_COST_HONOR_GUARNATEE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(war_prestige_cost_honor_guarnatee)),
+ "WAR_PRESTIGE_COST_UNCIVILIZED", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(war_prestige_cost_uncivilized)),
+ "WAR_PRESTIGE_COST_CORE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(war_prestige_cost_core)),
+ "WAR_FAILED_GOAL_MILITANCY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(war_failed_goal_militancy)),
+ "WAR_FAILED_GOAL_PRESTIGE_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(war_failed_goal_prestige_base)),
+ "WAR_FAILED_GOAL_PRESTIGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(war_failed_goal_prestige)),
+ "DISCREDIT_DAYS", ONE_EXACTLY, expect_days(assign_variable_callback(discredit_days)),
+ "DISCREDIT_INFLUENCE_COST_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(discredit_influence_cost_factor)),
+ "DISCREDIT_INFLUENCE_GAIN_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(discredit_influence_gain_factor)),
+ "BANEMBASSY_DAYS", ONE_EXACTLY, expect_days(assign_variable_callback(banembassy_days)),
+ "DECLAREWAR_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(declarewar_relation_on_accept)),
+ "DECLAREWAR_DIPLOMATIC_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(declarewar_diplomatic_cost)),
+ "ADDWARGOAL_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(addwargoal_relation_on_accept)),
+ "ADDWARGOAL_DIPLOMATIC_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(addwargoal_diplomatic_cost)),
+ "ADD_UNJUSTIFIED_GOAL_BADBOY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(add_unjustified_goal_badboy)),
+ "PEACE_RELATION_ON_ACCEPT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_relation_on_accept)),
+ "PEACE_RELATION_ON_DECLINE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_relation_on_decline)),
+ "PEACE_DIPLOMATIC_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_diplomatic_cost)),
+ "ALLIANCE_RELATION_ON_ACCEPT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(alliance_relation_on_accept)),
+ "ALLIANCE_RELATION_ON_DECLINE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(alliance_relation_on_decline)),
+ "ALLIANCE_DIPLOMATIC_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(alliance_diplomatic_cost)),
+ "CANCELALLIANCE_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(cancelalliance_relation_on_accept)),
+ "CANCELALLIANCE_DIPLOMATIC_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(cancelalliance_diplomatic_cost)),
+ "CALLALLY_RELATION_ON_ACCEPT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(callally_relation_on_accept)),
+ "CALLALLY_RELATION_ON_DECLINE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(callally_relation_on_decline)),
+ "CALLALLY_DIPLOMATIC_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(callally_diplomatic_cost)),
+ "ASKMILACCESS_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(askmilaccess_relation_on_accept)),
+ "ASKMILACCESS_RELATION_ON_DECLINE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(askmilaccess_relation_on_decline)),
+ "ASKMILACCESS_DIPLOMATIC_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(askmilaccess_diplomatic_cost)),
+ "CANCELASKMILACCESS_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(cancelaskmilaccess_relation_on_accept)),
+ "CANCELASKMILACCESS_DIPLOMATIC_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(cancelaskmilaccess_diplomatic_cost)),
+ "GIVEMILACCESS_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(givemilaccess_relation_on_accept)),
+ "GIVEMILACCESS_RELATION_ON_DECLINE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(givemilaccess_relation_on_decline)),
+ "GIVEMILACCESS_DIPLOMATIC_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(givemilaccess_diplomatic_cost)),
+ "CANCELGIVEMILACCESS_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(cancelgivemilaccess_relation_on_accept)),
+ "CANCELGIVEMILACCESS_DIPLOMATIC_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(cancelgivemilaccess_diplomatic_cost)),
+ "WARSUBSIDY_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(warsubsidy_relation_on_accept)),
+ "WARSUBSIDY_DIPLOMATIC_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(warsubsidy_diplomatic_cost)),
+ "CANCELWARSUBSIDY_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(cancelwarsubsidy_relation_on_accept)),
+ "CANCELWARSUBSIDY_DIPLOMATIC_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(cancelwarsubsidy_diplomatic_cost)),
+ "DISCREDIT_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(discredit_relation_on_accept)),
+ "DISCREDIT_INFLUENCE_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(discredit_influence_cost)),
+ "EXPELADVISORS_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(expeladvisors_relation_on_accept)),
+ "EXPELADVISORS_INFLUENCE_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(expeladvisors_influence_cost)),
+ "CEASECOLONIZATION_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(ceasecolonization_relation_on_accept)),
+ "CEASECOLONIZATION_RELATION_ON_DECLINE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(ceasecolonization_relation_on_decline)),
+ "CEASECOLONIZATION_DIPLOMATIC_COST", ONE_OR_MORE, // Appears twice in vanilla!
+ expect_fixed_point(assign_variable_callback(ceasecolonization_diplomatic_cost)),
+ "BANEMBASSY_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(banembassy_relation_on_accept)),
+ "BANEMBASSY_INFLUENCE_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(banembassy_influence_cost)),
+ "INCREASERELATION_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(increaserelation_relation_on_accept)),
+ "INCREASERELATION_RELATION_ON_DECLINE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(increaserelation_relation_on_decline)),
+ "INCREASERELATION_DIPLOMATIC_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(increaserelation_diplomatic_cost)),
+ "DECREASERELATION_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(decreaserelation_relation_on_accept)),
+ "DECREASERELATION_DIPLOMATIC_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(decreaserelation_diplomatic_cost)),
+ "ADDTOSPHERE_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(addtosphere_relation_on_accept)),
+ "ADDTOSPHERE_INFLUENCE_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(addtosphere_influence_cost)),
+ "REMOVEFROMSPHERE_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(removefromsphere_relation_on_accept)),
+ "REMOVEFROMSPHERE_INFLUENCE_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(removefromsphere_influence_cost)),
+ "REMOVEFROMSPHERE_PRESTIGE_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(removefromsphere_prestige_cost)),
+ "REMOVEFROMSPHERE_INFAMY_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(removefromsphere_infamy_cost)),
+ "INCREASEOPINION_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(increaseopinion_relation_on_accept)),
+ "INCREASEOPINION_INFLUENCE_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(increaseopinion_influence_cost)),
+ "DECREASEOPINION_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(decreaseopinion_relation_on_accept)),
+ "DECREASEOPINION_INFLUENCE_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(decreaseopinion_influence_cost)),
+ "MAKE_CB_DIPLOMATIC_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(make_cb_diplomatic_cost)),
+ "MAKE_CB_RELATION_ON_ACCEPT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(make_cb_relation_on_accept)),
+ "DISARMAMENT_ARMY_HIT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(disarmed_penalty)),
+ "REPARATIONS_TAX_HIT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(reparations_tax_hit)),
+ "PRESTIGE_REDUCTION_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_reduction_base)),
+ "PRESTIGE_REDUCTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(prestige_reduction)),
+ "REPARATIONS_YEARS", ONE_EXACTLY, expect_years(assign_variable_callback(reparations_duration)),
+ "MIN_WARSCORE_TO_INTERVENE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(min_warscore_to_intervene)),
+ "MIN_MONTHS_TO_INTERVENE", ONE_EXACTLY, expect_months(assign_variable_callback(min_time_to_intervene)),
+ "MAX_WARSCORE_FROM_BATTLES", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_warscore_from_battles)),
+ "GUNBOAT_DIPLOMATIC_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gunboat_diplomatic_cost)),
+ "GUNBOAT_RELATION_ON_ACCEPT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gunboat_relation_on_accept)),
+ "WARGOAL_JINGOISM_REQUIREMENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(wargoal_jingoism_requirement)),
+ "LIBERATE_STATE_RELATION_INCREASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(liberate_state_relation_increase)),
+ "DISHONORED_CALLALLY_PRESTIGE_PENALTY", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(dishonored_callally_prestige_penalty)),
+ "BASE_TRUCE_MONTHS", ONE_EXACTLY, expect_months(assign_variable_callback(base_truce_duration)),
+ "MAX_INFLUENCE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_influence)),
+ "WARSUBSIDIES_PERCENT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(warsubsidies_percent)),
+ "NEIGHBOUR_BONUS_INFLUENCE_PERCENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(neighbour_bonus_influence_percent)),
+ "SPHERE_NEIGHBOUR_BONUS_INFLUENCE_PERCENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(sphere_neighbour_bonus_influence_percent)),
+ "OTHER_CONTINENT_BONUS_INFLUENCE_PERCENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(other_continent_bonus_influence_percent)),
+ "PUPPET_BONUS_INFLUENCE_PERCENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(puppet_bonus_influence_percent)),
+ "RELEASE_NATION_PRESTIGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(release_nation_prestige)),
+ "RELEASE_NATION_INFAMY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(release_nation_infamy)),
+ "INFAMY_CLEAR_UNION_SPHERE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_clear_union_sphere)),
+ "BREAKTRUCE_INFAMY_CLEAR_UNION_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_infamy_clear_union_sphere)),
+ "BREAKTRUCE_PRESTIGE_CLEAR_UNION_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_prestige_clear_union_sphere)),
+ "BREAKTRUCE_MILITANCY_CLEAR_UNION_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_clear_union_sphere)),
+ "GOODRELATION_INFAMY_CLEAR_UNION_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_infamy_clear_union_sphere)),
+ "GOODRELATION_PRESTIGE_CLEAR_UNION_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_clear_union_sphere)),
+ "GOODRELATION_MILITANCY_CLEAR_UNION_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_clear_union_sphere)),
+ "PEACE_COST_CLEAR_UNION_SPHERE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(peace_cost_clear_union_sphere)),
+ "GOOD_PEACE_REFUSAL_MILITANCY", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(good_peace_refusal_militancy)),
+ "GOOD_PEACE_REFUSAL_WAREXH", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(good_peace_refusal_warexh)),
+ "PEACE_COST_GUNBOAT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(peace_cost_gunboat)),
+ "INFAMY_GUNBOAT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(infamy_gunboat)),
+ "BREAKTRUCE_INFAMY_GUNBOAT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(breaktruce_infamy_gunboat)),
+ "BREAKTRUCE_PRESTIGE_GUNBOAT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(breaktruce_prestige_gunboat)),
+ "BREAKTRUCE_MILITANCY_GUNBOAT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(breaktruce_militancy_gunboat)),
+ "GOODRELATION_INFAMY_GUNBOAT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(goodrelation_infamy_gunboat)),
+ "GOODRELATION_PRESTIGE_GUNBOAT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_prestige_gunboat)),
+ "GOODRELATION_MILITANCY_GUNBOAT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(goodrelation_militancy_gunboat)),
+ "CB_GENERATION_BASE_SPEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(cb_generation_base_speed)),
+ "CB_GENERATION_SPEED_BONUS_ON_COLONY_COMPETITION", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(cb_generation_speed_bonus_on_colony_competition)),
+ "CB_GENERATION_SPEED_BONUS_ON_COLONY_COMPETITION_TROOPS_PRESENCE", ONE_EXACTLY, expect_fixed_point(
+ assign_variable_callback(cb_generation_speed_bonus_on_colony_competition_troops_presence)
+ ),
+ "MAKE_CB_RELATION_LIMIT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(make_cb_relation_limit)),
+ "CB_DETECTION_CHANCE_BASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(cb_detection_chance_base)),
+ "INVESTMENT_INFLUENCE_DEFENSE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(investment_influence_defense)),
+ "RELATION_INFLUENCE_MODIFIER", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(relation_influence_modifier)),
+ "ON_CB_DETECTED_RELATION_CHANGE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(on_cb_detected_relation_change)),
+ "GW_INTERVENE_MIN_RELATIONS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gw_intervene_min_relations)),
+ "GW_INTERVENE_MAX_EXHAUSTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gw_intervene_max_exhaustion)),
+ "GW_JUSTIFY_CB_BADBOY_IMPACT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gw_justify_cb_badboy_impact)),
+ "GW_CB_CONSTRUCTION_SPEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gw_cb_construction_speed)),
+ "GW_WARGOAL_JINGOISM_REQUIREMENT_MOD", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(gw_wargoal_jingoism_requirement_mod)),
+ "GW_WARSCORE_COST_MOD", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gw_warscore_cost_mod)),
+ "GW_WARSCORE_COST_MOD_2", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gw_warscore_cost_mod_2)),
+ "GW_WARSCORE_2_THRESHOLD", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gw_warscore_2_threshold)),
+ "TENSION_DECAY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tension_decay)),
+ "TENSION_FROM_CB", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tension_from_cb)),
+ "TENSION_FROM_MOVEMENT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tension_from_movement)),
+ "TENSION_FROM_MOVEMENT_MAX", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tension_from_movement_max)),
+ "AT_WAR_TENSION_DECAY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(at_war_tension_decay)),
+ "TENSION_ON_CB_DISCOVERED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tension_on_cb_discovered)),
+ "TENSION_ON_REVOLT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tension_on_revolt)),
+ "TENSION_WHILE_CRISIS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tension_while_crisis)),
+ "CRISIS_COOLDOWN_MONTHS", ONE_EXACTLY, expect_months(assign_variable_callback(crisis_cooldown_duration)),
+ "CRISIS_BASE_CHANCE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(crisis_base_chance)),
+ "CRISIS_TEMPERATURE_INCREASE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(crisis_temperature_increase)),
+ "CRISIS_OFFER_DIPLOMATIC_COST", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_offer_diplomatic_cost)),
+ "CRISIS_OFFER_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_offer_relation_on_accept)),
+ "CRISIS_OFFER_RELATION_ON_DECLINE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_offer_relation_on_decline)),
+ "CRISIS_DID_NOT_TAKE_SIDE_PRESTIGE_FACTOR_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_did_not_take_side_prestige_factor_base)),
+ "CRISIS_DID_NOT_TAKE_SIDE_PRESTIGE_FACTOR_YEAR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_did_not_take_side_prestige_factor_year)),
+ "CRISIS_WINNER_PRESTIGE_FACTOR_BASE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_winner_prestige_factor_base)),
+ "CRISIS_WINNER_PRESTIGE_FACTOR_YEAR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_winner_prestige_factor_year)),
+ "CRISIS_WINNER_RELATIONS_IMPACT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_winner_relations_impact)),
+ "BACK_CRISIS_DIPLOMATIC_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(back_crisis_diplomatic_cost)),
+ "BACK_CRISIS_RELATION_ON_ACCEPT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(back_crisis_relation_on_accept)),
+ "BACK_CRISIS_RELATION_ON_DECLINE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(back_crisis_relation_on_decline)),
+ "CRISIS_TEMPERATURE_ON_OFFER_DECLINE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_temperature_on_offer_decline)),
+ "CRISIS_TEMPERATURE_PARTICIPANT_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_temperature_participant_factor)),
+ "CRISIS_TEMPERATURE_ON_MOBILIZE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_temperature_on_mobilize)),
+ "CRISIS_WARGOAL_INFAMY_MULT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(crisis_wargoal_infamy_mult)),
+ "CRISIS_WARGOAL_PRESTIGE_MULT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_wargoal_prestige_mult)),
+ "CRISIS_WARGOAL_MILITANCY_MULT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_wargoal_militancy_mult)),
+ "CRISIS_INTEREST_WAR_EXHAUSTION_LIMIT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(crisis_interest_war_exhaustion_limit)),
+ "RANK_1_TENSION_DECAY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(rank_1_tension_decay)),
+ "RANK_2_TENSION_DECAY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(rank_2_tension_decay)),
+ "RANK_3_TENSION_DECAY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(rank_3_tension_decay)),
+ "RANK_4_TENSION_DECAY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(rank_4_tension_decay)),
+ "RANK_5_TENSION_DECAY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(rank_5_tension_decay)),
+ "RANK_6_TENSION_DECAY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(rank_6_tension_decay)),
+ "RANK_7_TENSION_DECAY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(rank_7_tension_decay)),
+ "RANK_8_TENSION_DECAY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(rank_8_tension_decay)),
+ "TWS_FULFILLED_SPEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tws_fulfilled_speed)),
+ "TWS_NOT_FULFILLED_SPEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tws_not_fulfilled_speed)),
+ "TWS_GRACE_PERIOD_DAYS", ONE_EXACTLY, expect_days(assign_variable_callback(tws_grace_period_days)),
+ "TWS_CB_LIMIT_DEFAULT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tws_cb_limit_default)),
+ "TWS_FULFILLED_IDLE_SPACE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tws_fulfilled_idle_space)),
+ "TWS_BATTLE_MIN_COUNT", ONE_EXACTLY, expect_uint(assign_variable_callback(tws_battle_min_count)),
+ "TWS_BATTLE_MAX_ASPECT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(tws_battle_max_aspect)),
+ "LARGE_POPULATION_INFLUENCE_PENALTY", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(large_population_influence_penalty)),
+ "LONE_BACKER_PRESTIGE_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(lone_backer_prestige_factor))
+ );
+
+ return expect_dictionary_key_map(std::move(key_map));
+}
diff --git a/src/openvic-simulation/defines/DiplomacyDefines.hpp b/src/openvic-simulation/defines/DiplomacyDefines.hpp
new file mode 100644
index 0000000..d9195ab
--- /dev/null
+++ b/src/openvic-simulation/defines/DiplomacyDefines.hpp
@@ -0,0 +1,368 @@
+#pragma once
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ struct DefineManager;
+
+ struct DiplomacyDefines {
+ friend struct DefineManager;
+
+ private:
+ fixed_point_t PROPERTY(peace_cost_add_to_sphere);
+ fixed_point_t PROPERTY(peace_cost_release_puppet);
+ fixed_point_t PROPERTY(peace_cost_make_puppet);
+ fixed_point_t PROPERTY(peace_cost_disarmament);
+ fixed_point_t PROPERTY(peace_cost_destroy_forts);
+ fixed_point_t PROPERTY(peace_cost_destroy_naval_bases);
+ fixed_point_t PROPERTY(peace_cost_reparations);
+ fixed_point_t PROPERTY(peace_cost_transfer_provinces);
+ fixed_point_t PROPERTY(peace_cost_remove_cores);
+ fixed_point_t PROPERTY(peace_cost_prestige);
+ fixed_point_t PROPERTY(peace_cost_concede);
+ fixed_point_t PROPERTY(peace_cost_status_quo);
+ fixed_point_t PROPERTY(peace_cost_annex);
+ fixed_point_t PROPERTY(peace_cost_demand_state);
+ fixed_point_t PROPERTY(peace_cost_install_communist_gov_type);
+ fixed_point_t PROPERTY(peace_cost_uninstall_communist_gov_type);
+ fixed_point_t PROPERTY(peace_cost_colony);
+ fixed_point_t PROPERTY(infamy_add_to_sphere);
+ fixed_point_t PROPERTY(infamy_release_puppet);
+ fixed_point_t PROPERTY(infamy_make_puppet);
+ fixed_point_t PROPERTY(infamy_disarmament);
+ fixed_point_t PROPERTY(infamy_destroy_forts);
+ fixed_point_t PROPERTY(infamy_destroy_naval_bases);
+ fixed_point_t PROPERTY(infamy_reparations);
+ fixed_point_t PROPERTY(infamy_transfer_provinces);
+ fixed_point_t PROPERTY(infamy_remove_cores);
+ fixed_point_t PROPERTY(infamy_prestige);
+ fixed_point_t PROPERTY(infamy_concede);
+ fixed_point_t PROPERTY(infamy_status_quo);
+ fixed_point_t PROPERTY(infamy_annex);
+ fixed_point_t PROPERTY(infamy_demand_state);
+ fixed_point_t PROPERTY(infamy_install_communist_gov_type);
+ fixed_point_t PROPERTY(infamy_uninstall_communist_gov_type);
+ fixed_point_t PROPERTY(infamy_colony);
+ fixed_point_t PROPERTY(prestige_add_to_sphere_base);
+ fixed_point_t PROPERTY(prestige_release_puppet_base);
+ fixed_point_t PROPERTY(prestige_make_puppet_base);
+ fixed_point_t PROPERTY(prestige_disarmament_base);
+ fixed_point_t PROPERTY(prestige_destroy_forts_base);
+ fixed_point_t PROPERTY(prestige_destroy_naval_bases_base);
+ fixed_point_t PROPERTY(prestige_reparations_base);
+ fixed_point_t PROPERTY(prestige_transfer_provinces_base);
+ fixed_point_t PROPERTY(prestige_remove_cores_base);
+ fixed_point_t PROPERTY(prestige_prestige_base);
+ fixed_point_t PROPERTY(prestige_concede_base);
+ fixed_point_t PROPERTY(prestige_status_quo_base);
+ fixed_point_t PROPERTY(prestige_annex_base);
+ fixed_point_t PROPERTY(prestige_demand_state_base);
+ fixed_point_t PROPERTY(prestige_clear_union_sphere_base);
+ fixed_point_t PROPERTY(prestige_gunboat_base);
+ fixed_point_t PROPERTY(prestige_install_communist_gov_type_base);
+ fixed_point_t PROPERTY(prestige_uninstall_communist_gov_type_base);
+ fixed_point_t PROPERTY(prestige_colony_base);
+ fixed_point_t PROPERTY(prestige_add_to_sphere);
+ fixed_point_t PROPERTY(prestige_release_puppet);
+ fixed_point_t PROPERTY(prestige_make_puppet);
+ fixed_point_t PROPERTY(prestige_disarmament);
+ fixed_point_t PROPERTY(prestige_destroy_forts);
+ fixed_point_t PROPERTY(prestige_destroy_naval_bases);
+ fixed_point_t PROPERTY(prestige_reparations);
+ fixed_point_t PROPERTY(prestige_transfer_provinces);
+ fixed_point_t PROPERTY(prestige_remove_cores);
+ fixed_point_t PROPERTY(prestige_prestige);
+ fixed_point_t PROPERTY(prestige_concede);
+ fixed_point_t PROPERTY(prestige_status_quo);
+ fixed_point_t PROPERTY(prestige_annex);
+ fixed_point_t PROPERTY(prestige_demand_state);
+ fixed_point_t PROPERTY(prestige_clear_union_sphere);
+ fixed_point_t PROPERTY(prestige_gunboat);
+ fixed_point_t PROPERTY(prestige_install_communist_gov_type);
+ fixed_point_t PROPERTY(prestige_uninstall_communist_gov_type);
+ fixed_point_t PROPERTY(prestige_colony);
+ fixed_point_t PROPERTY(breaktruce_infamy_add_to_sphere);
+ fixed_point_t PROPERTY(breaktruce_infamy_release_puppet);
+ fixed_point_t PROPERTY(breaktruce_infamy_make_puppet);
+ fixed_point_t PROPERTY(breaktruce_infamy_disarmament);
+ fixed_point_t PROPERTY(breaktruce_infamy_destroy_forts);
+ fixed_point_t PROPERTY(breaktruce_infamy_destroy_naval_bases);
+ fixed_point_t PROPERTY(breaktruce_infamy_reparations);
+ fixed_point_t PROPERTY(breaktruce_infamy_transfer_provinces);
+ fixed_point_t PROPERTY(breaktruce_infamy_remove_cores);
+ fixed_point_t PROPERTY(breaktruce_infamy_prestige);
+ fixed_point_t PROPERTY(breaktruce_infamy_concede);
+ fixed_point_t PROPERTY(breaktruce_infamy_status_quo);
+ fixed_point_t PROPERTY(breaktruce_infamy_annex);
+ fixed_point_t PROPERTY(breaktruce_infamy_demand_state);
+ fixed_point_t PROPERTY(breaktruce_infamy_install_communist_gov_type);
+ fixed_point_t PROPERTY(breaktruce_infamy_uninstall_communist_gov_type);
+ fixed_point_t PROPERTY(breaktruce_infamy_colony);
+ fixed_point_t PROPERTY(breaktruce_prestige_add_to_sphere);
+ fixed_point_t PROPERTY(breaktruce_prestige_release_puppet);
+ fixed_point_t PROPERTY(breaktruce_prestige_make_puppet);
+ fixed_point_t PROPERTY(breaktruce_prestige_disarmament);
+ fixed_point_t PROPERTY(breaktruce_prestige_destroy_forts);
+ fixed_point_t PROPERTY(breaktruce_prestige_destroy_naval_bases);
+ fixed_point_t PROPERTY(breaktruce_prestige_reparations);
+ fixed_point_t PROPERTY(breaktruce_prestige_transfer_provinces);
+ fixed_point_t PROPERTY(breaktruce_prestige_remove_cores);
+ fixed_point_t PROPERTY(breaktruce_prestige_prestige);
+ fixed_point_t PROPERTY(breaktruce_prestige_concede);
+ fixed_point_t PROPERTY(breaktruce_prestige_status_quo);
+ fixed_point_t PROPERTY(breaktruce_prestige_annex);
+ fixed_point_t PROPERTY(breaktruce_prestige_demand_state);
+ fixed_point_t PROPERTY(breaktruce_prestige_install_communist_gov_type);
+ fixed_point_t PROPERTY(breaktruce_prestige_uninstall_communist_gov_type);
+ fixed_point_t PROPERTY(breaktruce_prestige_colony);
+ fixed_point_t PROPERTY(breaktruce_militancy_add_to_sphere);
+ fixed_point_t PROPERTY(breaktruce_militancy_release_puppet);
+ fixed_point_t PROPERTY(breaktruce_militancy_make_puppet);
+ fixed_point_t PROPERTY(breaktruce_militancy_disarmament);
+ fixed_point_t PROPERTY(breaktruce_militancy_destroy_forts);
+ fixed_point_t PROPERTY(breaktruce_militancy_destroy_naval_bases);
+ fixed_point_t PROPERTY(breaktruce_militancy_reparations);
+ fixed_point_t PROPERTY(breaktruce_militancy_transfer_provinces);
+ fixed_point_t PROPERTY(breaktruce_militancy_remove_cores);
+ fixed_point_t PROPERTY(breaktruce_militancy_prestige);
+ fixed_point_t PROPERTY(breaktruce_militancy_concede);
+ fixed_point_t PROPERTY(breaktruce_militancy_status_quo);
+ fixed_point_t PROPERTY(breaktruce_militancy_annex);
+ fixed_point_t PROPERTY(breaktruce_militancy_demand_state);
+ fixed_point_t PROPERTY(breaktruce_militancy_install_communist_gov_type);
+ fixed_point_t PROPERTY(breaktruce_militancy_uninstall_communist_gov_type);
+ fixed_point_t PROPERTY(breaktruce_militancy_colony);
+ fixed_point_t PROPERTY(goodrelation_infamy_add_to_sphere);
+ fixed_point_t PROPERTY(goodrelation_infamy_release_puppet);
+ fixed_point_t PROPERTY(goodrelation_infamy_make_puppet);
+ fixed_point_t PROPERTY(goodrelation_infamy_disarmament);
+ fixed_point_t PROPERTY(goodrelation_infamy_destroy_forts);
+ fixed_point_t PROPERTY(goodrelation_infamy_destroy_naval_bases);
+ fixed_point_t PROPERTY(goodrelation_infamy_reparations);
+ fixed_point_t PROPERTY(goodrelation_infamy_transfer_provinces);
+ fixed_point_t PROPERTY(goodrelation_infamy_remove_cores);
+ fixed_point_t PROPERTY(goodrelation_infamy_prestige);
+ fixed_point_t PROPERTY(goodrelation_infamy_concede);
+ fixed_point_t PROPERTY(goodrelation_infamy_status_quo);
+ fixed_point_t PROPERTY(goodrelation_infamy_annex);
+ fixed_point_t PROPERTY(goodrelation_infamy_demand_state);
+ fixed_point_t PROPERTY(goodrelation_infamy_install_communist_gov_type);
+ fixed_point_t PROPERTY(goodrelation_infamy_uninstall_communist_gov_type);
+ fixed_point_t PROPERTY(goodrelation_infamy_colony);
+ fixed_point_t PROPERTY(goodrelation_prestige_add_to_sphere);
+ fixed_point_t PROPERTY(goodrelation_prestige_release_puppet);
+ fixed_point_t PROPERTY(goodrelation_prestige_make_puppet);
+ fixed_point_t PROPERTY(goodrelation_prestige_disarmament);
+ fixed_point_t PROPERTY(goodrelation_prestige_destroy_forts);
+ fixed_point_t PROPERTY(goodrelation_prestige_destroy_naval_bases);
+ fixed_point_t PROPERTY(goodrelation_prestige_reparations);
+ fixed_point_t PROPERTY(goodrelation_prestige_transfer_provinces);
+ fixed_point_t PROPERTY(goodrelation_prestige_remove_cores);
+ fixed_point_t PROPERTY(goodrelation_prestige_prestige);
+ fixed_point_t PROPERTY(goodrelation_prestige_concede);
+ fixed_point_t PROPERTY(goodrelation_prestige_status_quo);
+ fixed_point_t PROPERTY(goodrelation_prestige_annex);
+ fixed_point_t PROPERTY(goodrelation_prestige_demand_state);
+ fixed_point_t PROPERTY(goodrelation_prestige_install_communist_gov_type);
+ fixed_point_t PROPERTY(goodrelation_prestige_uninstall_communist_gov_type);
+ fixed_point_t PROPERTY(goodrelation_prestige_colony);
+ fixed_point_t PROPERTY(goodrelation_militancy_add_to_sphere);
+ fixed_point_t PROPERTY(goodrelation_militancy_release_puppet);
+ fixed_point_t PROPERTY(goodrelation_militancy_make_puppet);
+ fixed_point_t PROPERTY(goodrelation_militancy_disarmament);
+ fixed_point_t PROPERTY(goodrelation_militancy_destroy_forts);
+ fixed_point_t PROPERTY(goodrelation_militancy_destroy_naval_bases);
+ fixed_point_t PROPERTY(goodrelation_militancy_reparations);
+ fixed_point_t PROPERTY(goodrelation_militancy_transfer_provinces);
+ fixed_point_t PROPERTY(goodrelation_militancy_remove_cores);
+ fixed_point_t PROPERTY(goodrelation_militancy_prestige);
+ fixed_point_t PROPERTY(goodrelation_militancy_concede);
+ fixed_point_t PROPERTY(goodrelation_militancy_status_quo);
+ fixed_point_t PROPERTY(goodrelation_militancy_annex);
+ fixed_point_t PROPERTY(goodrelation_militancy_demand_state);
+ fixed_point_t PROPERTY(goodrelation_militancy_install_communist_gov_type);
+ fixed_point_t PROPERTY(goodrelation_militancy_uninstall_communist_gov_type);
+ fixed_point_t PROPERTY(goodrelation_militancy_colony);
+ fixed_point_t PROPERTY(war_prestige_cost_base);
+ fixed_point_t PROPERTY(war_prestige_cost_high_prestige);
+ fixed_point_t PROPERTY(war_prestige_cost_neg_prestige);
+ fixed_point_t PROPERTY(war_prestige_cost_truce);
+ fixed_point_t PROPERTY(war_prestige_cost_honor_alliance);
+ fixed_point_t PROPERTY(war_prestige_cost_honor_guarnatee);
+ fixed_point_t PROPERTY(war_prestige_cost_uncivilized);
+ fixed_point_t PROPERTY(war_prestige_cost_core);
+ fixed_point_t PROPERTY(war_failed_goal_militancy);
+ fixed_point_t PROPERTY(war_failed_goal_prestige_base);
+ fixed_point_t PROPERTY(war_failed_goal_prestige);
+ Timespan PROPERTY(discredit_days);
+ fixed_point_t PROPERTY(discredit_influence_cost_factor);
+ fixed_point_t PROPERTY(discredit_influence_gain_factor);
+ Timespan PROPERTY(banembassy_days);
+ fixed_point_t PROPERTY(declarewar_relation_on_accept);
+ fixed_point_t PROPERTY(declarewar_diplomatic_cost);
+ fixed_point_t PROPERTY(addwargoal_relation_on_accept);
+ fixed_point_t PROPERTY(addwargoal_diplomatic_cost);
+ fixed_point_t PROPERTY(add_unjustified_goal_badboy);
+ fixed_point_t PROPERTY(peace_relation_on_accept);
+ fixed_point_t PROPERTY(peace_relation_on_decline);
+ fixed_point_t PROPERTY(peace_diplomatic_cost);
+ fixed_point_t PROPERTY(alliance_relation_on_accept);
+ fixed_point_t PROPERTY(alliance_relation_on_decline);
+ fixed_point_t PROPERTY(alliance_diplomatic_cost);
+ fixed_point_t PROPERTY(cancelalliance_relation_on_accept);
+ fixed_point_t PROPERTY(cancelalliance_diplomatic_cost);
+ fixed_point_t PROPERTY(callally_relation_on_accept);
+ fixed_point_t PROPERTY(callally_relation_on_decline);
+ fixed_point_t PROPERTY(callally_diplomatic_cost);
+ fixed_point_t PROPERTY(askmilaccess_relation_on_accept);
+ fixed_point_t PROPERTY(askmilaccess_relation_on_decline);
+ fixed_point_t PROPERTY(askmilaccess_diplomatic_cost);
+ fixed_point_t PROPERTY(cancelaskmilaccess_relation_on_accept);
+ fixed_point_t PROPERTY(cancelaskmilaccess_diplomatic_cost);
+ fixed_point_t PROPERTY(givemilaccess_relation_on_accept);
+ fixed_point_t PROPERTY(givemilaccess_relation_on_decline);
+ fixed_point_t PROPERTY(givemilaccess_diplomatic_cost);
+ fixed_point_t PROPERTY(cancelgivemilaccess_relation_on_accept);
+ fixed_point_t PROPERTY(cancelgivemilaccess_diplomatic_cost);
+ fixed_point_t PROPERTY(warsubsidy_relation_on_accept);
+ fixed_point_t PROPERTY(warsubsidy_diplomatic_cost);
+ fixed_point_t PROPERTY(cancelwarsubsidy_relation_on_accept);
+ fixed_point_t PROPERTY(cancelwarsubsidy_diplomatic_cost);
+ fixed_point_t PROPERTY(discredit_relation_on_accept);
+ fixed_point_t PROPERTY(discredit_influence_cost);
+ fixed_point_t PROPERTY(expeladvisors_relation_on_accept);
+ fixed_point_t PROPERTY(expeladvisors_influence_cost);
+ fixed_point_t PROPERTY(ceasecolonization_relation_on_accept);
+ fixed_point_t PROPERTY(ceasecolonization_relation_on_decline);
+ fixed_point_t PROPERTY(ceasecolonization_diplomatic_cost);
+ fixed_point_t PROPERTY(banembassy_relation_on_accept);
+ fixed_point_t PROPERTY(banembassy_influence_cost);
+ fixed_point_t PROPERTY(increaserelation_relation_on_accept);
+ fixed_point_t PROPERTY(increaserelation_relation_on_decline);
+ fixed_point_t PROPERTY(increaserelation_diplomatic_cost);
+ fixed_point_t PROPERTY(decreaserelation_relation_on_accept);
+ fixed_point_t PROPERTY(decreaserelation_diplomatic_cost);
+ fixed_point_t PROPERTY(addtosphere_relation_on_accept);
+ fixed_point_t PROPERTY(addtosphere_influence_cost);
+ fixed_point_t PROPERTY(removefromsphere_relation_on_accept);
+ fixed_point_t PROPERTY(removefromsphere_influence_cost);
+ fixed_point_t PROPERTY(removefromsphere_prestige_cost);
+ fixed_point_t PROPERTY(removefromsphere_infamy_cost);
+ fixed_point_t PROPERTY(increaseopinion_relation_on_accept);
+ fixed_point_t PROPERTY(increaseopinion_influence_cost);
+ fixed_point_t PROPERTY(decreaseopinion_relation_on_accept);
+ fixed_point_t PROPERTY(decreaseopinion_influence_cost);
+ fixed_point_t PROPERTY(make_cb_diplomatic_cost);
+ fixed_point_t PROPERTY(make_cb_relation_on_accept);
+ fixed_point_t PROPERTY(disarmed_penalty);
+ fixed_point_t PROPERTY(reparations_tax_hit);
+ fixed_point_t PROPERTY(prestige_reduction_base);
+ fixed_point_t PROPERTY(prestige_reduction);
+ Timespan PROPERTY(reparations_duration);
+ fixed_point_t PROPERTY(min_warscore_to_intervene);
+ Timespan PROPERTY(min_time_to_intervene);
+ fixed_point_t PROPERTY(max_warscore_from_battles);
+ fixed_point_t PROPERTY(gunboat_diplomatic_cost);
+ fixed_point_t PROPERTY(gunboat_relation_on_accept);
+ fixed_point_t PROPERTY(wargoal_jingoism_requirement);
+ fixed_point_t PROPERTY(liberate_state_relation_increase);
+ fixed_point_t PROPERTY(dishonored_callally_prestige_penalty);
+ Timespan PROPERTY(base_truce_duration);
+ fixed_point_t PROPERTY(max_influence);
+ fixed_point_t PROPERTY(warsubsidies_percent);
+ fixed_point_t PROPERTY(neighbour_bonus_influence_percent);
+ fixed_point_t PROPERTY(sphere_neighbour_bonus_influence_percent);
+ fixed_point_t PROPERTY(other_continent_bonus_influence_percent);
+ fixed_point_t PROPERTY(puppet_bonus_influence_percent);
+ fixed_point_t PROPERTY(release_nation_prestige);
+ fixed_point_t PROPERTY(release_nation_infamy);
+ fixed_point_t PROPERTY(infamy_clear_union_sphere);
+ fixed_point_t PROPERTY(breaktruce_infamy_clear_union_sphere);
+ fixed_point_t PROPERTY(breaktruce_prestige_clear_union_sphere);
+ fixed_point_t PROPERTY(breaktruce_militancy_clear_union_sphere);
+ fixed_point_t PROPERTY(goodrelation_infamy_clear_union_sphere);
+ fixed_point_t PROPERTY(goodrelation_prestige_clear_union_sphere);
+ fixed_point_t PROPERTY(goodrelation_militancy_clear_union_sphere);
+ fixed_point_t PROPERTY(peace_cost_clear_union_sphere);
+ fixed_point_t PROPERTY(good_peace_refusal_militancy);
+ fixed_point_t PROPERTY(good_peace_refusal_warexh);
+ fixed_point_t PROPERTY(peace_cost_gunboat);
+ fixed_point_t PROPERTY(infamy_gunboat);
+ fixed_point_t PROPERTY(breaktruce_infamy_gunboat);
+ fixed_point_t PROPERTY(breaktruce_prestige_gunboat);
+ fixed_point_t PROPERTY(breaktruce_militancy_gunboat);
+ fixed_point_t PROPERTY(goodrelation_infamy_gunboat);
+ fixed_point_t PROPERTY(goodrelation_prestige_gunboat);
+ fixed_point_t PROPERTY(goodrelation_militancy_gunboat);
+ fixed_point_t PROPERTY(cb_generation_base_speed);
+ fixed_point_t PROPERTY(cb_generation_speed_bonus_on_colony_competition);
+ fixed_point_t PROPERTY(cb_generation_speed_bonus_on_colony_competition_troops_presence);
+ fixed_point_t PROPERTY(make_cb_relation_limit);
+ fixed_point_t PROPERTY(cb_detection_chance_base);
+ fixed_point_t PROPERTY(investment_influence_defense);
+ fixed_point_t PROPERTY(relation_influence_modifier);
+ fixed_point_t PROPERTY(on_cb_detected_relation_change);
+ fixed_point_t PROPERTY(gw_intervene_min_relations);
+ fixed_point_t PROPERTY(gw_intervene_max_exhaustion);
+ fixed_point_t PROPERTY(gw_justify_cb_badboy_impact);
+ fixed_point_t PROPERTY(gw_cb_construction_speed);
+ fixed_point_t PROPERTY(gw_wargoal_jingoism_requirement_mod);
+ fixed_point_t PROPERTY(gw_warscore_cost_mod);
+ fixed_point_t PROPERTY(gw_warscore_cost_mod_2);
+ fixed_point_t PROPERTY(gw_warscore_2_threshold);
+ fixed_point_t PROPERTY(tension_decay);
+ fixed_point_t PROPERTY(tension_from_cb);
+ fixed_point_t PROPERTY(tension_from_movement);
+ fixed_point_t PROPERTY(tension_from_movement_max);
+ fixed_point_t PROPERTY(at_war_tension_decay);
+ fixed_point_t PROPERTY(tension_on_cb_discovered);
+ fixed_point_t PROPERTY(tension_on_revolt);
+ fixed_point_t PROPERTY(tension_while_crisis);
+ Timespan PROPERTY(crisis_cooldown_duration);
+ fixed_point_t PROPERTY(crisis_base_chance);
+ fixed_point_t PROPERTY(crisis_temperature_increase);
+ fixed_point_t PROPERTY(crisis_offer_diplomatic_cost);
+ fixed_point_t PROPERTY(crisis_offer_relation_on_accept);
+ fixed_point_t PROPERTY(crisis_offer_relation_on_decline);
+ fixed_point_t PROPERTY(crisis_did_not_take_side_prestige_factor_base);
+ fixed_point_t PROPERTY(crisis_did_not_take_side_prestige_factor_year);
+ fixed_point_t PROPERTY(crisis_winner_prestige_factor_base);
+ fixed_point_t PROPERTY(crisis_winner_prestige_factor_year);
+ fixed_point_t PROPERTY(crisis_winner_relations_impact);
+ fixed_point_t PROPERTY(back_crisis_diplomatic_cost);
+ fixed_point_t PROPERTY(back_crisis_relation_on_accept);
+ fixed_point_t PROPERTY(back_crisis_relation_on_decline);
+ fixed_point_t PROPERTY(crisis_temperature_on_offer_decline);
+ fixed_point_t PROPERTY(crisis_temperature_participant_factor);
+ fixed_point_t PROPERTY(crisis_temperature_on_mobilize);
+ fixed_point_t PROPERTY(crisis_wargoal_infamy_mult);
+ fixed_point_t PROPERTY(crisis_wargoal_prestige_mult);
+ fixed_point_t PROPERTY(crisis_wargoal_militancy_mult);
+ fixed_point_t PROPERTY(crisis_interest_war_exhaustion_limit);
+ fixed_point_t PROPERTY(rank_1_tension_decay);
+ fixed_point_t PROPERTY(rank_2_tension_decay);
+ fixed_point_t PROPERTY(rank_3_tension_decay);
+ fixed_point_t PROPERTY(rank_4_tension_decay);
+ fixed_point_t PROPERTY(rank_5_tension_decay);
+ fixed_point_t PROPERTY(rank_6_tension_decay);
+ fixed_point_t PROPERTY(rank_7_tension_decay);
+ fixed_point_t PROPERTY(rank_8_tension_decay);
+ fixed_point_t PROPERTY(tws_fulfilled_speed);
+ fixed_point_t PROPERTY(tws_not_fulfilled_speed);
+ Timespan PROPERTY(tws_grace_period_days);
+ fixed_point_t PROPERTY(tws_cb_limit_default);
+ fixed_point_t PROPERTY(tws_fulfilled_idle_space);
+ size_t PROPERTY(tws_battle_min_count);
+ fixed_point_t PROPERTY(tws_battle_max_aspect);
+ fixed_point_t PROPERTY(large_population_influence_penalty);
+ fixed_point_t PROPERTY(lone_backer_prestige_factor);
+
+ DiplomacyDefines();
+
+ std::string_view get_name() const;
+ NodeTools::node_callback_t expect_defines();
+ };
+}
diff --git a/src/openvic-simulation/defines/EconomyDefines.cpp b/src/openvic-simulation/defines/EconomyDefines.cpp
new file mode 100644
index 0000000..57c0157
--- /dev/null
+++ b/src/openvic-simulation/defines/EconomyDefines.cpp
@@ -0,0 +1,92 @@
+#include "EconomyDefines.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+EconomyDefines::EconomyDefines()
+ : max_daily_research {},
+ loan_base_interest {},
+ bankruptcy_external_loan_duration {},
+ bankruptcy_factor {},
+ shadowy_financiers_max_loan_amount {},
+ max_loan_cap_from_banks {},
+ gunboat_low_tax_cap {},
+ gunboat_high_tax_cap {},
+ gunboat_fleet_size_factor {},
+ province_size_divider {},
+ capitalist_build_factory_state_employment_percent {},
+ goods_focus_swap_chance {},
+ num_closed_factories_per_state_lassiez_faire {},
+ min_num_factories_per_state_before_deleting_lassiez_faire {},
+ bankrupcy_duration {},
+ second_rank_base_share_factor {},
+ civ_base_share_factor {},
+ unciv_base_share_factor {},
+ factory_paychecks_leftover_factor {},
+ max_factory_money_save {},
+ small_debt_limit {},
+ factory_upgrade_employee_factor {},
+ rgo_supply_demand_factor_hire_hi {},
+ rgo_supply_demand_factor_hire_lo {},
+ rgo_supply_demand_factor_fire {},
+ employment_hire_lowest {},
+ employment_fire_lowest {},
+ trade_cap_low_limit_land {},
+ trade_cap_low_limit_naval {},
+ trade_cap_low_limit_constructions {},
+ factory_purchase_min_factor {},
+ factory_purchase_drawdown_factor {} {}
+
+std::string_view EconomyDefines::get_name() const {
+ return "economy";
+}
+
+node_callback_t EconomyDefines::expect_defines() {
+ return expect_dictionary_keys(
+ "MAX_DAILY_RESEARCH", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_daily_research)),
+ "LOAN_BASE_INTEREST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(loan_base_interest)),
+ "BANKRUPTCY_EXTERNAL_LOAN_YEARS", ONE_EXACTLY,
+ expect_years(assign_variable_callback(bankruptcy_external_loan_duration)),
+ "BANKRUPTCY_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(bankruptcy_factor)),
+ "SHADOWY_FINANCIERS_MAX_LOAN_AMOUNT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(shadowy_financiers_max_loan_amount)),
+ "MAX_LOAN_CAP_FROM_BANKS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_loan_cap_from_banks)),
+ "GUNBOAT_LOW_TAX_CAP", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gunboat_low_tax_cap)),
+ "GUNBOAT_HIGH_TAX_CAP", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gunboat_high_tax_cap)),
+ "GUNBOAT_FLEET_SIZE_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gunboat_fleet_size_factor)),
+ "PROVINCE_SIZE_DIVIDER", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(province_size_divider)),
+ "CAPITALIST_BUILD_FACTORY_STATE_EMPLOYMENT_PERCENT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(capitalist_build_factory_state_employment_percent)),
+ "GOODS_FOCUS_SWAP_CHANCE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(goods_focus_swap_chance)),
+ "NUM_CLOSED_FACTORIES_PER_STATE_LASSIEZ_FAIRE", ONE_EXACTLY,
+ expect_uint(assign_variable_callback(num_closed_factories_per_state_lassiez_faire)),
+ "MIN_NUM_FACTORIES_PER_STATE_BEFORE_DELETING_LASSIEZ_FAIRE", ONE_EXACTLY,
+ expect_uint(assign_variable_callback(min_num_factories_per_state_before_deleting_lassiez_faire)),
+ "BANKRUPCY_DURATION", ONE_EXACTLY, expect_years(assign_variable_callback(bankrupcy_duration)),
+ "SECOND_RANK_BASE_SHARE_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(second_rank_base_share_factor)),
+ "CIV_BASE_SHARE_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(civ_base_share_factor)),
+ "UNCIV_BASE_SHARE_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(unciv_base_share_factor)),
+ "FACTORY_PAYCHECKS_LEFTOVER_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(factory_paychecks_leftover_factor)),
+ "MAX_FACTORY_MONEY_SAVE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_factory_money_save)),
+ "SMALL_DEBT_LIMIT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(small_debt_limit)),
+ "FACTORY_UPGRADE_EMPLOYEE_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(factory_upgrade_employee_factor)),
+ "RGO_SUPPLY_DEMAND_FACTOR_HIRE_HI", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(rgo_supply_demand_factor_hire_hi)),
+ "RGO_SUPPLY_DEMAND_FACTOR_HIRE_LO", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(rgo_supply_demand_factor_hire_lo)),
+ "RGO_SUPPLY_DEMAND_FACTOR_FIRE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(rgo_supply_demand_factor_fire)),
+ "EMPLOYMENT_HIRE_LOWEST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(employment_hire_lowest)),
+ "EMPLOYMENT_FIRE_LOWEST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(employment_fire_lowest)),
+ "TRADE_CAP_LOW_LIMIT_LAND", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(trade_cap_low_limit_land)),
+ "TRADE_CAP_LOW_LIMIT_NAVAL", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(trade_cap_low_limit_naval)),
+ "TRADE_CAP_LOW_LIMIT_CONSTRUCTIONS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(trade_cap_low_limit_constructions)),
+ "FACTORY_PURCHASE_MIN_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(factory_purchase_min_factor)),
+ "FACTORY_PURCHASE_DRAWDOWN_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(factory_purchase_drawdown_factor))
+ );
+}
diff --git a/src/openvic-simulation/defines/EconomyDefines.hpp b/src/openvic-simulation/defines/EconomyDefines.hpp
new file mode 100644
index 0000000..122475f
--- /dev/null
+++ b/src/openvic-simulation/defines/EconomyDefines.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ struct DefineManager;
+
+ struct EconomyDefines {
+ friend struct DefineManager;
+
+ private:
+ fixed_point_t PROPERTY(max_daily_research);
+ fixed_point_t PROPERTY(loan_base_interest);
+ Timespan PROPERTY(bankruptcy_external_loan_duration);
+ fixed_point_t PROPERTY(bankruptcy_factor);
+ fixed_point_t PROPERTY(shadowy_financiers_max_loan_amount);
+ fixed_point_t PROPERTY(max_loan_cap_from_banks);
+ fixed_point_t PROPERTY(gunboat_low_tax_cap);
+ fixed_point_t PROPERTY(gunboat_high_tax_cap);
+ fixed_point_t PROPERTY(gunboat_fleet_size_factor);
+ fixed_point_t PROPERTY(province_size_divider);
+ fixed_point_t PROPERTY(capitalist_build_factory_state_employment_percent);
+ fixed_point_t PROPERTY(goods_focus_swap_chance);
+ size_t PROPERTY(num_closed_factories_per_state_lassiez_faire);
+ size_t PROPERTY(min_num_factories_per_state_before_deleting_lassiez_faire);
+ Timespan PROPERTY(bankrupcy_duration);
+ fixed_point_t PROPERTY(second_rank_base_share_factor);
+ fixed_point_t PROPERTY(civ_base_share_factor);
+ fixed_point_t PROPERTY(unciv_base_share_factor);
+ fixed_point_t PROPERTY(factory_paychecks_leftover_factor);
+ fixed_point_t PROPERTY(max_factory_money_save);
+ fixed_point_t PROPERTY(small_debt_limit);
+ fixed_point_t PROPERTY(factory_upgrade_employee_factor);
+ fixed_point_t PROPERTY(rgo_supply_demand_factor_hire_hi);
+ fixed_point_t PROPERTY(rgo_supply_demand_factor_hire_lo);
+ fixed_point_t PROPERTY(rgo_supply_demand_factor_fire);
+ fixed_point_t PROPERTY(employment_hire_lowest);
+ fixed_point_t PROPERTY(employment_fire_lowest);
+ fixed_point_t PROPERTY(trade_cap_low_limit_land);
+ fixed_point_t PROPERTY(trade_cap_low_limit_naval);
+ fixed_point_t PROPERTY(trade_cap_low_limit_constructions);
+ fixed_point_t PROPERTY(factory_purchase_min_factor);
+ fixed_point_t PROPERTY(factory_purchase_drawdown_factor);
+
+ EconomyDefines();
+
+ std::string_view get_name() const;
+ NodeTools::node_callback_t expect_defines();
+ };
+}
diff --git a/src/openvic-simulation/defines/GraphicsDefines.cpp b/src/openvic-simulation/defines/GraphicsDefines.cpp
new file mode 100644
index 0000000..e68afe2
--- /dev/null
+++ b/src/openvic-simulation/defines/GraphicsDefines.cpp
@@ -0,0 +1,41 @@
+#include "GraphicsDefines.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+GraphicsDefines::GraphicsDefines()
+ : cities_sprawl_offset {},
+ cities_sprawl_width {},
+ cities_sprawl_height {},
+ cities_sprawl_iterations {},
+ cities_mesh_pool_size_for_country {},
+ cities_mesh_pool_size_for_culture {},
+ cities_mesh_pool_size_for_generic {},
+ cities_mesh_types_count {},
+ cities_mesh_sizes_count {},
+ cities_special_buildings_pool_size {},
+ cities_size_max_population_k {} {}
+
+std::string_view GraphicsDefines::get_name() const {
+ return "graphics";
+}
+
+node_callback_t GraphicsDefines::expect_defines() {
+ return expect_dictionary_keys(
+ "CITIES_SPRAWL_OFFSET", ONE_EXACTLY, expect_uint(assign_variable_callback(cities_sprawl_offset)),
+ "CITIES_SPRAWL_WIDTH", ONE_EXACTLY, expect_uint(assign_variable_callback(cities_sprawl_width)),
+ "CITIES_SPRAWL_HEIGHT", ONE_EXACTLY, expect_uint(assign_variable_callback(cities_sprawl_height)),
+ "CITIES_SPRAWL_ITERATIONS", ONE_EXACTLY, expect_uint(assign_variable_callback(cities_sprawl_iterations)),
+ "CITIES_MESH_POOL_SIZE_FOR_COUNTRY", ONE_EXACTLY,
+ expect_uint(assign_variable_callback(cities_mesh_pool_size_for_country)),
+ "CITIES_MESH_POOL_SIZE_FOR_CULTURE", ONE_EXACTLY,
+ expect_uint(assign_variable_callback(cities_mesh_pool_size_for_culture)),
+ "CITIES_MESH_POOL_SIZE_FOR_GENERIC", ONE_EXACTLY,
+ expect_uint(assign_variable_callback(cities_mesh_pool_size_for_generic)),
+ "CITIES_MESH_TYPES_COUNT", ONE_EXACTLY, expect_uint(assign_variable_callback(cities_mesh_types_count)),
+ "CITIES_MESH_SIZES_COUNT", ONE_EXACTLY, expect_uint(assign_variable_callback(cities_mesh_sizes_count)),
+ "CITIES_SPECIAL_BUILDINGS_POOL_SIZE", ONE_EXACTLY,
+ expect_uint(assign_variable_callback(cities_special_buildings_pool_size)),
+ "CITIES_SIZE_MAX_POPULATION_K", ONE_EXACTLY, expect_uint(assign_variable_callback(cities_size_max_population_k))
+ );
+}
diff --git a/src/openvic-simulation/defines/GraphicsDefines.hpp b/src/openvic-simulation/defines/GraphicsDefines.hpp
new file mode 100644
index 0000000..f4cd7e2
--- /dev/null
+++ b/src/openvic-simulation/defines/GraphicsDefines.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ struct DefineManager;
+
+ struct GraphicsDefines {
+ friend struct DefineManager;
+
+ private:
+ size_t PROPERTY(cities_sprawl_offset);
+ size_t PROPERTY(cities_sprawl_width);
+ size_t PROPERTY(cities_sprawl_height);
+ size_t PROPERTY(cities_sprawl_iterations);
+ size_t PROPERTY(cities_mesh_pool_size_for_country);
+ size_t PROPERTY(cities_mesh_pool_size_for_culture);
+ size_t PROPERTY(cities_mesh_pool_size_for_generic);
+ size_t PROPERTY(cities_mesh_types_count);
+ size_t PROPERTY(cities_mesh_sizes_count);
+ size_t PROPERTY(cities_special_buildings_pool_size);
+ size_t PROPERTY(cities_size_max_population_k);
+
+ GraphicsDefines();
+
+ std::string_view get_name() const;
+ NodeTools::node_callback_t expect_defines();
+ };
+}
diff --git a/src/openvic-simulation/defines/MilitaryDefines.cpp b/src/openvic-simulation/defines/MilitaryDefines.cpp
new file mode 100644
index 0000000..0ce4cb1
--- /dev/null
+++ b/src/openvic-simulation/defines/MilitaryDefines.cpp
@@ -0,0 +1,168 @@
+#include "MilitaryDefines.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+MilitaryDefines::MilitaryDefines()
+ : dig_in_increase_each_days {},
+ reinforce_speed {},
+ combat_difficulty_impact {},
+ base_combat_width {},
+ min_pop_size_for_regiment {},
+ pop_size_per_regiment {},
+ soldier_to_pop_damage {},
+ land_speed_modifier {},
+ naval_speed_modifier {},
+ exp_gain_div {},
+ leader_recruit_cost {},
+ supply_range {},
+ pop_size_per_regiment_protectorate_multiplier {},
+ pop_size_per_regiment_colony_multiplier {},
+ pop_size_per_regiment_non_core_multiplier {},
+ gas_attack_modifier {},
+ combatloss_war_exhaustion {},
+ leader_max_random_prestige {},
+ leader_age_death_factor {},
+ leader_prestige_to_morale_factor {},
+ leader_prestige_to_max_org_factor {},
+ leader_transfer_penalty_on_country_prestige {},
+ leader_prestige_land_gain {},
+ leader_prestige_naval_gain {},
+ naval_combat_seeking_chance {},
+ naval_combat_seeking_chance_min {},
+ naval_combat_self_defence_chance {},
+ naval_combat_shift_back_on_next_target {},
+ naval_combat_shift_back_duration_scale {},
+ naval_combat_speed_to_distance_factor {},
+ naval_combat_change_target_chance {},
+ naval_combat_damage_org_mult {},
+ naval_combat_damage_str_mult {},
+ naval_combat_damage_mult_no_org {},
+ naval_combat_retreat_chance {},
+ naval_combat_retreat_str_org_level {},
+ naval_combat_retreat_speed_mod {},
+ naval_combat_retreat_min_distance {},
+ naval_combat_damaged_target_selection {},
+ naval_combat_stacking_target_change {},
+ naval_combat_stacking_target_select {},
+ naval_combat_max_targets {},
+ ai_bigship_proportion {},
+ ai_lightship_proportion {},
+ ai_transport_proportion {},
+ ai_cavalry_proportion {},
+ ai_support_proportion {},
+ ai_special_proportion {},
+ ai_escort_ratio {},
+ ai_army_taxbase_fraction {},
+ ai_navy_taxbase_fraction {},
+ ai_blockade_range {},
+ recon_unit_ratio {},
+ engineer_unit_ratio {},
+ siege_brigades_min {},
+ siege_brigades_max {},
+ siege_brigades_bonus {},
+ recon_siege_effect {},
+ siege_attrition {},
+ base_military_tactics {},
+ naval_low_supply_damage_supply_status {},
+ naval_low_supply_damage_days_delay {},
+ naval_low_supply_damage_min_str {},
+ naval_low_supply_damage_per_day {} {}
+
+std::string_view MilitaryDefines::get_name() const {
+ return "military";
+}
+
+node_callback_t MilitaryDefines::expect_defines() {
+ return expect_dictionary_keys(
+ "DIG_IN_INCREASE_EACH_DAYS", ONE_EXACTLY, expect_days(assign_variable_callback(dig_in_increase_each_days)),
+ "REINFORCE_SPEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(reinforce_speed)),
+ "COMBAT_DIFFICULTY_IMPACT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(combat_difficulty_impact)),
+ "BASE_COMBAT_WIDTH", ONE_EXACTLY, expect_uint(assign_variable_callback(base_combat_width)),
+ "POP_MIN_SIZE_FOR_REGIMENT", ONE_EXACTLY, expect_uint(assign_variable_callback(min_pop_size_for_regiment)),
+ "POP_SIZE_PER_REGIMENT", ONE_EXACTLY, expect_uint(assign_variable_callback(pop_size_per_regiment)),
+ "SOLDIER_TO_POP_DAMAGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(soldier_to_pop_damage)),
+ "LAND_SPEED_MODIFIER", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(land_speed_modifier)),
+ "NAVAL_SPEED_MODIFIER", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(naval_speed_modifier)),
+ "EXP_GAIN_DIV", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(exp_gain_div)),
+ "LEADER_RECRUIT_COST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(leader_recruit_cost)),
+ "SUPPLY_RANGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(supply_range)),
+ "POP_MIN_SIZE_FOR_REGIMENT_PROTECTORATE_MULTIPLIER", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(pop_size_per_regiment_protectorate_multiplier)),
+ "POP_MIN_SIZE_FOR_REGIMENT_COLONY_MULTIPLIER", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(pop_size_per_regiment_colony_multiplier)),
+ "POP_MIN_SIZE_FOR_REGIMENT_NONCORE_MULTIPLIER", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(pop_size_per_regiment_non_core_multiplier)),
+ "GAS_ATTACK_MODIFIER", ONE_EXACTLY, expect_uint(assign_variable_callback(gas_attack_modifier)),
+ "COMBATLOSS_WAR_EXHAUSTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(combatloss_war_exhaustion)),
+ "LEADER_MAX_RANDOM_PRESTIGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(leader_max_random_prestige)),
+ "LEADER_AGE_DEATH_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(leader_age_death_factor)),
+ "LEADER_PRESTIGE_TO_MORALE_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(leader_prestige_to_morale_factor)),
+ "LEADER_PRESTIGE_TO_MAX_ORG_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(leader_prestige_to_max_org_factor)),
+ "LEADER_TRANSFER_PENALTY_ON_COUNTRY_PRESTIGE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(leader_transfer_penalty_on_country_prestige)),
+ "LEADER_PRESTIGE_LAND_GAIN", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(leader_prestige_land_gain)),
+ "LEADER_PRESTIGE_NAVAL_GAIN", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(leader_prestige_naval_gain)),
+ "NAVAL_COMBAT_SEEKING_CHANCE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(naval_combat_seeking_chance)),
+ "NAVAL_COMBAT_SEEKING_CHANCE_MIN", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_seeking_chance_min)),
+ "NAVAL_COMBAT_SELF_DEFENCE_CHANCE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_self_defence_chance)),
+ "NAVAL_COMBAT_SHIFT_BACK_ON_NEXT_TARGET", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_shift_back_on_next_target)),
+ "NAVAL_COMBAT_SHIFT_BACK_DURATION_SCALE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_shift_back_duration_scale)),
+ "NAVAL_COMBAT_SPEED_TO_DISTANCE_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_speed_to_distance_factor)),
+ "NAVAL_COMBAT_CHANGE_TARGET_CHANCE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_change_target_chance)),
+ "NAVAL_COMBAT_DAMAGE_ORG_MULT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_damage_org_mult)),
+ "NAVAL_COMBAT_DAMAGE_STR_MULT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_damage_str_mult)),
+ "NAVAL_COMBAT_DAMAGE_MULT_NO_ORG", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_damage_mult_no_org)),
+ "NAVAL_COMBAT_RETREAT_CHANCE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(naval_combat_retreat_chance)),
+ "NAVAL_COMBAT_RETREAT_STR_ORG_LEVEL", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_retreat_str_org_level)),
+ "NAVAL_COMBAT_RETREAT_SPEED_MOD", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_retreat_speed_mod)),
+ "NAVAL_COMBAT_RETREAT_MIN_DISTANCE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_retreat_min_distance)),
+ "NAVAL_COMBAT_DAMAGED_TARGET_SELECTION", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_damaged_target_selection)),
+ "NAVAL_COMBAT_STACKING_TARGET_CHANGE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_stacking_target_change)),
+ "NAVAL_COMBAT_STACKING_TARGET_SELECT", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_combat_stacking_target_select)),
+ "NAVAL_COMBAT_MAX_TARGETS", ONE_EXACTLY, expect_uint(assign_variable_callback(naval_combat_max_targets)),
+ "AI_BIGSHIP_PROPORTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ai_bigship_proportion)),
+ "AI_LIGHTSHIP_PROPORTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ai_lightship_proportion)),
+ "AI_TRANSPORT_PROPORTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ai_transport_proportion)),
+ "AI_CAVALRY_PROPORTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ai_cavalry_proportion)),
+ "AI_SUPPORT_PROPORTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ai_support_proportion)),
+ "AI_SPECIAL_PROPORTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ai_special_proportion)),
+ "AI_ESCORT_RATIO", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ai_escort_ratio)),
+ "AI_ARMY_TAXBASE_FRACTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ai_army_taxbase_fraction)),
+ "AI_NAVY_TAXBASE_FRACTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ai_navy_taxbase_fraction)),
+ "AI_BLOCKADE_RANGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ai_blockade_range)),
+ "RECON_UNIT_RATIO", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(recon_unit_ratio)),
+ "ENGINEER_UNIT_RATIO", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(engineer_unit_ratio)),
+ "SIEGE_BRIGADES_MIN", ONE_EXACTLY, expect_uint(assign_variable_callback(siege_brigades_min)),
+ "SIEGE_BRIGADES_MAX", ONE_EXACTLY, expect_uint(assign_variable_callback(siege_brigades_max)),
+ "SIEGE_BRIGADES_BONUS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(siege_brigades_bonus)),
+ "RECON_SIEGE_EFFECT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(recon_siege_effect)),
+ "SIEGE_ATTRITION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(siege_attrition)),
+ "BASE_MILITARY_TACTICS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base_military_tactics)),
+ "NAVAL_LOW_SUPPLY_DAMAGE_SUPPLY_STATUS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_low_supply_damage_supply_status)),
+ "NAVAL_LOW_SUPPLY_DAMAGE_DAYS_DELAY", ONE_EXACTLY,
+ expect_days(assign_variable_callback(naval_low_supply_damage_days_delay)),
+ "NAVAL_LOW_SUPPLY_DAMAGE_MIN_STR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_low_supply_damage_min_str)),
+ "NAVAL_LOW_SUPPLY_DAMAGE_PER_DAY", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(naval_low_supply_damage_per_day))
+ );
+}
diff --git a/src/openvic-simulation/defines/MilitaryDefines.hpp b/src/openvic-simulation/defines/MilitaryDefines.hpp
new file mode 100644
index 0000000..2921195
--- /dev/null
+++ b/src/openvic-simulation/defines/MilitaryDefines.hpp
@@ -0,0 +1,86 @@
+#pragma once
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/pop/Pop.hpp"
+#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ struct DefineManager;
+
+ struct MilitaryDefines {
+ friend struct DefineManager;
+
+ private:
+ Timespan PROPERTY(dig_in_increase_each_days);
+ fixed_point_t PROPERTY(reinforce_speed);
+ fixed_point_t PROPERTY(combat_difficulty_impact);
+ size_t PROPERTY(base_combat_width);
+ Pop::pop_size_t PROPERTY(min_pop_size_for_regiment);
+ Pop::pop_size_t PROPERTY(pop_size_per_regiment);
+ fixed_point_t PROPERTY(soldier_to_pop_damage);
+ fixed_point_t PROPERTY(land_speed_modifier);
+ fixed_point_t PROPERTY(naval_speed_modifier);
+ fixed_point_t PROPERTY(exp_gain_div);
+ fixed_point_t PROPERTY(leader_recruit_cost);
+ fixed_point_t PROPERTY(supply_range);
+ fixed_point_t PROPERTY(pop_size_per_regiment_protectorate_multiplier);
+ fixed_point_t PROPERTY(pop_size_per_regiment_colony_multiplier);
+ fixed_point_t PROPERTY(pop_size_per_regiment_non_core_multiplier);
+ size_t PROPERTY(gas_attack_modifier);
+ fixed_point_t PROPERTY(combatloss_war_exhaustion);
+ fixed_point_t PROPERTY(leader_max_random_prestige);
+ fixed_point_t PROPERTY(leader_age_death_factor);
+ fixed_point_t PROPERTY(leader_prestige_to_morale_factor);
+ fixed_point_t PROPERTY(leader_prestige_to_max_org_factor);
+ fixed_point_t PROPERTY(leader_transfer_penalty_on_country_prestige);
+ fixed_point_t PROPERTY(leader_prestige_land_gain);
+ fixed_point_t PROPERTY(leader_prestige_naval_gain);
+ fixed_point_t PROPERTY(naval_combat_seeking_chance);
+ fixed_point_t PROPERTY(naval_combat_seeking_chance_min);
+ fixed_point_t PROPERTY(naval_combat_self_defence_chance);
+ fixed_point_t PROPERTY(naval_combat_shift_back_on_next_target);
+ fixed_point_t PROPERTY(naval_combat_shift_back_duration_scale);
+ fixed_point_t PROPERTY(naval_combat_speed_to_distance_factor);
+ fixed_point_t PROPERTY(naval_combat_change_target_chance);
+ fixed_point_t PROPERTY(naval_combat_damage_org_mult);
+ fixed_point_t PROPERTY(naval_combat_damage_str_mult);
+ fixed_point_t PROPERTY(naval_combat_damage_mult_no_org);
+ fixed_point_t PROPERTY(naval_combat_retreat_chance);
+ fixed_point_t PROPERTY(naval_combat_retreat_str_org_level);
+ fixed_point_t PROPERTY(naval_combat_retreat_speed_mod);
+ fixed_point_t PROPERTY(naval_combat_retreat_min_distance);
+ fixed_point_t PROPERTY(naval_combat_damaged_target_selection);
+ fixed_point_t PROPERTY(naval_combat_stacking_target_change);
+ fixed_point_t PROPERTY(naval_combat_stacking_target_select);
+ size_t PROPERTY(naval_combat_max_targets);
+ fixed_point_t PROPERTY(ai_bigship_proportion);
+ fixed_point_t PROPERTY(ai_lightship_proportion);
+ fixed_point_t PROPERTY(ai_transport_proportion);
+ fixed_point_t PROPERTY(ai_cavalry_proportion);
+ fixed_point_t PROPERTY(ai_support_proportion);
+ fixed_point_t PROPERTY(ai_special_proportion);
+ fixed_point_t PROPERTY(ai_escort_ratio);
+ fixed_point_t PROPERTY(ai_army_taxbase_fraction);
+ fixed_point_t PROPERTY(ai_navy_taxbase_fraction);
+ fixed_point_t PROPERTY(ai_blockade_range);
+ fixed_point_t PROPERTY(recon_unit_ratio);
+ fixed_point_t PROPERTY(engineer_unit_ratio);
+ size_t PROPERTY(siege_brigades_min);
+ size_t PROPERTY(siege_brigades_max);
+ fixed_point_t PROPERTY(siege_brigades_bonus);
+ fixed_point_t PROPERTY(recon_siege_effect);
+ fixed_point_t PROPERTY(siege_attrition);
+ fixed_point_t PROPERTY(base_military_tactics);
+ fixed_point_t PROPERTY(naval_low_supply_damage_supply_status);
+ Timespan PROPERTY(naval_low_supply_damage_days_delay);
+ fixed_point_t PROPERTY(naval_low_supply_damage_min_str);
+ fixed_point_t PROPERTY(naval_low_supply_damage_per_day);
+
+ MilitaryDefines();
+
+ std::string_view get_name() const;
+ NodeTools::node_callback_t expect_defines();
+ };
+}
diff --git a/src/openvic-simulation/defines/PopsDefines.cpp b/src/openvic-simulation/defines/PopsDefines.cpp
new file mode 100644
index 0000000..6fc8d21
--- /dev/null
+++ b/src/openvic-simulation/defines/PopsDefines.cpp
@@ -0,0 +1,142 @@
+#include "PopsDefines.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+PopsDefines::PopsDefines()
+ : base_clergy_for_literacy {},
+ max_clergy_for_literacy {},
+ literacy_change_speed {},
+ assimilation_scale {},
+ conversion_scale {},
+ immigration_scale {},
+ promotion_scale {},
+ promotion_assimilation_chance {},
+ luxury_threshold {},
+ base_goods_demand {},
+ base_popgrowth {},
+ min_life_rating_for_growth {},
+ life_rating_growth_bonus {},
+ life_need_starvation_limit {},
+ mil_lack_everyday_need {},
+ mil_has_everyday_need {},
+ mil_has_luxury_need {},
+ mil_no_life_need {},
+ mil_require_reform {},
+ mil_ideology {},
+ mil_ruling_party {},
+ mil_reform_impact {},
+ mil_war_exhaustion {},
+ mil_non_accepted {},
+ con_literacy {},
+ con_luxury_goods {},
+ con_poor_clergy {},
+ con_midrich_clergy {},
+ con_reform_impact {},
+ con_colonial_factor {},
+ ruling_party_happy_change {},
+ ruling_party_angry_change {},
+ pdef_base_con {},
+ national_focus_divider {},
+ pop_savings {},
+ state_creation_admin_limit {},
+ mil_to_join_rebel {},
+ mil_to_join_rising {},
+ mil_to_autorise {},
+ reduction_after_riseing {},
+ reduction_after_defeat {},
+ pop_to_leadership {},
+ artisan_min_productivity {},
+ slave_growth_divisor {},
+ mil_hit_from_conquest {},
+ luxury_con_change {},
+ invention_impact_on_demand {},
+ artisan_suppressed_colonial_goods_category {},
+ issue_movement_join_limit {},
+ issue_movement_leave_limit {},
+ movement_con_factor {},
+ movement_lit_factor {},
+ mil_on_reb_move {},
+ population_suppression_factor {},
+ population_movement_radical_factor {},
+ nationalist_movement_mil_cap {},
+ movement_support_uh_factor {},
+ rebel_occupation_strength_bonus {},
+ large_population_limit {},
+ large_population_influence_penalty_chunk {} {}
+
+std::string_view PopsDefines::get_name() const {
+ return "pops";
+}
+
+node_callback_t PopsDefines::expect_defines() {
+ return expect_dictionary_keys(
+ "BASE_CLERGY_FOR_LITERACY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base_clergy_for_literacy)),
+ "MAX_CLERGY_FOR_LITERACY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_clergy_for_literacy)),
+ "LITERACY_CHANGE_SPEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(literacy_change_speed)),
+ "ASSIMILATION_SCALE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(assimilation_scale)),
+ "CONVERSION_SCALE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(conversion_scale)),
+ "IMMIGRATION_SCALE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(immigration_scale)),
+ "PROMOTION_SCALE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(promotion_scale)),
+ "PROMOTION_ASSIMILATION_CHANCE", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(promotion_assimilation_chance)),
+ "LUXURY_THRESHOLD", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(luxury_threshold)),
+ "BASE_GOODS_DEMAND", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base_goods_demand)),
+ "BASE_POPGROWTH", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base_popgrowth)),
+ "MIN_LIFE_RATING_FOR_GROWTH", ONE_EXACTLY, expect_uint(assign_variable_callback(min_life_rating_for_growth)),
+ "LIFE_RATING_GROWTH_BONUS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(life_rating_growth_bonus)),
+ "LIFE_NEED_STARVATION_LIMIT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(life_need_starvation_limit)),
+ "MIL_LACK_EVERYDAY_NEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_lack_everyday_need)),
+ "MIL_HAS_EVERYDAY_NEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_has_everyday_need)),
+ "MIL_HAS_LUXURY_NEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_has_luxury_need)),
+ "MIL_NO_LIFE_NEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_no_life_need)),
+ "MIL_REQUIRE_REFORM", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_require_reform)),
+ "MIL_IDEOLOGY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_ideology)),
+ "MIL_RULING_PARTY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_ruling_party)),
+ "MIL_REFORM_IMPACT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_reform_impact)),
+ "MIL_WAR_EXHAUSTION", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_war_exhaustion)),
+ "MIL_NON_ACCEPTED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_non_accepted)),
+ "CON_LITERACY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(con_literacy)),
+ "CON_LUXURY_GOODS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(con_luxury_goods)),
+ "CON_POOR_CLERGY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(con_poor_clergy)),
+ "CON_MIDRICH_CLERGY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(con_midrich_clergy)),
+ "CON_REFORM_IMPACT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(con_reform_impact)),
+ "CON_COLONIAL_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(con_colonial_factor)),
+ "RULING_PARTY_HAPPY_CHANGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ruling_party_happy_change)),
+ "RULING_PARTY_ANGRY_CHANGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(ruling_party_angry_change)),
+ "PDEF_BASE_CON", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(pdef_base_con)),
+ "NATIONAL_FOCUS_DIVIDER", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(national_focus_divider)),
+ "POP_SAVINGS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(pop_savings)),
+ "STATE_CREATION_ADMIN_LIMIT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(state_creation_admin_limit)),
+ "MIL_TO_JOIN_REBEL", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_to_join_rebel)),
+ "MIL_TO_JOIN_RISING", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_to_join_rising)),
+ "MIL_TO_AUTORISE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_to_autorise)),
+ "REDUCTION_AFTER_RISEING", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(reduction_after_riseing)),
+ "REDUCTION_AFTER_DEFEAT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(reduction_after_defeat)),
+ "POP_TO_LEADERSHIP", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(pop_to_leadership)),
+ "ARTISAN_MIN_PRODUCTIVITY", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(artisan_min_productivity)),
+ "SLAVE_GROWTH_DIVISOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(slave_growth_divisor)),
+ "MIL_HIT_FROM_CONQUEST", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_hit_from_conquest)),
+ "LUXURY_CON_CHANGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(luxury_con_change)),
+ "INVENTION_IMPACT_ON_DEMAND", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(invention_impact_on_demand)),
+ "ARTISAN_SUPPRESSED_COLONIAL_GOODS_CATEGORY", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(artisan_suppressed_colonial_goods_category)),
+ "ISSUE_MOVEMENT_JOIN_LIMIT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(issue_movement_join_limit)),
+ "ISSUE_MOVEMENT_LEAVE_LIMIT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(issue_movement_leave_limit)),
+ "MOVEMENT_CON_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(movement_con_factor)),
+ "MOVEMENT_LIT_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(movement_lit_factor)),
+ "MIL_ON_REB_MOVE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(mil_on_reb_move)),
+ "POPULATION_SUPPRESSION_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(population_suppression_factor)),
+ "POPULATION_MOVEMENT_RADICAL_FACTOR", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(population_movement_radical_factor)),
+ "NATIONALIST_MOVEMENT_MIL_CAP", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(nationalist_movement_mil_cap)),
+ "MOVEMENT_SUPPORT_UH_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(movement_support_uh_factor)),
+ "REBEL_OCCUPATION_STRENGTH_BONUS", ONE_EXACTLY,
+ expect_fixed_point(assign_variable_callback(rebel_occupation_strength_bonus)),
+ "LARGE_POPULATION_LIMIT", ONE_EXACTLY, expect_uint(assign_variable_callback(large_population_limit)),
+ "LARGE_POPULATION_INFLUENCE_PENALTY_CHUNK", ONE_EXACTLY,
+ expect_uint(assign_variable_callback(large_population_influence_penalty_chunk))
+ );
+}
diff --git a/src/openvic-simulation/defines/PopsDefines.hpp b/src/openvic-simulation/defines/PopsDefines.hpp
new file mode 100644
index 0000000..50d5b79
--- /dev/null
+++ b/src/openvic-simulation/defines/PopsDefines.hpp
@@ -0,0 +1,82 @@
+#pragma once
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/map/ProvinceInstance.hpp"
+#include "openvic-simulation/pop/Pop.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ struct DefineManager;
+
+ struct PopsDefines {
+ friend struct DefineManager;
+
+ private:
+ fixed_point_t PROPERTY(base_clergy_for_literacy);
+ fixed_point_t PROPERTY(max_clergy_for_literacy);
+ fixed_point_t PROPERTY(literacy_change_speed);
+ fixed_point_t PROPERTY(assimilation_scale);
+ fixed_point_t PROPERTY(conversion_scale);
+ fixed_point_t PROPERTY(immigration_scale);
+ fixed_point_t PROPERTY(promotion_scale);
+ fixed_point_t PROPERTY(promotion_assimilation_chance);
+ fixed_point_t PROPERTY(luxury_threshold);
+ fixed_point_t PROPERTY(base_goods_demand);
+ fixed_point_t PROPERTY(base_popgrowth);
+ ProvinceInstance::life_rating_t PROPERTY(min_life_rating_for_growth);
+ fixed_point_t PROPERTY(life_rating_growth_bonus);
+ fixed_point_t PROPERTY(life_need_starvation_limit);
+ fixed_point_t PROPERTY(mil_lack_everyday_need);
+ fixed_point_t PROPERTY(mil_has_everyday_need);
+ fixed_point_t PROPERTY(mil_has_luxury_need);
+ fixed_point_t PROPERTY(mil_no_life_need);
+ fixed_point_t PROPERTY(mil_require_reform);
+ fixed_point_t PROPERTY(mil_ideology);
+ fixed_point_t PROPERTY(mil_ruling_party);
+ fixed_point_t PROPERTY(mil_reform_impact);
+ fixed_point_t PROPERTY(mil_war_exhaustion);
+ fixed_point_t PROPERTY(mil_non_accepted);
+ fixed_point_t PROPERTY(con_literacy);
+ fixed_point_t PROPERTY(con_luxury_goods);
+ fixed_point_t PROPERTY(con_poor_clergy);
+ fixed_point_t PROPERTY(con_midrich_clergy);
+ fixed_point_t PROPERTY(con_reform_impact);
+ fixed_point_t PROPERTY(con_colonial_factor);
+ fixed_point_t PROPERTY(ruling_party_happy_change);
+ fixed_point_t PROPERTY(ruling_party_angry_change);
+ fixed_point_t PROPERTY(pdef_base_con);
+ fixed_point_t PROPERTY(national_focus_divider);
+ fixed_point_t PROPERTY(pop_savings);
+ fixed_point_t PROPERTY(state_creation_admin_limit);
+ fixed_point_t PROPERTY(mil_to_join_rebel);
+ fixed_point_t PROPERTY(mil_to_join_rising);
+ fixed_point_t PROPERTY(mil_to_autorise);
+ fixed_point_t PROPERTY(reduction_after_riseing);
+ fixed_point_t PROPERTY(reduction_after_defeat);
+ fixed_point_t PROPERTY(pop_to_leadership);
+ fixed_point_t PROPERTY(artisan_min_productivity);
+ fixed_point_t PROPERTY(slave_growth_divisor);
+ fixed_point_t PROPERTY(mil_hit_from_conquest);
+ fixed_point_t PROPERTY(luxury_con_change);
+ fixed_point_t PROPERTY(invention_impact_on_demand);
+ fixed_point_t PROPERTY(artisan_suppressed_colonial_goods_category);
+ fixed_point_t PROPERTY(issue_movement_join_limit);
+ fixed_point_t PROPERTY(issue_movement_leave_limit);
+ fixed_point_t PROPERTY(movement_con_factor);
+ fixed_point_t PROPERTY(movement_lit_factor);
+ fixed_point_t PROPERTY(mil_on_reb_move);
+ fixed_point_t PROPERTY(population_suppression_factor);
+ fixed_point_t PROPERTY(population_movement_radical_factor);
+ fixed_point_t PROPERTY(nationalist_movement_mil_cap);
+ fixed_point_t PROPERTY(movement_support_uh_factor);
+ fixed_point_t PROPERTY(rebel_occupation_strength_bonus);
+ Pop::pop_size_t PROPERTY(large_population_limit);
+ Pop::pop_size_t PROPERTY(large_population_influence_penalty_chunk);
+
+ PopsDefines();
+
+ std::string_view get_name() const;
+ NodeTools::node_callback_t expect_defines();
+ };
+}
diff --git a/src/openvic-simulation/economy/BuildingType.cpp b/src/openvic-simulation/economy/BuildingType.cpp
index e7c0d59..2801cfa 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;
@@ -61,7 +63,8 @@ bool BuildingTypeManager::load_buildings_file(
) -> bool {
BuildingType::building_type_args_t building_type_args {};
- bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(building_type_args.modifier),
+ bool ret = NodeTools::expect_dictionary_keys_and_default(
+ modifier_manager.expect_base_province_modifier(building_type_args.modifier),
"type", ONE_EXACTLY, expect_identifier(assign_variable_callback(building_type_args.type)),
"on_completion", ZERO_OR_ONE, expect_identifier(assign_variable_callback(building_type_args.on_completion)),
"completion_size", ZERO_OR_ONE,
@@ -112,18 +115,27 @@ bool BuildingTypeManager::load_buildings_file(
)(root);
lock_building_types();
- for (BuildingType const& building_type : building_types.get_items()) {
+ IndexedMap<BuildingType, ModifierEffectCache::building_type_effects_t>& building_type_effects =
+ modifier_manager.modifier_effect_cache.building_type_effects;
+
+ building_type_effects.set_keys(&get_building_types());
+
+ for (BuildingType const& building_type : get_building_types()) {
using enum ModifierEffect::format_t;
+ using enum ModifierEffect::target_t;
+
+ ModifierEffectCache::building_type_effects_t& this_building_type_effects = building_type_effects[building_type];
static constexpr std::string_view max_prefix = "max_";
static constexpr std::string_view min_prefix = "min_build_";
- ret &= modifier_manager.add_modifier_effect(
- StringUtils::append_string_views(max_prefix, building_type.get_identifier()), true, INT,
- StringUtils::append_string_views("$", building_type.get_identifier(), "$ $TECH_MAX_LEVEL$")
+ ret &= modifier_manager.register_technology_modifier_effect(
+ this_building_type_effects.max_level, StringUtils::append_string_views(max_prefix, building_type.get_identifier()),
+ true, INT, StringUtils::append_string_views("$", building_type.get_identifier(), "$ $TECH_MAX_LEVEL$")
);
// TODO - add custom localisation for "min_build_$building_type$" modifiers
- ret &= modifier_manager.add_modifier_effect(
- StringUtils::append_string_views(min_prefix, building_type.get_identifier()), false, INT
+ ret &= modifier_manager.register_terrain_modifier_effect(
+ this_building_type_effects.min_level, StringUtils::append_string_views(min_prefix, building_type.get_identifier()),
+ false, INT
);
if (building_type.is_in_province()) {
diff --git a/src/openvic-simulation/economy/GoodDefinition.cpp b/src/openvic-simulation/economy/GoodDefinition.cpp
index ed24549..5440b94 100644
--- a/src/openvic-simulation/economy/GoodDefinition.cpp
+++ b/src/openvic-simulation/economy/GoodDefinition.cpp
@@ -1,5 +1,7 @@
#include "GoodDefinition.hpp"
+#include "openvic-simulation/modifier/ModifierManager.hpp"
+
using namespace OpenVic;
using namespace OpenVic::NodeTools;
@@ -11,18 +13,18 @@ GoodDefinition::GoodDefinition(
index_t new_index,
GoodCategory const& new_category,
fixed_point_t new_base_price,
- bool new_available_from_start,
- bool new_tradeable,
- bool new_money,
- bool new_overseas_penalty
+ bool new_is_available_from_start,
+ bool new_is_tradeable,
+ bool new_is_money,
+ bool new_counters_overseas_penalty
) : HasIdentifierAndColour { new_identifier, new_colour, false },
HasIndex { new_index },
category { new_category },
base_price { new_base_price },
- available_from_start { new_available_from_start },
- tradeable { new_tradeable },
- money { new_money },
- overseas_penalty { new_overseas_penalty } {}
+ is_available_from_start { new_is_available_from_start },
+ is_tradeable { new_is_tradeable },
+ is_money { new_is_money },
+ counters_overseas_penalty { new_counters_overseas_penalty } {}
bool GoodDefinitionManager::add_good_category(std::string_view identifier) {
if (identifier.empty()) {
@@ -34,7 +36,7 @@ bool GoodDefinitionManager::add_good_category(std::string_view identifier) {
bool GoodDefinitionManager::add_good_definition(
std::string_view identifier, colour_t colour, GoodCategory const& category, fixed_point_t base_price,
- bool available_from_start, bool tradeable, bool money, bool overseas_penalty
+ bool is_available_from_start, bool is_tradeable, bool is_money, bool has_overseas_penalty
) {
if (identifier.empty()) {
Logger::error("Invalid good identifier - empty!");
@@ -45,8 +47,8 @@ bool GoodDefinitionManager::add_good_definition(
return false;
}
return good_definitions.add_item({
- identifier, colour, get_good_definition_count(), category, base_price, available_from_start,
- tradeable, money, overseas_penalty
+ identifier, colour, get_good_definition_count(), category, base_price, is_available_from_start,
+ is_tradeable, is_money, has_overseas_penalty
});
}
@@ -66,19 +68,19 @@ bool GoodDefinitionManager::load_goods_file(ast::NodeCPtr root) {
return expect_dictionary([this, &good_category](std::string_view key, ast::NodeCPtr value) -> bool {
colour_t colour = colour_t::null();
fixed_point_t base_price;
- bool available_from_start = true, tradeable = true;
- bool money = false, overseas_penalty = false;
+ bool is_available_from_start = true, is_tradeable = true;
+ bool is_money = false, has_overseas_penalty = false;
bool ret = expect_dictionary_keys(
"color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)),
"cost", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base_price)),
- "available_from_start", ZERO_OR_ONE, expect_bool(assign_variable_callback(available_from_start)),
- "tradeable", ZERO_OR_ONE, expect_bool(assign_variable_callback(tradeable)),
- "money", ZERO_OR_ONE, expect_bool(assign_variable_callback(money)),
- "overseas_penalty", ZERO_OR_ONE, expect_bool(assign_variable_callback(overseas_penalty))
+ "available_from_start", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_available_from_start)),
+ "tradeable", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_tradeable)),
+ "money", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_money)),
+ "overseas_penalty", ZERO_OR_ONE, expect_bool(assign_variable_callback(has_overseas_penalty))
)(value);
ret &= add_good_definition(
- key, colour, good_category, base_price, available_from_start, tradeable, money, overseas_penalty
+ key, colour, good_category, base_price, is_available_from_start, is_tradeable, is_money, has_overseas_penalty
);
return ret;
})(good_category_value);
@@ -88,40 +90,84 @@ bool GoodDefinitionManager::load_goods_file(ast::NodeCPtr root) {
}
bool GoodDefinitionManager::generate_modifiers(ModifierManager& modifier_manager) const {
+ constexpr bool has_no_effect = true;
using enum ModifierEffect::format_t;
+ using enum ModifierEffect::target_t;
+
+ IndexedMap<GoodDefinition, ModifierEffectCache::good_effects_t>& good_effects =
+ modifier_manager.modifier_effect_cache.good_effects;
+
+ good_effects.set_keys(&get_good_definitions());
bool ret = true;
- const auto good_modifier = [this, &modifier_manager, &ret](
- std::string_view name, bool is_positive_good, auto make_localisation_suffix
- ) -> void {
- ret &= modifier_manager.register_complex_modifier(name);
+ ret &= modifier_manager.register_complex_modifier("artisan_goods_input");
+ ret &= modifier_manager.register_complex_modifier("artisan_goods_output");
+ ret &= modifier_manager.register_complex_modifier("artisan_goods_throughput");
+ ret &= modifier_manager.register_complex_modifier("factory_goods_input");
+ ret &= modifier_manager.register_complex_modifier("factory_goods_output");
+ ret &= modifier_manager.register_complex_modifier("factory_goods_throughput");
+ ret &= modifier_manager.register_complex_modifier("rgo_goods_output");
+ ret &= modifier_manager.register_complex_modifier("rgo_goods_throughput");
+ ret &= modifier_manager.register_complex_modifier("rgo_size");
- for (GoodDefinition const& good : get_good_definitions()) {
- ret &= modifier_manager.add_modifier_effect(
- ModifierManager::get_flat_identifier(name, good.get_identifier()), is_positive_good, PROPORTION_DECIMAL,
- make_localisation_suffix(good.get_identifier())
+ for (GoodDefinition const& good : get_good_definitions()) {
+ const std::string_view good_identifier = good.get_identifier();
+ ModifierEffectCache::good_effects_t& this_good_effects = good_effects[good];
+
+ const auto good_modifier = [&modifier_manager, &ret, &good_identifier](
+ ModifierEffect const*& effect_cache, std::string_view name, bool is_positive_good,
+ std::string_view localisation_key, bool has_no_effect = false
+ ) -> void {
+ ret &= modifier_manager.register_technology_modifier_effect(
+ effect_cache, ModifierManager::get_flat_identifier(name, good_identifier), is_positive_good,
+ PROPORTION_DECIMAL, localisation_key, has_no_effect
);
- }
- };
+ };
- const auto make_production_localisation_suffix = [](std::string_view localisation_suffix) -> auto {
- return [localisation_suffix](std::string_view good_identifier) -> std::string {
- return StringUtils::append_string_views("$", good_identifier, "$ $", localisation_suffix, "$");
+ const auto make_production_localisation_suffix = [&good_identifier](
+ std::string_view localisation_suffix
+ ) -> std::string {
+ return StringUtils::append_string_views("$", good_identifier, "$ $", localisation_suffix, "$");
};
- };
-
- good_modifier("artisan_goods_input", false, make_production_localisation_suffix("TECH_INPUT"));
- good_modifier("artisan_goods_output", true, make_production_localisation_suffix("TECH_OUTPUT"));
- good_modifier("artisan_goods_throughput", true, make_production_localisation_suffix("TECH_THROUGHPUT"));
- good_modifier("factory_goods_input", false, make_production_localisation_suffix("TECH_INPUT"));
- good_modifier("factory_goods_output", true, make_production_localisation_suffix("TECH_OUTPUT"));
- good_modifier("factory_goods_throughput", true, make_production_localisation_suffix("TECH_THROUGHPUT"));
- good_modifier("rgo_goods_output", true, make_production_localisation_suffix("TECH_OUTPUT"));
- good_modifier("rgo_goods_throughput", true, make_production_localisation_suffix("TECH_THROUGHPUT"));
- good_modifier("rgo_size", true, [](std::string_view good_identifier) -> std::string {
- return StringUtils::append_string_views(good_identifier, "_RGO_SIZE");
- });
+
+ good_modifier(
+ this_good_effects.artisan_goods_input, "artisan_goods_input", false,
+ make_production_localisation_suffix("TECH_INPUT"), has_no_effect
+ );
+ good_modifier(
+ this_good_effects.artisan_goods_output, "artisan_goods_output", true,
+ make_production_localisation_suffix("TECH_OUTPUT"), has_no_effect
+ );
+ good_modifier(
+ this_good_effects.artisan_goods_throughput, "artisan_goods_throughput", true,
+ make_production_localisation_suffix("TECH_THROUGHPUT"), has_no_effect
+ );
+ good_modifier(
+ this_good_effects.factory_goods_input, "factory_goods_input", false,
+ make_production_localisation_suffix("TECH_INPUT")
+ );
+ good_modifier(
+ this_good_effects.factory_goods_output, "factory_goods_output", true,
+ make_production_localisation_suffix("TECH_OUTPUT")
+ );
+ good_modifier(
+ this_good_effects.factory_goods_throughput, "factory_goods_throughput", true,
+ make_production_localisation_suffix("TECH_THROUGHPUT")
+ );
+ good_modifier(
+ this_good_effects.rgo_goods_output, "rgo_goods_output", true,
+ make_production_localisation_suffix("TECH_OUTPUT")
+ );
+ good_modifier(
+ this_good_effects.rgo_goods_throughput, "rgo_goods_throughput", true,
+ make_production_localisation_suffix("TECH_THROUGHPUT")
+ );
+ good_modifier(
+ this_good_effects.rgo_size, "rgo_size", true,
+ StringUtils::append_string_views(good_identifier, "_RGO_SIZE")
+ );
+ }
return ret;
}
diff --git a/src/openvic-simulation/economy/GoodDefinition.hpp b/src/openvic-simulation/economy/GoodDefinition.hpp
index bc231cb..7cb87cc 100644
--- a/src/openvic-simulation/economy/GoodDefinition.hpp
+++ b/src/openvic-simulation/economy/GoodDefinition.hpp
@@ -1,6 +1,5 @@
#pragma once
-#include "openvic-simulation/modifier/Modifier.hpp"
#include "openvic-simulation/types/IdentifierRegistry.hpp"
namespace OpenVic {
@@ -36,21 +35,23 @@ namespace OpenVic {
private:
GoodCategory const& PROPERTY(category);
const fixed_point_t PROPERTY(base_price);
- const bool PROPERTY_CUSTOM_PREFIX(available_from_start, is);
- const bool PROPERTY_CUSTOM_PREFIX(tradeable, is);
- const bool PROPERTY(money);
- const bool PROPERTY(overseas_penalty);
+ const bool PROPERTY(is_available_from_start);
+ const bool PROPERTY(is_tradeable);
+ const bool PROPERTY(is_money);
+ const bool PROPERTY(counters_overseas_penalty);
GoodDefinition(
std::string_view new_identifier, colour_t new_colour, index_t new_index, GoodCategory const& new_category,
- fixed_point_t new_base_price, bool new_available_from_start, bool new_tradeable, bool new_money,
- bool new_overseas_penalty
+ fixed_point_t new_base_price, bool new_is_available_from_start, bool new_is_tradeable, bool new_is_money,
+ bool new_counters_overseas_penalty
);
public:
GoodDefinition(GoodDefinition&&) = default;
};
+ struct ModifierManager;
+
struct GoodDefinitionManager {
private:
IdentifierRegistry<GoodCategory> IDENTIFIER_REGISTRY_CUSTOM_PLURAL(good_category, good_categories);
@@ -61,7 +62,7 @@ namespace OpenVic {
bool add_good_definition(
std::string_view identifier, colour_t colour, GoodCategory const& category, fixed_point_t base_price,
- bool available_from_start, bool tradeable, bool money, bool overseas_penalty
+ bool is_available_from_start, bool is_tradeable, bool is_money, bool has_overseas_penalty
);
bool load_goods_file(ast::NodeCPtr root);
diff --git a/src/openvic-simulation/economy/GoodInstance.cpp b/src/openvic-simulation/economy/GoodInstance.cpp
index 6fe3a2f..ac081c9 100644
--- a/src/openvic-simulation/economy/GoodInstance.cpp
+++ b/src/openvic-simulation/economy/GoodInstance.cpp
@@ -4,7 +4,7 @@ using namespace OpenVic;
GoodInstance::GoodInstance(GoodDefinition const& new_good_definition)
: HasIdentifierAndColour { new_good_definition }, good_definition { new_good_definition },
- price { new_good_definition.get_base_price() }, available { new_good_definition.is_available_from_start() } {}
+ price { new_good_definition.get_base_price() }, is_available { new_good_definition.get_is_available_from_start() } {}
bool GoodInstanceManager::setup(GoodDefinitionManager const& good_definition_manager) {
if (good_instances_are_locked()) {
diff --git a/src/openvic-simulation/economy/GoodInstance.hpp b/src/openvic-simulation/economy/GoodInstance.hpp
index 20370ef..74ec939 100644
--- a/src/openvic-simulation/economy/GoodInstance.hpp
+++ b/src/openvic-simulation/economy/GoodInstance.hpp
@@ -14,7 +14,7 @@ namespace OpenVic {
private:
GoodDefinition const& PROPERTY(good_definition);
fixed_point_t PROPERTY(price);
- bool PROPERTY(available);
+ bool PROPERTY(is_available);
// TODO - supply, demand, actual bought
GoodInstance(GoodDefinition const& new_good_definition);
diff --git a/src/openvic-simulation/economy/production/ArtisanalProducer.hpp b/src/openvic-simulation/economy/production/ArtisanalProducer.hpp
index e5c0b80..65aa3fa 100644
--- a/src/openvic-simulation/economy/production/ArtisanalProducer.hpp
+++ b/src/openvic-simulation/economy/production/ArtisanalProducer.hpp
@@ -6,7 +6,7 @@
#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
- class ArtisanalProducer final {
+ struct ArtisanalProducer {
private:
ProductionType const& PROPERTY(production_type);
GoodDefinition::good_definition_map_t PROPERTY(stockpile);
diff --git a/src/openvic-simulation/economy/production/Employee.cpp b/src/openvic-simulation/economy/production/Employee.cpp
new file mode 100644
index 0000000..569299a
--- /dev/null
+++ b/src/openvic-simulation/economy/production/Employee.cpp
@@ -0,0 +1,8 @@
+#include "Employee.hpp"
+
+using namespace OpenVic;
+
+Employee::Employee(Pop& new_pop, const Pop::pop_size_t new_size)
+ : pop { new_pop },
+ size { new_size }
+ {} \ No newline at end of file
diff --git a/src/openvic-simulation/economy/production/Employee.hpp b/src/openvic-simulation/economy/production/Employee.hpp
new file mode 100644
index 0000000..8a09c31
--- /dev/null
+++ b/src/openvic-simulation/economy/production/Employee.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "openvic-simulation/pop/Pop.hpp"
+
+namespace OpenVic {
+ struct Employee {
+ private:
+ Pop::pop_size_t PROPERTY_RW(size);
+ public:
+ Pop& pop;
+ Employee(Pop& new_pop, const Pop::pop_size_t new_size);
+ };
+} \ No newline at end of file
diff --git a/src/openvic-simulation/economy/production/FactoryProducer.hpp b/src/openvic-simulation/economy/production/FactoryProducer.hpp
index 54ddfb8..9e660ba 100644
--- a/src/openvic-simulation/economy/production/FactoryProducer.hpp
+++ b/src/openvic-simulation/economy/production/FactoryProducer.hpp
@@ -8,7 +8,7 @@
#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
- class FactoryProducer final {
+ struct FactoryProducer {
private:
static constexpr uint8_t DAYS_OF_HISTORY = 7;
using daily_profit_history_t = std::array<fixed_point_t, DAYS_OF_HISTORY>;
diff --git a/src/openvic-simulation/economy/production/ProductionType.cpp b/src/openvic-simulation/economy/production/ProductionType.cpp
index 65f3eba..033026d 100644
--- a/src/openvic-simulation/economy/production/ProductionType.cpp
+++ b/src/openvic-simulation/economy/production/ProductionType.cpp
@@ -9,33 +9,33 @@ Job::Job(
PopType const* new_pop_type,
effect_t new_effect_type,
fixed_point_t new_effect_multiplier,
- fixed_point_t new_desired_workforce_share
+ fixed_point_t new_amount
) : pop_type { new_pop_type },
effect_type { new_effect_type },
effect_multiplier { new_effect_multiplier },
- desired_workforce_share { new_desired_workforce_share } {}
+ amount { new_amount } {}
ProductionType::ProductionType(
- std::string_view new_identifier,
- std::optional<Job> new_owner,
+ const std::string_view new_identifier,
+ const std::optional<Job> new_owner,
std::vector<Job>&& new_jobs,
- template_type_t new_template_type,
- Pop::pop_size_t new_base_workforce_size,
+ const template_type_t new_template_type,
+ const Pop::pop_size_t new_base_workforce_size,
GoodDefinition::good_definition_map_t&& new_input_goods,
- GoodDefinition const* new_output_goods,
- fixed_point_t new_base_output_quantity,
+ GoodDefinition const& new_output_good,
+ const fixed_point_t new_base_output_quantity,
std::vector<bonus_t>&& new_bonuses,
GoodDefinition::good_definition_map_t&& new_maintenance_requirements,
- bool new_is_coastal,
- bool new_is_farm,
- bool new_is_mine
+ const bool new_is_coastal,
+ const bool new_is_farm,
+ const bool new_is_mine
) : HasIdentifier { new_identifier },
owner { new_owner },
jobs { std::move(new_jobs) },
template_type { new_template_type },
base_workforce_size { new_base_workforce_size },
input_goods { std::move(new_input_goods) },
- output_goods { new_output_goods },
+ output_good { new_output_good },
base_output_quantity { new_base_output_quantity },
bonuses { std::move(new_bonuses) },
maintenance_requirements { std::move(new_maintenance_requirements) },
@@ -51,7 +51,9 @@ bool ProductionType::parse_scripts(DefinitionManager const& definition_manager)
return ret;
}
-ProductionTypeManager::ProductionTypeManager() : rgo_owner_sprite { 0 } {}
+ProductionTypeManager::ProductionTypeManager() :
+ good_to_rgo_production_type { nullptr },
+ rgo_owner_sprite { 0 } {}
node_callback_t ProductionTypeManager::_expect_job(
GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, callback_t<Job&&> callback
@@ -60,7 +62,7 @@ node_callback_t ProductionTypeManager::_expect_job(
using enum Job::effect_t;
std::string_view pop_type {};
- Job::effect_t effect_type {THROUGHPUT};
+ Job::effect_t effect_type { THROUGHPUT };
fixed_point_t effect_multiplier = 1, desired_workforce_share = 1;
static const string_map_t<Job::effect_t> effect_map = {
@@ -92,19 +94,19 @@ node_callback_t ProductionTypeManager::_expect_job_list(
}
bool ProductionTypeManager::add_production_type(
- std::string_view identifier,
+ const std::string_view identifier,
std::optional<Job> owner,
std::vector<Job>&& jobs,
- ProductionType::template_type_t template_type,
- Pop::pop_size_t base_workforce_size,
+ const ProductionType::template_type_t template_type,
+ const Pop::pop_size_t base_workforce_size,
GoodDefinition::good_definition_map_t&& input_goods,
- GoodDefinition const* output_goods,
- fixed_point_t base_output_quantity,
+ GoodDefinition const* const output_good,
+ const fixed_point_t base_output_quantity,
std::vector<ProductionType::bonus_t>&& bonuses,
GoodDefinition::good_definition_map_t&& maintenance_requirements,
- bool is_coastal,
- bool is_farm,
- bool is_mine
+ const bool is_coastal,
+ const bool is_farm,
+ const bool is_mine
) {
if (identifier.empty()) {
Logger::error("Invalid production type identifier - empty!");
@@ -121,7 +123,7 @@ bool ProductionTypeManager::add_production_type(
return false;
}
- if (output_goods == nullptr) {
+ if (output_good == nullptr) {
Logger::error("Output good for production type ", identifier, " was null!");
return false;
}
@@ -167,13 +169,25 @@ bool ProductionTypeManager::add_production_type(
}
const bool ret = production_types.add_item({
- identifier, owner, std::move(jobs), template_type, base_workforce_size, std::move(input_goods), output_goods,
+ identifier, owner, std::move(jobs), template_type, base_workforce_size, std::move(input_goods), *output_good,
base_output_quantity, std::move(bonuses), std::move(maintenance_requirements), is_coastal, is_farm, is_mine
});
+
+ if (ret && (template_type == RGO)) {
+ ProductionType const& production_type = production_types.get_items().back();
+ ProductionType const*& current_rgo_pt = good_to_rgo_production_type[*output_good];
+ if (current_rgo_pt == nullptr || (is_farm && !current_rgo_pt->is_farm())) {
+ // first rgo pt or farms are preferred (over mines) in V2
+ current_rgo_pt = &production_type;
+ }
+ //else ignore, we already have an rgo pt
+ }
+
if (rgo_owner_sprite <= 0 && ret && template_type == RGO && owner.has_value() && owner->get_pop_type() != nullptr) {
/* Set rgo owner sprite to that of the first RGO owner we find. */
rgo_owner_sprite = owner->get_pop_type()->get_sprite();
}
+
return ret;
}
@@ -224,7 +238,10 @@ bool ProductionTypeManager::load_production_types_file(
}
)(parser.get_file_node());
+
/* Pass #3: actually load production types */
+ good_to_rgo_production_type.set_keys(&good_definition_manager.get_good_definitions());
+
reserve_more_production_types(expected_types);
ret &= expect_dictionary(
[this, &good_definition_manager, &pop_manager, &template_target_map, &template_node_map](
@@ -238,7 +255,7 @@ bool ProductionTypeManager::load_production_types_file(
std::optional<Job> owner;
std::vector<Job> jobs;
ProductionType::template_type_t template_type { FACTORY };
- GoodDefinition const* output_goods = nullptr;
+ GoodDefinition const* output_good = nullptr;
Pop::pop_size_t base_workforce_size = 0;
GoodDefinition::good_definition_map_t input_goods, maintenance_requirements;
fixed_point_t base_output_quantity = 0;
@@ -254,13 +271,18 @@ bool ProductionTypeManager::load_production_types_file(
auto parse_node = expect_dictionary_keys(
"template", ZERO_OR_ONE, success_callback, /* Already parsed using expect_key in Pass #1 above. */
"bonus", ZERO_OR_MORE, [&bonuses](ast::NodeCPtr bonus_node) -> bool {
- ConditionScript trigger { scope_t::STATE, scope_t::NO_SCOPE, scope_t::NO_SCOPE };
+ using enum scope_type_t;
+
+ ConditionScript trigger { STATE, NO_SCOPE, NO_SCOPE };
fixed_point_t bonus_value {};
+
const bool ret = expect_dictionary_keys(
"trigger", ONE_EXACTLY, trigger.expect_script(),
"value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(bonus_value))
)(bonus_node);
+
bonuses.emplace_back(std::move(trigger), bonus_value);
+
return ret;
},
"owner", ZERO_OR_ONE, _expect_job(good_definition_manager, pop_manager, move_variable_callback(owner)),
@@ -271,7 +293,7 @@ bool ProductionTypeManager::load_production_types_file(
"input_goods", ZERO_OR_ONE,
good_definition_manager.expect_good_definition_decimal_map(move_variable_callback(input_goods)),
"output_goods", ZERO_OR_ONE,
- good_definition_manager.expect_good_definition_identifier(assign_variable_callback_pointer(output_goods)),
+ good_definition_manager.expect_good_definition_identifier(assign_variable_callback_pointer(output_good)),
"value", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(base_output_quantity)),
"efficiency", ZERO_OR_ONE, good_definition_manager.expect_good_definition_decimal_map(
move_variable_callback(maintenance_requirements)
@@ -300,9 +322,10 @@ bool ProductionTypeManager::load_production_types_file(
ret &= parse_node(node);
ret &= add_production_type(
- key, owner, std::move(jobs), template_type, base_workforce_size, std::move(input_goods), output_goods,
+ key, owner, std::move(jobs), template_type, base_workforce_size, std::move(input_goods), output_good,
base_output_quantity, std::move(bonuses), std::move(maintenance_requirements), is_coastal, is_farm, is_mine
);
+
return ret;
}
)(parser.get_file_node());
diff --git a/src/openvic-simulation/economy/production/ProductionType.hpp b/src/openvic-simulation/economy/production/ProductionType.hpp
index 5394938..f9b1778 100644
--- a/src/openvic-simulation/economy/production/ProductionType.hpp
+++ b/src/openvic-simulation/economy/production/ProductionType.hpp
@@ -20,13 +20,13 @@ namespace OpenVic {
PopType const* PROPERTY(pop_type);
effect_t PROPERTY(effect_type);
fixed_point_t PROPERTY(effect_multiplier);
- fixed_point_t PROPERTY(desired_workforce_share);
+ fixed_point_t PROPERTY(amount);
Job(
PopType const* new_pop_type,
effect_t new_effect_type,
fixed_point_t new_effect_multiplier,
- fixed_point_t new_desired_workforce_share
+ fixed_point_t new_amount
);
public:
@@ -47,7 +47,7 @@ namespace OpenVic {
const Pop::pop_size_t PROPERTY(base_workforce_size);
GoodDefinition::good_definition_map_t PROPERTY(input_goods);
- GoodDefinition const* PROPERTY(output_goods);
+ GoodDefinition const& PROPERTY(output_good);
const fixed_point_t PROPERTY(base_output_quantity);
std::vector<bonus_t> PROPERTY(bonuses);
@@ -58,19 +58,19 @@ namespace OpenVic {
const bool PROPERTY_CUSTOM_PREFIX(mine, is);
ProductionType(
- std::string_view new_identifier,
- std::optional<Job> new_owner,
+ const std::string_view new_identifier,
+ const std::optional<Job> new_owner,
std::vector<Job>&& new_jobs,
- template_type_t new_template_type,
- Pop::pop_size_t new_base_workforce_size,
+ const template_type_t new_template_type,
+ const Pop::pop_size_t new_base_workforce_size,
GoodDefinition::good_definition_map_t&& new_input_goods,
- GoodDefinition const* new_output_goods,
- fixed_point_t new_base_output_quantity,
+ GoodDefinition const& new_output_good,
+ const fixed_point_t new_base_output_quantity,
std::vector<bonus_t>&& new_bonuses,
GoodDefinition::good_definition_map_t&& new_maintenance_requirements,
- bool new_is_coastal,
- bool new_is_farm,
- bool new_is_mine
+ const bool new_is_coastal,
+ const bool new_is_farm,
+ const bool new_is_mine
);
bool parse_scripts(DefinitionManager const& definition_manager);
@@ -83,6 +83,7 @@ namespace OpenVic {
private:
IdentifierRegistry<ProductionType> IDENTIFIER_REGISTRY(production_type);
PopType::sprite_t PROPERTY(rgo_owner_sprite);
+ IndexedMap<GoodDefinition, ProductionType const*> PROPERTY(good_to_rgo_production_type);
NodeTools::node_callback_t _expect_job(
GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager,
@@ -97,19 +98,19 @@ namespace OpenVic {
ProductionTypeManager();
bool add_production_type(
- std::string_view identifier,
+ const std::string_view identifier,
std::optional<Job> owner,
- std::vector<Job>&& employees,
- ProductionType::template_type_t template_type,
- Pop::pop_size_t workforce,
+ std::vector<Job>&& jobs,
+ const ProductionType::template_type_t template_type,
+ const Pop::pop_size_t base_workforce_size,
GoodDefinition::good_definition_map_t&& input_goods,
- GoodDefinition const* output_goods,
- fixed_point_t value,
+ GoodDefinition const* const output_good,
+ const fixed_point_t base_output_quantity,
std::vector<ProductionType::bonus_t>&& bonuses,
GoodDefinition::good_definition_map_t&& maintenance_requirements,
- bool coastal,
- bool farm,
- bool mine
+ const bool is_coastal,
+ const bool is_farm,
+ const bool is_mine
);
bool load_production_types_file(
diff --git a/src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp b/src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp
index 9bf6f49..70cb64d 100644
--- a/src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp
+++ b/src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp
@@ -1,21 +1,351 @@
#include "ResourceGatheringOperation.hpp"
+#include <vector>
+
+#include "openvic-simulation/economy/production/Employee.hpp"
+#include "openvic-simulation/economy/production/ProductionType.hpp"
+#include "openvic-simulation/map/ProvinceInstance.hpp"
+#include "openvic-simulation/map/State.hpp"
+#include "openvic-simulation/modifier/ModifierEffectCache.hpp"
+#include "openvic-simulation/pop/Pop.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+#include "openvic-simulation/utility/Logger.hpp"
+
using namespace OpenVic;
ResourceGatheringOperation::ResourceGatheringOperation(
- ProductionType const& new_production_type,
+ ProductionType const* new_production_type_nullable,
fixed_point_t new_size_multiplier,
fixed_point_t new_revenue_yesterday,
fixed_point_t new_output_quantity_yesterday,
fixed_point_t new_unsold_quantity_yesterday,
- ordered_map<Pop*, Pop::pop_size_t>&& new_employees
-) : production_type { new_production_type },
+ std::vector<Employee>&& new_employees,
+ decltype(employee_count_per_type_cache)::keys_t const& pop_type_keys
+) : production_type_nullable { new_production_type_nullable },
revenue_yesterday { new_revenue_yesterday },
output_quantity_yesterday { new_output_quantity_yesterday },
unsold_quantity_yesterday { new_unsold_quantity_yesterday },
size_multiplier { new_size_multiplier },
- employees { std::move(new_employees) } {}
+ employees { std::move(new_employees) },
+ max_employee_count_cache { 0 },
+ total_employees_count_cache { 0 },
+ total_paid_employees_count_cache { 0 },
+ total_owner_income_cache { },
+ total_employee_income_cache { },
+ employee_count_per_type_cache { &pop_type_keys }
+{ }
-ResourceGatheringOperation::ResourceGatheringOperation(
- ProductionType const& new_production_type, fixed_point_t new_size_multiplier
-) : ResourceGatheringOperation { new_production_type, new_size_multiplier, 0, 0, 0, {} } {}
+ResourceGatheringOperation::ResourceGatheringOperation(decltype(employee_count_per_type_cache)::keys_t const& pop_type_keys) : ResourceGatheringOperation {
+ nullptr, fixed_point_t::_0(),
+ fixed_point_t::_0(), fixed_point_t::_0(),
+ fixed_point_t::_0(), {}, pop_type_keys
+} {}
+
+void ResourceGatheringOperation::initialise_for_new_game(ProvinceInstance& location, ModifierEffectCache const& modifier_effect_cache) {
+ if (production_type_nullable == nullptr) {
+ output_quantity_yesterday = 0;
+ revenue_yesterday = 0;
+ return;
+ }
+
+ ProductionType const& production_type = *production_type_nullable;
+ const fixed_point_t size_modifier = calculate_size_modifier(location, modifier_effect_cache);
+ const Pop::pop_size_t total_worker_count_in_province = update_size_and_return_total_worker_count(location, modifier_effect_cache, size_modifier);
+ hire(location, total_worker_count_in_province);
+ Pop::pop_size_t total_owner_count_in_state_cache = 0;
+ std::vector<Pop*> owner_pops_cache {};
+ output_quantity_yesterday = produce(location, owner_pops_cache, total_owner_count_in_state_cache, modifier_effect_cache, size_modifier);
+ revenue_yesterday = output_quantity_yesterday * production_type.get_output_good().get_base_price(); //TODO sell on market
+ pay_employees(location, revenue_yesterday, total_worker_count_in_province, owner_pops_cache, total_owner_count_in_state_cache);
+}
+
+Pop::pop_size_t ResourceGatheringOperation::update_size_and_return_total_worker_count(
+ ProvinceInstance& location,
+ ModifierEffectCache const& modifier_effect_cache,
+ const fixed_point_t size_modifier
+) {
+ if (production_type_nullable == nullptr) {
+ size_multiplier = fixed_point_t::_0();
+ max_employee_count_cache = fixed_point_t::_0();
+ return fixed_point_t::_0();
+ }
+
+ Pop::pop_size_t total_worker_count_in_province = 0; //not counting equivalents
+ ProductionType const& production_type = *production_type_nullable;
+ std::vector<Job> const& jobs = production_type.get_jobs();
+ //can't use pop_type_distribution as it is not filled correctly yet (possibly due to equivalent pop type conversion)
+ for (Pop const& pop : location.get_pops()){
+ PopType const* pop_type = pop.get_type();
+ for(Job const& job : jobs) {
+ if (job.get_pop_type() == pop_type) {
+ total_worker_count_in_province += pop.get_size();
+ break;
+ }
+ }
+ }
+
+ fixed_point_t base_size_modifier = fixed_point_t::_1();
+ if (production_type.is_farm()) {
+ base_size_modifier += location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_farm_rgo_size_local());
+ }
+ if (production_type.is_mine()) {
+ base_size_modifier += location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_mine_rgo_size_local());
+ }
+
+ const fixed_point_t base_workforce_size = production_type.get_base_workforce_size();
+ if (base_size_modifier == fixed_point_t::_0()) {
+ size_multiplier = 0;
+ } else {
+ size_multiplier = ((total_worker_count_in_province / (base_size_modifier * base_workforce_size)).ceil() * fixed_point_t::_1_50()).floor();
+ }
+ max_employee_count_cache = (size_modifier * size_multiplier * base_workforce_size).floor();
+ return total_worker_count_in_province;
+}
+
+fixed_point_t ResourceGatheringOperation::calculate_size_modifier(ProvinceInstance const& location, ModifierEffectCache const& modifier_effect_cache) const {
+ if (production_type_nullable == nullptr) {
+ return fixed_point_t::_1();
+ }
+
+ ProductionType const& production_type = *production_type_nullable;
+
+ fixed_point_t size_modifier = fixed_point_t::_1();
+ if (production_type.is_farm()) {
+ size_modifier += location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_farm_rgo_size_global())
+ + location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_farm_rgo_size_local());
+ }
+ if (production_type.is_mine()) {
+ size_modifier += location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_mine_rgo_size_global())
+ + location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_mine_rgo_size_local());
+ }
+ auto const& good_effects = modifier_effect_cache.get_good_effects()[production_type.get_output_good()];
+ size_modifier += location.get_modifier_effect_value_nullcheck(good_effects.get_rgo_size());
+ return size_modifier > fixed_point_t::_0() ? size_modifier : fixed_point_t::_0();
+}
+
+void ResourceGatheringOperation::hire(ProvinceInstance& location, Pop::pop_size_t available_worker_count) {
+ total_employees_count_cache = 0;
+ total_paid_employees_count_cache=0;
+ if (production_type_nullable == nullptr) {
+ employees.clear();
+ employee_count_per_type_cache.fill(fixed_point_t::_0());
+ return;
+ }
+
+ ProductionType const& production_type = *production_type_nullable;
+ if (max_employee_count_cache <= 0) { return; }
+ if (available_worker_count <= 0) { return; }
+
+ fixed_point_t proportion_to_hire;
+ if (max_employee_count_cache >= available_worker_count) {
+ //hire everyone
+ proportion_to_hire = fixed_point_t::_1();
+ } else {
+ //hire all pops proportionally
+ const fixed_point_t max_worker_count_real = max_employee_count_cache, available_worker_count_real = available_worker_count;
+ proportion_to_hire = max_worker_count_real / available_worker_count_real;
+ }
+
+ std::vector<Job> const& jobs = production_type.get_jobs();
+ for (Pop& pop : location.get_mutable_pops()){
+ PopType const& pop_type = *pop.get_type();
+ for(Job const& job : jobs) {
+ if (job.get_pop_type() == &pop_type) {
+ const Pop::pop_size_t pop_size_to_hire = static_cast<Pop::pop_size_t>((proportion_to_hire * pop.get_size()).floor());
+ employee_count_per_type_cache[pop_type] += pop_size_to_hire;
+ employees.emplace_back(pop, pop_size_to_hire);
+ total_employees_count_cache += pop_size_to_hire;
+ if (!pop_type.get_is_slave()) {
+ total_paid_employees_count_cache += pop_size_to_hire;
+ }
+ break;
+ }
+ }
+ }
+}
+
+fixed_point_t ResourceGatheringOperation::produce(
+ ProvinceInstance& location,
+ std::vector<Pop*>& owner_pops_cache,
+ Pop::pop_size_t& total_owner_count_in_state_cache,
+ ModifierEffectCache const& modifier_effect_cache,
+ const fixed_point_t size_modifier
+) {
+ if (size_modifier == fixed_point_t::_0()){
+ return fixed_point_t::_0();
+ }
+
+ total_owner_count_in_state_cache = 0;
+ owner_pops_cache = {};
+ if (production_type_nullable == nullptr || max_employee_count_cache <= 0) {
+ return fixed_point_t::_0();
+ }
+
+ ProductionType const& production_type = *production_type_nullable;
+ fixed_point_t throughput_multiplier = fixed_point_t::_1();
+ fixed_point_t output_multilpier = fixed_point_t::_1();
+
+ std::optional<Job> const& owner = production_type.get_owner();
+ if (owner.has_value()) {
+ Job const& owner_job = owner.value();
+ PopType const* owner_job_pop_type_nullable = owner_job.get_pop_type();
+ if (owner_job_pop_type_nullable == nullptr) {
+ Logger::error("Owner job for ", production_type.get_identifier(), " has nullptr as pop_type.");
+ return fixed_point_t::_0();
+ }
+ PopType const& owner_pop_type = *owner_job_pop_type_nullable;
+ State const* state_nullable = location.get_state();
+ if (state_nullable == nullptr) {
+ Logger::error("Province ", location.get_identifier(), " has no state.");
+ return fixed_point_t::_0();
+ }
+ State const& state = *state_nullable;
+ Pop::pop_size_t state_population = 0; //state.get_total_population() is not filled yet
+ std::vector<ProvinceInstance*> const& provinces_in_state = state.get_provinces();
+ for (ProvinceInstance* const province_nullable : provinces_in_state) {
+ if (province_nullable == nullptr) {
+ Logger::error("State ", state.get_identifier(), " has nullptr in provinces.");
+ return fixed_point_t::_0();
+ }
+ ProvinceInstance& province = *province_nullable;
+ for (Pop& pop : province.get_mutable_pops()){
+ state_population += pop.get_size();
+ if (&owner_pop_type == pop.get_type()) {
+ owner_pops_cache.push_back(&pop);
+ total_owner_count_in_state_cache += pop.get_size();
+ }
+ }
+ }
+
+ if (total_owner_count_in_state_cache > 0) {
+ switch (owner_job.get_effect_type()) {
+ case Job::effect_t::OUTPUT:
+ output_multilpier += owner_job.get_effect_multiplier() * total_owner_count_in_state_cache / state_population;
+ break;
+ case Job::effect_t::THROUGHPUT:
+ throughput_multiplier += owner_job.get_effect_multiplier() * total_owner_count_in_state_cache / state_population;
+ break;
+ default:
+ Logger::error("Invalid job effect in RGO ",production_type.get_identifier());
+ break;
+ }
+ }
+ }
+
+ throughput_multiplier += location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_rgo_throughput())
+ +location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_local_rgo_throughput());
+ output_multilpier += location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_rgo_output())
+ +location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_local_rgo_output());
+
+ if (production_type.is_farm()) {
+ throughput_multiplier += location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_farm_rgo_throughput_global());
+ output_multilpier += location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_farm_rgo_output_global())
+ + location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_farm_rgo_output_local());
+ }
+ if (production_type.is_mine()) {
+ throughput_multiplier += location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_mine_rgo_throughput_global());
+ output_multilpier += location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_mine_rgo_output_global())
+ + location.get_modifier_effect_value_nullcheck(modifier_effect_cache.get_mine_rgo_output_local());
+ }
+ auto const& good_effects = modifier_effect_cache.get_good_effects()[production_type.get_output_good()];
+ throughput_multiplier += location.get_modifier_effect_value_nullcheck(good_effects.get_rgo_goods_throughput());
+ output_multilpier += location.get_modifier_effect_value_nullcheck(good_effects.get_rgo_goods_output());
+
+ fixed_point_t throughput_from_workers = fixed_point_t::_0();
+ fixed_point_t output_from_workers = fixed_point_t::_1();
+ for (PopType const& pop_type : *employee_count_per_type_cache.get_keys()) {
+ const Pop::pop_size_t employees_of_type = employee_count_per_type_cache[pop_type];
+
+ for(Job const& job : production_type.get_jobs()) {
+ if (job.get_pop_type() != &pop_type) {
+ continue;
+ }
+
+ fixed_point_t const effect_multiplier = job.get_effect_multiplier();
+ fixed_point_t relative_to_workforce = fixed_point_t::parse(employees_of_type) / fixed_point_t::parse(max_employee_count_cache);
+ fixed_point_t const amount = job.get_amount();
+ if (effect_multiplier != fixed_point_t::_1() && relative_to_workforce > amount) {
+ relative_to_workforce = amount;
+ }
+ switch (job.get_effect_type()) {
+ case Job::effect_t::OUTPUT:
+ output_from_workers += effect_multiplier * relative_to_workforce;
+ break;
+ case Job::effect_t::THROUGHPUT:
+ throughput_from_workers += effect_multiplier * relative_to_workforce;
+ break;
+ default:
+ Logger::error("Invalid job effect in RGO ",production_type.get_identifier());
+ break;
+ }
+ }
+ }
+
+ //if province is overseas multiply by (1 + overseas penalty)
+
+ return production_type.get_base_output_quantity()
+ * size_modifier * size_multiplier
+ * throughput_multiplier * throughput_from_workers
+ * output_multilpier * output_from_workers;
+}
+
+void ResourceGatheringOperation::pay_employees(
+ ProvinceInstance& location,
+ const fixed_point_t revenue,
+ const Pop::pop_size_t total_worker_count_in_province,
+ std::vector<Pop*>& owner_pops_cache,
+ const Pop::pop_size_t total_owner_count_in_state_cache
+) {
+ total_owner_income_cache = 0;
+ total_employee_income_cache = 0;
+ if (production_type_nullable == nullptr || revenue <= 0 || total_worker_count_in_province <= 0) {
+ if (revenue < 0) { Logger::error("Negative revenue for province ", location.get_identifier()); }
+ if (total_worker_count_in_province < 0) { Logger::error("Negative total worker count for province ", location.get_identifier()); }
+ return;
+ }
+
+ ProductionType const& production_type = *production_type_nullable;
+
+ fixed_point_t revenue_left = revenue;
+ if (total_owner_count_in_state_cache > 0) {
+ Job const& owner_job = production_type.get_owner().value();
+ PopType const* owner_job_pop_type_nullable = owner_job.get_pop_type();
+
+ fixed_point_t owner_share = (fixed_point_t::_2() * total_owner_count_in_state_cache / total_worker_count_in_province);
+ constexpr fixed_point_t upper_limit = fixed_point_t::_0_50();
+ if (owner_share > upper_limit) {
+ owner_share = upper_limit;
+ }
+
+ for(Pop* owner_pop_nullable : owner_pops_cache) {
+ Pop& owner_pop = *owner_pop_nullable;
+ const fixed_point_t income_for_this_pop = revenue_left * owner_share * owner_pop.get_size() / total_owner_count_in_state_cache;
+ owner_pop.add_rgo_owner_income(income_for_this_pop);
+ total_owner_income_cache += income_for_this_pop;
+ }
+ revenue_left *= (fixed_point_t::_1() - owner_share);
+ }
+
+ if (total_paid_employees_count_cache > 0) {
+ for (Employee& employee : employees) {
+ Pop& employee_pop = employee.pop;
+ PopType const* employee_pop_type_nullable = employee_pop.get_type();
+ if (employee_pop_type_nullable == nullptr) {
+ Logger::error("employee has nullptr pop_type.");
+ return;
+ }
+ PopType const& employee_pop_type = *employee_pop_type_nullable;
+ if (employee_pop_type.get_is_slave()) {
+ continue;
+ }
+
+ const Pop::pop_size_t employee_size = employee.get_size();
+ const fixed_point_t income_for_this_pop = revenue_left * employee_size / total_paid_employees_count_cache;
+ employee_pop.add_rgo_worker_income(income_for_this_pop);
+ total_employee_income_cache += income_for_this_pop;
+ }
+ } else {
+ //scenario slaves only
+ //Money is removed from system in Victoria 2.
+ }
+} \ No newline at end of file
diff --git a/src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp b/src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp
index d71c569..a15e87d 100644
--- a/src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp
+++ b/src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp
@@ -1,25 +1,64 @@
#pragma once
+#include "openvic-simulation/economy/production/Employee.hpp"
#include "openvic-simulation/economy/production/ProductionType.hpp"
+#include "openvic-simulation/modifier/ModifierEffectCache.hpp"
+#include "openvic-simulation/pop/Pop.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
- class ResourceGatheringOperation final {
+ struct ResourceGatheringOperation {
private:
- ProductionType const& PROPERTY(production_type);
+ ProductionType const* PROPERTY_RW(production_type_nullable);
fixed_point_t PROPERTY(revenue_yesterday);
fixed_point_t PROPERTY(output_quantity_yesterday);
fixed_point_t PROPERTY(unsold_quantity_yesterday);
- fixed_point_t PROPERTY(size_multiplier);
- ordered_map<Pop*, Pop::pop_size_t> PROPERTY(employees);
+ fixed_point_t PROPERTY_RW(size_multiplier);
+ std::vector<Employee> PROPERTY(employees);
+ Pop::pop_size_t PROPERTY(max_employee_count_cache);
+ Pop::pop_size_t PROPERTY(total_employees_count_cache);
+ Pop::pop_size_t PROPERTY(total_paid_employees_count_cache);
+ fixed_point_t PROPERTY(total_owner_income_cache);
+ fixed_point_t PROPERTY(total_employee_income_cache);
+ IndexedMap<PopType, Pop::pop_size_t> PROPERTY(employee_count_per_type_cache);
+
+ Pop::pop_size_t update_size_and_return_total_worker_count(
+ ProvinceInstance& location,
+ ModifierEffectCache const& modifier_effect_cache,
+ const fixed_point_t size_modifier
+ );
+ fixed_point_t calculate_size_modifier(ProvinceInstance const& location, ModifierEffectCache const& modifier_effect_cache) const;
+ void hire(ProvinceInstance& location, const Pop::pop_size_t available_worker_count);
+ fixed_point_t produce(
+ ProvinceInstance& location,
+ std::vector<Pop*>& owner_pops_cache,
+ Pop::pop_size_t& total_owner_count_in_state_cache,
+ ModifierEffectCache const& modifier_effect_cache,
+ const fixed_point_t size_modifier
+ );
+ void pay_employees(
+ ProvinceInstance& location,
+ const fixed_point_t revenue,
+ const Pop::pop_size_t total_worker_count_in_province,
+ std::vector<Pop*>& owner_pops_cache,
+ const Pop::pop_size_t total_owner_count_in_state_cache
+ );
public:
ResourceGatheringOperation(
- ProductionType const& new_production_type, fixed_point_t new_size_multiplier, fixed_point_t new_revenue_yesterday,
- fixed_point_t new_output_quantity_yesterday, fixed_point_t new_unsold_quantity_yesterday,
- ordered_map<Pop*, Pop::pop_size_t>&& new_employees
+ ProductionType const* new_production_type_nullable,
+ fixed_point_t new_size_multiplier,
+ fixed_point_t new_revenue_yesterday,
+ fixed_point_t new_output_quantity_yesterday,
+ fixed_point_t new_unsold_quantity_yesterday,
+ std::vector<Employee>&& new_employees,
+ decltype(employee_count_per_type_cache)::keys_t const& pop_type_keys
);
- ResourceGatheringOperation(ProductionType const& new_production_type, fixed_point_t new_size_multiplier);
+ ResourceGatheringOperation(decltype(employee_count_per_type_cache)::keys_t const& pop_type_keys);
+ constexpr bool is_valid() const {
+ return production_type_nullable != nullptr;
+ }
+ void initialise_for_new_game(ProvinceInstance& location, ModifierEffectCache const& modifier_effect_cache);
};
}
diff --git a/src/openvic-simulation/history/CountryHistory.cpp b/src/openvic-simulation/history/CountryHistory.cpp
index cd51e19..c5d8977 100644
--- a/src/openvic-simulation/history/CountryHistory.cpp
+++ b/src/openvic-simulation/history/CountryHistory.cpp
@@ -35,6 +35,33 @@ bool CountryHistoryMap::_load_history_entry(
InventionManager const& invention_manager = definition_manager.get_research_manager().get_invention_manager();
DecisionManager const& decision_manager = definition_manager.get_decision_manager();
+ const auto accepted_culture_instruction = [&entry](bool add) {
+ return [&entry, add](Culture const& culture) -> bool {
+ const auto it = entry.accepted_cultures.find(&culture);
+ if (it == entry.accepted_cultures.end()) {
+ // No current culture instruction
+ entry.accepted_cultures.emplace(&culture, add);
+ return true;
+ } else if (it->second == add) {
+ // Desired culture instruction already exists
+ Logger::warning(
+ "Duplicate attempt to ", add ? "add" : "remove", " accepted culture ", culture.get_identifier(),
+ " ", add ? "to" : "from", " country history of ", entry.get_country()
+ );
+ return true;
+ } else {
+ // Opposite culture instruction exists
+ entry.accepted_cultures.erase(it);
+ Logger::warning(
+ "Attempted to ", add ? "add" : "remove", " accepted culture ", culture.get_identifier(),
+ " ", add ? "to" : "from", " country history of ", entry.get_country(),
+ " after previously ", add ? "removing" : "adding", " it"
+ );
+ return true;
+ }
+ };
+ };
+
return expect_dictionary_keys_and_default(
[this, &definition_manager, &dataloader, &deployment_manager, &issue_manager, &technology_manager, &invention_manager,
&country_definition_manager, &entry](std::string_view key, ast::NodeCPtr value) -> bool {
@@ -84,7 +111,8 @@ bool CountryHistoryMap::_load_history_entry(
),
"primary_culture", ZERO_OR_ONE,
culture_manager.expect_culture_identifier(assign_variable_callback_pointer_opt(entry.primary_culture)),
- "culture", ZERO_OR_MORE, culture_manager.expect_culture_identifier(set_callback_pointer(entry.accepted_cultures)),
+ "culture", ZERO_OR_MORE, culture_manager.expect_culture_identifier(accepted_culture_instruction(true)),
+ "remove_culture", ZERO_OR_MORE, culture_manager.expect_culture_identifier(accepted_culture_instruction(false)),
"religion", ZERO_OR_ONE, definition_manager.get_pop_manager().get_religion_manager().expect_religion_identifier(
assign_variable_callback_pointer_opt(entry.religion)
),
diff --git a/src/openvic-simulation/history/CountryHistory.hpp b/src/openvic-simulation/history/CountryHistory.hpp
index 04de653..7ee9d6b 100644
--- a/src/openvic-simulation/history/CountryHistory.hpp
+++ b/src/openvic-simulation/history/CountryHistory.hpp
@@ -33,7 +33,7 @@ namespace OpenVic {
CountryDefinition const& PROPERTY(country);
std::optional<Culture const*> PROPERTY(primary_culture);
- ordered_set<Culture const*> PROPERTY(accepted_cultures);
+ ordered_map<Culture const*, bool> PROPERTY(accepted_cultures);
std::optional<Religion const*> PROPERTY(religion);
std::optional<CountryParty const*> PROPERTY(ruling_party);
std::optional<Date> PROPERTY(last_election);
diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp
index ef8793b..bc92f48 100644
--- a/src/openvic-simulation/history/ProvinceHistory.cpp
+++ b/src/openvic-simulation/history/ProvinceHistory.cpp
@@ -1,7 +1,9 @@
#include "ProvinceHistory.hpp"
#include "openvic-simulation/DefinitionManager.hpp"
+#include "openvic-simulation/economy/GoodDefinition.hpp"
#include "openvic-simulation/map/ProvinceDefinition.hpp"
+#include "openvic-simulation/utility/Logger.hpp"
using namespace OpenVic;
using namespace OpenVic::NodeTools;
@@ -50,13 +52,16 @@ bool ProvinceHistoryMap::_load_history_entry(
Logger::warning(
"Attempted to ", add ? "add" : "remove", " core of country ", country.get_identifier(),
" ", add ? "to" : "from", " province history of ", entry.get_province(),
- " after previously ", add ? "adding" : "removing", " it"
+ " after previously ", add ? "removing" : "adding", " it"
);
return true;
}
};
};
+ constexpr bool allow_empty_true = true;
+ constexpr bool do_warn = true;
+
return expect_dictionary_keys_and_default(
[this, &definition_manager, &building_type_manager, &entry](
std::string_view key, ast::NodeCPtr value) -> bool {
@@ -98,7 +103,20 @@ bool ProvinceHistoryMap::_load_history_entry(
expect_identifier(expect_mapped_string(colony_status_map, assign_variable_callback(entry.colonial))),
"is_slave", ZERO_OR_ONE, expect_bool(assign_variable_callback(entry.slave)),
"trade_goods", ZERO_OR_ONE,
- good_definition_manager.expect_good_definition_identifier(assign_variable_callback_pointer_opt(entry.rgo)),
+ good_definition_manager.expect_good_definition_identifier_or_string(
+ [&definition_manager, &entry](GoodDefinition const& rgo_good) ->bool {
+ entry.rgo_production_type_nullable = definition_manager.get_economy_manager().get_production_type_manager().get_good_to_rgo_production_type()[rgo_good];
+ if (entry.rgo_production_type_nullable == nullptr) {
+ Logger::error(entry.province.get_identifier(), " has trade_goods ", rgo_good.get_identifier(), " which has no rgo production type defined.");
+ //we expect the good to have an rgo production type
+ //Victoria 2 treats this as null, but clearly the modder wanted there to be a good
+ return false;
+ }
+ return true;
+ },
+ allow_empty_true, //could be explicitly setting trade_goods to null
+ do_warn //could be typo in good identifier
+ ),
"life_rating", ZERO_OR_ONE, expect_uint<ProvinceInstance::life_rating_t>(assign_variable_callback(entry.life_rating)),
"terrain", ZERO_OR_ONE, terrain_type_manager.expect_terrain_type_identifier(
assign_variable_callback_pointer_opt(entry.terrain_type)
diff --git a/src/openvic-simulation/history/ProvinceHistory.hpp b/src/openvic-simulation/history/ProvinceHistory.hpp
index 99ea2af..f44fc81 100644
--- a/src/openvic-simulation/history/ProvinceHistory.hpp
+++ b/src/openvic-simulation/history/ProvinceHistory.hpp
@@ -32,7 +32,7 @@ namespace OpenVic {
std::optional<ProvinceInstance::colony_status_t> PROPERTY(colonial);
std::optional<bool> PROPERTY(slave);
ordered_map<CountryDefinition const*, bool> PROPERTY(cores);
- std::optional<GoodDefinition const*> PROPERTY(rgo);
+ std::optional<ProductionType const*> PROPERTY(rgo_production_type_nullable);
std::optional<ProvinceInstance::life_rating_t> PROPERTY(life_rating);
std::optional<TerrainType const*> PROPERTY(terrain_type);
ordered_map<BuildingType const*, BuildingType::level_t> PROPERTY(province_buildings);
diff --git a/src/openvic-simulation/map/Crime.cpp b/src/openvic-simulation/map/Crime.cpp
index fb521ad..ce0c623 100644
--- a/src/openvic-simulation/map/Crime.cpp
+++ b/src/openvic-simulation/map/Crime.cpp
@@ -1,5 +1,8 @@
#include "Crime.hpp"
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/modifier/ModifierManager.hpp"
+
using namespace OpenVic;
using namespace OpenVic::NodeTools;
@@ -27,17 +30,22 @@ bool CrimeManager::load_crime_modifiers(ModifierManager const& modifier_manager,
const bool ret = expect_dictionary_reserve_length(
crime_modifiers,
[this, &modifier_manager](std::string_view key, ast::NodeCPtr value) -> bool {
+ using enum scope_type_t;
+
ModifierValue modifier_value;
IconModifier::icon_t icon = 0;
- ConditionScript trigger { scope_t::PROVINCE, scope_t::NO_SCOPE, scope_t::NO_SCOPE };
+ ConditionScript trigger { PROVINCE, NO_SCOPE, NO_SCOPE };
bool default_active = false;
- bool ret = modifier_manager.expect_modifier_value_and_keys(
- move_variable_callback(modifier_value),
+
+ bool ret = NodeTools::expect_dictionary_keys_and_default(
+ modifier_manager.expect_base_province_modifier(modifier_value),
"icon", ZERO_OR_ONE, expect_uint(assign_variable_callback(icon)),
"trigger", ONE_EXACTLY, trigger.expect_script(),
"active", ZERO_OR_ONE, expect_bool(assign_variable_callback(default_active))
)(value);
+
ret &= add_crime_modifier(key, std::move(modifier_value), icon, std::move(trigger), default_active);
+
return ret;
}
)(root);
diff --git a/src/openvic-simulation/map/MapDefinition.cpp b/src/openvic-simulation/map/MapDefinition.cpp
index 488133c..faea838 100644
--- a/src/openvic-simulation/map/MapDefinition.cpp
+++ b/src/openvic-simulation/map/MapDefinition.cpp
@@ -1,9 +1,13 @@
#include "MapDefinition.hpp"
+#include <cstdint>
#include <vector>
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/modifier/ModifierManager.hpp"
#include "openvic-simulation/types/Colour.hpp"
#include "openvic-simulation/types/OrderedContainers.hpp"
+#include "openvic-simulation/types/Vector.hpp"
#include "openvic-simulation/utility/BMP.hpp"
#include "openvic-simulation/utility/Logger.hpp"
@@ -12,6 +16,9 @@ using namespace OpenVic::NodeTools;
MapDefinition::MapDefinition() : dims { 0, 0 }, max_provinces { ProvinceDefinition::MAX_INDEX } {}
+RiverSegment::RiverSegment(uint8_t new_size, std::vector<ivec2_t>&& new_points)
+ : size { new_size }, points { std::move(new_points) } {}
+
bool MapDefinition::add_province_definition(std::string_view identifier, colour_t colour) {
if (province_definitions.size() >= max_provinces) {
Logger::error(
@@ -490,7 +497,7 @@ static constexpr colour_t colour_at(uint8_t const* colour_data, int32_t idx) {
return { colour_data[idx + 2], colour_data[idx + 1], colour_data[idx] };
}
-bool MapDefinition::load_map_images(fs::path const& province_path, fs::path const& terrain_path, bool detailed_errors) {
+bool MapDefinition::load_map_images(fs::path const& province_path, fs::path const& terrain_path, fs::path const& rivers_path, bool detailed_errors) {
if (!province_definitions_are_locked()) {
Logger::error("Province index image cannot be generated until after provinces are locked!");
return false;
@@ -500,12 +507,14 @@ bool MapDefinition::load_map_images(fs::path const& province_path, fs::path cons
return false;
}
+ static constexpr uint16_t expected_province_bpp = 24;
+ static constexpr uint16_t expected_terrain_rivers_bpp = 8;
+
BMP province_bmp;
if (!(province_bmp.open(province_path) && province_bmp.read_header() && province_bmp.read_pixel_data())) {
Logger::error("Failed to read BMP for compatibility mode province image: ", province_path);
return false;
}
- static constexpr uint16_t expected_province_bpp = 24;
if (province_bmp.get_bits_per_pixel() != expected_province_bpp) {
Logger::error(
"Invalid province BMP bits per pixel: ", province_bmp.get_bits_per_pixel(), " (expected ", expected_province_bpp,
@@ -519,18 +528,33 @@ bool MapDefinition::load_map_images(fs::path const& province_path, fs::path cons
Logger::error("Failed to read BMP for compatibility mode terrain image: ", terrain_path);
return false;
}
- static constexpr uint16_t expected_terrain_bpp = 8;
- if (terrain_bmp.get_bits_per_pixel() != expected_terrain_bpp) {
+ if (terrain_bmp.get_bits_per_pixel() != expected_terrain_rivers_bpp) {
Logger::error(
- "Invalid terrain BMP bits per pixel: ", terrain_bmp.get_bits_per_pixel(), " (expected ", expected_terrain_bpp, ")"
+ "Invalid terrain BMP bits per pixel: ", terrain_bmp.get_bits_per_pixel(), " (expected ", expected_terrain_rivers_bpp, ")"
);
return false;
}
- if (province_bmp.get_width() != terrain_bmp.get_width() || province_bmp.get_height() != terrain_bmp.get_height()) {
+ BMP rivers_bmp;
+ if (!(rivers_bmp.open(rivers_path) && rivers_bmp.read_header() && rivers_bmp.read_pixel_data())) {
+ Logger::error("Failed to read BMP for compatibility mode river image: ", rivers_path);
+ return false;
+ }
+ if (rivers_bmp.get_bits_per_pixel() != expected_terrain_rivers_bpp) {
Logger::error(
- "Mismatched province and terrain BMP dims: ", province_bmp.get_width(), "x", province_bmp.get_height(), " vs ",
- terrain_bmp.get_width(), "x", terrain_bmp.get_height()
+ "Invalid rivers BMP bits per pixel: ", rivers_bmp.get_bits_per_pixel(), " (expected ", expected_terrain_rivers_bpp, ")"
+ );
+ return false;
+ }
+
+ if (province_bmp.get_width() != terrain_bmp.get_width() ||
+ province_bmp.get_height() != terrain_bmp.get_height() ||
+ province_bmp.get_width() != rivers_bmp.get_width() ||
+ province_bmp.get_height() != rivers_bmp.get_height()
+ ) {
+ Logger::error(
+ "Mismatched map BMP dims: provinces:", province_bmp.get_width(), "x", province_bmp.get_height(), ", terrain: ",
+ terrain_bmp.get_width(), "x", terrain_bmp.get_height(), ", rivers: ", rivers_bmp.get_width(), "x", rivers_bmp.get_height()
);
return false;
}
@@ -637,6 +661,196 @@ bool MapDefinition::load_map_images(fs::path const& province_path, fs::path cons
Logger::warning("Province image is missing ", missing, " province colours");
}
+ // Constants in the River BMP Palette
+ static constexpr uint8_t START_COLOUR = 0;
+ static constexpr uint8_t MERGE_COLOUR = 1;
+ static constexpr uint8_t RIVER_SIZE_1 = 2;
+ static constexpr uint8_t RIVER_SIZE_2 = 3;
+ static constexpr uint8_t RIVER_SIZE_3 = 4;
+ static constexpr uint8_t RIVER_SIZE_4 = 5;
+ static constexpr uint8_t RIVER_SIZE_5 = 6;
+ static constexpr uint8_t RIVER_SIZE_6 = 7;
+ static constexpr uint8_t RIVER_SIZE_7 = 8;
+ static constexpr uint8_t RIVER_SIZE_8 = 9;
+ static constexpr uint8_t RIVER_SIZE_9 = 10;
+ static constexpr uint8_t RIVER_SIZE_10 = 11;
+
+ uint8_t const* river_data = rivers_bmp.get_pixel_data().data();
+
+ /** Generating River Segments
+ 1. check pixels up, right, down, and left from last_segment_end for a colour <12
+ 2. add first point
+ 3. set size of segment based on color value at first point
+ 4. loop, adding adjacent points until the colour value changes (to make sure we don't backtrack, last_segment_direction provides a pixel to automatically ignore)
+ last_segment_direction:
+ 0 -> start, ignore nothing
+ 1 -> ignore up
+ 2 -> ignore down
+ 3 -> ignore left
+ 4 -> ignore right
+ 5. if the colour value changes to MERGE_COLOUR, add the point & finish the segment
+ 6. if there is no further point, finish the segment
+ 7. if the colour value changes to a different river size (>1 && <12), recursively call this function on the next segment
+ */
+ const std::function<void(ivec2_t, uint8_t, river_t&)> next_segment = [&river_data, &rivers_bmp, &next_segment](ivec2_t last_segment_end, uint8_t last_segment_direction, river_t& river) {
+ size_t idx = last_segment_end.x + last_segment_end.y * rivers_bmp.get_width();
+
+ std::vector<ivec2_t> points;
+ uint8_t direction = 0;
+
+ // check pixel above
+ if (last_segment_end.y > 0 && last_segment_direction != 1) { // check for bounds & ignore direction
+ if (river_data[idx - rivers_bmp.get_width()] < 12) {
+ points.push_back({ last_segment_end.x, last_segment_end.y - 1 });
+ direction = 2;
+ }
+ }
+ // check pixel to right
+ if (last_segment_end.x < rivers_bmp.get_width() - 1 && last_segment_direction != 4) {
+ if (river_data[idx + 1] < 12) {
+ points.push_back({ last_segment_end.x + 1, last_segment_end.y });
+ direction = 3;
+ }
+ }
+ // check pixel below
+ if (last_segment_end.y < rivers_bmp.get_height() - 1 && last_segment_direction != 2) {
+ if (river_data[idx + rivers_bmp.get_width()] < 12) {
+ points.push_back({ last_segment_end.x, last_segment_end.y + 1 });
+ direction = 1;
+ }
+ }
+ // check pixel to left
+ if (last_segment_end.x > 0 && last_segment_direction != 3) {
+ if (river_data[idx - 1] < 12) {
+ points.push_back({ last_segment_end.x - 1, last_segment_end.y });
+ direction = 4;
+ }
+ }
+
+ if (points.empty()) {
+ Logger::error("River analysis failed: single-pixel river @ (", last_segment_end.x, ", ", last_segment_end.y, ").");
+ return;
+ }
+ uint8_t size = river_data[points.front().x + points.front().y * rivers_bmp.get_width()] - 1; // size of river from 1 - 10 determined by colour
+
+ bool river_complete = false;
+ ivec2_t new_point;
+
+ size_t limit = 0; // stops infinite loop
+
+ while (true) {
+ limit++;
+ if (limit == 4096) {
+ Logger::error("River segment starting at (", points.front().x, ", ", points.front().y, ") is longer than limit 4096, check for misplaced pixels or other definition errors!");
+ river_complete = true;
+ break;
+ }
+
+ idx = points.back().x + points.back().y * rivers_bmp.get_width();
+
+ ivec2_t merge_location;
+ bool merge = false;
+
+ // check pixel above
+ if (points.back().y > 0 && direction != 1) { // check for bounds & ignore direction
+ if (river_data[idx - rivers_bmp.get_width()] == size + 1) { // now checking if size changes too
+ points.push_back({ points.back().x, points.back().y - 1 });
+ direction = 2;
+ continue;
+ } else if (river_data[idx - rivers_bmp.get_width()] == MERGE_COLOUR) { // check for merge node
+ merge_location = { points.back().x, points.back().y - 1 };
+ merge = true;
+ } else if (river_data[idx - rivers_bmp.get_width()] > 1 && river_data[idx - rivers_bmp.get_width()] < 12) { // new segment
+ new_point = { points.back().x, points.back().y - 1 };
+ direction = 2;
+ break;
+ }
+ }
+ // check pixel to right
+ if (points.back().x < rivers_bmp.get_width() - 1 && direction != 4) {
+ if (river_data[idx + 1] == size + 1) {
+ points.push_back({ points.back().x + 1, points.back().y });
+ direction = 3;
+ continue;
+ } else if (river_data[idx + 1] == MERGE_COLOUR) {
+ merge_location = { points.back().x + 1, points.back().y };
+ merge = true;
+ } else if (river_data[idx + 1] > 1 && river_data[idx + 1] < 12) { // new segment
+ new_point = { points.back().x + 1, points.back().y };
+ direction = 3;
+ break;
+ }
+ }
+ // check pixel below
+ if (points.back().y < rivers_bmp.get_height() - 1 && direction != 2) {
+ if (river_data[idx + rivers_bmp.get_width()] == size + 1) {
+ points.push_back({ points.back().x, points.back().y + 1 });
+ direction = 1;
+ continue;
+ } else if (river_data[idx + rivers_bmp.get_width()] == MERGE_COLOUR) {
+ merge_location = { points.back().x, points.back().y + 1 };
+ merge = true;
+ } else if (river_data[idx + rivers_bmp.get_width()] > 1 && river_data[idx + rivers_bmp.get_width()] < 12) { // new segment
+ new_point = { points.back().x, points.back().y + 1 };
+ direction = 1;
+ break;
+ }
+ }
+ // check pixel to left
+ if (points.back().x > 0 && direction != 3) {
+ if (river_data[idx - 1] == size + 1) {
+ points.push_back({ points.back().x - 1, points.back().y });
+ direction = 4;
+ continue;
+ } else if (river_data[idx - 1] == MERGE_COLOUR) {
+ merge_location = { points.back().x - 1, points.back().y };
+ merge = true;
+ } else if (river_data[idx - 1] > 1 && river_data[idx - 1] < 12) { // new segment
+ new_point = { points.back().x - 1, points.back().y };
+ direction = 4;
+ break;
+ }
+ }
+
+ // no further points
+ if (merge) points.push_back(merge_location);
+ river_complete = true;
+ break;
+ }
+
+ // save memory & simplify by storing only start, corner, and end points.
+ const auto is_corner_point = [](ivec2_t previous, ivec2_t current, ivec2_t next) {
+ return ((current.x - previous.x) * (next.y - current.y)) != ((current.y - previous.y) * (next.x - current.x)); // slope is fun
+ };
+ std::vector<ivec2_t> simplified_points;
+ simplified_points.push_back(points.front()); // add starting point
+ for (int i = 1; i < points.size()-1; ++i) {
+ if (is_corner_point(points[i-1], points[i], points[i+1])) { // add corner points
+ simplified_points.push_back(points[i]);
+ }
+ }
+ simplified_points.push_back(points.back());
+
+ // add segment then recursively call if neeeded
+ river.push_back({ size, std::move(simplified_points) });
+ if (river_complete) return;
+ next_segment(new_point, direction, river);
+ };
+
+ // find every river source and then run the segment algorithm.
+ for (int y = 0; y < rivers_bmp.get_height(); ++y) {
+ for (int x = 0; x < rivers_bmp.get_width(); ++x) {
+ if (river_data[x + y * rivers_bmp.get_width()] == START_COLOUR) { // start of a river
+ river_t river;
+
+ next_segment({ x, y }, 0, river);
+
+ rivers.push_back(std::move(river));
+ }
+ }
+ }
+ Logger::info("Generated ", rivers.size(), " rivers.");
+
return ret;
}
@@ -743,7 +957,11 @@ bool MapDefinition::load_climate_file(ModifierManager const& modifier_manager, a
Climate* cur_climate = climates.get_item_by_identifier(identifier);
if (cur_climate == nullptr) {
ModifierValue values;
- ret &= modifier_manager.expect_modifier_value(move_variable_callback(values))(node);
+
+ ret &= NodeTools::expect_dictionary(
+ modifier_manager.expect_base_province_modifier(values)
+ )(node);
+
ret &= climates.add_item({ identifier, std::move(values), Modifier::modifier_type_t::CLIMATE });
} else {
ret &= expect_list_reserve_length(*cur_climate, expect_province_definition_identifier(
@@ -787,6 +1005,7 @@ bool MapDefinition::load_continent_file(ModifierManager const& modifier_manager,
bool ret = expect_dictionary_reserve_length(
continents,
[this, &modifier_manager](std::string_view identifier, ast::NodeCPtr node) -> bool {
+
if (identifier.empty()) {
Logger::error("Invalid continent identifier - empty!");
return false;
@@ -794,7 +1013,8 @@ bool MapDefinition::load_continent_file(ModifierManager const& modifier_manager,
ModifierValue values;
std::vector<ProvinceDefinition const*> prov_list;
- bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(values),
+ bool ret = NodeTools::expect_dictionary_keys_and_default(
+ modifier_manager.expect_base_province_modifier(values),
"provinces", ONE_EXACTLY, expect_list_reserve_length(prov_list, expect_province_definition_identifier(
[&prov_list](ProvinceDefinition const& province) -> bool {
if (province.continent == nullptr) {
diff --git a/src/openvic-simulation/map/MapDefinition.hpp b/src/openvic-simulation/map/MapDefinition.hpp
index 9ec4367..e835da8 100644
--- a/src/openvic-simulation/map/MapDefinition.hpp
+++ b/src/openvic-simulation/map/MapDefinition.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <cstdint>
#include <filesystem>
#include <string_view>
#include <vector>
@@ -20,6 +21,19 @@ namespace OpenVic {
struct BuildingTypeManager;
struct ModifierManager;
+ struct RiverSegment {
+ friend struct MapDefinition;
+
+ private:
+ const uint8_t PROPERTY(size);
+ std::vector<ivec2_t> PROPERTY(points);
+
+ RiverSegment(uint8_t new_size, std::vector<ivec2_t>&& new_points);
+
+ public:
+ RiverSegment(RiverSegment&&) = default;
+ };
+
/* REQUIREMENTS:
* MAP-4
*/
@@ -35,6 +49,7 @@ namespace OpenVic {
private:
using colour_index_map_t = ordered_map<colour_t, ProvinceDefinition::index_t>;
+ using river_t = std::vector<RiverSegment>;
IdentifierRegistry<ProvinceDefinition> IDENTIFIER_REGISTRY_CUSTOM_INDEX_OFFSET(province_definition, 1);
IdentifierRegistry<Region> IDENTIFIER_REGISTRY(region);
@@ -43,6 +58,7 @@ namespace OpenVic {
ProvinceSet water_provinces;
TerrainTypeManager PROPERTY_REF(terrain_type_manager);
+ std::vector<river_t> PROPERTY(rivers); // TODO: calculate provinces affected by crossing
ivec2_t PROPERTY(dims);
std::vector<shape_pixel_t> PROPERTY(province_shape_image);
colour_index_map_t colour_index_map;
@@ -104,7 +120,7 @@ namespace OpenVic {
bool load_province_positions(BuildingTypeManager const& building_type_manager, ast::NodeCPtr root);
static bool load_region_colours(ast::NodeCPtr root, std::vector<colour_t>& colours);
bool load_region_file(ast::NodeCPtr root, std::vector<colour_t> const& colours);
- bool load_map_images(fs::path const& province_path, fs::path const& terrain_path, bool detailed_errors);
+ bool load_map_images(fs::path const& province_path, fs::path const& terrain_path, fs::path const& rivers_path, bool detailed_errors);
bool generate_and_load_province_adjacencies(std::vector<ovdl::csv::LineObject> const& additional_adjacencies);
bool load_climate_file(ModifierManager const& modifier_manager, ast::NodeCPtr root);
bool load_continent_file(ModifierManager const& modifier_manager, ast::NodeCPtr root);
diff --git a/src/openvic-simulation/map/MapInstance.cpp b/src/openvic-simulation/map/MapInstance.cpp
index 0ce8cea..4a4a1e5 100644
--- a/src/openvic-simulation/map/MapInstance.cpp
+++ b/src/openvic-simulation/map/MapInstance.cpp
@@ -93,24 +93,34 @@ bool MapInstance::apply_history_to_provinces(
if (history_map != nullptr) {
ProvinceHistoryEntry const* pop_history_entry = nullptr;
+ ProductionType const* rgo_production_type_nullable = nullptr;
for (auto const& [entry_date, entry] : history_map->get_entries()) {
- if (entry_date > date) {
- break;
+ if(entry_date > date) {
+ if(pop_history_entry != nullptr) {
+ break;
+ }
+ } else {
+ province.apply_history_to_province(*entry, country_manager);
+ std::optional<ProductionType const*> const& rgo_production_type_nullable_optional = entry->get_rgo_production_type_nullable();
+ if (rgo_production_type_nullable_optional.has_value()) {
+ rgo_production_type_nullable = rgo_production_type_nullable_optional.value();
+ }
}
- province.apply_history_to_province(*entry, country_manager);
-
if (!entry->get_pops().empty()) {
pop_history_entry = entry.get();
}
}
- if (pop_history_entry != nullptr) {
+ if (pop_history_entry == nullptr) {
+ Logger::warning("No pop history entry for province ",province.get_identifier(), " for date ", date.to_string());
+ } else {
province.add_pop_vec(pop_history_entry->get_pops());
-
province.setup_pop_test_values(issue_manager);
}
+
+ ret&=province.set_rgo_production_type_nullable(rgo_production_type_nullable);
}
}
}
@@ -118,6 +128,12 @@ bool MapInstance::apply_history_to_provinces(
return ret;
}
+void MapInstance::update_modifier_sums(Date today, StaticModifierCache const& static_modifier_cache) {
+ for (ProvinceInstance& province : province_instances.get_items()) {
+ province.update_modifier_sum(today, static_modifier_cache);
+ }
+}
+
void MapInstance::update_gamestate(Date today, DefineManager const& define_manager) {
for (ProvinceInstance& province : province_instances.get_items()) {
province.update_gamestate(today, define_manager);
@@ -144,3 +160,9 @@ void MapInstance::tick(Date today) {
province.tick(today);
}
}
+
+void MapInstance::initialise_for_new_game(ModifierEffectCache const& modifier_effect_cache){
+ for (ProvinceInstance& province : province_instances.get_items()) {
+ province.initialise_for_new_game(modifier_effect_cache);
+ }
+} \ No newline at end of file
diff --git a/src/openvic-simulation/map/MapInstance.hpp b/src/openvic-simulation/map/MapInstance.hpp
index 99c13d3..a580c55 100644
--- a/src/openvic-simulation/map/MapInstance.hpp
+++ b/src/openvic-simulation/map/MapInstance.hpp
@@ -52,7 +52,9 @@ namespace OpenVic {
IssueManager const& issue_manager
);
+ void update_modifier_sums(Date today, StaticModifierCache const& static_modifier_cache);
void update_gamestate(Date today, DefineManager const& define_manager);
void tick(Date today);
+ void initialise_for_new_game(ModifierEffectCache const& modifier_effect_cache);
};
}
diff --git a/src/openvic-simulation/map/Mapmode.cpp b/src/openvic-simulation/map/Mapmode.cpp
index f951a05..88eb2eb 100644
--- a/src/openvic-simulation/map/Mapmode.cpp
+++ b/src/openvic-simulation/map/Mapmode.cpp
@@ -179,7 +179,7 @@ bool MapmodeManager::setup_mapmodes() {
"mapmode_terrain_type", get_colour_mapmode(&ProvinceInstance::get_terrain_type)
},
{
- "mapmode_rgo", get_colour_mapmode(&ProvinceInstance::get_rgo)
+ "mapmode_rgo", get_colour_mapmode(&ProvinceInstance::get_rgo_good)
},
{
"mapmode_infrastructure",
diff --git a/src/openvic-simulation/map/ProvinceDefinition.cpp b/src/openvic-simulation/map/ProvinceDefinition.cpp
index 14828e8..60c8d6c 100644
--- a/src/openvic-simulation/map/ProvinceDefinition.cpp
+++ b/src/openvic-simulation/map/ProvinceDefinition.cpp
@@ -89,7 +89,7 @@ bool ProvinceDefinition::load_positions(
port = true;
port_adjacent_province = province;
} else {
- /* Expected provinces with invalid ports: 39, 296, 1047, 1406, 2044 */
+ /* Expected provinces with invalid ports: 39, 296, 1047, 1406, 2044 */
Logger::warning(
"Invalid port for province ", get_identifier(), ": facing province ", province,
" which has: water = ", province->is_water(), ", adjacent = ", is_adjacent_to(province)
diff --git a/src/openvic-simulation/map/ProvinceInstance.cpp b/src/openvic-simulation/map/ProvinceInstance.cpp
index 06b3f1e..b3d2df3 100644
--- a/src/openvic-simulation/map/ProvinceInstance.cpp
+++ b/src/openvic-simulation/map/ProvinceInstance.cpp
@@ -1,11 +1,19 @@
#include "ProvinceInstance.hpp"
#include "openvic-simulation/country/CountryInstance.hpp"
+#include "openvic-simulation/defines/Define.hpp"
+#include "openvic-simulation/economy/production/ProductionType.hpp"
+#include "openvic-simulation/economy/production/ResourceGatheringOperation.hpp"
#include "openvic-simulation/history/ProvinceHistory.hpp"
+#include "openvic-simulation/map/Crime.hpp"
#include "openvic-simulation/map/ProvinceDefinition.hpp"
+#include "openvic-simulation/map/Region.hpp"
+#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"
+#include "openvic-simulation/pop/Pop.hpp"
+#include "openvic-simulation/utility/Logger.hpp"
using namespace OpenVic;
@@ -21,9 +29,11 @@ ProvinceInstance::ProvinceInstance(
owner { nullptr },
controller { nullptr },
cores {},
+ modifier_sum {},
+ event_modifiers {},
slave { false },
crime { nullptr },
- rgo { nullptr },
+ rgo { pop_type_keys },
buildings { "buildings", false },
armies {},
navies {},
@@ -35,6 +45,25 @@ ProvinceInstance::ProvinceInstance(
religion_distribution {},
max_supported_regiments { 0 } {}
+GoodDefinition const* ProvinceInstance::get_rgo_good() const {
+ if (!rgo.is_valid()) { return nullptr; }
+ return &(rgo.get_production_type_nullable()->get_output_good());
+}
+bool ProvinceInstance::set_rgo_production_type_nullable(ProductionType const* rgo_production_type_nullable) {
+ bool is_valid_operation = true;
+ if (rgo_production_type_nullable != nullptr) {
+ ProductionType const& rgo_production_type = *rgo_production_type_nullable;
+ if (rgo_production_type.get_template_type() != ProductionType::template_type_t::RGO) {
+ Logger::error("Tried setting province ", get_identifier(), " rgo to ", rgo_production_type.get_identifier(), " which is not of template_type RGO.");
+ is_valid_operation = false;
+ }
+ is_valid_operation&=convert_rgo_worker_pops_to_equivalent(rgo_production_type);
+ }
+
+ rgo.set_production_type_nullable(rgo_production_type_nullable);
+ return is_valid_operation;
+}
+
bool ProvinceInstance::set_owner(CountryInstance* new_owner) {
bool ret = true;
@@ -155,12 +184,14 @@ void ProvinceInstance::_update_pops(DefineManager const& define_manager) {
max_supported_regiments = 0;
+ MilitaryDefines const& military_defines = define_manager.get_military_defines();
+
using enum colony_status_t;
const fixed_point_t pop_size_per_regiment_multiplier =
- colony_status == PROTECTORATE ? define_manager.get_pop_size_per_regiment_protectorate_multiplier()
- : colony_status == COLONY ? define_manager.get_pop_size_per_regiment_colony_multiplier()
- : is_owner_core() ? fixed_point_t::_1() : define_manager.get_pop_size_per_regiment_non_core_multiplier();
+ colony_status == PROTECTORATE ? military_defines.get_pop_size_per_regiment_protectorate_multiplier()
+ : colony_status == COLONY ? military_defines.get_pop_size_per_regiment_colony_multiplier()
+ : is_owner_core() ? fixed_point_t::_1() : military_defines.get_pop_size_per_regiment_non_core_multiplier();
for (Pop& pop : pops) {
pop.update_gamestate(define_manager, owner, pop_size_per_regiment_multiplier);
@@ -170,7 +201,7 @@ void ProvinceInstance::_update_pops(DefineManager const& define_manager) {
average_consciousness += pop.get_consciousness();
average_militancy += pop.get_militancy();
- pop_type_distribution[pop.get_type()] += pop.get_size();
+ pop_type_distribution[*pop.get_type()] += pop.get_size();
ideology_distribution += pop.get_ideologies();
culture_distribution[&pop.get_culture()] += pop.get_size();
religion_distribution[&pop.get_religion()] += pop.get_size();
@@ -185,6 +216,144 @@ void ProvinceInstance::_update_pops(DefineManager const& define_manager) {
}
}
+void ProvinceInstance::update_modifier_sum(Date today, StaticModifierCache const& static_modifier_cache) {
+ // Update sum of direct province modifiers
+ modifier_sum.clear();
+
+ const ModifierSum::modifier_source_t province_source { this };
+
+ // Erase expired event modifiers and add non-expired ones to the sum
+ std::erase_if(event_modifiers, [this, today, &province_source](ModifierInstance const& modifier) -> bool {
+ if (today <= modifier.get_expiry_date()) {
+ modifier_sum.add_modifier(*modifier.get_modifier(), province_source);
+ return false;
+ } else {
+ return true;
+ }
+ });
+
+ // Add static modifiers
+ if (is_owner_core()) {
+ modifier_sum.add_modifier(static_modifier_cache.get_core(), province_source);
+ }
+ if (province_definition.is_water()) {
+ modifier_sum.add_modifier(static_modifier_cache.get_sea_zone(), province_source);
+ } else {
+ modifier_sum.add_modifier(static_modifier_cache.get_land_province(), province_source);
+
+ if (province_definition.is_coastal()) {
+ modifier_sum.add_modifier(static_modifier_cache.get_coastal(), province_source);
+ } else {
+ modifier_sum.add_modifier(static_modifier_cache.get_non_coastal(), province_source);
+ }
+
+ // TODO - overseas, blockaded, no_adjacent_controlled, has_siege, occupied, nationalism, infrastructure
+ }
+
+ for (BuildingInstance const& building : buildings.get_items()) {
+ modifier_sum.add_modifier(building.get_building_type(), province_source);
+ }
+
+ modifier_sum.add_modifier_nullcheck(crime, province_source);
+
+ modifier_sum.add_modifier_nullcheck(province_definition.get_continent(), province_source);
+
+ 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 (controller != nullptr) {
+ controller->contribute_province_modifier_sum(modifier_sum);
+ }
+ }
+}
+
+void ProvinceInstance::contribute_country_modifier_sum(ModifierSum const& owner_modifier_sum) {
+ modifier_sum.add_modifier_sum_exclude_source(owner_modifier_sum, this);
+}
+
+fixed_point_t ProvinceInstance::get_modifier_effect_value(ModifierEffect const& effect) const {
+ if constexpr (ADD_OWNER_CONTRIBUTION) {
+ return modifier_sum.get_effect(effect);
+ } else {
+ using enum ModifierEffect::target_t;
+
+ if (owner != nullptr) {
+ 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 {
+ // 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 {
+ 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<ModifierSum::modifier_entry_t>& contributions
+) const {
+ if constexpr (ADD_OWNER_CONTRIBUTION) {
+ modifier_sum.push_contributing_modifiers(effect, contributions);
+ } else {
+ using enum ModifierEffect::target_t;
+
+ if (owner != nullptr) {
+ 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 {
+ // 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<ModifierSum::modifier_entry_t> ProvinceInstance::get_contributing_modifiers(ModifierEffect const& effect) const {
+ if constexpr (ADD_OWNER_CONTRIBUTION) {
+ return modifier_sum.get_contributing_modifiers(effect);
+ } else {
+ std::vector<ModifierSum::modifier_entry_t> contributions;
+
+ push_contributing_modifiers(effect, contributions);
+
+ return contributions;
+ }
+}
+
+bool ProvinceInstance::convert_rgo_worker_pops_to_equivalent(ProductionType const& production_type) {
+ bool is_valid_operation = true;
+ std::vector<Job> const& jobs = production_type.get_jobs();
+ for(Pop& pop : pops) {
+ for(Job const& job : jobs) {
+ PopType const* const job_pop_type = job.get_pop_type();
+ PopType const* old_pop_type = pop.get_type();
+ if (job_pop_type != old_pop_type) {
+ PopType const* const equivalent = old_pop_type->get_equivalent();
+ if (job_pop_type == equivalent) {
+ is_valid_operation&=pop.convert_to_equivalent();
+ }
+ }
+ }
+ }
+ return is_valid_operation;
+}
+
void ProvinceInstance::update_gamestate(Date today, DefineManager const& define_manager) {
for (BuildingInstance& building : buildings.get_items()) {
building.update_gamestate(today);
@@ -279,7 +448,7 @@ bool ProvinceInstance::apply_history_to_province(ProvinceHistoryEntry const& ent
ret &= remove_core(country_manager.get_country_instance_from_definition(*country));
}
}
- set_optional(rgo, entry.get_rgo());
+
set_optional(life_rating, entry.get_life_rating());
set_optional(terrain_type, entry.get_terrain_type());
for (auto const& [building, level] : entry.get_province_buildings()) {
@@ -299,8 +468,16 @@ bool ProvinceInstance::apply_history_to_province(ProvinceHistoryEntry const& ent
return ret;
}
+void ProvinceInstance::initialise_for_new_game(ModifierEffectCache const& modifier_effect_cache) {
+ rgo.initialise_for_new_game(*this, modifier_effect_cache);
+}
+
void ProvinceInstance::setup_pop_test_values(IssueManager const& issue_manager) {
for (Pop& pop : pops) {
pop.setup_pop_test_values(issue_manager);
}
}
+
+plf::colony<Pop>& ProvinceInstance::get_mutable_pops() {
+ return pops;
+} \ No newline at end of file
diff --git a/src/openvic-simulation/map/ProvinceInstance.hpp b/src/openvic-simulation/map/ProvinceInstance.hpp
index fa0be98..ba800a9 100644
--- a/src/openvic-simulation/map/ProvinceInstance.hpp
+++ b/src/openvic-simulation/map/ProvinceInstance.hpp
@@ -3,10 +3,12 @@
#include <plf_colony.h>
#include "openvic-simulation/economy/BuildingInstance.hpp"
+#include "openvic-simulation/economy/production/ProductionType.hpp"
+#include "openvic-simulation/economy/production/ResourceGatheringOperation.hpp"
#include "openvic-simulation/military/UnitInstance.hpp"
#include "openvic-simulation/military/UnitType.hpp"
+#include "openvic-simulation/modifier/ModifierSum.hpp"
#include "openvic-simulation/pop/Pop.hpp"
-#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
#include "openvic-simulation/types/HasIdentifier.hpp"
#include "openvic-simulation/types/OrderedContainers.hpp"
@@ -21,6 +23,7 @@ namespace OpenVic {
struct Ideology;
struct Culture;
struct Religion;
+ struct StaticModifierCache;
struct BuildingTypeManager;
struct ProvinceHistoryEntry;
struct IssueManager;
@@ -68,10 +71,18 @@ namespace OpenVic {
CountryInstance* PROPERTY(controller);
ordered_set<CountryInstance*> PROPERTY(cores);
+ 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<ModifierInstance> PROPERTY(event_modifiers);
+
bool PROPERTY(slave);
Crime const* PROPERTY_RW(crime);
- // TODO - change this into a factory-like structure
- GoodDefinition const* PROPERTY(rgo);
+ ResourceGatheringOperation PROPERTY(rgo);
IdentifierRegistry<BuildingInstance> IDENTIFIER_REGISTRY(building);
ordered_set<ArmyInstance*> PROPERTY(armies);
ordered_set<NavyInstance*> PROPERTY(navies);
@@ -84,7 +95,7 @@ namespace OpenVic {
fixed_point_t PROPERTY(average_literacy);
fixed_point_t PROPERTY(average_consciousness);
fixed_point_t PROPERTY(average_militancy);
- IndexedMap<PopType, fixed_point_t> PROPERTY(pop_type_distribution);
+ IndexedMap<PopType, Pop::pop_size_t> PROPERTY(pop_type_distribution);
IndexedMap<Ideology, fixed_point_t> PROPERTY(ideology_distribution);
fixed_point_map_t<Culture const*> PROPERTY(culture_distribution);
fixed_point_map_t<Religion const*> PROPERTY(religion_distribution);
@@ -97,6 +108,7 @@ namespace OpenVic {
void _add_pop(Pop&& pop);
void _update_pops(DefineManager const& define_manager);
+ bool convert_rgo_worker_pops_to_equivalent(ProductionType const& production_type);
public:
ProvinceInstance(ProvinceInstance&&) = default;
@@ -112,6 +124,9 @@ namespace OpenVic {
return controller;
}
+ GoodDefinition const* get_rgo_good() const;
+ bool set_rgo_production_type_nullable(ProductionType const* rgo_production_type_nullable);
+
bool set_owner(CountryInstance* new_owner);
bool set_controller(CountryInstance* new_controller);
bool add_core(CountryInstance& new_core);
@@ -124,6 +139,15 @@ namespace OpenVic {
bool add_pop_vec(std::vector<PopBase> const& pop_vec);
size_t get_pop_count() const;
+ void update_modifier_sum(Date today, StaticModifierCache const& static_modifier_cache);
+ 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<ModifierSum::modifier_entry_t>& contributions
+ ) const;
+ std::vector<ModifierSum::modifier_entry_t> get_contributing_modifiers(ModifierEffect const& effect) const;
+
void update_gamestate(Date today, DefineManager const& define_manager);
void tick(Date today);
@@ -135,6 +159,9 @@ namespace OpenVic {
bool setup(BuildingTypeManager const& building_type_manager);
bool apply_history_to_province(ProvinceHistoryEntry const& entry, CountryInstanceManager& country_manager);
+ void initialise_for_new_game(ModifierEffectCache const& modifier_effect_cache);
+
void setup_pop_test_values(IssueManager const& issue_manager);
+ plf::colony<Pop>& get_mutable_pops();
};
}
diff --git a/src/openvic-simulation/map/State.cpp b/src/openvic-simulation/map/State.cpp
index 020b6f1..31ea05f 100644
--- a/src/openvic-simulation/map/State.cpp
+++ b/src/openvic-simulation/map/State.cpp
@@ -5,6 +5,7 @@
#include "openvic-simulation/map/MapInstance.hpp"
#include "openvic-simulation/map/ProvinceInstance.hpp"
#include "openvic-simulation/map/Region.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
#include "openvic-simulation/utility/StringUtils.hpp"
using namespace OpenVic;
@@ -65,10 +66,19 @@ void State::update_gamestate() {
const int32_t potential_workforce_in_state = 0; // sum of worker pops, regardless of employment
const int32_t potential_employment_in_state = 0; // sum of (factory level * production method base_workforce_size)
- industrial_power = total_factory_levels_in_state * std::clamp(
- (fixed_point_t { potential_workforce_in_state } / 100).floor() * 400 / potential_employment_in_state,
- fixed_point_t::_0_20(), fixed_point_t::_4()
- );
+ fixed_point_t workforce_scalar;
+ constexpr fixed_point_t min_workforce_scalar = fixed_point_t::_0_20();
+ constexpr fixed_point_t max_workforce_scalar = fixed_point_t::_4();
+ if (potential_employment_in_state <= 0) {
+ workforce_scalar = min_workforce_scalar;
+ } else {
+ workforce_scalar = std::clamp(
+ (fixed_point_t { potential_workforce_in_state } / 100).floor() * 400 / potential_employment_in_state,
+ min_workforce_scalar, max_workforce_scalar
+ );
+ }
+
+ industrial_power = total_factory_levels_in_state * workforce_scalar;
}
/* Whether two provinces in the same region should be grouped into the same state or not.
diff --git a/src/openvic-simulation/map/State.hpp b/src/openvic-simulation/map/State.hpp
index 596206a..a39eea6 100644
--- a/src/openvic-simulation/map/State.hpp
+++ b/src/openvic-simulation/map/State.hpp
@@ -29,7 +29,7 @@ namespace OpenVic {
fixed_point_t PROPERTY(average_literacy);
fixed_point_t PROPERTY(average_consciousness);
fixed_point_t PROPERTY(average_militancy);
- IndexedMap<PopType, fixed_point_t> PROPERTY(pop_type_distribution);
+ IndexedMap<PopType, Pop::pop_size_t> PROPERTY(pop_type_distribution);
fixed_point_t PROPERTY(industrial_power);
diff --git a/src/openvic-simulation/map/TerrainType.cpp b/src/openvic-simulation/map/TerrainType.cpp
index b4cc430..011a3c3 100644
--- a/src/openvic-simulation/map/TerrainType.cpp
+++ b/src/openvic-simulation/map/TerrainType.cpp
@@ -1,5 +1,8 @@
#include "TerrainType.hpp"
+#include <string_view>
+
+#include "openvic-simulation/modifier/ModifierManager.hpp"
#include "openvic-simulation/types/Colour.hpp"
using namespace OpenVic;
@@ -16,6 +19,38 @@ TerrainTypeMapping::TerrainTypeMapping(
) : HasIdentifier { new_identifier }, type { new_type }, terrain_indices { std::move(new_terrain_indicies) },
priority { new_priority }, has_texture { new_has_texture } {}
+bool TerrainTypeManager::generate_modifiers(ModifierManager& modifier_manager) const {
+ using enum ModifierEffect::format_t;
+ IndexedMap<TerrainType, ModifierEffectCache::unit_terrain_effects_t>& unit_terrain_effects =
+ modifier_manager.modifier_effect_cache.unit_terrain_effects;
+
+ unit_terrain_effects.set_keys(&get_terrain_types());
+
+ constexpr bool has_no_effect = true;
+ bool ret = true;
+ for (TerrainType const& terrain_type : get_terrain_types()) {
+ const std::string_view identifier = terrain_type.get_identifier();
+ ModifierEffectCache::unit_terrain_effects_t& this_unit_terrain_effects = unit_terrain_effects[terrain_type];
+ ret &= modifier_manager.register_unit_terrain_modifier_effect(
+ this_unit_terrain_effects.attack, ModifierManager::get_flat_identifier("attack", identifier), true,
+ PROPORTION_DECIMAL, "UA_ATTACK", has_no_effect
+ );
+ ret &= modifier_manager.register_unit_terrain_modifier_effect(
+ this_unit_terrain_effects.defence, ModifierManager::get_flat_identifier("defence", identifier), true,
+ PROPORTION_DECIMAL, "UA_DEFENCE", has_no_effect
+ );
+ ret &= modifier_manager.register_unit_terrain_modifier_effect(
+ this_unit_terrain_effects.attrition, ModifierManager::get_flat_identifier("attrition", identifier), false,
+ RAW_DECIMAL, "UA_ATTRITION", has_no_effect
+ );
+ ret &= modifier_manager.register_unit_terrain_modifier_effect(
+ this_unit_terrain_effects.movement, ModifierManager::get_flat_identifier("movement", identifier), true,
+ PROPORTION_DECIMAL, "UA_MOVEMENT"
+ );
+ }
+ return ret;
+}
+
bool TerrainTypeManager::add_terrain_type(
std::string_view identifier, colour_t colour, ModifierValue&& values, bool is_water
) {
@@ -74,11 +109,15 @@ node_callback_t TerrainTypeManager::_load_terrain_type_categories(ModifierManage
ModifierValue values;
colour_t colour = colour_t::null();
bool is_water = false;
- bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(values),
+
+ bool ret = NodeTools::expect_dictionary_keys_and_default(
+ modifier_manager.expect_terrain_modifier(values),
"color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)),
"is_water", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_water))
)(type_node);
+
ret &= add_terrain_type(type_key, colour, std::move(values), is_water);
+
return ret;
}
)(root);
diff --git a/src/openvic-simulation/map/TerrainType.hpp b/src/openvic-simulation/map/TerrainType.hpp
index 3a88610..b15e650 100644
--- a/src/openvic-simulation/map/TerrainType.hpp
+++ b/src/openvic-simulation/map/TerrainType.hpp
@@ -67,5 +67,6 @@ namespace OpenVic {
TerrainTypeMapping::index_t get_terrain_texture_limit() const;
bool load_terrain_types(ModifierManager const& modifier_manager, ast::NodeCPtr root);
+ bool generate_modifiers(ModifierManager& modifier_manager) const;
};
}
diff --git a/src/openvic-simulation/military/Deployment.cpp b/src/openvic-simulation/military/Deployment.cpp
index bd176be..27cd124 100644
--- a/src/openvic-simulation/military/Deployment.cpp
+++ b/src/openvic-simulation/military/Deployment.cpp
@@ -144,7 +144,7 @@ bool DeploymentManager::load_oob_file(
return false;
}
- army_regiments.push_back({regiment_name, *regiment_type, regiment_home});
+ army_regiments.push_back({ regiment_name, *regiment_type, regiment_home });
return ret;
},
diff --git a/src/openvic-simulation/military/LeaderTrait.cpp b/src/openvic-simulation/military/LeaderTrait.cpp
index da7331a..e00deec 100644
--- a/src/openvic-simulation/military/LeaderTrait.cpp
+++ b/src/openvic-simulation/military/LeaderTrait.cpp
@@ -1,5 +1,8 @@
#include "LeaderTrait.hpp"
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/modifier/ModifierManager.hpp"
+
using namespace OpenVic;
using namespace OpenVic::NodeTools;
@@ -30,17 +33,14 @@ bool LeaderTraitManager::load_leader_traits_file(ModifierManager const& modifier
return expect_dictionary_reserve_length(
leader_traits,
[this, &modifier_manager, type](std::string_view trait_identifier, ast::NodeCPtr value) -> bool {
- static const string_set_t allowed_modifiers = {
- "attack", "defence", "morale", "organisation", "reconnaissance",
- "speed", "attrition", "experience", "reliability"
- };
-
ModifierValue modifiers;
- bool ret = modifier_manager.expect_whitelisted_modifier_value(
- move_variable_callback(modifiers), allowed_modifiers
+
+ bool ret = NodeTools::expect_dictionary(
+ modifier_manager.expect_leader_modifier(modifiers)
)(value);
ret &= add_leader_trait(trait_identifier, type, std::move(modifiers));
+
return ret;
}
);
diff --git a/src/openvic-simulation/military/UnitType.cpp b/src/openvic-simulation/military/UnitType.cpp
index 71bc5c3..c185154 100644
--- a/src/openvic-simulation/military/UnitType.cpp
+++ b/src/openvic-simulation/military/UnitType.cpp
@@ -1,7 +1,9 @@
#include "UnitType.hpp"
#include "openvic-simulation/country/CountryInstance.hpp"
+#include "openvic-simulation/dataloader/NodeTools.hpp"
#include "openvic-simulation/map/TerrainType.hpp"
+#include "openvic-simulation/modifier/ModifierManager.hpp"
using namespace OpenVic;
using namespace OpenVic::NodeTools;
@@ -28,8 +30,17 @@ UnitType::UnitType(
build_time { unit_args.build_time },
build_cost { std::move(unit_args.build_cost) },
supply_consumption { unit_args.supply_consumption },
- supply_cost { std::move(unit_args.supply_cost) },
- terrain_modifiers { std::move(unit_args.terrain_modifiers) } {}
+ supply_cost { std::move(unit_args.supply_cost) } {
+
+ using enum Modifier::modifier_type_t;
+
+ for (auto [terrain, modifier_value] : mutable_iterator(unit_args.terrain_modifier_values)) {
+ terrain_modifiers.emplace(terrain, Modifier {
+ StringUtils::append_string_views(new_identifier, " ", terrain->get_identifier()), std::move(modifier_value),
+ UNIT_TERRAIN
+ });
+ }
+}
bool UnitTypeBranched<LAND>::allowed_cultures_check_culture_in_country(
allowed_cultures_t allowed_cultures, Culture const& culture, CountryInstance const& country
@@ -105,8 +116,8 @@ static bool _check_shared_parameters(std::string_view identifier, UnitType::unit
return false;
}
- if (unit_args.icon <= 0) {
- Logger::error("Invalid icon for unit ", identifier, " - ", unit_args.icon, " (must be positive)");
+ if (unit_args.icon < 0) {
+ Logger::error("Invalid icon for unit ", identifier, " - ", unit_args.icon, " (must be >= 0)");
return false;
}
@@ -231,16 +242,18 @@ bool UnitTypeManager::load_unit_type_file(
good_definition_manager.expect_good_definition_decimal_map(move_variable_callback(unit_args.supply_cost))
);
- auto add_terrain_modifier = [&unit_args, &terrain_type_manager, &modifier_manager](
+ auto add_terrain_modifier_value = [&unit_args, &terrain_type_manager, &modifier_manager](
std::string_view default_key, ast::NodeCPtr default_value
) -> bool {
TerrainType const* terrain_type = terrain_type_manager.get_terrain_type_by_identifier(default_key);
+
if (terrain_type != nullptr) {
- // TODO - restrict what modifier effects can be used here
- return modifier_manager.expect_modifier_value(
- map_callback(unit_args.terrain_modifiers, terrain_type)
+ ModifierValue& modifier_value = unit_args.terrain_modifier_values[terrain_type];
+ return expect_dictionary(
+ modifier_manager.expect_unit_terrain_modifier(modifier_value, terrain_type->get_identifier())
)(default_value);
}
+
return key_value_invalid_callback(default_key, default_value);
};
@@ -274,7 +287,7 @@ bool UnitTypeManager::load_unit_type_file(
regiment_type_args.allowed_cultures = RegimentType::allowed_cultures_t::ALL_CULTURES;
}
- ret &= expect_dictionary_key_map_and_default(key_map, add_terrain_modifier)(value);
+ ret &= expect_dictionary_key_map_and_default(key_map, add_terrain_modifier_value)(value);
ret &= add_regiment_type(key, unit_args, regiment_type_args);
@@ -301,7 +314,7 @@ bool UnitTypeManager::load_unit_type_file(
"torpedo_attack", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(ship_type_args.torpedo_attack))
);
- ret &= expect_dictionary_key_map_and_default(key_map, add_terrain_modifier)(value);
+ ret &= expect_dictionary_key_map_and_default(key_map, add_terrain_modifier_value)(value);
ret &= add_ship_type(key, unit_args, ship_type_args);
@@ -319,59 +332,71 @@ bool UnitTypeManager::generate_modifiers(ModifierManager& modifier_manager) cons
bool ret = true;
const auto generate_stat_modifiers = [&modifier_manager, &ret](
- std::string_view identifier, UnitType::branch_t branch
+ std::derived_from<ModifierEffectCache::unit_type_effects_t> auto unit_type_effects, std::string_view identifier
) -> void {
+ using enum ModifierEffect::format_t;
+
const auto stat_modifier = [&modifier_manager, &ret, &identifier](
- std::string_view suffix, bool is_positive_good, ModifierEffect::format_t format, std::string_view localisation_key
+ ModifierEffect const*& effect_cache, std::string_view suffix, bool is_positive_good,
+ ModifierEffect::format_t format, std::string_view localisation_key
) -> void {
- ret &= modifier_manager.add_modifier_effect(
- ModifierManager::get_flat_identifier(identifier, suffix), is_positive_good, format,
+ ret &= modifier_manager.register_technology_modifier_effect(
+ effect_cache, ModifierManager::get_flat_identifier(identifier, suffix), is_positive_good, format,
StringUtils::append_string_views("$", identifier, "$: $", localisation_key, "$")
);
};
- using enum ModifierEffect::format_t;
-
ret &= modifier_manager.register_complex_modifier(identifier);
- stat_modifier("attack", true, RAW_DECIMAL, "ATTACK");
- stat_modifier("defence", true, RAW_DECIMAL, "DEFENCE");
- stat_modifier("default_organisation", true, RAW_DECIMAL, "DEFAULT_ORG");
- stat_modifier("maximum_speed", true, RAW_DECIMAL, "MAXIMUM_SPEED");
- stat_modifier("build_time", false, INT, "BUILD_TIME");
- stat_modifier("supply_consumption", false, PROPORTION_DECIMAL, "SUPPLY_CONSUMPTION");
+ stat_modifier(unit_type_effects.attack, "attack", true, RAW_DECIMAL, "ATTACK");
+ stat_modifier(unit_type_effects.defence, "defence", true, RAW_DECIMAL, "DEFENCE");
+ stat_modifier(unit_type_effects.default_organisation, "default_organisation", true, RAW_DECIMAL, "DEFAULT_ORG");
+ stat_modifier(unit_type_effects.maximum_speed, "maximum_speed", true, RAW_DECIMAL, "MAXIMUM_SPEED");
+ stat_modifier(unit_type_effects.build_time, "build_time", false, INT, "BUILD_TIME");
+ stat_modifier(
+ unit_type_effects.supply_consumption, "supply_consumption", false, PROPORTION_DECIMAL, "SUPPLY_CONSUMPTION"
+ );
- switch (branch) {
- case LAND:
- stat_modifier("reconnaissance", true, RAW_DECIMAL, "RECONAISSANCE");
- stat_modifier("discipline", true, PROPORTION_DECIMAL, "DISCIPLINE");
- stat_modifier("support", true, PROPORTION_DECIMAL, "SUPPORT");
- stat_modifier("maneuver", true, INT, "Maneuver");
- stat_modifier("siege", true, RAW_DECIMAL, "SIEGE");
- break;
- case NAVAL:
- stat_modifier("colonial_points", true, INT, "COLONIAL_POINTS_TECH");
- stat_modifier("supply_consumption_score", false, INT, "SUPPLY_LOAD");
- stat_modifier("hull", true, RAW_DECIMAL, "HULL");
- stat_modifier("gun_power", true, RAW_DECIMAL, "GUN_POWER");
- stat_modifier("fire_range", true, RAW_DECIMAL, "FIRE_RANGE");
- stat_modifier("evasion", true, PROPORTION_DECIMAL, "EVASION");
- stat_modifier("torpedo_attack", true, RAW_DECIMAL, "TORPEDO_ATTACK");
- break;
- default:
+ if constexpr (std::same_as<decltype(unit_type_effects), ModifierEffectCache::regiment_type_effects_t>) {
+ stat_modifier(unit_type_effects.reconnaissance, "reconnaissance", true, RAW_DECIMAL, "RECONAISSANCE");
+ stat_modifier(unit_type_effects.discipline, "discipline", true, PROPORTION_DECIMAL, "DISCIPLINE");
+ stat_modifier(unit_type_effects.support, "support", true, PROPORTION_DECIMAL, "SUPPORT");
+ stat_modifier(unit_type_effects.maneuver, "maneuver", true, INT, "Maneuver");
+ stat_modifier(unit_type_effects.siege, "siege", true, RAW_DECIMAL, "SIEGE");
+ } else if constexpr(std::same_as<decltype(unit_type_effects), ModifierEffectCache::ship_type_effects_t>) {
+ stat_modifier(unit_type_effects.colonial_points, "colonial_points", true, INT, "COLONIAL_POINTS_TECH");
+ stat_modifier(unit_type_effects.supply_consumption_score, "supply_consumption_score", false, INT, "SUPPLY_LOAD");
+ stat_modifier(unit_type_effects.hull, "hull", true, RAW_DECIMAL, "HULL");
+ stat_modifier(unit_type_effects.gun_power, "gun_power", true, RAW_DECIMAL, "GUN_POWER");
+ stat_modifier(unit_type_effects.fire_range, "fire_range", true, RAW_DECIMAL, "FIRE_RANGE");
+ stat_modifier(unit_type_effects.evasion, "evasion", true, PROPORTION_DECIMAL, "EVASION");
+ stat_modifier(unit_type_effects.torpedo_attack, "torpedo_attack", true, RAW_DECIMAL, "TORPEDO_ATTACK");
+ } else {
/* Unreachable - unit types are only added via add_regiment_type or add_ship_type which set branch to LAND or NAVAL. */
- Logger::error("Invalid branch for unit ", identifier, ": ", static_cast<int>(branch));
+ Logger::error("Invalid branch for unit ", identifier, " - not LAND or NAVAL!");
}
};
- generate_stat_modifiers("army_base", LAND);
+ generate_stat_modifiers(modifier_manager.modifier_effect_cache.army_base_effects, "army_base");
+
+ IndexedMap<RegimentType, ModifierEffectCache::regiment_type_effects_t>& regiment_type_effects =
+ modifier_manager.modifier_effect_cache.regiment_type_effects;
+
+ regiment_type_effects.set_keys(&get_regiment_types());
+
for (RegimentType const& regiment_type : get_regiment_types()) {
- generate_stat_modifiers(regiment_type.get_identifier(), LAND);
+ generate_stat_modifiers(regiment_type_effects[regiment_type], regiment_type.get_identifier());
}
- generate_stat_modifiers("navy_base", NAVAL);
+ generate_stat_modifiers(modifier_manager.modifier_effect_cache.navy_base_effects, "navy_base");
+
+ IndexedMap<ShipType, ModifierEffectCache::ship_type_effects_t>& ship_type_effects =
+ modifier_manager.modifier_effect_cache.ship_type_effects;
+
+ ship_type_effects.set_keys(&get_ship_types());
+
for (ShipType const& ship_type : get_ship_types()) {
- generate_stat_modifiers(ship_type.get_identifier(), NAVAL);
+ generate_stat_modifiers(ship_type_effects[ship_type], ship_type.get_identifier());
}
return ret;
diff --git a/src/openvic-simulation/military/UnitType.hpp b/src/openvic-simulation/military/UnitType.hpp
index 3fa9af5..9527041 100644
--- a/src/openvic-simulation/military/UnitType.hpp
+++ b/src/openvic-simulation/military/UnitType.hpp
@@ -20,7 +20,7 @@ namespace OpenVic {
struct UnitType : HasIdentifier {
using icon_t = uint32_t;
- using terrain_modifiers_t = ordered_map<TerrainType const*, ModifierValue>;
+ using terrain_modifiers_t = ordered_map<TerrainType const*, Modifier>;
enum struct branch_t : uint8_t { INVALID_BRANCH, LAND, NAVAL };
enum struct unit_category_t : uint8_t {
@@ -28,6 +28,8 @@ namespace OpenVic {
};
struct unit_type_args_t {
+ using terrain_modifier_values_t = ordered_map<TerrainType const*, ModifierValue>;
+
icon_t icon = 0;
unit_category_t unit_category = unit_category_t::INVALID_UNIT_CATEGORY;
// TODO defaults for move_sound and select_sound
@@ -38,7 +40,7 @@ namespace OpenVic {
supply_consumption = 0;
Timespan build_time;
GoodDefinition::good_definition_map_t build_cost, supply_cost;
- terrain_modifiers_t terrain_modifiers;
+ terrain_modifier_values_t terrain_modifier_values;
unit_type_args_t() = default;
unit_type_args_t(unit_type_args_t&&) = default;
diff --git a/src/openvic-simulation/military/Wargoal.cpp b/src/openvic-simulation/military/Wargoal.cpp
index 773e791..ce6b153 100644
--- a/src/openvic-simulation/military/Wargoal.cpp
+++ b/src/openvic-simulation/military/Wargoal.cpp
@@ -86,6 +86,7 @@ bool WargoalTypeManager::load_wargoal_file(ovdl::v2script::Parser const& parser)
}
using enum WargoalType::peace_options_t;
+ using enum scope_type_t;
std::string_view war_name;
Timespan available {}, truce {};
@@ -94,12 +95,12 @@ bool WargoalTypeManager::load_wargoal_file(ovdl::v2script::Parser const& parser)
mutual = false, all_allowed_states = false, always = false;
WargoalType::peace_options_t peace_options = NO_PEACE_OPTIONS;
WargoalType::peace_modifiers_t modifiers;
- ConditionScript can_use { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::COUNTRY };
- ConditionScript is_valid { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::COUNTRY };
- ConditionScript allowed_states { scope_t::STATE, scope_t::COUNTRY, scope_t::COUNTRY };
- ConditionScript allowed_substate_regions { scope_t::STATE, scope_t::COUNTRY, scope_t::COUNTRY };
- ConditionScript allowed_states_in_crisis { scope_t::STATE, scope_t::COUNTRY, scope_t::COUNTRY };
- ConditionScript allowed_countries { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::COUNTRY };
+ ConditionScript can_use { COUNTRY, COUNTRY, COUNTRY };
+ ConditionScript is_valid { COUNTRY, COUNTRY, COUNTRY };
+ ConditionScript allowed_states { STATE, COUNTRY, COUNTRY };
+ ConditionScript allowed_substate_regions { STATE, COUNTRY, COUNTRY };
+ ConditionScript allowed_states_in_crisis { STATE, COUNTRY, COUNTRY };
+ ConditionScript allowed_countries { COUNTRY, COUNTRY, COUNTRY };
EffectScript on_add, on_po_accepted; //country as default scope for both
const auto expect_peace_option = [&peace_options](WargoalType::peace_options_t peace_option) -> node_callback_t {
diff --git a/src/openvic-simulation/misc/Decision.cpp b/src/openvic-simulation/misc/Decision.cpp
index 41d4f81..7812fc1 100644
--- a/src/openvic-simulation/misc/Decision.cpp
+++ b/src/openvic-simulation/misc/Decision.cpp
@@ -55,12 +55,15 @@ bool DecisionManager::load_decision_file(ast::NodeCPtr root) {
"political_decisions", ZERO_OR_ONE, expect_dictionary_reserve_length(
decisions,
[this](std::string_view identifier, ast::NodeCPtr node) -> bool {
+ using enum scope_type_t;
+
bool alert = true, news = false;
std::string_view news_title, news_desc_long, news_desc_medium, news_desc_short, picture;
- ConditionScript potential { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
- ConditionScript allow { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
- ConditionalWeight ai_will_do { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
+ ConditionScript potential { COUNTRY, COUNTRY, NO_SCOPE };
+ ConditionScript allow { COUNTRY, COUNTRY, NO_SCOPE };
+ ConditionalWeight ai_will_do { COUNTRY, COUNTRY, NO_SCOPE };
EffectScript effect;
+
bool ret = expect_dictionary_keys(
"alert", ZERO_OR_ONE, expect_bool(assign_variable_callback(alert)),
"news", ZERO_OR_ONE, expect_bool(assign_variable_callback(news)),
@@ -74,10 +77,12 @@ bool DecisionManager::load_decision_file(ast::NodeCPtr root) {
"effect", ONE_EXACTLY, effect.expect_script(),
"ai_will_do", ZERO_OR_ONE, ai_will_do.expect_conditional_weight(ConditionalWeight::FACTOR)
)(node);
+
ret &= add_decision(
identifier, alert, news, news_title, news_desc_long, news_desc_medium, news_desc_short, picture,
std::move(potential), std::move(allow), std::move(ai_will_do), std::move(effect)
);
+
return ret;
}
)
diff --git a/src/openvic-simulation/misc/Define.cpp b/src/openvic-simulation/misc/Define.cpp
deleted file mode 100644
index c28aab0..0000000
--- a/src/openvic-simulation/misc/Define.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-#include "Define.hpp"
-
-#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp>
-
-#include "openvic-simulation/dataloader/NodeTools.hpp"
-#include "openvic-simulation/types/Date.hpp"
-#include "openvic-simulation/types/IdentifierRegistry.hpp"
-#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
-#include "openvic-simulation/utility/StringUtils.hpp"
-
-using namespace OpenVic;
-using namespace OpenVic::NodeTools;
-
-std::string_view Define::type_to_string(Type type) {
- using enum Type;
-
- switch (type) {
- case Date: return "date";
- case Country: return "country";
- case Economy: return "economy";
- case Military: return "military";
- case Diplomacy: return "diplomacy";
- case Pops: return "pops";
- case Ai: return "ai";
- case Graphics: return "graphics";
- default: return "unknown";
- }
-}
-
-Define::Type Define::string_to_type(std::string_view str) {
- using enum Type;
-
- static const string_map_t<Define::Type> type_map {
- { "country", Country },
- { "economy", Economy },
- { "military", Military },
- { "diplomacy", Diplomacy },
- { "pops", Pops },
- { "ai", Ai },
- { "graphics", Graphics },
- };
-
- const string_map_t<Define::Type>::const_iterator type_it = type_map.find(str);
-
- if (type_it != type_map.end()) {
- return type_it->second;
- } else {
- return Unknown;
- }
-}
-
-Define::Define(std::string_view new_identifier, std::string_view new_value, Type new_type)
- : HasIdentifier { new_identifier }, value { new_value }, type { new_type } {}
-
-Date Define::get_value_as_date(bool* successful) const {
- return Date::from_string(value, successful);
-}
-
-fixed_point_t Define::get_value_as_fp(bool* successful) const {
- return fixed_point_t::parse(value, successful);
-}
-
-int64_t Define::get_value_as_int(bool* successful) const {
- return StringUtils::string_to_int64(value, successful);
-}
-
-uint64_t Define::get_value_as_uint(bool* successful) const {
- return StringUtils::string_to_uint64(value, successful);
-}
-
-std::ostream& OpenVic::operator<<(std::ostream& os, Define::Type type) {
- return os << Define::type_to_string(type);
-}
-
-template<typename T>
-bool DefineManager::load_define(T& value, Define::Type type, std::string_view name) const {
- static_assert(
- std::same_as<T, OpenVic::Date> || std::same_as<T, fixed_point_t> || std::integral<T>
- );
-
- Define const* define = defines.get_item_by_identifier(name);
-
- if (define != nullptr) {
- if (define->type != type) {
- Logger::warning("Mismatched define type for \"", name, "\" - expected ", type, ", got ", define->type);
- }
-
- const auto parse =
- [define, &value, &name]<typename U, U (Define::*Func)(bool*) const>(std::string_view type_name) -> bool {
- bool success = false;
- const U result = (define->*Func)(&success);
- if (success) {
- value = static_cast<T>(result);
- return true;
- } else {
- Logger::error("Failed to parse ", type_name, " \"", define->get_value(), "\" for define \"", name, "\"");
- return false;
- }
- };
-
- if constexpr (std::same_as<T, OpenVic::Date>) {
- return parse.template operator()<Date, &Define::get_value_as_date>("date");
- } else if constexpr (std::same_as<T, fixed_point_t>) {
- return parse.template operator()<fixed_point_t, &Define::get_value_as_fp>("fixed point");
- } else if constexpr (std::signed_integral<T>) {
- return parse.template operator()<int64_t, &Define::get_value_as_int>("signed int");
- } else if constexpr (std::unsigned_integral<T>) {
- return parse.template operator()<uint64_t, &Define::get_value_as_uint>("unsigned int");
- }
- } else {
- Logger::error("Missing define \"", name, "\"");
- return false;
- }
-}
-
-template<Timespan (*Func)(Timespan::day_t)>
-bool DefineManager::_load_define_timespan(Timespan& value, Define::Type type, std::string_view name) const {
- Define const* define = defines.get_item_by_identifier(name);
- if (define != nullptr) {
- if (define->type != type) {
- Logger::warning("Mismatched define type for \"", name, "\" - expected ", type, ", got ", define->type);
- }
- bool success = false;
- const int64_t result = define->get_value_as_int(&success);
- if (success) {
- value = Func(result);
- return true;
- } else {
- Logger::error("Failed to parse days \"", define->get_value(), "\" for define \"", name, "\"");
- return false;
- }
- } else {
- Logger::error("Missing define \"", name, "\"");
- return false;
- }
-}
-
-bool DefineManager::load_define_days(Timespan& value, Define::Type type, std::string_view name) const {
- return _load_define_timespan<Timespan::from_days>(value, type, name);
-}
-
-bool DefineManager::load_define_months(Timespan& value, Define::Type type, std::string_view name) const {
- return _load_define_timespan<Timespan::from_months>(value, type, name);
-}
-
-bool DefineManager::load_define_years(Timespan& value, Define::Type type, std::string_view name) const {
- return _load_define_timespan<Timespan::from_years>(value, type, name);
-}
-
-DefineManager::DefineManager()
- : // Date
- start_date { 1836, 1, 1 },
- end_date { 1936, 1, 1 },
-
- // Country
- great_power_rank { 8 },
- lose_great_power_grace_days { Timespan::from_years(1) },
- secondary_power_rank { 16 },
- country_investment_industrial_score_factor { 1 },
-
- // Economy
-
- // Military
- pop_size_per_regiment { 1000 },
- min_pop_size_for_regiment { 1000 },
- pop_size_per_regiment_protectorate_multiplier { 1 },
- pop_size_per_regiment_colony_multiplier { 1 },
- pop_size_per_regiment_non_core_multiplier { 1 },
-
- // Diplomacy
- disarmed_penalty { 0 }
-
- // Pops
-
- // Ai
-
- // Graphics
-
- {}
-
-bool DefineManager::add_define(std::string_view name, std::string_view value, Define::Type type) {
- if (name.empty()) {
- Logger::error("Invalid define identifier - empty!");
- return false;
- }
-
- if (value.empty()) {
- Logger::error("Invalid define value for \"", name, "\" - empty!");
- return false;
- }
-
- return defines.add_item({ name, value, type }, duplicate_warning_callback);
-}
-
-bool DefineManager::in_game_period(Date date) const {
- return date.in_range(start_date, end_date);
-}
-
-bool DefineManager::load_defines_file(ast::NodeCPtr root) {
- using enum Define::Type;
-
- bool ret = expect_dictionary_keys(
- "defines", ONE_EXACTLY, expect_dictionary([this](std::string_view key, ast::NodeCPtr value) -> bool {
-
- const Define::Type type = Define::string_to_type(key);
-
- if (type != Unknown) {
-
- return expect_dictionary_reserve_length(
- defines,
- [this, type](std::string_view inner_key, ast::NodeCPtr value) -> bool {
- return expect_identifier_or_string(
- [this, &inner_key, type](std::string_view value) -> bool {
- return add_define(inner_key, value, type);
- }
- )(value);
- }
- )(value);
-
- } else if (key == "start_date" || key == "end_date") {
-
- return expect_identifier_or_string(
- [this, &key](std::string_view value) -> bool {
- return add_define(key, value, Date);
- }
- )(value);
-
- } else {
-
- Logger::error("Invalid define type - \"", key, "\"");
- return false;
-
- }
- })
- )(root);
-
- lock_defines();
-
- // Date
- ret &= load_define(start_date, Date, "start_date");
- ret &= load_define(end_date, Date, "end_date");
-
- // Country
- ret &= load_define(great_power_rank, Country, "GREAT_NATIONS_COUNT");
- ret &= load_define_days(lose_great_power_grace_days, Country, "GREATNESS_DAYS");
- ret &= load_define(secondary_power_rank, Country, "COLONIAL_RANK");
- ret &= load_define(country_investment_industrial_score_factor, Country, "INVESTMENT_SCORE_FACTOR");
-
- // Economy
-
- // Military
- ret &= load_define(pop_size_per_regiment, Military, "POP_SIZE_PER_REGIMENT");
- ret &= load_define(min_pop_size_for_regiment, Military, "POP_MIN_SIZE_FOR_REGIMENT");
- ret &= load_define(
- pop_size_per_regiment_protectorate_multiplier, Military, "POP_MIN_SIZE_FOR_REGIMENT_PROTECTORATE_MULTIPLIER"
- );
- ret &= load_define(pop_size_per_regiment_colony_multiplier, Military, "POP_MIN_SIZE_FOR_REGIMENT_COLONY_MULTIPLIER");
- ret &= load_define(pop_size_per_regiment_non_core_multiplier, Military, "POP_MIN_SIZE_FOR_REGIMENT_NONCORE_MULTIPLIER");
-
- // Diplomacy
- ret &= load_define(disarmed_penalty, Diplomacy, "DISARMAMENT_ARMY_HIT");
-
- // Pops
-
- // Ai
-
- // Graphics
-
- return ret;
-}
diff --git a/src/openvic-simulation/misc/Define.hpp b/src/openvic-simulation/misc/Define.hpp
deleted file mode 100644
index 064883c..0000000
--- a/src/openvic-simulation/misc/Define.hpp
+++ /dev/null
@@ -1,88 +0,0 @@
-#pragma once
-
-#include "openvic-simulation/pop/Pop.hpp"
-#include "openvic-simulation/types/IdentifierRegistry.hpp"
-#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
-
-namespace OpenVic {
- struct DefineManager;
-
- struct Define : HasIdentifier {
- friend struct DefineManager;
-
- enum class Type : unsigned char { Unknown, Date, Country, Economy, Military, Diplomacy, Pops, Ai, Graphics };
-
- static std::string_view type_to_string(Type type);
- // This only accepts type names found in defines.lua, so it will never return Type::Date
- static Type string_to_type(std::string_view str);
-
- private:
- std::string PROPERTY(value);
- const Type PROPERTY(type);
-
- Define(std::string_view new_identifier, std::string_view new_value, Type new_type);
-
- public:
- Define(Define&&) = default;
-
- Date get_value_as_date(bool* successful = nullptr) const;
- fixed_point_t get_value_as_fp(bool* successful = nullptr) const;
- int64_t get_value_as_int(bool* successful = nullptr) const;
- uint64_t get_value_as_uint(bool* successful = nullptr) const;
- };
-
- std::ostream& operator<<(std::ostream& os, Define::Type type);
-
- struct DefineManager {
- private:
- IdentifierRegistry<Define> IDENTIFIER_REGISTRY(define);
-
- // Date
- Date PROPERTY(start_date); // start_date
- Date PROPERTY(end_date); // end_date
-
- // Country
- size_t PROPERTY(great_power_rank); // GREAT_NATIONS_COUNT
- Timespan PROPERTY(lose_great_power_grace_days); // GREATNESS_DAYS
- size_t PROPERTY(secondary_power_rank); // COLONIAL_RANK
- fixed_point_t PROPERTY(country_investment_industrial_score_factor); // INVESTMENT_SCORE_FACTOR
-
- // Economy
-
- // Military
- Pop::pop_size_t PROPERTY(pop_size_per_regiment); // POP_SIZE_PER_REGIMENT
- Pop::pop_size_t PROPERTY(min_pop_size_for_regiment); // POP_MIN_SIZE_FOR_REGIMENT
- // POP_MIN_SIZE_FOR_REGIMENT_PROTECTORATE_MULTIPLIER
- fixed_point_t PROPERTY(pop_size_per_regiment_protectorate_multiplier);
- fixed_point_t PROPERTY(pop_size_per_regiment_colony_multiplier); // POP_MIN_SIZE_FOR_REGIMENT_COLONY_MULTIPLIER
- fixed_point_t PROPERTY(pop_size_per_regiment_non_core_multiplier); // POP_MIN_SIZE_FOR_REGIMENT_NONCORE_MULTIPLIER
-
- // Diplomacy
- fixed_point_t PROPERTY(disarmed_penalty); // DISARMAMENT_ARMY_HIT
-
- // Pops
-
- // Ai
-
- // Graphics
-
- template<typename T>
- bool load_define(T& value, Define::Type type, std::string_view name) const;
-
- template<Timespan (*Func)(Timespan::day_t)>
- bool _load_define_timespan(Timespan& value, Define::Type type, std::string_view name) const;
-
- bool load_define_days(Timespan& value, Define::Type type, std::string_view name) const;
- bool load_define_months(Timespan& value, Define::Type type, std::string_view name) const;
- bool load_define_years(Timespan& value, Define::Type type, std::string_view name) const;
-
- public:
- DefineManager();
-
- bool add_define(std::string_view name, std::string_view value, Define::Type type);
-
- bool in_game_period(Date date) const;
-
- bool load_defines_file(ast::NodeCPtr root);
- };
-}
diff --git a/src/openvic-simulation/misc/Event.cpp b/src/openvic-simulation/misc/Event.cpp
index 5bfc929..64b1f64 100644
--- a/src/openvic-simulation/misc/Event.cpp
+++ b/src/openvic-simulation/misc/Event.cpp
@@ -119,15 +119,17 @@ bool EventManager::load_event_file(IssueManager const& issue_manager, ast::NodeC
return expect_dictionary_reserve_length(
events,
[this, &issue_manager](std::string_view key, ast::NodeCPtr value) -> bool {
+ using enum scope_type_t;
+
Event::event_type_t type;
- scope_t initial_scope;
+ scope_type_t initial_scope;
if (key == "country_event") {
type = Event::event_type_t::COUNTRY;
- initial_scope = scope_t::COUNTRY;
+ initial_scope = COUNTRY;
} else if (key == "province_event") {
type = Event::event_type_t::PROVINCE;
- initial_scope = scope_t::PROVINCE;
+ initial_scope = PROVINCE;
} else {
Logger::error("Invalid event type: ", key);
return false;
@@ -138,8 +140,8 @@ bool EventManager::load_event_file(IssueManager const& issue_manager, ast::NodeC
bool triggered_only = false, major = false, fire_only_once = false, allows_multiple_instances = false,
news = false, election = false;
IssueGroup const* election_issue_group = nullptr;
- ConditionScript trigger { initial_scope, initial_scope, scope_t::NO_SCOPE };
- ConditionalWeight mean_time_to_happen { initial_scope, initial_scope, scope_t::NO_SCOPE };
+ ConditionScript trigger { initial_scope, initial_scope, NO_SCOPE };
+ ConditionalWeight mean_time_to_happen { initial_scope, initial_scope, NO_SCOPE };
EffectScript immediate;
std::vector<Event::EventOption> options;
@@ -166,7 +168,7 @@ bool EventManager::load_event_file(IssueManager const& issue_manager, ast::NodeC
ConditionalWeight ai_chance {
initial_scope,
initial_scope,
- scope_t::COUNTRY | scope_t::PROVINCE
+ COUNTRY | PROVINCE // TODO - decide which to use?
};
bool ret = expect_dictionary_keys_and_default(
@@ -181,7 +183,7 @@ bool EventManager::load_event_file(IssueManager const& issue_manager, ast::NodeC
return ret;
},
"trigger", ZERO_OR_ONE, trigger.expect_script(),
- "mean_time_to_happen", ZERO_OR_ONE, mean_time_to_happen.expect_conditional_weight(ConditionalWeight::MONTHS),
+ "mean_time_to_happen", ZERO_OR_ONE, mean_time_to_happen.expect_conditional_weight(ConditionalWeight::TIME),
"immediate", ZERO_OR_MORE, immediate.expect_script()
)(value);
ret &= register_event(
diff --git a/src/openvic-simulation/misc/SongChance.cpp b/src/openvic-simulation/misc/SongChance.cpp
index 94fb571..d05afdf 100644
--- a/src/openvic-simulation/misc/SongChance.cpp
+++ b/src/openvic-simulation/misc/SongChance.cpp
@@ -17,12 +17,14 @@ bool SongChanceManager::load_songs_file(ast::NodeCPtr root) {
ret &= expect_dictionary_reserve_length(
song_chances,
[this](std::string_view key, ast::NodeCPtr value) -> bool {
+ using enum scope_type_t;
+
if (key != "song") {
Logger::error("Invalid song declaration ", key);
return false;
}
std::string_view name {};
- ConditionalWeight chance { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
+ ConditionalWeight chance { COUNTRY, COUNTRY, NO_SCOPE };
bool ret = expect_dictionary_keys(
"name", ONE_EXACTLY, expect_string(assign_variable_callback(name)),
diff --git a/src/openvic-simulation/misc/SoundEffect.cpp b/src/openvic-simulation/misc/SoundEffect.cpp
index b32d353..6f64406 100644
--- a/src/openvic-simulation/misc/SoundEffect.cpp
+++ b/src/openvic-simulation/misc/SoundEffect.cpp
@@ -25,14 +25,14 @@ bool SoundEffectManager::_load_sound_define(std::string_view sfx_identifier, ast
return false;
}
- ret &= sound_effects.add_item({sfx_identifier,file,volume});
+ ret &= sound_effects.add_item({ sfx_identifier, file, volume });
return ret;
}
bool SoundEffectManager::load_sound_defines_file(ast::NodeCPtr root) {
return expect_dictionary_reserve_length(sound_effects,
[this](std::string_view key, ast::NodeCPtr value) -> bool {
- return _load_sound_define(key,value);
+ return _load_sound_define(key, value);
}
)(root);
}
diff --git a/src/openvic-simulation/modifier/Modifier.cpp b/src/openvic-simulation/modifier/Modifier.cpp
index b26b8dd..3cec7df 100644
--- a/src/openvic-simulation/modifier/Modifier.cpp
+++ b/src/openvic-simulation/modifier/Modifier.cpp
@@ -1,131 +1,31 @@
#include "Modifier.hpp"
-#include <string>
-
-#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp>
-
-#include <dryad/node.hpp>
-
-#include "openvic-simulation/types/OrderedContainers.hpp"
-#include "openvic-simulation/utility/TslHelper.hpp"
-
using namespace OpenVic;
-using namespace OpenVic::NodeTools;
-
-static std::string make_default_modifier_effect_localisation_key(std::string_view identifier) {
- return "MODIFIER_" + StringUtils::string_toupper(identifier);
-}
-
-ModifierEffect::ModifierEffect(
- std::string_view new_identifier, bool new_positive_good, format_t new_format, std::string_view new_localisation_key
-) : HasIdentifier { new_identifier }, positive_good { new_positive_good }, format { new_format },
- localisation_key {
- new_localisation_key.empty() ? make_default_modifier_effect_localisation_key(new_identifier) : new_localisation_key
- } {}
-
-ModifierValue::ModifierValue() = default;
-ModifierValue::ModifierValue(effect_map_t&& new_values) : values { std::move(new_values) } {}
-ModifierValue::ModifierValue(ModifierValue const&) = default;
-ModifierValue::ModifierValue(ModifierValue&&) = default;
-
-ModifierValue& ModifierValue::operator=(ModifierValue const&) = default;
-ModifierValue& ModifierValue::operator=(ModifierValue&&) = default;
-
-void ModifierValue::trim() {
- erase_if(values, [](effect_map_t::value_type const& value) -> bool {
- return value.second == fixed_point_t::_0();
- });
-}
-
-size_t ModifierValue::get_effect_count() const {
- return values.size();
-}
-
-void ModifierValue::clear() {
- values.clear();
-}
-bool ModifierValue::empty() const {
- return values.empty();
-}
-
-fixed_point_t ModifierValue::get_effect(ModifierEffect const& effect, bool* effect_found) const {
- const effect_map_t::const_iterator it = values.find(&effect);
- if (it != values.end()) {
- if (effect_found != nullptr) {
- *effect_found = true;
- }
- return it->second;
- }
- if (effect_found != nullptr) {
- *effect_found = false;
- }
- return fixed_point_t::_0();
-}
-
-bool ModifierValue::has_effect(ModifierEffect const& effect) const {
- return values.contains(&effect);
-}
-
-void ModifierValue::set_effect(ModifierEffect const& effect, fixed_point_t value) {
- values[&effect] = value;
-}
-
-ModifierValue& ModifierValue::operator+=(ModifierValue const& right) {
- for (effect_map_t::value_type const& value : right.values) {
- values[value.first] += value.second;
- }
- return *this;
-}
-
-ModifierValue ModifierValue::operator+(ModifierValue const& right) const {
- ModifierValue copy = *this;
- return copy += right;
-}
-
-ModifierValue ModifierValue::operator-() const {
- ModifierValue copy = *this;
- for (auto value : mutable_iterator(copy.values)) {
- value.second = -value.second;
- }
- return copy;
-}
-
-ModifierValue& ModifierValue::operator-=(ModifierValue const& right) {
- for (effect_map_t::value_type const& value : right.values) {
- values[value.first] -= value.second;
- }
- return *this;
-}
-
-ModifierValue ModifierValue::operator-(ModifierValue const& right) const {
- ModifierValue copy = *this;
- return copy -= right;
-}
-
-ModifierValue& ModifierValue::operator*=(fixed_point_t const& right) {
- for (auto value : mutable_iterator(values)) {
- value.second *= right;
- }
- return *this;
-}
-
-ModifierValue ModifierValue::operator*(fixed_point_t const& right) const {
- ModifierValue copy = *this;
- return copy *= right;
-}
-
-fixed_point_t& ModifierValue::operator[](ModifierEffect const& effect) {
- return values[&effect];
-}
-
-void ModifierValue::multiply_add(ModifierValue const& other, fixed_point_t multiplier) {
- if (multiplier == fixed_point_t::_1()) {
- *this += other;
- } else if (multiplier != fixed_point_t::_0()) {
- for (effect_map_t::value_type const& value : other.values) {
- values[value.first] += value.second * multiplier;
- }
+std::string_view Modifier::modifier_type_to_string(modifier_type_t type) {
+ using enum Modifier::modifier_type_t;
+
+ switch (type) {
+#define _CASE(X) case X: return #X;
+ _CASE(EVENT)
+ _CASE(STATIC)
+ _CASE(TRIGGERED)
+ _CASE(CRIME)
+ _CASE(TERRAIN)
+ _CASE(CLIMATE)
+ _CASE(CONTINENT)
+ _CASE(BUILDING)
+ _CASE(LEADER)
+ _CASE(UNIT_TERRAIN)
+ _CASE(NATIONAL_VALUE)
+ _CASE(NATIONAL_FOCUS)
+ _CASE(ISSUE)
+ _CASE(REFORM)
+ _CASE(TECHNOLOGY)
+ _CASE(INVENTION)
+ _CASE(TECH_SCHOOL)
+#undef _CASE
+ default: return "INVALID MODIFIER TYPE";
}
}
@@ -147,510 +47,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(
- std::string_view identifier, bool positive_good, ModifierEffect::format_t format, std::string_view localisation_key
-) {
- if (identifier.empty()) {
- Logger::error("Invalid modifier effect identifier - empty!");
- return false;
- }
- return modifier_effects.add_item({ std::move(identifier), positive_good, format, localisation_key });
-}
-
-bool ModifierManager::setup_modifier_effects() {
- bool ret = true;
-
- using enum ModifierEffect::format_t;
- /* Tech/inventions only */
- ret &= add_modifier_effect("cb_creation_speed", true, PROPORTION_DECIMAL, "CB_MANUFACTURE_TECH");
- ret &= add_modifier_effect("combat_width", false);
- ret &= add_modifier_effect("plurality", true, PERCENTAGE_DECIMAL, "TECH_PLURALITY");
- ret &= add_modifier_effect("pop_growth", true, PROPORTION_DECIMAL, "TECH_POP_GROWTH");
- ret &= add_modifier_effect("regular_experience_level", true, RAW_DECIMAL, "REGULAR_EXP_TECH");
- ret &= add_modifier_effect("reinforce_rate", true, PROPORTION_DECIMAL, "REINFORCE_TECH");
- ret &= add_modifier_effect("seperatism", false, PROPORTION_DECIMAL, "SEPARATISM_TECH"); // paradox typo
- ret &= add_modifier_effect("shared_prestige", true, RAW_DECIMAL, "SHARED_PRESTIGE_TECH");
- ret &= add_modifier_effect("tax_eff", true, PROPORTION_DECIMAL, "TECH_TAX_EFF");
-
- /* Country Modifier Effects */
- ret &= add_modifier_effect("administrative_efficiency", true);
- ret &= add_modifier_effect(
- "administrative_efficiency_modifier", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("administrative_efficiency")
- );
- ret &= add_modifier_effect("artisan_input", false);
- ret &= add_modifier_effect("artisan_output", true);
- ret &= add_modifier_effect("artisan_throughput", true);
- ret &= add_modifier_effect("badboy", false, RAW_DECIMAL);
- ret &= add_modifier_effect("cb_generation_speed_modifier", true);
- ret &= add_modifier_effect(
- "civilization_progress_modifier", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("civilization_progress")
- );
- ret &= add_modifier_effect("colonial_life_rating", false, INT, "COLONIAL_LIFE_TECH");
- ret &= add_modifier_effect("colonial_migration", true, PROPORTION_DECIMAL, "COLONIAL_MIGRATION_TECH");
- ret &= add_modifier_effect("colonial_points", true, INT, "COLONIAL_POINTS_TECH");
- ret &= add_modifier_effect("colonial_prestige", true, PROPORTION_DECIMAL, "COLONIAL_PRESTIGE_MODIFIER_TECH");
- ret &= add_modifier_effect("core_pop_consciousness_modifier", false, RAW_DECIMAL);
- ret &= add_modifier_effect("core_pop_militancy_modifier", false, RAW_DECIMAL);
- ret &= add_modifier_effect("dig_in_cap", true, INT, "DIGIN_FROM_TECH");
- ret &= add_modifier_effect("diplomatic_points", true, PROPORTION_DECIMAL, "DIPLOMATIC_POINTS_TECH");
- ret &= add_modifier_effect(
- "diplomatic_points_modifier", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("diplopoints_gain")
- );
- ret &= add_modifier_effect("education_efficiency", true);
- ret &= add_modifier_effect(
- "education_efficiency_modifier", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("education_efficiency")
- );
- ret &= add_modifier_effect("factory_cost", false);
- ret &= add_modifier_effect("factory_input", false);
- ret &= add_modifier_effect("factory_maintenance", false);
- ret &= add_modifier_effect("factory_output", true);
- ret &= add_modifier_effect("factory_owner_cost", false);
- ret &= add_modifier_effect("factory_throughput", true);
- ret &= add_modifier_effect(
- "global_assimilation_rate", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("assimilation_rate")
- );
- ret &= add_modifier_effect(
- "global_immigrant_attract", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("immigant_attract")
- );
- ret &= add_modifier_effect("global_pop_consciousness_modifier", false, RAW_DECIMAL);
- ret &= add_modifier_effect("global_pop_militancy_modifier", false, RAW_DECIMAL);
- ret &= add_modifier_effect(
- "global_population_growth", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("population_growth")
- );
- ret &= add_modifier_effect("goods_demand", false);
- ret &= add_modifier_effect("import_cost", false);
- ret &= add_modifier_effect("increase_research", true, PROPORTION_DECIMAL, "INC_RES_TECH");
- ret &= add_modifier_effect("influence", true, PROPORTION_DECIMAL, "TECH_GP_INFLUENCE");
- ret &= add_modifier_effect(
- "influence_modifier", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("greatpower_influence_gain")
- );
- ret &= add_modifier_effect("issue_change_speed", true);
- ret &= add_modifier_effect(
- "land_attack_modifier", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("land_attack")
- );
- ret &= add_modifier_effect("land_attrition", false, PROPORTION_DECIMAL, "LAND_ATTRITION_TECH");
- ret &= add_modifier_effect(
- "land_defense_modifier", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("land_defense")
- );
- ret &= add_modifier_effect("land_organisation", true);
- ret &= add_modifier_effect("land_unit_start_experience", true, RAW_DECIMAL);
- ret &= add_modifier_effect("leadership", true, RAW_DECIMAL, "LEADERSHIP");
- ret &= add_modifier_effect(
- "leadership_modifier", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("global_leadership_modifier")
- );
- ret &= add_modifier_effect("literacy_con_impact", false);
- ret &= add_modifier_effect("loan_interest", false);
- ret &= add_modifier_effect(
- "max_loan_modifier", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("max_loan_amount")
- );
- ret &= add_modifier_effect("max_military_spending", true);
- ret &= add_modifier_effect("max_national_focus", true, INT, "TECH_MAX_FOCUS");
- ret &= add_modifier_effect("max_social_spending", true);
- ret &= add_modifier_effect("max_tariff", true);
- ret &= add_modifier_effect("max_tax", true);
- ret &= add_modifier_effect("max_war_exhaustion", true, PERCENTAGE_DECIMAL, "MAX_WAR_EXHAUSTION");
- ret &= add_modifier_effect("military_tactics", true, PROPORTION_DECIMAL, "MIL_TACTICS_TECH");
- ret &= add_modifier_effect("min_military_spending", true);
- ret &= add_modifier_effect("min_social_spending", true);
- ret &= add_modifier_effect("min_tariff", true);
- ret &= add_modifier_effect("min_tax", true);
- ret &= add_modifier_effect(
- "minimum_wage", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("minimun_wage")
- );
- ret &= add_modifier_effect("mobilisation_economy_impact", false);
- ret &= add_modifier_effect("mobilisation_size", true);
- ret &= add_modifier_effect("mobilization_impact", false);
- ret &= add_modifier_effect(
- "naval_attack_modifier", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("naval_attack")
- );
- ret &= add_modifier_effect("naval_attrition", false, PROPORTION_DECIMAL, "NAVAL_ATTRITION_TECH");
- ret &= add_modifier_effect(
- "naval_defense_modifier", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("naval_defense")
- );
- ret &= add_modifier_effect("naval_organisation", true);
- ret &= add_modifier_effect("naval_unit_start_experience", true, RAW_DECIMAL);
- ret &= add_modifier_effect("non_accepted_pop_consciousness_modifier", false, RAW_DECIMAL);
- ret &= add_modifier_effect("non_accepted_pop_militancy_modifier", false, RAW_DECIMAL);
- ret &= add_modifier_effect("org_regain", true);
- ret &= add_modifier_effect("pension_level", true);
- ret &= add_modifier_effect("permanent_prestige", true, RAW_DECIMAL, "PERMANENT_PRESTIGE_TECH");
- ret &= add_modifier_effect("political_reform_desire", false);
- ret &= add_modifier_effect("poor_savings_modifier", true);
- ret &= add_modifier_effect("prestige", true, RAW_DECIMAL);
- ret &= add_modifier_effect("reinforce_speed", true);
- ret &= add_modifier_effect("research_points", true, RAW_DECIMAL);
- ret &= add_modifier_effect("research_points_modifier", true);
- ret &= add_modifier_effect("research_points_on_conquer", true);
- ret &= add_modifier_effect("rgo_output", true);
- ret &= add_modifier_effect("rgo_throughput", true);
- ret &= add_modifier_effect("ruling_party_support", true);
- ret &= add_modifier_effect(
- "self_unciv_economic_modifier", false, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("self_unciv_economic")
- );
- ret &= add_modifier_effect(
- "self_unciv_military_modifier", false, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("self_unciv_military")
- );
- ret &= add_modifier_effect("social_reform_desire", false);
- ret &= add_modifier_effect("soldier_to_pop_loss", true, PROPORTION_DECIMAL, "SOLDIER_TO_POP_LOSS_TECH");
- ret &= add_modifier_effect("supply_consumption", false);
- ret &= add_modifier_effect("supply_range", true, PROPORTION_DECIMAL, "SUPPLY_RANGE_TECH");
- ret &= add_modifier_effect("suppression_points_modifier", true, PROPORTION_DECIMAL, "SUPPRESSION_TECH");
- ret &= add_modifier_effect(
- "tariff_efficiency_modifier", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("tariff_efficiency")
- );
- ret &= add_modifier_effect("tax_efficiency", true);
- ret &= add_modifier_effect("unemployment_benefit", true);
- ret &= add_modifier_effect(
- "unciv_economic_modifier", false, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("unciv_economic")
- );
- ret &= add_modifier_effect(
- "unciv_military_modifier", false, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("unciv_military")
- );
- ret &= add_modifier_effect("unit_recruitment_time", false);
- ret &= add_modifier_effect("war_exhaustion", false, PROPORTION_DECIMAL, "WAR_EXHAUST_BATTLES");
-
- /* Province Modifier Effects */
- ret &= add_modifier_effect("assimilation_rate", true);
- ret &= add_modifier_effect("boost_strongest_party", false);
- ret &= add_modifier_effect("farm_rgo_eff", true, PROPORTION_DECIMAL, "TECH_FARM_OUTPUT");
- ret &= add_modifier_effect(
- "farm_rgo_size", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("farm_size")
- );
- ret &= add_modifier_effect(
- "immigrant_attract", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("immigant_attract")
- );
- ret &= add_modifier_effect(
- "immigrant_push", false, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("immigant_push")
- );
- ret &= add_modifier_effect("life_rating", true);
- ret &= add_modifier_effect(
- "local_artisan_input", false, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("artisan_input")
- );
- ret &= add_modifier_effect(
- "local_artisan_output", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("artisan_output")
- );
- ret &= add_modifier_effect(
- "local_artisan_throughput", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("artisan_throughput")
- );
- ret &= add_modifier_effect(
- "local_factory_input", false, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("factory_input")
- );
- ret &= add_modifier_effect(
- "local_factory_output", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("factory_output")
- );
- ret &= add_modifier_effect(
- "local_factory_throughput", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("factory_throughput")
- );
- ret &= add_modifier_effect("local_repair", true);
- ret &= add_modifier_effect(
- "local_rgo_output", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("rgo_output")
- );
- ret &= add_modifier_effect(
- "local_rgo_throughput", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("rgo_throughput")
- );
- ret &= add_modifier_effect(
- "local_ruling_party_support", true, PROPORTION_DECIMAL,
- make_default_modifier_effect_localisation_key("ruling_party_support")
- );
- ret &= add_modifier_effect("local_ship_build", false);
- ret &= add_modifier_effect("max_attrition", false, RAW_DECIMAL);
- ret &= add_modifier_effect("mine_rgo_eff", true, PROPORTION_DECIMAL, "TECH_MINE_OUTPUT");
- ret &= add_modifier_effect(
- "mine_rgo_size", true, PROPORTION_DECIMAL, make_default_modifier_effect_localisation_key("mine_size")
- );
- ret &= add_modifier_effect("movement_cost", false);
- ret &= add_modifier_effect("number_of_voters", false);
- ret &= add_modifier_effect("pop_consciousness_modifier", false, RAW_DECIMAL);
- ret &= add_modifier_effect("pop_militancy_modifier", false, RAW_DECIMAL);
- ret &= add_modifier_effect("population_growth", true);
- ret &= add_modifier_effect("supply_limit", true, RAW_DECIMAL);
-
- /* Military Modifier Effects */
- ret &= add_modifier_effect("attack", true, INT, "TRAIT_ATTACK");
- ret &= add_modifier_effect("attrition", false, RAW_DECIMAL, "ATTRITION");
- ret &= add_modifier_effect("defence", true, INT, "TRAIT_DEFEND");
- ret &= add_modifier_effect("experience", true, PROPORTION_DECIMAL, "TRAIT_EXPERIENCE");
- ret &= add_modifier_effect("morale", true, PROPORTION_DECIMAL, "TRAIT_MORALE");
- ret &= add_modifier_effect("organisation", true, PROPORTION_DECIMAL, "TRAIT_ORGANISATION");
- ret &= add_modifier_effect("reconnaissance", true, PROPORTION_DECIMAL, "TRAIT_RECONAISSANCE");
- ret &= add_modifier_effect("reliability", true, RAW_DECIMAL, "TRAIT_RELIABILITY");
- ret &= add_modifier_effect("speed", true, PROPORTION_DECIMAL, "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) {
- const 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();
-
- 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<ast::IdentifierValue>(value)) {
- return add_modifier_cb(effect, value);
- } else if (complex_modifiers.contains(key) && dryad::node_has_kind<ast::ListValue>(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<ModifierValue&&> 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<ModifierValue&&> 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<ModifierValue&&> 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<ModifierValue&&> 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<ModifierValue&&> 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<ModifierValue&&> 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<ModifierValue&&> 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<ModifierValue&&> 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 80d2db6..f8c28d8 100644
--- a/src/openvic-simulation/modifier/Modifier.hpp
+++ b/src/openvic-simulation/modifier/Modifier.hpp
@@ -1,89 +1,27 @@
#pragma once
+#include <string_view>
+
+#include "openvic-simulation/modifier/ModifierValue.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 ModifierManager;
-
- struct ModifierEffect : HasIdentifier {
- friend struct ModifierManager;
-
- enum class format_t {
- PROPORTION_DECIMAL, /* An unscaled fraction/ratio, with 1 being "full"/"whole" */
- PERCENTAGE_DECIMAL, /* A fraction/ratio scaled so that 100 is "full"/"whole" */
- RAW_DECIMAL, /* A continuous quantity, e.g. attack strength */
- INT /* A discrete quantity, e.g. building count limit */
- };
-
- private:
- /* If true, positive values will be green and negative values will be red.
- * If false, the colours will be switced.
- */
- const bool PROPERTY_CUSTOM_PREFIX(positive_good, is);
- const format_t PROPERTY(format);
- std::string PROPERTY(localisation_key);
-
- // TODO - format/precision, e.g. 80% vs 0.8 vs 0.800, 2 vs 2.0 vs 200%
-
- ModifierEffect(
- std::string_view new_identifier, bool new_positive_good, format_t new_format, std::string_view new_localisation_key
- );
-
- public:
- ModifierEffect(ModifierEffect&&) = default;
- };
-
- struct ModifierValue {
- friend struct ModifierManager;
-
- using effect_map_t = fixed_point_map_t<ModifierEffect const*>;
-
- private:
- effect_map_t PROPERTY(values);
-
- public:
- ModifierValue();
- ModifierValue(effect_map_t&& new_values);
- ModifierValue(ModifierValue const&);
- ModifierValue(ModifierValue&&);
-
- ModifierValue& operator=(ModifierValue const&);
- ModifierValue& operator=(ModifierValue&&);
-
- /* Removes effect entries with a value of zero. */
- void trim();
- size_t get_effect_count() const;
- void clear();
- bool empty() const;
-
- fixed_point_t get_effect(ModifierEffect const& effect, bool* effect_found = nullptr) const;
- bool has_effect(ModifierEffect const& effect) const;
- void set_effect(ModifierEffect const& effect, fixed_point_t value);
-
- ModifierValue& operator+=(ModifierValue const& right);
- ModifierValue operator+(ModifierValue const& right) const;
- ModifierValue operator-() const;
- ModifierValue& operator-=(ModifierValue const& right);
- ModifierValue operator-(ModifierValue const& right) const;
- ModifierValue& operator*=(fixed_point_t const& right);
- ModifierValue operator*(fixed_point_t const& right) const;
-
- fixed_point_t& operator[](ModifierEffect const& effect);
-
- void multiply_add(ModifierValue const& other, fixed_point_t multiplier);
-
- friend std::ostream& operator<<(std::ostream& stream, ModifierValue const& value);
- };
+ struct UnitType;
struct Modifier : HasIdentifier, ModifierValue {
friend struct ModifierManager;
+ friend struct StaticModifierCache;
+ friend struct UnitType;
enum struct modifier_type_t : uint8_t {
- EVENT, STATIC, TRIGGERED, CRIME, TERRAIN, CLIMATE, CONTINENT, BUILDING, LEADER, NATIONAL_VALUE, NATIONAL_FOCUS,
- ISSUE, REFORM, TECHNOLOGY, INVENTION, TECH_SCHOOL
+ EVENT, STATIC, TRIGGERED, CRIME, TERRAIN, CLIMATE, CONTINENT, BUILDING, LEADER, UNIT_TERRAIN,
+ NATIONAL_VALUE, NATIONAL_FOCUS, ISSUE, REFORM, TECHNOLOGY, INVENTION, TECH_SCHOOL
};
+ static std::string_view modifier_type_to_string(modifier_type_t type);
+
private:
const modifier_type_t PROPERTY(type);
@@ -137,108 +75,4 @@ namespace OpenVic {
public:
ModifierInstance(Modifier const& new_modifier, Date new_expiry_date);
};
-
- template<typename Fn>
- concept ModifierEffectValidator = std::predicate<Fn, ModifierEffect const&>;
-
- struct ModifierManager {
- /* 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<ModifierEffect, RegistryStorageInfoDeque> IDENTIFIER_REGISTRY(modifier_effect);
- case_insensitive_string_set_t complex_modifiers;
-
- IdentifierRegistry<IconModifier> IDENTIFIER_REGISTRY(event_modifier);
- IdentifierRegistry<Modifier> IDENTIFIER_REGISTRY(static_modifier);
- IdentifierRegistry<TriggeredModifier> IDENTIFIER_REGISTRY(triggered_modifier);
-
- /* 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(
- std::string_view identifier, bool positive_good,
- ModifierEffect::format_t format = ModifierEffect::format_t::PROPORTION_DECIMAL,
- 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<ModifierValue&&> 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<ModifierValue&&> modifier_callback, ModifierEffectValidator auto effect_validator
- ) const;
-
- NodeTools::node_callback_t expect_modifier_value_and_default(
- NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_value_callback_t default_callback
- ) const;
- NodeTools::node_callback_t expect_modifier_value(NodeTools::callback_t<ModifierValue&&> modifier_callback) const;
-
- NodeTools::node_callback_t expect_whitelisted_modifier_value_and_default(
- NodeTools::callback_t<ModifierValue&&> 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<ModifierValue&&> modifier_callback, string_set_t const& whitelist
- ) const;
-
- NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default(
- NodeTools::callback_t<ModifierValue&&> 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<ModifierValue&&> modifier_callback, NodeTools::key_map_t&& key_map
- ) const;
-
- template<typename... Args>
- NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default(
- NodeTools::callback_t<ModifierValue&&> 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<typename... Args>
- NodeTools::node_callback_t expect_modifier_value_and_keys_and_default(
- NodeTools::callback_t<ModifierValue&&> 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<typename... Args>
- NodeTools::node_callback_t expect_modifier_value_and_keys(
- NodeTools::callback_t<ModifierValue&&> 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/ModifierEffect.cpp b/src/openvic-simulation/modifier/ModifierEffect.cpp
new file mode 100644
index 0000000..eadaf58
--- /dev/null
+++ b/src/openvic-simulation/modifier/ModifierEffect.cpp
@@ -0,0 +1,49 @@
+#include "ModifierEffect.hpp"
+
+#include "openvic-simulation/utility/StringUtils.hpp"
+
+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);
+}
+
+ModifierEffect::ModifierEffect(
+ std::string_view new_identifier, bool new_is_positive_good, format_t new_format, target_t new_targets,
+ std::string_view new_localisation_key, bool new_has_no_effect
+) : HasIdentifier { new_identifier }, positive_good { new_is_positive_good }, format { new_format }, targets { new_targets },
+ localisation_key {
+ new_localisation_key.empty() ? make_default_modifier_effect_localisation_key(new_identifier) : new_localisation_key
+ }, no_effect { new_has_no_effect } {}
diff --git a/src/openvic-simulation/modifier/ModifierEffect.hpp b/src/openvic-simulation/modifier/ModifierEffect.hpp
new file mode 100644
index 0000000..9eb425b
--- /dev/null
+++ b/src/openvic-simulation/modifier/ModifierEffect.hpp
@@ -0,0 +1,64 @@
+#pragma once
+
+#include <string>
+#include <string_view>
+
+#include "openvic-simulation/types/EnumBitfield.hpp"
+#include "openvic-simulation/types/HasIdentifier.hpp"
+
+namespace OpenVic {
+ struct ModifierManager;
+
+ struct ModifierEffect : HasIdentifier {
+ friend struct ModifierManager;
+
+ enum class format_t : uint8_t {
+ PROPORTION_DECIMAL, /* An unscaled fraction/ratio, with 1 being "full"/"whole" */
+ PERCENTAGE_DECIMAL, /* A fraction/ratio scaled so that 100 is "full"/"whole" */
+ RAW_DECIMAL, /* A continuous quantity, e.g. attack strength */
+ INT /* A discrete quantity, e.g. building count limit */
+ };
+
+ enum class target_t : uint8_t {
+ NO_TARGETS = 0,
+ COUNTRY = 1 << 0,
+ PROVINCE = 1 << 1,
+ UNIT = 1 << 2,
+ 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:
+ /* If true, positive values will be green and negative values will be red.
+ * If false, the colours will be switced.
+ */
+ const bool PROPERTY_CUSTOM_PREFIX(positive_good, is);
+ const bool PROPERTY_CUSTOM_PREFIX(no_effect, has);
+ const format_t PROPERTY(format);
+ const target_t PROPERTY(targets);
+ std::string PROPERTY(localisation_key);
+
+ // TODO - format/precision, e.g. 80% vs 0.8 vs 0.800, 2 vs 2.0 vs 200%
+
+ ModifierEffect(
+ std::string_view new_identifier, bool new_is_positive_good, format_t new_format, target_t new_targets,
+ std::string_view new_localisation_key, bool new_has_no_effect
+ );
+
+ public:
+ ModifierEffect(ModifierEffect&&) = default;
+ };
+
+ template<> struct enable_bitfield<ModifierEffect::target_t> : 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/ModifierEffectCache.cpp b/src/openvic-simulation/modifier/ModifierEffectCache.cpp
new file mode 100644
index 0000000..a02dcb6
--- /dev/null
+++ b/src/openvic-simulation/modifier/ModifierEffectCache.cpp
@@ -0,0 +1,251 @@
+#include "ModifierEffectCache.hpp"
+
+#include "openvic-simulation/economy/BuildingType.hpp"
+#include "openvic-simulation/economy/GoodDefinition.hpp"
+#include "openvic-simulation/map/TerrainType.hpp"
+#include "openvic-simulation/politics/Rebel.hpp"
+#include "openvic-simulation/research/Technology.hpp"
+
+using namespace OpenVic;
+
+ModifierEffectCache::building_type_effects_t::building_type_effects_t()
+ : min_level { nullptr },
+ max_level { nullptr } {}
+
+ModifierEffectCache::good_effects_t::good_effects_t()
+ : artisan_goods_input { nullptr },
+ artisan_goods_output { nullptr },
+ artisan_goods_throughput { nullptr },
+ factory_goods_input { nullptr },
+ factory_goods_output { nullptr },
+ factory_goods_throughput { nullptr },
+ rgo_goods_output { nullptr },
+ rgo_goods_throughput { nullptr },
+ rgo_size { nullptr } {}
+
+ModifierEffectCache::unit_type_effects_t::unit_type_effects_t()
+ : attack { nullptr },
+ defence { nullptr },
+ default_organisation { nullptr },
+ maximum_speed { nullptr },
+ build_time { nullptr },
+ supply_consumption { nullptr } {}
+
+ModifierEffectCache::regiment_type_effects_t::regiment_type_effects_t()
+ : unit_type_effects_t {},
+ reconnaissance { nullptr },
+ discipline { nullptr },
+ support { nullptr },
+ maneuver { nullptr },
+ siege { nullptr } {}
+
+ModifierEffectCache::ship_type_effects_t::ship_type_effects_t()
+ : unit_type_effects_t {},
+ colonial_points { nullptr },
+ supply_consumption_score { nullptr },
+ hull { nullptr },
+ gun_power { nullptr },
+ fire_range { nullptr },
+ evasion { nullptr },
+ torpedo_attack { nullptr } {}
+
+ModifierEffectCache::unit_terrain_effects_t::unit_terrain_effects_t()
+ : attack { nullptr },
+ defence { nullptr },
+ attrition { nullptr },
+ movement { nullptr } {}
+
+ModifierEffectCache::strata_effects_t::strata_effects_t()
+ : income_modifier { nullptr },
+ vote { nullptr },
+ life_needs { nullptr },
+ everyday_needs { nullptr },
+ luxury_needs { nullptr } {}
+
+ModifierEffectCache::ModifierEffectCache()
+ : /* Tech/inventions only */
+ cb_creation_speed { nullptr },
+ combat_width_additive { nullptr },
+ plurality { nullptr },
+ pop_growth { nullptr },
+ prestige_gain_multiplier { nullptr },
+ regular_experience_level { nullptr },
+ reinforce_rate { nullptr },
+ separatism { nullptr },
+ shared_prestige { nullptr },
+ tax_eff { nullptr },
+
+ /* Country Modifier Effects */
+ administrative_efficiency { nullptr },
+ administrative_efficiency_modifier { nullptr },
+ artisan_input { nullptr },
+ artisan_output { nullptr },
+ artisan_throughput { nullptr },
+ badboy { nullptr },
+ cb_generation_speed_modifier { nullptr },
+ civilization_progress_modifier { nullptr },
+ colonial_life_rating { nullptr },
+ colonial_migration { nullptr },
+ colonial_points { nullptr },
+ colonial_prestige { nullptr },
+ core_pop_consciousness_modifier { nullptr },
+ core_pop_militancy_modifier { nullptr },
+ dig_in_cap { nullptr },
+ diplomatic_points { nullptr },
+ diplomatic_points_modifier { nullptr },
+ education_efficiency { nullptr },
+ education_efficiency_modifier { nullptr },
+ factory_cost { nullptr },
+ factory_input { nullptr },
+ factory_maintenance { nullptr },
+ factory_output { nullptr },
+ factory_owner_cost { nullptr },
+ factory_throughput { nullptr },
+ global_assimilation_rate { nullptr },
+ global_immigrant_attract { nullptr },
+ global_pop_consciousness_modifier { nullptr },
+ global_pop_militancy_modifier { nullptr },
+ global_population_growth { nullptr },
+ goods_demand { nullptr },
+ import_cost { nullptr },
+ increase_research { nullptr },
+ influence { nullptr },
+ influence_modifier { nullptr },
+ issue_change_speed { nullptr },
+ land_attack_modifier { nullptr },
+ land_attrition { nullptr },
+ land_defense_modifier { nullptr },
+ land_organisation { nullptr },
+ land_unit_start_experience { nullptr },
+ leadership { nullptr },
+ leadership_modifier { nullptr },
+ literacy_con_impact { nullptr },
+ loan_interest_base { nullptr },
+ loan_interest_foreign { nullptr },
+ max_loan_modifier { nullptr },
+ max_military_spending { nullptr },
+ max_national_focus { nullptr },
+ max_social_spending { nullptr },
+ max_tariff { nullptr },
+ max_tax { nullptr },
+ max_war_exhaustion { nullptr },
+ military_tactics { nullptr },
+ min_military_spending { nullptr },
+ min_social_spending { nullptr },
+ min_tariff { nullptr },
+ min_tax { nullptr },
+ minimum_wage { nullptr },
+ mobilisation_economy_impact { nullptr },
+ mobilisation_size { nullptr },
+ mobilization_impact { nullptr },
+ naval_attack_modifier { nullptr },
+ naval_attrition { nullptr },
+ naval_defense_modifier { nullptr },
+ naval_organisation { nullptr },
+ naval_unit_start_experience { nullptr },
+ non_accepted_pop_consciousness_modifier { nullptr },
+ non_accepted_pop_militancy_modifier { nullptr },
+ org_regain { nullptr },
+ pension_level { nullptr },
+ permanent_prestige { nullptr },
+ political_reform_desire { nullptr },
+ poor_savings_modifier { nullptr },
+ prestige_monthly_gain { nullptr },
+ reinforce_speed { nullptr },
+ research_points { nullptr },
+ research_points_modifier { nullptr },
+ research_points_on_conquer { nullptr },
+ rgo_output { nullptr },
+ rgo_throughput { nullptr },
+ ruling_party_support { nullptr },
+ self_unciv_economic_modifier { nullptr },
+ self_unciv_military_modifier { nullptr },
+ social_reform_desire { nullptr },
+ soldier_to_pop_loss { nullptr },
+ supply_consumption { nullptr },
+ supply_range { nullptr },
+ suppression_points_modifier { nullptr },
+ tariff_efficiency_modifier { nullptr },
+ tax_efficiency { nullptr },
+ unemployment_benefit { nullptr },
+ unciv_economic_modifier { nullptr },
+ unciv_military_modifier { nullptr },
+ unit_recruitment_time { nullptr },
+ war_exhaustion { nullptr },
+
+ /* Province Modifier Effects */
+ assimilation_rate { nullptr },
+ boost_strongest_party { nullptr },
+ combat_width_percentage_change { nullptr },
+ defence_terrain { nullptr },
+ farm_rgo_throughput_global { nullptr },
+ farm_rgo_output_global { nullptr },
+ farm_rgo_output_local { nullptr },
+ farm_rgo_size_fake { nullptr },
+ farm_rgo_size_global { nullptr },
+ farm_rgo_size_local { nullptr },
+ immigrant_attract { nullptr },
+ immigrant_push { nullptr },
+ life_rating { nullptr },
+ local_artisan_input { nullptr },
+ local_artisan_output { nullptr },
+ local_artisan_throughput { nullptr },
+ local_factory_input { nullptr },
+ local_factory_output { nullptr },
+ local_factory_throughput { nullptr },
+ local_repair { nullptr },
+ local_rgo_output { nullptr },
+ local_rgo_throughput { nullptr },
+ local_ruling_party_support { nullptr },
+ local_ship_build { nullptr },
+ attrition_local { nullptr },
+ max_attrition { nullptr },
+ mine_rgo_throughput_global { nullptr },
+ mine_rgo_output_global { nullptr },
+ mine_rgo_output_local { nullptr },
+ mine_rgo_size_fake { nullptr },
+ mine_rgo_size_global { nullptr },
+ mine_rgo_size_local { nullptr },
+ movement_cost_base { nullptr },
+ movement_cost_percentage_change { nullptr },
+ number_of_voters { nullptr },
+ pop_consciousness_modifier { nullptr },
+ pop_militancy_modifier { nullptr },
+ population_growth { nullptr },
+ supply_limit_global_percentage_change { nullptr },
+ supply_limit_local_base { nullptr },
+
+ /* Military Modifier Effects */
+ attack_leader { nullptr },
+ attrition_leader { nullptr },
+ defence_leader { nullptr },
+ experience { nullptr },
+ morale_global { nullptr },
+ morale_leader { nullptr },
+ organisation { nullptr },
+ reconnaissance { nullptr },
+ reliability { nullptr },
+ speed { nullptr },
+
+ /* BuildingType Effects */
+ building_type_effects { nullptr },
+
+ /* GoodDefinition Effects */
+ good_effects { nullptr },
+
+ /* UnitType Effects */
+ army_base_effects {},
+ regiment_type_effects { nullptr },
+ navy_base_effects {},
+ ship_type_effects { nullptr },
+ unit_terrain_effects { nullptr },
+
+ /* Rebel Effects */
+ rebel_org_gain_all { nullptr },
+ rebel_org_gain_effects { nullptr },
+
+ /* Pop Effects */
+ strata_effects { nullptr },
+
+ /* Technology Effects */
+ research_bonus_effects { nullptr } {}
diff --git a/src/openvic-simulation/modifier/ModifierEffectCache.hpp b/src/openvic-simulation/modifier/ModifierEffectCache.hpp
new file mode 100644
index 0000000..7d08d29
--- /dev/null
+++ b/src/openvic-simulation/modifier/ModifierEffectCache.hpp
@@ -0,0 +1,341 @@
+#pragma once
+
+#include "openvic-simulation/military/UnitType.hpp"
+#include "openvic-simulation/types/IndexedMap.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ struct ModifierEffect;
+ struct ModifierManager;
+
+ struct BuildingTypeManager;
+ struct BuildingType;
+ struct GoodDefinitionManager;
+ struct GoodDefinition;
+ struct RebelManager;
+ struct RebelType;
+ struct PopManager;
+ struct Strata;
+ struct TechnologyManager;
+ struct TechnologyFolder;
+ struct TerrainTypeManager;
+ struct TerrainType;
+
+ struct ModifierEffectCache {
+ friend struct ModifierManager;
+ friend struct BuildingTypeManager;
+ friend struct GoodDefinitionManager;
+ friend struct UnitTypeManager;
+ friend struct RebelManager;
+ friend struct PopManager;
+ friend struct TechnologyManager;
+ friend struct TerrainTypeManager;
+
+ private:
+ /* Tech/inventions only */
+ ModifierEffect const* PROPERTY(cb_creation_speed);
+ ModifierEffect const* PROPERTY(combat_width_additive);
+ ModifierEffect const* PROPERTY(plurality);
+ ModifierEffect const* PROPERTY(pop_growth);
+ ModifierEffect const* PROPERTY(prestige_gain_multiplier);
+ ModifierEffect const* PROPERTY(regular_experience_level);
+ ModifierEffect const* PROPERTY(reinforce_rate);
+ ModifierEffect const* PROPERTY(separatism);
+ ModifierEffect const* PROPERTY(shared_prestige);
+ ModifierEffect const* PROPERTY(tax_eff);
+
+ /* Country Modifier Effects */
+ ModifierEffect const* PROPERTY(administrative_efficiency);
+ ModifierEffect const* PROPERTY(administrative_efficiency_modifier);
+ ModifierEffect const* PROPERTY(artisan_input);
+ ModifierEffect const* PROPERTY(artisan_output);
+ ModifierEffect const* PROPERTY(artisan_throughput);
+ ModifierEffect const* PROPERTY(badboy);
+ ModifierEffect const* PROPERTY(cb_generation_speed_modifier);
+ ModifierEffect const* PROPERTY(civilization_progress_modifier);
+ ModifierEffect const* PROPERTY(colonial_life_rating);
+ ModifierEffect const* PROPERTY(colonial_migration);
+ ModifierEffect const* PROPERTY(colonial_points);
+ ModifierEffect const* PROPERTY(colonial_prestige);
+ ModifierEffect const* PROPERTY(core_pop_consciousness_modifier);
+ ModifierEffect const* PROPERTY(core_pop_militancy_modifier);
+ ModifierEffect const* PROPERTY(dig_in_cap);
+ ModifierEffect const* PROPERTY(diplomatic_points);
+ ModifierEffect const* PROPERTY(diplomatic_points_modifier);
+ ModifierEffect const* PROPERTY(education_efficiency);
+ ModifierEffect const* PROPERTY(education_efficiency_modifier);
+ ModifierEffect const* PROPERTY(factory_cost);
+ ModifierEffect const* PROPERTY(factory_input);
+ ModifierEffect const* PROPERTY(factory_maintenance);
+ ModifierEffect const* PROPERTY(factory_output);
+ ModifierEffect const* PROPERTY(factory_owner_cost);
+ ModifierEffect const* PROPERTY(factory_throughput);
+ ModifierEffect const* PROPERTY(global_assimilation_rate);
+ ModifierEffect const* PROPERTY(global_immigrant_attract);
+ ModifierEffect const* PROPERTY(global_pop_consciousness_modifier);
+ ModifierEffect const* PROPERTY(global_pop_militancy_modifier);
+ ModifierEffect const* PROPERTY(global_population_growth);
+ ModifierEffect const* PROPERTY(goods_demand);
+ ModifierEffect const* PROPERTY(import_cost);
+ ModifierEffect const* PROPERTY(increase_research);
+ ModifierEffect const* PROPERTY(influence);
+ ModifierEffect const* PROPERTY(influence_modifier);
+ ModifierEffect const* PROPERTY(issue_change_speed);
+ ModifierEffect const* PROPERTY(land_attack_modifier);
+ ModifierEffect const* PROPERTY(land_attrition);
+ ModifierEffect const* PROPERTY(land_defense_modifier);
+ ModifierEffect const* PROPERTY(land_organisation);
+ ModifierEffect const* PROPERTY(land_unit_start_experience);
+ ModifierEffect const* PROPERTY(leadership);
+ ModifierEffect const* PROPERTY(leadership_modifier);
+ ModifierEffect const* PROPERTY(literacy_con_impact);
+ ModifierEffect const* PROPERTY(loan_interest_base);
+ ModifierEffect const* PROPERTY(loan_interest_foreign);
+ ModifierEffect const* PROPERTY(max_loan_modifier);
+ ModifierEffect const* PROPERTY(max_military_spending);
+ ModifierEffect const* PROPERTY(max_national_focus);
+ ModifierEffect const* PROPERTY(max_social_spending);
+ ModifierEffect const* PROPERTY(max_tariff);
+ ModifierEffect const* PROPERTY(max_tax);
+ ModifierEffect const* PROPERTY(max_war_exhaustion);
+ ModifierEffect const* PROPERTY(military_tactics);
+ ModifierEffect const* PROPERTY(min_military_spending);
+ ModifierEffect const* PROPERTY(min_social_spending);
+ ModifierEffect const* PROPERTY(min_tariff);
+ ModifierEffect const* PROPERTY(min_tax);
+ ModifierEffect const* PROPERTY(minimum_wage);
+ ModifierEffect const* PROPERTY(mobilisation_economy_impact);
+ ModifierEffect const* PROPERTY(mobilisation_size);
+ ModifierEffect const* PROPERTY(mobilization_impact);
+ ModifierEffect const* PROPERTY(morale_global);
+ ModifierEffect const* PROPERTY(naval_attack_modifier);
+ ModifierEffect const* PROPERTY(naval_attrition);
+ ModifierEffect const* PROPERTY(naval_defense_modifier);
+ ModifierEffect const* PROPERTY(naval_organisation);
+ ModifierEffect const* PROPERTY(naval_unit_start_experience);
+ ModifierEffect const* PROPERTY(non_accepted_pop_consciousness_modifier);
+ ModifierEffect const* PROPERTY(non_accepted_pop_militancy_modifier);
+ ModifierEffect const* PROPERTY(org_regain);
+ ModifierEffect const* PROPERTY(pension_level);
+ ModifierEffect const* PROPERTY(permanent_prestige);
+ ModifierEffect const* PROPERTY(political_reform_desire);
+ ModifierEffect const* PROPERTY(poor_savings_modifier);
+ ModifierEffect const* PROPERTY(prestige_monthly_gain);
+ ModifierEffect const* PROPERTY(reinforce_speed);
+ ModifierEffect const* PROPERTY(research_points);
+ ModifierEffect const* PROPERTY(research_points_modifier);
+ ModifierEffect const* PROPERTY(research_points_on_conquer);
+ ModifierEffect const* PROPERTY(rgo_output);
+ ModifierEffect const* PROPERTY(rgo_throughput);
+ ModifierEffect const* PROPERTY(ruling_party_support);
+ ModifierEffect const* PROPERTY(self_unciv_economic_modifier);
+ ModifierEffect const* PROPERTY(self_unciv_military_modifier);
+ ModifierEffect const* PROPERTY(social_reform_desire);
+ ModifierEffect const* PROPERTY(soldier_to_pop_loss);
+ ModifierEffect const* PROPERTY(supply_consumption);
+ ModifierEffect const* PROPERTY(supply_range);
+ ModifierEffect const* PROPERTY(suppression_points_modifier);
+ ModifierEffect const* PROPERTY(tariff_efficiency_modifier);
+ ModifierEffect const* PROPERTY(tax_efficiency);
+ ModifierEffect const* PROPERTY(unemployment_benefit);
+ ModifierEffect const* PROPERTY(unciv_economic_modifier);
+ ModifierEffect const* PROPERTY(unciv_military_modifier);
+ ModifierEffect const* PROPERTY(unit_recruitment_time);
+ ModifierEffect const* PROPERTY(war_exhaustion);
+
+ /* Province Modifier Effects */
+ ModifierEffect const* PROPERTY(assimilation_rate);
+ ModifierEffect const* PROPERTY(boost_strongest_party);
+ ModifierEffect const* PROPERTY(combat_width_percentage_change);
+ ModifierEffect const* PROPERTY(defence_terrain);
+ ModifierEffect const* PROPERTY(farm_rgo_throughput_global);
+ ModifierEffect const* PROPERTY(farm_rgo_output_global);
+ ModifierEffect const* PROPERTY(farm_rgo_output_local);
+ ModifierEffect const* PROPERTY(farm_rgo_size_fake);
+ ModifierEffect const* PROPERTY(farm_rgo_size_global);
+ ModifierEffect const* PROPERTY(farm_rgo_size_local);
+ ModifierEffect const* PROPERTY(immigrant_attract);
+ ModifierEffect const* PROPERTY(immigrant_push);
+ ModifierEffect const* PROPERTY(life_rating);
+ ModifierEffect const* PROPERTY(local_artisan_input);
+ ModifierEffect const* PROPERTY(local_artisan_output);
+ ModifierEffect const* PROPERTY(local_artisan_throughput);
+ ModifierEffect const* PROPERTY(local_factory_input);
+ ModifierEffect const* PROPERTY(local_factory_output);
+ ModifierEffect const* PROPERTY(local_factory_throughput);
+ ModifierEffect const* PROPERTY(local_repair);
+ ModifierEffect const* PROPERTY(local_rgo_output);
+ ModifierEffect const* PROPERTY(local_rgo_throughput);
+ ModifierEffect const* PROPERTY(local_ruling_party_support);
+ ModifierEffect const* PROPERTY(local_ship_build);
+ ModifierEffect const* PROPERTY(attrition_local);
+ ModifierEffect const* PROPERTY(max_attrition);
+ ModifierEffect const* PROPERTY(mine_rgo_throughput_global);
+ ModifierEffect const* PROPERTY(mine_rgo_output_global);
+ ModifierEffect const* PROPERTY(mine_rgo_output_local);
+ ModifierEffect const* PROPERTY(mine_rgo_size_fake);
+ ModifierEffect const* PROPERTY(mine_rgo_size_global);
+ ModifierEffect const* PROPERTY(mine_rgo_size_local);
+ ModifierEffect const* PROPERTY(movement_cost_base);
+ ModifierEffect const* PROPERTY(movement_cost_percentage_change);
+ ModifierEffect const* PROPERTY(number_of_voters);
+ ModifierEffect const* PROPERTY(pop_consciousness_modifier);
+ ModifierEffect const* PROPERTY(pop_militancy_modifier);
+ ModifierEffect const* PROPERTY(population_growth);
+ ModifierEffect const* PROPERTY(supply_limit_global_percentage_change);
+ ModifierEffect const* PROPERTY(supply_limit_global_base);
+ ModifierEffect const* PROPERTY(supply_limit_local_base);
+
+ /* Military Modifier Effects */
+ ModifierEffect const* PROPERTY(attack_leader);
+ ModifierEffect const* PROPERTY(attrition_leader);
+ ModifierEffect const* PROPERTY(defence_leader);
+ ModifierEffect const* PROPERTY(experience);
+ ModifierEffect const* PROPERTY(morale_leader);
+ ModifierEffect const* PROPERTY(organisation);
+ ModifierEffect const* PROPERTY(reconnaissance);
+ ModifierEffect const* PROPERTY(reliability);
+ ModifierEffect const* PROPERTY(speed);
+
+ /* BuildingType Effects */
+ public:
+ struct building_type_effects_t {
+ friend struct BuildingTypeManager;
+
+ private:
+ ModifierEffect const* PROPERTY(min_level);
+ ModifierEffect const* PROPERTY(max_level);
+
+ public:
+ building_type_effects_t();
+ };
+
+ private:
+ IndexedMap<BuildingType, building_type_effects_t> PROPERTY(building_type_effects);
+
+ /* GoodDefinition Effects */
+ public:
+ struct good_effects_t {
+ friend struct GoodDefinitionManager;
+
+ private:
+ ModifierEffect const* PROPERTY(artisan_goods_input);
+ ModifierEffect const* PROPERTY(artisan_goods_output);
+ ModifierEffect const* PROPERTY(artisan_goods_throughput);
+ ModifierEffect const* PROPERTY(factory_goods_input);
+ ModifierEffect const* PROPERTY(factory_goods_output);
+ ModifierEffect const* PROPERTY(factory_goods_throughput);
+ ModifierEffect const* PROPERTY(rgo_goods_output);
+ ModifierEffect const* PROPERTY(rgo_goods_throughput);
+ ModifierEffect const* PROPERTY(rgo_size);
+
+ public:
+ good_effects_t();
+ };
+
+ private:
+ IndexedMap<GoodDefinition, good_effects_t> PROPERTY(good_effects);
+
+ /* UnitType Effects */
+ public:
+ struct unit_type_effects_t {
+ friend struct UnitTypeManager;
+
+ private:
+ ModifierEffect const* PROPERTY(attack);
+ ModifierEffect const* PROPERTY(defence);
+ ModifierEffect const* PROPERTY(default_organisation);
+ ModifierEffect const* PROPERTY(maximum_speed);
+ ModifierEffect const* PROPERTY(build_time);
+ ModifierEffect const* PROPERTY(supply_consumption);
+
+ protected:
+ unit_type_effects_t();
+ };
+
+ struct regiment_type_effects_t : unit_type_effects_t {
+ friend struct UnitTypeManager;
+
+ private:
+ ModifierEffect const* PROPERTY(reconnaissance);
+ ModifierEffect const* PROPERTY(discipline);
+ ModifierEffect const* PROPERTY(support);
+ ModifierEffect const* PROPERTY(maneuver);
+ ModifierEffect const* PROPERTY(siege);
+
+ public:
+ regiment_type_effects_t();
+ };
+
+ struct ship_type_effects_t : unit_type_effects_t {
+ friend struct UnitTypeManager;
+
+ private:
+ ModifierEffect const* PROPERTY(colonial_points);
+ ModifierEffect const* PROPERTY(supply_consumption_score);
+ ModifierEffect const* PROPERTY(hull);
+ ModifierEffect const* PROPERTY(gun_power);
+ ModifierEffect const* PROPERTY(fire_range);
+ ModifierEffect const* PROPERTY(evasion);
+ ModifierEffect const* PROPERTY(torpedo_attack);
+
+ public:
+ ship_type_effects_t();
+ };
+
+ private:
+ regiment_type_effects_t PROPERTY(army_base_effects);
+ IndexedMap<RegimentType, regiment_type_effects_t> PROPERTY(regiment_type_effects);
+ ship_type_effects_t PROPERTY(navy_base_effects);
+ IndexedMap<ShipType, ship_type_effects_t> PROPERTY(ship_type_effects);
+
+ /* Unit terrain Effects */
+ public:
+ struct unit_terrain_effects_t {
+ friend struct TerrainTypeManager;
+
+ private:
+ ModifierEffect const* PROPERTY(attack);
+ ModifierEffect const* PROPERTY(defence);
+ ModifierEffect const* PROPERTY(attrition);
+ ModifierEffect const* PROPERTY(movement);
+
+ public:
+ unit_terrain_effects_t();
+ };
+
+ private:
+ IndexedMap<TerrainType, unit_terrain_effects_t> PROPERTY(unit_terrain_effects);
+
+ /* Rebel Effects */
+ ModifierEffect const* PROPERTY(rebel_org_gain_all);
+ IndexedMap<RebelType, ModifierEffect const*> PROPERTY(rebel_org_gain_effects);
+
+ /* Pop Effects */
+ public:
+ struct strata_effects_t {
+ friend struct PopManager;
+
+ private:
+ ModifierEffect const* PROPERTY(income_modifier);
+ ModifierEffect const* PROPERTY(vote);
+ ModifierEffect const* PROPERTY(life_needs);
+ ModifierEffect const* PROPERTY(everyday_needs);
+ ModifierEffect const* PROPERTY(luxury_needs);
+
+ public:
+ strata_effects_t();
+ };
+
+ private:
+ IndexedMap<Strata, strata_effects_t> PROPERTY(strata_effects);
+
+ /* Technology Effects */
+ IndexedMap<TechnologyFolder, ModifierEffect const*> PROPERTY(research_bonus_effects);
+
+ ModifierEffectCache();
+
+ public:
+ ModifierEffectCache(ModifierEffectCache&&) = default;
+ };
+}
diff --git a/src/openvic-simulation/modifier/ModifierManager.cpp b/src/openvic-simulation/modifier/ModifierManager.cpp
new file mode 100644
index 0000000..3bc0c97
--- /dev/null
+++ b/src/openvic-simulation/modifier/ModifierManager.cpp
@@ -0,0 +1,800 @@
+#include "ModifierManager.hpp"
+
+#include <utility>
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/modifier/Modifier.hpp"
+#include "openvic-simulation/modifier/ModifierEffect.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+using namespace OpenVic::StringUtils;
+
+using enum ModifierEffect::target_t;
+
+void ModifierManager::lock_all_modifier_except_base_country_effects() {
+ lock_leader_modifier_effects();
+ lock_unit_terrain_modifier_effects();
+ lock_shared_tech_country_modifier_effects();
+ lock_technology_modifier_effects();
+ lock_base_province_modifier_effects();
+ lock_terrain_modifier_effects();
+}
+
+bool ModifierManager::_register_modifier_effect(
+ modifier_effect_registry_t& registry,
+ ModifierEffect::target_t targets,
+ ModifierEffect const*& effect_cache,
+ const std::string_view identifier,
+ const bool is_positive_good,
+ const ModifierEffect::format_t format,
+ const std::string_view localisation_key,
+ const bool has_no_effect
+) {
+ 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 (!NumberUtils::is_power_of_two(static_cast<uint64_t>(targets))) {
+ Logger::error(
+ "Invalid targets for modifier effect \"", identifier, "\" - ", ModifierEffect::target_to_string(targets),
+ " (can only contain one target)"
+ );
+ 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 = registry.add_item({ std::move(identifier), is_positive_good, format, targets, localisation_key, has_no_effect });
+
+ if (ret) {
+ effect_cache = &registry.get_items().back();
+ }
+
+ return ret;
+}
+
+#define REGISTER_MODIFIER_EFFECT(MAPPING_TYPE, TARGETS) \
+bool ModifierManager::register_##MAPPING_TYPE##_modifier_effect( \
+ ModifierEffect const*& effect_cache, \
+ const std::string_view identifier, \
+ const bool is_positive_good, \
+ const ModifierEffect::format_t format, \
+ const std::string_view localisation_key, \
+ const bool has_no_effect \
+) { \
+ return _register_modifier_effect( \
+ MAPPING_TYPE##_modifier_effects, \
+ TARGETS, \
+ effect_cache, \
+ std::move(identifier), \
+ is_positive_good, \
+ format, \
+ localisation_key, \
+ has_no_effect \
+ ); \
+}
+
+REGISTER_MODIFIER_EFFECT(leader, UNIT)
+REGISTER_MODIFIER_EFFECT(unit_terrain, COUNTRY)
+REGISTER_MODIFIER_EFFECT(shared_tech_country, COUNTRY)
+REGISTER_MODIFIER_EFFECT(technology, COUNTRY)
+REGISTER_MODIFIER_EFFECT(base_country, COUNTRY)
+REGISTER_MODIFIER_EFFECT(base_province, PROVINCE)
+REGISTER_MODIFIER_EFFECT(terrain, PROVINCE)
+
+#undef REGISTER_MODIFIER_EFFECT
+
+bool ModifierManager::setup_modifier_effects() {
+ constexpr bool has_no_effect = true;
+ bool ret = true;
+
+ using enum ModifierEffect::format_t;
+
+ /* Tech/inventions only */
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.cb_creation_speed, "cb_creation_speed", true, PROPORTION_DECIMAL, "CB_MANUFACTURE_TECH"
+ );
+ // When applied to countries (army tech/inventions), combat_width is an additive integer value.
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.combat_width_additive, "combat_width", false, INT
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.plurality, "plurality", true, PERCENTAGE_DECIMAL, "TECH_PLURALITY"
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.pop_growth, "pop_growth", true, PROPORTION_DECIMAL, "TECH_POP_GROWTH"
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.prestige_gain_multiplier, "prestige", true, PROPORTION_DECIMAL,
+ "PRESTIGE_MODIFIER_TECH"
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.regular_experience_level, "regular_experience_level", true, RAW_DECIMAL,
+ "REGULAR_EXP_TECH"
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.reinforce_rate, "reinforce_rate", true, PROPORTION_DECIMAL, "REINFORCE_TECH"
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.separatism, "seperatism", // paradox typo
+ false, PROPORTION_DECIMAL, "SEPARATISM_TECH"
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.shared_prestige, "shared_prestige", true, RAW_DECIMAL, "SHARED_PRESTIGE_TECH"
+ );
+ ret &= register_technology_modifier_effect(modifier_effect_cache.tax_eff, "tax_eff", true, PERCENTAGE_DECIMAL, "TECH_TAX_EFF");
+
+ /* Country Modifier Effects */
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.administrative_efficiency, "administrative_efficiency", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.administrative_efficiency_modifier, "administrative_efficiency_modifier", true,
+ PROPORTION_DECIMAL, ModifierEffect::make_default_modifier_effect_localisation_key("administrative_efficiency")
+ );
+ ret &= register_technology_modifier_effect(modifier_effect_cache.artisan_input, "artisan_input", false, PROPORTION_DECIMAL,{},has_no_effect);
+ ret &= register_technology_modifier_effect(modifier_effect_cache.artisan_output, "artisan_output", true, PROPORTION_DECIMAL,{},has_no_effect);
+ ret &= register_technology_modifier_effect( modifier_effect_cache.artisan_throughput, "artisan_throughput", true, PROPORTION_DECIMAL,{},has_no_effect);
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.badboy, "badboy", false, RAW_DECIMAL);
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.cb_generation_speed_modifier, "cb_generation_speed_modifier", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.civilization_progress_modifier, "civilization_progress_modifier", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("civilization_progress")
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.colonial_life_rating, "colonial_life_rating", false, INT, "COLONIAL_LIFE_TECH"
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.colonial_migration, "colonial_migration", true, PROPORTION_DECIMAL,
+ "COLONIAL_MIGRATION_TECH"
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.colonial_points, "colonial_points", true, INT, "COLONIAL_POINTS_TECH"
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.colonial_prestige, "colonial_prestige", true, PROPORTION_DECIMAL,
+ "COLONIAL_PRESTIGE_MODIFIER_TECH"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.core_pop_consciousness_modifier, "core_pop_consciousness_modifier", false, RAW_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.core_pop_militancy_modifier, "core_pop_militancy_modifier", false, RAW_DECIMAL
+ );
+ ret &= register_technology_modifier_effect(modifier_effect_cache.dig_in_cap, "dig_in_cap", true, INT, "DIGIN_FROM_TECH");
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.diplomatic_points, "diplomatic_points", true, PROPORTION_DECIMAL,
+ "DIPLOMATIC_POINTS_TECH"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.diplomatic_points_modifier, "diplomatic_points_modifier", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("diplopoints_gain")
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.education_efficiency, "education_efficiency", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.education_efficiency_modifier, "education_efficiency_modifier", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("education_efficiency")
+ );
+ ret &= register_shared_tech_country_modifier_effect(modifier_effect_cache.factory_cost, "factory_cost", false, PROPORTION_DECIMAL);
+ ret &= register_shared_tech_country_modifier_effect(modifier_effect_cache.factory_input, "factory_input", false, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.factory_maintenance, "factory_maintenance", false, PROPORTION_DECIMAL
+ );
+ ret &= register_shared_tech_country_modifier_effect(modifier_effect_cache.factory_output, "factory_output", true, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.factory_owner_cost, "factory_owner_cost", false, PROPORTION_DECIMAL
+ );
+ ret &= register_shared_tech_country_modifier_effect(
+ modifier_effect_cache.factory_throughput, "factory_throughput", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.global_assimilation_rate, "global_assimilation_rate", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("assimilation_rate")
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.global_immigrant_attract, "global_immigrant_attract", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("immigant_attract")
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.global_pop_consciousness_modifier, "global_pop_consciousness_modifier", false, RAW_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.global_pop_militancy_modifier, "global_pop_militancy_modifier", false, RAW_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.global_population_growth, "global_population_growth", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("population_growth")
+ );
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.goods_demand, "goods_demand", false, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.import_cost, "import_cost", false, PROPORTION_DECIMAL,{},has_no_effect);
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.increase_research, "increase_research", true, PROPORTION_DECIMAL, "INC_RES_TECH"
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.influence, "influence", true, PROPORTION_DECIMAL, "TECH_GP_INFLUENCE"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.influence_modifier, "influence_modifier", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("greatpower_influence_gain")
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.issue_change_speed, "issue_change_speed", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.land_attack_modifier, "land_attack_modifier", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("land_attack")
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.land_attrition, "land_attrition", false, PROPORTION_DECIMAL, "LAND_ATTRITION_TECH"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.land_defense_modifier, "land_defense_modifier", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("land_defense")
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.land_organisation, "land_organisation", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.land_unit_start_experience, "land_unit_start_experience", true, RAW_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.leadership, "leadership", true, RAW_DECIMAL, "LEADERSHIP");
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.leadership_modifier, "leadership_modifier", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("global_leadership_modifier")
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.literacy_con_impact, "literacy_con_impact", false, PROPORTION_DECIMAL
+ );
+ ret &= register_technology_modifier_effect(modifier_effect_cache.loan_interest_base, "loan_interest", false, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.loan_interest_foreign, "loan_interest", false, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.max_loan_modifier, "max_loan_modifier", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("max_loan_amount")
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.max_military_spending, "max_military_spending", true, PROPORTION_DECIMAL
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.max_national_focus, "max_national_focus", true, INT, "TECH_MAX_FOCUS"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.max_social_spending, "max_social_spending", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.max_tariff, "max_tariff", true, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.max_tax, "max_tax", true, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.max_war_exhaustion, "max_war_exhaustion", true, PERCENTAGE_DECIMAL, "MAX_WAR_EXHAUSTION"
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.military_tactics, "military_tactics", true, PROPORTION_DECIMAL, "MIL_TACTICS_TECH"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.min_military_spending, "min_military_spending", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.min_social_spending, "min_social_spending", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.min_tariff, "min_tariff", true, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.min_tax, "min_tax", true, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.minimum_wage, "minimum_wage", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("minimun_wage")
+ );
+ ret &= register_shared_tech_country_modifier_effect(
+ modifier_effect_cache.mobilisation_economy_impact, "mobilisation_economy_impact", false, PROPORTION_DECIMAL
+ );
+ ret &= register_shared_tech_country_modifier_effect(
+ modifier_effect_cache.mobilisation_size, "mobilisation_size", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.mobilization_impact, "mobilization_impact", false, PROPORTION_DECIMAL
+ );
+ ret &= register_technology_modifier_effect(modifier_effect_cache.morale_global, "morale", true, PROPORTION_DECIMAL, "MORALE_TECH");
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.naval_attack_modifier, "naval_attack_modifier", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("naval_attack")
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.naval_attrition, "naval_attrition", false, PROPORTION_DECIMAL, "NAVAL_ATTRITION_TECH"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.naval_defense_modifier, "naval_defense_modifier", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("naval_defense")
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.naval_organisation, "naval_organisation", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.naval_unit_start_experience, "naval_unit_start_experience", true, RAW_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.non_accepted_pop_consciousness_modifier, "non_accepted_pop_consciousness_modifier", false,
+ RAW_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.non_accepted_pop_militancy_modifier, "non_accepted_pop_militancy_modifier", false, RAW_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.org_regain, "org_regain", true, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.pension_level, "pension_level", true, PROPORTION_DECIMAL);
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.permanent_prestige, "permanent_prestige", true, RAW_DECIMAL, "PERMANENT_PRESTIGE_TECH"
+ );
+ ret &= register_shared_tech_country_modifier_effect(
+ modifier_effect_cache.political_reform_desire, "political_reform_desire", false, PROPORTION_DECIMAL
+ );
+
+ ret &= register_technology_modifier_effect( modifier_effect_cache.poor_savings_modifier, "poor_savings_modifier", true, PROPORTION_DECIMAL,{},has_no_effect);
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.prestige_monthly_gain, "prestige", true, RAW_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.reinforce_speed, "reinforce_speed", true, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.research_points, "research_points", true, RAW_DECIMAL);
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.research_points_modifier, "research_points_modifier", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.research_points_on_conquer, "research_points_on_conquer", true, PROPORTION_DECIMAL
+ );
+ ret &= register_shared_tech_country_modifier_effect(modifier_effect_cache.rgo_output, "rgo_output", true, PROPORTION_DECIMAL);
+ ret &= register_shared_tech_country_modifier_effect(modifier_effect_cache.rgo_throughput, "rgo_throughput", true, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.ruling_party_support, "ruling_party_support", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.self_unciv_economic_modifier, "self_unciv_economic_modifier", false, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("self_unciv_economic")
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.self_unciv_military_modifier, "self_unciv_military_modifier", false, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("self_unciv_military")
+ );
+ ret &= register_shared_tech_country_modifier_effect(
+ modifier_effect_cache.social_reform_desire, "social_reform_desire", false, PROPORTION_DECIMAL
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.soldier_to_pop_loss, "soldier_to_pop_loss", true, PROPORTION_DECIMAL,
+ "SOLDIER_TO_POP_LOSS_TECH"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.supply_consumption, "supply_consumption", false, PROPORTION_DECIMAL
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.supply_range, "supply_range", true, PROPORTION_DECIMAL, "SUPPLY_RANGE_TECH"
+ );
+ ret &= register_shared_tech_country_modifier_effect(
+ modifier_effect_cache.suppression_points_modifier, "suppression_points_modifier", true, PROPORTION_DECIMAL,
+ "SUPPRESSION_TECH"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.tariff_efficiency_modifier, "tariff_efficiency_modifier", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("tariff_efficiency")
+ );
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.tax_efficiency, "tax_efficiency", true, PROPORTION_DECIMAL);
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.unemployment_benefit, "unemployment_benefit", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.unciv_economic_modifier, "unciv_economic_modifier", false, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("unciv_economic"), has_no_effect
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.unciv_military_modifier, "unciv_military_modifier", false, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("unciv_military"), has_no_effect
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.unit_recruitment_time, "unit_recruitment_time", false, PROPORTION_DECIMAL
+ );
+ ret &= register_shared_tech_country_modifier_effect(
+ modifier_effect_cache.war_exhaustion, "war_exhaustion", false, PROPORTION_DECIMAL, "WAR_EXHAUST_BATTLES"
+ );
+
+ /* Province Modifier Effects */
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.assimilation_rate, "assimilation_rate", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.boost_strongest_party, "boost_strongest_party", false, PROPORTION_DECIMAL,{},has_no_effect
+ );
+ // When applied to provinces (terrain), combat_width is a multiplicative proportional decimal value.
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.combat_width_percentage_change, "combat_width", false, PROPORTION_DECIMAL
+ );
+ ret &= register_terrain_modifier_effect(modifier_effect_cache.defence_terrain, "defence", true, INT, "TRAIT_DEFEND");
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.farm_rgo_throughput_global, "farm_rgo_eff", true, PROPORTION_DECIMAL, "TECH_FARM_OUTPUT"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.farm_rgo_output_global, "farm_rgo_eff", true, PROPORTION_DECIMAL, "TECH_FARM_OUTPUT"
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.farm_rgo_output_local, "farm_rgo_eff", true, PROPORTION_DECIMAL, "TECH_FARM_OUTPUT"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.farm_rgo_size_fake, "farm_rgo_size", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("farm_size"), has_no_effect
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.farm_rgo_size_global, "farm_rgo_size", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("farm_size")
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.farm_rgo_size_local, "farm_rgo_size", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("farm_size")
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.immigrant_attract, "immigrant_attract", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("immigant_attract")
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.immigrant_push, "immigrant_push", false, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("immigant_push")
+ );
+ ret &= register_base_province_modifier_effect(modifier_effect_cache.life_rating, "life_rating", true, PROPORTION_DECIMAL);
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.local_artisan_input, "local_artisan_input", false, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("artisan_input"),
+ has_no_effect
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.local_artisan_output, "local_artisan_output", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("artisan_output"),
+ has_no_effect
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.local_artisan_throughput, "local_artisan_throughput", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("artisan_throughput"),
+ has_no_effect
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.local_factory_input, "local_factory_input", false, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("factory_input")
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.local_factory_output, "local_factory_output", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("factory_output")
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.local_factory_throughput, "local_factory_throughput", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("factory_throughput")
+ );
+ ret &= register_base_province_modifier_effect(modifier_effect_cache.local_repair, "local_repair", true, PROPORTION_DECIMAL);
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.local_rgo_output, "local_rgo_output", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("rgo_output")
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.local_rgo_throughput, "local_rgo_throughput", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("rgo_throughput")
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.local_ruling_party_support, "local_ruling_party_support", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("ruling_party_support")
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.local_ship_build, "local_ship_build", false, PROPORTION_DECIMAL
+ );
+ ret &= register_terrain_modifier_effect(modifier_effect_cache.attrition_local, "attrition", false, PROPORTION_DECIMAL, "UA_ATTRITION");
+ ret &= register_base_province_modifier_effect(modifier_effect_cache.max_attrition, "max_attrition", false, RAW_DECIMAL);
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.mine_rgo_throughput_global, "mine_rgo_eff", true, PROPORTION_DECIMAL, "TECH_MINE_OUTPUT"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.mine_rgo_output_global, "mine_rgo_eff", true, PROPORTION_DECIMAL, "TECH_MINE_OUTPUT"
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.mine_rgo_output_local, "mine_rgo_eff", true, PROPORTION_DECIMAL, "TECH_MINE_OUTPUT"
+ );
+ ret &= register_base_country_modifier_effect(
+ modifier_effect_cache.mine_rgo_size_fake, "mine_rgo_size", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("mine_size"), has_no_effect
+ );
+ ret &= register_technology_modifier_effect(
+ modifier_effect_cache.mine_rgo_size_global, "mine_rgo_size", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("mine_size")
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.mine_rgo_size_local, "mine_rgo_size", true, PROPORTION_DECIMAL,
+ ModifierEffect::make_default_modifier_effect_localisation_key("mine_size")
+ );
+ ret &= register_terrain_modifier_effect(
+ modifier_effect_cache.movement_cost_base, "movement_cost", true, PROPORTION_DECIMAL
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.movement_cost_percentage_change, "movement_cost", false, PROPORTION_DECIMAL
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.number_of_voters, "number_of_voters", false, PROPORTION_DECIMAL
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.pop_consciousness_modifier, "pop_consciousness_modifier", false, RAW_DECIMAL
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.pop_militancy_modifier, "pop_militancy_modifier", false, RAW_DECIMAL
+ );
+ ret &= register_base_province_modifier_effect(
+ modifier_effect_cache.population_growth, "population_growth", true, PROPORTION_DECIMAL
+ );
+ ret &= register_technology_modifier_effect(modifier_effect_cache.supply_limit_global_percentage_change, "supply_limit", true, RAW_DECIMAL);
+ ret &= register_base_country_modifier_effect(modifier_effect_cache.supply_limit_global_base, "supply_limit", true, RAW_DECIMAL);
+ ret &= register_base_province_modifier_effect(modifier_effect_cache.supply_limit_local_base, "supply_limit", true, RAW_DECIMAL);
+
+ /* Military Modifier Effects */
+ ret &= register_leader_modifier_effect(modifier_effect_cache.attack_leader, "attack", true, INT, "TRAIT_ATTACK");
+ ret &= register_leader_modifier_effect(modifier_effect_cache.attrition_leader, "attrition", false, RAW_DECIMAL, "ATTRITION");
+ ret &= register_leader_modifier_effect(modifier_effect_cache.defence_leader, "defence", true, INT, "TRAIT_DEFEND");
+ ret &= register_leader_modifier_effect(
+ modifier_effect_cache.experience, "experience", true, PROPORTION_DECIMAL, "TRAIT_EXPERIENCE"
+ );
+ ret &= register_leader_modifier_effect(modifier_effect_cache.morale_leader, "morale", true, PROPORTION_DECIMAL, "TRAIT_MORALE");
+ ret &= register_leader_modifier_effect(
+ modifier_effect_cache.organisation, "organisation", true, PROPORTION_DECIMAL, "TRAIT_ORGANISATION"
+ );
+ ret &= register_leader_modifier_effect(
+ modifier_effect_cache.reconnaissance, "reconnaissance", true, PROPORTION_DECIMAL, "TRAIT_RECONAISSANCE"
+ );
+ ret &= register_leader_modifier_effect(modifier_effect_cache.reliability, "reliability", true, RAW_DECIMAL, "TRAIT_RELIABILITY");
+ ret &= register_leader_modifier_effect(modifier_effect_cache.speed, "speed", true, PROPORTION_DECIMAL, "TRAIT_SPEED");
+
+ return ret;
+}
+
+bool ModifierManager::register_complex_modifier(const 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(
+ const std::string_view complex_modifier_identifier,
+ const std::string_view variant_identifier
+) {
+ return StringUtils::append_string_views(complex_modifier_identifier, " ", variant_identifier);
+}
+
+bool ModifierManager::add_event_modifier(
+ const std::string_view identifier,
+ ModifierValue&& values,
+ const IconModifier::icon_t icon,
+ const Modifier::modifier_type_t type
+) {
+
+ if (identifier.empty()) {
+ Logger::error("Invalid event modifier effect identifier - empty!");
+ return false;
+ }
+
+ return event_modifiers.add_item(
+ { identifier, std::move(values), type, icon }, duplicate_warning_callback
+ );
+}
+
+bool ModifierManager::load_event_modifiers(const 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_dictionary_keys_and_default(
+ expect_base_province_modifier(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);
+
+ return ret;
+}
+
+bool ModifierManager::load_static_modifiers(const ast::NodeCPtr root) {
+ return static_modifier_cache.load_static_modifiers(*this, root);
+}
+
+bool ModifierManager::add_triggered_modifier(
+ const std::string_view identifier,
+ ModifierValue&& values,
+ const IconModifier::icon_t icon,
+ ConditionScript&& trigger
+) {
+ using enum Modifier::modifier_type_t;
+
+ if (identifier.empty()) {
+ Logger::error("Invalid triggered modifier effect identifier - empty!");
+ return false;
+ }
+
+ return triggered_modifiers.add_item(
+ { identifier, std::move(values), TRIGGERED, icon, std::move(trigger) },
+ duplicate_warning_callback
+ );
+}
+
+bool ModifierManager::load_triggered_modifiers(const ast::NodeCPtr root) {
+ const bool ret = expect_dictionary_reserve_length(
+ triggered_modifiers,
+ [this](const std::string_view key, const ast::NodeCPtr value) -> bool {
+ using enum scope_type_t;
+
+ ModifierValue modifier_value {};
+ IconModifier::icon_t icon = 0;
+ ConditionScript trigger { COUNTRY, COUNTRY, NO_SCOPE };
+
+ bool ret = expect_dictionary_keys_and_default(
+ expect_base_country_modifier(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;
+}
+
+bool ModifierManager::_add_flattened_modifier_cb(
+ ModifierValue& modifier_value,
+ const std::string_view prefix,
+ const std::string_view key,
+ const ast::NodeCPtr value
+) const {
+ const std::string flat_identifier = get_flat_identifier(prefix, key);
+ ModifierEffect const* effect = technology_modifier_effects.get_item_by_identifier(flat_identifier);
+ if (effect != nullptr) {
+ return _add_modifier_cb(modifier_value, effect, value);
+ } else {
+ Logger::error("Could not find flattened modifier: ", flat_identifier);
+ return false;
+ }
+};
+
+bool ModifierManager::_add_modifier_cb(
+ ModifierValue& modifier_value,
+ ModifierEffect const* const effect,
+ const ast::NodeCPtr value
+) const {
+ if (effect->has_no_effect()) {
+ Logger::warning("This modifier does nothing: ", effect->get_identifier());
+ }
+ return expect_fixed_point(map_callback(modifier_value.values, effect))(value);
+}
+
+NodeTools::key_value_callback_t ModifierManager::_expect_modifier_effect(
+ modifier_effect_registry_t const& registry,
+ ModifierValue& modifier_value
+) const {
+ return _expect_modifier_effect_with_fallback(registry, modifier_value, key_value_invalid_callback);
+}
+NodeTools::key_value_callback_t ModifierManager::_expect_modifier_effect_with_fallback(
+ modifier_effect_registry_t const& registry,
+ ModifierValue& modifier_value,
+ const NodeTools::key_value_callback_t fallback
+) const {
+ return [this, &registry, &modifier_value, fallback](const std::string_view key, const ast::NodeCPtr value) -> bool {
+ if (dryad::node_has_kind<ast::ListValue>(value) && complex_modifiers.contains(key)) {
+ return expect_dictionary([this, &modifier_value, key](
+ const std::string_view inner_key, const ast::NodeCPtr inner_value
+ ) -> bool {
+ return _add_flattened_modifier_cb(modifier_value, key, inner_key, inner_value);
+ })(value);
+ }
+
+ ModifierEffect const* effect = registry.get_item_by_identifier(key);
+ if (effect == nullptr) {
+ return fallback(key, value);
+ }
+ return _add_modifier_cb(modifier_value, effect, value);
+ };
+}
+NodeTools::key_value_callback_t ModifierManager::_expect_shared_tech_country_modifier_effect(ModifierValue& modifier_value) const {
+ return _expect_modifier_effect(shared_tech_country_modifier_effects, modifier_value);
+}
+NodeTools::key_value_callback_t ModifierManager::expect_leader_modifier(ModifierValue& modifier_value) const {
+ return _expect_modifier_effect(leader_modifier_effects, modifier_value);
+}
+NodeTools::key_value_callback_t ModifierManager::expect_technology_modifier(ModifierValue& modifier_value) const {
+ return [this, &modifier_value](const std::string_view key, const ast::NodeCPtr value) {
+ if (strings_equal_case_insensitive(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(modifier_value, key, faction_identifier, value_node);
+
+ return ret;
+ }
+
+ if (strings_equal_case_insensitive(key, "farm_rgo_eff")) {
+ return _add_modifier_cb(modifier_value, modifier_effect_cache.farm_rgo_throughput_global, value)
+ && _add_modifier_cb(modifier_value, modifier_effect_cache.farm_rgo_output_global, value);
+ }
+
+ if (strings_equal_case_insensitive(key, "mine_rgo_eff")) {
+ return _add_modifier_cb(modifier_value, modifier_effect_cache.mine_rgo_throughput_global, value)
+ && _add_modifier_cb(modifier_value, modifier_effect_cache.mine_rgo_output_global, value);
+ }
+
+ return _expect_modifier_effect_with_fallback(
+ technology_modifier_effects,
+ modifier_value,
+ _expect_shared_tech_country_modifier_effect(modifier_value)
+ )(key, value);
+ };
+}
+NodeTools::key_value_callback_t ModifierManager::expect_unit_terrain_modifier(
+ ModifierValue& modifier_value,
+ const std::string_view terrain_type_identifier
+) const {
+ return [this, &modifier_value, terrain_type_identifier](const std::string_view key, const ast::NodeCPtr value) -> bool {
+ const std::string flat_identifier = get_flat_identifier(key, terrain_type_identifier);
+ ModifierEffect const* effect = unit_terrain_modifier_effects.get_item_by_identifier(flat_identifier);
+ if (effect == nullptr) {
+ return key_value_invalid_callback(flat_identifier, value);
+ }
+ return _add_modifier_cb(modifier_value, effect, value);
+ };
+}
+NodeTools::key_value_callback_t ModifierManager::expect_base_country_modifier(ModifierValue& modifier_value) const {
+ return _expect_modifier_effect_with_fallback(
+ base_country_modifier_effects,
+ modifier_value,
+ _expect_shared_tech_country_modifier_effect(modifier_value)
+ );
+}
+NodeTools::key_value_callback_t ModifierManager::expect_base_province_modifier(ModifierValue& modifier_value) const {
+ return _expect_modifier_effect_with_fallback(
+ base_province_modifier_effects,
+ modifier_value,
+ expect_base_country_modifier(modifier_value)
+ );
+}
+NodeTools::key_value_callback_t ModifierManager::expect_terrain_modifier(ModifierValue& modifier_value) const {
+ return _expect_modifier_effect_with_fallback(
+ terrain_modifier_effects,
+ modifier_value,
+ expect_base_province_modifier(modifier_value)
+ );
+} \ No newline at end of file
diff --git a/src/openvic-simulation/modifier/ModifierManager.hpp b/src/openvic-simulation/modifier/ModifierManager.hpp
new file mode 100644
index 0000000..eb524a3
--- /dev/null
+++ b/src/openvic-simulation/modifier/ModifierManager.hpp
@@ -0,0 +1,136 @@
+#pragma once
+
+#include <string_view>
+
+#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 {
+ struct ModifierManager {
+ friend struct StaticModifierCache;
+ friend struct BuildingTypeManager;
+ friend struct GoodDefinitionManager;
+ friend struct UnitTypeManager;
+ friend struct RebelManager;
+ friend struct PopManager;
+ friend struct TechnologyManager;
+ friend struct TerrainTypeManager;
+
+ using modifier_effect_registry_t = CaseInsensitiveIdentifierRegistry<ModifierEffect, RegistryStorageInfoDeque>;
+
+ /* 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:
+ modifier_effect_registry_t IDENTIFIER_REGISTRY(leader_modifier_effect);
+ modifier_effect_registry_t IDENTIFIER_REGISTRY(unit_terrain_modifier_effect);
+ modifier_effect_registry_t IDENTIFIER_REGISTRY(shared_tech_country_modifier_effect);
+ modifier_effect_registry_t IDENTIFIER_REGISTRY(technology_modifier_effect);
+ modifier_effect_registry_t IDENTIFIER_REGISTRY(base_country_modifier_effect);
+ modifier_effect_registry_t IDENTIFIER_REGISTRY(base_province_modifier_effect);
+ modifier_effect_registry_t IDENTIFIER_REGISTRY(terrain_modifier_effect);
+ case_insensitive_string_set_t complex_modifiers;
+
+ IdentifierRegistry<IconModifier> IDENTIFIER_REGISTRY(event_modifier);
+ IdentifierRegistry<TriggeredModifier> IDENTIFIER_REGISTRY(triggered_modifier);
+
+ ModifierEffectCache PROPERTY(modifier_effect_cache);
+ StaticModifierCache PROPERTY(static_modifier_cache);
+
+ bool _register_modifier_effect(
+ modifier_effect_registry_t& registry,
+ ModifierEffect::target_t targets,
+ ModifierEffect const*& effect_cache,
+ const std::string_view identifier,
+ const bool is_positive_good,
+ const ModifierEffect::format_t format,
+ const std::string_view localisation_key,
+ const bool has_no_effect
+ );
+
+
+#define REGISTER_MODIFIER_EFFECT_DEFINITION(MAPPING_TYPE) \
+ bool register_##MAPPING_TYPE##_modifier_effect( \
+ ModifierEffect const*& effect_cache, \
+ std::string_view identifier, \
+ bool is_positive_good, \
+ ModifierEffect::format_t format, \
+ std::string_view localisation_key = {}, \
+ bool has_no_effect = false \
+ );
+
+ REGISTER_MODIFIER_EFFECT_DEFINITION(leader)
+ REGISTER_MODIFIER_EFFECT_DEFINITION(unit_terrain)
+ REGISTER_MODIFIER_EFFECT_DEFINITION(shared_tech_country)
+ REGISTER_MODIFIER_EFFECT_DEFINITION(technology)
+ REGISTER_MODIFIER_EFFECT_DEFINITION(base_country)
+ REGISTER_MODIFIER_EFFECT_DEFINITION(base_province)
+ REGISTER_MODIFIER_EFFECT_DEFINITION(terrain)
+#undef REGISTER_MODIFIER_EFFECT_DEFINITION
+
+ bool _add_flattened_modifier_cb(
+ ModifierValue& modifier_value,
+ const std::string_view prefix,
+ const std::string_view key,
+ const ast::NodeCPtr value
+ ) const;
+
+ bool _add_modifier_cb(
+ ModifierValue& modifier_value,
+ ModifierEffect const* const effect,
+ const ast::NodeCPtr value
+ ) const;
+
+ NodeTools::key_value_callback_t _expect_modifier_effect(
+ modifier_effect_registry_t const& registry,
+ ModifierValue& modifier_value
+ ) const;
+
+ NodeTools::key_value_callback_t _expect_modifier_effect_with_fallback(
+ modifier_effect_registry_t const& registry,
+ ModifierValue& modifier_value,
+ const NodeTools::key_value_callback_t fallback
+ ) const;
+
+ NodeTools::key_value_callback_t _expect_shared_tech_country_modifier_effect(ModifierValue& modifier_value) const;
+ public:
+ bool register_complex_modifier(const std::string_view identifier);
+ static std::string get_flat_identifier(const std::string_view complex_modifier_identifier, const std::string_view variant_identifier);
+
+ bool setup_modifier_effects();
+
+ bool add_event_modifier(
+ const std::string_view identifier,
+ ModifierValue&& values,
+ const IconModifier::icon_t icon,
+ const Modifier::modifier_type_t type = Modifier::modifier_type_t::EVENT
+ );
+ bool load_event_modifiers(const ast::NodeCPtr root);
+
+ bool load_static_modifiers(const ast::NodeCPtr root);
+
+ bool add_triggered_modifier(
+ const std::string_view identifier,
+ ModifierValue&& values,
+ const IconModifier::icon_t icon,
+ ConditionScript&& trigger
+ );
+ bool load_triggered_modifiers(const ast::NodeCPtr root);
+
+ bool parse_scripts(DefinitionManager const& definition_manager);
+ void lock_all_modifier_except_base_country_effects();
+
+ NodeTools::key_value_callback_t expect_leader_modifier(ModifierValue& modifier_value) const;
+ NodeTools::key_value_callback_t expect_technology_modifier(ModifierValue& modifier_value) const;
+ NodeTools::key_value_callback_t expect_unit_terrain_modifier(
+ ModifierValue& modifier_value,
+ const std::string_view terrain_type_identifier
+ ) const;
+ NodeTools::key_value_callback_t expect_base_country_modifier(ModifierValue& modifier_value) const;
+ NodeTools::key_value_callback_t expect_base_province_modifier(ModifierValue& modifier_value) const;
+ NodeTools::key_value_callback_t expect_terrain_modifier(ModifierValue& modifier_value) const;
+ };
+}
diff --git a/src/openvic-simulation/modifier/ModifierSum.cpp b/src/openvic-simulation/modifier/ModifierSum.cpp
index 8e5ce48..676e872 100644
--- a/src/openvic-simulation/modifier/ModifierSum.cpp
+++ b/src/openvic-simulation/modifier/ModifierSum.cpp
@@ -1,7 +1,28 @@
#include "ModifierSum.hpp"
+#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();
@@ -15,44 +36,88 @@ fixed_point_t ModifierSum::get_effect(ModifierEffect const& effect, bool* effect
return value_sum.get_effect(effect, effect_found);
}
+fixed_point_t ModifierSum::get_effect_nullcheck(ModifierEffect const* effect, bool* effect_found) const {
+ return value_sum.get_effect_nullcheck(effect, effect_found);
+}
+
bool ModifierSum::has_effect(ModifierEffect const& effect) const {
return value_sum.has_effect(effect);
}
-void ModifierSum::add_modifier(Modifier const& modifier, fixed_point_t multiplier) {
- modifiers[&modifier] += multiplier;
- value_sum.multiply_add(modifier, multiplier);
+void ModifierSum::add_modifier(
+ Modifier const& modifier, modifier_source_t const& source, fixed_point_t multiplier,
+ ModifierEffect::target_t excluded_targets
+) {
+ using enum ModifierEffect::target_t;
+
+ // 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 excluded_targets
+) {
+ if (modifier != nullptr) {
+ add_modifier(*modifier, source, multiplier, excluded_targets);
+ }
}
void ModifierSum::add_modifier_sum(ModifierSum const& modifier_sum) {
- modifiers += modifier_sum.modifiers;
+ modifiers.insert(modifiers.end(), modifier_sum.modifiers.begin(), modifier_sum.modifiers.end());
value_sum += modifier_sum.value_sum;
}
-ModifierSum& ModifierSum::operator+=(Modifier const& modifier) {
- add_modifier(modifier);
- return *this;
+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) {
+ add_modifier(
+ *modifier_entry.modifier, modifier_entry.source, modifier_entry.multiplier,
+ modifier_entry.excluded_targets | excluded_targets
+ );
+ }
}
-ModifierSum& ModifierSum::operator+=(ModifierSum const& modifier_sum) {
- add_modifier_sum(modifier_sum);
- return *this;
+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.excluded_targets
+ );
+ }
+ }
}
// TODO - include value_sum[effect] in result? Early return if lookup in value_sum fails?
-std::vector<std::pair<Modifier const*, fixed_point_t>> ModifierSum::get_contributing_modifiers(
- ModifierEffect const& effect
+
+void ModifierSum::push_contributing_modifiers(
+ ModifierEffect const& effect, std::vector<modifier_entry_t>& contributions
) const {
- std::vector<std::pair<Modifier const*, fixed_point_t>> ret;
+ using enum ModifierEffect::target_t;
- for (auto const& [modifier, multiplier] : modifiers) {
- bool effect_found = false;
- const fixed_point_t value = modifier->get_effect(effect, &effect_found);
+ for (modifier_entry_t const& modifier_entry : modifiers) {
+ 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);
- if (effect_found) {
- ret.emplace_back(modifier, value * multiplier);
+ if (effect_found) {
+ contributions.push_back(modifier_entry);
+ }
}
}
+}
+
+std::vector<ModifierSum::modifier_entry_t> ModifierSum::get_contributing_modifiers(ModifierEffect const& effect) const {
+ std::vector<modifier_entry_t> 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 957ffab..843fcfc 100644
--- a/src/openvic-simulation/modifier/ModifierSum.hpp
+++ b/src/openvic-simulation/modifier/ModifierSum.hpp
@@ -1,30 +1,77 @@
#pragma once
-#include "openvic-simulation/modifier/Modifier.hpp"
-#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
+#include <variant>
+
+#include "openvic-simulation/modifier/ModifierValue.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
namespace OpenVic {
+ struct CountryInstance;
+ struct ProvinceInstance;
+ struct Modifier;
+
struct ModifierSum {
+ using modifier_source_t = std::variant<CountryInstance const*, ProvinceInstance const*>;
+
+ 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 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_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:
- fixed_point_map_t<Modifier const*> PROPERTY(modifiers);
+ std::vector<modifier_entry_t> PROPERTY(modifiers);
ModifierValue PROPERTY(value_sum);
public:
ModifierSum() = default;
+ ModifierSum(ModifierSum const&) = default;
ModifierSum(ModifierSum&&) = default;
+ ModifierSum& operator=(ModifierSum const&) = default;
+ ModifierSum& operator=(ModifierSum&&) = default;
void clear();
bool empty();
fixed_point_t get_effect(ModifierEffect const& effect, bool* effect_found = nullptr) const;
+ fixed_point_t get_effect_nullcheck(ModifierEffect const* effect, bool* effect_found = nullptr) const;
bool has_effect(ModifierEffect const& effect) const;
- void add_modifier(Modifier const& modifier, fixed_point_t multiplier = fixed_point_t::_1());
+ void add_modifier(
+ Modifier const& modifier, modifier_source_t const& source, fixed_point_t multiplier = fixed_point_t::_1(),
+ ModifierEffect::target_t excluded_targets = ModifierEffect::target_t::NO_TARGETS
+ );
+ void add_modifier_nullcheck(
+ Modifier const* modifier, modifier_source_t const& source, fixed_point_t multiplier = fixed_point_t::_1(),
+ ModifierEffect::target_t excluded_targets = ModifierEffect::target_t::NO_TARGETS
+ );
void add_modifier_sum(ModifierSum const& modifier_sum);
+ 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);
- ModifierSum& operator+=(Modifier const& modifier);
- ModifierSum& operator+=(ModifierSum const& modifier_sum);
-
- std::vector<std::pair<Modifier const*, fixed_point_t>> get_contributing_modifiers(ModifierEffect const& effect) const;
+ void push_contributing_modifiers(ModifierEffect const& effect, std::vector<modifier_entry_t>& contributions) const;
+ std::vector<modifier_entry_t> get_contributing_modifiers(ModifierEffect const& effect) const;
};
}
diff --git a/src/openvic-simulation/modifier/ModifierValue.cpp b/src/openvic-simulation/modifier/ModifierValue.cpp
new file mode 100644
index 0000000..4461048
--- /dev/null
+++ b/src/openvic-simulation/modifier/ModifierValue.cpp
@@ -0,0 +1,149 @@
+#include "ModifierValue.hpp"
+
+#include "openvic-simulation/utility/TslHelper.hpp"
+
+using namespace OpenVic;
+
+ModifierValue::ModifierValue() = default;
+ModifierValue::ModifierValue(effect_map_t&& new_values) : values { std::move(new_values) } {}
+ModifierValue::ModifierValue(ModifierValue const&) = default;
+ModifierValue::ModifierValue(ModifierValue&&) = default;
+
+ModifierValue& ModifierValue::operator=(ModifierValue const&) = default;
+ModifierValue& ModifierValue::operator=(ModifierValue&&) = default;
+
+void ModifierValue::trim() {
+ erase_if(values, [](effect_map_t::value_type const& value) -> bool {
+ return value.second == fixed_point_t::_0();
+ });
+}
+
+size_t ModifierValue::get_effect_count() const {
+ return values.size();
+}
+
+void ModifierValue::clear() {
+ values.clear();
+}
+
+bool ModifierValue::empty() const {
+ return values.empty();
+}
+
+fixed_point_t ModifierValue::get_effect(ModifierEffect const& effect, bool* effect_found) const {
+ const effect_map_t::const_iterator it = values.find(&effect);
+ if (it != values.end()) {
+ if (effect_found != nullptr) {
+ *effect_found = true;
+ }
+ return it->second;
+ }
+
+ if (effect_found != nullptr) {
+ *effect_found = false;
+ }
+ return fixed_point_t::_0();
+}
+
+fixed_point_t ModifierValue::get_effect_nullcheck(ModifierEffect const* effect, bool* effect_found) const {
+ if (effect != nullptr) {
+ return get_effect(*effect, effect_found);
+ }
+
+ if (effect_found != nullptr) {
+ *effect_found = false;
+ }
+ return fixed_point_t::_0();
+}
+
+bool ModifierValue::has_effect(ModifierEffect const& effect) const {
+ return values.contains(&effect);
+}
+
+void ModifierValue::set_effect(ModifierEffect const& effect, fixed_point_t value) {
+ values[&effect] = value;
+}
+
+ModifierValue& ModifierValue::operator+=(ModifierValue const& right) {
+ for (effect_map_t::value_type const& value : right.values) {
+ values[value.first] += value.second;
+ }
+ return *this;
+}
+
+ModifierValue ModifierValue::operator+(ModifierValue const& right) const {
+ ModifierValue copy = *this;
+ return copy += right;
+}
+
+ModifierValue ModifierValue::operator-() const {
+ ModifierValue copy = *this;
+ for (auto value : mutable_iterator(copy.values)) {
+ value.second = -value.second;
+ }
+ return copy;
+}
+
+ModifierValue& ModifierValue::operator-=(ModifierValue const& right) {
+ for (effect_map_t::value_type const& value : right.values) {
+ values[value.first] -= value.second;
+ }
+ return *this;
+}
+
+ModifierValue ModifierValue::operator-(ModifierValue const& right) const {
+ ModifierValue copy = *this;
+ return copy -= right;
+}
+
+ModifierValue& ModifierValue::operator*=(const fixed_point_t right) {
+ for (auto value : mutable_iterator(values)) {
+ value.second *= right;
+ }
+ return *this;
+}
+
+ModifierValue ModifierValue::operator*(const fixed_point_t right) const {
+ ModifierValue copy = *this;
+ return copy *= right;
+}
+
+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,
+ [excluded_targets](effect_map_t::value_type const& value) -> bool {
+ return !ModifierEffect::excludes_targets(value.first->get_targets(), excluded_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() && excluded_targets == NO_TARGETS) {
+ *this += other;
+ } 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 (ModifierEffect::excludes_targets(value.first->get_targets(), excluded_targets)) {
+ values[value.first] += value.second * multiplier;
+ }
+ }
+ }
+}
+
+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/ModifierValue.hpp b/src/openvic-simulation/modifier/ModifierValue.hpp
new file mode 100644
index 0000000..f693b7a
--- /dev/null
+++ b/src/openvic-simulation/modifier/ModifierValue.hpp
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "openvic-simulation/modifier/ModifierEffect.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
+
+namespace OpenVic {
+ struct ModifierValue {
+ friend struct ModifierManager;
+
+ using effect_map_t = fixed_point_map_t<ModifierEffect const*>;
+
+ private:
+ effect_map_t PROPERTY(values);
+
+ public:
+ ModifierValue();
+ ModifierValue(effect_map_t&& new_values);
+ ModifierValue(ModifierValue const&);
+ ModifierValue(ModifierValue&&);
+
+ ModifierValue& operator=(ModifierValue const&);
+ ModifierValue& operator=(ModifierValue&&);
+
+ /* Removes effect entries with a value of zero. */
+ void trim();
+ size_t get_effect_count() const;
+ void clear();
+ bool empty() const;
+
+ fixed_point_t get_effect(ModifierEffect const& effect, bool* effect_found = nullptr) const;
+ fixed_point_t get_effect_nullcheck(ModifierEffect const* effect, bool* effect_found = nullptr) const;
+ bool has_effect(ModifierEffect const& effect) const;
+ void set_effect(ModifierEffect const& effect, fixed_point_t value);
+
+ ModifierValue& operator+=(ModifierValue const& right);
+ ModifierValue operator+(ModifierValue const& right) const;
+ ModifierValue operator-() const;
+ ModifierValue& operator-=(ModifierValue const& right);
+ ModifierValue operator-(ModifierValue const& right) const;
+ ModifierValue& operator*=(const fixed_point_t right);
+ ModifierValue operator*(const fixed_point_t right) const;
+
+ 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);
+ };
+}
diff --git a/src/openvic-simulation/modifier/StaticModifierCache.cpp b/src/openvic-simulation/modifier/StaticModifierCache.cpp
new file mode 100644
index 0000000..953b49b
--- /dev/null
+++ b/src/openvic-simulation/modifier/StaticModifierCache.cpp
@@ -0,0 +1,171 @@
+#include "StaticModifierCache.hpp"
+
+#include <string_view>
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/modifier/Modifier.hpp"
+#include "openvic-simulation/modifier/ModifierManager.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+using enum Modifier::modifier_type_t;
+
+StaticModifierCache::StaticModifierCache()
+ : // Country modifiers
+ very_easy_player { "very_easy_player", {}, STATIC },
+ easy_player { "easy_player", {}, STATIC },
+ hard_player { "hard_player", {}, STATIC },
+ very_hard_player { "very_hard_player", {}, STATIC },
+ very_easy_ai { "very_easy_ai", {}, STATIC },
+ easy_ai { "easy_ai", {}, STATIC },
+ hard_ai { "hard_ai", {}, STATIC },
+ very_hard_ai { "very_hard_ai", {}, STATIC },
+ base_modifier { "base_values", {}, STATIC },
+ war { "war", {}, STATIC },
+ peace { "peace", {}, STATIC },
+ disarming { "disarming", {}, STATIC },
+ war_exhaustion { "war_exhaustion", {}, STATIC },
+ infamy { "badboy", {}, STATIC },
+ debt_default_to { "debt_default_to", {}, STATIC },
+ great_power { "great_power", {}, STATIC },
+ secondary_power { "second_power", {}, STATIC },
+ civilised { "civ_nation", {}, STATIC },
+ uncivilised { "unciv_nation", {}, STATIC },
+ literacy { "average_literacy", {}, STATIC },
+ plurality { "plurality", {}, STATIC },
+ total_occupation { "total_occupation", {}, STATIC },
+ total_blockaded { "total_blockaded", {}, STATIC },
+ in_bankruptcy { nullptr },
+ bad_debtor { nullptr },
+ generalised_debt_default { nullptr },
+ // Province modifiers
+ overseas { "overseas", {}, STATIC },
+ coastal { "coastal", {}, STATIC },
+ non_coastal { "non_coastal", {}, STATIC },
+ coastal_sea { "coastal_sea", {}, STATIC },
+ sea_zone { "sea_zone", {}, STATIC },
+ land_province { "land_province", {}, STATIC },
+ blockaded { "blockaded", {}, STATIC },
+ no_adjacent_controlled { "no_adjacent_controlled", {}, STATIC },
+ core { "core", {}, STATIC },
+ has_siege { "has_siege", {}, STATIC },
+ occupied { "occupied", {}, STATIC },
+ nationalism { "nationalism", {}, STATIC },
+ infrastructure { "infrastructure", {}, STATIC } {}
+
+bool StaticModifierCache::load_static_modifiers(ModifierManager& modifier_manager, const ast::NodeCPtr root) {
+ bool ret = true;
+ key_map_t key_map {};
+
+ const auto set_static_country_modifier = [&key_map, &modifier_manager, &ret](
+ Modifier& modifier
+ ) -> void {
+ ret &= add_key_map_entry(
+ key_map, modifier.get_identifier(), ONE_EXACTLY,
+ expect_dictionary(modifier_manager.expect_base_country_modifier(modifier))
+ );
+ };
+
+ const auto set_country_event_modifier = [&key_map, &modifier_manager, &ret](
+ const std::string_view identifier, const IconModifier::icon_t icon
+ ) -> void {
+ ret &= add_key_map_entry(
+ key_map, identifier, ONE_EXACTLY,
+ [&modifier_manager, identifier, icon](const ast::NodeCPtr value) -> bool {
+ if (modifier_manager.get_event_modifier_by_identifier(identifier) != nullptr) {
+ return true; //an event modifier overrides a static modifier with the same identifier.
+ }
+
+ ModifierValue modifier_value {};
+ bool has_parsed_modifier = expect_dictionary(modifier_manager.expect_base_country_modifier(modifier_value))(value);
+ has_parsed_modifier &= modifier_manager.add_event_modifier(identifier, std::move(modifier_value), icon, STATIC);
+ return has_parsed_modifier;
+ }
+ );
+
+ };
+
+ const auto set_static_province_modifier = [&key_map, &modifier_manager, &ret](
+ Modifier& modifier
+ ) -> void {
+ ret &= add_key_map_entry(
+ key_map, modifier.get_identifier(), ONE_EXACTLY,
+ expect_dictionary(modifier_manager.expect_base_province_modifier(modifier))
+ );
+ };
+
+ // Country modifiers
+ set_static_country_modifier(very_easy_player);
+ set_static_country_modifier(easy_player);
+ set_static_country_modifier(hard_player);
+ set_static_country_modifier(very_hard_player);
+ set_static_country_modifier(very_easy_ai);
+ set_static_country_modifier(easy_ai);
+ set_static_country_modifier(hard_ai);
+ set_static_country_modifier(very_hard_ai);
+
+ ret &= add_key_map_entry(
+ key_map, base_modifier.get_identifier(), ONE_EXACTLY,
+ expect_dictionary_keys_and_default(
+ modifier_manager.expect_base_country_modifier(base_modifier),
+ "supply_limit", ZERO_OR_ONE, [this, &modifier_manager](const ast::NodeCPtr value) -> bool {
+ return modifier_manager._add_modifier_cb(
+ base_modifier,
+ modifier_manager.get_modifier_effect_cache().get_supply_limit_global_base(),
+ value
+ );
+ }
+ )
+ );
+
+ set_static_country_modifier(war);
+ set_static_country_modifier(peace);
+ set_static_country_modifier(disarming);
+ set_static_country_modifier(war_exhaustion);
+ set_static_country_modifier(infamy);
+ set_static_country_modifier(debt_default_to);
+ set_static_country_modifier(great_power);
+ set_static_country_modifier(secondary_power);
+ set_static_country_modifier(civilised);
+ set_static_country_modifier(uncivilised);
+ set_static_country_modifier(literacy);
+ set_static_country_modifier(plurality);
+ set_static_country_modifier(total_occupation);
+ set_static_country_modifier(total_blockaded);
+
+ // Country Event modifiers
+ static constexpr IconModifier::icon_t default_icon = 0;
+ static constexpr std::string_view bad_debtor_id = "bad_debter"; //paradox typo
+ static constexpr std::string_view in_bankruptcy_id = "in_bankrupcy"; //paradox typo
+ static constexpr std::string_view generalised_debt_default_id = "generalised_debt_default";
+ set_country_event_modifier(bad_debtor_id, default_icon);
+ set_country_event_modifier(in_bankruptcy_id, default_icon);
+ set_country_event_modifier(generalised_debt_default_id, default_icon);
+
+ // Province modifiers
+ set_static_province_modifier(overseas);
+ set_static_province_modifier(coastal);
+ set_static_province_modifier(non_coastal);
+ set_static_province_modifier(coastal_sea);
+ set_static_province_modifier(sea_zone);
+ set_static_province_modifier(land_province);
+ set_static_province_modifier(blockaded);
+ set_static_province_modifier(no_adjacent_controlled);
+ set_static_province_modifier(core);
+ set_static_province_modifier(has_siege);
+ set_static_province_modifier(occupied);
+ set_static_province_modifier(nationalism);
+ set_static_province_modifier(infrastructure);
+
+
+ ret &= expect_dictionary_key_map_and_default(key_map, key_value_invalid_callback)(root);
+
+ if (ret) {
+ bad_debtor = modifier_manager.get_event_modifier_by_identifier(bad_debtor_id);
+ in_bankruptcy = modifier_manager.get_event_modifier_by_identifier(in_bankruptcy_id);
+ generalised_debt_default = modifier_manager.get_event_modifier_by_identifier(generalised_debt_default_id);
+ total_occupation *= 100;
+ }
+
+ return ret;
+}
diff --git a/src/openvic-simulation/modifier/StaticModifierCache.hpp b/src/openvic-simulation/modifier/StaticModifierCache.hpp
new file mode 100644
index 0000000..b31e127
--- /dev/null
+++ b/src/openvic-simulation/modifier/StaticModifierCache.hpp
@@ -0,0 +1,67 @@
+#pragma once
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/modifier/Modifier.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ struct ModifierManager;
+
+ struct StaticModifierCache {
+ friend struct ModifierManager;
+
+ private:
+ // Country modifiers
+ Modifier PROPERTY(very_easy_player);
+ Modifier PROPERTY(easy_player);
+ Modifier PROPERTY(hard_player);
+ Modifier PROPERTY(very_hard_player);
+ Modifier PROPERTY(very_easy_ai);
+ Modifier PROPERTY(easy_ai);
+ Modifier PROPERTY(hard_ai);
+ Modifier PROPERTY(very_hard_ai);
+
+ Modifier PROPERTY(base_modifier);
+ Modifier PROPERTY(war);
+ Modifier PROPERTY(peace);
+ Modifier PROPERTY(disarming);
+ Modifier PROPERTY(war_exhaustion);
+ Modifier PROPERTY(infamy);
+ Modifier PROPERTY(debt_default_to);
+ Modifier PROPERTY(great_power);
+ Modifier PROPERTY(secondary_power);
+ Modifier PROPERTY(civilised);
+ Modifier PROPERTY(uncivilised);
+ Modifier PROPERTY(literacy);
+ Modifier PROPERTY(plurality);
+ Modifier PROPERTY(total_occupation);
+ Modifier PROPERTY(total_blockaded);
+
+ // Country event modifiers
+ Modifier const* PROPERTY(in_bankruptcy);
+ Modifier const* PROPERTY(bad_debtor);
+ Modifier const* PROPERTY(generalised_debt_default); //possibly, as it's used to trigger gunboat CB
+
+ // Province modifiers
+ Modifier PROPERTY(overseas);
+ Modifier PROPERTY(coastal);
+ Modifier PROPERTY(non_coastal);
+ Modifier PROPERTY(coastal_sea);
+ Modifier PROPERTY(sea_zone);
+ Modifier PROPERTY(land_province);
+ Modifier PROPERTY(blockaded);
+ Modifier PROPERTY(no_adjacent_controlled);
+ Modifier PROPERTY(core);
+ Modifier PROPERTY(has_siege);
+ Modifier PROPERTY(occupied);
+ Modifier PROPERTY(nationalism);
+ Modifier PROPERTY(infrastructure);
+
+ StaticModifierCache();
+
+ bool load_static_modifiers(ModifierManager& modifier_manager, const ast::NodeCPtr root);
+
+ public:
+ StaticModifierCache(StaticModifierCache&&) = default;
+ };
+}
diff --git a/src/openvic-simulation/politics/Ideology.cpp b/src/openvic-simulation/politics/Ideology.cpp
index 546d16e..ca21997 100644
--- a/src/openvic-simulation/politics/Ideology.cpp
+++ b/src/openvic-simulation/politics/Ideology.cpp
@@ -83,15 +83,17 @@ bool IdeologyManager::load_ideology_file(ast::NodeCPtr root) {
IdeologyGroup const* ideology_group = get_ideology_group_by_identifier(ideology_group_key);
return expect_dictionary([this, ideology_group](std::string_view key, ast::NodeCPtr value) -> bool {
+ using enum scope_type_t;
+
colour_t colour = colour_t::null();
bool uncivilised = true, can_reduce_militancy = false;
Date spawn_date;
- ConditionalWeight add_political_reform { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
- ConditionalWeight remove_political_reform { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
- ConditionalWeight add_social_reform { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
- ConditionalWeight remove_social_reform { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
- ConditionalWeight add_military_reform { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
- ConditionalWeight add_economic_reform { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
+ ConditionalWeight add_political_reform { COUNTRY, COUNTRY, NO_SCOPE };
+ ConditionalWeight remove_political_reform { COUNTRY, COUNTRY, NO_SCOPE };
+ ConditionalWeight add_social_reform { COUNTRY, COUNTRY, NO_SCOPE };
+ ConditionalWeight remove_social_reform { COUNTRY, COUNTRY, NO_SCOPE };
+ ConditionalWeight add_military_reform { COUNTRY, COUNTRY, NO_SCOPE };
+ ConditionalWeight add_economic_reform { COUNTRY, COUNTRY, NO_SCOPE };
bool ret = expect_dictionary_keys(
"uncivilized", ZERO_OR_ONE, expect_bool(assign_variable_callback(uncivilised)),
@@ -99,20 +101,24 @@ bool IdeologyManager::load_ideology_file(ast::NodeCPtr root) {
"date", ZERO_OR_ONE, expect_date(assign_variable_callback(spawn_date)),
"can_reduce_militancy", ZERO_OR_ONE, expect_bool(assign_variable_callback(can_reduce_militancy)),
"add_political_reform", ONE_EXACTLY, add_political_reform.expect_conditional_weight(ConditionalWeight::BASE),
- "remove_political_reform", ONE_EXACTLY, remove_political_reform.expect_conditional_weight(ConditionalWeight::BASE),
+ "remove_political_reform", ONE_EXACTLY,
+ remove_political_reform.expect_conditional_weight(ConditionalWeight::BASE),
"add_social_reform", ONE_EXACTLY, add_social_reform.expect_conditional_weight(ConditionalWeight::BASE),
"remove_social_reform", ONE_EXACTLY, remove_social_reform.expect_conditional_weight(ConditionalWeight::BASE),
"add_military_reform", ZERO_OR_ONE, add_military_reform.expect_conditional_weight(ConditionalWeight::BASE),
"add_economic_reform", ZERO_OR_ONE, add_economic_reform.expect_conditional_weight(ConditionalWeight::BASE)
)(value);
+
ret &= add_ideology(
key, colour, ideology_group, uncivilised, can_reduce_militancy, spawn_date, std::move(add_political_reform),
std::move(remove_political_reform), std::move(add_social_reform), std::move(remove_social_reform),
std::move(add_military_reform), std::move(add_economic_reform)
);
+
return ret;
})(ideology_group_value);
})(root);
+
lock_ideologies();
return ret;
diff --git a/src/openvic-simulation/politics/Issue.cpp b/src/openvic-simulation/politics/Issue.cpp
index 3174e23..71356b6 100644
--- a/src/openvic-simulation/politics/Issue.cpp
+++ b/src/openvic-simulation/politics/Issue.cpp
@@ -1,5 +1,8 @@
#include "Issue.hpp"
+#include "openvic-simulation/modifier/ModifierManager.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+
using namespace OpenVic;
using namespace OpenVic::NodeTools;
@@ -180,9 +183,14 @@ bool IssueManager::_load_issue(
RuleSet rules;
bool jingoism = false;
- bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(values),
+ bool ret = NodeTools::expect_dictionary_keys_and_default(
+ modifier_manager.expect_base_country_modifier(values),
"is_jingoism", ZERO_OR_ONE, expect_bool(assign_variable_callback(jingoism)),
- "rules", ZERO_OR_ONE, rule_manager.expect_rule_set(move_variable_callback(rules))
+ "rules", ZERO_OR_ONE, rule_manager.expect_rule_set(move_variable_callback(rules)),
+ "war_exhaustion_effect", ZERO_OR_ONE, [](const ast::NodeCPtr _) -> bool {
+ Logger::warning("war_exhaustion_effect does nothing (vanilla issues have it).");
+ return true;
+ }
)(node);
ret &= add_issue(
@@ -213,16 +221,18 @@ bool IssueManager::_load_reform(
ModifierManager const& modifier_manager, RuleManager const& rule_manager, size_t ordinal, std::string_view identifier,
ReformGroup const* group, ast::NodeCPtr node
) {
+ using enum scope_type_t;
+
ModifierValue values;
RuleSet rules;
fixed_point_t administrative_multiplier = 0;
Reform::tech_cost_t technology_cost = 0;
- ConditionScript allow { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
- ConditionScript on_execute_trigger { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
+ ConditionScript allow { COUNTRY, COUNTRY, NO_SCOPE };
+ ConditionScript on_execute_trigger { COUNTRY, COUNTRY, NO_SCOPE };
EffectScript on_execute_effect;
- bool ret = modifier_manager.expect_modifier_value_and_keys(
- move_variable_callback(values),
+ bool ret = NodeTools::expect_dictionary_keys_and_default(
+ modifier_manager.expect_base_country_modifier(values),
"administrative_multiplier", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(administrative_multiplier)),
"technology_cost", ZERO_OR_ONE, expect_uint(assign_variable_callback(technology_cost)),
"allow", ZERO_OR_ONE, allow.expect_script(),
diff --git a/src/openvic-simulation/politics/NationalFocus.cpp b/src/openvic-simulation/politics/NationalFocus.cpp
index 4887ed6..b60b3f5 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"
@@ -116,6 +117,8 @@ bool NationalFocusManager::load_national_foci_file(
[this, &group, &pop_manager, &ideology_manager, &good_definition_manager, &modifier_manager](
std::string_view identifier, ast::NodeCPtr node
) -> bool {
+ using enum scope_type_t;
+
uint8_t icon = 0;
bool has_flashpoint = false, own_provinces = true, outliner_show_as_percent = false;
fixed_point_t flashpoint_tension = 0;
@@ -126,12 +129,12 @@ bool NationalFocusManager::load_national_foci_file(
fixed_point_map_t<GoodDefinition const*> encourage_goods;
fixed_point_map_t<PopType const*> encourage_pop_types;
ConditionScript limit {
- scope_t::PROVINCE | scope_t::COUNTRY, scope_t::PROVINCE | scope_t::COUNTRY, scope_t::NO_SCOPE
+ PROVINCE | COUNTRY, PROVINCE | COUNTRY, NO_SCOPE
};
- bool ret = modifier_manager.expect_modifier_value_and_keys_and_default(
- move_variable_callback(modifiers),
- [&good_definition_manager, &encourage_goods, &pop_manager, &encourage_pop_types](
+ const auto expect_base_province_modifier_cb = modifier_manager.expect_base_province_modifier(modifiers);
+ bool ret = NodeTools::expect_dictionary_keys_and_default(
+ [&good_definition_manager, &encourage_goods, &pop_manager, &encourage_pop_types, &expect_base_province_modifier_cb](
std::string_view key, ast::NodeCPtr value
) -> bool {
GoodDefinition const* good = good_definition_manager.get_good_definition_by_identifier(key);
@@ -144,7 +147,7 @@ bool NationalFocusManager::load_national_foci_file(
return expect_fixed_point(map_callback(encourage_pop_types, pop_type))(value);
}
- return key_value_invalid_callback(key, value);
+ return expect_base_province_modifier_cb(key, value) || key_value_invalid_callback(key, value);
},
"icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon)),
"ideology", ZERO_OR_ONE,
diff --git a/src/openvic-simulation/politics/NationalValue.cpp b/src/openvic-simulation/politics/NationalValue.cpp
index e9f7f2a..9a30fa1 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;
@@ -20,10 +22,12 @@ bool NationalValueManager::load_national_values_file(ModifierManager const& modi
national_values,
[this, &modifier_manager](std::string_view national_value_identifier, ast::NodeCPtr value) -> bool {
ModifierValue modifiers;
-
- bool ret = modifier_manager.expect_modifier_value(move_variable_callback(modifiers))(value);
+ bool ret = NodeTools::expect_dictionary(
+ modifier_manager.expect_base_country_modifier(modifiers)
+ )(value);
ret &= add_national_value(national_value_identifier, std::move(modifiers));
+
return ret;
}
)(root);
diff --git a/src/openvic-simulation/politics/Rebel.cpp b/src/openvic-simulation/politics/Rebel.cpp
index fef61c0..ccaee5e 100644
--- a/src/openvic-simulation/politics/Rebel.cpp
+++ b/src/openvic-simulation/politics/Rebel.cpp
@@ -2,6 +2,8 @@
#include <string_view>
+#include "openvic-simulation/modifier/ModifierManager.hpp"
+
using namespace OpenVic;
using namespace OpenVic::NodeTools;
@@ -96,6 +98,8 @@ bool RebelManager::load_rebels_file(
bool ret = expect_dictionary_reserve_length(
rebel_types,
[this, &ideology_manager, &government_type_manager](std::string_view identifier, ast::NodeCPtr node) -> bool {
+ using enum scope_type_t;
+
RebelType::icon_t icon = 0;
RebelType::area_t area = RebelType::area_t::ALL;
RebelType::government_map_t desired_governments;
@@ -107,11 +111,11 @@ bool RebelManager::load_rebels_file(
allow_all_religions = true, allow_all_ideologies = true, resilient = true, reinforcing = true, general = true,
smart = true, unit_transfer = false;
fixed_point_t occupation_mult = 0;
- ConditionalWeight will_rise { scope_t::POP, scope_t::COUNTRY, scope_t::NO_SCOPE };
- ConditionalWeight spawn_chance { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE };
- ConditionalWeight movement_evaluation { scope_t::PROVINCE, scope_t::PROVINCE, scope_t::NO_SCOPE };
- ConditionScript siege_won_trigger { scope_t::PROVINCE, scope_t::PROVINCE, scope_t::NO_SCOPE };
- ConditionScript demands_enforced_trigger { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
+ ConditionalWeight will_rise { POP, COUNTRY, NO_SCOPE };
+ ConditionalWeight spawn_chance { POP, POP, NO_SCOPE };
+ ConditionalWeight movement_evaluation { PROVINCE, PROVINCE, NO_SCOPE };
+ ConditionScript siege_won_trigger { PROVINCE, PROVINCE, NO_SCOPE };
+ ConditionScript demands_enforced_trigger { COUNTRY, COUNTRY, NO_SCOPE };
EffectScript siege_won_effect, demands_enforced_effect;
bool ret = expect_dictionary_keys(
@@ -175,6 +179,7 @@ bool RebelManager::load_rebels_file(
bool RebelManager::generate_modifiers(ModifierManager& modifier_manager) const {
using enum ModifierEffect::format_t;
+ using enum ModifierEffect::target_t;
bool ret = true;
@@ -183,13 +188,20 @@ bool RebelManager::generate_modifiers(ModifierManager& modifier_manager) const {
ret &= modifier_manager.register_complex_modifier(identifier);
- ret &= modifier_manager.add_modifier_effect(
- ModifierManager::get_flat_identifier(identifier, "all"), is_positive_good, PROPORTION_DECIMAL, "TECH_REBEL_ORG_GAIN"
+ ret &= modifier_manager.register_technology_modifier_effect(
+ modifier_manager.modifier_effect_cache.rebel_org_gain_all, ModifierManager::get_flat_identifier(identifier, "all"),
+ is_positive_good, PROPORTION_DECIMAL, "TECH_REBEL_ORG_GAIN"
);
+ IndexedMap<RebelType, ModifierEffect const*>& rebel_org_gain_effects =
+ modifier_manager.modifier_effect_cache.rebel_org_gain_effects;
+
+ rebel_org_gain_effects.set_keys(&get_rebel_types());
+
for (RebelType const& rebel_type : get_rebel_types()) {
- ret &= modifier_manager.add_modifier_effect(
- ModifierManager::get_flat_identifier(identifier, rebel_type.get_identifier()), is_positive_good, PROPORTION_DECIMAL,
+ ret &= modifier_manager.register_technology_modifier_effect(
+ rebel_org_gain_effects[rebel_type], ModifierManager::get_flat_identifier(identifier, rebel_type.get_identifier()),
+ is_positive_good, PROPORTION_DECIMAL,
StringUtils::append_string_views("$", rebel_type.get_identifier(), "_title$ $TECH_REBEL_ORG_GAIN$")
);
}
diff --git a/src/openvic-simulation/politics/Rebel.hpp b/src/openvic-simulation/politics/Rebel.hpp
index fc82c84..b47bcbb 100644
--- a/src/openvic-simulation/politics/Rebel.hpp
+++ b/src/openvic-simulation/politics/Rebel.hpp
@@ -2,7 +2,6 @@
#include <cstdint>
-#include "openvic-simulation/modifier/Modifier.hpp"
#include "openvic-simulation/politics/Government.hpp"
#include "openvic-simulation/politics/Ideology.hpp"
#include "openvic-simulation/scripts/ConditionalWeight.hpp"
@@ -79,6 +78,8 @@ namespace OpenVic {
RebelType(RebelType&&) = default;
};
+ struct ModifierManager;
+
struct RebelManager {
private:
IdentifierRegistry<RebelType> IDENTIFIER_REGISTRY(rebel_type);
diff --git a/src/openvic-simulation/pop/Pop.cpp b/src/openvic-simulation/pop/Pop.cpp
index dd829d9..89ff609 100644
--- a/src/openvic-simulation/pop/Pop.cpp
+++ b/src/openvic-simulation/pop/Pop.cpp
@@ -2,12 +2,14 @@
#include "openvic-simulation/country/CountryDefinition.hpp"
#include "openvic-simulation/country/CountryInstance.hpp"
+#include "openvic-simulation/defines/Define.hpp"
#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"
+#include "openvic-simulation/utility/Logger.hpp"
#include "openvic-simulation/utility/TslHelper.hpp"
using namespace OpenVic;
@@ -18,7 +20,7 @@ using enum PopType::income_type_t;
PopBase::PopBase(
PopType const& new_type, Culture const& new_culture, Religion const& new_religion, pop_size_t new_size,
fixed_point_t new_militancy, fixed_point_t new_consciousness, RebelType const* new_rebel_type
-) : type { new_type }, culture { new_culture }, religion { new_religion }, size { new_size }, militancy { new_militancy },
+) : type { &new_type }, culture { new_culture }, religion { new_religion }, size { new_size }, militancy { new_militancy },
consciousness { new_consciousness }, rebel_type { new_rebel_type } {}
Pop::Pop(PopBase const& pop_base, decltype(ideologies)::keys_t const& ideology_keys)
@@ -114,6 +116,17 @@ void Pop::setup_pop_test_values(IssueManager const& issue_manager) {
luxury_needs_fulfilled = test_range();
}
+bool Pop::convert_to_equivalent() {
+ PopType const* const equivalent = get_type()->get_equivalent();
+ if (equivalent == nullptr) {
+ Logger::error("Tried to convert pop of type ", get_type()->get_identifier(), " to equivalent, but there is no equivalent.");
+ return false;
+ }
+
+ type = equivalent;
+ return true;
+}
+
void Pop::set_location(ProvinceInstance const& new_location) {
if (location != &new_location) {
location = &new_location;
@@ -128,22 +141,28 @@ void Pop::set_location(ProvinceInstance const& new_location) {
}
void Pop::update_gamestate(
- DefineManager const& define_manager, CountryInstance const* owner, fixed_point_t const& pop_size_per_regiment_multiplier
+ DefineManager const& define_manager, CountryInstance const* owner, const fixed_point_t pop_size_per_regiment_multiplier
) {
- if (type.get_can_be_recruited()) {
+ if (type->get_can_be_recruited()) {
+ MilitaryDefines const& military_defines = define_manager.get_military_defines();
+
if (
- size < define_manager.get_min_pop_size_for_regiment() || owner == nullptr ||
+ size < military_defines.get_min_pop_size_for_regiment() || owner == nullptr ||
!RegimentType::allowed_cultures_check_culture_in_country(owner->get_allowed_regiment_cultures(), culture, *owner)
) {
max_supported_regiments = 0;
} else {
max_supported_regiments = (fixed_point_t::parse(size) / (
- fixed_point_t::parse(define_manager.get_pop_size_per_regiment()) * pop_size_per_regiment_multiplier
+ fixed_point_t::parse(military_defines.get_pop_size_per_regiment()) * pop_size_per_regiment_multiplier
)).to_int64_t() + 1;
}
}
}
+//TODO store income
+void Pop::add_rgo_owner_income(const fixed_point_t income) {}
+void Pop::add_rgo_worker_income(const fixed_point_t income) {}
+
Strata::Strata(std::string_view new_identifier) : HasIdentifier { new_identifier } {}
PopType::PopType(
@@ -235,13 +254,13 @@ bool PopType::parse_scripts(DefinitionManager const& definition_manager) {
PopManager::PopManager()
: slave_sprite { 0 }, administrative_sprite { 0 },
- promotion_chance { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE },
- demotion_chance { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE },
- migration_chance { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE },
- colonialmigration_chance { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE },
- emigration_chance { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE },
- assimilation_chance { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE },
- conversion_chance { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE } {}
+ promotion_chance { scope_type_t::POP, scope_type_t::POP, scope_type_t::NO_SCOPE },
+ demotion_chance { scope_type_t::POP, scope_type_t::POP, scope_type_t::NO_SCOPE },
+ migration_chance { scope_type_t::POP, scope_type_t::POP, scope_type_t::NO_SCOPE },
+ colonialmigration_chance { scope_type_t::POP, scope_type_t::POP, scope_type_t::NO_SCOPE },
+ emigration_chance { scope_type_t::POP, scope_type_t::POP, scope_type_t::NO_SCOPE },
+ assimilation_chance { scope_type_t::POP, scope_type_t::POP, scope_type_t::NO_SCOPE },
+ conversion_chance { scope_type_t::POP, scope_type_t::POP, scope_type_t::NO_SCOPE } {}
bool PopManager::add_strata(std::string_view identifier) {
if (identifier.empty()) {
@@ -422,6 +441,8 @@ bool PopManager::load_pop_type_file(
std::string_view filestem, GoodDefinitionManager const& good_definition_manager, IdeologyManager const& ideology_manager,
ast::NodeCPtr root
) {
+ using enum scope_type_t;
+
colour_t colour = colour_t::null();
Strata const* strata = nullptr;
PopType::sprite_t sprite = 0;
@@ -436,8 +457,8 @@ bool PopManager::load_pop_type_file(
fixed_point_t research_points = 0, leadership_points = 0, research_leadership_optimum = 0,
state_administration_multiplier = 0;
ast::NodeCPtr equivalent = nullptr;
- ConditionalWeight country_migration_target { scope_t::COUNTRY, scope_t::POP, scope_t::NO_SCOPE };
- ConditionalWeight migration_target { scope_t::PROVINCE, scope_t::POP, scope_t::NO_SCOPE };
+ ConditionalWeight country_migration_target { COUNTRY, POP, NO_SCOPE };
+ ConditionalWeight migration_target { PROVINCE, POP, NO_SCOPE };
ast::NodeCPtr promote_to_node = nullptr;
PopType::ideology_weight_map_t ideologies;
ast::NodeCPtr issues_node = nullptr;
@@ -486,9 +507,12 @@ bool PopManager::load_pop_type_file(
"ideologies", ZERO_OR_ONE, ideology_manager.expect_ideology_dictionary_reserve_length(
ideologies,
[&filestem, &ideologies](Ideology const& ideology, ast::NodeCPtr node) -> bool {
- ConditionalWeight weight { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE };
+ ConditionalWeight weight { POP, POP, NO_SCOPE };
+
bool ret = weight.expect_conditional_weight(ConditionalWeight::FACTOR)(node);
+
ret &= map_callback(ideologies, &ideology)(std::move(weight));
+
return ret;
}
),
@@ -545,7 +569,11 @@ bool PopManager::load_pop_type_file(
return ret;
}
-bool PopManager::load_delayed_parse_pop_type_data(UnitTypeManager const& unit_type_manager, IssueManager const& issue_manager) {
+bool PopManager::load_delayed_parse_pop_type_data(
+ UnitTypeManager const& unit_type_manager, IssueManager const& issue_manager
+) {
+ using enum scope_type_t;
+
bool ret = true;
for (size_t index = 0; index < delayed_parse_nodes.size(); ++index) {
const auto [rebel_units, equivalent, promote_to_node, issues_node] = delayed_parse_nodes[index];
@@ -572,7 +600,7 @@ bool PopManager::load_delayed_parse_pop_type_data(UnitTypeManager const& unit_ty
Logger::error("Pop type ", type, " cannot have promotion weight to itself!");
return false;
}
- ConditionalWeight weight { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE };
+ ConditionalWeight weight { POP, POP, NO_SCOPE };
bool ret = weight.expect_conditional_weight(ConditionalWeight::FACTOR)(node);
ret &= map_callback(pop_type->promote_to, &type)(std::move(weight));
return ret;
@@ -593,7 +621,7 @@ bool PopManager::load_delayed_parse_pop_type_data(UnitTypeManager const& unit_ty
Logger::error("Invalid issue in pop type ", pop_type, " issue weights: ", key);
return false;
}
- ConditionalWeight weight { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE };
+ ConditionalWeight weight { POP, POP, NO_SCOPE };
bool ret = weight.expect_conditional_weight(ConditionalWeight::FACTOR)(node);
ret &= map_callback(pop_type->issues, issue)(std::move(weight));
return ret;
@@ -654,24 +682,33 @@ bool PopManager::load_pop_bases_into_vector(
bool PopManager::generate_modifiers(ModifierManager& modifier_manager) const {
using enum ModifierEffect::format_t;
+ using enum ModifierEffect::target_t;
+
+ IndexedMap<Strata, ModifierEffectCache::strata_effects_t>& strata_effects =
+ modifier_manager.modifier_effect_cache.strata_effects;
+
+ strata_effects.set_keys(&get_stratas());
bool ret = true;
for (Strata const& strata : get_stratas()) {
const auto strata_modifier = [&modifier_manager, &ret, &strata](
- std::string_view suffix, bool is_positive_good
+ ModifierEffect const*& effect_cache, std::string_view suffix, bool is_positive_good
) -> void {
- ret &= modifier_manager.add_modifier_effect(
- StringUtils::append_string_views(strata.get_identifier(), suffix), is_positive_good
+ ret &= modifier_manager.register_base_country_modifier_effect(
+ effect_cache, StringUtils::append_string_views(strata.get_identifier(), suffix), is_positive_good,
+ PROPORTION_DECIMAL
);
};
- strata_modifier("_income_modifier", true);
- strata_modifier("_vote", true);
+ ModifierEffectCache::strata_effects_t& this_strata_effects = strata_effects[strata];
+
+ strata_modifier(this_strata_effects.income_modifier, "_income_modifier", true); // Has no effect in game
+ strata_modifier(this_strata_effects.vote, "_vote", true);
- strata_modifier("_life_needs", false);
- strata_modifier("_everyday_needs", false);
- strata_modifier("_luxury_needs", false);
+ strata_modifier(this_strata_effects.life_needs, "_life_needs", false);
+ strata_modifier(this_strata_effects.everyday_needs, "_everyday_needs", false);
+ strata_modifier(this_strata_effects.luxury_needs, "_luxury_needs", false);
}
return ret;
diff --git a/src/openvic-simulation/pop/Pop.hpp b/src/openvic-simulation/pop/Pop.hpp
index 59a7794..f808740 100644
--- a/src/openvic-simulation/pop/Pop.hpp
+++ b/src/openvic-simulation/pop/Pop.hpp
@@ -35,7 +35,7 @@ namespace OpenVic {
using pop_size_t = int32_t;
protected:
- PopType const& PROPERTY_ACCESS(type, protected);
+ PopType const* PROPERTY_ACCESS(type, protected);
Culture const& PROPERTY_ACCESS(culture, protected);
Religion const& PROPERTY_ACCESS(religion, protected);
pop_size_t PROPERTY_ACCESS(size, protected);
@@ -95,13 +95,17 @@ namespace OpenVic {
Pop& operator=(Pop&&) = delete;
void setup_pop_test_values(IssueManager const& issue_manager);
+ bool convert_to_equivalent();
void set_location(ProvinceInstance const& new_location);
void update_gamestate(
DefineManager const& define_manager, CountryInstance const* owner,
- fixed_point_t const& pop_size_per_regiment_multiplier
+ const fixed_point_t pop_size_per_regiment_multiplier
);
+
+ void add_rgo_owner_income(const fixed_point_t income);
+ void add_rgo_worker_income(const fixed_point_t income);
};
struct Strata : HasIdentifier {
diff --git a/src/openvic-simulation/research/Invention.cpp b/src/openvic-simulation/research/Invention.cpp
index 299cefb..4351337 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,12 +55,16 @@ 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](
- std::string_view identifier, ast::NodeCPtr value) -> bool {
+ std::string_view identifier, ast::NodeCPtr value
+ ) -> bool {
+ using enum scope_type_t;
+
+ // TODO - use the same variable for all modifiers rather than combining them at the end?
ModifierValue loose_modifiers;
ModifierValue modifiers;
@@ -71,18 +76,20 @@ bool InventionManager::load_inventions_file(
bool unlock_gas_defence = false;
bool news = true; //defaults to true!
- ConditionScript limit { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
- ConditionalWeight chance { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
+ ConditionScript limit { COUNTRY, COUNTRY, NO_SCOPE };
+ ConditionalWeight chance { COUNTRY, COUNTRY, NO_SCOPE };
- bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(loose_modifiers),
+ bool ret = NodeTools::expect_dictionary_keys_and_default(
+ modifier_manager.expect_base_country_modifier(loose_modifiers),
"news", ZERO_OR_ONE, expect_bool(assign_variable_callback(news)),
"limit", ONE_EXACTLY, limit.expect_script(),
"chance", ONE_EXACTLY, chance.expect_conditional_weight(ConditionalWeight::BASE),
- "effect", ZERO_OR_ONE, modifier_manager.expect_modifier_value_and_keys(
- move_variable_callback(modifiers),
+ "effect", ZERO_OR_ONE, NodeTools::expect_dictionary_keys_and_default(
+ modifier_manager.expect_technology_modifier(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 a5256f3..f2df94b 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;
@@ -141,7 +143,10 @@ bool TechnologyManager::load_technology_file_schools(
technology_schools,
[this, &modifier_manager](std::string_view school_key, ast::NodeCPtr school_value) -> bool {
ModifierValue modifiers;
- bool ret = modifier_manager.expect_modifier_value(move_variable_callback(modifiers))(school_value);
+
+ bool ret = NodeTools::expect_dictionary(
+ modifier_manager.expect_base_country_modifier(modifiers)
+ )(school_value);
ret &= add_technology_school(school_key, std::move(modifiers));
@@ -163,6 +168,8 @@ bool TechnologyManager::load_technologies_file(
return expect_dictionary_reserve_length(technologies, [this, &modifier_manager, &unit_type_manager, &building_type_manager](
std::string_view tech_key, ast::NodeCPtr tech_value
) -> bool {
+ using enum scope_type_t;
+
ModifierValue modifiers;
TechnologyArea const* area = nullptr;
Date::year_t year = 0;
@@ -171,10 +178,10 @@ bool TechnologyManager::load_technologies_file(
std::optional<CountryInstance::unit_variant_t> unit_variant;
Technology::unit_set_t activated_units;
Technology::building_set_t activated_buildings;
- ConditionalWeight ai_chance { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
+ ConditionalWeight ai_chance { COUNTRY, COUNTRY, NO_SCOPE };
- bool ret = modifier_manager.expect_modifier_value_and_keys(
- move_variable_callback(modifiers),
+ bool ret = NodeTools::expect_dictionary_keys_and_default(
+ modifier_manager.expect_technology_modifier(modifiers),
"area", ONE_EXACTLY, expect_technology_area_identifier(assign_variable_callback_pointer(area)),
"year", ONE_EXACTLY, expect_uint(assign_variable_callback(year)),
"cost", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(cost)),
@@ -197,13 +204,21 @@ bool TechnologyManager::load_technologies_file(
bool TechnologyManager::generate_modifiers(ModifierManager& modifier_manager) const {
using enum ModifierEffect::format_t;
+ using enum ModifierEffect::target_t;
+
+ IndexedMap<TechnologyFolder, ModifierEffect const*>& research_bonus_effects =
+ modifier_manager.modifier_effect_cache.research_bonus_effects;
+
+ research_bonus_effects.set_keys(&get_technology_folders());
bool ret = true;
for (TechnologyFolder const& folder : get_technology_folders()) {
const std::string modifier_identifier = StringUtils::append_string_views(folder.get_identifier(), "_research_bonus");
- ret &= modifier_manager.add_modifier_effect(modifier_identifier, true, PROPORTION_DECIMAL, modifier_identifier);
+ ret &= modifier_manager.register_base_country_modifier_effect(
+ research_bonus_effects[folder], modifier_identifier, true, PROPORTION_DECIMAL, modifier_identifier
+ );
}
return ret;
diff --git a/src/openvic-simulation/scripts/Condition.cpp b/src/openvic-simulation/scripts/Condition.cpp
index 7abd717..bb8b662 100644
--- a/src/openvic-simulation/scripts/Condition.cpp
+++ b/src/openvic-simulation/scripts/Condition.cpp
@@ -7,12 +7,12 @@ using namespace OpenVic;
using namespace OpenVic::NodeTools;
using enum value_type_t;
-using enum scope_t;
+using enum scope_type_t;
using enum identifier_type_t;
Condition::Condition(
- std::string_view new_identifier, value_type_t new_value_type, scope_t new_scope,
- scope_t new_scope_change, identifier_type_t new_key_identifier_type,
+ std::string_view new_identifier, value_type_t new_value_type, scope_type_t new_scope,
+ scope_type_t new_scope_change, identifier_type_t new_key_identifier_type,
identifier_type_t new_value_identifier_type
) : HasIdentifier { new_identifier }, value_type { new_value_type }, scope { new_scope },
scope_change { new_scope_change }, key_identifier_type { new_key_identifier_type },
@@ -26,7 +26,7 @@ ConditionNode::ConditionNode(
condition_key_item { new_condition_key_item }, condition_value_item { new_condition_key_item } {}
bool ConditionManager::add_condition(
- std::string_view identifier, value_type_t value_type, scope_t scope, scope_t scope_change,
+ std::string_view identifier, value_type_t value_type, scope_type_t scope, scope_type_t scope_change,
identifier_type_t key_identifier_type, identifier_type_t value_identifier_type
) {
if (identifier.empty()) {
@@ -155,7 +155,7 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana
ret &= add_condition("great_wars_enabled", BOOLEAN, COUNTRY);
ret &= add_condition("have_core_in", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("has_country_flag", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_FLAG);
- ret &= add_condition("has_country_modifier", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, MODIFIER);
+ ret &= add_condition("has_country_modifier", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_EVENT_MODIFIER);
ret &= add_condition("has_cultural_sphere", BOOLEAN, COUNTRY);
ret &= add_condition("has_leader", STRING, COUNTRY);
ret &= add_condition("has_pop_culture", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, CULTURE);
@@ -299,7 +299,7 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana
ret &= add_condition("has_empty_adjacent_state", BOOLEAN, PROVINCE);
ret &= add_condition("has_national_minority", BOOLEAN, PROVINCE);
ret &= add_condition("has_province_flag", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, PROVINCE_FLAG);
- ret &= add_condition("has_province_modifier", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, MODIFIER);
+ ret &= add_condition("has_province_modifier", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, PROVINCE_EVENT_MODIFIER);
ret &= add_condition("has_recent_imigration", INTEGER, PROVINCE); //paradox typo
ret &= add_condition("is_blockaded", BOOLEAN, PROVINCE);
ret &= add_condition("is_accepted_culture", IDENTIFIER | BOOLEAN, PROVINCE, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
@@ -337,8 +337,8 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana
const auto import_identifiers = [this, &ret](
std::vector<std::string_view> const& identifiers,
value_type_t value_type,
- scope_t scope,
- scope_t scope_change = NO_SCOPE,
+ scope_type_t scope,
+ scope_type_t scope_change = NO_SCOPE,
identifier_type_t key_identifier_type = NO_IDENTIFIER,
identifier_type_t value_identifier_type = NO_IDENTIFIER
) -> void {
@@ -505,9 +505,8 @@ callback_t<std::string_view> ConditionManager::expect_parse_identifier(
EXPECT_CALL(BUILDING, building_type, definition_manager.get_economy_manager().get_building_type_manager(), "FACTORY");
EXPECT_CALL(CASUS_BELLI, wargoal_type, definition_manager.get_military_manager().get_wargoal_type_manager());
EXPECT_CALL(GOVERNMENT_TYPE, government_type, definition_manager.get_politics_manager().get_government_type_manager());
- EXPECT_CALL(MODIFIER, event_modifier, definition_manager.get_modifier_manager());
- EXPECT_CALL(MODIFIER, triggered_modifier, definition_manager.get_modifier_manager());
- EXPECT_CALL(MODIFIER, static_modifier, definition_manager.get_modifier_manager());
+ EXPECT_CALL(COUNTRY_EVENT_MODIFIER | PROVINCE_EVENT_MODIFIER, event_modifier, definition_manager.get_modifier_manager());
+ EXPECT_CALL(COUNTRY_EVENT_MODIFIER, triggered_modifier, definition_manager.get_modifier_manager());
EXPECT_CALL(NATIONAL_VALUE, national_value, definition_manager.get_politics_manager().get_national_value_manager());
EXPECT_CALL(
CULTURE_UNION, country_definition, definition_manager.get_country_definition_manager(), "THIS", "FROM", "THIS_UNION"
@@ -524,10 +523,10 @@ callback_t<std::string_view> ConditionManager::expect_parse_identifier(
}
node_callback_t ConditionManager::expect_condition_node(
- DefinitionManager const& definition_manager, Condition const& condition, scope_t this_scope,
- scope_t from_scope, scope_t cur_scope, callback_t<ConditionNode&&> callback
+ DefinitionManager const& definition_manager, Condition const& condition, scope_type_t current_scope,
+ scope_type_t this_scope, scope_type_t from_scope, callback_t<ConditionNode&&> callback
) const {
- return [this, &definition_manager, &condition, callback, this_scope, from_scope, cur_scope](
+ return [this, &definition_manager, &condition, callback, current_scope, this_scope, from_scope](
ast::NodeCPtr node
) -> bool {
bool ret = false;
@@ -535,8 +534,8 @@ node_callback_t ConditionManager::expect_condition_node(
const std::string_view identifier = condition.get_identifier();
const value_type_t value_type = condition.get_value_type();
- const scope_t scope = condition.get_scope();
- const scope_t scope_change = condition.get_scope_change();
+ const scope_type_t scope = condition.get_scope();
+ const scope_type_t scope_change = condition.get_scope_change();
const identifier_type_t key_identifier_type = condition.get_key_identifier_type();
const identifier_type_t value_identifier_type = condition.get_value_identifier_type();
@@ -648,23 +647,24 @@ node_callback_t ConditionManager::expect_condition_node(
if (!ret && share_value_type(value_type, GROUP)) {
ConditionNode::condition_list_t node_list;
ret |= expect_condition_node_list(
- definition_manager, this_scope, from_scope,
- scope_change == NO_SCOPE ? cur_scope : scope_change,
- false,
+ definition_manager,
+ scope_change == NO_SCOPE ? current_scope : scope_change,
+ this_scope,
+ from_scope,
vector_callback(node_list)
)(node);
value = std::move(node_list);
}
// scope validation
- scope_t effective_current_scope = cur_scope;
- if (share_scope(effective_current_scope, THIS)) {
+ scope_type_t effective_current_scope = current_scope;
+ if (share_scope_type(effective_current_scope, THIS)) {
effective_current_scope = this_scope;
- } else if (share_scope(effective_current_scope, FROM)) {
+ } else if (share_scope_type(effective_current_scope, FROM)) {
effective_current_scope = from_scope;
}
- if (!share_scope(scope, effective_current_scope) && effective_current_scope > scope) {
+ if (!share_scope_type(scope, effective_current_scope) && effective_current_scope > scope) {
Logger::warning(
"Condition or scope ", identifier, " was found in wrong scope ", effective_current_scope, ", expected ",
scope, "!"
@@ -707,15 +707,15 @@ static bool top_scope_fallback(std::string_view id, ast::NodeCPtr node) {
};
node_callback_t ConditionManager::expect_condition_node_list(
- DefinitionManager const& definition_manager, scope_t this_scope, scope_t from_scope,
- scope_t cur_scope, bool top_scope, callback_t<ConditionNode&&> callback
+ DefinitionManager const& definition_manager, scope_type_t current_scope, scope_type_t this_scope, scope_type_t from_scope,
+ callback_t<ConditionNode&&> callback, bool top_scope
) const {
- return [this, &definition_manager, callback, this_scope, from_scope, cur_scope, top_scope](ast::NodeCPtr node) -> bool {
+ return [this, &definition_manager, callback, current_scope, this_scope, from_scope, top_scope](ast::NodeCPtr node) -> bool {
const auto expect_node = [
- this, &definition_manager, callback, this_scope, from_scope, cur_scope
+ this, &definition_manager, callback, current_scope, this_scope, from_scope
](Condition const& condition, ast::NodeCPtr node) -> bool {
return expect_condition_node(
- definition_manager, condition, this_scope, from_scope, cur_scope, callback
+ definition_manager, condition, current_scope, this_scope, from_scope, callback
)(node);
};
@@ -730,19 +730,19 @@ node_callback_t ConditionManager::expect_condition_node_list(
}
node_callback_t ConditionManager::expect_condition_script(
- DefinitionManager const& definition_manager, scope_t initial_scope, scope_t this_scope,
- scope_t from_scope, callback_t<ConditionNode&&> callback
+ DefinitionManager const& definition_manager, scope_type_t initial_scope, scope_type_t this_scope,
+ scope_type_t from_scope, callback_t<ConditionNode&&> callback
) const {
return [this, &definition_manager, initial_scope, this_scope, from_scope, callback](ast::NodeCPtr node) -> bool {
ConditionNode::condition_list_t conds;
bool ret = expect_condition_node_list(
definition_manager,
+ initial_scope,
this_scope,
from_scope,
- initial_scope,
- true,
- NodeTools::vector_callback(conds)
+ NodeTools::vector_callback(conds),
+ true
)(node);
ret &= callback({ root_condition, std::move(conds), true });
diff --git a/src/openvic-simulation/scripts/Condition.hpp b/src/openvic-simulation/scripts/Condition.hpp
index 748453f..1f4929a 100644
--- a/src/openvic-simulation/scripts/Condition.hpp
+++ b/src/openvic-simulation/scripts/Condition.hpp
@@ -27,7 +27,7 @@ namespace OpenVic {
// Order matters in this enum, for the fallback system to work
// smaller entities must have smaller integers associated!
- enum class scope_t : uint8_t { //TODO: maybe distinguish TRANSPARENT from NO_SCOPE
+ enum class scope_type_t : uint8_t { //TODO: maybe distinguish TRANSPARENT from NO_SCOPE
NO_SCOPE = 0,
POP = 1 << 0,
PROVINCE = 1 << 1,
@@ -63,25 +63,26 @@ namespace OpenVic {
BUILDING = 1 << 20,
CASUS_BELLI = 1 << 21,
GOVERNMENT_TYPE = 1 << 22,
- MODIFIER = 1 << 23,
- NATIONAL_VALUE = 1 << 24,
- CULTURE_UNION = 1 << 25, // same as COUNTRY_TAG but also accepts scope this_union
- CONTINENT = 1 << 26,
- CRIME = 1 << 27,
- TERRAIN = 1 << 28,
+ COUNTRY_EVENT_MODIFIER = 1 << 23,
+ PROVINCE_EVENT_MODIFIER = 1 << 24,
+ NATIONAL_VALUE = 1 << 25,
+ CULTURE_UNION = 1 << 26, // same as COUNTRY_TAG but also accepts scope this_union
+ CONTINENT = 1 << 27,
+ CRIME = 1 << 28,
+ TERRAIN = 1 << 29
};
/* Allows enum types to be used with bitwise operators. */
template<> struct enable_bitfield<value_type_t> : std::true_type {};
- template<> struct enable_bitfield<scope_t> : std::true_type {};
+ template<> struct enable_bitfield<scope_type_t> : std::true_type {};
template<> struct enable_bitfield<identifier_type_t> : std::true_type {};
/* Returns true if the values have any bit in common. */
inline constexpr bool share_value_type(value_type_t lhs, value_type_t rhs) {
return (lhs & rhs) != value_type_t::NO_TYPE;
}
- inline constexpr bool share_scope(scope_t lhs, scope_t rhs) {
- return (lhs & rhs) != scope_t::NO_SCOPE;
+ inline constexpr bool share_scope_type(scope_type_t lhs, scope_type_t rhs) {
+ return (lhs & rhs) != scope_type_t::NO_SCOPE;
}
inline constexpr bool share_identifier_type(identifier_type_t lhs, identifier_type_t rhs) {
return (lhs & rhs) != identifier_type_t::NO_IDENTIFIER;
@@ -121,10 +122,10 @@ namespace OpenVic {
}
#undef BUILD_STRING
-#define BUILD_STRING(entry) _BUILD_STRING(entry, share_scope)
+#define BUILD_STRING(entry) _BUILD_STRING(entry, share_scope_type)
- inline std::ostream& operator<<(std::ostream& stream, scope_t value) {
- using enum scope_t;
+ inline std::ostream& operator<<(std::ostream& stream, scope_type_t value) {
+ using enum scope_type_t;
if (value == NO_SCOPE) {
return stream << "[NO_SCOPE]";
}
@@ -175,7 +176,8 @@ namespace OpenVic {
BUILD_STRING(BUILDING);
BUILD_STRING(CASUS_BELLI);
BUILD_STRING(GOVERNMENT_TYPE);
- BUILD_STRING(MODIFIER);
+ BUILD_STRING(COUNTRY_EVENT_MODIFIER);
+ BUILD_STRING(PROVINCE_EVENT_MODIFIER);
BUILD_STRING(NATIONAL_VALUE);
BUILD_STRING(CULTURE_UNION);
BUILD_STRING(CONTINENT);
@@ -196,14 +198,14 @@ namespace OpenVic {
private:
const value_type_t PROPERTY(value_type);
- const scope_t PROPERTY(scope);
- const scope_t PROPERTY(scope_change);
+ const scope_type_t PROPERTY(scope);
+ const scope_type_t PROPERTY(scope_change);
const identifier_type_t PROPERTY(key_identifier_type);
const identifier_type_t PROPERTY(value_identifier_type);
Condition(
- std::string_view new_identifier, value_type_t new_value_type, scope_t new_scope,
- scope_t new_scope_change, identifier_type_t new_key_identifier_type,
+ std::string_view new_identifier, value_type_t new_value_type, scope_type_t new_scope,
+ scope_type_t new_scope_change, identifier_type_t new_key_identifier_type,
identifier_type_t new_value_identifier_type
);
@@ -247,8 +249,8 @@ namespace OpenVic {
Condition const* root_condition = nullptr;
bool add_condition(
- std::string_view identifier, value_type_t value_type, scope_t scope,
- scope_t scope_change = scope_t::NO_SCOPE,
+ std::string_view identifier, value_type_t value_type, scope_type_t scope,
+ scope_type_t scope_change = scope_type_t::NO_SCOPE,
identifier_type_t key_identifier_type = identifier_type_t::NO_IDENTIFIER,
identifier_type_t value_identifier_type = identifier_type_t::NO_IDENTIFIER
);
@@ -259,21 +261,21 @@ namespace OpenVic {
) const;
NodeTools::node_callback_t expect_condition_node(
- DefinitionManager const& definition_manager, Condition const& condition, scope_t this_scope,
- scope_t from_scope, scope_t cur_scope, NodeTools::callback_t<ConditionNode&&> callback
+ DefinitionManager const& definition_manager, Condition const& condition, scope_type_t current_scope,
+ scope_type_t this_scope, scope_type_t from_scope, NodeTools::callback_t<ConditionNode&&> callback
) const;
NodeTools::node_callback_t expect_condition_node_list(
- DefinitionManager const& definition_manager, scope_t this_scope, scope_t from_scope,
- scope_t cur_scope, bool top_scope, NodeTools::callback_t<ConditionNode&&> callback
+ DefinitionManager const& definition_manager, scope_type_t current_scope, scope_type_t this_scope,
+ scope_type_t from_scope, NodeTools::callback_t<ConditionNode&&> callback, bool top_scope = false
) const;
public:
bool setup_conditions(DefinitionManager const& definition_manager);
NodeTools::node_callback_t expect_condition_script(
- DefinitionManager const& definition_manager, scope_t initial_scope, scope_t this_scope, scope_t from_scope,
- NodeTools::callback_t<ConditionNode&&> callback
+ DefinitionManager const& definition_manager, scope_type_t initial_scope, scope_type_t this_scope,
+ scope_type_t from_scope, NodeTools::callback_t<ConditionNode&&> callback
) const;
};
}
diff --git a/src/openvic-simulation/scripts/ConditionScript.cpp b/src/openvic-simulation/scripts/ConditionScript.cpp
index bee4d07..c556bd2 100644
--- a/src/openvic-simulation/scripts/ConditionScript.cpp
+++ b/src/openvic-simulation/scripts/ConditionScript.cpp
@@ -6,7 +6,7 @@ using namespace OpenVic;
using namespace OpenVic::NodeTools;
ConditionScript::ConditionScript(
- scope_t new_initial_scope, scope_t new_this_scope, scope_t new_from_scope
+ scope_type_t new_initial_scope, scope_type_t new_this_scope, scope_type_t new_from_scope
) : initial_scope { new_initial_scope }, this_scope { new_this_scope }, from_scope { new_from_scope } {}
bool ConditionScript::_parse_script(ast::NodeCPtr root, DefinitionManager const& definition_manager) {
diff --git a/src/openvic-simulation/scripts/ConditionScript.hpp b/src/openvic-simulation/scripts/ConditionScript.hpp
index e6ed255..aa386e8 100644
--- a/src/openvic-simulation/scripts/ConditionScript.hpp
+++ b/src/openvic-simulation/scripts/ConditionScript.hpp
@@ -10,14 +10,14 @@ namespace OpenVic {
private:
ConditionNode PROPERTY_REF(condition_root);
- scope_t PROPERTY(initial_scope);
- scope_t PROPERTY(this_scope);
- scope_t PROPERTY(from_scope);
+ scope_type_t PROPERTY(initial_scope);
+ scope_type_t PROPERTY(this_scope);
+ scope_type_t PROPERTY(from_scope);
protected:
bool _parse_script(ast::NodeCPtr root, DefinitionManager const& definition_manager) override;
public:
- ConditionScript(scope_t new_initial_scope, scope_t new_this_scope, scope_t new_from_scope);
+ ConditionScript(scope_type_t new_initial_scope, scope_type_t new_this_scope, scope_type_t new_from_scope);
};
}
diff --git a/src/openvic-simulation/scripts/ConditionalWeight.cpp b/src/openvic-simulation/scripts/ConditionalWeight.cpp
index 7c3e0a0..1bb83d0 100644
--- a/src/openvic-simulation/scripts/ConditionalWeight.cpp
+++ b/src/openvic-simulation/scripts/ConditionalWeight.cpp
@@ -3,12 +3,12 @@
using namespace OpenVic;
using namespace OpenVic::NodeTools;
-ConditionalWeight::ConditionalWeight(scope_t new_initial_scope, scope_t new_this_scope, scope_t new_from_scope)
+ConditionalWeight::ConditionalWeight(scope_type_t new_initial_scope, scope_type_t new_this_scope, scope_type_t new_from_scope)
: initial_scope { new_initial_scope }, this_scope { new_this_scope }, from_scope { new_from_scope } {}
template<typename T>
static NodeCallback auto expect_modifier(
- std::vector<T>& items, scope_t initial_scope, scope_t this_scope, scope_t from_scope
+ std::vector<T>& items, scope_type_t initial_scope, scope_type_t this_scope, scope_type_t from_scope
) {
return [&items, initial_scope, this_scope, from_scope](ast::NodeCPtr node) -> bool {
fixed_point_t weight = 0;
@@ -26,23 +26,86 @@ static NodeCallback auto expect_modifier(
}
node_callback_t ConditionalWeight::expect_conditional_weight(base_key_t base_key) {
- return expect_dictionary_keys(
- // TODO - add days and years as options with a shared expected count of ONE_EXACTLY
- base_key_to_string(base_key), ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(base)),
- "days", ZERO_OR_ONE, success_callback,
- "years", ZERO_OR_ONE, success_callback,
+ key_map_t key_map;
+ bool successfully_set_up_base_keys = true;
+
+ switch (base_key) {
+ case BASE:
+ {
+ successfully_set_up_base_keys &= add_key_map_entry(
+ key_map,
+ "base", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base))
+ );
+
+ break;
+ }
+ case FACTOR:
+ {
+ successfully_set_up_base_keys &= add_key_map_entry(
+ key_map,
+ "factor", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base))
+ );
+
+ break;
+ }
+ case TIME:
+ {
+ const auto time_callback = [this](std::string_view key, Timespan (*to_timespan)(Timespan::day_t)) -> auto {
+ return [this, key, to_timespan](uint32_t value) -> bool {
+ if (base == fixed_point_t::_0()) {
+ base = fixed_point_t::parse((*to_timespan)(value).to_int());
+ return true;
+ } else {
+ Logger::error(
+ "ConditionalWeight cannot have multiple base values - trying to set base to ", value, " ", key,
+ " when it already has a value equivalent to ", base, " days!"
+ );
+ return false;
+ }
+ };
+ };
+
+ successfully_set_up_base_keys &= add_key_map_entries(
+ key_map,
+ "days", ZERO_OR_ONE, expect_uint<uint32_t>(time_callback("days", Timespan::from_days)),
+ "months", ZERO_OR_ONE, expect_uint<uint32_t>(time_callback("months", Timespan::from_months)),
+ "years", ZERO_OR_ONE, expect_uint<uint32_t>(time_callback("years", Timespan::from_years))
+ );
+
+ break;
+ }
+ default:
+ {
+ successfully_set_up_base_keys = false;
+ }
+ }
+
+ if (!successfully_set_up_base_keys) {
+ return [base_key](ast::NodeCPtr node) -> bool {
+ Logger::error(
+ "Failed to set up base keys for ConditionalWeight with base value: ", static_cast<uint32_t>(base_key)
+ );
+ return false;
+ };
+ }
+
+ return expect_dictionary_key_map(
+ std::move(key_map),
"modifier", ZERO_OR_MORE, expect_modifier(condition_weight_items, initial_scope, this_scope, from_scope),
"group", ZERO_OR_MORE, [this](ast::NodeCPtr node) -> bool {
condition_weight_group_t items;
+
const bool ret = expect_dictionary_keys(
"modifier", ONE_OR_MORE, expect_modifier(items, initial_scope, this_scope, from_scope)
)(node);
+
if (!items.empty()) {
condition_weight_items.emplace_back(std::move(items));
return ret;
+ } else {
+ Logger::error("ConditionalWeight group must have at least one modifier!");
+ return false;
}
- Logger::error("ConditionalWeight group must have at least one modifier!");
- return false;
}
);
}
diff --git a/src/openvic-simulation/scripts/ConditionalWeight.hpp b/src/openvic-simulation/scripts/ConditionalWeight.hpp
index c99d6b0..fcab0a6 100644
--- a/src/openvic-simulation/scripts/ConditionalWeight.hpp
+++ b/src/openvic-simulation/scripts/ConditionalWeight.hpp
@@ -14,32 +14,23 @@ namespace OpenVic {
using condition_weight_item_t = std::variant<condition_weight_t, condition_weight_group_t>;
enum class base_key_t : uint8_t {
- BASE, FACTOR, MONTHS
+ BASE, FACTOR, TIME
};
using enum base_key_t;
private:
fixed_point_t PROPERTY(base);
std::vector<condition_weight_item_t> PROPERTY(condition_weight_items);
- scope_t PROPERTY(initial_scope);
- scope_t PROPERTY(this_scope);
- scope_t PROPERTY(from_scope);
+ scope_type_t PROPERTY(initial_scope);
+ scope_type_t PROPERTY(this_scope);
+ scope_type_t PROPERTY(from_scope);
struct parse_scripts_visitor_t;
public:
- ConditionalWeight(scope_t new_initial_scope, scope_t new_this_scope, scope_t new_from_scope);
+ ConditionalWeight(scope_type_t new_initial_scope, scope_type_t new_this_scope, scope_type_t new_from_scope);
ConditionalWeight(ConditionalWeight&&) = default;
- static constexpr std::string_view base_key_to_string(base_key_t base_key) {
- switch (base_key) {
- case base_key_t::BASE: return "base";
- case base_key_t::FACTOR: return "factor";
- case base_key_t::MONTHS: return "months"; // TODO - add functionality for days or months or years
- default: return "INVALID BASE KEY";
- }
- }
-
NodeTools::node_callback_t expect_conditional_weight(base_key_t base_key);
bool parse_scripts(DefinitionManager const& definition_manager);
diff --git a/src/openvic-simulation/types/IndexedMap.hpp b/src/openvic-simulation/types/IndexedMap.hpp
index 73ff313..4f6fc9c 100644
--- a/src/openvic-simulation/types/IndexedMap.hpp
+++ b/src/openvic-simulation/types/IndexedMap.hpp
@@ -19,6 +19,7 @@ namespace OpenVic {
using keys_t = std::vector<key_t>;
using key_type = key_t; // To match tsl::ordered_map's key_type
+ using mapped_type = value_t; // To match tsl::ordered_map's mapped_type
using container_t::operator[];
using container_t::size;
diff --git a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
index 7752226..bc74d1c 100644
--- a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
+++ b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
@@ -38,6 +38,11 @@ namespace OpenVic {
#include "openvic-simulation/types/fixed_point/FixedPointLUT_sin.hpp"
static_assert(SIN_LUT_PRECISION == PRECISION);
+
+ // Doesn't account for sign, so -n.abc -> 1 - 0.abc
+ constexpr fixed_point_t get_frac() const {
+ return value & FRAC_MASK;
+ }
public:
constexpr fixed_point_t() : value { 0 } {}
@@ -74,110 +79,22 @@ namespace OpenVic {
return 2;
}
- static constexpr fixed_point_t _3() {
- return 3;
- }
-
static constexpr fixed_point_t _4() {
return 4;
}
- static constexpr fixed_point_t _5() {
- return 5;
- }
-
- static constexpr fixed_point_t _6() {
- return 6;
- }
-
- static constexpr fixed_point_t _7() {
- return 7;
- }
-
- static constexpr fixed_point_t _8() {
- return 8;
- }
-
- static constexpr fixed_point_t _9() {
- return 9;
- }
-
- static constexpr fixed_point_t _10() {
- return 10;
- }
-
- static constexpr fixed_point_t _50() {
- return 50;
- }
-
static constexpr fixed_point_t _100() {
return 100;
}
- static constexpr fixed_point_t _200() {
- return 200;
- }
-
- static constexpr fixed_point_t _0_01() {
- return _1() / _100();
- }
-
- static constexpr fixed_point_t _0_02() {
- return _0_01() * 2;
- }
-
- static constexpr fixed_point_t _0_03() {
- return _0_01() * 3;
- }
-
- static constexpr fixed_point_t _0_04() {
- return _0_01() * 4;
- }
-
- static constexpr fixed_point_t _0_05() {
- return _0_01() * 5;
- }
-
- static constexpr fixed_point_t _0_10() {
- return _1() / 10;
- }
-
static constexpr fixed_point_t _0_20() {
- return _0_10() * 2;
- }
-
- static constexpr fixed_point_t _0_25() {
- return _1() / 4;
- }
-
- static constexpr fixed_point_t _0_33() {
- return _1() / 3;
+ return _1() / 5;
}
static constexpr fixed_point_t _0_50() {
return _1() / 2;
}
- static constexpr fixed_point_t _0_75() {
- return _1() - _0_25();
- }
-
- static constexpr fixed_point_t _0_95() {
- return _1() - _0_05();
- }
-
- static constexpr fixed_point_t _0_99() {
- return _1() - _0_01();
- }
-
- static constexpr fixed_point_t _1_01() {
- return _1() + _0_01();
- }
-
- static constexpr fixed_point_t _1_10() {
- return _1() + _0_10();
- }
-
static constexpr fixed_point_t _1_50() {
return _1() + _0_50();
}
@@ -253,11 +170,6 @@ namespace OpenVic {
: 0;
}
- // Doesn't account for sign, so -n.abc -> 1 - 0.abc
- constexpr fixed_point_t get_frac() const {
- return value & FRAC_MASK;
- }
-
constexpr bool is_integer() const {
return get_frac() == 0;
}
diff --git a/src/openvic-simulation/utility/NumberUtils.hpp b/src/openvic-simulation/utility/NumberUtils.hpp
index d814019..8656f27 100644
--- a/src/openvic-simulation/utility/NumberUtils.hpp
+++ b/src/openvic-simulation/utility/NumberUtils.hpp
@@ -49,4 +49,8 @@ namespace OpenVic::NumberUtils {
return c;
}
+
+ constexpr bool is_power_of_two(uint64_t n) {
+ return n > 0 && (n & (n - 1)) == 0;
+ }
}