mhpmax of life-drained monsters
The report about problems after stone-to-flesh on a petrified long worm included stethoscope feedback of 0(-1) hit points, after life-draining. I was unable to reproduce a maximum hp of -1 and hope that it was a side-effect of the [already fixed] stale mon->wormno value used when resurrecting the long worm. Anyway, this changes life-draining to never take mon->hpmax below mon->m_lev + 1 (the +1 is needed to cope with m_lev==0 monsters). The same limit is also applied to monster life-saving but more to avoid replicating the arbitrary minimum of 10 (four instances) then because it might be less than m_lev+1 somehow. Sanity checking now tests whether a monster's max HP is less than its level + 1 so if there are ways other than life-drain attacks for it to drop that low, the fuzzer will choke. The new check also tests whether a monster's current HP is greater than max HP. Polymophred hero killing a golem or vortex by vampire bite reported "<Mon> dies." Give an alternate message since those aren't alive.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 artifact.c $NHDT-Date: 1581886858 2020/02/16 21:00:58 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.153 $ */
|
||||
/* NetHack 3.6 artifact.c $NHDT-Date: 1593306896 2020/06/28 01:14:56 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.157 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2013. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -1337,11 +1337,21 @@ int dieroll; /* needed for Magicbane and vorpal blades */
|
||||
}
|
||||
}
|
||||
if (spec_ability(otmp, SPFX_DRLI)) {
|
||||
/* some non-living creatures (golems, vortices) are
|
||||
vulnerable to life drain effects */
|
||||
/* some non-living creatures (golems, vortices) are vulnerable to
|
||||
life drain effects so can get "<Arti> draws the <life>" feedback */
|
||||
const char *life = nonliving(mdef->data) ? "animating force" : "life";
|
||||
|
||||
if (!youdefend) {
|
||||
int m_lev = (int) mdef->m_lev, /* will be 0 for 1d4 mon */
|
||||
mhpmax = mdef->mhpmax,
|
||||
drain = monhp_per_lvl(mdef); /* usually 1d8 */
|
||||
/* note: DRLI attack uses 2d6, attacker doesn't get healed */
|
||||
|
||||
/* stop draining HP if it drops too low (still drains level;
|
||||
also caller still inflicts regular weapon damage) */
|
||||
if (mhpmax - drain <= m_lev)
|
||||
drain = (mhpmax > m_lev) ? (mhpmax - (m_lev + 1)) : 0;
|
||||
|
||||
if (vis) {
|
||||
if (otmp->oartifact == ART_STORMBRINGER)
|
||||
pline_The("%s blade draws the %s from %s!",
|
||||
@@ -1355,21 +1365,20 @@ int dieroll; /* needed for Magicbane and vorpal blades */
|
||||
/* losing a level when at 0 is fatal */
|
||||
*dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
|
||||
} else {
|
||||
int drain = monhp_per_lvl(mdef);
|
||||
|
||||
*dmgptr += drain;
|
||||
mdef->mhpmax -= drain;
|
||||
mdef->m_lev--;
|
||||
drain /= 2;
|
||||
if (drain) {
|
||||
/* attacker heals in proportion to amount drained */
|
||||
if (youattack) {
|
||||
healup(drain, 0, FALSE, FALSE);
|
||||
} else {
|
||||
magr->mhp += drain;
|
||||
if (magr->mhp > magr->mhpmax)
|
||||
magr->mhp = magr->mhpmax;
|
||||
}
|
||||
}
|
||||
|
||||
if (drain > 0) {
|
||||
/* drain: was target's damage, now heal attacker by half */
|
||||
drain = (drain + 1) / 2; /* drain/2 rounded up */
|
||||
if (youattack) {
|
||||
healup(drain, 0, FALSE, FALSE);
|
||||
} else {
|
||||
magr->mhp += drain;
|
||||
if (magr->mhp > magr->mhpmax)
|
||||
magr->mhp = magr->mhpmax;
|
||||
}
|
||||
}
|
||||
return vis;
|
||||
@@ -1389,7 +1398,7 @@ int dieroll; /* needed for Magicbane and vorpal blades */
|
||||
life);
|
||||
losexp("life drainage");
|
||||
if (magr && magr->mhp < magr->mhpmax) {
|
||||
magr->mhp += (oldhpmax - u.uhpmax) / 2;
|
||||
magr->mhp += (oldhpmax - u.uhpmax + 1) / 2;
|
||||
if (magr->mhp > magr->mhpmax)
|
||||
magr->mhp = magr->mhpmax;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user