summaryrefslogtreecommitdiffstats
path: root/CONTEXT.md
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-10-26 17:53:40 +0100
committersalmonik <salmonik@tuta.io>2026-10-26 17:53:40 +0100
commitd164e3373108d0c0f83452fbea22f8569b84eec6 (patch)
tree141999a0ac933728382f344c56f009cb0464b044 /CONTEXT.md
parentConfig: store in $XDG_CONFIG_HOME/hl2hake/config (diff)
downloadhl2h-d164e3373108d0c0f83452fbea22f8569b84eec6.tar.gz
hl2h-d164e3373108d0c0f83452fbea22f8569b84eec6.zip
Docs/cleanup: refresh CONTEXT, update ISurface status, remove dead code
- rewrite CONTEXT.md for the current architecture, interfaces, netvars, menu tree, bones/ESP, aimbot/vischeck, triggerbot, silent aim and ABH - update ISURFACE_STATUS.md: DrawLine slot, current menu/config path, 9 build TUs, current file layout - remove the stale root-level `tree` file - drop unused class_health_off/per-class health scan (NPC HP is not networked), surf_call_slot, and unused scancode helpers
Diffstat (limited to 'CONTEXT.md')
-rw-r--r--CONTEXT.md185
1 files changed, 153 insertions, 32 deletions
diff --git a/CONTEXT.md b/CONTEXT.md
index 21128f7..1969781 100644
--- a/CONTEXT.md
+++ b/CONTEXT.md
@@ -1,47 +1,168 @@
1# Context: HL2 Linux Internal Cheat (`hl2hake`) 1# Context: HL2 Linux Internal Cheat (`hl2hake`)
2 2
3## What is this project? 3## What this is
4 4
5A minimal, featureless cheat for Half-Life 2 (native Linux build, 32-bit `hl2_linux`). Originally ported from a Windows reference (`hake`) that implemented auto-bhop, auto-ABH, and auto-climb via a `CHLClient::CreateMove` vtable hook. 5A 32-bit Linux internal for Half-Life 2 (native `hl2_linux`), loaded with
6`LD_PRELOAD` through Steam's bundled 32-bit runtime. It started as a port of
7the Windows `hake` reference (auto-bhop / auto-ABH / auto-climb) and now also
8covers ESP, aimbot, triggerbot and silent aim.
6 9
7## Resolved terms 10## Build / run
8 11
9- **Build**: LD_PRELOAD a 32-bit `.so` into `hl2_linux` via Steam's bundled 32-bit runtime (`steam-runtime/run.sh`). 12- `./build.sh` -> `libhl2hake.so`
10- **Hook**: Copy-and-swap vtable on the `CHLClient` instance (slot 21 = `CreateMove`). 256-slot copy to cover all dispatched virtuals. 13 (`g++ -m32 -O2 -std=c++17 -Wall -Wextra -Werror -fPIC -shared`,
11- **Netvars**: RecvTable walk from `IBaseClientDLL::GetAllClasses` (vtable slot 8). Prediction datamap scan for `CBaseEntity::m_MoveType` (networked `movetype` is a virtual proxy with offset 0). 14 sources: `hl2h modules cinput netvars menu esp server bones vischeck`, `-ldl`).
12- **CInput**: Discovered via byte-scan of `CHLClient::CreateMove` prologue (gcc PIC `call thunk; add $imm,%esi` idiom), resolving the module-level `IInput*` variable. 15- `./play.sh` -> Steam runtime + `hl2.sh -steam -novid -console +map d1_town_01`.
13- **UserCMD CRC**: Standard CRC-32 (IEEE reflected, poly `0xEDB88320`, init `0xFFFFFFFF`). Field set and offsets verified against the binary's `CInput::ValidateUserCmd` disassembly. 16- Logs: `/tmp/hl2hake.log` (`logf`) and stderr. `./play.sh > /tmp/hl2run.log 2>&1`
14- **Module discovery**: `/proc/self/maps` scan for `client.so` / `engine.so` basenames (exact match at `/` boundary). PROT_NONE (`---p`) entries excluded. Merged file-backed ranges absorb one directly-adjacent anonymous `.bss` tail; anon-to-anon chaining is prohibited. 17 captures everything.
15- **Calling convention**: All game virtuals use **cdecl** with `this` as first stack arg (`0x8(%ebp)` in prologues, bare `ret`). No MSVC `__thiscall`. 18- Debug env:
19 - `HL2H_DRAW_TEST=1` — red probe rect + text, no menu needed.
20 - `HL2H_BONE_DEBUG=1` — white marker at each NPC head hitbox.
21 - `HL2H_NO_SERVER=1` — disable server-side health reads.
22- Config: `$XDG_CONFIG_HOME/hl2hake/config`, falling back to
23 `~/.config/hl2hake/config`. Plain INI, saved on every change.
16 24
17## Netvar offsets (this build, verified via both RecvTable walk and pred-TD scan) 25## Runtime architecture
18 26
19| Field | Offset | Source | 27- Modules from `/proc/self/maps`: `client.so`, `engine.so`, `server.so`.
20|---|---|---| 28 PROT_NONE ranges excluded; file-backed bss tails merged.
21| `m_fFlags` | `0x33C` | RecvTable + pred TD | 29- Calling convention: cdecl (i386); `this` is the first stack argument.
22| `m_vecVelocity[0]` | `0xE0` | RecvTable (array, FIELD_VECTOR) | 30- Hooks (copy-and-swap vtable, 256 slots):
23| `m_MoveType` | `0x164` | pred-TD only (networked `movetype` has offset 0) | 31 - `CHLClient` slot 21 `CreateMove`; slot 35 `FrameStageNotify`.
32 - `ISurface` slot 114 `PaintTraverseEx` (primary draw);
33 slot 22 `DrawPrintText` fallback. Draws wrapped in
34 `PushMakeCurrent`/`PopMakeCurrent`.
35- `CInput*` discovered by byte-scanning the `CHLClient::CreateMove` prologue.
36 Usercmd CRC-32 is repaired after any cmd edit (`note_modified`).
37- Console output via `ConMsg` from `libtier0.so`
38 (`_Z6ConMsgPKcz`), not `IVEngineClient::ClientCmd`.
24 39
25## Key engine index table (IVEngineClient014, this build) 40## Interfaces / indices
26 41
27| Index | Method | Verification | 42| Interface | Version | Notes |
28|---|---|---| 43|---|---|---|
29| 8 | *(not ClientCmd)* | Disasm: per-player index bounds check on `(arg-1)` — likely `GetPlayerInfo` | 44| Client | `VClient017` | |
30| 9 | *(not ClientCmd_Unrestricted)* | Disasm: loop over split-screen players — no-op'd in single-player | 45| Entity list | `VClientEntityList003` | |
31| 12 | `GetLocalPlayer` | Disasm: `return *(CClientState + 0x1b0) + 1` — confirmed in-game | 46| Engine | `VEngineClient014` | |
32| 65 | `HudUpdate`-family | Crash-site (256-slot bump): `call *(this, float)` | 47| Model info | `VModelInfoClient006` | |
48| Engine server | `VEngineServer021` | edicts / listen-server entities |
49| Debug overlay | `VDebugOverlay003` | accurate world->screen |
50| Engine trace | `EngineTraceClient003` | vischeck / trigger ray |
51| Surface | `VGUI_Surface030` | |
52
53Relevant vtable slots (this build):
54
55- Engine: `GetLocalPlayer` 12, `Time` 14, `GetViewAngles` 19, `SetViewAngles` 20.
56- Entity list: `GetClientNetworkable` 0, `GetClientEntity` 3,
57 `GetHighestEntityIndex` 6.
58- `IClientNetworkable`: `GetClientClass` 2. `ClientClass::m_pNetworkName` at +8.
59- `IClientUnknown`: `GetClientRenderable` 6.
60- `IClientRenderable`: `GetModel` 9, `SetupBones` 16.
61- `IVModelInfo`: `GetModel` 2, `GetModelName` 4, `GetStudiomodel` 29.
62- `IVEngineServer`: `PEntityOfEntIndex` 19.
63 Edict `m_pUnk` at +0xC; `IServerUnknown::GetBaseEntity` 6.
64- `IVDebugOverlay`: `ScreenPosition` 9.
65- `IEngineTrace`: `TraceRay` 4. `Ray_t` uses 16-byte `VectorAligned`;
66 `trace_t`: `fraction` 44, `startsolid` 55, `m_pEnt` 76.
67
68## Netvars / entity data (this build)
69
70| Field | Client offset |
71|---|---|
72| `m_fFlags` | `0x33C` |
73| `m_vecVelocity[0]` | `0xE0` |
74| `m_MoveType` (prediction datamap) | `0x164` |
75| `m_iHealth` | `0x80` |
76| `m_iMaxHealth` | not networked |
77| `m_iTeamNum` | `0x88` |
78| `m_vecOrigin` | `0x324` |
79| `m_vecViewOffset[0]` | `0xD4` |
80| `m_vecMins` / `m_vecMaxs` | `0x1A8` / `0x1B4` |
81| `m_lifeState` | `0x7F` |
82| `m_nModelIndex` | `0x7C` |
83
84- Eye position = `m_vecOrigin + m_vecViewOffset` on **all three axes**.
85 (The old code added the X component to Z, which left the eye ~64 units low.)
86- NPC health is not networked. Alive state comes from the networked client
87 `m_lifeState`; real HP is read from the listen-server `CBaseEntity` found via
88 `PEntityOfEntIndex -> edict->m_pUnk -> GetBaseEntity`, using offsets scanned
89 from `server.so`'s datamap:
90 - `m_iHealth` `0xF4`, `m_iMaxHealth` `0xF0`,
91 `m_lifeState` `0xF8`, `m_nModelIndex` `0x7A` (short).
92
93## Menu
94
95Starts fully collapsed on first open. `Insert` toggles; `Up`/`Down` navigate;
96`Enter` expands/toggles; `Left`/`Right` edit values; `Escape` closes.
97Bind rows enter bind-select mode: press a key/button to assign, `Escape` sets
98None (always-on), `Enter` cancels.
99
100```
101HL2hake
102 Bunnyhop
103 Active
104 Uni-directional auto-strafe
105 ABH
106 Active
107 ESP
108 Active
109 Show neutral / healthbar / healthnum / name / skeleton / box
110 Aimbot
111 Active
112 Bind
113 Vischeck
114 Bones -> Head / Torso / Left arm / Right arm / Left leg / Right leg
115 Smoothness (1..45 deg/tick, Left/Right)
116 Triggerbot
117 Active
118 Bind
119 Silent aim
120 Active
121 Bind
122```
123
124Binds use SDL scancodes; mouse buttons are pseudo-scancodes 600..604.
125
126## Bones / ESP
33 127
34Console output uses `ConMsg` from `libtier0.so` (resolved via `dlsym(RTLD_DEFAULT, "_Z6ConMsgPKcz")`), not `IVEngineClient::ClientCmd`. 128- `SetupBones(BONE_USED_BY_ANYTHING)` with engine `Time()`; studio header via
129 `GetStudiomodel`; hitboxes and bone names/parents from that header.
130- HL2 strips many ValveBiped bone names (the zombie's spine/legs/left arm are
131 unnamed), so the humanoid skeleton is built from the **union of hitbox bone
132 parent paths** (`HITGROUP_*`). Head group 1 includes the zombie headcrab body
133 and its `HC_Head` child; fingers, toes and other `HC_*` limbs are excluded.
134- Non-humanoid NPCs (headcrabs, crows, antlions, ...) draw the full bone tree.
135- `aim_points` = head hitbox/bone + hitbox centers for the selected groups;
136 the aim features pick the nearest visible point.
35 137
36## Menu system 138## Aim features
37 139
38- **Toggle architecture**: each feature is runtime-toggleable, ON by default. A `MenuState` struct holds per-feature `active` bool and `bind` (key code or None). 140- Shared target selection (`select_aim_target`): live hostile NPCs, skip
39- **Rendering**: hook `IEngineVGui::Paint` via `VEngineVGui001` — draws every frame including the main menu. Text-only overlay in top-left corner. 141 friendly/neutral, rank by angle to the crosshair, then pick the nearest
40- **Persistence**: INI-style plain text config; one line per setting (`climb_active=1`, `climb_bind=MOUSE3`). Config written on every state change; loaded before hooks install. 142 selected hitgroup point. Target candidates are tried nearest-first.
41- **Input model**: Insert toggles menu open/closed; arrow keys navigate the tree; Enter expands/collapses nodes and toggles boolean fields; Escape closes the menu. Modal while open (all game input blocked). Long-term: selective pass-through for unused inputs. 143- Vischeck: `EngineTraceClient003::TraceRay`, `MASK_VISIBLE`,
42- **Bind assignment UX**: selecting a Bind node enters bind-select mode; any key press becomes the new bind; Escape sets bind to None (disabling the feature); Enter cancels bind change and reverts. 144 `TRACE_WORLD_ONLY` (world only; static props are not tested — deliberate).
43- **Tree layout**: HL2hake (root) → Climb (Active + Bind), Bunnyhop (Active), ABH (Active). Children indented. All nodes expanded by default when the menu opens. 145- Aimbot: bounded smoothing — 0.05 deg deadzone, max `Smoothness` deg/tick,
146 shortest-path yaw, pitch clamped to ±89; pushes the new view with
147 `SetViewAngles`.
148- Triggerbot: crosshair ray with `MASK_SHOT` + `TRACE_EVERYTHING` (filter
149 ignores the local player). First hit must be a live hostile NPC; sets
150 `IN_ATTACK`.
151- Silent aim: exact target angle written to `cmd->viewangles`, `IN_ATTACK`,
152 then the rendered view is restored immediately **and** at
153 `FRAME_RENDER_START`; `forwardmove`/`sidemove` are rewritten to preserve the
154 world-space movement wish vector.
155- ABH: on the landing/jump tick, face opposite the horizontal velocity with
156 zero forward/side movement; HL2's jump speed-bound subtraction then
157 accelerates along the velocity. Camera restored at `FRAME_RENDER_START`.
44 158
45## Open questions 159## Gotchas / lessons
46 160
47None currently. 161- Never pipe-mask build failures:
162 `./build.sh > /tmp/build.log 2>&1; echo rc=$?`.
163- `CHLClient` slot numbers: `CreateMove` 21, `FrameStageNotify` 35.
164- `ISurface` binary slot = SDK header slot + 4; see `src/ISURFACE_STATUS.md`.
165- Silent aim and ABH temporarily replace the usercmd view; silent aim preserves
166 movement, ABH intentionally zeroes it for the jump tick.
167- Aimbot vischeck (`MASK_VISIBLE`/world-only) differs from triggerbot
168 (`MASK_SHOT`/all entities): glass and static props can behave differently.