H206 - passive fire damage affecting weapons (trunk only)

<email deleted> 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.
This commit is contained in:
cohrs
2007-03-20 20:08:09 +00:00
parent 338e8b0a19
commit a5640e4bc8
10 changed files with 94 additions and 50 deletions
+1
View File
@@ -199,6 +199,7 @@ artifacts which subsequently evade your grasp/control after already being
worn or wielded become unworn/unwielded worn or wielded become unworn/unwielded
hero with lycanthropy is vulnerable to silver in human form as well as beast 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 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 Platform- and/or Interface-Specific Fixes
+1 -1
View File
@@ -2519,7 +2519,7 @@ 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 *,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(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 *));
+1 -1
View File
@@ -1761,7 +1761,7 @@ boolean acid_dmg;
struct obj *otmph = some_armor(victim); struct obj *otmph = some_armor(victim);
if (otmph && (otmph != uarmf)) { 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(); if (carried(otmph)) update_inventory();
} }
} }
+10 -5
View File
@@ -885,7 +885,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, TRUE); 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; break;
case AD_RUST: case AD_RUST:
if (magr->mcan) break; if (magr->mcan) break;
@@ -1299,16 +1299,19 @@ mrustm(magr, mdef, obj)
register struct monst *magr, *mdef; register struct monst *magr, *mdef;
register struct obj *obj; register struct obj *obj;
{ {
boolean is_acid; int dmgtyp;
if (!magr || !mdef || !obj) return; /* just in case */ if (!magr || !mdef || !obj) return; /* just in case */
/* AD_ACID is handled in passivemm */
if (dmgtype(mdef->data, AD_CORR)) if (dmgtype(mdef->data, AD_CORR))
is_acid = TRUE; dmgtyp = 3;
else if (dmgtype(mdef->data, AD_RUST)) else if (dmgtype(mdef->data, AD_RUST))
is_acid = FALSE; dmgtyp = 1;
else if (dmgtype(mdef->data, AD_FIRE))
dmgtyp = 0;
else else
return; return;
(void) erode_obj(obj, is_acid, FALSE, FALSE); (void) erode_obj(obj, dmgtyp, FALSE, FALSE);
} }
STATIC_OVL void STATIC_OVL void
@@ -1365,6 +1368,8 @@ int mdead;
tmp = 0; tmp = 0;
} }
} else 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; 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) {
+8 -5
View File
@@ -2077,16 +2077,19 @@ urustm(mon, obj)
register struct monst *mon; register struct monst *mon;
register struct obj *obj; register struct obj *obj;
{ {
boolean is_acid; int dmgtyp;
if (!mon || !obj) return; /* just in case */ if (!mon || !obj) return; /* just in case */
/* AD_ACID is handled in passiveum */
if (dmgtype(youmonst.data, AD_CORR)) if (dmgtype(youmonst.data, AD_CORR))
is_acid = TRUE; dmgtyp = 3;
else if (dmgtype(youmonst.data, AD_RUST)) else if (dmgtype(youmonst.data, AD_RUST))
is_acid = FALSE; dmgtyp = 1;
else if (dmgtype(youmonst.data, AD_FIRE))
dmgtyp = 0;
else else
return; return;
(void) erode_obj(obj, is_acid, FALSE, FALSE); (void) erode_obj(obj, dmgtyp, FALSE, FALSE);
} }
int int
@@ -2466,7 +2469,7 @@ register struct attack *mattk;
} }
} else tmp = 0; } else tmp = 0;
if (!rn2(30)) erode_armor(mtmp, TRUE); 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; goto assess_dmg;
case AD_STON: /* cockatrice */ case AD_STON: /* cockatrice */
{ {
+1 -1
View File
@@ -1934,7 +1934,7 @@ dodip()
} }
if (potion->otyp == POT_ACID) { if (potion->otyp == POT_ACID) {
if (erode_obj(obj, TRUE, FALSE, TRUE)) if (erode_obj(obj, 3, FALSE, TRUE))
goto poof; goto poof;
} }
+4 -4
View File
@@ -932,7 +932,7 @@ unsigned trflags;
break; break;
if (u.twoweap || (uwep && bimanual(uwep))) if (u.twoweap || (uwep && bimanual(uwep)))
(void) erode_obj(u.twoweap ? uswapwep : uwep, (void) erode_obj(u.twoweap ? uswapwep : uwep,
FALSE, TRUE, FALSE); 1, TRUE, FALSE);
glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst);
/* 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
@@ -941,7 +941,7 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst);
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, FALSE, TRUE, FALSE); (void) erode_obj(uwep, 1, TRUE, FALSE);
goto glovecheck; goto glovecheck;
default: default:
pline("%s you!", A_gush_of_water_hits); pline("%s you!", A_gush_of_water_hits);
@@ -2090,7 +2090,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, FALSE, TRUE, FALSE); (void) erode_obj(target, 1, TRUE, FALSE);
glovecheck: target = which_armor(mtmp, W_ARMG); glovecheck: target = which_armor(mtmp, W_ARMG);
(void) rust_dmg(target, "gauntlets", 1, TRUE, mtmp); (void) rust_dmg(target, "gauntlets", 1, TRUE, mtmp);
break; break;
@@ -2098,7 +2098,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), FALSE, TRUE, FALSE); (void) erode_obj(MON_WEP(mtmp), 1, TRUE, FALSE);
goto glovecheck; goto glovecheck;
default: default:
if (in_sight) if (in_sight)
+19 -3
View File
@@ -2204,6 +2204,17 @@ boolean wep_was_destroyed;
switch(ptr->mattk[i].adtyp) { 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: case AD_ACID:
if(mhit && rn2(2)) { if(mhit && rn2(2)) {
if (Blind || !flags.verbose) You("are splashed!"); if (Blind || !flags.verbose) You("are splashed!");
@@ -2415,19 +2426,24 @@ struct attack *mattk; /* null means we find one internally */
switch(mattk->adtyp) { switch(mattk->adtyp) {
case AD_FIRE:
if(!rn2(6) && !mon->mcan) {
(void) erode_obj(obj, 0, FALSE, FALSE);
}
break;
case AD_ACID: case AD_ACID:
if(!rn2(6)) { if(!rn2(6)) {
(void) erode_obj(obj, TRUE, FALSE, FALSE); (void) erode_obj(obj, 3, FALSE, FALSE);
} }
break; break;
case AD_RUST: case AD_RUST:
if(!mon->mcan) { if(!mon->mcan) {
(void) erode_obj(obj, FALSE, FALSE, FALSE); (void) erode_obj(obj, 1, FALSE, FALSE);
} }
break; break;
case AD_CORR: case AD_CORR:
if(!mon->mcan) { if(!mon->mcan) {
(void) erode_obj(obj, TRUE, FALSE, FALSE); (void) erode_obj(obj, 3, FALSE, FALSE);
} }
break; break;
case AD_ENCH: case AD_ENCH:
+46 -27
View File
@@ -611,18 +611,24 @@ untwoweapon()
return; 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. */ * Returns TRUE if something happened. */
boolean 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 */ struct obj *target; /* object (e.g. weapon or armor) to erode */
boolean acid_dmg; int type;
boolean fade_scrolls; boolean fade_scrolls;
boolean for_dip; 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 erosion;
int dmgtyp = AD_ACID;
struct monst *victim; struct monst *victim;
boolean vismon, visobj, chill, erodible; boolean vismon, visobj, chill;
boolean ret = FALSE; boolean ret = FALSE;
boolean already_affected = FALSE; boolean already_affected = FALSE;
@@ -633,17 +639,34 @@ boolean for_dip;
vismon = victim && (victim != &youmonst) && canseemon(victim); vismon = victim && (victim != &youmonst) && canseemon(victim);
visobj = !victim && cansee(bhitpos.x, bhitpos.y); /* assume thrown */ visobj = !victim && cansee(bhitpos.x, bhitpos.y); /* assume thrown */
if (!acid_dmg && target->lamplit) { switch(type) {
already_affected = snuff_lit(target); case 0: vulnerable = is_flammable(target);
if (already_affected) ret = TRUE; 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; erosion = is_primary ? target->oeroded : target->oeroded2;
erodible = acid_dmg ? is_corrodeable(target) : is_rustprone(target);
if (target->greased) { if (target->greased && grprot) {
grease_protect(target,(char *)0,victim); grease_protect(target,(char *)0,victim);
ret = TRUE; 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 if(fade_scrolls && target->otyp != SCR_BLANK_PAPER
#ifdef MAIL #ifdef MAIL
&& target->otyp != SCR_MAIL && target->otyp != SCR_MAIL
@@ -658,15 +681,13 @@ boolean for_dip;
target->spe = 0; target->spe = 0;
ret = TRUE; ret = TRUE;
} }
} else if (target->oartifact && } else if (target->oartifact && arti_immune(target, dmgtyp)) {
/* (no artifacts currently meet either of these criteria) */ if (flags.verbose && (dmgtyp != AD_FIRE)) {
arti_immune(target, acid_dmg ? AD_ACID : AD_RUST)) {
if (flags.verbose) {
if (victim == &youmonst) if (victim == &youmonst)
pline("%s.", Yobjnam2(target, "sizzle")); pline("%s.", Yobjnam2(target, "sizzle"));
} }
/* no damage to object */ /* no damage to object */
} else if (target->oartifact && !acid_dmg && } else if (target->oartifact && (type == 1) &&
/* cold and fire provide partial protection against rust */ /* cold and fire provide partial protection against rust */
((chill = arti_immune(target, AD_COLD)) != 0 || ((chill = arti_immune(target, AD_COLD)) != 0 ||
arti_immune(target, AD_FIRE)) && arti_immune(target, AD_FIRE)) &&
@@ -678,39 +699,37 @@ boolean for_dip;
Yobjnam2(target, chill ? "freeze" : "boil")); Yobjnam2(target, chill ? "freeze" : "boil"));
} }
/* no damage to object */ /* no damage to object */
} else if (target->oerodeproof || !erodible) { } else if (target->oerodeproof || !vulnerable) {
/* no message if dipping or not carried */ /* no message if dipping or not carried */
if (for_dip) { if (for_dip) {
/* assumes that for_dip implies player action */ /* assumes that for_dip implies player action */
if (!Blind) target->rknown = 0; if (!Blind) target->rknown = 0;
} else if (victim == &youmonst || vismon) { } else if (victim == &youmonst || vismon) {
if (flags.verbose || (erodible && !target->rknown)) if (flags.verbose || (vulnerable && !target->rknown))
pline("%s not %s.", Yobjnam2(target, "are"), pline("%s not %s.", Yobjnam2(target, "are"),
already_affected ? "harmed" : "affected"); already_affected ? "harmed" : "affected");
if (erodible) target->rknown = 1; if (vulnerable) target->rknown = 1;
} }
} else if (erosion < MAX_ERODE) { } else if (erosion < MAX_ERODE) {
if (victim == &youmonst || vismon || visobj) { 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+1 == MAX_ERODE ? " completely" :
erosion ? " further" : ""); erosion ? " further" : "");
target->rknown = 1; /* it's obviously not erode-proof */ target->rknown = 1; /* it's obviously not erode-proof */
} }
if (acid_dmg) if (is_primary)
target->oeroded2++;
else
target->oeroded++; target->oeroded++;
else
target->oeroded2++;
ret = TRUE; ret = TRUE;
} else { } else {
if (flags.verbose && !for_dip) { if (flags.verbose && !for_dip) {
if (victim == &youmonst) if (victim == &youmonst)
pline("%s completely %s.", pline("%s completely %s.",
Yobjnam2(target, Blind ? "feel" : "look"), Yobjnam2(target, Blind ? "feel" : "look"), msg[type]);
acid_dmg ? "corroded" : "rusty");
else if (vismon || visobj) else if (vismon || visobj)
pline("%s completely %s.", pline("%s completely %s.",
Yobjnam2(target, "look"), Yobjnam2(target, "look"), msg[type]);
acid_dmg ? "corroded" : "rusty");
} }
} }
+3 -3
View File
@@ -3321,7 +3321,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), TRUE, TRUE, FALSE); if (!rn2(6)) (void) erode_obj(MON_WEP(mon), 3, TRUE, FALSE);
if (!rn2(6)) erode_armor(mon, TRUE); if (!rn2(6)) erode_armor(mon, TRUE);
break; break;
} }
@@ -3451,9 +3451,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, TRUE, TRUE, FALSE); (void) erode_obj(uwep, 3, TRUE, FALSE);
if (u.twoweap && !rn2(3)) 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); if (!rn2(6)) erode_armor(&youmonst, TRUE);
break; break;
} }