Bullet Penetration (Basic)

Hello, I wanted to get some feedback on this penetration script I made up (well more like a series of functions), it works but I’m not exactly sure how efficient the whole thing is. Using it with http://steamcommunity.com/sharedfiles/filedetails/?id=122666302



-- Have the bullet penetrate
-- End recursion if the max distance is reached or if it hits an empty space
function BulletPenetrate(start, maxDistance, angle, distance)
	if distance > maxDistance then return false end

	local tr = GetBulletTrace(start, angle, 10)
	local newBulletOrigin

	if tr.Entity ~= NULL then
		if tr.Entity:GetClass() == "prop_physics" then
		end
	end

	if tr.Entity == NULL then
		newBulletOrigin = start
		return newBulletOrigin
	else
		newBulletOrigin = BulletPenetrate(BulletForward(start, angle),
		maxDistance, angle, distance + 1)
	end

	if newBulletOrigin == false then return false end

	return newBulletOrigin
end

-- Checks how far the bullet will travel
function CheckBulletDistance(origin, angle)

	local tr = GetBulletTrace(origin, angle, 10000)
	local endDest = tr.HitPos

	local hitdist = origin:Distance(endDest)

	return hitdist
end

-- Get the trace of the bullet path
function GetBulletTrace(origin, angle, distance)
	local tr = util.TraceLine( {
		start = origin,
		endpos = origin + angle:Forward() * distance,
		filter = function( ent )
			if ( ent:GetClass() == "prop_physics" ) then
				return true
			end
		end} )

	return tr
end

-- Move the bullet forward through the entity
function BulletForward(origin, angle)
	return origin + angle:Forward()
end

function MaterialStrength(matEnum)

	materialStrengths = {
		[MAT_CONCRETE] = 5,
		[MAT_GLASS] = 45,
		[MAT_METAL] = 5,
		[MAT_PLASTIC] = 30,
		[MAT_WOOD] = 30
	}

	return materialStrengths[matEnum]

end

function PenPowerLoss(matEnum)

	materialModifiers = {
		[MAT_CONCRETE] = 80,
		[MAT_GLASS] = 5,
		[MAT_METAL] = 80,
		[MAT_PLASTIC] = 20,
		[MAT_WOOD] = 40
	}

	return materialModifiers[matEnum]
end

-- START HERE
-- Fire a bullet
function FirePenBullet(bullet, owner, maxPenDist)
	if maxPenDist < 0 then return false end

	print("Strength left: ", maxPenDist)

	CheckBulletDistance(bullet.Src, bullet.Dir:Angle())
	local tr = GetBulletTrace(bullet.Src, bullet.Dir:Angle(), 10000)

	owner:FireBullets( bullet )

	if MaterialStrength(tr.MatType) == nil then
		return false
	else
		maxPenDist = maxPenDist - PenPowerLoss(tr.MatType)
	end

	local penTest = BulletPenetrate(tr.HitPos, MaterialStrength(tr.MatType), bullet.Dir:Angle(), 0)
	if penTest ~= false then
		bullet.Src = penTest
		owner:FireBullets( bullet )
	end

	if maxPenDist > 0 then FirePenBullet(bullet, owner, maxPenDist) end

	return true
end


[lua]
function MaterialStrength(matEnum)

materialStrengths = {
	[MAT_CONCRETE] = 5,
	[MAT_GLASS] = 45,
	[MAT_METAL] = 5,
	[MAT_PLASTIC] = 30,
	[MAT_WOOD] = 30
}

return materialStrengths[matEnum]

end

function PenPowerLoss(matEnum)

materialModifiers = {
	[MAT_CONCRETE] = 80,
	[MAT_GLASS] = 5,
	[MAT_METAL] = 80,
	[MAT_PLASTIC] = 20,
	[MAT_WOOD] = 40
}
return materialModifiers[matEnum]

end
[/lua]

In these functions, you can move the table definitions to the start of your file, so you don’t constantly have to rebuild the table with each call. Apart from that, looks alright if you ask me. Also, here, you can merge the 2 if statements:

[lua]
if tr.Entity ~= NULL then
if tr.Entity:GetClass() == “prop_physics” then
end
end

if tr.Entity == NULL then
	newBulletOrigin = start
	return newBulletOrigin
else
	newBulletOrigin = BulletPenetrate(BulletForward(start, angle),
	maxDistance, angle, distance + 1)
end

[/lua]

would become

[lua]
if tr.Entity == NULL then
newBulletOrigin = start
return newBulletOrigin
else
if tr.Entity:GetClass() == “prop_physics” then

	end
	newBulletOrigin = BulletPenetrate(BulletForward(start, angle),
	maxDistance, angle, distance + 1)
end

[/lua]

Thanks for this one, don’t know why I didn’t think about doing that earlier.

2nd part I was a bit silly with, it had a little message that popped up on console if I hit a prop, but I don’t really need to do that anymore.