summaryrefslogtreecommitdiffstats
path: root/src/bones.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/bones.cpp63
1 files changed, 42 insertions, 21 deletions
diff --git a/src/bones.cpp b/src/bones.cpp
index a9c6887..35756c2 100644
--- a/src/bones.cpp
+++ b/src/bones.cpp
@@ -91,8 +91,10 @@ struct BoneEntry {
91 void *ent; 91 void *ent;
92 double stamp; 92 double stamp;
93 bool valid; 93 bool valid;
94 bool humanoid;
94 const StudioHdr *hdr; 95 const StudioHdr *hdr;
95 int count; 96 int count;
97 bool core[MAX_BONES];
96 Matrix3x4 mats[MAX_BONES]; 98 Matrix3x4 mats[MAX_BONES];
97}; 99};
98 100
@@ -182,23 +184,41 @@ static bool hitbox_world(const BoneEntry *e, const Hitbox &b, Vector &out) {
182 return true; 184 return true;
183} 185}
184 186
185// HL2 humanoids (combine, metrocop, citizen, zombie, ...) use the ValveBiped 187// HL2 humanoids use the ValveBiped skeleton, but many of its bone names are
186// skeleton. Draw only the core chain: pelvis/spine/neck/head, clavicle to 188// stripped (the zombie's spine/legs/left arm are unnamed). Instead of matching
187// hand, thigh to foot. Fingers, toes and extra model bones (e.g. the headcrab 189// names, mark the paths from every hitbox bone up to the root: that yields the
188// on a zombie) are skipped. 190// chest/spine, arms and legs, while fingers/toes have no hitboxes and the
189static bool core_bone_name(const char *n) { 191// headcrab's HC_* hitbox is skipped explicitly.
190 if (!n || strncasecmp(n, "ValveBiped.Bip01_", 17) != 0) 192static void build_core_mask(BoneEntry *e) {
191 return false; 193 e->humanoid = false;
192 if (contains_ci(n, "Finger") || contains_ci(n, "Toe") || 194 for (int i = 0; i < e->count; i++) {
193 contains_ci(n, "Headcrab")) 195 const char *n = bone_name_raw(e->hdr, i);
194 return false; 196 if (n && strncasecmp(n, "ValveBiped.Bip01_", 17) == 0) {
195 static const char *tokens[] = {"Pelvis", "Spine", "Neck", "Head1", 197 e->humanoid = true;
196 "Clavicle", "UpperArm", "Forearm", "Hand", 198 break;
197 "Thigh", "Calf", "Foot", nullptr}; 199 }
198 for (int i = 0; tokens[i]; i++) 200 }
199 if (contains_ci(n, tokens[i])) 201 memset(e->core, 0, sizeof(e->core));
200 return true; 202 if (!e->humanoid)
201 return false; 203 return;
204 const HitboxSet *s = hitbox_set0(e->hdr);
205 if (!s)
206 return;
207 const Hitbox *boxes = hitboxes(s);
208 for (int i = 0; i < s->numhitboxes; i++) {
209 int b = boxes[i].bone;
210 if (b < 0 || b >= e->count)
211 continue;
212 const char *bn = bone_name_raw(e->hdr, b);
213 if (bn && (contains_ci(bn, "Headcrab") || contains_ci(bn, "HC_") ||
214 contains_ci(bn, "Finger") || contains_ci(bn, "Toe")))
215 continue;
216 int cur = b;
217 for (int guard = 0; cur >= 0 && cur < e->count && guard < 64; guard++) {
218 e->core[cur] = true;
219 cur = bone_at(e->hdr, cur)->parent;
220 }
221 }
202} 222}
203 223
204static void dump_hitboxes(const BoneEntry *e) { 224static void dump_hitboxes(const BoneEntry *e) {
@@ -297,6 +317,7 @@ bool bones_update(int idx, void *ent) {
297 317
298 e->hdr = hdr; 318 e->hdr = hdr;
299 e->count = hdr->numbones; 319 e->count = hdr->numbones;
320 build_core_mask(e);
300 e->valid = true; 321 e->valid = true;
301 e->stamp = now; 322 e->stamp = now;
302 if (g_logged < 4) { 323 if (g_logged < 4) {
@@ -333,18 +354,18 @@ int bone_parent(int idx, int bone) {
333 354
334bool bone_is_skeleton_core(int idx, int bone) { 355bool bone_is_skeleton_core(int idx, int bone) {
335 BoneEntry *e = find_entry(idx); 356 BoneEntry *e = find_entry(idx);
336 if (!e || !e->valid || bone < 0 || bone >= e->count) 357 if (!e || !e->valid || !e->humanoid || bone < 0 || bone >= e->count)
337 return false; 358 return false;
338 return core_bone_name(bone_name_raw(e->hdr, bone)); 359 return e->core[bone];
339} 360}
340 361
341int bone_nearest_core_parent(int idx, int bone) { 362int bone_nearest_core_parent(int idx, int bone) {
342 BoneEntry *e = find_entry(idx); 363 BoneEntry *e = find_entry(idx);
343 if (!e || !e->valid || bone < 0 || bone >= e->count) 364 if (!e || !e->valid || !e->humanoid || bone < 0 || bone >= e->count)
344 return -1; 365 return -1;
345 int p = bone_at(e->hdr, bone)->parent; 366 int p = bone_at(e->hdr, bone)->parent;
346 for (int guard = 0; p >= 0 && p < e->count && guard < 64; guard++) { 367 for (int guard = 0; p >= 0 && p < e->count && guard < 64; guard++) {
347 if (core_bone_name(bone_name_raw(e->hdr, p))) 368 if (e->core[p])
348 return p; 369 return p;
349 p = bone_at(e->hdr, p)->parent; 370 p = bone_at(e->hdr, p)->parent;
350 } 371 }