Skip to content
Merged
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
32 changes: 32 additions & 0 deletions ImperatorToCK3/CK3/Religions/ReligionCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,47 +38,79 @@
parser.ParseGameFolder("common/religion/religions", ck3ModFS, "txt", recursive: true);
}

public void LoadConverterFaiths(string converterFaithsPath, ColorFactory colorFactory) {
OrderedSet<Faith> loadedConverterFaiths = [];

var parser = new Parser();
parser.RegisterRegex(CommonRegexes.String, (religionReader, religionId) => {
var optReligion = new Religion(religionId, religionReader, this, colorFactory);

// For validation, store all faiths loaded inside the converter religion.
loadedConverterFaiths.UnionWith(optReligion.Faiths);

// Check if religion already exists. If it does, add converter faiths to it.
// Otherwise, add the converter faith's religion.
if (TryGetValue(religionId, out var religion)) {
foreach (var faith in optReligion.Faiths) {
faith.Religion = religion;
religion.Faiths.Add(faith);
}
} else {
Add(optReligion);
}
});
parser.RegisterRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreAndLogItem);
parser.ParseFile(converterFaithsPath);

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

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

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

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

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/Religions/ReligionCollection.cs#L41-L113

Complex Method
public void RemoveChristianAndIslamicSyncretismFromAllFaiths() {
Logger.Info("Removing Christian and Islamic syncretism tenets from all faiths...");
string[] tenetsToRemove = ["tenet_christian_syncretism", "tenet_islamic_syncretism"];
Expand Down Expand Up @@ -226,73 +258,73 @@
return new HolySite(barony, ck3Faith, landedTitles, imperatorModifiers, holySiteEffectMapper);
}

public void DetermineHolySites(
ProvinceCollection ck3Provinces,
Imperator.Religions.ReligionCollection imperatorReligions,
HolySiteEffectMapper holySiteEffectMapper,
Date date
) {
var provincesByFaith = GetProvincesFromImperatorByFaith(ck3Provinces, date);

foreach (var faith in Faiths) {
if (!ReplaceableHolySitesByFaith.TryGetValue(faith.Id, out var replaceableSiteIds)) {
continue;
}
Logger.Info($"Determining holy sites for faith {faith.Id}...");

var dynamicHolySiteBaronies = GetDynamicHolySiteBaroniesForFaith(faith, provincesByFaith);
foreach (var holySiteId in faith.HolySiteIds.ToArray()) {
if (!HolySites.TryGetValue(holySiteId, out var holySite)) {
Logger.Warn($"Holy site with ID {holySiteId} not found!");
continue;
}

var holySiteBarony = GetHolySiteBarony(holySite);
if (holySiteBarony is not null && dynamicHolySiteBaronies.Contains(holySiteBarony)) {
// One of dynamic holy site baronies is same as an exising holy site's barony.
// We need to avoid faith having two holy sites in one barony.

if (replaceableSiteIds.Contains(holySiteId)) {
var newHolySiteInSameBarony = GenerateHolySiteForBarony(
holySiteBarony,
faith,
ck3Provinces,
imperatorReligions,
holySiteEffectMapper
);
if (HolySites.ContainsKey(newHolySiteInSameBarony.Id)) {
Logger.Warn($"Created duplicate holy site: {newHolySiteInSameBarony.Id}!");
}
HolySites.AddOrReplace(newHolySiteInSameBarony);

faith.ReplaceHolySiteId(holySiteId, newHolySiteInSameBarony.Id);
}
dynamicHolySiteBaronies.Remove(holySiteBarony);
} else if (!replaceableSiteIds.Contains(holySiteId)) {
continue;
} else if (dynamicHolySiteBaronies.Count != 0) {
var selectedDynamicBarony = dynamicHolySiteBaronies[0];
dynamicHolySiteBaronies.Remove(selectedDynamicBarony);

var replacementSite = GenerateHolySiteForBarony(
selectedDynamicBarony,
faith,
ck3Provinces,
imperatorReligions,
holySiteEffectMapper
);
if (HolySites.ContainsKey(replacementSite.Id)) {
Logger.Warn($"Created duplicate holy site: {replacementSite.Id}!");
}
HolySites.AddOrReplace(replacementSite);

faith.ReplaceHolySiteId(holySiteId, replacementSite.Id);
}
}
}
}

// Returns a dictionary with CK3 provinces that are mapped to Imperator provinces, grouped by faith.

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

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/Religions/ReligionCollection.cs#L261-L327

