Configuration::Configuration() { printf("Reading configuration file.\n"); log("Reading configuration file.\n"); Object* tempObj = doParseFile("configuration.txt"); if (tempObj == NULL) { log("Could not parse file configuration.txt\n"); exit(-1); } vector<Object*> obj = tempObj->getValue("configuration"); if (obj.size() != 1) { printf("Configuration file must contain exactly one configuration section."); log("Configuration file must contain exactly one configuration section."); exit (-2); } startDate = date(obj[0]->getLeaf("start_date")); if (startDate < date("1835.1.1")) { log("Warning: start dates prior to 1835 are likely to cause crashes!\n"); } maxLiteracy = atof(obj[0]->getLeaf("max_literacy").c_str()); V2Path = obj[0]->getLeaf("v2directory"); EU3Path = obj[0]->getLeaf("EU3directory"); EU3gametype = obj[0]->getLeaf("EU3gametype"); V2gametype = obj[0]->getLeaf("V2gametype"); removetype = obj[0]->getLeaf("removetype"); }
void V2FactoryFactory::loadRequiredTechs(string filename) { Object* obj = doParseFile(filename.c_str()); if (obj == NULL) { log("Could not parse file %s\n", filename.c_str()); exit(-1); } vector<Object*> techObjs = obj->getLeaves(); for (vector<Object*>::iterator itr = techObjs.begin(); itr != techObjs.end(); ++itr) { vector<Object*> building = (*itr)->getValue("activate_building"); for (vector<Object*>::iterator bitr = building.begin(); bitr != building.end(); ++bitr) { factoryTechReqs.insert(make_pair((*bitr)->getLeaf(), (*itr)->getKey())); } } }
void V2FactoryFactory::loadRequiredInventions(string filename) { Object* obj = doParseFile(filename.c_str()); if (obj == NULL) { log("Could not parse file %s\n", filename.c_str()); exit(-1); } vector<Object*> invObjs = obj->getLeaves(); for (vector<Object*>::iterator itr = invObjs.begin(); itr != invObjs.end(); ++itr) { vector<Object*> effect = (*itr)->getValue("effect"); if (effect.size() == 0) { continue; } vector<Object*> building = effect[0]->getValue("activate_building"); for (vector<Object*>::iterator bitr = building.begin(); bitr != building.end(); ++bitr) { factoryInventionReqs.insert(make_pair((*bitr)->getLeaf(), (*itr)->getKey())); } } }
// Converts the given EU3 save into a V2 mod. // Returns 0 on success or a non-zero failure code on error. int ConvertEU3ToV2(const std::string& EU3SaveFileName) { Object* obj; // generic object ifstream read; // ifstream for reading files char curDir[MAX_PATH]; GetCurrentDirectory(MAX_PATH, curDir); LOG(LogLevel::Debug) << "Current directory is " << curDir; Configuration::getInstance(); //Get V2 install location LOG(LogLevel::Info) << "Get V2 Install Path"; string V2Loc = Configuration::getV2Path(); struct _stat st; if (V2Loc.empty() || (_stat(V2Loc.c_str(), &st) != 0)) { LOG(LogLevel::Error) << "No Victoria 2 path was specified in configuration.txt, or the path was invalid"; return (-1); } else { LOG(LogLevel::Debug) << "Victoria 2 install path is " << V2Loc; } // Get V2 Documents Directory LOG(LogLevel::Debug) << "Get V2 Documents directory"; string V2DocLoc = Configuration::getV2DocumentsPath(); if (V2DocLoc.empty() || (_stat(V2DocLoc.c_str(), &st) != 0)) { LOG(LogLevel::Error) << "No Victoria 2 documents directory was specified in configuration.txt, or the path was invalid"; return (-1); } else { LOG(LogLevel::Debug) << "Victoria 2 documents directory is " << V2DocLoc; } //Get EU3 install location LOG(LogLevel::Debug) << "Get EU3 Install Path"; string EU3Loc = Configuration::getEU3Path(); if (EU3Loc.empty() || (_stat(EU3Loc.c_str(), &st) != 0)) { LOG(LogLevel::Error) << "No Europa Universalis 3 path was specified in configuration.txt, or the path was invalid"; return (-1); } else { LOG(LogLevel::Debug) << "EU3 install path is " << EU3Loc; } // Get EU3 Mod LOG(LogLevel::Debug) << "Get EU3 Mod"; string fullModPath; string modName = Configuration::getEU3Mod(); if (modName != "") { fullModPath = EU3Loc + "\\mod\\" + modName; if (fullModPath.empty() || (_stat(fullModPath.c_str(), &st) != 0)) { LOG(LogLevel::Error) << modName << " could not be found at the specified directory. A valid path and mod must be specified."; return (-1); } else { LOG(LogLevel::Debug) << "EU3 Mod directory is " << fullModPath; } } //get output name const int slash = EU3SaveFileName.find_last_of("\\"); // the last slash in the save's filename string outputName = EU3SaveFileName.substr(slash + 1, EU3SaveFileName.length()); const int length = outputName.find_first_of("."); // the first period after the slash outputName = outputName.substr(0, length); // the name to use to output the mod int dash = outputName.find_first_of('-'); while (dash != string::npos) { outputName.replace(dash, 1, "_"); dash = outputName.find_first_of('-'); } int space = outputName.find_first_of(' '); while (space != string::npos) { outputName.replace(space, 1, "_"); space = outputName.find_first_of(' '); } Configuration::setOutputName(outputName); LOG(LogLevel::Info) << "Using output name " << outputName; LOG(LogLevel::Info) << "* Importing EU3 save *"; // Parse EU3 Save LOG(LogLevel::Info) << "Parsing save"; obj = doParseFile(EU3SaveFileName.c_str()); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file " << EU3SaveFileName; exit(-1); } // Read all localisations. LOG(LogLevel::Info) << "Reading localisation"; EU3Localisation localisation; localisation.ReadFromAllFilesInFolder(Configuration::getEU3Path() + "\\localisation"); if (!fullModPath.empty()) { LOG(LogLevel::Debug) << "Reading mod localisation"; localisation.ReadFromAllFilesInFolder(fullModPath + "\\localisation"); } // Construct world from EU3 save. LOG(LogLevel::Info) << "Building world"; EU3World sourceWorld(obj); // Read EU3 common\countries LOG(LogLevel::Info) << "Reading EU3 common\\countries"; { ifstream commonCountries(Configuration::getEU3Path() + "\\common\\countries.txt"); sourceWorld.readCommonCountries(commonCountries, Configuration::getEU3Path()); if (!fullModPath.empty()) { ifstream convertedCommonCountries(fullModPath + "\\common\\countries.txt"); sourceWorld.readCommonCountries(convertedCommonCountries, fullModPath); } } // Figure out what EU3 gametype we're using WorldType game = sourceWorld.getWorldType(); switch (game) { case VeryOld: LOG(LogLevel::Error) << "EU3 game appears to be from an old version; only IN, HttT, and DW are supported."; exit(1); case InNomine: LOG(LogLevel::Info) << "Game type is: EU3 In Nomine. EXPERIMENTAL."; break; case HeirToTheThrone: LOG(LogLevel::Info) << "Game type is: EU3 Heir to the Throne."; break; case DivineWind: LOG(LogLevel::Info) << "Game type is: EU3 Divine Wind."; break; default: LOG(LogLevel::Error) << "Error: Could not determine savegame type."; exit(1); } sourceWorld.setLocalisations(localisation); // Resolve unit types LOG(LogLevel::Info) << "Resolving unit types."; RegimentTypeMap rtm; read.open("unit_strength.txt"); if (read.is_open()) { read.close(); read.clear(); LOG(LogLevel::Info) << "\tReading unit strengths from unit_strength.txt"; obj = doParseFile("unit_strength.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file unit_strength.txt"; exit(-1); } for (int i = 0; i < num_reg_categories; ++i) { AddCategoryToRegimentTypeMap(obj, (RegimentCategory)i, RegimentCategoryNames[i], rtm); } } else { LOG(LogLevel::Info) << "Reading unit strengths from EU3 installation folder"; struct _finddata_t unitFileData; intptr_t fileListing; if ( (fileListing = _findfirst( (EU3Loc + "\\common\\units\\*.txt").c_str(), &unitFileData)) == -1L) { LOG(LogLevel::Info) << "Could not open units directory."; return -1; } do { if (strcmp(unitFileData.name, ".") == 0 || strcmp(unitFileData.name, "..") == 0 ) { continue; } string unitFilename = unitFileData.name; string unitName = unitFilename.substr(0, unitFilename.find_first_of('.')); AddUnitFileToRegimentTypeMap((EU3Loc + "\\common\\units"), unitName, rtm); } while(_findnext(fileListing, &unitFileData) == 0); _findclose(fileListing); } read.close(); read.clear(); sourceWorld.resolveRegimentTypes(rtm); // Merge nations LOG(LogLevel::Info) << "Merging nations."; obj = doParseFile("merge_nations.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file merge_nations.txt"; exit(-1); } mergeNations(sourceWorld, obj); // Parse V2 input file LOG(LogLevel::Info) << "Parsing Vicky2 data"; vector<pair<string, string>> minorityPops; minorityPops.push_back(make_pair("ashkenazi","jewish")); minorityPops.push_back(make_pair("sephardic","jewish")); minorityPops.push_back(make_pair("","jewish")); V2World destWorld(minorityPops); // Construct factory factory LOG(LogLevel::Info) << "Determining factory allocation rules."; V2FactoryFactory factoryBuilder; // Parse province mappings LOG(LogLevel::Info) << "Parsing province mappings"; obj = doParseFile("province_mappings.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file province_mappings.txt"; exit(-1); } provinceMapping provinceMap; inverseProvinceMapping inverseProvinceMap; resettableMap resettableProvinces; initProvinceMap(obj, sourceWorld.getWorldType(), provinceMap, inverseProvinceMap, resettableProvinces); sourceWorld.checkAllProvincesMapped(inverseProvinceMap); sourceWorld.setEU3WorldProvinceMappings(inverseProvinceMap); // Get country mappings LOG(LogLevel::Info) << "Getting country mappings"; CountryMapping countryMap; countryMap.ReadRules("country_mappings.txt"); // Get adjacencies LOG(LogLevel::Info) << "Importing adjacencies"; adjacencyMapping adjacencyMap = initAdjacencyMap(); // Generate continent mapping LOG(LogLevel::Info) << "Finding Continents"; string EU3Mod = Configuration::getEU3Mod(); continentMapping continentMap; if (EU3Mod != "") { string continentFile = Configuration::getEU3Path() + "\\mod\\" + EU3Mod + "\\map\\continent.txt"; if ((_stat(continentFile.c_str(), &st) == 0)) { obj = doParseFile(continentFile.c_str()); if ((obj != NULL) && (obj->getLeaves().size() > 0)) { initContinentMap(obj, continentMap); } } } if (continentMap.size() == 0) { obj = doParseFile((EU3Loc + "\\map\\continent.txt").c_str()); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file " << EU3Loc << "\\map\\continent.txt"; exit(-1); } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Failed to parse continent.txt"; return 1; } initContinentMap(obj, continentMap); } if (continentMap.size() == 0) { LOG(LogLevel::Warning) << "No continent mappings found - may lead to problems later"; } // Generate region mapping LOG(LogLevel::Info) << "Parsing region structure"; if (_stat(".\\blankMod\\output\\map\\region.txt", &st) == 0) { obj = doParseFile(".\\blankMod\\output\\map\\region.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file .\\blankMod\\output\\map\\region.txt"; exit(-1); } } else { obj = doParseFile((V2Loc + "\\map\\region.txt").c_str()); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file " << V2Loc << "\\map\\region.txt"; exit(-1); } } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Could not parse region.txt"; return 1; } stateMapping stateMap; stateIndexMapping stateIndexMap; initStateMap(obj, stateMap, stateIndexMap); // Parse Culture Mappings LOG(LogLevel::Info) << "Parsing culture mappings"; obj = doParseFile("cultureMap.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file cultureMap.txt"; exit(-1); } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Failed to parse cultureMap.txt"; return 1; } cultureMapping cultureMap; cultureMap = initCultureMap(obj->getLeaves()[0]); obj = doParseFile("slaveCultureMap.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file slaveCultureMap.txt"; exit(-1); } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Failed to parse slaveCultureMap.txt"; return 1; } cultureMapping slaveCultureMap; slaveCultureMap = initCultureMap(obj->getLeaves()[0]); unionCulturesMap unionCultures; inverseUnionCulturesMap inverseUnionCultures; if (EU3Mod != "") { string modCultureFile = Configuration::getEU3Path() + "\\mod\\" + EU3Mod + "\\common\\cultures.txt"; if ((_stat(modCultureFile.c_str(), &st) == 0)) { obj = doParseFile(modCultureFile.c_str()); if ((obj != NULL) && (obj->getLeaves().size() > 0)) { initUnionCultures(obj, unionCultures, inverseUnionCultures); } } } if (unionCultures.size() == 0) { obj = doParseFile((EU3Loc + "\\common\\cultures.txt").c_str()); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file " << EU3Loc << "\\common\\cultures.txt"; exit(-1); } initUnionCultures(obj, unionCultures, inverseUnionCultures); } sourceWorld.checkAllEU3CulturesMapped(cultureMap, inverseUnionCultures); // Parse EU3 Religions LOG(LogLevel::Info) << "Parsing EU3 religions"; bool parsedReligions = false; if (EU3Mod != "") { string modReligionFile = Configuration::getEU3Path() + "\\mod\\" + EU3Mod + "\\common\\religion.txt"; if ((_stat(modReligionFile.c_str(), &st) == 0)) { obj = doParseFile(modReligionFile.c_str()); if ((obj != NULL) && (obj->getLeaves().size() > 0)) { EU3Religion::parseReligions(obj); parsedReligions = true; } } } if (!parsedReligions) { obj = doParseFile((EU3Loc + "\\common\\religion.txt").c_str()); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file " << EU3Loc << "\\common\\religion.txt"; exit(-1); } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Failed to parse religion.txt."; return 1; } EU3Religion::parseReligions(obj); } // Parse Religion Mappings LOG(LogLevel::Info) << "Parsing religion mappings"; obj = doParseFile("religionMap.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file religionMap.txt"; exit(-1); } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Failed to parse religionMap.txt"; return 1; } religionMapping religionMap; religionMap = initReligionMap(obj->getLeaves()[0]); sourceWorld.checkAllEU3ReligionsMapped(religionMap); //Parse unions mapping LOG(LogLevel::Info) << "Parsing union mappings"; obj = doParseFile("unions.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file unions.txt"; exit(-1); } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Failed to parse unions.txt"; return 1; } unionMapping unionMap; unionMap = initUnionMap(obj->getLeaves()[0]); //Parse government mapping LOG(LogLevel::Info) << "Parsing governments mappings"; initParser(); obj = doParseFile("governmentMapping.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file governmentMapping.txt"; exit(-1); } governmentMapping governmentMap; governmentMap = initGovernmentMap(obj->getLeaves()[0]); //Parse tech schools LOG(LogLevel::Info) << "Parsing tech schools."; initParser(); obj = doParseFile("blocked_tech_schools.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file blocked_tech_schools.txt"; exit(-1); } vector<string> blockedTechSchools; blockedTechSchools = initBlockedTechSchools(obj); initParser(); obj = doParseFile( (V2Loc + "\\common\\technology.txt").c_str() ); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file " << V2Loc << "\\common\\technology.txt"; exit(-1); } vector<techSchool> techSchools; techSchools = initTechSchools(obj, blockedTechSchools); // Get Leader traits LOG(LogLevel::Info) << "Getting leader traits"; V2LeaderTraits lt; map<int, int> leaderIDMap; // <EU3, V2> // Parse EU4 Regions LOG(LogLevel::Info) << "Parsing EU4 regions"; obj = doParseFile((EU3Loc + "\\map\\region.txt").c_str()); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file " << EU3Loc << "\\map\\region.txt"; exit(-1); } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Failed to parse region.txt"; return 1; } EU3RegionsMapping EU3RegionsMap; initEU3RegionMap(obj, EU3RegionsMap); if (EU3Mod != "") { string modRegionFile = Configuration::getEU3Path() + "\\mod\\" + EU3Mod + "\\map\\region.txt"; if ((_stat(modRegionFile.c_str(), &st) == 0)) { obj = doParseFile(modRegionFile.c_str()); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file " << modRegionFile; exit(-1); } EU3Religion::parseReligions(obj); } } // Create Country Mapping removeEmptyNations(sourceWorld); if (Configuration::getRemovetype() == "dead") { removeDeadLandlessNations(sourceWorld); } else if (Configuration::getRemovetype() == "all") { removeLandlessNations(sourceWorld); } countryMap.CreateMapping(sourceWorld, destWorld); // Convert LOG(LogLevel::Info) << "Converting countries"; destWorld.convertCountries(sourceWorld, countryMap, cultureMap, unionCultures, religionMap, governmentMap, inverseProvinceMap, techSchools, leaderIDMap, lt, EU3RegionsMap); destWorld.scalePrestige(); LOG(LogLevel::Info) << "Converting provinces"; destWorld.convertProvinces(sourceWorld, provinceMap, resettableProvinces, countryMap, cultureMap, slaveCultureMap, religionMap, stateIndexMap, EU3RegionsMap); LOG(LogLevel::Info) << "Converting diplomacy"; destWorld.convertDiplomacy(sourceWorld, countryMap); LOG(LogLevel::Info) << "Setting colonies"; destWorld.setupColonies(adjacencyMap, continentMap); LOG(LogLevel::Info) << "Creating states"; destWorld.setupStates(stateMap); LOG(LogLevel::Info) << "Setting unciv reforms"; destWorld.convertUncivReforms(); LOG(LogLevel::Info) << "Converting techs"; destWorld.convertTechs(sourceWorld); LOG(LogLevel::Info) << "Allocating starting factories"; destWorld.allocateFactories(sourceWorld, factoryBuilder); LOG(LogLevel::Info) << "Creating pops"; destWorld.setupPops(sourceWorld); LOG(LogLevel::Info) << "Adding unions"; destWorld.addUnions(unionMap); LOG(LogLevel::Info) << "Converting armies and navies"; destWorld.convertArmies(sourceWorld, inverseProvinceMap, leaderIDMap, adjacencyMap); // Output results LOG(LogLevel::Info) << "Outputting mod"; system("%systemroot%\\System32\\xcopy blankMod output /E /Q /Y /I"); FILE* modFile; if (fopen_s(&modFile, ("Output\\" + Configuration::getOutputName() + ".mod").c_str(), "w") != 0) { LOG(LogLevel::Error) << "Could not create .mod file"; exit(-1); } fprintf(modFile, "name = \"Converted - %s\"\n", Configuration::getOutputName().c_str()); fprintf(modFile, "path = \"mod/%s\"\n", Configuration::getOutputName().c_str()); fprintf(modFile, "user_dir = \"%s\"\n", Configuration::getOutputName().c_str()); fprintf(modFile, "replace = \"history/provinces\"\n"); fprintf(modFile, "replace = \"history/countries\"\n"); fprintf(modFile, "replace = \"history/diplomacy\"\n"); fprintf(modFile, "replace = \"history/units\"\n"); fprintf(modFile, "replace = \"history/pops/1836.1.1\"\n"); fprintf(modFile, "replace = \"common/religion.txt\"\n"); fprintf(modFile, "replace = \"common/cultures.txt\"\n"); fprintf(modFile, "replace = \"gfx/interface/icon_religion.dds\"\n"); fprintf(modFile, "replace = \"localisation/text.csv\"\n"); fprintf(modFile, "replace = \"localisation/0_Names.csv\"\n"); fprintf(modFile, "replace = \"localisation/0_Cultures.csv\"\n"); fprintf(modFile, "replace = \"history/wars\"\n"); fclose(modFile); string renameCommand = "move /Y output\\output output\\" + Configuration::getOutputName(); system(renameCommand.c_str()); destWorld.output(); LOG(LogLevel::Info) << "* Conversion complete *"; return 0; }
V2FactoryFactory::V2FactoryFactory(string V2Loc) { // load required techs/inventions factoryTechReqs.clear(); loadRequiredTechs(V2Loc + "\\technologies\\army_tech.txt"); loadRequiredTechs(V2Loc + "\\technologies\\commerce_tech.txt"); loadRequiredTechs(V2Loc + "\\technologies\\culture_tech.txt"); loadRequiredTechs(V2Loc + "\\technologies\\industry_tech.txt"); loadRequiredTechs(V2Loc + "\\technologies\\navy_tech.txt"); factoryInventionReqs.clear(); loadRequiredInventions(V2Loc + "\\inventions\\army_inventions.txt"); loadRequiredInventions(V2Loc + "\\inventions\\commerce_inventions.txt"); loadRequiredInventions(V2Loc + "\\inventions\\culture_inventions.txt"); loadRequiredInventions(V2Loc + "\\inventions\\industry_inventions.txt"); loadRequiredInventions(V2Loc + "\\inventions\\navy_inventions.txt"); // load factory types factoryTypes.clear(); Object* obj = doParseFile((V2Loc + "\\common\\production_types.txt").c_str()); if (obj == NULL) { log("Could not parse file %s\n", (V2Loc + "\\common\\production_types.txt").c_str()); exit(-1); } vector<Object*> factoryObjs = obj->getLeaves(); for (vector<Object*>::iterator itr = factoryObjs.begin(); itr != factoryObjs.end(); ++itr) { V2FactoryType* ft = new V2FactoryType(*itr); map<string,string>::iterator reqitr = factoryTechReqs.find(ft->name); if (reqitr != factoryTechReqs.end()) { ft->requireTech = reqitr->second; } reqitr = factoryInventionReqs.find(ft->name); if (reqitr != factoryInventionReqs.end()) { for (int i = 0; i <= VANILLA_naval_exercises; ++i) { if ((Configuration::getV2Gametype() != "HOD") && (reqitr->second == vanillaInventionNames[i])) { ft->vanillaRequiredInvention = (vanillaInventionType)i; break; } else if ((Configuration::getV2Gametype() != "HOD") && (reqitr->second == HODInventionNames[i])) { ft->HODRequiredInvention = (HODInventionType)i; break; } } } factoryTypes[ft->name] = ft; } factoryCounts.clear(); obj = doParseFile("starting_factories.txt"); if (obj == NULL) { log("Could not parse file starting_factories.txt\n"); exit(-1); } vector<Object*> top = obj->getValue("starting_factories"); if (top.size() != 1) { log("Error: Could not load starting factory list!\n"); printf("Error: Could not load starting factory list!\n"); exit(-1); } vector<Object*> factories = top[0]->getLeaves(); for (vector<Object*>::iterator itr = factories.begin(); itr != factories.end(); ++itr) { string factoryType = (*itr)->getKey(); int count = atoi((*itr)->getLeaf().c_str()); map<string, V2FactoryType*>::iterator t = factoryTypes.find(factoryType); if (t == factoryTypes.end()) { log("Error: Could not locate V2 factory type for starting factories of type %s!\n", factoryType.c_str()); continue; } factoryCounts.push_back(pair<V2FactoryType*, int>(t->second, count)); } }
void AddUnitFileToRegimentTypeMap(string directory, string name, RegimentTypeMap& rtm) { Object* obj = doParseFile((directory + "\\" + name + ".txt").c_str()); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file " << directory << '\\' << name << ".txt"; exit(-1); } int rc = -1; vector<Object*> typeObj = obj->getValue("type"); if (typeObj.size() < 1) { LOG(LogLevel::Warning) << "Unit file for " << name << " has no type"; return; } string type = typeObj[0]->getLeaf(); for (int i = 0; i < num_reg_categories; ++i) { if (type == RegimentCategoryNames[i]) rc = i; } if (rc == -1) { LOG(LogLevel::Warning) << "Unit file for " << name << " has unrecognized type " << type; return; } int unitStrength = 0; vector<Object*> strObj; strObj = obj->getValue("maneuver"); if (strObj.size() > 0) unitStrength += atoi(strObj[0]->getLeaf().c_str()); strObj = obj->getValue("offensive_morale"); if (strObj.size() > 0) unitStrength += atoi(strObj[0]->getLeaf().c_str()); strObj = obj->getValue("defensive_morale"); if (strObj.size() > 0) unitStrength += atoi(strObj[0]->getLeaf().c_str()); strObj = obj->getValue("offensive_fire"); if (strObj.size() > 0) unitStrength += atoi(strObj[0]->getLeaf().c_str()); strObj = obj->getValue("defensive_fire"); if (strObj.size() > 0) unitStrength += atoi(strObj[0]->getLeaf().c_str()); strObj = obj->getValue("offensive_shock"); if (strObj.size() > 0) unitStrength += atoi(strObj[0]->getLeaf().c_str()); strObj = obj->getValue("defensive_shock"); if (strObj.size() > 0) unitStrength += atoi(strObj[0]->getLeaf().c_str()); strObj = obj->getValue("hull_size"); if (strObj.size() > 0) unitStrength += atoi(strObj[0]->getLeaf().c_str()); // give all transports equal weight for 1-to-1 conversion if (rc == transport) { unitStrength = 24; } if (unitStrength == 0) { LOG(LogLevel::Warning) << "Unit " << name << " has no strength"; return; } rtm[name] = pair<RegimentCategory, int>((RegimentCategory)rc, unitStrength); }
bool Configuration::Init(std::string sConfigPath) { std::string sSave = ""; std::string sName = ""; std::string sHoi3Dir = ""; std::string sHoi3ModDir = ""; std::string sDefconDir = ""; std::string sSuperpowerOption = ""; Object* ConfigFile = doParseFile(sConfigPath.c_str()); if (nullptr == ConfigFile) { LOG(LogLevel::Error) << "Could not open the configuration file."; return false; } std::vector<Object*> Configs = ConfigFile->getValue("configuration"); if (Configs.empty()) { LOG(LogLevel::Error) << "Could not read the configuration file."; return false; } Object* Config = Configs.at(0); for (auto ConfigLeaf : Config->getLeaves()) { if (ConfigLeaf->getKey() == "save") sSave = ConfigLeaf->getLeaf(); else if (ConfigLeaf->getKey() == "HOI3directory") sHoi3Dir = ConfigLeaf->getLeaf(); else if (ConfigLeaf->getKey() == "HOI3ModDirectory") sHoi3ModDir = ConfigLeaf->getLeaf(); else if (ConfigLeaf->getKey() == "DEFCONdirectory") sDefconDir = ConfigLeaf->getLeaf(); else if (ConfigLeaf->getKey() == "superpowers") { sSuperpowerOption = ConfigLeaf->getLeaf(); if (sSuperpowerOption == "custom") m_SuperpowerOption = Superpowers::Custom; else if (sSuperpowerOption == "factions") m_SuperpowerOption = Superpowers::Factions; else m_SuperpowerOption = Superpowers::Powerful; } else if (ConfigLeaf->getKey().size() == 5) { if (ConfigLeaf->getKey().substr(0, 4) == "side") { int index = ConfigLeaf->getKey().at(4) - '0' - 1; if (index > 5) continue; for (std::string Tag : ConfigLeaf->getTokens()) m_Sides[index].push_back(Tag); } } } m_SavePath = sSave; m_Hoi3Path = sHoi3Dir; m_DefconPath = sDefconDir; m_Hoi3ModPath = sHoi3ModDir; // Sanity checks if (m_SavePath.empty()) { LOG(LogLevel::Error) << "No Hearts Of Iron 3 save file specified."; return false; } if (m_Hoi3Path.empty()) { LOG(LogLevel::Error) << "No path to Hearts Of Iron 3 specified."; return false; } if (m_DefconPath.empty()) { LOG(LogLevel::Warning) << "No path to DEFCON specified. The created mod will not be copied into place."; } if (m_SuperpowerOption == Superpowers::Custom) { int iEmptySides = 0; for (int i = 0; i < 6; i++) { if (m_Sides[i].empty()) { LOG(LogLevel::Warning) << "Custom superpowers chosen, but side " << i << " is empty."; iEmptySides++; } } if (iEmptySides == 6) { LOG(LogLevel::Error) << "This nuclear war has no sides. World peace!"; return false; } else if (iEmptySides == 5) { LOG(LogLevel::Error) << "This nuclear war has only one side. World conquest ensues!"; return false; } } return true; }
void HoI3Province::init(int newNumber) { num = newNumber; name = ""; points = 0; metal = oil = rare_materials = energy = manpower = leadership = 0.0; industry = 0; is_coastal = false; is_land = false; is_blacklisted_port = false; avg_mil = 0.0; char sNum[8]; sprintf_s(sNum, 8, "%d", num); string HoI3Loc = Configuration::getHoI3Path(); string parentDir = HoI3Loc + "\\history\\provinces\\*"; string folder; struct _finddata_t dirData; intptr_t dirListing; if ( (dirListing = _findfirst(parentDir.c_str(), &dirData)) != -1L) { do { string filename = HoI3Loc + "\\history\\provinces\\" + dirData.name + "\\" + sNum + "*.txt"; struct _finddata_t fileData; intptr_t fileListing; if ( (fileListing = _findfirst(filename.c_str(), &fileData)) != -1L) { Object* obj = doParseFile( (HoI3Loc + "\\history\\provinces\\" + dirData.name + "\\" + fileData.name).c_str() ); vector<Object*> results = obj->getValue("owner"); if (results.size() > 0) { is_land = true; } results = obj->getValue("points"); if (results.size() > 0) { points = atoi(results[0]->getLeaf().c_str()); } results = obj->getValue("metal"); if (results.size() > 0) { metal = atof(results[0]->getLeaf().c_str()); } results = obj->getValue("crude_oil"); if (results.size() > 0) { oil = atof(results[0]->getLeaf().c_str()); } results = obj->getValue("rare_materials"); if (results.size() > 0) { rare_materials = atof(results[0]->getLeaf().c_str()); } results = obj->getValue("energy"); if (results.size() > 0) { energy = atof(results[0]->getLeaf().c_str()); } results = obj->getValue("manpower"); if (results.size() > 0) { manpower = atof(results[0]->getLeaf().c_str()); } results = obj->getValue("leadership"); if (results.size() > 0) { leadership = atof(results[0]->getLeaf().c_str()); } #ifdef IND_DIAG results = obj->getValue("industry"); if (results.size() > 0) { int temp_industry = atoi(results[0]->getLeaf().c_str()); map<int, int>::iterator itr = industryDistribution.find(temp_industry); if (itr == industryDistribution.end()) industryDistribution[temp_industry] = 1; else ++itr->second; } #endif _findclose(fileListing); break; } _findclose(fileListing); } while (_findnext(dirListing, &dirData) == 0); } _findclose(dirListing); naval_base = air_base = land_fort = coastal_fort = anti_air = infrastructure = 0; // hack for naval bases. some coastal provinces can't have a naval base at all. static vector<int> port_blacklist; if (port_blacklist.size() == 0) { int temp = 0; ifstream s("port_blacklist.txt"); while (s.good() && !s.eof()) { s >> temp; port_blacklist.push_back(temp); } s.close(); }
// Converts the given V2 save into a HOI3 mod. // Returns 0 on success or a non-zero failure code on error. int ConvertV2ToHoI3(const std::string& V2SaveFileName) { LOG(LogLevel::Info) << "Converter version 1.2"; Object* obj; // generic object Configuration::getInstance(); char curDir[MAX_PATH]; GetCurrentDirectory(MAX_PATH, curDir); LOG(LogLevel::Debug) << "Current directory is " << curDir; // Get HoI3 install location LOG(LogLevel::Debug) << "Get HoI3 Install Path"; string HoI3Loc = Configuration::getHoI3Path(); // the HOI3 install location as stated in the configuration file struct _stat st; // the file info if (HoI3Loc.empty() || (_stat(HoI3Loc.c_str(), &st) != 0)) { LOG(LogLevel::Error) << "No HoI3 path was specified in configuration.txt, or the path was invalid"; return (-1); } else { LOG(LogLevel::Debug) << "HoI3 path install path is " << HoI3Loc; } // Get HOI3 Documents Directory LOG(LogLevel::Debug) << "Get HOI3 Documents directory"; string HoI3DocLoc = Configuration::getHoI3DocumentsPath(); // the HoI3 My Documents location as stated in the configuration file if (HoI3DocLoc.empty() || (_stat(HoI3DocLoc.c_str(), &st) != 0)) { LOG(LogLevel::Error) << "No HoI3 documents directory was specified in configuration.txt, or the path was invalid"; return (-1); } else { LOG(LogLevel::Debug) << "HoI3 documents directory is " << HoI3DocLoc; } // Get V2 install location LOG(LogLevel::Debug) << "Get V2 Install Path"; string V2Loc = Configuration::getV2Path(); // the V2 install location as stated in the configuration file if (V2Loc.empty() || (_stat(V2Loc.c_str(), &st) != 0)) { LOG(LogLevel::Error) << "No Victoria 2 path was specified in configuration.txt, or the path was invalid"; return (-1); } else { LOG(LogLevel::Debug) << "Victoria 2 install path is " << V2Loc; } // Get V2 Mod directory map<string, string> possibleMods; // name, path LOG(LogLevel::Debug) << "Get V2 Documents Directory"; string V2DocumentsLoc = Configuration::getV2DocumentsPath(); // the Victoria 2 My Documents location as stated in the configuration file if (V2DocumentsLoc.empty() || (_stat(V2DocumentsLoc.c_str(), &st) != 0)) { LOG(LogLevel::Error) << "No Victoria 2 documents directory was specified in configuration.txt, or the path was invalid"; return (-1); } else { LOG(LogLevel::Debug) << "Victoria 2 Documents directory is " << V2DocumentsLoc; } // Sanity check Vic2 mods LOG(LogLevel::Debug) << "Double-check Vic2 mods"; vector<string> vic2Mods = Configuration::getVic2Mods(); for (auto itr: vic2Mods) { LOG(LogLevel::Debug) << "\tExpecting a mod with name " << itr; } set<string> fileNames; WinUtils::GetAllFilesInFolder(Configuration::getV2Path() + "\\mod", fileNames); for (set<string>::iterator itr = fileNames.begin(); itr != fileNames.end(); itr++) { const int pos = itr->find_last_of('.'); // the position of the last period in the filename if (itr->substr(pos, itr->length()) == ".mod") { string folderName = itr->substr(0, pos); if (WinUtils::doesFolderExist(Configuration::getV2Path() + "\\mod\\" + folderName)) { LOG(LogLevel::Debug) << "\tFound mod with name " << folderName; } } } // get inventions LOG(LogLevel::Info) << "Getting inventions"; inventionNumToName iNumToname; getInventionNums(iNumToname); // parse technologies LOG(LogLevel::Info) << "Parsing Vic2 technologies"; map<string, string> armyTechs; obj = doParseFile((Configuration::getV2Path() + "\\technologies\\army_tech.txt").c_str()); if (obj != NULL) { for (auto tech: obj->getLeaves()) { armyTechs.insert(make_pair(tech->getKey(), tech->getKey())); } } map<string, string> navyTechs; obj = doParseFile((Configuration::getV2Path() + "\\technologies\\navy_tech.txt").c_str()); if (obj != NULL) { for (auto tech: obj->getLeaves()) { navyTechs.insert(make_pair(tech->getKey(), tech->getKey())); } } // parse continents LOG(LogLevel::Info) << "Parsing continents"; continentMapping continentMap; obj = doParseFile((Configuration::getV2Path() + "\\map\\continent.txt").c_str()); if (obj != NULL) { initContinentMap(obj, continentMap); } //get output name const int slash = V2SaveFileName.find_last_of("\\"); // the last slash in the save's filename string outputName = V2SaveFileName.substr(slash + 1, V2SaveFileName.length()); const int length = outputName.find_first_of("."); // the first period after the slash outputName = outputName.substr(0, length); // the name to use to output the mod int dash = outputName.find_first_of('-'); // the first (if any) dask in the output name while (dash != string::npos) { outputName.replace(dash, 1, "_"); dash = outputName.find_first_of('-'); } int space = outputName.find_first_of(' '); // the first space (if any) in the output name while (space != string::npos) { outputName.replace(space, 1, "_"); space = outputName.find_first_of(' '); } Configuration::setOutputName(outputName); LOG(LogLevel::Info) << "Using output name " << outputName; string outputFolder = string(curDir) + "\\output\\" + Configuration::getOutputName(); if (WinUtils::doesFolderExist(outputFolder.c_str())) { LOG(LogLevel::Error) << "Output folder " << Configuration::getOutputName() << " already exists! Clear the output folder before running again!"; exit(0); } // Parse government mapping LOG(LogLevel::Info) << "Parsing governments mappings"; initParser(); obj = doParseFile("governmentMapping.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file governmentMapping.txt"; exit(-1); } governmentMapper::getInstance()->initGovernmentMap(obj->getLeaves()[0]); // Parse issues LOG(LogLevel::Info) << "Parsing governments reforms"; for (auto itr : vic2Mods) { if (WinUtils::DoesFileExist(Configuration::getV2Path() + "\\mod\\" + itr + "\\common\\issues.txt")) { obj = doParseFile((Configuration::getV2Path() + "\\mod\\" + itr + "\\common\\issues.txt").c_str()); if (obj != NULL) { governmentMapper::getInstance()->initReforms(obj); break; } } } if (!governmentMapper::getInstance()->areReformsInitialized()) { obj = doParseFile((Configuration::getV2Path() + "\\common\\issues.txt").c_str()); if (obj != NULL) { governmentMapper::getInstance()->initReforms(obj); } } LOG(LogLevel::Info) << "* Importing V2 save *"; // Parse V2 Save LOG(LogLevel::Info) << "Parsing save"; obj = doParseFile(V2SaveFileName.c_str()); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file " << V2SaveFileName << ". File is likely missing."; exit(-1); } // Construct world from V2 save. LOG(LogLevel::Info) << "Building world"; V2World sourceWorld(obj, iNumToname, armyTechs, navyTechs, continentMap); // Read all localisations. LOG(LogLevel::Info) << "Reading localisation"; V2Localisation localisation; localisation.ReadFromAllFilesInFolder(Configuration::getV2Path() + "\\localisation"); for (auto itr: vic2Mods) { LOG(LogLevel::Debug) << "Reading mod localisation"; localisation.ReadFromAllFilesInFolder(Configuration::getV2Path() + "\\mod\\" + itr + "\\localisation"); } sourceWorld.setLocalisations(localisation); // Merge nations LOG(LogLevel::Info) << "Merging nations"; obj = doParseFile("merge_nations.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file merge_nations.txt"; exit(-1); } mergeNations(sourceWorld, obj); // Parse province mappings LOG(LogLevel::Info) << "Parsing province mappings"; obj = doParseFile("province_mappings.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file province_mappings.txt"; exit(-1); } provinceMapping provinceMap; inverseProvinceMapping inverseProvinceMap; resettableMap resettableProvinces; initProvinceMap(obj, provinceMap, inverseProvinceMap, resettableProvinces); sourceWorld.checkAllProvincesMapped(inverseProvinceMap); // Parse HoI3 data files LOG(LogLevel::Info) << "Parsing HoI3 data"; HoI3World destWorld; destWorld.importProvinces(provinceMap); destWorld.checkCoastalProvinces(); // Get country mappings CountryMapping countryMap; countryMap.ReadRules("country_mappings.txt"); destWorld.importPotentialCountries(); countryMap.CreateMapping(sourceWorld, destWorld); // Get adjacencies LOG(LogLevel::Info) << "Importing HoI3 adjacencies"; HoI3AdjacencyMapping HoI3AdjacencyMap = initHoI3AdjacencyMap(); // Leaders map<int, int> leaderIDMap; // <V2, HoI3> // Parse government jobs LOG(LogLevel::Info) << "Parsing government jobs"; initParser(); obj = doParseFile("governmentJobs.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file governmentJobs.txt"; exit(-1); } governmentJobsMap governmentJobs; initGovernmentJobTypes(obj->getLeaves()[0], governmentJobs); // Parse leader traits LOG(LogLevel::Info) << "Parsing government jobs"; initParser(); obj = doParseFile("leader_traits.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file leader_traits.txt"; exit(-1); } leaderTraitsMap leaderTraits; initLeaderTraitsMap(obj->getLeaves()[0], leaderTraits); // parse names LOG(LogLevel::Info) << "Parsing names"; namesMapping namesMap; vic2Mods = Configuration::getVic2Mods(); for (auto itr: vic2Mods) { LOG(LogLevel::Debug) << "Reading mod cultures"; obj = doParseFile((Configuration::getV2Path() + "\\mod\\" + itr + "\\common\\cultures.txt").c_str()); if (obj != NULL) { initNamesMapping(obj, namesMap); } } obj = doParseFile((Configuration::getV2Path() + "\\common\\cultures.txt").c_str()); if (obj != NULL) { initNamesMapping(obj, namesMap); } // parse portraits list LOG(LogLevel::Info) << "Parsing portraits list"; portraitMapping portraitMap; obj = doParseFile("portraits.txt"); if (obj != NULL) { initPortraitMapping(obj, portraitMap); } // parse culture mapping LOG(LogLevel::Info) << "Parsing culture mappings"; obj = doParseFile("culture_map.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file culture_map.txt"; exit(-1); } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Failed to parse culture_map.txt"; return 1; } cultureMapping cultureMap; cultureMap = initCultureMap(obj->getLeaves()[0]); // parse personality mapping LOG(LogLevel::Info) << "Parsing personality mappings"; obj = doParseFile("personality_map.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file personality_map.txt"; exit(-1); } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Failed to parse personality_map.txt"; return 1; } personalityMap landPersonalityMap; personalityMap seaPersonalityMap; initLeaderPersonalityMap(obj->getLeaves()[0], landPersonalityMap, seaPersonalityMap); // parse background mapping LOG(LogLevel::Info) << "Parsing background mappings"; obj = doParseFile("background_map.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file background_map.txt"; exit(-1); } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Failed to parse background_map.txt"; return 1; } backgroundMap landBackgroundMap; backgroundMap seaBackgroundMap; initLeaderBackgroundMap(obj->getLeaves()[0], landBackgroundMap, seaBackgroundMap); // parse AI focus data LOG(LogLevel::Info) << "Parsing AI focuses"; obj = doParseFile("ai_focus.txt"); if (obj == NULL) { LOG(LogLevel::Error) << "Could not parse file ai_focus.txt"; exit(-1); } if (obj->getLeaves().size() < 1) { LOG(LogLevel::Error) << "Failed to parse ai_focus.txt"; return 1; } AIFocusModifiers focusModifiers; initAIFocusModifiers(obj, focusModifiers); // Convert LOG(LogLevel::Info) << "Converting countries"; destWorld.convertCountries(sourceWorld, countryMap, inverseProvinceMap, leaderIDMap, localisation, governmentJobs, leaderTraits, namesMap, portraitMap, cultureMap, landPersonalityMap, seaPersonalityMap, landBackgroundMap, seaBackgroundMap); LOG(LogLevel::Info) << "Converting provinces"; destWorld.convertProvinceOwners(sourceWorld, provinceMap, countryMap); destWorld.convertNavalBases(sourceWorld, inverseProvinceMap); destWorld.convertProvinceItems(sourceWorld, provinceMap, inverseProvinceMap, countryMap, HoI3AdjacencyMap); destWorld.consolidateProvinceItems(inverseProvinceMap); LOG(LogLevel::Info) << "Converting diplomacy"; destWorld.convertDiplomacy(sourceWorld, countryMap); LOG(LogLevel::Info) << "Converting techs"; destWorld.convertTechs(sourceWorld); LOG(LogLevel::Info) << "Adding minimal levels of airbase and port"; destWorld.addMinimalItems(inverseProvinceMap); LOG(LogLevel::Info) << "Converting armies and navies"; destWorld.convertArmies(sourceWorld, inverseProvinceMap, HoI3AdjacencyMap); LOG(LogLevel::Info) << "Setting up factions"; destWorld.configureFactions(sourceWorld, countryMap); LOG(LogLevel::Info) << "Generating Leaders"; destWorld.generateLeaders(leaderTraits, namesMap, portraitMap); LOG(LogLevel::Info) << "Converting victory points"; destWorld.convertVictoryPoints(sourceWorld, countryMap); LOG(LogLevel::Info) << "Setting AI focuses"; destWorld.setAIFocuses(focusModifiers); // Output results LOG(LogLevel::Info) << "Outputting mod"; system("%systemroot%\\System32\\xcopy blankMod output /E /Q /Y /I"); FILE* modFile; // the .mod file for this mod if (fopen_s(&modFile, ("Output\\" + Configuration::getOutputName() + ".mod").c_str(), "w") != 0) { LOG(LogLevel::Error) << "Could not create .mod file"; exit(-1); } fprintf(modFile, "name = \"Converted - %s\"\n", Configuration::getOutputName().c_str()); fprintf(modFile, "path = mod/%s\"\n", Configuration::getOutputName().c_str()); fprintf(modFile, "user_dir = \"%s_user_dir\"\n", Configuration::getOutputName().c_str()); fprintf(modFile, "replace = \"history/countries\"\n"); fprintf(modFile, "replace = \"history/diplomacy\"\n"); fprintf(modFile, "replace = \"history/provinces\"\n"); fprintf(modFile, "replace = \"script\"\n"); fprintf(modFile, "replace_path = \"events\"\n"); fprintf(modFile, "replace_path = \"decisions\"\n"); fclose(modFile); string renameCommand = "move /Y output\\output output\\" + Configuration::getOutputName(); // the command to rename the mod correctly system(renameCommand.c_str()); LOG(LogLevel::Info) << "Copying flags"; destWorld.copyFlags(sourceWorld, countryMap); LOG(LogLevel::Info) << "Outputting world"; destWorld.output(); LOG(LogLevel::Info) << "* Conversion complete *"; return 0; }