Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
f5dfccf
Lucius Verus release banner
IhateTrains Nov 1, 2025
542a402
Handle hegemony rank titles in common/landed_titles
IhateTrains Nov 1, 2025
82e8b10
Update flatmap.dds path in BookmarkOutputter for CK3 1.18
IhateTrains Nov 1, 2025
54fbad3
Rename mapping files in preparation for TI -> vanilla CK3 mappings
IhateTrains Nov 2, 2025
4f0afde
Merge branch 'master' into feat/ck3-1.18
IhateTrains Nov 4, 2025
1d48e72
Update invictus_to_vanilla_ck3.txt
IhateTrains Nov 4, 2025
f1a8057
Some TI -> CK3 triangulation pairs
IhateTrains Nov 7, 2025
33e8edb
Update terra_indomita_to_vanilla_ck3.txt
IhateTrains Nov 7, 2025
c03d3d6
Some triangulation pairs west of China
IhateTrains Nov 8, 2025
74d79af
Some triangulation pairs for China
IhateTrains Nov 9, 2025
b2cce74
Some more triangulation pairs
IhateTrains Nov 9, 2025
4ac57e5
Use terra_indomita_to_vanilla_ck3 mappings when it makes sense
IhateTrains Nov 9, 2025
29c1a37
Fix some holes in terra_indomita_to_vanilla_ck3.txt
IhateTrains Nov 9, 2025
e45e07d
Fix some holes in terra_indomita_to_vanilla_ck3.txt
IhateTrains Nov 9, 2025
ca22c48
More triangulation pairs for terra_indomita_to_vanilla_ck3.txt
IhateTrains Nov 9, 2025
c6097a3
More triangulation pairs for terra_indomita_to_vanilla_ck3.txt
IhateTrains Nov 9, 2025
aa3ad54
Parse new landed title attributes
IhateTrains Nov 9, 2025
d5bb392
Don't generate filler holders for noble family counties
IhateTrains Nov 9, 2025
c916a05
Don't try to overwrite history for noble family counties
IhateTrains Nov 9, 2025
56af117
Exclude 2 big TI impassables from automapping
IhateTrains Nov 9, 2025
fb95701
Update terra_indomita_to_vanilla_ck3.txt
IhateTrains Nov 9, 2025
fbb0f30
tanner918 AUH Patch (#2812)
tanner918 Nov 9, 2025
fbdcdd8
Merge branch 'master' into feat/ck3-1.18
IhateTrains Nov 15, 2025
18d3bf5
Merge branch 'master' into feat/ck3-1.18
IhateTrains Nov 15, 2025
37b5c3c
Update terra_indomita_to_vanilla_ck3.txt
IhateTrains Nov 15, 2025
050e1cb
Update terra_indomita_to_vanilla_ck3.txt
IhateTrains Nov 15, 2025
a210b6a
Add Invictus 1.7 -> CK3 province mappings
IhateTrains Nov 15, 2025
f3093ad
Update terra_indomita_to_vanilla_ck3.txt
IhateTrains Nov 15, 2025
2e1b2c0
Update terra_indomita_to_vanilla_ck3.txt
IhateTrains Nov 15, 2025
a7f604e
Update terra_indomita_to_vanilla_ck3.txt
IhateTrains Nov 15, 2025
a2b7660
Exclude h_china from dynamic de jure
IhateTrains Nov 16, 2025
383de82
Calculate character variables for tanner's Dynastic Cycle setup script
IhateTrains Nov 16, 2025
6732071
Unit test for years_with_government and imperator_unrest calculation
IhateTrains Nov 16, 2025
0f376e3
[CodeFactor] Apply fixes
code-factor Nov 16, 2025
800829d
Generate subheading loc for bookmark screen
IhateTrains Nov 16, 2025
7e34d4a
Merge branch 'master' into feat/ck3-1.18
IhateTrains Nov 16, 2025
3479156
Don't remove capital attribute from noble family counties
IhateTrains Nov 16, 2025
88be720
Handle effect field in province history
IhateTrains Nov 16, 2025
adaf5d8
Ignore 3 unneeded new CK3 region keywords
IhateTrains Nov 16, 2025
d36a4a7
Handle `kingdoms` keyword in CK3 regions
IhateTrains Nov 17, 2025
854eed1
Add hegemony_keywords keyword to country_rank_map.txt
IhateTrains Nov 21, 2025
a5a186b
Fix Title.DetermineId method limiting the title rank to empire
IhateTrains Nov 22, 2025
cfb0ae6
CleanUpHistory: don't consider hegemonies to be invalid lieges
IhateTrains Nov 22, 2025
f1b5104
[CodeFactor] Apply fixes to commit cfb0ae6
code-factor Nov 22, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
using Xunit;
using System;
using System.IO;
using System.Globalization;
using System.Reflection;
using System.Text.RegularExpressions;
using ImperatorRulerTerm = ImperatorToCK3.Imperator.Countries.RulerTerm;

namespace ImperatorToCK3.UnitTests.CK3.Characters;

Expand Down Expand Up @@ -415,4 +419,75 @@ public void ImperatorCharacterNamesCanBeOverriddenByConfigurable() {
// Clean up.
File.Delete(overridesFilePath);
}

[Fact]
public void ChineseDynasticCycleVariablesAreCorrectlyCalculatedForChineseEmpireCountryRulers() {
Date ck3BookmarkDate = new(810, 1, 1);
Date irEndDate = new(780, 1, 1);

var characters = new CharacterCollection();
var holder = new Character("imperator_han_emperor", "Han Emperor", new Date(760, 1, 1), characters) {
FromImperator = true
};
characters.Add(holder);

var landedTitles = new Title.LandedTitles();
var celestialEmpire = landedTitles.Add("e_chinese_empire");
celestialEmpire.SetHolder(holder, ck3BookmarkDate);

var imperatorCountry = new Country(1) { Tag = "HAN" };
SetPrivateProperty(imperatorCountry, nameof(Country.Government), "chinese_empire");
imperatorCountry.TotalPowerBase = 60f;
imperatorCountry.NonLoyalPowerBase = 15f;

var precedingNonChineseStartDate = new Date(700, 3, 1);
var earliestChineseStartDate = new Date(720, 6, 1);
var laterChineseStartDate = new Date(760, 2, 1);

imperatorCountry.RulerTerms.Add(CreateRulerTerm(precedingNonChineseStartDate, "tribal"));
imperatorCountry.RulerTerms.Add(CreateRulerTerm(earliestChineseStartDate, "chinese_empire"));
imperatorCountry.RulerTerms.Add(CreateRulerTerm(laterChineseStartDate, "chinese_empire"));

imperatorCountry.CK3Title = celestialEmpire;
SetPrivateProperty(celestialEmpire, nameof(Title.ImperatorCountry), imperatorCountry);

characters.CalculateChineseDynasticCycleVariables(landedTitles, irEndDate, ck3BookmarkDate);

var effectsField = holder.History.Fields["effects"];
var effectEntry = Assert.Single(effectsField.DateToEntriesDict);
Assert.Equal(ck3BookmarkDate, effectEntry.Key);
var effectString = Assert.IsType<StringOfItem>(Assert.Single(effectEntry.Value).Value).ToString();

var expectedYearsWithGovernment = ck3BookmarkDate.DiffInYears(earliestChineseStartDate) + (earliestChineseStartDate.DiffInYears(precedingNonChineseStartDate) / 2);
var expectedUnrest = imperatorCountry.NonLoyalPowerBase / imperatorCountry.TotalPowerBase;
var effectLines = effectString.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
var yearsLine = Assert.Single(effectLines, line => line.Contains("years_with_government", StringComparison.Ordinal));
var yearsValue = ExtractVariableValue(yearsLine);
Assert.Equal(expectedYearsWithGovernment, yearsValue, precision: 5);
var unrestLine = Assert.Single(effectLines, line => line.Contains("imperator_unrest", StringComparison.Ordinal));
var unrestValue = ExtractVariableValue(unrestLine);
Assert.Equal(expectedUnrest, unrestValue, precision: 5);
}

private static void SetPrivateProperty(object target, string propertyName, object? value) {
var targetType = target.GetType();
var property = targetType.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Assert.NotNull(property);
var setter = property!.GetSetMethod(nonPublic: true);
Assert.NotNull(setter);
setter!.Invoke(target, new[] { value });
}

private static ImperatorRulerTerm CreateRulerTerm(Date startDate, string governmentId) {
var term = new ImperatorRulerTerm();
SetPrivateProperty(term, nameof(ImperatorRulerTerm.StartDate), startDate);
SetPrivateProperty(term, nameof(ImperatorRulerTerm.Government), governmentId);
return term;
}

private static double ExtractVariableValue(string line) {
var match = Regex.Match(line, "value\\s*=\\s*(?<value>[-+]?[0-9]*\\.?[0-9]+)");
Assert.True(match.Success, $"Could not parse value from line '{line}'.");
return double.Parse(match.Groups["value"].Value, CultureInfo.InvariantCulture);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace ImperatorToCK3.UnitTests.CK3.Titles;

public class TitleRankUtilsTests {
[Theory]
[InlineData('h', TitleRank.hegemony)]
[InlineData('e', TitleRank.empire)]
[InlineData('k', TitleRank.kingdom)]
[InlineData('d', TitleRank.duchy)]
Expand Down
64 changes: 63 additions & 1 deletion ImperatorToCK3.UnitTests/Mappers/Region/CK3RegionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,51 @@
using commonItems.Colors;
using ImperatorToCK3.CK3.Titles;
using ImperatorToCK3.Mappers.Region;
using System.Linq;
using Xunit;

namespace ImperatorToCK3.UnitTests.Mappers.Region;

public class CK3RegionTests {
private static readonly ColorFactory colorFactory = new();
[Fact]
public void BlankRegionLoadsWithNoRegionsAndNoDuchies() {
public void BlankRegionLoadsWithNoRegionsNoDuchiesAndNoProvinces() {
var reader = new BufferedReader(string.Empty);
var region = CK3Region.Parse("region1", reader);

Assert.Empty(region.Regions);
Assert.Empty(region.Duchies);
Assert.Empty(region.Provinces);
}

[Fact]
public void KingdomCanBeLoaded() {
var reader = new BufferedReader("kingdoms = { k_kingdom }");
var region = CK3Region.Parse("region1", reader);
Assert.Empty(region.Duchies); // not linked yet

var titles = new Title.LandedTitles();
var titlesReader = new BufferedReader(
"""
{
k_kingdom = {
d_duchy = { c_county = { b_barony = { province = 42 } } }
d_duchy2 = { c_county2 = { b_barony2 = { province = 43 } }
}
}
""");
titles.LoadTitles(titlesReader, colorFactory);

region.LinkRegions(
regions: new(),
kingdoms: titles.Where(t => t.Rank == TitleRank.kingdom).ToDictionary(t => t.Id, t => t),
duchies: titles.Where(t => t.Rank == TitleRank.duchy).ToDictionary(t => t.Id, t => t),
counties: titles.Where(t => t.Rank == TitleRank.county).ToDictionary(t => t.Id, t => t)
);
Assert.Collection(region.Duchies,
item => Assert.Equal("d_duchy", item.Key),
item => Assert.Equal("d_duchy2", item.Key)
);
}

[Fact]
Expand Down Expand Up @@ -42,6 +74,36 @@ public void RegionCanBeLoaded() {
);
}

[Fact]
public void MultipleKingdomsCanBeLoaded() {
var reader = new BufferedReader("kingdoms = { k_rome k_greece k_egypt }");
var region = CK3Region.Parse("region1", reader);
Assert.Empty(region.Duchies); // not linked yet

var titles = new Title.LandedTitles();
var titlesReader = new BufferedReader(
"""
{
k_rome = { d_duchy_rome = { c_county_rome = { b_barony_rome = { province = 41 } } } }
k_greece = { d_duchy_greece = { c_county_greece = { b_barony_greece = { province = 42 } } } }
k_egypt = { d_duchy_egypt = { c_county_egypt = { b_barony_egypt = { province = 43 } } } }
}
""");
titles.LoadTitles(titlesReader, colorFactory);

region.LinkRegions(
regions: new(),
kingdoms: titles.Where(t => t.Rank == TitleRank.kingdom).ToDictionary(t => t.Id, t => t),
duchies: titles.Where(t => t.Rank == TitleRank.duchy).ToDictionary(t => t.Id, t => t),
counties: titles.Where(t => t.Rank == TitleRank.county).ToDictionary(t => t.Id, t => t)
);
Assert.Collection(region.Duchies,
item => Assert.Equal("d_duchy_rome", item.Key),
item => Assert.Equal("d_duchy_greece", item.Key),
item => Assert.Equal("d_duchy_egypt", item.Key)
);
}

[Fact]
public void MultipleDuchiesCanBeLoaded() {
var reader = new BufferedReader("duchies = { d_ivrea d_athens d_oppo }");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,17 @@ public void GetCK3TitleRankReturnsCorrectRank() {
tag11.RegisterProvince(new(i));
}
Assert.Equal('d', mapper.GetTitleForTag(tag11, "Test Dukedom", maxTitleRank: TitleRank.empire, ck3LocDB)![0]);

var tag12 = Country.Parse(new BufferedReader("tag=TEST_TAG12"), 12);
for (ulong i = 1; i < 800; ++i) {
// makes the country a great power, with enough territories to convert to a hegemony
tag12.RegisterProvince(new(i));
}
Assert.Equal('h', mapper.GetTitleForTag(tag12, "Test Hegemony", maxTitleRank: TitleRank.hegemony, ck3LocDB)![0]);
}

[Fact]
public void GetTitleForTagPreventsLocKeyHaskConflict() {
public void GetTitleForTagPreventsLocKeyHashConflict() {
// k_IRTOCK3_ATV_adj and building_nishapur_mines_02 have a conflicting Murmur3A hash.
var ck3LocDB = new TestCK3LocDB();
ck3LocDB.AddLocForLanguage("building_nishapur_mines_02", "english", "Nishapur Mines");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Some words specific to empires, kingdoms and duchies override the mappings based on rank.
# Some words specific to hegemonies, empires, kingdoms and duchies found in country names can override the rank-based mappings.
hegemony_keywords = { }
empire_keywords = { "empire" "imperium" }
kingdom_keywords = { "kingdom" "regnum" }
duchy_keywords = { "duchy" "principality" "dukedom" "ducatus" }

# Every Imperator country rank should be mapped to CK3 title rank.
# d - duchy, k - kingdom, e - empire
# d - duchy, k - kingdom, e - empire, h - hegemony
# Mapping to county and barony level is not supported.

# A mapping can contain optional required_territories field.
Expand All @@ -18,4 +19,5 @@ link = { ir=local_power ck3=k }
link = { ir=regional_power ck3=k }
link = { ir=major_power required_territories=300 ck3=e }
link = { ir=major_power ck3=k }
link = { ir=great_power required_territories=700 ck3=h }
link = { ir=great_power ck3=e }
47 changes: 47 additions & 0 deletions ImperatorToCK3/CK3/Characters/CharacterCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using System.Collections.Concurrent;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
Expand Down Expand Up @@ -879,4 +880,50 @@ public void RemoveInvalidDynastiesFromHistory(DynastyCollection dynasties) {
});
}
}

internal void CalculateChineseDynasticCycleVariables(Title.LandedTitles titles, Date irEndDate, Date ck3BookmarkDate) {
var celestialGovTitles = titles
.Where(t => t.ImperatorCountry is not null &&
string.Equals(t.ImperatorCountry.Government, "chinese_empire", StringComparison.Ordinal) &&
t.GetDeFactoLiege(ck3BookmarkDate) is null);
foreach (var title in celestialGovTitles) {
// Get current holder (can be Imperator character or a generated successor).
var holderId = title.GetHolderId(ck3BookmarkDate);
if (holderId.Equals("0", StringComparison.Ordinal) || !TryGetValue(holderId, out var holder)) {
continue;
}

// Calculate "years_with_government" value (estimated years the country had chinese_empire government).
double yearsWithChineseGov = 0;
Date dateOfFirstChineseGovTerm = irEndDate;
foreach (var term in Enumerable.Reverse(title.ImperatorCountry!.RulerTerms)) {
if (string.Equals(term.Government, "chinese_empire", StringComparison.Ordinal)) {
dateOfFirstChineseGovTerm = term.StartDate;
} else {
// Calculate additional years as half of the years between the
// start of the last non-Chinese gov term and the first Chinese gob term.
yearsWithChineseGov += dateOfFirstChineseGovTerm.DiffInYears(term.StartDate) / 2;
break;
}
}
yearsWithChineseGov += ck3BookmarkDate.DiffInYears(dateOfFirstChineseGovTerm);

// Calculate "imperator_unrest" based on values from the save.
double unrest;
if (title.ImperatorCountry.TotalPowerBase > 0) {
unrest = title.ImperatorCountry.NonLoyalPowerBase / title.ImperatorCountry.TotalPowerBase;
} else {
unrest = 0;
}

// Add the variables to character's history.
string effectStr = $$"""
{
set_variable = { name = years_with_government value = {{yearsWithChineseGov.ToString("0.#####", CultureInfo.InvariantCulture)}} }
set_variable = { name = imperator_unrest value = {{unrest.ToString("0.#####", CultureInfo.InvariantCulture)}} }
}
""";
holder.History.AddFieldValue(ck3BookmarkDate, "effects", "effect", new StringOfItem(effectStr));
}
}
}
4 changes: 2 additions & 2 deletions ImperatorToCK3/CK3/Provinces/ProvinceHistory.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using commonItems;
using commonItems.Collections;
using ImperatorToCK3.CK3.Cultures;
using ImperatorToCK3.CommonUtils;
using System.Collections.Generic;
Expand Down Expand Up @@ -86,12 +85,13 @@ public void SetBuildings(IEnumerable<string> buildings, Date? date) {

private static readonly HistoryFactory historyFactory = new HistoryFactory.HistoryFactoryBuilder()
.WithSimpleField("culture", "culture", null)
.WithSimpleField("faith", new OrderedSet<string> {"faith", "religion"}, null)
.WithSimpleField("faith", ["faith", "religion"], null)
.WithSimpleField("holding", "holding", "none")
.WithSimpleField("buildings", "buildings", new List<string>())
.WithSimpleField("special_building_slot", "special_building_slot", null)
.WithSimpleField("special_building", "special_building", null)
.WithSimpleField("duchy_capital_building", "duchy_capital_building", null)
.WithSimpleField("terrain", "terrain", null)
.WithLiteralField("effects", "effect")
.Build();
}
2 changes: 1 addition & 1 deletion ImperatorToCK3/CK3/Regexes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace ImperatorToCK3.CK3;
public static partial class Regexes {
public static Regex TitleId => TitleIdRegex();

[GeneratedRegex(@"^(e|k|d|c|b)_[A-Za-z0-9_\-\']+$")]
[GeneratedRegex(@"^(h|e|k|d|c|b)_[A-Za-z0-9_\-\']+$")]
private static partial Regex TitleIdRegex();
}
16 changes: 16 additions & 0 deletions ImperatorToCK3/CK3/Religions/ReligionCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,22 @@
}
}
}

