329 lines
12 KiB
C++
329 lines
12 KiB
C++
#pragma once
|
|
#include <algorithm>
|
|
#include "../Framework/ImGui/imgui.h"
|
|
#include "../Framework/ImGui/imgui_impl_win32.h"
|
|
#include "../Framework/ImGui/imgui_impl_dx11.h"
|
|
#include "../Framework/ImGui/Custom.h"
|
|
#include "../Framework/ImGui/Fonts/fa.h"
|
|
#include "../Framework/ImGui/Fonts/RobotoRegular.h"
|
|
#include "../Framework/ImGui/Fonts/IconsFontAwesome6.h"
|
|
#include "SDK/CPlayer/CPlayer.h"
|
|
#include "SDK/CExfil/CExfil.h"
|
|
#include "SDK/CItem/CItem.h"
|
|
#include "SDK/CContainer/CContainer.h"
|
|
#include "SnapshotHealth.h"
|
|
#include <mutex>
|
|
#include <memory>
|
|
#include <atomic>
|
|
#include <cstdint>
|
|
#include <utility>
|
|
|
|
struct GrenadeSnapshot
|
|
{
|
|
uintptr_t address{ 0 };
|
|
Vector3 position{};
|
|
};
|
|
|
|
struct DynamicWorldSnapshot
|
|
{
|
|
uint64_t generation{ 0 };
|
|
std::chrono::steady_clock::time_point capturedAt{};
|
|
uint64_t refreshAttempts{ 0 };
|
|
uint64_t consecutiveRefreshFailures{ 0 };
|
|
GameRefreshStatus refreshStatus{ GameRefreshStatus::Waiting };
|
|
bool initialized{ false };
|
|
bool inRaid{ false };
|
|
bool cameraValid{ false };
|
|
uintptr_t moduleBase{ 0 };
|
|
uintptr_t gameObjectManager{ 0 };
|
|
uintptr_t activeNodeList{ 0 };
|
|
uintptr_t lastActiveNode{ 0 };
|
|
uintptr_t gameWorld{ 0 };
|
|
uintptr_t localGameWorld{ 0 };
|
|
uintptr_t fpsCamera{ 0 };
|
|
Matrix viewMatrix{};
|
|
CPlayer local{};
|
|
std::vector<CPlayer> players{};
|
|
std::vector<GrenadeSnapshot> grenades{};
|
|
};
|
|
|
|
|
|
struct WorkerConfigSnapshot
|
|
{
|
|
bool needDynamic{ false };
|
|
bool wantRemotePlayers{ false };
|
|
bool wantHealth{ false };
|
|
bool wantSkeleton{ false };
|
|
bool wantGrenades{ false };
|
|
bool wantExfils{ false };
|
|
bool wantItems{ false };
|
|
bool wantContainers{ false };
|
|
float remoteMaxDistance{ 0.f };
|
|
};
|
|
|
|
struct StaticWorldSnapshot
|
|
{
|
|
uint64_t generation{ 0 };
|
|
std::vector<CExfil> exfils{};
|
|
std::vector<CItem> items{};
|
|
std::vector<CContainer> containers{};
|
|
};
|
|
|
|
class CFramework
|
|
{
|
|
public:
|
|
ImFont* icon{ nullptr };
|
|
|
|
void UpdateList();
|
|
void UpdateStaticList();
|
|
void RenderInfo();
|
|
void RenderMenu();
|
|
void RenderESP();
|
|
void AimAll();
|
|
void UpdateFeatures();
|
|
void ResetFeatureOverrides();
|
|
void UpdateWorkerConfigFromUi();
|
|
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 };
|
|
};
|
|
|
|
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 UpdateFallDamageOverride();
|
|
void UpdateSwayOverride();
|
|
void ResetStaminaOverride();
|
|
void ResetFallDamageOverride();
|
|
void ResetSwayOverride();
|
|
|
|
std::unique_ptr<CGame> tarkov{ std::make_unique<CGame>() };
|
|
// Render/features keep this as a render-thread-only scratch object. The list thread never mutates it.
|
|
CPlayer local;
|
|
|
|
std::shared_ptr<const DynamicWorldSnapshot> m_dynamicSnapshot{ std::make_shared<DynamicWorldSnapshot>() };
|
|
std::shared_ptr<const StaticWorldSnapshot> m_staticSnapshot{ std::make_shared<StaticWorldSnapshot>() };
|
|
std::atomic_uint64_t m_dynamicGeneration{ 0 };
|
|
std::atomic_uint64_t m_staticGeneration{ 0 };
|
|
mutable std::mutex m_workerConfigMutex{};
|
|
WorkerConfigSnapshot m_workerConfig{};
|
|
|
|
WorkerConfigSnapshot GetWorkerConfig() const
|
|
{
|
|
std::scoped_lock lock(m_workerConfigMutex);
|
|
return m_workerConfig;
|
|
}
|
|
|
|
std::shared_ptr<const DynamicWorldSnapshot> GetDynamicSnapshot() const
|
|
{
|
|
return std::atomic_load(&m_dynamicSnapshot);
|
|
}
|
|
|
|
std::shared_ptr<const StaticWorldSnapshot> GetStaticSnapshot() const
|
|
{
|
|
return std::atomic_load(&m_staticSnapshot);
|
|
}
|
|
|
|
void PublishDynamicSnapshot(std::shared_ptr<const DynamicWorldSnapshot> snapshot)
|
|
{
|
|
std::atomic_store(&m_dynamicSnapshot, std::move(snapshot));
|
|
}
|
|
|
|
void PublishStaticSnapshot(std::shared_ptr<const StaticWorldSnapshot> snapshot)
|
|
{
|
|
std::atomic_store(&m_staticSnapshot, std::move(snapshot));
|
|
}
|
|
|
|
StaminaOverrideState m_staminaOverride{};
|
|
FallDamageOverrideState m_fallDamageOverride{};
|
|
SwayOverrideState m_swayOverride{};
|
|
NoRecoilOverrideState m_noRecoilOverride{};
|
|
NoMalfunctionOverrideState m_noMalfunctionOverride{};
|
|
|
|
|
|
// Compatibility accessors for menu/legacy call sites. New render/aim code consumes immutable snapshots directly.
|
|
std::vector<CPlayer> GetEntityList() const
|
|
{
|
|
auto snapshot = GetDynamicSnapshot();
|
|
return snapshot && IsSnapshotFresh(snapshot->capturedAt) ? snapshot->players : std::vector<CPlayer>{};
|
|
}
|
|
std::vector<CExfil> GetExfilList() const
|
|
{
|
|
auto snapshot = GetStaticSnapshot();
|
|
return snapshot ? snapshot->exfils : std::vector<CExfil>{};
|
|
}
|
|
std::vector<CItem> GetItemList() const
|
|
{
|
|
auto snapshot = GetStaticSnapshot();
|
|
return snapshot ? snapshot->items : std::vector<CItem>{};
|
|
}
|
|
std::vector<CContainer> GetContainerList() const
|
|
{
|
|
auto snapshot = GetStaticSnapshot();
|
|
return snapshot ? snapshot->containers : std::vector<CContainer>{};
|
|
}
|
|
|
|
// Colors
|
|
ImColor Col_ESP_PMC = { 1.f, 0.f, 0.85f, 1.f };
|
|
ImColor Col_ESP_Team = { 0.f, 1.f, 0.f, 0.f };
|
|
ImColor Col_ESP_Scav = { 1.f, 1.f, 1.f, 1.f };
|
|
ImColor Col_ESP_pScav = { 1.f, 1.f, 0.f, 1.f };
|
|
ImColor Col_ESP_SpecialScav = { 1.f, 0.5f, 0.f, 1.f };
|
|
ImColor Col_ESP_Boss = { 1.f, 0.f, 0.f, 1.f };
|
|
ImColor Col_ESP_Filled = { 0.f, 0.f, 0.f, 0.25f };
|
|
|
|
ImColor Col_ESP_ExfilOpen = { 0.f, 1.f, 0.f, 0.5f };
|
|
ImColor Col_ESP_ExfilClose = { 1.f, 0.3f, 0.f, 0.5f };
|
|
ImColor Col_ESP_ExfilPending = { 1.f, 1.f, 0.f, 0.9f };
|
|
ImColor Col_ESP_ExfilUnknown = { 1.f, 0.65f, 0.f, 0.9f };
|
|
|
|
ImColor Col_ESP_ItemQuest = { 1.f, 1.f, 0.f, 0.9f };
|
|
ImColor Col_ESP_ItemCommon = { 1.f, 1.f, 1.f, 0.9f };
|
|
ImColor Col_ESP_ItemRare = { 0.38f, 0.43f, 1.f, 0.9f };
|
|
ImColor Col_ESP_ItemSuperRare = { 1.f, 0.29f, 0.36f, 0.9f };
|
|
ImColor Col_ESP_Container = { 1.f, 0.2f, 0.09f, 1.f };
|
|
|
|
ImColor Col_ESP_Corpse = { 1.f, 1.f, 1.f, 0.9f };
|
|
ImColor Col_ESP_RareItem = { 1.f, 0.f, 0.f, 0.9f };
|
|
|
|
ImColor CrosshairColor = { 0.f, 1.f, 0.f, 1.f };
|
|
|
|
ImColor AimFovColor = { 1.f, 1.f, 1.f, 0.35f };
|
|
ImColor AimTargetColor = { 1.f, 0.f, 0.f, 0.85f };
|
|
|
|
ImColor TEXT_COLOR_DEFAULT{ 1.f, 1.f, 1.f, 1.f };
|
|
ImColor TEXT_COLOR_ATTENTION{ 1.f, 1.f, 0.f, 1.f };
|
|
ImColor TEXT_COLOR_WARNING{ 1.f, 0.f, 0.f, 1.f };
|
|
|
|
void GetESPInfo(const int& SpawnType, std::string& vOutStr, ImColor& vOutColor);
|
|
|
|
// Aim.cpp
|
|
bool IsValidAimTarget(const CPlayer& player);
|
|
Vector3 GetAimBone(const CPlayer* pEntity);
|
|
void AimMouse(const Vector2& target, const Vector2& center);
|
|
void AimMemory(const Vector3& target, const Vector3& localPos, uintptr_t localAddress);
|
|
void ScanRotationOffset(); // 2阶段扫描: Player->MC 与 MC->Rotation 偏移
|
|
|
|
// Runtime feature backup state is declared above.
|
|
|
|
|
|
// 旋转偏移扫描器状态
|
|
int m_scanPhase = 0; // 0 = 待机/Step1, 1 = 等待转动鼠标后 Step2
|
|
char m_scanResult[192]{ 0 };
|
|
|
|
// 自瞄诊断计数(菜单 Aim Status 显示)
|
|
int m_diagTotal = 0; // 遍历到的实体数
|
|
int m_diagHealth = 0; // 被健康检查判死跳过的数
|
|
int m_diagSkipped = 0; // 其他原因跳过的数
|
|
uintptr_t m_diagBestAddr = 0; // 最近一帧锁定的目标地址
|
|
float m_diagBestDist = 0.f;// 最近一帧目标到屏幕中心的距离
|
|
|
|
// 鼠标自瞄的亚像素累积,避免小误差因 LONG 截断而永远到不了目标。
|
|
uintptr_t m_aimLastTarget = 0;
|
|
float m_aimResidualX = 0.f;
|
|
float m_aimResidualY = 0.f;
|
|
|
|
void DrawLine(ImVec2 a, ImVec2 b, ImColor color, float width)
|
|
{
|
|
ImGui::GetBackgroundDrawList()->AddLine(ImVec2((int)a.x, (int)a.y), ImVec2((int)b.x, (int)b.y), color, width);
|
|
}
|
|
void RectFilled(float x0, float y0, float x1, float y1, ImColor color, float rounding, int rounding_corners_flags)
|
|
{
|
|
ImGui::GetBackgroundDrawList()->AddRectFilled(ImVec2(x0, y0), ImVec2(x1, y1), color, rounding, rounding_corners_flags);
|
|
}
|
|
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((std::min)(510 * (v_max - value) / 100, 255), (std::min)(510 * value / 100, 255), 25, 255), 0.0f, 0);
|
|
}
|
|
void Circle(ImVec2 pos, float fov_size, ImColor color)
|
|
{
|
|
ImGui::GetBackgroundDrawList()->AddCircle(pos, fov_size, color, 100, 0);
|
|
}
|
|
void String(ImVec2 pos, ImColor color, const char* text)
|
|
{
|
|
ImGui::GetBackgroundDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize(), pos, color, text, text + strlen(text), 1024, 0);
|
|
}
|
|
void StringEx(ImVec2 pos, ImColor color, float font_size, const char* text)
|
|
{
|
|
ImGui::GetBackgroundDrawList()->AddText(ImGui::GetFont(), font_size, ImVec2(pos.x + 1.f, pos.y + 1.f), ImColor(0.f, 0.f, 0.f, 1.f), text, text + strlen(text), 1024, 0);
|
|
ImGui::GetBackgroundDrawList()->AddText(ImGui::GetFont(), font_size, pos, color, text, text + strlen(text), 1024, 0);
|
|
}
|
|
|
|
// Render.cpp
|
|
ImVec2 ToImVec2(const ImVec2& value); // Convert to int
|
|
ImVec2 ToImVec2(const Vector2& value);
|
|
ImColor WithAlpha(const ImColor& color, const float& alpha);
|
|
float GetHueFromTime(float speed = 5.0f);
|
|
ImColor GenerateRainbow(float speed = 5.0f);
|
|
void DrawLine(const Vector2 p1, const Vector2 p2, ImColor color, float thickness = 1.f);
|
|
void DrawBox(int right, int left, int top, int bottom, ImColor color, float thickness = 1.f);
|
|
void DrawCircle(const Vector2 pos, float size, ImColor color);
|
|
void DrawCircle(const Vector2 pos, float size, ImColor color, float alpha);
|
|
void DrawCircleFilled(const Vector2 pos, float size, ImColor color, float alpha);
|
|
void RectFilled(int x0, int y0, int x1, int y1, ImColor color);
|
|
void RectFilled(int x0, int y0, int x1, int y1, ImColor color, float alpha);
|
|
void HealthBar(int x, int y, int w, int h, int value, int v_max, ImColor shadow, float global_alpha);
|
|
void String(const Vector2 pos, ImColor color, float alpha, const char* text);
|
|
void StringEx(Vector2 pos, ImColor shadow_color, float global_alpht, float font_size, const char* text);
|
|
};
|