#ifndef HL2H_CORE_H #define HL2H_CORE_H #include #include #include #include #include #include #include #include // Shared float-precision constant. More digits than a float can hold are // rounded at compile time and have no runtime cost; a coarse value would only // hurt angular accuracy, never performance. constexpr float PI_F = 3.14159265f; // --------------------------------------------------------------------------- // logging // --------------------------------------------------------------------------- void logf(const char *fmt, ...); void logd(const char *fmt, ...); // debug-only (HL2H_DEBUG=1) // --------------------------------------------------------------------------- // init readiness // --------------------------------------------------------------------------- // // setup_thread runs detached while the game threads are already live, and some // hooks are installed lazily from the game thread. Hooks therefore always stay // installed but pass straight through to the original until setup reaches // INIT_LIVE, so the game can never observe half-initialised state. INIT_FAILED // is terminal: the cheat stays inert instead of half-working. enum { INIT_FAILED = -1, INIT_NONE = 0, INIT_INTERFACES = 1, // modules + interfaces + netvars resolved INIT_READY = 2, // config loaded, ISurface/fonts resolved INIT_LIVE = 3 // hooks may run their bodies }; void init_set_stage(int stage); int init_stage(); // acquire load inline bool init_live() { return init_stage() == INIT_LIVE; } // Clone a vtable into a new array, preserving the Itanium ABI header at // [-2]/[-1] (offset-to-top and typeinfo) so RTTI on the hooked object still // works. Returns the slot-0 pointer to install (i.e. the clone + 2). void **vtable_clone(void *iface, size_t slots); // --------------------------------------------------------------------------- // on-screen toasts // --------------------------------------------------------------------------- enum ToastLevel { TOAST_INFO = 0, TOAST_WARN, TOAST_ERROR }; void toastf(int level, const char *fmt, ...); bool gui_toasts_active(); void gui_draw_toasts(); // --------------------------------------------------------------------------- // module discovery // --------------------------------------------------------------------------- struct Module { struct Range { uintptr_t lo, hi; bool file; }; std::vector ranges; std::string path; bool valid() const { return !ranges.empty(); } bool contains(uintptr_t p) const { for (auto &r : ranges) if (p >= r.lo && p < r.hi) return true; return false; } }; // Immutable module snapshots. A reader gets a reference that stays valid for // the whole process: find_modules() publishes a new snapshot instead of // mutating the old one, and retired snapshots are intentionally never freed, so // a concurrent refresh can never invalidate a reference already in use. const Module &mod_client(); const Module &mod_engine(); const Module &mod_server(); // True only when the whole byte range [p, p+n) lies inside one known module // range. Use before dereferencing pointers read out of engine memory. bool module_range(uintptr_t p, size_t n); // --------------------------------------------------------------------------- // game interfaces // --------------------------------------------------------------------------- using CreateInterfaceFn = void *(*)(const char *, int *); struct GameInterfaces { void *client = nullptr; void *entitylist = nullptr; void *engine = nullptr; void *modelinfo = nullptr; // IVModelInfoClient006 (model index -> model name) void *engineserver = nullptr; // IVEngineServer021 (edict access, incl. server entities) void *debugoverlay = nullptr; // IVDebugOverlay003 (engine-accurate world->screen) void *enginetrace = nullptr; // EngineTraceClient003 (world vischeck) void *cvar = nullptr; // VEngineCvar004 (mat_fullbright etc.) void *modelrender = nullptr; // VEngineModel016 (chams) void *renderview = nullptr; // VEngineRenderView014 (alpha/color modulation) }; extern GameInterfaces g_iface; #define VTABLE(obj) (*(void ***)(obj)) template inline Fn vfunc(void *obj, size_t idx) { return reinterpret_cast(VTABLE(obj)[idx]); } // --------------------------------------------------------------------------- // netvars // --------------------------------------------------------------------------- struct NetVars { int flags = -1; int velocity = -1; int movetype = -1; int health = -1; int maxhealth = -1; int teamnum = -1; int origin = -1; int viewoffset = -1; int mins = -1; int maxs = -1; int lifestate = -1; int modelindex = -1; int absvelocity = -1; // client C_BaseEntity::m_vecAbsVelocity (prediction) int activeweapon = -1; // client m_hActiveWeapon handle int owner = -1; // client m_hOwnerEntity handle int weapon_owner = -1; // client m_hOwner handle (C_BaseCombatWeapon) int clr_render = -1; // client m_clrRender (entity render colour) int punch = -1; // client m_vecPunchAngle (aim punch) int default_fov = -1; // client m_iDefaultFOV (camera fov) int dmg_radius = -1; // client C_BaseGrenade::m_DmgRadius int my_weapons = -1; // client m_hMyWeapons[48] array base int ammo = -1; // client m_iAmmo[] array base // ponytail: mins/maxs may be absent from some HL2 netvar tables; esp.cpp falls back to h=72 bool ok() const { return flags >= 0 && velocity >= 0 && movetype >= 0; } // ponytail: m_iMaxHealth isn't a netvar in HL2 SP; esp.cpp falls back to 100. // m_iHealth only ever updates for players — NPCs are detected via m_lifeState. bool esp_ok() const { return ok() && health >= 0 && teamnum >= 0 && origin >= 0 && viewoffset >= 0; } }; extern NetVars g_net; // --------------------------------------------------------------------------- // CInput // --------------------------------------------------------------------------- extern uintptr_t g_input; // --------------------------------------------------------------------------- // console output // --------------------------------------------------------------------------- extern void (*g_conmsg)(const char *, ...); // --------------------------------------------------------------------------- // CUserCmd // --------------------------------------------------------------------------- struct CUserCmd { void *vtable; int command_number; int tick_count; float viewangles[3]; float forwardmove; float sidemove; float upmove; int buttons; uint8_t impulse; int weaponselect; int weaponsubtype; int random_seed; short mousedx; short mousedy; bool hasbeenpredicted; }; // --------------------------------------------------------------------------- // engine constants // --------------------------------------------------------------------------- enum { IN_ATTACK = 1 << 0, IN_JUMP = 1 << 1, IN_DUCK = 1 << 2, IN_USE = 1 << 5, IN_ATTACK2 = 1 << 11, IN_SPEED = 1 << 17 }; enum { FL_ONGROUND = 1 << 0, FL_DUCKING = 1 << 1, FL_INWATER = 1 << 9 }; enum { MOVETYPE_WALK = 2, MOVETYPE_NOCLIP = 8, MOVETYPE_LADDER = 9 }; // --------------------------------------------------------------------------- // vector math // --------------------------------------------------------------------------- struct Vector { float x, y, z; }; struct QAngle { float x, y, z; }; // camera state captured each CreateMove (used by ESP / future aimbot) extern Vector g_cam_eye; extern Vector g_cam_view; QAngle vector_angles(const Vector &forward); Vector angle_forward_vector(const QAngle &angles); float getfov(const QAngle &my_view, const QAngle &aim_ang); #endif