Complex Method
public static IDictionary<string, ISet<Province>> GetProvincesFromImperatorByFaith(ProvinceCollection ck3Provinces, Date date) {
var provincesByFaith = new Dictionary<string, ISet<Province>>();

Expand Down Expand Up @@ -352,106 +384,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 420 in ImperatorToCK3/CK3/Religions/ReligionCollection.cs

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/Religions/ReligionCollection.cs#L387-L420

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 486 in ImperatorToCK3/CK3/Religions/ReligionCollection.cs

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/Religions/ReligionCollection.cs#L421-L486

Complex Method
private List<Title> GetDynamicHolySiteBaroniesForFaith(Faith faith, IDictionary<string, ISet<Province>> provincesByFaith) {
// Collect all Imperator territories that are mapped to this faith.
ISet<Province> faithTerritories;
Expand Down
1 change: 1 addition & 0 deletions ImperatorToCK3/CK3/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,358 +71,358 @@
public Date CorrectedDate { get; private set; } = new Date(2, 1, 1); // overwritten by DetermineCK3BookmarkDate

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

warMapper.DetectUnmappedWarGoals(impWorld.ModFS);

DetermineCK3Dlcs(config);
LoadAndDetectCK3Mods(config);

// 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, config.GetCK3ModFlags());

// 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();
}
);

System.Collections.Generic.OrderedDictionary<string, bool> ck3ModFlags = config.GetCK3ModFlags();

Parallel.Invoke(
() => { // 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);
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);

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

Title.LandedTitles overrideTitles = [];
overrideTitles.LoadStaticTitles();
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.txt", ck3ColorFactory);
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),

() => {
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, ck3ModFlags),

() => { // 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);

// Load existing CK3 government IDs.
Logger.Info("Loading CK3 government IDs...");
var ck3GovernmentIds = new HashSet<string>();
var governmentsParser = new Parser();
governmentsParser.RegisterRegex(CommonRegexes.String, (reader, governmentId) => {
ck3GovernmentIds.Add(governmentId);
ParserHelpers.IgnoreItem(reader);
});
governmentsParser.ParseGameFolder("common/governments", ModFS, "txt", recursive: false, logFilePaths: true);
Logger.IncrementProgress();
GovernmentMapper governmentMapper = new(ck3GovernmentIds);
Logger.IncrementProgress();

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

SuccessionLawMapper successionLawMapper = new("configurables/succession_law_map.liquid", ck3ModFlags);
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, 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);
// Import holding owners as barons and counts (optional).
if (!config.SkipHoldingOwnersImport) {
LandedTitles.ImportImperatorHoldings(Provinces, impWorld.Characters, impWorld.EndDate);
} else {
Logger.Info("Skipping holding owners import per configuration.");
}

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

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

// Check if any muslim religion exists in Imperator. Otherwise, remove Islam from the entire CK3 map.
var possibleMuslimReligionNames = new List<string> { "muslim", "islam", "sunni", "shiite" };
var muslimReligionExists = impWorld.Religions
.Any(r => possibleMuslimReligionNames.Contains(r.Id.ToLowerInvariant()));
if (muslimReligionExists) {
Logger.Info("Found muslim religion in Imperator save, keeping Islam in CK3.");
} else {
RemoveIslam(config);
}
Logger.IncrementProgress();

// Now that Islam has been handled, we can generate filler holders without the risk of making them Muslim.
GenerateFillerHoldersForUnownedLands(Cultures, config);
Logger.IncrementProgress();
if (!config.StaticDeJure) {
LandedTitles.SetDeJureKingdomsAndEmpires(config.CK3BookmarkDate, Cultures, Characters, MapData, 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 I:R 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, CorrectedDate, unitTypeMapper, MenAtArmsTypes, provinceMapper, LocDB, config);

// 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);
}
);
}

private void DetermineCK3BookmarkDate(Imperator.World irWorld, Configuration config) {
CorrectedDate = irWorld.EndDate.Year > 1 ? irWorld.EndDate : new Date(2, 1, 1);
if (config.CK3BookmarkDate.Year == 0) { // bookmark date is not set
config.CK3BookmarkDate = CorrectedDate;
Logger.Info($"CK3 bookmark date set to: {config.CK3BookmarkDate}");
} else if (CorrectedDate > config.CK3BookmarkDate) {
Logger.Warn($"Corrected save can't be later than CK3 bookmark date, setting CK3 bookmark date to {CorrectedDate}!");
config.CK3BookmarkDate = CorrectedDate;
}

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

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/World.cs#L74-L425

Complex Method
}

private void LoadAndDetectCK3Mods(Configuration config) {
Expand Down Expand Up @@ -709,113 +709,113 @@
RevokeBaroniesFromCountyGivenToImperatorCharacter(county);
return true;
}

