Right. As promised, here are a few things I've discovered so far about bullets, which might at some point save somebody some time. The basic idea is that you rez a bullet using llRezObject to give it an appropriate velocity towards the target - but I think if you're looking for advice you probably know that much already, as it's already in the standard .
I had a frustrating time originally when I tried to build an automated gun turret that fired at intruders. It was pointing in the right direction, it was firing bullets properly, but a lot of the time they would do absolutely nothing, just shoot straight through me (the only test subject here). You could watch them go past by changing the camera angle. Very annoying. Speeding them up didn't seem to help at all, though slowing them down did, but then they have a hard time hitting anything.
What I'd been suspecting based on this experience was confirmed to me later on - the physics engine works on a frames basis, moving objects a certain distance N times per second (N usually around 44 in my experience, you can get the current framerate with a script) and detects collisions after each move, it doesn't interpolate between the two positions. A small fast-moving object can therefore just appear on each side of a target without ever touching it. So you can't use one of those small round bullets that you get in the old free gun scripts, uh uh. What you actually need is a long thin spear-type thing, to ensure that it will cover all of the intervening arc that it travels along. I calculated that a bullet that travels at 100m/s - slow for a real-world bullet but works in SL - should be around 100/40 = 2.5m long to be absolutely sure that it would hit intervening targets. This seems to work.
So my bullet here is a 2.5 x 0.1 x 0.1 cylinder. When rezzed it turns itself fully transparent since the gun isn't supposed to fire spears, but you can see where it is from a particle at the centre. When it detects a collision event, it uses llPushObject to apply an upwards impulse to that object, determined by the parameter that the gun passes to it after it rezzes.
More about the revolver
I modified the gun and bullet so that one could change the degree of push applied by voice command ("push 1", "push 50" etc); the gun passes a parameter to the bullet which is multiplied by 100,000 to get the upward impulse used by llPushObject. On a direct hit, the default setting of 1 sends a target dummy pretty high, but then they're quite light, and since the impulse is divided by the cube of the distance between the centre of mass of the bullet, and the centre of mass of the object pushed, hitting a dummy in the foot means it just bounces upwards a little. So there is a slight challenge involved to satisfactory target practice.
There are also two bullet types now - one pushes forward, or at least in the same direction as the vector from the bullet's centre to the object hit's centre i.e. the following vector:
so if you shoot low it could be mostly upwards, and one pushes strictly upwards:
bulletForce * llVecNorm(llDetectedPos(0) - llGetPos())
These can be selected by voice command as well ("push fwd" and "push up").
<0, 0, bulletForce>
One has to have something to shoot at. I wrote a script that displays the weight of the object it is put into as float text, records and displays the maximum height above ground that the object reaches, and, after a certain period of time (about two minutes) sends an IM back to the owner saying the maximum height and the distance that it is currently from its starting point, and then dies. This helps solve the "oops where did that one go?" problem that seems to happen a lot to me. I hope nobody was disturbed by large wooden objects falling from the sky, but in SL they only weigh 8kg despite being two metres high.
Of course, if one of these bullets hits a person by accident, it'll send them flying up in the air as well, which is at best annoying for them and at worst gets your account suspended. The base push is quite low, so it won't send somebody into orbit. I could have modified the bullet so it wouldn't push an avatar but I decided not to...
It adds an extra level of required complexity;
There might come a time when there's a legitimate reason to push somebody, a game, as a demo, to get them out of somewhere, whatever;
(and most importantly) If I'm building a gun it should be something I have to take care with. It wouldn't be hard to make something safe that would only interact with target scripted objects and I'd never have to worry about anything but... I don't know, what good is that?