// Validation: every faith should have a theism doctrine.
string? theismFallback = DoctrineCategories.TryGetValue("doctrine_theism", out var theismCategory)
? theismCategory.DoctrineIds.FirstOrDefault(d => d == "doctrine_polytheist")
: null;
foreach (var converterFaith in loadedConverterFaiths) {
var theismDoctrine = converterFaith.GetDoctrineIdsForDoctrineCategoryId("doctrine_theism");
if (theismDoctrine.Count == 0) {
if (theismFallback is not null) {
Logger.Warn($"Faith {converterFaith.Id} has no theism doctrine! Setting {theismFallback}");
converterFaith.DoctrineIds.Add(theismFallback);
} else {
Logger.Warn($"Faith {converterFaith.Id} has no theism doctrine!");
}
}
}
}

public void RemoveChristianAndIslamicSyncretismFromAllFaiths() {
Expand Down Expand Up @@ -384,106 +400,106 @@
}
}

private static string GetCultureIdForGeneratedHeadOfFaith(Faith faith,
CharacterCollection characters,
ProvinceCollection provinces,
Title.LandedTitles titles,
CultureCollection cultures,
Date date) {
var cultureId = provinces
.Where(p => p.GetFaithId(date) == faith.Id)
.Select(p => p.GetCultureId(date))
.FirstOrDefault();
if (cultureId is null) {
cultureId = characters
.Where(c => c.BirthDate <= date && (c.DeathDate is null || c.DeathDate > date))
.Where(c => c.GetFaithId(date) == faith.Id)
.Select(c => c.GetCultureId(date))
.FirstOrDefault();
}
if (cultureId is null && faith.ReligiousHeadTitleId is not null) {
if (titles.TryGetValue(faith.ReligiousHeadTitleId, out var title)) {
var capitalCounty = title.CapitalCounty;
var capitalProvince = capitalCounty?.CapitalBaronyProvinceId;
if (capitalProvince is not null) {
cultureId = provinces[capitalProvince.Value].GetCultureId(date);
}
}
}
if (cultureId is null) {
Logger.Warn($"Found no matching culture for religious head of {faith.Id}, using first one in database!");
cultureId = cultures.First().Id;
}

return cultureId;
}

