]> granicus.if.org Git - nethack/commitdiff
high-end monster tuning
authornethack.rankin <nethack.rankin>
Tue, 19 Feb 2002 03:38:31 +0000 (03:38 +0000)
committernethack.rankin <nethack.rankin>
Tue, 19 Feb 2002 03:38:31 +0000 (03:38 +0000)
     Strengthen Death by making his "drains your life force"
result take away some max HPs to augment the ordinary damage
it does.  The chance for that effect is reduced from 80% to
75% though.  Weaken Famine, Pestilence, and Demogorgon by
preventing them from hitting with both of their disease or
hunger attacks on the same turn.  When their first attack
hits, the second now gets treated as a stun attack, but if
the first one misses then the second is unchanged and yields
another chance to deliver the disease or hunger effect.

include/extern.h
src/mhitm.c
src/mhitu.c
src/uhitm.c

index 7137a5ff83f8249e11f48e8bf650f0aa6148a94c..ca661a9286b2acc6fa109f2f2f952090be57a637 100644 (file)
@@ -929,6 +929,7 @@ E const char *FDECL(mpoisons_subj, (struct monst *,struct attack *));
 E void NDECL(u_slow_down);
 E struct monst *NDECL(cloneu);
 E void FDECL(expels, (struct monst *,struct permonst *,BOOLEAN_P));
+E struct attack *FDECL(getmattk, (struct permonst *,int,int *,struct attack *));
 E int FDECL(mattacku, (struct monst *));
 E int FDECL(gazemu, (struct monst *,struct attack *));
 E void FDECL(mdamageu, (struct monst *,int));
index 8b5209284bebe0ab5b7a6a4ea49e7df3e7bea6ca..7ec1037e5ca27e08bbb3921d7cc675eaa3058f0a 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)mhitm.c    3.4     2002/02/07      */
+/*     SCCS Id: @(#)mhitm.c    3.4     2002/02/17      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -189,7 +189,7 @@ mattackm(magr, mdef)
                    attk,       /* attack attempted this time */
                    struck = 0, /* hit at least once */
                    res[NATTK]; /* results of all attacks */
-    struct attack   *mattk;
+    struct attack   *mattk, alt_attk;
     struct permonst *pa, *pd;
 
     if (!magr || !mdef) return(MM_MISS);               /* mike@genat */
