implement #H4340 - indirect kills vs pacifism
Implement the suggestion that a monster killing itself with acid to avoid turning to stone or with fire to avoid turning into green slime not break pacifist conduct even if the player caused the "turning into" situation that triggered the accidental suicide. Along the way I discovered a serious bug: zhitm() applies damage to target monster but leaves it to caller to finish killing off that monster when damage is fatal, but muse_unslime() called it without checking whether the monster should die. For fire breath that shouldn't matter since all fire breathers are immune to fire damage, but when support for wands of fire and fire horns was added later it just cloned the fire breath code and neglected to check for fatal damage. The result was that a monster with 0 HP would be left on the map, then impossible "dmonsfree: 1 removed doesn't match 0 pending" would be given when taking it off fmon list, but a stale monster symbol (presumably level.monsters[][] pointer too) was left on the map which eventually led to monsndx panic or arbitrary crash.
This commit is contained in:
@@ -40,8 +40,7 @@ int expltype;
|
||||
int idamres, idamnonres;
|
||||
struct monst *mtmp, *mdef = 0;
|
||||
uchar adtyp;
|
||||
int explmask[3][3];
|
||||
/* 0=normal explosion, 1=do shieldeff, 2=do nothing */
|
||||
int explmask[3][3]; /* 0=normal explosion, 1=do shieldeff, 2=do nothing */
|
||||
boolean shopdamage = FALSE, generic = FALSE, physical_dmg = FALSE,
|
||||
do_hallu = FALSE, inside_engulfer;
|
||||
char hallu_buf[BUFSZ];
|
||||
@@ -414,9 +413,23 @@ int expltype;
|
||||
mtmp->mhp -= (idamres + idamnonres);
|
||||
}
|
||||
if (mtmp->mhp <= 0) {
|
||||
if (mdef ? (mtmp == mdef) : !context.mon_moving)
|
||||
if (!context.mon_moving) {
|
||||
killed(mtmp);
|
||||
else
|
||||
} else if (mdef && mtmp == mdef) {
|
||||
/* 'mdef' killed self trying to cure being turned
|
||||
* into slime due to some action by the player.
|
||||
* Hero gets the credit (experience) and most of
|
||||
* the blame (possible loss of alignment and/or
|
||||
* luck and/or telepathy depending on mtmp) but
|
||||
* doesn't break pacifism. xkilled()'s message
|
||||
* would be "you killed <mdef>" so give our own.
|
||||
*/
|
||||
if (cansee(mtmp->mx, mtmp->my) || canspotmon(mtmp))
|
||||
pline("%s is %s!", Monnam(mtmp),
|
||||
nonliving(mtmp->data) ? "destroyed"
|
||||
: "killed");
|
||||
xkilled(mtmp, XKILL_NOMSG | XKILL_NOCONDUCT);
|
||||
} else
|
||||
monkilled(mtmp, "", (int) adtyp);
|
||||
} else if (!context.mon_moving) {
|
||||
/* all affected monsters, even if mdef is set */
|
||||
|
||||
Reference in New Issue
Block a user