fix: update offsets from dump
This commit is contained in:
parent
4dca333267
commit
52454e23ea
|
|
@ -365,8 +365,8 @@ void CFramework::ScanRotationOffset()
|
|||
s_cands.clear();
|
||||
m_scanResult[0] = 0;
|
||||
|
||||
// Player 構造 [0x100, 0x700] 内の 8byte アライン済みポインタ
|
||||
for (uintptr_t mcOff = 0x100; mcOff <= 0x700; mcOff += 0x8)
|
||||
// Player 构造 [0x20, 0x700] 内的 8byte アライン済みポインタ
|
||||
for (uintptr_t mcOff = 0x20; mcOff <= 0x700; mcOff += 0x8)
|
||||
{
|
||||
uintptr_t ptr = m.Read<uintptr_t>(local.m_address + mcOff);
|
||||
if (!ptr)
|
||||
|
|
@ -392,7 +392,7 @@ void CFramework::ScanRotationOffset()
|
|||
|
||||
if (s_cands.empty())
|
||||
{
|
||||
strcpy_s(m_scanResult, "未找到候选,请扩大扫描范围 (0x100-0x700)");
|
||||
strcpy_s(m_scanResult, "未找到候选,请扩大扫描范围 (0x20-0x700)");
|
||||
m_scanPhase = 0;
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,9 @@ private:
|
|||
}
|
||||
void HealthBar(float x, float y, float w, float h, int value, int v_max)
|
||||
{
|
||||
if (v_max <= 0)
|
||||
return;
|
||||
|
||||
RectFilled(x, y, x + w, y + h, ImColor(0.f, 0.f, 0.f, 0.725f), 0.f, 0);
|
||||
RectFilled(x, y, x + w, y + ((h / float(v_max)) * (float)value), ImColor(min(510 * (v_max - value) / 100, 255), min(510 * value / 100, 255), 25, 255), 0.0f, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,11 +234,11 @@ void CFramework::RenderMenu()
|
|||
ImGui::InputInt("MC", &g.g_AimMcOffset, 8, 8, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::InputInt("旋转", &g.g_AimRotOffset, 4, 4, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
|
||||
// 误改输入框会直接导致 Memory 模式失效, 一键恢复本客户端实测默认值
|
||||
if (ImGui::Button("重置偏移 (0x1E0/0x3AC)", ImVec2(ImGui::GetContentRegionAvail().x, 0.f)))
|
||||
// dump.txt: MovementContext = Player +0x58, Rotation_1 = MovementContext +0x27C
|
||||
if (ImGui::Button("重置偏移 (0x58/0x27C)", ImVec2(ImGui::GetContentRegionAvail().x, 0.f)))
|
||||
{
|
||||
g.g_AimMcOffset = 0x1E0;
|
||||
g.g_AimRotOffset = 0x3AC;
|
||||
g.g_AimMcOffset = 0x58;
|
||||
g.g_AimRotOffset = 0x27C;
|
||||
}
|
||||
|
||||
if (ImGui::Button("扫描旋转偏移(两步)", ImVec2(ImGui::GetContentRegionAvail().x, 0.f)))
|
||||
|
|
|
|||
|
|
@ -4,83 +4,130 @@ std::vector<int> PlayerBoneList{ BONE_PELVIS, BONE_LEFT_THIGH, BONE_LEFT_FOOT, B
|
|||
|
||||
bool CPlayer::Update()
|
||||
{
|
||||
// Position
|
||||
m_vecOrigin = GetBonePosition(BONE_ORIGIN);
|
||||
|
||||
if (Vec3_Empty(m_vecOrigin))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return !Vec3_Empty(m_vecOrigin);
|
||||
}
|
||||
|
||||
void CPlayer::UpdateStatic()
|
||||
{
|
||||
// Health
|
||||
uintptr_t m_pHealthController = m.Read<uintptr_t>(m_address + offset::Player::pHealthController); // HealthController
|
||||
uintptr_t m_pHealthBody = m.Read<uintptr_t>(m_pHealthController + 0x68);
|
||||
m_pBodyController = m.Read<uintptr_t>(m_pHealthBody + 0x18);
|
||||
m_pHealthController = 0;
|
||||
m_pProfile = 0;
|
||||
m_pInfo = 0;
|
||||
m_pSetting = 0;
|
||||
m_pWeaponAnimation = 0;
|
||||
m_iSpawnType = 0;
|
||||
m_pBoneArray = {};
|
||||
m_vecBoneList.clear();
|
||||
|
||||
// Bone
|
||||
uintptr_t boneMatrix = m.ReadChain(m_address, { offset::Player::pPlayerBody, 0x30, 0x30, 0x10 });
|
||||
m_pBoneArray = m.Read<CBoneArray>(boneMatrix + 0x20);
|
||||
if (!m_address)
|
||||
return;
|
||||
|
||||
// EFT.Player fields from dump.txt.
|
||||
m_pHealthController = m.Read<uintptr_t>(m_address + offset::Player::pHealthController);
|
||||
m_pWeaponAnimation = m.Read<uintptr_t>(m_address + offset::Player::pWeaponAnimation);
|
||||
|
||||
// Other pointer
|
||||
m_pProfile = m.Read<uintptr_t>(m_address + offset::Player::pProfile);
|
||||
m_pInfo = m.Read<uintptr_t>(m_pProfile + 0x40);
|
||||
m_pSetting = m.Read<uintptr_t>(m_pInfo + 0x50);
|
||||
if (m_pProfile)
|
||||
{
|
||||
m_pInfo = m.Read<uintptr_t>(m_pProfile + offset::Profile::pInfoClass);
|
||||
if (m_pInfo)
|
||||
{
|
||||
m_pSetting = m.Read<uintptr_t>(m_pInfo + offset::InfoClass::profileInfoSettingsClass);
|
||||
if (m_pSetting)
|
||||
m_iSpawnType = m.Read<int>(m_pSetting + 0x10); // ProfileInfoSettingsClass.Role
|
||||
}
|
||||
}
|
||||
|
||||
m.Read<uintptr_t>(m_address + offset::Player::pWeaponAnimation);
|
||||
|
||||
// Player data
|
||||
m_iSpawnType = m.Read<int>(m_pSetting + 0x10); // SpawnType
|
||||
// PlayerBody +0x30 = SkeletonRootJoint; Skeleton +0x30 = values List;
|
||||
// List +0x10 = Transform[] data pointer, as described by dump.txt.
|
||||
const uintptr_t boneMatrix = m.ReadChain(m_address, { offset::Player::pPlayerBody, 0x30, 0x30, 0x10 });
|
||||
if (boneMatrix)
|
||||
m_pBoneArray = m.Read<CBoneArray>(boneMatrix + 0x20);
|
||||
}
|
||||
|
||||
void CPlayer::UpdateHealth()
|
||||
{
|
||||
float h{ 0 };
|
||||
float max{ 0 };
|
||||
m_fHealth = 0.f;
|
||||
m_fHealthMax = 0.f;
|
||||
|
||||
for (int j = 0; j < 7; j++)
|
||||
if (!m_address)
|
||||
return;
|
||||
|
||||
const uintptr_t healthController = m_pHealthController != 0
|
||||
? m_pHealthController
|
||||
: m.Read<uintptr_t>(m_address + offset::Player::pHealthController);
|
||||
if (!healthController)
|
||||
return;
|
||||
|
||||
// GClass3009<T>.Dictionary_0_1 contains BodyPartState<T> entries.
|
||||
const uintptr_t bodyParts = m.Read<uintptr_t>(healthController + offset::HealthController::BodyParts);
|
||||
if (!bodyParts)
|
||||
return;
|
||||
|
||||
const uintptr_t entries = m.Read<uintptr_t>(bodyParts + offset::HealthController::DictionaryEntries);
|
||||
const int entryCount = m.Read<int>(bodyParts + offset::HealthController::DictionaryCount);
|
||||
if (!entries || entryCount <= 0 || entryCount > 64)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < entryCount; ++i)
|
||||
{
|
||||
uintptr_t body_part = m.Read<uintptr_t>(m_pBodyController + 0x30 + (j * 0x18));
|
||||
uintptr_t health_container = m.Read<uintptr_t>(body_part + 0x10);
|
||||
h += m.Read<float>(health_container + 0x10);
|
||||
max += m.Read<float>(health_container + 0x14);
|
||||
}
|
||||
const uintptr_t entry = entries + offset::HealthController::ArrayData
|
||||
+ static_cast<uintptr_t>(i) * offset::HealthController::EntryStride;
|
||||
const uintptr_t bodyPartState = m.Read<uintptr_t>(entry + offset::HealthController::EntryValue);
|
||||
if (!bodyPartState)
|
||||
continue;
|
||||
|
||||
m_fHealth = h;
|
||||
m_fHealthMax = max;
|
||||
const uintptr_t healthValue = m.Read<uintptr_t>(bodyPartState + offset::HealthController::BodyPartHealth);
|
||||
if (!healthValue)
|
||||
continue;
|
||||
|
||||
m_fHealth += m.Read<float>(healthValue + offset::HealthController::HealthValue + offset::HealthController::Current);
|
||||
m_fHealthMax += m.Read<float>(healthValue + offset::HealthController::HealthValue + offset::HealthController::Maximum);
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayer::UpdateBone()
|
||||
{
|
||||
m_vecHeadOrigin = GetBonePosition(BONE_HEAD);
|
||||
m_vecNeckOrigin = GetBonePosition(BONE_NECK);
|
||||
|
||||
if (g.g_ESP_Skeleton)
|
||||
{
|
||||
for (auto& id : PlayerBoneList)
|
||||
{
|
||||
Vector3 bone = GetBonePosition(id);
|
||||
|
||||
if (Vec3_Empty(bone)) {
|
||||
m_vecBoneList.clear();
|
||||
break;
|
||||
|
||||
if (!g.g_ESP_Skeleton)
|
||||
return;
|
||||
|
||||
m_vecBoneList.reserve(PlayerBoneList.size());
|
||||
for (const auto id : PlayerBoneList)
|
||||
{
|
||||
const Vector3 bone = GetBonePosition(id);
|
||||
if (Vec3_Empty(bone))
|
||||
{
|
||||
m_vecBoneList.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
m_vecBoneList.push_back(bone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CPlayer::IsAiming()
|
||||
{
|
||||
return m.Read<bool>(m_pWeaponAnimation + offset::WeaponAnimations::isAiming);
|
||||
return m_pWeaponAnimation != 0 && m.Read<bool>(m_pWeaponAnimation + offset::WeaponAnimations::isAiming);
|
||||
}
|
||||
|
||||
Vector3 CPlayer::GetBonePosition(const int BoneId)
|
||||
{
|
||||
uintptr_t TransformPtr = m.Read<uintptr_t>(m_pBoneArray.address[BoneId] + 0x10);
|
||||
constexpr int kBoneCount = static_cast<int>(sizeof(m_pBoneArray.address) / sizeof(m_pBoneArray.address[0]));
|
||||
if (BoneId < 0 || BoneId >= kBoneCount)
|
||||
return {};
|
||||
|
||||
return GetTransformPosition(TransformPtr);
|
||||
const uintptr_t bone = m_pBoneArray.address[BoneId];
|
||||
if (!bone)
|
||||
return {};
|
||||
|
||||
uintptr_t transform = m.Read<uintptr_t>(bone + 0x10);
|
||||
if (!transform)
|
||||
return {};
|
||||
|
||||
return GetTransformPosition(transform);
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ public:
|
|||
uintptr_t m_pProfile{ 0 };
|
||||
uintptr_t m_pInfo{ 0 };
|
||||
uintptr_t m_pSetting{ 0 };
|
||||
uintptr_t m_pBodyController{ 0 };
|
||||
uintptr_t m_pHealthController{ 0 };
|
||||
uintptr_t m_pWeaponAnimation{ 0 };
|
||||
|
||||
// データ
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ float GetDistance(Vector3 value1, Vector3 value2)
|
|||
|
||||
Vector3 GetTransformPosition(uintptr_t& transform)
|
||||
{
|
||||
if (!transform)
|
||||
return {};
|
||||
|
||||
__m128 result{};
|
||||
|
||||
const __m128 mulVec0 = { -2.000, 2.000, -2.000, 0.000 };
|
||||
|
|
@ -29,6 +32,9 @@ Vector3 GetTransformPosition(uintptr_t& transform)
|
|||
|
||||
TransformAccessReadOnly pTransformAccessReadOnly = m.Read<TransformAccessReadOnly>(transform + 0x38);
|
||||
unsigned int Index = m.Read<unsigned int>(transform + 0x40);
|
||||
if (!pTransformAccessReadOnly.pTransformData)
|
||||
return {};
|
||||
|
||||
TransformData transform_data = m.Read<TransformData>(pTransformAccessReadOnly.pTransformData + 0x18);
|
||||
|
||||
if (transform_data.pTransformArray && transform_data.pTransformIndices)
|
||||
|
|
@ -96,6 +102,9 @@ bool WorldToScreen(Matrix ViewMatrix, const Vector2& GameSize, Vector3& vIn, Vec
|
|||
|
||||
uintptr_t GetObjectFromList(uintptr_t listPtr, uintptr_t lastObjectPtr, const char* objectName)
|
||||
{
|
||||
if (!listPtr || !objectName)
|
||||
return 0;
|
||||
|
||||
char ObjectName[128]{};
|
||||
uintptr_t classNamePtr = 0;
|
||||
BaseObject activeObject = m.Read<BaseObject>(listPtr);
|
||||
|
|
@ -111,7 +120,8 @@ uintptr_t GetObjectFromList(uintptr_t listPtr, uintptr_t lastObjectPtr, const ch
|
|||
if (strcmp(ObjectName, objectName) == 0)
|
||||
return activeObject.object;
|
||||
|
||||
Sleep(1);
|
||||
if (!activeObject.nextObjectLink)
|
||||
break;
|
||||
|
||||
activeObject = m.Read<BaseObject>(activeObject.nextObjectLink);
|
||||
}
|
||||
|
|
@ -135,13 +145,22 @@ bool CGame::InitAddress()
|
|||
{
|
||||
// GameObjectManager
|
||||
uintptr_t pGOM = m.Read<uintptr_t>(m.m_gBaseAddress + offset::dwGameObjectManager);
|
||||
if (!pGOM)
|
||||
{
|
||||
m_objGameObjectManager = {};
|
||||
return false;
|
||||
}
|
||||
|
||||
m_objGameObjectManager = m.Read<GameObjectManager>(pGOM);
|
||||
|
||||
return m_objGameObjectManager.lastActiveObject != NULL ? true : false;
|
||||
return m_objGameObjectManager.lastActiveObject != 0;
|
||||
}
|
||||
|
||||
bool CGame::Update()
|
||||
{
|
||||
m_pGameWorld = 0;
|
||||
m_pLocalGameWorld = 0;
|
||||
|
||||
// GameWorld
|
||||
uintptr_t activeNodes = m.Read<uintptr_t>(m_objGameObjectManager.ActiveNodes);
|
||||
uintptr_t lastActiveNode = m.Read<uintptr_t>(m_objGameObjectManager.LastActiveNode);
|
||||
|
|
@ -161,21 +180,30 @@ bool CGame::Update()
|
|||
|
||||
bool CGame::UpdateCamera()
|
||||
{
|
||||
Camera all_cameras = m.Read<Camera>(m.Read<uintptr_t>(m.m_gBaseAddress + offset::dwAllCamera));
|
||||
m_pFpsCamera = 0;
|
||||
|
||||
if (all_cameras.count == 0)
|
||||
uintptr_t all_camera_ptr = m.Read<uintptr_t>(m.m_gBaseAddress + offset::dwAllCamera);
|
||||
if (!all_camera_ptr)
|
||||
return false;
|
||||
|
||||
Camera all_cameras = m.Read<Camera>(all_camera_ptr);
|
||||
|
||||
if (all_cameras.list == 0 || all_cameras.count == 0)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < all_cameras.count; i++)
|
||||
{
|
||||
uintptr_t camera = m.Read<uintptr_t>(all_cameras.list + (i * 0x8));
|
||||
if (camera != NULL)
|
||||
if (camera != 0)
|
||||
{
|
||||
uintptr_t camera_obj = m.Read<uintptr_t>(camera + 0x30);
|
||||
if (!camera_obj)
|
||||
continue;
|
||||
|
||||
uintptr_t camera_name_ptr = m.Read<uintptr_t>(camera_obj + 0x60);
|
||||
|
||||
if (!camera_name_ptr)
|
||||
return false;
|
||||
continue;
|
||||
|
||||
char name[64]{};
|
||||
m.ReadString(camera_name_ptr, name, sizeof(name));
|
||||
|
|
@ -197,9 +225,17 @@ bool CGame::IsInRaid()
|
|||
|
||||
Matrix CGame::GetViewMatrix()
|
||||
{
|
||||
if (!m_pFpsCamera)
|
||||
return {};
|
||||
|
||||
// ここ省略できるかチェック
|
||||
uintptr_t dw = m.Read<uintptr_t>(m_pFpsCamera + 0x30);
|
||||
if (!dw)
|
||||
return {};
|
||||
|
||||
uintptr_t viewmatrix_ptr = m.Read<uintptr_t>(dw + 0x18);
|
||||
if (!viewmatrix_ptr)
|
||||
return {};
|
||||
|
||||
return m.Read<Matrix>(viewmatrix_ptr + 0x100);
|
||||
}
|
||||
|
|
@ -1,65 +1,72 @@
|
|||
#pragma once
|
||||
#pragma once
|
||||
|
||||
// by Unispect and UC
|
||||
namespace offset
|
||||
{
|
||||
// Base
|
||||
// Base (not present in dump.txt; keep the native UnityPlayer values used by this build)
|
||||
constexpr auto dwGameObjectManager = 0x1CF93E0;
|
||||
constexpr auto dwAllCamera = 0x1BF8BC0;
|
||||
|
||||
// EFT.GameWorld
|
||||
// EFT.GameWorld / EFT.ClientLocalGameWorld
|
||||
constexpr auto ExfilController = 0x30;
|
||||
constexpr auto LootList = 0x118;
|
||||
constexpr auto RegisteredPlayers = 0x140;
|
||||
constexpr auto MainPlayer = 0x1A8;
|
||||
constexpr auto GrenadeList = 0x200;
|
||||
|
||||
// EFT.Player
|
||||
// EFT.Player (dump.txt: EFT.Player)
|
||||
namespace Player
|
||||
{
|
||||
constexpr auto pPlayerBody = 0xC0;
|
||||
constexpr auto pMovementContext = 0x1E0; // EXFIL DELTA (Mono 0.16.9) 实测. IL2CPP 0.15.x 是 0x170
|
||||
constexpr auto pWeaponAnimation = 0x1E0; // IL2CPP 版定义, Mono 版实际是 MovementContext (框架旧代码保留)
|
||||
constexpr auto pProfile = 0x600;
|
||||
constexpr auto pPhysics = 0x610;
|
||||
constexpr auto pHealthController = 0x640;
|
||||
constexpr auto pPlayerBody = 0xC0; // _playerBody
|
||||
constexpr auto pMovementContext = 0x58; // <MovementContext>k__BackingField
|
||||
constexpr auto pWeaponAnimation = 0x1E0; // <ProceduralWeaponAnimation>k__BackingField
|
||||
constexpr auto pProfile = 0x618; // <Profile>k__BackingField
|
||||
constexpr auto pPhysics = 0x630; // Physical
|
||||
constexpr auto pHealthController = 0x660; // _healthController
|
||||
}
|
||||
|
||||
// EFT.MovementContext
|
||||
// EFT.MovementContext (dump.txt: EFT.MovementContext)
|
||||
namespace MovementContext
|
||||
{
|
||||
// Vector2 (x = yaw, y = pitch) [rad]
|
||||
// EXFIL DELTA (Mono 0.16.9) 实测: +0x3AC = Rotation_1 (视角旋转)
|
||||
// +0x3A4 = MovementDirection_1 (移动方向, 勿用!) 依据 Mono.Cecil 字段表
|
||||
constexpr auto Rotation = 0x3AC;
|
||||
// Vector2 (x = yaw, y = pitch), in radians.
|
||||
constexpr auto Rotation = 0x27C; // Rotation_1
|
||||
}
|
||||
|
||||
// EFT.Profile
|
||||
namespace Profile
|
||||
{
|
||||
constexpr auto Id = 0x10; // str
|
||||
constexpr auto AccountId = 0x18; // str
|
||||
constexpr auto pInfoClass = 0x40; // pointer
|
||||
constexpr auto Id = 0x10;
|
||||
constexpr auto AccountId = 0x18;
|
||||
constexpr auto pInfoClass = 0x40; // Info
|
||||
}
|
||||
|
||||
// EFT.Profile -> InfoClass
|
||||
namespace InfoClass
|
||||
{
|
||||
constexpr auto Nickname = 0x10; // str
|
||||
constexpr auto EntryPoint = 0x18; // str
|
||||
constexpr auto MainProfileNickname = 0x20; // str
|
||||
constexpr auto MGroupId = 0x28; // str
|
||||
constexpr auto TeamId = 0x30; // str
|
||||
constexpr auto profileInfoSettingsClass = 0x50; // pointer
|
||||
constexpr auto eplayerSide_0 = 0x90; // int
|
||||
constexpr auto RegistrationDate = 0x94; // int
|
||||
constexpr auto Type = 0x98; // int
|
||||
constexpr auto Nickname = 0x10;
|
||||
constexpr auto EntryPoint = 0x18;
|
||||
constexpr auto MainProfileNickname = 0x20;
|
||||
constexpr auto MGroupId = 0x28;
|
||||
constexpr auto TeamId = 0x30;
|
||||
constexpr auto profileInfoSettingsClass = 0x48; // ProfileInfoSettingsClass
|
||||
constexpr auto eplayerSide_0 = 0x88;
|
||||
constexpr auto RegistrationDate = 0x8C;
|
||||
constexpr auto Type = 0x90;
|
||||
}
|
||||
|
||||
// EFT.Player->.BasePhysicalClass
|
||||
namespace Physics
|
||||
// EFT.HealthSystem.ActiveHealthController / GClass3009<T>
|
||||
namespace HealthController
|
||||
{
|
||||
|
||||
constexpr auto BodyParts = 0x68; // Dictionary<int, BodyPartState<T>>
|
||||
constexpr auto DictionaryEntries = 0x18;
|
||||
constexpr auto DictionaryCount = 0x40;
|
||||
constexpr auto ArrayData = 0x20;
|
||||
constexpr auto EntryStride = 0x18;
|
||||
constexpr auto EntryValue = 0x10;
|
||||
constexpr auto BodyPartHealth = 0x10; // BodyPartState.Health
|
||||
constexpr auto HealthValue = 0x10; // HealthValue.Value
|
||||
constexpr auto Current = 0x00;
|
||||
constexpr auto Maximum = 0x04;
|
||||
}
|
||||
|
||||
// EFT.Animations.ProceduralWeaponAnimation
|
||||
|
|
@ -74,7 +81,7 @@ namespace offset
|
|||
{
|
||||
constexpr auto Stamina = 0x38;
|
||||
constexpr auto HandsStamina = 0x40;
|
||||
constexpr auto Oxygen = 0x40;
|
||||
constexpr auto Oxygen = 0x48;
|
||||
constexpr auto FallDamageMultiplier = 0xBC;
|
||||
constexpr auto OxygenRestoreRate = 0xD4;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,12 +91,13 @@ void CFramework::UpdateStaticList() // C6262 :(
|
|||
|
||||
std::vector<CItem> list_item{};
|
||||
std::vector<CExfil> list_exfil{};
|
||||
const auto GameWorld = tarkov->m_pLocalGameWorld;
|
||||
tarkov->UpdateCamera();
|
||||
|
||||
// ItemList
|
||||
if (tarkov->Update())
|
||||
{
|
||||
const auto GameWorld = tarkov->m_pLocalGameWorld;
|
||||
|
||||
// Exfil
|
||||
if (g.g_ESP_Exfil)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,13 +53,11 @@ struct Globals
|
|||
float g_RecoilStrength = 4.f; // 每次下拉的鼠标单位(mickeys)
|
||||
int g_RecoilInterval = 15; // 下拉间隔 [ms]
|
||||
|
||||
// Aim Offset (运行时可调, 默认 = 本客户端实测值)
|
||||
// Aim Offset (运行时可调, 由 F:\desktop\Release\dump.txt 校准)
|
||||
// Memory 模式自瞄用: Player + g_AimMcOffset -> + g_AimRotOffset (Vector2 yaw/pitch)
|
||||
// EXFIL DELTA (Mono 0.16.9) 实测: Player+0x1E0 = MovementContext
|
||||
// +0x3A4 = MovementDirection(移动方向, 非视角!), +0x3AC = Rotation_1(视角旋转, 正解)
|
||||
// 依据: Mono.Cecil 字段表 + 运行时验证 (0x3A4 读出的俯仰恒 0)
|
||||
int g_AimMcOffset = 0x1E0;
|
||||
int g_AimRotOffset = 0x3AC;
|
||||
// EFT.Player: MovementContext = +0x58; EFT.MovementContext: Rotation_1 = +0x27C
|
||||
int g_AimMcOffset = 0x58;
|
||||
int g_AimRotOffset = 0x27C;
|
||||
|
||||
// System
|
||||
bool g_StreamProof = false;
|
||||
|
|
|
|||
|
|
@ -58,19 +58,24 @@ uintptr_t Memory::GetModuleBase(const std::string moduleName)
|
|||
entry.dwSize = sizeof(MODULEENTRY32);
|
||||
const auto snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, PID);
|
||||
|
||||
while (Module32Next(snapShot, &entry))
|
||||
if (snapShot == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
if (Module32First(snapShot, &entry))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!moduleName.compare(entry.szModule))
|
||||
{
|
||||
const auto base = reinterpret_cast<uintptr_t>(entry.modBaseAddr);
|
||||
CloseHandle(snapShot);
|
||||
return reinterpret_cast<uintptr_t>(entry.modBaseAddr);
|
||||
return base;
|
||||
}
|
||||
} while (Module32Next(snapShot, &entry));
|
||||
}
|
||||
|
||||
if (snapShot)
|
||||
CloseHandle(snapShot);
|
||||
|
||||
return reinterpret_cast<uintptr_t>(entry.modBaseAddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PROCESSENTRY32 Memory::GetProcess(const std::string processName)
|
||||
|
|
@ -79,17 +84,22 @@ PROCESSENTRY32 Memory::GetProcess(const std::string processName)
|
|||
entry.dwSize = sizeof(PROCESSENTRY32);
|
||||
const auto snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
|
||||
|
||||
while (Process32Next(snapShot, &entry))
|
||||
if (snapShot == INVALID_HANDLE_VALUE)
|
||||
return PROCESSENTRY32();
|
||||
|
||||
if (Process32First(snapShot, &entry))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!processName.compare(entry.szExeFile))
|
||||
{
|
||||
CloseHandle(snapShot);
|
||||
return entry;
|
||||
}
|
||||
} while (Process32Next(snapShot, &entry));
|
||||
}
|
||||
|
||||
CloseHandle(snapShot);
|
||||
|
||||
return PROCESSENTRY32();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,9 +48,17 @@ public:
|
|||
}
|
||||
uintptr_t ReadChain(uintptr_t address, const std::vector<uintptr_t>& offsets)
|
||||
{
|
||||
uintptr_t result = Read<uintptr_t>(address + offsets.at(0));
|
||||
for (int i = 1; i < offsets.size(); i++)
|
||||
result = Read<uintptr_t>(result + offsets.at(i));
|
||||
if (!address || offsets.empty())
|
||||
return 0;
|
||||
|
||||
uintptr_t result = Read<uintptr_t>(address + offsets.front());
|
||||
for (std::size_t i = 1; i < offsets.size(); ++i)
|
||||
{
|
||||
if (!result)
|
||||
return 0;
|
||||
|
||||
result = Read<uintptr_t>(result + offsets[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -62,9 +70,17 @@ public:
|
|||
}
|
||||
std::string ReadString(uintptr_t address, int length)
|
||||
{
|
||||
static char Buffer[256]{};
|
||||
ReadProcessMemory(pHandle, (void*)(address), Buffer, length, nullptr);
|
||||
if (!address || length <= 0)
|
||||
return {};
|
||||
|
||||
char Buffer[256]{};
|
||||
if (length >= static_cast<int>(sizeof(Buffer)))
|
||||
length = static_cast<int>(sizeof(Buffer)) - 1;
|
||||
|
||||
if (!ReadProcessMemory(pHandle, reinterpret_cast<void*>(address), Buffer, length, nullptr))
|
||||
return {};
|
||||
|
||||
Buffer[length] = '\0';
|
||||
return std::string(Buffer);
|
||||
};
|
||||
wchar_t* ReadWString(uintptr_t address, int length)
|
||||
|
|
|
|||
Loading…
Reference in New Issue