Personally, I'm using sensors for short-range weapons (melee weapons, flamethrowers, and the like), and bullets for medium- and long-range weapons. So I've made the sensor cone fairly large but the distance short (say, 2 meters).
As for the guns which fire bullets, the bullets don't work well at close range, since they tend to hit nearby targets before their on_rez event can set up the bullet properties, and no, it can't be done in state_entry instead due to validation of the bullet requiring the key of the bullet.
Hmm, actually, I have an idea. Perhaps I can make the bullet recognize if its properties haven't been set yet upon collision, and if so, send a short-range attack message instead. I think this'll be a little tricky - events can apparently queue up while other events are being executed, so I'm relying on setting a variable to 0 in state_entry, setting it to 1 in on_rez, and setting it to 2 in the timer event, with llSetTimerEvent(0.1) being called after on_rez has set the bullet properties. The collision events will check to see what the variable is, and for now just tell me what it is if it's not 2. I'm expecting it to be 2 at long range and 1 at all other ranges. Here's my reasoning:
I'm theorizing that (a) events in one script can NOT interrupt other events in the same script, and (b) events can be queued during other events, and (c) on_rez should be queued first so nothing else executes before it
My reasoning for (a) is that nothing would work reliably at all if it wasn't true.
My reasoning for (b) is that I have witnessed a timer() event happening after llSetTimerEvent(0.0) has been called, and the only sane reason that could happen would be if (b) was true and was the cause. Here's almost-LSL pseudocode similar to the test script I made to check this:
integer timerEnabled;
default {
state_entry() {
timerEnabled=1;
llSetTimerEvent(0.1);
}
collision_start(integer num_detected) {
//we are doing stuff here;
//timer elapsed, timer() event is queued as a result;
//we are doing some more stuff;
timerEnabled=0;
llSetTimerEvent(0.0);
}
timer() {
if (timerEnabled==0) {
llOwnerSay("zounds!");
}
}
}
The "zounds!" message was going off. (I don't remember exactly what event - it might not have been collision_start - I was seeing this in. I also don't remember where I put the test script.

)
I don't have any evidence for (c), but that why I'm testing this to see what results I get. If I see 0s, then I'll know that collision events can be queued before on_rez.