Вопрос TraceRay External

Пользователь
Пользователь
Статус
Оффлайн
Регистрация
26 Май 2019
Сообщения
204
Реакции
39
Привет. Пытаюсь сделать локальный external софт для личного юза. Сделал ESP и AimBot. Хотел сделать WallCheck, но что-то пошло не так. Проверки через m_bSpottedByMask/m_entitySpottedState не работают. Читал что есть такая штука как TraceRay, но её юзают в Internal читах. Видел что чел вызывал его через шелкод, но не знаю видил-ли это вак или нет.
Сам вопрос: Есть у кого какие-то идеи как можно сделать WallCheck в формате External?
 
есть такой смешной репозиторий:
Пожалуйста, авторизуйтесь для просмотра ссылки.
 
Привет. Пытаюсь сделать локальный external софт для личного юза. Сделал ESP и AimBot. Хотел сделать WallCheck, но что-то пошло не так. Проверки через m_bSpottedByMask/m_entitySpottedState не работают. Читал что есть такая штука как TraceRay, но её юзают в Internal читах. Видел что чел вызывал его через шелкод, но не знаю видил-ли это вак или нет.
Сам вопрос: Есть у кого какие-то идеи как можно сделать WallCheck в формате External?
то что у тебя не работает bSpottedByMask это ненормально

а так разберись почему не работает bSpottedByMask или же юзай парс карт(.vpk) как указали выше
 
есть такой смешной репозиторий:
Пожалуйста, авторизуйтесь для просмотра ссылки.
меня смущает это
1748034572966.png

то что у тебя не работает bSpottedByMask это ненормально

а так разберись почему не работает bSpottedByMask или же юзай парс карт(.vpk) как указали выше
я пастер, но сделал через ChatGPT(plus), так что не засирай

game.cpp:
Expand Collapse Copy
#include "game.hh"
#include "offs.hh"          // ВСЕ актуальные оффсеты хранятся здесь
#include <TlHelp32.h>
#include <thread>
#include <string>
#include <sstream>

/* ───────── helpers ───────── */
static DWORD getPid(const wchar_t* exe)
{
    PROCESSENTRY32W pe{ sizeof pe };
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snap == INVALID_HANDLE_VALUE) return 0;

    for (BOOL ok = Process32FirstW(snap, &pe); ok; ok = Process32NextW(snap, &pe))
        if (!_wcsicmp(pe.szExeFile, exe)) { CloseHandle(snap); return pe.th32ProcessID; }

    CloseHandle(snap);
    return 0;
}

static uintptr_t getModule(DWORD pid, const wchar_t* mod)
{
    MODULEENTRY32W me{ sizeof me };
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
    if (snap == INVALID_HANDLE_VALUE) return 0;

    for (BOOL ok = Module32FirstW(snap, &me); ok; ok = Module32NextW(snap, &me))
        if (!_wcsicmp(me.szModule, mod)) { CloseHandle(snap); return (uintptr_t)me.modBaseAddr; }

    CloseHandle(snap);
    return 0;
}

template<class T>
static bool rpm(HANDLE h, uintptr_t addr, T& out)
{
    return ReadProcessMemory(h, reinterpret_cast<LPCVOID>(addr),
        &out, sizeof(T), nullptr);
}

/* ───────── глобалы, объявлены в game.hh ───────── */
namespace game {
    std::vector<Enemy> enemies;
    float              view[16]{};
    std::atomic_bool   running{ false };
    std::mutex         mtx;
}

/* временный контейнер для первого прохода */
struct Enemy {
    Vec3  pos;
    int   hp;
    bool  visible;
};

struct EnemyTmp {
    Vec3      pos;
    int       hp;
    uintptr_t spottedState;
    uint64_t  lastSeenTick;   // время, когда m_bSpotted = true
};


template<typename T>
std::string ToHexString(T value) {
    std::stringstream ss;
    ss << "0x" << std::hex << value;
    return ss.str();
}

/* ------------------------------------------------------------------
   game::start  /  game::stop
   ------------------------------------------------------------------ */
