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
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 ### */
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);
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 *));
"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 *));
(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]) {
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;
}
}
-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
}
} 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) {
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 *));
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);
}
}
-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;
}
} 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 */
{
}
if (potion->otyp == POT_ACID) {
- if (erode_obj(obj, 3, FALSE, TRUE))
+ if (rust_dmg(obj, 0, ERODE_CORRODE, TRUE, FALSE))
goto poof;
}
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 */
/* 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.
*/
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))) {
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"));
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,
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
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);
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;
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)
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
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:
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;
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;
}
}
/* 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;
}