mondead() uncluttering
Pull request #1005 introduced some code that needed minor reformatting. This goes beyond that, splitting the livelog/#chronicle handling and the vampire unshifting code out of mondead() into separate routines. The livelog phrasing for death of a unique monster always assumed that the hero was directly responsible: "killed|destroyed <unique mon|shk+details> (Nth time)." If it dies while monsters are moving, switch to: "<unique mon|shk+details> has been killed|destroyed (Nth time)." It isn't phrased as if the hero is responsible if the monster dies due to passive counter-attack against poly'd hero but that isn't blatantly wrong and doesn't seem worth worrying about.
This commit is contained in:
278
src/mon.c
278
src/mon.c
@@ -19,6 +19,8 @@ static void mon_leaving_level(struct monst *);
|
||||
static void m_detach(struct monst *, struct permonst *, boolean);
|
||||
static void set_mon_min_mhpmax(struct monst *, int);
|
||||
static void lifesaved_monster(struct monst *);
|
||||
static boolean vamprises(struct monst *);
|
||||
static void logdeadmon(struct monst *, int);
|
||||
static boolean ok_to_obliterate(struct monst *);
|
||||
static void qst_guardians_respond(void);
|
||||
static void peacefuls_respond(struct monst *);
|
||||
@@ -39,13 +41,6 @@ extern const struct shclass shtypes[]; /* defined in shknam.c */
|
||||
|| !gl.level.flags.deathdrops \
|
||||
|| (gl.level.flags.graveyard && is_undead(mdat) && rn2(3)))
|
||||
|
||||
/* A specific combination of x_monnam flags for livelogging. The livelog
|
||||
* shouldn't show that you killed a hallucinatory monster and not what it
|
||||
* actually is. */
|
||||
#define livelog_mon_nam(mtmp) \
|
||||
x_monnam(mtmp, ARTICLE_THE, (char *) 0, \
|
||||
(SUPPRESS_IT | SUPPRESS_HALLUCINATION), FALSE)
|
||||
|
||||
|
||||
#if 0
|
||||
/* part of the original warning code which was replaced in 3.3.1 */
|
||||
@@ -2622,6 +2617,157 @@ lifesaved_monster(struct monst* mtmp)
|
||||
|
||||
DISABLE_WARNING_FORMAT_NONLITERAL
|
||||
|
||||
/* when a ahape-shifted vampire is killed, it reverts to base form instead
|
||||
of dying; moved into separate routine to unclutter mondead() */
|
||||
static boolean
|
||||
vamprises(struct monst *mtmp)
|
||||
{
|
||||
int mndx = mtmp->cham;
|
||||
|
||||
if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)
|
||||
&& !(gm.mvitals[mndx].mvflags & G_GENOD)) {
|
||||
coord new_xy;
|
||||
char buf[BUFSZ];
|
||||
/* alternate message phrasing for some monster types */
|
||||
boolean spec_mon = (nonliving(mtmp->data)
|
||||
|| noncorporeal(mtmp->data)
|
||||
|| amorphous(mtmp->data)),
|
||||
spec_death = (gd.disintegested /* disintegrated/digested */
|
||||
|| noncorporeal(mtmp->data)
|
||||
|| amorphous(mtmp->data));
|
||||
coordxy x = mtmp->mx, y = mtmp->my;
|
||||
|
||||
/* construct a format string before transformation;
|
||||
will be capitalized when used, expects one %s arg */
|
||||
Snprintf(buf, sizeof buf,
|
||||
"%s suddenly %s and rises as %%s!",
|
||||
x_monnam(mtmp, ARTICLE_THE,
|
||||
spec_mon ? (char *) 0 : "seemingly dead",
|
||||
(SUPPRESS_INVISIBLE | SUPPRESS_IT), FALSE),
|
||||
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 */
|
||||
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 (mtmp->data == &mons[mndx])
|
||||
mtmp->cham = NON_PM;
|
||||
else
|
||||
mtmp->cham = mndx;
|
||||
|
||||
if (canspotmon(mtmp)) {
|
||||
/* 3.6.0 used a_monnam(mtmp); that was weird if mtmp was
|
||||
named: "Dracula suddenly transforms and rises as Dracula";
|
||||
3.6.1 used mtmp->data->mname; that ignored hallucination */
|
||||
pline(upstart(buf),
|
||||
x_monnam(mtmp, ARTICLE_A, (char *) 0,
|
||||
(SUPPRESS_NAME | SUPPRESS_IT | SUPPRESS_INVISIBLE),
|
||||
FALSE));
|
||||
gv.vamp_rise_msg = TRUE;
|
||||
}
|
||||
newsym(x, y);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RESTORE_WARNING_FORMAT_NONLITERAL
|
||||
|
||||
/* A specific combination of x_monnam flags for livelogging. The livelog
|
||||
* shouldn't show that you killed a hallucinatory monster and not what it
|
||||
* actually is. */
|
||||
#define livelog_mon_nam(mtmp) \
|
||||
x_monnam(mtmp, ARTICLE_THE, (char *) 0, \
|
||||
(SUPPRESS_IT | SUPPRESS_HALLUCINATION), FALSE)
|
||||
|
||||
/* when a mon has died, mabye record an achievment of issue livelog message;
|
||||
moved into separate routine to unclutter mondead() */
|
||||
static void
|
||||
logdeadmon(struct monst *mtmp, int mndx)
|
||||
{
|
||||
int howmany = gm.mvitals[mndx].died;
|
||||
|
||||
if (mndx == PM_MEDUSA && howmany == 1) {
|
||||
record_achievement(ACH_MEDU); /* also generates a livelog event */
|
||||
} else if (unique_corpstat(mtmp->data)
|
||||
|| (mtmp->isshk && !mtmp->mrevived)) {
|
||||
char shkdetail[QBUFSZ];
|
||||
const char *mkilled;
|
||||
boolean herodidit = !gc.context.mon_moving;
|
||||
|
||||
/*
|
||||
* livelog event; unique_corpstat() includes the Wizard and
|
||||
* any High Priest even though they aren't actually unique.
|
||||
*
|
||||
* Shopkeeper kills are logged, but only the first time per
|
||||
* shopkeeper, since their shared kill counter wouldn't work
|
||||
* for this purpose (and it wouldn't account for polymorphed
|
||||
* shopkeepers either).
|
||||
*/
|
||||
shkdetail[0] = '\0';
|
||||
if (mtmp->isshk) {
|
||||
howmany = 1;
|
||||
/* ", the <shoptype> priorietor" needs a trailing comma for
|
||||
the alternate phrasing "<shk>, shkdetails, has been killed"
|
||||
when hero isn't directly responsible */
|
||||
Snprintf(shkdetail, sizeof shkdetail, ", the %s %s%s",
|
||||
shtypes[ESHK(mtmp)->shoptype - SHOPBASE].name,
|
||||
/* in case shk name doesn't include Mr or Ms honoric */
|
||||
mtmp->female ? "proprietrix" : "proprietor",
|
||||
herodidit ? "" : ",");
|
||||
}
|
||||
|
||||
/* killing a unique more than once doesn't get logged every time;
|
||||
the Wizard and the Riders can be killed more than once
|
||||
"naturally", others require deliberate player action such as
|
||||
use of undead turning to revive a corpse or petrification plus
|
||||
stone-to-flesh to create and revive a statue */
|
||||
if (howmany <= 3 || howmany == 5 || howmany == 10 || howmany == 25
|
||||
|| (howmany % 50) == 0) { /* 50, 100, 150, 200, 250 */
|
||||
char xtra[40]; /* space for " (Nth time)" when N > 1 */
|
||||
long llevent_type = LL_UMONST;
|
||||
|
||||
/* the first kill of any unique monster is a major event;
|
||||
all kills of the Wizard and the Riders are major when
|
||||
they're logged but they still don't get logged every time */
|
||||
if (howmany == 1 || mtmp->iswiz || is_rider(mtmp->data))
|
||||
llevent_type |= LL_ACHIEVE;
|
||||
xtra[0] = '\0';
|
||||
if (howmany > 1) /* "(2nd time)" or "(50th time)" */
|
||||
Sprintf(xtra, " (%d%s time)", howmany, ordin(howmany));
|
||||
|
||||
mkilled = nonliving(mtmp->data) ? "destroyed" : "killed";
|
||||
/* hero is responsible: "killed <monst>" */
|
||||
if (herodidit)
|
||||
livelog_printf(llevent_type, "%s %s%s%s",
|
||||
mkilled,
|
||||
livelog_mon_nam(mtmp), shkdetail, xtra);
|
||||
else /* trap, pet, conflict: "<monst> has been killed" */
|
||||
livelog_printf(llevent_type, "%s%s has been %s%s",
|
||||
livelog_mon_nam(mtmp), shkdetail,
|
||||
mkilled, xtra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef livelog_mon_nam
|
||||
|
||||
/* monster 'mtmp' has died; maybe life-save, otherwise unshapeshift and
|
||||
update vanquished stats and update map */
|
||||
void
|
||||
mondead(struct monst *mtmp)
|
||||
{
|
||||
@@ -2638,66 +2784,9 @@ mondead(struct monst *mtmp)
|
||||
if (!DEADMONSTER(mtmp))
|
||||
return;
|
||||
|
||||
if (is_vampshifter(mtmp)) {
|
||||
/* this only happens if shapeshifted */
|
||||
mndx = mtmp->cham;
|
||||
if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)
|
||||
&& !(gm.mvitals[mndx].mvflags & G_GENOD)) {
|
||||
coord new_xy;
|
||||
char buf[BUFSZ];
|
||||
/* alternate message phrasing for some monster types */
|
||||
boolean spec_mon = (nonliving(mtmp->data)
|
||||
|| noncorporeal(mtmp->data)
|
||||
|| amorphous(mtmp->data)),
|
||||
spec_death = (gd.disintegested /* disintegrated/digested */
|
||||
|| noncorporeal(mtmp->data)
|
||||
|| amorphous(mtmp->data));
|
||||
coordxy x = mtmp->mx, y = mtmp->my;
|
||||
|
||||
/* construct a format string before transformation;
|
||||
will be capitalized when used, expects one %s arg */
|
||||
Sprintf(buf, "%s suddenly %s and rises as %%s!",
|
||||
x_monnam(mtmp, ARTICLE_THE,
|
||||
spec_mon ? (char *) 0 : "seemingly dead",
|
||||
(SUPPRESS_INVISIBLE | SUPPRESS_IT), FALSE),
|
||||
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 */
|
||||
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 (mtmp->data == &mons[mndx])
|
||||
mtmp->cham = NON_PM;
|
||||
else
|
||||
mtmp->cham = mndx;
|
||||
if (canspotmon(mtmp)) {
|
||||
/* 3.6.0 used a_monnam(mtmp); that was weird if mtmp was
|
||||
named: "Dracula suddenly transforms and rises as Dracula";
|
||||
3.6.1 used mtmp->data->mname; that ignored hallucination */
|
||||
pline(upstart(buf),
|
||||
x_monnam(mtmp, ARTICLE_A, (char *) 0,
|
||||
(SUPPRESS_NAME | SUPPRESS_IT
|
||||
| SUPPRESS_INVISIBLE), FALSE));
|
||||
gv.vamp_rise_msg = TRUE;
|
||||
}
|
||||
newsym(x, y);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* vampire in bat/fog/wolf form reverts to vampire instead of dying */
|
||||
if (is_vampshifter(mtmp) && vamprises(mtmp))
|
||||
return;
|
||||
|
||||
if (be_sad)
|
||||
You("have a sad feeling for a moment, then it passes.");
|
||||
@@ -2762,65 +2851,18 @@ mondead(struct monst *mtmp)
|
||||
}
|
||||
}
|
||||
|
||||
if (mndx == PM_MEDUSA && gm.mvitals[mndx].died == 1) {
|
||||
record_achievement(ACH_MEDU); /* also generates a livelog event */
|
||||
} else if (unique_corpstat(mtmp->data)
|
||||
|| (mtmp->isshk && !mtmp->mrevived)) {
|
||||
/*
|
||||
* livelog event; unique_corpstat() includes the Wizard and
|
||||
* any High Priest even though they aren't actually unique.
|
||||
*
|
||||
* Shopkeeper kills are logged, but only the first time per
|
||||
* shopkeeper, since their shared kill counter wouldn't work
|
||||
* for this purpose (and it wouldn't account for polymorphed
|
||||
* shopkeepers either).
|
||||
*/
|
||||
int howmany = gm.mvitals[mndx].died;
|
||||
char shkdetail[100];
|
||||
shkdetail[0]='\0';
|
||||
if (mtmp->isshk) {
|
||||
struct eshk *eshk = ESHK(mtmp);
|
||||
howmany = 1;
|
||||
Sprintf(shkdetail, ", the %s proprietor",
|
||||
shtypes[eshk->shoptype - SHOPBASE].name);
|
||||
}
|
||||
|
||||
/* killing a unique more than once doesn't get logged every time;
|
||||
the Wizard and the Riders can be killed more than once
|
||||
"naturally", others require deliberate player action such as
|
||||
use of undead turning to revive a corpse or petrification plus
|
||||
stone-to-flesh to create and revive a statue */
|
||||
if (howmany <= 3 || howmany == 5 || howmany == 10 || howmany == 25
|
||||
|| (howmany % 50) == 0) { /* 50, 100, 150, 200, 250 */
|
||||
char xtra[40];
|
||||
long llevent_type = LL_UMONST;
|
||||
|
||||
/* first kill of any unique is a major event; all kills of the
|
||||
Wizard and the Riders are major if they're logged but they
|
||||
still don't get logged every time */
|
||||
if (howmany == 1 || mtmp->iswiz || is_rider(mtmp->data))
|
||||
llevent_type |= LL_ACHIEVE;
|
||||
xtra[0] = '\0';
|
||||
if (howmany > 1) /* "(2nd time)" or "(50th time)" */
|
||||
Sprintf(xtra, " (%d%s time)", howmany, ordin(howmany));
|
||||
|
||||
livelog_printf(llevent_type, "%s %s%s%s",
|
||||
nonliving(mtmp->data) ? "destroyed" : "killed",
|
||||
livelog_mon_nam(mtmp), shkdetail, xtra);
|
||||
}
|
||||
}
|
||||
/* achievement and/or livelog */
|
||||
logdeadmon(mtmp, mndx);
|
||||
|
||||
if (glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph))
|
||||
unmap_object(mtmp->mx, mtmp->my);
|
||||
|
||||
/* remove 'mtmp' from play; it will stay on the fmon list until end of
|
||||
current move, then dmonsfree() will get rid of it */
|
||||
m_detach(mtmp, mptr, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
RESTORE_WARNING_FORMAT_NONLITERAL
|
||||
|
||||
#undef livelog_mon_nam
|
||||
|
||||
/* TRUE if corpse might be dropped, magr may die if mon was swallowed */
|
||||
boolean
|
||||
corpse_chance(
|
||||
|
||||
Reference in New Issue
Block a user