<feed xmlns='http://www.w3.org/2005/Atom'>
<title>hl2h/build.sh, 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:09:55Z</updated>
<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>
<entry>
<title>World tint: tint map-static props through IStudioRender</title>
<updated>2026-11-04T00:16:51Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-04T00:16:51Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=76c88403d18ef01e8f15b89fcd6d09f0825a1bfc'/>
<id>urn:sha1:76c88403d18ef01e8f15b89fcd6d09f0825a1bfc</id>
<content type='text'>
Most of the crates are prop_static, which have no client entity, so writing
m_clrRender only reached the three dynamic ones. Hook the StudioRender
interface (VStudioRender025) on the interface object's vtable: substitute the
prop colour in SetColorModulation/SetAlphaModulation while
DrawModelStaticProp is drawing a models/props model, and set the modulation
explicitly before the original draw in case the engine sets it just before the
call.

Vtable indices verified by disassembling CStudioRenderContext: 27 = three
float stores from the argument pointer, 28 = one float, 30 = the
DrawModelInfo_t-drawing entry with three arguments (the 2013 SDK header lists
these slots five positions earlier in this build).
</content>
</entry>
<entry>
<title>World: add world/sky material colour modulation</title>
<updated>2026-11-03T22:21:13Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-03T22:21:13Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=1f7c91905f69baba0aca8265c84deaba2ddac98a'/>
<id>urn:sha1:1f7c91905f69baba0aca8265c84deaba2ddac98a</id>
<content type='text'>
Port Amalgam's modulation approach: obtain IMaterialSystem from the already
loaded materialsystem.so (VMaterialSystem080) and walk materials with
FirstMaterial/NextMaterial/GetMaterial. ColorModulate the "World textures"
group (sky names excluded) and the "SkyBox textures"/sky-named group.

The walk runs only when the enabled groups or colours change, restores white
when disabled, and re-applies after level changes. Before touching materials,
GetNumMaterials() and the first material's name/group are sanity-checked so a
wrong vtable slot logs and aborts instead of walking garbage.

GUI: "World tint" card with world/sky toggles and RGB sliders; config section
[worldtint].
</content>
</entry>
<entry>
<title>Fix undefined fullbright symbols; link with --no-undefined</title>
<updated>2026-11-03T21:44:22Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-03T21:44:22Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=5f256e1f92bf7b495667a0ff453b491f98a38fbf'/>
<id>urn:sha1:5f256e1f92bf7b495667a0ff453b491f98a38fbf</id>
<content type='text'>
The fullbright_update/fullbright_invalidate definitions were lost when the
old text-menu section was removed, leaving undefined symbols that made the
dynamic loader reject libhl2hake.so. Restore both definitions and add
-Wl,--no-undefined so missing definitions fail the build instead of the game.
</content>
</entry>
<entry>
<title>GUI: add F2 preview shell with dummy controls</title>
<updated>2026-10-27T17:02:10Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-10-27T17:02:10Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=0e9f3422e37d0b2d1344efec5ceb07c2246bfcd7'/>
<id>urn:sha1:0e9f3422e37d0b2d1344efec5ceb07c2246bfcd7</id>
<content type='text'>
First vertical slice for the custom ISurface GUI:

- window/sidebar/content shell with Movement, Combat, Visuals, Weapons and
  System categories;
- cards with dummy Active/Bind, collapsible settings, toggles, sliders,
  buttons, bind capture, scrolling and tooltips;
- native OS cursor by releasing SDL relative mode; reasserted while open;
- F2 toggles the preview; Insert still opens the old text tree;
- while the GUI is open, do_move freezes movement/buttons/impulses/view and
  skips combat features; ESP and the speed graph keep drawing.

Dummy controls do not touch the real config yet. The text menu is removed
after feature parity in the next pass.
</content>
</entry>
<entry>
<title>Spread control: override the server FireBullets seed for the local player</title>
<updated>2026-10-27T14:49:54Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-10-27T14:49:54Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=1dd3a4d504e98b8d18f236cb1df1fea366ddc36e'/>
<id>urn:sha1:1dd3a4d504e98b8d18f236cb1df1fea366ddc36e</id>
<content type='text'>
The installed 2024 server ignores the client usercmd random_seed and uses its
own shot seed. Force the server's CBaseEntity::FireBullets RandomSeed call for
the local player only:

