I have successfully implemented hierarchical bullet ricochet, skimming, and skewing.
Right now, the system will use this little bit of code:
-- Process ricochets if they should still occur
if (bullet.ricochetcount < 3) then
local I = bullet.velocity--Subtract3(pick.position,bullet.origin)
local N = pick.normal--:Normalize()
local angle = 180 - math.deg(math.acos(Dot3(I,N)/(I:Length()*N:Length())))
if (angle < (60)) then return end
local R = Subtract3(I,N:Scale(2 * Dot3(I,N)))--:Scale(bullet.velocity:Length()*HOST_TIMESCALE)
local ricochet = CreateBullet(pick.position, R, Vec3(0.0,0.0,0.0), ricochets)
ricochet.ricochetcount = bullet.ricochetcount + 1
end
Which grabs the bullet velocity (our incident vector), the normal of the surface we hit (the normal), calculates the angle between these two (which will be obtuse, so we subtract from 180 to get an acute angle that is easier to run comparisons on relative the bullet and player).
Presently it is hardcoded to ignore impacts for ricochet if the incident angle is less than 60 degrees. To explain, when you think of a protractor, where the far right flat line is 0, as you move up towards the top is goes from 0 to 90 , this is backwards of how the system works. The Normal is 0 degrees, and as the bullet angle towards the impact point gets close to parallel with the surface that the normal is from, it gets closer to 90. It is checking to see the angle between the normal plane of the object you hit, and the bullet velocity.
This has worked and given realistic results (minus that I didn't add friction, velocity fall off, etc. physical effects), and appears to be how this would work in real life.
The next thing I want to work on is bullet penetration through surfaces, but I am not entirely sure how this is done, and wouldn't mind some suggestions or ideas on how to do this.