]> granicus.if.org Git - nethack/commitdiff
anti-magic trap (trunk only)
authornethack.rankin <nethack.rankin>
Sat, 25 Nov 2006 02:29:39 +0000 (02:29 +0000)
committernethack.rankin <nethack.rankin>
Sat, 25 Nov 2006 02:29:39 +0000 (02:29 +0000)
     Make anti-magic fields do something against targets which have magic
resistance, expanding the functionality of that trap type and giving a
minor drawback to the most valuable intrinsic in the game.  Make them work
against monsters too.

     Heroes who lack magic resistance lose spell energy as before, except
that if they drop below 0 they don't take as hard a hit against max spell
energy as they used to.  Monsters with spell or breath attack and lacking
magic resistance get their ability-last-used field bumped up a little bit,
so they can't cast or breathe for a few turns.  Heroes and monsters who
have magic resistance take HP damage instead.  I retained the concept of
feeling lethargic when being hit by something which normally drains enery,
and also tried to make it be the inverse of a "magical explosion":  the
message refers to torpor/lethargy/sluggishness and cause of death if the
damage happens to be fatal is "anti-magic implosion".  The latter suggests
some sort of compression, so creatures who can pass through walls (xorns
and ghosts) have been given partial resistance and take reduced damage.

doc/fixes35.0
src/trap.c

index 05433163018610e5ae9c87b5915f8d3ea65172e8..80e877e9341b9b9f8c29cddc0795fa5b364a0be0 100644 (file)
@@ -257,6 +257,7 @@ lembas and cram never rot unless cursed
 multiple squeaks for squeaky boards
 include time, user ID, and play mode in paniclog entries
 add oracle and rumor regarding priestly donations
+anti-magic traps have alternate effect on targets who have magic resistance
 
 
 Platform- and/or Interface-Specific New Features
