Initial commit: DayZ memory C++ port with DMA backend and overlay
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
#include "Resolvers/LocalPlayerResolver.h"
|
||||
|
||||
#include "Offsets.h"
|
||||
#include "Memory/MemoryValidation.h"
|
||||
|
||||
bool LocalPlayerResolver::TryResolve(VmmAccessor& mem,
|
||||
const RuntimeSession& session,
|
||||
LocalPlayerData& player)
|
||||
{
|
||||
const uint32_t pid = session.processId;
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 1. Read the local player pointer from the world object
|
||||
// -----------------------------------------------------------------
|
||||
uint64_t localPlayerPointer = 0;
|
||||
if (!mem.TryReadPointer(pid,
|
||||
session.worldAddress + Offsets::World::LocalPlayer,
|
||||
localPlayerPointer))
|
||||
{
|
||||
m_lastFailureReason = "Failed to read LocalPlayer pointer from world";
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 2. Second hop — the actual entity sits 0xA8 bytes before the
|
||||
// pointed-to structure.
|
||||
// -----------------------------------------------------------------
|
||||
uint64_t secondHop = 0;
|
||||
if (!mem.TryReadValue<uint64_t>(pid, localPlayerPointer + 0x8, secondHop)) {
|
||||
m_lastFailureReason = "Failed to read secondHop from LocalPlayer";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (secondHop <= 0xA8) {
|
||||
m_lastFailureReason = "secondHop value too small";
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t chainedEntity = secondHop - 0xA8;
|
||||
|
||||
if (!MemoryValidation::IsValidUserAddress(chainedEntity)) {
|
||||
m_lastFailureReason = "chainedEntity address is not a valid user address";
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 3. VisualState pointer
|
||||
// -----------------------------------------------------------------
|
||||
uint64_t visualStateAddr = 0;
|
||||
if (!mem.TryReadPointer(pid,
|
||||
chainedEntity + Offsets::Common::VisualState,
|
||||
visualStateAddr))
|
||||
{
|
||||
m_lastFailureReason = "Failed to read VisualState pointer";
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 4. Position
|
||||
// -----------------------------------------------------------------
|
||||
Vector3 pos{};
|
||||
if (!mem.TryReadValue<Vector3>(pid,
|
||||
visualStateAddr + Offsets::Common::Position,
|
||||
pos))
|
||||
{
|
||||
m_lastFailureReason = "Failed to read position from VisualState";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MemoryValidation::IsValidVector(pos)) {
|
||||
m_lastFailureReason = "Position vector is not valid";
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 5. Heading from direction vector
|
||||
// -----------------------------------------------------------------
|
||||
float dirX = 0.0f;
|
||||
float dirY = 0.0f;
|
||||
mem.TryReadValue<float>(pid, visualStateAddr + Offsets::Common::DirectionX, dirX);
|
||||
mem.TryReadValue<float>(pid, visualStateAddr + Offsets::Common::DirectionY, dirY);
|
||||
|
||||
float heading = 0.0f;
|
||||
MemoryValidation::TryGetCorrectedHeadingFromDirection(dirX, dirY, heading);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 6. Commit
|
||||
// -----------------------------------------------------------------
|
||||
player = LocalPlayerData{
|
||||
.entityAddress = chainedEntity,
|
||||
.visualStateAddress = visualStateAddr,
|
||||
.position = pos,
|
||||
.lookDirection = heading,
|
||||
};
|
||||
|
||||
m_lastFailureReason.clear();
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user