yet another pass at 'A' bugs
I think this finally quashes the "cursed without otmp" issue. Various ways of destroying wielded weapon used setnotworn() rather than unwield(), so the previous change to have unwield() clear the pending W_WEP bit from takeoff.mask wasn't sufficient to prevent 'A' moving on from another item (blindfold--it's the only thing processed before primary weapon) to weapon which wasn't there any more. Also, if weapon was already set in takeoff.what to be processed on the next move, clearing W_WEP from takeoff.mask wasn't sufficient either. Move the previous unwield() 'fix' to setworn() and setnotworn() and extend it to include cancel_don() if the item being replaced or removed is in progress or scheduled for next. (Most of the time, remove_worn_item() has already done that before setworn() or setnotworn() is called.)
This commit is contained in:
@@ -379,7 +379,9 @@ levitation vs encumbrance message sequencing issues: putting on boots of
|
||||
and float-up messages, taking off such boots didn't report increase
|
||||
of encumbrance until player took another action
|
||||
removing a blindfold with 'A' took two turns, with 'R' (and 'T') only one,
|
||||
and could result in a panic if the blindfold was stolen during removal
|
||||
and could result in a crash if the blindfold was stolen during removal
|
||||
removing a blindfold and wielded weapon with 'A' could result in crash if the
|
||||
weapon was destroyed by various methods
|
||||
cmdassist help for movement prefix followed by invalid direction was strange
|
||||
when the direction was up, down, or self disallowed for that prefix
|
||||
poor message when shape-shifted vampire reverts to vampire if it has a name:
|
||||
@@ -396,6 +398,7 @@ adult green dragons and the Chromatic Dragon were blinded by gas clouds
|
||||
named floating eye (when hit by another monster with reflection) or named
|
||||
silver weapon (when hero hits silver-hating monster) could disrupt
|
||||
message formatting and conceivably trigger crash if name had '%' in it
|
||||
crashes for 'A' above were downgraded to impossible "cursed without otmp"
|
||||
|
||||
|
||||
Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 extern.h $NHDT-Date: 1496860756 2017/06/07 18:39:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.590 $ */
|
||||
/* NetHack 3.6 extern.h $NHDT-Date: 1496959470 2017/06/08 22:04:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.591 $ */
|
||||
/* Copyright (c) Steve Creps, 1988. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -436,6 +436,7 @@ E void FDECL(off_msg, (struct obj *));
|
||||
E void FDECL(set_wear, (struct obj *));
|
||||
E boolean FDECL(donning, (struct obj *));
|
||||
E boolean FDECL(doffing, (struct obj *));
|
||||
E void FDECL(cancel_doff, (struct obj *, long));
|
||||
E void NDECL(cancel_don);
|
||||
E int FDECL(stop_donning, (struct obj *));
|
||||
E int NDECL(Armor_off);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 do_wear.c $NHDT-Date: 1496614914 2017/06/04 22:21:54 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.97 $ */
|
||||
/* NetHack 3.6 do_wear.c $NHDT-Date: 1496959478 2017/06/08 22:04:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.98 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1207,7 +1207,7 @@ struct obj *otmp;
|
||||
{
|
||||
boolean result = FALSE;
|
||||
|
||||
/* 'W' and 'T' set afternmv, 'A' sets context.takeoff.what */
|
||||
/* 'W' (or 'P' used for armor) sets afternmv */
|
||||
if (doffing(otmp))
|
||||
result = TRUE;
|
||||
else if (otmp == uarm)
|
||||
@@ -1237,7 +1237,7 @@ struct obj *otmp;
|
||||
long what = context.takeoff.what;
|
||||
boolean result = FALSE;
|
||||
|
||||
/* 'T' (also 'W') sets afternmv, 'A' sets context.takeoff.what */
|
||||
/* 'T' (or 'R' used for armor) sets afternmv, 'A' sets takeoff.what */
|
||||
if (otmp == uarm)
|
||||
result = (afternmv == Armor_off || what == WORN_ARMOR);
|
||||
else if (otmp == uarmu)
|
||||
@@ -1252,8 +1252,7 @@ struct obj *otmp;
|
||||
result = (afternmv == Gloves_off || what == WORN_GLOVES);
|
||||
else if (otmp == uarms)
|
||||
result = (afternmv == Shield_off || what == WORN_SHIELD);
|
||||
/* these 1-turn items don't need 'afternmv' checks
|
||||
[and may not actually need 'what' checks] */
|
||||
/* these 1-turn items don't need 'afternmv' checks */
|
||||
else if (otmp == uamul)
|
||||
result = (what == WORN_AMUL);
|
||||
else if (otmp == uleft)
|
||||
@@ -1272,6 +1271,29 @@ struct obj *otmp;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* despite their names, cancel_don() and cancel_doff() both apply to both
|
||||
donning and doffing... */
|
||||
void
|
||||
cancel_doff(obj, slotmask)
|
||||
struct obj *obj;
|
||||
long slotmask;
|
||||
{
|
||||
/* Called by setworn() for old item in specified slot or by setnotworn()
|
||||
* for specified item. We don't want to call cancel_don() if we got
|
||||
* here via <X>_off() -> setworn((struct obj *)0) -> cancel_doff()
|
||||
* because that would stop the 'A' command from continuing with next
|
||||
* selected item. So do_takeoff() sets a flag in takeoff.mask for us.
|
||||
* [For taking off an individual item with 'T'/'R'/'w-', it doesn't
|
||||
* matter whether cancel_don() gets called here--the item has already
|
||||
* been removed by now.]
|
||||
*/
|
||||
if (!(context.takeoff.mask & I_SPECIAL) && donning(obj))
|
||||
cancel_don(); /* applies to doffing too */
|
||||
context.takeoff.mask &= ~slotmask;
|
||||
}
|
||||
|
||||
/* despite their names, cancel_don() and cancel_doff() both apply to both
|
||||
donning and doffing... */
|
||||
void
|
||||
cancel_don()
|
||||
{
|
||||
@@ -1308,7 +1330,7 @@ struct obj *stolenobj; /* no message if stolenobj is already being doffing */
|
||||
|
||||
/* donning() returns True when doffing too; doffing() is more specific */
|
||||
putting_on = !doffing(otmp);
|
||||
/* cancel_don() looks at afternmv; it also serves as cancel_doff() */
|
||||
/* cancel_don() looks at afternmv; it can also cancel doffing */
|
||||
cancel_don();
|
||||
/* don't want <armor>_on() or <armor>_off() being called
|
||||
by unmul() since the on or off action isn't completing */
|
||||
@@ -2302,6 +2324,7 @@ do_takeoff()
|
||||
struct obj *otmp = (struct obj *) 0;
|
||||
struct takeoff_info *doff = &context.takeoff;
|
||||
|
||||
context.takeoff.mask |= I_SPECIAL; /* set flag for cancel_doff() */
|
||||
if (doff->what == W_WEP) {
|
||||
if (!cursed(uwep)) {
|
||||
setuwep((struct obj *) 0);
|
||||
@@ -2361,6 +2384,7 @@ do_takeoff()
|
||||
} else {
|
||||
impossible("do_takeoff: taking off %lx", doff->what);
|
||||
}
|
||||
context.takeoff.mask &= ~I_SPECIAL; /* clear cancel_doff() flag */
|
||||
|
||||
return otmp;
|
||||
}
|
||||
@@ -2378,10 +2402,9 @@ take_off(VOID_ARGS)
|
||||
if (doff->delay > 0) {
|
||||
doff->delay--;
|
||||
return 1; /* still busy */
|
||||
} else {
|
||||
if ((otmp = do_takeoff()))
|
||||
off_msg(otmp);
|
||||
}
|
||||
if ((otmp = do_takeoff()) != 0)
|
||||
off_msg(otmp);
|
||||
doff->mask &= ~doff->what;
|
||||
doff->what = 0L;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 wield.c $NHDT-Date: 1496614915 2017/06/04 22:21:55 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.53 $ */
|
||||
/* NetHack 3.6 wield.c $NHDT-Date: 1496959480 2017/06/08 22:04:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.54 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -676,10 +676,6 @@ uwepgone()
|
||||
pline("%s shining.", Tobjnam(uwep, "stop"));
|
||||
}
|
||||
setworn((struct obj *) 0, W_WEP);
|
||||
/* update takeoff mask in case uwep has just gone away while
|
||||
its removal via 'A' was pending, similar to what the various
|
||||
Xyzzy_off(do_wear.c) routines do for armor and accessories */
|
||||
context.takeoff.mask &= ~W_WEP;
|
||||
unweapon = TRUE;
|
||||
update_inventory();
|
||||
}
|
||||
@@ -690,7 +686,6 @@ uswapwepgone()
|
||||
{
|
||||
if (uswapwep) {
|
||||
setworn((struct obj *) 0, W_SWAPWEP);
|
||||
context.takeoff.mask &= ~W_SWAPWEP;
|
||||
update_inventory();
|
||||
}
|
||||
}
|
||||
@@ -700,7 +695,6 @@ uqwepgone()
|
||||
{
|
||||
if (uquiver) {
|
||||
setworn((struct obj *) 0, W_QUIVER);
|
||||
context.takeoff.mask &= ~W_QUIVER;
|
||||
update_inventory();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 worn.c $NHDT-Date: 1493510127 2017/04/29 23:55:27 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $ */
|
||||
/* NetHack 3.6 worn.c $NHDT-Date: 1496959481 2017/06/08 22:04:41 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -77,6 +77,9 @@ long mask;
|
||||
if (oobj->oartifact)
|
||||
set_artifact_intrinsic(oobj, 0, mask);
|
||||
}
|
||||
/* in case wearing or removal is in progress or removal
|
||||
is pending (via 'A' command for multiple items) */
|
||||
cancel_doff(oobj, wp->w_mask);
|
||||
}
|
||||
*(wp->w_obj) = obj;
|
||||
if (obj) {
|
||||
@@ -119,6 +122,10 @@ register struct obj *obj;
|
||||
u.twoweap = 0;
|
||||
for (wp = worn; wp->w_mask; wp++)
|
||||
if (obj == *(wp->w_obj)) {
|
||||
/* in case wearing or removal is in progress or removal
|
||||
is pending (via 'A' command for multiple items) */
|
||||
cancel_doff(obj, wp->w_mask);
|
||||
|
||||
*(wp->w_obj) = 0;
|
||||
p = objects[obj->otyp].oc_oprop;
|
||||
u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask;
|
||||
|
||||
Reference in New Issue
Block a user