index 87ebfc44431a4d0d96d39694642e17d9963dca1c..03fa1968ed8ae2dcf1238ca526e5c298663d6b9e 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)trap.c     3.5     2006/09/28      */
+/*     SCCS Id: @(#)trap.c     3.5     2006/11/22      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1182,10 +1182,36 @@ glovecheck:             (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst);
 
            case ANTI_MAGIC:
                seetrap(trap);
-               if(Antimagic) {
-                   shieldeff(u.ux, u.uy);
-                   You_feel("momentarily lethargic.");
-               } else drain_en(rnd(u.ulevel) + 1);
+               /* hero without magic resistance loses spell energy,
+                  hero with magic resistance takes damage instead;
+                  possibly non-intuitive but useful for play balance */
+               if (!Antimagic) {
+                   drain_en(rnd(u.ulevel) + 1);
+               } else {
+                   int dmgval = rnd(4), hp = Upolyd ? u.mh : u.uhp;
+
+                   /* Half_XXX_damage has opposite its usual effect (approx)
+                      but isn't cumulative if hero has more than one */
+                   if (Half_physical_damage || Half_spell_damage)
+                       dmgval += rnd(4);
+                   /* give Magicbane wielder dose of own medicine */
+                   if (uwep && uwep->oartifact == ART_MAGICBANE)
+                       dmgval += rnd(4);
+                   /* having an artifact--other than own quest one--which
+                      confers magic resistance simply by being carried
+                      also increases the effect */
+                   for (otmp = invent; otmp; otmp = otmp->nobj)
+                       if (otmp->oartifact && !is_quest_artifact(otmp) &&
+                           protects(AD_MAGM, otmp)) break;
+                   if (otmp) dmgval += rnd(4);
+                   if (Passes_walls) dmgval = (dmgval + 3) / 4;
+
+                   You_feel((dmgval >= hp) ? "unbearably torpid!" :
+                            (dmgval >= hp / 4) ? "very lethargic." :
+                            "sluggish.");
+                   /* opposite of magical explosion */
+                   losehp(dmgval, "anti-magic implosion", KILLED_BY_AN);
+               }
                break;
 
            case POLY_TRAP: {
@@ -1898,7 +1924,7 @@ register struct monst *mtmp;
 #endif
            if (!inescapable &&
                    ((mtmp->mtrapseen & (1 << (tt-1))) != 0 ||
-                       (tt == HOLE && !mindless(mtmp->data)))) {
+                       (tt == HOLE && !mindless(mptr)))) {
                /* it has been in such a trap - perhaps it escapes */
                if(rn2(4)) return(0);
            } else {
@@ -2112,7 +2138,7 @@ glovecheck:                   target = which_armor(mtmp, W_ARMG);
 
                            /* paper burns very fast, assume straw is tightly
                             * packed and burns a bit slower */
-                           switch (monsndx(mtmp->data)) {
+                           switch (monsndx(mptr)) {
                            case PM_PAPER_GOLEM:   immolate = TRUE;
                                                   alt = mtmp->mhpmax; break;
                            case PM_STRAW_GOLEM:   alt = mtmp->mhpmax / 2; break;
@@ -2166,7 +2192,8 @@ glovecheck:                   target = which_armor(mtmp, W_ARMG);
                            pline("%s %s into %s pit!",
                                  Monnam(mtmp), fallverb,
                                  a_your[trap->madeby_u]);
-                           if (mptr == &mons[PM_PIT_VIPER] || mptr == &mons[PM_PIT_FIEND])
+                           if (mptr == &mons[PM_PIT_VIPER] ||
+                                   mptr == &mons[PM_PIT_FIEND])
                                pline("How pitiful.  Isn't that the pits?");
                            seetrap(trap);
                        }
@@ -2317,6 +2344,36 @@ glovecheck:                  target = which_armor(mtmp, W_ARMG);
                        if (!rn2(21)) goto mfiretrap;
                        break;
                case ANTI_MAGIC:
+                       /* similar to hero's case, more or less */
+                       if (!resists_magm(mtmp)) {      /* lose spell energy */
+                           if (attacktype(mptr, AT_MAGC) ||
+                                   attacktype(mptr, AT_BREA)) {
+                               mtmp->mspec_used += d(2, 2);
+                               if (in_sight) {
+                                   seetrap(trap);
+                                   pline("%s seems lethargic.", Monnam(mtmp));
+                               }
+                           }
+                       } else {                        /* take some damage */
+                           int dmgval = rnd(4);
+
+                           if ((otmp = MON_WEP(mtmp)) != 0 &&
+                                   otmp->oartifact == ART_MAGICBANE)
+                               dmgval += rnd(4);
+                           for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 
+                               if (otmp->oartifact && protects(AD_MAGM, otmp))
+                                   break;
+                           if (otmp) dmgval += rnd(4);
+                           if (passes_walls(mptr)) dmgval = (dmgval + 3) / 4;
+
+                           if (in_sight) seetrap(trap);
+                           if ((mtmp->mhp -= dmgval) <= 0)
+                               monkilled(mtmp, in_sight ?
+                                   "compression from an anti-magic field" : 0,
+                                         -AD_MAGM);
+                           if (mtmp->mhp <= 0) trapkilled = TRUE;
+                           if (see_it) newsym(trap->tx, trap->ty);
+                       }
                        break;
 
                case LANDMINE:
@@ -2364,8 +2421,9 @@ glovecheck:                   target = which_armor(mtmp, W_ARMG);
                    if (resists_magm(mtmp)) {
                        shieldeff(mtmp->mx, mtmp->my);
                    } else if (!resist(mtmp, WAND_CLASS, 0, NOTELL)) {
-                       (void) newcham(mtmp, (struct permonst *)0,
-                                      FALSE, FALSE);
+                       if (newcham(mtmp, (struct permonst *)0, FALSE, FALSE))
+                           /* we're done with mptr but keep it up to date */
+                           mptr = mtmp->data;
                        if (in_sight) seetrap(trap);
                    }
                    break;
@@ -3288,15 +3346,18 @@ void
 drain_en(n)
 register int n;
 {
-       if (!u.uenmax) return;
+    if (!u.uenmax) {
+       You_feel("momentarily lethargic.");
+    } else {
        You_feel("your magical energy drain away!");
        u.uen -= n;
        if(u.uen < 0)  {
-               u.uenmax += u.uen;
+               u.uenmax -= rnd(-u.uen);
                if(u.uenmax < 0) u.uenmax = 0;
                u.uen = 0;
        }
        context.botl = 1;
+    }
 }
 
 int