<feed xmlns='http://www.w3.org/2005/Atom'>
<title>hl2h, branch master</title>
<subtitle>Simple internal C++ cheat for HL2 for GNU/Linux.
</subtitle>
<id>https://git.2137697.xyz/hl2h/atom?h=master</id>
<link rel='self' href='https://git.2137697.xyz/hl2h/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/'/>
<updated>2026-11-06T15:30:21Z</updated>
<entry>
<title>docs: record the settings table in the plan</title>
<updated>2026-11-06T15:30:21Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-06T15:30:21Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=7ddd5c680a28b32c0ba864699864e8b6b090d664'/>
<id>urn:sha1:7ddd5c680a28b32c0ba864699864e8b6b090d664</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Config: generate save/load/reset from one settings table</title>
<updated>2026-11-06T15:30:10Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-06T15:30:10Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=e339d1dc45b3113648552b0002e0c15f55e61cb2'/>
<id>urn:sha1:e339d1dc45b3113648552b0002e0c15f55e61cb2</id>
<content type='text'>
Every persisted setting now lives in a single descriptor table
(config_table.cpp) with its section, key, type, default and clamp range.
config_save(), config_load() and config_reset_defaults() iterate it, so the
three functions can no longer disagree about defaults or bounds, and the old
hand-written 350-line parser is gone.

Section and key names are unchanged, so existing config files keep loading, and
the duplicated [view] scalar clamp block is replaced by per-entry limits.
</content>
</entry>
<entry>
<title>docs: record the esp.cpp split in the plan</title>
<updated>2026-11-06T15:26:47Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-06T15:26:47Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=181fee4681e3ec65536dafd8a2093c44bdf8fdba'/>
<id>urn:sha1:181fee4681e3ec65536dafd8a2093c44bdf8fdba</id>
<content type='text'>
</content>
</entry>
<entry>
<title>ESP: finish the split into entity, combat, item and projectile units</title>
<updated>2026-11-06T15:25:48Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-06T15:25:48Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=c43cb2e42a5ac1cc09f83cd72fa7e568c9ef37e1'/>
<id>urn:sha1:c43cb2e42a5ac1cc09f83cd72fa7e568c9ef37e1</id>
<content type='text'>
esp.cpp keeps the scan and drawing (~1000 lines, down from 3665). Entity
lookups and NPC classification move to entity_query.cpp together with the
per-map caches and the session reset; combat (aimbot, silent aim, melee,
spread, triggerbot) moves to combat.cpp. Shared helpers are declared in
esp_internal.h.
</content>
</entry>
<entry>
<title>ESP: extract item ESP into its own translation unit</title>
<updated>2026-11-06T15:23:29Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-06T15:23:29Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=5a9fd14f9424d7f66b0454464be95b40b10ee5c4'/>
<id>urn:sha1:5a9fd14f9424d7f66b0454464be95b40b10ee5c4</id>
<content type='text'>
Second slice of the esp.cpp split. Model-name lookup joins the shared helpers in
esp_internal.h.
</content>
</entry>
<entry>
<title>ESP: extract projectile ESP into its own translation unit</title>
<updated>2026-11-06T15:23:01Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-06T15:23:01Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=7352766582e140483ebcc1d8660a76e1bccbec0d'/>
<id>urn:sha1:7352766582e140483ebcc1d8660a76e1bccbec0d</id>
<content type='text'>
First slice of the esp.cpp split. Shared helpers move to esp_internal.h
(entity lookups, screen size, surf primitives, segment projection); esp.cpp
keeps the definitions and drops their static qualifiers.
</content>
</entry>
<entry>
<title>Headers: split the shared header by declaration group</title>
<updated>2026-11-06T15:21:27Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-06T15:21:27Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=3c27e7ce262e612fa75c6e6f090e04041a688861'/>
<id>urn:sha1:3c27e7ce262e612fa75c6e6f090e04041a688861</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>Hooks: central vtable install with restore support</title>
<updated>2026-11-06T15:19:25Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-06T15:19:25Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=9f0724dcd25a06c5674d30d045dc485a341253b1'/>
<id>urn:sha1:9f0724dcd25a06c5674d30d045dc485a341253b1</id>
<content type='text'>
Move vtable patching into hooks.cpp: one call clones the table, validates every
slot, records the originals and installs the clone. Installs happen from the
setup, game and paint threads, so the bookkeeping is mutex-protected.

