github issue #1263 - lich attacks

Issue reported by loggersviii:  monsters killed by liches can
produce corpses which auto-revive as zombies, but liches aren't
able to harm zombies and get stuck in an endless slap fight when
those revive.

Liches have a touch attack for cold damage and they have a spell
casting attack.  They don't use their spell attack in monster vs
monster combat, so cold resistant foes don't receive any damage.
Prevent them from becoming harmless by changing the cold damage to
physical damage if the target resists cold.

Fixes #1263
This commit is contained in:
PatR
2024-07-24 11:01:23 -07:00
parent faca234055
commit d963c6dd6f
2 changed files with 44 additions and 15 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 permonst.h $NHDT-Date: 1596498555 2020/08/03 23:49:15 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.14 $ */
/* NetHack 3.7 permonst.h $NHDT-Date: 1721844081 2024/07/24 18:01:21 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.25 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -11,14 +11,14 @@ enum monnums {
#include "monsters.h"
#undef MONS_ENUM
NUMMONS,
NON_PM = -1, /* "not a monster */
LOW_PM = NON_PM + 1, /* first monster in mons */
LEAVESTATUE = NON_PM - 1, /* leave statue instead of corpse;
* there are two lower values assigned
* in end.c so that (x == LEAVESTATUE)
* will test FALSE in bones.c:
* (NON_PM - 2) for no corpse
* (NON_PM - 3) for no corpse, no grave */
NON_PM = -1, /* "not a monster" */
LOW_PM = NON_PM + 1, /* first monster in mons */
LEAVESTATUE = NON_PM - 1, /* leave statue instead of corpse;
* there are two lower values assigned
* in end.c so that (x == LEAVESTATUE)
* will test FALSE in bones.c:
* (NON_PM - 2) for no corpse
* (NON_PM - 3) for no corpse, no grave */
HIGH_PM = NUMMONS - 1,
SPECIAL_PM = PM_LONG_WORM_TAIL /* [normal] < ~ < [special] */
/* mons[SPECIAL_PM] through mons[NUMMONS-1], inclusive, are

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 mhitu.c $NHDT-Date: 1689448844 2023/07/15 19:20:44 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.301 $ */
/* NetHack 3.7 mhitu.c $NHDT-Date: 1721844072 2024/07/24 18:01:12 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.318 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -132,8 +132,10 @@ mswings(
boolean bash) /* True: polearm used at too close range */
{
if (flags.verbose && !Blind && mon_visible(mtmp)) {
pline_mon(mtmp, "%s %s %s%s %s.", Monnam(mtmp), mswings_verb(otemp, bash),
(otemp->quan > 1L) ? "one of " : "", mhis(mtmp), xname(otemp));
pline_mon(mtmp, "%s %s %s%s %s.", Monnam(mtmp),
mswings_verb(otemp, bash),
(otemp->quan > 1L) ? "one of " : "",
mhis(mtmp), xname(otemp));
}
}
@@ -302,12 +304,15 @@ expels(
/* select a monster's next attack, possibly substituting for its usual one */
struct attack *
getmattk(struct monst *magr, struct monst *mdef,
int indx, int prev_result[], struct attack *alt_attk_buf)
getmattk(
struct monst *magr, struct monst *mdef,
int indx, int prev_result[],
struct attack *alt_attk_buf)
{
struct permonst *mptr = magr->data;
struct attack *attk = &mptr->mattk[indx];
struct obj *weap = (magr == &gy.youmonst) ? uwep : MON_WEP(magr);
boolean udefend = mdef == &gy.youmonst;
/* honor SEDUCE=0 */
if (!SYSOPT_SEDUCE) {
@@ -338,7 +343,7 @@ getmattk(struct monst *magr, struct monst *mdef,
attk->adtyp = AD_STUN;
/* make drain-energy damage be somewhat in proportion to energy */
} else if (attk->adtyp == AD_DREN && mdef == &gy.youmonst) {
} else if (attk->adtyp == AD_DREN && udefend) {
int ulev = max(u.ulevel, 6);
*alt_attk_buf = *attk;
@@ -400,7 +405,31 @@ getmattk(struct monst *magr, struct monst *mdef,
*alt_attk_buf = *attk;
attk = alt_attk_buf;
attk->adtyp = AD_PHYS;
/* liches have a touch attack for cold damage and also a spell attack;
they won't use the spell for monster vs monster so become impotent
aganst cold resistant foes; change the touch damage from cold to
physical if target will resist */
} else if (indx == 0 && attk->aatyp == AT_TUCH && attk->adtyp == AD_COLD
&& (udefend ? Cold_resistance : resists_cold(mdef))
/* don't substitute if target is immune to normal damage */
&& mdef->data != &mons[PM_SHADE]) {
*alt_attk_buf = *attk;
attk = alt_attk_buf;
attk->adtyp = AD_PHYS;
/* lessen new physical damage compared to old cold damage:
* before after
* lich: 1d10 1d6
* demi: 3d4 2d4
* master: 3d6 2d6
* arch-: 5d6 3d6
*/
attk->damn = (attk->damn + 1) / 2;
if (attk->damd == 10)
attk->damd = 6;
}
return attk;
}