diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-06 16:21:27 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-06 16:21:27 +0100 |
| commit | 3c27e7ce262e612fa75c6e6f090e04041a688861 (patch) | |
| tree | 1c2bfd6accea27904dc9d81a61624905b220a8a0 /src/core.h | |
| parent | Hooks: central vtable install with restore support (diff) | |
| download | hl2h-3c27e7ce262e612fa75c6e6f090e04041a688861.tar.gz hl2h-3c27e7ce262e612fa75c6e6f090e04041a688861.zip | |
Headers: split the shared header by declaration group
hl2h.h becomes an umbrella over core.h (logging, init stage, module snapshots,
interfaces, netvars, CUserCmd, engine constants, vector math), settings.h
(feature ids, feature state, user settings) and features.h (cross-module
declarations). Translation units keep including hl2h.h, so this only moves
declarations.
Diffstat (limited to '')
| -rw-r--r-- | src/core.h | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/core.h b/src/core.h new file mode 100644 index 0000000..320b62b --- /dev/null +++ b/src/core.h | |||
| @@ -0,0 +1,205 @@ | |||
| 1 | #ifndef HL2H_CORE_H | ||
| 2 | #define HL2H_CORE_H | ||
| 3 | |||
| 4 | #include <cstdint> | ||
| 5 | #include <cstdio> | ||
| 6 | #include <cstring> | ||
| 7 | #include <string> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include <dlfcn.h> | ||
| 11 | #include <pthread.h> | ||
| 12 | #include <unistd.h> | ||
| 13 | |||
| 14 | // Shared float-precision constant. More digits than a float can hold are | ||
| 15 | // rounded at compile time and have no runtime cost; a coarse value would only | ||
| 16 | // hurt angular accuracy, never performance. | ||
| 17 | constexpr float PI_F = 3.14159265f; | ||
| 18 | |||
| 19 | // --------------------------------------------------------------------------- | ||
| 20 | // logging | ||
| 21 | // --------------------------------------------------------------------------- | ||
| 22 | |||
| 23 | void logf(const char *fmt, ...); | ||
| 24 | void logd(const char *fmt, ...); // debug-only (HL2H_DEBUG=1) | ||
| 25 | |||
| 26 | // --------------------------------------------------------------------------- | ||
| 27 | // init readiness | ||
| 28 | // --------------------------------------------------------------------------- | ||
| 29 | // | ||
| 30 | // setup_thread runs detached while the game threads are already live, and some | ||
| 31 | // hooks are installed lazily from the game thread. Hooks therefore always stay | ||
| 32 | // installed but pass straight through to the original until setup reaches | ||
| 33 | // INIT_LIVE, so the game can never observe half-initialised state. INIT_FAILED | ||
| 34 | // is terminal: the cheat stays inert instead of half-working. | ||
| 35 | enum { | ||
| 36 | INIT_FAILED = -1, | ||
| 37 | INIT_NONE = 0, | ||
| 38 | INIT_INTERFACES = 1, // modules + interfaces + netvars resolved | ||
| 39 | INIT_READY = 2, // config loaded, ISurface/fonts resolved | ||
| 40 | INIT_LIVE = 3 // hooks may run their bodies | ||
| 41 | }; | ||
| 42 | void init_set_stage(int stage); | ||
| 43 | int init_stage(); // acquire load | ||
| 44 | inline bool init_live() { return init_stage() == INIT_LIVE; } | ||
| 45 | |||
| 46 | // Clone a vtable into a new array, preserving the Itanium ABI header at | ||
| 47 | // [-2]/[-1] (offset-to-top and typeinfo) so RTTI on the hooked object still | ||
| 48 | // works. Returns the slot-0 pointer to install (i.e. the clone + 2). | ||
| 49 | void **vtable_clone(void *iface, size_t slots); | ||
| 50 | |||
| 51 | // --------------------------------------------------------------------------- | ||
| 52 | // on-screen toasts | ||
| 53 | // --------------------------------------------------------------------------- | ||
| 54 | |||
| 55 | enum ToastLevel { TOAST_INFO = 0, TOAST_WARN, TOAST_ERROR }; | ||
| 56 | void toastf(int level, const char *fmt, ...); | ||
| 57 | bool gui_toasts_active(); | ||
| 58 | void gui_draw_toasts(); | ||
| 59 | |||
| 60 | // --------------------------------------------------------------------------- | ||
| 61 | // module discovery | ||
| 62 | // --------------------------------------------------------------------------- | ||
| 63 | |||
| 64 | struct Module { | ||
| 65 | struct Range { | ||
| 66 | uintptr_t lo, hi; | ||
| 67 | bool file; | ||
| 68 | }; | ||
| 69 | std::vector<Range> ranges; | ||
| 70 | std::string path; | ||
| 71 | bool valid() const { return !ranges.empty(); } | ||
| 72 | bool contains(uintptr_t p) const { | ||
| 73 | for (auto &r : ranges) | ||
| 74 | if (p >= r.lo && p < r.hi) | ||
| 75 | return true; | ||
| 76 | return false; | ||
| 77 | } | ||
| 78 | }; | ||
| 79 | // Immutable module snapshots. A reader gets a reference that stays valid for | ||
| 80 | // the whole process: find_modules() publishes a new snapshot instead of | ||
| 81 | // mutating the old one, and retired snapshots are intentionally never freed, so | ||
| 82 | // a concurrent refresh can never invalidate a reference already in use. | ||
| 83 | const Module &mod_client(); | ||
| 84 | const Module &mod_engine(); | ||
| 85 | const Module &mod_server(); | ||
| 86 | |||
| 87 | // True only when the whole byte range [p, p+n) lies inside one known module | ||
| 88 | // range. Use before dereferencing pointers read out of engine memory. | ||
| 89 | bool module_range(uintptr_t p, size_t n); | ||
| 90 | |||
| 91 | // --------------------------------------------------------------------------- | ||
| 92 | // game interfaces | ||
| 93 | // --------------------------------------------------------------------------- | ||
| 94 | |||
| 95 | using CreateInterfaceFn = void *(*)(const char *, int *); | ||
| 96 | |||
| 97 | struct GameInterfaces { | ||
| 98 | void *client = nullptr; | ||
| 99 | void *entitylist = nullptr; | ||
| 100 | void *engine = nullptr; | ||
| 101 | void *modelinfo = nullptr; // IVModelInfoClient006 (model index -> model name) | ||
| 102 | void *engineserver = nullptr; // IVEngineServer021 (edict access, incl. server entities) | ||
| 103 | void *debugoverlay = nullptr; // IVDebugOverlay003 (engine-accurate world->screen) | ||
| 104 | void *enginetrace = nullptr; // EngineTraceClient003 (world vischeck) | ||
| 105 | void *cvar = nullptr; // VEngineCvar004 (mat_fullbright etc.) | ||
| 106 | void *modelrender = nullptr; // VEngineModel016 (chams) | ||
| 107 | void *renderview = nullptr; // VEngineRenderView014 (alpha/color modulation) | ||
| 108 | }; | ||
| 109 | extern GameInterfaces g_iface; | ||
| 110 | |||
| 111 | #define VTABLE(obj) (*(void ***)(obj)) | ||
| 112 | template <typename Fn> inline Fn vfunc(void *obj, size_t idx) { | ||
| 113 | return reinterpret_cast<Fn>(VTABLE(obj)[idx]); | ||
| 114 | } | ||
| 115 | |||
| 116 | // --------------------------------------------------------------------------- | ||
| 117 | // netvars | ||
| 118 | // --------------------------------------------------------------------------- | ||
| 119 | struct NetVars { | ||
| 120 | int flags = -1; | ||
| 121 | int velocity = -1; | ||
| 122 | int movetype = -1; | ||
| 123 | int health = -1; | ||
| 124 | int maxhealth = -1; | ||
| 125 | int teamnum = -1; | ||
| 126 | int origin = -1; | ||
| 127 | int viewoffset = -1; | ||
| 128 | int mins = -1; | ||
| 129 | int maxs = -1; | ||
| 130 | int lifestate = -1; | ||
| 131 | int modelindex = -1; | ||
| 132 | int absvelocity = -1; // client C_BaseEntity::m_vecAbsVelocity (prediction) | ||
| 133 | int activeweapon = -1; // client m_hActiveWeapon handle | ||
| 134 | int owner = -1; // client m_hOwnerEntity handle | ||
| 135 | int weapon_owner = -1; // client m_hOwner handle (C_BaseCombatWeapon) | ||
| 136 | int clr_render = -1; // client m_clrRender (entity render colour) | ||
| 137 | int punch = -1; // client m_vecPunchAngle (aim punch) | ||
| 138 | int default_fov = -1; // client m_iDefaultFOV (camera fov) | ||
| 139 | int dmg_radius = -1; // client C_BaseGrenade::m_DmgRadius | ||
| 140 | int my_weapons = -1; // client m_hMyWeapons[48] array base | ||
| 141 | int ammo = -1; // client m_iAmmo[] array base | ||
| 142 | // ponytail: mins/maxs may be absent from some HL2 netvar tables; esp.cpp falls back to h=72 | ||
| 143 | bool ok() const { return flags >= 0 && velocity >= 0 && movetype >= 0; } | ||
| 144 | // ponytail: m_iMaxHealth isn't a netvar in HL2 SP; esp.cpp falls back to 100. | ||
| 145 | // m_iHealth only ever updates for players — NPCs are detected via m_lifeState. | ||
| 146 | bool esp_ok() const { return ok() && health >= 0 && teamnum >= 0 && origin >= 0 && viewoffset >= 0; } | ||
| 147 | }; | ||
| 148 | extern NetVars g_net; | ||
| 149 | |||
| 150 | // --------------------------------------------------------------------------- | ||
| 151 | // CInput | ||
| 152 | // --------------------------------------------------------------------------- | ||
| 153 | |||
| 154 | extern uintptr_t g_input; | ||
| 155 | |||
| 156 | // --------------------------------------------------------------------------- | ||
| 157 | // console output | ||
| 158 | // --------------------------------------------------------------------------- | ||
| 159 | |||
| 160 | extern void (*g_conmsg)(const char *, ...); | ||
| 161 | |||
| 162 | // --------------------------------------------------------------------------- | ||
| 163 | // CUserCmd | ||
| 164 | // --------------------------------------------------------------------------- | ||
| 165 | |||
| 166 | struct CUserCmd { | ||
| 167 | void *vtable; | ||
| 168 | int command_number; | ||
| 169 | int tick_count; | ||
| 170 | float viewangles[3]; | ||
| 171 | float forwardmove; | ||
| 172 | float sidemove; | ||
| 173 | float upmove; | ||
| 174 | int buttons; | ||
| 175 | uint8_t impulse; | ||
| 176 | int weaponselect; | ||
| 177 | int weaponsubtype; | ||
| 178 | int random_seed; | ||
| 179 | short mousedx; | ||
| 180 | short mousedy; | ||
| 181 | bool hasbeenpredicted; | ||
| 182 | }; | ||
| 183 | |||
| 184 | // --------------------------------------------------------------------------- | ||
| 185 | // engine constants | ||
| 186 | // --------------------------------------------------------------------------- | ||
| 187 | |||
| 188 | 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 }; | ||
| 189 | enum { FL_ONGROUND = 1 << 0, FL_DUCKING = 1 << 1, FL_INWATER = 1 << 9 }; | ||
| 190 | enum { MOVETYPE_WALK = 2, MOVETYPE_NOCLIP = 8, MOVETYPE_LADDER = 9 }; | ||
| 191 | |||
| 192 | // --------------------------------------------------------------------------- | ||
| 193 | // vector math | ||
| 194 | // --------------------------------------------------------------------------- | ||
| 195 | |||
| 196 | struct Vector { float x, y, z; }; | ||
| 197 | struct QAngle { float x, y, z; }; | ||
| 198 | // camera state captured each CreateMove (used by ESP / future aimbot) | ||
| 199 | extern Vector g_cam_eye; | ||
| 200 | extern Vector g_cam_view; | ||
| 201 | QAngle vector_angles(const Vector &forward); | ||
| 202 | Vector angle_forward_vector(const QAngle &angles); | ||
| 203 | float getfov(const QAngle &my_view, const QAngle &aim_ang); | ||
| 204 | |||
| 205 | #endif | ||