Client, CInput, IVModelRender, IStudioRender and ISurface all use it, and
hooks_restore_all() can now put every interface back (previously impossible).
</content>
</entry>
<entry>
<title>Chams: leave engine-forced material passes alone</title>
<updated>2026-11-06T15:17:02Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-06T15:17:02Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=8a5efe20e6e077e10592aa427d704836d2a08dd1'/>
<id>urn:sha1:8a5efe20e6e077e10592aa427d704836d2a08dd1</id>
<content type='text'>
Shadow-depth and reflection passes call DrawModelExecute with a material
already forced via IVModelRender::ForcedMaterialOverride. Chams could not tell
that apart from a free draw, substituted its own material (putting chams into
the shadow map) and then cleared the override to null, which broke the shadow
material for every model drawn afterwards.

Hook slot 1 as a tracker so the current forced material is known, and skip the
chams substitution whenever one is active.
</content>
</entry>
<entry>
<title>Fix audit findings: crash safety, correctness, rendering, performance</title>
<updated>2026-11-06T15:09:55Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-06T15:09:55Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=33f5ed9ef58f26c6b3b52cf605dd4311d658a60d'/>
<id>urn:sha1:33f5ed9ef58f26c6b3b52cf605dd4311d658a60d</id>
<content type='text'>
Crash/UB:
- gate every hook behind an init-stage flag until config/surface/input are ready
- publish module maps as immutable atomic snapshots instead of reallocating
  shared vectors under unlocked readers
- validate the %ebp walk in the RandomSeed/RandomFloat hooks against the stack
- bounds-check every RecvTable/RecvProp/string dereference with module_range()
- preserve the Itanium vtable header when cloning (client, CInput, model render,
  studio render)
- reject negative usercmd sequence numbers; guard config_load against a null
  section target; cap the bone parent walk; check mprotect; drop PROT_EXEC on
  the GOT patch; absorb server.so .bss tail

Correctness:
- filter dormant entities across ESP, aimbot, triggerbot, melee, items and
  projectiles (slot self-tested against the local player)
- reset the server-health latch per map and only latch on valid model indices
- bone cache sized for the 128-target scan; set valid=false on every failure;
  head_position keeps searching past an invalid bone
- vischeck steps past glass by probing until clear, and ignores entities owned
  by the target (held weapons, bone followers)
- aimbot: maxs no longer disables it, AABB-aware FOV prefilter, lock hysteresis,
  lead point re-checked for FOV and visibility
- spread: seed hook arms on the no-spread toggle alone; engine toggle only
  controls the RandomFloat zeroing
- resolve m_hOwnerEntity/m_hOwner; NPC lead velocity from the server entity
- vector_angles pitch range, point_ground normal test, underwater jump+duck no
  longer skips combat, semi-auto press/release edge for synthetic fire
- item/projectile markers and blast rings refresh origin per frame while
  discovery stays at 10 Hz; trajectory uses the real m_DmgRadius and honours
  the blast-radius toggle

Rendering/GUI:
- one overlay draw per engine frame (FRAME_RENDER_START boundary), fixing
  alpha stacking and the speed-graph flicker
- clipped lines/outlines and ellipsised text instead of drawing past the
  content pane or shifting over neighbours
- dropdown dismissal consumes the click; hover ignores hidden controls
- chams: reset AlphaModulate, reference shared materials once, restore prop
  tint colour; fonts created once per handle
- projection uses Source's 4:3 aspect scaling and roll; screen size refreshed
  each frame; FOV circle gated on the aim toggles, not the bind

Performance:
- TTL caches for NPC relation, friendly/neutral and damage class
- model names memoised per model index
- entity pointer -&gt; index cache for the triggerbot (was a 4096-slot walk/tick)

Build:
- real Makefile with -MMD dependency tracking, debug/release objects and an
  always-relink rule; build.sh kept as a thin wrapper
</content>
</entry>
</feed>
