diff --git a/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp b/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp index 3772b500..fbd1add2 100644 --- a/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp +++ b/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp @@ -1953,6 +1953,7 @@ void __fastcall patchesForGame::onEvent(DWORD** vTab, DWORD arg2) { minorSettlementDb::load(); eopSettlementDataDb::get()->onGameLoaded(); + eopFortDataDb::get()->onGameLoaded(); //eopCharacterDataDb::get()->onGameLoaded(); } else if (eventCode == conflictPhaseCommenced) @@ -2073,6 +2074,7 @@ void __fastcall patchesForGame::onLoadSaveFile(UNICODE_STRING**& savePath) minorSettlementDb::clear(); stratModelsChange::disableChecker(); eopSettlementDataDb::get()->onGameLoad(files); + eopFortDataDb::get()->onGameLoad(files); eopCharacterDataDb::get()->onGameLoad(files); gameEvents::onLoadGamePl(&files); plannedRetreatRoute::onGameLoad(files); @@ -2093,6 +2095,8 @@ void __fastcall patchesForGame::onSaveGame(UNICODE_STRING**& savePath) files.push_back(retreatsFile); if (const std::string settlementData = eopSettlementDataDb::get()->onGameSave(); !settlementData.empty()) files.push_back(settlementData); + if (const std::string fortData = eopFortDataDb::get()->onGameSave(); !fortData.empty()) + files.push_back(fortData); if (const std::string characterData = eopCharacterDataDb::get()->onGameSave(); !characterData.empty()) files.push_back(characterData); techFuncs::saveGameMakeArchive(savePath, files); diff --git a/M2TWEOP Code/M2TWEOP library/stratModelsChange.cpp b/M2TWEOP Code/M2TWEOP library/stratModelsChange.cpp index 84b7c04a..9ad3cb8f 100644 --- a/M2TWEOP Code/M2TWEOP library/stratModelsChange.cpp +++ b/M2TWEOP Code/M2TWEOP library/stratModelsChange.cpp @@ -4,6 +4,7 @@ #include "functionsOffsets.h" #include "dataOffsets.h" #include "character.h" +#include "fort.h" #include "gameHelpers.h" #include "strategyMap.h" @@ -97,7 +98,8 @@ namespace stratModelsChange if (const auto tile = stratMapHelpers::getTile(x, y); tile->getFort()) { fortEntryCount++; - rec->isFort = true; + rec->isFort = true; + eopFortDataDb::get()->addFortData(x, y, modelId, modelId2); } else if (const auto sett = tile->getSettlement(); sett) { diff --git a/M2TWEOP Code/M2TWEOP library/types/fort.cpp b/M2TWEOP Code/M2TWEOP library/types/fort.cpp index c8f31059..5147bc13 100644 --- a/M2TWEOP Code/M2TWEOP library/types/fort.cpp +++ b/M2TWEOP Code/M2TWEOP library/types/fort.cpp @@ -19,6 +19,9 @@ #include "gameHelpers.h" #include "strategyMap.h" #include "rebelFactions.h" +#include "stratModelsChange.h" + +eopFortDataDb* eopFortDataDb::m_Instance = new eopFortDataDb(); namespace fortHelpers { @@ -116,6 +119,10 @@ namespace fortHelpers void deleteFort(const factionStruct* fac, fortStruct* fort) { + if (!fort) + return; + if (eopFortDataDb::get()->getFortData(fort->xCoord, fort->yCoord)) + eopFortDataDb::get()->removeFortData(fort->xCoord, fort->yCoord); fortStruct* delFort = fort; const factionStruct* delFaction = fac; DWORD funcB = codes::offsets.deleteFortFuncOne; @@ -356,3 +363,85 @@ character* fortStruct::getCharacter(const int index) const auto tile = stratMapHelpers::getTile(xCoord, yCoord); return tile->getTileCharacterAtIndex(index); } + +eopFortData* eopFortDataDb::getFortData(const int x, const int y) +{ + const std::string identifier = std::to_string(x) + "_" + std::to_string(y); + if (const auto it = m_FortData.find(identifier); it != m_FortData.end()) + return it->second.get(); + return nullptr; +} + +void eopFortDataDb::addFortData(int x, int y, int modelId, int modelIdWalls) +{ + const std::string identifier = std::to_string(x) + "_" + std::to_string(y); + m_FortData.insert_or_assign(identifier, std::make_shared(x, y, modelId, modelIdWalls)); +} + +void eopFortDataDb::removeFortData(const int x, const int y) +{ + const std::string identifier = std::to_string(x) + "_" + std::to_string(y); + if (const auto it = m_FortData.find(identifier); it != m_FortData.end()) + m_FortData.erase(it); +} + +std::string eopFortDataDb::onGameSave() +{ + std::string fPath = gameHelpers::getModPath(); + fPath += "\\eopData\\TempSaveData"; + std::string outFile = fPath; + outFile += "\\fortData.json"; + ofstream f1(outFile); + const jsn::json json = serialize(); + f1 << setw(4) << json; + f1.close(); + return outFile; +} + +void eopFortDataDb::onGameLoad(const std::vector& filePaths) +{ + for (auto& path : filePaths) + { + if (path.find("fortData.json") == string::npos) + continue; + jsn::json json; + try + { + std::ifstream file(path); + file >> json; + file.close(); + } + catch (jsn::json::parse_error& e) + { + MessageBoxA(nullptr, e.what(), "Warning!", MB_APPLMODAL | MB_SETFOREGROUND); + } + try + { + deserialize(json); + m_Initialized = true; + } + catch (jsn::json::exception& e) + { + MessageBoxA(nullptr, e.what(), "Warning!", MB_APPLMODAL | MB_SETFOREGROUND); + } + return; + } +} + +void eopFortDataDb::onGameLoaded() +{ + const auto campaign = campaignHelpers::getCampaignData(); + if (!campaign) + return; + const auto fortNum = campaign->fortsNum; + for (int i = 0; i < fortNum; i++) + { + const auto fort = campaign->fortsArray[i]; + if (!fort) + continue; + if (const auto fortData = getFortData(fort->xCoord, fort->yCoord); fortData && fortData->modelId != -1) + { + stratModelsChange::setModel(fort->xCoord, fort->yCoord, fortData->modelId, fortData->modelIdWalls); + } + } +} diff --git a/M2TWEOP Code/M2TWEOP library/types/fort.h b/M2TWEOP Code/M2TWEOP library/types/fort.h index f34f73c5..62f15a7a 100644 --- a/M2TWEOP Code/M2TWEOP library/types/fort.h +++ b/M2TWEOP Code/M2TWEOP library/types/fort.h @@ -1,4 +1,5 @@ #pragma once +#include "json.hpp" #include "realGameTypes.h" #include "lua/sol.hpp" @@ -69,6 +70,71 @@ public : } }; +class eopFortData +{ +public: + eopFortData() = default; + eopFortData(const int x, const int y, const int modelId, const int modelIdWalls) + : xCoord(x), yCoord(y), modelId(modelId), modelIdWalls(modelIdWalls) {} + int xCoord{}; + int yCoord{}; + int modelId = -1; + int modelIdWalls = -1; + nlohmann::json serialize() + { + nlohmann::json json; + json["xCoord"] = xCoord; + json["yCoord"] = yCoord; + json["modelId"] = modelId; + json["modelIdWalls"] = modelIdWalls; + return json; + } + void deserialize(const nlohmann::json& json) + { + xCoord = json["xCoord"]; + yCoord = json["yCoord"]; + modelId = json["modelId"]; + modelIdWalls = json["modelIdWalls"]; + } +private: +}; + +class eopFortDataDb +{ +public: + static eopFortDataDb* get() { return m_Instance; } + eopFortData* getFortData(int x, int y); + void addFortData(int x, int y, int modelId, int modelIdWalls); + void removeFortData(int x, int y); + nlohmann::json serialize() + { + nlohmann::json json; + for (auto& [label, data] : m_FortData) + { + json[label] = data->serialize(); + } + return json; + } + void deserialize(const nlohmann::json& json) + { + m_FortData = std::unordered_map>(); + for (auto it = json.begin(); it != json.end(); ++it) + { + const auto data = std::make_shared(); + data->deserialize(it.value()); + m_FortData[it.key()] = data; + } + } + std::string onGameSave(); + void onGameLoad(const std::vector& filePaths); + void onGameLoaded(); + +private: + static eopFortDataDb* m_Instance; + bool m_Initialized = false; + std::unordered_map> m_FortData{}; +}; + namespace fortHelpers { void addToLua(sol::state& luaState);