diff --git a/EGameTools/EGameTools.vcxproj b/EGameTools/EGameTools.vcxproj
index 79b7906..bde176c 100644
--- a/EGameTools/EGameTools.vcxproj
+++ b/EGameTools/EGameTools.vcxproj
@@ -45,7 +45,6 @@
-
@@ -158,7 +157,6 @@
-
diff --git a/EGameTools/pch/pch.h b/EGameTools/pch/pch.h
index 1677226..5da84ab 100644
--- a/EGameTools/pch/pch.h
+++ b/EGameTools/pch/pch.h
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include
#include
diff --git a/EGameTools/source/core.cpp b/EGameTools/source/core.cpp
index c523539..010438b 100644
--- a/EGameTools/source/core.cpp
+++ b/EGameTools/source/core.cpp
@@ -38,7 +38,9 @@ namespace Core {
#pragma endregion
// Core
- bool exiting = false;
+ std::atomic exiting = false;
+ static std::vector threads{};
+ static HANDLE keepAliveEvent{};
int rendererAPI = 0;
DWORD gameVer = 0;
@@ -232,36 +234,52 @@ namespace Core {
spdlog::warn("Initializing config");
Config::InitConfig();
- std::thread(Config::ConfigLoop).detach();
+ threads.emplace_back(Config::ConfigLoop);
CreateSymlinkForLoadingFiles();
for (auto& hook : *Utils::Hook::HookBase::GetInstances()) {
- std::thread([&hook]() {
+ threads.emplace_back([&hook]() {
maxHookThreads.acquire();
- spdlog::warn("Hooking \"{}\"", hook->name.data());
- if (hook->HookLoop())
+ if (hook->isHooking) {
+ spdlog::warn("Hooking \"{}\"", hook->name.data());
+ while (hook->isHooking)
+ Sleep(10);
+
+ if (hook->isHooked)
+ spdlog::info("Hooked \"{}\"!", hook->name.data());
+ } else if (hook->isHooked)
spdlog::info("Hooked \"{}\"!", hook->name.data());
+ else {
+ spdlog::warn("Hooking \"{}\"", hook->name.data());
+ if (hook->HookLoop())
+ spdlog::info("Hooked \"{}\"!", hook->name.data());
+ }
maxHookThreads.release();
}).detach();
}
spdlog::warn("Sorting Player Variables");
- std::thread([]() {
+ threads.emplace_back([]() {
GamePH::PlayerVariables::SortPlayerVars();
spdlog::info("Player Variables sorted");
}).detach();
spdlog::warn("Hooking DX11/DX12 renderer");
- std::thread([]() {
+ threads.emplace_back([]() {
LoopHookRenderer();
spdlog::info("Hooked \"DX11/DX12 renderer\"!");
}).detach();
- const HANDLE proc = GetCurrentProcess();
- WaitForSingleObject(proc, INFINITE);
+ keepAliveEvent = CreateEventA(nullptr, TRUE, FALSE, nullptr);
+ WaitForSingleObject(keepAliveEvent, INFINITE);
+
+ for (auto& thread : threads) {
+ if (thread.joinable())
+ thread.join();
+ }
return TRUE;
}
@@ -278,5 +296,7 @@ namespace Core {
MH_DisableHook(MH_ALL_HOOKS);
MH_Uninitialize();
spdlog::info("Unhooked everything");
+
+ SetEvent(keepAliveEvent);
}
}
diff --git a/EGameTools/source/core.h b/EGameTools/source/core.h
index a5ccc0c..0f28666 100644
--- a/EGameTools/source/core.h
+++ b/EGameTools/source/core.h
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include "..\utils\values.h"
#ifndef VK_NONE
@@ -225,7 +226,7 @@ private:
};
namespace Core {
- extern bool exiting;
+ extern std::atomic exiting;
extern int rendererAPI;
extern DWORD gameVer;
diff --git a/EGameTools/source/game/Engine/CoPhysicsProperty.cpp b/EGameTools/source/game/Engine/CoPhysicsProperty.cpp
index 61e6c33..b347674 100644
--- a/EGameTools/source/game/Engine/CoPhysicsProperty.cpp
+++ b/EGameTools/source/game/Engine/CoPhysicsProperty.cpp
@@ -1,15 +1,15 @@
#include
-#include "..\GamePH\PlayerObjProperties.h"
+#include "..\GamePH\PlayerDI_PH.h"
#include "CoPhysicsProperty.h"
namespace Engine {
CoPhysicsProperty* CoPhysicsProperty::Get() {
__try {
- GamePH::PlayerObjProperties* pPlayerObjProperties = GamePH::PlayerObjProperties::Get();
- if (!pPlayerObjProperties)
+ GamePH::PlayerDI_PH* pPlayerDI_PH = GamePH::PlayerDI_PH::Get();
+ if (!pPlayerDI_PH)
return nullptr;
- CoPhysicsProperty* ptr = pPlayerObjProperties->pCoPhysicsProperty;
+ CoPhysicsProperty* ptr = pPlayerDI_PH->pCoPhysicsProperty;
if (!Utils::Memory::IsValidPtrMod(ptr, "engine_x64_rwdi.dll"))
return nullptr;
diff --git a/EGameTools/source/game/GamePH/LevelDI.cpp b/EGameTools/source/game/GamePH/LevelDI.cpp
index d088ee1..a70ac27 100644
--- a/EGameTools/source/game/GamePH/LevelDI.cpp
+++ b/EGameTools/source/game/GamePH/LevelDI.cpp
@@ -2,7 +2,7 @@
#include "..\Engine\CLevel.h"
#include "..\offsets.h"
#include "LevelDI.h"
-#include "PlayerObjProperties.h"
+#include "PlayerDI_PH.h"
namespace GamePH {
bool LevelDI::IsLoading() {
@@ -20,7 +20,7 @@ namespace GamePH {
static Utils::Time::Timer loadTimer{ 7500 };
static bool isStillLoading = false;
- if (IsLoading() || !GamePH::PlayerObjProperties::Get()) {
+ if (IsLoading() || !GamePH::PlayerDI_PH::Get()) {
isStillLoading = true;
return false;
}
diff --git a/EGameTools/source/game/GamePH/PlayerDI_PH.h b/EGameTools/source/game/GamePH/PlayerDI_PH.h
index e71e9fe..c370449 100644
--- a/EGameTools/source/game/GamePH/PlayerDI_PH.h
+++ b/EGameTools/source/game/GamePH/PlayerDI_PH.h
@@ -3,10 +3,15 @@
#include "InventoryItem.h"
#include "InventoryContainerDI.h"
+namespace Engine {
+ class CoPhysicsProperty;
+}
+
namespace GamePH {
class PlayerDI_PH {
public:
union {
+ buffer<0xF0, Engine::CoPhysicsProperty*> pCoPhysicsProperty;
buffer<0x35E9, bool> enableTPPModel1;
buffer<0x35EA, bool> enableTPPModel2;
};
diff --git a/EGameTools/source/game/GamePH/PlayerObjProperties.cpp b/EGameTools/source/game/GamePH/PlayerObjProperties.cpp
deleted file mode 100644
index 163aa57..0000000
--- a/EGameTools/source/game/GamePH/PlayerObjProperties.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#include
-#include "..\offsets.h"
-#include "PlayerObjProperties.h"
-
-namespace GamePH {
- PlayerObjProperties* PlayerObjProperties::Get() {
- __try {
- if (!Offsets::Get_g_PlayerObjProperties())
- return nullptr;
-
- PlayerObjProperties* ptr = *reinterpret_cast(Offsets::Get_g_PlayerObjProperties());
- if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
- return nullptr;
-
- return ptr;
- } __except (EXCEPTION_EXECUTE_HANDLER) {
- return nullptr;
- }
- }
-}
\ No newline at end of file
diff --git a/EGameTools/source/game/GamePH/PlayerObjProperties.h b/EGameTools/source/game/GamePH/PlayerObjProperties.h
deleted file mode 100644
index d9e9695..0000000
--- a/EGameTools/source/game/GamePH/PlayerObjProperties.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma once
-#include "..\buffer.h"
-
-namespace Engine {
- class CoPhysicsProperty;
-}
-
-namespace GamePH {
- class PlayerObjProperties {
- public:
- union {
- buffer<0xF0, Engine::CoPhysicsProperty*> pCoPhysicsProperty;
- //buffer<0x2E80, bool> isOutOfBounds;
- //buffer<0x2E84, float> outOfBoundsTimer;
- };
-
- static PlayerObjProperties* Get();
- };
-}
\ No newline at end of file
diff --git a/EGameTools/source/menu/camera.cpp b/EGameTools/source/menu/camera.cpp
index bf498ac..d77447d 100644
--- a/EGameTools/source/menu/camera.cpp
+++ b/EGameTools/source/menu/camera.cpp
@@ -6,7 +6,7 @@
#include "..\game\GamePH\GameDI_PH.h"
#include "..\game\GamePH\LevelDI.h"
#include "..\game\GamePH\PlayerVariables.h"
-#include "..\game\GamePH\PlayerObjProperties.h"
+#include "..\game\GamePH\PlayerDI_PH.h"
#include "..\game\GamePH\gameph_misc.h"
#include "..\offsets.h"
#include "camera.h"
@@ -149,8 +149,8 @@ namespace Menu {
if (!iLevel || !iLevel->IsLoaded())
return;
- GamePH::PlayerObjProperties* playerObjProperties = GamePH::PlayerObjProperties::Get();
- if (playerObjProperties) {
+ GamePH::PlayerDI_PH* pPlayerDI_PH = GamePH::PlayerDI_PH::Get();
+ if (pPlayerDI_PH) {
if (Menu::Camera::freeCam.GetValue() && !iLevel->IsTimerFrozen())
GamePH::ShowTPPModel(true);
else if (Menu::Camera::freeCam.GetValue() && iLevel->IsTimerFrozen() && !photoMode.GetValue())
diff --git a/EGameTools/source/menu/debug.cpp b/EGameTools/source/menu/debug.cpp
index a82631a..6ab945a 100644
--- a/EGameTools/source/menu/debug.cpp
+++ b/EGameTools/source/menu/debug.cpp
@@ -10,7 +10,6 @@
#include "..\game\GamePH\LogicalPlayer.h"
#include "..\game\GamePH\PlayerDI_PH.h"
#include "..\game\GamePH\PlayerHealthModule.h"
-#include "..\game\GamePH\PlayerObjProperties.h"
#include "..\game\GamePH\PlayerState.h"
#include "..\game\GamePH\PlayerVariables.h"
#include "..\game\GamePH\SessionCooperativeDI.h"
@@ -41,7 +40,6 @@ namespace Menu {
{ "LogicalPlayer", reinterpret_cast(&GamePH::LogicalPlayer::Get) },
{ "PlayerDI_PH", reinterpret_cast(&GamePH::PlayerDI_PH::Get) },
{ "PlayerHealthModule", reinterpret_cast(&GamePH::PlayerHealthModule::Get) },
- { "PlayerObjProperties", reinterpret_cast(&GamePH::PlayerObjProperties::Get) },
{ "PlayerState", reinterpret_cast(&GamePH::PlayerState::Get) },
{ "PlayerVariables", reinterpret_cast(&GamePH::PlayerVariables::Get) },
{ "SessionCooperativeDI", reinterpret_cast(&GamePH::SessionCooperativeDI::Get) },
diff --git a/EGameTools/source/offsets.h b/EGameTools/source/offsets.h
index 55fbf36..d408a5b 100644
--- a/EGameTools/source/offsets.h
+++ b/EGameTools/source/offsets.h
@@ -71,7 +71,7 @@ struct Offsets {
AddStaticOffset(allowVelocityMod_offset, 0x5C)
AddStaticOffset(disableHeadCorrection_offset, 0x108)
AddOffset(CLobbySteam, "engine_x64_rwdi.dll", "48 8B 05 [?? ?? ?? ?? 48 85 C0 74 ?? 48 83 C0", Utils::SigScan::PatternType::RelativePointer, LPVOID)
- AddOffset(g_PlayerObjProperties, "gamedll_ph_x64_rwdi.dll", "48 89 0D [?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0", Utils::SigScan::PatternType::RelativePointer, LPVOID)
+ //AddOffset(g_PlayerDI_PH, "gamedll_ph_x64_rwdi.dll", "48 89 0D [?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0", Utils::SigScan::PatternType::RelativePointer, LPVOID) // also PlayerObjProperties
AddOffset(g_DayNightCycle, "gamedll_ph_x64_rwdi.dll", "48 8B 0D [?? ?? ?? ?? 48 85 C9 74 ?? E8 ?? ?? ?? ?? 84 C0 74 ?? B0 ?? 48 83 C4 ?? C3 32 C0", Utils::SigScan::PatternType::RelativePointer, LPVOID)
//AddOffset(g_CameraFPPDI, "gamedll_ph_x64_rwdi.dll", "48 89 05 [?? ?? ?? ?? 40 84 FF", PatternType::RelativePointer, DWORD64*)
AddOffset(g_FreeCamera, "gamedll_ph_x64_rwdi.dll", "48 89 05 [?? ?? ?? ?? 48 89 4C 24", Utils::SigScan::PatternType::RelativePointer, DWORD64*)
diff --git a/EGameTools/source/utils/hook.h b/EGameTools/source/utils/hook.h
index fce2e43..26181d8 100644
--- a/EGameTools/source/utils/hook.h
+++ b/EGameTools/source/utils/hook.h
@@ -1,6 +1,7 @@
#pragma once
#include
#include
+#include
#include "..\MinHook\MinHook.h"
namespace Utils {
@@ -30,7 +31,9 @@ namespace Utils {
virtual bool HookLoop() { return false; };
- const std::string_view name;
+ const std::string_view name{};
+ std::atomic isHooking = false;
+ std::atomic isHooked = false;
};
template
class ByteHook : HookBase {
@@ -38,13 +41,18 @@ namespace Utils {
ByteHook(const std::string_view& name, GetTargetOffsetRetType(*pGetOffsetFunc)(), unsigned char* patchBytes, size_t bytesAmount, Option* optionRef = nullptr) : HookBase(name), pGetOffsetFunc(pGetOffsetFunc), patchBytes(patchBytes), bytesAmount(bytesAmount), optionRef(optionRef) {}
bool HookLoop() override {
- if (hooked || (optionRef && !optionRef->GetValue()))
+ if (isHooked || (optionRef && !optionRef->GetValue()))
return true;
+ if (isHooking)
+ return true;
+
+ isHooking = true;
timeSpentHooking = Utils::Time::Timer(120000);
while (true) {
if (timeSpentHooking.DidTimePass()) {
spdlog::error("Failed hooking \"{}\" after 120 seconds", name);
+ isHooking = false;
return false;
}
if (!pGetOffsetFunc || !pGetOffsetFunc())
@@ -60,7 +68,8 @@ namespace Utils {
}
memcpy_s(pGetOffsetFunc(), bytesAmount, patchBytes, bytesAmount);
VirtualProtect(pGetOffsetFunc(), bytesAmount, originalProtection, &oldProtection);
- hooked = true;
+ isHooked = true;
+ isHooking = false;
return true;
Sleep(10);
@@ -68,7 +77,7 @@ namespace Utils {
}
void Enable() {
- if (hooked)
+ if (isHooked)
return;
DWORD originalProtection = 0;
@@ -81,10 +90,10 @@ namespace Utils {
}
memcpy_s(pGetOffsetFunc(), bytesAmount, patchBytes, bytesAmount);
VirtualProtect(pGetOffsetFunc(), bytesAmount, originalProtection, &oldProtection);
- hooked = true;
+ isHooked = true;
}
void Disable() {
- if (!hooked)
+ if (!isHooked)
return;
DWORD originalProtection = 0;
@@ -93,11 +102,11 @@ namespace Utils {
VirtualProtect(pGetOffsetFunc(), bytesAmount, PAGE_EXECUTE_READWRITE, &originalProtection);
memcpy_s(pGetOffsetFunc(), bytesAmount, origBytes, bytesAmount);
VirtualProtect(pGetOffsetFunc(), bytesAmount, originalProtection, &oldProtection);
- hooked = false;
+ isHooked = false;
}
void Toggle() {
if (!optionRef) {
- hooked ? Disable() : Enable();
+ isHooked ? Disable() : Enable();
return;
}
@@ -111,8 +120,6 @@ namespace Utils {
unsigned char* patchBytes = nullptr;
size_t bytesAmount = 0;
- bool hooked = false;
-
Utils::Time::Timer timeSpentHooking{ 120000 };
};
template
@@ -123,11 +130,16 @@ namespace Utils {
bool HookLoop() override {
if (pOriginal)
return true;
+ if (isHooking)
+ return true;
+
+ isHooking = true;
timeSpentHooking = Utils::Time::Timer(120000);
while (true) {
if (timeSpentHooking.DidTimePass()) {
spdlog::error("Failed hooking function \"{}\" after 120 seconds", name);
+ isHooking = false;
return false;
}
if (!pGetOffsetFunc)
@@ -137,6 +149,8 @@ namespace Utils {
pTarget = reinterpret_cast(pGetOffsetFunc());
else if (!pOriginal && MH_CreateHook(pTarget, pDetour, reinterpret_cast(&pOriginal)) == MH_OK) {
MH_EnableHook(pTarget);
+ isHooked = true;
+ isHooking = false;
return true;
}
@@ -160,11 +174,16 @@ namespace Utils {
bool HookLoop() override {
if (pOriginal)
return true;
+ if (isHooking)
+ return true;
+
+ isHooking = true;
timeSpentHooking = Utils::Time::Timer(120000);
while (true) {
if (timeSpentHooking.DidTimePass()) {
spdlog::error("Failed hooking function \"{}\" after 120 seconds", name);
+ isHooking = false;
return false;
}
if (!pGetOffsetFunc)
@@ -174,7 +193,11 @@ namespace Utils {
pInstance = pGetOffsetFunc();
else if (!pOriginal) {
HookVT(pInstance, pDetour, reinterpret_cast(&pOriginal), offset);
- return true;
+ if (pOriginal) {
+ isHooked = true;
+ isHooking = false;
+ return true;
+ }
}
Sleep(10);