feat: add recoil malfunction and aim fixes
This commit is contained in:
parent
632dc46116
commit
99d599026d
|
|
@ -43,8 +43,19 @@ namespace
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsFiniteRotation(const Vector2& value)
|
||||||
|
{
|
||||||
|
return std::isfinite(value.x) && std::isfinite(value.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsUsableAimAddress(const uintptr_t address)
|
||||||
|
{
|
||||||
|
return address > 0x10000ULL && address < 0x0000800000000000ULL;
|
||||||
|
}
|
||||||
|
|
||||||
float FrameScale()
|
float FrameScale()
|
||||||
{
|
{
|
||||||
|
|
||||||
float deltaTime = ImGui::GetIO().DeltaTime;
|
float deltaTime = ImGui::GetIO().DeltaTime;
|
||||||
if (!(deltaTime > 0.f) || deltaTime > 0.2f)
|
if (!(deltaTime > 0.f) || deltaTime > 0.2f)
|
||||||
deltaTime = 1.f / 60.f;
|
deltaTime = 1.f / 60.f;
|
||||||
|
|
@ -382,14 +393,28 @@ void CFramework::AimMouse(const Vector2& target, const Vector2& center)
|
||||||
// オフセットは g.g_AimMcOffset / g.g_AimRotOffset (运行时可变) を使用
|
// オフセットは g.g_AimMcOffset / g.g_AimRotOffset (运行时可变) を使用
|
||||||
void CFramework::AimMemory(const Vector3& target, const Vector3& localPos)
|
void CFramework::AimMemory(const Vector3& target, const Vector3& localPos)
|
||||||
{
|
{
|
||||||
uintptr_t mc = m.Read<uintptr_t>(local.m_address + (uintptr_t)g.g_AimMcOffset);
|
if (!IsUsableAimAddress(local.m_address) ||
|
||||||
if (!mc)
|
g.g_AimMcOffset <= 0 || g.g_AimMcOffset > 0x1000 ||
|
||||||
|
g.g_AimRotOffset < 0 || g.g_AimRotOffset > 0x1000)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 現在の回転 [rad]
|
uintptr_t mc = 0;
|
||||||
Vector2 rot = m.Read<Vector2>(mc + (uintptr_t)g.g_AimRotOffset);
|
if (!m.TryRead(local.m_address + static_cast<uintptr_t>(g.g_AimMcOffset), mc) ||
|
||||||
|
!IsUsableAimAddress(mc))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MovementContext.Rotation_1 is a dump-confirmed Vector2 at +0x27C in this build.
|
||||||
|
Vector2 rot{};
|
||||||
|
if (!m.TryRead(mc + static_cast<uintptr_t>(g.g_AimRotOffset), rot) ||
|
||||||
|
!IsFiniteRotation(rot))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 目標までの方向
|
|
||||||
Vector3 delta = target - localPos;
|
Vector3 delta = target - localPos;
|
||||||
float len2d = sqrtf(delta.x * delta.x + delta.z * delta.z);
|
float len2d = sqrtf(delta.x * delta.x + delta.z * delta.z);
|
||||||
if (len2d < 0.001f)
|
if (len2d < 0.001f)
|
||||||
|
|
@ -401,19 +426,27 @@ void CFramework::AimMemory(const Vector3& target, const Vector3& localPos)
|
||||||
yaw = ClampAngle(yaw);
|
yaw = ClampAngle(yaw);
|
||||||
pitch = ClampAngle(pitch);
|
pitch = ClampAngle(pitch);
|
||||||
|
|
||||||
// Distance-adaptive exponential smoothing. It is never 0 or 1, so the
|
|
||||||
// slider cannot produce either a one-frame snap or a permanently lagging aim.
|
|
||||||
float dyaw = ClampAngle(yaw - rot.x);
|
float dyaw = ClampAngle(yaw - rot.x);
|
||||||
float dpitch = ClampAngle(pitch - rot.y);
|
float dpitch = ClampAngle(pitch - rot.y);
|
||||||
float angleError = sqrtf(dyaw * dyaw + dpitch * dpitch);
|
float angleError = sqrtf(dyaw * dyaw + dpitch * dpitch);
|
||||||
|
if (!(angleError > 0.0001f) || !std::isfinite(angleError))
|
||||||
|
return;
|
||||||
|
|
||||||
float t = AimResponse(angleError, g.g_AimSmooth, 0.75f);
|
float t = AimResponse(angleError, g.g_AimSmooth, 0.75f);
|
||||||
|
|
||||||
|
// Cap the absolute angular step. AimResponse alone still gives a large
|
||||||
|
// first-frame move for a far target, which looks like a teleport in memory mode.
|
||||||
|
const float smooth = Clamp01(g.g_AimSmooth * 0.01f);
|
||||||
|
const float maxAngleStep = 0.10f + (1.f - smooth) * 0.12f;
|
||||||
|
if (angleError > maxAngleStep)
|
||||||
|
t = min(t, maxAngleStep / angleError);
|
||||||
|
|
||||||
Vector2 newRot{
|
Vector2 newRot{
|
||||||
ClampAngle(rot.x + dyaw * t),
|
ClampAngle(rot.x + dyaw * t),
|
||||||
ClampAngle(rot.y + dpitch * t)
|
ClampAngle(rot.y + dpitch * t)
|
||||||
};
|
};
|
||||||
|
|
||||||
m.Write<Vector2>(mc + (uintptr_t)g.g_AimRotOffset, newRot);
|
m.TryWrite<Vector2>(mc + static_cast<uintptr_t>(g.g_AimRotOffset), newRot);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "Framework.h"
|
#include "Framework.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
// 只实现 dump 明确的对象字段;后座/故障链路等类布局确认后再接入,当前不写内存。
|
// 只写入 dump 明确的对象字段;后座与故障也只使用本轮已确认的链路,弹道追踪暂不写。
|
||||||
|
|
||||||
void CFramework::GetESPInfo(const int& SpawnType, std::string& vOutStr, ImColor& vOutColor)
|
void CFramework::GetESPInfo(const int& SpawnType, std::string& vOutStr, ImColor& vOutColor)
|
||||||
{
|
{
|
||||||
|
|
@ -227,10 +227,162 @@ void CFramework::UpdateFeatures()
|
||||||
UpdateSwayOverride();
|
UpdateSwayOverride();
|
||||||
else
|
else
|
||||||
ResetSwayOverride();
|
ResetSwayOverride();
|
||||||
|
|
||||||
|
if (g.g_NoRecoil)
|
||||||
|
UpdateNoRecoilOverride();
|
||||||
|
else
|
||||||
|
ResetNoRecoilOverride();
|
||||||
|
|
||||||
|
if (g.g_NoMalfunction)
|
||||||
|
UpdateNoMalfunctionOverride();
|
||||||
|
else
|
||||||
|
ResetNoMalfunctionOverride();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFramework::ResolveCurrentWeapon(uintptr_t& weaponAnimation, uintptr_t& shotEffector,
|
||||||
|
uintptr_t& weapon, uintptr_t& weaponTemplate)
|
||||||
|
{
|
||||||
|
weaponAnimation = 0;
|
||||||
|
shotEffector = 0;
|
||||||
|
weapon = 0;
|
||||||
|
weaponTemplate = 0;
|
||||||
|
|
||||||
|
if (!IsUsableAddress(local.m_address) ||
|
||||||
|
!m.TryRead(local.m_address + offset::Player::pWeaponAnimation, weaponAnimation) ||
|
||||||
|
!IsUsableAddress(weaponAnimation) ||
|
||||||
|
!m.TryRead(weaponAnimation + offset::WeaponAnimations::ShotEffector, shotEffector) ||
|
||||||
|
!IsUsableAddress(shotEffector) ||
|
||||||
|
!m.TryRead(shotEffector + offset::ShotEffector::MainWeaponInHands, weapon) ||
|
||||||
|
!IsUsableAddress(weapon) ||
|
||||||
|
!m.TryRead(weapon + offset::Weapon::Template, weaponTemplate) ||
|
||||||
|
!IsUsableAddress(weaponTemplate))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramework::UpdateNoRecoilOverride()
|
||||||
|
{
|
||||||
|
uintptr_t weaponAnimation = 0;
|
||||||
|
uintptr_t shotEffector = 0;
|
||||||
|
uintptr_t weapon = 0;
|
||||||
|
uintptr_t weaponTemplate = 0;
|
||||||
|
uintptr_t recoilSettings = 0;
|
||||||
|
|
||||||
|
if (!ResolveCurrentWeapon(weaponAnimation, shotEffector, weapon, weaponTemplate) ||
|
||||||
|
!m.TryRead(weaponTemplate + offset::WeaponTemplate::WeaponRecoilSettings, recoilSettings) ||
|
||||||
|
!IsUsableAddress(recoilSettings))
|
||||||
|
{
|
||||||
|
ResetNoRecoilOverride();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_noRecoilOverride.captured &&
|
||||||
|
(m_noRecoilOverride.player != local.m_address ||
|
||||||
|
m_noRecoilOverride.weaponAnimation != weaponAnimation ||
|
||||||
|
m_noRecoilOverride.shotEffector != shotEffector ||
|
||||||
|
m_noRecoilOverride.weapon != weapon ||
|
||||||
|
m_noRecoilOverride.weaponTemplate != weaponTemplate ||
|
||||||
|
m_noRecoilOverride.recoilSettings != recoilSettings))
|
||||||
|
{
|
||||||
|
ResetNoRecoilOverride();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_noRecoilOverride.captured)
|
||||||
|
{
|
||||||
|
bool enable = false;
|
||||||
|
if (!m.TryRead(recoilSettings + offset::WeaponRecoil::Enable, enable))
|
||||||
|
{
|
||||||
|
ResetNoRecoilOverride();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_noRecoilOverride.player = local.m_address;
|
||||||
|
m_noRecoilOverride.weaponAnimation = weaponAnimation;
|
||||||
|
m_noRecoilOverride.shotEffector = shotEffector;
|
||||||
|
m_noRecoilOverride.weapon = weapon;
|
||||||
|
m_noRecoilOverride.weaponTemplate = weaponTemplate;
|
||||||
|
m_noRecoilOverride.recoilSettings = recoilSettings;
|
||||||
|
m_noRecoilOverride.enable = enable;
|
||||||
|
m_noRecoilOverride.captured = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WeaponRecoil.Enable is a dump-confirmed instance field. Do not touch its Values array yet.
|
||||||
|
m.TryWrite<bool>(recoilSettings + offset::WeaponRecoil::Enable, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramework::UpdateNoMalfunctionOverride()
|
||||||
|
{
|
||||||
|
uintptr_t weaponAnimation = 0;
|
||||||
|
uintptr_t shotEffector = 0;
|
||||||
|
uintptr_t weapon = 0;
|
||||||
|
uintptr_t weaponTemplate = 0;
|
||||||
|
uintptr_t malfunctionState = 0;
|
||||||
|
|
||||||
|
if (!ResolveCurrentWeapon(weaponAnimation, shotEffector, weapon, weaponTemplate) ||
|
||||||
|
!m.TryRead(weapon + offset::Weapon::MalfState, malfunctionState) ||
|
||||||
|
!IsUsableAddress(malfunctionState))
|
||||||
|
{
|
||||||
|
ResetNoMalfunctionOverride();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_noMalfunctionOverride.captured &&
|
||||||
|
(m_noMalfunctionOverride.player != local.m_address ||
|
||||||
|
m_noMalfunctionOverride.weapon != weapon ||
|
||||||
|
m_noMalfunctionOverride.weaponTemplate != weaponTemplate ||
|
||||||
|
m_noMalfunctionOverride.malfunctionState != malfunctionState))
|
||||||
|
{
|
||||||
|
ResetNoMalfunctionOverride();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_noMalfunctionOverride.captured)
|
||||||
|
{
|
||||||
|
bool allowJam = false;
|
||||||
|
bool allowFeed = false;
|
||||||
|
bool allowMisfire = false;
|
||||||
|
bool allowSlide = false;
|
||||||
|
float baseChance = 0.f;
|
||||||
|
int state = 0;
|
||||||
|
|
||||||
|
if (!m.TryRead(weaponTemplate + offset::WeaponTemplate::AllowJam, allowJam) ||
|
||||||
|
!m.TryRead(weaponTemplate + offset::WeaponTemplate::AllowFeed, allowFeed) ||
|
||||||
|
!m.TryRead(weaponTemplate + offset::WeaponTemplate::AllowMisfire, allowMisfire) ||
|
||||||
|
!m.TryRead(weaponTemplate + offset::WeaponTemplate::AllowSlide, allowSlide) ||
|
||||||
|
!m.TryRead(weaponTemplate + offset::WeaponTemplate::BaseMalfunctionChance, baseChance) ||
|
||||||
|
!m.TryRead(malfunctionState + offset::WeaponMalfunctionState::State, state) ||
|
||||||
|
!std::isfinite(baseChance))
|
||||||
|
{
|
||||||
|
ResetNoMalfunctionOverride();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_noMalfunctionOverride.player = local.m_address;
|
||||||
|
m_noMalfunctionOverride.weapon = weapon;
|
||||||
|
m_noMalfunctionOverride.weaponTemplate = weaponTemplate;
|
||||||
|
m_noMalfunctionOverride.malfunctionState = malfunctionState;
|
||||||
|
m_noMalfunctionOverride.allowJam = allowJam;
|
||||||
|
m_noMalfunctionOverride.allowFeed = allowFeed;
|
||||||
|
m_noMalfunctionOverride.allowMisfire = allowMisfire;
|
||||||
|
m_noMalfunctionOverride.allowSlide = allowSlide;
|
||||||
|
m_noMalfunctionOverride.baseChance = baseChance;
|
||||||
|
m_noMalfunctionOverride.state = state;
|
||||||
|
m_noMalfunctionOverride.captured = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m.TryWrite<bool>(weaponTemplate + offset::WeaponTemplate::AllowJam, false);
|
||||||
|
m.TryWrite<bool>(weaponTemplate + offset::WeaponTemplate::AllowFeed, false);
|
||||||
|
m.TryWrite<bool>(weaponTemplate + offset::WeaponTemplate::AllowMisfire, false);
|
||||||
|
m.TryWrite<bool>(weaponTemplate + offset::WeaponTemplate::AllowSlide, false);
|
||||||
|
m.TryWrite<float>(weaponTemplate + offset::WeaponTemplate::BaseMalfunctionChance, 0.f);
|
||||||
|
m.TryWrite<int>(malfunctionState + offset::WeaponMalfunctionState::State, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFramework::UpdateStaminaOverride()
|
void CFramework::UpdateStaminaOverride()
|
||||||
{
|
{
|
||||||
|
|
||||||
uintptr_t physical = 0;
|
uintptr_t physical = 0;
|
||||||
uintptr_t stamina = 0;
|
uintptr_t stamina = 0;
|
||||||
uintptr_t handsStamina = 0;
|
uintptr_t handsStamina = 0;
|
||||||
|
|
@ -370,8 +522,48 @@ void CFramework::UpdateSwayOverride()
|
||||||
m.TryWrite<Vector3>(motionEffector + offset::MotionEffector::SwayFactors, Vector3{});
|
m.TryWrite<Vector3>(motionEffector + offset::MotionEffector::SwayFactors, Vector3{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CFramework::ResetNoRecoilOverride()
|
||||||
|
{
|
||||||
|
if (m_noRecoilOverride.captured && IsUsableAddress(m_noRecoilOverride.recoilSettings))
|
||||||
|
{
|
||||||
|
m.TryWrite<bool>(m_noRecoilOverride.recoilSettings + offset::WeaponRecoil::Enable,
|
||||||
|
m_noRecoilOverride.enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_noRecoilOverride = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramework::ResetNoMalfunctionOverride()
|
||||||
|
{
|
||||||
|
if (m_noMalfunctionOverride.captured)
|
||||||
|
{
|
||||||
|
if (IsUsableAddress(m_noMalfunctionOverride.weaponTemplate))
|
||||||
|
{
|
||||||
|
m.TryWrite<bool>(m_noMalfunctionOverride.weaponTemplate + offset::WeaponTemplate::AllowJam,
|
||||||
|
m_noMalfunctionOverride.allowJam);
|
||||||
|
m.TryWrite<bool>(m_noMalfunctionOverride.weaponTemplate + offset::WeaponTemplate::AllowFeed,
|
||||||
|
m_noMalfunctionOverride.allowFeed);
|
||||||
|
m.TryWrite<bool>(m_noMalfunctionOverride.weaponTemplate + offset::WeaponTemplate::AllowMisfire,
|
||||||
|
m_noMalfunctionOverride.allowMisfire);
|
||||||
|
m.TryWrite<bool>(m_noMalfunctionOverride.weaponTemplate + offset::WeaponTemplate::AllowSlide,
|
||||||
|
m_noMalfunctionOverride.allowSlide);
|
||||||
|
m.TryWrite<float>(m_noMalfunctionOverride.weaponTemplate + offset::WeaponTemplate::BaseMalfunctionChance,
|
||||||
|
m_noMalfunctionOverride.baseChance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsUsableAddress(m_noMalfunctionOverride.malfunctionState))
|
||||||
|
{
|
||||||
|
m.TryWrite<int>(m_noMalfunctionOverride.malfunctionState + offset::WeaponMalfunctionState::State,
|
||||||
|
m_noMalfunctionOverride.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_noMalfunctionOverride = {};
|
||||||
|
}
|
||||||
|
|
||||||
void CFramework::ResetStaminaOverride()
|
void CFramework::ResetStaminaOverride()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_staminaOverride.captured)
|
if (m_staminaOverride.captured)
|
||||||
{
|
{
|
||||||
if (IsUsableAddress(m_staminaOverride.stamina))
|
if (IsUsableAddress(m_staminaOverride.stamina))
|
||||||
|
|
@ -404,4 +596,6 @@ void CFramework::ResetFeatureOverrides()
|
||||||
ResetStaminaOverride();
|
ResetStaminaOverride();
|
||||||
ResetFallDamageOverride();
|
ResetFallDamageOverride();
|
||||||
ResetSwayOverride();
|
ResetSwayOverride();
|
||||||
|
ResetNoRecoilOverride();
|
||||||
|
ResetNoMalfunctionOverride();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,40 @@ private:
|
||||||
bool captured{ false };
|
bool captured{ false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NoRecoilOverrideState
|
||||||
|
{
|
||||||
|
uintptr_t player{ 0 };
|
||||||
|
uintptr_t weaponAnimation{ 0 };
|
||||||
|
uintptr_t shotEffector{ 0 };
|
||||||
|
uintptr_t weapon{ 0 };
|
||||||
|
uintptr_t weaponTemplate{ 0 };
|
||||||
|
uintptr_t recoilSettings{ 0 };
|
||||||
|
bool enable{ false };
|
||||||
|
bool captured{ false };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NoMalfunctionOverrideState
|
||||||
|
{
|
||||||
|
uintptr_t player{ 0 };
|
||||||
|
uintptr_t weapon{ 0 };
|
||||||
|
uintptr_t weaponTemplate{ 0 };
|
||||||
|
uintptr_t malfunctionState{ 0 };
|
||||||
|
bool allowJam{ false };
|
||||||
|
bool allowFeed{ false };
|
||||||
|
bool allowMisfire{ false };
|
||||||
|
bool allowSlide{ false };
|
||||||
|
float baseChance{ 0.f };
|
||||||
|
int state{ 0 };
|
||||||
|
bool captured{ false };
|
||||||
|
};
|
||||||
|
|
||||||
|
bool ResolveCurrentWeapon(uintptr_t& weaponAnimation, uintptr_t& shotEffector,
|
||||||
|
uintptr_t& weapon, uintptr_t& weaponTemplate);
|
||||||
|
void UpdateNoRecoilOverride();
|
||||||
|
void UpdateNoMalfunctionOverride();
|
||||||
|
void ResetNoRecoilOverride();
|
||||||
|
void ResetNoMalfunctionOverride();
|
||||||
|
|
||||||
void UpdateStaminaOverride();
|
void UpdateStaminaOverride();
|
||||||
void UpdateFallDamageOverride();
|
void UpdateFallDamageOverride();
|
||||||
void UpdateSwayOverride();
|
void UpdateSwayOverride();
|
||||||
|
|
@ -66,6 +100,8 @@ private:
|
||||||
StaminaOverrideState m_staminaOverride{};
|
StaminaOverrideState m_staminaOverride{};
|
||||||
FallDamageOverrideState m_fallDamageOverride{};
|
FallDamageOverrideState m_fallDamageOverride{};
|
||||||
SwayOverrideState m_swayOverride{};
|
SwayOverrideState m_swayOverride{};
|
||||||
|
NoRecoilOverrideState m_noRecoilOverride{};
|
||||||
|
NoMalfunctionOverrideState m_noMalfunctionOverride{};
|
||||||
|
|
||||||
|
|
||||||
std::mutex m_mtxEntityList;
|
std::mutex m_mtxEntityList;
|
||||||
|
|
|
||||||
|
|
@ -123,11 +123,13 @@ void CFramework::RenderMenu()
|
||||||
ImGui::Checkbox("无限耐力", &g.g_InfStamina);
|
ImGui::Checkbox("无限耐力", &g.g_InfStamina);
|
||||||
ImGui::Checkbox("无跌落伤害", &g.g_NoFallDamage);
|
ImGui::Checkbox("无跌落伤害", &g.g_NoFallDamage);
|
||||||
ImGui::Checkbox("无摇摆", &g.g_NoSway);
|
ImGui::Checkbox("无摇摆", &g.g_NoSway);
|
||||||
|
ImGui::Checkbox("无后座(内存)", &g.g_NoRecoil);
|
||||||
|
ImGui::Checkbox("无故障/卡弹", &g.g_NoMalfunction);
|
||||||
|
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::TextDisabled("仅写入 dump 已确认的对象字段");
|
ImGui::TextDisabled("只写入 dump 已确认的对象字段");
|
||||||
ImGui::TextDisabled("后座 / 故障:等待下一轮类布局确认");
|
ImGui::TextDisabled("弹道追踪:暂不写入,等待 runtime 验证");
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
ImGui::BeginChild("##C021", ImVec2(ImGui::GetContentRegionAvail()), true);
|
ImGui::BeginChild("##C021", ImVec2(ImGui::GetContentRegionAvail()), true);
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,20 @@ void CPlayer::UpdateHealth()
|
||||||
|
|
||||||
void CPlayer::UpdateBone()
|
void CPlayer::UpdateBone()
|
||||||
{
|
{
|
||||||
|
// Refresh the direct PlayerBody -> PlayerBones link before reading the selected aim bone.
|
||||||
|
// The list thread is intentionally slow, while animation/weapon objects can be replaced sooner.
|
||||||
|
if (m_address)
|
||||||
|
{
|
||||||
|
uintptr_t playerBody = 0;
|
||||||
|
uintptr_t playerBones = 0;
|
||||||
|
if (m.TryRead(m_address + offset::Player::pPlayerBody, playerBody) && playerBody &&
|
||||||
|
m.TryRead(playerBody + offset::PlayerBody::PlayerBones, playerBones) && playerBones)
|
||||||
|
{
|
||||||
|
m_pPlayerBody = playerBody;
|
||||||
|
m_pPlayerBones = playerBones;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_vecHeadOrigin = GetBonePosition(BONE_HEAD);
|
m_vecHeadOrigin = GetBonePosition(BONE_HEAD);
|
||||||
m_vecNeckOrigin = GetBonePosition(BONE_NECK);
|
m_vecNeckOrigin = GetBonePosition(BONE_NECK);
|
||||||
m_vecBoneList.clear();
|
m_vecBoneList.clear();
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ namespace offset
|
||||||
{
|
{
|
||||||
constexpr auto Breath = 0x30;
|
constexpr auto Breath = 0x30;
|
||||||
constexpr auto MotionReact = 0x40; // MotionEffector
|
constexpr auto MotionReact = 0x40; // MotionEffector
|
||||||
|
constexpr auto ShotEffector = 0x50; // ShotEffector / Shootingg
|
||||||
constexpr auto isAiming = 0x1C5;
|
constexpr auto isAiming = 0x1C5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,6 +113,41 @@ namespace offset
|
||||||
constexpr auto SwayFactors = 0x94; // UnityEngine.Vector3
|
constexpr auto SwayFactors = 0x94; // UnityEngine.Vector3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -.ShotEffector
|
||||||
|
namespace ShotEffector
|
||||||
|
{
|
||||||
|
constexpr auto MainWeaponInHands = 0x38; // EFT.InventoryLogic.Weapon
|
||||||
|
}
|
||||||
|
|
||||||
|
// EFT.InventoryLogic.Weapon
|
||||||
|
namespace Weapon
|
||||||
|
{
|
||||||
|
constexpr auto Template = 0x40; // CompoundItem.Template
|
||||||
|
constexpr auto MalfState = 0xF0; // WeaponMalfunctionStateClass
|
||||||
|
}
|
||||||
|
|
||||||
|
// EFT.InventoryLogic.WeaponTemplate
|
||||||
|
namespace WeaponTemplate
|
||||||
|
{
|
||||||
|
constexpr auto WeaponRecoilSettings = 0x180; // WeaponRecoil
|
||||||
|
constexpr auto AllowJam = 0x2F0;
|
||||||
|
constexpr auto AllowFeed = 0x2F1;
|
||||||
|
constexpr auto AllowMisfire = 0x2F2;
|
||||||
|
constexpr auto AllowSlide = 0x2F3;
|
||||||
|
constexpr auto BaseMalfunctionChance = 0x2F4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -.WeaponRecoil / -.Weapon.WeaponMalfunctionStateClass
|
||||||
|
namespace WeaponRecoil
|
||||||
|
{
|
||||||
|
constexpr auto Enable = 0x18;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace WeaponMalfunctionState
|
||||||
|
{
|
||||||
|
constexpr auto State = 0x6C;
|
||||||
|
}
|
||||||
|
|
||||||
// -.GClass774 (stamina/oxygen state)
|
// -.GClass774 (stamina/oxygen state)
|
||||||
namespace PhysicalState
|
namespace PhysicalState
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,11 @@ struct Globals
|
||||||
float g_ESP_MaxItemDistance = 50.f;
|
float g_ESP_MaxItemDistance = 50.f;
|
||||||
|
|
||||||
// Misc (仅使用 dump 已确认的对象字段)
|
// Misc (仅使用 dump 已确认的对象字段)
|
||||||
bool g_InfStamina = false;
|
bool g_InfStamina = false;
|
||||||
bool g_NoFallDamage = false;
|
bool g_NoFallDamage = false;
|
||||||
bool g_NoSway = false;
|
bool g_NoSway = false;
|
||||||
|
bool g_NoRecoil = false;
|
||||||
|
bool g_NoMalfunction = false;
|
||||||
|
|
||||||
|
|
||||||
// Aim (自瞄)
|
// Aim (自瞄)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue