feat: add dump-backed runtime modifiers
This commit is contained in:
parent
6fc8d8c16b
commit
632dc46116
|
|
@ -1,7 +1,7 @@
|
||||||
#include "Framework.h"
|
#include "Framework.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
// 内存修改类功能 (NoSway/InfStamina/NoFallDmg) 已移除:
|
// 只实现 dump 明确的对象字段;后座/故障链路等类布局确认后再接入,当前不写内存。
|
||||||
// 它们依赖 IL2CPP 版偏移, 在 EXFIL DELTA (Mono 0.16.9) 上偏移不兼容, 会乱写内存。
|
|
||||||
|
|
||||||
void CFramework::GetESPInfo(const int& SpawnType, std::string& vOutStr, ImColor& vOutColor)
|
void CFramework::GetESPInfo(const int& SpawnType, std::string& vOutStr, ImColor& vOutColor)
|
||||||
{
|
{
|
||||||
|
|
@ -168,4 +168,240 @@ void CFramework::GetESPInfo(const int& SpawnType, std::string& vOutStr, ImColor&
|
||||||
vOutColor = ImColor(1.f, 1.f, 1.f, 1.f);
|
vOutColor = ImColor(1.f, 1.f, 1.f, 1.f);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool IsUsableAddress(const uintptr_t address)
|
||||||
|
{
|
||||||
|
// x64 user-mode canonical range; reject null/obviously bogus chains before any write.
|
||||||
|
return address > 0x10000ULL && address < 0x0000800000000000ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFiniteValue(const float value)
|
||||||
|
{
|
||||||
|
return std::isfinite(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFiniteVector(const Vector3& value)
|
||||||
|
{
|
||||||
|
return IsFiniteValue(value.x) && IsFiniteValue(value.y) && IsFiniteValue(value.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsUsableCapacity(const float value)
|
||||||
|
{
|
||||||
|
return IsFiniteValue(value) && value > 0.f && value < 100000.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramework::UpdateFeatures()
|
||||||
|
{
|
||||||
|
if (!tarkov->IsInRaid() || !IsUsableAddress(tarkov->m_pLocalGameWorld))
|
||||||
|
{
|
||||||
|
ResetFeatureOverrides();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh MainPlayer from the current LocalGameWorld instead of trusting a stale list-thread cache.
|
||||||
|
uintptr_t currentLocal = 0;
|
||||||
|
if (!m.TryRead(tarkov->m_pLocalGameWorld + offset::MainPlayer, currentLocal) ||
|
||||||
|
!IsUsableAddress(currentLocal))
|
||||||
|
{
|
||||||
|
ResetFeatureOverrides();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
local.m_address = currentLocal;
|
||||||
|
|
||||||
|
if (g.g_InfStamina)
|
||||||
|
|
||||||
|
UpdateStaminaOverride();
|
||||||
|
else
|
||||||
|
ResetStaminaOverride();
|
||||||
|
|
||||||
|
if (g.g_NoFallDamage)
|
||||||
|
UpdateFallDamageOverride();
|
||||||
|
else
|
||||||
|
ResetFallDamageOverride();
|
||||||
|
|
||||||
|
if (g.g_NoSway)
|
||||||
|
UpdateSwayOverride();
|
||||||
|
else
|
||||||
|
ResetSwayOverride();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramework::UpdateStaminaOverride()
|
||||||
|
{
|
||||||
|
uintptr_t physical = 0;
|
||||||
|
uintptr_t stamina = 0;
|
||||||
|
uintptr_t handsStamina = 0;
|
||||||
|
|
||||||
|
if (!m.TryRead(local.m_address + offset::Player::pPhysics, physical) ||
|
||||||
|
!IsUsableAddress(physical) ||
|
||||||
|
!m.TryRead(physical + offset::Physics::Stamina, stamina) ||
|
||||||
|
!m.TryRead(physical + offset::Physics::HandsStamina, handsStamina) ||
|
||||||
|
!IsUsableAddress(stamina) ||
|
||||||
|
!IsUsableAddress(handsStamina))
|
||||||
|
{
|
||||||
|
ResetStaminaOverride();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_staminaOverride.captured &&
|
||||||
|
(m_staminaOverride.player != local.m_address ||
|
||||||
|
m_staminaOverride.physical != physical ||
|
||||||
|
m_staminaOverride.stamina != stamina ||
|
||||||
|
m_staminaOverride.handsStamina != handsStamina))
|
||||||
|
{
|
||||||
|
ResetStaminaOverride();
|
||||||
|
}
|
||||||
|
|
||||||
|
float staminaCapacity = 0.f;
|
||||||
|
float handsCapacity = 0.f;
|
||||||
|
if (!m.TryRead(physical + offset::Physics::StaminaCapacity, staminaCapacity) ||
|
||||||
|
!m.TryRead(physical + offset::Physics::HandsCapacity, handsCapacity) ||
|
||||||
|
!IsUsableCapacity(staminaCapacity) ||
|
||||||
|
!IsUsableCapacity(handsCapacity))
|
||||||
|
{
|
||||||
|
ResetStaminaOverride();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_staminaOverride.captured)
|
||||||
|
{
|
||||||
|
float staminaCurrent = 0.f;
|
||||||
|
float handsCurrent = 0.f;
|
||||||
|
if (!m.TryRead(stamina + offset::PhysicalState::Current, staminaCurrent) ||
|
||||||
|
!m.TryRead(handsStamina + offset::PhysicalState::Current, handsCurrent) ||
|
||||||
|
!IsFiniteValue(staminaCurrent) ||
|
||||||
|
!IsFiniteValue(handsCurrent))
|
||||||
|
{
|
||||||
|
ResetStaminaOverride();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_staminaOverride.player = local.m_address;
|
||||||
|
m_staminaOverride.physical = physical;
|
||||||
|
m_staminaOverride.stamina = stamina;
|
||||||
|
m_staminaOverride.handsStamina = handsStamina;
|
||||||
|
m_staminaOverride.staminaCurrent = staminaCurrent;
|
||||||
|
m_staminaOverride.handsCurrent = handsCurrent;
|
||||||
|
m_staminaOverride.captured = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both current fields and both capacities are dump-confirmed object fields.
|
||||||
|
m.TryWrite<float>(stamina + offset::PhysicalState::Current, staminaCapacity);
|
||||||
|
m.TryWrite<float>(handsStamina + offset::PhysicalState::Current, handsCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramework::UpdateFallDamageOverride()
|
||||||
|
{
|
||||||
|
uintptr_t physical = 0;
|
||||||
|
if (!m.TryRead(local.m_address + offset::Player::pPhysics, physical) ||
|
||||||
|
!IsUsableAddress(physical))
|
||||||
|
{
|
||||||
|
ResetFallDamageOverride();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_fallDamageOverride.captured &&
|
||||||
|
(m_fallDamageOverride.player != local.m_address ||
|
||||||
|
m_fallDamageOverride.physical != physical))
|
||||||
|
{
|
||||||
|
ResetFallDamageOverride();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_fallDamageOverride.captured)
|
||||||
|
{
|
||||||
|
float multiplier = 0.f;
|
||||||
|
if (!m.TryRead(physical + offset::Physics::FallDamageMultiplier, multiplier) ||
|
||||||
|
!IsFiniteValue(multiplier))
|
||||||
|
{
|
||||||
|
ResetFallDamageOverride();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fallDamageOverride.player = local.m_address;
|
||||||
|
m_fallDamageOverride.physical = physical;
|
||||||
|
m_fallDamageOverride.multiplier = multiplier;
|
||||||
|
m_fallDamageOverride.captured = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m.TryWrite<float>(physical + offset::Physics::FallDamageMultiplier, 0.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramework::UpdateSwayOverride()
|
||||||
|
{
|
||||||
|
uintptr_t weaponAnimation = 0;
|
||||||
|
uintptr_t motionEffector = 0;
|
||||||
|
if (!m.TryRead(local.m_address + offset::Player::pWeaponAnimation, weaponAnimation) ||
|
||||||
|
!IsUsableAddress(weaponAnimation) ||
|
||||||
|
!m.TryRead(weaponAnimation + offset::WeaponAnimations::MotionReact, motionEffector) ||
|
||||||
|
!IsUsableAddress(motionEffector))
|
||||||
|
{
|
||||||
|
ResetSwayOverride();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_swayOverride.captured &&
|
||||||
|
(m_swayOverride.player != local.m_address ||
|
||||||
|
m_swayOverride.weaponAnimation != weaponAnimation ||
|
||||||
|
m_swayOverride.motionEffector != motionEffector))
|
||||||
|
{
|
||||||
|
ResetSwayOverride();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_swayOverride.captured)
|
||||||
|
{
|
||||||
|
Vector3 swayFactors{};
|
||||||
|
if (!m.TryRead(motionEffector + offset::MotionEffector::SwayFactors, swayFactors) ||
|
||||||
|
!IsFiniteVector(swayFactors))
|
||||||
|
{
|
||||||
|
ResetSwayOverride();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_swayOverride.player = local.m_address;
|
||||||
|
m_swayOverride.weaponAnimation = weaponAnimation;
|
||||||
|
m_swayOverride.motionEffector = motionEffector;
|
||||||
|
m_swayOverride.swayFactors = swayFactors;
|
||||||
|
m_swayOverride.captured = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m.TryWrite<Vector3>(motionEffector + offset::MotionEffector::SwayFactors, Vector3{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramework::ResetStaminaOverride()
|
||||||
|
{
|
||||||
|
if (m_staminaOverride.captured)
|
||||||
|
{
|
||||||
|
if (IsUsableAddress(m_staminaOverride.stamina))
|
||||||
|
m.TryWrite<float>(m_staminaOverride.stamina + offset::PhysicalState::Current, m_staminaOverride.staminaCurrent);
|
||||||
|
if (IsUsableAddress(m_staminaOverride.handsStamina))
|
||||||
|
m.TryWrite<float>(m_staminaOverride.handsStamina + offset::PhysicalState::Current, m_staminaOverride.handsCurrent);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_staminaOverride = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramework::ResetFallDamageOverride()
|
||||||
|
{
|
||||||
|
if (m_fallDamageOverride.captured && IsUsableAddress(m_fallDamageOverride.physical))
|
||||||
|
m.TryWrite<float>(m_fallDamageOverride.physical + offset::Physics::FallDamageMultiplier, m_fallDamageOverride.multiplier);
|
||||||
|
|
||||||
|
m_fallDamageOverride = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramework::ResetSwayOverride()
|
||||||
|
{
|
||||||
|
if (m_swayOverride.captured && IsUsableAddress(m_swayOverride.motionEffector))
|
||||||
|
m.TryWrite<Vector3>(m_swayOverride.motionEffector + offset::MotionEffector::SwayFactors, m_swayOverride.swayFactors);
|
||||||
|
|
||||||
|
m_swayOverride = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramework::ResetFeatureOverrides()
|
||||||
|
{
|
||||||
|
ResetStaminaOverride();
|
||||||
|
ResetFallDamageOverride();
|
||||||
|
ResetSwayOverride();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,52 @@ public:
|
||||||
void RenderMenu();
|
void RenderMenu();
|
||||||
void RenderESP();
|
void RenderESP();
|
||||||
void AimAll();
|
void AimAll();
|
||||||
|
void UpdateFeatures();
|
||||||
|
void ResetFeatureOverrides();
|
||||||
private:
|
private:
|
||||||
|
struct StaminaOverrideState
|
||||||
|
{
|
||||||
|
uintptr_t player{ 0 };
|
||||||
|
uintptr_t physical{ 0 };
|
||||||
|
uintptr_t stamina{ 0 };
|
||||||
|
uintptr_t handsStamina{ 0 };
|
||||||
|
float staminaCurrent{ 0.f };
|
||||||
|
float handsCurrent{ 0.f };
|
||||||
|
bool captured{ false };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FallDamageOverrideState
|
||||||
|
{
|
||||||
|
uintptr_t player{ 0 };
|
||||||
|
uintptr_t physical{ 0 };
|
||||||
|
float multiplier{ 0.f };
|
||||||
|
bool captured{ false };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SwayOverrideState
|
||||||
|
{
|
||||||
|
uintptr_t player{ 0 };
|
||||||
|
uintptr_t weaponAnimation{ 0 };
|
||||||
|
uintptr_t motionEffector{ 0 };
|
||||||
|
Vector3 swayFactors{};
|
||||||
|
bool captured{ false };
|
||||||
|
};
|
||||||
|
|
||||||
|
void UpdateStaminaOverride();
|
||||||
|
void UpdateFallDamageOverride();
|
||||||
|
void UpdateSwayOverride();
|
||||||
|
void ResetStaminaOverride();
|
||||||
|
void ResetFallDamageOverride();
|
||||||
|
void ResetSwayOverride();
|
||||||
|
|
||||||
CGame* tarkov = new CGame();
|
CGame* tarkov = new CGame();
|
||||||
CPlayer local;
|
CPlayer local;
|
||||||
|
|
||||||
|
StaminaOverrideState m_staminaOverride{};
|
||||||
|
FallDamageOverrideState m_fallDamageOverride{};
|
||||||
|
SwayOverrideState m_swayOverride{};
|
||||||
|
|
||||||
|
|
||||||
std::mutex m_mtxEntityList;
|
std::mutex m_mtxEntityList;
|
||||||
std::mutex m_mtxExfilList;
|
std::mutex m_mtxExfilList;
|
||||||
std::mutex m_mtxItemList;
|
std::mutex m_mtxItemList;
|
||||||
|
|
@ -81,6 +123,9 @@ private:
|
||||||
void AimMemory(const Vector3& target, const Vector3& localPos);
|
void AimMemory(const Vector3& target, const Vector3& localPos);
|
||||||
void ScanRotationOffset(); // 2阶段扫描: Player->MC 与 MC->Rotation 偏移
|
void ScanRotationOffset(); // 2阶段扫描: Player->MC 与 MC->Rotation 偏移
|
||||||
|
|
||||||
|
// Runtime feature backup state is declared above.
|
||||||
|
|
||||||
|
|
||||||
// 旋转偏移扫描器状态
|
// 旋转偏移扫描器状态
|
||||||
int m_scanPhase = 0; // 0 = 待机/Step1, 1 = 等待转动鼠标后 Step2
|
int m_scanPhase = 0; // 0 = 待机/Step1, 1 = 等待转动鼠标后 Step2
|
||||||
char m_scanResult[192]{ 0 };
|
char m_scanResult[192]{ 0 };
|
||||||
|
|
|
||||||
|
|
@ -120,10 +120,16 @@ void CFramework::RenderMenu()
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
||||||
ImGui::TextDisabled("内存修改类功能已移除");
|
ImGui::Checkbox("无限耐力", &g.g_InfStamina);
|
||||||
ImGui::TextDisabled("(Mono 版偏移不兼容, 防止乱写内存)");
|
ImGui::Checkbox("无跌落伤害", &g.g_NoFallDamage);
|
||||||
|
ImGui::Checkbox("无摇摆", &g.g_NoSway);
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::TextDisabled("仅写入 dump 已确认的对象字段");
|
||||||
|
ImGui::TextDisabled("后座 / 故障:等待下一轮类布局确认");
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
ImGui::BeginChild("##C021", ImVec2(ImGui::GetContentRegionAvail()), true);
|
ImGui::BeginChild("##C021", ImVec2(ImGui::GetContentRegionAvail()), true);
|
||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
@ -305,9 +311,18 @@ void CFramework::RenderMenu()
|
||||||
case 2: // Misc
|
case 2: // Misc
|
||||||
ImGui::BeginChild("##C200", ImVec2(ImGui::GetContentRegionAvail()), true);
|
ImGui::BeginChild("##C200", ImVec2(ImGui::GetContentRegionAvail()), true);
|
||||||
|
|
||||||
|
ImGui::Text("功能状态");
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::Text("局内:%s", tarkov->IsInRaid() ? "是" : "否");
|
||||||
|
ImGui::Text("本地:0x%llX", (unsigned long long)local.m_address);
|
||||||
|
ImGui::TextDisabled("关闭开关或离开局内会恢复原值");
|
||||||
|
ImGui::TextDisabled("非法/不完整指针链不会写入");
|
||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
break;
|
break;
|
||||||
case 3: // Setting
|
case 3: // Setting
|
||||||
|
|
||||||
ImGui::BeginChild("##C300", ImVec2(ImGui::GetContentRegionAvail()), true);
|
ImGui::BeginChild("##C300", ImVec2(ImGui::GetContentRegionAvail()), true);
|
||||||
|
|
||||||
ImGui::Text("退出");
|
ImGui::Text("退出");
|
||||||
|
|
|
||||||
|
|
@ -102,9 +102,22 @@ namespace offset
|
||||||
namespace WeaponAnimations
|
namespace WeaponAnimations
|
||||||
{
|
{
|
||||||
constexpr auto Breath = 0x30;
|
constexpr auto Breath = 0x30;
|
||||||
|
constexpr auto MotionReact = 0x40; // MotionEffector
|
||||||
constexpr auto isAiming = 0x1C5;
|
constexpr auto isAiming = 0x1C5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -.MotionEffector
|
||||||
|
namespace MotionEffector
|
||||||
|
{
|
||||||
|
constexpr auto SwayFactors = 0x94; // UnityEngine.Vector3
|
||||||
|
}
|
||||||
|
|
||||||
|
// -.GClass774 (stamina/oxygen state)
|
||||||
|
namespace PhysicalState
|
||||||
|
{
|
||||||
|
constexpr auto Current = 0x48; // Single
|
||||||
|
}
|
||||||
|
|
||||||
// .BasePhysicalClass
|
// .BasePhysicalClass
|
||||||
namespace Physics
|
namespace Physics
|
||||||
{
|
{
|
||||||
|
|
@ -112,6 +125,9 @@ namespace offset
|
||||||
constexpr auto HandsStamina = 0x40;
|
constexpr auto HandsStamina = 0x40;
|
||||||
constexpr auto Oxygen = 0x48;
|
constexpr auto Oxygen = 0x48;
|
||||||
constexpr auto FallDamageMultiplier = 0xBC;
|
constexpr auto FallDamageMultiplier = 0xBC;
|
||||||
|
constexpr auto StaminaCapacity = 0xC0;
|
||||||
|
constexpr auto HandsCapacity = 0xC8;
|
||||||
constexpr auto OxygenRestoreRate = 0xD4;
|
constexpr auto OxygenRestoreRate = 0xD4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,12 @@ void CFramework::UpdateList()
|
||||||
std::vector<CPlayer> list_player{};
|
std::vector<CPlayer> list_player{};
|
||||||
std::vector<uintptr_t> list_grenade{};
|
std::vector<uintptr_t> list_grenade{};
|
||||||
|
|
||||||
if (g.g_ESP || g.g_Aim)
|
if (g.g_ESP || g.g_Aim || g.g_InfStamina || g.g_NoFallDamage || g.g_NoSway)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Failed refreshes must not leave a stale player address available to memory features.
|
||||||
|
local.m_address = 0;
|
||||||
|
|
||||||
// not In raid
|
// not In raid
|
||||||
if (!tarkov->Update())
|
if (!tarkov->Update())
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,11 @@ struct Globals
|
||||||
float g_ESP_MaxDistance = 500.f;
|
float g_ESP_MaxDistance = 500.f;
|
||||||
float g_ESP_MaxItemDistance = 50.f;
|
float g_ESP_MaxItemDistance = 50.f;
|
||||||
|
|
||||||
// Misc (内存修改类功能已移除: Mono 版偏移不兼容, 防止乱写内存)
|
// Misc (仅使用 dump 已确认的对象字段)
|
||||||
|
bool g_InfStamina = false;
|
||||||
|
bool g_NoFallDamage = false;
|
||||||
|
bool g_NoSway = false;
|
||||||
|
|
||||||
|
|
||||||
// Aim (自瞄)
|
// Aim (自瞄)
|
||||||
bool g_Aim = false;
|
bool g_Aim = false;
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,36 @@ public:
|
||||||
{
|
{
|
||||||
WriteProcessMemory(pHandle, reinterpret_cast<void*>(address), &value, sizeof(T), NULL);
|
WriteProcessMemory(pHandle, reinterpret_cast<void*>(address), &value, sizeof(T), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool TryRead(const uintptr_t& address, T& value) const noexcept
|
||||||
|
{
|
||||||
|
value = T{};
|
||||||
|
if (!pHandle || !address)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SIZE_T sizeRead = 0;
|
||||||
|
return !!ReadProcessMemory(pHandle, reinterpret_cast<const void*>(address), &value, sizeof(T), &sizeRead)
|
||||||
|
&& sizeRead == sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool TryWrite(const uintptr_t& address, const T& value) const noexcept
|
||||||
|
{
|
||||||
|
if (!pHandle || !address)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SIZE_T sizeWritten = 0;
|
||||||
|
return !!WriteProcessMemory(pHandle, reinterpret_cast<void*>(address), &value, sizeof(T), &sizeWritten)
|
||||||
|
&& sizeWritten == sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t ReadChain(uintptr_t address, const std::vector<uintptr_t>& offsets)
|
uintptr_t ReadChain(uintptr_t address, const std::vector<uintptr_t>& offsets)
|
||||||
{
|
{
|
||||||
if (!address || offsets.empty())
|
if (!address || offsets.empty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
uintptr_t result = Read<uintptr_t>(address + offsets.front());
|
uintptr_t result = Read<uintptr_t>(address + offsets.front());
|
||||||
for (std::size_t i = 1; i < offsets.size(); ++i)
|
for (std::size_t i = 1; i < offsets.size(); ++i)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ void Overlay::OverlayUserFunction()
|
||||||
if (g.g_ESP)
|
if (g.g_ESP)
|
||||||
cheat->RenderESP();
|
cheat->RenderESP();
|
||||||
|
|
||||||
|
// 只在局内且指针链完整时更新 dump 已确认的运行时字段。
|
||||||
|
cheat->UpdateFeatures();
|
||||||
|
|
||||||
// 自瞄/压枪 (Aim.cpp)
|
// 自瞄/压枪 (Aim.cpp)
|
||||||
cheat->AimAll();
|
cheat->AimAll();
|
||||||
|
|
||||||
|
|
@ -91,9 +94,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
std::thread([&]() { cheat->UpdateStaticList(); }).detach();
|
std::thread([&]() { cheat->UpdateStaticList(); }).detach();
|
||||||
|
|
||||||
overlay->OverlayLoop();
|
overlay->OverlayLoop();
|
||||||
|
g.process_active = false;
|
||||||
|
cheat->ResetFeatureOverrides();
|
||||||
overlay->DestroyOverlay();
|
overlay->DestroyOverlay();
|
||||||
m.DetachProcess();
|
m.DetachProcess();
|
||||||
g.process_active = false;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue