From: cohrs Date: Tue, 20 Mar 2007 20:08:09 +0000 (+0000) Subject: H206 - passive fire damage affecting weapons (trunk only) X-Git-Tag: MOVE2GIT~661 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a5640e4bc8bd0c6e89a8420de82731210e802e0b;p=nethack H206 - passive fire damage affecting weapons (trunk only) reported back on 8/31/06 that elven weapons were not affected when he poked a fire elemental with them. This is true, but moreover, there was no code to have passive fire to affect attackers. Now erode_obj() supports all the same damage types as rust_dmg(), and added the connecting code to allow passive fire attacks do something. There probably should be macros for the damage types used by rust_dmg and erode_obj, and possibly these functions should be combined, but they are slightly different and dealing with that requires more thought. --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 020a61356..f8431ba08 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -199,6 +199,7 @@ artifacts which subsequently evade your grasp/control after already being worn or wielded become unworn/unwielded hero with lycanthropy is vulnerable to silver in human form as well as beast changing alignment or shape triggers a check for equipment evading hero's grasp +passive fire effects can damage attackers weapons Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index f356c7ec6..662f988c0 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2519,7 +2519,7 @@ E void NDECL(uwepgone); E void NDECL(uswapwepgone); E void NDECL(uqwepgone); E void NDECL(untwoweapon); -E boolean FDECL(erode_obj, (struct obj *,BOOLEAN_P,BOOLEAN_P,BOOLEAN_P)); +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/do_wear.c b/src/do_wear.c index 8fc236f68..9044f7930 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -1761,7 +1761,7 @@ boolean acid_dmg; struct obj *otmph = some_armor(victim); if (otmph && (otmph != uarmf)) { - (void) erode_obj(otmph, acid_dmg, FALSE, FALSE); + (void) erode_obj(otmph, acid_dmg ? 3 : 1, FALSE, FALSE); if (carried(otmph)) update_inventory(); } } diff --git a/src/mhitm.c b/src/mhitm.c index c4b43edb7..82c76356c 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -885,7 +885,7 @@ mdamagem(magr, mdef, mattk) pline("It burns %s!", mon_nam(mdef)); } if (!rn2(30)) erode_armor(mdef, TRUE); - if (!rn2(6)) (void) erode_obj(MON_WEP(mdef), TRUE, TRUE, FALSE); + if (!rn2(6)) (void) erode_obj(MON_WEP(mdef), 3, TRUE, FALSE); break; case AD_RUST: if (magr->mcan) break; @@ -1299,16 +1299,19 @@ mrustm(magr, mdef, obj) register struct monst *magr, *mdef; register struct obj *obj; { - boolean is_acid; + int dmgtyp; if (!magr || !mdef || !obj) return; /* just in case */ + /* AD_ACID is handled in passivemm */ if (dmgtype(mdef->data, AD_CORR)) - is_acid = TRUE; + dmgtyp = 3; else if (dmgtype(mdef->data, AD_RUST)) - is_acid = FALSE; + dmgtyp = 1; + else if (dmgtype(mdef->data, AD_FIRE)) + dmgtyp = 0; else return; - (void) erode_obj(obj, is_acid, FALSE, FALSE); + (void) erode_obj(obj, dmgtyp, FALSE, FALSE); } STATIC_OVL void @@ -1365,6 +1368,8 @@ int mdead; tmp = 0; } } else tmp = 0; + if (!rn2(30)) erode_armor(magr, TRUE); + if (!rn2(6)) (void)erode_obj(MON_WEP(magr), 3, TRUE, FALSE); 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 9d1ea1c14..420f9dff4 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -2077,16 +2077,19 @@ urustm(mon, obj) register struct monst *mon; register struct obj *obj; { - boolean is_acid; + int dmgtyp; if (!mon || !obj) return; /* just in case */ + /* AD_ACID is handled in passiveum */ if (dmgtype(youmonst.data, AD_CORR)) - is_acid = TRUE; + dmgtyp = 3; else if (dmgtype(youmonst.data, AD_RUST)) - is_acid = FALSE; + dmgtyp = 1; + else if (dmgtype(youmonst.data, AD_FIRE)) + dmgtyp = 0; else return; - (void) erode_obj(obj, is_acid, FALSE, FALSE); + (void) erode_obj(obj, dmgtyp, FALSE, FALSE); } int @@ -2466,7 +2469,7 @@ register struct attack *mattk; } } else tmp = 0; if (!rn2(30)) erode_armor(mtmp, TRUE); - if (!rn2(6)) (void)erode_obj(MON_WEP(mtmp), TRUE, TRUE, FALSE); + if (!rn2(6)) (void)erode_obj(MON_WEP(mtmp), 3, TRUE, FALSE); goto assess_dmg; case AD_STON: /* cockatrice */ { diff --git a/src/potion.c b/src/potion.c index c2be4cc9f..f68a5f781 100644 --- a/src/potion.c +++ b/src/potion.c @@ -1934,7 +1934,7 @@ dodip() } if (potion->otyp == POT_ACID) { - if (erode_obj(obj, TRUE, FALSE, TRUE)) + if (erode_obj(obj, 3, FALSE, TRUE)) goto poof; } diff --git a/src/trap.c b/src/trap.c index b91e3c713..a3aa0b372 100644 --- a/src/trap.c +++ b/src/trap.c @@ -932,7 +932,7 @@ unsigned trflags; break; if (u.twoweap || (uwep && bimanual(uwep))) (void) erode_obj(u.twoweap ? uswapwep : uwep, - FALSE, TRUE, FALSE); + 1, TRUE, FALSE); glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); /* Not "metal gauntlets" since it gets called * even if it's leather for the message @@ -941,7 +941,7 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); case 2: pline("%s your right %s!", A_gush_of_water_hits, body_part(ARM)); - (void) erode_obj(uwep, FALSE, TRUE, FALSE); + (void) erode_obj(uwep, 1, TRUE, FALSE); goto glovecheck; default: pline("%s you!", A_gush_of_water_hits); @@ -2090,7 +2090,7 @@ register struct monst *mtmp; break; target = MON_WEP(mtmp); if (target && bimanual(target)) - (void) erode_obj(target, FALSE, TRUE, FALSE); + (void) erode_obj(target, 1, TRUE, FALSE); glovecheck: target = which_armor(mtmp, W_ARMG); (void) rust_dmg(target, "gauntlets", 1, TRUE, mtmp); break; @@ -2098,7 +2098,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), FALSE, TRUE, FALSE); + (void) erode_obj(MON_WEP(mtmp), 1, TRUE, FALSE); goto glovecheck; default: if (in_sight) diff --git a/src/uhitm.c b/src/uhitm.c index 80d656ab5..c63e38b9b 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -2204,6 +2204,17 @@ boolean wep_was_destroyed; switch(ptr->mattk[i].adtyp) { + case AD_FIRE: + if(mhit && !mon->mcan) { + if (aatyp == AT_KICK) { + if (uarmf && !rn2(6)) + (void)rust_dmg(uarmf, xname(uarmf), 0, TRUE, &youmonst); + } else if (aatyp == AT_WEAP || aatyp == AT_CLAW || + aatyp == AT_MAGC || aatyp == AT_TUCH) + passive_obj(mon, (struct obj*)0, &(ptr->mattk[i])); + } + break; + case AD_ACID: if(mhit && rn2(2)) { if (Blind || !flags.verbose) You("are splashed!"); @@ -2415,19 +2426,24 @@ struct attack *mattk; /* null means we find one internally */ switch(mattk->adtyp) { + case AD_FIRE: + if(!rn2(6) && !mon->mcan) { + (void) erode_obj(obj, 0, FALSE, FALSE); + } + break; case AD_ACID: if(!rn2(6)) { - (void) erode_obj(obj, TRUE, FALSE, FALSE); + (void) erode_obj(obj, 3, FALSE, FALSE); } break; case AD_RUST: if(!mon->mcan) { - (void) erode_obj(obj, FALSE, FALSE, FALSE); + (void) erode_obj(obj, 1, FALSE, FALSE); } break; case AD_CORR: if(!mon->mcan) { - (void) erode_obj(obj, TRUE, FALSE, FALSE); + (void) erode_obj(obj, 3, FALSE, FALSE); } break; case AD_ENCH: diff --git a/src/wield.c b/src/wield.c index 0c5f9708f..47a511a54 100644 --- a/src/wield.c +++ b/src/wield.c @@ -611,18 +611,24 @@ untwoweapon() return; } -/* Maybe rust object, or corrode it if acid damage is called for. +/* Maybe rust (or corrode, burn, rot) object. * Returns TRUE if something happened. */ boolean -erode_obj(target, acid_dmg, fade_scrolls, for_dip) +erode_obj(target, type, fade_scrolls, for_dip) struct obj *target; /* object (e.g. weapon or armor) to erode */ -boolean acid_dmg; +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, erodible; + boolean vismon, visobj, chill; boolean ret = FALSE; boolean already_affected = FALSE; @@ -633,17 +639,34 @@ boolean for_dip; vismon = victim && (victim != &youmonst) && canseemon(victim); visobj = !victim && cansee(bhitpos.x, bhitpos.y); /* assume thrown */ - if (!acid_dmg && target->lamplit) { - already_affected = snuff_lit(target); - if (already_affected) ret = TRUE; + 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 = acid_dmg ? target->oeroded2 : target->oeroded; - erodible = acid_dmg ? is_corrodeable(target) : is_rustprone(target); + erosion = is_primary ? target->oeroded : target->oeroded2; - if (target->greased) { + if (target->greased && grprot) { grease_protect(target,(char *)0,victim); ret = TRUE; - } else if (target->oclass == SCROLL_CLASS) { + } else if (target->oclass == SCROLL_CLASS && (type == 1 || type == 3)) { if(fade_scrolls && target->otyp != SCR_BLANK_PAPER #ifdef MAIL && target->otyp != SCR_MAIL @@ -658,15 +681,13 @@ boolean for_dip; target->spe = 0; ret = TRUE; } - } else if (target->oartifact && - /* (no artifacts currently meet either of these criteria) */ - arti_immune(target, acid_dmg ? AD_ACID : AD_RUST)) { - if (flags.verbose) { + } 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 && !acid_dmg && + } 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)) && @@ -678,39 +699,37 @@ boolean for_dip; Yobjnam2(target, chill ? "freeze" : "boil")); } /* no damage to object */ - } else if (target->oerodeproof || !erodible) { + } 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 || (erodible && !target->rknown)) + if (flags.verbose || (vulnerable && !target->rknown)) pline("%s not %s.", Yobjnam2(target, "are"), already_affected ? "harmed" : "affected"); - if (erodible) target->rknown = 1; + if (vulnerable) target->rknown = 1; } } else if (erosion < MAX_ERODE) { if (victim == &youmonst || vismon || visobj) { - pline("%s%s!", Yobjnam2(target, acid_dmg ? "corrode" : "rust"), + pline("%s%s!", Yobjnam2(target, action[type]), erosion+1 == MAX_ERODE ? " completely" : erosion ? " further" : ""); target->rknown = 1; /* it's obviously not erode-proof */ } - if (acid_dmg) - target->oeroded2++; - else + 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"), - acid_dmg ? "corroded" : "rusty"); + Yobjnam2(target, Blind ? "feel" : "look"), msg[type]); else if (vismon || visobj) pline("%s completely %s.", - Yobjnam2(target, "look"), - acid_dmg ? "corroded" : "rusty"); + Yobjnam2(target, "look"), msg[type]); } } diff --git a/src/zap.c b/src/zap.c index 7b2065a3c..048aa9367 100644 --- a/src/zap.c +++ b/src/zap.c @@ -3321,7 +3321,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), TRUE, TRUE, FALSE); + if (!rn2(6)) (void) erode_obj(MON_WEP(mon), 3, TRUE, FALSE); if (!rn2(6)) erode_armor(mon, TRUE); break; } @@ -3451,9 +3451,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, TRUE, TRUE, FALSE); + (void) erode_obj(uwep, 3, TRUE, FALSE); if (u.twoweap && !rn2(3)) - (void) erode_obj(uswapwep, TRUE, TRUE, FALSE); + (void) erode_obj(uswapwep, 3, TRUE, FALSE); if (!rn2(6)) erode_armor(&youmonst, TRUE); break; }