vampshifters vs closed doors
If a vampire in fog cloud form moves under a closed door and then before moving further gets killed and revives in vampire form, destroy the door instead of moving the vampire to a nearby open spot (which might be a distant spot if the map is crowded). If the door is trapped, explode the trap. That will damage the vampire but usually not by enough to kill it. This probably ought to be generalized to be done for any shape change at a closed location but I ran out of gas.
This commit is contained in:
66
src/mon.c
66
src/mon.c
@@ -1937,7 +1937,7 @@ can_touch_safely(struct monst *mtmp, struct obj *otmp)
|
||||
*
|
||||
* to support the new pet behavior, this now returns the max # of objects
|
||||
* that a given monster could pick up from a pile. frequently this will be
|
||||
* otmp->quan, but special cases for 'only one' now exist so.
|
||||
* otmp->quan, but special cases for 'only one' now exist.
|
||||
*
|
||||
* this will probably cause very amusing behavior with pets and gold coins.
|
||||
*
|
||||
@@ -2812,15 +2812,20 @@ lifesaved_monster(struct monst *mtmp)
|
||||
}
|
||||
|
||||
/* when a shape-shifted vampire is killed, it reverts to base form instead
|
||||
of dying; moved into separate routine to unclutter mondead() */
|
||||
of dying; returns True if mtmp successfully revives, False otherwise;
|
||||
"successfully revived" vampire might be killed by a booby trapped door */
|
||||
staticfn boolean
|
||||
vamprises(struct monst *mtmp)
|
||||
{
|
||||
int mndx = mtmp->cham;
|
||||
|
||||
/*
|
||||
* Protection from shape changers protects against this because
|
||||
* the vampire will always be in normal form instead of shifted.
|
||||
* So there's no need to check for that attribute being active.
|
||||
*/
|
||||
if (ismnum(mndx) && mndx != monsndx(mtmp->data)
|
||||
&& !(svm.mvitals[mndx].mvflags & G_GENOD)) {
|
||||
coord new_xy;
|
||||
char action[BUFSZ];
|
||||
/* alternate message phrasing for some monster types */
|
||||
boolean spec_mon = (nonliving(mtmp->data)
|
||||
@@ -2833,30 +2838,28 @@ vamprises(struct monst *mtmp)
|
||||
|
||||
/* construct a 'before' argument to pass to pline(); this used
|
||||
to construct a dynamic format string but that's overkill */
|
||||
Snprintf(action, sizeof action, "%s suddenly %s and rises as",
|
||||
Snprintf(action, sizeof action, "%s%s %s%s and rises as",
|
||||
Unaware ? "you dream that " : "",
|
||||
x_monnam(mtmp, ARTICLE_THE,
|
||||
spec_mon ? (char *) 0 : "seemingly dead",
|
||||
(SUPPRESS_INVISIBLE | AUGMENT_IT), FALSE),
|
||||
Unaware ? "" : "suddenly ",
|
||||
spec_death ? "reconstitutes" : "transforms");
|
||||
mtmp->mcanmove = 1;
|
||||
mtmp->mfrozen = 0;
|
||||
set_mon_min_mhpmax(mtmp, 10); /* mtmp->mhpmax=max(m_lev+1,10) */
|
||||
mtmp->mhp = mtmp->mhpmax;
|
||||
/* mtmp==u.ustuck can happen if previously a fog cloud
|
||||
or poly'd hero is hugging a vampire bat */
|
||||
/* mtmp==u.ustuck can happen if previously a fog cloud or if
|
||||
poly'd hero is hugging a vampire bat */
|
||||
if (mtmp == u.ustuck) {
|
||||
if (u.uswallow)
|
||||
expels(mtmp, mtmp->data, FALSE);
|
||||
else
|
||||
uunstick();
|
||||
}
|
||||
/* if fog cloud is on a closed door space, move it to a more
|
||||
appropriate spot for its intended new form */
|
||||
if (amorphous(mtmp->data) && closed_door(mtmp->mx, mtmp->my)) {
|
||||
if (enexto(&new_xy, mtmp->mx, mtmp->my, &mons[mndx]))
|
||||
rloc_to(mtmp, new_xy.x, new_xy.y);
|
||||
}
|
||||
(void) newcham(mtmp, &mons[mndx], NO_NC_FLAGS);
|
||||
|
||||
if (!newcham(mtmp, &mons[mndx], NO_NC_FLAGS))
|
||||
return !DEADMONSTER(mtmp);
|
||||
mtmp->cham = (mtmp->data == &mons[mndx]) ? NON_PM : mndx;
|
||||
|
||||
if (canspotmon(mtmp)) {
|
||||
@@ -2869,6 +2872,42 @@ vamprises(struct monst *mtmp)
|
||||
FALSE));
|
||||
gv.vamp_rise_msg = TRUE;
|
||||
}
|
||||
/* revived vampire is in normal shape, so can't be amorphous; if on
|
||||
a closed door spot, destroy the door and if trapped, blow it up */
|
||||
if (closed_door(x, y)) {
|
||||
static const char
|
||||
door_smashed[] = "a door being smashed",
|
||||
door_go_boom[] = "a door exploding";
|
||||
struct rm *door = &levl[x][y];
|
||||
boolean trapped = (door->doormask & D_TRAPPED) != 0,
|
||||
seeit = cansee(x, y);
|
||||
|
||||
set_msg_xy(x, y); /* You()/pline() will reset this */
|
||||
if (!seeit)
|
||||
You_hear("%s.", trapped ? "an explosion" : door_smashed);
|
||||
else if (!canspotmon(mtmp))
|
||||
You_see("%s.", trapped ? door_go_boom : door_smashed);
|
||||
else if (!Unaware)
|
||||
pline_The("door is smashed%s",
|
||||
trapped ? " and it explodes!" : ".");
|
||||
set_msg_xy(0, 0); /* in case none of the messages was delivered */
|
||||
|
||||
door->doormask = D_NODOOR;
|
||||
unblock_point(x, y);
|
||||
if (trapped) {
|
||||
boolean trap_killed, save_verbose = flags.verbose;
|
||||
|
||||
flags.verbose = FALSE; /* suppress mb_trapped() messages
|
||||
* (that makes the 'seeit' arg moot) */
|
||||
trap_killed = mb_trapped(mtmp, seeit);
|
||||
flags.verbose = save_verbose;
|
||||
/* if the booby trap has killed the monster, mondied() will
|
||||
have been called but no message about its death given yet;
|
||||
mtmp was a vampire so use unconditional "destroyed" */
|
||||
if (trap_killed && canspotmon(mtmp) && !Unaware)
|
||||
pline_mon(mtmp, "%s is destroyed!", Monnam(mtmp));
|
||||
}
|
||||
}
|
||||
newsym(x, y);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -4593,6 +4632,7 @@ hideunder(struct monst *mtmp)
|
||||
if (undetected && seenmon && seenobj) {
|
||||
if (!locomo)
|
||||
locomo = locomotion(mtmp->data, "hide");
|
||||
set_msg_xy(mtmp->mx, mtmp->my); /* pline() will reset this */
|
||||
You_see("%s %s under %s.", seenmon, locomo, seenobj);
|
||||
iflags.last_msg = PLNMSG_HIDE_UNDER;
|
||||
gl.last_hider = mtmp->m_id;
|
||||
|
||||
@@ -1491,9 +1491,9 @@ postmov(
|
||||
&& amorphous(ptr)) {
|
||||
if (flags.verbose && canseemon(mtmp))
|
||||
pline_mon(mtmp, "%s %s under the door.", YMonnam(mtmp),
|
||||
(ptr == &mons[PM_FOG_CLOUD]
|
||||
|| ptr->mlet == S_LIGHT) ? "flows" : "oozes");
|
||||
} else if (here->doormask & D_LOCKED && can_unlock) {
|
||||
(ptr == &mons[PM_FOG_CLOUD]
|
||||
|| ptr->mlet == S_LIGHT) ? "flows" : "oozes");
|
||||
} else if ((here->doormask & D_LOCKED) != 0 && can_unlock) {
|
||||
/* like the vampshift hack, there are sequencing
|
||||
issues when the monster is moved to the door's spot
|
||||
first then door handling plus feedback comes after */
|
||||
@@ -1532,7 +1532,7 @@ postmov(
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (here->doormask & (D_LOCKED | D_CLOSED)) {
|
||||
} else if ((here->doormask & (D_LOCKED | D_CLOSED)) != 0) {
|
||||
/* mfndpos guarantees this must be a doorbuster */
|
||||
unsigned mask;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user