fix #332 - strangulation affects headless monsters (trunk only)
From a bug report: amulet of strangulation
continues to kill hero if he polymorphs into a creature which doesn't
need to breathe or doesn't have a head or even a circulatory system.
Currently, the messages are different when the hero doesn't need to
breathe, but that doesn't seem good enough. This makes strangulation
stop when you polymorph into something which shouldn't be vulnerable and
restart if you poly into something vulnerable while still wearing the
bad amulet.
can_be_strangled() is doing more checks that necessary, in case the
strangulation property ever gets conferred by something other than an
amulet. Its criteria for protection from strangling might need tweaking.
This commit is contained in:
@@ -229,6 +229,7 @@ eliminate case-sensitivity when converting words from singular to plural and
|
||||
breath attack directed at self by poly'd hero always hits
|
||||
override non-silver vs shades for artifacts which deal extra damage to undead
|
||||
assorted mirror fixes--mainly visibility issues
|
||||
some monsters can't be strangled; self-polymorph can stop/restart strangulation
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific Fixes
|
||||
|
||||
@@ -1329,6 +1329,7 @@ E boolean FDECL(hates_silver, (struct permonst *));
|
||||
E boolean FDECL(mon_hates_silver, (struct monst *));
|
||||
E boolean FDECL(passes_bars, (struct permonst *));
|
||||
E boolean FDECL(can_blow, (struct monst *));
|
||||
E boolean FDECL(can_be_strangled, (struct monst *));
|
||||
E boolean FDECL(can_track, (struct permonst *));
|
||||
E boolean FDECL(breakarm, (struct permonst *));
|
||||
E boolean FDECL(sliparm, (struct permonst *));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)do_wear.c 3.5 2007/03/19 */
|
||||
/* SCCS Id: @(#)do_wear.c 3.5 2007/05/16 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -626,9 +626,11 @@ Amulet_on()
|
||||
break;
|
||||
}
|
||||
case AMULET_OF_STRANGULATION:
|
||||
makeknown(AMULET_OF_STRANGULATION);
|
||||
pline("It constricts your throat!");
|
||||
Strangled = 6;
|
||||
if (can_be_strangled(&youmonst)) {
|
||||
makeknown(AMULET_OF_STRANGULATION);
|
||||
pline("It constricts your throat!");
|
||||
Strangled = 6L;
|
||||
}
|
||||
break;
|
||||
case AMULET_OF_RESTFUL_SLEEP:
|
||||
HSleeping = rnd(100);
|
||||
@@ -671,8 +673,11 @@ Amulet_off()
|
||||
break;
|
||||
case AMULET_OF_STRANGULATION:
|
||||
if (Strangled) {
|
||||
if (Breathless)
|
||||
Your("%s is no longer constricted!", body_part(NECK));
|
||||
else
|
||||
You("can breathe more easily!");
|
||||
Strangled = 0;
|
||||
Strangled = 0L;
|
||||
}
|
||||
break;
|
||||
case AMULET_OF_RESTFUL_SLEEP:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)mondata.c 3.5 2007/03/02 */
|
||||
/* SCCS Id: @(#)mondata.c 3.5 2007/05/16 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -299,6 +299,37 @@ register struct monst *mtmp;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
boolean
|
||||
can_be_strangled(mon) /* TRUE if mon is vulnerable to strangulation */
|
||||
struct monst *mon;
|
||||
{
|
||||
struct obj *mamul;
|
||||
boolean nonbreathing, nobrainer;
|
||||
|
||||
/* For amulet of strangulation support: here we're considering
|
||||
strangulation to be loss of blood flow to the brain due to
|
||||
constriction of the arteries in the neck, so all headless
|
||||
creatures are immune (no neck) as are mindless creatures
|
||||
who don't need to breathe (brain, if any, doesn't care).
|
||||
Mindless creatures who do need to breath are vulnerable, as
|
||||
are non-breathing creatures which have higher brain function. */
|
||||
if (!has_head(mon->data)) return FALSE;
|
||||
if (mon == &youmonst) {
|
||||
/* hero can't be mindless but poly'ing into mindless form can
|
||||
confer strangulation protection */
|
||||
nobrainer = mindless(youmonst.data);
|
||||
nonbreathing = Breathless;
|
||||
} else {
|
||||
nobrainer = mindless(mon->data);
|
||||
/* monsters don't wear amulets of magical breathing,
|
||||
so second part doesn't achieve anything useful... */
|
||||
nonbreathing = (breathless(mon->data) ||
|
||||
((mamul = which_armor(mon, W_AMUL)) != 0 &&
|
||||
(mamul->otyp == AMULET_OF_MAGICAL_BREATHING)));
|
||||
}
|
||||
return (boolean)(!nobrainer || !nonbreathing);
|
||||
}
|
||||
|
||||
boolean
|
||||
can_track(ptr) /* returns TRUE if monster can track well */
|
||||
register struct permonst *ptr;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "hack.h"
|
||||
|
||||
STATIC_DCL void FDECL(check_strangling, (BOOLEAN_P));
|
||||
STATIC_DCL void FDECL(polyman, (const char *,const char *));
|
||||
STATIC_DCL void NDECL(break_armor);
|
||||
STATIC_DCL void FDECL(drop_weapon,(int));
|
||||
@@ -46,6 +47,30 @@ set_uasmon()
|
||||
#endif
|
||||
}
|
||||
|
||||
/* for changing into form that's immune to strangulation */
|
||||
STATIC_OVL void
|
||||
check_strangling(on)
|
||||
boolean on;
|
||||
{
|
||||
if (on) { /* on -- maybe resume strangling */
|
||||
/* when Strangled is already set, polymorphing from one
|
||||
vulnerable form into another causes the counter to be reset */
|
||||
if (uamul && uamul->otyp == AMULET_OF_STRANGULATION &&
|
||||
can_be_strangled(&youmonst)) {
|
||||
Your("%s %s your %s!", simpleonames(uamul),
|
||||
Strangled ? "still constricts" : "begins constricting",
|
||||
body_part(NECK)); /* "throat" */
|
||||
Strangled = 6L;
|
||||
makeknown(AMULET_OF_STRANGULATION);
|
||||
}
|
||||
} else { /* off -- maybe block strangling */
|
||||
if (Strangled && !can_be_strangled(&youmonst)) {
|
||||
Strangled = 0L;
|
||||
You("are no longer being strangled.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* make a (new) human out of the player */
|
||||
STATIC_OVL void
|
||||
polyman(fmt, arg)
|
||||
@@ -109,6 +134,7 @@ const char *fmt, *arg;
|
||||
Blinded = 1L;
|
||||
make_blinded(0L, TRUE); /* remove blindness */
|
||||
}
|
||||
check_strangling(TRUE);
|
||||
|
||||
if(!Levitation && !u.ustuck &&
|
||||
(is_pool(u.ux,u.uy) || is_lava(u.ux,u.uy)))
|
||||
@@ -491,6 +517,7 @@ int mntmp;
|
||||
make_slimed(0L, (char*) 0);
|
||||
}
|
||||
}
|
||||
check_strangling(FALSE); /* maybe stop strangling */
|
||||
if (nohands(youmonst.data)) Glib = 0;
|
||||
|
||||
/*
|
||||
@@ -631,6 +658,7 @@ int mntmp;
|
||||
You("orient yourself on the web.");
|
||||
u.utrap = 0;
|
||||
}
|
||||
check_strangling(TRUE); /* maybe start strangling */
|
||||
(void) polysense(youmonst.data);
|
||||
|
||||
context.botl = 1;
|
||||
|
||||
@@ -354,6 +354,12 @@ nh_timeout()
|
||||
Strcpy(killer.name,
|
||||
(u.uburied) ? "suffocation" : "strangulation");
|
||||
done(DIED);
|
||||
/* must be declining to die in explore|wizard mode;
|
||||
treat like being cured of strangulation by prayer */
|
||||
if (uamul && uamul->otyp == AMULET_OF_STRANGULATION) {
|
||||
Your("amulet vanishes!");
|
||||
useup(uamul);
|
||||
}
|
||||
break;
|
||||
case FUMBLING:
|
||||
/* call this only when a move took place. */
|
||||
|
||||
Reference in New Issue
Block a user