From: Sean Hunt Date: Tue, 24 Feb 2015 20:20:01 +0000 (-0500) Subject: Eliminate `erode_obj()` and other erosion. X-Git-Tag: NetHack-3.6.0_RC01~639 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3a049cf66e0c8587c278aa90e0d9da19db587583;p=nethack Eliminate `erode_obj()` and other erosion. Now all erosion that isn't fire-based goes through `rust_dmg()` --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 48da8da36..9dc59fa66 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -859,9 +859,11 @@ if lava burns up the player's water walking boots, the player falls in the messages for lava burning items up are always printed fix used-up magic trap trying to hit steed. messages are now printed when objects on the ground are eroded -object erosion now always identifies rust/rot/fire/corrodeproof objects +object erosion now always identifies fooproof objects grease protects from all types of erosion all sources of erosion now affect objects the same way +passive attacks no longer erode armor covered by other armor +dipping a fooproof item into acid no longer forgets that it's fooproof Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 87d3adee7..6ca49b411 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1070,6 +1070,7 @@ E int FDECL(sleep_monst, (struct monst *,int,int)); E void FDECL(slept_monst, (struct monst *)); E void FDECL(xdrainenergym, (struct monst *,BOOLEAN_P)); E long FDECL(attk_protection, (int)); +E void FDECL(rustm, (struct monst *,struct obj *)); /* ### mhitu.c ### */ @@ -2222,6 +2223,7 @@ E void FDECL(fill_pit, (int,int)); E int FDECL(float_down, (long, long)); E void NDECL(climb_pit); E int FDECL(fire_damage, (struct obj *,BOOLEAN_P,BOOLEAN_P,XCHAR_P,XCHAR_P)); +E void acid_damage(struct obj *); E int FDECL(water_damage, (struct obj *,const char*,BOOLEAN_P)); E void FDECL(water_damage_chain, (struct obj *,BOOLEAN_P)); E boolean NDECL(drown); @@ -2516,7 +2518,6 @@ E void NDECL(uwepgone); E void NDECL(uswapwepgone); E void NDECL(uqwepgone); E void NDECL(untwoweapon); -E boolean FDECL(erode_obj, (struct obj *,int,BOOLEAN_P,BOOLEAN_P)); E int FDECL(chwepon, (struct obj *,int)); E int FDECL(welded, (struct obj *)); E void FDECL(weldmsg, (struct obj *)); diff --git a/src/mhitm.c b/src/mhitm.c index ae66279e7..31c9dba11 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -16,7 +16,6 @@ static const char brief_feeling[] = "have a %s feeling for a moment, then it passes."; STATIC_DCL char *FDECL(mon_nam_too, (char *,struct monst *,struct monst *)); -STATIC_DCL void FDECL(mrustm, (struct monst *, struct monst *, struct obj *)); STATIC_DCL int FDECL(hitmm, (struct monst *,struct monst *,struct attack *)); STATIC_DCL int FDECL(gazemm, (struct monst *,struct monst *,struct attack *)); STATIC_DCL int FDECL(gulpmm, (struct monst *,struct monst *,struct attack *)); @@ -796,7 +795,7 @@ mdamagem(magr, mdef, mattk) (grow_up(magr,mdef) ? 0 : MM_AGR_DIED)); } if (tmp) - mrustm(magr, mdef, otmp); + rustm(mdef, otmp); } } else if (pa == &mons[PM_PURPLE_WORM] && pd == &mons[PM_SHRIEKER]) { @@ -884,7 +883,7 @@ mdamagem(magr, mdef, mattk) pline("It burns %s!", mon_nam(mdef)); } if (!rn2(30)) erode_armor(mdef, ERODE_CORRODE); - if (!rn2(6)) (void) erode_obj(MON_WEP(mdef), 3, TRUE, FALSE); + if (!rn2(6)) acid_damage(MON_WEP(mdef)); break; case AD_RUST: if (magr->mcan) break; @@ -1287,24 +1286,24 @@ struct monst *mon; } } -STATIC_OVL void -mrustm(magr, mdef, obj) -register struct monst *magr, *mdef; +void +rustm(mdef, obj) +register struct monst *mdef; register struct obj *obj; { int dmgtyp; - if (!magr || !mdef || !obj) return; /* just in case */ + if (!mdef || !obj) return; /* just in case */ /* AD_ACID is handled in passivemm */ if (dmgtype(mdef->data, AD_CORR)) - dmgtyp = 3; + dmgtyp = ERODE_CORRODE; else if (dmgtype(mdef->data, AD_RUST)) - dmgtyp = 1; + dmgtyp = ERODE_RUST; else if (dmgtype(mdef->data, AD_FIRE)) - dmgtyp = 0; + dmgtyp = ERODE_BURN; else return; - (void) erode_obj(obj, dmgtyp, FALSE, FALSE); + (void) rust_dmg(obj, 0, dmgtyp, TRUE, TRUE); } STATIC_OVL void @@ -1362,7 +1361,7 @@ int mdead; } } else tmp = 0; if (!rn2(30)) erode_armor(magr, ERODE_CORRODE); - if (!rn2(6)) (void)erode_obj(MON_WEP(magr), 3, TRUE, FALSE); + if (!rn2(6)) acid_damage(MON_WEP(magr)); goto assess_dmg; case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ if (mhit && !mdef->mcan && otmp) { diff --git a/src/mhitu.c b/src/mhitu.c index cc9b6f1be..6aa4225f7 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -8,7 +8,6 @@ STATIC_VAR NEARDATA struct obj *otmp; -STATIC_DCL void FDECL(urustm, (struct monst *, struct obj *)); STATIC_DCL boolean FDECL(u_slip_free, (struct monst *,struct attack *)); STATIC_DCL int FDECL(passiveum, (struct permonst *,struct monst *,struct attack *)); @@ -920,7 +919,7 @@ hitmu(mtmp, mattk) if (cloneu()) You("divide as %s hits you!", mon_nam(mtmp)); } - urustm(mtmp, otmp); + rustm(&youmonst, otmp); } else if (mattk->aatyp != AT_TUCH || dmg != 0 || mtmp != u.ustuck) hitmsg(mtmp, mattk); @@ -2079,26 +2078,6 @@ register int n; } } -STATIC_OVL void -urustm(mon, obj) -register struct monst *mon; -register struct obj *obj; -{ - int dmgtyp; - - if (!mon || !obj) return; /* just in case */ - /* AD_ACID is handled in passiveum */ - if (dmgtype(youmonst.data, AD_CORR)) - dmgtyp = 3; - else if (dmgtype(youmonst.data, AD_RUST)) - dmgtyp = 1; - else if (dmgtype(youmonst.data, AD_FIRE)) - dmgtyp = 0; - else - return; - (void) erode_obj(obj, dmgtyp, FALSE, FALSE); -} - int could_seduce(magr,mdef,mattk) struct monst *magr, *mdef; @@ -2442,7 +2421,7 @@ register struct attack *mattk; } } else tmp = 0; if (!rn2(30)) erode_armor(mtmp, ERODE_CORRODE); - if (!rn2(6)) (void)erode_obj(MON_WEP(mtmp), 3, TRUE, FALSE); + if (!rn2(6)) acid_damage(MON_WEP(mtmp)); goto assess_dmg; case AD_STON: /* cockatrice */ { diff --git a/src/potion.c b/src/potion.c index 7542ea451..483544c2b 100644 --- a/src/potion.c +++ b/src/potion.c @@ -1931,7 +1931,7 @@ dodip() } if (potion->otyp == POT_ACID) { - if (erode_obj(obj, 3, FALSE, TRUE)) + if (rust_dmg(obj, 0, ERODE_CORRODE, TRUE, FALSE)) goto poof; } diff --git a/src/spell.c b/src/spell.c index e1f6fc55b..5d499bf73 100644 --- a/src/spell.c +++ b/src/spell.c @@ -144,21 +144,7 @@ cursed_book(bp) case 5: pline_The("book was coated with contact poison!"); if (uarmg) { - if (uarmg->oerodeproof || !is_corrodeable(uarmg)) { - Your("gloves seem unaffected."); - } else if (uarmg->oeroded2 < MAX_ERODE) { - if (uarmg->greased) { - grease_protect(uarmg, "gloves", &youmonst); - } else { - Your("gloves corrode%s!", - uarmg->oeroded2+1 == MAX_ERODE ? - " completely" : uarmg->oeroded2 ? - " further" : ""); - uarmg->oeroded2++; - } - } else - Your("gloves %s completely corroded.", - Blind ? "feel" : "look"); + rust_dmg(uarmg, "gloves", ERODE_CORRODE, TRUE, TRUE); break; } /* temp disable in_use; death should not destroy the book */ diff --git a/src/trap.c b/src/trap.c index f6266791f..f78b7ad66 100644 --- a/src/trap.c +++ b/src/trap.c @@ -103,6 +103,8 @@ struct monst *victim; /* Generic erode-item function. Returns TRUE if any change in state * occurred, or if grease protected the item. + * "ostr", if non-null, is an alternate string to print instead of the + * object's name. * "check_grease", if FALSE, means that grease is not checked for * "print", if set, means to print a message even if no change occurs. */ @@ -165,8 +167,8 @@ boolean print; if (victim == &youmonst) Your("%s %s not affected.", ostr, vtense(ostr, "are")); else if (vismon) - pline("%s's %s %s not affected.", Monnam(victim), ostr, - vtense(ostr, "are")); + pline("%s %s %s not affected.", s_suffix(Monnam(victim)), + ostr, vtense(ostr, "are")); } return FALSE; } else if (otmp->oerodeproof || (otmp->blessed && !rnl(4))) { @@ -175,8 +177,9 @@ boolean print; pline("Somehow, your %s %s not affected.", ostr, vtense(ostr, "are")); else if (vismon) - pline("Somehow, %s's %s %s not affected.", - mon_nam(victim), ostr, vtense(ostr, "are")); + pline("Somehow, %s %s %s not affected.", + s_suffix(mon_nam(victim)), ostr, + vtense(ostr, "are")); else if (visobj) pline("Somehow, the %s %s not affected.", ostr, vtense(ostr, "are")); @@ -214,8 +217,8 @@ boolean print; vtense(ostr, Blind ? "feel" : "look"), msg[type]); else if (vismon) - pline("%s's %s %s completely %s.", - Monnam(victim), ostr, + pline("%s %s %s completely %s.", + s_suffix(Monnam(victim)), ostr, vtense(ostr, "look"), msg[type]); else if (visobj) pline("The %s %s completely %s.", ostr, @@ -952,8 +955,8 @@ unsigned trflags; if (water_damage(uarms, "shield", TRUE)) break; if (u.twoweap || (uwep && bimanual(uwep))) - (void) erode_obj(u.twoweap ? uswapwep : uwep, - 1, TRUE, FALSE); + (void) water_damage(u.twoweap ? uswapwep : uwep, 0, + TRUE); glovecheck: (void) water_damage(uarmg, "gauntlets", TRUE); /* Not "metal gauntlets" since it gets called * even if it's leather for the message @@ -962,7 +965,7 @@ glovecheck: (void) water_damage(uarmg, "gauntlets", TRUE); case 2: pline("%s your right %s!", A_gush_of_water_hits, body_part(ARM)); - (void) erode_obj(uwep, 1, TRUE, FALSE); + (void) water_damage(uwep, 0, TRUE); goto glovecheck; default: pline("%s you!", A_gush_of_water_hits); @@ -2098,7 +2101,7 @@ register struct monst *mtmp; break; target = MON_WEP(mtmp); if (target && bimanual(target)) - (void) erode_obj(target, 1, TRUE, FALSE); + (void) water_damage(target, 0, TRUE); glovecheck: target = which_armor(mtmp, W_ARMG); (void) water_damage(target, "gauntlets", TRUE); break; @@ -2106,7 +2109,7 @@ glovecheck: target = which_armor(mtmp, W_ARMG); if (in_sight) pline("%s %s's right %s!", A_gush_of_water_hits, mon_nam(mtmp), mbodypart(mtmp, ARM)); - (void) erode_obj(MON_WEP(mtmp), 1, TRUE, FALSE); + (void) water_damage(MON_WEP(mtmp), 0, TRUE); goto glovecheck; default: if (in_sight) @@ -3069,6 +3072,38 @@ xchar x, y; return retval; } +void +acid_damage(obj) +struct obj *obj; +{ + /* Scrolls but not spellbooks can be erased by acid. */ + struct monst *victim = + carried(obj) ? &youmonst : mcarried(obj) ? obj->ocarry : NULL; + boolean vismon = victim && (victim != &youmonst) && canseemon(victim); + + if (obj->greased) + grease_protect(obj, NULL, victim); + else if (obj->oclass == SCROLL_CLASS && obj->otyp != SCR_BLANK_PAPER) { + if (obj->otyp != SCR_BLANK_PAPER +#ifdef MAIL + && obj->otyp != SCR_MAIL +#endif + ) { + if (!Blind) { + if (victim == &youmonst) + pline("Your %s.", aobjnam(obj, "fade")); + else if (vismon) + pline("%s %s.", s_suffix(Monnam(victim)), + aobjnam(obj, "fade")); + } + } + obj->otyp = SCR_BLANK_PAPER; + obj->spe = 0; + obj->dknown = 0; + } else + rust_dmg(obj, NULL, ERODE_CORRODE, TRUE, TRUE); +} + /* returns: * 0 if obj is unaffected * 1 if obj is protected by grease diff --git a/src/uhitm.c b/src/uhitm.c index a0f90d3de..51f38eee0 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -2446,22 +2446,22 @@ struct attack *mattk; /* null means we find one internally */ case AD_FIRE: if(!rn2(6) && !mon->mcan) { - (void) erode_obj(obj, 0, FALSE, FALSE); + (void) rust_dmg(obj, 0, ERODE_BURN, FALSE, FALSE); } break; case AD_ACID: if(!rn2(6)) { - (void) erode_obj(obj, 3, FALSE, FALSE); + (void) rust_dmg(obj, 0, ERODE_CORRODE, FALSE, FALSE); } break; case AD_RUST: if(!mon->mcan) { - (void) erode_obj(obj, 1, FALSE, FALSE); + (void) rust_dmg(obj, 0, ERODE_RUST, FALSE, FALSE); } break; case AD_CORR: if(!mon->mcan) { - (void) erode_obj(obj, 3, FALSE, FALSE); + (void) rust_dmg(obj, 0, ERODE_CORRODE, FALSE, FALSE); } break; case AD_ENCH: diff --git a/src/wield.c b/src/wield.c index dbb5d271f..9e1447bff 100644 --- a/src/wield.c +++ b/src/wield.c @@ -597,131 +597,6 @@ untwoweapon() return; } -/* Maybe rust (or corrode, burn, rot) object. - * Returns TRUE if something happened. */ -boolean -erode_obj(target, type, fade_scrolls, for_dip) -struct obj *target; /* object (e.g. weapon or armor) to erode */ -int type; -boolean fade_scrolls; -boolean for_dip; -{ - static NEARDATA const char * const action[] = { "smoulder", "rust", "rot", "corrode" }; - static NEARDATA const char * const msg[] = { "burnt", "rusty", "rotten", "corroded" }; - boolean vulnerable = FALSE; - boolean grprot = FALSE; - boolean is_primary = TRUE; - int erosion; - int dmgtyp = AD_ACID; - struct monst *victim; - boolean vismon, visobj, chill; - boolean ret = FALSE; - boolean already_affected = FALSE; - - if (!target) - return FALSE; - victim = carried(target) ? &youmonst : - mcarried(target) ? target->ocarry : (struct monst *)0; - vismon = victim && (victim != &youmonst) && canseemon(victim); - visobj = !victim && cansee(bhitpos.x, bhitpos.y); /* assume thrown */ - - switch(type) { - case 0: vulnerable = is_flammable(target); - dmgtyp = AD_FIRE; - break; - case 1: vulnerable = is_rustprone(target); - dmgtyp = AD_RUST; - grprot = TRUE; - if (target->lamplit) { - already_affected = snuff_lit(target); - if (already_affected) ret = TRUE; - } - break; - case 2: vulnerable = is_rottable(target); - dmgtyp = AD_DCAY; - is_primary = FALSE; - break; - case 3: vulnerable = is_corrodeable(target); - dmgtyp = AD_ACID; - grprot = TRUE; - is_primary = FALSE; - break; - } - erosion = is_primary ? target->oeroded : target->oeroded2; - - if (target->greased && grprot) { - grease_protect(target,(char *)0,victim); - ret = TRUE; - } else if (target->oclass == SCROLL_CLASS && (type == 1 || type == 3)) { - if(fade_scrolls && target->otyp != SCR_BLANK_PAPER -#ifdef MAIL - && target->otyp != SCR_MAIL -#endif - ) - { - if (!Blind) { - if ((victim == &youmonst) || vismon || visobj) - pline("%s.", Yobjnam2(target, "fade")); - } - target->otyp = SCR_BLANK_PAPER; - target->spe = 0; - ret = TRUE; - } - } else if (target->oartifact && arti_immune(target, dmgtyp)) { - if (flags.verbose && (dmgtyp != AD_FIRE)) { - if (victim == &youmonst) - pline("%s.", Yobjnam2(target, "sizzle")); - } - /* no damage to object */ - } else if (target->oartifact && (type == 1) && - /* cold and fire provide partial protection against rust */ - ((chill = arti_immune(target, AD_COLD)) != 0 || - arti_immune(target, AD_FIRE)) && - /* once rusted, the chance for further rusting goes up */ - rn2(2 * (MAX_ERODE + 1 - erosion))) { - if (flags.verbose && target->oclass == WEAPON_CLASS) { - if (victim == &youmonst || vismon || visobj) - pline("%s some water.", - Yobjnam2(target, chill ? "freeze" : "boil")); - } - /* no damage to object */ - } else if (target->oerodeproof || !vulnerable) { - /* no message if dipping or not carried */ - if (for_dip) { - /* assumes that for_dip implies player action */ - if (!Blind) target->rknown = 0; - } else if (victim == &youmonst || vismon) { - if (flags.verbose || (vulnerable && !target->rknown)) - pline("%s not %s.", Yobjnam2(target, "are"), - already_affected ? "harmed" : "affected"); - if (vulnerable) target->rknown = 1; - } - } else if (erosion < MAX_ERODE) { - if (victim == &youmonst || vismon || visobj) { - pline("%s%s!", Yobjnam2(target, action[type]), - erosion+1 == MAX_ERODE ? " completely" : - erosion ? " further" : ""); - target->rknown = 1; /* it's obviously not erode-proof */ - } - if (is_primary) - target->oeroded++; - else - target->oeroded2++; - ret = TRUE; - } else { - if (flags.verbose && !for_dip) { - if (victim == &youmonst) - pline("%s completely %s.", - Yobjnam2(target, Blind ? "feel" : "look"), msg[type]); - else if (vismon || visobj) - pline("%s completely %s.", - Yobjnam2(target, "look"), msg[type]); - } - } - - return ret; -} - int chwepon(otmp, amount) register struct obj *otmp; diff --git a/src/zap.c b/src/zap.c index 2fb2396de..95b9760a3 100644 --- a/src/zap.c +++ b/src/zap.c @@ -3395,7 +3395,7 @@ struct obj **ootmp; /* to return worn armor for caller to disintegrate */ break; } tmp = d(nd,6); - if (!rn2(6)) (void) erode_obj(MON_WEP(mon), 3, TRUE, FALSE); + if (!rn2(6)) acid_damage(MON_WEP(mon)); if (!rn2(6)) erode_armor(mon, ERODE_CORRODE); break; } @@ -3522,9 +3522,9 @@ xchar sx, sy; } /* using two weapons at once makes both of them more vulnerable */ if (!rn2(u.twoweap ? 3 : 6)) - (void) erode_obj(uwep, 3, TRUE, FALSE); + acid_damage(uwep); if (u.twoweap && !rn2(3)) - (void) erode_obj(uswapwep, 3, TRUE, FALSE); + acid_damage(uswapwep); if (!rn2(6)) erode_armor(&youmonst, ERODE_CORRODE); break; }