diff --git a/ImperatorToCK3.UnitTests/Imperator/Characters/CharacterTests.cs b/ImperatorToCK3.UnitTests/Imperator/Characters/CharacterTests.cs index 4e16080b0..3cf5fd5cd 100644 --- a/ImperatorToCK3.UnitTests/Imperator/Characters/CharacterTests.cs +++ b/ImperatorToCK3.UnitTests/Imperator/Characters/CharacterTests.cs @@ -12,6 +12,7 @@ public void FieldsCanBeSet() { var reader = new BufferedReader( "= {" + "\tcountry=69" + + "\thome_country=68" + "\tculture=\"paradoxian\"" + "\treligion=\"orthodox\"" + "\tfemale=yes" + @@ -34,6 +35,7 @@ public void FieldsCanBeSet() { "\tdna=\"paradoxianDna\"" + "\tage=56\n" + "\tprovince=69" + + "\tprisoner_home=68" + "}" ); var character = ImperatorToCK3.Imperator.Characters.Character.Parse(reader, "42", genesDB); @@ -47,12 +49,22 @@ public void FieldsCanBeSet() { Assert.Equal((ulong)42, character.Id); Assert.Null(character.Country); // we have a country id, but no linked country yet - var countriesReader = new BufferedReader("={ 69={} }"); + var countriesReader = new BufferedReader("={ 69={} 68={} }"); var countries = new ImperatorToCK3.Imperator.Countries.Countries(countriesReader); character.LinkCountry(countries); Assert.NotNull(character.Country); Assert.Equal((ulong)69, character.Country.Id); + Assert.Null(character.HomeCountry); // we have a home country id, but no linked home country yet + character.LinkHomeCountry(countries); + Assert.NotNull(character.HomeCountry); + Assert.Equal((ulong)68, character.HomeCountry.Id); + + Assert.Null(character.PrisonerHome); // we have a prisoner home id, but no linked prisoner home yet + character.LinkPrisonerHome(countries); + Assert.NotNull(character.PrisonerHome); + Assert.Equal((ulong)68, character.PrisonerHome.Id); + Assert.Equal("paradoxian", character.Culture); Assert.Equal("orthodox", character.Religion); Assert.True(character.Female); @@ -264,5 +276,17 @@ public void IgnoredTokensAreSaved() { }; Assert.True(ImperatorToCK3.Imperator.Characters.Character.IgnoredTokens.SetEquals(expectedIgnoredTokens)); } + + [Fact] + public void CountryIsNotLinkedWithoutParsedId() { + var character = new ImperatorToCK3.Imperator.Characters.Character(1); + var countries = new ImperatorToCK3.Imperator.Countries.Countries(); + character.LinkCountry(countries); + character.LinkHomeCountry(countries); + character.LinkPrisonerHome(countries); + Assert.Null(character.Country); + Assert.Null(character.HomeCountry); + Assert.Null(character.PrisonerHome); + } } } diff --git a/ImperatorToCK3/CK3/Characters/Character.cs b/ImperatorToCK3/CK3/Characters/Character.cs index 2987717b4..ccffb90ba 100644 --- a/ImperatorToCK3/CK3/Characters/Character.cs +++ b/ImperatorToCK3/CK3/Characters/Character.cs @@ -204,7 +204,15 @@ Date ck3BookmarkDate DeathReason = deathReasonMapper.GetCK3ReasonForImperatorReason(impDeathReason); } - if (ImperatorCharacter.PrisonerHome is not null) { + // if character is imprisoned, set jailor + SetJailor(); + SetEmployer(); + + void SetJailor() { + if (ImperatorCharacter.PrisonerHome is null) { + return; + } + var prisonCountry = ImperatorCharacter.Country; if (prisonCountry is null) { Logger.Warn($"Imperator character {ImperatorCharacter.Id} is imprisoned but has no country!"); @@ -214,6 +222,16 @@ Date ck3BookmarkDate jailorId = prisonCountry.CK3Title.GetHolderId(dateOnConversion); } } + + void SetEmployer() { + var prisonerHome = ImperatorCharacter.PrisonerHome; + var homeCountry = ImperatorCharacter.HomeCountry; + if (prisonerHome?.CK3Title is not null) { // is imprisoned + EmployerId = prisonerHome.CK3Title.GetHolderId(dateOnConversion); + } else if (homeCountry?.CK3Title is not null) { + EmployerId = homeCountry.CK3Title.GetHolderId(dateOnConversion); + } + } } public void BreakAllLinks() { @@ -299,7 +317,8 @@ public Character? Father { public string? DynastyId { get; set; } // not always set - private readonly string? jailorId; + private string? jailorId; + public string? EmployerId { get; set; } public bool LinkJailor(Characters characters) { if (jailorId is null) { diff --git a/ImperatorToCK3/CK3/Characters/Characters.cs b/ImperatorToCK3/CK3/Characters/Characters.cs index 174fd3875..7a5e62e96 100644 --- a/ImperatorToCK3/CK3/Characters/Characters.cs +++ b/ImperatorToCK3/CK3/Characters/Characters.cs @@ -132,9 +132,9 @@ private void LinkPrisoners() { } public void PurgeLandlessVanillaCharacters(LandedTitles titles, Date ck3BookmarkDate) { - var landedCharacterIdSelect = titles.Values.Select(t => t.GetHolderId(ck3BookmarkDate)); + var landedCharacterIds = titles.GetHolderIds(ck3BookmarkDate); var farewellIds = Keys.Where( - id => !id.StartsWith("imperator") && !landedCharacterIdSelect.Contains(id) + id => !id.StartsWith("imperator") && !landedCharacterIds.Contains(id) ); foreach (var characterId in farewellIds) { @@ -143,5 +143,12 @@ public void PurgeLandlessVanillaCharacters(LandedTitles titles, Date ck3Bookmark } Logger.Info($"Purged {farewellIds.Count()} landless vanilla characters."); } + + public void RemoveEmployerIdFromLandedCharacters(LandedTitles titles, Date conversionDate) { + var landedCharacterIds = titles.GetHolderIds(conversionDate); + foreach (var character in Values.Where(character => landedCharacterIds.Contains(character.Id))) { + character.EmployerId = null; + } + } } } diff --git a/ImperatorToCK3/CK3/Titles/LandedTitles.cs b/ImperatorToCK3/CK3/Titles/LandedTitles.cs index d0480f2df..82223baa6 100644 --- a/ImperatorToCK3/CK3/Titles/LandedTitles.cs +++ b/ImperatorToCK3/CK3/Titles/LandedTitles.cs @@ -69,6 +69,10 @@ public void EraseTitle(string name) { return null; } + public HashSet GetHolderIds(Date date) { + return new HashSet(Values.Select(t => t.GetHolderId(date))); + } + private void RegisterKeys(Parser parser) { parser.RegisterRegex(@"(e|k|d|c|b)_[A-Za-z0-9_\-\']+", (reader, titleNameStr) => { // Pull the titles beneath this one and add them to the lot, overwriting existing ones. diff --git a/ImperatorToCK3/CK3/World.cs b/ImperatorToCK3/CK3/World.cs index 68d17a56d..b56820aa6 100644 --- a/ImperatorToCK3/CK3/World.cs +++ b/ImperatorToCK3/CK3/World.cs @@ -1,4 +1,5 @@ using commonItems; +using ImperatorToCK3.CK3.Characters; using ImperatorToCK3.CK3.Dynasties; using ImperatorToCK3.CK3.Provinces; using ImperatorToCK3.CK3.Titles; @@ -88,6 +89,7 @@ public World(Imperator.World impWorld, Configuration theConfiguration) { RemoveInvalidLandlessTitles(theConfiguration.Ck3BookmarkDate); Characters.PurgeLandlessVanillaCharacters(LandedTitles, theConfiguration.Ck3BookmarkDate); + Characters.RemoveEmployerIdFromLandedCharacters(LandedTitles, impWorld.EndDate); } private void ClearFeaturedCharactersDescriptions(Date ck3BookmarkDate) { diff --git a/ImperatorToCK3/Imperator/Characters/Character.cs b/ImperatorToCK3/Imperator/Characters/Character.cs index 45c26f004..496ced33c 100644 --- a/ImperatorToCK3/Imperator/Characters/Character.cs +++ b/ImperatorToCK3/Imperator/Characters/Character.cs @@ -13,6 +13,8 @@ public Character(ulong id) { private ulong? parsedCountryId; public Country? Country { get; set; } + private ulong? parsedHomeCountryId; + public Country? HomeCountry { get; set; } private ulong? parsedPrisonerHomeId; public Country? PrisonerHome { get; private set; } @@ -108,6 +110,7 @@ static Character() { parsedCharacter.CustomName = characterName.CustomName; }); parser.RegisterKeyword("country", reader => parsedCharacter.parsedCountryId = ParserHelpers.GetULong(reader)); + parser.RegisterKeyword("home_country", reader => parsedCharacter.parsedHomeCountryId = ParserHelpers.GetULong(reader)); parser.RegisterKeyword("province", reader => parsedCharacter.ProvinceId = ParserHelpers.GetULong(reader)); parser.RegisterKeyword("culture", reader => parsedCharacter.culture = ParserHelpers.GetString(reader)); parser.RegisterKeyword("religion", reader => parsedCharacter.Religion = ParserHelpers.GetString(reader)); @@ -182,6 +185,20 @@ public bool LinkCountry(Countries.Countries countries) { return false; } + // Returns whether a country was linked + public bool LinkHomeCountry(Countries.Countries countries) { + if (parsedHomeCountryId is null) { + return false; + } + var homeCountryId = (ulong)parsedHomeCountryId; + if (countries.TryGetValue(homeCountryId, out var countryToLink)) { + HomeCountry = countryToLink; + return true; + } + Logger.Warn($"Country with ID {homeCountryId} has no definition!"); + return false; + } + // Returns whether a country was linked public bool LinkPrisonerHome(Countries.Countries countries) { if (parsedPrisonerHomeId is null) { diff --git a/ImperatorToCK3/Imperator/Characters/Characters.cs b/ImperatorToCK3/Imperator/Characters/Characters.cs index f2caae1e0..0370eb6cc 100644 --- a/ImperatorToCK3/Imperator/Characters/Characters.cs +++ b/ImperatorToCK3/Imperator/Characters/Characters.cs @@ -54,6 +54,9 @@ public void LinkCountries(Countries.Countries countries) { var counter = Values.Count(character => character.LinkCountry(countries)); Logger.Info($"{counter} countries linked to characters."); + counter = Values.Count(character => character.LinkHomeCountry(countries)); + Logger.Info($"{counter} home countries linked to characters."); + counter = Values.Count(character => character.LinkPrisonerHome(countries)); Logger.Info($"{counter} prisoner homes linked to characters."); } diff --git a/ImperatorToCK3/Outputter/CharacterOutputter.cs b/ImperatorToCK3/Outputter/CharacterOutputter.cs index 53285e8ed..224af0767 100644 --- a/ImperatorToCK3/Outputter/CharacterOutputter.cs +++ b/ImperatorToCK3/Outputter/CharacterOutputter.cs @@ -62,6 +62,7 @@ public static void OutputCharacter(StreamWriter output, Character character, Dat OutputBirthAndDeathDates(output, character); OutputPrisoners(output, character, conversionDate); + OutputEmployer(output, character, conversionDate); output.WriteLine("}"); } @@ -92,5 +93,12 @@ private static void OutputPrisoners(TextWriter output, Character character, Date } output.WriteLine("\t}"); } + private static void OutputEmployer(TextWriter output, Character character, Date conversionDate) { + if (character.EmployerId is null) { + return; + } + + output.WriteLine($"\t{conversionDate}={{employer={character.EmployerId}}}"); + } } }