EasyUniversal / DocsДокументация · SDK 0.3Подписка Universal ↗
Easy Universal / Справочник SDK

cs2-esp-test.as

AngelScript · native runtime · локальная сборка
// Experimental read-only CS2 ESP sample, using the workspace's 2026-10-01
// dump. Offsets must be updated after game changes. No injection or writes.
// Add .as, select your CS2 PID, allow read access and optionally enable
// Overlay selected window. Conventional windowed/borderless output only;
// exclusive fullscreen and live game compatibility are not guaranteed.
const uint64 ENTITY_LIST = 0x2715828;
const uint64 VIEW_MATRIX = 0x2566910;
const uint64 LOCAL_CONTROLLER = 0x2538008;
const uint64 PAWN_HANDLE = 0x6bc;
const uint64 SCENE_NODE = 0x330;
const uint64 HEALTH = 0x34c;
const uint64 TEAM = 0x3e7;
const uint64 ABS_ORIGIN = 0xc8;

class Position { float x=0,y=0,z=0; }
class Pixel { float x=0,y=0; }
class Matrix {
    float a=0,b=0,c=0,d=0,e=0,f=0,g=0,h=0;
    float i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;
}
uint64 clientBase=0;
float nextModuleCheck=0;
bool pointer(uint64 value) { return value>=0x10000 && value<0x7fffffff0000 && (value&7)==0; }
bool finite(float value) { return value>-1000000000 && value<1000000000; }
bool matrix_read(uint64 at, Matrix &out v) {
    return process::read_float(at,v.a) && process::read_float(at+4,v.b) &&
        process::read_float(at+8,v.c) && process::read_float(at+12,v.d) &&
        process::read_float(at+16,v.e) && process::read_float(at+20,v.f) &&
        process::read_float(at+24,v.g) && process::read_float(at+28,v.h) &&
        process::read_float(at+32,v.i) && process::read_float(at+36,v.j) &&
        process::read_float(at+40,v.k) && process::read_float(at+44,v.l) &&
        process::read_float(at+48,v.m) && process::read_float(at+52,v.n) &&
        process::read_float(at+56,v.o) && process::read_float(at+60,v.p);
}
bool project(const Matrix &in v, const Position &in point, Pixel &out outPoint) {
    float w=v.m*point.x+v.n*point.y+v.o*point.z+v.p;
    if (!finite(w) || w<0.01) return false;
    float x=(v.a*point.x+v.b*point.y+v.c*point.z+v.d)/w;
    float y=(v.e*point.x+v.f*point.y+v.g*point.z+v.h)/w;
    if (!finite(x)||!finite(y)||x<-2||x>2||y<-2||y>2) return false;
    outPoint.x=(x+1)*screen::width()*0.5;
    outPoint.y=(1-y)*screen::height()*0.5;
    return finite(outPoint.x)&&finite(outPoint.y);
}
void on_frame() {
    if (!process::attached()) {
        render::text(20,20,"CS2 ESP test: select PID and enable read access.",0xf79b53ff);
        return;
    }
    if (!process::alive()) {render::text(20,20,"Target exited. Stop the script.");return;}
    if (process::name()!="cs2.exe") {render::text(20,20,"Select cs2.exe, not another process.");return;}
    if (clientBase==0 && time::seconds()>=nextModuleCheck) {
        clientBase=process::module_base("client.dll");nextModuleCheck=time::seconds()+1;
    }
    if (clientBase==0) {render::text(20,20,"Waiting for client.dll...");return;}
    uint64 list=0,controllers=0,local=0;
    Matrix matrix;
    if (!process::read_u64(clientBase+ENTITY_LIST,list)||!pointer(list)||
        !process::read_u64(list+0x10,controllers)||!pointer(controllers)||
        !matrix_read(clientBase+VIEW_MATRIX,matrix)) {
        render::text(20,20,"No readable world. Check offsets and match state.");return;
    }
    uint localTeam=0;
    if (process::read_u64(clientBase+LOCAL_CONTROLLER,local)&&pointer(local))
        process::read_u32(local+TEAM,localTeam);
    localTeam=localTeam&255;
    if(localTeam!=2 && localTeam!=3){render::text(20,20,"Waiting for a valid local team.");return;}
    uint drawn=0;
    // With ten occupied slots this stays below the 256-operation budget.
    // Extra populated slots fail closed on quota; this is a test sample.
    for (uint slot=1;slot<=64;slot++) {
        uint64 controller=0,pawnBucket=0,pawn=0,scene=0;uint handle=0,hp=0,team=0;
        if (!process::read_u64(controllers+uint64(slot)*0x70,controller)||!pointer(controller)||controller==local) continue;
        if (!process::read_u32(controller+PAWN_HANDLE,handle)||handle==0||handle==0xffffffff) continue;
        uint index=handle&0x7fff;
        if (!process::read_u64(list+0x10+8*uint64(index>>9),pawnBucket)||!pointer(pawnBucket)||
            !process::read_u64(pawnBucket+0x70*uint64(index&0x1ff),pawn)||!pointer(pawn)) continue;
        if (!process::read_u32(pawn+HEALTH,hp)||hp<1||hp>100 ||
            !process::read_u32(pawn+TEAM,team)) continue;
        team=team&255;
        if ((team!=2&&team!=3)||team==localTeam) continue;
        if (!process::read_u64(pawn+SCENE_NODE,scene)||!pointer(scene)) continue;
        Position feet,head;
        if (!process::read_float(scene+ABS_ORIGIN,feet.x)||
            !process::read_float(scene+ABS_ORIGIN+4,feet.y)||
            !process::read_float(scene+ABS_ORIGIN+8,feet.z)) continue;
        if (!finite(feet.x)||!finite(feet.y)||!finite(feet.z)) continue;
        // Approximate standing height, not a bone-accurate box or skeleton.
        head.x=feet.x;head.y=feet.y;head.z=feet.z+72;
        Pixel bottom,top;
        if (!project(matrix,feet,bottom)||!project(matrix,head,top)) continue;
        float height=bottom.y-top.y;
        if (height<3||height>screen::height()*1.5) continue;
        float left=top.x-height*0.22,right=top.x+height*0.22;
        uint color=0xf79b53ff;
        render::line(left,top.y,right,top.y,color);
        render::line(right,top.y,right,bottom.y,color);
        render::line(right,bottom.y,left,bottom.y,color);
        render::line(left,bottom.y,left,top.y,color);
        render::text(left,top.y-20,"HP "+hp,color);
        drawn++;
    }
    render::text(20,20,"CS2 ESP test | visible projections: "+drawn,0xf79b53ff);
}
Easy Universal — отдельный проект. Easy External не изменён.