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;