void game::start()
{
    if (running) return;
    running = true;

    std::thread([] {

        /* ---------- attach к процессу ---------- */
        const DWORD pid = getPid(L"cs2.exe");
        if (!pid) { running = false; return; }

        HANDLE h = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
            FALSE, pid);
        if (!h) { running = false; return; }

        const uintptr_t client = getModule(pid, L"client.dll");
        if (!client) { CloseHandle(h); running = false; return; }

        /* ---------- основной цикл ---------- */
        while (running)
        {
            /* локальный pawn -------------------------------------------------- */
            uintptr_t localPawn = 0;
            if (!rpm(h, client + offs::dwLocalPlayerPawn, localPawn) || !localPawn)
            {
                Sleep(10); continue;
            }

            uint8_t localTeam = 0;
            rpm(h, localPawn + offs::m_iTeamNum, localTeam);

            /* view-matrix ----------------------------------------------------- */
            rpm(h, client + offs::dwViewMatrix, game::view);

            /* индекс локального controller-a --------------------------------- */
            uintptr_t localCtrl = 0;
            rpm(h, client + offs::dwLocalPlayerController, localCtrl);
            if (!localCtrl) { Sleep(10); continue; }

            uint32_t hPawn = 0;                       // CHandle
            rpm(h, localCtrl + offs::m_hPlayerPawn, hPawn);

            int localBit = (hPawn & 0x7FF);
            if (localBit == 0x7FF) continue;

            const int dword_index = (localBit / 32) ^ 1; // 0 или 1 (для CS2 порядок обратный)
            const int bit_mask = 1 << (localBit % 32);



            Vec3 eyeOrigin{};  rpm(h, localPawn + offs::m_vecAbsOrigin, eyeOrigin);
            Vec3 viewOffset{}; rpm(h, localPawn + offs::m_vecViewOffset, viewOffset);
            Vec3 eye{ eyeOrigin.x + viewOffset.x,
                      eyeOrigin.y + viewOffset.y,
                      eyeOrigin.z + viewOffset.z };

            int localCtrlIdx = -1;
            std::vector<EnemyTmp> tmpRaw;

            /* проход #1 — собираем pos/hp/spottedState ----------------------- */

            uintptr_t entList = 0;
            if (!rpm(h, client + offs::dwEntityList, entList)) { Sleep(10); continue; }

            for (int idx = 1; idx < 2048; ++idx)
            {
                uintptr_t seg = 0;
                rpm(h, entList + 0x10 + 0x8 * ((idx >> 9) & 0x7F), seg);
                if (!seg) continue;

                uintptr_t ent = 0;
                rpm(h, seg + 0x78 * (idx & 0x1FF), ent);
                if (!ent) continue;

                /* 1  если это наш controller — запоминаем индекс и пропускаем */
                if (ent == localCtrl) { localCtrlIdx = idx; continue; }

                /* --- фильтры pawn-ов --- */
                int hp = 0; rpm(h, ent + offs::m_iHealth, hp);
                if (hp <= 0 || hp > 100) continue;

                uint8_t life = 0; rpm(h, ent + offs::m_lifeState, life);
                if (life) continue;

                uint8_t team = 0; rpm(h, ent + offs::m_iTeamNum, team);
                if (team == localTeam || team == 0) continue;

                /* позиция */
                uintptr_t node = 0; rpm(h, ent + offs::m_pGameSceneNode, node);
                if (!node) continue;

                Vec3 pos{}; rpm(h, node + offs::m_vecAbsOrigin, pos);

                /* spottedState */
                uintptr_t spotted = 0; rpm(h, ent + offs::m_entitySpottedState, spotted);

                tmpRaw.push_back({ pos, hp, spotted, 0 });
            }

            if (localCtrlIdx == -1) { Sleep(10); continue; }   // safety

            const uint64_t now = GetTickCount64();

            std::vector<Enemy> out;
            out.reserve(tmpRaw.size());

            // В функции game::start (обработка видимости врагов):
            for (auto& r : tmpRaw)
            {
                bool vis = false;

                if (r.spottedState)
                {
                    uint32_t spotted_mask[2]{};
                    bool readSuccess = rpm(h, r.spottedState + offs::m_bSpottedByMask, spotted_mask);

                    // Проверка общего флага видимости m_bSpotted
                    bool base_spotted = false;
                    rpm(h, r.spottedState + offs::m_bSpotted, base_spotted);

                    // Корректный расчет индекса
                    const int dword_index = (localBit / 32) % 2; // 0 или 1
                    const int bit_mask = 1 << (localBit % 32);
                    vis = base_spotted && (spotted_mask[dword_index] & bit_mask) != 0;
                }

                out.push_back({ r.pos, r.hp, vis });
            }

            /* ---------- публикуем ---------- */
            {
                std::lock_guard<std::mutex> lk(game::mtx);
                game::enemies.swap(out);
            }

            Sleep(10);   // ~100 Гц
        }

        CloseHandle(h);
        }).detach();
}

void game::stop()
{
    running = false;
}

offsets:
Expand Collapse Copy
namespace offs
{
    /* client-dll сигнатуры */
    constexpr DWORD dwLocalPlayerPawn = 0x18530D0;
    constexpr DWORD dwEntityList = 0x19FEE38;
    constexpr DWORD dwViewMatrix = 0x1A67FA0;
    constexpr DWORD dwLocalPlayerController = 0x1A4D840;

    /* controller → handle pawn */
    constexpr DWORD m_hPlayerPawn = 0x824;

    /* pawn-поля */
    constexpr DWORD m_iHealth = 0x344;
    constexpr DWORD m_lifeState = 0x348;
    constexpr DWORD m_iTeamNum = 0x3E3;
    constexpr DWORD m_pGameSceneNode = 0x328;
    constexpr DWORD m_vecAbsOrigin = 0xD0;

    /* spotted */
    constexpr DWORD m_entitySpottedState = 0x23D0;
    constexpr DWORD m_bSpottedByMask = 0xC;      // uint32[2], НЕ pointer

    constexpr DWORD m_bSpotted = 0x8;

    constexpr DWORD m_vecViewOffset = 0xCB0;
}

esp.cpp:
Expand Collapse Copy
#include "esp.hh"
#include "game.hh"           // enemies, view-matrix, mtx
#include <mutex>
#include "imgui/imgui.h"
#include "Main.h"
#include "settings.hh"

/* --- параметры коробки --- */
namespace {
    constexpr float kHeadOffsetZ = 72.f; // высота «головы» (units)
    constexpr float kWidthMul = 0.6f; // ширина = height * kWidthMul
}

/* --- утилита W2S --- */
static bool W2S(const Vec3& in, ImVec2& out,
    const float m[16], float sw, float sh)
{
    const float clipX = m[0] * in.x + m[1] * in.y + m[2] * in.z + m[3];
    const float clipY = m[4] * in.x + m[5] * in.y + m[6] * in.z + m[7];
    const float clipW = m[12] * in.x + m[13] * in.y + m[14] * in.z + m[15];
    if (clipW < 0.1f) return false;

    const float ndcX = clipX / clipW;
    const float ndcY = clipY / clipW;

    out.x = (sw * 0.5f) * (1.f + ndcX);
    out.y = (sh * 0.5f) * (1.f - ndcY);
    return true;
}

/* --- основной рендер ESP --- */
void esp::render(ImDrawList* dl)
{
    if (!game::running) return;

    // размер overlay-окна
    RECT rc{}; GetClientRect(main_hwnd, &rc);
    const float sw = float(rc.right - rc.left);
    const float sh = float(rc.bottom - rc.top);

    // копируем список врагов под мьютексом
    std::vector<game::Enemy> list;
    {
        std::lock_guard<std::mutex> lk(game::mtx);
        list = game::enemies;
    }

    for (const auto& e : list)
    {
        ImVec2 feet;
        if (!W2S(e.pos, feet, game::view, sw, sh))
            continue;

        // голова
        Vec3 headWorld = e.pos; headWorld.z += kHeadOffsetZ;
        ImVec2 head;
        if (!W2S(headWorld, head, game::view, sw, sh))
            continue;

        const float height = feet.y - head.y;
        if (height <= 0.f) continue;

        const float width = height * kWidthMul;
        ImVec2 tl{ head.x - width * 0.5f, head.y };
        ImVec2 br{ head.x + width * 0.5f, feet.y };

        // Проверка видимости через MessageBoxA
        char visMsg[256];
        sprintf_s(visMsg, "Enemy HP: %d | Visible: %s", e.hp, e.visible ? "YES" : "NO");
        MessageBoxA(nullptr, visMsg, "ESP Debug", MB_OK);

        // Отрисовка коробки
        ImU32 col = (settings::ignoreWalls || e.visible)
            ? IM_COL32(0, 255, 0, 255)
            : IM_COL32(255, 0, 0, 255);
        dl->AddRect(tl, br, col, 0.f, 0, 1.5f);
    }

    /*for (const auto& e : list)
    {
        // ступни
        ImVec2 feet;
        if (!W2S(e.pos, feet, game::view, sw, sh))
            continue;

        // голова
        Vec3 headWorld = e.pos; headWorld.z += kHeadOffsetZ;
        ImVec2 head;
        if (!W2S(headWorld, head, game::view, sw, sh))
            continue;

        const float height = feet.y - head.y;
        if (height <= 0.f) continue;

        const float width = height * kWidthMul;
        ImVec2 tl{ head.x - width * 0.5f, head.y };
        ImVec2 br{ head.x + width * 0.5f, feet.y };

        ImU32 col = (settings::ignoreWalls || e.visible)
            ? IM_COL32(0, 255, 0, 255)
            : IM_COL32(255, 0, 0, 255);


        // B,A
        dl->AddRect(tl, br, col, 0.f, 0, 1.5f);
    }*/
}

game.h:
Expand Collapse Copy
#pragma once
#include <vector>
#include <mutex>
#include <atomic>
#include <Windows.h>

struct Vec3 { float x, y, z; };

namespace game
{
    struct Enemy { Vec3 pos; int hp; bool visible;};

    extern std::vector<Enemy> enemies;
    extern float              view[16];
    extern std::atomic_bool   running;

    extern std::mutex mtx;            // <── добавили

    void start();
    void stop();
}

esp.h:
Expand Collapse Copy
#pragma once
#include "imgui/imgui.h"

namespace esp
{
    // вызывайте один раз в кадр — сразу после ImGui::NewFrame()
    void render(ImDrawList* dl);
}
 
Ну ребилди функции себе тогдатвсе эти что нужнв для рейтрейса,либо можешь через шеллкод вызывать, но это уже не совсем экстернал будет
 
я пастер, но сделал через ChatGPT(plus), так что не засирай
Нейросети тебе не помогут в читах.
m_entitySpottedState не указатель, а структура в C_CSPlayerPawn, т.е читать её нужно просто по оффсету

Код:
Expand Collapse Copy
// uintptr_t это те же 8 байт, что у двух uint32
this->spotted_by_mask = mem::read<uintptr_t>(this->pawn + offsets::m_entitySpottedState + offsets::m_bSpottedByMask);

bool is_visible_to(size_t ent_index) const {
        return spotted_by_mask & (1 << (ent_index - 1));
}

Но лучше юзать метод, что скинули выше, с парсером
 
меня смущает этоПосмотреть вложение 307047

я пастер, но сделал через ChatGPT(plus), так что не засирай

game.cpp:
Expand Collapse Copy
#include "game.hh"
#include "offs.hh"          // ВСЕ актуальные оффсеты хранятся здесь
#include <TlHelp32.h>
#include <thread>
#include <string>
#include <sstream>

/* ───────── helpers ───────── */
static DWORD getPid(const wchar_t* exe)
{
    PROCESSENTRY32W pe{ sizeof pe };
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snap == INVALID_HANDLE_VALUE) return 0;

    for (BOOL ok = Process32FirstW(snap, &pe); ok; ok = Process32NextW(snap, &pe))
        if (!_wcsicmp(pe.szExeFile, exe)) { CloseHandle(snap); return pe.th32ProcessID; }

    CloseHandle(snap);
    return 0;
}

static uintptr_t getModule(DWORD pid, const wchar_t* mod)
{
    MODULEENTRY32W me{ sizeof me };
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
    if (snap == INVALID_HANDLE_VALUE) return 0;

    for (BOOL ok = Module32FirstW(snap, &me); ok; ok = Module32NextW(snap, &me))
        if (!_wcsicmp(me.szModule, mod)) { CloseHandle(snap); return (uintptr_t)me.modBaseAddr; }

    CloseHandle(snap);
    return 0;
}

template<class T>
static bool rpm(HANDLE h, uintptr_t addr, T& out)
{
    return ReadProcessMemory(h, reinterpret_cast<LPCVOID>(addr),
        &out, sizeof(T), nullptr);
}

/* ───────── глобалы, объявлены в game.hh ───────── */
namespace game {
    std::vector<Enemy> enemies;
    float              view[16]{};
    std::atomic_bool   running{ false };
    std::mutex         mtx;
}

/* временный контейнер для первого прохода */
struct Enemy {
    Vec3  pos;
    int   hp;
    bool  visible;
};

struct EnemyTmp {
    Vec3      pos;
    int       hp;
    uintptr_t spottedState;
    uint64_t  lastSeenTick;   // время, когда m_bSpotted = true
};


template<typename T>
std::string ToHexString(T value) {
    std::stringstream ss;
    ss << "0x" << std::hex << value;
    return ss.str();
}

/* ------------------------------------------------------------------
   game::start  /  game::stop
   ------------------------------------------------------------------ */
void game::start()
{
    if (running) return;
    running = true;

    std::thread([] {

        /* ---------- attach к процессу ---------- */
        const DWORD pid = getPid(L"cs2.exe");
        if (!pid) { running = false; return; }

        HANDLE h = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
            FALSE, pid);
        if (!h) { running = false; return; }

        const uintptr_t client = getModule(pid, L"client.dll");
        if (!client) { CloseHandle(h); running = false; return; }

        /* ---------- основной цикл ---------- */
        while (running)
        {
            /* локальный pawn -------------------------------------------------- */
            uintptr_t localPawn = 0;
            if (!rpm(h, client + offs::dwLocalPlayerPawn, localPawn) || !localPawn)
            {
                Sleep(10); continue;
            }

            uint8_t localTeam = 0;
            rpm(h, localPawn + offs::m_iTeamNum, localTeam);

            /* view-matrix ----------------------------------------------------- */
            rpm(h, client + offs::dwViewMatrix, game::view);

            /* индекс локального controller-a --------------------------------- */
            uintptr_t localCtrl = 0;
            rpm(h, client + offs::dwLocalPlayerController, localCtrl);
            if (!localCtrl) { Sleep(10); continue; }

            uint32_t hPawn = 0;                       // CHandle
            rpm(h, localCtrl + offs::m_hPlayerPawn, hPawn);

            int localBit = (hPawn & 0x7FF);
            if (localBit == 0x7FF) continue;

            const int dword_index = (localBit / 32) ^ 1; // 0 или 1 (для CS2 порядок обратный)
            const int bit_mask = 1 << (localBit % 32);



            Vec3 eyeOrigin{};  rpm(h, localPawn + offs::m_vecAbsOrigin, eyeOrigin);
            Vec3 viewOffset{}; rpm(h, localPawn + offs::m_vecViewOffset, viewOffset);
            Vec3 eye{ eyeOrigin.x + viewOffset.x,
                      eyeOrigin.y + viewOffset.y,
                      eyeOrigin.z + viewOffset.z };

            int localCtrlIdx = -1;
            std::vector<EnemyTmp> tmpRaw;

            /* проход #1 — собираем pos/hp/spottedState ----------------------- */

            uintptr_t entList = 0;
            if (!rpm(h, client + offs::dwEntityList, entList)) { Sleep(10); continue; }

            for (int idx = 1; idx < 2048; ++idx)
            {
                uintptr_t seg = 0;
                rpm(h, entList + 0x10 + 0x8 * ((idx >> 9) & 0x7F), seg);
                if (!seg) continue;

                uintptr_t ent = 0;
                rpm(h, seg + 0x78 * (idx & 0x1FF), ent);
                if (!ent) continue;

                /* 1  если это наш controller — запоминаем индекс и пропускаем */
                if (ent == localCtrl) { localCtrlIdx = idx; continue; }

                /* --- фильтры pawn-ов --- */
                int hp = 0; rpm(h, ent + offs::m_iHealth, hp);
                if (hp <= 0 || hp > 100) continue;

                uint8_t life = 0; rpm(h, ent + offs::m_lifeState, life);
                if (life) continue;

                uint8_t team = 0; rpm(h, ent + offs::m_iTeamNum, team);
                if (team == localTeam || team == 0) continue;

                /* позиция */
                uintptr_t node = 0; rpm(h, ent + offs::m_pGameSceneNode, node);
                if (!node) continue;

                Vec3 pos{}; rpm(h, node + offs::m_vecAbsOrigin, pos);

                /* spottedState */
                uintptr_t spotted = 0; rpm(h, ent + offs::m_entitySpottedState, spotted);

                tmpRaw.push_back({ pos, hp, spotted, 0 });
            }

            if (localCtrlIdx == -1) { Sleep(10); continue; }   // safety

            const uint64_t now = GetTickCount64();

            std::vector<Enemy> out;
            out.reserve(tmpRaw.size());

            // В функции game::start (обработка видимости врагов):
            for (auto& r : tmpRaw)
            {
                bool vis = false;

                if (r.spottedState)
                {
                    uint32_t spotted_mask[2]{};
                    bool readSuccess = rpm(h, r.spottedState + offs::m_bSpottedByMask, spotted_mask);

                    // Проверка общего флага видимости m_bSpotted
                    bool base_spotted = false;
                    rpm(h, r.spottedState + offs::m_bSpotted, base_spotted);

                    // Корректный расчет индекса
                    const int dword_index = (localBit / 32) % 2; // 0 или 1
                    const int bit_mask = 1 << (localBit % 32);
                    vis = base_spotted && (spotted_mask[dword_index] & bit_mask) != 0;
                }

                out.push_back({ r.pos, r.hp, vis });
            }

            /* ---------- публикуем ---------- */
            {
                std::lock_guard<std::mutex> lk(game::mtx);
                game::enemies.swap(out);
            }

            Sleep(10);   // ~100 Гц
        }

        CloseHandle(h);
        }).detach();
}

