fix: restore esp transform fallback
This commit is contained in:
parent
52454e23ea
commit
fcb1f599a4
|
|
@ -258,7 +258,7 @@ Vector3 CFramework::GetAimBone(CPlayer* pEntity)
|
||||||
switch (g.g_AimBone)
|
switch (g.g_AimBone)
|
||||||
{
|
{
|
||||||
case 1: return pEntity->m_vecNeckOrigin;
|
case 1: return pEntity->m_vecNeckOrigin;
|
||||||
case 2: return pEntity->m_vecOrigin;
|
case 2: return pEntity->GetBonePosition(BONE_SPINE_3); // Ribcage
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
default:
|
||||||
return pEntity->m_vecHeadOrigin;
|
return pEntity->m_vecHeadOrigin;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,42 @@
|
||||||
|
|
||||||
std::vector<int> PlayerBoneList{ BONE_PELVIS, BONE_LEFT_THIGH, BONE_LEFT_FOOT, BONE_RIGHT_THIGH, BONE_RIGHT_FOOT, BONE_LEFT_FOREARM, BONE_LEFT_PALM, BONE_RIGHT_FOREARM, BONE_RIGHT_PALM };
|
std::vector<int> PlayerBoneList{ BONE_PELVIS, BONE_LEFT_THIGH, BONE_LEFT_FOOT, BONE_RIGHT_THIGH, BONE_RIGHT_FOOT, BONE_LEFT_FOREARM, BONE_LEFT_PALM, BONE_RIGHT_FOREARM, BONE_RIGHT_PALM };
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
uintptr_t ReadBifacialOriginal(uintptr_t playerBones, uintptr_t fieldOffset)
|
||||||
|
{
|
||||||
|
const uintptr_t bifacialTransform = m.Read<uintptr_t>(playerBones + fieldOffset);
|
||||||
|
return bifacialTransform
|
||||||
|
? m.Read<uintptr_t>(bifacialTransform + offset::BifacialTransform::Original)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t ReadTransformArrayElement(uintptr_t array, int index)
|
||||||
|
{
|
||||||
|
if (!array || index < 0 || index > 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m.Read<uintptr_t>(array + offset::PlayerBones::TransformArrayData + static_cast<uintptr_t>(index) * sizeof(uintptr_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 ReadTransformPositionWithFallback(uintptr_t transform)
|
||||||
|
{
|
||||||
|
if (!transform)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
Vector3 position = GetTransformPosition(transform);
|
||||||
|
if (!Vec3_Empty(position))
|
||||||
|
return position;
|
||||||
|
|
||||||
|
// Keep compatibility with the previous Transform wrapper layout.
|
||||||
|
uintptr_t wrappedTransform = m.Read<uintptr_t>(transform + 0x10);
|
||||||
|
if (!wrappedTransform || wrappedTransform == transform)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return GetTransformPosition(wrappedTransform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CPlayer::Update()
|
bool CPlayer::Update()
|
||||||
{
|
{
|
||||||
m_vecOrigin = GetBonePosition(BONE_ORIGIN);
|
m_vecOrigin = GetBonePosition(BONE_ORIGIN);
|
||||||
|
|
@ -15,6 +51,8 @@ void CPlayer::UpdateStatic()
|
||||||
m_pProfile = 0;
|
m_pProfile = 0;
|
||||||
m_pInfo = 0;
|
m_pInfo = 0;
|
||||||
m_pSetting = 0;
|
m_pSetting = 0;
|
||||||
|
m_pPlayerBody = 0;
|
||||||
|
m_pPlayerBones = 0;
|
||||||
m_pWeaponAnimation = 0;
|
m_pWeaponAnimation = 0;
|
||||||
m_iSpawnType = 0;
|
m_iSpawnType = 0;
|
||||||
m_pBoneArray = {};
|
m_pBoneArray = {};
|
||||||
|
|
@ -27,6 +65,10 @@ void CPlayer::UpdateStatic()
|
||||||
m_pHealthController = m.Read<uintptr_t>(m_address + offset::Player::pHealthController);
|
m_pHealthController = m.Read<uintptr_t>(m_address + offset::Player::pHealthController);
|
||||||
m_pWeaponAnimation = m.Read<uintptr_t>(m_address + offset::Player::pWeaponAnimation);
|
m_pWeaponAnimation = m.Read<uintptr_t>(m_address + offset::Player::pWeaponAnimation);
|
||||||
|
|
||||||
|
m_pPlayerBody = m.Read<uintptr_t>(m_address + offset::Player::pPlayerBody);
|
||||||
|
if (m_pPlayerBody)
|
||||||
|
m_pPlayerBones = m.Read<uintptr_t>(m_pPlayerBody + offset::PlayerBody::PlayerBones);
|
||||||
|
|
||||||
m_pProfile = m.Read<uintptr_t>(m_address + offset::Player::pProfile);
|
m_pProfile = m.Read<uintptr_t>(m_address + offset::Player::pProfile);
|
||||||
if (m_pProfile)
|
if (m_pProfile)
|
||||||
{
|
{
|
||||||
|
|
@ -41,7 +83,7 @@ void CPlayer::UpdateStatic()
|
||||||
|
|
||||||
// PlayerBody +0x30 = SkeletonRootJoint; Skeleton +0x30 = values List;
|
// PlayerBody +0x30 = SkeletonRootJoint; Skeleton +0x30 = values List;
|
||||||
// List +0x10 = Transform[] data pointer, as described by dump.txt.
|
// List +0x10 = Transform[] data pointer, as described by dump.txt.
|
||||||
const uintptr_t boneMatrix = m.ReadChain(m_address, { offset::Player::pPlayerBody, 0x30, 0x30, 0x10 });
|
const uintptr_t boneMatrix = m.ReadChain(m_address, { offset::Player::pPlayerBody, offset::PlayerBody::SkeletonRootJoint, 0x30, 0x10 });
|
||||||
if (boneMatrix)
|
if (boneMatrix)
|
||||||
m_pBoneArray = m.Read<CBoneArray>(boneMatrix + 0x20);
|
m_pBoneArray = m.Read<CBoneArray>(boneMatrix + 0x20);
|
||||||
}
|
}
|
||||||
|
|
@ -121,13 +163,61 @@ Vector3 CPlayer::GetBonePosition(const int BoneId)
|
||||||
if (BoneId < 0 || BoneId >= kBoneCount)
|
if (BoneId < 0 || BoneId >= kBoneCount)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const uintptr_t bone = m_pBoneArray.address[BoneId];
|
uintptr_t transform = 0;
|
||||||
if (!bone)
|
if (m_pPlayerBones)
|
||||||
return {};
|
{
|
||||||
|
switch (BoneId)
|
||||||
|
{
|
||||||
|
case BONE_ORIGIN:
|
||||||
|
transform = m.Read<uintptr_t>(m_pPlayerBones + offset::PlayerBones::RootJoint);
|
||||||
|
break;
|
||||||
|
case BONE_NECK:
|
||||||
|
transform = m.Read<uintptr_t>(m_pPlayerBones + offset::PlayerBones::Neck);
|
||||||
|
break;
|
||||||
|
case BONE_HEAD:
|
||||||
|
transform = ReadBifacialOriginal(m_pPlayerBones, offset::PlayerBones::Head);
|
||||||
|
break;
|
||||||
|
case BONE_PELVIS:
|
||||||
|
transform = ReadBifacialOriginal(m_pPlayerBones, offset::PlayerBones::Pelvis);
|
||||||
|
break;
|
||||||
|
case BONE_LEFT_THIGH:
|
||||||
|
transform = ReadBifacialOriginal(m_pPlayerBones, offset::PlayerBones::LeftThigh);
|
||||||
|
break;
|
||||||
|
case BONE_RIGHT_THIGH:
|
||||||
|
transform = ReadBifacialOriginal(m_pPlayerBones, offset::PlayerBones::RightThigh);
|
||||||
|
break;
|
||||||
|
case BONE_LEFT_FOREARM:
|
||||||
|
transform = ReadTransformArrayElement(m.Read<uintptr_t>(m_pPlayerBones + offset::PlayerBones::Forearms), 0);
|
||||||
|
break;
|
||||||
|
case BONE_RIGHT_FOREARM:
|
||||||
|
transform = ReadTransformArrayElement(m.Read<uintptr_t>(m_pPlayerBones + offset::PlayerBones::Forearms), 1);
|
||||||
|
break;
|
||||||
|
case BONE_LEFT_PALM:
|
||||||
|
transform = m.Read<uintptr_t>(m_pPlayerBones + offset::PlayerBones::LeftPalm);
|
||||||
|
break;
|
||||||
|
case BONE_RIGHT_PALM:
|
||||||
|
transform = m.Read<uintptr_t>(m_pPlayerBones + offset::PlayerBones::RightPalm);
|
||||||
|
break;
|
||||||
|
case BONE_SPINE_3:
|
||||||
|
transform = ReadBifacialOriginal(m_pPlayerBones, offset::PlayerBones::Ribcage);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t transform = m.Read<uintptr_t>(bone + 0x10);
|
// Feet and any unmapped legacy IDs fall back to the current Skeleton.values array.
|
||||||
|
// The array elements are Transform references; do not dereference +0x10 here.
|
||||||
if (!transform)
|
if (!transform)
|
||||||
|
transform = m_pBoneArray.address[BoneId];
|
||||||
|
|
||||||
|
const Vector3 position = ReadTransformPositionWithFallback(transform);
|
||||||
|
if (!Vec3_Empty(position))
|
||||||
|
return position;
|
||||||
|
|
||||||
|
const uintptr_t legacyTransform = m_pBoneArray.address[BoneId];
|
||||||
|
if (!legacyTransform || legacyTransform == transform)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return GetTransformPosition(transform);
|
return ReadTransformPositionWithFallback(legacyTransform);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ public:
|
||||||
uintptr_t m_pProfile{ 0 };
|
uintptr_t m_pProfile{ 0 };
|
||||||
uintptr_t m_pInfo{ 0 };
|
uintptr_t m_pInfo{ 0 };
|
||||||
uintptr_t m_pSetting{ 0 };
|
uintptr_t m_pSetting{ 0 };
|
||||||
|
uintptr_t m_pPlayerBody{ 0 };
|
||||||
|
uintptr_t m_pPlayerBones{ 0 };
|
||||||
uintptr_t m_pHealthController{ 0 };
|
uintptr_t m_pHealthController{ 0 };
|
||||||
uintptr_t m_pWeaponAnimation{ 0 };
|
uintptr_t m_pWeaponAnimation{ 0 };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,35 @@ namespace offset
|
||||||
constexpr auto pHealthController = 0x660; // _healthController
|
constexpr auto pHealthController = 0x660; // _healthController
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EFT.PlayerBody / EFT.PlayerBones (dump.txt)
|
||||||
|
namespace PlayerBody
|
||||||
|
{
|
||||||
|
constexpr auto PlayerBones = 0x28;
|
||||||
|
constexpr auto SkeletonRootJoint = 0x30;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace PlayerBones
|
||||||
|
{
|
||||||
|
constexpr auto Neck = 0x48;
|
||||||
|
constexpr auto Forearms = 0x70;
|
||||||
|
constexpr auto LeftPalm = 0x78;
|
||||||
|
constexpr auto RightPalm = 0x80;
|
||||||
|
constexpr auto RootJoint = 0x90;
|
||||||
|
constexpr auto Ribcage = 0x110;
|
||||||
|
constexpr auto Head = 0x118;
|
||||||
|
constexpr auto Body = 0x140;
|
||||||
|
constexpr auto Pelvis = 0x150;
|
||||||
|
constexpr auto LeftThigh = 0x158;
|
||||||
|
constexpr auto RightThigh = 0x160;
|
||||||
|
constexpr auto Spine3 = 0x168;
|
||||||
|
constexpr auto TransformArrayData = 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace BifacialTransform
|
||||||
|
{
|
||||||
|
constexpr auto Original = 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
// EFT.MovementContext (dump.txt: EFT.MovementContext)
|
// EFT.MovementContext (dump.txt: EFT.MovementContext)
|
||||||
namespace MovementContext
|
namespace MovementContext
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ struct Globals
|
||||||
float g_AimSens = 1.0f; // Mouse 模式灵敏度倍率
|
float g_AimSens = 1.0f; // Mouse 模式灵敏度倍率
|
||||||
float g_AimMaxSpeed = 80.f; // Mouse 模式单帧最大移动 [px]
|
float g_AimMaxSpeed = 80.f; // Mouse 模式单帧最大移动 [px]
|
||||||
float g_AimMaxDist = 500.f; // 最大锁定距离 [m]
|
float g_AimMaxDist = 500.f; // 最大锁定距离 [m]
|
||||||
int g_AimBone = 0; // 0=Head 1=Neck 2=Body
|
int g_AimBone = 0; // 0=Head 1=Neck 2=Body (PlayerBones direct transforms)
|
||||||
bool g_AimTargetPMC = true;
|
bool g_AimTargetPMC = true;
|
||||||
bool g_AimTargetScav = true;
|
bool g_AimTargetScav = true;
|
||||||
bool g_AimTargetBoss = true;
|
bool g_AimTargetBoss = true;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ bool Overlay::CreateOverlay()
|
||||||
// Create Overlay
|
// Create Overlay
|
||||||
wc = { sizeof(WNDCLASSEXA), 0, WndProc, 0, 0, NULL, NULL, NULL, NULL, Title, Class, NULL};
|
wc = { sizeof(WNDCLASSEXA), 0, WndProc, 0, 0, NULL, NULL, NULL, NULL, Title, Class, NULL};
|
||||||
RegisterClassExA(&wc);
|
RegisterClassExA(&wc);
|
||||||
Hwnd = CreateWindowExA(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW | WS_EX_TOPMOST, wc.lpszClassName, wc.lpszMenuName, WS_POPUP | WS_VISIBLE, g.GamePoint.x, g.GamePoint.y, g.GameRect.right, g.GameRect.bottom, NULL, NULL, wc.hInstance, NULL);
|
Hwnd = CreateWindowExA(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_NOACTIVATE, wc.lpszClassName, wc.lpszMenuName, WS_POPUP | WS_VISIBLE, g.GamePoint.x, g.GamePoint.y, g.GameRect.right, g.GameRect.bottom, NULL, NULL, wc.hInstance, NULL);
|
||||||
SetLayeredWindowAttributes(Hwnd, RGB(0, 0, 0), 255, LWA_ALPHA);
|
SetLayeredWindowAttributes(Hwnd, RGB(0, 0, 0), 255, LWA_ALPHA);
|
||||||
MARGINS margin = { -1 };
|
MARGINS margin = { -1 };
|
||||||
DwmExtendFrameIntoClientArea(Hwnd, &margin);
|
DwmExtendFrameIntoClientArea(Hwnd, &margin);
|
||||||
|
|
@ -117,6 +117,12 @@ extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg
|
||||||
|
|
||||||
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
// ESP overlay must never activate or consume the game's mouse input.
|
||||||
|
if (!g.ShowMenu && msg == WM_NCHITTEST)
|
||||||
|
return HTTRANSPARENT;
|
||||||
|
if (!g.ShowMenu && msg == WM_MOUSEACTIVATE)
|
||||||
|
return MA_NOACTIVATE;
|
||||||
|
|
||||||
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
|
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ private:
|
||||||
|
|
||||||
// Window LONG
|
// Window LONG
|
||||||
LONG MenuStyle = WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
|
LONG MenuStyle = WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
|
||||||
LONG ESPStyle = WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
|
LONG ESPStyle = WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_NOACTIVATE;
|
||||||
|
|
||||||
bool CreateOverlay();
|
bool CreateOverlay();
|
||||||
HWND GetTargetWindow(const std::string processName); // 実行ファイル名からウィンドウハンドルを取得する
|
HWND GetTargetWindow(const std::string processName); // 実行ファイル名からウィンドウハンドルを取得する
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ bool Overlay::InitOverlay(const std::string targetName, int InitMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
GetClassNameA(TargetHwnd, TargetClass, sizeof(TargetClass));
|
GetClassNameA(TargetHwnd, TargetClass, sizeof(TargetClass));
|
||||||
|
g.GameHwnd = TargetHwnd;
|
||||||
|
|
||||||
return CreateOverlay();
|
return CreateOverlay();
|
||||||
}
|
}
|
||||||
|
|
@ -68,9 +69,9 @@ void Overlay::OverlayManager()
|
||||||
LONG TmpLong = GetWindowLong(Hwnd, GWL_EXSTYLE);
|
LONG TmpLong = GetWindowLong(Hwnd, GWL_EXSTYLE);
|
||||||
|
|
||||||
if (g.ShowMenu && MenuStyle != TmpLong)
|
if (g.ShowMenu && MenuStyle != TmpLong)
|
||||||
SetWindowLong(Hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST);
|
SetWindowLong(Hwnd, GWL_EXSTYLE, MenuStyle);
|
||||||
else if (!g.ShowMenu && ESPStyle != TmpLong)
|
else if (!g.ShowMenu && ESPStyle != TmpLong)
|
||||||
SetWindowLong(Hwnd, GWL_EXSTYLE, WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST);
|
SetWindowLong(Hwnd, GWL_EXSTYLE, ESPStyle);
|
||||||
|
|
||||||
// MenuToggle
|
// MenuToggle
|
||||||
if (GetKeyState(g.g_MenuKey) && !g.ShowMenu) {
|
if (GetKeyState(g.g_MenuKey) && !g.ShowMenu) {
|
||||||
|
|
@ -97,7 +98,7 @@ void Overlay::OverlayManager()
|
||||||
{
|
{
|
||||||
g.GameRect = TmpRect;
|
g.GameRect = TmpRect;
|
||||||
g.GamePoint = TmpPoint;
|
g.GamePoint = TmpPoint;
|
||||||
SetWindowPos(Hwnd, nullptr, TmpPoint.x, TmpPoint.y, g.GameRect.right, g.GameRect.bottom, SWP_NOREDRAW);
|
SetWindowPos(Hwnd, nullptr, TmpPoint.x, TmpPoint.y, g.GameRect.right, g.GameRect.bottom, SWP_NOREDRAW | SWP_NOACTIVATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
{
|
{
|
||||||
auto overlay = std::make_unique<Overlay>();
|
auto overlay = std::make_unique<Overlay>();
|
||||||
|
|
||||||
// Fix DPI Scale
|
// 使用每监视器 DPI,保证 overlay、GameRect 和 W2S 使用同一套物理像素坐标。
|
||||||
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
|
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||||
|
|
||||||
// ウィンドウをベースにして初期化を行う
|
// ウィンドウをベースにして初期化を行う
|
||||||
if (!m.AttachProcess("EscapeFromTarkov", InitMode::WINDOW_TITLE)) // 詳細は Memory/Memory.h を参照
|
if (!m.AttachProcess("EscapeFromTarkov", InitMode::WINDOW_TITLE)) // 詳細は Memory/Memory.h を参照
|
||||||
|
|
@ -50,8 +50,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
if (!overlay->InitOverlay("EscapeFromTarkov", InitMode::WINDOW_TITLE)) // MemoryInitModeと同様
|
if (!overlay->InitOverlay("EscapeFromTarkov", InitMode::WINDOW_TITLE)) // MemoryInitModeと同様
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
// 低级输入钩子 (GetAsyncKeyState 检测不到鼠标键的环境用)
|
// 不安装全局 WH_MOUSE_LL 钩子,避免改变游戏原始鼠标输入链路。
|
||||||
InstallInputHook();
|
// 鼠标按键使用 GetAsyncKeyState,F9 可作为触发键兜底。
|
||||||
|
|
||||||
// ImGui io setting
|
// ImGui io setting
|
||||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||||
|
|
@ -92,7 +92,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
|
|
||||||
overlay->OverlayLoop();
|
overlay->OverlayLoop();
|
||||||
overlay->DestroyOverlay();
|
overlay->DestroyOverlay();
|
||||||
RemoveInputHook();
|
|
||||||
m.DetachProcess();
|
m.DetachProcess();
|
||||||
g.process_active = false;
|
g.process_active = false;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue