diff options
Diffstat (limited to '')
| -rw-r--r-- | src/bones.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
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) { | |||
| 182 | return true; | 182 | return true; |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | // HL2 humanoids (combine, metrocop, citizen, zombie, ...) use the ValveBiped | ||
| 186 | // skeleton. Draw only the core chain: pelvis/spine/neck/head, clavicle to | ||
| 187 | // hand, thigh to foot. Fingers, toes and extra model bones (e.g. the headcrab | ||
| 188 | // on a zombie) are skipped. | ||
| 189 | static bool core_bone_name(const char *n) { | ||
| 190 | if (!n || strncasecmp(n, "ValveBiped.Bip01_", 17) != 0) | ||
| 191 | return false; | ||
| 192 | if (contains_ci(n, "Finger") || contains_ci(n, "Toe") || | ||
| 193 | contains_ci(n, "Headcrab")) | ||
| 194 | return false; | ||
| 195 | static const char *tokens[] = {"Pelvis", "Spine", "Neck", "Head1", | ||
| 196 | "Clavicle", "UpperArm", "Forearm", "Hand", | ||
| 197 | "Thigh", "Calf", "Foot", nullptr}; | ||
| 198 | for (int i = 0; tokens[i]; i++) | ||
| 199 | if (contains_ci(n, tokens[i])) | ||
| 200 | return true; | ||
| 201 | return false; | ||
| 202 | } | ||
| 203 | |||
| 185 | static void dump_hitboxes(const BoneEntry *e) { | 204 | static void dump_hitboxes(const BoneEntry *e) { |
| 186 | const StudioHdr *h = e->hdr; | 205 | const StudioHdr *h = e->hdr; |
| 187 | logf("hitbox dump: idx=%d sets=%d setidx=%d", e->idx, h->numhitboxsets, | 206 | logf("hitbox dump: idx=%d sets=%d setidx=%d", e->idx, h->numhitboxsets, |
| @@ -312,6 +331,26 @@ int bone_parent(int idx, int bone) { | |||
| 312 | return bone_at(e->hdr, bone)->parent; | 331 | return bone_at(e->hdr, bone)->parent; |
| 313 | } | 332 | } |
| 314 | 333 | ||
| 334 | bool bone_is_skeleton_core(int idx, int bone) { | ||
| 335 | BoneEntry *e = find_entry(idx); | ||
| 336 | if (!e || !e->valid || bone < 0 || bone >= e->count) | ||
| 337 | return false; | ||
| 338 | return core_bone_name(bone_name_raw(e->hdr, bone)); | ||
| 339 | } | ||
| 340 | |||
| 341 | int bone_nearest_core_parent(int idx, int bone) { | ||
| 342 | BoneEntry *e = find_entry(idx); | ||
| 343 | if (!e || !e->valid || bone < 0 || bone >= e->count) | ||
| 344 | return -1; | ||
| 345 | int p = bone_at(e->hdr, bone)->parent; | ||
| 346 | for (int guard = 0; p >= 0 && p < e->count && guard < 64; guard++) { | ||
| 347 | if (core_bone_name(bone_name_raw(e->hdr, p))) | ||
| 348 | return p; | ||
| 349 | p = bone_at(e->hdr, p)->parent; | ||
| 350 | } | ||
| 351 | return -1; | ||
| 352 | } | ||
| 353 | |||
| 315 | bool bone_pos(int idx, int bone, Vector &out) { | 354 | bool bone_pos(int idx, int bone, Vector &out) { |
| 316 | BoneEntry *e = find_entry(idx); | 355 | BoneEntry *e = find_entry(idx); |
| 317 | if (!e || !e->valid || bone < 0 || bone >= e->count) | 356 | if (!e || !e->valid || bone < 0 || bone >= e->count) |
