fix #H4057 - rusting amulets

There have been two or three reports on getting feedback about
amulets rusting.  Object formatting doesn't display erosion for
them, so being told about damage then not seeing that damage
feels like a bug.  Even if damage was displayed, it has no effect
on them so would still feel somewhat strange.  It does display
erosion for wands and rings, which is strange too.

This limits erosion damage--and its feedback--to items which are
actually impacted by erosion:  armor, weapons and weapon-tools;
also heavy iron balls and iron chains since they've traditionally
shown rust even though it has little effect.

A side-effect of this change is that flammable items (other than
armor and weapons) which don't burn up immediately will no longer
become burnt, then very burnt, thorougly burnt, and finally be
destroyed.  Since the player couldn't see or possibly repair the
erosion state, it seemed incomplete.  It could be reinstated by
making other flammable items be subject to erosion and displayed
as such by xname() & co.

Wishing now avoids applying erosion and erosion-proofing to items
that aren't affected by it, regardless of material.  It also now
allows wishing for "rusty rustproof <iron-object>" which used to
suppress "rusty" in that combination and triggered a couple of
old bug reports.

Heavy iron balls and iron chains can have rust repaired and can
be made rustproof by wielding, then reading enchant weapon while
confused, as if they were weapons.
This commit is contained in:
PatR
2016-03-09 16:37:43 -08:00
parent 9a1bbbd14d
commit ef863f3c9f
6 changed files with 65 additions and 34 deletions

View File

