Monsters can revive corpses on floor with undead turning
... but only if the corpse is in direct line from the monster to hero
This commit is contained in:
@@ -324,6 +324,8 @@ brown pudding monster hitting another monster with decay attack corroded armor
|
||||
and ^A/re-do was suppressed due lack of obsolete '#define REDO'
|
||||
add missing key binding support for rush.numpad; default is M-5 for numpad==1
|
||||
or plain 5 for numpad==2 where behavior of 5 and M-5 are swapped
|
||||
allow monsters to use wand of undead turning to revive corpses on floor
|
||||
in some situations
|
||||
|
||||
|
||||
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
|
||||
|
||||
@@ -1683,6 +1683,7 @@ E int FDECL(ohitmon, (struct monst *, struct obj *, int, BOOLEAN_P));
|
||||
E void FDECL(thrwmu, (struct monst *));
|
||||
E int FDECL(spitmu, (struct monst *, struct attack *));
|
||||
E int FDECL(breamu, (struct monst *, struct attack *));
|
||||
E boolean FDECL(linedup_callback, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P, boolean FDECL((*), (int,int))));
|
||||
E boolean FDECL(linedup, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P, int));
|
||||
E boolean FDECL(lined_up, (struct monst *));
|
||||
E struct obj *FDECL(m_carrying, (struct monst *, int));
|
||||
|
||||
@@ -969,6 +969,43 @@ struct attack *mattk;
|
||||
return breamm(mtmp, mattk, &g.youmonst);
|
||||
}
|
||||
|
||||
/* Move from (ax,ay) to (bx,by), but only if distance is up to BOLT_LIM
|
||||
and only in straight line or diagonal, calling fnc for each step.
|
||||
Stops if fnc return TRUE, or if step was blocked by wall or closed door.
|
||||
Returns TRUE if fnc returned TRUE. */
|
||||
boolean
|
||||
linedup_callback(ax, ay, bx, by, fnc)
|
||||
xchar ax, ay, bx, by;
|
||||
boolean FDECL((*fnc), (int, int));
|
||||
{
|
||||
int dx, dy;
|
||||
|
||||
/* These two values are set for use after successful return. */
|
||||
g.tbx = ax - bx;
|
||||
g.tby = ay - by;
|
||||
|
||||
/* sometimes displacement makes a monster think that you're at its
|
||||
own location; prevent it from throwing and zapping in that case */
|
||||
if (!g.tbx && !g.tby)
|
||||
return FALSE;
|
||||
|
||||
if ((!g.tbx || !g.tby || abs(g.tbx) == abs(g.tby)) /* straight line or diagonal */
|
||||
&& distmin(g.tbx, g.tby, 0, 0) < BOLT_LIM) {
|
||||
dx = sgn(ax - bx), dy = sgn(ay - by);
|
||||
do {
|
||||
/* <bx,by> is guaranteed to eventually converge with <ax,ay> */
|
||||
bx += dx, by += dy;
|
||||
if (!isok(bx, by))
|
||||
return FALSE;
|
||||
if (IS_ROCK(levl[bx][by].typ) || closed_door(bx, by))
|
||||
return FALSE;
|
||||
if ((*fnc)(bx, by))
|
||||
return TRUE;
|
||||
} while (bx != ax || by != ay);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
boolean
|
||||
linedup(ax, ay, bx, by, boulderhandling)
|
||||
register xchar ax, ay, bx, by;
|
||||
|
||||
89
src/muse.c
89
src/muse.c
@@ -20,6 +20,8 @@ static void FDECL(mplayhorn, (struct monst *, struct obj *, BOOLEAN_P));
|
||||
static void FDECL(mreadmsg, (struct monst *, struct obj *));
|
||||
static void FDECL(mquaffmsg, (struct monst *, struct obj *));
|
||||
static boolean FDECL(m_use_healing, (struct monst *));
|
||||
static boolean FDECL(linedup_chk_corpse, (int, int));
|
||||
static void FDECL(m_use_undead_turning, (struct monst *, struct obj *));
|
||||
static int FDECL(mbhitm, (struct monst *, struct obj *));
|
||||
static void FDECL(mbhit, (struct monst *, int,
|
||||
int FDECL((*), (MONST_P, OBJ_P)),
|
||||
@@ -1134,6 +1136,60 @@ struct monst *mtmp;
|
||||
/*#define MUSE_WAN_UNDEAD_TURNING 20*/ /* also a defensive item so don't
|
||||
* redefine; nonconsecutive value is ok */
|
||||
|
||||
static boolean
|
||||
linedup_chk_corpse(x, y)
|
||||
int x, y;
|
||||
{
|
||||
return (sobj_at(CORPSE, x, y) != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
m_use_undead_turning(mtmp, obj)
|
||||
struct monst *mtmp;
|
||||
struct obj *obj;
|
||||
{
|
||||
int ax = u.ux + sgn(mtmp->mux - mtmp->mx) * 3,
|
||||
ay = u.uy + sgn(mtmp->muy - mtmp->my) * 3;
|
||||
int bx = mtmp->mx, by = mtmp->my;
|
||||
|
||||
if (!(obj->otyp == WAN_UNDEAD_TURNING && obj->spe > 0))
|
||||
return;
|
||||
|
||||
/* not necrophiliac(); unlike deciding whether to pick this
|
||||
type of wand up, we aren't interested in corpses within
|
||||
carried containers until they're moved into open inventory;
|
||||
we don't check whether hero is poly'd into an undead--the
|
||||
wand's turning effect is too weak to be a useful direct
|
||||
attack--only whether hero is carrying at least one corpse */
|
||||
if (carrying(CORPSE)) {
|
||||
/*
|
||||
* Hero is carrying one or more corpses but isn't wielding
|
||||
* a cockatrice corpse (unless being hit by one won't do
|
||||
* the monster much harm); otherwise we'd be using this wand
|
||||
* as a defensive item with higher priority.
|
||||
*
|
||||
* Might be cockatrice intended as a weapon (or being denied
|
||||
* to glove-wearing monsters for use as a weapon) or lizard
|
||||
* intended as a cure or lichen intended as veggy food or
|
||||
* sacrifice fodder being lugged to an altar. Zapping with
|
||||
* this will deprive hero of one from each stack although
|
||||
* they might subsequently be recovered after killing again.
|
||||
* In the sacrifice fodder case, it could even be to the
|
||||
* player's advantage (fresher corpse if a new one gets
|
||||
* dropped; player might not choose to spend a wand charge
|
||||
* on that when/if hero acquires this wand).
|
||||
*/
|
||||
g.m.offensive = obj;
|
||||
g.m.has_offense = MUSE_WAN_UNDEAD_TURNING;
|
||||
} else if (linedup_callback(ax, ay, bx, by, linedup_chk_corpse)) {
|
||||
/* There's a corpse on the ground in a direct line from the
|
||||
* monster to the hero, and up to 3 steps beyond.
|
||||
*/
|
||||
g.m.offensive = obj;
|
||||
g.m.has_offense = MUSE_WAN_UNDEAD_TURNING;
|
||||
}
|
||||
}
|
||||
|
||||
/* Select an offensive item/action for a monster. Returns TRUE iff one is
|
||||
* found.
|
||||
*/
|
||||
@@ -1208,34 +1264,7 @@ struct monst *mtmp;
|
||||
}
|
||||
}
|
||||
nomore(MUSE_WAN_UNDEAD_TURNING);
|
||||
if (obj->otyp == WAN_UNDEAD_TURNING && obj->spe > 0
|
||||
/* not necrophiliac(); unlike deciding whether to pick this
|
||||
type of wand up, we aren't interested in corpses within
|
||||
carried containers until they're moved into open inventory;
|
||||
we don't check whether hero is poly'd into an undead--the
|
||||
wand's turning effect is too weak to be a useful direct
|
||||
attack--only whether hero is carrying at least one corpse */
|
||||
&& carrying(CORPSE)) {
|
||||
/*
|
||||
* Hero is carrying one or more corpses but isn't wielding
|
||||
* a cockatrice corpse (unless being hit by one won't do
|
||||
* the monster much harm); otherwise we'd be using this wand
|
||||
* as a defensive item with higher priority.
|
||||
*
|
||||
* Might be cockatrice intended as a weapon (or being denied
|
||||
* to glove-wearing monsters for use as a weapon) or lizard
|
||||
* intended as a cure or lichen intended as veggy food or
|
||||
* sacrifice fodder being lugged to an altar. Zapping with
|
||||
* this will deprive hero of one from each stack although
|
||||
* they might subsequently be recovered after killing again.
|
||||
* In the sacrifice fodder case, it could even be to the
|
||||
* player's advantage (fresher corpse if a new one gets
|
||||
* dropped; player might not choose to spend a wand charge
|
||||
* on that when/if hero acquires this wand).
|
||||
*/
|
||||
g.m.offensive = obj;
|
||||
g.m.has_offense = MUSE_WAN_UNDEAD_TURNING;
|
||||
}
|
||||
m_use_undead_turning(mtmp, obj);
|
||||
nomore(MUSE_WAN_STRIKING);
|
||||
if (obj->otyp == WAN_STRIKING && obj->spe > 0) {
|
||||
g.m.offensive = obj;
|
||||
@@ -2342,11 +2371,9 @@ struct obj *obj;
|
||||
if (typ == WAN_POLYMORPH)
|
||||
return (boolean) (mons[monsndx(mon->data)].difficulty < 6);
|
||||
if (objects[typ].oc_dir == RAY || typ == WAN_STRIKING
|
||||
|| typ == WAN_UNDEAD_TURNING
|
||||
|| typ == WAN_TELEPORTATION || typ == WAN_CREATE_MONSTER)
|
||||
return TRUE;
|
||||
if (typ == WAN_UNDEAD_TURNING)
|
||||
return (necrophiliac(g.invent, TRUE)
|
||||
|| (Upolyd && is_undead(g.youmonst.data)));
|
||||
break;
|
||||
case POTION_CLASS:
|
||||
if (typ == POT_HEALING || typ == POT_EXTRA_HEALING
|
||||
|
||||
Reference in New Issue
Block a user