mirror of
https://github.com/EricPlayZ/EGameTools.git
synced 2025-07-18 17:37:53 +08:00
backup, made a lot of changes related to vftable scanning
This commit is contained in:
@ -9,9 +9,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EGameTools", "EGameTools\EG
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EGameSDK", "EGameSDK\EGameSDK.vcxproj", "{152BCFEC-E42D-4370-AEDD-36F044085C0C}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{47F0BD81-B327-0619-BC31-6A3C28E82C12} = {47F0BD81-B327-0619-BC31-6A3C28E82C12}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ultimate-ASI-Loader-x64", "Ultimate-ASI-Loader-x64\Ultimate-ASI-Loader-x64.vcxproj", "{47F0BD81-B327-0619-BC31-6A3C28E82C12}"
|
||||
EndProject
|
@ -13,6 +13,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="deps\memscan\memscan.c" />
|
||||
<ClCompile Include="deps\memscan\util\util.c" />
|
||||
<ClCompile Include="src\ClassHelpers.cpp" />
|
||||
<ClCompile Include="src\Core\Core.cpp" />
|
||||
<ClCompile Include="src\dllmain.cpp" />
|
||||
<ClCompile Include="src\Engine\CBaseCamera.cpp" />
|
||||
|
@ -136,6 +136,9 @@
|
||||
<ClCompile Include="src\Vector3.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ClassHelpers.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="include">
|
||||
|
@ -2,61 +2,72 @@
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <typeinfo>
|
||||
#include <EGSDK\Utils\Memory.h>
|
||||
#include <EGSDK\Utils\RTTI.h>
|
||||
#include <EGSDK\Utils\Values.h>
|
||||
#include <EGSDK\Exports.h>
|
||||
|
||||
namespace EGSDK {
|
||||
namespace ClassHelpers {
|
||||
#pragma pack(1)
|
||||
template<size_t size, typename T>
|
||||
class buffer {
|
||||
char buffer[size];
|
||||
public:
|
||||
T data;
|
||||
template<size_t size, typename T>
|
||||
class buffer {
|
||||
char buffer[size];
|
||||
public:
|
||||
T data;
|
||||
|
||||
operator T() { return data; }
|
||||
T operator->() { return data; }
|
||||
operator T() { return data; }
|
||||
T operator->() { return data; }
|
||||
|
||||
DWORD64 operator&(const DWORD64 other) const { return reinterpret_cast<DWORD64>(data) & other; }
|
||||
DWORD64 operator>>(const int shift) const { return reinterpret_cast<DWORD64>(data) >> shift; }
|
||||
DWORD64 operator<<(const int shift) const { return reinterpret_cast<DWORD64>(data) << shift; }
|
||||
DWORD64 operator&(const DWORD64 other) const { return reinterpret_cast<DWORD64>(data) & other; }
|
||||
DWORD64 operator>>(const int shift) const { return reinterpret_cast<DWORD64>(data) >> shift; }
|
||||
DWORD64 operator<<(const int shift) const { return reinterpret_cast<DWORD64>(data) << shift; }
|
||||
|
||||
T& operator=(const T& other) { data = other; return data; }
|
||||
T& operator*=(const T& other) { data *= other; return data; }
|
||||
T operator*(const T& other) const { return data * other; }
|
||||
T& operator/=(const T& other) { data /= other; return data; }
|
||||
T operator/(const T& other) const { return data / other; }
|
||||
T& operator+=(const T& other) { data += other; return data; }
|
||||
T operator+(const T& other) const { return data + other; }
|
||||
T& operator-=(const T& other) { data -= other; return data; }
|
||||
T operator-(const T& other) const { return data - other; }
|
||||
};
|
||||
T& operator=(const T& other) { data = other; return data; }
|
||||
T& operator*=(const T& other) { data *= other; return data; }
|
||||
T operator*(const T& other) const { return data * other; }
|
||||
T& operator/=(const T& other) { data /= other; return data; }
|
||||
T operator/(const T& other) const { return data / other; }
|
||||
T& operator+=(const T& other) { data += other; return data; }
|
||||
T operator+(const T& other) const { return data + other; }
|
||||
T& operator-=(const T& other) { data -= other; return data; }
|
||||
T operator-(const T& other) const { return data - other; }
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
template <typename T, typename GetOffsetFunc, typename GetVTFunc = std::nullptr_t, typename... Args>
|
||||
static T* _SafeGetImpl(GetOffsetFunc getOffset, const char* moduleName, bool isDoublePtr, GetVTFunc getVT, Args... args) {
|
||||
if (!getOffset(args...))
|
||||
return nullptr;
|
||||
extern EGameSDK_API bool IsVftableScanningDisabled();
|
||||
extern EGameSDK_API void SetIsVftableScanningDisabled(bool value);
|
||||
|
||||
T* ptr = isDoublePtr ? *reinterpret_cast<T**>(getOffset(args...)) : reinterpret_cast<T*>(getOffset(args...));
|
||||
if (moduleName && !Utils::Memory::IsValidPtrMod(ptr, moduleName))
|
||||
return nullptr;
|
||||
|
||||
if constexpr (!std::is_same_v<GetVTFunc, std::nullptr_t>) {
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != getVT())
|
||||
template <typename T, typename GetOffsetFunc, typename... Args>
|
||||
T* _SafeGetImpl(GetOffsetFunc getOffset, bool isDoublePtr, std::string_view className, Args... args) {
|
||||
if (!getOffset(args...))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
T* ptr = isDoublePtr ? *reinterpret_cast<T**>(getOffset(args...)) : reinterpret_cast<T*>(getOffset(args...));
|
||||
if (Utils::Memory::IsBadReadPtr(ptr))
|
||||
return nullptr;
|
||||
|
||||
if (IsVftableScanningDisabled())
|
||||
return ptr;
|
||||
|
||||
if (!className.empty() && !Utils::RTTI::IsClassVTableNameEqualTo(ptr, className))
|
||||
return nullptr;
|
||||
else if (className.empty() && !Utils::RTTI::IsClassVTableNameEqualTo(ptr, Utils::Values::GetSimpleTypeName(typeid(T).name())))
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
template <typename T, typename GetOffsetFunc, typename... Args>
|
||||
T* SafeGetter(GetOffsetFunc getOffset, bool isDoublePtr = true, std::string_view className = {}, Args... args) {
|
||||
return Utils::Memory::SafeExecution::Execute<T*>(
|
||||
reinterpret_cast<uint64_t>(&_SafeGetImpl<T, GetOffsetFunc, Args...>),
|
||||
nullptr,
|
||||
reinterpret_cast<void*>(getOffset),
|
||||
isDoublePtr,
|
||||
className,
|
||||
args...
|
||||
);
|
||||
}
|
||||
}
|
||||
template <typename T, typename GetOffsetFunc, typename GetVTFunc = std::nullptr_t, typename... Args>
|
||||
static T* _SafeGetter(GetOffsetFunc getOffset, const char* moduleName, bool isDoublePtr = true, GetVTFunc getVT = nullptr, Args... args) {
|
||||
return Utils::Memory::SafeExecution::Execute<T*>(
|
||||
reinterpret_cast<uint64_t>(&_SafeGetImpl<T, GetOffsetFunc, GetVTFunc, Args...>),
|
||||
nullptr,
|
||||
reinterpret_cast<void*>(getOffset),
|
||||
moduleName,
|
||||
isDoublePtr,
|
||||
reinterpret_cast<void*>(getVT),
|
||||
args...
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,11 +5,11 @@ namespace EGSDK::Engine {
|
||||
class EGameSDK_API CBaseCamera {
|
||||
public:
|
||||
/*union {
|
||||
buffer<0x48, float> yaw;
|
||||
buffer<0x4C, float> X;
|
||||
buffer<0x58, float> pitch;
|
||||
buffer<0x5C, float> Y;
|
||||
buffer<0x6C, float> Z;
|
||||
ClassHelpers::buffer<0x48, float> yaw;
|
||||
ClassHelpers::buffer<0x4C, float> X;
|
||||
ClassHelpers::buffer<0x58, float> pitch;
|
||||
ClassHelpers::buffer<0x5C, float> Y;
|
||||
ClassHelpers::buffer<0x6C, float> Z;
|
||||
};*/
|
||||
Vector3* GetForwardVector(Vector3* outForwardVec);
|
||||
Vector3* GetUpVector(Vector3* outUpVec);
|
||||
|
@ -6,9 +6,9 @@ namespace EGSDK::Engine {
|
||||
class EGameSDK_API CBulletPhysicsCharacter {
|
||||
public:
|
||||
union {
|
||||
buffer<0xCB8, Vector3> playerPos2;
|
||||
buffer<0xCD0, Vector3> playerPos;
|
||||
buffer<0x1050, float> playerDownwardVelocity;
|
||||
ClassHelpers::buffer<0xCB8, Vector3> playerPos2;
|
||||
ClassHelpers::buffer<0xCD0, Vector3> playerPos;
|
||||
ClassHelpers::buffer<0x1050, float> playerDownwardVelocity;
|
||||
};
|
||||
|
||||
static Vector3 posBeforeFreeze;
|
||||
|
@ -7,7 +7,7 @@ namespace EGSDK::Engine {
|
||||
class EGameSDK_API CGSObject {
|
||||
public:
|
||||
union {
|
||||
buffer<0x48, CLevel2*> pCLevel2;
|
||||
ClassHelpers::buffer<0x48, CLevel2*> pCLevel2;
|
||||
};
|
||||
|
||||
static CGSObject* Get();
|
||||
|
@ -10,7 +10,7 @@ namespace EGSDK {
|
||||
class EGameSDK_API CGSObject2 {
|
||||
public:
|
||||
union {
|
||||
buffer<0x20, GamePH::LogicalPlayer*> pLogicalPlayer;
|
||||
ClassHelpers::buffer<0x20, GamePH::LogicalPlayer*> pLogicalPlayer;
|
||||
};
|
||||
|
||||
static CGSObject2* Get();
|
||||
|
@ -13,9 +13,9 @@ namespace EGSDK {
|
||||
class EGameSDK_API CGame {
|
||||
public:
|
||||
union {
|
||||
buffer<0x8, GamePH::GameDI_PH*> pGameDI_PH;
|
||||
buffer<0x28, CVideoSettings*> pCVideoSettings;
|
||||
buffer<0x390, CLevel*> pCLevel;
|
||||
ClassHelpers::buffer<0x8, GamePH::GameDI_PH*> pGameDI_PH;
|
||||
ClassHelpers::buffer<0x28, CVideoSettings*> pCVideoSettings;
|
||||
ClassHelpers::buffer<0x390, CLevel*> pCLevel;
|
||||
};
|
||||
|
||||
static CGame* Get();
|
||||
|
@ -12,8 +12,8 @@ namespace EGSDK {
|
||||
class EGameSDK_API CLevel {
|
||||
public:
|
||||
union {
|
||||
buffer<0x20, GamePH::LevelDI*> pLevelDI;
|
||||
buffer<0x30, CGSObject*> pCGSObject;
|
||||
ClassHelpers::buffer<0x20, GamePH::LevelDI*> pLevelDI;
|
||||
ClassHelpers::buffer<0x30, CGSObject*> pCGSObject;
|
||||
};
|
||||
|
||||
static CLevel* Get();
|
||||
|
@ -7,7 +7,7 @@ namespace EGSDK::Engine {
|
||||
class EGameSDK_API CLevel2 {
|
||||
public:
|
||||
union {
|
||||
buffer<0x28, CGSObject2*> pCGSObject2;
|
||||
ClassHelpers::buffer<0x28, CGSObject2*> pCGSObject2;
|
||||
};
|
||||
|
||||
static CLevel2* Get();
|
||||
|
@ -7,7 +7,7 @@ namespace EGSDK::Engine {
|
||||
class EGameSDK_API CLobbySteam {
|
||||
public:
|
||||
union {
|
||||
buffer<0xF8, CGame*> pCGame;
|
||||
ClassHelpers::buffer<0xF8, CGame*> pCGame;
|
||||
};
|
||||
|
||||
static CLobbySteam* Get();
|
||||
|
@ -5,7 +5,7 @@ namespace EGSDK::Engine {
|
||||
class EGameSDK_API CVideoSettings {
|
||||
public:
|
||||
union {
|
||||
buffer<0x7C, float> extraFOV;
|
||||
ClassHelpers::buffer<0x7C, float> extraFOV;
|
||||
};
|
||||
|
||||
static CVideoSettings* Get();
|
||||
|
@ -7,7 +7,7 @@ namespace EGSDK::Engine {
|
||||
class EGameSDK_API CoPhysicsProperty {
|
||||
public:
|
||||
union {
|
||||
buffer<0x20, CBulletPhysicsCharacter*> pCBulletPhysicsCharacter;
|
||||
ClassHelpers::buffer<0x20, CBulletPhysicsCharacter*> pCBulletPhysicsCharacter;
|
||||
};
|
||||
|
||||
static CoPhysicsProperty* Get();
|
||||
|
@ -7,7 +7,7 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API CoBaseCameraProxy {
|
||||
public:
|
||||
union {
|
||||
buffer<0xD0, TPPCameraDI*> pTPPCameraDI;
|
||||
ClassHelpers::buffer<0xD0, TPPCameraDI*> pTPPCameraDI;
|
||||
};
|
||||
};
|
||||
}
|
@ -5,9 +5,9 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API DayNightCycle {
|
||||
public:
|
||||
union {
|
||||
buffer<0x10, float> time1;
|
||||
buffer<0x20, float> time2;
|
||||
buffer<0x5C, float> time3;
|
||||
ClassHelpers::buffer<0x10, float> time1;
|
||||
ClassHelpers::buffer<0x20, float> time2;
|
||||
ClassHelpers::buffer<0x5C, float> time3;
|
||||
};
|
||||
|
||||
void SetDaytime(float time);
|
||||
|
@ -8,12 +8,12 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API FreeCamera : public Engine::CBaseCamera {
|
||||
public:
|
||||
union {
|
||||
buffer<0x18, CoBaseCameraProxy*> pCoBaseCameraProxy;
|
||||
buffer<0x38, Engine::CBaseCamera*> pCBaseCamera;
|
||||
buffer<0x42, bool> enableSpeedMultiplier1;
|
||||
buffer<0x43, bool> enableSpeedMultiplier2;
|
||||
buffer<0x1B4, float> FOV;
|
||||
buffer<0x1CC, float> speedMultiplier;
|
||||
ClassHelpers::buffer<0x18, CoBaseCameraProxy*> pCoBaseCameraProxy;
|
||||
ClassHelpers::buffer<0x38, Engine::CBaseCamera*> pCBaseCamera;
|
||||
ClassHelpers::buffer<0x42, bool> enableSpeedMultiplier1;
|
||||
ClassHelpers::buffer<0x43, bool> enableSpeedMultiplier2;
|
||||
ClassHelpers::buffer<0x1B4, float> FOV;
|
||||
ClassHelpers::buffer<0x1CC, float> speedMultiplier;
|
||||
};
|
||||
|
||||
void AllowCameraMovement(int mode = 2);
|
||||
|
@ -7,8 +7,8 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API GameDI_PH {
|
||||
public:
|
||||
union {
|
||||
buffer<0x130, SessionCooperativeDI*> pSessionCooperativeDI;
|
||||
buffer<0x910, bool> blockPauseGameOnPlayerAfk;
|
||||
ClassHelpers::buffer<0x130, SessionCooperativeDI*> pSessionCooperativeDI;
|
||||
ClassHelpers::buffer<0x910, bool> blockPauseGameOnPlayerAfk;
|
||||
};
|
||||
|
||||
float GetGameTimeDelta();
|
||||
|
@ -4,6 +4,6 @@
|
||||
namespace EGSDK::GamePH {
|
||||
class EGameSDK_API InventoryMoney {
|
||||
public:
|
||||
buffer<0x38, int> oldWorldMoney;
|
||||
ClassHelpers::buffer<0x38, int> oldWorldMoney;
|
||||
};
|
||||
}
|
@ -5,7 +5,7 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API ItemDescWithContext {
|
||||
public:
|
||||
union {
|
||||
buffer<0xA8, float> weaponDurability;
|
||||
ClassHelpers::buffer<0xA8, float> weaponDurability;
|
||||
};
|
||||
};
|
||||
}
|
@ -7,7 +7,7 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API LocalClientDI {
|
||||
public:
|
||||
union {
|
||||
buffer<0x90, PlayerDI_PH*> pPlayerDI_PH;
|
||||
ClassHelpers::buffer<0x90, PlayerDI_PH*> pPlayerDI_PH;
|
||||
};
|
||||
|
||||
static LocalClientDI* Get();
|
||||
|
@ -11,9 +11,9 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API PlayerDI_PH {
|
||||
public:
|
||||
union {
|
||||
buffer<0xF0, Engine::CoPhysicsProperty*> pCoPhysicsProperty;
|
||||
buffer<0x35E9, bool> enableTPPModel1;
|
||||
buffer<0x35EA, bool> enableTPPModel2;
|
||||
ClassHelpers::buffer<0xF0, Engine::CoPhysicsProperty*> pCoPhysicsProperty;
|
||||
ClassHelpers::buffer<0x35E9, bool> enableTPPModel1;
|
||||
ClassHelpers::buffer<0x35EA, bool> enableTPPModel2;
|
||||
};
|
||||
|
||||
static PlayerDI_PH* Get();
|
||||
|
@ -8,9 +8,9 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API PlayerHealthModule {
|
||||
public:
|
||||
union {
|
||||
buffer<0x8, PlayerDI_PH*> pPlayerDI_PH;
|
||||
buffer<0x2C, float> health;
|
||||
buffer<0x3C, float> maxHealth;
|
||||
ClassHelpers::buffer<0x8, PlayerDI_PH*> pPlayerDI_PH;
|
||||
ClassHelpers::buffer<0x2C, float> health;
|
||||
ClassHelpers::buffer<0x3C, float> maxHealth;
|
||||
};
|
||||
|
||||
~PlayerHealthModule();
|
||||
|
@ -8,9 +8,9 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API PlayerInfectionModule {
|
||||
public:
|
||||
union {
|
||||
buffer<0x8, PlayerDI_PH*> pPlayerDI_PH;
|
||||
buffer<0x20, float> maxImmunity;
|
||||
buffer<0x2C, float> immunity;
|
||||
ClassHelpers::buffer<0x8, PlayerDI_PH*> pPlayerDI_PH;
|
||||
ClassHelpers::buffer<0x20, float> maxImmunity;
|
||||
ClassHelpers::buffer<0x2C, float> immunity;
|
||||
};
|
||||
|
||||
~PlayerInfectionModule();
|
||||
|
@ -7,7 +7,7 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API PlayerState {
|
||||
public:
|
||||
union {
|
||||
buffer<0x300, PlayerVariables*> pPlayerVariables;
|
||||
ClassHelpers::buffer<0x300, PlayerVariables*> pPlayerVariables;
|
||||
};
|
||||
|
||||
static PlayerState* Get();
|
||||
|
@ -7,7 +7,7 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API SessionCooperativeDI {
|
||||
public:
|
||||
union {
|
||||
buffer<0xE08, LocalClientDI*> pLocalClientDI;
|
||||
ClassHelpers::buffer<0xE08, LocalClientDI*> pLocalClientDI;
|
||||
};
|
||||
|
||||
static SessionCooperativeDI* Get();
|
||||
|
@ -9,7 +9,7 @@ namespace EGSDK {
|
||||
static EGameSDK_API retType Get_## name () {\
|
||||
static retType name = NULL;\
|
||||
static int i = 0;\
|
||||
if (Utils::Memory::IsValidPtr(name) || !GetModuleHandleA(moduleName) || i >= 50) return name;\
|
||||
if (!Utils::Memory::IsBadReadPtr(name) || !GetModuleHandleA(moduleName) || i >= 50) return name;\
|
||||
i++;\
|
||||
return name=reinterpret_cast<retType>(Utils::SigScan::PatternScanner::FindPattern(moduleName, {pattern, type}));\
|
||||
}
|
||||
@ -22,54 +22,21 @@ namespace EGSDK {
|
||||
#define AddStaticOffset2(name, moduleName, off) \
|
||||
static EGameSDK_API DWORD64 Get_## name () {\
|
||||
static DWORD64 name = 0;\
|
||||
if (Utils::Memory::IsValidPtr(name)) return name;\
|
||||
if (!Utils::Memory::IsBadReadPtr(name)) return name;\
|
||||
return name=reinterpret_cast<DWORD64>(GetModuleHandleA(moduleName)) + static_cast<DWORD64>(off);\
|
||||
}
|
||||
|
||||
#define AddVTOffset(name, moduleName, rttiName, retType)\
|
||||
static EGameSDK_API retType GetVT_## name () {\
|
||||
static retType VT_## name = NULL;\
|
||||
static int i = 0;\
|
||||
if (Utils::Memory::IsValidPtr(VT_## name)|| !GetModuleHandleA(moduleName) || i >= 50) return VT_## name;\
|
||||
i++;\
|
||||
return VT_## name=reinterpret_cast<retType>(Utils::RTTI::GetVTablePtr(moduleName, rttiName));\
|
||||
}
|
||||
|
||||
struct Offsets {
|
||||
// Input related
|
||||
AddOffset(CInput, "engine_x64_rwdi.dll", "48 8B 0D [?? ?? ?? ?? 48 85 C9 74 ?? 48 8B 01 84 D2", Utils::SigScan::PatternType::RelativePointer, DWORD64**) // g_CInput
|
||||
|
||||
// Player vars related
|
||||
AddVTOffset(FloatPlayerVariable, "gamedll_ph_x64_rwdi.dll", "FloatPlayerVariable", void*)
|
||||
AddVTOffset(BoolPlayerVariable, "gamedll_ph_x64_rwdi.dll", "BoolPlayerVariable", void*)
|
||||
AddVTOffset(TypedFieldMetaFloatPlayerVariable, "gamedll_ph_x64_rwdi.dll", "?$TypedFieldMeta@VFloatPlayerVariable@@@?$FieldsCollection@VPlayerVariables@@@constds", void*)
|
||||
AddVTOffset(TypedFieldMetaBoolPlayerVariable, "gamedll_ph_x64_rwdi.dll", "?$TypedFieldMeta@VBoolPlayerVariable@@@?$FieldsCollection@VPlayerVariables@@@constds", void*)
|
||||
//AddVTOffset(TypedFieldMetaFloatPlayerVariable, "gamedll_ph_x64_rwdi.dll", "?$TypedFieldMeta@VFloatPlayerVariable@@@?$FieldsCollection@VPlayerVariables@@@constds", void*)
|
||||
//AddVTOffset(TypedFieldMetaBoolPlayerVariable, "gamedll_ph_x64_rwdi.dll", "?$TypedFieldMeta@VBoolPlayerVariable@@@?$FieldsCollection@VPlayerVariables@@@constds", void*)
|
||||
AddOffset(LoadPlayerVars, "gamedll_ph_x64_rwdi.dll", "48 89 4C 24 ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 8C 24", Utils::SigScan::PatternType::Address, void*)
|
||||
AddOffset(PlayerState, "gamedll_ph_x64_rwdi.dll", "48 8B 35 [?? ?? ?? ?? 4C 8B F2 48 8B F9", Utils::SigScan::PatternType::RelativePointer, void*)
|
||||
|
||||
// Game related
|
||||
AddVTOffset(CBulletPhysicsCharacter, "engine_x64_rwdi.dll", "CBulletPhysicsCharacter", void*)
|
||||
AddVTOffset(CGSObject, "engine_x64_rwdi.dll", "CGSObject", void*)
|
||||
AddVTOffset(CInput, "engine_x64_rwdi.dll", "CInput", void*)
|
||||
AddVTOffset(CLevel, "engine_x64_rwdi.dll", "CLevel", void*)
|
||||
AddVTOffset(CLobbySteam, "engine_x64_rwdi.dll", "CLobbySteam", void*)
|
||||
AddVTOffset(CVideoSettings, "engine_x64_rwdi.dll", "CVideoSettings", void*)
|
||||
|
||||
AddVTOffset(DayNightCycle, "gamedll_ph_x64_rwdi.dll", "DayNightCycle", void*)
|
||||
AddVTOffset(FreeCamera, "gamedll_ph_x64_rwdi.dll", "FreeCamera", void*)
|
||||
AddVTOffset(GameDI_PH, "gamedll_ph_x64_rwdi.dll", "GameDI_PH", void*)
|
||||
AddVTOffset(InventoryContainerDI, "gamedll_ph_x64_rwdi.dll", "InventoryContainerDI", void*)
|
||||
AddVTOffset(InventoryItem, "gamedll_ph_x64_rwdi.dll", "InventoryItem", void*)
|
||||
AddVTOffset(InventoryMoney, "gamedll_ph_x64_rwdi.dll", "InventoryMoney", void*)
|
||||
AddVTOffset(ItemDescWithContext, "gamedll_ph_x64_rwdi.dll", "ItemDescWithContext", void*)
|
||||
AddVTOffset(LevelDI, "gamedll_ph_x64_rwdi.dll", "LevelDI", void*)
|
||||
AddVTOffset(LocalClientDI, "gamedll_ph_x64_rwdi.dll", "LocalClientDI", void*)
|
||||
AddVTOffset(LogicalPlayer, "gamedll_ph_x64_rwdi.dll", "LogicalPlayer", void*)
|
||||
AddVTOffset(PlayerDI_PH, "gamedll_ph_x64_rwdi.dll", "PlayerDI_PH", void*)
|
||||
AddVTOffset(PlayerState, "gamedll_ph_x64_rwdi.dll", "PlayerState", void*)
|
||||
AddVTOffset(SessionCooperativeDI, "gamedll_ph_x64_rwdi.dll", "SessionCooperativeDI", void*)
|
||||
AddVTOffset(TPPCameraDI, "gamedll_ph_x64_rwdi.dll", "TPPCameraDI", void*)
|
||||
|
||||
AddStaticOffset(gameDI_PH2_offset, 0x28)
|
||||
AddStaticOffset(allowVelocityMod_offset, 0x5C)
|
||||
AddStaticOffset(disableHeadCorrection_offset, 0x108)
|
||||
|
@ -13,10 +13,10 @@ namespace EGSDK::Utils {
|
||||
static const BYTE SigScanWildCard = 0xAA;
|
||||
static const std::string_view SigScanWildCardStr = "AA";
|
||||
|
||||
class SafeExecution {
|
||||
private:
|
||||
static int fail(unsigned int code, struct _EXCEPTION_POINTERS* ep);
|
||||
class EGameSDK_API SafeExecution {
|
||||
public:
|
||||
static int fail(unsigned int code, struct _EXCEPTION_POINTERS* ep);
|
||||
|
||||
template<typename T = void*, typename R = T, typename... Args>
|
||||
static T Execute(uint64_t ptr, R ret, Args... args) {
|
||||
__try {
|
||||
@ -40,25 +40,93 @@ namespace EGSDK::Utils {
|
||||
extern EGameSDK_API const MODULEINFO GetModuleInfo(const char* szModule);
|
||||
extern EGameSDK_API const FARPROC GetProcAddr(const std::string_view& module, const std::string_view& funcName);
|
||||
|
||||
extern EGameSDK_API const bool IsAddressValidMod(const DWORD64 ptr, const char* moduleName);
|
||||
|
||||
extern EGameSDK_API std::string BytesToIDAPattern(BYTE* bytes, size_t size);
|
||||
extern EGameSDK_API std::string ConvertSigToScannerSig(const char* pattern, int* offsetToAddrInSig = nullptr);
|
||||
|
||||
extern EGameSDK_API DWORD64 CalcTargetAddrOfRelInst(DWORD64 addrOfInst, size_t opSize);
|
||||
extern EGameSDK_API DWORD64 CalcTargetAddrOfRelativeInstr(DWORD64 addrOfInst, size_t opSize);
|
||||
extern EGameSDK_API std::vector<DWORD64> GetXrefsTo(DWORD64 address, DWORD64 start, size_t size);
|
||||
|
||||
#pragma region Templates
|
||||
template<typename ptrT> bool IsValidPtr(ptrT ptr) {
|
||||
__try {
|
||||
return !IsBadReadPtr(reinterpret_cast<void*>(ptr), sizeof(void*));
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
/*
|
||||
Copyright (c) 2017 Artem Boldarev <artem.boldarev@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files(the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
// COPYRIGHT NOTICE - START
|
||||
template <typename T>
|
||||
bool IsBadMemPtr(const bool write, T* ptr, const std::size_t size) {
|
||||
const auto min_ptr = 0x10000;
|
||||
const auto max_ptr = 0x000F000000000000;
|
||||
|
||||
if (ptr == nullptr || reinterpret_cast<DWORD64>(ptr) < min_ptr || reinterpret_cast<DWORD64>(ptr) >= max_ptr)
|
||||
return true;
|
||||
|
||||
DWORD mask = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
|
||||
|
||||
if (write)
|
||||
mask = PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
|
||||
|
||||
auto current = reinterpret_cast<BYTE*>(ptr);
|
||||
const auto last = current + size;
|
||||
|
||||
// So we are considering the region:
|
||||
// [ptr, ptr+size)
|
||||
|
||||
while (current < last) {
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
|
||||
// We couldn't get any information on this region.
|
||||
// Let's not risk any read/write operation.
|
||||
if (VirtualQuery(reinterpret_cast<LPCVOID>(current), &mbi, sizeof mbi) == 0)
|
||||
return true;
|
||||
|
||||
// We can't perform our desired read/write operations in this region.
|
||||
if ((mbi.Protect & mask) == 0)
|
||||
return true;
|
||||
|
||||
// We can't access this region.
|
||||
if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS))
|
||||
return true;
|
||||
|
||||
// Let's consider the next region.
|
||||
current = reinterpret_cast<BYTE*>(mbi.BaseAddress) + mbi.RegionSize;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
template<typename ptrT = void*> bool IsValidPtrMod(ptrT ptr, const char* moduleName, const bool checkForVT = true) {
|
||||
return IsValidPtr<ptrT>(ptr) && IsAddressValidMod(checkForVT ? *(PDWORD64)(ptr) : (DWORD64)(ptr), moduleName);
|
||||
template <typename T>
|
||||
bool IsBadReadPtr(T* ptr, const std::size_t size) {
|
||||
return IsBadMemPtr(false, ptr, size);
|
||||
}
|
||||
template <typename T>
|
||||
bool IsBadReadPtr(T* ptr) {
|
||||
return IsBadReadPtr(ptr, sizeof ptr);
|
||||
}
|
||||
template <typename T>
|
||||
bool IsBadWritePtr(T* ptr, const std::size_t size) {
|
||||
return IsBadMemPtr(true, ptr, size);
|
||||
}
|
||||
template <typename T>
|
||||
bool IsBadWritePtr(T* ptr) {
|
||||
return IsBadWritePtr(ptr, sizeof ptr);
|
||||
}
|
||||
// COPYRIGHT NOTICE - END
|
||||
|
||||
template <std::size_t Index, typename ReturnType = void, typename... Args> __forceinline ReturnType CallVT(void* instance, Args... args) {
|
||||
using Fn = ReturnType(__thiscall*)(void*, Args...);
|
||||
|
@ -6,6 +6,9 @@
|
||||
|
||||
namespace EGSDK::Utils {
|
||||
namespace RTTI {
|
||||
extern EGameSDK_API DWORD64 GetVTablePtr(const char* moduleName, const char* tableName);
|
||||
extern EGameSDK_API std::string GetVTableNameFromVTPtr(void* vtPtr);
|
||||
extern EGameSDK_API std::string GetVTableName(void* classPtr);
|
||||
extern EGameSDK_API bool IsClassVTableNameEqualTo(void* classPtr, std::string_view tableName);
|
||||
extern EGameSDK_API bool IsVTableNameEqualTo(void* vtPtr, std::string_view tableName);
|
||||
}
|
||||
}
|
@ -16,5 +16,7 @@ namespace EGSDK::Utils {
|
||||
else
|
||||
return std::to_string(val);
|
||||
}
|
||||
|
||||
extern EGameSDK_API std::string GetSimpleTypeName(std::string fullName);
|
||||
}
|
||||
}
|
10
EGameSDK/src/ClassHelpers.cpp
Normal file
10
EGameSDK/src/ClassHelpers.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include <EGSDK\ClassHelpers.h>
|
||||
|
||||
namespace EGSDK {
|
||||
namespace ClassHelpers {
|
||||
static volatile LONG disableVftableScanning = 0;
|
||||
|
||||
bool IsVftableScanningDisabled() { return _InterlockedCompareExchange(&disableVftableScanning, 0, 0) != 0; }
|
||||
void SetIsVftableScanningDisabled(bool value) { _InterlockedExchange(&disableVftableScanning, value ? 1 : 0); }
|
||||
}
|
||||
}
|
@ -20,6 +20,6 @@ namespace EGSDK::Engine {
|
||||
return pCoPhysicsProperty ? pCoPhysicsProperty->pCBulletPhysicsCharacter : nullptr;
|
||||
}
|
||||
CBulletPhysicsCharacter* CBulletPhysicsCharacter::Get() {
|
||||
return _SafeGetter<CBulletPhysicsCharacter>(GetOffset_CBulletPhysicsCharacter, "engine_x64_rwdi.dll", false, Offsets::GetVT_CBulletPhysicsCharacter);
|
||||
return ClassHelpers::SafeGetter<CBulletPhysicsCharacter>(GetOffset_CBulletPhysicsCharacter, false);
|
||||
}
|
||||
}
|
@ -9,6 +9,6 @@ namespace EGSDK::Engine {
|
||||
return pCLevel ? pCLevel->pCGSObject : nullptr;
|
||||
}
|
||||
CGSObject* CGSObject::Get() {
|
||||
return _SafeGetter<CGSObject>(GetOffset_CGSObject, "engine_x64_rwdi.dll", false, Offsets::GetVT_CGSObject);
|
||||
return ClassHelpers::SafeGetter<CGSObject>(GetOffset_CGSObject, false);
|
||||
}
|
||||
}
|
@ -9,6 +9,6 @@ namespace EGSDK::Engine {
|
||||
return pCLevel2 ? pCLevel2->pCGSObject2 : nullptr;
|
||||
}
|
||||
CGSObject2* CGSObject2::Get() {
|
||||
return _SafeGetter<CGSObject2>(GetOffset_CGSObject2, "engine_x64_rwdi.dll", false, nullptr);
|
||||
return ClassHelpers::SafeGetter<CGSObject2>(GetOffset_CGSObject2, false);
|
||||
}
|
||||
}
|
@ -9,6 +9,6 @@ namespace EGSDK::Engine {
|
||||
return pCLobbySteam ? pCLobbySteam->pCGame : nullptr;
|
||||
}
|
||||
CGame* CGame::Get() {
|
||||
return _SafeGetter<CGame>(GetOffset_CGame, "engine_x64_rwdi.dll", false, nullptr);
|
||||
return ClassHelpers::SafeGetter<CGame>(GetOffset_CGame, false);
|
||||
}
|
||||
}
|
@ -11,6 +11,6 @@ namespace EGSDK::Engine {
|
||||
}
|
||||
|
||||
CInput* CInput::Get() {
|
||||
return _SafeGetter<CInput>(Offsets::Get_CInput, "engine_x64_rwdi.dll", true, Offsets::GetVT_CInput);
|
||||
return ClassHelpers::SafeGetter<CInput>(Offsets::Get_CInput, true);
|
||||
}
|
||||
}
|
@ -9,6 +9,6 @@ namespace EGSDK::Engine {
|
||||
return pCGame ? pCGame->pCLevel : nullptr;
|
||||
}
|
||||
CLevel* CLevel::Get() {
|
||||
return _SafeGetter<CLevel>(GetOffset_CLevel, "engine_x64_rwdi.dll", false, Offsets::GetVT_CLevel);
|
||||
return ClassHelpers::SafeGetter<CLevel>(GetOffset_CLevel, false);
|
||||
}
|
||||
}
|
@ -9,6 +9,6 @@ namespace EGSDK::Engine {
|
||||
return pCGSObject ? pCGSObject->pCLevel2 : nullptr;
|
||||
}
|
||||
CLevel2* CLevel2::Get() {
|
||||
return _SafeGetter<CLevel2>(GetOffset_CLevel2, "engine_x64_rwdi.dll", false, nullptr);
|
||||
return ClassHelpers::SafeGetter<CLevel2>(GetOffset_CLevel2, false);
|
||||
}
|
||||
}
|
@ -4,6 +4,6 @@
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
CLobbySteam* CLobbySteam::Get() {
|
||||
return _SafeGetter<CLobbySteam>(Offsets::Get_CLobbySteam, "engine_x64_rwdi.dll", true, Offsets::GetVT_CLobbySteam);
|
||||
return ClassHelpers::SafeGetter<CLobbySteam>(Offsets::Get_CLobbySteam, true);
|
||||
}
|
||||
}
|
@ -9,6 +9,6 @@ namespace EGSDK::Engine {
|
||||
return pCGame ? pCGame->pCVideoSettings : nullptr;
|
||||
}
|
||||
CVideoSettings* CVideoSettings::Get() {
|
||||
return _SafeGetter<CVideoSettings>(GetOffset_CVideoSettings, "engine_x64_rwdi.dll", false, Offsets::GetVT_CVideoSettings);
|
||||
return ClassHelpers::SafeGetter<CVideoSettings>(GetOffset_CVideoSettings, false);
|
||||
}
|
||||
}
|
@ -9,6 +9,6 @@ namespace EGSDK::Engine {
|
||||
return pPlayerDI_PH ? pPlayerDI_PH->pCoPhysicsProperty : nullptr;
|
||||
}
|
||||
CoPhysicsProperty* CoPhysicsProperty::Get() {
|
||||
return _SafeGetter<CoPhysicsProperty>(GetOffset_CoPhysicsProperty, "engine_x64_rwdi.dll", false, nullptr);
|
||||
return ClassHelpers::SafeGetter<CoPhysicsProperty>(GetOffset_CoPhysicsProperty, false);
|
||||
}
|
||||
}
|
@ -11,6 +11,6 @@ namespace EGSDK::GamePH {
|
||||
}
|
||||
|
||||
DayNightCycle* DayNightCycle::Get() {
|
||||
return _SafeGetter<DayNightCycle>(Offsets::Get_DayNightCycle, "gamedll_ph_x64_rwdi.dll", true, Offsets::GetVT_DayNightCycle);
|
||||
return ClassHelpers::SafeGetter<DayNightCycle>(Offsets::Get_DayNightCycle, true);
|
||||
}
|
||||
}
|
@ -8,6 +8,6 @@ namespace EGSDK::GamePH {
|
||||
}
|
||||
|
||||
FreeCamera* FreeCamera::Get() {
|
||||
return _SafeGetter<FreeCamera>(Offsets::Get_FreeCamera, "gamedll_ph_x64_rwdi.dll", true, Offsets::GetVT_FreeCamera);
|
||||
return ClassHelpers::SafeGetter<FreeCamera>(Offsets::Get_FreeCamera, true);
|
||||
}
|
||||
}
|
@ -17,6 +17,6 @@ namespace EGSDK::GamePH {
|
||||
return pCGame ? pCGame->pGameDI_PH : nullptr;
|
||||
}
|
||||
GameDI_PH* GameDI_PH::Get() {
|
||||
return _SafeGetter<GameDI_PH>(GetOffset_GameDI_PH, "gamedll_ph_x64_rwdi.dll", false, Offsets::GetVT_GameDI_PH);
|
||||
return ClassHelpers::SafeGetter<GameDI_PH>(GetOffset_GameDI_PH, false);
|
||||
}
|
||||
}
|
@ -9,6 +9,6 @@ namespace EGSDK::GamePH {
|
||||
return pGameDI_PH ? reinterpret_cast<GameDI_PH2*>(reinterpret_cast<DWORD64>(pGameDI_PH) + Offsets::Get_gameDI_PH2_offset()) : nullptr;
|
||||
}
|
||||
GameDI_PH2* GameDI_PH2::Get() {
|
||||
return _SafeGetter<GameDI_PH2>(GetOffset_GameDI_PH2, "gamedll_ph_x64_rwdi.dll", false, nullptr);
|
||||
return ClassHelpers::SafeGetter<GameDI_PH2>(GetOffset_GameDI_PH2, false);
|
||||
}
|
||||
}
|
@ -8,6 +8,6 @@ namespace EGSDK::GamePH {
|
||||
return Utils::Memory::_SafeCallFunctionOffset<InventoryMoney*>(Offsets::Get_PlayerGetInventoryMoney, nullptr, pInventoryContainerDI, indexMaybe);
|
||||
}
|
||||
InventoryMoney* InventoryContainerDI::GetInventoryMoney(UINT indexMaybe) {
|
||||
return _SafeGetter<InventoryMoney>(GetOffset_InventoryMoney, "gamedll_ph_x64_rwdi.dll", false, Offsets::GetVT_InventoryMoney, this, indexMaybe);
|
||||
return ClassHelpers::SafeGetter<InventoryMoney>(GetOffset_InventoryMoney, false, {}, this, indexMaybe);
|
||||
}
|
||||
}
|
@ -8,6 +8,6 @@ namespace EGSDK::GamePH {
|
||||
return reinterpret_cast<ItemDescWithContext*>(reinterpret_cast<DWORD64>(pInventoryItem) + 0x40);
|
||||
}
|
||||
ItemDescWithContext* InventoryItem::GetItemDescCtx() {
|
||||
return _SafeGetter<ItemDescWithContext>(GetOffset_ItemDescWithContext, "gamedll_ph_x64_rwdi.dll", false, Offsets::GetVT_ItemDescWithContext, this);
|
||||
return ClassHelpers::SafeGetter<ItemDescWithContext>(GetOffset_ItemDescWithContext, false, {}, this);
|
||||
}
|
||||
}
|
@ -70,7 +70,7 @@ namespace EGSDK::GamePH {
|
||||
return pCLevel ? pCLevel->pLevelDI : nullptr;
|
||||
}
|
||||
LevelDI* LevelDI::Get() {
|
||||
LevelDI* ptr = _SafeGetter<LevelDI>(GetOffset_LevelDI, "gamedll_ph_x64_rwdi.dll", false, Offsets::GetVT_LevelDI);
|
||||
LevelDI* ptr = ClassHelpers::SafeGetter<LevelDI>(GetOffset_LevelDI, false);
|
||||
if (!ptr)
|
||||
ResetLoadTimer();
|
||||
|
||||
|
@ -9,6 +9,6 @@ namespace EGSDK::GamePH {
|
||||
return pSessionCooperativeDI ? pSessionCooperativeDI->pLocalClientDI : nullptr;
|
||||
}
|
||||
LocalClientDI* LocalClientDI::Get() {
|
||||
return _SafeGetter<LocalClientDI>(GetOffset_LocalClientDI, "gamedll_ph_x64_rwdi.dll", false, Offsets::GetVT_LocalClientDI);
|
||||
return ClassHelpers::SafeGetter<LocalClientDI>(GetOffset_LocalClientDI, false);
|
||||
}
|
||||
}
|
@ -9,6 +9,6 @@ namespace EGSDK::GamePH{
|
||||
return pCGSObject2 ? pCGSObject2->pLogicalPlayer : nullptr;
|
||||
}
|
||||
LogicalPlayer* LogicalPlayer::Get() {
|
||||
return _SafeGetter<LogicalPlayer>(GetOffset_LogicalPlayer, "gamedll_ph_x64_rwdi.dll", false, Offsets::GetVT_LogicalPlayer);
|
||||
return ClassHelpers::SafeGetter<LogicalPlayer>(GetOffset_LogicalPlayer, false);
|
||||
}
|
||||
}
|
@ -10,14 +10,14 @@ namespace EGSDK::GamePH {
|
||||
return Utils::Memory::_SafeCallFunctionOffset<InventoryItem*>(Offsets::Get_PlayerGetCurrentWeapon, nullptr, pPlayerDI_PH, indexMaybe);
|
||||
}
|
||||
InventoryItem* PlayerDI_PH::GetCurrentWeapon(UINT indexMaybe) {
|
||||
return _SafeGetter<InventoryItem>(GetOffset_CurrentWeapon, "gamedll_ph_x64_rwdi.dll", false, Offsets::GetVT_InventoryItem, this, indexMaybe);
|
||||
return ClassHelpers::SafeGetter<InventoryItem>(GetOffset_CurrentWeapon, false, {}, this, indexMaybe);
|
||||
}
|
||||
|
||||
static InventoryContainerDI* GetOffset_InventoryContainer(PlayerDI_PH* pPlayerDI_PH) {
|
||||
return reinterpret_cast<InventoryContainerDI*>(*reinterpret_cast<DWORD64*>(reinterpret_cast<DWORD64>(pPlayerDI_PH) + 0x470));
|
||||
}
|
||||
InventoryContainerDI* PlayerDI_PH::GetInventoryContainer() {
|
||||
return _SafeGetter<InventoryContainerDI>(GetOffset_InventoryContainer, "gamedll_ph_x64_rwdi.dll", false, Offsets::GetVT_InventoryContainerDI, this);
|
||||
return ClassHelpers::SafeGetter<InventoryContainerDI>(GetOffset_InventoryContainer, false, {}, this);
|
||||
}
|
||||
|
||||
static PlayerDI_PH* GetOffset_PlayerDI_PH() {
|
||||
@ -25,6 +25,6 @@ namespace EGSDK::GamePH {
|
||||
return pLocalClientDI ? pLocalClientDI->pPlayerDI_PH : nullptr;
|
||||
}
|
||||
PlayerDI_PH* PlayerDI_PH::Get() {
|
||||
return _SafeGetter<PlayerDI_PH>(GetOffset_PlayerDI_PH, "gamedll_ph_x64_rwdi.dll", false, Offsets::GetVT_PlayerDI_PH);
|
||||
return ClassHelpers::SafeGetter<PlayerDI_PH>(GetOffset_PlayerDI_PH, false);
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ namespace EGSDK::GamePH {
|
||||
return pPlayerHealthModule;
|
||||
}
|
||||
PlayerHealthModule* PlayerHealthModule::Get() {
|
||||
return _SafeGetter<PlayerHealthModule>(GetOffset_PlayerHealthModule, nullptr, false, nullptr);
|
||||
return ClassHelpers::SafeGetter<PlayerHealthModule>(GetOffset_PlayerHealthModule, false);
|
||||
}
|
||||
|
||||
void PlayerHealthModule::EmplaceBack(PlayerHealthModule* ptr) {
|
||||
|
@ -20,7 +20,7 @@ namespace EGSDK::GamePH {
|
||||
return pPlayerInfectionModule;
|
||||
}
|
||||
PlayerInfectionModule* PlayerInfectionModule::Get() {
|
||||
return _SafeGetter<PlayerInfectionModule>(GetOffset_PlayerInfectionModule, nullptr, false, nullptr);
|
||||
return ClassHelpers::SafeGetter<PlayerInfectionModule>(GetOffset_PlayerInfectionModule, false);
|
||||
}
|
||||
|
||||
void PlayerInfectionModule::EmplaceBack(PlayerInfectionModule* ptr) {
|
||||
|
@ -4,6 +4,6 @@
|
||||
|
||||
namespace EGSDK::GamePH {
|
||||
PlayerState* PlayerState::Get() {
|
||||
return _SafeGetter<PlayerState>(Offsets::Get_PlayerState, "gamedll_ph_x64_rwdi.dll", true, Offsets::GetVT_PlayerState);
|
||||
return ClassHelpers::SafeGetter<PlayerState>(Offsets::Get_PlayerState, true);
|
||||
}
|
||||
}
|
@ -34,8 +34,8 @@ namespace EGSDK::GamePH {
|
||||
static int offset = 0;
|
||||
__try {
|
||||
while (true) {
|
||||
const bool isFloatPlayerVar = *(playerVarsGetter() + offset) == Offsets::GetVT_FloatPlayerVariable();
|
||||
const bool isBoolPlayerVar = *(playerVarsGetter() + offset) == Offsets::GetVT_BoolPlayerVariable();
|
||||
const bool isFloatPlayerVar = Utils::RTTI::IsClassVTableNameEqualTo(*(playerVarsGetter() + offset), "FloatPlayerVariable");
|
||||
const bool isBoolPlayerVar = Utils::RTTI::IsClassVTableNameEqualTo(*(playerVarsGetter() + offset), "BoolPlayerVariable");
|
||||
|
||||
if (isFloatPlayerVar || isBoolPlayerVar) {
|
||||
var.second.first = playerVarsGetter() + offset + VAR_LOC_OFFSET;
|
||||
@ -71,8 +71,6 @@ namespace EGSDK::GamePH {
|
||||
return;
|
||||
if (!Get())
|
||||
return;
|
||||
if (!Offsets::GetVT_FloatPlayerVariable() || !Offsets::GetVT_BoolPlayerVariable())
|
||||
return;
|
||||
|
||||
for (auto& var : playerVars)
|
||||
processPlayerVar(reinterpret_cast<DWORD64**(*)()>(&Get), var);
|
||||
@ -83,11 +81,11 @@ namespace EGSDK::GamePH {
|
||||
#pragma region Player Variables Sorting
|
||||
struct VarTypeFieldMeta {
|
||||
PlayerVariables::PlayerVarType type;
|
||||
void*(*getFieldMetaVT)();
|
||||
std::string_view className;
|
||||
};
|
||||
const std::vector<VarTypeFieldMeta> varTypeFields = {
|
||||
{ PlayerVariables::PlayerVarType::Float, Offsets::GetVT_TypedFieldMetaFloatPlayerVariable },
|
||||
{ PlayerVariables::PlayerVarType::Bool, Offsets::GetVT_TypedFieldMetaBoolPlayerVariable }
|
||||
{ PlayerVariables::PlayerVarType::Float, "constds::FieldsCollection<PlayerVariables>::TypedFieldMeta<FloatPlayerVariable>" },
|
||||
{ PlayerVariables::PlayerVarType::Bool, "constds::FieldsCollection<PlayerVariables>::TypedFieldMeta<BoolPlayerVariable>" }
|
||||
};
|
||||
|
||||
bool isRetInstruction(BYTE* address) {
|
||||
@ -117,7 +115,7 @@ namespace EGSDK::GamePH {
|
||||
continue;
|
||||
}
|
||||
|
||||
playerVarName = reinterpret_cast<const char*>(Utils::Memory::CalcTargetAddrOfRelInst(reinterpret_cast<DWORD64>(funcAddress), 3));
|
||||
playerVarName = reinterpret_cast<const char*>(Utils::Memory::CalcTargetAddrOfRelativeInstr(reinterpret_cast<DWORD64>(funcAddress), 3));
|
||||
if (!playerVarName) {
|
||||
funcAddress++;
|
||||
continue;
|
||||
@ -139,9 +137,8 @@ namespace EGSDK::GamePH {
|
||||
continue;
|
||||
}
|
||||
|
||||
DWORD64 startOfLoadVarFunc = Utils::Memory::CalcTargetAddrOfRelInst(reinterpret_cast<DWORD64>(funcAddress), 1);
|
||||
DWORD64 startOfLoadVarFunc = Utils::Memory::CalcTargetAddrOfRelativeInstr(reinterpret_cast<DWORD64>(funcAddress), 1);
|
||||
for (const auto& varType : varTypeFields) {
|
||||
DWORD64 metaVTAddr = reinterpret_cast<DWORD64>(varType.getFieldMetaVT());
|
||||
BYTE* loadVarFuncAddress = reinterpret_cast<BYTE*>(startOfLoadVarFunc);
|
||||
DWORD64 metaVTAddrFromFunc = 0;
|
||||
|
||||
@ -152,15 +149,15 @@ namespace EGSDK::GamePH {
|
||||
continue;
|
||||
}
|
||||
|
||||
metaVTAddrFromFunc = Utils::Memory::CalcTargetAddrOfRelInst(reinterpret_cast<DWORD64>(loadVarFuncAddress), 3);
|
||||
if (metaVTAddrFromFunc != metaVTAddr) {
|
||||
metaVTAddrFromFunc = Utils::Memory::CalcTargetAddrOfRelativeInstr(reinterpret_cast<DWORD64>(loadVarFuncAddress), 3);
|
||||
if (!Utils::RTTI::IsVTableNameEqualTo(reinterpret_cast<DWORD64*>(metaVTAddrFromFunc), varType.className)) {
|
||||
metaVTAddrFromFunc = 0;
|
||||
loadVarFuncAddress++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (metaVTAddr == metaVTAddrFromFunc) {
|
||||
if (Utils::RTTI::IsVTableNameEqualTo(reinterpret_cast<DWORD64*>(metaVTAddrFromFunc), varType.className)) {
|
||||
playerVarType = varType.type;
|
||||
break;
|
||||
}
|
||||
@ -219,6 +216,6 @@ namespace EGSDK::GamePH {
|
||||
return pPlayerState ? pPlayerState->pPlayerVariables : nullptr;
|
||||
}
|
||||
PlayerVariables* PlayerVariables::Get() {
|
||||
return _SafeGetter<PlayerVariables>(GetOffset_PlayerVariables, "gamedll_ph_x64_rwdi.dll", false, nullptr);
|
||||
return ClassHelpers::SafeGetter<PlayerVariables>(GetOffset_PlayerVariables, false);
|
||||
}
|
||||
}
|
@ -9,6 +9,6 @@ namespace EGSDK::GamePH {
|
||||
return pGameDI_PH ? pGameDI_PH->pSessionCooperativeDI : nullptr;
|
||||
}
|
||||
SessionCooperativeDI* SessionCooperativeDI::Get() {
|
||||
return _SafeGetter<SessionCooperativeDI>(GetOffset_SessionCooperativeDI, "gamedll_ph_x64_rwdi.dll", false, Offsets::GetVT_SessionCooperativeDI);
|
||||
return ClassHelpers::SafeGetter<SessionCooperativeDI>(GetOffset_SessionCooperativeDI, false);
|
||||
}
|
||||
}
|
@ -17,6 +17,6 @@ namespace EGSDK::GamePH {
|
||||
return pCoBaseCameraProxy->pTPPCameraDI;
|
||||
}
|
||||
TPPCameraDI* TPPCameraDI::Get() {
|
||||
return _SafeGetter<TPPCameraDI>(GetOffset_TPPCameraDI, "gamedll_ph_x64_rwdi.dll", false, Offsets::GetVT_TPPCameraDI);
|
||||
return ClassHelpers::SafeGetter<TPPCameraDI>(GetOffset_TPPCameraDI, false);
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ namespace EGSDK::GamePH {
|
||||
return pLevelDI ? pLevelDI->GetTimeWeatherSystem() : nullptr;
|
||||
}
|
||||
CSystem* CSystem::Get() {
|
||||
return _SafeGetter<CSystem>(GetOffset_CSystem, nullptr, false, nullptr);
|
||||
return ClassHelpers::SafeGetter<CSystem>(GetOffset_CSystem, false);
|
||||
}
|
||||
}
|
||||
}
|
@ -50,14 +50,6 @@ namespace EGSDK::Utils {
|
||||
return GetProcAddress(moduleHandle, funcName.data());
|
||||
}
|
||||
|
||||
const bool IsAddressValidMod(const DWORD64 ptr, const char* moduleName) {
|
||||
const MODULEINFO moduleInf = GetModuleInfo(moduleName);
|
||||
|
||||
const DWORD64 moduleEntryPoint = reinterpret_cast<DWORD64>(moduleInf.EntryPoint);
|
||||
const DWORD64 moduleEndPoint = moduleEntryPoint + moduleInf.SizeOfImage;
|
||||
return ptr && (ptr <= moduleEndPoint && ptr >= moduleEntryPoint);
|
||||
}
|
||||
|
||||
std::string BytesToIDAPattern(BYTE* bytes, size_t size) {
|
||||
std::stringstream idaPattern;
|
||||
idaPattern << std::hex << std::uppercase << std::setfill('0');
|
||||
@ -103,7 +95,7 @@ namespace EGSDK::Utils {
|
||||
|
||||
return patt;
|
||||
}
|
||||
DWORD64 CalcTargetAddrOfRelInst(DWORD64 addrOfInst, size_t opSize) {
|
||||
DWORD64 CalcTargetAddrOfRelativeInstr(DWORD64 addrOfInst, size_t opSize) {
|
||||
int offset = *reinterpret_cast<int*>(addrOfInst + opSize);
|
||||
|
||||
return addrOfInst + opSize + 4 + offset;
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <Windows.h>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <unordered_map>
|
||||
#include <DbgHelp.h>
|
||||
#include <memscan\memscan.h>
|
||||
#include <EGSDK\Utils\RTTI.h>
|
||||
#include <EGSDK\Utils\Sigscan.h>
|
||||
@ -10,129 +12,65 @@
|
||||
|
||||
namespace EGSDK::Utils {
|
||||
namespace RTTI {
|
||||
static std::vector<DWORD64> getXrefsTo(DWORD64 moduleBaseAddr, DWORD64 address, DWORD64 start, size_t size) {
|
||||
std::vector<DWORD64> xrefs = {};
|
||||
static std::unordered_map<DWORD64, std::string> vtableAddressCache{};
|
||||
|
||||
const DWORD64 finalOffset = address - moduleBaseAddr;
|
||||
const std::string idaPattern = Memory::BytesToIDAPattern(reinterpret_cast<BYTE*>(const_cast<DWORD64*>(&finalOffset)), 4);
|
||||
std::string patt = Memory::ConvertSigToScannerSig(idaPattern.c_str());
|
||||
static std::string _GetVTableNameFromVTPtr(void* vtPtr) {
|
||||
if (Utils::Memory::IsBadReadPtr(vtPtr))
|
||||
return "bad_read_vtable";
|
||||
DWORD64 vtableStructAddr = reinterpret_cast<DWORD64>(vtPtr);
|
||||
if (auto it = vtableAddressCache.find(vtableStructAddr); it != vtableAddressCache.end())
|
||||
return it->second;
|
||||
|
||||
// Get the end of the section (in our case the end of the .rdata section)
|
||||
const DWORD64 end = start + size;
|
||||
DWORD64 objectLocatorAddr = *reinterpret_cast<DWORD64*>(vtableStructAddr - sizeof(DWORD64));
|
||||
|
||||
while (start && start < end) {
|
||||
const auto scanner = memscan::mapped_region_t(start, end);
|
||||
auto patternFind = scanner.find_pattern<ms_uptr_t>(patt);
|
||||
DWORD64 baseOffset = *reinterpret_cast<DWORD64*>(objectLocatorAddr + 0x14);
|
||||
DWORD64 baseAddr = objectLocatorAddr - baseOffset;
|
||||
|
||||
// If the xref is 0 it means that there either were no xrefs, or there are no remaining xrefs.
|
||||
// So we should break out of our loop, otherwise it will keep on trying to look for xrefs.
|
||||
if (!patternFind.has_value())
|
||||
break;
|
||||
DWORD classHierarchyDescriptorOffset = *reinterpret_cast<DWORD*>(objectLocatorAddr + 0x10);
|
||||
DWORD64 classHierarchyDescriptorAddr = baseAddr + classHierarchyDescriptorOffset;
|
||||
|
||||
// We've found an xref, save it in the vector, and add 8 to start, so it wil now search for xrefs
|
||||
// from the previously found xref untill we're at the end of the section, or there aren't any xrefs left.
|
||||
xrefs.push_back(patternFind.value());
|
||||
start = patternFind.value() + 8;
|
||||
}
|
||||
int baseClassCount = *reinterpret_cast<int*>(classHierarchyDescriptorAddr + 0x8);
|
||||
if (baseClassCount == 0 || baseClassCount > 24)
|
||||
return {};
|
||||
|
||||
return xrefs;
|
||||
DWORD baseClassArrayOffset = *reinterpret_cast<DWORD*>(classHierarchyDescriptorAddr + 0xC);
|
||||
DWORD64 baseClassArrayAddr = baseAddr + baseClassArrayOffset;
|
||||
|
||||
DWORD baseClassDescriptorOffset = *reinterpret_cast<DWORD*>(baseClassArrayAddr);
|
||||
DWORD64 baseClassDescriptorAddr = baseAddr + baseClassDescriptorOffset;
|
||||
|
||||
DWORD typeDescriptorOffset = *reinterpret_cast<DWORD*>(baseClassDescriptorAddr);
|
||||
DWORD64 typeDescriptorAddr = baseAddr + typeDescriptorOffset;
|
||||
|
||||
std::string decoratedClassName = "?" + std::string(reinterpret_cast<const char*>(typeDescriptorAddr + 0x14));
|
||||
char outUndecoratedClassName[255]{};
|
||||
UnDecorateSymbolName(decoratedClassName.c_str(), outUndecoratedClassName, sizeof(outUndecoratedClassName), UNDNAME_NAME_ONLY);
|
||||
|
||||
vtableAddressCache[vtableStructAddr] = outUndecoratedClassName;
|
||||
|
||||
return outUndecoratedClassName;
|
||||
}
|
||||
static bool getSectionInfo(DWORD64 baseAddress, const char* sectionName, DWORD64& sectionStart, DWORD64& sectionSize) {
|
||||
const PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(baseAddress);
|
||||
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return false;
|
||||
|
||||
const PIMAGE_NT_HEADERS32 ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS32>(baseAddress + dosHeader->e_lfanew);
|
||||
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
|
||||
return false;
|
||||
|
||||
PIMAGE_SECTION_HEADER sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);
|
||||
USHORT numOfSections = ntHeaders->FileHeader.NumberOfSections;
|
||||
while (numOfSections > 0) {
|
||||
// If we're at the right section
|
||||
if (!strcmp(sectionName, (const char*)sectionHeader->Name)) {
|
||||
sectionStart = baseAddress + sectionHeader->VirtualAddress;
|
||||
sectionSize = sectionHeader->SizeOfRawData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
sectionHeader++;
|
||||
numOfSections--;
|
||||
}
|
||||
|
||||
return false;
|
||||
static std::string _GetVTableName(void* classPtr) {
|
||||
if (Utils::Memory::IsBadReadPtr(classPtr))
|
||||
return "bad_read_class";
|
||||
return _GetVTableNameFromVTPtr(*reinterpret_cast<DWORD64**>(classPtr));
|
||||
}
|
||||
|
||||
DWORD64 GetVTablePtr(const char* moduleName, const char* tableName) {
|
||||
if (!moduleName || !tableName)
|
||||
return 0;
|
||||
std::string GetVTableNameFromVTPtr(void* vtPtr) {
|
||||
std::string result = _GetVTableNameFromVTPtr(vtPtr);
|
||||
if (result.empty())
|
||||
vtableAddressCache.try_emplace(*reinterpret_cast<DWORD64*>(vtPtr), "");
|
||||
|
||||
DWORD64 baseAddress = reinterpret_cast<DWORD64>(GetModuleHandleA(moduleName));
|
||||
if (!baseAddress)
|
||||
return 0;
|
||||
|
||||
// Type descriptor names look like this: .?AVFloatPlayerVariable@@ (so: ".?AV" + table_name + "@@")
|
||||
const std::string typeDescriptorName = ".?AV" + std::string(tableName) + "@@";
|
||||
|
||||
// Convert the string to an IDA pattern so that we can pattern scan it
|
||||
std::string idaPattern = Memory::BytesToIDAPattern(reinterpret_cast<BYTE*>(const_cast<char*>(typeDescriptorName.data())), typeDescriptorName.size());
|
||||
|
||||
DWORD64 rttiTypeDescriptor = reinterpret_cast<DWORD64>(Utils::SigScan::PatternScanner::FindPattern(moduleName, { idaPattern.c_str(), Utils::SigScan::PatternType::Address }));
|
||||
if (!rttiTypeDescriptor)
|
||||
return 0;
|
||||
|
||||
// We're doing - 0x10 here, because the location of the rtti_type_descriptor is 0x10 bytes before the string (open up gamedll_ph_x64_rwdi.dll in IDA and take a look)
|
||||
rttiTypeDescriptor -= 0x10;
|
||||
|
||||
// We only need to get xrefs that are inside the .rdata section (there sometimes are xrefs in .text, so we have to filter them out)
|
||||
DWORD64 rdataStart = 0;
|
||||
DWORD64 rdataSize = 0;
|
||||
if (!getSectionInfo(baseAddress, ".rdata", rdataStart, rdataSize))
|
||||
return 0;
|
||||
|
||||
// Get all xrefs to the type_descriptor
|
||||
const std::vector<DWORD64> xrefs = getXrefsTo(baseAddress, rttiTypeDescriptor, rdataStart, rdataSize);
|
||||
for (const DWORD64 xref : xrefs) {
|
||||
// xref - 0x8 = offset of this vtable in complete class (from top)
|
||||
// So if it's 0 it means it's the class we need, and not some class it inherits from (again, opening up gamedll_ph_x64_rwdi.dll in IDA will help you understand)
|
||||
const int offsetFromClass = *reinterpret_cast<int*>(xref - 0x8);
|
||||
if (offsetFromClass != 0)
|
||||
continue;
|
||||
|
||||
// We've found the correct xref, the object locator is 0xC bytes before the xref. (Again, gamedll_ph_x64_rwdi.dll yada yada yada)
|
||||
const DWORD64 objectLocator = xref - 0xC;
|
||||
|
||||
// Now we need to get an xref to the object locator, as that's where the vtable is located
|
||||
{
|
||||
// Convert the object locator address to an IDA pattern
|
||||
idaPattern = Memory::BytesToIDAPattern(reinterpret_cast<BYTE*>(const_cast<DWORD64*>(&objectLocator)), 8);
|
||||
|
||||
const DWORD64 vtableAddr = reinterpret_cast<DWORD64>(Utils::SigScan::PatternScanner::FindPattern(reinterpret_cast<void*>(rdataStart), rdataSize, { idaPattern.c_str(), Utils::SigScan::PatternType::Address })) + 0x8;
|
||||
|
||||
// Here I'm checking for <= 8 as we're adding 0x8 to it. So if the pattern scan returns 0 we still head the fuck out
|
||||
if (vtableAddr <= 8)
|
||||
continue;
|
||||
|
||||
return vtableAddr;
|
||||
|
||||
// We've now found the vtable address, however, we probably want a pointer to the vtable (which is in .text).
|
||||
// To do this, we're going to find a reference to the vtable address, and use that as pointer.
|
||||
|
||||
// If you don't need a pointer to the vtable in your implementation however, just return vtable_address
|
||||
/*DWORD64 textStart = 0;
|
||||
DWORD64 textSize = 0;
|
||||
if (!getSectionInfo(baseAddress, ".text", textStart, textSize))
|
||||
return nullptr;
|
||||
|
||||
// Convert the vtable address to an IDA pattern
|
||||
idaPattern = bytesToIDAPattern(reinterpret_cast<BYTE*>(const_cast<DWORD64*>(&vtableAddr)), 8);
|
||||
return reinterpret_cast<DWORD64*>(Utils::SigScan::PatternScanner::FindPattern(reinterpret_cast<void*>(textStart), textSize, { idaPattern.c_str(), Utils::SigScan::PatternType::Address })) + 0x8;*/
|
||||
}
|
||||
}
|
||||
|
||||
// We for some odd reason didn't find any valid xrefs
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
std::string GetVTableName(void* classPtr) {
|
||||
std::string result = _GetVTableName(classPtr);
|
||||
if (result.empty())
|
||||
vtableAddressCache.try_emplace(*reinterpret_cast<DWORD64*>(classPtr), "");
|
||||
|
||||
return result;
|
||||
}
|
||||
bool IsClassVTableNameEqualTo(void* classPtr, std::string_view tableName) { return GetVTableName(classPtr) == tableName; }
|
||||
bool IsVTableNameEqualTo(void* vtPtr, std::string_view tableName) { return GetVTableNameFromVTPtr(vtPtr) == tableName; }
|
||||
}
|
||||
}
|
@ -30,5 +30,20 @@ namespace EGSDK::Utils {
|
||||
str.replace(start_pos, from.length(), to);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string GetSimpleTypeName(std::string fullName) {
|
||||
if (fullName.compare(0, 6, "class ") == 0)
|
||||
fullName.erase(0, 6);
|
||||
else if (fullName.compare(0, 7, "struct ") == 0)
|
||||
fullName.erase(0, 7);
|
||||
else if (fullName.compare(0, 5, "enum ") == 0)
|
||||
fullName.erase(0, 5);
|
||||
|
||||
size_t pos = fullName.find_last_of("::");
|
||||
if (pos != std::string::npos)
|
||||
fullName.erase(0, pos + 1);
|
||||
|
||||
return fullName;
|
||||
}
|
||||
}
|
||||
}
|
@ -5,8 +5,7 @@
|
||||
|
||||
namespace EGT::ImGui_impl {
|
||||
namespace Win32 {
|
||||
extern void EnableMouseHook();
|
||||
extern void DisableMouseHook();
|
||||
extern void ToggleMouseHook(bool value);
|
||||
|
||||
extern void Init(HWND hwnd);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
namespace EGT::Menu {
|
||||
namespace Debug {
|
||||
extern bool disableLowLevelMouseHook;
|
||||
extern bool disableVftableScanning;
|
||||
|
||||
class Tab : MenuTab {
|
||||
public:
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <EGT\Menu\Teleport.h>
|
||||
#include <EGT\Menu\Weapon.h>
|
||||
#include <EGT\Menu\World.h>
|
||||
#include <EGT\Menu\Debug.h>
|
||||
#include <EGT\Config\Config.h>
|
||||
|
||||
namespace EGT::Config {
|
||||
@ -258,7 +259,13 @@ namespace EGT::Config {
|
||||
{ "Misc:GameChecks", "DisableDataPAKsCRCCheck", true, &Menu::Misc::disableDataPAKsCRCCheck, OPTION },
|
||||
{ "Misc:GameChecks", "IncreaseDataPAKsLimit", true, &Menu::Misc::increaseDataPAKsLimit, OPTION },
|
||||
{ "World:Time", "SlowMotionSpeed", 0.4f, &Menu::World::slowMotionSpeed, Float },
|
||||
{ "World:Time", "SlowMotionTransitionTime", 1.0f, &Menu::World::slowMotionTransitionTime, Float }
|
||||
{ "World:Time", "SlowMotionTransitionTime", 1.0f, &Menu::World::slowMotionTransitionTime, Float },
|
||||
#ifdef _DEBUG
|
||||
{ "Debug:Misc", "DisableLowLevelMouseHook", true, &Menu::Debug::disableLowLevelMouseHook, OPTION },
|
||||
#else
|
||||
{ "Debug:Misc", "DisableLowLevelMouseHook", false, &Menu::Debug::disableLowLevelMouseHook, OPTION },
|
||||
#endif
|
||||
{ "Debug:Misc", "DisableVftableScanning", false, &Menu::Debug::disableVftableScanning, OPTION },
|
||||
});
|
||||
std::vector<ConfigEntry> configVariables(configVariablesDefault.begin(), configVariablesDefault.end());
|
||||
static constexpr const char* configFileName = "EGameTools.ini";
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <EGT\Engine\Engine_Hooks.h>
|
||||
#include <EGT\Menu\Menu.h>
|
||||
#include <EGT\Menu\Misc.h>
|
||||
#include <EGT\Menu\Debug.h>
|
||||
#include <DbgHelp.h>
|
||||
#include <thread>
|
||||
#include <semaphore>
|
||||
@ -292,6 +293,9 @@ namespace EGT::Core {
|
||||
Config::InitConfig();
|
||||
threads.emplace_back(Config::ConfigLoop);
|
||||
|
||||
SPDLOG_WARN("Setting vftable scanning to: {}", Menu::Debug::disableVftableScanning);
|
||||
EGSDK::ClassHelpers::SetIsVftableScanningDisabled(Menu::Debug::disableVftableScanning);
|
||||
|
||||
SPDLOG_WARN("Creating symlink for loading files");
|
||||
CreateSymlinkForLoadingFiles();
|
||||
|
||||
|
@ -130,8 +130,8 @@ namespace EGT::Engine {
|
||||
struct mount_path {
|
||||
union {
|
||||
const char* gamePath;
|
||||
EGSDK::buffer<0x8, const char*> pakPath;
|
||||
EGSDK::buffer<0x10, const char*> fullPakPath;
|
||||
EGSDK::ClassHelpers::buffer<0x8, const char*> pakPath;
|
||||
EGSDK::ClassHelpers::buffer<0x10, const char*> fullPakPath;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -118,7 +118,7 @@ namespace EGT::ImGui_impl {
|
||||
}
|
||||
}
|
||||
|
||||
void EnableMouseHook() {
|
||||
static void EnableMouseHook() {
|
||||
if (oMouseProc)
|
||||
return;
|
||||
|
||||
@ -135,13 +135,14 @@ namespace EGT::ImGui_impl {
|
||||
MouseHkMsgLoop();
|
||||
}).detach();
|
||||
}
|
||||
void DisableMouseHook() {
|
||||
static void DisableMouseHook() {
|
||||
if (!oMouseProc)
|
||||
return;
|
||||
|
||||
UnhookWindowsHookEx(oMouseProc);
|
||||
oMouseProc = nullptr;
|
||||
}
|
||||
void ToggleMouseHook(bool value) { value ? EnableMouseHook() : DisableMouseHook(); }
|
||||
|
||||
void Init(HWND hwnd) {
|
||||
gHwnd = hwnd;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <ImGui\imguiex.h>
|
||||
#include <EGSDK\ClassHelpers.h>
|
||||
#include <EGT\ImGui_impl\Win32_impl.h>
|
||||
#include <EGT\Menu\Debug.h>
|
||||
|
||||
@ -66,6 +67,7 @@ namespace EGT::Menu {
|
||||
#else
|
||||
bool disableLowLevelMouseHook = false;
|
||||
#endif
|
||||
bool disableVftableScanning = false;
|
||||
|
||||
static void RenderClassAddrPair(const std::pair<std::string_view, void*(*)()>* pair) {
|
||||
const float maxInputTextWidth = ImGui::CalcTextSize("0x0000000000000000").x;
|
||||
@ -97,8 +99,10 @@ namespace EGT::Menu {
|
||||
void Tab::Update() {}
|
||||
void Tab::Render() {
|
||||
ImGui::SeparatorText("Misc##Debug");
|
||||
if (ImGui::Checkbox("Disable Low Level Mouse Hook", &disableLowLevelMouseHook, "Disables the low level mouse hook that is used to capture mouse input in the game"))
|
||||
disableLowLevelMouseHook ? ImGui_impl::Win32::DisableMouseHook() : ImGui_impl::Win32::EnableMouseHook();
|
||||
if (ImGui::Checkbox("Disable Low Level Mouse Hook", &disableLowLevelMouseHook, "Disables the low level mouse hook that is used to capture mouse input in the game; this option is used for debugging purposes"))
|
||||
ImGui_impl::Win32::ToggleMouseHook(disableLowLevelMouseHook);
|
||||
if (ImGui::Checkbox("Disable Vftable Scanning", &disableVftableScanning, "Disables the vftable scanning for classes that are used in the game and used to validate a class in memory; this option is used for debugging purposes"))
|
||||
EGSDK::ClassHelpers::SetIsVftableScanningDisabled(disableVftableScanning);
|
||||
ImGui::SeparatorText("Class addresses##Debug");
|
||||
if (ImGui::CollapsingHeader("GamePH", ImGuiTreeNodeFlags_None)) {
|
||||
ImGui::Indent();
|
||||
|
Reference in New Issue
Block a user