void game::stop()
{
    running = false;
}

offsets:
Expand Collapse Copy
namespace offs
{
    /* client-dll сигнатуры */
    constexpr DWORD dwLocalPlayerPawn = 0x18530D0;
    constexpr DWORD dwEntityList = 0x19FEE38;
    constexpr DWORD dwViewMatrix = 0x1A67FA0;
    constexpr DWORD dwLocalPlayerController = 0x1A4D840;

    /* controller → handle pawn */
    constexpr DWORD m_hPlayerPawn = 0x824;

    /* pawn-поля */
    constexpr DWORD m_iHealth = 0x344;
    constexpr DWORD m_lifeState = 0x348;
    constexpr DWORD m_iTeamNum = 0x3E3;
    constexpr DWORD m_pGameSceneNode = 0x328;
    constexpr DWORD m_vecAbsOrigin = 0xD0;

    /* spotted */
    constexpr DWORD m_entitySpottedState = 0x23D0;
    constexpr DWORD m_bSpottedByMask = 0xC;      // uint32[2], НЕ pointer

    constexpr DWORD m_bSpotted = 0x8;

    constexpr DWORD m_vecViewOffset = 0xCB0;
}

esp.cpp:
Expand Collapse Copy
#include "esp.hh"
#include "game.hh"           // enemies, view-matrix, mtx
#include <mutex>
#include "imgui/imgui.h"
#include "Main.h"
#include "settings.hh"

/* --- параметры коробки --- */
namespace {
    constexpr float kHeadOffsetZ = 72.f; // высота «головы» (units)
    constexpr float kWidthMul = 0.6f; // ширина = height * kWidthMul
}

