mirror of
https://github.com/EricPlayZ/EGameTools.git
synced 2025-07-18 17:37:53 +08:00
changed VarManagerBase alongside the other var management classes
This commit is contained in:
@ -13,10 +13,10 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="deps\memscan\memscan.c" />
|
||||
<ClCompile Include="deps\memscan\util\util.c" />
|
||||
<ClCompile Include="Offsets.cpp" />
|
||||
<ClCompile Include="SaveGameManager.cpp" />
|
||||
<ClCompile Include="src\ClassHelpers.cpp" />
|
||||
<ClCompile Include="src\Core\Core.cpp" />
|
||||
<ClCompile Include="src\Core\SaveGameManager.cpp" />
|
||||
<ClCompile Include="src\Core\SteamAPI.cpp" />
|
||||
<ClCompile Include="src\dllmain.cpp" />
|
||||
<ClCompile Include="src\Engine\CBulletPhysicsCharacter.cpp" />
|
||||
<ClCompile Include="src\Engine\CGame.cpp" />
|
||||
@ -34,6 +34,9 @@
|
||||
<ClCompile Include="src\Engine\CVideoSettings.cpp" />
|
||||
<ClCompile Include="src\Engine\Engine_Misc.cpp" />
|
||||
<ClCompile Include="src\Engine\VarBase.cpp" />
|
||||
<ClCompile Include="src\Engine\VarManagerBase.cpp" />
|
||||
<ClCompile Include="src\Engine\VarMapBase.cpp" />
|
||||
<ClCompile Include="src\Engine\VarRef.cpp" />
|
||||
<ClCompile Include="src\GamePH\CoPlayerRestrictions.cpp" />
|
||||
<ClCompile Include="src\GamePH\DayNightCycle.cpp" />
|
||||
<ClCompile Include="src\GamePH\FreeCamera.cpp" />
|
||||
@ -55,6 +58,7 @@
|
||||
<ClCompile Include="src\GamePH\TimeWeather\CSystem.cpp" />
|
||||
<ClCompile Include="src\GamePH\TPPCameraDI.cpp" />
|
||||
<ClCompile Include="src\Mtx34.cpp" />
|
||||
<ClCompile Include="src\Offsets.cpp" />
|
||||
<ClCompile Include="src\Utils\Files.cpp" />
|
||||
<ClCompile Include="src\Utils\Hook.cpp" />
|
||||
<ClCompile Include="src\Utils\Memory.cpp" />
|
||||
@ -62,13 +66,10 @@
|
||||
<ClCompile Include="src\Utils\Sigscan.cpp" />
|
||||
<ClCompile Include="src\Utils\Time.cpp" />
|
||||
<ClCompile Include="src\Utils\Values.cpp" />
|
||||
<ClCompile Include="src\Utils\WinMemory.cpp" />
|
||||
<ClCompile Include="src\Vec2.cpp" />
|
||||
<ClCompile Include="src\Vec3.cpp" />
|
||||
<ClCompile Include="src\Vec4.cpp" />
|
||||
<ClCompile Include="SteamAPI.cpp" />
|
||||
<ClCompile Include="VarManagerBase.cpp" />
|
||||
<ClCompile Include="VarMapBase.cpp" />
|
||||
<ClCompile Include="WinMemory.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\EGSDK\ClassHelpers.h" />
|
||||
@ -95,6 +96,7 @@
|
||||
<ClInclude Include="include\EGSDK\Engine\VarBase.h" />
|
||||
<ClInclude Include="include\EGSDK\Engine\VarManagerBase.h" />
|
||||
<ClInclude Include="include\EGSDK\Engine\VarMapBase.h" />
|
||||
<ClInclude Include="include\EGSDK\Engine\VarRef.h" />
|
||||
<ClInclude Include="include\EGSDK\Exports.h" />
|
||||
<ClInclude Include="include\EGSDK\GamePH\CameraFPPDI.h" />
|
||||
<ClInclude Include="include\EGSDK\GamePH\CoBaseCameraProxy.h" />
|
||||
|
@ -133,21 +133,9 @@
|
||||
<ClCompile Include="src\GamePH\CoPlayerRestrictions.cpp">
|
||||
<Filter>src\GamePH</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SaveGameManager.cpp">
|
||||
<Filter>src\Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SteamAPI.cpp">
|
||||
<Filter>src\Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Offsets.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Engine\CVars.cpp">
|
||||
<Filter>src\Engine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WinMemory.cpp">
|
||||
<Filter>src\Utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Engine\IBaseCamera.cpp">
|
||||
<Filter>src\Engine</Filter>
|
||||
</ClCompile>
|
||||
@ -166,15 +154,30 @@
|
||||
<ClCompile Include="src\Vec2.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VarMapBase.cpp">
|
||||
<Filter>src\Engine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VarManagerBase.cpp">
|
||||
<Filter>src\Engine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Engine\VarBase.cpp">
|
||||
<Filter>src\Engine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Core\SaveGameManager.cpp">
|
||||
<Filter>src\Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Core\SteamAPI.cpp">
|
||||
<Filter>src\Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Offsets.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Utils\WinMemory.cpp">
|
||||
<Filter>src\Utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Engine\VarRef.cpp">
|
||||
<Filter>src\Engine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Engine\VarMapBase.cpp">
|
||||
<Filter>src\Engine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Engine\VarManagerBase.cpp">
|
||||
<Filter>src\Engine</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="include">
|
||||
@ -419,5 +422,8 @@
|
||||
<ClInclude Include="include\EGSDK\Engine\VarBase.h">
|
||||
<Filter>include\Engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\EGSDK\Engine\VarRef.h">
|
||||
<Filter>include\Engine</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,137 +0,0 @@
|
||||
#include <EGSDK\Offsets.h>
|
||||
#include <EGSDK\Engine\CBulletPhysicsCharacter.h>
|
||||
#include <EGSDK\Engine\CGame.h>
|
||||
#include <EGSDK\Engine\CVideoSettings.h>
|
||||
#include <EGSDK\GamePH\CoPlayerRestrictions.h>
|
||||
#include <EGSDK\GamePH\FreeCamera.h>
|
||||
#include <EGSDK\GamePH\GameDI_PH.h>
|
||||
#include <EGSDK\GamePH\LocalClientDI.h>
|
||||
#include <EGSDK\GamePH\PlayerDI_PH.h>
|
||||
#include <EGSDK\GamePH\PlayerState.h>
|
||||
#include <EGSDK\GamePH\SessionCooperativeDI.h>
|
||||
#include <EGSDK\ClassHelpers.h>
|
||||
|
||||
namespace EGSDK {
|
||||
bool OffsetManager::initialized = false;
|
||||
|
||||
void OffsetManager::InitializeOffsetsAndPatterns() {
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
AddOffsets(11200, {
|
||||
{ "OnPostUpdate", 0x378 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerPos2), 0x880 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerPos), 0x898 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerDownwardVelocity), 0xC18 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CGame::pCLevel), 0x380 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CVideoSettings::extraFOV), 0x78 },
|
||||
|
||||
{ GetOffsetNameFromClassMember(&GamePH::CoPlayerRestrictions::flags), 0x1C0 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::enableSpeedMultiplier1), 0x4C },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::enableSpeedMultiplier2), 0x4D },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::speedMultiplier), 0x150 },
|
||||
//{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::mouseSensitivityMultiplier), 0x1A0 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::GameDI_PH::blockPauseGameOnPlayerAfk), 0x830 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::GameDI_PH::pSessionCooperativeDI), 0xE8 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::LocalClientDI::pPlayerDI_PH), 0x88 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::pCoPhysicsProperty), 0xE8 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::pInventoryContainerDI), 0x550 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::nextPlayerOrientation), 0xC68 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::restrictionsEnabled), 0x2CF0 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::enableTPPModel1), 0x2DC1 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::enableTPPModel2), 0x2DC2 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerState::playerVariables), 0x280 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::SessionCooperativeDI::pLocalClientDI), 0xD10 },
|
||||
});
|
||||
AddOffsets(12001, {
|
||||
{ "OnPostUpdate", 0x3A8 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerPos2), 0xCB8 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerPos), 0xCD0 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerDownwardVelocity), 0x1050 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CGame::pCLevel), 0x390 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CVideoSettings::extraFOV), 0x7C },
|
||||
|
||||
{ GetOffsetNameFromClassMember(&GamePH::CoPlayerRestrictions::flags), 0x1F0 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::enableSpeedMultiplier1), 0x42 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::enableSpeedMultiplier2), 0x43 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::speedMultiplier), 0x1CC },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::GameDI_PH::blockPauseGameOnPlayerAfk), 0x910 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::GameDI_PH::pSessionCooperativeDI), 0x130 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::LocalClientDI::pPlayerDI_PH), 0x90 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::pCoPhysicsProperty), 0xF0 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::pInventoryContainerDI), 0x470 },
|
||||
//{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::pPlayerFppVis_PH), 0x420 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::nextPlayerOrientation), 0xB88 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::restrictionsEnabled), 0x3520 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::enableTPPModel1), 0x35E9 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::enableTPPModel2), 0x35EA },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerState::playerVariables), 0x300 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::SessionCooperativeDI::pLocalClientDI), 0xE08 },
|
||||
});
|
||||
|
||||
AddPatterns(11200, {
|
||||
{ "LoadPlayerVars", { "40 55 53 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 33 FF", Utils::SigScan::PatternType::Address } },
|
||||
{ "PlayerState", { "48 8B 3D [?? ?? ?? ?? 4C 8B EA", Utils::SigScan::PatternType::RelativePointer } },
|
||||
{ "SaveGameCRCBoolCheck", { "FF 50 ?? [40 22 FB 0F 85 ?? ?? ?? ?? 0F B6 05 ?? ?? ?? ?? 48 8D 1D", Utils::SigScan::PatternType::Address } },
|
||||
{ "IsNotOutOfMapBounds", { "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 4C 8B C2", Utils::SigScan::PatternType::Address } },
|
||||
{ "IsNotOutOfMissionBounds", { "48 89 5C 24 ?? 57 48 83 EC ?? 4C 8B C2 48 8B F9", Utils::SigScan::PatternType::Address } },
|
||||
{ "PlaySoundEvent", { "4C 8B DC 49 89 5B ?? 49 89 73 ?? 57 48 81 EC ?? ?? ?? ?? 4C 8B 4C 24 ?? 48 8B F9 4D 8B D0 66 C7 84 24 ?? ?? ?? ?? ?? ?? 49 8B C1 66 C7 84 24", Utils::SigScan::PatternType::Address } },
|
||||
{ "GetPlayerRestrictionsFlags", { "48 89 5C 24 ?? 57 48 83 EC ?? 48 8B F9 48 8B DA 48 8B CA E8 ?? ?? ?? ?? 48 8B 4F", Utils::SigScan::PatternType::Address } },
|
||||
{ "EnablePlayerRestrictionsSubFunc", { "40 53 48 83 EC ?? 48 8B D9 48 81 C1 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B CB 48 83 C4 ?? 5B E9 ?? ?? ?? ?? CC CC CC CC CC CC CC CC CC CC CC CC CC CC 48 89 4C 24", Utils::SigScan::PatternType::Address } },
|
||||
{ "DisablePlayerRestrictionsSubFunc", { "48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC ?? 0F B7 81", Utils::SigScan::PatternType::Address } },
|
||||
{ "HandlePlayerRestrictions", { "40 57 48 83 EC ?? 48 89 5C 24 ?? 48 8B F9 48 89 6C 24 ?? 0F B6 A9", Utils::SigScan::PatternType::Address } }
|
||||
});
|
||||
AddPatterns(12001, {
|
||||
{ "LoadPlayerVars", { "48 89 4C 24 ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 8C 24", Utils::SigScan::PatternType::Address } },
|
||||
{ "PlayerState", { "48 8B 35 [?? ?? ?? ?? 4C 8B F2 48 8B F9", Utils::SigScan::PatternType::RelativePointer } },
|
||||
{ "SaveGameCRCBoolCheck", { "FF 50 ?? [40 22 DF 0F 85 ?? ?? ?? ?? 0F B6 05 ?? ?? ?? ?? 48 8D 3D", Utils::SigScan::PatternType::Address } },
|
||||
{ "IsNotOutOfMapBounds", { "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 4C 8B F9 48 85 D2", Utils::SigScan::PatternType::Address } },
|
||||
{ "IsNotOutOfMissionBounds", { "48 89 5C 24 ?? 57 48 83 EC ?? 48 8B F9 48 85 D2 74 ?? 48 8D 8A", Utils::SigScan::PatternType::Address } },
|
||||
{ "PlaySoundEvent", { "4C 8B DC 49 89 5B ?? 49 89 73 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B 44 24 ?? 48 8B F9 48 8B DA", Utils::SigScan::PatternType::Address } },
|
||||
{ "GetPlayerRestrictionsFlags", { "48 89 5C 24 ?? 57 48 83 EC ?? 48 8B D9 48 8B FA 48 8B CA E8 ?? ?? ?? ?? 48 8B 4B", Utils::SigScan::PatternType::Address } },
|
||||
{ "EnablePlayerRestrictionsSubFunc", { "40 53 48 83 EC ?? 48 8B D9 48 81 C1 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B CB 48 83 C4 ?? 5B E9 ?? ?? ?? ?? CC CC CC CC CC CC CC CC CC CC CC CC CC CC 40 57", Utils::SigScan::PatternType::Address } },
|
||||
{ "DisablePlayerRestrictionsSubFunc", { "48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC ?? 0F B6 81", Utils::SigScan::PatternType::Address } },
|
||||
{ "HandlePlayerRestrictions", { "40 57 48 83 EC ?? 48 89 5C 24 ?? 48 8B F9 48 89 74 24 ?? 0F B6 B1", Utils::SigScan::PatternType::Address } }
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
DWORD OffsetManager::GetOffset(const std::string& offsetName) {
|
||||
if (!initialized)
|
||||
return 0;
|
||||
|
||||
auto& offsets = GetOffsetsMap();
|
||||
if (offsets.find(Core::gameVer) != offsets.end() && offsets[Core::gameVer].find(offsetName) != offsets[Core::gameVer].end())
|
||||
return offsets[Core::gameVer][offsetName];
|
||||
|
||||
SPDLOG_ERROR("Offset not found for key: \"{}\" in version: {}", offsetName, Core::gameVer);
|
||||
return 0;
|
||||
}
|
||||
Utils::SigScan::Pattern OffsetManager::GetPattern(const std::string& patternName) {
|
||||
if (!initialized)
|
||||
return {};
|
||||
|
||||
auto& patterns = GetPatternsMap();
|
||||
if (patterns.find(Core::gameVer) != patterns.end() && patterns[Core::gameVer].find(patternName) != patterns[Core::gameVer].end())
|
||||
return patterns[Core::gameVer][patternName];
|
||||
|
||||
SPDLOG_ERROR("Pattern not found for key: \"{}\" in version: {}", patternName, Core::gameVer);
|
||||
return {};
|
||||
}
|
||||
|
||||
void OffsetManager::AddOffsets(DWORD gameVer, const std::unordered_map<std::string, DWORD>& offsets) {
|
||||
GetOffsetsMap()[gameVer] = offsets;
|
||||
}
|
||||
void OffsetManager::AddPatterns(DWORD gameVer, const std::unordered_map<std::string, Utils::SigScan::Pattern>& patterns) {
|
||||
GetPatternsMap()[gameVer] = patterns;
|
||||
}
|
||||
|
||||
std::unordered_map<DWORD, std::unordered_map<std::string, DWORD>>& OffsetManager::GetOffsetsMap() {
|
||||
static std::unordered_map<DWORD, std::unordered_map<std::string, DWORD>> offsetsMap;
|
||||
return offsetsMap;
|
||||
}
|
||||
std::unordered_map<DWORD, std::unordered_map<std::string, Utils::SigScan::Pattern>>& OffsetManager::GetPatternsMap() {
|
||||
static std::unordered_map<DWORD, std::unordered_map<std::string, Utils::SigScan::Pattern>> patternsMap;
|
||||
return patternsMap;
|
||||
}
|
||||
}
|
@ -1,168 +0,0 @@
|
||||
#include <spdlog\spdlog.h>
|
||||
#include <EGSDK\Utils\Files.h>
|
||||
#include <EGSDK\Core\Core.h>
|
||||
#include <EGSDK\Core\SaveGameManager.h>
|
||||
#include <EGSDK\Core\SteamAPI.h>
|
||||
|
||||
namespace EGSDK::Core {
|
||||
std::filesystem::path SaveGameManager::saveGamePath{};
|
||||
std::filesystem::path SaveGameManager::backupRootPath{};
|
||||
int SaveGameManager::maxBackupSlots = 16;
|
||||
std::chrono::minutes SaveGameManager::backupInterval{ 20 };
|
||||
int SaveGameManager::currentBackupSlot = 0;
|
||||
|
||||
Utils::Time::Timer SaveGameManager::timeSpentInitializing{ 30000 };
|
||||
bool SaveGameManager::initialized = false;
|
||||
bool SaveGameManager::isInitializing = false;
|
||||
bool SaveGameManager::triedInitializingWithSteam = false;
|
||||
bool SaveGameManager::loopIsRunning = false;
|
||||
|
||||
void SaveGameManager::Init() {
|
||||
if (initialized || isInitializing)
|
||||
return;
|
||||
isInitializing = true;
|
||||
timeSpentInitializing.Reset();
|
||||
|
||||
while (true) {
|
||||
if (timeSpentInitializing.DidTimePass()) {
|
||||
if (!triedInitializingWithSteam) {
|
||||
triedInitializingWithSteam = true;
|
||||
timeSpentInitializing.Reset();
|
||||
continue;
|
||||
}
|
||||
SPDLOG_ERROR("Failed initializing SaveGameManager after 20 seconds");
|
||||
MessageBoxA(nullptr, "EGameSDK encountered an issue trying to initialize its Savegame Manager.\nPLEASE MANUALLY MAKE BACKUPS OF YOUR SAVEGAME BEFORE using EGameSDK and any other mods, such as EGameTools!", "Failed initializing SaveGameManager", MB_ICONERROR | MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (backupRootPath.empty()) {
|
||||
SPDLOG_INFO("Getting SDK storage path");
|
||||
std::filesystem::path sdkStoragePath = GetSDKStoragePath();
|
||||
if (!sdkStoragePath.empty())
|
||||
backupRootPath = sdkStoragePath / "SavegameBackups";
|
||||
}
|
||||
if (saveGamePath.empty()) {
|
||||
SPDLOG_INFO("Detecting savegame path");
|
||||
saveGamePath = !triedInitializingWithSteam ? DetectSaveGamePathSteam() : DetectSaveGamePathEpic();
|
||||
}
|
||||
|
||||
if (!saveGamePath.empty() && !backupRootPath.empty())
|
||||
break;
|
||||
|
||||
Sleep(2000);
|
||||
}
|
||||
|
||||
SPDLOG_INFO("SaveGameManager initialization successful");
|
||||
isInitializing = false;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void SaveGameManager::Loop() {
|
||||
if (!initialized || loopIsRunning)
|
||||
return;
|
||||
loopIsRunning = true;
|
||||
|
||||
SPDLOG_INFO("Initializing backup slot");
|
||||
InitializeBackupSlot();
|
||||
|
||||
SPDLOG_INFO("Performing first savegame backup...");
|
||||
PerformBackup();
|
||||
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(backupInterval);
|
||||
SPDLOG_INFO("Performing periodic savegame backup...");
|
||||
PerformBackup();
|
||||
}
|
||||
}
|
||||
|
||||
void SaveGameManager::PerformBackup() {
|
||||
std::filesystem::path destinationPath = backupRootPath / ("Backup_" + std::to_string(currentBackupSlot));
|
||||
if (triedInitializingWithSteam)
|
||||
destinationPath = destinationPath / "out" / "storage";
|
||||
|
||||
try {
|
||||
if (std::filesystem::exists(destinationPath))
|
||||
std::filesystem::remove_all(destinationPath);
|
||||
|
||||
std::filesystem::create_directories(destinationPath);
|
||||
std::filesystem::copy(saveGamePath, destinationPath, std::filesystem::copy_options::recursive);
|
||||
|
||||
SPDLOG_INFO("Backup successfully created in \"{}\"!", destinationPath.string());
|
||||
|
||||
// Calculate next backup slot and cleanup
|
||||
int slotToDelete = (currentBackupSlot + 85) % 100;
|
||||
std::filesystem::path deletePath = backupRootPath / ("Backup_" + std::to_string(slotToDelete));
|
||||
if (std::filesystem::exists(deletePath)) {
|
||||
std::filesystem::remove_all(deletePath);
|
||||
SPDLOG_INFO("Deleted old backup folder: \"{}\"", deletePath.string());
|
||||
}
|
||||
currentBackupSlot = (currentBackupSlot + 1) % 100;
|
||||
} catch (const std::exception& ex) {
|
||||
SPDLOG_ERROR("Exception caught while trying to backup savegame: {}", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
void SaveGameManager::InitializeBackupSlot() {
|
||||
int highestSlot = -1;
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(backupRootPath)) {
|
||||
if (entry.is_directory()) {
|
||||
std::string folderName = entry.path().filename().string();
|
||||
if (folderName.rfind("Backup_", 0) == 0) { // Check if it starts with "Backup_"
|
||||
try {
|
||||
int slotNumber = std::stoi(folderName.substr(7));
|
||||
if (slotNumber > highestSlot)
|
||||
highestSlot = slotNumber;
|
||||
} catch (const std::exception& ex) {
|
||||
SPDLOG_ERROR("Failed to parse backup folder name: \"{}\", exception: {}", folderName, ex.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (highestSlot != -1) {
|
||||
currentBackupSlot = (highestSlot + 1) % 100;
|
||||
SPDLOG_INFO("Initialized current backup slot to: {}", currentBackupSlot);
|
||||
} else
|
||||
SPDLOG_INFO("No existing backups found. Starting with slot 0");
|
||||
}
|
||||
std::filesystem::path SaveGameManager::DetectSaveGamePathSteam() {
|
||||
auto steamUser = SteamAPI::GetISteamUser();
|
||||
if (!steamUser) {
|
||||
SPDLOG_ERROR("Failed getting Steam user");
|
||||
return {};
|
||||
}
|
||||
|
||||
char userDataFolder[256];
|
||||
if (!steamUser->GetUserDataFolder(userDataFolder, sizeof(userDataFolder))) {
|
||||
SPDLOG_ERROR("Failed getting Steam user data path");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::filesystem::path gameUserDataPath = userDataFolder;
|
||||
if (gameUserDataPath.filename() == "local")
|
||||
gameUserDataPath = gameUserDataPath.parent_path() / "remote";
|
||||
|
||||
if (!std::filesystem::exists(gameUserDataPath)) {
|
||||
SPDLOG_ERROR("Savegame path does not exist: {}", gameUserDataPath.string());
|
||||
return {};
|
||||
}
|
||||
|
||||
return gameUserDataPath;
|
||||
}
|
||||
std::filesystem::path SaveGameManager::DetectSaveGamePathEpic() {
|
||||
std::filesystem::path documentsPath = Utils::Files::GetDocumentsDir();
|
||||
if (documentsPath.empty()) {
|
||||
SPDLOG_ERROR("Failed getting user Documents path");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::filesystem::path gameStoragePath = documentsPath / "dying light 2" / "out" / "storage";
|
||||
if (!std::filesystem::exists(gameStoragePath)) {
|
||||
SPDLOG_ERROR("Savegame path does not exist: {}", gameStoragePath.string());
|
||||
return {};
|
||||
}
|
||||
|
||||
return gameStoragePath;
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
#include <EGSDK\Core\SteamAPI.h>
|
||||
#include <EGSDK\Utils\Memory.h>
|
||||
#include <EGSDK\Utils\WinMemory.h>
|
||||
|
||||
namespace EGSDK::Core {
|
||||
ISteamClient* SteamAPI::SteamClient() {
|
||||
return Utils::Memory::SafeCallFunction("steam_api64.dll", "SteamClient", nullptr);
|
||||
}
|
||||
HSteamUser SteamAPI::GetHSteamUser() {
|
||||
return Utils::Memory::SafeCallFunction("steam_api64.dll", "SteamAPI_GetHSteamUser", -1);
|
||||
}
|
||||
HSteamPipe SteamAPI::GetHSteamPipe() {
|
||||
return Utils::Memory::SafeCallFunction("steam_api64.dll", "SteamAPI_GetHSteamPipe", -1);
|
||||
}
|
||||
|
||||
ISteamUser* SteamAPI::GetISteamUser() {
|
||||
auto steamClient = SteamClient();
|
||||
if (!steamClient)
|
||||
return nullptr;
|
||||
|
||||
auto hSteamUser = SteamAPI::GetHSteamUser();
|
||||
auto hSteamPipe = SteamAPI::GetHSteamPipe();
|
||||
if (!hSteamUser || !hSteamPipe)
|
||||
return {};
|
||||
|
||||
return steamClient->GetISteamUser(hSteamUser, hSteamPipe, STEAMUSER_INTERFACE_VERSION);
|
||||
}
|
||||
ISteamUtils* SteamAPI::GetISteamUtils() {
|
||||
auto steamClient = SteamClient();
|
||||
if (!steamClient)
|
||||
return nullptr;
|
||||
|
||||
auto hSteamPipe = SteamAPI::GetHSteamPipe();
|
||||
if (!hSteamPipe)
|
||||
return {};
|
||||
|
||||
return steamClient->GetISteamUtils(hSteamPipe, STEAMUTILS_INTERFACE_VERSION);
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
#include <EGSDK\Engine\VarManagerBase.h>
|
||||
#include <EGSDK\Engine\CVars.h>
|
||||
#include <EGSDK\GamePH\PlayerVariables.h>
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarMapT VarManagerBase<VarMapT, VarT>::vars{};
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarMapT VarManagerBase<VarMapT, VarT>::customVars{};
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarMapT VarManagerBase<VarMapT, VarT>::defaultVars{};
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarMapT VarManagerBase<VarMapT, VarT>::defaultCustomVars{};
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::recursive_mutex VarManagerBase<VarMapT, VarT>::mutex{};
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::unordered_map<std::string, std::any> VarManagerBase<VarMapT, VarT>::prevVarValueMap{};
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::unordered_map<std::string, bool> VarManagerBase<VarMapT, VarT>::prevBoolValueMap{};
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::unordered_map<std::string, uint64_t> VarManagerBase<VarMapT, VarT>::varOwnerMap{};
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::AreAnyVarsPresent() {
|
||||
return !vars.empty();
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::AreAnyCustomVarsPresent() {
|
||||
return !customVars.empty();
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::AreAllCustomVarsManagedByBool() {
|
||||
bool allManagedByBool = true;
|
||||
|
||||
customVars.ForEach([&allManagedByBool](const std::unique_ptr<VarT>& varPtr) {
|
||||
if (!_IsManagedByBool(varPtr->GetName())) {
|
||||
allManagedByBool = false;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return allManagedByBool;
|
||||
}
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::_IsManagedByBool(const char* name) {
|
||||
std::lock_guard lock(mutex);
|
||||
return prevBoolValueMap.find(name) != prevBoolValueMap.end() && prevBoolValueMap[name];
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::_IsManagedByBool(VarRef<VarMapT, VarT>* var) {
|
||||
return _IsManagedByBool(var->GetName());
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::_HasCustomValue(VarRef<VarMapT, VarT>* var) {
|
||||
return !customVars.none_of(var->GetName());
|
||||
}
|
||||
|
||||
template EGameSDK_API class VarManagerBase<CVarMap, CVar>;
|
||||
template EGameSDK_API class VarManagerBase<GamePH::PlayerVarMap, GamePH::PlayerVar>;
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
#include <EGSDK\Engine\VarMapBase.h>
|
||||
#include <EGSDK\Engine\CVars.h>
|
||||
#include <EGSDK\GamePH\PlayerVariables.h>
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
template <typename VarT>
|
||||
std::unique_ptr<VarT>& VarMapBase<VarT>::try_emplace(std::unique_ptr<VarT> var) {
|
||||
std::lock_guard lock(mutex);
|
||||
const std::string& name = var->GetName();
|
||||
auto [it, inserted] = vars.try_emplace(name, std::move(var));
|
||||
if (inserted)
|
||||
varsOrdered.emplace_back(name);
|
||||
return it->second;
|
||||
}
|
||||
template <typename VarT>
|
||||
bool VarMapBase<VarT>::empty() const {
|
||||
std::lock_guard lock(mutex);
|
||||
return vars.empty();
|
||||
}
|
||||
template <typename VarT>
|
||||
bool VarMapBase<VarT>::none_of(const std::string& name) const {
|
||||
std::lock_guard lock(mutex);
|
||||
return vars.find(name) == vars.end();
|
||||
}
|
||||
template <typename VarT>
|
||||
void VarMapBase<VarT>::reserve(size_t count) {
|
||||
std::lock_guard lock(mutex);
|
||||
vars.reserve(count);
|
||||
}
|
||||
template <typename VarT>
|
||||
size_t VarMapBase<VarT>::size() {
|
||||
std::lock_guard lock(mutex);
|
||||
return vars.size();
|
||||
}
|
||||
|
||||
template <typename VarT>
|
||||
VarT* VarMapBase<VarT>::Find(const std::string& name) const {
|
||||
std::lock_guard lock(mutex);
|
||||
auto it = vars.find(name);
|
||||
return (it != vars.end()) ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
template <typename VarT>
|
||||
void VarMapBase<VarT>::Erase(const std::string& name) {
|
||||
std::lock_guard lock(mutex);
|
||||
auto it = vars.find(name);
|
||||
if (it == vars.end())
|
||||
return;
|
||||
|
||||
auto orderIt = std::find(varsOrdered.begin(), varsOrdered.end(), name);
|
||||
if (orderIt != varsOrdered.end())
|
||||
varsOrdered.erase(orderIt);
|
||||
|
||||
vars.erase(it);
|
||||
}
|
||||
|
||||
template EGameSDK_API class VarMapBase<CVar>;
|
||||
template EGameSDK_API class VarMapBase<GamePH::PlayerVar>;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
#include <unordered_map>
|
||||
#include <EGSDK\Utils\WinMemory.h>
|
||||
|
||||
namespace EGSDK::Utils {
|
||||
namespace Memory {
|
||||
HMODULE GetCallingDLLModule(void* callerAddress) {
|
||||
HMODULE callerModule{};
|
||||
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)callerAddress, &callerModule))
|
||||
return callerModule;
|
||||
return nullptr;
|
||||
}
|
||||
MODULEINFO GetModuleInfo(const char* szModule) {
|
||||
if (!szModule)
|
||||
return MODULEINFO();
|
||||
|
||||
static std::unordered_map<std::string_view, MODULEINFO> moduleInfoCache;
|
||||
auto it = moduleInfoCache.find(szModule);
|
||||
if (it != moduleInfoCache.end())
|
||||
return it->second;
|
||||
|
||||
HMODULE hModule = GetModuleHandle(szModule);
|
||||
if (hModule == 0)
|
||||
return MODULEINFO();
|
||||
|
||||
MODULEINFO moduleInfo{};
|
||||
GetModuleInformation(GetCurrentProcess(), hModule, &moduleInfo, sizeof(MODULEINFO));
|
||||
moduleInfoCache[szModule] = moduleInfo;
|
||||
|
||||
return moduleInfoCache[szModule];
|
||||
}
|
||||
FARPROC GetProcAddr(const std::string_view& module, const std::string_view& funcName) {
|
||||
HMODULE moduleHandle = GetModuleHandle(module.data());
|
||||
if (!moduleHandle)
|
||||
return nullptr;
|
||||
|
||||
return GetProcAddress(moduleHandle, funcName.data());
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ namespace EGSDK::Engine {
|
||||
union {
|
||||
ClassHelpers::StaticBuffer<0x50, uint32_t> valueOffset;
|
||||
};
|
||||
|
||||
explicit CVar(const std::string& name);
|
||||
explicit CVar(const std::string& name, VarType type);
|
||||
|
||||
@ -44,19 +43,43 @@ namespace EGSDK::Engine {
|
||||
|
||||
class EGameSDK_API CVarMap : public VarMapBase<CVar> {
|
||||
public:
|
||||
using VarMapBase<CVar>::Find;
|
||||
using VarMapBase<CVar>::none_of;
|
||||
|
||||
bool none_of(uint32_t valueOffset);
|
||||
|
||||
CVar* Find(uint32_t valueOffset) const;
|
||||
using Base = VarMapBase<CVar>;
|
||||
using Base::Find;
|
||||
using Base::none_of;
|
||||
|
||||
std::unique_ptr<CVar>& try_emplace(std::unique_ptr<CVar> var) override;
|
||||
|
||||
CVar* Find(uint32_t valueOffset) const;
|
||||
void Erase(const std::string& name) override;
|
||||
|
||||
bool none_of(uint32_t valueOffset);
|
||||
private:
|
||||
std::unordered_map<uint32_t, CVar*> varsByValueOffset;
|
||||
};
|
||||
|
||||
class EGameSDK_API CVars : public VarManagerBase<CVarMap, CVar> {};
|
||||
class EGameSDK_API CVarRef : public VarRef<CVarMap, CVar> {
|
||||
public:
|
||||
using Base = VarRef<CVarMap, CVar>;
|
||||
CVarRef(uint32_t valueOffset, CVarMap& map);
|
||||
|
||||
uint32_t GetValueOffset() const;
|
||||
void AddValuePtr(uint64_t* ptr);
|
||||
private:
|
||||
uint32_t valueOffset = 0;
|
||||
};
|
||||
|
||||
class EGameSDK_API CVars : public VarManagerBase<CVarMap, CVar> {
|
||||
public:
|
||||
using Base = VarManagerBase<CVarMap, CVar>;
|
||||
using Base::GetVarRef;
|
||||
using Base::GetCustomVarRef;
|
||||
using Base::GetDefaultVarRef;
|
||||
using Base::GetCustomDefaultVarRef;
|
||||
|
||||
static std::optional<CVarRef> GetVarRef(uint32_t valueOffset);
|
||||
static std::optional<CVarRef> GetCustomVarRef(uint32_t valueOffset);
|
||||
static std::optional<CVarRef> GetDefaultVarRef(uint32_t valueOffset);
|
||||
static std::optional<CVarRef> GetCustomDefaultVarRef(uint32_t valueOffset);
|
||||
private:
|
||||
static std::optional<CVarRef> _GetVarRef(uint32_t valueOffset, CVarMap& map);
|
||||
};
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <variant>
|
||||
#include <type_traits>
|
||||
#include <EGSDK\Exports.h>
|
||||
#include <EGSDK\Vec3.h>
|
||||
#include <EGSDK\Vec4.h>
|
||||
@ -19,11 +20,12 @@ namespace EGSDK::Engine {
|
||||
};
|
||||
|
||||
using VarValueType = std::variant<std::string, float, int, Vec3, Vec4, bool>;
|
||||
template <typename T>
|
||||
concept AllowedVarTypes = std::is_same_v<T, std::string> || std::is_same_v<T, float> || std::is_same_v<T, int> || std::is_same_v<T, Vec3> || std::is_same_v<T, Vec4> || std::is_same_v<T, bool>;
|
||||
|
||||
class EGameSDK_API VarBase {
|
||||
public:
|
||||
VarBase(const std::string& name);
|
||||
VarBase(const std::string& name, VarType type);
|
||||
VarBase(const std::string& name, VarType type = VarType::NONE);
|
||||
~VarBase();
|
||||
|
||||
const char* GetName() const;
|
||||
|
@ -11,124 +11,27 @@
|
||||
#include <EGSDK\Vec4.h>
|
||||
#include <EGSDK\Utils\Values.h>
|
||||
#include <EGSDK\Engine\VarBase.h>
|
||||
#include <EGSDK\Engine\VarRef.h>
|
||||
#include <EGSDK\Engine\VarMapBase.h>
|
||||
|
||||
#pragma intrinsic(_ReturnAddress)
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
template <typename T>
|
||||
concept AllowedVarTypes = std::is_same_v<T, std::string> || std::is_same_v<T, float> || std::is_same_v<T, int> || std::is_same_v<T, Vec3> || std::is_same_v<T, Vec4> || std::is_same_v<T, bool>;
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
class VarManagerBase;
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
class VarRef {
|
||||
public:
|
||||
VarRef(VarT* var) : ptr(var) {
|
||||
name = var->GetName();
|
||||
}
|
||||
VarRef(const char* name, VarMapT& map) : name(name), ptr(map.Find(name)) {}
|
||||
|
||||
const char* GetName() const {
|
||||
return name;
|
||||
}
|
||||
VarType GetType() const {
|
||||
return ptr ? ptr->GetType() : VarType::NONE;
|
||||
}
|
||||
VarT* GetPtr() const {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <AllowedVarTypes T>
|
||||
std::optional<T> GetValue() {
|
||||
if (!ptr)
|
||||
return std::nullopt;
|
||||
|
||||
auto value = ptr->GetValue();
|
||||
auto variantValue = std::get_if<T>(&value);
|
||||
return variantValue ? std::optional<T>(*variantValue) : std::nullopt;
|
||||
}
|
||||
template <AllowedVarTypes T>
|
||||
void SetValue(T value) {
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
if constexpr (std::is_same_v<T, std::string>) {
|
||||
switch (ptr->GetType()) {
|
||||
case VarType::Float:
|
||||
SetValue<float>(std::stof(Utils::Values::to_string(value)));
|
||||
return;
|
||||
case VarType::Int:
|
||||
SetValue<int>(std::stof(Utils::Values::to_string(value)));
|
||||
return;
|
||||
case VarType::Bool:
|
||||
SetValue<bool>(std::stof(Utils::Values::to_string(value)));
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ptr->SetValue(value);
|
||||
}
|
||||
template <AllowedVarTypes T>
|
||||
void SetValueFromList(T value) {
|
||||
VarManagerBase<VarMapT, VarT>::template _SetValueFromList<T>(this, value);
|
||||
}
|
||||
|
||||
bool IsManagedByBool() {
|
||||
return VarManagerBase<VarMapT, VarT>::_IsManagedByBool(this);
|
||||
}
|
||||
bool HasCustomValue() {
|
||||
return VarManagerBase<VarMapT, VarT>::_HasCustomValue(this);
|
||||
}
|
||||
|
||||
template <AllowedVarTypes T>
|
||||
void ManageByBool(T valueIfTrue, T valueIfFalse, bool boolVal, bool usePreviousVal = true) {
|
||||
VarManagerBase<VarMapT, VarT>::template _ManageByBool<T>(this, valueIfTrue, valueIfFalse, boolVal, usePreviousVal);
|
||||
}
|
||||
template <AllowedVarTypes T>
|
||||
void SaveVariableAsDefault() {
|
||||
VarManagerBase<VarMapT, VarT>::template _SaveVariableAsDefault<T>(this);
|
||||
}
|
||||
template <AllowedVarTypes T>
|
||||
void RestoreVarToDefault(bool restoreToSavedVars = false) {
|
||||
VarManagerBase<VarMapT, VarT>::template _RestoreVarToDefault<T>(this, restoreToSavedVars);
|
||||
}
|
||||
private:
|
||||
const char* name = nullptr;
|
||||
VarT* ptr = nullptr;
|
||||
};
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
class EGameSDK_API VarManagerBase {
|
||||
template <typename, typename>
|
||||
friend class VarRef;
|
||||
|
||||
public:
|
||||
static VarMapT vars;
|
||||
static VarMapT customVars;
|
||||
static VarMapT defaultVars;
|
||||
static VarMapT defaultCustomVars;
|
||||
|
||||
static std::optional<VarRef<VarMapT, VarT>> GetVarRef(VarT* var) {
|
||||
return std::optional<VarRef<VarMapT, VarT>>(VarRef<VarMapT, VarT>(var));
|
||||
}
|
||||
static std::optional<VarRef<VarMapT, VarT>> GetVarRef(const char* name) {
|
||||
VarRef<VarMapT, VarT> varRef(name, vars);
|
||||
return varRef.GetPtr() ? std::optional<VarRef<VarMapT, VarT>>(varRef) : std::nullopt;
|
||||
}
|
||||
static std::optional<VarRef<VarMapT, VarT>> GetCustomVarRef(const char* name) {
|
||||
VarRef<VarMapT, VarT> varRef(name, customVars);
|
||||
return varRef.GetPtr() ? std::optional<VarRef<VarMapT, VarT>>(varRef) : std::nullopt;
|
||||
}
|
||||
static std::optional<VarRef<VarMapT, VarT>> GetDefaultVarRef(const char* name) {
|
||||
VarRef<VarMapT, VarT> varRef(name, defaultVars);
|
||||
return varRef.GetPtr() ? std::optional<VarRef<VarMapT, VarT>>(varRef) : std::nullopt;
|
||||
}
|
||||
static std::optional<VarRef<VarMapT, VarT>> GetCustomDefaultVarRef(const char* name) {
|
||||
VarRef<VarMapT, VarT> varRef(name, defaultCustomVars);
|
||||
return varRef.GetPtr() ? std::optional<VarRef<VarMapT, VarT>>(varRef) : std::nullopt;
|
||||
}
|
||||
static std::optional<VarRef<VarMapT, VarT>> GetVarRef(VarT* var);
|
||||
static std::optional<VarRef<VarMapT, VarT>> GetVarRef(const char* name);
|
||||
static std::optional<VarRef<VarMapT, VarT>> GetCustomVarRef(const char* name);
|
||||
static std::optional<VarRef<VarMapT, VarT>> GetDefaultVarRef(const char* name);
|
||||
static std::optional<VarRef<VarMapT, VarT>> GetCustomDefaultVarRef(const char* name);
|
||||
|
||||
static bool AreAnyVarsPresent();
|
||||
static bool AreAnyCustomVarsPresent();
|
||||
@ -146,6 +49,8 @@ namespace EGSDK::Engine {
|
||||
static std::unordered_map<std::string, uint64_t> varOwnerMap;
|
||||
static std::recursive_mutex mutex;
|
||||
|
||||
static std::optional<VarRef<VarMapT, VarT>> _GetVarRef(const char* name, VarMapT& map);
|
||||
|
||||
static bool _IsManagedByBool(const char* name);
|
||||
static bool _IsManagedByBool(VarRef<VarMapT, VarT>* var);
|
||||
static bool _HasCustomValue(VarRef<VarMapT, VarT>* var);
|
||||
|
@ -5,29 +5,30 @@
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <EGSDK\Exports.h>
|
||||
#include <EGSDK\Engine\VarBase.h>
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
template <typename VarT>
|
||||
class EGameSDK_API VarMapBase {
|
||||
static_assert(std::is_base_of_v<VarBase, VarT>, "VarT must inherit from VarBase");
|
||||
public:
|
||||
VarMapBase() = default;
|
||||
VarMapBase();
|
||||
VarMapBase(const VarMapBase&) = delete;
|
||||
VarMapBase& operator=(const VarMapBase&) = delete;
|
||||
VarMapBase(VarMapBase&&) noexcept = default;
|
||||
VarMapBase& operator=(VarMapBase&&) noexcept = default;
|
||||
|
||||
virtual ~VarMapBase() = default;
|
||||
|
||||
virtual std::unique_ptr<VarT>& try_emplace(std::unique_ptr<VarT> var);
|
||||
VarT* Find(const std::string& name) const;
|
||||
virtual void Erase(const std::string& name);
|
||||
|
||||
bool empty() const;
|
||||
bool none_of(const std::string& name) const;
|
||||
void reserve(size_t count);
|
||||
size_t size();
|
||||
|
||||
VarT* Find(const std::string& name) const;
|
||||
|
||||
virtual void Erase(const std::string& name);
|
||||
void reserve(size_t count);
|
||||
|
||||
template <typename Callable, typename... Args>
|
||||
void ForEach(Callable&& func, Args&&... args) {
|
||||
@ -36,8 +37,8 @@ namespace EGSDK::Engine {
|
||||
func(vars.at(name), std::forward<Args>(args)...);
|
||||
}
|
||||
protected:
|
||||
std::unordered_map<std::string, std::unique_ptr<VarT>> vars{};
|
||||
std::vector<std::string> varsOrdered{};
|
||||
mutable std::recursive_mutex mutex{};
|
||||
std::unordered_map<std::string, std::unique_ptr<VarT>> vars;
|
||||
std::vector<std::string> varsOrdered;
|
||||
mutable std::recursive_mutex mutex;
|
||||
};
|
||||
}
|
77
EGameSDK/include/EGSDK/Engine/VarRef.h
Normal file
77
EGameSDK/include/EGSDK/Engine/VarRef.h
Normal file
@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
#include <optional>
|
||||
#include <EGSDK\Engine\VarBase.h>
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
template <typename VarMapT, typename VarT>
|
||||
class EGameSDK_API VarManagerBase;
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
class EGameSDK_API VarRef {
|
||||
public:
|
||||
using VarMgrBase = VarManagerBase<VarMapT, VarT>;
|
||||
|
||||
VarRef(VarT* var);
|
||||
VarRef(const char* name, VarMapT& map);
|
||||
|
||||
const char* GetName() const;
|
||||
VarType GetType() const;
|
||||
VarT* GetPtr() const;
|
||||
|
||||
template <AllowedVarTypes T>
|
||||
std::optional<T> GetValue() const {
|
||||
if (!ptr)
|
||||
return std::nullopt;
|
||||
|
||||
auto value = ptr->GetValue();
|
||||
if (auto* typedValue = std::get_if<T>(&value))
|
||||
return *typedValue;
|
||||
return std::nullopt;
|
||||
}
|
||||
template <AllowedVarTypes T>
|
||||
void SetValue(T value) {
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
if constexpr (std::is_same_v<T, std::string>) {
|
||||
switch (ptr->GetType()) {
|
||||
case VarType::Float:
|
||||
SetValue<float>(std::stof(Utils::Values::to_string(value)));
|
||||
return;
|
||||
case VarType::Int:
|
||||
SetValue<int>(std::stof(Utils::Values::to_string(value)));
|
||||
return;
|
||||
case VarType::Bool:
|
||||
SetValue<bool>(std::stof(Utils::Values::to_string(value)));
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ptr->SetValue(std::move(value));
|
||||
}
|
||||
template <AllowedVarTypes T>
|
||||
void SetValueFromList(T value) {
|
||||
VarMgrBase::template _SetValueFromList<T>(this, value);
|
||||
}
|
||||
|
||||
bool IsManagedByBool();
|
||||
bool HasCustomValue();
|
||||
|
||||
template <AllowedVarTypes T>
|
||||
void ManageByBool(T valueIfTrue, T valueIfFalse, bool boolVal, bool usePreviousVal = true) {
|
||||
VarMgrBase::template _ManageByBool<T>(this, valueIfTrue, valueIfFalse, boolVal, usePreviousVal);
|
||||
}
|
||||
template <AllowedVarTypes T>
|
||||
void SaveVariableAsDefault() {
|
||||
VarMgrBase::template _SaveVariableAsDefault<T>(this);
|
||||
}
|
||||
template <AllowedVarTypes T>
|
||||
void RestoreVarToDefault(bool restoreToSavedVars = false) {
|
||||
VarMgrBase::template _RestoreVarToDefault<T>(this, restoreToSavedVars);
|
||||
}
|
||||
protected:
|
||||
const char* name;
|
||||
VarT* ptr;
|
||||
};
|
||||
}
|
@ -39,13 +39,20 @@ namespace EGSDK::GamePH {
|
||||
|
||||
class EGameSDK_API PlayerVarMap : public Engine::VarMapBase<PlayerVar> {
|
||||
public:
|
||||
using Engine::VarMapBase<PlayerVar>::Find;
|
||||
using Engine::VarMapBase<PlayerVar>::none_of;
|
||||
using Engine::VarMapBase<PlayerVar>::empty;
|
||||
using Base = VarMapBase<PlayerVar>;
|
||||
using Base::Find;
|
||||
using Base::none_of;
|
||||
using Base::empty;
|
||||
};
|
||||
|
||||
class EGameSDK_API PlayerVariables : public Engine::VarManagerBase<PlayerVarMap, PlayerVar> {
|
||||
public:
|
||||
using Base = VarManagerBase<PlayerVarMap, PlayerVar>;
|
||||
using Base::GetVarRef;
|
||||
using Base::GetCustomVarRef;
|
||||
using Base::GetDefaultVarRef;
|
||||
using Base::GetCustomDefaultVarRef;
|
||||
|
||||
static std::atomic<bool> gotPlayerVars;
|
||||
|
||||
#ifdef EGameSDK_EXPORTS
|
||||
|
@ -1 +1,168 @@
|
||||
|
||||
#include <spdlog\spdlog.h>
|
||||
#include <EGSDK\Utils\Files.h>
|
||||
#include <EGSDK\Core\Core.h>
|
||||
#include <EGSDK\Core\SaveGameManager.h>
|
||||
#include <EGSDK\Core\SteamAPI.h>
|
||||
|
||||
namespace EGSDK::Core {
|
||||
std::filesystem::path SaveGameManager::saveGamePath{};
|
||||
std::filesystem::path SaveGameManager::backupRootPath{};
|
||||
int SaveGameManager::maxBackupSlots = 16;
|
||||
std::chrono::minutes SaveGameManager::backupInterval{ 20 };
|
||||
int SaveGameManager::currentBackupSlot = 0;
|
||||
|
||||
Utils::Time::Timer SaveGameManager::timeSpentInitializing{ 30000 };
|
||||
bool SaveGameManager::initialized = false;
|
||||
bool SaveGameManager::isInitializing = false;
|
||||
bool SaveGameManager::triedInitializingWithSteam = false;
|
||||
bool SaveGameManager::loopIsRunning = false;
|
||||
|
||||
void SaveGameManager::Init() {
|
||||
if (initialized || isInitializing)
|
||||
return;
|
||||
isInitializing = true;
|
||||
timeSpentInitializing.Reset();
|
||||
|
||||
while (true) {
|
||||
if (timeSpentInitializing.DidTimePass()) {
|
||||
if (!triedInitializingWithSteam) {
|
||||
triedInitializingWithSteam = true;
|
||||
timeSpentInitializing.Reset();
|
||||
continue;
|
||||
}
|
||||
SPDLOG_ERROR("Failed initializing SaveGameManager after 20 seconds");
|
||||
MessageBoxA(nullptr, "EGameSDK encountered an issue trying to initialize its Savegame Manager.\nPLEASE MANUALLY MAKE BACKUPS OF YOUR SAVEGAME BEFORE using EGameSDK and any other mods, such as EGameTools!", "Failed initializing SaveGameManager", MB_ICONERROR | MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (backupRootPath.empty()) {
|
||||
SPDLOG_INFO("Getting SDK storage path");
|
||||
std::filesystem::path sdkStoragePath = GetSDKStoragePath();
|
||||
if (!sdkStoragePath.empty())
|
||||
backupRootPath = sdkStoragePath / "SavegameBackups";
|
||||
}
|
||||
if (saveGamePath.empty()) {
|
||||
SPDLOG_INFO("Detecting savegame path");
|
||||
saveGamePath = !triedInitializingWithSteam ? DetectSaveGamePathSteam() : DetectSaveGamePathEpic();
|
||||
}
|
||||
|
||||
if (!saveGamePath.empty() && !backupRootPath.empty())
|
||||
break;
|
||||
|
||||
Sleep(2000);
|
||||
}
|
||||
|
||||
SPDLOG_INFO("SaveGameManager initialization successful");
|
||||
isInitializing = false;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void SaveGameManager::Loop() {
|
||||
if (!initialized || loopIsRunning)
|
||||
return;
|
||||
loopIsRunning = true;
|
||||
|
||||
SPDLOG_INFO("Initializing backup slot");
|
||||
InitializeBackupSlot();
|
||||
|
||||
SPDLOG_INFO("Performing first savegame backup...");
|
||||
PerformBackup();
|
||||
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(backupInterval);
|
||||
SPDLOG_INFO("Performing periodic savegame backup...");
|
||||
PerformBackup();
|
||||
}
|
||||
}
|
||||
|
||||
void SaveGameManager::PerformBackup() {
|
||||
std::filesystem::path destinationPath = backupRootPath / ("Backup_" + std::to_string(currentBackupSlot));
|
||||
if (triedInitializingWithSteam)
|
||||
destinationPath = destinationPath / "out" / "storage";
|
||||
|
||||
try {
|
||||
if (std::filesystem::exists(destinationPath))
|
||||
std::filesystem::remove_all(destinationPath);
|
||||
|
||||
std::filesystem::create_directories(destinationPath);
|
||||
std::filesystem::copy(saveGamePath, destinationPath, std::filesystem::copy_options::recursive);
|
||||
|
||||
SPDLOG_INFO("Backup successfully created in \"{}\"!", destinationPath.string());
|
||||
|
||||
// Calculate next backup slot and cleanup
|
||||
int slotToDelete = (currentBackupSlot + 85) % 100;
|
||||
std::filesystem::path deletePath = backupRootPath / ("Backup_" + std::to_string(slotToDelete));
|
||||
if (std::filesystem::exists(deletePath)) {
|
||||
std::filesystem::remove_all(deletePath);
|
||||
SPDLOG_INFO("Deleted old backup folder: \"{}\"", deletePath.string());
|
||||
}
|
||||
currentBackupSlot = (currentBackupSlot + 1) % 100;
|
||||
} catch (const std::exception& ex) {
|
||||
SPDLOG_ERROR("Exception caught while trying to backup savegame: {}", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
void SaveGameManager::InitializeBackupSlot() {
|
||||
int highestSlot = -1;
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(backupRootPath)) {
|
||||
if (entry.is_directory()) {
|
||||
std::string folderName = entry.path().filename().string();
|
||||
if (folderName.rfind("Backup_", 0) == 0) { // Check if it starts with "Backup_"
|
||||
try {
|
||||
int slotNumber = std::stoi(folderName.substr(7));
|
||||
if (slotNumber > highestSlot)
|
||||
highestSlot = slotNumber;
|
||||
} catch (const std::exception& ex) {
|
||||
SPDLOG_ERROR("Failed to parse backup folder name: \"{}\", exception: {}", folderName, ex.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (highestSlot != -1) {
|
||||
currentBackupSlot = (highestSlot + 1) % 100;
|
||||
SPDLOG_INFO("Initialized current backup slot to: {}", currentBackupSlot);
|
||||
} else
|
||||
SPDLOG_INFO("No existing backups found. Starting with slot 0");
|
||||
}
|
||||
std::filesystem::path SaveGameManager::DetectSaveGamePathSteam() {
|
||||
auto steamUser = SteamAPI::GetISteamUser();
|
||||
if (!steamUser) {
|
||||
SPDLOG_ERROR("Failed getting Steam user");
|
||||
return {};
|
||||
}
|
||||
|
||||
char userDataFolder[256];
|
||||
if (!steamUser->GetUserDataFolder(userDataFolder, sizeof(userDataFolder))) {
|
||||
SPDLOG_ERROR("Failed getting Steam user data path");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::filesystem::path gameUserDataPath = userDataFolder;
|
||||
if (gameUserDataPath.filename() == "local")
|
||||
gameUserDataPath = gameUserDataPath.parent_path() / "remote";
|
||||
|
||||
if (!std::filesystem::exists(gameUserDataPath)) {
|
||||
SPDLOG_ERROR("Savegame path does not exist: {}", gameUserDataPath.string());
|
||||
return {};
|
||||
}
|
||||
|
||||
return gameUserDataPath;
|
||||
}
|
||||
std::filesystem::path SaveGameManager::DetectSaveGamePathEpic() {
|
||||
std::filesystem::path documentsPath = Utils::Files::GetDocumentsDir();
|
||||
if (documentsPath.empty()) {
|
||||
SPDLOG_ERROR("Failed getting user Documents path");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::filesystem::path gameStoragePath = documentsPath / "dying light 2" / "out" / "storage";
|
||||
if (!std::filesystem::exists(gameStoragePath)) {
|
||||
SPDLOG_ERROR("Savegame path does not exist: {}", gameStoragePath.string());
|
||||
return {};
|
||||
}
|
||||
|
||||
return gameStoragePath;
|
||||
}
|
||||
}
|
@ -1 +1,39 @@
|
||||
|
||||
#include <EGSDK\Core\SteamAPI.h>
|
||||
#include <EGSDK\Utils\Memory.h>
|
||||
#include <EGSDK\Utils\WinMemory.h>
|
||||
|
||||
namespace EGSDK::Core {
|
||||
ISteamClient* SteamAPI::SteamClient() {
|
||||
return Utils::Memory::SafeCallFunction("steam_api64.dll", "SteamClient", nullptr);
|
||||
}
|
||||
HSteamUser SteamAPI::GetHSteamUser() {
|
||||
return Utils::Memory::SafeCallFunction("steam_api64.dll", "SteamAPI_GetHSteamUser", -1);
|
||||
}
|
||||
HSteamPipe SteamAPI::GetHSteamPipe() {
|
||||
return Utils::Memory::SafeCallFunction("steam_api64.dll", "SteamAPI_GetHSteamPipe", -1);
|
||||
}
|
||||
|
||||
ISteamUser* SteamAPI::GetISteamUser() {
|
||||
auto steamClient = SteamClient();
|
||||
if (!steamClient)
|
||||
return nullptr;
|
||||
|
||||
auto hSteamUser = SteamAPI::GetHSteamUser();
|
||||
auto hSteamPipe = SteamAPI::GetHSteamPipe();
|
||||
if (!hSteamUser || !hSteamPipe)
|
||||
return {};
|
||||
|
||||
return steamClient->GetISteamUser(hSteamUser, hSteamPipe, STEAMUSER_INTERFACE_VERSION);
|
||||
}
|
||||
ISteamUtils* SteamAPI::GetISteamUtils() {
|
||||
auto steamClient = SteamClient();
|
||||
if (!steamClient)
|
||||
return nullptr;
|
||||
|
||||
auto hSteamPipe = SteamAPI::GetHSteamPipe();
|
||||
if (!hSteamPipe)
|
||||
return {};
|
||||
|
||||
return steamClient->GetISteamUtils(hSteamPipe, STEAMUTILS_INTERFACE_VERSION);
|
||||
}
|
||||
}
|
@ -98,11 +98,6 @@ namespace EGSDK::Engine {
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
bool CVarMap::none_of(uint32_t valueOffset) {
|
||||
std::lock_guard lock(mutex);
|
||||
return varsByValueOffset.find(valueOffset) == varsByValueOffset.end();
|
||||
}
|
||||
|
||||
CVar* CVarMap::Find(uint32_t valueOffset) const {
|
||||
std::lock_guard lock(mutex);
|
||||
auto it = varsByValueOffset.find(valueOffset);
|
||||
@ -121,4 +116,36 @@ namespace EGSDK::Engine {
|
||||
varsByValueOffset.erase(it->second->valueOffset.data);
|
||||
vars.erase(it);
|
||||
}
|
||||
|
||||
bool CVarMap::none_of(uint32_t valueOffset) {
|
||||
std::lock_guard lock(mutex);
|
||||
return varsByValueOffset.find(valueOffset) == varsByValueOffset.end();
|
||||
}
|
||||
|
||||
CVarRef::CVarRef(uint32_t valueOffset, CVarMap& map) : valueOffset(valueOffset), Base(map.Find(valueOffset)) {}
|
||||
uint32_t CVarRef::GetValueOffset() const {
|
||||
return valueOffset;
|
||||
}
|
||||
void CVarRef::AddValuePtr(uint64_t* ptr) {
|
||||
if (!ptr)
|
||||
return;
|
||||
Base::ptr->AddValuePtr(ptr);
|
||||
}
|
||||
|
||||
std::optional<CVarRef> CVars::GetVarRef(uint32_t valueOffset) {
|
||||
return _GetVarRef(valueOffset, Base::vars);
|
||||
}
|
||||
std::optional<CVarRef> CVars::GetCustomVarRef(uint32_t valueOffset) {
|
||||
return _GetVarRef(valueOffset, Base::customVars);
|
||||
}
|
||||
std::optional<CVarRef> CVars::GetDefaultVarRef(uint32_t valueOffset) {
|
||||
return _GetVarRef(valueOffset, Base::defaultVars);
|
||||
}
|
||||
std::optional<CVarRef> CVars::GetCustomDefaultVarRef(uint32_t valueOffset) {
|
||||
return _GetVarRef(valueOffset, Base::defaultCustomVars);
|
||||
}
|
||||
std::optional<CVarRef> CVars::_GetVarRef(uint32_t valueOffset, CVarMap& map) {
|
||||
CVarRef varRef(valueOffset, map);
|
||||
return varRef.GetPtr() ? std::optional<CVarRef>(varRef) : std::nullopt;
|
||||
}
|
||||
}
|
@ -5,15 +5,10 @@ namespace EGSDK::Engine {
|
||||
std::unordered_map<const VarBase*, VarType> VarBase::varTypes{};
|
||||
std::recursive_mutex VarBase::mutex{};
|
||||
|
||||
VarBase::VarBase(const std::string& name) {
|
||||
std::lock_guard lock(mutex);
|
||||
varNames[this] = name;
|
||||
varTypes[this] = VarType::NONE;
|
||||
}
|
||||
VarBase::VarBase(const std::string& name, VarType type) {
|
||||
std::lock_guard lock(mutex);
|
||||
varNames[this] = name;
|
||||
varTypes[this] = type;
|
||||
SetName(name);
|
||||
SetType(type);
|
||||
}
|
||||
VarBase::~VarBase() {
|
||||
std::lock_guard lock(mutex);
|
||||
@ -24,9 +19,7 @@ namespace EGSDK::Engine {
|
||||
const char* VarBase::GetName() const {
|
||||
std::lock_guard lock(mutex);
|
||||
auto it = varNames.find(this);
|
||||
if (it != varNames.end())
|
||||
return it->second.c_str();
|
||||
return nullptr;
|
||||
return it != varNames.end() ? it->second.c_str() : nullptr;
|
||||
}
|
||||
void VarBase::SetName(const std::string& newName) {
|
||||
std::lock_guard lock(mutex);
|
||||
@ -36,9 +29,7 @@ namespace EGSDK::Engine {
|
||||
VarType VarBase::GetType() const {
|
||||
std::lock_guard lock(mutex);
|
||||
auto it = varTypes.find(this);
|
||||
if (it != varTypes.end())
|
||||
return it->second;
|
||||
return VarType::NONE;
|
||||
return it != varTypes.end() ? it->second : VarType::NONE;
|
||||
}
|
||||
void VarBase::SetType(VarType newType) {
|
||||
std::lock_guard lock(mutex);
|
||||
|
@ -1 +1,89 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <EGSDK\Engine\VarManagerBase.h>
|
||||
#include <EGSDK\Engine\CVars.h>
|
||||
#include <EGSDK\GamePH\PlayerVariables.h>
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarMapT VarManagerBase<VarMapT, VarT>::vars{};
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarMapT VarManagerBase<VarMapT, VarT>::customVars{};
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarMapT VarManagerBase<VarMapT, VarT>::defaultVars{};
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarMapT VarManagerBase<VarMapT, VarT>::defaultCustomVars{};
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::unordered_map<std::string, std::any> VarManagerBase<VarMapT, VarT>::prevVarValueMap{};
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::unordered_map<std::string, bool> VarManagerBase<VarMapT, VarT>::prevBoolValueMap{};
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::unordered_map<std::string, uint64_t> VarManagerBase<VarMapT, VarT>::varOwnerMap{};
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::recursive_mutex VarManagerBase<VarMapT, VarT>::mutex{};
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::optional<VarRef<VarMapT, VarT>> VarManagerBase<VarMapT, VarT>::GetVarRef(VarT* var) {
|
||||
return var ? std::optional<VarRef<VarMapT, VarT>>(VarRef<VarMapT, VarT>(var)) : std::nullopt;
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::optional<VarRef<VarMapT, VarT>> VarManagerBase<VarMapT, VarT>::GetVarRef(const char* name) {
|
||||
return _GetVarRef(name, vars);
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::optional<VarRef<VarMapT, VarT>> VarManagerBase<VarMapT, VarT>::GetCustomVarRef(const char* name) {
|
||||
return _GetVarRef(name, customVars);
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::optional<VarRef<VarMapT, VarT>> VarManagerBase<VarMapT, VarT>::GetDefaultVarRef(const char* name) {
|
||||
return _GetVarRef(name, defaultVars);
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::optional<VarRef<VarMapT, VarT>> VarManagerBase<VarMapT, VarT>::GetCustomDefaultVarRef(const char* name) {
|
||||
return _GetVarRef(name, defaultCustomVars);
|
||||
}
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
std::optional<VarRef<VarMapT, VarT>> VarManagerBase<VarMapT, VarT>::_GetVarRef(const char* name, VarMapT& map) {
|
||||
VarRef<VarMapT, VarT> varRef(name, map);
|
||||
return varRef.GetPtr() ? std::optional<VarRef<VarMapT, VarT>>(varRef) : std::nullopt;
|
||||
}
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::AreAnyVarsPresent() {
|
||||
return !vars.empty();
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::AreAnyCustomVarsPresent() {
|
||||
return !customVars.empty();
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::AreAllCustomVarsManagedByBool() {
|
||||
bool allManagedByBool = true;
|
||||
vars.ForEach([&allManagedByBool](const std::unique_ptr<VarT>& varPtr) {
|
||||
if (!_IsManagedByBool(varPtr->GetName())) {
|
||||
allManagedByBool = false;
|
||||
return;
|
||||
}
|
||||
});
|
||||
return allManagedByBool;
|
||||
}
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::_IsManagedByBool(const char* name) {
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
return (prevBoolValueMap.find(name) != prevBoolValueMap.end()) && prevBoolValueMap[name];
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::_IsManagedByBool(VarRef<VarMapT, VarT>* var) {
|
||||
return _IsManagedByBool(var->GetName());
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarManagerBase<VarMapT, VarT>::_HasCustomValue(VarRef<VarMapT, VarT>* var) {
|
||||
return !customVars.none_of(var->GetName());
|
||||
}
|
||||
|
||||
template class VarManagerBase<CVarMap, CVar>;
|
||||
template class VarManagerBase<GamePH::PlayerVarMap, GamePH::PlayerVar>;
|
||||
}
|
@ -1 +1,66 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <EGSDK\Engine\VarMapBase.h>
|
||||
#include <EGSDK\Engine\CVars.h>
|
||||
#include <EGSDK\GamePH\PlayerVariables.h>
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
template <typename VarT>
|
||||
VarMapBase<VarT>::VarMapBase() : vars(), varsOrdered(), mutex() {}
|
||||
|
||||
template <typename VarT>
|
||||
std::unique_ptr<VarT>& VarMapBase<VarT>::try_emplace(std::unique_ptr<VarT> var) {
|
||||
std::lock_guard lock(mutex);
|
||||
const std::string& name = var->GetName();
|
||||
auto [it, inserted] = vars.try_emplace(name, std::move(var));
|
||||
if (inserted)
|
||||
varsOrdered.push_back(name);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
template <typename VarT>
|
||||
VarT* VarMapBase<VarT>::Find(const std::string& name) const {
|
||||
std::lock_guard lock(mutex);
|
||||
auto it = vars.find(name);
|
||||
return (it != vars.end()) ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
template <typename VarT>
|
||||
void VarMapBase<VarT>::Erase(const std::string& name) {
|
||||
std::lock_guard lock(mutex);
|
||||
auto it = vars.find(name);
|
||||
if (it == vars.end())
|
||||
return;
|
||||
auto orderIt = std::find(varsOrdered.begin(), varsOrdered.end(), name);
|
||||
if (orderIt != varsOrdered.end())
|
||||
varsOrdered.erase(orderIt);
|
||||
vars.erase(it);
|
||||
}
|
||||
|
||||
template <typename VarT>
|
||||
bool VarMapBase<VarT>::empty() const {
|
||||
std::lock_guard lock(mutex);
|
||||
return vars.empty();
|
||||
}
|
||||
|
||||
template <typename VarT>
|
||||
bool VarMapBase<VarT>::none_of(const std::string& name) const {
|
||||
std::lock_guard lock(mutex);
|
||||
return vars.find(name) == vars.end();
|
||||
}
|
||||
|
||||
template <typename VarT>
|
||||
size_t VarMapBase<VarT>::size() {
|
||||
std::lock_guard lock(mutex);
|
||||
return vars.size();
|
||||
}
|
||||
|
||||
template <typename VarT>
|
||||
void VarMapBase<VarT>::reserve(size_t count) {
|
||||
std::lock_guard lock(mutex);
|
||||
vars.reserve(count);
|
||||
varsOrdered.reserve(count);
|
||||
}
|
||||
|
||||
template class VarMapBase<CVar>;
|
||||
template class VarMapBase<GamePH::PlayerVar>;
|
||||
}
|
37
EGameSDK/src/Engine/VarRef.cpp
Normal file
37
EGameSDK/src/Engine/VarRef.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include <EGSDK\Utils\Values.h>
|
||||
#include <EGSDK\Engine\VarRef.h>
|
||||
#include <EGSDK\Engine\VarBase.h>
|
||||
#include <EGSDK\Engine\CVars.h>
|
||||
#include <EGSDK\GamePH\PlayerVariables.h>
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarRef<VarMapT, VarT>::VarRef(VarT* var) : name(var ? var->GetName() : nullptr), ptr(var) {}
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarRef<VarMapT, VarT>::VarRef(const char* name, VarMapT& map) : name(name), ptr(map.Find(name)) {}
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
const char* VarRef<VarMapT, VarT>::GetName() const {
|
||||
return name;
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarType VarRef<VarMapT, VarT>::GetType() const {
|
||||
return ptr ? ptr->GetType() : VarType::NONE;
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
VarT* VarRef<VarMapT, VarT>::GetPtr() const {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarRef<VarMapT, VarT>::IsManagedByBool() {
|
||||
return VarMgrBase::_IsManagedByBool(this);
|
||||
}
|
||||
template <typename VarMapT, typename VarT>
|
||||
bool VarRef<VarMapT, VarT>::HasCustomValue() {
|
||||
return VarMgrBase::_HasCustomValue(this);
|
||||
}
|
||||
|
||||
template class VarRef<CVarMap, CVar>;
|
||||
template class VarRef<GamePH::PlayerVarMap, GamePH::PlayerVar>;
|
||||
}
|
@ -62,6 +62,7 @@ namespace EGSDK::GamePH {
|
||||
}, value);
|
||||
}
|
||||
|
||||
|
||||
StringPlayerVariable::StringPlayerVariable(const std::string& name) : PlayerVar(name) {
|
||||
SetType(Engine::VarType::String);
|
||||
}
|
||||
|
@ -1 +1,137 @@
|
||||
|
||||
#include <EGSDK\Offsets.h>
|
||||
#include <EGSDK\Engine\CBulletPhysicsCharacter.h>
|
||||
#include <EGSDK\Engine\CGame.h>
|
||||
#include <EGSDK\Engine\CVideoSettings.h>
|
||||
#include <EGSDK\GamePH\CoPlayerRestrictions.h>
|
||||
#include <EGSDK\GamePH\FreeCamera.h>
|
||||
#include <EGSDK\GamePH\GameDI_PH.h>
|
||||
#include <EGSDK\GamePH\LocalClientDI.h>
|
||||
#include <EGSDK\GamePH\PlayerDI_PH.h>
|
||||
#include <EGSDK\GamePH\PlayerState.h>
|
||||
#include <EGSDK\GamePH\SessionCooperativeDI.h>
|
||||
#include <EGSDK\ClassHelpers.h>
|
||||
|
||||
namespace EGSDK {
|
||||
bool OffsetManager::initialized = false;
|
||||
|
||||
void OffsetManager::InitializeOffsetsAndPatterns() {
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
AddOffsets(11200, {
|
||||
{ "OnPostUpdate", 0x378 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerPos2), 0x880 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerPos), 0x898 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerDownwardVelocity), 0xC18 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CGame::pCLevel), 0x380 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CVideoSettings::extraFOV), 0x78 },
|
||||
|
||||
{ GetOffsetNameFromClassMember(&GamePH::CoPlayerRestrictions::flags), 0x1C0 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::enableSpeedMultiplier1), 0x4C },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::enableSpeedMultiplier2), 0x4D },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::speedMultiplier), 0x150 },
|
||||
//{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::mouseSensitivityMultiplier), 0x1A0 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::GameDI_PH::blockPauseGameOnPlayerAfk), 0x830 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::GameDI_PH::pSessionCooperativeDI), 0xE8 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::LocalClientDI::pPlayerDI_PH), 0x88 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::pCoPhysicsProperty), 0xE8 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::pInventoryContainerDI), 0x550 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::nextPlayerOrientation), 0xC68 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::restrictionsEnabled), 0x2CF0 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::enableTPPModel1), 0x2DC1 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::enableTPPModel2), 0x2DC2 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerState::playerVariables), 0x280 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::SessionCooperativeDI::pLocalClientDI), 0xD10 },
|
||||
});
|
||||
AddOffsets(12001, {
|
||||
{ "OnPostUpdate", 0x3A8 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerPos2), 0xCB8 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerPos), 0xCD0 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CBulletPhysicsCharacter::playerDownwardVelocity), 0x1050 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CGame::pCLevel), 0x390 },
|
||||
{ GetOffsetNameFromClassMember(&Engine::CVideoSettings::extraFOV), 0x7C },
|
||||
|
||||
{ GetOffsetNameFromClassMember(&GamePH::CoPlayerRestrictions::flags), 0x1F0 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::enableSpeedMultiplier1), 0x42 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::enableSpeedMultiplier2), 0x43 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::FreeCamera::speedMultiplier), 0x1CC },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::GameDI_PH::blockPauseGameOnPlayerAfk), 0x910 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::GameDI_PH::pSessionCooperativeDI), 0x130 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::LocalClientDI::pPlayerDI_PH), 0x90 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::pCoPhysicsProperty), 0xF0 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::pInventoryContainerDI), 0x470 },
|
||||
//{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::pPlayerFppVis_PH), 0x420 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::nextPlayerOrientation), 0xB88 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::restrictionsEnabled), 0x3520 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::enableTPPModel1), 0x35E9 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerDI_PH::enableTPPModel2), 0x35EA },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::PlayerState::playerVariables), 0x300 },
|
||||
{ GetOffsetNameFromClassMember(&GamePH::SessionCooperativeDI::pLocalClientDI), 0xE08 },
|
||||
});
|
||||
|
||||
AddPatterns(11200, {
|
||||
{ "LoadPlayerVars", { "40 55 53 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 33 FF", Utils::SigScan::PatternType::Address } },
|
||||
{ "PlayerState", { "48 8B 3D [?? ?? ?? ?? 4C 8B EA", Utils::SigScan::PatternType::RelativePointer } },
|
||||
{ "SaveGameCRCBoolCheck", { "FF 50 ?? [40 22 FB 0F 85 ?? ?? ?? ?? 0F B6 05 ?? ?? ?? ?? 48 8D 1D", Utils::SigScan::PatternType::Address } },
|
||||
{ "IsNotOutOfMapBounds", { "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 4C 8B C2", Utils::SigScan::PatternType::Address } },
|
||||
{ "IsNotOutOfMissionBounds", { "48 89 5C 24 ?? 57 48 83 EC ?? 4C 8B C2 48 8B F9", Utils::SigScan::PatternType::Address } },
|
||||
{ "PlaySoundEvent", { "4C 8B DC 49 89 5B ?? 49 89 73 ?? 57 48 81 EC ?? ?? ?? ?? 4C 8B 4C 24 ?? 48 8B F9 4D 8B D0 66 C7 84 24 ?? ?? ?? ?? ?? ?? 49 8B C1 66 C7 84 24", Utils::SigScan::PatternType::Address } },
|
||||
{ "GetPlayerRestrictionsFlags", { "48 89 5C 24 ?? 57 48 83 EC ?? 48 8B F9 48 8B DA 48 8B CA E8 ?? ?? ?? ?? 48 8B 4F", Utils::SigScan::PatternType::Address } },
|
||||
{ "EnablePlayerRestrictionsSubFunc", { "40 53 48 83 EC ?? 48 8B D9 48 81 C1 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B CB 48 83 C4 ?? 5B E9 ?? ?? ?? ?? CC CC CC CC CC CC CC CC CC CC CC CC CC CC 48 89 4C 24", Utils::SigScan::PatternType::Address } },
|
||||
{ "DisablePlayerRestrictionsSubFunc", { "48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC ?? 0F B7 81", Utils::SigScan::PatternType::Address } },
|
||||
{ "HandlePlayerRestrictions", { "40 57 48 83 EC ?? 48 89 5C 24 ?? 48 8B F9 48 89 6C 24 ?? 0F B6 A9", Utils::SigScan::PatternType::Address } }
|
||||
});
|
||||
AddPatterns(12001, {
|
||||
{ "LoadPlayerVars", { "48 89 4C 24 ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 8C 24", Utils::SigScan::PatternType::Address } },
|
||||
{ "PlayerState", { "48 8B 35 [?? ?? ?? ?? 4C 8B F2 48 8B F9", Utils::SigScan::PatternType::RelativePointer } },
|
||||
{ "SaveGameCRCBoolCheck", { "FF 50 ?? [40 22 DF 0F 85 ?? ?? ?? ?? 0F B6 05 ?? ?? ?? ?? 48 8D 3D", Utils::SigScan::PatternType::Address } },
|
||||
{ "IsNotOutOfMapBounds", { "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 4C 8B F9 48 85 D2", Utils::SigScan::PatternType::Address } },
|
||||
{ "IsNotOutOfMissionBounds", { "48 89 5C 24 ?? 57 48 83 EC ?? 48 8B F9 48 85 D2 74 ?? 48 8D 8A", Utils::SigScan::PatternType::Address } },
|
||||
{ "PlaySoundEvent", { "4C 8B DC 49 89 5B ?? 49 89 73 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B 44 24 ?? 48 8B F9 48 8B DA", Utils::SigScan::PatternType::Address } },
|
||||
{ "GetPlayerRestrictionsFlags", { "48 89 5C 24 ?? 57 48 83 EC ?? 48 8B D9 48 8B FA 48 8B CA E8 ?? ?? ?? ?? 48 8B 4B", Utils::SigScan::PatternType::Address } },
|
||||
{ "EnablePlayerRestrictionsSubFunc", { "40 53 48 83 EC ?? 48 8B D9 48 81 C1 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B CB 48 83 C4 ?? 5B E9 ?? ?? ?? ?? CC CC CC CC CC CC CC CC CC CC CC CC CC CC 40 57", Utils::SigScan::PatternType::Address } },
|
||||
{ "DisablePlayerRestrictionsSubFunc", { "48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC ?? 0F B6 81", Utils::SigScan::PatternType::Address } },
|
||||
{ "HandlePlayerRestrictions", { "40 57 48 83 EC ?? 48 89 5C 24 ?? 48 8B F9 48 89 74 24 ?? 0F B6 B1", Utils::SigScan::PatternType::Address } }
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
DWORD OffsetManager::GetOffset(const std::string& offsetName) {
|
||||
if (!initialized)
|
||||
return 0;
|
||||
|
||||
auto& offsets = GetOffsetsMap();
|
||||
if (offsets.find(Core::gameVer) != offsets.end() && offsets[Core::gameVer].find(offsetName) != offsets[Core::gameVer].end())
|
||||
return offsets[Core::gameVer][offsetName];
|
||||
|
||||
SPDLOG_ERROR("Offset not found for key: \"{}\" in version: {}", offsetName, Core::gameVer);
|
||||
return 0;
|
||||
}
|
||||
Utils::SigScan::Pattern OffsetManager::GetPattern(const std::string& patternName) {
|
||||
if (!initialized)
|
||||
return {};
|
||||
|
||||
auto& patterns = GetPatternsMap();
|
||||
if (patterns.find(Core::gameVer) != patterns.end() && patterns[Core::gameVer].find(patternName) != patterns[Core::gameVer].end())
|
||||
return patterns[Core::gameVer][patternName];
|
||||
|
||||
SPDLOG_ERROR("Pattern not found for key: \"{}\" in version: {}", patternName, Core::gameVer);
|
||||
return {};
|
||||
}
|
||||
|
||||
void OffsetManager::AddOffsets(DWORD gameVer, const std::unordered_map<std::string, DWORD>& offsets) {
|
||||
GetOffsetsMap()[gameVer] = offsets;
|
||||
}
|
||||
void OffsetManager::AddPatterns(DWORD gameVer, const std::unordered_map<std::string, Utils::SigScan::Pattern>& patterns) {
|
||||
GetPatternsMap()[gameVer] = patterns;
|
||||
}
|
||||
|
||||
std::unordered_map<DWORD, std::unordered_map<std::string, DWORD>>& OffsetManager::GetOffsetsMap() {
|
||||
static std::unordered_map<DWORD, std::unordered_map<std::string, DWORD>> offsetsMap;
|
||||
return offsetsMap;
|
||||
}
|
||||
std::unordered_map<DWORD, std::unordered_map<std::string, Utils::SigScan::Pattern>>& OffsetManager::GetPatternsMap() {
|
||||
static std::unordered_map<DWORD, std::unordered_map<std::string, Utils::SigScan::Pattern>> patternsMap;
|
||||
return patternsMap;
|
||||
}
|
||||
}
|
@ -1 +1,39 @@
|
||||
|
||||
#include <unordered_map>
|
||||
#include <EGSDK\Utils\WinMemory.h>
|
||||
|
||||
namespace EGSDK::Utils {
|
||||
namespace Memory {
|
||||
HMODULE GetCallingDLLModule(void* callerAddress) {
|
||||
HMODULE callerModule{};
|
||||
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)callerAddress, &callerModule))
|
||||
return callerModule;
|
||||
return nullptr;
|
||||
}
|
||||
MODULEINFO GetModuleInfo(const char* szModule) {
|
||||
if (!szModule)
|
||||
return MODULEINFO();
|
||||
|
||||
static std::unordered_map<std::string_view, MODULEINFO> moduleInfoCache;
|
||||
auto it = moduleInfoCache.find(szModule);
|
||||
if (it != moduleInfoCache.end())
|
||||
return it->second;
|
||||
|
||||
HMODULE hModule = GetModuleHandle(szModule);
|
||||
if (hModule == 0)
|
||||
return MODULEINFO();
|
||||
|
||||
MODULEINFO moduleInfo{};
|
||||
GetModuleInformation(GetCurrentProcess(), hModule, &moduleInfo, sizeof(MODULEINFO));
|
||||
moduleInfoCache[szModule] = moduleInfo;
|
||||
|
||||
return moduleInfoCache[szModule];
|
||||
}
|
||||
FARPROC GetProcAddr(const std::string_view& module, const std::string_view& funcName) {
|
||||
HMODULE moduleHandle = GetModuleHandle(module.data());
|
||||
if (!moduleHandle)
|
||||
return nullptr;
|
||||
|
||||
return GetProcAddress(moduleHandle, funcName.data());
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
|
@ -159,10 +159,10 @@
|
||||
<ClCompile Include="deps\ImGui\imguiex_animation.cpp">
|
||||
<Filter>deps\ImGui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ImGui_impl\DeferredActions.cpp">
|
||||
<ClCompile Include="src\ImGui_impl\NextFrameTask.cpp">
|
||||
<Filter>src\ImGui_impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ImGui_impl\NextFrameTask.cpp">
|
||||
<ClCompile Include="src\ImGui_impl\DeferredActions.cpp">
|
||||
<Filter>src\ImGui_impl</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
@ -7,7 +7,7 @@ namespace EGT::Menu {
|
||||
namespace Camera {
|
||||
extern EGSDK::Vec3 cameraOffset;
|
||||
extern float firstPersonFOV;
|
||||
extern float originalFirstPersonFOVAfterZoomIn;
|
||||
extern float originalFirstPersonFOVBeforeZoomIn;
|
||||
extern ImGui::KeyBindOption firstPersonZoomIn;
|
||||
|
||||
extern ImGui::Option photoMode;
|
||||
|
@ -90,7 +90,7 @@ namespace EGT::Engine {
|
||||
if (Menu::Camera::thirdPersonCamera.GetValue())
|
||||
fov = static_cast<float>(Menu::Camera::thirdPersonFOV);
|
||||
else if (!Menu::Camera::firstPersonZoomIn.IsKeyDown())
|
||||
Menu::Camera::originalFirstPersonFOVAfterZoomIn = fov;
|
||||
Menu::Camera::originalFirstPersonFOVBeforeZoomIn = fov;
|
||||
|
||||
return SetFOVHook.ExecuteCallbacksWithOriginal(pCBaseCamera, fov);
|
||||
} };
|
||||
@ -321,40 +321,41 @@ namespace EGT::Engine {
|
||||
if (!varValuePtr)
|
||||
return varValuePtr;
|
||||
|
||||
EGSDK::Engine::CVar* cVar = EGSDK::Engine::CVars::vars.Find(valueOffset);
|
||||
auto cVar = EGSDK::Engine::CVars::GetVarRef(valueOffset);
|
||||
if (!cVar)
|
||||
return varValuePtr;
|
||||
cVar->AddValuePtr(varValuePtr);
|
||||
|
||||
EGSDK::Engine::CVar* customCVar = EGSDK::Engine::CVars::customVars.Find(cVar->GetName());
|
||||
//EGSDK::Engine::CVar* customCVar = EGSDK::Engine::CVars::customVars.Find(cVar->GetName());
|
||||
auto customCVar = EGSDK::Engine::CVars::GetCustomVarRef(cVar->GetName());
|
||||
if (!customCVar)
|
||||
return varValuePtr;
|
||||
|
||||
switch (cVar->GetType()) {
|
||||
case EGSDK::Engine::VarType::Float:
|
||||
{
|
||||
auto value = EGSDK::Engine::CVars::GetVarValue<float>(customCVar);
|
||||
auto value = customCVar->GetValue<float>();
|
||||
if (value)
|
||||
cVar->SetValue(*value);
|
||||
break;
|
||||
}
|
||||
case EGSDK::Engine::VarType::Int:
|
||||
{
|
||||
auto value = EGSDK::Engine::CVars::GetVarValue<int>(customCVar);
|
||||
auto value = customCVar->GetValue<int>();
|
||||
if (value)
|
||||
cVar->SetValue(*value);
|
||||
break;
|
||||
}
|
||||
case EGSDK::Engine::VarType::Vec3:
|
||||
{
|
||||
auto value = EGSDK::Engine::CVars::GetVarValue<EGSDK::Vec3>(customCVar);
|
||||
auto value = customCVar->GetValue<EGSDK::Vec3>();
|
||||
if (value)
|
||||
cVar->SetValue(*value);
|
||||
break;
|
||||
}
|
||||
case EGSDK::Engine::VarType::Vec4:
|
||||
{
|
||||
auto value = EGSDK::Engine::CVars::GetVarValue<EGSDK::Vec4>(customCVar);
|
||||
auto value = customCVar->GetValue<EGSDK::Vec4>();
|
||||
if (value)
|
||||
cVar->SetValue(*value);
|
||||
break;
|
||||
|
@ -20,7 +20,7 @@ namespace EGT::Menu {
|
||||
|
||||
EGSDK::Vec3 cameraOffset{};
|
||||
float firstPersonFOV = baseFOV;
|
||||
float originalFirstPersonFOVAfterZoomIn = firstPersonFOV;
|
||||
float originalFirstPersonFOVBeforeZoomIn = firstPersonFOV;
|
||||
ImGui::KeyBindOption firstPersonZoomIn{ false, 'Q', false };
|
||||
static bool isZoomingIn = false;
|
||||
|
||||
@ -90,25 +90,39 @@ namespace EGT::Menu {
|
||||
}
|
||||
|
||||
if (iLevel && iLevel->IsLoaded() && viewCam && !thirdPersonCamera.GetValue() && !freeCam.GetValue()) {
|
||||
constexpr float level1Min = 42.0f;
|
||||
constexpr float level2Min = 25.0f;
|
||||
constexpr float level3Min = 15.0f;
|
||||
|
||||
if (firstPersonZoomIn.IsKeyDown()) {
|
||||
if (firstPersonZoomIn.IsKeyPressed()) {
|
||||
hasChangedZoomLevel = true;
|
||||
if (!isZoomingIn) {
|
||||
originalFirstPersonFOVAfterZoomIn = viewCam->GetFOV();
|
||||
previousFirstPersonFOV = originalFirstPersonFOVAfterZoomIn;
|
||||
originalFirstPersonFOVBeforeZoomIn = viewCam->GetFOV();
|
||||
previousFirstPersonFOV = originalFirstPersonFOVBeforeZoomIn;
|
||||
} else
|
||||
previousFirstPersonFOV = firstPersonFOV;
|
||||
|
||||
float rawFOVLevel1 = originalFirstPersonFOVBeforeZoomIn - 25.0f;
|
||||
float rawFOVLevel2 = originalFirstPersonFOVBeforeZoomIn - 45.0f;
|
||||
|
||||
if (std::abs(rawFOVLevel1 - level1Min) > 5.0f)
|
||||
zoomLevel = 2;
|
||||
else if (std::abs(rawFOVLevel2 - level2Min) > 5.0f)
|
||||
zoomLevel = 3;
|
||||
else
|
||||
zoomLevel = 1;
|
||||
}
|
||||
|
||||
isZoomingIn = true;
|
||||
|
||||
float targetFOV = previousFirstPersonFOV;
|
||||
if (zoomLevel == 0)
|
||||
targetFOV = std::max(originalFirstPersonFOVAfterZoomIn - 25.0f, 42.0f);
|
||||
else if (zoomLevel == 1)
|
||||
targetFOV = std::max(originalFirstPersonFOVAfterZoomIn - 45.0f, 25.0f);
|
||||
if (zoomLevel == 1)
|
||||
targetFOV = std::max(originalFirstPersonFOVBeforeZoomIn - 25.0f, level1Min);
|
||||
else if (zoomLevel == 2)
|
||||
targetFOV = std::max(originalFirstPersonFOVAfterZoomIn - 65.0f, 15.0f);
|
||||
targetFOV = std::max(originalFirstPersonFOVBeforeZoomIn - 45.0f, level2Min);
|
||||
else if (zoomLevel == 3)
|
||||
targetFOV = std::max(originalFirstPersonFOVBeforeZoomIn - 65.0f, level3Min);
|
||||
|
||||
firstPersonFOV = ImGui::AnimateLerp("zoomInFOVLerp", previousFirstPersonFOV, targetFOV, 0.3f, hasChangedZoomLevel, &ImGui::AnimEaseOutSine);
|
||||
viewCam->SetFOV(firstPersonFOV);
|
||||
@ -116,28 +130,28 @@ namespace EGT::Menu {
|
||||
|
||||
if (ImGui::KeyBindOption::scrolledMouseWheelUp) {
|
||||
ImGui::KeyBindOption::scrolledMouseWheelUp = false;
|
||||
if (zoomLevel < 2) {
|
||||
if (zoomLevel < 3) {
|
||||
zoomLevel++;
|
||||
previousFirstPersonFOV = firstPersonFOV;
|
||||
hasChangedZoomLevel = true;
|
||||
}
|
||||
} else if (ImGui::KeyBindOption::scrolledMouseWheelDown) {
|
||||
ImGui::KeyBindOption::scrolledMouseWheelDown = false;
|
||||
if (zoomLevel > 0) {
|
||||
if (zoomLevel > 1) {
|
||||
zoomLevel--;
|
||||
previousFirstPersonFOV = firstPersonFOV;
|
||||
hasChangedZoomLevel = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
zoomLevel = 0;
|
||||
zoomLevel = 1;
|
||||
if (firstPersonZoomIn.IsKeyReleased()) {
|
||||
hasChangedZoomLevel = true;
|
||||
previousFirstPersonFOV = firstPersonFOV;
|
||||
}
|
||||
|
||||
if (!EGSDK::Utils::Values::are_samef(firstPersonFOV, originalFirstPersonFOVAfterZoomIn) && isZoomingIn) {
|
||||
firstPersonFOV = ImGui::AnimateLerp("zoomInFOVLerp", previousFirstPersonFOV, originalFirstPersonFOVAfterZoomIn, 0.25f, hasChangedZoomLevel, &ImGui::AnimEaseOutSine);
|
||||
if (!EGSDK::Utils::Values::are_samef(firstPersonFOV, originalFirstPersonFOVBeforeZoomIn) && isZoomingIn) {
|
||||
firstPersonFOV = ImGui::AnimateLerp("zoomInFOVLerp", previousFirstPersonFOV, originalFirstPersonFOVBeforeZoomIn, 0.25f, hasChangedZoomLevel, &ImGui::AnimEaseOutSine);
|
||||
viewCam->SetFOV(firstPersonFOV);
|
||||
hasChangedZoomLevel = false;
|
||||
} else
|
||||
@ -251,7 +265,7 @@ namespace EGT::Menu {
|
||||
lensDistortionJustEnabled = false;
|
||||
}
|
||||
|
||||
EGSDK::GamePH::PlayerVariables::ChangeVar("FOVCorrection", goProMode.GetValue() ? (altLensDistortion / 100.0f) : (lensDistortion / 100.0f));
|
||||
EGSDK::GamePH::PlayerVariables::GetVarRef("FOVCorrection")->SetValue(goProMode.GetValue() ? (altLensDistortion / 100.0f) : (lensDistortion / 100.0f));
|
||||
EGSDK::GamePH::PlayerVariables::ManageVarByBool("SprintHeadCorrectionFactor", 0.0f, baseSprintHeadCorrectionFactor, goProMode.GetValue() ? goProMode.GetValue() : disableHeadCorrection.GetValue(), true);
|
||||
}
|
||||
static void UpdateDisabledOptions() {
|
||||
|
Reference in New Issue
Block a user