Here's some rough pseudocode (with some exact function calls and syntax where more needed)
function firePenetratingBullet(penetratingTypes, intialDamage, damageLoss, numentrys, ignoreobject)
{
%ray = containerRayCast(muzzlePos, endPos, hitTypes, ignoreobject)
%pos = posfromraycast(%ray)
spawn explosion at %pos
%obj = objfromraycast(%ray)
if obj.getType() & $TypeMasks::PlayerObjectType
damage player
if (obj.getType() & penetratingTypes) && numentrys > 0
firePenetratingBullet(penetratingTypes, initialDamage * (1-damageLoss), damageLoss, numentrys-1,%obj)
}
penetratingTypes defines what types the bullet will penetrate through
hitTypes defines what types the bullet will interact with; that is, be stopped by OR travel through
Both are a series a typemaks and bitwise or operators (ex: $TypeMasks::PlayerObjectType | $TypeMasks::FxBrickObjectType | $TypeMasks::VehicleObjectType will hit players, bricks, and vehicles)
ignoreobj should be the object firing the weapon (most likely the player)