summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--CONTEXT.md185
-rw-r--r--src/ISURFACE_STATUS.md36
-rw-r--r--src/hl2h.h5
-rw-r--r--src/menu.cpp24
-rw-r--r--src/netvars.cpp44
-rw-r--r--tree9
6 files changed, 180 insertions, 123 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.
diff --git a/src/ISURFACE_STATUS.md b/src/ISURFACE_STATUS.md
index de952cd..00a7adf 100644
--- a/src/ISURFACE_STATUS.md
+++ b/src/ISURFACE_STATUS.md
@@ -1,13 +1,13 @@
1# HL2hake ISurface Drawing — Status Report 1# HL2hake ISurface Drawing — Status Report
2 2
3## Date: 2026-09-12 (final round) 3## Date: 2026-09-12, updated 2026-10-26
4 4
5## Result: WORKING 5## Result: WORKING
6 6
7Overlay drawing works in-game and in menus. Draw path: `PaintTraverseEx` 7Overlay drawing works in-game and in menus. Draw path: `PaintTraverseEx`
8hook (slot 114) on the copied ISurface vtable, wrapping our draws in 8hook (slot 114) on the copied ISurface vtable, wrapping our draws in
9`PushMakeCurrent(panel, false)` / `PopMakeCurrent(panel)` around ISurface 9`PushMakeCurrent(panel, false)` / `PopMakeCurrent(panel)` around ISurface
10slots 6/10/12/17/18/20/22/66/67. 10slots 6/10/12/15/17/18/20/22/66/67.
11 11
12## Confirmed ISurface VTable Slots (disassembly-verified, binary=SDK header+4) 12## Confirmed ISurface VTable Slots (disassembly-verified, binary=SDK header+4)
13 13
@@ -18,6 +18,8 @@ slots 6/10/12/17/18/20/22/66/67.
18| 9 | `PopMakeCurrent(VPANEL)` | verified via disassembly | 18| 9 | `PopMakeCurrent(VPANEL)` | verified via disassembly |
19| 10 | `DrawSetColor(int r,g,b,a)` | stores RGBA at `this+0x24..0x27` | 19| 10 | `DrawSetColor(int r,g,b,a)` | stores RGBA at `this+0x24..0x27` |
20| 12 | `DrawFilledRect(int x0,y0,x1,y1)` | verified via disassembly | 20| 12 | `DrawFilledRect(int x0,y0,x1,y1)` | verified via disassembly |
21| 14 | `DrawOutlinedRect(int x0,y0,x1,y1)` | SDK header 10 + 4 |
22| 15 | `DrawLine(int x0,y0,x1,y1)` | SDK header 11 + 4 (skeleton ESP) |
21| 17 | `DrawSetTextFont(HFont)` | stores HFont at `this+0x290` | 23| 17 | `DrawSetTextFont(HFont)` | stores HFont at `this+0x290` |
22| 18 | `DrawSetTextColor(int r,g,b,a)` | stores RGBA at `this+0x28..0x2b` | 24| 18 | `DrawSetTextColor(int r,g,b,a)` | stores RGBA at `this+0x28..0x2b` |
23| 20 | `DrawSetTextPos(int x,y)` | stores at `this+0x2c/0x30` | 25| 20 | `DrawSetTextPos(int x,y)` | stores at `this+0x2c/0x30` |
@@ -65,24 +67,27 @@ fc-match findings (system fontconfig):
65 67
66## Menu 68## Menu
67 69
68- Tree: HL2hake → Bunnyhop/ABH, children indented (`g_depth[]`, +12px/level). 70- Starts fully collapsed on first open; `Insert` toggles it.
69- Right-aligned state at x=200: `[on]`/`[off]` for Active rows, 71- Tree: HL2hake -> Bunnyhop (Active, Auto-strafe), ABH (Active), ESP (Active,
70 `[keyname]` for Bind rows, `[press key]` while binding. 72 Show neutral/healthbar/healthnum/name/skeleton/box), Aimbot (Active, Bind,
73 Vischeck, Bones, Smoothness), Triggerbot (Active, Bind), Silent aim
74 (Active, Bind). Children indented by `g_depth[]` (+12px/level).
75- Right-aligned state at x=270: `[on]`/`[off]` for toggles, `[keyname]` for
76 binds, `[press key]` while binding, `N deg/tick` for values.
71- Feature gating: `feature_active(int)` (menu.cpp) — active AND 77- Feature gating: `feature_active(int)` (menu.cpp) — active AND
72 (bind==0 or key held). Called from `do_move` (hl2h.cpp) to gate 78 (bind==0 or key held), used by `do_move` and the aim features.
73 bhop (jump) and ABH branches. 79- Config: `$XDG_CONFIG_HOME/hl2hake/config` (fallback `~/.config/hl2hake/config`).
74- Config: INI at `~/.hl2hake.ini` (bhop/abh active+bind).
75 80
76## Build / Run 81## Build / Run
77 82
78- `./build.sh`: g++ `-m32 -O2 -fPIC -shared`, links 5 TUs, `-ldl`, 83- `./build.sh`: g++ `-m32 -O2 -std=c++17 -fPIC -shared`, 9 TUs
84 (`hl2h modules cinput netvars menu esp server bones vischeck`), `-ldl`,
79 `-Wall -Wextra -Werror` (all warnings fatal). 85 `-Wall -Wextra -Werror` (all warnings fatal).
80- `./play.sh -windowed +map d1_trainstation_01` (Steam runtime wrapper, 86- `./play.sh -windowed +map d1_trainstation_01` (Steam runtime wrapper,
81 `LD_PRELOAD=libhl2hake.so`). 87 `LD_PRELOAD=libhl2hake.so`).
82- Logs: `/tmp/hl2hake.log` (logf), `/tmp/hl2run.log` (stderr). 88- Logs: `/tmp/hl2hake.log` (logf), stderr.
83- Probe logging (`hook fired:`, `probe:`) removed 2026-09-12.
84- `HL2H_DRAW_TEST=1` env: draws red rect + "HL2H DRAW TEST" without 89- `HL2H_DRAW_TEST=1` env: draws red rect + "HL2H DRAW TEST" without
85 opening the menu. 90 opening the menu. `HL2H_BONE_DEBUG=1` draws head-hitbox markers.
86 91
87## Lessons 92## Lessons
88 93
@@ -98,7 +103,12 @@ fc-match findings (system fontconfig):
98## File Locations 103## File Locations
99 104
100- Project: `/home/salmon/Documents/rust/hl2h/` 105- Project: `/home/salmon/Documents/rust/hl2h/`
101- Hook + feature logic: `src/hl2h.cpp` 106- Hook + movement/feature logic: `src/hl2h.cpp`
102- Menu + drawing + config + input: `src/menu.cpp` 107- Menu + drawing + config + input: `src/menu.cpp`
108- ESP / skeleton drawing / aimbot / silent aim: `src/esp.cpp`
109- Bones + hitboxes: `src/bones.cpp`
110- Server-side entity/health access: `src/server.cpp`
111- World vischeck / entity trace: `src/vischeck.cpp`
103- Shared API: `src/hl2h.h` 112- Shared API: `src/hl2h.h`
113- Current project overview: `CONTEXT.md`
104- SDK headers: `source-sdk-2013/src/public/vgui/` 114- SDK headers: `source-sdk-2013/src/public/vgui/`
diff --git a/src/hl2h.h b/src/hl2h.h
index a08f029..37c849f 100644
--- a/src/hl2h.h
+++ b/src/hl2h.h
@@ -168,7 +168,6 @@ void fix_verified_crc(int seq, uint32_t crc);
168uint32_t usercmd_checksum(const CUserCmd *c); 168uint32_t usercmd_checksum(const CUserCmd *c);
169bool find_input_global(); 169bool find_input_global();
170void resolve_netvars(); 170void resolve_netvars();
171int class_health_off(const char *name);
172bool resolve_server_netvars(); 171bool resolve_server_netvars();
173int server_entity_health(int idx, int *maxhealth, int *lifestate, void **base_out); 172int server_entity_health(int idx, int *maxhealth, int *lifestate, void **base_out);
174int server_model_index(void *base); 173int server_model_index(void *base);
@@ -203,10 +202,6 @@ bool head_position(int idx, Vector &out);
203int aim_points(int idx, unsigned group_mask, Vector *out, int max); 202int aim_points(int idx, unsigned group_mask, Vector *out, int max);
204 203
205void outer_draw(); 204void outer_draw();
206// raw ISurface slot calls used by the PaintTraverseEx hook (hl2h.cpp)
207using SurfFn = void (*)(void *, ...);
208long surf_call_slot(void *surf, int slot, long a1 = 0, long a2 = 0);
209
210// ISurface pointer (defined in menu.cpp, used for drawing tests) 205// ISurface pointer (defined in menu.cpp, used for drawing tests)
211struct ISurface; 206struct ISurface;
212extern ISurface *g_surface; 207extern ISurface *g_surface;
diff --git a/src/menu.cpp b/src/menu.cpp
index c3bb9ae..d628873 100644
--- a/src/menu.cpp
+++ b/src/menu.cpp
@@ -217,22 +217,6 @@ static std::string config_path() {
217 return dir + "/config"; 217 return dir + "/config";
218} 218}
219 219
220[[maybe_unused]] static const char *sdl_scancode_name(int sc) {
221 if (sc == 0)
222 return "None";
223 static char buf[32];
224 snprintf(buf, sizeof(buf), "Key%d", sc);
225 return buf;
226}
227
228[[maybe_unused]] static int parse_sdl_scancode(const char *s) {
229 if (strcmp(s, "None") == 0 || strcmp(s, "") == 0)
230 return 0;
231 if (strncmp(s, "Key", 3) == 0)
232 return atoi(s + 3);
233 return 0;
234}
235
236static void config_save() { 220static void config_save() {
237 FILE *f = fopen(config_path().c_str(), "w"); 221 FILE *f = fopen(config_path().c_str(), "w");
238 if (!f) 222 if (!f)
@@ -758,14 +742,6 @@ void outer_draw() {
758 surf_pop_make_current(panel); 742 surf_pop_make_current(panel);
759} 743}
760 744
761// Call an arbitrary ISurface vtable slot with up to 2 long args (cdecl thiscall
762// on i386: this first, rest on stack).
763long surf_call_slot(void *surf, int slot, long a1, long a2) {
764 void **vt = *(void ***)surf;
765 using Fn = long (*)(void *, long, long);
766 return ((Fn)vt[slot])(surf, a1, a2);
767}
768
769// --------------------------------------------------------------------------- 745// ---------------------------------------------------------------------------
770// ISurface discovery — try known modules and all loaded .so files 746// ISurface discovery — try known modules and all loaded .so files
771// --------------------------------------------------------------------------- 747// ---------------------------------------------------------------------------
diff --git a/src/netvars.cpp b/src/netvars.cpp
index f702c41..b4e31d5 100644
--- a/src/netvars.cpp
+++ b/src/netvars.cpp
@@ -27,24 +27,7 @@ static bool module_string(uintptr_t p, char *out, size_t outn) {
27 27
28static int g_dumped_tables = 0; 28static int g_dumped_tables = 0;
29 29
30// per-client-class health offset (m_iHealth lives at different offsets per 30static void collect_netvars(uintptr_t table, uintptr_t base_off, int depth) {
31// class chain: CBasePlayer via DT_BasePlayer=128, NPCs via DT_BaseCombatCharacter)
32static struct {
33 char name[32];
34 int off;
35} g_class_health[256];
36static int g_class_health_n = 0;
37
38int class_health_off(const char *name) {
39 for (int i = 0; i < g_class_health_n; i++)
40 if (strcmp(name, g_class_health[i].name) == 0)
41 return g_class_health[i].off;
42 return -1;
43}
44
45static void collect_netvars(uintptr_t table, uintptr_t base_off, int depth,
46 int *out_health)
47{
48 if (depth > 8) 31 if (depth > 8)
49 return; 32 return;
50 uintptr_t props = *(uintptr_t *)(table + 0x00); 33 uintptr_t props = *(uintptr_t *)(table + 0x00);
@@ -85,13 +68,10 @@ static void collect_netvars(uintptr_t table, uintptr_t base_off, int depth,
85 logf(" [%s] %s type=%d off=%d(0x%x) table=%s array=%s", tname, pname2, 68 logf(" [%s] %s type=%d off=%d(0x%x) table=%s array=%s", tname, pname2,
86 ptype, poff, poff, ptable ? "yes" : "no", parray ? "yes" : "no"); 69 ptype, poff, poff, ptable ? "yes" : "no", parray ? "yes" : "no");
87 if (ptable) { 70 if (ptable) {
88 collect_netvars(ptable, base_off + (uint32_t)poff, depth + 1, 71 collect_netvars(ptable, base_off + (uint32_t)poff, depth + 1);
89 out_health);
90 continue; 72 continue;
91 } 73 }
92 74
93 if (out_health && *out_health < 0 && strcmp(pname2, "m_iHealth") == 0)
94 *out_health = (int)(base_off + (uint32_t)poff);
95 if (strcmp(pname2, "m_lifeState") == 0 && g_net.lifestate < 0) { 75 if (strcmp(pname2, "m_lifeState") == 0 && g_net.lifestate < 0) {
96 g_net.lifestate = (int)(base_off + (uint32_t)poff); 76 g_net.lifestate = (int)(base_off + (uint32_t)poff);
97 } else if (strcmp(pname2, "m_nModelIndex") == 0 && g_net.modelindex < 0) { 77 } else if (strcmp(pname2, "m_nModelIndex") == 0 && g_net.modelindex < 0) {
@@ -217,25 +197,9 @@ void resolve_netvars() {
217 for (uintptr_t cc = head; cc && g_client.contains(cc) && classes < 1024; 197 for (uintptr_t cc = head; cc && g_client.contains(cc) && classes < 1024;
218 cc = *(uintptr_t *)(cc + 0x10)) { 198 cc = *(uintptr_t *)(cc + 0x10)) {
219 classes++; 199 classes++;
220 char cname[32]; 200 collect_netvars(*(uintptr_t *)(cc + 0x0C), 0, 0);
221 int hoff = -1;
222 // per-class health offset — NPCs send m_iHealth via their own table chain,
223 // not DT_BasePlayer's; g_net.health keeps the player's for aimbot use
224 if (module_string(*(uintptr_t *)(cc + 0x08), cname, sizeof(cname))) {
225 collect_netvars(*(uintptr_t *)(cc + 0x0C), 0, 0, &hoff);
226 if (hoff >= 0 && g_class_health_n < 256) {
227 char *dst = g_class_health[g_class_health_n].name;
228 const char *src = cname;
229 size_t n = sizeof(g_class_health[g_class_health_n].name) - 1;
230 for (size_t i = 0; i < n && src[i]; i++) dst[i] = src[i];
231 dst[n] = 0;
232 g_class_health[g_class_health_n].off = hoff;
233 g_class_health_n++;
234 }
235 }
236 } 201 }
237 logf("client classes walked: %d, health-offset classes: %d", classes, 202 logf("client classes walked: %d", classes);
238 g_class_health_n);
239 203
240 if (g_net.movetype < 0 && !resolve_movetype()) { 204 if (g_net.movetype < 0 && !resolve_movetype()) {
241 // movetype unresolved — bhop still works, just no noclip/ladder guard 205 // movetype unresolved — bhop still works, just no noclip/ladder guard
diff --git a/tree b/tree
deleted file mode 100644
index a03e5af..0000000
--- a/tree
+++ /dev/null
@@ -1,9 +0,0 @@
1HL2hake
2
3Climb
4 Active: <state>
5 Bind: <bind>
6Bunnyhop
7 Active: <state>
8ABH
9 Active: <state>