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:
+3
-1
@@ -1624,6 +1624,8 @@ extern void costly_alteration(struct obj *, int) NONNULLARG1;
|
|||||||
extern void clear_dknown(struct obj *);
|
extern void clear_dknown(struct obj *);
|
||||||
extern void unknow_object(struct obj *);
|
extern void unknow_object(struct obj *);
|
||||||
extern struct obj *mksobj(int, boolean, boolean) NONNULL;
|
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 bcsign(struct obj *) NONNULLARG1;
|
||||||
extern int weight(struct obj *) NONNULLARG1;
|
extern int weight(struct obj *) NONNULLARG1;
|
||||||
extern struct obj *mkgold(long, coordxy, coordxy);
|
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,
|
extern int passive(struct monst *, struct obj *, boolean, boolean, uchar,
|
||||||
boolean) NONNULLARG1;
|
boolean) NONNULLARG1;
|
||||||
extern void passive_obj(struct monst *, struct obj *, struct attack *) 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 void stumble_onto_mimic(struct monst *) NONNULLARG1;
|
||||||
extern int flash_hits_mon(struct monst *, struct obj *) NONNULLARG12;
|
extern int flash_hits_mon(struct monst *, struct obj *) NONNULLARG12;
|
||||||
extern void light_hits_gremlin(struct monst *, int) NONNULLARG1;
|
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_ALTMON 4 /* if mimicking a monster, include that */
|
||||||
#define MHID_REGION 8 /* include region when mon is in one */
|
#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 */
|
/* flags for make_corpse() and mkcorpstat(); 0..7 are recorded in obj->spe */
|
||||||
#define CORPSTAT_NONE 0x00
|
#define CORPSTAT_NONE 0x00
|
||||||
#define CORPSTAT_GENDER 0x03 /* 0x01 | 0x02 */
|
#define CORPSTAT_GENDER 0x03 /* 0x01 | 0x02 */
|
||||||
|
|||||||
+36
@@ -1251,6 +1251,42 @@ mksobj(int otyp, boolean init, boolean artif)
|
|||||||
return otmp;
|
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
|
* Several areas of the code made direct reassignments
|
||||||
* to obj->corpsenm. Because some special handling is
|
* to obj->corpsenm. Because some special handling is
|
||||||
|
|||||||
+10
-5
@@ -6103,11 +6103,13 @@ DISABLE_WARNING_FORMAT_NONLITERAL
|
|||||||
void
|
void
|
||||||
that_is_a_mimic(
|
that_is_a_mimic(
|
||||||
struct monst *mtmp, /* a hidden mimic (nonnull) */
|
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";
|
static char generic[] = "a monster";
|
||||||
char fmtbuf[BUFSZ];
|
char fmtbuf[BUFSZ];
|
||||||
const char *what = NULL;
|
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!");
|
Strcpy(fmtbuf, "Wait! That's %s!");
|
||||||
if (Blind) {
|
if (Blind) {
|
||||||
@@ -6116,7 +6118,7 @@ that_is_a_mimic(
|
|||||||
else if (M_AP_TYPE(mtmp) == M_AP_MONSTER)
|
else if (M_AP_TYPE(mtmp) == M_AP_MONSTER)
|
||||||
what = a_monnam(mtmp); /* differs from what was sensed */
|
what = a_monnam(mtmp); /* differs from what was sensed */
|
||||||
} else {
|
} 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);
|
int glyph = glyph_at(x, y);
|
||||||
|
|
||||||
if (glyph_is_cmap(glyph)) {
|
if (glyph_is_cmap(glyph)) {
|
||||||
@@ -6167,8 +6169,11 @@ that_is_a_mimic(
|
|||||||
what = a_monnam(mtmp);
|
what = a_monnam(mtmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (what)
|
if (what) {
|
||||||
pline(fmtbuf, what);
|
int i = (omit_wait && !strncmp(fmtbuf, "Wait! ", 7)) ? 7 : 0;
|
||||||
|
|
||||||
|
pline(&fmtbuf[i], what);
|
||||||
|
}
|
||||||
if (reveal_it)
|
if (reveal_it)
|
||||||
seemimic(mtmp);
|
seemimic(mtmp);
|
||||||
}
|
}
|
||||||
@@ -6179,7 +6184,7 @@ RESTORE_WARNING_FORMAT_NONLITERAL
|
|||||||
void
|
void
|
||||||
stumble_onto_mimic(struct monst *mtmp)
|
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)
|
if (!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data, AD_STCK)
|
||||||
/* must be adjacent; attack via polearm could be from farther away */
|
/* must be adjacent; attack via polearm could be from farther away */
|
||||||
|
|||||||
@@ -365,7 +365,7 @@ bhitm(struct monst *mtmp, struct obj *otmp)
|
|||||||
case WAN_LOCKING:
|
case WAN_LOCKING:
|
||||||
case SPE_WIZARD_LOCK:
|
case SPE_WIZARD_LOCK:
|
||||||
if (disguised_mimic && box_or_door(mtmp))
|
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);
|
wake = closeholdingtrap(mtmp, &learn_it);
|
||||||
break;
|
break;
|
||||||
case WAN_PROBING:
|
case WAN_PROBING:
|
||||||
@@ -377,7 +377,7 @@ bhitm(struct monst *mtmp, struct obj *otmp)
|
|||||||
case WAN_OPENING:
|
case WAN_OPENING:
|
||||||
case SPE_KNOCK:
|
case SPE_KNOCK:
|
||||||
if (disguised_mimic && box_or_door(mtmp))
|
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 */
|
wake = FALSE; /* don't want immediate counterattack */
|
||||||
if (mtmp == u.ustuck) {
|
if (mtmp == u.ustuck) {
|
||||||
/* zapping either holder/holdee or self [zapyourself()] will
|
/* zapping either holder/holdee or self [zapyourself()] will
|
||||||
@@ -483,21 +483,35 @@ bhitm(struct monst *mtmp, struct obj *otmp)
|
|||||||
learn_it = TRUE;
|
learn_it = TRUE;
|
||||||
break;
|
break;
|
||||||
case SPE_STONE_TO_FLESH:
|
case SPE_STONE_TO_FLESH:
|
||||||
/* FIXME: mimics disguished as stone furniture or stone object
|
if (mtmp->data->mlet == S_GOLEM) {
|
||||||
should be taken out of concealment. */
|
const char *mesg;
|
||||||
if (monsndx(mtmp->data) == PM_STONE_GOLEM) {
|
char *name = Monnam(mtmp); /* before possible polymorph */
|
||||||
char *name = Monnam(mtmp);
|
|
||||||
|
|
||||||
/* turn into flesh golem */
|
/* turn stone golem into flesh golem */
|
||||||
if (newcham(mtmp, &mons[PM_FLESH_GOLEM], NO_NC_FLAGS)) {
|
if (monsndx(mtmp->data) == PM_STONE_GOLEM
|
||||||
if (canseemon(mtmp))
|
&& newcham(mtmp, &mons[PM_FLESH_GOLEM], NO_NC_FLAGS))
|
||||||
pline("%s turns to flesh!", name);
|
mesg = "turns to flesh!";
|
||||||
} else {
|
else if (monsndx(mtmp->data) == PM_FLESH_GOLEM)
|
||||||
if (canseemon(mtmp))
|
mesg = "seems fleshier...";
|
||||||
pline("%s looks rather fleshy for a moment.", name);
|
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;
|
wake = FALSE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPE_DRAIN_LIFE:
|
case SPE_DRAIN_LIFE:
|
||||||
if (disguised_mimic)
|
if (disguised_mimic)
|
||||||
@@ -530,22 +544,19 @@ bhitm(struct monst *mtmp, struct obj *otmp)
|
|||||||
impossible("What an interesting effect (%d)", otyp);
|
impossible("What an interesting effect (%d)", otyp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (wake) {
|
if (wake && !DEADMONSTER(mtmp)) {
|
||||||
if (!DEADMONSTER(mtmp)) {
|
/* seemimic() is done by wakeup() and might unblock vision */
|
||||||
wakeup(mtmp, helpful_gesture ? FALSE : TRUE);
|
wakeup(mtmp, helpful_gesture ? FALSE : TRUE);
|
||||||
m_respond(mtmp);
|
m_respond(mtmp);
|
||||||
if (mtmp->isshk && !*u.ushops)
|
if (mtmp->isshk && !*u.ushops)
|
||||||
hot_pursuit(mtmp);
|
hot_pursuit(mtmp);
|
||||||
} else if (M_AP_TYPE(mtmp))
|
|
||||||
seemimic(mtmp); /* might unblock if mimicking a boulder/door */
|
|
||||||
}
|
}
|
||||||
/* note: gb.bhitpos won't be set if swallowed, but that's okay since
|
/* 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
|
* reveal_invis will be false. We can't use mtmp->mx, my since it
|
||||||
* might be an invisible worm hit on the tail.
|
* might be an invisible worm hit on the tail.
|
||||||
*/
|
*/
|
||||||
if (reveal_invis) {
|
if (reveal_invis && !DEADMONSTER(mtmp)) {
|
||||||
if (!DEADMONSTER(mtmp) && cansee(gb.bhitpos.x, gb.bhitpos.y)
|
if (cansee(gb.bhitpos.x, gb.bhitpos.y) && !canspotmon(mtmp))
|
||||||
&& !canspotmon(mtmp))
|
|
||||||
map_invisible(gb.bhitpos.x, gb.bhitpos.y);
|
map_invisible(gb.bhitpos.x, gb.bhitpos.y);
|
||||||
}
|
}
|
||||||
/* if effect was observable then discover the wand type provided
|
/* if effect was observable then discover the wand type provided
|
||||||
|
|||||||
Reference in New Issue
Block a user