EasyBallistics plugin

-If you have armor as a separate component, what you should do is to check if penetration depth is greater than thickness of the armor, and if yes, then pass the damage to the underlying object.
Unfortunately none of the penetration check algorithms can reliably deal with multiple “layers” directly.

Solid: best for convex collisions (ie simplified collisions, ragdolls, capsules etc), skips inside.
Backtrace: arbitrary mesh, tests collision from the other side, so if there’s multiple “layers” it skips the inside.
Forward: arbitrary mesh with double sided collision. In theory this could work if you had armor with double sided collision, and some room (collision margin) between it and next layer. However I wouldn’t recommend it, very fiddly setup. It would work for a tank, but definitely a bad idea for deforming character.

-As for how exactly the values stack: Spreads are added up, Friction and restitution are interpolated (influence controls how much, 0 is all controlled by the bullet, 1 is all controlled by the material), ricochet probability is a multiplier.

-The not despawning thing - is this in multiplayer? In multiplayer the client copies of the bullet only despawn when the server copy despawns, so if there’s any delay they might do that. However, as you said, they shouldn’t produce any additional hit events.
If it happens in singleplayer too, it could be a bug, could you try creating a small project that reproduces it?

-I still have no idea why impulse is applied in opposite direction. And even less of an idea why setting impulse multiplier to -1 doesn’t reverse it. The value isn’t clamped in any way and -1 should definitely reverse it.