From: nethack.rankin Date: Tue, 19 Feb 2002 03:38:31 +0000 (+0000) Subject: high-end monster tuning X-Git-Tag: MOVE2GIT~3161 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=81684b1672e4e43d07f685077511f1c9a29d69b3;p=nethack high-end monster tuning 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. --- diff --git a/include/extern.h b/include/extern.h index 7137a5ff8..ca661a928 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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)); diff --git a/src/mhitm.c b/src/mhitm.c index 8b5209284..7ec1037e5 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -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) { diff --git a/src/mhitu.c b/src/mhitu.c index 4c492c7f1..53bf6b49e 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -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); } diff --git a/src/uhitm.c b/src/uhitm.c index 7e238f751..aae731aa2 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -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: