From: nethack.rankin Date: Thu, 21 Apr 2011 22:06:06 +0000 (+0000) Subject: fix #H2247 - lava inconsistencies (trunk only) X-Git-Tag: MOVE2GIT~215 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9cad30853620fcf583e904a143a4105a8faef1e0;p=nethack fix #H2247 - lava inconsistencies (trunk only) From a bug report, if you move into lava, die, and are life-saved or leave bones, your potions will remain intact, whereas if you have fire resistance and survive, they'll be subjected to destroy_item() and usually be destroyed (not always, because stacks of more than 1 don't always destroy the whole stack). Also, wooden ring will be destroyed even if it happens to be ring of fire resistance. This addresses both of those bugs. He also thought that all vulnerable armor should be destroyed rather than just boots in the case where you have fire resistance and survive, but I didn't change that. It is a little odd, but presumeably only your feet are in lava at first (although later sinking further into lava doesn't actually burn up any other stuff). --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 78a44a170..78ee47d55 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -357,6 +357,11 @@ effectiveness of magic cancellation by worn armor has been reduced Protection improves the effectiveness of magic cancellation if an angry shopkeeper chased the hero to a different level and then got paid off, he'd dismiss kops on that other level but not on his shop level +dying in lava and being life-saved or leaving bones would destroy ring of + fire resistance if it happened to be made of wood, and also burn up + scrolls of fire and spellbook of fireball +surviving in lava boils away carried potions, but dying in lava and being + life-saved or leaving bones would keep them intact Platform- and/or Interface-Specific Fixes diff --git a/src/trap.c b/src/trap.c index 8ef4a10df..f05067fd6 100644 --- a/src/trap.c +++ b/src/trap.c @@ -4652,15 +4652,28 @@ lava_effects() int dmg = d(6, 6); /* only applicable for water walking */ boolean usurvive, boil_away; + burn_away_slime(); + if (likes_lava(youmonst.data)) return FALSE; + usurvive = Fire_resistance || (Wwalking && dmg < u.uhp); - /* a timely interrupt might manage to salvage your life - but not your gear; do this before messages */ + /* + * A timely interrupt might manage to salvage your life + * but not your gear. For scrolls and potions this + * will destroy whole stacks, where fire resistant hero + * survivor only loses partial stacks via destroy_item(). + * + * Flag items to be destroyed before any messages so + * that player causing hangup at --More-- won't get an + * emergency save file created before item destruction. + */ 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 ((is_organic(obj) || obj->oclass == POTION_CLASS) && + !obj->oerodeproof && + objects[obj->otyp].oc_oprop != FIRE_RES && + obj->otyp != SCR_FIRE && obj->otyp != SPE_FIREBALL && + !obj_resists(obj, 0, 0)) /* for invocation items */ + obj->in_use = TRUE; if (!Fire_resistance) { if(Wwalking) { @@ -4677,35 +4690,21 @@ lava_effects() 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) */ + /* prevent remove_worn_item() -> Boots_off(WATER_WALKING_BOOTS) -> + 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 (and access stale memory, probably panic) */ iflags.in_lava_effects++; for(obj = invent; obj; obj = obj2) { obj2 = obj->nobj; - if(is_organic(obj) && !obj->oerodeproof) { - if(obj->owornmask) { + /* above, we set in_use for objects which are to be destroyed */ + if (obj->in_use) { + if (obj->owornmask) { if (usurvive) pline("%s into flame!", Yobjnam2(obj, "burst")); - - if(obj == uarm) (void) Armor_gone(); - else if(obj == uarmc) (void) Cloak_off(); - else if(obj == uarmh) (void) Helmet_off(); - else if(obj == uarms) (void) Shield_off(); - else if(obj == uarmg) (void) Gloves_off(); - else if(obj == uarmf) (void) Boots_off(); -#ifdef TOURIST - else if(obj == uarmu) (void) Shirt_off(); -#endif - else if(obj == uleft) Ring_gone(obj); - else if(obj == uright) Ring_gone(obj); - else if(obj == ublindf) Blindf_off(obj); - else if(obj == uamul) Amulet_off(); - else if(obj == uwep) uwepgone(); - else if (obj == uquiver) uqwepgone(); - else if (obj == uswapwep) uswapwepgone(); + remove_worn_item(obj, TRUE); } useupall(obj); } @@ -4731,7 +4730,7 @@ lava_effects() } You("find yourself back on solid %s.", surface(u.ux, u.uy)); return(TRUE); - } + } /* !Fire_resistance */ if (!Wwalking) { u.utrap = rn1(4, 4) + (rn1(4, 12) << 8); @@ -4743,7 +4742,8 @@ lava_effects() /* just want to burn boots, not all armor; destroy_item doesn't work on armor anyway */ burn_stuff: - if(uarmf && !uarmf->oerodeproof && is_organic(uarmf)) { + if (uarmf && !uarmf->oerodeproof && is_organic(uarmf) && + objects[uarmf->otyp].oc_oprop != FIRE_RES) { /* save uarmf value because Boots_off() sets uarmf to null */ obj = uarmf; pline("%s into flame!", Yobjnam2(obj, "burst"));