- hook the server.so RandomSeed GOT slot (R_386_JUMP_SLOT at 0xce1348);
- read the FireBullets `this` from the caller frame and compare it with the
  local server player base;
- replace the seed with the precomputed best single/shotgun window and step it
  per pellet; NPC shots and everything else pass through.
- client prediction still uses the same chosen usercmd seed, so both sides
  agree on the spread pattern.
</content>
</entry>
<entry>
<title>Aimbot v3: world-only vischeck</title>
<updated>2026-10-26T16:16:35Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-10-26T16:16:35Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=b37e1f6892895e438aa7974e1144a6269d94e4aa'/>
<id>urn:sha1:b37e1f6892895e438aa7974e1144a6269d94e4aa</id>
<content type='text'>
- resolve EngineTraceClient003; TraceRay (slot 4) from the eye to the exact
  selected hitbox/bone point with MASK_VISIBLE
- TRACE_WORLD_ONLY filter as requested (static props are not tested, per SDK)
- Aimbot -&gt; Vischeck toggle, persisted as vischeck=1; when on, blocked targets
  are skipped and the next-nearest candidate is tried
- target candidates are ranked by angle; on each target the nearest visible
  selected hitbox point wins
</content>
</entry>
<entry>
<title>Bones: client-side SetupBones/studiohdr groundwork</title>
<updated>2026-10-26T15:04:18Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-10-26T15:04:18Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=7101b7955071485a9bff33d55fc9f83f117b8f58'/>
<id>urn:sha1:7101b7955071485a9bff33d55fc9f83f117b8f58</id>
<content type='text'>
- bones.cpp: resolve IClientRenderable via IClientUnknown slot 6, validate it
  against IVModelInfo GetModel, call SetupBones (slot 16) with engine Time()
  (slot 14), and parse the studio header (GetStudiomodel, slot 29) for
  bones/bone names/parents and hitboxes
- cache up to 64 entity bone snapshots, refreshed at ~30 Hz
- helpers: bone_find/parent/pos, hitbox_center (e.g. "head")
- debug probe: HL2H_BONE_DEBUG=1 draws a white marker at each NPC's head
  hitbox center and logs bone count/head position once
</content>
</entry>
<entry>
<title>ESP working: NPC detection + authoritative server-side health</title>
<updated>2026-10-26T14:33:02Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-10-26T14:33:02Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=d7edcc9d9e3d90e1c53885870461e046389dee96'/>
<id>urn:sha1:d7edcc9d9e3d90e1c53885870461e046389dee96</id>
<content type='text'>
- entitylist slot 6 (GetHighestEntityIndex); class name via
  GetClientNetworkable -&gt; GetClientClass (replaces the unsafe slot-2 call)
- HL2 SP NPCs: class CAI_BaseNPC + m_lifeState, since NPC m_iHealth is not
  networked; model names from VModelInfoClient006 for labels/friend-foe
- real HP/HP-max from the listen-server entity (IVEngineServer021 -&gt;
  PEntityOfEntIndex -&gt; edict-&gt;m_pUnk -&gt; GetBaseEntity) using offsets scanned
  from server.so's datamap; validated against the client model index
- world_to_screen via IVDebugOverlay003::ScreenPosition (fixes box drift)
- maxs sanity clamp, NPC-only debug logging, neutral colour for wildlife
- build.sh: restore -o libhl2hake.so and add server.cpp
</content>
</entry>
<entry>
<title>Default map d1_town_01 (intro-less, enemies spawned)</title>
<updated>2026-09-14T14:47:32Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-09-14T14:47:32Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/hl2h/commit/?id=8af245ae414cb548a2188030ed8a52b31986252f'/>
<id>urn:sha1:8af245ae414cb548a2188030ed8a52b31986252f</id>
<content type='text'>
</content>
</entry>
</feed>