@@ -233,7 +233,7 @@ mattackm(magr, mdef)
     /* Now perform all attacks for the monster. */
     for (i = 0; i < NATTK; i++) {
        res[i] = MM_MISS;
-       mattk = &(pa->mattk[i]);
+       mattk = getmattk(pa, i, res, &alt_attk);
        otmp = (struct obj *)0;
        attk = 1;
        switch (mattk->aatyp) {
index 4c492c7f18a0aaabc7a560134e68106c1d1d496a..53bf6b49eb0eb18bd4369d71daaccedf76087c46 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)mhitu.c    3.4     2001/12/06      */
+/*     SCCS Id: @(#)mhitu.c    3.4     2002/02/17      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -265,6 +265,30 @@ boolean message;
 #endif /* OVLB */
 #ifdef OVL0
 
+/* select a monster's next attack, possibly substituting for its usual one */
+struct attack *
+getmattk(mptr, indx, prev_result, alt_attk_buf)
+struct permonst *mptr;
+int indx, prev_result[];
+struct attack *alt_attk_buf;
+{
+    struct attack *attk = &mptr->mattk[indx];
+
+    /* prevent a monster with two consecutive disease or hunger attacks
+       from hitting with both of them on the same turn; if the first has
+       already hit, switch to a stun attack for the second */
+    if (indx > 0 && prev_result[indx - 1] > 0 &&
+           (attk->adtyp == AD_DISE ||
+               attk->adtyp == AD_PEST ||
+               attk->adtyp == AD_FAMN) &&
+           attk->adtyp == mptr->mattk[indx - 1].adtyp) {
+       *alt_attk_buf = *attk;
+       attk = alt_attk_buf;
+       attk->adtyp = AD_STUN;
+    }
+    return attk;
+}
+
 /*
  * mattacku: monster attacks you
  *     returns 1 if monster dies (e.g. "yellow light"), 0 otherwise
@@ -278,7 +302,7 @@ int
 mattacku(mtmp)
        register struct monst *mtmp;
 {
-       struct  attack  *mattk;
+       struct  attack  *mattk, alt_attk;
        int     i, j, tmp, sum[NATTK];
        struct  permonst *mdat = mtmp->data;
        boolean ranged = (distu(mtmp->mx, mtmp->my) > 3);
@@ -399,7 +423,8 @@ mattacku(mtmp)
                }
                return(0);
        }
-       if (youmonst.data->mlet == S_MIMIC && youmonst.m_ap_type && !range2 && foundyou && !u.uswallow) {
+       if (youmonst.data->mlet == S_MIMIC && youmonst.m_ap_type &&
+                   !range2 && foundyou && !u.uswallow) {
                if (!youseeit) pline("It gets stuck on you.");
                else pline("Wait, %s!  That's a %s named %s!",
                           m_monnam(mtmp), youmonst.data->mname, plname);
@@ -498,7 +523,7 @@ mattacku(mtmp)
        for(i = 0; i < NATTK; i++) {
 
            sum[i] = 0;
-           mattk = &(mdat->mattk[i]);
+           mattk = getmattk(mdat, i, sum, &alt_attk);
            if (u.uswallow && (mattk->aatyp != AT_ENGL))
                continue;
            switch(mattk->aatyp) {
@@ -774,7 +799,7 @@ hitmu(mtmp, mattk)
 {
        register struct permonst *mdat = mtmp->data;
        register int uncancelled, ptmp;
-       int dmg, armpro;
+       int dmg, armpro, permdmg;
        char     buf[BUFSZ];
        struct permonst *olduasmon = youmonst.data;
        int res;
@@ -823,6 +848,7 @@ hitmu(mtmp, mattk)
                armpro = objects[uarmh->otyp].a_can;
        uncancelled = !mtmp->mcan && ((rn2(3) >= armpro) || !rn2(50));
 
+       permdmg = 0;
 /*     Now, adjust damages via resistances or specific attacks */
        switch(mattk->adtyp) {
            case AD_PHYS:
@@ -1388,16 +1414,24 @@ do_stone:
                    pline("Was that the touch of death?");
                    break;
                }
-               if(!Antimagic && rn2(20) > 16)  {
-                   killer_format = KILLED_BY_AN;
-                   killer = "touch of death";
-                   done(DIED);
-               } else {
-                   if(!rn2(5)) {
-                       if(Antimagic) shieldeff(u.ux, u.uy);
-                       pline("Lucky for you, it didn't work!");
+               switch (rn2(20)) {
+               case 19: case 18: case 17:
+                   if (!Antimagic) {
+                       killer_format = KILLED_BY_AN;
+                       killer = "touch of death";
+                       done(DIED);
                        dmg = 0;
-                   } else You_feel("your life force draining away...");
+                       break;
+                   } /* else FALLTHRU */
+               default: /* case 16: ... case 5: */
+                   You_feel("your life force draining away...");
+                   permdmg = 1;        /* actual damage done below */
+                   break;
+               case 4: case 3: case 2: case 1: case 0:
+                   if (Antimagic) shieldeff(u.ux, u.uy);
+                   pline("Lucky for you, it didn't work!");
+                   dmg = 0;
+                   break;
                }
                break;
            case AD_PEST:
@@ -1464,6 +1498,40 @@ do_stone:
                || (Role_if(PM_PRIEST) && uarmh && is_quest_artifact(uarmh) &&
                    (is_undead(mtmp->data) || is_demon(mtmp->data))))
                dmg = (dmg+1) / 2;
+
+           if (permdmg) {      /* Death's life force drain */
+               int lowerlimit, *hpmax_p;
+               /*
+                * Apply some of the damage to permanent hit points:
+                *      polymorphed         100% against poly'd hpmax
+                *      hpmax > 25*lvl      100% against normal hpmax
+                *      hpmax > 10*lvl  50..100%
+                *      hpmax >  5*lvl  25..75%
+                *      otherwise        0..50%
+                * Never reduces hpmax below 1 hit point per level.
+                */
+               permdmg = rn2(dmg / 2 + 1);
+               if (Upolyd || u.uhpmax > 25 * u.ulevel) permdmg = dmg;
+               else if (u.uhpmax > 10 * u.ulevel) permdmg += dmg / 2;
+               else if (u.uhpmax > 5 * u.ulevel) permdmg += dmg / 4;
+
+               if (Upolyd) {
+                   hpmax_p = &u.mhmax;
+                   /* [can't use youmonst.m_lev] */
+                   lowerlimit = min((int)youmonst.data->mlevel, u.ulevel);
+               } else {
+                   hpmax_p = &u.uhpmax;
+                   lowerlimit = u.ulevel;
+               }
+               if (*hpmax_p - permdmg > lowerlimit)
+                   *hpmax_p -= permdmg;
+               else if (*hpmax_p > lowerlimit)
+                   *hpmax_p = lowerlimit;
+               else    /* unlikely... */
+                   ;   /* already at or below minimum threshold; do nothing */
+               flags.botl = 1;
+           }
+
            mdamageu(mtmp, dmg);
        }
 
index 7e238f751da299b5a93d9525fe401a65f66e4dee..aae731aa21a819da5cae2c0772ffbeee16cfe981 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)uhitm.c    3.4     2001/09/06      */
+/*     SCCS Id: @(#)uhitm.c    3.4     2002/02/17      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1735,7 +1735,7 @@ hmonas(mon, tmp)          /* attack monster as a monster. */
 register struct monst *mon;
 register int tmp;
 {
-       register struct attack *mattk;
+       struct attack *mattk, alt_attk;
        int     i, sum[NATTK], hittmp = 0;
        int     nsum = 0;
        int     dhit = 0;
@@ -1743,7 +1743,7 @@ register int tmp;
        for(i = 0; i < NATTK; i++) {
 
            sum[i] = 0;
-           mattk = &(youmonst.data->mattk[i]);
+           mattk = getmattk(youmonst.data, i, sum, &alt_attk);
            switch(mattk->aatyp) {
                case AT_WEAP:
 use_weapon: