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).
This commit is contained in:
nethack.rankin
2011-04-21 22:06:06 +00:00
parent 95f5e029d8
commit 9cad308536
2 changed files with 37 additions and 32 deletions

View File

@@ -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

View File

@@ -4652,16 +4652,29 @@ lava_effects()
int dmg = d(6, 6); /* only applicable for water walking */
boolean usurvive, boil_away;
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;
usurvive = Fire_resistance || (Wwalking && dmg < u.uhp);
/*
* 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->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) {
pline_The("lava here burns you!");
@@ -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"));