@@ -182,6 +182,8 @@ when looting multiple containers, add 'n' for "loot next container", change
change looting to choose ":iobrs nq" action from a menu for menustyle:Partial
wand/spell/breath zaps that reached the edge of the level on the Plane of Air
and "vanished into the aether" left temporary display effects on screen
stop amulets and other items which aren't affected by erosion damage from
being subjected to erosion damage
Platform- and/or Interface-Specific Fixes

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1457397476 2016/03/08 00:37:56 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.551 $ */
/* NetHack 3.6 extern.h $NHDT-Date: 1457570257 2016/03/10 00:37:37 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.552 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1591,6 +1591,7 @@ E char *FDECL(xname, (struct obj *));
E char *FDECL(mshot_xname, (struct obj *));
E boolean FDECL(the_unique_obj, (struct obj *));
E boolean FDECL(the_unique_pm, (struct permonst *));
E boolean FDECL(erosion_matters, (struct obj *));
E char *FDECL(doname, (struct obj *));
E char *FDECL(doname_with_price, (struct obj *));
E boolean FDECL(not_fully_identified, (struct obj *));

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 objnam.c $NHDT-Date: 1455672990 2016/02/17 01:36:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.165 $ */
/* NetHack 3.6 objnam.c $NHDT-Date: 1457570258 2016/03/10 00:37:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.166 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -730,6 +730,31 @@ char *prefix;
: "");
}
/* used to prevent rust on items where rust makes no difference */
boolean
erosion_matters(obj)
struct obj *obj;
{
switch (obj->oclass) {
case TOOL_CLASS:
/* it's possible for a rusty weptool to be polymorphed into some
non-weptool iron tool, in which case the rust implicitly goes
away, but it's also possible for it to be polymorphed into a
non-iron tool, in which case rust also implicitly goes away,
so there's no particular reason to try to handle the first
instance differently [this comment belongs in poly_obj()...] */
return is_weptool(obj) ? TRUE : FALSE;
case WEAPON_CLASS:
case ARMOR_CLASS:
case BALL_CLASS:
case CHAIN_CLASS:
return TRUE;
default:
break;
}
return FALSE;
}
static char *
doname_base(obj, with_price)
register struct obj *obj;
@@ -853,31 +878,27 @@ boolean with_price;
plur(itemcount));
}
switch (obj->oclass) {
switch (is_weptool(obj) ? WEAPON_CLASS : obj->oclass) {
case AMULET_CLASS:
if (obj->owornmask & W_AMUL)
Strcat(bp, " (being worn)");
break;
case ARMOR_CLASS:
if (obj->owornmask & W_ARMOR)
Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
: " (being worn)");
/*FALLTHRU*/
case WEAPON_CLASS:
if (ispoisoned)
Strcat(prefix, "poisoned ");
plus:
add_erosion_words(obj, prefix);
if (known) {
Strcat(prefix, sitoa(obj->spe));
Strcat(prefix, " ");
}
break;
case ARMOR_CLASS:
if (obj->owornmask & W_ARMOR)
Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
: " (being worn)");
goto plus;
case TOOL_CLASS:
/* weptools already get this done when we go to the +n code */
if (!is_weptool(obj))
add_erosion_words(obj, prefix);
if (obj->owornmask & (W_TOOL /* blindfold */ | W_SADDLE)) {
if (obj->owornmask & (W_TOOL | W_SADDLE)) { /* blindfold */
Strcat(bp, " (being worn)");
break;
}
@@ -885,8 +906,6 @@ boolean with_price;
Strcat(bp, " (in use)");
break;
}
if (is_weptool(obj))
goto plus;
if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
if (!obj->spe)
Strcpy(tmpbuf, "no");
@@ -908,7 +927,6 @@ boolean with_price;
goto charges;
break;
case WAND_CLASS:
add_erosion_words(obj, prefix);
charges:
if (known)
Sprintf(eos(bp), " (%d:%d)", (int) obj->recharged, obj->spe);
@@ -918,7 +936,6 @@ boolean with_price;
Strcat(bp, " (lit)");
break;
case RING_CLASS:
add_erosion_words(obj, prefix);
ring:
if (obj->owornmask & W_RINGR)
Strcat(bp, " (on right ");
@@ -3443,15 +3460,19 @@ typfnd:
curse(otmp);
}
/* set eroded */
if (is_damageable(otmp) || otmp->otyp == CRYSKNIFE) {
/* set eroded and erodeproof */
if (erosion_matters(otmp)) {
if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
otmp->oeroded = eroded;
if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
otmp->oeroded2 = eroded2;
/* set erodeproof */
if (erodeproof && !eroded && !eroded2)
/*
* 3.6.1: earlier versions included `&& !eroded && !eroded2' here,
* but damageproof combined with damaged is feasible (eroded
* armor modified by confused reading of cursed destroy armor)
* so don't prevent player from wishing for such a combination.
*/
if (erodeproof && (is_damageable(otmp) || otmp->otyp == CRYSKNIFE))
otmp->oerodeproof = (Luck >= 0 || wizard);
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 read.c $NHDT-Date: 1450577673 2015/12/20 02:14:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.131 $ */
/* NetHack 3.6 read.c $NHDT-Date: 1457570260 2016/03/10 00:37:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.135 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -60,6 +60,7 @@ struct obj *otmp;
char *buf;
{
int erosion = greatest_erosion(otmp);
if (erosion)
wipeout_text(buf, (int) (strlen(buf) * erosion / (2 * MAX_ERODE)),
otmp->o_id ^ (unsigned) ubirthday);
@@ -1312,8 +1313,11 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
*/
break;
case SCR_ENCHANT_WEAPON:
/* [What about twoweapon mode? Proofing/repairing/enchanting both
would be too powerful, but shouldn't we choose randomly between
primary and secondary instead of always acting on primary?] */
if (confused && uwep
&& (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))) {
&& erosion_matters(uwep) && uwep->oclass != ARMOR_CLASS) {
old_erodeproof = (uwep->oerodeproof != 0);
new_erodeproof = !scursed;
uwep->oerodeproof = 0; /* for messages */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 trap.c $NHDT-Date: 1454528963 2016/02/03 19:49:23 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.261 $ */
/* NetHack 3.6 trap.c $NHDT-Date: 1457570259 2016/03/10 00:37:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.262 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -197,6 +197,8 @@ int ef_flags;
if (check_grease && otmp->greased) {
grease_protect(otmp, ostr, victim);
return ER_GREASED;
} else if (!erosion_matters(otmp)) {
return ER_NOTHING;
} else if (!vulnerable || (otmp->oerodeproof && otmp->rknown)) {
if (flags.verbose && print && (uvictim || vismon))
pline("%s %s %s not affected by %s.",

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 zap.c $NHDT-Date: 1457482920 2016/03/09 00:22:00 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.248 $ */
/* NetHack 3.6 zap.c $NHDT-Date: 1457570259 2016/03/10 00:37:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.249 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1423,14 +1423,15 @@ int id;
otmp->cursed = obj->cursed;
otmp->blessed = obj->blessed;
otmp->oeroded = obj->oeroded;
otmp->oeroded2 = obj->oeroded2;
if (!is_flammable(otmp) && !is_rustprone(otmp))
otmp->oeroded = 0;
if (!is_corrodeable(otmp) && !is_rottable(otmp))
otmp->oeroded2 = 0;
if (is_damageable(otmp))
otmp->oerodeproof = obj->oerodeproof;
if (erosion_matters(otmp)) {
if (is_flammable(otmp) || is_rustprone(otmp))
otmp->oeroded = obj->oeroded;
if (is_corrodeable(otmp) || is_rottable(otmp))
otmp->oeroded2 = obj->oeroded2;
if (is_damageable(otmp))
otmp->oerodeproof = obj->oerodeproof;
}
/* Keep chest/box traps and poisoned ammo if we may */
if (obj->otrapped && Is_box(otmp))