From 75cdd9a978c41e2ac7e28ad5856526093d77e599 Mon Sep 17 00:00:00 2001 From: FynnTW Date: Tue, 8 Oct 2024 16:01:07 +0300 Subject: [PATCH] hash lookup traits & ancillaries --- M2TWEOP Code/M2TWEOP library/dataOffsets.cpp | 4 + M2TWEOP Code/M2TWEOP library/dataOffsets.h | 2 + M2TWEOP Code/M2TWEOP library/luaPlugin.cpp | 17 ++++ M2TWEOP Code/M2TWEOP library/luaPlugin.h | 4 + .../M2TWEOP library/patchesForGame.cpp | 2 +- .../M2TWEOP library/types/characterRecord.cpp | 97 +++++++------------ .../M2TWEOP library/types/characterRecord.h | 18 ++++ 7 files changed, 82 insertions(+), 62 deletions(-) diff --git a/M2TWEOP Code/M2TWEOP library/dataOffsets.cpp b/M2TWEOP Code/M2TWEOP library/dataOffsets.cpp index f0759f33..92c55027 100644 --- a/M2TWEOP Code/M2TWEOP library/dataOffsets.cpp +++ b/M2TWEOP Code/M2TWEOP library/dataOffsets.cpp @@ -96,6 +96,8 @@ void dataOffsets::initDataOffsets(int gameVer) offsets.eventManager = 0x16F0BC8; offsets.uiStratUiV2 = 0x2CB62FC; offsets.currentRegion = 0x18FD970; + offsets.traitDb = 0x1666F90; + offsets.ancillaryDb = 0x1666F40; offsets.fortVtbl = 0x13362F4; @@ -145,6 +147,8 @@ void dataOffsets::initDataOffsets(int gameVer) offsets.perfectSpy = 0x016A7CC4; offsets.portraitDatabase = 0x018671D0; + offsets.traitDb = 0x161F0B8; + offsets.ancillaryDb = 0x161F068; offsets.cultureDatabase = 0x0161F0F0; offsets.loadGameHandler = 0x02C6DC60; diff --git a/M2TWEOP Code/M2TWEOP library/dataOffsets.h b/M2TWEOP Code/M2TWEOP library/dataOffsets.h index 73435c26..ddaa6b3b 100644 --- a/M2TWEOP Code/M2TWEOP library/dataOffsets.h +++ b/M2TWEOP Code/M2TWEOP library/dataOffsets.h @@ -59,6 +59,8 @@ class dataOffsets DWORD edbDataStart = NULL; DWORD religionDatabase = NULL; DWORD portraitDatabase = NULL; + DWORD traitDb = NULL; + DWORD ancillaryDb = NULL; DWORD cultureDatabase = NULL; DWORD loadGameHandler = NULL; DWORD selectedEra = NULL; diff --git a/M2TWEOP Code/M2TWEOP library/luaPlugin.cpp b/M2TWEOP Code/M2TWEOP library/luaPlugin.cpp index 33185f8d..de0d8c9b 100644 --- a/M2TWEOP Code/M2TWEOP library/luaPlugin.cpp +++ b/M2TWEOP Code/M2TWEOP library/luaPlugin.cpp @@ -1017,5 +1017,22 @@ void luaPlugin::fillHashMapsNonCampaign() buildingLevelLines.insert_or_assign(std::string(level->name), building->buildingID); } } + + const auto traitsDb = characterRecordHelpers::getTraitDb(); + const int traitNum = traitsDb->traitsNum; + for (int i = 0; i < traitNum; i++) + { + const auto trait = &traitsDb->traits[i]; + traits.insert_or_assign(std::string(trait->name), i); + } + + const auto ancDb = characterRecordHelpers::getAncillaryDb(); + const int ancNum = ancDb->ancillariesNum; + for (int i = 0; i < ancNum; i++) + { + const auto anc = &ancDb->ancillaries[i]; + ancillaries.insert_or_assign(std::string(anc->ancName), i); + } + hashNonCampaignLoaded = true; } diff --git a/M2TWEOP Code/M2TWEOP library/luaPlugin.h b/M2TWEOP Code/M2TWEOP library/luaPlugin.h index ba4636d5..5625ad41 100644 --- a/M2TWEOP Code/M2TWEOP library/luaPlugin.h +++ b/M2TWEOP Code/M2TWEOP library/luaPlugin.h @@ -107,6 +107,10 @@ class luaPlugin }; std::unordered_map buildingLevels = { }; + std::unordered_map traits = { + }; + std::unordered_map ancillaries = { + }; sol::function* onCampaignMapLoaded = nullptr; sol::function* onRemoveFromUnitQueue = nullptr; sol::function* onReadGameDbsAtStart = nullptr; diff --git a/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp b/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp index 2b045fce..087400c4 100644 --- a/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp +++ b/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp @@ -1702,7 +1702,7 @@ void __stdcall patchesForGame::onGameInit() cultures::eopPortraitDb::createEopPortraitDb(); discordManager::menuLoaded(); gameEvents::onGameInit(); - const auto edb = eopBuildings::getEdb(); + *reinterpret_cast(dataOffsets::offsets.bugReport) = true; } void __stdcall patchesForGame::onUnloadCampaign() diff --git a/M2TWEOP Code/M2TWEOP library/types/characterRecord.cpp b/M2TWEOP Code/M2TWEOP library/types/characterRecord.cpp index 327739b0..26f9d653 100644 --- a/M2TWEOP Code/M2TWEOP library/types/characterRecord.cpp +++ b/M2TWEOP Code/M2TWEOP library/types/characterRecord.cpp @@ -13,6 +13,7 @@ #include "cultures.h" #include "faction.h" #include "gameHelpers.h" +#include "luaPlugin.h" #include "stratModelsChange.h" #include "techFuncs.h" #include "unit.h" @@ -191,13 +192,18 @@ namespace characterRecordHelpers { if (ancName.empty()) return nullptr; - return GAME_FUNC(ancillary*(__cdecl*)(const char*), findAncillary)(ancName.c_str()); + if (plugData::data.luaAll.ancillaries.empty()) + plugData::data.luaAll.fillHashMapsNonCampaign(); + const auto ancDb = getAncillaryDb(); + if (const auto ancIndex = plugData::data.luaAll.ancillaries.find(ancName); ancIndex != plugData::data.luaAll.ancillaries.end()) + return &ancDb->ancillaries[ancIndex->second]; + return nullptr; } int addAncillaryName(characterRecord* character, const std::string& ancName) { ancillary* anc = findAncillary(ancName); - if (anc == nullptr) + if (!anc) return 0; return addAncillary(character, anc); } @@ -331,77 +337,46 @@ namespace characterRecordHelpers return &level->effects[index]; } + traitDb* getTraitDb() + { + return reinterpret_cast(dataOffsets::offsets.traitDb); + } + + ancillaryDb* getAncillaryDb() + { + return reinterpret_cast(dataOffsets::offsets.ancillaryDb); + } + traitEntry* findTrait(const std::string& name) { - const auto hashed = reinterpret_cast(gameStringHelpers::createHashedString(name.c_str())); - return GAME_FUNC(traitEntry*(__cdecl*)(const char*, int), getTrait)(hashed->name, hashed->hash); + if (plugData::data.luaAll.traits.empty()) + plugData::data.luaAll.fillHashMapsNonCampaign(); + const auto traitsDb = getTraitDb(); + if (const auto traitIndex = plugData::data.luaAll.traits.find(name); traitIndex != plugData::data.luaAll.traits.end()) + return &traitsDb->traits[traitIndex->second]; + return nullptr; } void addTrait(characterRecord* character, const char* traitName, int traitLevel) { - DWORD adrFunc = codes::offsets.getTrait; - char** cryptS = gameStringHelpers::createHashedString(traitName); - void* resTrait = nullptr; - auto oneArg = cryptS[0]; - auto nextArg = cryptS[1]; - _asm - { - push nextArg - push oneArg - - mov eax, adrFunc - call eax - - mov resTrait, eax - add esp, 0x8 - } - if (resTrait == nullptr) + const auto traitsDb = getTraitDb(); + traitEntry* trait = nullptr; + if (const auto traitIndex = plugData::data.luaAll.traits.find(traitName); traitIndex != plugData::data.luaAll.traits.end()) + trait = &traitsDb->traits[traitIndex->second]; + if (!trait) return; - - //set trait - adrFunc = codes::offsets.addTrait; - _asm - { - push 1 - push traitLevel - push resTrait - mov ecx, character - mov eax, adrFunc - call eax - } + GAME_FUNC(void(__thiscall*)(characterRecord*, traitEntry*, int, bool), addTrait)(character, trait, traitLevel, true); } void removeTrait(characterRecord* character, const char* traitName) { - DWORD adrFunc = codes::offsets.getTrait; - char** cryptS = gameStringHelpers::createHashedString(traitName); - void* resTrait = nullptr; - auto oneArg = cryptS[0]; - auto nextArg = cryptS[1]; - _asm - { - push nextArg - push oneArg - - mov eax, adrFunc - call eax - - mov resTrait, eax - add esp, 0x8 - } - if (resTrait == nullptr) + const auto traitsDb = getTraitDb(); + traitEntry* trait = nullptr; + if (const auto traitIndex = plugData::data.luaAll.traits.find(traitName); traitIndex != plugData::data.luaAll.traits.end()) + trait = &traitsDb->traits[traitIndex->second]; + if (!trait) return; - - //set trait - adrFunc = codes::offsets.removeTrait; - _asm - { - push resTrait - mov ecx, character - - mov eax, adrFunc - call eax - } + GAME_FUNC(void(__thiscall*)(characterRecord*, traitEntry*), removeTrait)(character, trait); } #pragma endregion Trait helpers diff --git a/M2TWEOP Code/M2TWEOP library/types/characterRecord.h b/M2TWEOP Code/M2TWEOP library/types/characterRecord.h index 752a486f..4c7bcb9d 100644 --- a/M2TWEOP Code/M2TWEOP library/types/characterRecord.h +++ b/M2TWEOP Code/M2TWEOP library/types/characterRecord.h @@ -74,6 +74,22 @@ struct traitEntry { /* char* at 0x4 */ } }; +struct traitDb +{ + traitEntry* traits; + int traitsSize; + int traitsNum; +}; + +struct ancillaryDb +{ +public: + struct ancillary *ancillaries; //0x0000 + int32_t ancillariesSize; //0x0004 + int32_t ancillariesNum; //0x0008 +}; //Size: 0x129F0 + + struct traitContainer { struct trait* trait; struct traitContainer* prev; @@ -527,6 +543,8 @@ namespace characterRecordHelpers void namedCharSetLocalizedNicknameForSave(characterRecord* genChar, const char* str); void setHeir(characterRecord* gen, bool isJustSet); std::string getEopSetModel(); + traitDb* getTraitDb(); + ancillaryDb* getAncillaryDb(); int addAncillaryName(characterRecord* character, const std::string& ancName); int addAncillary(characterRecord* character, ancillary* anc);