'f' for aklys
Adopt a feature mentioned in the xNetHack release announcement.
If you use the fire ('f') command when wielding a throw-and-return
weapon while your quiver is empty and the 'autoquiver' option is
Off, throw the wielded weapon instead of prompting to fill the
quiver. It will usually return and be re-wielded, so be ready to
fire again.
Implemented from scratch.
This commit is contained in:
@@ -20,6 +20,14 @@ static boolean toss_up(struct obj *, boolean);
|
||||
static void sho_obj_return_to_u(struct obj * obj);
|
||||
static boolean mhurtle_step(genericptr_t, int, int);
|
||||
|
||||
/* uwep might already be removed from inventory so test for W_WEP instead;
|
||||
for Valk+Mjollnir, caller needs to validate the strength requirement */
|
||||
#define AutoReturn(o,wmsk) \
|
||||
((((wmsk) & W_WEP) != 0 \
|
||||
&& ((o)->otyp == AKLYS \
|
||||
|| ((o)->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE)))) \
|
||||
|| (o)->otyp == BOOMERANG)
|
||||
|
||||
/* g.thrownobj (decl.c) tracks an object until it lands */
|
||||
|
||||
int
|
||||
@@ -270,18 +278,24 @@ throw_ok(struct obj *obj)
|
||||
if (!obj)
|
||||
return GETOBJ_EXCLUDE;
|
||||
|
||||
if (obj->bknown && welded(obj)) /* not a candidate if known to be stuck */
|
||||
return GETOBJ_DOWNPLAY;
|
||||
|
||||
if (AutoReturn(obj, obj->owornmask)
|
||||
/* to get here, obj is boomerang or is uwep and (alkys or Mjollnir) */
|
||||
&& (obj->oartifact != ART_MJOLLNIR || ACURR(A_STR) >= STR19(25)))
|
||||
return GETOBJ_SUGGEST;
|
||||
|
||||
if (obj->quan == 1 && (obj == uwep || (obj == uswapwep && u.twoweap)))
|
||||
return GETOBJ_DOWNPLAY;
|
||||
/* Possible extension: return GETOBJ_SUGGEST for uwep if it will return when
|
||||
* thrown. */
|
||||
|
||||
if (obj->oclass == COIN_CLASS)
|
||||
return GETOBJ_SUGGEST;
|
||||
|
||||
if (!uslinging() && obj->oclass == WEAPON_CLASS)
|
||||
return GETOBJ_SUGGEST;
|
||||
/* Possible extension: exclude weapons that make no sense to throw, such as
|
||||
* whips, bows, slings, rubber hoses. */
|
||||
/* Possible extension: exclude weapons that make no sense to throw,
|
||||
such as whips, bows, slings, rubber hoses. */
|
||||
|
||||
if (uslinging() && obj->oclass == GEM_CLASS)
|
||||
return GETOBJ_SUGGEST;
|
||||
@@ -396,23 +410,24 @@ dofire(void)
|
||||
* of asking what to throw/shoot.
|
||||
*
|
||||
* 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.
|
||||
* corresponding option is on. If the option is off and hero
|
||||
* is wielding a thrown-and-return weapon, use the wielded
|
||||
* weapon. If option is off and not wielding such a weapon or
|
||||
* if autoquiver doesn't select anything, we ask what to throw.
|
||||
* Then we put the chosen item into the quiver slot unless
|
||||
* it is already in another slot. [Matters most if it is a
|
||||
* stack but also matters for single item if this throw gets
|
||||
* aborted (ESC at the direction prompt). Already wielded
|
||||
* item is excluded because wielding might be necessary
|
||||
* (Mjollnir) or make the throw behave differently (aklys),
|
||||
* and alt-wielded item is excluded because switching slots
|
||||
* would end two-weapon combat even if throw gets aborted.]
|
||||
* aborted (ESC at the direction prompt).]
|
||||
*/
|
||||
if (!ok_to_throw(&shotlimit))
|
||||
return 0;
|
||||
|
||||
if ((obj = uquiver) == 0) {
|
||||
if (!flags.autoquiver) {
|
||||
You("have no ammunition readied.");
|
||||
if (uwep && AutoReturn(uwep, uwep->owornmask))
|
||||
obj = uwep;
|
||||
else
|
||||
You("have no ammunition readied.");
|
||||
} else {
|
||||
autoquiver();
|
||||
if ((obj = uquiver) == 0)
|
||||
@@ -1136,10 +1151,10 @@ sho_obj_return_to_u(struct obj *obj)
|
||||
/* throw an object, NB: obj may be consumed in the process */
|
||||
void
|
||||
throwit(struct obj *obj,
|
||||
long wep_mask, /* used to re-equip returning boomerang */
|
||||
boolean twoweap, /* used to restore twoweapon mode if
|
||||
wielded weapon returns */
|
||||
struct obj *oldslot) /* for thrown-and-return used with !fixinv */
|
||||
long wep_mask, /* used to re-equip returning boomerang */
|
||||
boolean twoweap, /* used to restore twoweapon mode if
|
||||
wielded weapon returns */
|
||||
struct obj *oldslot) /* for thrown-and-return used with !fixinv */
|
||||
{
|
||||
register struct monst *mon;
|
||||
int range, urange;
|
||||
@@ -1187,10 +1202,8 @@ throwit(struct obj *obj,
|
||||
|
||||
g.thrownobj = obj;
|
||||
g.thrownobj->was_thrown = 1;
|
||||
iflags.returning_missile = ((obj->oartifact == ART_MJOLLNIR
|
||||
&& Role_if(PM_VALKYRIE))
|
||||
|| tethered_weapon) ? (genericptr_t) obj
|
||||
: (genericptr_t) 0;
|
||||
iflags.returning_missile = AutoReturn(obj, wep_mask) ? (genericptr_t) obj
|
||||
: (genericptr_t) 0;
|
||||
/* NOTE: No early returns after this point or returning_missile
|
||||
will be left with a stale pointer. */
|
||||
|
||||
@@ -1234,6 +1247,7 @@ throwit(struct obj *obj,
|
||||
} else if (obj->otyp == BOOMERANG && !Underwater) {
|
||||
if (Is_airlevel(&u.uz) || Levitation)
|
||||
hurtle(-u.dx, -u.dy, 1, TRUE);
|
||||
iflags.returning_missile = 0; /* doesn't return if it hits monster */
|
||||
mon = boomhit(obj, u.dx, u.dy);
|
||||
if (mon == &g.youmonst) { /* the thing was caught */
|
||||
exercise(A_DEX, TRUE);
|
||||
@@ -1241,6 +1255,7 @@ throwit(struct obj *obj,
|
||||
(void) encumber_msg();
|
||||
if (wep_mask && !(obj->owornmask & wep_mask)) {
|
||||
setworn(obj, wep_mask);
|
||||
/* moot; can no longer two-weapon with missile(s) */
|
||||
set_twoweap(twoweap); /* u.twoweap = twoweap */
|
||||
}
|
||||
clear_thrownobj = TRUE;
|
||||
|
||||
Reference in New Issue
Block a user