private static void RevokeBaroniesFromCountyGivenToImperatorCharacter(Title county) {
foreach (var barony in county.DeJureVassals) {
// Skip the county capital barony.
if (barony.ProvinceId == county.CapitalBaronyProvinceId) {
continue;
}

// Clear the barony holders history.
barony.ClearHolderSpecificHistory();
}
}

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 (irWorld.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:
UsePaganRulers();
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.
UsePaganRulers();
} 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);
}

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

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/World.cs#L712-L818

Complex Method
}

Logger.IncrementProgress();
Expand Down Expand Up @@ -969,161 +969,161 @@

var neighborFaithId = Provinces
.Except(muslimProvinces)
.Where(p => neighborIds.Contains(p.Id))
.Select(p => p.GetFaithId(date))
.FirstOrDefault(f => f is not null);
if (neighborFaithId is null) {
continue;
}

Logger.Debug($"Using neighbor's faith \"{neighborFaithId}\" for province {province.Id}.");
province.SetFaithIdAndOverrideExistingEntries(neighborFaithId);
muslimProvinces.Remove(province);
}
}

private void GenerateFillerHoldersForUnownedLands(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) {
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;

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

View check run for this annotation

codefactor.io / CodeFactor

ImperatorToCK3/CK3/World.cs#L972-L1126

Very Complex Method
if (duchy is null || duchy.Rank != TitleRank.duchy) {
continue;
}
Expand Down Expand Up @@ -1165,6 +1165,7 @@
{"dlc018.dlc", "arctic_attire"},
{"dlc019.dlc", "crowns_of_the_world"},
{"dlc020.dlc", "khans_of_the_steppe"},
{"dlc021.dlc", "coronations"},
};

