#define CG_BONES 36
#define CG_BONE_PAD 3.0
#define CG_BONE_LIMIT 128.0
stock corpseFitBox(iEnt)
{
if (!pev_valid(iEnt))
return;
new Float:origin[3];
pev(iEnt, pev_origin, origin);
new Float:mins[3];
new Float:maxs[3];
for (new axis; axis < 3; axis++)
{
mins[axis] = 99999.0;
maxs[axis] = -99999.0;
}
new found;
// GetBonePosition возвращает координаты костей
// в мировом пространстве. Не вращаем их повторно.
for (new bone; bone < CG_BONES; bone++)
{
new Float:bonePos[3];
new Float:boneAngles[3];
engfunc(
EngFunc_GetBonePosition,
iEnt,
bone,
bonePos,
boneAngles
);
new bool:valid = true;
for (new axis; axis < 3; axis++)
{
new Float:delta = bonePos[axis] - origin[axis];
if (floatabs(delta) > CG_BONE_LIMIT)
{
valid = false;
break;
}
}
if (!valid)
continue;
for (new axis; axis < 3; axis++)
{
new Float:delta = bonePos[axis] - origin[axis];
mins[axis] = floatmin(mins[axis], delta);
maxs[axis] = floatmax(maxs[axis], delta);
}
found++;
}
// Если скелет не удалось прочитать,
// не используем случайные экстремальные значения.
if (!found)
{
mins[0] = -32.0;
mins[1] = -32.0;
mins[2] = -24.0;
maxs[0] = 32.0;
maxs[1] = 32.0;
maxs[2] = 24.0;
}
else
{
for (new axis; axis < 3; axis++)
{
mins[axis] -= CG_BONE_PAD;
maxs[axis] += CG_BONE_PAD;
}
}
// Не делаем искусственно плоский Z-бокс.
// Важно: mins/maxs здесь задаются относительно origin.
engfunc(EngFunc_SetSize, iEnt, mins, maxs);
// Не перемещаем модель к центру рассчитанного бокса:
// это сместило бы её визуально.
engfunc(EngFunc_SetOrigin, iEnt, origin);
#if defined CG_DEBUG
server_print(
"[CorpseGore] ent=%d bones=%d "
"mins=(%.1f %.1f %.1f) maxs=(%.1f %.1f %.1f)",
iEnt,
found,
mins[0], mins[1], mins[2],
maxs[0], maxs[1], maxs[2]
);
#endif
}