/* --- утилита W2S --- */
static bool W2S(const Vec3& in, ImVec2& out,
    const float m[16], float sw, float sh)
{
    const float clipX = m[0] * in.x + m[1] * in.y + m[2] * in.z + m[3];
    const float clipY = m[4] * in.x + m[5] * in.y + m[6] * in.z + m[7];
    const float clipW = m[12] * in.x + m[13] * in.y + m[14] * in.z + m[15];
    if (clipW < 0.1f) return false;

    const float ndcX = clipX / clipW;
    const float ndcY = clipY / clipW;

    out.x = (sw * 0.5f) * (1.f + ndcX);
    out.y = (sh * 0.5f) * (1.f - ndcY);
    return true;
}

/* --- основной рендер ESP --- */
void esp::render(ImDrawList* dl)
{
    if (!game::running) return;

    // overlay window size
    RECT rc{}; GetClientRect(main_hwnd, &rc);
    const float sw = float(rc.right - rc.left);
    const float sh = float(rc.bottom - rc.top);

    // copy the list of enemies under the mutex
    std::vector<game::Enemy> list;
    {
        std::lock_guard<std::mutex> lk(game::mtx);
        list = game::enemies;
    }

    for (const auto& e : list)
    {
        ImVec2 feet;
        if (!W2S(e.pos, feet, game::view, sw, sh))
            continue;

        // head
        Vec3 headWorld = e.pos; headWorld.z += kHeadOffsetZ;
        ImVec2 head;
        if (!W2S(headWorld, head, game::view, sw, sh))
            continue;

        const float height = feet.y - head.y;
        if (height <= 0.f) continue;

        const float width = height * kWidthMul;
        ImVec2 tl{ head.x - width * 0.5f, head.y };
        ImVec2 br{ head.x + width * 0.5f, feet.y };

        // Check visibility via MessageBoxA
        char visMsg[256];
        sprintf_s(visMsg, "Enemy HP: %d | Visible: %s", e.hp, e.visible ? "YES" : "NO");
        MessageBoxA(nullptr, visMsg, "ESP Debug", MB_OK);

        // Draw the box
        ImU32 col = (settings::ignoreWalls || e.visible)
            ?IM_COL32(0, 255, 0, 255)
            : IM_COL32(255, 0, 0, 255);
        dl->AddRect(tl, br, col, 0.f, 0, 1.5f);
    }

    /*for (const auto& e : list)
    {
        // feet
        ImVec2 feet;
        if (!W2S(e.pos, feet, game::view, sw, sh))
            continue;

        // head
        Vec3 headWorld = e.pos; headWorld.z += kHeadOffsetZ;
        ImVec2 head;
        if (!W2S(headWorld, head, game::view, sw, sh))
            continue;

        const float height = feet.y - head.y;
        if (height <= 0.f) continue;

        const float width = height * kWidthMul;
        ImVec2 tl{ head.x - width * 0.5f, head.y };
        ImVec2 br{ head.x + width * 0.5f, feet.y };

        ImU32 col = (settings::ignoreWalls || e.visible)
            ?IM_COL32(0, 255, 0, 255)
            : IM_COL32(255, 0, 0, 255);


        // B,A
        dl->AddRect(tl, br, col, 0.f, 0, 1.5f);
    }*/
}

game.h:
Expand Collapse Copy
#pragma once
#include <vector>
#include <mutex>
#include <atomic>
#include <Windows.h>

struct Vec3 { float x, y, z; };

namespace game
{
    struct Enemy { Vec3 pos; int hp; bool visible;};

    extern std::vector<Enemy> enemies;
    extern float view[16];
    extern std::atomic_bool running;

    extern std::mutex mtx; // <── added

    void start();
    void stop();
}

esp.h:
Expand Collapse Copy
#pragma once
#include "imgui/imgui.h"

namespace esp
{
    // call once per frame - right after ImGui::NewFrame()
    void render(ImDrawList* dl);
}
you should at least learn the basics about programming before blindly pasting from chatgpt or other cheats
 
you should at least learn the basics about programming before blindly pasting from chatgpt or other cheats
I'm not familiar with CS2, so I searched the internet first for information about External, but I didn't want to copy a ready-made 1-in-1 solution. So I started using ChatGPT.
 
Назад
Сверху Снизу