From d054d010b24915889aeb447c5a3a6e0be5253a23 Mon Sep 17 00:00:00 2001 From: iht <IhateTrains@users.noreply.github.com> Date: Tue, 1 Oct 2024 19:04:46 +0200 Subject: [PATCH] Convert many cpp files to WIP csharp files --- .../Characters/Character.cpp | 0 .../{CK3World => CK3}/Characters/Character.h | 0 .../Characters/CharacterDomain.cpp | 0 .../Characters/CharacterDomain.h | 0 .../Characters/Characters.cpp | 6 +- .../{CK3World => CK3}/Characters/Characters.h | 0 .../Source/CK3/CoatsOfArms/CoatsOfArms.cs | 59 ++ .../Source/CK3/CoatsOfArms/EmblemInstance.cs | 16 +- CK3ToEU4/Source/CK3/Cultures/Culture.cs | 160 ++++++ CK3ToEU4/Source/CK3/Cultures/Cultures.cs | 43 ++ .../{CK3World => CK3}/Dynasties/Dynasties.cpp | 2 +- .../{CK3World => CK3}/Dynasties/Dynasties.h | 0 .../{CK3World => CK3}/Dynasties/Dynasty.cpp | 0 .../{CK3World => CK3}/Dynasties/Dynasty.h | 0 .../{CK3World => CK3}/Dynasties/House.cpp | 0 .../{CK3World => CK3}/Dynasties/House.h | 0 .../Dynasties/HouseNameScraper.cpp | 0 .../Dynasties/HouseNameScraper.h | 0 .../Dynasties/HouseNameScraping.cpp | 0 .../Dynasties/HouseNameScraping.h | 0 .../{CK3World => CK3}/Dynasties/Houses.cpp | 0 .../{CK3World => CK3}/Dynasties/Houses.h | 0 CK3ToEU4/Source/CK3/Flags/Flags.cs | 58 ++ CK3ToEU4/Source/CK3/Geography/CountyDetail.cs | 46 ++ .../Geography/CountyDetails.cpp | 6 +- .../Geography/CountyDetails.h | 0 .../Geography/ProvinceHolding.cpp | 0 .../Geography/ProvinceHolding.h | 0 .../Geography/ProvinceHoldings.cpp | 0 .../Geography/ProvinceHoldings.h | 0 CK3ToEU4/Source/CK3/Religions/Faith.cs | 88 +++ CK3ToEU4/Source/CK3/Religions/Faiths.cs | 66 +++ CK3ToEU4/Source/CK3/Religions/Religion.cs | 50 ++ CK3ToEU4/Source/CK3/Religions/Religions.cs | 70 +++ CK3ToEU4/Source/CK3/Titles/DynamicTemplate.cs | 28 + CK3ToEU4/Source/CK3/Titles/LandedTitles.cs | 148 +++++ CK3ToEU4/Source/CK3/Titles/Title.cs | 24 +- .../Titles.cpp => CK3/Titles/Titles.cs} | 274 +++++---- CK3ToEU4/Source/CK3/World.cs | 27 +- .../CK3World/CoatsOfArms/CoatOfArms.cpp | 70 --- .../Source/CK3World/CoatsOfArms/CoatOfArms.h | 45 -- .../CK3World/CoatsOfArms/CoatsOfArms.cpp | 53 -- .../Source/CK3World/CoatsOfArms/CoatsOfArms.h | 25 - .../Source/CK3World/CoatsOfArms/Emblem.cpp | 61 --- CK3ToEU4/Source/CK3World/CoatsOfArms/Emblem.h | 35 -- .../CK3World/CoatsOfArms/EmblemInstance.cpp | 31 -- .../CK3World/CoatsOfArms/EmblemInstance.h | 32 -- CK3ToEU4/Source/CK3World/Cultures/Culture.cpp | 127 ----- CK3ToEU4/Source/CK3World/Cultures/Culture.h | 54 -- .../Source/CK3World/Cultures/Cultures.cpp | 34 -- CK3ToEU4/Source/CK3World/Cultures/Cultures.h | 27 - CK3ToEU4/Source/CK3World/Flags/Flags.cpp | 51 -- CK3ToEU4/Source/CK3World/Flags/Flags.h | 26 - .../CK3World/Geography/CountyDetail.cpp | 29 - .../Source/CK3World/Geography/CountyDetail.h | 34 -- CK3ToEU4/Source/CK3World/Religions/Faith.cpp | 50 -- CK3ToEU4/Source/CK3World/Religions/Faith.h | 53 -- CK3ToEU4/Source/CK3World/Religions/Faiths.cpp | 49 -- CK3ToEU4/Source/CK3World/Religions/Faiths.h | 29 - .../Source/CK3World/Religions/Religion.cpp | 26 - CK3ToEU4/Source/CK3World/Religions/Religion.h | 31 -- .../Source/CK3World/Religions/Religions.cpp | 54 -- .../Source/CK3World/Religions/Religions.h | 28 - .../CK3World/Titles/DynamicTemplate.cpp | 21 - .../Source/CK3World/Titles/DynamicTemplate.h | 23 - .../Source/CK3World/Titles/LandedTitles.cpp | 136 ----- .../Source/CK3World/Titles/LandedTitles.h | 60 -- CK3ToEU4/Source/CK3World/Titles/Title.cpp | 518 ------------------ CK3ToEU4/Source/CK3World/Titles/Title.h | 184 ------- CK3ToEU4/Source/CK3World/Titles/Titles.h | 36 -- .../Source/Configuration/Configuration.cpp | 218 -------- CK3ToEU4/Source/Configuration/Configuration.h | 145 ----- 72 files changed, 993 insertions(+), 2573 deletions(-) rename CK3ToEU4/Source/{CK3World => CK3}/Characters/Character.cpp (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Characters/Character.h (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Characters/CharacterDomain.cpp (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Characters/CharacterDomain.h (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Characters/Characters.cpp (98%) rename CK3ToEU4/Source/{CK3World => CK3}/Characters/Characters.h (100%) create mode 100644 CK3ToEU4/Source/CK3/CoatsOfArms/CoatsOfArms.cs create mode 100644 CK3ToEU4/Source/CK3/Cultures/Culture.cs create mode 100644 CK3ToEU4/Source/CK3/Cultures/Cultures.cs rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/Dynasties.cpp (97%) rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/Dynasties.h (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/Dynasty.cpp (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/Dynasty.h (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/House.cpp (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/House.h (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/HouseNameScraper.cpp (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/HouseNameScraper.h (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/HouseNameScraping.cpp (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/HouseNameScraping.h (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/Houses.cpp (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Dynasties/Houses.h (100%) create mode 100644 CK3ToEU4/Source/CK3/Flags/Flags.cs create mode 100644 CK3ToEU4/Source/CK3/Geography/CountyDetail.cs rename CK3ToEU4/Source/{CK3World => CK3}/Geography/CountyDetails.cpp (95%) rename CK3ToEU4/Source/{CK3World => CK3}/Geography/CountyDetails.h (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Geography/ProvinceHolding.cpp (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Geography/ProvinceHolding.h (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Geography/ProvinceHoldings.cpp (100%) rename CK3ToEU4/Source/{CK3World => CK3}/Geography/ProvinceHoldings.h (100%) create mode 100644 CK3ToEU4/Source/CK3/Religions/Faith.cs create mode 100644 CK3ToEU4/Source/CK3/Religions/Faiths.cs create mode 100644 CK3ToEU4/Source/CK3/Religions/Religion.cs create mode 100644 CK3ToEU4/Source/CK3/Religions/Religions.cs create mode 100644 CK3ToEU4/Source/CK3/Titles/DynamicTemplate.cs create mode 100644 CK3ToEU4/Source/CK3/Titles/LandedTitles.cs rename CK3ToEU4/Source/{CK3World/Titles/Titles.cpp => CK3/Titles/Titles.cs} (78%) delete mode 100644 CK3ToEU4/Source/CK3World/CoatsOfArms/CoatOfArms.cpp delete mode 100644 CK3ToEU4/Source/CK3World/CoatsOfArms/CoatOfArms.h delete mode 100644 CK3ToEU4/Source/CK3World/CoatsOfArms/CoatsOfArms.cpp delete mode 100644 CK3ToEU4/Source/CK3World/CoatsOfArms/CoatsOfArms.h delete mode 100644 CK3ToEU4/Source/CK3World/CoatsOfArms/Emblem.cpp delete mode 100644 CK3ToEU4/Source/CK3World/CoatsOfArms/Emblem.h delete mode 100644 CK3ToEU4/Source/CK3World/CoatsOfArms/EmblemInstance.cpp delete mode 100644 CK3ToEU4/Source/CK3World/CoatsOfArms/EmblemInstance.h delete mode 100644 CK3ToEU4/Source/CK3World/Cultures/Culture.cpp delete mode 100644 CK3ToEU4/Source/CK3World/Cultures/Culture.h delete mode 100644 CK3ToEU4/Source/CK3World/Cultures/Cultures.cpp delete mode 100644 CK3ToEU4/Source/CK3World/Cultures/Cultures.h delete mode 100644 CK3ToEU4/Source/CK3World/Flags/Flags.cpp delete mode 100644 CK3ToEU4/Source/CK3World/Flags/Flags.h delete mode 100644 CK3ToEU4/Source/CK3World/Geography/CountyDetail.cpp delete mode 100644 CK3ToEU4/Source/CK3World/Geography/CountyDetail.h delete mode 100644 CK3ToEU4/Source/CK3World/Religions/Faith.cpp delete mode 100644 CK3ToEU4/Source/CK3World/Religions/Faith.h delete mode 100644 CK3ToEU4/Source/CK3World/Religions/Faiths.cpp delete mode 100644 CK3ToEU4/Source/CK3World/Religions/Faiths.h delete mode 100644 CK3ToEU4/Source/CK3World/Religions/Religion.cpp delete mode 100644 CK3ToEU4/Source/CK3World/Religions/Religion.h delete mode 100644 CK3ToEU4/Source/CK3World/Religions/Religions.cpp delete mode 100644 CK3ToEU4/Source/CK3World/Religions/Religions.h delete mode 100644 CK3ToEU4/Source/CK3World/Titles/DynamicTemplate.cpp delete mode 100644 CK3ToEU4/Source/CK3World/Titles/DynamicTemplate.h delete mode 100644 CK3ToEU4/Source/CK3World/Titles/LandedTitles.cpp delete mode 100644 CK3ToEU4/Source/CK3World/Titles/LandedTitles.h delete mode 100644 CK3ToEU4/Source/CK3World/Titles/Title.cpp delete mode 100644 CK3ToEU4/Source/CK3World/Titles/Title.h delete mode 100644 CK3ToEU4/Source/CK3World/Titles/Titles.h delete mode 100644 CK3ToEU4/Source/Configuration/Configuration.cpp delete mode 100644 CK3ToEU4/Source/Configuration/Configuration.h diff --git a/CK3ToEU4/Source/CK3World/Characters/Character.cpp b/CK3ToEU4/Source/CK3/Characters/Character.cpp similarity index 100% rename from CK3ToEU4/Source/CK3World/Characters/Character.cpp rename to CK3ToEU4/Source/CK3/Characters/Character.cpp diff --git a/CK3ToEU4/Source/CK3World/Characters/Character.h b/CK3ToEU4/Source/CK3/Characters/Character.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Characters/Character.h rename to CK3ToEU4/Source/CK3/Characters/Character.h diff --git a/CK3ToEU4/Source/CK3World/Characters/CharacterDomain.cpp b/CK3ToEU4/Source/CK3/Characters/CharacterDomain.cpp similarity index 100% rename from CK3ToEU4/Source/CK3World/Characters/CharacterDomain.cpp rename to CK3ToEU4/Source/CK3/Characters/CharacterDomain.cpp diff --git a/CK3ToEU4/Source/CK3World/Characters/CharacterDomain.h b/CK3ToEU4/Source/CK3/Characters/CharacterDomain.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Characters/CharacterDomain.h rename to CK3ToEU4/Source/CK3/Characters/CharacterDomain.h diff --git a/CK3ToEU4/Source/CK3World/Characters/Characters.cpp b/CK3ToEU4/Source/CK3/Characters/Characters.cpp similarity index 98% rename from CK3ToEU4/Source/CK3World/Characters/Characters.cpp rename to CK3ToEU4/Source/CK3/Characters/Characters.cpp index d1ef9c3e..75986910 100644 --- a/CK3ToEU4/Source/CK3World/Characters/Characters.cpp +++ b/CK3ToEU4/Source/CK3/Characters/Characters.cpp @@ -1,11 +1,11 @@ #include "Characters.h" #include "../../Mappers/TraitScraper/TraitScraper.h" -#include "../Cultures/Cultures.h" +#include "../Cultures/Cultures.cs" #include "../Dynasties/House.h" #include "../Dynasties/Houses.h" -#include "../Religions/Faiths.h" +#include "../Religions/Faiths.cs" #include "../Titles/Title.h" -#include "../Titles/Titles.h" +#include "../Titles/Titles.cs" #include "Character.h" #include "CharacterDomain.h" #include "CommonRegexes.h" diff --git a/CK3ToEU4/Source/CK3World/Characters/Characters.h b/CK3ToEU4/Source/CK3/Characters/Characters.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Characters/Characters.h rename to CK3ToEU4/Source/CK3/Characters/Characters.h diff --git a/CK3ToEU4/Source/CK3/CoatsOfArms/CoatsOfArms.cs b/CK3ToEU4/Source/CK3/CoatsOfArms/CoatsOfArms.cs new file mode 100644 index 00000000..ba68fb84 --- /dev/null +++ b/CK3ToEU4/Source/CK3/CoatsOfArms/CoatsOfArms.cs @@ -0,0 +1,59 @@ + +namespace CK3ToEU4.CK3.CoatsOfArms; + +class CoatsOfArms +{ + public CoatsOfArms() + { + } + + public CoatsOfArms(std::istream& theStream) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + } + public auto getCoats() const { return coats; } + + public void linkParents(const Titles& titles) + { + auto counter = 0; + const auto& titleData = titles.getTitles(); + for (const auto& coat: coats) + { + if (!coat.second->getParent()) + continue; + const auto& titleDataItr = titleData.find(coat.second->getParent()->first); + if (titleDataItr != titleData.end()) + { + if (!titleDataItr->second->getCoA()) + throw std::runtime_error("CoA " + std::to_string(coat.first) + " has parent " + coat.second->getParent()->first + " which has no coat defined!"); + if (!coats.count(titleDataItr->second->getCoA()->first)) + throw std::runtime_error( + "CoA " + std::to_string(coat.first) + " has parent " + coat.second->getParent()->first + " which has invalid coat defined!"); + coat.second->loadParent(std::make_pair(coat.second->getParent()->first, coats[titleDataItr->second->getCoA()->first])); + ++counter; + } + else + { + throw std::runtime_error("CoA " + std::to_string(coat.first) + " has parent " + coat.second->getParent()->first + " which is undefined!"); + } + } + Log(LogLevel::Info) << "<> " << counter << " coats updated."; + } + + : + private void registerKeys() + { + registerRegex(R"(\d+)", [this](const std::string& coaID, std::istream& theStream) { + auto newCoA = std::make_shared<CoatOfArms>(theStream, std::stoll(coaID)); + coats.insert(std::pair(newCoA->getID(), newCoA)); + }); + registerKeyword("coat_of_arms_manager_database", [this](const std::string& unused, std::istream& theStream) { + coats = CoatsOfArms(theStream).getCoats(); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + private std::map<long long, std::shared_ptr<CoatOfArms>> coats; +}; \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3/CoatsOfArms/EmblemInstance.cs b/CK3ToEU4/Source/CK3/CoatsOfArms/EmblemInstance.cs index 050681eb..562e6845 100644 --- a/CK3ToEU4/Source/CK3/CoatsOfArms/EmblemInstance.cs +++ b/CK3ToEU4/Source/CK3/CoatsOfArms/EmblemInstance.cs @@ -14,22 +14,22 @@ public EmblemInstance(BufferedReader reader) private void RegisterKeys(Parser parser) { - registerKeyword("rotation", [this](const std::string& unused, std::istream& theStream) { - rotation = commonItems::singleDouble(theStream).getDouble(); + parser.RegisterKeyword("rotation", reader => { + rotation = reader.GetDouble(); }); - registerKeyword("depth", [this](const std::string& unused, std::istream& theStream) { - depth = commonItems::singleDouble(theStream).getDouble(); + parser.RegisterKeyword("depth", reader => { + depth = reader.GetDouble(); }); - registerKeyword("position", [this](const std::string& unused, std::istream& theStream) { + parser.RegisterKeyword("position", reader => { position = commonItems::doubleList(theStream).getDoubles(); }); - registerKeyword("scale", [this](const std::string& unused, std::istream& theStream) { + parser.RegisterKeyword("scale", reader => { scale = commonItems::doubleList(theStream).getDoubles(); }); - registerKeyword("offset", [this](const std::string& unused, std::istream& theStream) { + parser.RegisterKeyword("offset", reader => { offset = commonItems::doubleList(theStream).getDoubles(); }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + parser.RegisterRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); } public void DefaultPosition() diff --git a/CK3ToEU4/Source/CK3/Cultures/Culture.cs b/CK3ToEU4/Source/CK3/Cultures/Culture.cs new file mode 100644 index 00000000..c14c0c45 --- /dev/null +++ b/CK3ToEU4/Source/CK3/Cultures/Culture.cs @@ -0,0 +1,160 @@ +using System.Collections.Generic; +using commonItems; + +namespace CK3ToEU4.CK3.Cultures +{ +class Culture +{ + public Culture() {} + public Culture(BufferedReader reader, long theID) + { + ID = theID; + + var parser = new Parser(); + registerKeys(parser); + parser.ParseStream(reader); + } + + public auto getID() const { return ID; } + public auto isEU4Ready() const { return eu4Ready; } + public auto isDynamic() const { return dynamic; } + public const auto& getLocalizedName() const { return localizedName; } + public const auto& getName() const { return name; } + public const auto& getNameLists() const { return nameLists; } + public const auto& getHeritage() const { return heritage; } + public const auto& getTemplate() const { return culture_template; } + public const auto& getEthos() const { return ethos; } + public const auto& getTraditions() const { return traditions; } + + public void setDynamic() { dynamic = true; } + public void concoctCultureName(LocalizationMapper localizationMapper, + CultureMapper cultureMapper, + Dictionary<string, int> cultureNamingCounter) +{ + /* This function is responsible for determining what a culture is and where it's going. Base/vanilla cultures are known to us but + * hybrids and divergences most certainly are not. We can try to normalize some of them like Swiss (hybrid) or Austrian (divergence) into + * eu4 cultures (sidestepping cultural mapping altogether), and if that fails we can generate dynamic cultures and file them in culture + * groups according to their heritages. In this function we do the first half. + */ + + // Is this a base ck3 culture? + if (culture_template) + { + name = *culture_template; + return; + } + + // Does this culture have a name? If not that means the player was very funny. We'll do the same. + if (!localizedName) + { + name = "noname"; + return; + } + + /* We have a divergent culture. Hybrids and divergents are by definition eu4-ready cultures but: + * 1. we allow for overrides using "ck3 = culture" mappings + * 2. not all of them have eu4 definitions which we'll have to generate. + * If a culture is not in "eu4 = " target block then 2) applies and we need to know this. + */ + + // Can we reverse map it via localization into some common base like "austrian"? + const auto& match = localizationMapper.reverseLookupCultureName(*localizedName); + if (match) + { + auto strippedName = *match; + strippedName = strippedName.substr(0, strippedName.size() - 5); + if (cultureMapper.getTargetCultures().contains(strippedName)) + { + // this is a full-flegded eu4 culture with predefined definitions. + name = strippedName; + eu4Ready = true; + return; + } + + if (cultureMapper.getSourceCultures().contains(strippedName)) + { + // this is a culture we've mapped to something else. Proceed normally as if it were vanilla ck3 culture. + name = strippedName; + return; + } + } + + // Now everything else, we need to Concoct the culture name, finally. + name = "dynamic-"; + for (const auto& entry: nameLists) + { + // Enery name component must be mapped to some base eu4 culture, so that eu4tovic2 can decompose it. + const auto& cultureMatch = cultureMapper.cultureNonRegionalNonReligiousMatch(entry, "", 0, ""); + if (cultureMatch) + { + name += *cultureMatch + "-"; + } + else + { + Log(LogLevel::Warning) << "Mapping " << entry << " to an EU4 culture failed! Check mappings!"; + name += entry + "-"; + } + } + name += "culture"; + + // did we see this culture before, elsewhere? + + if (cultureNamingCounter.contains(name)) + { + + ++cultureNamingCounter.at(name); + name += "-num" + std::to_string(cultureNamingCounter.at(name)); + } + else + { + cultureNamingCounter.emplace(name, 1); + name += "-num1"; + } + + dynamic = true; +} + + + + private void registerKeys() + { + registerKeyword("culture_template", [this](std::istream& theStream) { + culture_template = commonItems::getString(theStream); + }); + registerKeyword("name", [this](std::istream& theStream) { + localizedName = commonItems::getString(theStream); + }); + registerKeyword("heritage", [this](std::istream& theStream) { + heritage = commonItems::getString(theStream); + }); + registerKeyword("ethos", [this](std::istream& theStream) { + ethos = commonItems::singleString(theStream).getString(); + }); + registerKeyword("traditions", [this](std::istream& theStream) { + traditions = commonItems::getStrings(theStream); + }); + registerKeyword("name_list", [this](std::istream& theStream) { + auto temp = commonItems::getString(theStream); + if (temp.size() > 10) + { + temp = temp.substr(10, temp.size()); // drop "name_list_", leave "polish" + nameLists.insert(temp); + } + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + private long long ID = 0; + private bool eu4Ready = false; // this culture has eu4 match and needs zero processing + private bool dynamic = false; // this culture is dynamic and will need generation of cultural data + + private std::optional<std::string> culture_template; // this has data only for base ck3 cultures, like czech or german + private std::optional<std::string> localizedName; // this can be anything - user input or localized name in a particular language game is running. + private std::string heritage; // all cultures should have this. + private std::set<std::string> nameLists; // We use these to generate dynamic culture code names, in lack of a better solution. + private std::string ethos; // used to generate custom ideas for custom tags with a custom culture + private std::vector<std::string> traditions; // used to generate custom ideas for custom tags with a custom culture + + private std::string name; // calculated value from all of the above - can be either *eu4* culture, ck3 vanilla, or anything in between. +}; +} \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3/Cultures/Cultures.cs b/CK3ToEU4/Source/CK3/Cultures/Cultures.cs new file mode 100644 index 00000000..4e468af4 --- /dev/null +++ b/CK3ToEU4/Source/CK3/Cultures/Cultures.cs @@ -0,0 +1,43 @@ +using CK3; + +namespace CK3ToEU4.CK3.Cultures; + +class Cultures: commonItems::parser +{ + public Cultures() {} + public Cultures(std::istream& theStream) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + } + + public const auto& getCultures() const { return cultures; } + public void concoctCultures(const mappers::LocalizationMapper& localizationMapper, const mappers::CultureMapper& cultureMapper) + { + for (const auto& culture: cultures | std::views::values) + { + culture->concoctCultureName(localizationMapper, cultureMapper, cultureNamingCounter); + } + } + + + + private void registerKeys() + { + registerRegex(R"(\d+)", [this](const std::string& cultureID, std::istream& theStream) { + auto newCulture = std::make_shared<Culture>(theStream, std::stoll(cultureID)); + cultures.insert(std::pair(newCulture->getID(), newCulture)); + }); + registerKeyword("cultures", [this](std::istream& theStream) { + const auto scraper = Cultures(theStream); + cultures = scraper.getCultures(); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + + + private std::map<long long, std::shared_ptr<Culture>> cultures; + private std::map<std::string, int> cultureNamingCounter; +}; \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3World/Dynasties/Dynasties.cpp b/CK3ToEU4/Source/CK3/Dynasties/Dynasties.cpp similarity index 97% rename from CK3ToEU4/Source/CK3World/Dynasties/Dynasties.cpp rename to CK3ToEU4/Source/CK3/Dynasties/Dynasties.cpp index 0a0f8e9b..9a574874 100644 --- a/CK3ToEU4/Source/CK3World/Dynasties/Dynasties.cpp +++ b/CK3ToEU4/Source/CK3/Dynasties/Dynasties.cpp @@ -1,5 +1,5 @@ #include "Dynasties.h" -#include "../CoatsOfArms/CoatsOfArms.h" +#include "../CoatsOfArms/CoatsOfArms.cs" #include "CommonRegexes.h" #include "Dynasty.h" #include "Log.h" diff --git a/CK3ToEU4/Source/CK3World/Dynasties/Dynasties.h b/CK3ToEU4/Source/CK3/Dynasties/Dynasties.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Dynasties/Dynasties.h rename to CK3ToEU4/Source/CK3/Dynasties/Dynasties.h diff --git a/CK3ToEU4/Source/CK3World/Dynasties/Dynasty.cpp b/CK3ToEU4/Source/CK3/Dynasties/Dynasty.cpp similarity index 100% rename from CK3ToEU4/Source/CK3World/Dynasties/Dynasty.cpp rename to CK3ToEU4/Source/CK3/Dynasties/Dynasty.cpp diff --git a/CK3ToEU4/Source/CK3World/Dynasties/Dynasty.h b/CK3ToEU4/Source/CK3/Dynasties/Dynasty.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Dynasties/Dynasty.h rename to CK3ToEU4/Source/CK3/Dynasties/Dynasty.h diff --git a/CK3ToEU4/Source/CK3World/Dynasties/House.cpp b/CK3ToEU4/Source/CK3/Dynasties/House.cpp similarity index 100% rename from CK3ToEU4/Source/CK3World/Dynasties/House.cpp rename to CK3ToEU4/Source/CK3/Dynasties/House.cpp diff --git a/CK3ToEU4/Source/CK3World/Dynasties/House.h b/CK3ToEU4/Source/CK3/Dynasties/House.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Dynasties/House.h rename to CK3ToEU4/Source/CK3/Dynasties/House.h diff --git a/CK3ToEU4/Source/CK3World/Dynasties/HouseNameScraper.cpp b/CK3ToEU4/Source/CK3/Dynasties/HouseNameScraper.cpp similarity index 100% rename from CK3ToEU4/Source/CK3World/Dynasties/HouseNameScraper.cpp rename to CK3ToEU4/Source/CK3/Dynasties/HouseNameScraper.cpp diff --git a/CK3ToEU4/Source/CK3World/Dynasties/HouseNameScraper.h b/CK3ToEU4/Source/CK3/Dynasties/HouseNameScraper.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Dynasties/HouseNameScraper.h rename to CK3ToEU4/Source/CK3/Dynasties/HouseNameScraper.h diff --git a/CK3ToEU4/Source/CK3World/Dynasties/HouseNameScraping.cpp b/CK3ToEU4/Source/CK3/Dynasties/HouseNameScraping.cpp similarity index 100% rename from CK3ToEU4/Source/CK3World/Dynasties/HouseNameScraping.cpp rename to CK3ToEU4/Source/CK3/Dynasties/HouseNameScraping.cpp diff --git a/CK3ToEU4/Source/CK3World/Dynasties/HouseNameScraping.h b/CK3ToEU4/Source/CK3/Dynasties/HouseNameScraping.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Dynasties/HouseNameScraping.h rename to CK3ToEU4/Source/CK3/Dynasties/HouseNameScraping.h diff --git a/CK3ToEU4/Source/CK3World/Dynasties/Houses.cpp b/CK3ToEU4/Source/CK3/Dynasties/Houses.cpp similarity index 100% rename from CK3ToEU4/Source/CK3World/Dynasties/Houses.cpp rename to CK3ToEU4/Source/CK3/Dynasties/Houses.cpp diff --git a/CK3ToEU4/Source/CK3World/Dynasties/Houses.h b/CK3ToEU4/Source/CK3/Dynasties/Houses.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Dynasties/Houses.h rename to CK3ToEU4/Source/CK3/Dynasties/Houses.h diff --git a/CK3ToEU4/Source/CK3/Flags/Flags.cs b/CK3ToEU4/Source/CK3/Flags/Flags.cs new file mode 100644 index 00000000..27ebdb47 --- /dev/null +++ b/CK3ToEU4/Source/CK3/Flags/Flags.cs @@ -0,0 +1,58 @@ +#ifndef CK3_FLAGS_H +#define CK3_FLAGS_H +#include <set> + +#include "Parser.h" + +namespace CK3 +{ +class Flags: commonItems::parser +{ + public: + Flags() = default; + explicit Flags(std::istream& theStream) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + + if (itemType == "flag" && !incomingFlag.empty()) + flags.insert(incomingFlag); + } + + [[nodiscard]] const auto& getFlags() const { return flags; } + + private: + void registerKeys() + { + registerKeyword("list", [this](const std::string& unused, std::istream& theStream) { + for (const auto& blob: commonItems::blobList(theStream).getBlobs()) + { + auto blobStream = std::stringstream(blob); + const auto scraper = Flags(blobStream); + const auto& foundFlags = scraper.getFlags(); + flags.insert(foundFlags.begin(), foundFlags.end()); + } + }); + registerKeyword("item", [this](const std::string& unused, std::istream& theStream) { + const auto scraper = Flags(theStream); + const auto& foundFlags = scraper.getFlags(); + flags.insert(foundFlags.begin(), foundFlags.end()); + }); + registerKeyword("flag", [this](const std::string& unused, std::istream& theStream) { + incomingFlag = commonItems::singleString(theStream).getString(); + }); + registerKeyword("type", [this](const std::string& unused, std::istream& theStream) { + itemType = commonItems::singleString(theStream).getString(); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + + std::string itemType; + std::string incomingFlag; + std::set<std::string> flags; +}; +} // namespace CK3 + +#endif // CK3_FLAGS_H diff --git a/CK3ToEU4/Source/CK3/Geography/CountyDetail.cs b/CK3ToEU4/Source/CK3/Geography/CountyDetail.cs new file mode 100644 index 00000000..9dd2a7be --- /dev/null +++ b/CK3ToEU4/Source/CK3/Geography/CountyDetail.cs @@ -0,0 +1,46 @@ + +namespace CK3ToEU4.CK3.Geography; + +class CountyDetail +{ + public CountyDetail() {}; + public CountyDetail(std::istream& theStream) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + } + + public auto getDevelopment() const { return development; } + public const auto& getCulture() const { return culture; } + public const auto& getFaith() const { return faith; } + public const auto& isDeJureHRE() const { return deJureHRE; } + + public void loadCulture(const std::pair<long long, std::shared_ptr<Culture>>& theCulture) { culture = theCulture; } + public void loadFaith(const std::pair<long long, std::shared_ptr<Faith>>& theFaith) { faith = theFaith; } + public void setDeJureHRE() { deJureHRE = true; } + + private void registerKeys() + { + registerKeyword("development", [this](const std::string& unused, std::istream& theStream) { + development = commonItems::singleInt(theStream).getInt(); + }); + registerKeyword("culture", [this](const std::string& unused, std::istream& theStream) { + culture = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + if (culture.first == 4294967295) + culture.first = 0; + }); + registerKeyword("faith", [this](const std::string& unused, std::istream& theStream) { + faith = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + if (faith.first == 4294967295) + faith.first = 0; + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + + private int development = 0; + private std::pair<long long, std::shared_ptr<Culture>> culture; + private std::pair<long long, std::shared_ptr<Faith>> faith; + private bool deJureHRE = false; +} \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3World/Geography/CountyDetails.cpp b/CK3ToEU4/Source/CK3/Geography/CountyDetails.cpp similarity index 95% rename from CK3ToEU4/Source/CK3World/Geography/CountyDetails.cpp rename to CK3ToEU4/Source/CK3/Geography/CountyDetails.cpp index 57a476f6..0a3ff3c0 100644 --- a/CK3ToEU4/Source/CK3World/Geography/CountyDetails.cpp +++ b/CK3ToEU4/Source/CK3/Geography/CountyDetails.cpp @@ -1,8 +1,8 @@ #include "CountyDetails.h" -#include "../Cultures/Cultures.h" -#include "../Religions/Faiths.h" +#include "../Cultures/Cultures.cs" +#include "../Religions/Faiths.cs" #include "CommonRegexes.h" -#include "CountyDetail.h" +#include "CountyDetail.cs" #include "Log.h" #include "ParserHelpers.h" diff --git a/CK3ToEU4/Source/CK3World/Geography/CountyDetails.h b/CK3ToEU4/Source/CK3/Geography/CountyDetails.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Geography/CountyDetails.h rename to CK3ToEU4/Source/CK3/Geography/CountyDetails.h diff --git a/CK3ToEU4/Source/CK3World/Geography/ProvinceHolding.cpp b/CK3ToEU4/Source/CK3/Geography/ProvinceHolding.cpp similarity index 100% rename from CK3ToEU4/Source/CK3World/Geography/ProvinceHolding.cpp rename to CK3ToEU4/Source/CK3/Geography/ProvinceHolding.cpp diff --git a/CK3ToEU4/Source/CK3World/Geography/ProvinceHolding.h b/CK3ToEU4/Source/CK3/Geography/ProvinceHolding.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Geography/ProvinceHolding.h rename to CK3ToEU4/Source/CK3/Geography/ProvinceHolding.h diff --git a/CK3ToEU4/Source/CK3World/Geography/ProvinceHoldings.cpp b/CK3ToEU4/Source/CK3/Geography/ProvinceHoldings.cpp similarity index 100% rename from CK3ToEU4/Source/CK3World/Geography/ProvinceHoldings.cpp rename to CK3ToEU4/Source/CK3/Geography/ProvinceHoldings.cpp diff --git a/CK3ToEU4/Source/CK3World/Geography/ProvinceHoldings.h b/CK3ToEU4/Source/CK3/Geography/ProvinceHoldings.h similarity index 100% rename from CK3ToEU4/Source/CK3World/Geography/ProvinceHoldings.h rename to CK3ToEU4/Source/CK3/Geography/ProvinceHoldings.h diff --git a/CK3ToEU4/Source/CK3/Religions/Faith.cs b/CK3ToEU4/Source/CK3/Religions/Faith.cs new file mode 100644 index 00000000..d4e12efa --- /dev/null +++ b/CK3ToEU4/Source/CK3/Religions/Faith.cs @@ -0,0 +1,88 @@ + + +namespace CK3 +{ +class Religion; +class Faith: commonItems::parser +{ + public: + Faith() = default; + Faith(std::istream& theStream, long long theID): ID(theID) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + } + + [[nodiscard]] const auto& getName() const { return tag; } + [[nodiscard]] const auto& getColor() const { return color; } + [[nodiscard]] const auto& getDoctrines() const { return doctrines; } + [[nodiscard]] const auto& getReligion() const { return religion; } + [[nodiscard]] const auto& getReligiousHead() const { return religiousHead; } + [[nodiscard]] auto getID() const { return ID; } + [[nodiscard]] const auto& getCustomName() const { return customName; } + [[nodiscard]] const auto& getCustomAdj() const { return customAdjective; } + [[nodiscard]] const auto& getDescription() const { return description; } + [[nodiscard]] const auto& getTemplate() const { return religionTemplate; } + [[nodiscard]] const auto& getIconPath() const { return iconPath; } + [[nodiscard]] const auto& getReformedFlag() const { return reformedFlag; } + + void setReligiousHead(const auto& newHead) { religiousHead = newHead; } + void loadReligion(const std::pair<long long, std::shared_ptr<Religion>>& theReligion) { religion = theReligion; } + + private: + void registerKeys() + { + registerKeyword("tag", [this](const std::string& unused, std::istream& theStream) { + tag = commonItems::singleString(theStream).getString(); + }); + registerKeyword("doctrine", [this](const std::string& unused, std::istream& theStream) { + doctrines.emplace_back(commonItems::singleString(theStream).getString()); + }); + registerKeyword("religion", [this](const std::string& unused, std::istream& theStream) { + religion = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + }); + registerKeyword("color", [this](const std::string& unused, std::istream& theStream) { + color = laFabricaDeColor.getColor(theStream); + }); + registerKeyword("template", [this](const std::string& unused, std::istream& theStream) { + religionTemplate = commonItems::singleString(theStream).getString(); + }); + registerKeyword("name", [this](const std::string& unused, std::istream& theStream) { + customName = commonItems::singleString(theStream).getString(); + }); + registerKeyword("adjective", [this](const std::string& unused, std::istream& theStream) { + customAdjective = commonItems::singleString(theStream).getString(); + }); + registerKeyword("religious_head", [this](const std::string& unused, std::istream& theStream) { + religiousHead = commonItems::singleString(theStream).getString(); + }); + registerKeyword("desc", [this](const std::string& unused, std::istream& theStream) { + description = commonItems::singleString(theStream).getString(); + }); + registerKeyword("icon", [this](const std::string& unused, std::istream& theStream) { + iconPath = commonItems::singleString(theStream).getString(); + }); + registerKeyword("variables", [this](const std::string& unused, std::istream& theStream) { + if (commonItems::stringOfItem(theStream).getString().find("has_been_reformed") != std::string::npos) + reformedFlag = true; + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + + bool reformedFlag = false; + long long ID = 0; + std::string tag; + std::string religionTemplate; + std::string iconPath; + std::string customName; + std::string customAdjective; + std::string description; + std::string religiousHead; + std::optional<commonItems::Color> color; + std::vector<std::string> + doctrines; // This is a vector in order to keep order consistent. We want the first things read (tenets) to be the first things output, ALWAYS + std::pair<long long, std::shared_ptr<Religion>> religion; +}; +} \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3/Religions/Faiths.cs b/CK3ToEU4/Source/CK3/Religions/Faiths.cs new file mode 100644 index 00000000..77e58ed8 --- /dev/null +++ b/CK3ToEU4/Source/CK3/Religions/Faiths.cs @@ -0,0 +1,66 @@ +#ifndef CK3_FAITHS_H +#define CK3_FAITHS_H +#include "../Titles/LandedTitles.cs" +#include "../Titles/Title.h" +#include "../Titles/Titles.cs" +#include "Parser.h" + +namespace CK3 +{ +class Faith; +class Religions; +class Faiths: commonItems::parser +{ + public: + Faiths() = default; + public Faiths(std::istream& theStream) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + } + + [[nodiscard]] const auto& getFaiths() const { return faiths; } + + void linkReligions(const Religions& religions, const Titles& titles) + { + auto counter = 0; + const auto& religionData = religions.getReligions(); + std::map<std::string, std::string> religiousHeadList; // ID, Title + for (const auto& title: titles.getTitles()) + if (title.second) + religiousHeadList.emplace(std::to_string(title.second->getID()), title.first); + for (const auto& faith: faiths) + { + const auto& religionDataItr = religionData.find(faith.second->getReligion().first); + if (religionDataItr != religionData.end()) + { + faith.second->loadReligion(*religionDataItr); + if (religiousHeadList.contains(faith.second->getReligiousHead())) + faith.second->setReligiousHead(religiousHeadList.at(faith.second->getReligiousHead())); + ++counter; + } + else + { + throw std::runtime_error( + "Faith " + faith.second->getName() + " has religion " + std::to_string(faith.second->getReligion().first) + " which has no definition!"); + } + } + Log(LogLevel::Info) << "<> " << counter << " faiths updated."; + } + + private: + void registerKeys() + { + registerRegex(R"(\d+)", [this](const std::string& faithID, std::istream& theStream) { + auto newFaith = std::make_shared<Faith>(theStream, std::stoll(faithID)); + faiths.insert(std::pair(newFaith->getID(), newFaith)); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + std::map<long long, std::shared_ptr<Faith>> faiths; +}; +} // namespace CK3 + +#endif // CK3_FAITHS_H diff --git a/CK3ToEU4/Source/CK3/Religions/Religion.cs b/CK3ToEU4/Source/CK3/Religions/Religion.cs new file mode 100644 index 00000000..1e20f003 --- /dev/null +++ b/CK3ToEU4/Source/CK3/Religions/Religion.cs @@ -0,0 +1,50 @@ +#ifndef CK3_RELIGION_H +#define CK3_RELIGION_H +#include "Parser.h" + +namespace CK3 +{ +class Faith; +class Religion: commonItems::parser +{ + public: + Religion() = default; + Religion(std::istream& theStream, long long theID): ID(theID) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + } + + [[nodiscard]] auto getID() const { return ID; } + [[nodiscard]] const auto& getName() const { return tag; } + [[nodiscard]] const auto& getFamily() const { return family; } + [[nodiscard]] const auto& getFaiths() const { return faiths; } + + void loadFaiths(const std::map<long long, std::shared_ptr<Faith>>& theFaiths) { faiths = theFaiths; } + + private: + void registerKeys() + { + registerKeyword("tag", [this](const std::string& unused, std::istream& theStream) { + tag = commonItems::singleString(theStream).getString(); + }); + registerKeyword("family", [this](const std::string& unused, std::istream& theStream) { + family = commonItems::singleString(theStream).getString(); + }); + registerKeyword("faiths", [this](const std::string& unused, std::istream& theStream) { + for (auto faith: commonItems::llongList(theStream).getLlongs()) + faiths.insert(std::pair(faith, nullptr)); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + + long long ID = 0; + std::string tag; + std::string family; + std::map<long long, std::shared_ptr<Faith>> faiths; +}; +} // namespace CK3 + +#endif // CK3_RELIGION_H diff --git a/CK3ToEU4/Source/CK3/Religions/Religions.cs b/CK3ToEU4/Source/CK3/Religions/Religions.cs new file mode 100644 index 00000000..d51a7779 --- /dev/null +++ b/CK3ToEU4/Source/CK3/Religions/Religions.cs @@ -0,0 +1,70 @@ +#ifndef CK3_RELIGIONS_H +#define CK3_RELIGIONS_H +#include "Faiths.cs" +#include "Parser.h" + +namespace CK3 +{ +class Religion; +class Religions: commonItems::parser +{ + public: + explicit Religions(std::istream& theStream) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + } + + [[nodiscard]] const auto& getReligions() const { return religions; } + [[nodiscard]] auto getFaiths() { return std::move(faiths); } // Use this only once in World.cpp + + void linkFaiths(const Faiths& theFaiths) + { + auto counter = 0; + const auto& faithData = theFaiths.getFaiths(); + for (const auto& religion: religions) + { + const auto& religionFaiths = religion.second->getFaiths(); + std::map<long long, std::shared_ptr<Faith>> replacementMap; + + for (const auto& faith: religionFaiths) + { + const auto& faithDataItr = faithData.find(faith.first); + if (faithDataItr != faithData.end()) + { + replacementMap.insert(*faithDataItr); + } + else + { + throw std::runtime_error("Religion " + religion.second->getName() + " has faith " + std::to_string(faith.first) + " which has no definition!"); + } + } + religion.second->loadFaiths(replacementMap); + ++counter; + } + Log(LogLevel::Info) << "<> " << counter << " religions updated."; + } + + private: + void registerKeys() + { + registerRegex(R"(\d+)", [this](const std::string& faithID, std::istream& theStream) { + auto newReligion = std::make_shared<Religion>(theStream, std::stoll(faithID)); + religions.insert(std::pair(newReligion->getID(), newReligion)); + }); + registerKeyword("religions", [this](const std::string& unused, std::istream& theStream) { + religions = Religions(theStream).getReligions(); + }); + registerKeyword("faiths", [this](const std::string& unused, std::istream& theStream) { + faiths = Faiths(theStream); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + std::map<long long, std::shared_ptr<Religion>> religions; + Faiths faiths; +}; +} // namespace CK3 + +#endif // CK3_RELIGIONS_H diff --git a/CK3ToEU4/Source/CK3/Titles/DynamicTemplate.cs b/CK3ToEU4/Source/CK3/Titles/DynamicTemplate.cs new file mode 100644 index 00000000..137ff82e --- /dev/null +++ b/CK3ToEU4/Source/CK3/Titles/DynamicTemplate.cs @@ -0,0 +1,28 @@ +using commonItems; + +namespace CK3ToEU4.CK3.Titles; + +class DynamicTemplate +{ + public DynamicTemplate(BufferedReader reader) + { + var parser = new Parser(); + RegisterKeys(parser); + parser.ParseStream(reader); + } + + public string DynamicTitleKey { get; private set; } = string.Empty; + public string DynamicTitleRank { get; private set; } = string.Empty; + + private void RegisterKeys(Parser parser) + { + parser.RegisterKeyword("key", reader => { + DynamicTitleKey = reader.GetString(); + }); + parser.RegisterKeyword("tier", reader => { + DynamicTitleRank = reader.GetString(); + }); + parser.RegisterRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); + } +} + diff --git a/CK3ToEU4/Source/CK3/Titles/LandedTitles.cs b/CK3ToEU4/Source/CK3/Titles/LandedTitles.cs new file mode 100644 index 00000000..2b13bac2 --- /dev/null +++ b/CK3ToEU4/Source/CK3/Titles/LandedTitles.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using commonItems; +using commonItems.Colors; + +namespace CK3ToEU4.CK3.Titles; + +class LandedTitles +{ + // This is a recursive class that scrapes 00_landed_titles.txt (and related files) looking for title colors, landlessness, + // and most importantly relation between baronies and barony provinces so we can link titles to actual clay. + // Since titles are nested according to hierarchy we do this recursively. + + // Keep in mind that we use this class as middleware between titles and hard geographical data. Baronies and Counties have said data, + // but newfangled custom empires and such found in Titles will not be present here. They should have colors defined in their Title block + // anyway, and whatever relates to Title over there takes precedence over data in this class. + + public void loadTitles(BufferedReader reader) + { + var parser = new Parser(); + registerKeys(parser); + parser.ParseStream(reader); + } + public void loadTitles(string fileName) + { + var parser = new Parser(); + registerKeys(parser); + parser.ParseFile(fileName); + } + + public bool DefiniteForm { get;private set; } = false; + public bool Landless { get; private set; } = false; + public bool CanBeNamedAfterDynasty { get; private set; } = true; + public Color? Color { get; private set; } + + // This is of questionable use as savegame already defines defacto capitals. Not always present, and if present then a COUNTY. + public KeyValuePair<string, Title?>? Capital { get; private set; } + + // only b_baronies have these - holdings are related to individual provinces on map. + public KeyValuePair<int, ProvinceHolding?>? Province { get; private set; } + + // only c_counties have these - these define common data for group of baronies under county. + public KeyValuePair<string, CountyDetail?>? County { get; private set; } + + // We're using title name, not savegame ID for key value. + public IReadOnlyDictionary<string, LandedTitles?> FoundTitles => foundTitles; + private readonly Dictionary<string, LandedTitles?> foundTitles; + + public void loadProvinceHolding(const KeyValuePair<int, ProvinceHolding?>& provinceHolding) { province = provinceHolding; } + public void loadCountyDetails(const KeyValuePair<string, std::shared_ptr<CountyDetail>>& countyDetail) { county = countyDetail; } + public void loadCapital(const KeyValuePair<string, Title?>& theCapital) { capital = theCapital; } + + public void linkProvinceHoldings(ProvinceHoldings provinceHoldings) { + // We're linking provinces into BARONY titles only, as other titles have no holding data. + int counter = 0; + var provinceData = provinceHoldings.getProvinceHoldings(); + foreach (var landedTitle in foundTitles) + { + if (landedTitle.first.find("b_") != 0) + continue; + if (!landedTitle.second->getProvince()) + throw std::runtime_error("Landed title " + landedTitle.first + " has not province holding defined!"); + + const auto& provinceDataItr = provinceData.find(landedTitle.second->getProvince()->first); + if (provinceDataItr != provinceData.end()) + { + landedTitle.second->loadProvinceHolding(*provinceDataItr); + ++counter; + } + else + { + throw new Exception("Landed title " + landedTitle.first + " has province holding " + std::to_string(landedTitle.second->getProvince()->first) + + " which has no definition!"); + } + } + Logger.Info("<> " + counter + " landed titles updated."); + } + public void linkCountyDetails(CountyDetails countyDetails) { + // We're linking county details into COUNTY titles only, as other titles have no such details. + int counter = 0; + var countyData = countyDetails.getCountyDetails(); + foreach (var landedTitle in foundTitles) + { + if (!landedTitle.Key.StartsWith("c_")) + continue; + const auto& countyDataItr = countyData.find(landedTitle.first); + if (countyDataItr != countyData.end()) + { + landedTitle.second->loadCountyDetails(*countyDataItr); + ++counter; + } + else + { + // Nothing. People with missing titles from mods and whatnot can have holes on their map. + Logger.Warn("Landed title " + landedTitle.first + " has no definition in counties={} section of the save game!"); + } + } + Logger.Info("<> " + counter + " landed titles updated."); + } + public void linkTitles(Titles titles) { + int counter = 0; + var titleData = titles.getTitles(); + foreach (var landedTitle in foundTitles) + { + const auto& theCapital = landedTitle.second->getCapital(); + if (!theCapital) + continue; + if (const auto& titleDataItr = titleData.find(theCapital->first); titleDataItr != titleData.end()) + { + landedTitle.second->loadCapital(*titleDataItr); + ++counter; + } + else + { + Log(LogLevel::Error) << "Landed title " + landedTitle.first + " has a capital " + theCapital->first + " which has no definition!"; + } + } + Logger.Info("<> " + counter + " landed title capitals updated."); + } + + + private void registerKeys(Parser parser, ColorFactory colorFactory) + { + parser.RegisterRegex(R"((e|k|d|c|b)_[A-Za-z0-9_\-\']+)", (reader, titleName) => { + // Pull the titles beneath this one and add them to the lot, overwriting existing ones. + var newTitle = new LandedTitles(); + newTitle.loadTitles(theStream); + foreach (var locatedTitle: newTitle->getFoundTitles()) + foundTitles[locatedTitle.first] = locatedTitle.second; + + // And then add this one as well, overwriting existing. + foundTitles[titleName] = newTitle; + }); + parser.RegisterKeyword("definite_form", reader => DefiniteForm = reader.GetString() == "yes"); + parser.RegisterKeyword("landless", reader => Landless = reader.GetString() == "yes"); + parser.RegisterKeyword("color", reader => Color = colorFactory.GetColor(reader)); + parser.RegisterKeyword("capital", reader => { + Capital = new(reader.GetString(), null); + }); + parser.RegisterKeyword("province", reader => { + Province = new (reader.GetInt(), null); + }); + parser.RegisterKeyword("can_be_named_after_dynasty", reader => { + CanBeNamedAfterDynasty = reader.GetString() == "yes"; + }); + parser.RegisterRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); + } +}; \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3/Titles/Title.cs b/CK3ToEU4/Source/CK3/Titles/Title.cs index f4cca0d1..fbfdb30c 100644 --- a/CK3ToEU4/Source/CK3/Titles/Title.cs +++ b/CK3ToEU4/Source/CK3/Titles/Title.cs @@ -113,13 +113,13 @@ public Title(BufferedReader reader, long theID) public void setThePope() { thePope = true; } public void setCustomTitle() { customTitle = true; } public void setManualNameClaim() { nameClaimed = true; } - public void pickDisplayName(const Dictionary<string, std::shared_ptr<Title>>& possibleTitles); // Grants one county's name to another during N:1/N:M mappings + public void pickDisplayName(const Dictionary<string, Title?>& possibleTitles); // Grants one county's name to another during N:1/N:M mappings public Title findDuchyCapital(); // Only for c_, for now public void congregateDFCounties(); public void congregateDJCounties(); - public void loadGeneratedLiege(const std::pair<string, std::shared_ptr<Title>>& liege) { generatedLiege = liege; } - public void addGeneratedVassal(const std::pair<string, std::shared_ptr<Title>>& theVassal) { generatedVassals.insert(theVassal); } - public void loadHoldingTitle(const std::pair<string, std::shared_ptr<Title>>& theTitle) { holdingTitle = theTitle; } + public void loadGeneratedLiege(const KeyValuePair<string, Title?>& liege) { generatedLiege = liege; } + public void addGeneratedVassal(const KeyValuePair<string, Title?>& theVassal) { generatedVassals.insert(theVassal); } + public void loadHoldingTitle(const KeyValuePair<string, Title?>& theTitle) { holdingTitle = theTitle; } public void setElectorate() { electorate = true; } public void relinkDeFactoVassals(); #endregion @@ -135,14 +135,14 @@ public Title(BufferedReader reader, long theID) Dictionary<string, Title> coalesceDJCounties() const; #endregion - private void RegisterKeys(Parser parser) + private void RegisterKeys(Parser parser, ColorFactory colorFactory) { parser.RegisterKeyword("key", reader => { name = reader.GetString(); }); parser.RegisterKeyword("name", reader => { displayName = reader.GetString(); - if (displayName.find("\x15") != std::string::npos) + if (displayName.find("\x15") != string::npos) { cleanUpDisplayName(); } @@ -170,13 +170,13 @@ private void RegisterKeys(Parser parser) dCapitalBarony = reader.GetString() == "yes"; }); parser.RegisterKeyword("capital", reader => { - capital = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + capital = new(reader.GetLong(), null); }); parser.RegisterKeyword("de_facto_liege", reader => { - dfLiege = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + dfLiege = KeyValuePair(commonItems::singleLlong(theStream).getLlong(), nullptr); }); parser.RegisterKeyword("de_jure_liege", reader => { - djLiege = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + djLiege = KeyValuePair(commonItems::singleLlong(theStream).getLlong(), nullptr); }); parser.RegisterKeyword("de_jure_vassals", reader => { for (auto vassalID: commonItems::llongList(theStream).getLlongs()) @@ -191,7 +191,7 @@ private void RegisterKeys(Parser parser) laws = std::set(theLaws.begin(), theLaws.end()); }); parser.RegisterKeyword("holder", reader => { - holder = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + holder = KeyValuePair(commonItems::singleLlong(theStream).getLlong(), nullptr); }); parser.RegisterKeyword("renamed", [this](std::istream& theStream) { renamed = commonItems::getString(theStream) == "yes"; @@ -211,7 +211,7 @@ private void RegisterKeys(Parser parser) landless = reader.GetString() == "yes"; }); parser.RegisterKeyword("color", reader => { - color = laFabricaDeColor.getColor(theStream); + color = colorFactory.GetColor(reader); }); parser.RegisterKeyword("history", reader => { previousHolders = new Title(reader, 0).getPreviousHolders(); @@ -237,7 +237,7 @@ private void RegisterKeys(Parser parser) - private KeyValuePair<long, Title> capital; // capital title is a COUNTY, even for county itself and baronies beneath it! + private KeyValuePair<long, Title?> capital; // capital title is a COUNTY, even for county itself and baronies beneath it! private string name; // c_ashmaka private string displayName; // Ashmaka private string adjective; // Ashmakan diff --git a/CK3ToEU4/Source/CK3World/Titles/Titles.cpp b/CK3ToEU4/Source/CK3/Titles/Titles.cs similarity index 78% rename from CK3ToEU4/Source/CK3World/Titles/Titles.cpp rename to CK3ToEU4/Source/CK3/Titles/Titles.cs index 27ab7252..e0332703 100644 --- a/CK3ToEU4/Source/CK3World/Titles/Titles.cpp +++ b/CK3ToEU4/Source/CK3/Titles/Titles.cs @@ -1,132 +1,49 @@ -#include "Titles.h" -#include "../Characters/Character.h" -#include "../Characters/Characters.h" -#include "../CoatsOfArms/CoatOfArms.h" -#include "../CoatsOfArms/CoatsOfArms.h" -#include "CommonRegexes.h" -#include "DynamicTemplate.h" -#include "LandedTitles.h" -#include "Log.h" -#include "ParserHelpers.h" -#include "Title.h" -CK3::Titles::Titles(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); - - // This bit assigns CK3::Level to dynamic titles that have a rank definition in the save. It should be all of them, but it's CK3, so who knows. - if (!dynamicTitleRanks.empty()) - transcribeDynamicRanks(); -} -void CK3::Titles::registerKeys() -{ - registerKeyword("dynamic_templates", [this](const std::string& unused, std::istream& theStream) { - const commonItems::blobList dynamicRanks(theStream); - for (const auto& dynamicTitle: dynamicRanks.getBlobs()) - { - std::stringstream blobStream(dynamicTitle); - const DynamicTemplate dynamicTitleTemplate(blobStream); - if (!dynamicTitleTemplate.getDynamicTitleKey().empty() && !dynamicTitleTemplate.getDynamicTitleRank().empty()) - dynamicTitleRanks.insert(std::pair(dynamicTitleTemplate.getDynamicTitleKey(), dynamicTitleTemplate.getDynamicTitleRank())); - } - }); - registerKeyword("landed_titles", [this](const std::string& unused, std::istream& theStream) { - // A bit of recursion is good for the soul. - const auto& tempTitles = Titles(theStream); - titles = tempTitles.getTitles(); - titleCounter = tempTitles.getCounter(); - }); - registerRegex(R"(\d+)", [this](const std::string& ID, std::istream& theStream) { - // Incoming titles may not be actual titles but half-deleted junk. - const auto& titleBlob = commonItems::stringOfItem(theStream).getString(); - if (titleBlob.find('{') != std::string::npos) - { - std::stringstream tempStream(titleBlob); - try - { - auto newTitle = std::make_shared<Title>(tempStream, std::stoll(ID)); - if (!newTitle->getName().empty()) - titles.insert(std::pair(newTitle->getName(), newTitle)); - if (newTitle->getName().find("b_") == 0) - ++titleCounter[0]; - else if (newTitle->getName().find("c_") == 0) - ++titleCounter[1]; - else if (newTitle->getName().find("d_") == 0) - ++titleCounter[2]; - else if (newTitle->getName().find("k_") == 0) - ++titleCounter[3]; - else if (newTitle->getName().find("e_") == 0) - ++titleCounter[4]; - else - ++titleCounter[5]; // x_x_, x_mc_ and the rest. - } - catch (std::exception& e) - { - throw std::runtime_error("Cannot import title ID: " + ID + " (" + e.what() + ")"); - } - } - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} +namespace CK3ToEU4.CK3.Titles; -void CK3::Titles::transcribeDynamicRanks() +class Titles { - Log(LogLevel::Info) << "-> Transcribing dynamic ranks."; - auto counter = 0; - for (const auto& [key, rank]: dynamicTitleRanks) + public Titles(std::istream& theStream) { - if (!titles.contains(key)) - continue; // Yay? - if (!titles.at(key)) - continue; // Huh? + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); - // There will not be a dynamic county or barony. - if (rank == "duchy") - titles.at(key)->setDynamicLevel(LEVEL::DUCHY); - else if (rank == "kingdom") - { - titles.at(key)->setDynamicLevel(LEVEL::KINGDOM); - titles.at(key)->setCustomTitle(); - } - else if (rank == "empire") - { - titles.at(key)->setDynamicLevel(LEVEL::EMPIRE); - titles.at(key)->setCustomTitle(); - } - counter++; + // This bit assigns CK3::Level to dynamic titles that have a rank definition in the save. It should be all of them, but it's CK3, so who knows. + if (!dynamicTitleRanks.empty()) + transcribeDynamicRanks(); } - Log(LogLevel::Info) << "<> Transcribed " << counter << " dynamics."; -} -void CK3::Titles::linkCoats(const CoatsOfArms& coats) -{ - auto counter = 0; - const auto& coatData = coats.getCoats(); - for (const auto& title: titles) + public const auto& getTitles() const { return titles; } + public const auto& getCounter() const { return titleCounter; } + + public void linkCoats(const CoatsOfArms& coats) { - if (!title.second->getCoA()) - continue; - const auto& coatDataItr = coatData.find(title.second->getCoA()->first); - if (coatDataItr != coatData.end()) - { - title.second->loadCoat(*coatDataItr); - ++counter; - } - else + auto counter = 0; + const auto& coatData = coats.getCoats(); + for (const auto& title: titles) { - Log(LogLevel::Warning) << "Title " + title.first + " has CoA " + std::to_string(title.second->getCoA()->first) + - " which has no definition. Using Default."; - auto defaultCoat = std::make_pair(title.second->getCoA()->first, std::make_shared<CoatOfArms>()); - title.second->loadCoat(defaultCoat); + if (!title.second->getCoA()) + continue; + const auto& coatDataItr = coatData.find(title.second->getCoA()->first); + if (coatDataItr != coatData.end()) + { + title.second->loadCoat(*coatDataItr); + ++counter; + } + else + { + Log(LogLevel::Warning) << "Title " + title.first + " has CoA " + std::to_string(title.second->getCoA()->first) + + " which has no definition. Using Default."; + auto defaultCoat = std::make_pair(title.second->getCoA()->first, std::make_shared<CoatOfArms>()); + title.second->loadCoat(defaultCoat); + } } + Log(LogLevel::Info) << "<> " << counter << " titles updated."; } - Log(LogLevel::Info) << "<> " << counter << " titles updated."; -} -void CK3::Titles::linkTitles() + public void linkTitles() { auto DFLcounter = 0; auto DJLcounter = 0; @@ -275,14 +192,7 @@ void CK3::Titles::linkTitles() Log(LogLevel::Info) << "<> " << DFLcounter << " defacto lieges, " << DJLcounter << " dejure lieges, " << DFVcounter << " defacto vassals, " << DJVcounter << " dejure vassals updated."; } - -void CK3::Titles::relinkDeFactoVassals() -{ - for (const auto& title: titles) - title.second->relinkDeFactoVassals(); -} - -void CK3::Titles::linkCharacters(const Characters& characters) + public void linkCharacters(Characters characters) { auto holderCounter = 0; auto claimantCounter = 0; @@ -405,24 +315,112 @@ void CK3::Titles::linkCharacters(const Characters& characters) Log(LogLevel::Info) << "<> " << holderCounter << " holders, " << claimantCounter << " claimants, " << heirCounter << " heirs, " << exCounter << " previous holders, " << electorCounter << " electors updated."; } + public void linkLandedTitles(LandedTitles landedTitles) + { + // We're injecting clay towards titles instead the other way around. + auto counter = 0; + for (const auto& clay: landedTitles.getFoundTitles()) + { + const auto& titleItr = titles.find(clay.first); + if (titleItr != titles.end()) + { + titleItr->second->loadClay(clay.second); + ++counter; + } + else + { + Log(LogLevel::Error) << "Clay for " << clay.first + << " has no title definition! THIS IS BAD! Are you converting an old save against a new CK3 version?"; + } + } + Log(LogLevel::Info) << "<> " << counter << " titles updated."; + } + public void relinkDeFactoVassals() + { + for (const auto& title: titles) + title.second->relinkDeFactoVassals(); + } -void CK3::Titles::linkLandedTitles(const LandedTitles& landedTitles) + private void registerKeys() { - // We're injecting clay towards titles instead the other way around. - auto counter = 0; - for (const auto& clay: landedTitles.getFoundTitles()) - { - const auto& titleItr = titles.find(clay.first); - if (titleItr != titles.end()) + registerKeyword("dynamic_templates", [this](const std::string& unused, std::istream& theStream) { + const commonItems::blobList dynamicRanks(theStream); + for (const auto& dynamicTitle: dynamicRanks.getBlobs()) { - titleItr->second->loadClay(clay.second); - ++counter; + std::stringstream blobStream(dynamicTitle); + const DynamicTemplate dynamicTitleTemplate(blobStream); + if (!dynamicTitleTemplate.getDynamicTitleKey().empty() && !dynamicTitleTemplate.getDynamicTitleRank().empty()) + dynamicTitleRanks.insert(std::pair(dynamicTitleTemplate.getDynamicTitleKey(), dynamicTitleTemplate.getDynamicTitleRank())); } - else + }); + registerKeyword("landed_titles", [this](const std::string& unused, std::istream& theStream) { + // A bit of recursion is good for the soul. + const auto& tempTitles = Titles(theStream); + titles = tempTitles.getTitles(); + titleCounter = tempTitles.getCounter(); + }); + registerRegex(R"(\d+)", [this](const std::string& ID, std::istream& theStream) { + // Incoming titles may not be actual titles but half-deleted junk. + const auto& titleBlob = commonItems::stringOfItem(theStream).getString(); + if (titleBlob.find('{') != std::string::npos) { - Log(LogLevel::Error) << "Clay for " << clay.first - << " has no title definition! THIS IS BAD! Are you converting an old save against a new CK3 version?"; + std::stringstream tempStream(titleBlob); + try + { + auto newTitle = std::make_shared<Title>(tempStream, std::stoll(ID)); + if (!newTitle->getName().empty()) + titles.insert(std::pair(newTitle->getName(), newTitle)); + if (newTitle->getName().find("b_") == 0) + ++titleCounter[0]; + else if (newTitle->getName().find("c_") == 0) + ++titleCounter[1]; + else if (newTitle->getName().find("d_") == 0) + ++titleCounter[2]; + else if (newTitle->getName().find("k_") == 0) + ++titleCounter[3]; + else if (newTitle->getName().find("e_") == 0) + ++titleCounter[4]; + else + ++titleCounter[5]; // x_x_, x_mc_ and the rest. + } + catch (std::exception& e) + { + throw std::runtime_error("Cannot import title ID: " + ID + " (" + e.what() + ")"); + } } - } - Log(LogLevel::Info) << "<> " << counter << " titles updated."; + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); } + private void transcribeDynamicRanks() + { + Log(LogLevel::Info) << "-> Transcribing dynamic ranks."; + auto counter = 0; + for (const auto& [key, rank]: dynamicTitleRanks) + { + if (!titles.contains(key)) + continue; // Yay? + if (!titles.at(key)) + continue; // Huh? + + // There will not be a dynamic county or barony. + if (rank == "duchy") + titles.at(key)->setDynamicLevel(LEVEL::DUCHY); + else if (rank == "kingdom") + { + titles.at(key)->setDynamicLevel(LEVEL::KINGDOM); + titles.at(key)->setCustomTitle(); + } + else if (rank == "empire") + { + titles.at(key)->setDynamicLevel(LEVEL::EMPIRE); + titles.at(key)->setCustomTitle(); + } + counter++; + } + Log(LogLevel::Info) << "<> Transcribed " << counter << " dynamics."; + } + + private std::vector<int> titleCounter = {0, 0, 0, 0, 0, 0}; + private std::map<std::string, std::shared_ptr<Title>> titles; // We're using NAME, not ID for key value! + private std::map<std::string, std::string> dynamicTitleRanks; +}; diff --git a/CK3ToEU4/Source/CK3/World.cs b/CK3ToEU4/Source/CK3/World.cs index e77299cd..376d8c02 100644 --- a/CK3ToEU4/Source/CK3/World.cs +++ b/CK3ToEU4/Source/CK3/World.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using CK3ToEU4.CK3.Titles; using CK3ToEU4.Configuration; using commonItems; using commonItems.Mods; @@ -257,9 +258,9 @@ private void locatePlayerTitle(Config theConfiguration) { foreach (var (titleId, title) in IndependentTitles) { - if (title.getHolder() && title->getHolder()->first == playerId) + if (title.getHolder() && title.getHolder().first == playerId) { - Logger.Info("Player title: " << title->getName(); + Logger.Info("Player title: " << title.getName(); PlayerTitleId = title.first; break; } @@ -626,7 +627,7 @@ private void shatterHRE(Config theConfiguration) const foreach (var afflictedPerson: brickedPeople) { const auto& holderDomain = afflictedPerson.second->getCharacterDomain()->getDomain(); - const auto holderTitles = std::map(holderDomain.begin(), holderDomain.end()); + const auto holderTitles = Dictionary(holderDomain.begin(), holderDomain.end()); foreach (var holderTitle: holderDomain) { @@ -636,7 +637,7 @@ private void shatterHRE(Config theConfiguration) const { // fix this title. const auto& djLiege = holderTitle.second->getDJLiege(); - djLiege->second->addDFVassals(std::map{holderTitle}); + djLiege->second->addDFVassals(Dictionary{holderTitle}); holderTitle.second->loadDFLiege(*djLiege); } } @@ -760,7 +761,7 @@ private void shatterEmpires(Config theConfiguration) const } const auto& holderDomain = afflictedPerson.second->getCharacterDomain()->getDomain(); - const auto holderTitles = std::map(holderDomain.begin(), holderDomain.end()); + const auto holderTitles = Dictionary(holderDomain.begin(), holderDomain.end()); foreach (var holderTitle: holderDomain) { @@ -770,7 +771,7 @@ private void shatterEmpires(Config theConfiguration) const { // fix this title. const auto& djLiege = holderTitle.second->getDJLiege(); - djLiege->second->addDFVassals(std::map{holderTitle}); + djLiege->second->addDFVassals(Dictionary{holderTitle}); holderTitle.second->loadDFLiege(*djLiege); } } @@ -899,7 +900,7 @@ private void splitVassals(Config theConfiguration) double threshold = static_cast<double>(countiesClaimed.size()) / relevantVassals + 0.1 * static_cast<double>(countiesClaimed.size()); threshold *= vassalSplitoffMapper.getFactor(); if (static_cast<double>(vassalProvincesClaimed.size()) > threshold) - newIndeps.insert(std::pair(vassal.second->getName(), vassal.second)); + newIndeps.insert(KeyValuePair(vassal.second->getName(), vassal.second)); } } @@ -908,7 +909,7 @@ private void splitVassals(Config theConfiguration) { const auto& liege = newIndep.second->getDFLiege(); liege->second->addGeneratedVassal(newIndep); - newIndep.second->loadGeneratedLiege(std::pair(liege->second->getName(), liege->second)); + newIndep.second->loadGeneratedLiege(KeyValuePair(liege->second->getName(), liege->second)); newIndep.second->grantIndependence(); independentTitles.insert(newIndep); } @@ -940,7 +941,7 @@ private void gatherCourtierNames() if (character.second->getEmployer() && character.second->getEmployer()->second) { // easiest case. - holderCourtiers[character.second->getEmployer()->first].insert(std::pair(character.second->getName(), !character.second->isFemale())); + holderCourtiers[character.second->getEmployer()->first].insert(KeyValuePair(character.second->getName(), !character.second->isFemale())); holderCouncilors[character.second->getEmployer()->first].insert(character); } else if (character.second->getCharacterDomain() && !character.second->getCharacterDomain()->getDomain().empty()) @@ -955,7 +956,7 @@ private void gatherCourtierNames() const auto& liege = liegeTitle->second->getHolder(); if (!liege || !liege->second) continue; // Or maybe we should fire his liege. - holderCourtiers[liege->first].insert(std::pair(character.second->getName(), character.second->isFemale())); + holderCourtiers[liege->first].insert(KeyValuePair(character.second->getName(), character.second->isFemale())); holderCouncilors[liege->first].insert(character); } else @@ -967,7 +968,7 @@ private void gatherCourtierNames() else if (character.second->getEmployer()) { // Being employed but without a council task means a knight or physician or similar. Works for us. - holderCourtiers[character.second->getEmployer()->first].insert(std::pair(character.second->getName(), !character.second->isFemale())); + holderCourtiers[character.second->getEmployer()->first].insert(KeyValuePair(character.second->getName(), !character.second->isFemale())); } } @@ -1000,7 +1001,7 @@ private void congregateDFCounties() title.second->congregateDFCounties(); foreach (var province: title.second->getOwnedDFCounties()) { - province.second->loadHoldingTitle(std::pair(title.first, title.second)); + province.second->loadHoldingTitle(KeyValuePair(title.first, title.second)); } counter += static_cast<int>(title.second->getOwnedDFCounties().size()); } @@ -1065,7 +1066,7 @@ private void setElectors() // Preambule done, we start here. // Make a registry of indep titles and their holders. Dictionary<long, Dictionary<string, Title?>> holderTitles; // holder/titles - std::pair<long, Character?> hreHolder; + KeyValuePair<long, Character?> hreHolder; foreach (var title: independentTitles) { diff --git a/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatOfArms.cpp b/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatOfArms.cpp deleted file mode 100644 index 4419d5fd..00000000 --- a/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatOfArms.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "CoatOfArms.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -CK3::CoatOfArms::CoatOfArms(std::istream& theStream, long long theID): ID(theID) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::CoatOfArms::registerKeys() -{ - registerKeyword("pattern", [this](const std::string& unused, std::istream& theStream) { - pattern = commonItems::singleString(theStream).getString(); - }); - registerKeyword("color1", [this](const std::string& unused, std::istream& theStream) { - try - { - color1 = laFabricaDeColor.getColor(theStream); - } - catch (std::exception& e) - { - Log(LogLevel::Warning) << e.what() << " - sidestepping with black."; - color1 = commonItems::Color(std::array<int, 3>{0, 0, 0}); - } - }); - registerKeyword("color2", [this](const std::string& unused, std::istream& theStream) { - try - { - color2 = laFabricaDeColor.getColor(theStream); - } - catch (std::exception& e) - { - Log(LogLevel::Warning) << e.what() << " - sidestepping with black."; - color2 = commonItems::Color(std::array<int, 3>{0, 0, 0}); - } - }); - registerKeyword("color3", [this](const std::string& unused, std::istream& theStream) { - try - { - color3 = laFabricaDeColor.getColor(theStream); - } - catch (std::exception& e) - { - Log(LogLevel::Warning) << e.what() << " - sidestepping with black."; - color3 = commonItems::Color(std::array<int, 3>{0, 0, 0}); - } - }); - registerKeyword("textured_emblem", [this](const std::string& unused, std::istream& theStream) { - texturedEmblems.emplace_back(Emblem(theStream)); - }); - registerKeyword("colored_emblem", [this](const std::string& unused, std::istream& theStream) { - coloredEmblems.emplace_back(Emblem(theStream)); - }); - registerKeyword("sub", [this](const std::string& unused, std::istream& theStream) { - subs.emplace_back(std::make_shared<CoatOfArms>(theStream, 0)); - }); - registerKeyword("instance", [this](const std::string& unused, std::istream& theStream) { - auto instance = EmblemInstance(theStream); - if (instance.getOffset().empty()) - instance.defaultOffset(); - instances.emplace_back(instance); - }); - registerKeyword("parent", [this](const std::string& unused, std::istream& theStream) { - parent = std::make_pair(commonItems::singleString(theStream).getString(), nullptr); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} diff --git a/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatOfArms.h b/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatOfArms.h deleted file mode 100644 index 453a5d2c..00000000 --- a/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatOfArms.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef CK3_COATOFARMS_H -#define CK3_COATOFARMS_H -#include "Color.h" -#include "Emblem.h" -#include "Parser.h" -extern commonItems::Color::Factory laFabricaDeColor; - -namespace CK3 -{ -class CoatOfArms: commonItems::parser -{ - public: - CoatOfArms() = default; - CoatOfArms(std::istream& theStream, long long theID); - - [[nodiscard]] auto getID() const { return ID; } - [[nodiscard]] const auto& getPattern() const { return pattern; } - [[nodiscard]] const auto& getColor1() const { return color1; } - [[nodiscard]] const auto& getColor2() const { return color2; } - [[nodiscard]] const auto& getColor3() const { return color3; } - [[nodiscard]] const auto& getTexturedEmblems() const { return texturedEmblems; } - [[nodiscard]] const auto& getColoredEmblems() const { return coloredEmblems; } - [[nodiscard]] const auto& getSubs() const { return subs; } - [[nodiscard]] const auto& getInstances() const { return instances; } - [[nodiscard]] const auto& getParent() const { return parent; } - - void loadParent(const std::pair<std::string, std::shared_ptr<CoatOfArms>>& theParent) { parent = theParent; } - - private: - void registerKeys(); - - long long ID = 0; - std::optional<std::string> pattern; - std::optional<commonItems::Color> color1; // mask: 255, 0, 0 - red - std::optional<commonItems::Color> color2; // mask: 255, 255, 0 - yellow - std::optional<commonItems::Color> color3; // mask: 255, 255, 255 - white - std::vector<Emblem> texturedEmblems; - std::vector<Emblem> coloredEmblems; - std::vector<std::shared_ptr<CoatOfArms>> subs; // These are sub-coatsofarms. They are recursive! - std::vector<EmblemInstance> instances; // Used to position sub-coats. - std::optional<std::pair<std::string, std::shared_ptr<CoatOfArms>>> parent; // Used for recursive external flags. -}; -} // namespace CK3 - -#endif // CK3_COATOFARMS_H diff --git a/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatsOfArms.cpp b/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatsOfArms.cpp deleted file mode 100644 index 50d6cb3c..00000000 --- a/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatsOfArms.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "CoatsOfArms.h" -#include "../Titles/Title.h" -#include "../Titles/Titles.h" -#include "CoatOfArms.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -CK3::CoatsOfArms::CoatsOfArms(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::CoatsOfArms::registerKeys() -{ - registerRegex(R"(\d+)", [this](const std::string& coaID, std::istream& theStream) { - auto newCoA = std::make_shared<CoatOfArms>(theStream, std::stoll(coaID)); - coats.insert(std::pair(newCoA->getID(), newCoA)); - }); - registerKeyword("coat_of_arms_manager_database", [this](const std::string& unused, std::istream& theStream) { - coats = CoatsOfArms(theStream).getCoats(); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - -void CK3::CoatsOfArms::linkParents(const Titles& titles) -{ - auto counter = 0; - const auto& titleData = titles.getTitles(); - for (const auto& coat: coats) - { - if (!coat.second->getParent()) - continue; - const auto& titleDataItr = titleData.find(coat.second->getParent()->first); - if (titleDataItr != titleData.end()) - { - if (!titleDataItr->second->getCoA()) - throw std::runtime_error("CoA " + std::to_string(coat.first) + " has parent " + coat.second->getParent()->first + " which has no coat defined!"); - if (!coats.count(titleDataItr->second->getCoA()->first)) - throw std::runtime_error( - "CoA " + std::to_string(coat.first) + " has parent " + coat.second->getParent()->first + " which has invalid coat defined!"); - coat.second->loadParent(std::make_pair(coat.second->getParent()->first, coats[titleDataItr->second->getCoA()->first])); - ++counter; - } - else - { - throw std::runtime_error("CoA " + std::to_string(coat.first) + " has parent " + coat.second->getParent()->first + " which is undefined!"); - } - } - Log(LogLevel::Info) << "<> " << counter << " coats updated."; -} \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatsOfArms.h b/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatsOfArms.h deleted file mode 100644 index 39732733..00000000 --- a/CK3ToEU4/Source/CK3World/CoatsOfArms/CoatsOfArms.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef CK3_COATSOFARMS_H -#define CK3_COATSOFARMS_H -#include "Parser.h" - -namespace CK3 -{ -class CoatOfArms; -class Titles; -class CoatsOfArms: commonItems::parser -{ - public: - CoatsOfArms() = default; - explicit CoatsOfArms(std::istream& theStream); - [[nodiscard]] auto getCoats() const { return coats; } - - void linkParents(const Titles& titles); - - private: - void registerKeys(); - - std::map<long long, std::shared_ptr<CoatOfArms>> coats; -}; -} // namespace CK3 - -#endif // CK3_COATSOFARMS_H diff --git a/CK3ToEU4/Source/CK3World/CoatsOfArms/Emblem.cpp b/CK3ToEU4/Source/CK3World/CoatsOfArms/Emblem.cpp deleted file mode 100644 index e72a1b29..00000000 --- a/CK3ToEU4/Source/CK3World/CoatsOfArms/Emblem.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "Emblem.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -CK3::Emblem::Emblem(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::Emblem::registerKeys() -{ - registerKeyword("texture", [this](const std::string& unused, std::istream& theStream) { - texture = commonItems::singleString(theStream).getString(); - }); - registerKeyword("color1", [this](const std::string& unused, std::istream& theStream) { - try - { - color1 = laFabricaDeColor.getColor(theStream); - } - catch (std::exception& e) - { - Log(LogLevel::Warning) << e.what() << " - sidestepping with black."; - color1 = commonItems::Color(std::array<int, 3>{0, 0, 0}); - } - }); - registerKeyword("color2", [this](const std::string& unused, std::istream& theStream) { - try - { - color2 = laFabricaDeColor.getColor(theStream); - } - catch (std::exception& e) - { - Log(LogLevel::Warning) << e.what() << " - sidestepping with black."; - color2 = commonItems::Color(std::array<int, 3>{0, 0, 0}); - } - }); - registerKeyword("color3", [this](const std::string& unused, std::istream& theStream) { - try - { - color3 = laFabricaDeColor.getColor(theStream); - } - catch (std::exception& e) - { - Log(LogLevel::Warning) << e.what() << " - sidestepping with black."; - color3 = commonItems::Color(std::array<int, 3>{0, 0, 0}); - } - }); - registerKeyword("mask", [this](const std::string& unused, std::istream& theStream) { - mask = commonItems::intList(theStream).getInts(); - }); - registerKeyword("instance", [this](const std::string& unused, std::istream& theStream) { - auto instance = EmblemInstance(theStream); - if (instance.getPosition().empty()) - instance.defaultPosition(); - instances.emplace_back(instance); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} diff --git a/CK3ToEU4/Source/CK3World/CoatsOfArms/Emblem.h b/CK3ToEU4/Source/CK3World/CoatsOfArms/Emblem.h deleted file mode 100644 index f3d0aa60..00000000 --- a/CK3ToEU4/Source/CK3World/CoatsOfArms/Emblem.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef CK3_EMBLEM_H -#define CK3_EMBLEM_H -#include "Color.h" -#include "EmblemInstance.h" -#include "Parser.h" -extern commonItems::Color::Factory laFabricaDeColor; - -namespace CK3 -{ -class Emblem: commonItems::parser -{ - public: - Emblem() = default; - Emblem(std::istream& theStream); - - [[nodiscard]] const auto& getTexture() const { return texture; } - [[nodiscard]] const auto& getColor1() const { return color1; } - [[nodiscard]] const auto& getColor2() const { return color2; } - [[nodiscard]] const auto& getColor3() const { return color3; } - [[nodiscard]] const auto& getMask() const { return mask; } - [[nodiscard]] const auto& getInstances() const { return instances; } - - private: - void registerKeys(); - - std::optional<std::string> texture; - std::optional<commonItems::Color> color1; // mask: 0, 0, 128 - blueish - std::optional<commonItems::Color> color2; // mask: 0, 255, 128 - greenish - std::optional<commonItems::Color> color3; // mask: 255, 0, 128 - unsupported by PDX, must render to white! - std::vector<int> mask; - std::vector<EmblemInstance> instances; -}; -} // namespace CK3 - -#endif // CK3_EMBLEM_H diff --git a/CK3ToEU4/Source/CK3World/CoatsOfArms/EmblemInstance.cpp b/CK3ToEU4/Source/CK3World/CoatsOfArms/EmblemInstance.cpp deleted file mode 100644 index c4939fc5..00000000 --- a/CK3ToEU4/Source/CK3World/CoatsOfArms/EmblemInstance.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "EmblemInstance.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -CK3::EmblemInstance::EmblemInstance(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::EmblemInstance::registerKeys() -{ - registerKeyword("rotation", [this](const std::string& unused, std::istream& theStream) { - rotation = commonItems::singleDouble(theStream).getDouble(); - }); - registerKeyword("depth", [this](const std::string& unused, std::istream& theStream) { - depth = commonItems::singleDouble(theStream).getDouble(); - }); - registerKeyword("position", [this](const std::string& unused, std::istream& theStream) { - position = commonItems::doubleList(theStream).getDoubles(); - }); - registerKeyword("scale", [this](const std::string& unused, std::istream& theStream) { - scale = commonItems::doubleList(theStream).getDoubles(); - }); - registerKeyword("offset", [this](const std::string& unused, std::istream& theStream) { - offset = commonItems::doubleList(theStream).getDoubles(); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} diff --git a/CK3ToEU4/Source/CK3World/CoatsOfArms/EmblemInstance.h b/CK3ToEU4/Source/CK3World/CoatsOfArms/EmblemInstance.h deleted file mode 100644 index 5409cfd2..00000000 --- a/CK3ToEU4/Source/CK3World/CoatsOfArms/EmblemInstance.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef CK3_EMBLEMINSTANCE_H -#define CK3_EMBLEMINSTANCE_H -#include "Parser.h" - -namespace CK3 -{ -class EmblemInstance: commonItems::parser -{ - public: - EmblemInstance() = default; - EmblemInstance(std::istream& theStream); - - [[nodiscard]] auto getRotation() const { return rotation; } - [[nodiscard]] auto getDepth() const { return depth; } - [[nodiscard]] const auto& getPosition() const { return position; } - [[nodiscard]] const auto& getScale() const { return scale; } - [[nodiscard]] const auto& getOffset() const { return offset; } - void defaultPosition() { position = {0.5, 0.5}; } - void defaultOffset() { offset = {0.0, 0.0}; } - - private: - void registerKeys(); - - double rotation = 0.0; // Degrees, clockwise. - double depth = 0.0; // Do. Not. Ask. Go to wiki and complain there. - std::vector<double> position; // Default position is UPPER LEFT corner. Targets CENTER of emblem. - std::vector<double> scale = {1.0, 1.0}; // Relative to image size. Defaults to "across entire image". - std::vector<double> offset; // Used in sub-coat instances. Also UPPER LEFT corner. Targets UPPER LEFT corner of subcoat. -}; -} // namespace CK3 - -#endif // CK3_EMBLEMINSTANCE_H diff --git a/CK3ToEU4/Source/CK3World/Cultures/Culture.cpp b/CK3ToEU4/Source/CK3World/Cultures/Culture.cpp deleted file mode 100644 index 026b9c38..00000000 --- a/CK3ToEU4/Source/CK3World/Cultures/Culture.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include "Culture.h" -#include "../../Mappers/CultureMapper/CultureMapper.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -CK3::Culture::Culture(std::istream& theStream, long long theID): ID(theID) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::Culture::registerKeys() -{ - registerKeyword("culture_template", [this](std::istream& theStream) { - culture_template = commonItems::getString(theStream); - }); - registerKeyword("name", [this](std::istream& theStream) { - localizedName = commonItems::getString(theStream); - }); - registerKeyword("heritage", [this](std::istream& theStream) { - heritage = commonItems::getString(theStream); - }); - registerKeyword("ethos", [this](std::istream& theStream) { - ethos = commonItems::singleString(theStream).getString(); - }); - registerKeyword("traditions", [this](std::istream& theStream) { - traditions = commonItems::getStrings(theStream); - }); - registerKeyword("name_list", [this](std::istream& theStream) { - auto temp = commonItems::getString(theStream); - if (temp.size() > 10) - { - temp = temp.substr(10, temp.size()); // drop "name_list_", leave "polish" - nameLists.insert(temp); - } - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - -void CK3::Culture::concoctCultureName(const mappers::LocalizationMapper& localizationMapper, - const mappers::CultureMapper& cultureMapper, - std::map<std::string, int>& cultureNamingCounter) -{ - /* This function is responsible for determining what a culture is and where it's going. Base/vanilla cultures are known to us but - * hybrids and divergences most certainly are not. We can try to normalize some of them like Swiss (hybrid) or Austrian (divergence) into - * eu4 cultures (sidestepping cultural mapping altogether), and if that fails we can generate dynamic cultures and file them in culture - * groups according to their heritages. In this function we do the first half. - */ - - // Is this a base ck3 culture? - if (culture_template) - { - name = *culture_template; - return; - } - - // Does this culture have a name? If not that means the player was very funny. We'll do the same. - if (!localizedName) - { - name = "noname"; - return; - } - - /* We have a divergent culture. Hybrids and divergents are by definition eu4-ready cultures but: - * 1. we allow for overrides using "ck3 = culture" mappings - * 2. not all of them have eu4 definitions which we'll have to generate. - * If a culture is not in "eu4 = " target block then 2) applies and we need to know this. - */ - - // Can we reverse map it via localization into some common base like "austrian"? - const auto& match = localizationMapper.reverseLookupCultureName(*localizedName); - if (match) - { - auto strippedName = *match; - strippedName = strippedName.substr(0, strippedName.size() - 5); - if (cultureMapper.getTargetCultures().contains(strippedName)) - { - // this is a full-flegded eu4 culture with predefined definitions. - name = strippedName; - eu4Ready = true; - return; - } - - if (cultureMapper.getSourceCultures().contains(strippedName)) - { - // this is a culture we've mapped to something else. Proceed normally as if it were vanilla ck3 culture. - name = strippedName; - return; - } - } - - // Now everything else, we need to Concoct the culture name, finally. - name = "dynamic-"; - for (const auto& entry: nameLists) - { - // Enery name component must be mapped to some base eu4 culture, so that eu4tovic2 can decompose it. - const auto& cultureMatch = cultureMapper.cultureNonRegionalNonReligiousMatch(entry, "", 0, ""); - if (cultureMatch) - { - name += *cultureMatch + "-"; - } - else - { - Log(LogLevel::Warning) << "Mapping " << entry << " to an EU4 culture failed! Check mappings!"; - name += entry + "-"; - } - } - name += "culture"; - - // did we see this culture before, elsewhere? - - if (cultureNamingCounter.contains(name)) - { - - ++cultureNamingCounter.at(name); - name += "-num" + std::to_string(cultureNamingCounter.at(name)); - } - else - { - cultureNamingCounter.emplace(name, 1); - name += "-num1"; - } - - dynamic = true; -} diff --git a/CK3ToEU4/Source/CK3World/Cultures/Culture.h b/CK3ToEU4/Source/CK3World/Cultures/Culture.h deleted file mode 100644 index bccf188b..00000000 --- a/CK3ToEU4/Source/CK3World/Cultures/Culture.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef CK3_CULTURE_H -#define CK3_CULTURE_H -#include "../../Mappers/LocalizationMapper/LocalizationMapper.h" -#include "Parser.h" -#include <set> - -namespace mappers -{ -class CultureMapper; -} - -namespace CK3 -{ -class Culture: commonItems::parser -{ - public: - Culture() = default; - Culture(std::istream& theStream, long long theID); - - [[nodiscard]] auto getID() const { return ID; } - [[nodiscard]] auto isEU4Ready() const { return eu4Ready; } - [[nodiscard]] auto isDynamic() const { return dynamic; } - [[nodiscard]] const auto& getLocalizedName() const { return localizedName; } - [[nodiscard]] const auto& getName() const { return name; } - [[nodiscard]] const auto& getNameLists() const { return nameLists; } - [[nodiscard]] const auto& getHeritage() const { return heritage; } - [[nodiscard]] const auto& getTemplate() const { return culture_template; } - [[nodiscard]] const auto& getEthos() const { return ethos; } - [[nodiscard]] const auto& getTraditions() const { return traditions; } - - void setDynamic() { dynamic = true; } - void concoctCultureName(const mappers::LocalizationMapper& localizationMapper, - const mappers::CultureMapper& cultureMapper, - std::map<std::string, int>& cultureNamingCounter); - - private: - void registerKeys(); - - long long ID = 0; - bool eu4Ready = false; // this culture has eu4 match and needs zero processing - bool dynamic = false; // this culture is dynamic and will need generation of cultural data - - std::optional<std::string> culture_template; // this has data only for base ck3 cultures, like czech or german - std::optional<std::string> localizedName; // this can be anything - user input or localized name in a particular language game is running. - std::string heritage; // all cultures should have this. - std::set<std::string> nameLists; // We use these to generate dynamic culture code names, in lack of a better solution. - std::string ethos; // used to generate custom ideas for custom tags with a custom culture - std::vector<std::string> traditions; // used to generate custom ideas for custom tags with a custom culture - - std::string name; // calculated value from all of the above - can be either *eu4* culture, ck3 vanilla, or anything in between. -}; -} // namespace CK3 - -#endif // CK3_CULTURE_H diff --git a/CK3ToEU4/Source/CK3World/Cultures/Cultures.cpp b/CK3ToEU4/Source/CK3World/Cultures/Cultures.cpp deleted file mode 100644 index 2022fab7..00000000 --- a/CK3ToEU4/Source/CK3World/Cultures/Cultures.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "Cultures.h" -#include "CommonRegexes.h" -#include "Culture.h" -#include "Log.h" -#include "ParserHelpers.h" -#include <ranges> - -CK3::Cultures::Cultures(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::Cultures::registerKeys() -{ - registerRegex(R"(\d+)", [this](const std::string& cultureID, std::istream& theStream) { - auto newCulture = std::make_shared<Culture>(theStream, std::stoll(cultureID)); - cultures.insert(std::pair(newCulture->getID(), newCulture)); - }); - registerKeyword("cultures", [this](std::istream& theStream) { - const auto scraper = Cultures(theStream); - cultures = scraper.getCultures(); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - -void CK3::Cultures::concoctCultures(const mappers::LocalizationMapper& localizationMapper, const mappers::CultureMapper& cultureMapper) -{ - for (const auto& culture: cultures | std::views::values) - { - culture->concoctCultureName(localizationMapper, cultureMapper, cultureNamingCounter); - } -} diff --git a/CK3ToEU4/Source/CK3World/Cultures/Cultures.h b/CK3ToEU4/Source/CK3World/Cultures/Cultures.h deleted file mode 100644 index 62b7a951..00000000 --- a/CK3ToEU4/Source/CK3World/Cultures/Cultures.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef CK3_CULTURES_H -#define CK3_CULTURES_H -#include "../../Mappers/CultureMapper/CultureMapper.h" -#include "../../Mappers/LocalizationMapper/LocalizationMapper.h" -#include "Parser.h" - -namespace CK3 -{ -class Culture; -class Cultures: commonItems::parser -{ - public: - Cultures() = default; - explicit Cultures(std::istream& theStream); - - [[nodiscard]] const auto& getCultures() const { return cultures; } - void concoctCultures(const mappers::LocalizationMapper& localizationMapper, const mappers::CultureMapper& cultureMapper); - - private: - void registerKeys(); - - std::map<long long, std::shared_ptr<Culture>> cultures; - std::map<std::string, int> cultureNamingCounter; -}; -} // namespace CK3 - -#endif // CK3_CULTURES_H diff --git a/CK3ToEU4/Source/CK3World/Flags/Flags.cpp b/CK3ToEU4/Source/CK3World/Flags/Flags.cpp deleted file mode 100644 index a00e0c18..00000000 --- a/CK3ToEU4/Source/CK3World/Flags/Flags.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "Flags.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -// This file loads data flags ("flag_re_restored_antioch"), not graphical flags. -// Since game uses this type of syntax: -// type=flag -// flag="flag_formed_kingdom_of_aragon" -// we'll be loading only those flags that have type = flag set. Unsure if any other flag type exists. -// Flags in "data" section of save are ignored - those appear to be gameplay-session related and not really global. -// -// Flags are further complicated by being bundled in data groups. As of yet we do not know if -// name="unavailable_unique_decisions" { flag="flag_formed_kingdom_of_aragon" } -// means aragon is already formed, thus decision is unavailable (giving proper semantics to the flag we scrape) or -// aragon forming decision is simply unavailable, in which case the flag means the opposite of what we assume it to be. - -CK3::Flags::Flags(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); - - if (itemType == "flag" && !incomingFlag.empty()) - flags.insert(incomingFlag); -} - -void CK3::Flags::registerKeys() -{ - registerKeyword("list", [this](const std::string& unused, std::istream& theStream) { - for (const auto& blob: commonItems::blobList(theStream).getBlobs()) - { - auto blobStream = std::stringstream(blob); - const auto scraper = Flags(blobStream); - const auto& foundFlags = scraper.getFlags(); - flags.insert(foundFlags.begin(), foundFlags.end()); - } - }); - registerKeyword("item", [this](const std::string& unused, std::istream& theStream) { - const auto scraper = Flags(theStream); - const auto& foundFlags = scraper.getFlags(); - flags.insert(foundFlags.begin(), foundFlags.end()); - }); - registerKeyword("flag", [this](const std::string& unused, std::istream& theStream) { - incomingFlag = commonItems::singleString(theStream).getString(); - }); - registerKeyword("type", [this](const std::string& unused, std::istream& theStream) { - itemType = commonItems::singleString(theStream).getString(); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} diff --git a/CK3ToEU4/Source/CK3World/Flags/Flags.h b/CK3ToEU4/Source/CK3World/Flags/Flags.h deleted file mode 100644 index b61ea9fd..00000000 --- a/CK3ToEU4/Source/CK3World/Flags/Flags.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef CK3_FLAGS_H -#define CK3_FLAGS_H -#include <set> - -#include "Parser.h" - -namespace CK3 -{ -class Flags: commonItems::parser -{ - public: - Flags() = default; - explicit Flags(std::istream& theStream); - - [[nodiscard]] const auto& getFlags() const { return flags; } - - private: - void registerKeys(); - - std::string itemType; - std::string incomingFlag; - std::set<std::string> flags; -}; -} // namespace CK3 - -#endif // CK3_FLAGS_H diff --git a/CK3ToEU4/Source/CK3World/Geography/CountyDetail.cpp b/CK3ToEU4/Source/CK3World/Geography/CountyDetail.cpp deleted file mode 100644 index b2eee219..00000000 --- a/CK3ToEU4/Source/CK3World/Geography/CountyDetail.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "CountyDetail.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -CK3::CountyDetail::CountyDetail(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::CountyDetail::registerKeys() -{ - registerKeyword("development", [this](const std::string& unused, std::istream& theStream) { - development = commonItems::singleInt(theStream).getInt(); - }); - registerKeyword("culture", [this](const std::string& unused, std::istream& theStream) { - culture = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - if (culture.first == 4294967295) - culture.first = 0; - }); - registerKeyword("faith", [this](const std::string& unused, std::istream& theStream) { - faith = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - if (faith.first == 4294967295) - faith.first = 0; - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} diff --git a/CK3ToEU4/Source/CK3World/Geography/CountyDetail.h b/CK3ToEU4/Source/CK3World/Geography/CountyDetail.h deleted file mode 100644 index 5f276542..00000000 --- a/CK3ToEU4/Source/CK3World/Geography/CountyDetail.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef CK3_COUNTYDETAIL_H -#define CK3_COUNTYDETAIL_H -#include "Parser.h" - -namespace CK3 -{ -class Faith; -class Culture; -class CountyDetail: commonItems::parser -{ - public: - CountyDetail() = default; - CountyDetail(std::istream& theStream); - - [[nodiscard]] auto getDevelopment() const { return development; } - [[nodiscard]] const auto& getCulture() const { return culture; } - [[nodiscard]] const auto& getFaith() const { return faith; } - [[nodiscard]] const auto& isDeJureHRE() const { return deJureHRE; } - - void loadCulture(const std::pair<long long, std::shared_ptr<Culture>>& theCulture) { culture = theCulture; } - void loadFaith(const std::pair<long long, std::shared_ptr<Faith>>& theFaith) { faith = theFaith; } - void setDeJureHRE() { deJureHRE = true; } - - private: - void registerKeys(); - - int development = 0; - std::pair<long long, std::shared_ptr<Culture>> culture; - std::pair<long long, std::shared_ptr<Faith>> faith; - bool deJureHRE = false; -}; -} // namespace CK3 - -#endif // CK3_COUNTYDETAIL_H diff --git a/CK3ToEU4/Source/CK3World/Religions/Faith.cpp b/CK3ToEU4/Source/CK3World/Religions/Faith.cpp deleted file mode 100644 index 7a5a68df..00000000 --- a/CK3ToEU4/Source/CK3World/Religions/Faith.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "Faith.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -CK3::Faith::Faith(std::istream& theStream, long long theID): ID(theID) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::Faith::registerKeys() -{ - registerKeyword("tag", [this](const std::string& unused, std::istream& theStream) { - tag = commonItems::singleString(theStream).getString(); - }); - registerKeyword("doctrine", [this](const std::string& unused, std::istream& theStream) { - doctrines.emplace_back(commonItems::singleString(theStream).getString()); - }); - registerKeyword("religion", [this](const std::string& unused, std::istream& theStream) { - religion = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - }); - registerKeyword("color", [this](const std::string& unused, std::istream& theStream) { - color = laFabricaDeColor.getColor(theStream); - }); - registerKeyword("template", [this](const std::string& unused, std::istream& theStream) { - religionTemplate = commonItems::singleString(theStream).getString(); - }); - registerKeyword("name", [this](const std::string& unused, std::istream& theStream) { - customName = commonItems::singleString(theStream).getString(); - }); - registerKeyword("adjective", [this](const std::string& unused, std::istream& theStream) { - customAdjective = commonItems::singleString(theStream).getString(); - }); - registerKeyword("religious_head", [this](const std::string& unused, std::istream& theStream) { - religiousHead = commonItems::singleString(theStream).getString(); - }); - registerKeyword("desc", [this](const std::string& unused, std::istream& theStream) { - description = commonItems::singleString(theStream).getString(); - }); - registerKeyword("icon", [this](const std::string& unused, std::istream& theStream) { - iconPath = commonItems::singleString(theStream).getString(); - }); - registerKeyword("variables", [this](const std::string& unused, std::istream& theStream) { - if (commonItems::stringOfItem(theStream).getString().find("has_been_reformed") != std::string::npos) - reformedFlag = true; - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} diff --git a/CK3ToEU4/Source/CK3World/Religions/Faith.h b/CK3ToEU4/Source/CK3World/Religions/Faith.h deleted file mode 100644 index e3634e6b..00000000 --- a/CK3ToEU4/Source/CK3World/Religions/Faith.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef CK3_FAITH_H -#define CK3_FAITH_H -#include "Color.h" -#include "Parser.h" -#include <set> - -extern commonItems::Color::Factory laFabricaDeColor; - -namespace CK3 -{ -class Religion; -class Faith: commonItems::parser -{ - public: - Faith() = default; - Faith(std::istream& theStream, long long theID); - - [[nodiscard]] const auto& getName() const { return tag; } - [[nodiscard]] const auto& getColor() const { return color; } - [[nodiscard]] const auto& getDoctrines() const { return doctrines; } - [[nodiscard]] const auto& getReligion() const { return religion; } - [[nodiscard]] const auto& getReligiousHead() const { return religiousHead; } - [[nodiscard]] auto getID() const { return ID; } - [[nodiscard]] const auto& getCustomName() const { return customName; } - [[nodiscard]] const auto& getCustomAdj() const { return customAdjective; } - [[nodiscard]] const auto& getDescription() const { return description; } - [[nodiscard]] const auto& getTemplate() const { return religionTemplate; } - [[nodiscard]] const auto& getIconPath() const { return iconPath; } - [[nodiscard]] const auto& getReformedFlag() const { return reformedFlag; } - - void setReligiousHead(const auto& newHead) { religiousHead = newHead; } - void loadReligion(const std::pair<long long, std::shared_ptr<Religion>>& theReligion) { religion = theReligion; } - - private: - void registerKeys(); - - bool reformedFlag = false; - long long ID = 0; - std::string tag; - std::string religionTemplate; - std::string iconPath; - std::string customName; - std::string customAdjective; - std::string description; - std::string religiousHead; - std::optional<commonItems::Color> color; - std::vector<std::string> - doctrines; // This is a vector in order to keep order consistent. We want the first things read (tenets) to be the first things output, ALWAYS - std::pair<long long, std::shared_ptr<Religion>> religion; -}; -} // namespace CK3 - -#endif // CK3_FAITH_H diff --git a/CK3ToEU4/Source/CK3World/Religions/Faiths.cpp b/CK3ToEU4/Source/CK3World/Religions/Faiths.cpp deleted file mode 100644 index ff0b71e9..00000000 --- a/CK3ToEU4/Source/CK3World/Religions/Faiths.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "Faiths.h" -#include "CommonRegexes.h" -#include "Faith.h" -#include "Log.h" -#include "ParserHelpers.h" -#include "Religions.h" - -CK3::Faiths::Faiths(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::Faiths::registerKeys() -{ - registerRegex(R"(\d+)", [this](const std::string& faithID, std::istream& theStream) { - auto newFaith = std::make_shared<Faith>(theStream, std::stoll(faithID)); - faiths.insert(std::pair(newFaith->getID(), newFaith)); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - -void CK3::Faiths::linkReligions(const Religions& religions, const Titles& titles) -{ - auto counter = 0; - const auto& religionData = religions.getReligions(); - std::map<std::string, std::string> religiousHeadList; // ID, Title - for (const auto& title: titles.getTitles()) - if (title.second) - religiousHeadList.emplace(std::to_string(title.second->getID()), title.first); - for (const auto& faith: faiths) - { - const auto& religionDataItr = religionData.find(faith.second->getReligion().first); - if (religionDataItr != religionData.end()) - { - faith.second->loadReligion(*religionDataItr); - if (religiousHeadList.contains(faith.second->getReligiousHead())) - faith.second->setReligiousHead(religiousHeadList.at(faith.second->getReligiousHead())); - ++counter; - } - else - { - throw std::runtime_error( - "Faith " + faith.second->getName() + " has religion " + std::to_string(faith.second->getReligion().first) + " which has no definition!"); - } - } - Log(LogLevel::Info) << "<> " << counter << " faiths updated."; -} \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3World/Religions/Faiths.h b/CK3ToEU4/Source/CK3World/Religions/Faiths.h deleted file mode 100644 index 6d5daee1..00000000 --- a/CK3ToEU4/Source/CK3World/Religions/Faiths.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef CK3_FAITHS_H -#define CK3_FAITHS_H -#include "../Titles/LandedTitles.h" -#include "../Titles/Title.h" -#include "../Titles/Titles.h" -#include "Parser.h" - -namespace CK3 -{ -class Faith; -class Religions; -class Faiths: commonItems::parser -{ - public: - Faiths() = default; - explicit Faiths(std::istream& theStream); - - [[nodiscard]] const auto& getFaiths() const { return faiths; } - - void linkReligions(const Religions& religions, const Titles& titles); - - private: - void registerKeys(); - - std::map<long long, std::shared_ptr<Faith>> faiths; -}; -} // namespace CK3 - -#endif // CK3_FAITHS_H diff --git a/CK3ToEU4/Source/CK3World/Religions/Religion.cpp b/CK3ToEU4/Source/CK3World/Religions/Religion.cpp deleted file mode 100644 index 114fe290..00000000 --- a/CK3ToEU4/Source/CK3World/Religions/Religion.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "Religion.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -CK3::Religion::Religion(std::istream& theStream, long long theID): ID(theID) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::Religion::registerKeys() -{ - registerKeyword("tag", [this](const std::string& unused, std::istream& theStream) { - tag = commonItems::singleString(theStream).getString(); - }); - registerKeyword("family", [this](const std::string& unused, std::istream& theStream) { - family = commonItems::singleString(theStream).getString(); - }); - registerKeyword("faiths", [this](const std::string& unused, std::istream& theStream) { - for (auto faith: commonItems::llongList(theStream).getLlongs()) - faiths.insert(std::pair(faith, nullptr)); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} diff --git a/CK3ToEU4/Source/CK3World/Religions/Religion.h b/CK3ToEU4/Source/CK3World/Religions/Religion.h deleted file mode 100644 index 8cf74710..00000000 --- a/CK3ToEU4/Source/CK3World/Religions/Religion.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef CK3_RELIGION_H -#define CK3_RELIGION_H -#include "Parser.h" - -namespace CK3 -{ -class Faith; -class Religion: commonItems::parser -{ - public: - Religion() = default; - Religion(std::istream& theStream, long long theID); - - [[nodiscard]] auto getID() const { return ID; } - [[nodiscard]] const auto& getName() const { return tag; } - [[nodiscard]] const auto& getFamily() const { return family; } - [[nodiscard]] const auto& getFaiths() const { return faiths; } - - void loadFaiths(const std::map<long long, std::shared_ptr<Faith>>& theFaiths) { faiths = theFaiths; } - - private: - void registerKeys(); - - long long ID = 0; - std::string tag; - std::string family; - std::map<long long, std::shared_ptr<Faith>> faiths; -}; -} // namespace CK3 - -#endif // CK3_RELIGION_H diff --git a/CK3ToEU4/Source/CK3World/Religions/Religions.cpp b/CK3ToEU4/Source/CK3World/Religions/Religions.cpp deleted file mode 100644 index 371797c2..00000000 --- a/CK3ToEU4/Source/CK3World/Religions/Religions.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "Religions.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" -#include "Religion.h" - -CK3::Religions::Religions(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::Religions::registerKeys() -{ - registerRegex(R"(\d+)", [this](const std::string& faithID, std::istream& theStream) { - auto newReligion = std::make_shared<Religion>(theStream, std::stoll(faithID)); - religions.insert(std::pair(newReligion->getID(), newReligion)); - }); - registerKeyword("religions", [this](const std::string& unused, std::istream& theStream) { - religions = Religions(theStream).getReligions(); - }); - registerKeyword("faiths", [this](const std::string& unused, std::istream& theStream) { - faiths = Faiths(theStream); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - -void CK3::Religions::linkFaiths(const Faiths& theFaiths) -{ - auto counter = 0; - const auto& faithData = theFaiths.getFaiths(); - for (const auto& religion: religions) - { - const auto& religionFaiths = religion.second->getFaiths(); - std::map<long long, std::shared_ptr<Faith>> replacementMap; - - for (const auto& faith: religionFaiths) - { - const auto& faithDataItr = faithData.find(faith.first); - if (faithDataItr != faithData.end()) - { - replacementMap.insert(*faithDataItr); - } - else - { - throw std::runtime_error("Religion " + religion.second->getName() + " has faith " + std::to_string(faith.first) + " which has no definition!"); - } - } - religion.second->loadFaiths(replacementMap); - ++counter; - } - Log(LogLevel::Info) << "<> " << counter << " religions updated."; -} diff --git a/CK3ToEU4/Source/CK3World/Religions/Religions.h b/CK3ToEU4/Source/CK3World/Religions/Religions.h deleted file mode 100644 index 2c3158d6..00000000 --- a/CK3ToEU4/Source/CK3World/Religions/Religions.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef CK3_RELIGIONS_H -#define CK3_RELIGIONS_H -#include "Faiths.h" -#include "Parser.h" - -namespace CK3 -{ -class Religion; -class Religions: commonItems::parser -{ - public: - Religions() = default; - explicit Religions(std::istream& theStream); - - [[nodiscard]] const auto& getReligions() const { return religions; } - [[nodiscard]] auto getFaiths() { return std::move(faiths); } // Use this only once in World.cpp - - void linkFaiths(const Faiths& theFaiths); - - private: - void registerKeys(); - - std::map<long long, std::shared_ptr<Religion>> religions; - Faiths faiths; -}; -} // namespace CK3 - -#endif // CK3_RELIGIONS_H diff --git a/CK3ToEU4/Source/CK3World/Titles/DynamicTemplate.cpp b/CK3ToEU4/Source/CK3World/Titles/DynamicTemplate.cpp deleted file mode 100644 index 62edba0e..00000000 --- a/CK3ToEU4/Source/CK3World/Titles/DynamicTemplate.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "DynamicTemplate.h" -#include "CommonRegexes.h" -#include "ParserHelpers.h" - -CK3::DynamicTemplate::DynamicTemplate(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::DynamicTemplate::registerKeys() -{ - registerKeyword("key", [this](const std::string& unused, std::istream& theStream) { - dynamicKey = commonItems::singleString(theStream).getString(); - }); - registerKeyword("tier", [this](const std::string& unused, std::istream& theStream) { - dynamicRank = commonItems::singleString(theStream).getString(); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} diff --git a/CK3ToEU4/Source/CK3World/Titles/DynamicTemplate.h b/CK3ToEU4/Source/CK3World/Titles/DynamicTemplate.h deleted file mode 100644 index 02c2c2cb..00000000 --- a/CK3ToEU4/Source/CK3World/Titles/DynamicTemplate.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef CK3_DYNAMICTEMPLATE_H -#define CK3_DYNAMICTEMPLATE_H -#include "Parser.h" - -namespace CK3 -{ -class DynamicTemplate: commonItems::parser -{ - public: - explicit DynamicTemplate(std::istream& theStream); - - [[nodiscard]] const auto& getDynamicTitleKey() const { return dynamicKey; } - [[nodiscard]] const auto& getDynamicTitleRank() const { return dynamicRank; } - - private: - void registerKeys(); - - std::string dynamicKey; - std::string dynamicRank; -}; -} // namespace CK3 - -#endif // CK3_DYNAMICTEMPLATE_H diff --git a/CK3ToEU4/Source/CK3World/Titles/LandedTitles.cpp b/CK3ToEU4/Source/CK3World/Titles/LandedTitles.cpp deleted file mode 100644 index a2a90bac..00000000 --- a/CK3ToEU4/Source/CK3World/Titles/LandedTitles.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "LandedTitles.h" -#include "../Geography/CountyDetails.h" -#include "../Geography/ProvinceHoldings.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" -#include "Title.h" -#include "Titles.h" - -// This is a recursive class that scrapes 00_landed_titles.txt (and related files) looking for title colors, landlessness, -// and most importantly relation between baronies and barony provinces so we can link titles to actual clay. -// Since titles are nested according to hierarchy we do this recursively. - -// Keep in mind that we use this class as middleware between titles and hard geographical data. Baronies and Counties have said data, -// but newfangled custom empires and such found in Titles will not be present here. They should have colors defined in their Title block -// anyway, and whatever relates to Title over there takes precedence over data in this class. - -void CK3::LandedTitles::loadTitles(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::LandedTitles::loadTitles(const std::string& fileName) -{ - registerKeys(); - parseFile(fileName); - clearRegisteredKeywords(); -} - -void CK3::LandedTitles::registerKeys() -{ - registerRegex(R"((e|k|d|c|b)_[A-Za-z0-9_\-\']+)", [this](const std::string& titleName, std::istream& theStream) { - // Pull the titles beneath this one and add them to the lot, overwriting existing ones. - auto newTitle = std::make_shared<LandedTitles>(); - newTitle->loadTitles(theStream); - for (const auto& locatedTitle: newTitle->getFoundTitles()) - foundTitles[locatedTitle.first] = locatedTitle.second; - - // And then add this one as well, overwriting existing. - foundTitles[titleName] = newTitle; - }); - registerKeyword("definite_form", [this](const std::string& unused, std::istream& theStream) { - definiteForm = commonItems::singleString(theStream).getString() == "yes"; - }); - registerKeyword("landless", [this](const std::string& unused, std::istream& theStream) { - landless = commonItems::singleString(theStream).getString() == "yes"; - }); - registerKeyword("color", [this](const std::string& unused, std::istream& theStream) { - color = laFabricaDeColor.getColor(theStream); - }); - registerKeyword("capital", [this](const std::string& unused, std::istream& theStream) { - capital = std::make_pair(commonItems::singleString(theStream).getString(), nullptr); - }); - registerKeyword("province", [this](const std::string& unused, std::istream& theStream) { - province = std::make_pair(commonItems::singleInt(theStream).getInt(), nullptr); - }); - registerKeyword("can_be_named_after_dynasty", [this](const std::string& unused, std::istream& theStream) { - mayBeNamedAfterDynasty = commonItems::singleString(theStream).getString() == "yes"; - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - -void CK3::LandedTitles::linkProvinceHoldings(const ProvinceHoldings& provinceHoldings) -{ - // We're linking provinces into BARONY titles only, as other titles have no holding data. - auto counter = 0; - const auto& provinceData = provinceHoldings.getProvinceHoldings(); - for (const auto& landedTitle: foundTitles) - { - if (landedTitle.first.find("b_") != 0) - continue; - if (!landedTitle.second->getProvince()) - throw std::runtime_error("Landed title " + landedTitle.first + " has not province holding defined!"); - - const auto& provinceDataItr = provinceData.find(landedTitle.second->getProvince()->first); - if (provinceDataItr != provinceData.end()) - { - landedTitle.second->loadProvinceHolding(*provinceDataItr); - ++counter; - } - else - { - throw std::runtime_error("Landed title " + landedTitle.first + " has province holding " + std::to_string(landedTitle.second->getProvince()->first) + - " which has no definition!"); - } - } - Log(LogLevel::Info) << "<> " << counter << " landed titles updated."; -} - -void CK3::LandedTitles::linkCountyDetails(const CountyDetails& countyDetails) -{ - // We're linking county details into COUNTY titles only, as other titles have no such details. - auto counter = 0; - const auto& countyData = countyDetails.getCountyDetails(); - for (const auto& landedTitle: foundTitles) - { - if (landedTitle.first.find("c_") != 0) - continue; - const auto& countyDataItr = countyData.find(landedTitle.first); - if (countyDataItr != countyData.end()) - { - landedTitle.second->loadCountyDetails(*countyDataItr); - ++counter; - } - else - { - // Nothing. People with missing titles from mods and whatnot can have holes on their map. - Log(LogLevel::Warning) << "Landed title " << landedTitle.first << " has no definition in counties={} section of the save game!"; - } - } - Log(LogLevel::Info) << "<> " << counter << " landed titles updated."; -} - -void CK3::LandedTitles::linkTitles(const Titles& titles) -{ - auto counter = 0; - const auto& titleData = titles.getTitles(); - for (const auto& landedTitle: foundTitles) - { - const auto& theCapital = landedTitle.second->getCapital(); - if (!theCapital) - continue; - if (const auto& titleDataItr = titleData.find(theCapital->first); titleDataItr != titleData.end()) - { - landedTitle.second->loadCapital(*titleDataItr); - ++counter; - } - else - { - Log(LogLevel::Error) << "Landed title " + landedTitle.first + " has a capital " + theCapital->first + " which has no definition!"; - } - } - Log(LogLevel::Info) << "<> " << counter << " landed title capitals updated."; -} diff --git a/CK3ToEU4/Source/CK3World/Titles/LandedTitles.h b/CK3ToEU4/Source/CK3World/Titles/LandedTitles.h deleted file mode 100644 index 206baaf8..00000000 --- a/CK3ToEU4/Source/CK3World/Titles/LandedTitles.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef CK3_LANDEDTITLES_H -#define CK3_LANDEDTITLES_H -#include "Color.h" -#include "Parser.h" -extern commonItems::Color::Factory laFabricaDeColor; - -namespace CK3 -{ -class Title; -class Titles; -class ProvinceHolding; -class ProvinceHoldings; -class CountyDetails; -class CountyDetail; -class LandedTitles: commonItems::parser -{ - public: - void loadTitles(std::istream& theStream); - void loadTitles(const std::string& fileName); - - [[nodiscard]] auto isDefiniteForm() const { return definiteForm; } - [[nodiscard]] auto isLandless() const { return landless; } - [[nodiscard]] auto canBeNamedAfterDynasty() const { return mayBeNamedAfterDynasty; } - [[nodiscard]] const auto& getColor() const { return color; } - [[nodiscard]] const auto& getCapital() const { return capital; } - [[nodiscard]] const auto& getProvince() const { return province; } - [[nodiscard]] const auto& getCounty() const { return county; } - [[nodiscard]] const auto& getFoundTitles() const { return foundTitles; } - - void loadProvinceHolding(const std::pair<int, std::shared_ptr<ProvinceHolding>>& provinceHolding) { province = provinceHolding; } - void loadCountyDetails(const std::pair<std::string, std::shared_ptr<CountyDetail>>& countyDetail) { county = countyDetail; } - void loadCapital(const std::pair<std::string, std::shared_ptr<Title>>& theCapital) { capital = theCapital; } - - void linkProvinceHoldings(const ProvinceHoldings& provinceHoldings); - void linkCountyDetails(const CountyDetails& countyDetails); - void linkTitles(const Titles& titles); - - private: - void registerKeys(); - - bool definiteForm = false; - bool landless = false; - bool mayBeNamedAfterDynasty = true; - std::optional<commonItems::Color> color; - - // This is of questionable use as savegame already defines defacto capitals. Not always present, and if present then a COUNTY. - std::optional<std::pair<std::string, std::shared_ptr<Title>>> capital; - - // only b_baronies have these - holdings are related to individual provinces on map. - std::optional<std::pair<int, std::shared_ptr<ProvinceHolding>>> province; - - // only c_counties have these - these define common data for group of baronies under county. - std::optional<std::pair<std::string, std::shared_ptr<CountyDetail>>> county; - - // We're using title name, not savegame ID for key value. - std::map<std::string, std::shared_ptr<LandedTitles>> foundTitles; -}; -} // namespace CK3 - -#endif // CK3_TITLES_H diff --git a/CK3ToEU4/Source/CK3World/Titles/Title.cpp b/CK3ToEU4/Source/CK3World/Titles/Title.cpp deleted file mode 100644 index fd600aa7..00000000 --- a/CK3ToEU4/Source/CK3World/Titles/Title.cpp +++ /dev/null @@ -1,518 +0,0 @@ -#include "Title.h" -#include "../../Mappers/DevWeightsMapper/DevWeightsMapper.h" -#include "../Characters/Character.h" -#include "../Geography/CountyDetail.h" -#include "../Geography/ProvinceHolding.h" -#include "CommonRegexes.h" -#include "LandedTitles.h" -#include "Log.h" -#include "ParserHelpers.h" - -CK3::Title::Title(std::istream& theStream, long long theID): ID(theID) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); - - // Obligatory sanity check. - if (!holder) - { - // This title does NOT in fact exist. - dfLiege.reset(); - } -} - -void CK3::Title::registerKeys() -{ - registerKeyword("key", [this](const std::string& unused, std::istream& theStream) { - name = commonItems::singleString(theStream).getString(); - }); - registerKeyword("name", [this](const std::string& unused, std::istream& theStream) { - displayName = commonItems::singleString(theStream).getString(); - if (displayName.find("\x15") != std::string::npos) - { - cleanUpDisplayName(); - } - }); - registerKeyword("adj", [this](const std::string& unused, std::istream& theStream) { - adjective = commonItems::singleString(theStream).getString(); - }); - registerKeyword("date", [this](const std::string& unused, std::istream& theStream) { - creationDate = date(commonItems::singleString(theStream).getString()); - }); - registerKeyword("claim", [this](const std::string& unused, std::istream& theStream) { - for (auto claimantID: commonItems::llongList(theStream).getLlongs()) - claimants.insert(std::make_pair(claimantID, nullptr)); - }); - registerKeyword("history_government", [this](const std::string& unused, std::istream& theStream) { - historyGovernment = commonItems::singleString(theStream).getString(); - }); - registerKeyword("theocratic_lease", [this](const std::string& unused, std::istream& theStream) { - theocraticLease = commonItems::singleString(theStream).getString() == "yes"; - }); - registerKeyword("capital_barony", [this](const std::string& unused, std::istream& theStream) { - cCapitalBarony = commonItems::singleString(theStream).getString() == "yes"; - }); - registerKeyword("duchy_capital_barony", [this](const std::string& unused, std::istream& theStream) { - dCapitalBarony = commonItems::singleString(theStream).getString() == "yes"; - }); - registerKeyword("capital", [this](const std::string& unused, std::istream& theStream) { - capital = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - }); - registerKeyword("de_facto_liege", [this](const std::string& unused, std::istream& theStream) { - dfLiege = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - }); - registerKeyword("de_jure_liege", [this](const std::string& unused, std::istream& theStream) { - djLiege = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - }); - registerKeyword("de_jure_vassals", [this](const std::string& unused, std::istream& theStream) { - for (auto vassalID: commonItems::llongList(theStream).getLlongs()) - djVassals.insert(std::make_pair(vassalID, nullptr)); - }); - registerKeyword("heir", [this](const std::string& unused, std::istream& theStream) { - for (auto heirID: commonItems::llongList(theStream).getLlongs()) - heirs.emplace_back(std::make_pair(heirID, nullptr)); - }); - registerKeyword("laws", [this](const std::string& unused, std::istream& theStream) { - const auto& theLaws = commonItems::stringList(theStream).getStrings(); - laws = std::set(theLaws.begin(), theLaws.end()); - }); - registerKeyword("holder", [this](const std::string& unused, std::istream& theStream) { - holder = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - }); - registerKeyword("renamed", [this](std::istream& theStream) { - renamed = commonItems::getString(theStream) == "yes"; - }); - registerKeyword("coat_of_arms_id", [this](const std::string& unused, std::istream& theStream) { - coa = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - }); - registerKeyword("succession_election", [this](const std::string& unused, std::istream& theStream) { - const auto newTitle = Title(theStream, 0); - electors = newTitle.getElectors(); - }); - registerKeyword("electors", [this](const std::string& unused, std::istream& theStream) { - for (auto electorID: commonItems::intList(theStream).getInts()) - electors.insert(std::pair(electorID, nullptr)); - }); - registerKeyword("landless", [this](const std::string& unused, std::istream& theStream) { - landless = commonItems::singleString(theStream).getString() == "yes"; - }); - registerKeyword("color", [this](const std::string& unused, std::istream& theStream) { - color = laFabricaDeColor.getColor(theStream); - }); - registerKeyword("history", [this](const std::string& unused, std::istream& theStream) { - previousHolders = Title(theStream, 0).getPreviousHolders(); - }); - registerRegex(R"(\d+.\d+.\d+)", [this](const std::string& unused, std::istream& theStream) { - const auto questionableItem = commonItems::stringOfItem(theStream).getString(); - auto tempStream = std::stringstream(questionableItem); - if (questionableItem.find('{') == std::string::npos) - { - try - { - previousHolders.emplace_back(std::pair(commonItems::singleLlong(tempStream).getLlong(), nullptr)); - } - catch (std::exception&) - { - Log(LogLevel::Warning) << "Invalid previous holder ID: " << questionableItem; - } - } - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - -void CK3::Title::cleanUpDisplayName() -{ - auto start = displayName.find('\x15'); - auto silence = false; - auto silenceOverRide = false; - auto braceDepth = 0; - std::string newName; - while (start != std::string::npos) - { - if ((!silence || silenceOverRide) && start != 0) - { - newName += displayName.substr(0, start); - displayName = displayName.substr(start, displayName.length()); - silence = true; - silenceOverRide = false; - start = displayName.find('\x15'); - } - else if (displayName.at(start + 1) == 'L') - { - if (displayName.length() >= start + 3) - displayName = displayName.substr(start + 3, displayName.length()); - else - break; - silence = true; - silenceOverRide = true; - braceDepth++; - start = displayName.find('\x15'); - } - else if (displayName.at(start + 1) == '!') - { - if (displayName.length() >= start + 2) - displayName = displayName.substr(start + 2, displayName.length()); - else - break; - braceDepth--; - if (braceDepth <= 0) - { - silence = false; - braceDepth = 0; - } - silenceOverRide = false; - start = displayName.find('\x15'); - } - else - { - silence = true; - silenceOverRide = false; - if (displayName.length() >= start + 1) - displayName = displayName.substr(start + 1, displayName.length()); - else - break; - braceDepth++; - start = displayName.find('\x15'); - } - } - displayName = newName; -} - -int CK3::Title::flagDeJureHREProvinces() -{ - auto counter = 0; - // For CK3 flagging dejure alone is not enough as we'll be losing a ton of land when duchies break away in full independence. - // Flag our dejure AND defacto counties, or our dejure/defacto vassals' counties, wherever those may be. - // Actual flagging will happen on county level as higher titles have no dejure provinces linked to them at this stage. - // We're leaving baronies out of this, counties are sufficient. - for (const auto& deJureVassal: djVassals) - { - counter += deJureVassal.second->flagDeJureHREProvinces(); - } - for (const auto& deFactoVassal: dfVassals) - { - counter += deFactoVassal.second->flagDeJureHREProvinces(); - } - if (!clay) // We really need the county clay to confirm we're a landful proper county. - return counter; - if (!clay->getCounty() || getLevel() != LEVEL::COUNTY) - return counter; - - clay->getCounty()->second->setDeJureHRE(); - ++counter; - - return counter; -} - -void CK3::Title::brickTitle() -{ - grantIndependence(); - - // Drop from own holder's domain. - if (holder && holder->second) - holder->second->dropTitleFromDomain(ID); - else - Log(LogLevel::Warning) << "Bricking " << name << " without holder!"; - - // Drop holder - holder.reset(); - - // release all vassals - std::vector<std::shared_ptr<Title>> independentList; - for (const auto& vassal: dfVassals) - if (vassal.second) - independentList.emplace_back(vassal.second); - else - Log(LogLevel::Warning) << "Granting independence to " << vassal.first << " that's not linked!"; - - for (const auto& independentVassal: independentList) - independentVassal->grantIndependence(); - - dfVassals.clear(); // just in case? -} - -void CK3::Title::dropTitleFromDFVassals(long long titleID) -{ - const auto& dfvItr = dfVassals.find(titleID); - if (dfvItr != dfVassals.end()) - dfVassals.erase(dfvItr); - else - Log(LogLevel::Warning) << "dropping vassal " << titleID << " that doesn't exist!"; -} - -void CK3::Title::grantIndependence() -{ - // Drop this title from liege holder's vassals - if (dfLiege && dfLiege->second) - dfLiege->second->dropTitleFromDFVassals(ID); - - // Drop liege - dfLiege.reset(); -} - -std::map<std::string, std::shared_ptr<CK3::Title>> CK3::Title::coalesceDFCounties() const -{ - // We're gathering vassal's counties + self (if c_), and passing them on, adding nothing to ourselves. - std::map<std::string, std::shared_ptr<Title>> toReturn; - for (const auto& vassal: dfVassals) - { - const auto& vassalCounties = vassal.second->coalesceDFCounties(); - toReturn.insert(vassalCounties.begin(), vassalCounties.end()); - } - toReturn.insert(ownedDFCounties.begin(), ownedDFCounties.end()); - return toReturn; -} - -std::map<std::string, std::shared_ptr<CK3::Title>> CK3::Title::coalesceDJCounties() const -{ - // We're gathering vassal dejure provinces + our own, and passing them on, adding nothing to ourselves. - std::map<std::string, std::shared_ptr<Title>> toReturn; - for (const auto& deJureVassal: djVassals) - { - const auto& vassalDJCounties = deJureVassal.second->coalesceDJCounties(); - toReturn.insert(vassalDJCounties.begin(), vassalDJCounties.end()); - } - toReturn.insert(ownedDJCounties.begin(), ownedDJCounties.end()); - return toReturn; -} - -void CK3::Title::pickDisplayName(const std::map<std::string, std::shared_ptr<Title>>& possibleTitles) -{ - // Guard clause all used pointers - if (!isRenamed()) - return; - - // Duchy capital ptrs are all null_ptr, outsource fixing and validation - const auto myDuchyCapital = findDuchyCapital(); - - if (!myDuchyCapital || myDuchyCapital->getID() == getID() || !myDuchyCapital->getDFLiege() || !getDFLiege()) - return; - - // If the title's name is transfering to EU4, make sure it makes sense. Thrace should use Constantinople's name... - // ... if they belong to the same owner, Constantinople also has a custom name and they are in the same mapping - if (myDuchyCapital->isRenamed() && possibleTitles.contains(myDuchyCapital->getName()) && myDuchyCapital->getDFLiege()->first == getDFLiege()->first) - { - displayName = myDuchyCapital->getDisplayName(); - } -} - -std::shared_ptr<CK3::Title> CK3::Title::findDuchyCapital() -{ - if (name[0] != 'c' || !getDJLiege() || !getDJLiege()->second) - return nullptr; - - const auto myDuchy = getDJLiege()->second; - const auto& capID = myDuchy->getCapital().first; - - if (myDuchy->getDJVassals().empty() || !myDuchy->getDJVassals().contains(capID) || !myDuchy->getDJVassals().at(capID)) - return nullptr; - - return myDuchy->getDJVassals().at(capID); -} - -void CK3::Title::congregateDFCounties() -{ - // We're gathering vassal counties and adding to our own. - for (const auto& vassal: dfVassals) - { - const auto& vassalDFCounties = vassal.second->coalesceDFCounties(); - ownedDFCounties.insert(vassalDFCounties.begin(), vassalDFCounties.end()); - } -} - -void CK3::Title::congregateDJCounties() -{ - // We're gathering de jure vassal de jure counties and adding to our own. - for (const auto& deJureVassal: djVassals) - { - const auto& deJureVassalDJCounties = deJureVassal.second->coalesceDJCounties(); - ownedDJCounties.insert(deJureVassalDJCounties.begin(), deJureVassalDJCounties.end()); - } -} - -CK3::LEVEL CK3::Title::getLevel() const -{ - // It's easy, until it's not. - if (name.find("b_") == 0) - return LEVEL::BARONY; - if (name.find("c_") == 0) - return LEVEL::COUNTY; - if (name.find("d_") == 0) - return LEVEL::DUCHY; - if (name.find("k_") == 0) - return LEVEL::KINGDOM; - if (name.find("e_") == 0) - return LEVEL::EMPIRE; - - // for dynamic tiles we may have a level set already. - if (dynamicLevel) - return *dynamicLevel; - - // If not... - // This is the questionable part. It should work for customs as they are treated identically as any other - with dejure parents and all. - // exceptions are dynamic mercs, landless religious orders and similar - but those don't hold land, at least initially. - - // see if they hold any vassals and if so, assign a level one step higher. - auto level = -1; - const std::set<char> allowedPrefixes = {'b', 'c', 'd', 'k'}; - for (const auto& vassal: djVassals) // run through all as they can vary in levels. - { - if (!allowedPrefixes.count(vassal.second->getName().at(0))) - continue; // Those dynamic vassals can't help us. Or heaven's forbid, it's an empire. - if (LevelToInt[vassal.second->getLevel()] > level) - level = LevelToInt[vassal.second->getLevel()] + 1; - } - if (level > -1) - return IntToLevel[std::max(level, 4)]; - - // Without vassals we must poke at our hierarchy, if any. - if (djLiege) - return IntToLevel[LevelToInt[djLiege->second->getLevel()] - 1]; - else - return LEVEL::EMPIRE; // If this is wrong for landless mercs, it won't affect anything as they are landless anyway. -} - -std::optional<commonItems::Color> CK3::Title::getColor() const -{ - if (color) - return color; - if (clay && clay->getColor()) - return clay->getColor(); - return std::nullopt; -} - -bool CK3::Title::isLandless() const -{ - if (landless) - return true; - if (clay && clay->isLandless()) - return true; - return false; -} - -double CK3::Title::getBuildingWeight(const mappers::DevWeightsMapper& devWeightsMapper) const -{ - if (getLevel() != LEVEL::COUNTY) // This applies to nothing but counties. - return 0; - - // buildingWeight is a mixture of all holdings, their potential buildings, and general county development. - if (!clay) - throw std::runtime_error("County " + name + " has no clay?"); - if (!clay->getCounty() || !clay->getCounty()->second) - throw std::runtime_error("County " + name + " has no county in its clay?"); - const auto development = clay->getCounty()->second->getDevelopment(); - auto buildingCount = 0; - auto holdingCount = 0; - - for (const auto& barony: djVassals) - { - if (!barony.second) - { - Log(LogLevel::Error) << "Running unlinked vassals, are we? " << std::to_string(barony.first) << " has no link."; - continue; - } - if (!barony.second->getClay()) - { - Log(LogLevel::Error) << "Supposed barony " << barony.second->getName() << " of " << name << " has no clay?"; - continue; - } - if (!barony.second->getClay()->getProvince() || !barony.second->getClay()->getProvince()->second) - { - Log(LogLevel::Error) << "Barony " << barony.second->getName() << " of " << name << " has no clay province?"; - continue; - } - const auto& baronyProvince = barony.second->getClay()->getProvince(); - buildingCount += baronyProvince->second->countBuildings(); - if (!baronyProvince->second->getHoldingType().empty()) - ++holdingCount; - } - - const auto totalDev = devWeightsMapper.getDevFromHolding() * holdingCount + devWeightsMapper.getDevFromBuilding() * buildingCount + - std::max(0.0, development - devWeightsMapper.getDevTreshold()) * devWeightsMapper.getDevFromDev(); - return totalDev; -} - -void CK3::Title::relinkDeFactoVassals() -{ - // We're reconstructing defacto hierarchy; we're redirecting our DFvassals from our DFtitle into our DJtitle - if holder of this title holds hold both. - // This is important - otherwise secondary titles wouldn't have their own vassals under them but under primary title, breaking PU splitoffs, - // and resulting with those secondary duchies/kingdoms being discarded as landless. - - if (name.starts_with("c_") || name.starts_with("b_")) - return; // don't bother with counties and below. - - std::set<long long> dropList; - - for (const auto& [dfVassalID, dfVassal]: dfVassals) - { - if (!dfVassal) - continue; - - if (dfVassal->areDFLiegeAndDJLiegeSet() && !dfVassal->areDFLiegeAndDJLiegeSame()) // We have different df and dj lieges there. - { - // Do we own both titles? - if (doesHolderHaveCharacterDomain()) - { - const auto holderTitles = holder->second->getCharacterDomain()->getDomain(); - - // Make a small cache of the holder's owned title names. - const auto titleNameCache = getTitleNamesFromHolderDomain(); - - if (titleNameCache.contains(dfVassal->getDFLiege()->second->getName()) && titleNameCache.contains(dfVassal->getDJLiege()->second->getName())) - { - // We do own both. Tell the vassal to relink its defacto owner to dejure title. - dfVassal->loadDFLiege(*dfVassal->getDJLiege()); - // Tell dejure title it's now owner of a brand new vassal. - dfVassal->getDJLiege()->second->addDFVassals(std::map{std::pair(dfVassalID, dfVassal)}); - // And finally... - dropList.insert(dfVassalID); - } - } - else - { - if (!isHolderSet()) - Log(LogLevel::Warning) << name << " has no holder but has vassals?"; - else if (!isHolderLinked()) - Log(LogLevel::Warning) << name << "'s holder is not linked up!"; - else - Log(LogLevel::Warning) << name << "' holder has no domain but has vassals?"; - } - } - } - - for (auto dropVassalID: dropList) - dropTitleFromDFVassals(dropVassalID); -} - -bool CK3::Title::areDFLiegeAndDJLiegeSet() const -{ - return dfLiege && djLiege; -} - -bool CK3::Title::areDFLiegeAndDJLiegeSame() const -{ - if (!areDFLiegeAndDJLiegeSet()) - return false; // Can't check if they're not set. - return dfLiege->first == djLiege->first; -} - -bool CK3::Title::doesHolderHaveCharacterDomain() const -{ - return isHolderSet() && isHolderLinked() && holder->second->getCharacterDomain(); -} - -std::set<std::string> CK3::Title::getTitleNamesFromHolderDomain() const -{ - std::set<std::string> toReturn; - if (!doesHolderHaveCharacterDomain()) - return toReturn; - - const auto holderTitles = holder->second->getCharacterDomain()->getDomain(); - - for (const auto& [domainTitleID, domainTitle]: holderTitles) - if (domainTitle) - toReturn.insert(domainTitle->getName()); - - return toReturn; -} diff --git a/CK3ToEU4/Source/CK3World/Titles/Title.h b/CK3ToEU4/Source/CK3World/Titles/Title.h deleted file mode 100644 index 51e0ed8c..00000000 --- a/CK3ToEU4/Source/CK3World/Titles/Title.h +++ /dev/null @@ -1,184 +0,0 @@ -#ifndef CK3_TITLE_H -#define CK3_TITLE_H -#include "Color.h" -#include "Date.h" -#include "Parser.h" -#include <set> - -namespace mappers -{ -class DevWeightsMapper; -} -namespace EU4 -{ -class Country; -} - -namespace CK3 -{ -class Character; -class CoatOfArms; -class LandedTitles; - -enum class LEVEL -{ - BARONY, - COUNTY, - DUCHY, - KINGDOM, - EMPIRE -}; - -static std::map<int, LEVEL> IntToLevel{{0, LEVEL::BARONY}, {1, LEVEL::COUNTY}, {2, LEVEL::DUCHY}, {3, LEVEL::KINGDOM}, {4, LEVEL::EMPIRE}}; -static std::map<LEVEL, int> LevelToInt{{LEVEL::BARONY, 0}, {LEVEL::COUNTY, 1}, {LEVEL::DUCHY, 2}, {LEVEL::KINGDOM, 3}, {LEVEL::EMPIRE, 4}}; - -class Title: commonItems::parser -{ - public: - Title(std::istream& theStream, long long theID); - [[nodiscard]] auto getID() const { return ID; } - [[nodiscard]] auto isTheocraticLease() const { return theocraticLease; } - [[nodiscard]] auto isCountyCapitalBarony() const { return cCapitalBarony; } - [[nodiscard]] auto isDuchyCapitalBarony() const { return dCapitalBarony; } - [[nodiscard]] auto isHREEmperor() const { return HREEmperor; } - [[nodiscard]] auto isInHRE() const { return inHRE; } - [[nodiscard]] auto isThePope() const { return thePope; } - [[nodiscard]] auto isElectorate() const { return electorate; } - [[nodiscard]] auto isHolderCapital() const { return holderCapital; } - [[nodiscard]] auto isHRECapital() const { return HRECapital; } - [[nodiscard]] auto isCustomTitle() const { return customTitle; } - [[nodiscard]] auto isRenamed() const { return renamed; } - [[nodiscard]] auto isManualNameClaimed() const { return nameClaimed; } - [[nodiscard]] const auto& getName() const { return name; } - [[nodiscard]] const auto& getDisplayName() const { return displayName; } - [[nodiscard]] const auto& getAdjective() const { return adjective; } - [[nodiscard]] const auto& getCreationDate() const { return creationDate; } - [[nodiscard]] const auto& getHistoryGovernment() const { return historyGovernment; } - [[nodiscard]] const auto& getCapital() const { return capital; } - [[nodiscard]] const auto& getDFLiege() const { return dfLiege; } - [[nodiscard]] const auto& getDJLiege() const { return djLiege; } - [[nodiscard]] const auto& getDFVassals() const { return dfVassals; } - [[nodiscard]] const auto& getDJVassals() const { return djVassals; } - [[nodiscard]] const auto& getHeirs() const { return heirs; } - [[nodiscard]] const auto& getClaimants() const { return claimants; } - [[nodiscard]] const auto& getElectors() const { return electors; } - [[nodiscard]] const auto& getLaws() const { return laws; } - [[nodiscard]] const auto& getHolder() const { return holder; } - [[nodiscard]] const auto& getCoA() const { return coa; } - [[nodiscard]] const auto& getClay() const { return clay; } - [[nodiscard]] const auto& getOwnedDFCounties() const { return ownedDFCounties; } - [[nodiscard]] const auto& getOwnedDJCounties() const { return ownedDJCounties; } - [[nodiscard]] const auto& getHoldingTitle() const { return holdingTitle; } - [[nodiscard]] const auto& getGeneratedLiege() const { return generatedLiege; } - [[nodiscard]] const auto& getGeneratedVassals() const { return generatedVassals; } - [[nodiscard]] const auto& getEU4Tag() const { return tagCountry; } - [[nodiscard]] const auto& getPreviousHolders() const { return previousHolders; } - - [[nodiscard]] std::optional<commonItems::Color> getColor() const; - [[nodiscard]] bool isLandless() const; - [[nodiscard]] bool areDFLiegeAndDJLiegeSet() const; - [[nodiscard]] bool areDFLiegeAndDJLiegeSame() const; - [[nodiscard]] bool isHolderSet() const { return holder != std::nullopt; } - [[nodiscard]] bool isHolderLinked() const { return holder && holder->second; } - [[nodiscard]] bool doesHolderHaveCharacterDomain() const; - [[nodiscard]] std::set<std::string> getTitleNamesFromHolderDomain() const; - [[nodiscard]] LEVEL getLevel() const; - - // linkage - void loadCoat(const std::pair<long long, std::shared_ptr<CoatOfArms>>& coat) { coa = coat; } - void loadDFLiege(const std::pair<long long, std::shared_ptr<Title>>& DFLiege) { dfLiege = DFLiege; } - void loadDJLiege(const std::pair<long long, std::shared_ptr<Title>>& DJLiege) { djLiege = DJLiege; } - void loadDFVassals(const std::map<long long, std::shared_ptr<Title>>& DFVassals) { dfVassals = DFVassals; } - void addDFVassals(const std::map<long long, std::shared_ptr<Title>>& DFVassals) { dfVassals.insert(DFVassals.begin(), DFVassals.end()); } - void loadDJVassals(const std::map<long long, std::shared_ptr<Title>>& DJVassals) { djVassals = DJVassals; } - void loadHolder(const std::pair<long long, std::shared_ptr<Character>>& theHolder) { holder = theHolder; } - void loadHeirs(const std::vector<std::pair<long long, std::shared_ptr<Character>>>& theHeirs) { heirs = theHeirs; } - void loadPreviousHolders(const std::vector<std::pair<long long, std::shared_ptr<Character>>>& theHolders) { previousHolders = theHolders; } - void loadClaimants(const std::map<long long, std::shared_ptr<Character>>& theClaimants) { claimants = theClaimants; } - void loadElectors(const std::map<long long, std::shared_ptr<Character>>& theElectors) { electors = theElectors; } - void loadClay(const std::shared_ptr<LandedTitles>& theClay) { clay = theClay; } - void loadOwnedDFCounties(const std::map<std::string, std::shared_ptr<Title>>& theOwnedCounties) { ownedDFCounties = theOwnedCounties; } - void loadOwnedDJCounties(const std::map<std::string, std::shared_ptr<Title>>& theOwnedCounties) { ownedDJCounties = theOwnedCounties; } - - // processing - void setDynamicLevel(LEVEL theLevel) { dynamicLevel = theLevel; } - void cleanUpDisplayName(); - [[nodiscard]] int flagDeJureHREProvinces(); - void brickTitle(); - void grantIndependence(); - void resetDFLiege() { dfLiege.reset(); } - void resetDJLiege() { djLiege.reset(); } - void setHREEmperor() { HREEmperor = true; } - void setInHRE() { inHRE = true; } - void dropTitleFromDFVassals(long long titleID); - void setThePope() { thePope = true; } - void setCustomTitle() { customTitle = true; } - void setManualNameClaim() { nameClaimed = true; } - void pickDisplayName(const std::map<std::string, std::shared_ptr<Title>>& possibleTitles); // Grants one county's name to another during N:1/N:M mappings - std::shared_ptr<Title> findDuchyCapital(); // Only for c_, for now - void congregateDFCounties(); - void congregateDJCounties(); - void loadGeneratedLiege(const std::pair<std::string, std::shared_ptr<Title>>& liege) { generatedLiege = liege; } - void addGeneratedVassal(const std::pair<std::string, std::shared_ptr<Title>>& theVassal) { generatedVassals.insert(theVassal); } - void loadHoldingTitle(const std::pair<std::string, std::shared_ptr<Title>>& theTitle) { holdingTitle = theTitle; } - void setElectorate() { electorate = true; } - void relinkDeFactoVassals(); - - // conversion - void loadEU4Tag(const std::pair<std::string, std::shared_ptr<EU4::Country>>& theCountry) { tagCountry = theCountry; } - [[nodiscard]] double getBuildingWeight(const mappers::DevWeightsMapper& devWeightsMapper) const; - void setHolderCapital() { holderCapital = true; } - void setHRECapital() { HRECapital = true; } - void clearGeneratedVassals() { generatedVassals.clear(); } - - [[nodiscard]] std::map<std::string, std::shared_ptr<Title>> coalesceDFCounties() const; - [[nodiscard]] std::map<std::string, std::shared_ptr<Title>> coalesceDJCounties() const; - - private: - void registerKeys(); - - long long ID = 0; // 11038 - std::pair<long long, std::shared_ptr<Title>> capital; // capital title is a COUNTY, even for county itself and baronies beneath it! - std::string name; // c_ashmaka - std::string displayName; // Ashmaka - std::string adjective; // Ashmakan - std::string article; // "the ". Not always present. - std::string historyGovernment; // Unclear why this is history. Maybe further governments override it. - date creationDate; // Unclear. Ranges to 9999.1.1, probably is PDX alternative for "bool isCreated"; - std::optional<std::pair<long long, std::shared_ptr<CoatOfArms>>> coa; // This is dejure flag but not defacto. - std::optional<std::pair<long long, std::shared_ptr<Title>>> dfLiege; // defacto liege title (d_kalyani) - std::optional<std::pair<long long, std::shared_ptr<Title>>> djLiege; // dejure liege title (d_rattapadi) - std::optional<std::pair<long long, std::shared_ptr<Character>>> holder; // Holding character - std::map<long long, std::shared_ptr<Title>> dfVassals; // defacto vassals, not in save, manually linked post-loading - std::map<long long, std::shared_ptr<Title>> djVassals; // dejure vassals (for all except baronies and titulars) - std::vector<std::pair<long long, std::shared_ptr<Character>>> heirs; // Order of heirs is unclear so we're keeping them ordered and using first if able. - std::map<long long, std::shared_ptr<Character>> claimants; // People holding a claim to this title. Incredibly useful. - std::map<long long, std::shared_ptr<Character>> electors; // People involved in elections regardless of election type law. - bool theocraticLease = false; // Does this apply to non-baronies? Maybe? Who owns it then, dejure liege? - std::set<std::string> laws; - bool cCapitalBarony = false; - bool dCapitalBarony = false; - std::shared_ptr<LandedTitles> clay; // Middleware towards geographical data, essential for b_&c_, potentially obsolete for others. - bool HREEmperor = false; - bool inHRE = false; - bool thePope = false; - bool customTitle = false; // True if title was fromed via "Found a New Kingdom/Empire" decision. Vestigal - bool renamed = false; // True if title was manually named - bool nameClaimed = false; // Flag for 1:M (or N:M) province mappings to decide who gets the manual name - std::map<std::string, std::shared_ptr<Title>> ownedDFCounties; // used to map higher-lvl titles directly to clay. Includes self! Every c_+ title has this. - std::map<std::string, std::shared_ptr<Title>> ownedDJCounties; // ditto - std::optional<std::pair<std::string, std::shared_ptr<Title>>> generatedLiege; // Liege we set manually while splitting vassals. - std::map<std::string, std::shared_ptr<Title>> generatedVassals; // Vassals we split off deliberately. - std::pair<std::string, std::shared_ptr<Title>> holdingTitle; // topmost owner title (e_francia or similar), only c_s have this. - bool electorate = false; - std::optional<std::pair<std::string, std::shared_ptr<EU4::Country>>> tagCountry; - bool landless = false; - std::optional<commonItems::Color> color; - std::vector<std::pair<long long, std::shared_ptr<Character>>> previousHolders; - bool holderCapital = false; - bool HRECapital = false; - std::optional<LEVEL> dynamicLevel; // Maybe assigned through dynamic ranks, otherwise getLevel will try to guesstimate. -}; -} // namespace CK3 - -#endif // CK3_TITLE_H diff --git a/CK3ToEU4/Source/CK3World/Titles/Titles.h b/CK3ToEU4/Source/CK3World/Titles/Titles.h deleted file mode 100644 index 95132b95..00000000 --- a/CK3ToEU4/Source/CK3World/Titles/Titles.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef CK3_TITLES_H -#define CK3_TITLES_H -#include "Parser.h" - -namespace CK3 -{ -class Title; -class CoatsOfArms; -class Characters; -class LandedTitles; -class Titles: commonItems::parser -{ - public: - Titles() = default; - explicit Titles(std::istream& theStream); - - [[nodiscard]] const auto& getTitles() const { return titles; } - [[nodiscard]] const auto& getCounter() const { return titleCounter; } - - void linkCoats(const CoatsOfArms& coats); - void linkTitles(); - void linkCharacters(const Characters& characters); - void linkLandedTitles(const LandedTitles& landedTitles); - void relinkDeFactoVassals(); - - private: - void registerKeys(); - void transcribeDynamicRanks(); - - std::vector<int> titleCounter = {0, 0, 0, 0, 0, 0}; - std::map<std::string, std::shared_ptr<Title>> titles; // We're using NAME, not ID for key value! - std::map<std::string, std::string> dynamicTitleRanks; -}; -} // namespace CK3 - -#endif // CK3_TITLES_H diff --git a/CK3ToEU4/Source/Configuration/Configuration.cpp b/CK3ToEU4/Source/Configuration/Configuration.cpp deleted file mode 100644 index 3bf61e2a..00000000 --- a/CK3ToEU4/Source/Configuration/Configuration.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "Configuration.h" -#include "Color.h" -#include "CommonFunctions.h" -#include "CommonRegexes.h" -#include "GameVersion.h" -#include "Log.h" -#include "OSCompatibilityLayer.h" -#include "ParserHelpers.h" -#include <fstream> -auto laFabricaDeColor = commonItems::Color::Factory(); - -Configuration::Configuration(const commonItems::ConverterVersion& converterVersion) -{ - Log(LogLevel::Info) << "Reading configuration file"; - registerKeys(); - parseFile("configuration.txt"); - clearRegisteredKeywords(); - setOutputName(); - verifyCK3Path(); - verifyCK3Version(converterVersion); - verifyEU4Path(); - verifyEU4Version(converterVersion); - Log(LogLevel::Progress) << "3 %"; -} - -Configuration::Configuration(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); - setOutputName(); -} - -void Configuration::registerKeys() -{ - registerKeyword("SaveGame", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString path(theStream); - SaveGamePath = path.getString(); - Log(LogLevel::Info) << "Save Game set to: " << SaveGamePath; - }); - registerKeyword("CK3directory", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString path(theStream); - CK3Path = path.getString(); - }); - registerKeyword("EU4directory", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString path(theStream); - EU4Path = path.getString(); - }); - registerKeyword("CK3DocDirectory", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString path(theStream); - CK3DocPath = path.getString(); - }); - registerKeyword("output_name", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString nameStr(theStream); - outputName = nameStr.getString(); - Log(LogLevel::Info) << "Output name set to: " << outputName; - }); - registerKeyword("start_date", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString startDateString(theStream); - startDate = STARTDATE(std::stoi(startDateString.getString())); - Log(LogLevel::Info) << "Start date set to: " << startDateString.getString(); - }); - registerKeyword("i_am_hre", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString hreString(theStream); - iAmHre = I_AM_HRE(std::stoi(hreString.getString())); - Log(LogLevel::Info) << "HRE set to: " << hreString.getString(); - }); - registerKeyword("dejure", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString dejureString(theStream); - dejure = DEJURE(std::stoi(dejureString.getString())); - Log(LogLevel::Info) << "DeJure set to: " << dejureString.getString(); - }); - registerKeyword("split_vassals", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString splitVassalsString(theStream); - splitVassals = SPLITVASSALS(std::stoi(splitVassalsString.getString())); - Log(LogLevel::Info) << "Split Vassals set to: " << splitVassalsString.getString(); - }); - registerKeyword("shatter_empires", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString shatterEmpiresString(theStream); - shatterEmpires = SHATTER_EMPIRES(std::stoi(shatterEmpiresString.getString())); - Log(LogLevel::Info) << "Shatter Empires set to: " << shatterEmpiresString.getString(); - }); - registerKeyword("shatter_level", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString shatterLevelString(theStream); - shatterLevel = SHATTER_LEVEL(std::stoi(shatterLevelString.getString())); - Log(LogLevel::Info) << "Shatter Level set to: " << shatterLevelString.getString(); - }); - registerKeyword("shatter_hre_level", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString shatterHRELevelString(theStream); - shatterHRELevel = SHATTER_HRE_LEVEL(std::stoi(shatterHRELevelString.getString())); - Log(LogLevel::Info) << "Shatter HRE Level set to: " << shatterHRELevelString.getString(); - }); - registerKeyword("siberia", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString siberiaString(theStream); - siberia = SIBERIA(std::stoi(siberiaString.getString())); - Log(LogLevel::Info) << "Siberia set to: " << siberiaString.getString(); - }); - registerKeyword("sunset", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString sunsetString(theStream); - sunset = SUNSET(std::stoi(sunsetString.getString())); - Log(LogLevel::Info) << "Sunset set to: " << sunsetString.getString(); - }); - registerKeyword("dynamicInstitutions", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString dynamicInstitutionsString(theStream); - dynamicInstitutions = INSTITUTIONS(std::stoi(dynamicInstitutionsString.getString())); - Log(LogLevel::Info) << "Dynamic Institutions set to: " << dynamicInstitutionsString.getString(); - }); - registerKeyword("development", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString developmentString(theStream); - development = DEVELOPMENT(std::stoi(developmentString.getString())); - Log(LogLevel::Info) << "Development set to: " << developmentString.getString(); - }); - registerKeyword("multiprovdevtransfer", [this](std::istream& theStream) { - const commonItems::singleString multiprovdevtransferString(theStream); - multiProvinceDevelopmentTransfer = MULTIPROVDEVTRANSFER(std::stoi(multiprovdevtransferString.getString())); - Log(LogLevel::Info) << "Multiple Province Dev Transfer set to: " << multiprovdevtransferString.getString(); - }); - registerKeyword("dynasticNames", [this](std::istream& theStream) { - const commonItems::singleString dynasticNamesString(theStream); - dynasticNames = DYNASTICNAMES(std::stoi(dynasticNamesString.getString())); - Log(LogLevel::Info) << "Dynastic Names set to: " << dynasticNamesString.getString(); - }); - registerKeyword("discoveredBy", [this](std::istream& theStream) { - const commonItems::singleString discoveredByString(theStream); - discoveredBy = DISCOVEREDBY(std::stoi(discoveredByString.getString())); - Log(LogLevel::Info) << "Discovered By set to: " << discoveredByString.getString(); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - -void Configuration::verifyCK3Path() -{ - if (!commonItems::DoesFolderExist(CK3Path)) - throw std::runtime_error(CK3Path + " does not exist!"); - // TODO: OSX and Linux paths are speculative - if (!commonItems::DoesFileExist(CK3Path + "/binaries/ck3.exe") && !commonItems::DoesFileExist(CK3Path + "/CK3game") && - !commonItems::DoesFileExist(CK3Path + "/binaries/ck3")) - throw std::runtime_error(CK3Path + " does not contain Crusader Kings 3!"); - if (!commonItems::DoesFileExist(CK3Path + "/game/map_data/positions.txt")) - throw std::runtime_error(CK3Path + " does not appear to be a valid CK3 install!"); - Log(LogLevel::Info) << "\tCK3 install path is " << CK3Path; - CK3Path += "/game/"; // We're adding "/game/" since all we ever need from now on is in that subdirectory. -} - -void Configuration::verifyEU4Path() const -{ - if (!commonItems::DoesFolderExist(EU4Path)) - throw std::runtime_error(EU4Path + " does not exist!"); - if (!commonItems::DoesFileExist(EU4Path + "/eu4.exe") && !commonItems::DoesFileExist(EU4Path + "/eu4")) - throw std::runtime_error(EU4Path + " does not contain Europa Universalis 4!"); - if (!commonItems::DoesFileExist(EU4Path + "/map/positions.txt")) - throw std::runtime_error(EU4Path + " does not appear to be a valid EU4 install!"); - Log(LogLevel::Info) << "\tEU4 install path is " << EU4Path; -} - -void Configuration::setOutputName() -{ - if (outputName.empty()) - { - outputName = trimPath(SaveGamePath); - } - outputName = trimExtension(outputName); - outputName = replaceCharacter(outputName, '-'); - outputName = replaceCharacter(outputName, ' '); - - outputName = commonItems::normalizeUTF8Path(outputName); - Log(LogLevel::Info) << "Using output name " << outputName; -} - -void Configuration::verifyCK3Version(const commonItems::ConverterVersion& converterVersion) const -{ - const auto CK3Version = GameVersion::extractVersionFromLauncher(CK3Path + "../launcher/launcher-settings.json"); - if (!CK3Version) - { - Log(LogLevel::Error) << "CK3 version could not be determined, proceeding blind!"; - return; - } - - Log(LogLevel::Info) << "CK3 version: " << CK3Version->toShortString(); - - if (converterVersion.getMinSource() > *CK3Version) - { - Log(LogLevel::Error) << "CK3 version is v" << CK3Version->toShortString() << ", converter requires minimum v" - << converterVersion.getMinSource().toShortString() << "!"; - throw std::runtime_error("Converter vs CK3 installation mismatch!"); - } - if (!converterVersion.getMaxSource().isLargerishThan(*CK3Version)) - { - Log(LogLevel::Error) << "CK3 version is v" << CK3Version->toShortString() << ", converter requires maximum v" - << converterVersion.getMaxSource().toShortString() << "!"; - throw std::runtime_error("Converter vs CK3 installation mismatch!"); - } -} - -void Configuration::verifyEU4Version(const commonItems::ConverterVersion& converterVersion) const -{ - const auto EU4Version = GameVersion::extractVersionFromLauncher(EU4Path + "/launcher-settings.json"); - if (!EU4Version) - { - Log(LogLevel::Error) << "EU4 version could not be determined, proceeding blind!"; - return; - } - - Log(LogLevel::Info) << "EU4 version: " << EU4Version->toShortString(); - - if (converterVersion.getMinTarget() > *EU4Version) - { - Log(LogLevel::Error) << "EU4 version is v" << EU4Version->toShortString() << ", converter requires minimum v" - << converterVersion.getMinTarget().toShortString() << "!"; - throw std::runtime_error("Converter vs EU4 installation mismatch!"); - } - if (!converterVersion.getMaxTarget().isLargerishThan(*EU4Version)) - { - Log(LogLevel::Error) << "EU4 version is v" << EU4Version->toShortString() << ", converter requires maximum v" - << converterVersion.getMaxTarget().toShortString() << "!"; - throw std::runtime_error("Converter vs EU4 installation mismatch!"); - } -} diff --git a/CK3ToEU4/Source/Configuration/Configuration.h b/CK3ToEU4/Source/Configuration/Configuration.h deleted file mode 100644 index 5281bba3..00000000 --- a/CK3ToEU4/Source/Configuration/Configuration.h +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef CONFIGURATION_H -#define CONFIGURATION_H -#include "ConverterVersion.h" -#include "Parser.h" - -class Configuration: commonItems::parser -{ - public: - Configuration() = default; - explicit Configuration(const commonItems::ConverterVersion& converterVersion); - explicit Configuration(std::istream& theStream); - - enum class STARTDATE - { - EU = 1, - CK = 2, - MANUAL = 3 - }; - enum class SPLITVASSALS - { - YES = 1, - NO = 2 - }; - enum class DEJURE - { - ENABLED = 1, - DISABLED = 2 - }; - enum class DEVELOPMENT - { - IMPORT = 1, - VANILLA = 2 - }; - enum class MULTIPROVDEVTRANSFER - { - DEFAULT = 1, - MP = 2 - }; - enum class SUNSET - { - DISABLED = 1, - ACTIVE = 2 - }; - enum class I_AM_HRE - { - HRE = 1, - BYZANTIUM = 2, - ROME = 3, - CUSTOM = 4, - NONE = 5 - }; - enum class SHATTER_EMPIRES - { - NONE = 1, - ALL = 2, - CUSTOM = 3 - }; - enum class SHATTER_LEVEL - { - DUTCHY = 1, - KINGDOM = 2 - }; - enum class SHATTER_HRE_LEVEL - { - DUTCHY = 1, - KINGDOM = 2 - }; - enum class SIBERIA - { - SMALL_SIBERIA = 1, - CLEAR_SIBERIA = 2, - LEAVE_SIBERIA = 3 - }; - enum class INSTITUTIONS - { - HISTORIC = 1, - DYNAMIC = 2 - }; - enum class DYNASTICNAMES - { - ENABLED = 1, - DISABLED = 2 - }; - enum class DISCOVEREDBY - { - VANILLA = 1, - DYNAMIC = 2 - }; - - [[nodiscard]] const auto& getSaveGamePath() const { return SaveGamePath; } - [[nodiscard]] const auto& getCK3Path() const { return CK3Path; } - [[nodiscard]] const auto& getCK3DocPath() const { return CK3DocPath; } - [[nodiscard]] const auto& getEU4Path() const { return EU4Path; } - [[nodiscard]] const auto& getOutputName() const { return outputName; } - [[nodiscard]] const auto& getStartDateOption() const { return startDate; } - [[nodiscard]] const auto& getHRE() const { return iAmHre; } - [[nodiscard]] const auto& getShatterEmpires() const { return shatterEmpires; } - [[nodiscard]] const auto& getShatterLevel() const { return shatterLevel; } - [[nodiscard]] const auto& getDejure() const { return dejure; } - [[nodiscard]] const auto& getShatterHRELevel() const { return shatterHRELevel; } - [[nodiscard]] const auto& getSiberia() const { return siberia; } - [[nodiscard]] const auto& getSunset() const { return sunset; } - [[nodiscard]] const auto& getDynamicInstitutions() const { return dynamicInstitutions; } - [[nodiscard]] const auto& getDevelopment() const { return development; } - [[nodiscard]] const auto& getMultiProvDevTransfer() const { return multiProvinceDevelopmentTransfer; } - [[nodiscard]] const auto& getSplitVassals() const { return splitVassals; } - [[nodiscard]] const auto& getPlayerTitle() const { return playerTitle; } - [[nodiscard]] const auto& getDynasticNames() const { return dynasticNames; } - [[nodiscard]] const auto& getDiscoveredBy() const { return discoveredBy; } - - void setCraftFlagForPlayerTitle(const std::string& title) { playerTitle = title; } - - private: - void registerKeys(); - void setOutputName(); - void verifyCK3Path(); - void verifyEU4Path() const; - void verifyCK3Version(const commonItems::ConverterVersion& converterVersion) const; - void verifyEU4Version(const commonItems::ConverterVersion& converterVersion) const; - - std::string SaveGamePath; - std::string CK3Path; - std::string CK3DocPath; - std::string EU4Path; - std::string outputName; - - STARTDATE startDate = STARTDATE::EU; - I_AM_HRE iAmHre = I_AM_HRE::HRE; - SHATTER_EMPIRES shatterEmpires = SHATTER_EMPIRES::NONE; - SHATTER_HRE_LEVEL shatterHRELevel = SHATTER_HRE_LEVEL::DUTCHY; - SHATTER_LEVEL shatterLevel = SHATTER_LEVEL::DUTCHY; - SIBERIA siberia = SIBERIA::CLEAR_SIBERIA; - SUNSET sunset = SUNSET::DISABLED; - INSTITUTIONS dynamicInstitutions = INSTITUTIONS::HISTORIC; - DEVELOPMENT development = DEVELOPMENT::IMPORT; - MULTIPROVDEVTRANSFER multiProvinceDevelopmentTransfer = MULTIPROVDEVTRANSFER::DEFAULT; - DEJURE dejure = DEJURE::ENABLED; - SPLITVASSALS splitVassals = SPLITVASSALS::YES; - DYNASTICNAMES dynasticNames = DYNASTICNAMES::ENABLED; - DISCOVEREDBY discoveredBy = DISCOVEREDBY::VANILLA; - - std::optional<std::string> playerTitle; -}; - -#endif // CONFIGURATION_H