Check notice on line 436 in ImperatorToCK3/CK3/Religions/ReligionCollection.cs

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/Religions/ReligionCollection.cs#L403-L436

Complex Method
private static void GenerateReligiousHeadForFaithIfMissing(
Faith faith,
Title.LandedTitles titles,
CharacterCollection characters,
ProvinceCollection provinces,
CultureCollection cultures,
Date date
) {
var religiousHeadTitleId = faith.ReligiousHeadTitleId;
if (religiousHeadTitleId is null) {
return;
}

if (!titles.TryGetValue(religiousHeadTitleId, out var title)) {
Logger.Warn($"Religious head title {religiousHeadTitleId} for {faith.Id} not found!");
return;
}
var holderId = title.GetHolderId(date);
if (holderId != "0") {
if (!characters.TryGetValue(holderId, out var holder)) {
Logger.Warn($"Religious head {holderId} of title {title.Id} for {faith.Id} not found!");
return;
}

var holderDeathDate = holder.DeathDate;
if (holderDeathDate is null || holderDeathDate > date) {
return;
}
}

// Generate title holder.
Logger.Debug($"Generating religious head for faith {faith.Id}...");

// Determine culture.
string cultureId = GetCultureIdForGeneratedHeadOfFaith(faith, characters, provinces, titles, cultures, date);
if (!cultures.TryGetValue(cultureId, out var culture)) {
Logger.Warn($"Culture {cultureId} not found!");
return;
}

// If title has male_names defined, use one of them for character's name.
// Otherwise, get name from culture.
var name = title.MaleNames?.FirstOrDefault();
if (name is null) {
var maleNames = culture.MaleNames.ToImmutableList();
if (maleNames.Count > 0) {
name = maleNames.ElementAtOrDefault(Math.Abs(date.Year) % maleNames.Count);
}
}
if (name is null) {
const string fallbackName = "Alexandros";
Logger.Warn($"Found no name for religious head of {faith.Id}, defaulting to {fallbackName}!");
name = fallbackName;
}
var age = 30 + (Math.Abs(date.Year) % 50);
var character = new Character($"IRToCK3_head_of_faith_{faith.Id}", name, date.ChangeByYears(-age), characters);
character.SetFaithId(faith.Id, date: null);
character.SetCultureId(cultureId, date: null);
var traitsToAdd = new[] {"chaste", "celibate", "devoted"};
foreach (var traitId in traitsToAdd) {
character.History.AddFieldValue(date: null, "traits", "trait", traitId);
}
characters.Add(character);
title.SetHolder(character, date);
}

Check notice on line 502 in ImperatorToCK3/CK3/Religions/ReligionCollection.cs

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/Religions/ReligionCollection.cs#L437-L502

Complex Method
private List<Title> GetDynamicHolySiteBaroniesForFaith(Faith faith, Dictionary<string, HashSet<Province>> provincesByFaith) {
// Collect all Imperator territories that are mapped to this faith.
HashSet<Province> faithTerritories;
Expand Down
Loading
Loading