From 2f6e9ae06f43ca47bddf648433f5a3f4aa7c2179 Mon Sep 17 00:00:00 2001 From: FynnTW Date: Tue, 5 Nov 2024 15:10:03 +0200 Subject: [PATCH] add tick events --- M2TWEOP Code/M2TWEOP library/Injects.cpp | 53 +++++++++++++++++ M2TWEOP Code/M2TWEOP library/Injects.h | 24 ++++++++ M2TWEOP Code/M2TWEOP library/luaPlugin.cpp | 2 +- M2TWEOP Code/M2TWEOP library/luaPlugin.h | 2 + M2TWEOP Code/M2TWEOP library/managerF.cpp | 12 ++++ .../M2TWEOP library/patchesForGame.cpp | 12 ++++ M2TWEOP Code/M2TWEOP library/patchesForGame.h | 2 + M2TWEOP Code/M2TWEOP library/types/battle.cpp | 6 +- M2TWEOP Code/M2TWEOP library/types/battle.h | 4 +- M2TWEOP Code/M2TWEOP library/types/events.cpp | 45 ++++++++++++++ M2TWEOP Code/M2TWEOP library/types/events.h | 2 + .../M2TWEOP library/types/strategyMap.cpp | 59 +++++++++++-------- .../M2TWEOP library/types/strategyMap.h | 10 ++++ 13 files changed, 202 insertions(+), 31 deletions(-) diff --git a/M2TWEOP Code/M2TWEOP library/Injects.cpp b/M2TWEOP Code/M2TWEOP library/Injects.cpp index 640ffb87..e3903c1f 100644 --- a/M2TWEOP Code/M2TWEOP library/Injects.cpp +++ b/M2TWEOP Code/M2TWEOP library/Injects.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "Injects.h" +#include "dataOffsets.h" + Injects::Injects(MemWork* mem) :AATemplate(mem) @@ -5782,6 +5784,57 @@ void onEnemyClicked::SetNewCode() delete a; } +onCampaignTick::onCampaignTick(MemWork* mem, LPVOID addr, int ver) + :AATemplate(mem), funcAddress(addr) +{ + if (ver == 2)//steam + m_adress = 0x47D5B6; + + else if (ver == 1)//kingdoms + m_adress = 0x47D1D6; +} + +void onCampaignTick::SetNewCode() +{ + const auto a = new Assembler(); + a->push(edx); + a->push(eax); + a->mov(eax, reinterpret_cast(funcAddress)); + a->call(eax); + a->mov(ecx, eax); + a->pop(eax); + a->pop(edx); + a->ret(); + m_cheatBytes = static_cast(a->make()); + delete a; +} + +onBattleTick::onBattleTick(MemWork* mem, LPVOID addr, int ver) + :AATemplate(mem), funcAddress(addr) +{ + if (ver == 2)//steam + m_adress = 0x60FE6F; + + else if (ver == 1)//kingdoms + m_adress = 0x60FABF; +} + +void onBattleTick::SetNewCode() +{ + const auto a = new Assembler(); + a->push(ecx); + a->push(edx); + a->mov(eax, reinterpret_cast(funcAddress)); + a->call(eax); + a->pop(edx); + a->pop(ecx); + a->mov(eax, dword_ptr(esi, 0x4)); + a->cmp(eax, 5); + a->ret(); + m_cheatBytes = static_cast(a->make()); + delete a; +} + onCreateMarriageOption2::onCreateMarriageOption2(MemWork* mem, LPVOID addr, int ver) :AATemplate(mem), funcAddress(addr) { diff --git a/M2TWEOP Code/M2TWEOP library/Injects.h b/M2TWEOP Code/M2TWEOP library/Injects.h index 28c29624..8b1e3038 100644 --- a/M2TWEOP Code/M2TWEOP library/Injects.h +++ b/M2TWEOP Code/M2TWEOP library/Injects.h @@ -2117,6 +2117,30 @@ class onEnemyClicked LPVOID funcAddress; }; +class onCampaignTick + :public AATemplate +{ +public: + onCampaignTick(MemWork* mem, LPVOID addr, int ver); + ~onCampaignTick() = default; + + void SetNewCode(); +private: + LPVOID funcAddress; +}; + +class onBattleTick + :public AATemplate +{ +public: + onBattleTick(MemWork* mem, LPVOID addr, int ver); + ~onBattleTick() = default; + + void SetNewCode(); +private: + LPVOID funcAddress; +}; + class onCreateMarriageOption2 :public AATemplate { diff --git a/M2TWEOP Code/M2TWEOP library/luaPlugin.cpp b/M2TWEOP Code/M2TWEOP library/luaPlugin.cpp index 5c051d81..d170bc3a 100644 --- a/M2TWEOP Code/M2TWEOP library/luaPlugin.cpp +++ b/M2TWEOP Code/M2TWEOP library/luaPlugin.cpp @@ -1075,7 +1075,7 @@ void luaPlugin::fillHashMaps() factions.insert_or_assign(std::string(faction->factionRecord->facName), faction->factionID); } const auto stratMap = stratMapHelpers::getStratMap(); - if (!stratMap) + if (!stratMap || !stratMap->isOpen) return; for (int i = 0; i < stratMap->regionsNum; i++) { diff --git a/M2TWEOP Code/M2TWEOP library/luaPlugin.h b/M2TWEOP Code/M2TWEOP library/luaPlugin.h index b023e88d..e0fde4c6 100644 --- a/M2TWEOP Code/M2TWEOP library/luaPlugin.h +++ b/M2TWEOP Code/M2TWEOP library/luaPlugin.h @@ -127,6 +127,8 @@ class luaPlugin sol::function* onChangeTurnNumFunc = nullptr; sol::function* onClickAtTile = nullptr; sol::function* onCharacterClicked = nullptr; + sol::function* onCampaignTick = nullptr; + sol::function* onBattleTick = nullptr; sol::function* onNewGameStart = nullptr; sol::function* onPluginLoad = nullptr; sol::function* onCreateSaveFile = nullptr; diff --git a/M2TWEOP Code/M2TWEOP library/managerF.cpp b/M2TWEOP Code/M2TWEOP library/managerF.cpp index 1d994c3f..3d8f96bd 100644 --- a/M2TWEOP Code/M2TWEOP library/managerF.cpp +++ b/M2TWEOP Code/M2TWEOP library/managerF.cpp @@ -922,6 +922,18 @@ void managerF::execPatches() toCreateMarriageOption2->Enable(); f1 << "Done" << '\n'; + f1 << "Start applying onCampaignTick patch" << '\n'; + onCampaignTick* toCampaignTick = new onCampaignTick(mem, (LPVOID)patchesForGame::onCampaignTick, globals::dataS.gameVersion); + toCampaignTick->SetNewCode(); + toCampaignTick->Enable(); + f1 << "Done" << '\n'; + + f1 << "Start applying onBattleTick patch" << '\n'; + onBattleTick* toBattleTick = new onBattleTick(mem, (LPVOID)patchesForGame::onBattleTick, globals::dataS.gameVersion); + toBattleTick->SetNewCode(); + toBattleTick->Enable(); + f1 << "Done" << '\n'; + //f1 << "Start applying onEnemyClicked patch" << '\n'; //onEnemyClicked* toEnemyClicked = new onEnemyClicked(mem, (LPVOID)patchesForGame::onEnemyClicked, globals::dataS.gameVersion); //toEnemyClicked->SetNewCode(); diff --git a/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp b/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp index c39769b8..7b32b776 100644 --- a/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp +++ b/M2TWEOP Code/M2TWEOP library/patchesForGame.cpp @@ -1689,6 +1689,18 @@ void __fastcall patchesForGame::onCharacterClicked(character* enemy) gameEvents::onCharacterClicked(enemy); } +DWORD patchesForGame::onCampaignTick() +{ + gameEvents::onCampaignTick(); + const auto stratMap = stratMapHelpers::getStratMap(); + return reinterpret_cast(stratMap); +} + +void patchesForGame::onBattleTick() +{ + gameEvents::onBattleTick(); +} + void __stdcall patchesForGame::afterCampaignMapLoaded() { discordManager::onCampaignMapLoaded(); diff --git a/M2TWEOP Code/M2TWEOP library/patchesForGame.h b/M2TWEOP Code/M2TWEOP library/patchesForGame.h index 53082b5d..2bd5cb83 100644 --- a/M2TWEOP Code/M2TWEOP library/patchesForGame.h +++ b/M2TWEOP Code/M2TWEOP library/patchesForGame.h @@ -123,6 +123,8 @@ class patchesForGame static unitGroup** __fastcall onGetGroupByLabel(DWORD groupLabels, char* label); static char* __fastcall onGetCultureEndTurnSound(int cultureID); static void __fastcall onCharacterClicked(character* enemy); + static DWORD __fastcall onCampaignTick(); + static void __fastcall onBattleTick(); static character* __fastcall mercenaryMovePointsGetGeneral(armyStruct* army); diff --git a/M2TWEOP Code/M2TWEOP library/types/battle.cpp b/M2TWEOP Code/M2TWEOP library/types/battle.cpp index 4a5799ba..7b48f64b 100644 --- a/M2TWEOP Code/M2TWEOP library/types/battle.cpp +++ b/M2TWEOP Code/M2TWEOP library/types/battle.cpp @@ -370,7 +370,8 @@ namespace battleHelpers @tfield int finishTimer @tfield float battleSpeed @tfield float secondsPassed - @tfield int secondsSinceBattleLoaded + @tfield int tickCount + @tfield int ticksSinceBattleStart @tfield int hidingEnabledSet @tfield fortBattleInfo fortInfo @tfield float mapWidth @@ -424,7 +425,8 @@ namespace battleHelpers typeAll.battleTable.set("inBattle", &battleDataS::inBattle); typeAll.battleTable.set("battleSpeed", &battleDataS::speed); typeAll.battleTable.set("secondsPassed", &battleDataS::secondsPassed); - typeAll.battleTable.set("secondsSinceBattleLoaded", &battleDataS::secondsSinceBattleLoaded); + typeAll.battleTable.set("tickCount", &battleDataS::tickCount); + typeAll.battleTable.set("ticksSinceBattleStart", &battleDataS::ticksSinceBattleStart); typeAll.battleTable.set("hidingEnabledSet", &battleDataS::hidingEnabledSet); typeAll.battleTable.set("mapWidthDoubled", &battleDataS::mapWidth); typeAll.battleTable.set("mapHeightDoubled", &battleDataS::mapHeight); diff --git a/M2TWEOP Code/M2TWEOP library/types/battle.h b/M2TWEOP Code/M2TWEOP library/types/battle.h index 31fb0eab..ac2e6c02 100644 --- a/M2TWEOP Code/M2TWEOP library/types/battle.h +++ b/M2TWEOP Code/M2TWEOP library/types/battle.h @@ -1445,10 +1445,10 @@ struct battleDataS { bool paused; //0x0054 char pad_0055[3]; //0x0055 float speed; //0x0058 - int ticks; + int ticksSinceBattleStart; int ticksMilliSec; float secondsPassed; //0x0064 - int32_t secondsSinceBattleLoaded; //0x0068 + int32_t tickCount; //0x0068 int finishTimer; int32_t autoResolveMode; float centreX; diff --git a/M2TWEOP Code/M2TWEOP library/types/events.cpp b/M2TWEOP Code/M2TWEOP library/types/events.cpp index f197ca9f..9edf319b 100644 --- a/M2TWEOP Code/M2TWEOP library/types/events.cpp +++ b/M2TWEOP Code/M2TWEOP library/types/events.cpp @@ -803,6 +803,23 @@ void onCharacterClicked(character* enemy) } } +void onCampaignTick() +{ + if (plugData::data.luaAll.onCampaignTick != nullptr) + { + tryLua((*plugData::data.luaAll.onCampaignTick)()); + } +} + + +void onBattleTick() +{ + if (plugData::data.luaAll.onBattleTick != nullptr) + { + tryLua((*plugData::data.luaAll.onBattleTick)()); + } +} + std::string* onSelectWorldpkgdesc(const char* selectedRec, const char* selectedGroup) { std::string tmpS; @@ -1347,6 +1364,8 @@ void luaPlugin::onPluginLoadF() @tfield onAiTurn onAiTurn @tfield onClickAtTile onClickAtTile @tfield onCharacterClicked onCharacterClicked + @tfield onCampaignTick onCampaignTick + @tfield onBattleTick onBattleTick @tfield onCampaignMapLoaded onCampaignMapLoaded @tfield onCreateSaveFile onCreateSaveFile @tfield onLoadSaveFile onLoadSaveFile @@ -4217,6 +4236,32 @@ void luaPlugin::onPluginLoadF() onCharacterClicked = new sol::function(luaState["onCharacterClicked"]); checkLuaFunc(&onCharacterClicked); + /*** + Called on campaign tick. + + @function onCampaignTick + @usage + + function onCampaignTick() + --something here + end + */ + onCampaignTick = new sol::function(luaState["onCampaignTick"]); + checkLuaFunc(&onCampaignTick); + + /*** + Called on battle tick. + + @function onBattleTick + @usage + + function onBattleTick() + --something here + end + */ + onBattleTick = new sol::function(luaState["onBattleTick"]); + checkLuaFunc(&onBattleTick); + /*** Called after loading the campaign map diff --git a/M2TWEOP Code/M2TWEOP library/types/events.h b/M2TWEOP Code/M2TWEOP library/types/events.h index 0bc53437..04a9b7f0 100644 --- a/M2TWEOP Code/M2TWEOP library/types/events.h +++ b/M2TWEOP Code/M2TWEOP library/types/events.h @@ -237,6 +237,8 @@ namespace gameEvents void onClickAtTile(int x, int y); void onCharacterClicked(character* enemy); + void onCampaignTick(); + void onBattleTick(); std::string * onSelectWorldpkgdesc(const char* selectedRec, const char* selectedGroup); int onFortificationLevelS(settlementStruct * settlement, bool* isCastle, bool* isChanged); float onCalculateUnitValue(eduEntry* entry, float value); diff --git a/M2TWEOP Code/M2TWEOP library/types/strategyMap.cpp b/M2TWEOP Code/M2TWEOP library/types/strategyMap.cpp index 47ffa738..45302891 100644 --- a/M2TWEOP Code/M2TWEOP library/types/strategyMap.cpp +++ b/M2TWEOP Code/M2TWEOP library/types/strategyMap.cpp @@ -30,7 +30,7 @@ minorSettlementBalance* minorSettlementDb::m_BalanceModifiers = new minorSettlem oneTile* landingTile::getTile() { const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[tileId]; } @@ -38,7 +38,7 @@ oneTile* landingTile::getTile() oneTile* landingPoint::getTile() { const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[tileIndex]; } @@ -163,7 +163,7 @@ oneTileDouble* oneTile::tileToDoubleTile() void regionStruct::changeRegionName(const char* newName) { - const auto nameMem = new UNICODE_STRING*; + const auto nameMem = techFuncs::createGameClass(); localizedRegionName = nameMem; gameStringHelpers::createUniString(localizedRegionName, newName); eopSettlementDataDb::get()->getSettlementData(regionID, 0)->regionName = newName; @@ -171,14 +171,14 @@ void regionStruct::changeRegionName(const char* newName) void regionStruct::changeRegionSettlementName(const char* newName) { - const auto nameMem = new UNICODE_STRING*; + const auto nameMem = techFuncs::createGameClass(); localizedSettlementName = nameMem; gameStringHelpers::createUniString(localizedSettlementName, newName); } void regionStruct::changeRebelsName(const char* newName) { - const auto nameMem = new UNICODE_STRING*; + const auto nameMem = techFuncs::createGameClass(); localizedRebelsName = nameMem; gameStringHelpers::createUniString(localizedRebelsName, newName); eopSettlementDataDb::get()->getSettlementData(regionID, 0)->regionRebelsName = newName; @@ -203,7 +203,7 @@ void regionStruct::setHiddenResource(const char* name, const bool enable) std::pair oneTile::getTileCoords() { const stratMap* map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return {-1, -1}; const int index = this - map->tilesArr; const int y = index / map->mapWidth; @@ -214,7 +214,7 @@ std::pair oneTile::getTileCoords() int oneTile::getTileX() { const stratMap* map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return -1; const int index = this - map->tilesArr; const int y = index / map->mapWidth; @@ -242,7 +242,7 @@ armyStruct* oneTile::getArmy(const bool onlyLead) int oneTile::getTileY() { const stratMap* map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return -1; const int index = this - map->tilesArr; return index / map->mapWidth; @@ -251,7 +251,7 @@ int oneTile::getTileY() oneTile* landingPoint::getSeaTile() { const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[seaTileIndex]; } @@ -261,7 +261,7 @@ oneTile* neighbourRegion::getBorderTile(const int index) if (index < 0 || index >= borderTilesCount) return nullptr; const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[borderTiles[index]]; } @@ -271,7 +271,7 @@ oneTile* neighbourRegion::getFrontierTile(const int index) if (index < 0 || index >= frontierTilesCount) return nullptr; const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[frontierTiles[index]]; } @@ -281,7 +281,7 @@ oneTile* neighbourRegion::getAmbushTile(const int index) if (index < 0 || index >= ambushTilesCount) return nullptr; const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[ambushTiles[index]]; } @@ -291,7 +291,7 @@ oneTile* neighbourRegion::getDeepFrontierTile(const int index) if (index < 0 || index >= deepFrontierTilesCount) return nullptr; const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[deepFrontierTiles[index]]; } @@ -301,7 +301,7 @@ oneTile* neighbourRegion::getBorderCrossing(const int index) if (index < 0 || index >= passableTilesCount) return nullptr; const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[passableTiles[index]]; } @@ -423,7 +423,7 @@ oneTile* regionStruct::getPatrolPoint(const int index) if (index < 0 || index >= patrolPointsCount) return nullptr; const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[patrolPoints[index]]; } @@ -433,7 +433,7 @@ oneTile* regionStruct::getDevastatedTile(const int index) if (index < 0 || index >= devastatedTilesCount) return nullptr; const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[devastatedTiles[index]]; } @@ -443,7 +443,7 @@ oneTile* regionStruct::getTile(int index) if (index < 0 || index >= tileCount) return nullptr; const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[tiles[index]]; } @@ -453,7 +453,7 @@ oneTile* regionStruct::getFertileTile(int index) if (index < 0 || index >= fertileTilesCount) return nullptr; const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[fertileTiles[index]]; } @@ -463,7 +463,7 @@ oneTile* regionStruct::getTileBorderingEdgeOfMap(int index) if (index < 0 || index >= tilesBorderingEdgeOfMapCount) return nullptr; const auto map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return nullptr; return &map->tilesArr[tilesBorderingEdgeOfMap[index]]; } @@ -471,7 +471,7 @@ oneTile* regionStruct::getTileBorderingEdgeOfMap(int index) int oneTile::getTileHeatValue() { const stratMap* map = stratMapHelpers::getStratMap(); - if (!map) + if (!map || !map->isOpen) return -1; const auto climate = getTileClimate(); return map->climates->climateArray[climate].heatValue; @@ -560,7 +560,7 @@ namespace stratMapHelpers std::pair convertTileCoords(const DWORD arrayIndex) { const auto map = getStratMap(); - if (!map) + if (!map || !map->isOpen) return {-1, -1}; const int x = arrayIndex % map->mapWidth; const int y = arrayIndex / map->mapWidth; @@ -569,14 +569,14 @@ namespace stratMapHelpers regionStruct* getRegion(const int index) { - if (stratMap* map = getStratMap(); map) + if (stratMap* map = getStratMap(); map && map->isOpen) return map->getRegion(index); return nullptr; } oneTile* getTile(const int x, const int y) { - if (stratMap* map = getStratMap(); map) + if (stratMap* map = getStratMap(); map && map->isOpen) return map->getTile(x, y); return nullptr; } @@ -594,8 +594,8 @@ namespace stratMapHelpers float getTileMoveCost(int x, int y, int destX, int destY) { - if (const auto map = getStratMap(); - x < 0 || x > map->mapWidth || y < 0 || y > map->mapHeight) + if (const auto map = getStratMap(); !map || !map->isOpen || + (x < 0 || x > map->mapWidth || y < 0 || y > map->mapHeight)) return -1; int start[2] = {x, y}; int end[2] = {destX, destY}; @@ -605,6 +605,8 @@ namespace stratMapHelpers std::queue> getNeighbourTiles(int x, int y) { const auto map = getStratMap(); + if (!map || !map->isOpen) + return {}; std::queue> neighbours; if (x - 1 < map->mapWidth - 1 && x - 1 >= 0) neighbours.emplace(x - 1, y); @@ -702,7 +704,10 @@ namespace stratMapHelpers return false; if (*isStratMap == 0) return false; - return true; + const auto map = getStratMap(); + if (map == nullptr) + return false; + return map->isOpen; } std::tuple getStratHoveredCoords() @@ -876,6 +881,7 @@ namespace stratMapHelpers /*** Basic strat map table. + @tfield bool isLoaded @tfield int mapWidth @tfield int mapHeight @tfield int regionsNum @@ -904,6 +910,7 @@ namespace stratMapHelpers */ typeAll.stratMap = luaState.new_usertype("stratMap"); typeAll.stratMap.set("mapWidth", &stratMap::mapWidth); + typeAll.stratMap.set("isLoaded", &stratMap::isOpen); typeAll.stratMap.set("mapHeight", &stratMap::mapHeight); typeAll.stratMap.set("regionsNum", &stratMap::regionsNum); typeAll.stratMap.set("volcanoesNum", &stratMap::volcanoesNum); diff --git a/M2TWEOP Code/M2TWEOP library/types/strategyMap.h b/M2TWEOP Code/M2TWEOP library/types/strategyMap.h index 19c8a29a..c2552622 100644 --- a/M2TWEOP Code/M2TWEOP library/types/strategyMap.h +++ b/M2TWEOP Code/M2TWEOP library/types/strategyMap.h @@ -861,26 +861,36 @@ struct stratMap { public: regionStruct* getRegion(const int index) { + if (!isOpen) + return nullptr; if (index < 0 || index >= regionsNum) return nullptr; return ®ions[index]; } oneTile* getTile(const int x, const int y) { + if (!isOpen) + return nullptr; if (x < 0 || x >= mapWidth || y < 0 || y >= mapHeight) return nullptr; return &tilesArr[y * mapWidth + x]; } coordPair* getVolcanoCoords(const int index) { + if (!isOpen) + return nullptr; return &volcanoes[index]; } coordPair* getLandConnection(const int index) { + if (!isOpen) + return nullptr; return &landMassConnections[index]; } landMass* getLandMass(const int index) { + if (!isOpen) + return nullptr; return &landMasses[index]; } };