diff --git a/CMakeLists.txt b/CMakeLists.txt
index 19d869e28..06854ab73 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -123,6 +123,10 @@ set(HOI4WORLD_PLANE_DESIGNS_SOURCES ${HOI4WORLD_PLANE_DESIGNS_SOURCES} "${PROJEC
set(HOI4WORLD_REGIONS_SOURCES ${HOI4WORLD_REGIONS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Regions/RegionFactory.cpp")
set(HOI4WORLD_REGIONS_SOURCES ${HOI4WORLD_REGIONS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Regions/Regions.cpp")
set(HOI4WORLD_REGIONS_SOURCES ${HOI4WORLD_REGIONS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Regions/RegionsFactory.cpp")
+set(HOI4WORLD_SCORERS_SOURCES ${HOI4WORLD_SCORERS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Scorers/Scorer.cpp")
+set(HOI4WORLD_SCORERS_SOURCES ${HOI4WORLD_SCORERS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Scorers/ScorerFactory.cpp")
+set(HOI4WORLD_SCORERS_SOURCES ${HOI4WORLD_SCORERS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Scorers/Scorers.cpp")
+set(HOI4WORLD_SCORERS_SOURCES ${HOI4WORLD_SCORERS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Scorers/ScorersFactory.cpp")
set(HOI4WORLD_SCRIPTED_EFFECTS_SOURCES ${HOI4WORLD_SCRIPTED_EFFECTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/ScriptedEffects/ScriptedEffectFactory.cpp")
set(HOI4WORLD_SCRIPTED_EFFECTS_SOURCES ${HOI4WORLD_SCRIPTED_EFFECTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/ScriptedEffects/ScriptedEffectFile.cpp")
set(HOI4WORLD_SCRIPTED_EFFECTS_SOURCES ${HOI4WORLD_SCRIPTED_EFFECTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/ScriptedEffects/ScriptedEffects.cpp")
@@ -277,6 +281,8 @@ set(OUTHOI4_PEACECONFERENCE_SOURCES ${OUTHOI4_PEACECONFERENCE_SOURCES} "${PROJEC
set(OUTHOI4_PLANE_DESIGNS_SOURCES ${OUTHOI4_PLANE_DESIGNS_SOURCES} "${PROJECT_SOURCE_DIR}/src/OutHoi4/PlaneDesigns/OutPlaneDesign.cpp")
set(OUTHOI4_PLANE_DESIGNS_SOURCES ${OUTHOI4_PLANE_DESIGNS_SOURCES} "${PROJECT_SOURCE_DIR}/src/OutHoi4/PlaneDesigns/OutPlaneDesigns.cpp")
set(OUTHOI4_PLANE_DESIGNS_SOURCES ${OUTHOI4_PLANE_DESIGNS_SOURCES} "${PROJECT_SOURCE_DIR}/src/OutHoi4/PlaneDesigns/OutPlaneModules.cpp")
+set(OUTHOI4_SCORERS_SOURCES ${OUTHOI4_SCORERS_SOURCES} "${PROJECT_SOURCE_DIR}/src/OutHoi4/Scorers/OutScorers.cpp")
+set(OUTHOI4_SCORERS_SOURCES ${OUTHOI4_SCORERS_SOURCES} "${PROJECT_SOURCE_DIR}/src/OutHoi4/Scorers/OutScorer.cpp")
set(OUTHOI4_SCRIPTED_EFFECTS_SOURCES ${OUTHOI4_SCRIPTED_EFFECTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/OutHoi4/ScriptedEffects/OutScriptedEffects.cpp")
set(OUTHOI4_SCRIPTED_EFFECTS_SOURCES ${OUTHOI4_SCRIPTED_EFFECTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/OutHoi4/ScriptedEffects/OutScriptedEffect.cpp")
file(GLOB OUTHOI4_SCRIPTED_LOCALISATIONS_SOURCES "${PROJECT_SOURCE_DIR}/src/OutHoi4/ScriptedLocalisations/*.cpp")
@@ -345,6 +351,7 @@ list(APPEND ALL_HOI4_FILES
${OUTHOI4_PEACECONFERENCE_SOURCES}
${OUTHOI4_PLANE_DESIGNS_SOURCES}
${OUTHOI4_NAVIES_SOURCES}
+ ${OUTHOI4_SCORERS_SOURCES}
${OUTHOI4_SCRIPTED_EFFECTS_SOURCES}
${OUTHOI4_SCRIPTED_LOCALISATIONS_SOURCES}
${OUTHOI4_SCRIPTED_TRIGGERS_SOURCES}
@@ -423,6 +430,7 @@ list(APPEND ALL_HOI4_FILES
${HOI4WORLD_PEACECONFERENCES_SOURCES}
${HOI4WORLD_PLANE_DESIGNS_SOURCES}
${HOI4WORLD_REGIONS_SOURCES}
+ ${HOI4WORLD_SCORERS_SOURCES}
${HOI4WORLD_SCRIPTED_EFFECTS_SOURCES}
${HOI4WORLD_SCRIPTED_LOCALISATIONS_SOURCES}
${HOI4WORLD_SCRIPTED_TRIGGERS_SOURCES}
@@ -634,6 +642,10 @@ set(HOI4WORLD_PLANE_DESIGNS_TESTS_SOURCES ${HOI4WORLD_PLANE_DESIGNS_TESTS_SOURCE
set(HOI4WORLD_PLANE_DESIGNS_TESTS_SOURCES ${HOI4WORLD_PLANE_DESIGNS_TESTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/PlaneDesigns/PossiblePlaneDesignsTests.cpp")
set(HOI4WORLD_REGIONS_TESTS_SOURCES ${HOI4WORLD_REGIONS_TESTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Regions/RegionTests.cpp")
set(HOI4WORLD_REGIONS_TESTS_SOURCES ${HOI4WORLD_REGIONS_TESTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Regions/RegionsTests.cpp")
+set(HOI4WORLD_SCORERS_TESTS_SOURCES ${HOI4WORLD_SCORERS_TESTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Scorers/ScorerFactoryTests.cpp")
+set(HOI4WORLD_SCORERS_TESTS_SOURCES ${HOI4WORLD_SCORERS_TESTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Scorers/ScorerTests.cpp")
+set(HOI4WORLD_SCORERS_TESTS_SOURCES ${HOI4WORLD_SCORERS_TESTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Scorers/ScorersFactoryTests.cpp")
+set(HOI4WORLD_SCORERS_TESTS_SOURCES ${HOI4WORLD_SCORERS_TESTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/Scorers/ScorersTests.cpp")
set(HOI4WORLD_SCRIPTED_EFFECTS_TESTS_SOURCES ${HOI4WORLD_SCRIPTED_EFFECTS_TESTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/ScriptedEffects/ScriptedEffectTests.cpp")
set(HOI4WORLD_SCRIPTED_EFFECTS_TESTS_SOURCES ${HOI4WORLD_SCRIPTED_EFFECTS_TESTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/ScriptedEffects/ScriptedEffectFileTests.cpp")
set(HOI4WORLD_SCRIPTED_LOCALISATIONS_TESTS_SOURCES ${HOI4WORLD_SCRIPTED_LOCALISATIONS_TESTS_SOURCES} "${PROJECT_SOURCE_DIR}/src/HOI4World/ScriptedLocalisations/ScriptedLocalisationTests.cpp")
@@ -768,6 +780,7 @@ list(APPEND ALL_HOI4_TESTS_FILES
${HOI4WORLD_PEACECONFERENCES_TESTS_SOURCES}
${HOI4WORLD_PLANE_DESIGNS_TESTS_SOURCES}
${HOI4WORLD_REGIONS_TESTS_SOURCES}
+ ${HOI4WORLD_SCORERS_TESTS_SOURCES}
${HOI4WORLD_SCRIPTED_EFFECTS_TESTS_SOURCES}
${HOI4WORLD_SCRIPTED_LOCALISATIONS_TESTS_SOURCES}
${HOI4WORLD_SCRIPTED_TRIGGERS_TESTS_SOURCES}
@@ -896,6 +909,7 @@ configure_file("data/test_files/operations.txt" "${TEST_OUTPUT_DIRECTORY}/blankm
configure_file("data/test_files/regions.txt" "${TEST_OUTPUT_DIRECTORY}/Configurables/Map/regions.txt" COPYONLY)
configure_file("data/test_files/ReadMe.txt" "${TEST_OUTPUT_DIRECTORY}/Vic2Windows/ReadMe.txt" COPYONLY)
configure_file("data/test_files/ReadMe.txt" "${TEST_OUTPUT_DIRECTORY}/Vic2Linux/ReadMe.txt" COPYONLY)
+configure_file("data/test_files/Scorers.txt" "${TEST_OUTPUT_DIRECTORY}/Configurables/Scorers/generic_platonic_scorers.txt" COPYONLY)
configure_file("data/test_files/ScriptedEffects/effects_file.txt" "${TEST_OUTPUT_DIRECTORY}/ScriptedEffects/effects_file.txt" COPYONLY)
configure_file("data/test_files/ScriptedEffects/empty_effects_file.txt" "${TEST_OUTPUT_DIRECTORY}/ScriptedEffects/empty_effects_file.txt" COPYONLY)
configure_file("data/test_files/Sounds/CultureToVoiceMappings.txt" "${TEST_OUTPUT_DIRECTORY}/Configurables/Sounds/CultureToVoiceMappings.txt" COPYONLY)
@@ -1034,6 +1048,7 @@ add_library(run_clang_tidy
${HOI4WORLD_OPERATIVE_NAMES_SOURCES}
${HOI4WORLD_PEACECONFERENCES_SOURCES}
${HOI4WORLD_REGIONS_SOURCES}
+ ${HOI4WORLD_SCORERS_SOURCES}
${HOI4WORLD_SCRIPTED_EFFECTS_SOURCES}
${HOI4WORLD_SCRIPTED_LOCALISATIONS_SOURCES}
${HOI4WORLD_SCRIPTED_TRIGGERS_SOURCES}
@@ -1095,6 +1110,7 @@ add_library(run_clang_tidy
${OUTHOI4_OPERATIVE_SOURCES}
${OUTHOI4_NAVIES_SOURCES}
${OUTHOI4_PEACECONFERENCE_SOURCES}
+ ${OUTHOI4_SCORERS_SOURCES}
${OUTHOI4_SCRIPTED_EFFECTS_SOURCES}
${OUTHOI4_SCRIPTED_LOCALISATIONS_SOURCES}
${OUTHOI4_SCRIPTED_TRIGGERS_SOURCES}
@@ -1133,6 +1149,7 @@ add_library(run_clang_tidy
${HOI4WORLD_PEACECONFERENCES_TESTS_SOURCES}
${HOI4WORLD_PLANE_DESIGNS_TESTS_SOURCES}
${HOI4WORLD_REGIONS_TESTS_SOURCES}
+ ${HOI4WORLD_SCORERS_TESTS_SOURCES}
${HOI4WORLD_SCRIPTED_EFFECTS_TESTS_SOURCES}
${HOI4WORLD_SCRIPTED_LOCALISATIONS_TESTS_SOURCES}
${HOI4WORLD_SCRIPTED_TRIGGERS_TESTS_SOURCES}
diff --git a/Vic2ToHoI4Tests.vcxproj b/Vic2ToHoI4Tests.vcxproj
index f48819275..de76f45af 100644
--- a/Vic2ToHoI4Tests.vcxproj
+++ b/Vic2ToHoI4Tests.vcxproj
@@ -128,6 +128,10 @@
+
+
+
+
@@ -452,6 +456,12 @@
$(OutDir)/configurables/Localisations
+
+
+ $(OutDir)/configurables/Scorers/
+ generic_platonic_scorers%(Extension)
+
+
$(OutDir)/ScriptedEffects
diff --git a/Vic2ToHoI4Tests.vcxproj.filters b/Vic2ToHoI4Tests.vcxproj.filters
index 1d3911540..ea548bc05 100644
--- a/Vic2ToHoI4Tests.vcxproj.filters
+++ b/Vic2ToHoI4Tests.vcxproj.filters
@@ -634,6 +634,18 @@
src\V2World\Pops
+
+ src\HOI4World\Scorers
+
+
+ src\HOI4World\Scorers
+
+
+ src\HOI4World\Scorers
+
+
+ src\HOI4World\Scorers
+
@@ -1059,6 +1071,9 @@
{0f64a54e-5b9c-47ae-89cd-58afdec9b5cc}
+
+ {c7079fbb-9df6-467f-a26e-cbfcf59b89a3}
+
@@ -1393,6 +1408,9 @@
data\test_files
+
+ data\test_files
+
data\test_files
diff --git a/Vic2ToHoI4lib.vcxproj b/Vic2ToHoI4lib.vcxproj
index 81c462493..b3b5bfdcb 100644
--- a/Vic2ToHoI4lib.vcxproj
+++ b/Vic2ToHoI4lib.vcxproj
@@ -144,6 +144,10 @@
+
+
+
+
@@ -300,6 +304,8 @@
+
+
@@ -548,6 +554,10 @@
+
+
+
+
@@ -735,6 +745,8 @@
+
+
diff --git a/Vic2ToHoI4lib.vcxproj.filters b/Vic2ToHoI4lib.vcxproj.filters
index d5333956f..a1ef5d980 100644
--- a/Vic2ToHoI4lib.vcxproj.filters
+++ b/Vic2ToHoI4lib.vcxproj.filters
@@ -313,6 +313,12 @@
{3b5bae8f-1a84-4852-b2b3-1024028d64d8}
+
+ {c7817af0-36c6-489a-b034-64638a55d80f}
+
+
+ {e4d5ceee-934a-4813-8a4f-2c6e321263b5}
+
@@ -1416,6 +1422,24 @@
src\V2World\World
+
+ src\HoI4World\Scorers
+
+
+ src\HoI4World\Scorers
+
+
+ src\HoI4World\Scorers
+
+
+ src\HoI4World\Scorers
+
+
+ src\OutHoi4\Scorers
+
+
+ src\OutHoi4\Scorers
+
@@ -2780,5 +2804,23 @@
external\bitmap
+
+ src\HoI4World\Scorers
+
+
+ src\HoI4World\Scorers
+
+
+ src\HoI4World\Scorers
+
+
+ src\HoI4World\Scorers
+
+
+ src\OutHoi4\Scorers
+
+
+ src\OutHoi4\Scorers
+
\ No newline at end of file
diff --git a/data/configurables/Scorers/generic_platonic_scorers.txt b/data/configurables/Scorers/generic_platonic_scorers.txt
new file mode 100644
index 000000000..b0ceb6684
--- /dev/null
+++ b/data/configurables/Scorers/generic_platonic_scorers.txt
@@ -0,0 +1,458 @@
+$IDEOLOGY_major_scorer = {
+ # Valid example of mission scorer:
+ targets = {
+ # describe the target to consider
+ targets_dynamic = no
+ target_non_existing = no
+ #target_array = global.majors
+ target_array = global.countries
+ # MTTH like score description
+ # THIS is a target
+ # FROM is the initiator
+ score = {
+ base = 1
+ # Add tension added by country
+ modifier = {
+ always = yes
+ add = has_added_tension_amount
+ }
+ # Add total number of Divisions
+ modifier = {
+ always = yes
+ add = num_armies
+ }
+ # add factories
+ modifier = {
+ always = yes
+ add = num_of_factories
+ }
+ modifier = {
+ is_major = yes
+ add = 100
+ }
+ modifier = {
+ is_faction_leader = yes
+ add = 50
+ }
+ modifier = {
+ NOT = { has_government = $IDEOLOGY }
+ factor = 0
+ }
+ modifier = {
+ exists = no
+ factor = 0
+ }
+ }
+ }
+}
+
+local_$IDEOLOGY_country = {
+ # Valid example of mission scorer:
+ targets = {
+ # describe the target to consider
+ targets_dynamic = no
+ target_non_existing = no
+ #target_array = global.majors
+ target_array = global.countries
+ # MTTH like score description
+ # THIS is a target
+ # FROM is the initiator
+ score = {
+ base = 1
+
+ modifier = {
+ is_major = yes
+ factor = 10
+ }
+ # Add tension added by country
+ modifier = {
+ always = yes
+ add = has_added_tension_amount
+ }
+ # Add total number of Divisions
+ modifier = {
+ always = yes
+ add = num_armies
+ }
+ # Same continent also more scary
+ modifier = {
+ OR = {
+ AND = {
+ THIS.capital_scope = { is_on_continent = europe }
+ FROM.capital_scope = { is_on_continent = europe }
+ }
+ AND = {
+ THIS.capital_scope = { is_on_continent = asia }
+ FROM.capital_scope = { is_on_continent = asia }
+ }
+ AND = {
+ OR = {
+ THIS.capital_scope = { is_on_continent = north_america }
+ THIS.capital_scope = { is_on_continent = south_america }
+ }
+ OR = {
+ FROM.capital_scope = { is_on_continent = north_america }
+ FROM.capital_scope = { is_on_continent = south_america }
+ }
+ }
+ AND = {
+ THIS.capital_scope = { is_on_continent = africa }
+ FROM.capital_scope = { is_on_continent = africa }
+ }
+ AND = {
+ THIS.capital_scope = { is_on_continent = middle_east }
+ FROM.capital_scope = { is_on_continent = middle_east }
+ }
+ AND = {
+ OR = {
+ THIS.capital_scope = { is_on_continent = australia }
+ THIS.capital_scope = { is_on_continent = asia }
+ }
+ FROM.capital_scope = { is_on_continent = australia }
+ }
+ }
+ factor = 3
+ }
+ modifier = {
+ add = num_armies
+ }
+ # add factories
+ modifier = {
+ always = yes
+ add = num_of_factories
+ }
+ modifier = {
+ NOT = { has_government = $IDEOLOGY }
+ factor = 0
+ }
+ }
+ }
+}
+
+$IDEOLOGY_bully_scorer = {
+ # Valid example of mission scorer:
+ targets = {
+ # describe the target to consider
+ targets_dynamic = no
+ target_non_existing = no
+ #target_array = global.majors
+ target_array = global.countries
+ # MTTH like score description
+ # THIS is a target
+ # FROM is the initiator
+ score = {
+ base = 1
+ # Add tension added by country
+ # Add total number of Divisions
+ modifier = {
+ always = yes
+ add = num_armies
+ }
+ # add factories
+ modifier = {
+ always = yes
+ add = num_of_factories
+ }
+ modifier = {
+ always = yes
+ add = has_added_tension_amount
+ }
+ modifier = {
+ is_major = yes
+ add = 100
+ }
+ modifier = {
+ is_faction_leader = yes
+ add = 100
+ }
+ modifier = {
+ NOT = { has_government = $IDEOLOGY }
+ factor = 0
+ }
+ }
+ }
+}
+
+$IDEOLOGY_faction_leader_scorer = {
+ targets = {
+ # describe the target to consider
+ targets_dynamic = no
+ target_non_existing = no
+ #target_array = global.majors
+ target_array = global.countries
+ # MTTH like score description
+ # THIS is a target
+ # FROM is the initiator
+ score = {
+ base = 1
+ # Add tension added by country
+ modifier = {
+ always = yes
+ add = has_added_tension_amount
+ }
+ # Add total number of Divisions
+ modifier = {
+ always = yes
+ add = num_armies
+ }
+ # add factories
+ modifier = {
+ always = yes
+ add = num_of_factories
+ }
+ modifier = {
+ is_major = yes
+ add = 100
+ }
+ modifier = {
+ is_faction_leader = no
+ factor = 0.1
+ }
+ modifier = {
+ NOT = { has_government = $IDEOLOGY }
+ factor = 0
+ }
+ }
+ }
+}
+
+$IDEOLOGY_sleeping_giant_scorer = {
+ targets = {
+ # describe the target to consider
+ targets_dynamic = no
+ target_non_existing = no
+ #target_array = global.majors
+ target_array = global.countries
+ # MTTH like score description
+ # THIS is a target
+ # FROM is the initiator
+ score = {
+ base = 1
+ # Add tension added by country
+ # Add total number of Divisions
+ # add factories
+ modifier = {
+ always = yes
+ add = num_of_factories
+ }
+ modifier = {
+ always = yes
+ add = -num_armies
+ }
+ modifier = {
+ always = yes
+ add = -has_added_tension_amount
+ }
+ modifier = {
+ is_major = yes
+ add = 30
+ }
+ modifier = {
+ is_faction_leader = yes
+ factor = 0.5
+ }
+ modifier = {
+ NOT = { has_government = $IDEOLOGY }
+ factor = 0
+ }
+ }
+ }
+}
+
+european_$IDEOLOGY_major_scorer = {
+ # Valid example of mission scorer:
+ targets = {
+ # describe the target to consider
+ targets_dynamic = no
+ target_non_existing = no
+ #target_array = global.majors
+ target_array = global.countries
+ # MTTH like score description
+ # THIS is a target
+ # FROM is the initiator
+ score = {
+ base = 1
+ # Add tension added by country
+ modifier = {
+ always = yes
+ add = has_added_tension_amount
+ }
+ # Add total number of Divisions
+ modifier = {
+ always = yes
+ add = num_armies
+ }
+ # add factories
+ modifier = {
+ always = yes
+ add = num_of_factories
+ }
+ modifier = {
+ is_major = yes
+ add = 100
+ }
+ modifier = {
+ is_faction_leader = yes
+ add = 50
+ }
+ modifier = {
+ NOT = { has_government = $IDEOLOGY }
+ factor = 0
+ }
+ modifier = {
+ NOT = { THIS.capital_scope = { is_on_continent = europe } }
+ }
+ }
+ }
+}
+
+asian_$IDEOLOGY_major_scorer = {
+ # Valid example of mission scorer:
+ targets = {
+ # describe the target to consider
+ targets_dynamic = no
+ target_non_existing = no
+ #target_array = global.majors
+ target_array = global.countries
+ # MTTH like score description
+ # THIS is a target
+ # FROM is the initiator
+ score = {
+ base = 1
+ # Add tension added by country
+ modifier = {
+ always = yes
+ add = has_added_tension_amount
+ }
+ # Add total number of Divisions
+ modifier = {
+ always = yes
+ add = num_armies
+ }
+ # add factories
+ modifier = {
+ always = yes
+ add = num_of_factories
+ }
+ modifier = {
+ is_major = yes
+ add = 100
+ }
+ modifier = {
+ is_faction_leader = yes
+ add = 50
+ }
+ modifier = {
+ NOT = { has_government = $IDEOLOGY }
+ factor = 0
+ }
+ modifier = {
+ OR = {
+ NOT = { THIS.capital_scope = { is_on_continent = asia } }
+ NOT = { THIS.capital_scope = { is_on_continent = australia } }
+ NOT = { THIS.capital_scope = { is_on_continent = middle_east } }
+ }
+ factor = 0
+ }
+ }
+ }
+}
+
+american_$IDEOLOGY_major_scorer = {
+ # Valid example of mission scorer:
+ targets = {
+ # describe the target to consider
+ targets_dynamic = no
+ target_non_existing = no
+ #target_array = global.majors
+ target_array = global.countries
+ # MTTH like score description
+ # THIS is a target
+ # FROM is the initiator
+ score = {
+ base = 1
+ # Add tension added by country
+ modifier = {
+ always = yes
+ add = has_added_tension_amount
+ }
+ # Add total number of Divisions
+ modifier = {
+ always = yes
+ add = num_armies
+ }
+ # add factories
+ modifier = {
+ always = yes
+ add = num_of_factories
+ }
+ modifier = {
+ is_major = yes
+ add = 100
+ }
+ modifier = {
+ is_faction_leader = yes
+ add = 50
+ }
+ modifier = {
+ NOT = { has_government = $IDEOLOGY }
+ factor = 0
+ }
+ modifier = {
+ OR = {
+ NOT = { THIS.capital_scope = { is_on_continent = south_america } }
+ NOT = { THIS.capital_scope = { is_on_continent = north_america } }
+ }
+ factor = 0
+ }
+ }
+ }
+}
+
+african_$IDEOLOGY_major_scorer = {
+ # Valid example of mission scorer:
+ targets = {
+ # describe the target to consider
+ targets_dynamic = no
+ target_non_existing = no
+ #target_array = global.majors
+ target_array = global.countries
+ # MTTH like score description
+ # THIS is a target
+ # FROM is the initiator
+ score = {
+ base = 1
+ # Add tension added by country
+ modifier = {
+ always = yes
+ add = has_added_tension_amount
+ }
+ # Add total number of Divisions
+ modifier = {
+ always = yes
+ add = num_armies
+ }
+ # add factories
+ modifier = {
+ always = yes
+ add = num_of_factories
+ }
+ modifier = {
+ is_major = yes
+ add = 100
+ }
+ modifier = {
+ is_faction_leader = yes
+ add = 50
+ }
+ modifier = {
+ NOT = { has_government = $IDEOLOGY }
+ factor = 0
+ }
+ modifier = {
+ NOT = { THIS.capital_scope = { is_on_continent = africa } }
+ }
+ }
+ }
+}
+
diff --git a/data/test_files/Scorers.txt b/data/test_files/Scorers.txt
new file mode 100644
index 000000000..5773b2dea
--- /dev/null
+++ b/data/test_files/Scorers.txt
@@ -0,0 +1,2 @@
+scorer_one = {}
+scorer_two = {}
\ No newline at end of file
diff --git a/src/HOI4World/HoI4World.cpp b/src/HOI4World/HoI4World.cpp
index ad317ee98..7c739fcd5 100644
--- a/src/HOI4World/HoI4World.cpp
+++ b/src/HOI4World/HoI4World.cpp
@@ -207,6 +207,8 @@ HoI4::World::World(const Vic2::World& sourceWorld,
convertMilitaries(*provinceDefinitions, provinceMapper, theConfiguration);
scriptedEffects = std::make_unique(theConfiguration.getHoI4Path());
+ scorers = Scorers::Factory().getScorers();
+ scorers->updateScorers(ideologies->getMajorIdeologies());
setupNavalTreaty();
Log(LogLevel::Progress) << "64%";
diff --git a/src/HOI4World/HoI4World.h b/src/HOI4World/HoI4World.h
index 7381968b6..7aeace3d5 100644
--- a/src/HOI4World/HoI4World.h
+++ b/src/HOI4World/HoI4World.h
@@ -36,6 +36,7 @@
#include "src/HOI4World/OnActions.h"
#include "src/HOI4World/Operations/Operations.h"
#include "src/HOI4World/OperativeNames/OperativeNames.h"
+#include "src/HOI4World/Scorers/ScorersFactory.h"
#include "src/HOI4World/ScriptedEffects/ScriptedEffects.h"
#include "src/HOI4World/ScriptedLocalisations/ScriptedLocalisations.h"
#include "src/HOI4World/ScriptedTriggers/ScriptedTriggers.h"
@@ -104,6 +105,8 @@ class World: commonItems::parser
[[nodiscard]] const auto& getTheIdeas() const { return *theIdeas; }
[[nodiscard]] const auto& getOccupationLaws() const { return *occupationLaws; }
[[nodiscard]] const auto& getDynamicModifiers() const { return dynamicModifiers; }
+ [[nodiscard]] const auto& getScorers() const { return *scorers; }
+ [[nodiscard]] const auto& getCustomizedScorers() const { return scorers->getCustomizedScorers(); }
[[nodiscard]] const auto& getScriptedEffects() const { return *scriptedEffects; }
[[nodiscard]] const auto& getScriptedLocalisations() const { return scriptedLocalisations; }
[[nodiscard]] const auto& getScriptedTriggers() const { return scriptedTriggers; }
@@ -289,6 +292,7 @@ class World: commonItems::parser
std::unique_ptr theMapData;
std::unique_ptr scriptedEffects;
+ std::unique_ptr scorers;
std::unique_ptr scriptedLocalisations;
ScriptedTriggers scriptedTriggers;
diff --git a/src/HOI4World/Scorers/Scorer.cpp b/src/HOI4World/Scorers/Scorer.cpp
new file mode 100644
index 000000000..2c9869b94
--- /dev/null
+++ b/src/HOI4World/Scorers/Scorer.cpp
@@ -0,0 +1,25 @@
+#include "src/HoI4World/Scorers/Scorer.h"
+
+std::shared_ptr HoI4::Scorer::makeCustomizedCopy(const std::string& ideology) const
+{
+ constexpr std::string ideologyToken = "$IDEOLOGY";
+ const std::map ideologyNameMap = {{"fascism", "fascist"},
+ {"communism", "communist"},
+ {"democratic", "democratic"},
+ {"neutrality", "non_aligned"},
+ {"absolutist", "absolutist"},
+ {"radical", "radical"}};
+
+
+ auto newScorer = std::make_shared(*this);
+
+ if (const auto& ideologyNameItr = newScorer->name.find(ideologyToken); ideologyNameItr != std::string::npos)
+ {
+ newScorer->name.replace(ideologyNameItr, ideologyToken.size(), ideologyNameMap.at(ideology));
+ }
+ if (const auto& ideologyTargetItr = newScorer->targets.find(ideologyToken); ideologyTargetItr != std::string::npos)
+ {
+ newScorer->targets.replace(ideologyTargetItr, ideologyToken.size(), ideology);
+ }
+ return newScorer;
+}
\ No newline at end of file
diff --git a/src/HOI4World/Scorers/Scorer.h b/src/HOI4World/Scorers/Scorer.h
new file mode 100644
index 000000000..020697d74
--- /dev/null
+++ b/src/HOI4World/Scorers/Scorer.h
@@ -0,0 +1,35 @@
+#ifndef SCORER_H
+#define SCORER_H
+
+
+
+#include
+#include
+
+
+
+namespace HoI4
+{
+
+class Scorer
+{
+ public:
+ class Factory;
+ [[nodiscard]] const auto& getName() const { return name; }
+ [[nodiscard]] const auto& getTargets() const { return targets; }
+
+ std::shared_ptr makeCustomizedCopy(const std::string& ideology) const;
+
+ void setName(std::string _name) { name = std::move(_name); }
+ void setTargets(std::string _targets) { targets = std::move(_targets); }
+
+ private:
+ std::string name;
+ std::string targets;
+};
+
+} // namespace HoI4
+
+
+
+#endif // SCORER_H
\ No newline at end of file
diff --git a/src/HOI4World/Scorers/ScorerFactory.cpp b/src/HOI4World/Scorers/ScorerFactory.cpp
new file mode 100644
index 000000000..45ce433a1
--- /dev/null
+++ b/src/HOI4World/Scorers/ScorerFactory.cpp
@@ -0,0 +1,24 @@
+#include "src/HOI4World/Scorers/ScorerFactory.h"
+#include "external/common_items/CommonRegexes.h"
+#include "external/common_items/ParserHelpers.h"
+
+
+
+HoI4::Scorer::Factory::Factory()
+{
+ registerKeyword("targets", [this](std::istream& theStream) {
+ scorer->setTargets(commonItems::stringOfItem(theStream).getString());
+ });
+ registerRegex(commonItems::catchallRegex, commonItems::ignoreItem);
+}
+
+
+std::unique_ptr HoI4::Scorer::Factory::getScorer(const std::string& name, std::istream& theStream)
+{
+ scorer = std::make_unique();
+ scorer->setName(name);
+
+ parseStream(theStream);
+
+ return std::move(scorer);
+}
\ No newline at end of file
diff --git a/src/HOI4World/Scorers/ScorerFactory.h b/src/HOI4World/Scorers/ScorerFactory.h
new file mode 100644
index 000000000..f7eb5f8df
--- /dev/null
+++ b/src/HOI4World/Scorers/ScorerFactory.h
@@ -0,0 +1,29 @@
+#ifndef SCORER_FACTORY_H
+#define SCORER_FACTORY_H
+
+
+
+#include "external/common_items/ConvenientParser.h"
+#include "src/HOI4World/Scorers/Scorer.h"
+#include
+
+
+
+namespace HoI4
+{
+
+class Scorer::Factory: commonItems::parser
+{
+ public:
+ Factory();
+ std::unique_ptr getScorer(const std::string& name, std::istream& theStream);
+
+ private:
+ std::unique_ptr scorer;
+};
+
+} // namespace HoI4
+
+
+
+#endif // SCORER_FACTORY_H
\ No newline at end of file
diff --git a/src/HOI4World/Scorers/ScorerFactoryTests.cpp b/src/HOI4World/Scorers/ScorerFactoryTests.cpp
new file mode 100644
index 000000000..814b3e18f
--- /dev/null
+++ b/src/HOI4World/Scorers/ScorerFactoryTests.cpp
@@ -0,0 +1,33 @@
+#include "external/common_items/external/googletest/googletest/include/gtest/gtest.h"
+#include "src/HOI4World/Scorers/ScorerFactory.h"
+
+
+
+TEST(HoI4World_Scorers_ScorerFactoryTests, NameCanBeSet)
+{
+ std::stringstream input;
+ const auto scorer = HoI4::Scorer::Factory().getScorer("scorer_name", input);
+
+ ASSERT_EQ("scorer_name", scorer->getName());
+}
+
+
+TEST(HoI4World_Scorers_ScorerFactoryTests, TargetsDefaultsToEmpty)
+{
+ std::stringstream input;
+ const auto scorer = HoI4::Scorer::Factory().getScorer("scorer_name", input);
+
+ ASSERT_TRUE(scorer->getTargets().empty());
+}
+
+
+TEST(HoI4World_Scorers_ScorerFactoryTests, TargetsCanBeSet)
+{
+ std::stringstream input;
+ input << "{\n";
+ input << "\ttargets = { targets_dynamic = no }\n";
+ input << "}";
+ const auto scorer = HoI4::Scorer::Factory().getScorer("scorer_name", input);
+
+ ASSERT_EQ("= { targets_dynamic = no }", scorer->getTargets());
+}
\ No newline at end of file
diff --git a/src/HOI4World/Scorers/ScorerTests.cpp b/src/HOI4World/Scorers/ScorerTests.cpp
new file mode 100644
index 000000000..b595d5ac9
--- /dev/null
+++ b/src/HOI4World/Scorers/ScorerTests.cpp
@@ -0,0 +1,15 @@
+#include "external/common_items/external/googletest/googletest/include/gtest/gtest.h"
+#include "src/HOI4World/Scorers/Scorer.h"
+
+
+
+TEST(HoI4World_Scorers_Scorer, CanMakeCustomizedCopyOfScorer)
+{
+ HoI4::Scorer scorer;
+ scorer.setName("$IDEOLOGY_major_scorer");
+ scorer.setTargets("= { score = { modifier = { NOT = { has_government = $IDEOLOGY }}}}");
+
+ const auto& customScorer = scorer.makeCustomizedCopy("communism");
+ EXPECT_EQ("communist_major_scorer", customScorer->getName());
+ EXPECT_EQ("= { score = { modifier = { NOT = { has_government = communism }}}}", customScorer->getTargets());
+}
\ No newline at end of file
diff --git a/src/HOI4World/Scorers/Scorers.cpp b/src/HOI4World/Scorers/Scorers.cpp
new file mode 100644
index 000000000..dcef93470
--- /dev/null
+++ b/src/HOI4World/Scorers/Scorers.cpp
@@ -0,0 +1,16 @@
+#include "src/HOI4World/Scorers/Scorers.h"
+#include
+
+
+
+void HoI4::Scorers::updateScorers(const std::set& majorIdeologies)
+{
+ for (const auto& scorer: scorers)
+ {
+ for (const auto& ideology: majorIdeologies)
+ {
+ const auto& newScorer = scorer.makeCustomizedCopy(ideology);
+ customizedScorers[newScorer->getName()] = *newScorer;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/HOI4World/Scorers/Scorers.h b/src/HOI4World/Scorers/Scorers.h
new file mode 100644
index 000000000..452da8f2b
--- /dev/null
+++ b/src/HOI4World/Scorers/Scorers.h
@@ -0,0 +1,35 @@
+#ifndef SCORERS_H
+#define SCORERS_H
+
+
+
+#include "src/HOI4World/Scorers/Scorer.h"
+#include
+#include
+
+
+
+namespace HoI4
+{
+
+class Scorers
+{
+ public:
+ class Factory;
+ [[nodiscard]] const auto& getScorers() const { return scorers; }
+ [[nodiscard]] const auto& getCustomizedScorers() const { return customizedScorers; }
+
+ void giveScorer(Scorer&& scorer) { scorers.emplace_back(scorer); }
+
+ void updateScorers(const std::set& majorIdeologies);
+
+ private:
+ std::vector scorers;
+ std::map customizedScorers;
+};
+
+} // namespace HoI4
+
+
+
+#endif // SCORERS_H
\ No newline at end of file
diff --git a/src/HOI4World/Scorers/ScorersFactory.cpp b/src/HOI4World/Scorers/ScorersFactory.cpp
new file mode 100644
index 000000000..dd56fefbd
--- /dev/null
+++ b/src/HOI4World/Scorers/ScorersFactory.cpp
@@ -0,0 +1,21 @@
+#include "src/HOI4World/Scorers/ScorersFactory.h"
+#include "external/common_items/CommonRegexes.h"
+#include "external/common_items/ParserHelpers.h"
+#include "src/HOI4World/Scorers/ScorerFactory.h"
+
+
+
+std::unique_ptr HoI4::Scorers::Factory::getScorers()
+{
+ auto scorers = std::make_unique();
+ Scorer::Factory scorerFactory;
+
+ registerRegex(commonItems::catchallRegex,
+ [&scorers, &scorerFactory](const std::string& name, std::istream& theStream) {
+ const auto scorer = scorerFactory.getScorer(name, theStream);
+ scorers->giveScorer(std::move(*scorer));
+ });
+
+ parseFile("Configurables/Scorers/generic_platonic_scorers.txt");
+ return scorers;
+}
\ No newline at end of file
diff --git a/src/HOI4World/Scorers/ScorersFactory.h b/src/HOI4World/Scorers/ScorersFactory.h
new file mode 100644
index 000000000..8f4bef598
--- /dev/null
+++ b/src/HOI4World/Scorers/ScorersFactory.h
@@ -0,0 +1,24 @@
+#ifndef SCORERS_FACTORY_H
+#define SCORERS_FACTORY_H
+
+
+
+#include "external/common_items/ConvenientParser.h"
+#include "src/Configuration.h"
+#include "src/HOI4World/Scorers/Scorers.h"
+
+
+namespace HoI4
+{
+
+class Scorers::Factory: commonItems::parser
+{
+ public:
+ std::unique_ptr getScorers();
+};
+
+} // namespace HoI4
+
+
+
+#endif // SCORERS_FACTORY_H
\ No newline at end of file
diff --git a/src/HOI4World/Scorers/ScorersFactoryTests.cpp b/src/HOI4World/Scorers/ScorersFactoryTests.cpp
new file mode 100644
index 000000000..28312b3a5
--- /dev/null
+++ b/src/HOI4World/Scorers/ScorersFactoryTests.cpp
@@ -0,0 +1,13 @@
+#include "external/common_items/external/googletest/googletest/include/gtest/gtest.h"
+#include "src/HOI4World/Scorers/ScorersFactory.h"
+
+
+
+TEST(HoI4World_Scorers_ScorersFactoryTests, ScorersCanBeImported)
+{
+ const auto scorers = HoI4::Scorers::Factory().getScorers();
+
+ ASSERT_EQ(2, scorers->getScorers().size());
+ ASSERT_EQ("scorer_one", scorers->getScorers()[0].getName());
+ ASSERT_EQ("scorer_two", scorers->getScorers()[1].getName());
+}
\ No newline at end of file
diff --git a/src/HOI4World/Scorers/ScorersTests.cpp b/src/HOI4World/Scorers/ScorersTests.cpp
new file mode 100644
index 000000000..b87958594
--- /dev/null
+++ b/src/HOI4World/Scorers/ScorersTests.cpp
@@ -0,0 +1,16 @@
+#include "external/common_items/external/googletest/googletest/include/gtest/gtest.h"
+#include "src/HOI4World/Scorers/Scorers.h"
+
+
+
+TEST(HoI4World_Scorers_Scorers, ScorersCanBeUpdated)
+{
+ HoI4::Scorer scorer;
+ scorer.setName("$IDEOLOGY_major_scorer");
+
+ HoI4::Scorers scorers;
+ scorers.giveScorer(std::move(scorer));
+
+ scorers.updateScorers({"democratic"});
+ ASSERT_TRUE(scorers.getCustomizedScorers().find("democratic_major_scorer") != scorers.getCustomizedScorers().end());
+}
\ No newline at end of file
diff --git a/src/OutHoi4/OutHoi4World.cpp b/src/OutHoi4/OutHoi4World.cpp
index c0b78b465..ffcdbb45e 100644
--- a/src/OutHoi4/OutHoi4World.cpp
+++ b/src/OutHoi4/OutHoi4World.cpp
@@ -26,6 +26,7 @@
#include "src/OutHoi4/OutOnActions.h"
#include "src/OutHoi4/PeaceConference/OutAiPeace.h"
#include "src/OutHoi4/PeaceConference/OutCostModifiers.h"
+#include "src/OutHoi4/Scorers/OutScorers.h"
#include "src/OutHoi4/ScriptedEffects/OutScriptedEffects.h"
#include "src/OutHoi4/ScriptedLocalisations/OutScriptedLocalisations.h"
#include "src/OutHoi4/ScriptedTriggers/OutScriptedTriggers.h"
@@ -237,6 +238,7 @@ void HoI4::OutputWorld(const World& world,
outputOperativeNames(world.getOperativeNames(), outputName);
outputOperations(world.getOperations(), outputName);
outputScriptedEffects(world.getScriptedEffects(), world.getMajorIdeologies(), outputName);
+ outputScorers(world.getScorers(), theConfiguration);
outCountryCategories(world.getCountryCategories(), outputName);
outputSounds(outputName, world.getSoundEffects());
outMonarchInterface(outputName, world.getCountries());
diff --git a/src/OutHoi4/Scorers/OutScorer.cpp b/src/OutHoi4/Scorers/OutScorer.cpp
new file mode 100644
index 000000000..70313b180
--- /dev/null
+++ b/src/OutHoi4/Scorers/OutScorer.cpp
@@ -0,0 +1,13 @@
+#include "src/OutHoi4/Scorers/OutScorer.h"
+
+
+
+std::ostream& HoI4::operator<<(std::ostream& output, const Scorer& scorer)
+{
+ output << scorer.getName() << " = {\n";
+ output << "\ttargets " << scorer.getTargets() << "\n";
+ output << "\t\n";
+ output << "}\n";
+
+ return output;
+}
\ No newline at end of file
diff --git a/src/OutHoi4/Scorers/OutScorer.h b/src/OutHoi4/Scorers/OutScorer.h
new file mode 100644
index 000000000..519ff456a
--- /dev/null
+++ b/src/OutHoi4/Scorers/OutScorer.h
@@ -0,0 +1,20 @@
+#ifndef OUT_OCCUPATION_LAW_H
+#define OUT_OCCUPATION_LAW_H
+
+
+
+#include "src/HOI4World/Scorers/Scorer.h"
+#include
+
+
+
+namespace HoI4
+{
+
+std::ostream& operator<<(std::ostream& output, const Scorer& scorer);
+
+}
+
+
+
+#endif // OUT_OCCUPATION_LAW_H
\ No newline at end of file
diff --git a/src/OutHoi4/Scorers/OutScorers.cpp b/src/OutHoi4/Scorers/OutScorers.cpp
new file mode 100644
index 000000000..e89497f01
--- /dev/null
+++ b/src/OutHoi4/Scorers/OutScorers.cpp
@@ -0,0 +1,31 @@
+#include "src/OutHoi4/Scorers/OutScorers.h"
+#include "external/common_items/OSCompatibilityLayer.h"
+#include "src/OutHoi4/Scorers/OutScorer.h"
+#include
+#include
+
+
+
+void HoI4::outputScorers(const Scorers& scorers, const Configuration& configuration)
+{
+ if (!commonItems::TryCreateFolder("output/" + configuration.getOutputName() + "/common/scorers/country/"))
+ {
+ throw std::runtime_error("Could not create output/" + configuration.getOutputName() + "/common/scorers/country/");
+ }
+
+ std::ofstream output(
+ "output/" + configuration.getOutputName() + "/common/scorers/country/generic_platonic_scorers.txt");
+ if (!output.is_open())
+ {
+ throw std::runtime_error("Could not create output/" + configuration.getOutputName() +
+ "/common/scorers/country/generic_platonic_scorers.txt");
+ }
+
+ for (const auto& scorer: scorers.getCustomizedScorers() | std::views::values)
+ {
+ output << scorer;
+ output << "\n";
+ }
+
+ output.close();
+}
\ No newline at end of file
diff --git a/src/OutHoi4/Scorers/OutScorers.h b/src/OutHoi4/Scorers/OutScorers.h
new file mode 100644
index 000000000..c93f98f1d
--- /dev/null
+++ b/src/OutHoi4/Scorers/OutScorers.h
@@ -0,0 +1,20 @@
+#ifndef OUT_SCORERS_H
+#define OUT_SCORERS_H
+
+
+
+#include "src/Configuration.h"
+#include "src/HOI4World/Scorers/Scorers.h"
+
+
+
+namespace HoI4
+{
+
+void outputScorers(const Scorers& scorers, const Configuration& configuration);
+
+}
+
+
+
+#endif // OUT_SCORERS_H
\ No newline at end of file