Making blood decals consistent with blood drips - FreeSlave/halflife-updated GitHub Wiki
If you shoot a security guard in the helmet, there will be no blood drips, but the blood decal will appear on the wall behind him. Let's figure why it happens.
Usually when a monster gets shot, its TraceAttack
function gets called, which among other lines call these functions:
SpawnBlood(ptr->vecEndPos, BloodColor(), flDamage); // a little surface blood.
TraceBleed(flDamage, vecDir, ptr, bitsDamageType);
SpawnBlood
calls UTIL_BloodDrips
, casting the floating point value of damage to integer (dropping the fractional part of the number). The more damage means more blood drips.
In specific case of barney, when he gets shot in the helmet, the code in its TraceAttack
override may decrease the damage almost to zero:
if ((bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_CLUB)) != 0)
{
flDamage -= 20;
if (flDamage <= 0)
{
UTIL_Ricochet(ptr->vecEndPos, 1.0);
flDamage = 0.01;
}
}
In SpawnBlood
it gets truncated to 0 before passing to UTIL_BloodDrips
which means no blood drips will be shown.
TraceBleed
is responsilbe for making blood decals. The more damage means more decals. However unlike SpawnBlood
, it doesn't cast the value to integer before the check. So even if the damage value is small (like in case of shooting barney in the helmet), the decals will spawn anyway. To fix this we simply apply the same logic as with SpawnBlood
and UTIL_BloodDrips
, truncating the value to integer before the check.
Go to dlls/combat.cpp
, in TraceBleed
function apply the following:
- if (flDamage == 0)
+ if ((int)flDamage == 0)
return;