Eliminate erode_obj() and other erosion.

Now all erosion that isn't fire-based goes through `rust_dmg()`
This commit is contained in:
Sean Hunt
2015-02-24 15:20:01 -05:00
committed by Pasi Kallinen
parent 4e05b9a1ec
commit 04a0331ccc
10 changed files with 73 additions and 196 deletions

View File

@@ -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 the messages for lava burning items up are always printed
fix used-up magic trap trying to hit steed. fix used-up magic trap trying to hit steed.
messages are now printed when objects on the ground are eroded 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 grease protects from all types of erosion
all sources of erosion now affect objects the same way 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 Platform- and/or Interface-Specific Fixes

View File

@@ -1070,6 +1070,7 @@ E int FDECL(sleep_monst, (struct monst *,int,int));
E void FDECL(slept_monst, (struct monst *)); E void FDECL(slept_monst, (struct monst *));
E void FDECL(xdrainenergym, (struct monst *,BOOLEAN_P)); E void FDECL(xdrainenergym, (struct monst *,BOOLEAN_P));
E long FDECL(attk_protection, (int)); E long FDECL(attk_protection, (int));
E void FDECL(rustm, (struct monst *,struct obj *));
/* ### mhitu.c ### */ /* ### mhitu.c ### */
@@ -2222,6 +2223,7 @@ E void FDECL(fill_pit, (int,int));
E int FDECL(float_down, (long, long)); E int FDECL(float_down, (long, long));
E void NDECL(climb_pit); E void NDECL(climb_pit);
E int FDECL(fire_damage, (struct obj *,BOOLEAN_P,BOOLEAN_P,XCHAR_P,XCHAR_P)); 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 int FDECL(water_damage, (struct obj *,const char*,BOOLEAN_P));
E void FDECL(water_damage_chain, (struct obj *,BOOLEAN_P)); E void FDECL(water_damage_chain, (struct obj *,BOOLEAN_P));
E boolean NDECL(drown); E boolean NDECL(drown);
@@ -2516,7 +2518,6 @@ E void NDECL(uwepgone);
E void NDECL(uswapwepgone); E void NDECL(uswapwepgone);
E void NDECL(uqwepgone); E void NDECL(uqwepgone);
E void NDECL(untwoweapon); 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(chwepon, (struct obj *,int));
E int FDECL(welded, (struct obj *)); E int FDECL(welded, (struct obj *));
E void FDECL(weldmsg, (struct obj *)); E void FDECL(weldmsg, (struct obj *));

View File

@@ -16,7 +16,6 @@ static const char brief_feeling[] =
"have a %s feeling for a moment, then it passes."; "have a %s feeling for a moment, then it passes.";
STATIC_DCL char *FDECL(mon_nam_too, (char *,struct monst *,struct monst *)); 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(hitmm, (struct monst *,struct monst *,struct attack *));
STATIC_DCL int FDECL(gazemm, (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 *)); 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)); (grow_up(magr,mdef) ? 0 : MM_AGR_DIED));
} }
if (tmp) if (tmp)
mrustm(magr, mdef, otmp); rustm(mdef, otmp);
} }
} else if (pa == &mons[PM_PURPLE_WORM] && } else if (pa == &mons[PM_PURPLE_WORM] &&
pd == &mons[PM_SHRIEKER]) { pd == &mons[PM_SHRIEKER]) {
@@ -884,7 +883,7 @@ mdamagem(magr, mdef, mattk)
pline("It burns %s!", mon_nam(mdef)); pline("It burns %s!", mon_nam(mdef));
} }
if (!rn2(30)) erode_armor(mdef, ERODE_CORRODE); 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; break;
case AD_RUST: case AD_RUST:
if (magr->mcan) break; if (magr->mcan) break;
@@ -1287,24 +1286,24 @@ struct monst *mon;
} }
} }
STATIC_OVL void void
mrustm(magr, mdef, obj) rustm(mdef, obj)
register struct monst *magr, *mdef; register struct monst *mdef;
register struct obj *obj; register struct obj *obj;
{ {
int dmgtyp; int dmgtyp;
if (!magr || !mdef || !obj) return; /* just in case */ if (!mdef || !obj) return; /* just in case */
/* AD_ACID is handled in passivemm */ /* AD_ACID is handled in passivemm */
if (dmgtype(mdef->data, AD_CORR)) if (dmgtype(mdef->data, AD_CORR))
dmgtyp = 3; dmgtyp = ERODE_CORRODE;
else if (dmgtype(mdef->data, AD_RUST)) else if (dmgtype(mdef->data, AD_RUST))
dmgtyp = 1; dmgtyp = ERODE_RUST;
else if (dmgtype(mdef->data, AD_FIRE)) else if (dmgtype(mdef->data, AD_FIRE))
dmgtyp = 0; dmgtyp = ERODE_BURN;
else else
return; return;
(void) erode_obj(obj, dmgtyp, FALSE, FALSE); (void) rust_dmg(obj, 0, dmgtyp, TRUE, TRUE);
} }
STATIC_OVL void STATIC_OVL void
@@ -1362,7 +1361,7 @@ int mdead;
} }
} else tmp = 0; } else tmp = 0;
if (!rn2(30)) erode_armor(magr, ERODE_CORRODE); 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; goto assess_dmg;
case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
if (mhit && !mdef->mcan && otmp) { if (mhit && !mdef->mcan && otmp) {

View File

@@ -8,7 +8,6 @@
STATIC_VAR NEARDATA struct obj *otmp; 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 boolean FDECL(u_slip_free, (struct monst *,struct attack *));
STATIC_DCL int FDECL(passiveum, (struct permonst *,struct monst *,struct attack *)); STATIC_DCL int FDECL(passiveum, (struct permonst *,struct monst *,struct attack *));
@@ -920,7 +919,7 @@ hitmu(mtmp, mattk)
if (cloneu()) if (cloneu())
You("divide as %s hits you!", mon_nam(mtmp)); You("divide as %s hits you!", mon_nam(mtmp));
} }
urustm(mtmp, otmp); rustm(&youmonst, otmp);
} else if (mattk->aatyp != AT_TUCH || dmg != 0 || } else if (mattk->aatyp != AT_TUCH || dmg != 0 ||
mtmp != u.ustuck) mtmp != u.ustuck)
hitmsg(mtmp, mattk); 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 int
could_seduce(magr,mdef,mattk) could_seduce(magr,mdef,mattk)
struct monst *magr, *mdef; struct monst *magr, *mdef;
@@ -2442,7 +2421,7 @@ register struct attack *mattk;
} }
} else tmp = 0; } else tmp = 0;
if (!rn2(30)) erode_armor(mtmp, ERODE_CORRODE); 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; goto assess_dmg;
case AD_STON: /* cockatrice */ case AD_STON: /* cockatrice */
{ {

View File

@@ -1931,7 +1931,7 @@ dodip()
} }
if (potion->otyp == POT_ACID) { if (potion->otyp == POT_ACID) {
if (erode_obj(obj, 3, FALSE, TRUE)) if (rust_dmg(obj, 0, ERODE_CORRODE, TRUE, FALSE))
goto poof; goto poof;
} }

