From: nethack.rankin Date: Thu, 22 Sep 2005 06:02:08 +0000 (+0000) Subject: level drain while polymorphed (trunk only) X-Git-Tag: MOVE2GIT~1234 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7828cb368709ce7e49131d561720a805ed9e3999;p=nethack level drain while polymorphed (trunk only) Noticed when incorporating the "vampire dancing" patch: losing a level while polymorphed would subtract from your normal hit points but didn't affect your monster hit points. Now they'll lose d8 from max and current, similar to the amount they increase when gaining a level. This also addresses an issue from the newsgroup a few weeks back: someone mentioned an assumption that Stormbringer drained an amount other than d8 for monsters who use some other formula for their hit points. It wasn't true, but now it will be (approximately). Most monsters with unusual hit points aren't subject to level drain, so it shouldn't have much impact. --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index dcc66ec72..a8ca82367 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -86,6 +86,8 @@ various actions--such as enchanting--performed on an unpaid shop object adjust health threshold where wounded hero will be healed by successful prayer prevent lose-level+regain-level cycle from arbritrarily boosting HP and Pw prevent polymorphing into "new man" at low level from magnifying HP and Pw +losing a level while polymorphed affects hero's current monster HP as well as + underlying normal HP Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 1584fea30..934ef429f 100644 --- a/include/extern.h +++ b/include/extern.h @@ -960,6 +960,7 @@ E void FDECL(readmail, (struct obj *)); E boolean FDECL(is_home_elemental, (struct permonst *)); E struct monst *FDECL(clone_mon, (struct monst *,XCHAR_P,XCHAR_P)); +E int FDECL(monhp_per_lvl, (struct monst *)); E void FDECL(newmonhp, (struct monst *,int)); E struct monst *FDECL(makemon, (struct permonst *,int,int,int)); E boolean FDECL(create_critters, (int,struct permonst *)); diff --git a/src/artifact.c b/src/artifact.c index 2d9cbb719..c8950b1e5 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)artifact.c 3.5 2005/04/15 */ +/* SCCS Id: @(#)artifact.c 3.5 2005/09/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1133,7 +1133,7 @@ int dieroll; /* needed for Magicbane and vorpal blades */ if (mdef->m_lev == 0) { *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER; } else { - int drain = rnd(8); + int drain = monhp_per_lvl(mdef); *dmgptr += drain; mdef->mhpmax -= drain; mdef->m_lev--; diff --git a/src/exper.c b/src/exper.c index ec276c4da..523a72e37 100644 --- a/src/exper.c +++ b/src/exper.c @@ -190,6 +190,14 @@ const char *drainer; /* cause of death, if drain should be fatal */ if (u.uexp > 0) u.uexp = newuexp(u.ulevel) - 1; + + if (Upolyd) { + num = monhp_per_lvl(&youmonst); + u.mhmax -= num; + u.mh -= num; + if (u.mh <= 0) rehumanize(); + } + context.botl = 1; } @@ -217,7 +225,7 @@ boolean incr; /* true iff via incremental experience growth */ /* increase hit points (when polymorphed, do monster form first in order to retain normal human/whatever increase for later) */ if (Upolyd) { - hpinc = rnd(8); + hpinc = monhp_per_lvl(&youmonst); u.mhmax += hpinc; u.mh += hpinc; } diff --git a/src/makemon.c b/src/makemon.c index 23177d7e0..05945ab6c 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)makemon.c 3.5 2005/07/13 */ +/* SCCS Id: @(#)makemon.c 3.5 2005/09/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -803,6 +803,31 @@ boolean ghostly; return result; } +/* amount of HP to lose from level drain (or gain from Stormbringer) */ +int +monhp_per_lvl(mon) +struct monst *mon; +{ + struct permonst *ptr = mon->data; + int hp = rnd(8); /* default is d8 */ + + /* like newmonhp, but home elementals are ignored, riders use normal d8 */ + if (is_golem(ptr)) { + /* draining usually won't be applicable for these critters */ + hp = golemhp(monsndx(ptr)) / (int)ptr->mlevel; + } else if (ptr->mlevel > 49) { + /* arbitrary; such monsters won't be involved in draining anyway */ + hp = 4 + rnd(4); /* 5..8 */ + } else if (ptr->mlet == S_DRAGON && monsndx(ptr) >= PM_GRAY_DRAGON) { + /* adult dragons; newmonhp() uses In_endgame(&u.uz) ? 8 : 4 + rnd(4) */ + hp = 4 + rn2(5); /* 4..8 */ + } else if (!mon->m_lev) { + /* level 0 monsters use 1d4 instead of Nd8 */ + hp = rnd(4); + } + return hp; +} + /* set up a new monster's initial level and hit points; used by newcham() as well as by makemon() */ void diff --git a/src/zap.c b/src/zap.c index 8e78c3bc9..95297223c 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)zap.c 3.5 2005/06/22 */ +/* SCCS Id: @(#)zap.c 3.5 2005/09/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -311,7 +311,7 @@ struct obj *otmp; wake = FALSE; break; case SPE_DRAIN_LIFE: - dmg = rnd(8); + dmg = monhp_per_lvl(mtmp); if(dbldam) dmg *= 2; if (otyp == SPE_DRAIN_LIFE) dmg += spell_damage_bonus();