-/* SCCS Id: @(#)do_wear.c 3.5 2004/11/11 */
+/* SCCS Id: @(#)do_wear.c 3.5 2005/12/07 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
STATIC_DCL int NDECL(Cloak_on);
STATIC_PTR int NDECL(Helmet_on);
STATIC_PTR int NDECL(Gloves_on);
+STATIC_DCL void FDECL(wielding_corpse, (struct obj *,BOOLEAN_P));
STATIC_PTR int NDECL(Shield_on);
#ifdef TOURIST
STATIC_PTR int NDECL(Shirt_on);
/* check for lava since fireproofed boots make it viable */
if ((is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) &&
!Levitation && !Flying && !is_clinger(youmonst.data) &&
- !context.takeoff.cancelled_don) {
+ !context.takeoff.cancelled_don &&
+ /* avoid recursive call to lava_effects() */
+ !context.in_lava_effects) {
/* make boots known in case you survive the drowning */
makeknown(otyp);
spoteffects(TRUE);
return 0;
}
+STATIC_OVL void
+wielding_corpse(obj, voluntary)
+struct obj *obj;
+boolean voluntary; /* taking gloves off on purpose? */
+{
+ char kbuf[BUFSZ];
+
+ if (!obj || obj->otyp != CORPSE) return;
+ if (obj != uwep && (obj != uswapwep || !u.twoweap)) return;
+
+ if (touch_petrifies(&mons[obj->corpsenm]) && !Stone_resistance) {
+ You("now wield %s in your bare %s.",
+ the(corpse_xname(obj, TRUE)),
+ makeplural(body_part(HAND)));
+ Sprintf(kbuf, "%s gloves while wielding %s",
+ voluntary ? "removing" : "losing",
+ killer_xname(obj));
+ instapetrify(kbuf);
+ /* life-saved; can't continue wielding cockatrice corpse though */
+ remove_worn_item(obj, FALSE);
+ }
+}
+
int
Gloves_off()
{
u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES;
context.takeoff.mask &= ~W_ARMG;
+ boolean on_purpose = !context.mon_moving && !uarmg->in_use;
switch(uarmg->otyp) {
case LEATHER_GLOVES:
context.takeoff.cancelled_don = FALSE;
(void) encumber_msg(); /* immediate feedback for GoP */
- /* Prevent wielding cockatrice when not wearing gloves */
- if (uwep && uwep->otyp == CORPSE &&
- touch_petrifies(&mons[uwep->corpsenm])) {
- char kbuf[BUFSZ];
+ /* prevent wielding cockatrice when not wearing gloves */
+ if (uwep && uwep->otyp == CORPSE)
+ wielding_corpse(uwep, on_purpose);
- You("wield the %s in your bare %s.",
- corpse_xname(uwep, TRUE), makeplural(body_part(HAND)));
- Strcpy(kbuf, an(corpse_xname(uwep, TRUE)));
- instapetrify(kbuf);
- uwepgone(); /* life-saved still doesn't allow touching cockatrice */
- }
-
- /* KMH -- ...or your secondary weapon when you're wielding it */
- if (u.twoweap && uswapwep && uswapwep->otyp == CORPSE &&
- touch_petrifies(&mons[uswapwep->corpsenm])) {
- char kbuf[BUFSZ];
-
- You("wield the %s in your bare %s.",
- corpse_xname(uswapwep, TRUE), body_part(HAND));
-
- Strcpy(kbuf, an(corpse_xname(uswapwep, TRUE)));
- instapetrify(kbuf);
- uswapwepgone(); /* lifesaved still doesn't allow touching cockatrice */
- }
+ /* KMH -- ...or your secondary weapon when you're wielding it
+ [This case can't actually happen; twoweapon mode won't
+ engage if a corpse has been set up as the alternate weapon.] */
+ if (u.twoweap && uswapwep && uswapwep->otyp == CORPSE)
+ wielding_corpse(uswapwep, on_purpose);
return 0;
}
register struct obj *otmp;
#define DESTROY_ARM(o) ((otmp = (o)) != 0 && \
(!atmp || atmp == otmp) && \
- (!obj_resists(otmp, 0, 90)))
+ (!obj_resists(otmp, 0, 90)) ? \
+ (otmp->in_use = TRUE) : FALSE)
if (DESTROY_ARM(uarmc)) {
if (donning(otmp)) cancel_don();
/* KMH -- catch underflow */
s = sobj->cursed ? -otmp->spe : otmp->spe;
if (s > (special_armor ? 5 : 3) && rn2(s)) {
- pline("%s violently %s%s%s for a while, then %s.",
- Yname2(otmp),
- otense(otmp, Blind ? "vibrate" : "glow"),
- (!Blind && !same_color) ? " " : nul,
- (Blind || same_color) ? nul :
- hcolor(sobj->cursed ? NH_BLACK : NH_SILVER),
- otense(otmp, "evaporate"));
+ otmp->in_use = TRUE;
+ pline("%s violently %s%s%s for a while, then %s.",
+ Yname2(otmp),
+ otense(otmp, Blind ? "vibrate" : "glow"),
+ (!Blind && !same_color) ? " " : nul,
+ (Blind || same_color) ? nul :
+ hcolor(sobj->cursed ? NH_BLACK : NH_SILVER),
+ otense(otmp, "evaporate"));
if(is_cloak(otmp)) (void) Cloak_off();
if(is_boots(otmp)) (void) Boots_off();
if(is_helmet(otmp)) (void) Helmet_off();
if(is_gloves(otmp)) (void) Gloves_off();
if(is_shield(otmp)) (void) Shield_off();
if(otmp == uarm) (void) Armor_gone();
+#ifdef TOURIST
+ if (is_shirt(otmp)) (void) Shirt_off();
+#endif
useup(otmp);
break;
}
lava_effects()
{
register struct obj *obj, *obj2;
- int dmg;
+ int dmg = d(6, 6); /* only applicable for water walking */
boolean usurvive;
+ usurvive = Fire_resistance || (Wwalking && dmg < u.uhp);
+ /* a timely interrupt might manage to salvage your life
+ but not your gear; do this before messages */
+ if (!usurvive)
+ for (obj = invent; obj; obj = obj->nobj)
+ if (is_organic(obj) && !obj->oerodeproof) obj->in_use = TRUE;
+
burn_away_slime();
if (likes_lava(youmonst.data)) return FALSE;
if (!Fire_resistance) {
if(Wwalking) {
- dmg = d(6,6);
pline_The("lava here burns you!");
- if(dmg < u.uhp) {
+ if (usurvive) {
losehp(dmg, lava_killer, KILLED_BY); /* lava damage */
goto burn_stuff;
}
#ifdef WIZARD
if (wizard) usurvive = TRUE;
#endif
+
+ /* prevent Boots_off() -> spoteffects() -> lava_effects() recursion
+ which would successfully delete (via useupall) the no-longer-worn
+ boots; once recursive call returned, we would try to delete them
+ again here in the outer call (access stale memory, probably panic) */
+ context.in_lava_effects++;
+
for(obj = invent; obj; obj = obj2) {
obj2 = obj->nobj;
if(is_organic(obj) && !obj->oerodeproof) {
else if(obj == uarmg) (void) Gloves_off();
else if(obj == uarmf) (void) Boots_off();
#ifdef TOURIST
- else if(obj == uarmu) setnotworn(obj);
+ else if(obj == uarmu) (void) Shirt_off();
#endif
else if(obj == uleft) Ring_gone(obj);
else if(obj == uright) Ring_gone(obj);
}
}
+ context.in_lava_effects--;
+
/* s/he died... */
u.uhp = -1;
killer.format = KILLED_BY;