From d156c4d06abca9284cb116063494355f53354d86 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 28 Oct 2026 13:54:16 +0100 Subject: Handles: use the 11-bit networked EHANDLE entity index The client m_hActiveWeapon is a networked EHANDLE: low 11 bits are the entity index and the rest is the serial. Masking with 0xFFFF included serial bits, so on later maps the weapon index became garbage (e.g. 49184/12319) and melee killbot could not recognize the crowbar. Use 0x7FF for client and server active-weapon handles, weapon owner checks and item-ESP weapon skips. Document the layout in CONTEXT. --- CONTEXT.md | 4 ++++ src/esp.cpp | 8 ++++---- src/server.cpp | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index a9b85b9..5f27572 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -283,6 +283,10 @@ vocabulary / decisions. - Never pipe-mask build failures: `./build.sh > /tmp/build.log 2>&1; echo rc=$?`. - `CHLClient` slot numbers: `CreateMove` 21, `FrameStageNotify` 35. +- Networked EHANDLE values use an 11-bit entity index in the low bits; bits + 11+ are the serial. Mask with `0x7FF`, not the local `CBaseHandle` 16-bit + mask. This caused active-weapon lookups to produce bogus indices after a + map change once the weapon serial was nonzero (melee killbot looked dead). - `ISurface` binary slot = SDK header slot + 4; see `src/ISURFACE_STATUS.md`. - Silent aim and ABH temporarily replace the usercmd view; silent aim preserves movement, ABH intentionally zeroes it for the jump tick. diff --git a/src/esp.cpp b/src/esp.cpp index a0d84dd..3db25e6 100644 --- a/src/esp.cpp +++ b/src/esp.cpp @@ -675,7 +675,7 @@ static bool active_weapon_contains(void *local_ent, const char *needle) { uint32_t h = *(uint32_t *)((uintptr_t)local_ent + g_net.activeweapon); if (h == 0xFFFFFFFFu) return false; - int idx = (int)(h & 0xFFFF); + int idx = (int)(h & 0x7FF); // networked EHANDLE: 11-bit entity index if (idx <= 0 || idx > 4096) return false; void *wep = entitylist_get(idx); @@ -902,7 +902,7 @@ bool melee_weapon_active(void *local_ent) { if (g_net.activeweapon >= 0) { uint32_t h = *(uint32_t *)((uintptr_t)local_ent + g_net.activeweapon); if (h != 0xFFFFFFFFu) - idx = (int)(h & 0xFFFF); + idx = (int)(h & 0x7FF); // 11-bit entity index; upper bits are serial } const char *cls = nullptr, *model = nullptr; bool crowbar = check(idx, &cls, &model); @@ -1221,7 +1221,7 @@ static bool active_weapon_is_shotgun(void *local_ent) { uint32_t h = *(uint32_t *)((uintptr_t)local_ent + g_net.activeweapon); if (h == 0xFFFFFFFFu) return false; - int idx = (int)(h & 0xFFFF); + int idx = (int)(h & 0x7FF); // networked EHANDLE: 11-bit entity index if (idx <= 0 || idx > 4096) return false; void *wep = entitylist_get(idx); @@ -1486,7 +1486,7 @@ static int local_active_weapon_idx(int local_idx) { uint32_t h = *(uint32_t *)((uintptr_t)local + g_net.activeweapon); if (!item_handle_valid(h)) return -1; - return (int)(h & 0xFFFF); + return (int)(h & 0x7FF); } static int classify_weapon(const char *model, const char *cls, char *label, diff --git a/src/server.cpp b/src/server.cpp index 115cd53..5599227 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -210,6 +210,6 @@ int server_active_weapon(int idx) { uint32_t h = *(uint32_t *)((uintptr_t)base + g_srv_activeweapon); if (h == 0xFFFFFFFFu) return -1; - int wi = (int)(h & 0xFFFF); + int wi = (int)(h & 0x7FF); // 11-bit entity index return (wi > 0 && wi <= 4096) ? wi : -1; } -- cgit v1.2.3