Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/build_dev_version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ jobs:
onlyPrefix: 'ImperatorToCK3-${{ matrix.build }}-dev-${{ env.BRANCH_NAME }}'
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: "Setup Dotnet for use with actions"
# don't run on self-hosted Windows
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/integration_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ jobs:
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: "Check if docs folders exist"
run: |
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/spelling.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ jobs:
**/*_l_polish.yml
**/*_l_korean.yml
**/*_l_german.yml
ImperatorToCK3/Data_Files/configurables/province_mappings/invictus_to_wtwsms.txt


3 changes: 3 additions & 0 deletions .github/workflows/steam_mod_update_notifier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ jobs:
check-steam-mod-updates:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Check Steam Workshop mods and notify
shell: bash
env:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ jobs:
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: "Setup Dotnet for use with actions"
uses: actions/setup-dotnet@v5
Expand All @@ -41,7 +40,6 @@ jobs:
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: "Setup Dotnet for use with actions"
# don't run on self-hosted Windows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,14 @@ public void ImperatorCountriesGoldCanBeDistributedAmongRulerAndVassals() {
ruler_term={ character=1000 start_date=440.10.1 }
");
var country = Country.Parse(countryReader, 589);

imperatorWorld.Provinces[1].OwnerCountry = country;
imperatorWorld.Provinces[2].OwnerCountry = country;
imperatorWorld.Provinces[3].OwnerCountry = country;
imperatorWorld.Provinces[4].OwnerCountry = country;
imperatorWorld.Provinces[5].OwnerCountry = country;
imperatorWorld.Provinces[6].OwnerCountry = country;

Assert.Equal(200, country.Currencies.Gold);
imperatorWorld.Countries.Add(country);
imperatorWorld.Characters.LinkCountries(imperatorWorld.Countries);
Expand Down
85 changes: 79 additions & 6 deletions ImperatorToCK3.UnitTests/CK3/Titles/LandedTitlesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,22 +235,33 @@ public void GovernorshipsCanBeRecognizedAsCountyLevel() {
var config = new Configuration { ImperatorPath = "TestFiles/LandedTitlesTests/Imperator" };
var imperatorWorld = new TestImperatorWorld(config);

imperatorWorld.Provinces.Add(new Province(1));
imperatorWorld.Provinces.Add(new Province(2));
imperatorWorld.Provinces.Add(new Province(3));
var irProv1 = new Province(1);
var irProv2 = new Province(2);
var irProv3 = new Province(3);
imperatorWorld.Provinces.Add(irProv1);
imperatorWorld.Provinces.Add(irProv2);
imperatorWorld.Provinces.Add(irProv3);

var governor = new ImperatorToCK3.Imperator.Characters.Character(25212);
imperatorWorld.Characters.Add(governor);

var countryReader = new BufferedReader("tag=PRY capital=1");
var country = Country.Parse(countryReader, 589);
irProv1.OwnerCountry = country;
irProv2.OwnerCountry = country;
irProv3.OwnerCountry = country;
country.RegisterProvince(irProv1);
country.RegisterProvince(irProv2);
country.RegisterProvince(irProv3);
imperatorWorld.Countries.Add(country);

imperatorWorld.Areas.LoadAreas(imperatorWorld.ModFS, imperatorWorld.Provinces);
var irRegionMapper = new ImperatorRegionMapper(imperatorWorld.Areas, irMapData);
irRegionMapper.LoadRegions(imperatorWorld.ModFS, new ColorFactory());
Assert.True(irRegionMapper.RegionNameIsValid("galatia_area"));
Assert.True(irRegionMapper.RegionNameIsValid("galatia_region"));
Assert.True(irRegionMapper.ProvinceIsInRegion(2, "galatia_region"));
Assert.True(irRegionMapper.ProvinceIsInRegion(3, "galatia_region"));
var ck3RegionMapper = new CK3RegionMapper();

var reader = new BufferedReader(
Expand Down Expand Up @@ -335,14 +346,14 @@ public void GovernorshipsCanBeRecognizedAsCountyLevel() {
title => Assert.Equal("d_IRTOCK3_PRY", title.Id)
);

var provinces = new ProvinceCollection(ck3ModFS);
var ck3Provinces = new ProvinceCollection(ck3ModFS);
var ck3MapData = new MapData(ck3ModFS);
ck3MapData.ProvinceDefinitions.Add(new(1));
ck3MapData.ProvinceDefinitions.Add(new(2));
ck3MapData.ProvinceDefinitions.Add(new(3));
provinces.ImportImperatorProvinces(imperatorWorld, ck3MapData, titles, cultureMapper, religionMapper, provinceMapper, conversionDate, config);
ck3Provinces.ImportImperatorProvinces(imperatorWorld, ck3MapData, titles, cultureMapper, religionMapper, provinceMapper, conversionDate, config);
// Country 589 is imported as duchy-level title, so its governorship of galatia_region will be county level.
titles.ImportImperatorGovernorships(imperatorWorld, provinces, tagTitleMapper, irLocDB, ck3LocDB, config, provinceMapper, definiteFormMapper, irRegionMapper, coaMapper, countyLevelGovernorships);
titles.ImportImperatorGovernorships(imperatorWorld, ck3Provinces, tagTitleMapper, irLocDB, ck3LocDB, config, provinceMapper, definiteFormMapper, irRegionMapper, coaMapper, countyLevelGovernorships);

Assert.Collection(titles,
title => Assert.Equal("c_county1", title.Id),
Expand Down Expand Up @@ -610,6 +621,68 @@ public void TitlesCanBeExpandedInOtherFiles() {
Assert.Equal("c_karakorum", mongoliaKingdom.CapitalCountyId);
}

[Fact]
public void KingdomUsesNextDominantHeritageWhenMostDominantOneCannotProvideEmpire() {
var date = new Date(867, 1, 1);
var titles = new Title.LandedTitles();
titles.LoadTitles(new BufferedReader(
"e_mongolia = { }\n" +
"k_test = {\n" +
"\td_test = {\n" +
"\t\tc_county1 = { b_barony1 = { province = 1 } }\n" +
"\t\tc_county2 = { b_barony2 = { province = 2 } }\n" +
"\t\tc_county3 = { b_barony3 = { province = 3 } }\n" +
"\t}\n" +
"}\n" +
"k_xia = {\n" +
"\td_xia = {\n" +
"\t\tc_xia_county = { b_xia_barony = { province = 4 } }\n" +
"\t}\n" +
"}\n"
), colorFactory);

var cultureCollection = new TestCK3CultureCollection();
cultureCollection.GenerateTestCulture("han", "heritage_chinese");
cultureCollection.GenerateTestCulture("mongol", "heritage_mongolic");

var characters = new CharacterCollection();
var hanHolder1 = new Character("1", "Han Holder 1", new Date(800, 1, 1), characters);
hanHolder1.SetCultureId("han", null);
characters.Add(hanHolder1);

var hanHolder2 = new Character("2", "Han Holder 2", new Date(801, 1, 1), characters);
hanHolder2.SetCultureId("han", null);
characters.Add(hanHolder2);

var mongolHolder = new Character("3", "Mongol Holder", new Date(802, 1, 1), characters);
mongolHolder.SetCultureId("mongol", null);
characters.Add(mongolHolder);

titles["c_county1"].SetHolder(hanHolder1, date);
titles["c_county2"].SetHolder(hanHolder2, date);
titles["c_county3"].SetHolder(mongolHolder, date);
titles["c_xia_county"].SetHolder(mongolHolder, date);

var heritageMapPath = Path.Combine("configurables", "heritage_empires_map.txt");
var originalHeritageMap = File.Exists(heritageMapPath) ? File.ReadAllText(heritageMapPath) : null;
Directory.CreateDirectory("configurables");
File.WriteAllText(heritageMapPath,
"heritage_chinese = none\n" +
"heritage_mongolic = e_mongolia\n");

try {
titles.SetDeJureKingdomsAndAbove(date, cultureCollection, characters, new MapData(ck3ModFS), new CK3RegionMapper(), new TestCK3LocDB());

Assert.Equal("e_mongolia", titles["k_test"].DeJureLiege?.Id);
} finally {
if (originalHeritageMap is null) {
File.Delete(heritageMapPath);
} else {
File.WriteAllText(heritageMapPath, originalHeritageMap);
}
}
}

[Fact]
public void RemoveBreaksAllLinks() {
var landedTitles = new Title.LandedTitles();
Expand Down
30 changes: 19 additions & 11 deletions ImperatorToCK3/CK3/Titles/LandedTitles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@
return newTitle;
}

internal Title Add(
private Title Add(
string id,
Governorship governorship,
Country country,
Expand Down Expand Up @@ -778,6 +778,11 @@
// add new ones from Imperator governorships.
var counter = 0;
foreach (var governorship in governorships) {
// Don't import if the governorship has no I:R provinces.
if (governorship.GetIRProvinceCount(irWorld.Provinces) == 0) {
continue;
}

ImportImperatorGovernorship(
governorship,
this,
Expand Down Expand Up @@ -819,7 +824,8 @@

var id = DetermineId(governorship, titles, irProvinces, ck3Provinces, imperatorRegionMapper, tagTitleMapper, provinceMapper);
if (id is null) {
Logger.Warn($"Cannot convert {governorship.Region.Id} of country {country.Id}");
Logger.Warn($"Cannot convert {governorship.Region.Id} of country {country.Id}. " +
$"I:R provinces: {string.Join(", ", governorship.GetIRProvinces(irProvinces).Select(p => p.Id))}");
return;
}

Expand Down Expand Up @@ -861,54 +867,54 @@
}
}

public void ImportImperatorHoldings(ProvinceCollection ck3Provinces, Imperator.Characters.CharacterCollection irCharacters, Date conversionDate) {
Logger.Info("Importing Imperator holdings...");
var counter = 0;

var highLevelTitlesThatHaveHolders = this
.Where(t => t.Rank >= TitleRank.duchy && t.GetHolderId(conversionDate) != "0")
.ToImmutableList();
var highLevelTitleCapitalBaronyIds = highLevelTitlesThatHaveHolders
.Select(t=>t.CapitalCounty?.CapitalBaronyId ?? t.CapitalBaronyId)
.ToImmutableHashSet();

// Dukes and above should be excluded from having their holdings converted.
// Otherwise, governors with holdings would own parts of other governorships.
var dukeAndAboveIds = highLevelTitlesThatHaveHolders
.Where(t => t.Rank >= TitleRank.duchy)
.Select(t => t.GetHolderId(conversionDate))
.ToImmutableHashSet();

// We exclude baronies that are capitals of duchies and above.
var eligibleBaronies = this
.Where(t => t.Rank == TitleRank.barony)
.Where(b => !highLevelTitleCapitalBaronyIds.Contains(b.Id))
.ToArray();

var countyCapitalBaronies = eligibleBaronies
.Where(b => b.DeJureLiege?.CapitalBaronyId == b.Id)
.OrderBy(b => b.Id)
.ToArray();

var nonCapitalBaronies = eligibleBaronies.Except(countyCapitalBaronies).OrderBy(b => b.Id).ToArray();

// In CK3, a county holder shouldn't own baronies in counties that are not their own.
// This dictionary tracks what counties are held by what characters.
Dictionary<string, HashSet<string>> countiesPerCharacter = []; // characterId -> countyIds

// Evaluate all capital baronies first (we want to distribute counties first, then baronies).
foreach (var barony in countyCapitalBaronies) {
var ck3Province = GetBaronyProvince(barony);
if (ck3Province is null) {
continue;
}

// Skip none holdings and temple holdings.
if (ck3Province.GetHoldingType(conversionDate) is "church_holding" or "none") {
continue;
}

var irProvince = ck3Province.PrimaryImperatorProvince; // TODO: when the holding owner of the primary I:R province is not able to hold the CK3 equivalent, also check the holding owners from secondary source provinces

Check warning on line 917 in ImperatorToCK3/CK3/Titles/LandedTitles.cs

View workflow job for this annotation

GitHub Actions / test (macos-14)

TODO when the holding owner of the primary I:R province is not able to hold the CK3 equivalent, also check the holding owners from secondary source provinces (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)

Check warning on line 917 in ImperatorToCK3/CK3/Titles/LandedTitles.cs

View workflow job for this annotation

GitHub Actions / test_and_check_coverage

TODO when the holding owner of the primary I:R province is not able to hold the CK3 equivalent, also check the holding owners from secondary source provinces (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)
var ck3Owner = GetEligibleCK3OwnerForImperatorProvince(irProvince);
if (ck3Owner is null) {
continue;
Expand Down Expand Up @@ -962,7 +968,7 @@
continue;
}

var irProvince = ck3Province.PrimaryImperatorProvince; // TODO: when the holding owner of the primary I:R province is not able to hold the CK3 equivalent, also check the holding owners from secondary source provinces

Check warning on line 971 in ImperatorToCK3/CK3/Titles/LandedTitles.cs

View workflow job for this annotation

GitHub Actions / test (macos-14)

TODO when the holding owner of the primary I:R province is not able to hold the CK3 equivalent, also check the holding owners from secondary source provinces (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)

Check warning on line 971 in ImperatorToCK3/CK3/Titles/LandedTitles.cs

View workflow job for this annotation

GitHub Actions / test_and_check_coverage

TODO when the holding owner of the primary I:R province is not able to hold the CK3 equivalent, also check the holding owners from secondary source provinces (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)
var ck3Owner = GetEligibleCK3OwnerForImperatorProvince(irProvince);
if (ck3Owner is null) {
continue;
Expand Down Expand Up @@ -1388,21 +1394,23 @@
}
kingdomToDominantHeritagesDict[kingdom.Id] = dominantHeritages;

var dominantHeritage = dominantHeritages[0];

if (heritageToEmpireDict.TryGetValue(dominantHeritage.Id, out var empire)) {
if (empire is null) {
// The heritage is not supposed to have an empire.
continue;
foreach (var dominantHeritage in dominantHeritages) {
if (heritageToEmpireDict.TryGetValue(dominantHeritage.Id, out var empire)) {
if (empire is null) {
// The heritage is not supposed to have an empire, try the next dominant heritage.
continue;
}
kingdom.DeJureLiege = empire;
break;
}
kingdom.DeJureLiege = empire;
} else {
// Create new de jure empire based on heritage.

// Create new de jure empire based on the first usable heritage.
var heritageEmpire = CreateEmpireForHeritage(dominantHeritage, ck3Cultures, ck3LocDB);
removableEmpireIds.Add(heritageEmpire.Id);

kingdom.DeJureLiege = heritageEmpire;
heritageToEmpireDict[dominantHeritage.Id] = heritageEmpire;
break;
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion ImperatorToCK3/CK3/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,340 +74,340 @@
/// </summary>
public Date CorrectedDate { get; private set; } = new Date(2, 1, 1); // overwritten by DetermineCK3BookmarkDate

internal World(Imperator.World impWorld, Configuration config, Thread? irCoaExtractThread) {
Logger.Info("*** Hello CK3, let's get painting. ***");

warMapper.DetectUnmappedWarGoals(impWorld.ModFS);

DetermineCK3Dlcs(config);
LoadAndDetectCK3Mods(config);

// Now that the CK3 mods are detected, we can build a collection of variables for Liquid files.
var liquidVariables = config.GetLiquidVariables();

// Initialize fields that depend on other fields.
Religions = new ReligionCollection(LandedTitles);

DetermineCK3BookmarkDate(impWorld, config);

// Recreate output mod folder.
string outputModPath = Path.Join("output", config.OutputModName);
WorldOutputter.ClearOutputModFolder(outputModPath);
WorldOutputter.CreateModFolder(outputModPath);
// This will also convert all Liquid templates into simple text files.
WorldOutputter.CopyBlankModFilesToOutput(outputModPath, liquidVariables);

// Include a fake mod pointing to blankMod in the output folder.
LoadedMods.Add(new Mod("blankMod", outputModPath));
ModFS = new ModFilesystem(Path.Combine(config.CK3Path, "game"), LoadedMods);

var ck3Defines = new Defines();
ck3Defines.LoadDefines(ModFS);

ColorFactory ck3ColorFactory = new();
// Now that we have the mod filesystem, we can initialize the localization database.
Parallel.Invoke(
() => LoadCorrectProvinceMappingsFile(impWorld, config), // Depends on loaded mods.
() => {
LocDB.LoadLocFromModFS(ModFS, config.GetActiveCK3ModFlags());
Logger.IncrementProgress();
},
() => ScriptValues.LoadScriptValues(ModFS, ck3Defines),
() => {
NamedColors.LoadNamedColors("common/named_colors", ModFS);
ck3ColorFactory.AddNamedColorDict(NamedColors);
},
() => {
Logger.Info("Loading map data...");
MapData = new MapData(ModFS);
},
() => CK3CoaMapper = new(ModFS),
() => {
// Modify some CK3 and mod files and put them in the output before we start outputting anything.
FileTweaker.ModifyAndRemovePartsOfFiles(ModFS, outputModPath, config).Wait();
}
);

var ck3ModFlags = config.GetCK3ModFlags();

Parallel.Invoke(
() => provinceMapper.DetectInvalidMappings(impWorld.MapData, MapData), // depends on ProvinceMapper and MapData
() => { // depends on ck3ColorFactory and CulturalPillars
// Load CK3 cultures from CK3 mod filesystem.
Logger.Info("Loading cultural pillars...");
CulturalPillars = new(ck3ColorFactory, ck3ModFlags);
CulturalPillars.LoadPillars(ModFS, ck3ModFlags);
Logger.Info("Loading converter cultural pillars...");
CulturalPillars.LoadConverterPillars("configurables/cultural_pillars", ck3ModFlags, liquidVariables);
Cultures = new CultureCollection(ck3ColorFactory, CulturalPillars, ck3ModFlags);
Cultures.LoadNameLists(ModFS);
Cultures.LoadInnovationIds(ModFS);
Cultures.LoadCultures(ModFS);
Cultures.LoadConverterCultures("configurables/converter_cultures.txt");
Cultures.WarnAboutCircularParents();
Logger.IncrementProgress();
},
() => LoadMenAtArmsTypes(ModFS, ScriptValues), // depends on ScriptValues
() => { // depends on LocDB and CK3CoaMapper
// Load vanilla CK3 landed titles and their history
LandedTitles.LoadTitles(ModFS, LocDB, ck3ColorFactory);

if (config.StaticDeJure) {
Logger.Info("Setting static de jure kingdoms and empires...");

Title.LandedTitles overrideTitles = [];
overrideTitles.LoadStaticTitles(ck3ColorFactory);
LandedTitles.CarveTitles(overrideTitles);

Logger.IncrementProgress();
}

LandedTitles.SetCoatsOfArms(CK3CoaMapper);

LandedTitles.LoadHistory(config, ModFS);
LandedTitles.LoadCulturalNamesFromConfigurables();
}
);

// Load regions.
CK3RegionMapper = new CK3RegionMapper(ModFS, LandedTitles);
imperatorRegionMapper = impWorld.ImperatorRegionMapper;

CultureMapper cultureMapper = null!;
TraitMapper traitMapper = null!;
DNAFactory dnaFactory = null!;
Parallel.Invoke(
() => { // depends on ck3ColorFactory and landed titles being loaded
// Load CK3 religions from game and blankMod.
// Holy sites need to be loaded after landed titles.
Religions.LoadDoctrines(ModFS);
Logger.Info("Loaded CK3 doctrines.");
Religions.LoadConverterHolySites("configurables/converter_holy_sites.txt");
Logger.Info("Loaded converter holy sites.");
Religions.LoadHolySites(ModFS);
Logger.Info("Loaded CK3 holy sites.");
Logger.Info("Loading religions from CK3 game and mods...");
Religions.LoadReligions(ModFS, ck3ColorFactory);
Logger.Info("Loaded CK3 religions.");
Logger.IncrementProgress();
Logger.Info("Loading converter faiths...");
Religions.LoadConverterFaiths("configurables/converter_faiths.liquid", ck3ColorFactory, liquidVariables);
Logger.Info("Loaded converter faiths.");
Logger.IncrementProgress();
Religions.RemoveChristianAndIslamicSyncretismFromAllFaiths();
// Now that all the faiths are loaded, remove liege entries from the history of religious head titles.
LandedTitles.RemoveLiegeEntriesFromReligiousHeadHistory(Religions);

Religions.LoadReplaceableHolySites("configurables/replaceable_holy_sites.txt");
Logger.Info("Loaded replaceable holy sites.");
},

() => cultureMapper = new CultureMapper(imperatorRegionMapper, CK3RegionMapper, Cultures),

() => {
traitMapper = new("configurables/trait_map.txt", ModFS);
traitMapper.LogUnmappedImperatorTraits(impWorld.ModFS);
},

() => {
Logger.Info("Initializing DNA factory...");
dnaFactory = new(impWorld.ModFS, ModFS);
Logger.IncrementProgress();
},

() => {
Characters.LoadCK3Characters(ModFS, config.CK3BookmarkDate);
Logger.IncrementProgress();
}
);

var religionMapper = new ReligionMapper(Religions, imperatorRegionMapper, CK3RegionMapper);

Parallel.Invoke(
() => Cultures.ImportTechnology(impWorld.Countries, cultureMapper, provinceMapper, impWorld.InventionsDB, impWorld.LocDB, liquidVariables),

() => { // depends on religionMapper
// Check if all I:R religions have a base mapping.
foreach (var irReligionId in impWorld.Religions.Select(r => r.Id)) {
var baseMapping = religionMapper.Match(irReligionId, null, null, null, null, config);
if (baseMapping is null) {
string religionStr = "ID: " + irReligionId;
var localizedName = impWorld.LocDB.GetLocBlockForKey(irReligionId)?["english"];
if (localizedName is not null) {
religionStr += $", name: {localizedName}";
}
Logger.Warn($"No base mapping found for I:R religion {religionStr}!");
}
}
},
() => { // depends on cultureMapper
// Check if all I:R cultures have a base mapping.
var irCultureIds = impWorld.CulturesDB.SelectMany(g => g.Select(c => c.Id));
foreach (var irCultureId in irCultureIds) {
var baseMapping = cultureMapper.Match(irCultureId, null, null, null);
if (baseMapping is null) {
string cultureStr = "ID: " + irCultureId;
var localizedName = impWorld.LocDB.GetLocBlockForKey(irCultureId)?["english"];
if (localizedName is not null) {
cultureStr += $", name: {localizedName}";
}
Logger.Warn($"No base mapping found for I:R culture {cultureStr}!");
}
}
},
() => { // depends on TraitMapper and CK3 characters being loaded
Characters.RemoveUndefinedTraits(traitMapper);
}
);

Characters.ImportImperatorCharacters(
impWorld,
religionMapper,
cultureMapper,
Cultures,
traitMapper,
nicknameMapper,
provinceMapper,
deathReasonMapper,
dnaFactory,
LocDB,
impWorld.EndDate,
config
);
// Now that we have loaded all characters, we can mark some of them as non-removable.
Characters.LoadCharacterIDsToPreserve(config.CK3BookmarkDate);
ClearFeaturedCharactersDescriptions(config.CK3BookmarkDate);

Dynasties.LoadCK3Dynasties(ModFS);
// Now that we have loaded all dynasties from CK3, we can remove invalid dynasty IDs from character history.
Characters.RemoveInvalidDynastiesFromHistory(Dynasties);
Dynasties.ImportImperatorFamilies(impWorld, cultureMapper, impWorld.LocDB, LocDB, CorrectedDate);
DynastyHouses.LoadCK3Houses(ModFS);

GovernmentMapper governmentMapper = InitializeGovernmentMapper();

// Before we can import Imperator countries and governorships, the CoA extraction thread needs to finish.
irCoaExtractThread?.Join();

SuccessionLawMapper successionLawMapper = new("configurables/succession_law_map.liquid", liquidVariables);
List<KeyValuePair<Country, Dependency?>> countyLevelCountries = [];
LandedTitles.ImportImperatorCountries(
impWorld.Countries,
impWorld.Dependencies,
tagTitleMapper,
impWorld.LocDB,
LocDB,
provinceMapper,
impWorld.CoaMapper,
governmentMapper,
successionLawMapper,
definiteFormMapper,
religionMapper,
cultureMapper,
nicknameMapper,
Characters,
CorrectedDate,
config,
countyLevelCountries,
enabledDlcFlags
);

// Now we can deal with provinces since we know to whom to assign them. We first import vanilla province data.
// Some of it will be overwritten, but not all.
Provinces.ImportVanillaProvinces(ModFS, MapData.ProvinceDefinitions, Religions, Cultures);

// Next we import Imperator provinces and translate them ontop a significant part of all imported provinces.
Provinces.ImportImperatorProvinces(impWorld, MapData, LandedTitles, cultureMapper, religionMapper, provinceMapper, CorrectedDate, config);
Provinces.LoadPrehistory();

var countyLevelGovernorships = new List<Governorship>();
LandedTitles.ImportImperatorGovernorships(
impWorld,
Provinces,
tagTitleMapper,
impWorld.LocDB,
LocDB,
config,
provinceMapper,
definiteFormMapper,
imperatorRegionMapper,
impWorld.CoaMapper,
countyLevelGovernorships
);

// Give counties to rulers and governors.
OverwriteCountiesHistory(impWorld.Countries, impWorld.JobsDB.Governorships, countyLevelCountries, countyLevelGovernorships, impWorld.Characters, impWorld.Provinces, CorrectedDate);
ImportImperatorHoldingsIfNotDisabledByConfiguration(impWorld, config);

LandedTitles.ImportDevelopmentFromImperator(Provinces, CorrectedDate, config.ImperatorCivilizationWorth);

// Apply region-specific tweaks.
HandleIcelandAndFaroeIslands(impWorld, config);

// Apply religion-specific tweaks.
RemoveIslamFromMapIfNotInImperator(impWorld, config);
HandleChristianity(impWorld, config);
HandleManichaeism(impWorld, config);

// Now that Islam has been handled, we can generate filler holders without the risk of making them Muslim.
GenerateFillerHoldersForUnownedLands(impWorld.Provinces, Cultures, config);
// The filler holders have overwritten some counties, so now we can remove holders from titles that have become landless.
LandedTitles.RemoveInvalidLandlessTitles(config.CK3BookmarkDate);
Logger.IncrementProgress();
if (!config.StaticDeJure) {
LandedTitles.SetDeJureKingdomsAndAbove(config.CK3BookmarkDate, Cultures, Characters, MapData, CK3RegionMapper, LocDB);
}

Dynasties.SetCoasForRulingDynasties(LandedTitles, config.CK3BookmarkDate);

Characters.RemoveEmployerIdFromLandedCharacters(LandedTitles, CorrectedDate);
Characters.PurgeUnneededCharacters(LandedTitles, Dynasties, DynastyHouses, config.CK3BookmarkDate);
// We could convert Imperator character DNA while importing the characters.
// But that'd be wasteful, because some of them are purged. So, we do it now.
Characters.ConvertImperatorCharacterDNA(dnaFactory);

// If there's a gap between the Imperator save date and the CK3 bookmark date,
// generate successors for old I:R characters instead of making them live for centuries.
if (config.CK3BookmarkDate.DiffInYears(impWorld.EndDate) > 1) {
Characters.GenerateSuccessorsForOldCharacters(LandedTitles, Cultures, impWorld.EndDate, config.CK3BookmarkDate, impWorld.RandomSeed);
}

// Gold needs to be distributed after characters' successors are generated.
Characters.DistributeCountriesGold(LandedTitles, config);
Characters.ImportLegions(LandedTitles, impWorld.Units, impWorld.Characters, impWorld.Countries, CorrectedDate, unitTypeMapper, MenAtArmsTypes, provinceMapper, LocDB, config);

// For titles linked to I:R countries with chinese_empire government, ensure the character variables
// needed for Dynastic Cycle script are calculated and stores as character variables.
Characters.CalculateChineseDynasticCycleVariables(LandedTitles, impWorld.EndDate, config.CK3BookmarkDate);

// After the purging of unneeded characters, we should clean up the title history.
LandedTitles.CleanUpHistory(Characters, config.CK3BookmarkDate);

// Now that the title history is basically done, convert officials as council members and courtiers.
LandedTitles.ImportImperatorGovernmentOffices(impWorld.JobsDB.OfficeJobs, Religions, impWorld.EndDate);

Parallel.Invoke(
() => ImportImperatorWars(impWorld, config.CK3BookmarkDate),

() => {
var holySiteEffectMapper = new HolySiteEffectMapper("configurables/holy_site_effect_mappings.txt");
Religions.DetermineHolySites(Provinces, impWorld.Religions, holySiteEffectMapper, config.CK3BookmarkDate);

Religions.GenerateMissingReligiousHeads(LandedTitles, Characters, Provinces, Cultures, config.CK3BookmarkDate);
Logger.IncrementProgress();
},

() => {
LegendSeeds.LoadSeeds(ModFS);
LegendSeeds.RemoveAnachronisticSeeds("configurables/legend_seeds_to_remove.txt");
},

() => {
Diplomacy.ImportImperatorLeagues(impWorld.DefensiveLeagues, impWorld.Countries);
}
);
}

Check notice on line 410 in ImperatorToCK3/CK3/World.cs

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/World.cs#L77-L410

Complex Method
private void ImportImperatorHoldingsIfNotDisabledByConfiguration(Imperator.World irWorld, Configuration config) {
if (!config.SkipHoldingOwnersImport) {
// Import holding owners as barons and counts.
Expand Down Expand Up @@ -551,7 +551,7 @@
private void LoadCorrectProvinceMappingsFile(Imperator.World irWorld, Configuration config) {
// Terra Indomita mappings should be used if either TI or Antiquitas is detected.
bool irHasTI = config.TerraIndomitaDetected;

bool ck3HasRajasOfAsia = config.RajasOfAsiaEnabled;
bool ck3HasAEP = config.AsiaExpansionProjectEnabled;

Expand All @@ -562,6 +562,8 @@
mappingsToUse = "terra_indomita_to_aep";
} else if (irHasTI) {
mappingsToUse = "terra_indomita_to_vanilla_ck3";
} else if (config.WhenTheWorldStoppedMakingSenseEnabled) {
mappingsToUse = "invictus_to_wtwsms";
} else if (config is {InvictusDetected: true, Invictus1_7Detected: true}) {
mappingsToUse = "invictus_1_7_to_vanilla_ck3";
} else if (config.InvictusDetected) {
Expand Down Expand Up @@ -603,93 +605,93 @@
}
}

private void OverwriteCountiesHistory(CountryCollection irCountries, List<Governorship> governorships, List<KeyValuePair<Country, Dependency?>> countyLevelCountries, List<Governorship> countyLevelGovernorships, Imperator.Characters.CharacterCollection impCharacters, Imperator.Provinces.ProvinceCollection irProvinces, Date conversionDate) {
Logger.Info("Overwriting counties' history...");
FrozenSet<Governorship> governorshipsSet = governorships.ToFrozenSet();
FrozenSet<Governorship> countyLevelGovernorshipsSet = countyLevelGovernorships.ToFrozenSet();

foreach (var county in LandedTitles.Counties) {
if (county.NobleFamily == true) {
continue;
}
if (county.CapitalBaronyProvinceId is null) {
Logger.Warn($"County {county} has no capital barony province!");
continue;
}
ulong capitalBaronyProvId = (ulong)county.CapitalBaronyProvinceId;
if (capitalBaronyProvId == 0) {
// title's capital province has an invalid ID (0 is not a valid province in CK3)
Logger.Warn($"County {county} has invalid capital barony province!");
continue;
}

if (!Provinces.ContainsKey(capitalBaronyProvId)) {
Logger.Warn($"Capital barony province not found: {capitalBaronyProvId}");
continue;
}

var ck3CapitalBaronyProvince = Provinces[capitalBaronyProvId];
var irProvince = ck3CapitalBaronyProvince.PrimaryImperatorProvince;
// If the county capital's primary I:R province has no owner,
// try to use other source provinces.
// If this fails, try using source provinces of other baronies.
if (irProvince?.OwnerCountry is null) {
foreach (var secondarySourceProv in ck3CapitalBaronyProvince.SecondaryImperatorProvinces) {
if (secondarySourceProv.OwnerCountry is null) {
continue;
}

irProvince = secondarySourceProv;
Logger.Debug($"Using secondary source province {secondarySourceProv.Id} of capital barony" +
$"province {capitalBaronyProvId} for history of county {county.Id}!");
}
}
if (irProvince?.OwnerCountry is null) {
foreach (var barony in county.DeJureVassals) {
var baronyCk3ProvId = barony.ProvinceId;
if (baronyCk3ProvId is null) {
continue;
}
var primarySourceProvForBarony = Provinces[baronyCk3ProvId.Value].PrimaryImperatorProvince;
if (primarySourceProvForBarony?.OwnerCountry is null) {
continue;
}

irProvince = primarySourceProvForBarony;
Logger.Debug($"Using province {baronyCk3ProvId.Value} of barony {barony.Id} instead of" +
$"capital barony province {capitalBaronyProvId} for history of county {county.Id}!");
break;
}
}
if (irProvince?.OwnerCountry is null) {
foreach (var barony in county.DeJureVassals) {
var baronyCk3ProvId = barony.ProvinceId;
if (baronyCk3ProvId is null) {
continue;
}

var secondaryProvWithOwner = Provinces[baronyCk3ProvId.Value].SecondaryImperatorProvinces
.FirstOrDefault(p => p.OwnerCountry is not null);
if (secondaryProvWithOwner is null) {
continue;
}

irProvince = secondaryProvWithOwner;
Logger.Debug($"Using province {baronyCk3ProvId.Value} of barony {barony.Id} instead of" +
$"capital barony province {capitalBaronyProvId} for history of county {county.Id}!");
break;
}
}

if (irProvince is null) { // probably outside of Imperator map
continue;
}

OverwriteCountyHistory(county, irProvince, irCountries, countyLevelCountries, governorshipsSet, countyLevelGovernorshipsSet, impCharacters, irProvinces, conversionDate);
}
Logger.IncrementProgress();
}

Check notice on line 694 in ImperatorToCK3/CK3/World.cs

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/World.cs#L608-L694

Complex Method
private void OverwriteCountyHistory(Title county, Imperator.Provinces.Province irProvince, CountryCollection irCountries,
List<KeyValuePair<Country, Dependency?>> countyLevelCountries, FrozenSet<Governorship> governorshipsSet, FrozenSet<Governorship> countyLevelGovernorshipsSet,
Imperator.Characters.CharacterCollection irCharacters, Imperator.Provinces.ProvinceCollection irProvinces, Date conversionDate) {
Expand Down Expand Up @@ -858,105 +860,105 @@
}
}

private void HandleIcelandAndFaroeIslands(Imperator.World irWorld, Configuration config) {
Logger.Info("Handling Iceland and Faroe Islands...");
Date bookmarkDate = config.CK3BookmarkDate;
var year = bookmarkDate.Year;

var faiths = Religions.Faiths.ToArray();

OrderedSet<string> titleIdsToHandle;
if (config.FallenEagleEnabled) {
// Iceland doesn't exist on TFE map.
titleIdsToHandle = ["c_faereyar"];
} else if (config.TerraIndomitaDetected) {
// The Faroe Islands are on the map in TI, so it should be handled normally instead of being given an Eremitic holder.
titleIdsToHandle = ["d_iceland"];
} else {
titleIdsToHandle = ["d_iceland", "c_faereyar"];
}

bool generateHermits = true;
IEnumerable<string> faithCandidates = new OrderedSet<string>();
Queue<string> namePool = new();
const string defaultCultureId = "irish";
string cultureId = defaultCultureId;

switch (year) {
case <= 300:
UsePaganRulersForIcelandAndFaroeIslands(out faithCandidates, out cultureId, out namePool);
break;
case < 874:
faithCandidates = new OrderedSet<string> { "insular_celtic", "catholic", "orthodox", "chalcedonian", "nicene" };
var christianFaiths = Religions.TryGetValue("christianity_religion", out var christianityReligion) ? christianityReligion.Faiths : [];

// If there is at least one Irish Christian county, give it to the Irish Papar.
// If there is at least one Christian county of another Gaelic culture, give it to a character of this Gaelic culture.
var cultureCandidates = new[] { "irish", "gaelic" };
bool provinceFound = false;
foreach (var potentialCultureId in cultureCandidates) {
var cultureProvinces = Provinces.Where(p =>
p.GetCultureId(bookmarkDate) == potentialCultureId);
foreach (var cultureProvince in cultureProvinces) {
var faithId = cultureProvince.GetFaithId(bookmarkDate);
if (faithId is null || !christianFaiths.ContainsKey(faithId)) {
continue;
}
provinceFound = true;
cultureId = potentialCultureId;
faithCandidates = faithCandidates.Prepend(faithId);
break;
}
if (provinceFound) {
break;
}
}
if (!provinceFound) {
// If all the Gaels are pagan but at least one province in Ireland or Scotland is Christian,
// give the handled titles to a generated ruler of the same culture as that Christian province.
var potentialSourceProvinces = Provinces.Where(p =>
CK3RegionMapper.ProvinceIsInRegion(p.Id, "custom_ireland") || CK3RegionMapper.ProvinceIsInRegion(p.Id, "custom_scotland"));
foreach (var potentialSourceProvince in potentialSourceProvinces) {
var faithId = potentialSourceProvince.GetFaithId(bookmarkDate);
if (faithId is null || !christianFaiths.ContainsKey(faithId)) {
continue;
}
provinceFound = true;
cultureId = potentialSourceProvince.GetCultureId(bookmarkDate) ?? defaultCultureId;
faithCandidates = faithCandidates.Prepend(faithId);
break;
}
}
if (!provinceFound) {
// Give up and create a pagan ruler.
UsePaganRulersForIcelandAndFaroeIslands(out faithCandidates, out cultureId, out namePool);
} else {
Logger.Info("Giving Iceland and Faroe Islands to Papar...");
namePool = new Queue<string>(["Canann", "Petair", "Fergus"]);
}
break;
default:
Logger.Info("Keeping Iceland and Faroe Islands as is in history...");
// Let CK3 use rulers from its history.
generateHermits = false;
break;
}

if (generateHermits) {
var faithId = faithCandidates.First(c => faiths.Any(f => f.Id == c));
foreach (var titleId in titleIdsToHandle) {
if (!LandedTitles.TryGetValue(titleId, out var title)) {
Logger.Warn($"Title {titleId} not found!");
continue;
}

GenerateHermitForTitle(title, namePool, bookmarkDate, faithId, cultureId, config);
}
}

Logger.IncrementProgress();
}

Check notice on line 961 in ImperatorToCK3/CK3/World.cs

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/World.cs#L863-L961

Complex Method
private void UsePaganRulersForIcelandAndFaroeIslands(out IEnumerable<string> faithCandidates, out string cultureId, out Queue<string> namePool) {
Logger.Info("Giving Iceland and Faroe Islands to pagan Gaels...");
faithCandidates = new OrderedSet<string> { "gaelic_paganism", "celtic_pagan", "briton_paganism", "pagan" };
Expand Down Expand Up @@ -1186,178 +1188,178 @@
}
}

private void GenerateFillerHoldersForUnownedLands(Imperator.Provinces.ProvinceCollection irProvinces, CultureCollection cultures, Configuration config) {
Logger.Info("Generating filler holders for unowned lands...");
var date = config.CK3BookmarkDate;
List<Title> unheldCounties = [];
foreach (var county in LandedTitles.Counties) {
if (county.NobleFamily == true) {
continue;
}

// If the county's provinces are have no owners in Imperator,
// // generate a filler holder even if a valid vanilla holder exists.
// This fixes stuff like a vanilla Tang China in one county.
var irProvIds = county.CountyProvinceIds
.SelectMany(id => provinceMapper.GetImperatorProvinceNumbers(id)).ToArray();
if (irProvIds.Length > 0 && irProvIds.All(p => !irProvinces.TryGetValue(p, out var irProv) || irProv.OwnerCountry is null)) {
Logger.Debug($"Adding {county.Id} to unheld counties because all its provinces are mapped to I:R wastelands.");
unheldCounties.Add(county);
continue;
}

var holderId = county.GetHolderId(date);
if (holderId == "0") {
unheldCounties.Add(county);
} else if (Characters.TryGetValue(holderId, out var holder)) {
if (holder.DeathDate is not null && holder.DeathDate <= date) {
Logger.Debug($"Adding {county.Id} to unheld counties because holder {holderId} is dead.");
unheldCounties.Add(county);
}
}
}

var duchyIdToHolderDict = new Dictionary<string, Character>();

foreach (var county in unheldCounties) {
if (config.FillerDukes) {
var duchy = county.DeJureLiege;
if (duchy is not null && duchy.Rank == TitleRank.duchy) {
if (duchyIdToHolderDict.TryGetValue(duchy.Id, out var duchyHolder)) {
county.SetHolder(duchyHolder, date);
continue;
}
}
}

var candidateProvinces = new OrderedSet<Province>();
if (county.CapitalBaronyProvinceId is not null) {
// Give priority to capital province.
if (Provinces.TryGetValue(county.CapitalBaronyProvinceId.Value, out var capitalProvince)) {
candidateProvinces.Add(capitalProvince);
}
}

var allCountyProvinces = county.CountyProvinceIds
.Select(id => Provinces.TryGetValue(id, out var province) ? province : null)
.Where(p => p is not null)
.Select(p => p!);
candidateProvinces.UnionWith(allCountyProvinces);

int pseudoRandomSeed;
if (candidateProvinces.Count != 0) {
pseudoRandomSeed = (int)candidateProvinces.First().Id;
} else {
// Use county ID for seed if no province is available.
pseudoRandomSeed = county.Id.Aggregate(0, (current, c) => current + c);
}

// Determine culture of the holder.
var culture = candidateProvinces
.Select(p => p.GetCulture(date, cultures))
.FirstOrDefault(c => c is not null);
if (culture is null) {
Logger.Debug($"Trying to use de jure duchy for culture of holder for {county.Id}...");
var deJureDuchy = county.DeJureLiege;
if (deJureDuchy is not null) {
culture = Provinces
.Where(p => deJureDuchy.DuchyContainsProvince(p.Id))
.Select(p => p.GetCulture(date, cultures))
.FirstOrDefault(c => c is not null);
}
if (culture is null && deJureDuchy?.DeJureLiege is not null) {
Logger.Debug($"Trying to use de jure kingdom for culture of holder for {county.Id}...");
var deJureKingdom = deJureDuchy.DeJureLiege;
culture = Provinces
.Where(p => deJureKingdom.KingdomContainsProvince(p.Id))
.Select(p => p.GetCulture(date, cultures))
.FirstOrDefault(c => c is not null);
}
if (culture is null) {
Logger.Warn($"Found no fitting culture for generated holder of {county.Id}, " +
"using first culture from database!");
culture = cultures.First();
}
}

// Determine faith of the holder.
var faithId = candidateProvinces
.Select(p => p.GetFaithId(date))
.FirstOrDefault(f => f is not null);
if (faithId is null) {
Logger.Debug($"Trying to use de jure duchy for faith of holder for {county.Id}...");
var deJureDuchy = county.DeJureLiege;
if (deJureDuchy is not null) {
faithId = Provinces
.Where(p => deJureDuchy.DuchyContainsProvince(p.Id))
.Select(p => p.GetFaithId(date))
.FirstOrDefault(f => f is not null);
}
if (faithId is null && deJureDuchy?.DeJureLiege is not null) {
Logger.Debug($"Trying to use de jure kingdom for faith of holder for {county.Id}...");
var deJureKingdom = deJureDuchy.DeJureLiege;
faithId = Provinces
.Where(p => deJureKingdom.KingdomContainsProvince(p.Id))
.Select(p => p.GetFaithId(date))
.FirstOrDefault(f => f is not null);
}
if (faithId is null) {
Logger.Warn($"Found no fitting faith for generated holder of {county.Id}, " +
"using first faith from database!");
faithId = Religions.Faiths.First().Id;
}
}

bool female = false;
string name;
var maleNames = culture.MaleNames.ToImmutableList();
if (maleNames.Count > 0) {
name = maleNames[pseudoRandomSeed % maleNames.Count];
} else { // Generate a female if no male name is available.
female = true;
var femaleNames = culture.FemaleNames.ToImmutableList();
name = femaleNames[pseudoRandomSeed % femaleNames.Count];
}
int age = 18 + (pseudoRandomSeed % 60);
var holder = new Character($"IRToCK3_{county.Id}_holder", name, date, Characters) {
FromImperator = true,
Female = female,
BirthDate = date.ChangeByYears(-age)
};
holder.SetFaithId(faithId, null);
holder.SetCultureId(culture.Id, null);
holder.History.AddFieldValue(holder.BirthDate, "effects", "effect", "{ set_variable = irtock3_uncolonized_filler }");
Characters.AddOrReplace(holder);

var countyHoldingTypes = county.CountyProvinceIds
.Select(id => Provinces.TryGetValue(id, out var province) ? province : null)
.Where(p => p is not null)
.Select(p => p!.GetHoldingType(date))
.Where(t => t is not null)
.Select(t => t!)
.ToFrozenSet();
string government = countyHoldingTypes.Contains("castle_holding")
? "feudal_government"
: "tribal_government";

county.SetHolder(holder, date);
if (config.FillerDukes) {
var duchy = county.DeJureLiege;
if (duchy is null || duchy.Rank != TitleRank.duchy) {
continue;
}

duchy.SetHolder(holder, date);
duchy.SetGovernment(government, date);
duchy.SetDeFactoLiege(newLiege: null, date);
duchyIdToHolderDict[duchy.Id] = holder;
} else {
county.SetGovernment(government, date);
}
county.SetDeFactoLiege(newLiege: null, date);
}
}

Check warning on line 1362 in ImperatorToCK3/CK3/World.cs

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/World.cs#L1191-L1362

Very Complex Method
private void DetermineCK3Dlcs(Configuration config) {
var dlcFolderPath = Path.Join(config.CK3Path, "game/dlc");
if (!Directory.Exists(dlcFolderPath)) {
Expand Down
1 change: 0 additions & 1 deletion ImperatorToCK3/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using ImperatorToCK3.CommonUtils;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,8 @@ irtock3_form_prefecture_magna_taprobana_decision = {
}
}


{% unless wtwsms %} # WtWSMS doesn't have playable East Asia yet.
# irtock3_rome_empire_division_insulae_remotae: "Insulae Remotae"
irtock3_form_prefecture_insulae_remotae_decision = {
picture = {
Expand Down Expand Up @@ -1845,6 +1847,7 @@ irtock3_form_prefecture_insulae_solis_decision = {
irtock3_form_roman_prefecture_effect = { REGION = irtock3_rome_empire_division_insulae_solis }
}
}
{% endunless %}

# irtock3_rome_empire_division_septentrionalis_deserti: "Septentrionalis Deserti"
irtock3_form_prefecture_septentrionalis_deserti_decision = {
Expand Down Expand Up @@ -1917,6 +1920,7 @@ irtock3_form_prefecture_septentrionalis_deserti_decision = {
}
}

{% unless wtwsms %} # WtWSMS doesn't have playable East Asia yet.
# irtock3_rome_empire_division_serica_ultima: "Serica Ultima"
irtock3_form_prefecture_serica_ultima_decision = {
picture = {
Expand Down Expand Up @@ -2342,3 +2346,4 @@ irtock3_form_prefecture_serica_deserti_decision = {
irtock3_form_roman_prefecture_effect = { REGION = irtock3_rome_empire_division_serica_deserti }
}
}
{% endunless %}
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ IRToCK3_game_start_onaction_effects = {
REGION = irtock3_rome_empire_division_imoan_montem
EMPIRE = e_tibet
}
{% unless wtwsms %} # WtWSMS doesn't have playable East Asia yet.
# Insulae Remotae
irtock3_gamestart_add_title_to_prefecture_region_effect = {
REGION = irtock3_rome_empire_division_insulae_remotae
Expand All @@ -275,11 +276,13 @@ IRToCK3_game_start_onaction_effects = {
REGION = irtock3_rome_empire_division_insulae_solis
EMPIRE = e_japan
}
{% endunless %}
# Septentrionalis Deserti
irtock3_gamestart_add_title_to_prefecture_region_effect = {
REGION = irtock3_rome_empire_division_septentrionalis_deserti
EMPIRE = e_mongolia
}
{% unless wtwsms %} # WtWSMS doesn't have playable East Asia yet.
# Serica Meridiana
irtock3_gamestart_add_title_to_prefecture_region_effect = {
REGION = irtock3_rome_empire_division_serica_meridiana
Expand All @@ -305,6 +308,7 @@ IRToCK3_game_start_onaction_effects = {
REGION = irtock3_rome_empire_division_serica_deserti
EMPIRE = e_yongliang
}
{% endunless %}

## If a hegemony Rome title exists at game start, need to make sure it's de jure empires are properly setup as Praetorian Prefectures
if = {
Expand Down Expand Up @@ -364,12 +368,15 @@ IRToCK3_game_start_onaction_effects = {
irtock3_setup_roman_prefectures_game_start = { REGION = india_extra_gangem }
# Magna Taprobana
irtock3_setup_roman_prefectures_game_start = { REGION = magna_taprobana }
{% unless wtwsms %} # WtWSMS doesn't have playable East Asia yet.
# Insulae Remotae
irtock3_setup_roman_prefectures_game_start = { REGION = insulae_remotae }
# Insulae Solis
irtock3_setup_roman_prefectures_game_start = { REGION = insulae_solis }
{% endunless %}
# Septentrionalis Deserti
irtock3_setup_roman_prefectures_game_start = { REGION = septentrionalis_deserti }
{% unless wtwsms %} # WtWSMS doesn't have playable East Asia yet.
# Serica Ultima
irtock3_setup_roman_prefectures_game_start = { REGION = serica_ultima }
# Serica Meridiana
Expand All @@ -383,6 +390,7 @@ IRToCK3_game_start_onaction_effects = {
# Serica Deserti
irtock3_setup_roman_prefectures_game_start = { REGION = serica_deserti }
}
{% endunless %}

## If anyone holds the Rome hegemony titles at game start, they should have the Augustus trait and naming flag, and their vassals should get flags so their titles are properly named as well
if = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,12 +347,15 @@ split_byzantine_empire_effect = {
irtock3_split_rome_empire_region_effect = { REGION = irtock3_rome_empire_division_india_extra_gangem }
# Magna Taprobana
irtock3_split_rome_empire_region_effect = { REGION = irtock3_rome_empire_division_magna_taprobana }
{% unless wtwsms %} # WtWSMS doesn't have playable East Asia yet.
# Insulae Remotae
irtock3_split_rome_empire_region_effect = { REGION = irtock3_rome_empire_division_insulae_remotae }
# Insulae Solis
irtock3_split_rome_empire_region_effect = { REGION = irtock3_rome_empire_division_insulae_solis }
{% endunless %}
# Septentrionalis Deserti
irtock3_split_rome_empire_region_effect = { REGION = irtock3_rome_empire_division_septentrionalis_deserti }
{% unless wtwsms %} # WtWSMS doesn't have playable East Asia yet.
# Serica Ultima
irtock3_split_rome_empire_region_effect = { REGION = irtock3_rome_empire_division_serica_ultima }
# Serica Meridiana
Expand All @@ -365,6 +368,7 @@ split_byzantine_empire_effect = {
irtock3_split_rome_empire_region_effect = { REGION = irtock3_rome_empire_division_serica_septentrionalis }
# Serica Deserti
irtock3_split_rome_empire_region_effect = { REGION = irtock3_rome_empire_division_serica_deserti }
{% endunless %}

# Leftover titles
## If a kingdom title under these empires is somehow split enough across multiple regions, it might not get put under one of the above prefectures, so need to check those
Expand Down
Loading
Loading