var dlcFiles = Directory.GetFiles(dlcFolderPath, "*.dlc", SearchOption.AllDirectories);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,49 @@ name_list_phrygian = {
{ name = "ir_band_of_anatolia" coat_of_arms = "antiochus_seleucid" }
}
}
name_list_anatolian = {
cadet_dynasty_names = {
dynn_Aramid dynn_Arid dynn_Arkhid dynn_Asinid dynn_Arsacid dynn_Deiocid dynn_Menid dynn_Pacorid
dynn_Savacid dynn_Vardanid dynn_Surenid dynn_Karinid dynn_Gaumatid dynn_Gobryasid
dynn_Hydarnid dynn_Smerdid dynn_Vivanid dynn_Xerxid dynn_Abadanid dynn_Orontid dynn_Atropatid
dynn_Mithridatid dynn_Artiaxid dynn_Mihranid dynn_Chosroid dynn_Artashid dynn_Bagabignid dynn_Cambysid
dynn_Frataraka
}

dynasty_names = {
dynn_Aramid dynn_Arid dynn_Arkhid dynn_Asinid dynn_Arsacid dynn_Deiocid dynn_Menid dynn_Pacorid
dynn_Savacid dynn_Vardanid dynn_Surenid dynn_Karinid dynn_Gaumatid dynn_Gobryasid
dynn_Hydarnid dynn_Smerdid dynn_Vivanid dynn_Xerxid dynn_Abadanid dynn_Orontid dynn_Atropatid
dynn_Mithridatid dynn_Artiaxid dynn_Mihranid dynn_Chosroid dynn_Artashid dynn_Bagabignid dynn_Cambysid
dynn_Frataraka
}

male_names = {
Morzios Pylaemenes Mithridates Datames Ariobarzanes Ariamnes Ariarathes Croesus Gyges Ardys Sadyattes Atys Adrastus Gordias Midas
Hecatomnus Hyssaldomus Mausolus Idrieus Pixodarus Lygdamis Kybernis Kuprilli
Arppakhu Arbinas Kheriga Kherei Abistamenes Syennesis Appuasu Oromedon
Zipoetes Bas Ziaelas Prusias Arcathias Xiphares Dareios Gaizatorix Odius Gergis
}

female_names = {
Nysa Aryenis Ada Glaphyra Pythodorida Etazeta Drypetina Orsabaris Hypsicratea Boa Amasia
}

# Patronymics (Apparently comes from Hittite/Luwian words for "descendant". Best I could find without being really repetitive)
patronym_prefix_male = prefix_hams
patronym_prefix_female = prefix_hams

# Chance of male children being named after their paternal or maternal grandfather, or their father. Sum must not exceed 100.
pat_grf_name_chance = 50
mat_grf_name_chance = 5
father_name_chance = 20

# Chance of female children being named after their paternal or maternal grandmother, or their mother. Sum must not exceed 100.
pat_grm_name_chance = 10
mat_grm_name_chance = 50
mother_name_chance = 5

mercenary_names = {
{ name = "ir_band_of_anatolia" coat_of_arms = "antiochus_seleucid" }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ on_game_start = {

cretan_to_neo_minoan_on_game_start = {
effect = {
# Give Neo-Minoan the culture innovations from Cretan
culture:neo_minoan = { get_all_innovations_from = culture:cretan }

# Make Neo-Minoan culture only appear in provinces where the holder is of Cretan culture and is of kingdom or empire tier.
every_ruler = {
limit = {
Expand All @@ -23,23 +26,34 @@ cretan_to_neo_minoan_on_game_start = {
# Convert the character and his entire realm from Cretan to Neo-Minoan.
set_culture = culture:neo_minoan
every_realm_county = {
limit = {
culture = culture:cretan
}
limit = { culture = culture:cretan }
set_county_culture = culture:neo_minoan
}

every_vassal_or_below = {
limit = {
culture = culture:cretan
}
limit = { culture = culture:cretan }
set_culture = culture:neo_minoan

every_close_or_extended_family_member = {
limit = { culture = culture:cretan }
set_culture = culture:neo_minoan
}

every_courtier = {
limit = { culture = culture:cretan }
set_culture = culture:neo_minoan
}
}

every_close_or_extended_family_member = {
limit = {
culture = culture:cretan
limit = { culture = culture:cretan }
set_culture = culture:neo_minoan
}

every_courtier = {
limit = { culture = culture:cretan }
set_culture = culture:neo_minoan
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
language_luwian_name: "$luwian$"
language_lydian_name: "$lydian$"
language_hittite_name: "$hittite$"
language_anatolian_name: "$anatolian$"
language_phrygian_name: "$phrygian$"
language_albanian_name: "$albanian$"
language_kemetic_name: "kémétique"
Expand All @@ -25,3 +26,4 @@
language_dacian_name: "$dacian$"
language_etruscan_name: "$etruscan$"
language_gothic_name: "$gothic$"
language_illyrian_name: "$dalmatian$"
Original file line number Diff line number Diff line change
Expand Up @@ -2532,6 +2532,8 @@
Drypetina: "Drypétina"
Orsabaris: "Orsabaris"
Hypsicratea: "Hypsicratéa"
Boa: "Boa"
Amasia: "Amasia"
#Cappadocian dynasties
dynn_Surenid: "Surénide"
dynn_Karinid: "Carinide"
Expand Down Expand Up @@ -4784,6 +4786,7 @@
prefix_yiliydoa: "yiliydoa "
prefix_dbartoa: "dbartoa "
prefix_dmen: "dmen "
prefix_hams: "hams "
Bardo: "Bardo"
Bardol: "Bardol"
Barnahy: "Barnahy"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
language_luwian_name: "$luwian$"
language_lydian_name: "$lydian$"
language_hittite_name: "$hittite$"
language_anatolian_name: "$anatolian$"
language_phrygian_name: "$phrygian$"
language_albanian_name: "$albanian$"
language_kemetic_name: "Kemetisch"
Expand All @@ -25,3 +26,4 @@
language_dacian_name: "$dacian$"
language_etruscan_name: "$etruscan$"
language_gothic_name: "$gothic$"
language_illyrian_name: "$dalmatian$"
Original file line number Diff line number Diff line change
Expand Up @@ -2532,6 +2532,8 @@
Drypetina: "Drypetina"
Orsabaris: "Orsabaris"
Hypsicratea: "Hypsicratea"
Boa: "Boa"
Amasia: "Amasia"
#Cappadocian dynasties
dynn_Surenid: "Surenid"
dynn_Karinid: "Carinid"
Expand Down Expand Up @@ -4784,6 +4786,7 @@
prefix_yiliydoa: "yiliydoa "
prefix_dbartoa: "dbartoa "
prefix_dmen: "dmen "
prefix_hams: "hams "
Bardo: "Bardo"
Bardol: "Bardol"
Barnahy: "Barnahy"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
language_luwian_name: "$luwian$"
language_lydian_name: "$lydian$"
language_hittite_name: "$hittite$"
language_anatolian_name: "$anatolian$"
language_phrygian_name: "$phrygian$"
language_albanian_name: "$albanian$"
language_kemetic_name: "Kemetic"
Expand All @@ -25,3 +26,4 @@
language_dacian_name: "$dacian$"
language_etruscan_name: "$etruscan$"
language_gothic_name: "$gothic$"
language_illyrian_name: "$dalmatian$"
Original file line number Diff line number Diff line change
Expand Up @@ -2532,6 +2532,8 @@
Drypetina: "ㄷ리페티나"
Orsabaris: "오ㄹ사바릿"
Hypsicratea: "잎싴라테아"
Boa: "보아"
Amasia: "아마지아"
#Cappadocian dynasties
dynn_Surenid: "수레닏"
dynn_Karinid: "카리닏"
Expand Down Expand Up @@ -4781,6 +4783,7 @@
prefix_yiliydoa: "이리도아·"
prefix_dbartoa: "드발도아·"
prefix_dmen: "드멘·"
prefix_hams: "함스·"
Bardo: "발도"
Bardol: "발돌"
Barnahy: "발나히"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,8 @@

roman_restoration.0125.a_set: "Our Mother Church is whole!"
roman_restoration.0125.a_restore: "Our Mother Church is whole once more!"

# "Albanian" heritage now used for more than just Albanians
heritage_albanian: "Illyrian"
heritage_albanian_name: "Illyrian"
heritage_albanian_collective_noun: "Illyrians"
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
language_luwian_name: "$luwian$"
language_lydian_name: "$lydian$"
language_hittite_name: "$hittite$"
language_anatolian_name: "$anatolian$"
language_phrygian_name: "$phrygian$"
language_albanian_name: "$albanian$"
language_kemetic_name: "Кеметск"
Expand All @@ -25,4 +26,5 @@
language_dacian_name: "$dacian$"
language_etruscan_name: "$etruscan$"
language_gothic_name: "$gothic$"
language_chong_name: "Chong"
language_chong_name: "Chong"
language_illyrian_name: "$dalmatian$"
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
language_luwian_name: "$luwian$"
language_lydian_name: "$lydian$"
language_hittite_name: "$hittite$"
language_anatolian_name: "$anatolian$"
language_phrygian_name: "$phrygian$"
language_albanian_name: "$albanian$"
language_kemetic_name: "Kemetic"
Expand All @@ -25,3 +26,4 @@
language_dacian_name: "$dacian$"
language_etruscan_name: "$etruscan$"
language_gothic_name: "$gothic$"
language_illyrian_name: "$dalmatian$"
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
language_luwian_name: "$luwian$"
language_lydian_name: "$lydian$"
language_hittite_name: "$hittite$"
language_anatolian_name: "$anatolian$"
language_phrygian_name: "$phrygian$"
language_albanian_name: "$albanian$"
language_kemetic_name: "quemética"
Expand All @@ -25,3 +26,4 @@
language_dacian_name: "$dacian$"
language_etruscan_name: "$etruscan$"
language_gothic_name: "$gothic$"
language_illyrian_name: "$dalmatian$"
55 changes: 54 additions & 1 deletion ImperatorToCK3/Data_Files/configurables/converter_cultures.txt
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ dalmatian = {
color = rgb { 246 223 15 }

heritage = heritage_albanian
language = language_albanian
language = language_illyrian
martial_custom = martial_custom_equal
head_determination = head_determination_domain
traditions = {
Expand Down Expand Up @@ -3896,3 +3896,56 @@ basque = {
10 = mediterranean
}
}

# Broader Anatolian culture to replace old anachronistic Hittite culture
anatolian = {
INVALIDATED_BY = {
tfe = { anatolian }
wtwsms = { anatolian }
roa = { anatolian }
vanilla = { anatolian }
}

color = rgb { 85 148 124 }

heritage = heritage_anatolian
language = language_anatolian
martial_custom = martial_custom_male_only
ethos = ethos_bellicose # Were known warriors/mercenaries
head_determination = head_determination_domain
traditions = {
tradition_hill_dwellers # Many lived in Hill Forts
tradition_highland_warriors # Lived in hills, known to be mercenaries/warriors
tradition_swords_for_hire # Known to be mercenaries
}
dlc_tradition = {
trait = tradition_culture_blending # Had to adapt to changing overlords/neighboring influential powers
requires_dlc_flag = hybridize_culture
}

name_list = name_list_anatolian

ethnicities = {
10 = mediterranean_byzantine
}

MOD_DEPENDENT = {
IF tfe = {
# Fixes "Gfx culture byzantine_group_coa_gfx in armenian doesn't match existing sequence in luwian"
coa_gfx = { byzantine_group_coa_gfx western_coa_gfx }
}
ELSE = {
coa_gfx = {
byzantine_group_coa_gfx
# israelite_group_coa_gfx
# western_coa_gfx
}
}
}
building_gfx = { mena_building_gfx }
clothing_gfx = {
byzantine_clothing_gfx
# dde_abbasid_clothing_gfx
}
unit_gfx = { eastern_unit_gfx }
}
Loading
Loading