]> granicus.if.org Git - nethack/commitdiff
H206 - passive fire damage affecting weapons (trunk only)
authorcohrs <cohrs>
Tue, 20 Mar 2007 20:08:09 +0000 (20:08 +0000)
committercohrs <cohrs>
Tue, 20 Mar 2007 20:08:09 +0000 (20:08 +0000)
<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.

doc/fixes35.0
include/extern.h
src/do_wear.c
src/mhitm.c
src/mhitu.c
src/potion.c
src/trap.c
src/uhitm.c
src/wield.c
src/zap.c

index 020a61356bf7a7e24aeb6a5b7cdfe9e8a261cb6e..f8431ba08805244b4162e76c8c80b6d2acf5a751 100644 (file)
@@ -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
index f356c7ec6b19d082136545846412b304f36a0fbb..662f988c084561a35925600c89b4197b9fe20fbe 100644 (file)
@@ -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 *));
index 8fc236f68b58922f087382e28d6a3c62e3363836..9044f793046444f075e8f0bb42704c80e9d1387f 100644 (file)
@@ -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();
        }
 }
index c4b43edb75e1fde9b08728c1f0ab469601c8c8d8..82c76356cedb45ab7ad9fea323bc13b6a412ddc2 100644 (file)
@@ -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) {
index 9d1ea1c14a052db4ab8ae76445257c2ac94b5d3a..420f9dff42e2c7fb7a776ffd7bb0cffe2210535a 100644 (file)
@@ -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 */
            {
index c2be4cc9ff09822b5b75eaf0a1ae8c3b0f65a050..f68a5f781c1ebf8542ca551a96ed0e0771db9052 100644 (file)
@@ -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;
        }
 
index b91e3c7131bfa0c9a99251eceac0d4889e188561..a3aa0b372cada2a62158f4e0e7c1d1d7e00d6ac6 100644 (file)
@@ -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)
index 80d656ab500320375f718a59dae97d6ea4a366e1..c63e38b9be0b9bce2f0643c09d89d401b89dd3bb 100644 (file)
@@ -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:
index 0c5f9708f8e9ed722a113fea1e04a279a738759c..47a511a5422c40744cf48ffe6a9025ce693c66df 100644 (file)
@@ -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]);
            }
        }
 
index 7b2065a3c8d71c222c4b8f5681cd91f3636f2d9f..048aa936799cd09b08c523e20370718cd1e21cc3 100644 (file)
--- 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;
        }