From a3e769a2a8d6f04fdae4e97d2a39d45e1cb062b8 Mon Sep 17 00:00:00 2001 From: salmonik Date: Mon, 26 Oct 2026 16:20:05 +0100 Subject: ESP: restrict skeleton to humanoid core bones (no fingers/toes/headcrab) --- src/bones.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'src/bones.cpp') diff --git a/src/bones.cpp b/src/bones.cpp index 88aa429..a9c6887 100644 --- a/src/bones.cpp +++ b/src/bones.cpp @@ -182,6 +182,25 @@ static bool hitbox_world(const BoneEntry *e, const Hitbox &b, Vector &out) { return true; } +// HL2 humanoids (combine, metrocop, citizen, zombie, ...) use the ValveBiped +// skeleton. Draw only the core chain: pelvis/spine/neck/head, clavicle to +// hand, thigh to foot. Fingers, toes and extra model bones (e.g. the headcrab +// on a zombie) are skipped. +static bool core_bone_name(const char *n) { + if (!n || strncasecmp(n, "ValveBiped.Bip01_", 17) != 0) + return false; + if (contains_ci(n, "Finger") || contains_ci(n, "Toe") || + contains_ci(n, "Headcrab")) + return false; + static const char *tokens[] = {"Pelvis", "Spine", "Neck", "Head1", + "Clavicle", "UpperArm", "Forearm", "Hand", + "Thigh", "Calf", "Foot", nullptr}; + for (int i = 0; tokens[i]; i++) + if (contains_ci(n, tokens[i])) + return true; + return false; +} + static void dump_hitboxes(const BoneEntry *e) { const StudioHdr *h = e->hdr; logf("hitbox dump: idx=%d sets=%d setidx=%d", e->idx, h->numhitboxsets, @@ -312,6 +331,26 @@ int bone_parent(int idx, int bone) { return bone_at(e->hdr, bone)->parent; } +bool bone_is_skeleton_core(int idx, int bone) { + BoneEntry *e = find_entry(idx); + if (!e || !e->valid || bone < 0 || bone >= e->count) + return false; + return core_bone_name(bone_name_raw(e->hdr, bone)); +} + +int bone_nearest_core_parent(int idx, int bone) { + BoneEntry *e = find_entry(idx); + if (!e || !e->valid || bone < 0 || bone >= e->count) + return -1; + int p = bone_at(e->hdr, bone)->parent; + for (int guard = 0; p >= 0 && p < e->count && guard < 64; guard++) { + if (core_bone_name(bone_name_raw(e->hdr, p))) + return p; + p = bone_at(e->hdr, p)->parent; + } + return -1; +} + bool bone_pos(int idx, int bone, Vector &out) { BoneEntry *e = find_entry(idx); if (!e || !e->valid || bone < 0 || bone >= e->count) -- cgit v1.2.3