View File

@@ -144,21 +144,7 @@ cursed_book(bp)
case 5: case 5:
pline_The("book was coated with contact poison!"); pline_The("book was coated with contact poison!");
if (uarmg) { if (uarmg) {
if (uarmg->oerodeproof || !is_corrodeable(uarmg)) { rust_dmg(uarmg, "gloves", ERODE_CORRODE, TRUE, TRUE);
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");
break; break;
} }
/* temp disable in_use; death should not destroy the book */ /* temp disable in_use; death should not destroy the book */

View File

@@ -103,6 +103,8 @@ struct monst *victim;
/* Generic erode-item function. Returns TRUE if any change in state /* Generic erode-item function. Returns TRUE if any change in state
* occurred, or if grease protected the item. * 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 * "check_grease", if FALSE, means that grease is not checked for
* "print", if set, means to print a message even if no change occurs. * "print", if set, means to print a message even if no change occurs.
*/ */
@@ -165,8 +167,8 @@ boolean print;
if (victim == &youmonst) if (victim == &youmonst)
Your("%s %s not affected.", ostr, vtense(ostr, "are")); Your("%s %s not affected.", ostr, vtense(ostr, "are"));
else if (vismon) else if (vismon)
pline("%s's %s %s not affected.", Monnam(victim), ostr, pline("%s %s %s not affected.", s_suffix(Monnam(victim)),
vtense(ostr, "are")); ostr, vtense(ostr, "are"));
} }
return FALSE; return FALSE;
} else if (otmp->oerodeproof || (otmp->blessed && !rnl(4))) { } else if (otmp->oerodeproof || (otmp->blessed && !rnl(4))) {
@@ -175,8 +177,9 @@ boolean print;
pline("Somehow, your %s %s not affected.", pline("Somehow, your %s %s not affected.",
ostr, vtense(ostr, "are")); ostr, vtense(ostr, "are"));
else if (vismon) else if (vismon)
pline("Somehow, %s's %s %s not affected.", pline("Somehow, %s %s %s not affected.",
mon_nam(victim), ostr, vtense(ostr, "are")); s_suffix(mon_nam(victim)), ostr,
vtense(ostr, "are"));
else if (visobj) else if (visobj)
pline("Somehow, the %s %s not affected.", ostr, pline("Somehow, the %s %s not affected.", ostr,
vtense(ostr, "are")); vtense(ostr, "are"));
@@ -214,8 +217,8 @@ boolean print;
vtense(ostr, Blind ? "feel" : "look"), vtense(ostr, Blind ? "feel" : "look"),
msg[type]); msg[type]);
else if (vismon) else if (vismon)
pline("%s's %s %s completely %s.", pline("%s %s %s completely %s.",
Monnam(victim), ostr, s_suffix(Monnam(victim)), ostr,
vtense(ostr, "look"), msg[type]); vtense(ostr, "look"), msg[type]);
else if (visobj) else if (visobj)
pline("The %s %s completely %s.", ostr, pline("The %s %s completely %s.", ostr,
@@ -952,8 +955,8 @@ unsigned trflags;
if (water_damage(uarms, "shield", TRUE)) if (water_damage(uarms, "shield", TRUE))
break; break;
if (u.twoweap || (uwep && bimanual(uwep))) if (u.twoweap || (uwep && bimanual(uwep)))
(void) erode_obj(u.twoweap ? uswapwep : uwep, (void) water_damage(u.twoweap ? uswapwep : uwep, 0,
1, TRUE, FALSE); TRUE);
glovecheck: (void) water_damage(uarmg, "gauntlets", TRUE); glovecheck: (void) water_damage(uarmg, "gauntlets", TRUE);
/* Not "metal gauntlets" since it gets called /* Not "metal gauntlets" since it gets called
* even if it's leather for the message * even if it's leather for the message
@@ -962,7 +965,7 @@ glovecheck: (void) water_damage(uarmg, "gauntlets", TRUE);
case 2: case 2:
pline("%s your right %s!", A_gush_of_water_hits, pline("%s your right %s!", A_gush_of_water_hits,
body_part(ARM)); body_part(ARM));
(void) erode_obj(uwep, 1, TRUE, FALSE); (void) water_damage(uwep, 0, TRUE);
goto glovecheck; goto glovecheck;
default: default:
pline("%s you!", A_gush_of_water_hits); pline("%s you!", A_gush_of_water_hits);
@@ -2098,7 +2101,7 @@ register struct monst *mtmp;
break; break;
target = MON_WEP(mtmp); target = MON_WEP(mtmp);
if (target && bimanual(target)) if (target && bimanual(target))
(void) erode_obj(target, 1, TRUE, FALSE); (void) water_damage(target, 0, TRUE);
glovecheck: target = which_armor(mtmp, W_ARMG); glovecheck: target = which_armor(mtmp, W_ARMG);
(void) water_damage(target, "gauntlets", TRUE); (void) water_damage(target, "gauntlets", TRUE);
break; break;
@@ -2106,7 +2109,7 @@ glovecheck: target = which_armor(mtmp, W_ARMG);
if (in_sight) if (in_sight)
pline("%s %s's right %s!", A_gush_of_water_hits, pline("%s %s's right %s!", A_gush_of_water_hits,
mon_nam(mtmp), mbodypart(mtmp, ARM)); 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; goto glovecheck;
default: default:
if (in_sight) if (in_sight)
@@ -3069,6 +3072,38 @@ xchar x, y;
return retval; 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: /* returns:
* 0 if obj is unaffected * 0 if obj is unaffected
* 1 if obj is protected by grease * 1 if obj is protected by grease

View File

@@ -2446,22 +2446,22 @@ struct attack *mattk; /* null means we find one internally */
case AD_FIRE: case AD_FIRE:
if(!rn2(6) && !mon->mcan) { if(!rn2(6) && !mon->mcan) {
(void) erode_obj(obj, 0, FALSE, FALSE); (void) rust_dmg(obj, 0, ERODE_BURN, FALSE, FALSE);
} }
break; break;
case AD_ACID: case AD_ACID:
if(!rn2(6)) { if(!rn2(6)) {
(void) erode_obj(obj, 3, FALSE, FALSE); (void) rust_dmg(obj, 0, ERODE_CORRODE, FALSE, FALSE);
} }
break; break;
case AD_RUST: case AD_RUST:
if(!mon->mcan) { if(!mon->mcan) {
(void) erode_obj(obj, 1, FALSE, FALSE); (void) rust_dmg(obj, 0, ERODE_RUST, FALSE, FALSE);
} }
break; break;
case AD_CORR: case AD_CORR:
if(!mon->mcan) { if(!mon->mcan) {
(void) erode_obj(obj, 3, FALSE, FALSE); (void) rust_dmg(obj, 0, ERODE_CORRODE, FALSE, FALSE);
} }
break; break;
case AD_ENCH: case AD_ENCH:

View File

@@ -597,131 +597,6 @@ untwoweapon()
return; 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 int
chwepon(otmp, amount) chwepon(otmp, amount)
register struct obj *otmp; register struct obj *otmp;

View File

@@ -3395,7 +3395,7 @@ struct obj **ootmp; /* to return worn armor for caller to disintegrate */
break; break;
} }
tmp = d(nd,6); 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); if (!rn2(6)) erode_armor(mon, ERODE_CORRODE);
break; break;
} }
@@ -3522,9 +3522,9 @@ xchar sx, sy;
} }
/* using two weapons at once makes both of them more vulnerable */ /* using two weapons at once makes both of them more vulnerable */
if (!rn2(u.twoweap ? 3 : 6)) if (!rn2(u.twoweap ? 3 : 6))
(void) erode_obj(uwep, 3, TRUE, FALSE); acid_damage(uwep);
if (u.twoweap && !rn2(3)) if (u.twoweap && !rn2(3))
(void) erode_obj(uswapwep, 3, TRUE, FALSE); acid_damage(uswapwep);
if (!rn2(6)) erode_armor(&youmonst, ERODE_CORRODE); if (!rn2(6)) erode_armor(&youmonst, ERODE_CORRODE);
break; break;
} }