While my older, patched up Smaug base (I want to say from the 1.4 FUSS days) has been kept more or less current, I am fairly certain most flavors still have this kind of behavior to one degree or another, so thought I'd post up since I've been on a MUD kick lately and had ran into this while testing something related (thrown item code, which is heavily based on projectiles, obviously).
you fire a projectile into a portal, e.g. "fire bow portal" and, because portal is often the direction "?" or "somewhere", if and only if the projectile doesn't hit anyone and tries to continue on (not yet out of range) in the same direction, it will do so by coming back through the portal at you.
As I said, some may call that a bug, some perhaps an unintended side effect. Personally, if I fire an arrow or throw an axe into a portal at someone/thing, I would not expect nor want it to potentially fly back out at me and strike someone in the room.
Again, my code is somewhat different from Smaug FUSS 1.9 as it exists today, but you can find the relevant code for the current release in skills.c, look for the function
ch_ret ranged_attack( )
and, in particular, this part:
if( dist == range )
if( projectile )
act( color, "Your $t falls harmlessly to the $T.", ch, myobj( projectile ), dir_name[dir], TO_CHAR );
act( color, "$p flies in from $T and falls harmlessly to the ground.", ch, projectile, dtxt, TO_ROOM );
if( projectile->in_obj )
obj_from_obj( projectile );
if( projectile->carried_by )
obj_from_char( projectile );
obj_to_room( projectile, ch->in_room );
act( color, "Your $t fizzles out harmlessly to the $T.", ch, stxt, dir_name[dir], TO_CHAR );
act( color, "$t flies in from $T and fizzles out harmlessly.", ch, aoran( stxt ), dtxt, TO_ROOM );
My suggestion, if you want it to go through the portal and just stop trying to continue on, is to simply augment the ifcheck at the top, i.e.
if ( dist == range || dir == 10 )
I thought about something more involved, i.e. have it pick a random, viable direction on the other side of the portal, but that just seemed silly. If your destination has more than two exits, and they are opposite each other in at least once instance, sure, you can say it comes in from "somewhere" and "flies north", say, but in the case where your only exits are, say, N and W, the idea that the projects "flies in from somewhere" followed by "flies west" would suggest it changed direction in mid-flight. Personally I prefer the approach that traveling through a portal robs it of momentum so when it pops out the other side, if it doesn't hit anyone, it basically flops to the ground, and so that's what the above achieves.
The astute observer might notice that falling to the ground "to the somewhere
" is probably not the most ideal message to the person who fired/threw the projectile into a portal. In the code I have (and I don't even know if I changed this or someone else did, it's been a while), it is split up by direction so that in some cases (i.e. up, down, 'somewhere') it doesn't return a direction. That's something of a separate issue from this bug, but if you're picky like me, you might think about tinkering with the ACT( ) calls while you're in here.
if ( projectile )
if ( dir == 4 || dir == 5 || dir == 10 )
act( color, "Your $t falls harmlessly to the ground.", ch, myobj(projectile), NULL, TO_CHAR );
act( color, "Your $t falls harmlessly to the ground to the $T.", ch, myobj(projectile), dir_name[dir], TO_CHAR );
act( color, "$p falls harmlessly to the ground here.", ch, projectile, NULL, TO_ROOM );
Again, beside the point of this post, but there you have it, in case it helps anyone.
As for the bug itself with projectiles returning back, open to suggestions, but for me, the above seems to work just fine and is a relatively painless fix. As I said, I found this while testing thrown item code which is heavily based on the projectile code, so if you've gone the same route (and I know many have), you probably have to fix it there as well.
Hope this helps someone!