stone-to-flesh vs mimics
Handle a FIXME in zap.c: stone-to-flesh spell hitting a mimic that is disguised as a stone object or stone furniture should bring it out of hiding.
This commit is contained in:
@@ -1624,6 +1624,8 @@ extern void costly_alteration(struct obj *, int) NONNULLARG1;
|
||||
extern void clear_dknown(struct obj *);
|
||||
extern void unknow_object(struct obj *);
|
||||
extern struct obj *mksobj(int, boolean, boolean) NONNULL;
|
||||
extern boolean stone_object_type(unsigned);
|
||||
extern boolean stone_furniture_type(unsigned);
|
||||
extern int bcsign(struct obj *) NONNULLARG1;
|
||||
extern int weight(struct obj *) NONNULLARG1;
|
||||
extern struct obj *mkgold(long, coordxy, coordxy);
|
||||
@@ -3385,7 +3387,7 @@ extern boolean mhitm_knockback(struct monst *, struct monst *,struct attack *,
|
||||
extern int passive(struct monst *, struct obj *, boolean, boolean, uchar,
|
||||
boolean) NONNULLARG1;
|
||||
extern void passive_obj(struct monst *, struct obj *, struct attack *) NONNULLARG1;
|
||||
extern void that_is_a_mimic(struct monst *, boolean) NONNULLARG1;
|
||||
extern void that_is_a_mimic(struct monst *, unsigned) NONNULLARG1;
|
||||
extern void stumble_onto_mimic(struct monst *) NONNULLARG1;
|
||||
extern int flash_hits_mon(struct monst *, struct obj *) NONNULLARG12;
|
||||
extern void light_hits_gremlin(struct monst *, int) NONNULLARG1;
|
||||
|
||||
@@ -1155,6 +1155,10 @@ typedef uint32_t mmflags_nht; /* makemon MM_ flags */
|
||||
#define MHID_ALTMON 4 /* if mimicking a monster, include that */
|
||||
#define MHID_REGION 8 /* include region when mon is in one */
|
||||
|
||||
/* flags for that_is_a_mimic() */
|
||||
#define MIM_REVEAL 1 /* seemimic() */
|
||||
#define MIM_OMIT_WAIT 2 /* strip beginning from "Wait! That is a <foo>" */
|
||||
|
||||
/* flags for make_corpse() and mkcorpstat(); 0..7 are recorded in obj->spe */
|
||||
#define CORPSTAT_NONE 0x00
|
||||
#define CORPSTAT_GENDER 0x03 /* 0x01 | 0x02 */
|
||||
|
||||
36
src/mkobj.c
36
src/mkobj.c
@@ -1251,6 +1251,42 @@ mksobj(int otyp, boolean init, boolean artif)
|
||||
return otmp;
|
||||
}
|
||||
|
||||
/* potential mimic shapes that should be undone by stone-to-flesh;
|
||||
not used for objects that will be transformed when hit by stone-to-flesh */
|
||||
boolean
|
||||
stone_object_type(unsigned mappearance)
|
||||
{
|
||||
int otyp = (int) mappearance;
|
||||
|
||||
/* we exclude wands, rings, and gems even though some qualify as stone;
|
||||
there aren't any weapons or armor classified as made out of stone */
|
||||
return (otyp == BOULDER || otyp == STATUE || otyp == FIGURINE);
|
||||
}
|
||||
|
||||
/* possible mimic shapes that are affected by stone-to-flesh;
|
||||
mappearance for furniture is a display symbol rather than a terrain type */
|
||||
boolean
|
||||
stone_furniture_type(unsigned mappearance)
|
||||
{
|
||||
int sym = (int) mappearance;
|
||||
|
||||
switch (sym) {
|
||||
case S_upstair:
|
||||
case S_dnstair:
|
||||
case S_brupstair:
|
||||
case S_brdnstair:
|
||||
case S_altar:
|
||||
case S_throne:
|
||||
case S_sink: /* stone sink is iffy; metal might be more appropriate */
|
||||
return TRUE;
|
||||
default:
|
||||
if (sym >= S_vwall && sym <= S_trwall)
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Several areas of the code made direct reassignments
|
||||
* to obj->corpsenm. Because some special handling is
|
||||
|
||||
15
src/uhitm.c
15
src/uhitm.c
@@ -6103,11 +6103,13 @@ DISABLE_WARNING_FORMAT_NONLITERAL
|
||||
void
|
||||
that_is_a_mimic(
|
||||
struct monst *mtmp, /* a hidden mimic (nonnull) */
|
||||
boolean reveal_it) /* True: remove its disguise */
|
||||
unsigned mimic_flags) /* 0, MIM_REVEAL, MIM_OMIT_WAIT, REVEAL+OMIT */
|
||||
{
|
||||
static char generic[] = "a monster";
|
||||
char fmtbuf[BUFSZ];
|
||||
const char *what = NULL;
|
||||
boolean reveal_it = (mimic_flags & MIM_REVEAL) != 0,
|
||||
omit_wait = (mimic_flags & MIM_OMIT_WAIT) != 0;
|
||||
|
||||
Strcpy(fmtbuf, "Wait! That's %s!");
|
||||
if (Blind) {
|
||||
@@ -6116,7 +6118,7 @@ that_is_a_mimic(
|
||||
else if (M_AP_TYPE(mtmp) == M_AP_MONSTER)
|
||||
what = a_monnam(mtmp); /* differs from what was sensed */
|
||||
} else {
|
||||
coordxy x = u.ux + u.dx, y = u.uy + u.dy;
|
||||
coordxy x = mtmp->mx, y = mtmp->my;
|
||||
int glyph = glyph_at(x, y);
|
||||
|
||||
if (glyph_is_cmap(glyph)) {
|
||||
@@ -6167,8 +6169,11 @@ that_is_a_mimic(
|
||||
what = a_monnam(mtmp);
|
||||
}
|
||||
|
||||
if (what)
|
||||
pline(fmtbuf, what);
|
||||
if (what) {
|
||||
int i = (omit_wait && !strncmp(fmtbuf, "Wait! ", 7)) ? 7 : 0;
|
||||
|
||||
pline(&fmtbuf[i], what);
|
||||
}
|
||||
if (reveal_it)
|
||||
seemimic(mtmp);
|
||||
}
|
||||
@@ -6179,7 +6184,7 @@ RESTORE_WARNING_FORMAT_NONLITERAL
|
||||
void
|
||||
stumble_onto_mimic(struct monst *mtmp)
|
||||
{
|
||||
that_is_a_mimic(mtmp, TRUE);
|
||||
that_is_a_mimic(mtmp, MIM_REVEAL);
|
||||
|
||||
if (!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data, AD_STCK)
|
||||
/* must be adjacent; attack via polearm could be from farther away */
|
||||
|
||||
61
src/zap.c
61
src/zap.c
@@ -365,7 +365,7 @@ bhitm(struct monst *mtmp, struct obj *otmp)
|
||||
case WAN_LOCKING:
|
||||
case SPE_WIZARD_LOCK:
|
||||
if (disguised_mimic && box_or_door(mtmp))
|
||||
that_is_a_mimic(mtmp, TRUE); /*seemimic()*/
|
||||
that_is_a_mimic(mtmp, MIM_REVEAL); /*seemimic()*/
|
||||
wake = closeholdingtrap(mtmp, &learn_it);
|
||||
break;
|
||||
case WAN_PROBING:
|
||||
@@ -377,7 +377,7 @@ bhitm(struct monst *mtmp, struct obj *otmp)
|
||||
case WAN_OPENING:
|
||||
case SPE_KNOCK:
|
||||
if (disguised_mimic && box_or_door(mtmp))
|
||||
that_is_a_mimic(mtmp, TRUE); /*seemimic()*/
|
||||
that_is_a_mimic(mtmp, MIM_REVEAL); /*seemimic()*/
|
||||
wake = FALSE; /* don't want immediate counterattack */
|
||||
if (mtmp == u.ustuck) {
|
||||
/* zapping either holder/holdee or self [zapyourself()] will
|
||||
@@ -483,21 +483,35 @@ bhitm(struct monst *mtmp, struct obj *otmp)
|
||||
learn_it = TRUE;
|
||||
break;
|
||||
case SPE_STONE_TO_FLESH:
|
||||
/* FIXME: mimics disguished as stone furniture or stone object
|
||||
should be taken out of concealment. */
|
||||
if (monsndx(mtmp->data) == PM_STONE_GOLEM) {
|
||||
char *name = Monnam(mtmp);
|
||||
if (mtmp->data->mlet == S_GOLEM) {
|
||||
const char *mesg;
|
||||
char *name = Monnam(mtmp); /* before possible polymorph */
|
||||
|
||||
/* turn into flesh golem */
|
||||
if (newcham(mtmp, &mons[PM_FLESH_GOLEM], NO_NC_FLAGS)) {
|
||||
if (canseemon(mtmp))
|
||||
pline("%s turns to flesh!", name);
|
||||
} else {
|
||||
if (canseemon(mtmp))
|
||||
pline("%s looks rather fleshy for a moment.", name);
|
||||
/* turn stone golem into flesh golem */
|
||||
if (monsndx(mtmp->data) == PM_STONE_GOLEM
|
||||
&& newcham(mtmp, &mons[PM_FLESH_GOLEM], NO_NC_FLAGS))
|
||||
mesg = "turns to flesh!";
|
||||
else if (monsndx(mtmp->data) == PM_FLESH_GOLEM)
|
||||
mesg = "seems fleshier...";
|
||||
else
|
||||
mesg = "looks rather fleshy for a moment.";
|
||||
|
||||
if (canseemon(mtmp))
|
||||
pline("%s %s", name, mesg);
|
||||
} else if (mtmp->data->mlet == S_MIMIC
|
||||
&& ((M_AP_TYPE(mtmp) == M_AP_FURNITURE
|
||||
&& stone_furniture_type(mtmp->mappearance))
|
||||
|| (M_AP_TYPE(mtmp) == M_AP_OBJECT
|
||||
&& stone_object_type(mtmp->mappearance)))) {
|
||||
/* note: if that_is_a_mimic() doesn't get called to reveal the
|
||||
mimic, wakeup() below will call seemimic() */
|
||||
if (cansee(mtmp->mx, mtmp->my)) {
|
||||
set_msg_xy(mtmp->mx, mtmp->my);
|
||||
that_is_a_mimic(mtmp, MIM_REVEAL | MIM_OMIT_WAIT);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
wake = FALSE;
|
||||
}
|
||||
break;
|
||||
case SPE_DRAIN_LIFE:
|
||||
if (disguised_mimic)
|
||||
@@ -530,22 +544,19 @@ bhitm(struct monst *mtmp, struct obj *otmp)
|
||||
impossible("What an interesting effect (%d)", otyp);
|
||||
break;
|
||||
}
|
||||
if (wake) {
|
||||
if (!DEADMONSTER(mtmp)) {
|
||||
wakeup(mtmp, helpful_gesture ? FALSE : TRUE);
|
||||
m_respond(mtmp);
|
||||
if (mtmp->isshk && !*u.ushops)
|
||||
hot_pursuit(mtmp);
|
||||
} else if (M_AP_TYPE(mtmp))
|
||||
seemimic(mtmp); /* might unblock if mimicking a boulder/door */
|
||||
if (wake && !DEADMONSTER(mtmp)) {
|
||||
/* seemimic() is done by wakeup() and might unblock vision */
|
||||
wakeup(mtmp, helpful_gesture ? FALSE : TRUE);
|
||||
m_respond(mtmp);
|
||||
if (mtmp->isshk && !*u.ushops)
|
||||
hot_pursuit(mtmp);
|
||||
}
|
||||
/* note: gb.bhitpos won't be set if swallowed, but that's okay since
|
||||
* reveal_invis will be false. We can't use mtmp->mx, my since it
|
||||
* might be an invisible worm hit on the tail.
|
||||
*/
|
||||
if (reveal_invis) {
|
||||
if (!DEADMONSTER(mtmp) && cansee(gb.bhitpos.x, gb.bhitpos.y)
|
||||
&& !canspotmon(mtmp))
|
||||
if (reveal_invis && !DEADMONSTER(mtmp)) {
|
||||
if (cansee(gb.bhitpos.x, gb.bhitpos.y) && !canspotmon(mtmp))
|
||||
map_invisible(gb.bhitpos.x, gb.bhitpos.y);
|
||||
}
|
||||
/* if effect was observable then discover the wand type provided
|
||||
|
||||
Reference in New Issue
Block a user