]> granicus.if.org Git - nethack/commitdiff
f-iring without ammo
authornethack.rankin <nethack.rankin>
Sat, 21 Apr 2007 02:43:32 +0000 (02:43 +0000)
committernethack.rankin <nethack.rankin>
Sat, 21 Apr 2007 02:43:32 +0000 (02:43 +0000)
     There was a suggestion in the newsgroup that if you use the 'f'
command when your quiver is empty, that whatever missile you supply to the
"what do you want to throw?" prompt be automatically put into the quiver.
This implements that, and separates most of the common code from dothrow()
and dofire() into a separate routine.  A post-3.4.3 change to dothrow() to
require hands for throwing wasn't propagated to dofire().  With the common
routine, they're much less likely to get out of sync like that.

     This is going into the branch as well as the trunk because the hands
checking mismatch was added there too.

doc/fixes34.4
src/dothrow.c

index 8254a7353eba90d69d2c51807bdb69167cc18f64..84d0c58d4a88ae1802c159dc4ccd8094f7eccc6f 100644 (file)
@@ -387,6 +387,8 @@ intelligent pets will use keys to unlock doors
 destroyed drawbridge leaves some iron chains
 give feedback when a nearby monster grows into a stronger form
 familiars are now created without any starting inventory
+using the 'f' command when quiver is empty will fill quiver if player selects
+       a stack of 2 or more items in response to the "what to throw?" prompt
 
 
 Platform- and/or Interface-Specific New Features
index 42bf9fbba757a27cdf67066dd280e6b350c5309b..fb7479b0bc81c2d2850ad632099a8bffb00641d7 100644 (file)
@@ -7,6 +7,7 @@
 #include "hack.h"
 
 STATIC_DCL int FDECL(throw_obj, (struct obj *,int));
+STATIC_DCL boolean FDECL(ok_to_throw, (int *));
 STATIC_DCL void NDECL(autoquiver);
 STATIC_DCL int FDECL(gem_accept, (struct monst *, struct obj *));
 STATIC_DCL void FDECL(tmiss, (struct obj *, struct monst *,BOOLEAN_P));
@@ -208,6 +209,28 @@ int shotlimit;
        return 1;
 }
 
+/* common to dothrow() and dofire() */
+STATIC_OVL boolean
+ok_to_throw(shotlimit_p)
+int *shotlimit_p;      /* (see dothrow()) */
+{
+       /* kludge to work around parse()'s pre-decrement of `multi' */
+       *shotlimit_p = (multi || save_cm) ? multi + 1 : 0;
+       multi = 0;              /* reset; it's been used up */
+
+       if (notake(youmonst.data)) {
+           You("are physically incapable of throwing or shooting anything.");
+           return FALSE;
+       } else if (nohands(youmonst.data)) {
+           You_cant("throw or shoot without hands."); /* not body_part(HAND) */
+           return FALSE;
+           /*[what about !freehand(), aside from cursed missile launcher?]*/
+       }
+       if (check_capacity((char *)0)) return FALSE;
+       return TRUE;
+}
+
+/* t command - throw */
 int
 dothrow()
 {
@@ -222,27 +245,16 @@ dothrow()
         *
         * Prior to 3.3.0, command ``3t'' meant ``t(shoot) t(shoot) t(shoot)''
         * and took 3 turns.  Now it means ``t(shoot at most 3 missiles)''.
+        *
+        * [3.5.0:  shot count setup has been moved into ok_to_throw().]
         */
-       /* kludge to work around parse()'s pre-decrement of `multi' */
-       shotlimit = (multi || save_cm) ? multi + 1 : 0;
-       multi = 0;              /* reset; it's been used up */
+       if (!ok_to_throw(&shotlimit)) return 0;
 
-       if (notake(youmonst.data)) {
-           You("are physically incapable of throwing anything.");
-           return 0;
-       } else if (nohands(youmonst.data)) {
-           You_cant("throw without hands.");   /* not `body_part(HAND)' */
-           return 0;
-           /*[what about !freehand(), aside from cursed missile launcher?]*/
-       }
-
-       if(check_capacity((char *)0)) return(0);
        obj = getobj(uslinging() ? bullets : toss_objs, "throw");
        /* it is also possible to throw food */
        /* (or jewels, or iron balls... ) */
 
-       if (!obj) return(0);
-       return throw_obj(obj, shotlimit);
+       return obj ? throw_obj(obj, shotlimit) : 0;
 }
 
 
@@ -311,50 +323,47 @@ autoquiver()
        return;
 }
 
-
-/* Throw from the quiver */
+/* f command -- fire: throw from the quiver */
 int
 dofire()
 {
        int shotlimit;
-
-       if (notake(youmonst.data)) {
-           You("are physically incapable of doing that.");
-           return 0;
-       }
-
-       if(check_capacity((char *)0)) return(0);
-       if (!uquiver) {
-               if (!flags.autoquiver) {
-                       /* Don't automatically fill the quiver */
-                       You("have no ammunition readied!");
-                       return(dothrow());
-               }
-               autoquiver();
-               if (!uquiver) {
-                       You("have nothing appropriate for your quiver!");
-                       return(dothrow());
-               } else {
-                       You("fill your quiver:");
-                       prinv((char *)0, uquiver, 0L);
-               }
-       }
+       struct obj *obj;
 
        /*
-        * Since some characters shoot multiple missiles at one time,
-        * allow user to specify a count prefix for 'f' or 't' to limit
-        * number of items thrown (to avoid possibly hitting something
-        * behind target after killing it, or perhaps to conserve ammo).
+        * Same as dothrow(), except we use quivered missile instead
+        * of asking what to throw/shoot.
         *
-        * The number specified can never increase the number of missiles.
-        * Using ``5f'' when the shooting skill (plus RNG) dictates launch
-        * of 3 projectiles will result in 3 being shot, not 5.
+        * If quiver is empty, we use autoquiver to fill it when the
+        * corresponding option is on.  If the option is off or if
+        * autoquiver doesn't select anything, we ask what to throw.
+        * For the last, if player's response is a stack, we put
+        * that stack into quiver slot provided it's not wielded.
         */
-       /* kludge to work around parse()'s pre-decrement of `multi' */
-       shotlimit = (multi || save_cm) ? multi + 1 : 0;
-       multi = 0;              /* reset; it's been used up */
+       if (!ok_to_throw(&shotlimit)) return 0;
+
+       if ((obj = uquiver) == 0) {
+           if (!flags.autoquiver) {
+               You("have no ammunition readied.");
+           } else {
+               autoquiver();
+               if ((obj = uquiver) == 0)
+                   You("have nothing appropriate for your quiver.");
+           }
+           /* if autoquiver is disabled or has failed, prompt for missile;
+              fill quiver with it if it's a stack that's not wielded */
+           if (!obj) {
+               obj = getobj(uslinging() ? bullets : toss_objs, "throw");
+               if (obj && obj->quan > 1L && !obj->owornmask &&
+                       /* Q command doesn't allow gold in quiver */
+                       obj->oclass != COIN_CLASS)
+                   setuqwep(obj);      /* demi-autoquiver */
+           }
+           /* give feedback if quiver has now been filled */
+           if (uquiver) prinv("You ready:", uquiver, 0L);
+       }
 
-       return throw_obj(uquiver, shotlimit);
+       return obj ? throw_obj(obj, shotlimit) : 0;
 }
 
 /* if in midst of multishot shooting/throwing, stop early */