fix "Killed by foo, while paralyzed by a monster"

If the killer and the paralyzer are the same monster, truncate
that to "Killed by a foo, while paralyzed".  When not the same,
spell out the paralyzer's monster type instead of using generic
"monster".  "Killed by a fox, while paralyzed by a ghoul", or
"Killed by a ghoul, while paralyzed by a ghoul" *if* they were
two different ghouls.
This commit is contained in:
PatR
2021-04-22 16:13:41 -07:00
parent 3aacb38006
commit b4ae19ed0c
7 changed files with 76 additions and 6 deletions

View File

@@ -259,6 +259,9 @@ const struct instance_globals g_init = {
UNDEFINED_VALUES, /* command_line */
0, /* command_count */
NULL, /* multi_reason */
/* multi_reason usually points to a string literal (when not Null)
but multireasonbuf[] is available for when it needs to be dynamic */
DUMMY, /* multireasonbuf[] */
0, /* nroom */
0, /* nsubroom */
0, /* occtime */

View File

@@ -494,6 +494,37 @@ done_in_by(struct monst *mtmp, int how)
}
Strcpy(g.killer.name, buf);
/* might need to fix up multi_reason if 'mtmp' caused the reason */
if (g.multi_reason
&& g.multi_reason > g.multireasonbuf
&& g.multi_reason < g.multireasonbuf + sizeof g.multireasonbuf - 1) {
char reasondummy, *p;
unsigned reasonmid = 0;
/*
* multireasonbuf[] contains 'm_id:reason' and multi_reason
* points at the text past the colon, so we have something
* like "42:paralyzed by a ghoul"; if mtmp->m_id matches 42
* then we truncate 'reason' at its first space so that final
* death reason becomes "Killed by a ghoul, while paralyzed."
* instead of "Killed by a ghoul, while paralyzed by a ghoul."
* (3.6.x gave "Killed by a ghoul, while paralyzed by a monster."
* which is potenitally misleading when the monster is also
* the killer.)
*
* Note that if the hero is life-saved and then killed again
* before the helplessness has cleared, the second death will
* report the truncated helplessness reason even if some other
* monster peforms the /coup de grace/.
*/
if (sscanf(g.multireasonbuf, "%u:%c", &reasonmid, &reasondummy) == 2
&& mtmp->m_id == reasonmid) {
if ((p = index(g.multireasonbuf, ' ')) != 0)
*p = '\0';
}
}
/*
* Chicken and egg issue:
* Ordinarily Unchanging ought to override something like this,
@@ -555,6 +586,7 @@ fixup_death(int how)
g.multi_reason = death_fixups[i].include;
else /* remove the helplessness reason */
g.multi_reason = (char *) 0;
g.multireasonbuf[0] = '\0'; /* dynamic buf stale either way */
if (death_fixups[i].unmulti) /* possibly hide helplessness */
g.multi = 0L;
break;

View File

@@ -3020,7 +3020,7 @@ nomul(int nval)
u.usleep = 0;
g.multi = nval;
if (nval == 0)
g.multi_reason = NULL;
g.multi_reason = NULL, g.multireasonbuf[0] = '\0';
end_running(TRUE);
}
@@ -3047,7 +3047,7 @@ unmul(const char *msg_override)
}
g.nomovemsg = 0;
u.usleep = 0;
g.multi_reason = NULL;
g.multi_reason = NULL, g.multireasonbuf[0] = '\0';
if (g.afternmv) {
int (*f)(void) = g.afternmv;

View File

@@ -28,6 +28,30 @@ static boolean shade_aware(struct obj *);
#define PROJECTILE(obj) ((obj) && is_ammo(obj))
/* multi_reason is usually a literal string; here we generate one that
has the causing monster's type included */
void
dynamic_multi_reason(struct monst *mon, const char *verb, boolean by_gaze)
{
/* combination of noname_monnam() and m_monnam(), more or less;
accurate regardless of visibility or hallucination (only seen
if game ends) and without personal name (M2_PNAME excepted) */
char *who = x_monnam(mon, ARTICLE_A, (char *) 0,
(SUPPRESS_IT | SUPPRESS_INVISIBLE
| SUPPRESS_HALLUCINATION | SUPPRESS_SADDLE
| SUPPRESS_NAME),
FALSE),
*p = g.multireasonbuf;
/* prefix info for done_in_by() */
Sprintf(p, "%u:", mon->m_id);
p = eos(p);
Sprintf(p, "%s by %s%s", verb,
!by_gaze ? who : s_suffix(who),
!by_gaze ? "" : " gaze");
g.multi_reason = p;
}
void
erode_armor(struct monst *mdef, int hurt)
{
@@ -2813,7 +2837,9 @@ mhitm_ad_plys(struct monst *magr, struct attack *mattk, struct monst *mdef,
You("are frozen by %s!", mon_nam(magr));
g.nomovemsg = You_can_move_again;
nomul(-rnd(10));
g.multi_reason = "paralyzed by a monster";
/* set g.multi_reason;
3.6.x used "paralyzed by a monster"; be more specific */
dynamic_multi_reason(magr, "paralyzed", FALSE);
exercise(A_DEX, FALSE);
}
}
@@ -4967,7 +4993,9 @@ passive(struct monst *mon,
} else {
You("are frozen by %s gaze!", s_suffix(mon_nam(mon)));
nomul((ACURR(A_WIS) > 12 || rn2(4)) ? -tmp : -127);
g.multi_reason = "frozen by a monster's gaze";
/* set g.multi_reason;
3.6.x used "frozen by a monster's gaze" */
dynamic_multi_reason(mon, "frozen", TRUE);
g.nomovemsg = 0;
}
} else {
@@ -4982,7 +5010,9 @@ passive(struct monst *mon,
You("are frozen by %s!", mon_nam(mon));
g.nomovemsg = You_can_move_again;
nomul(-tmp);
g.multi_reason = "frozen by a monster";
/* set g.multi_reason;
3.6.x used "frozen by a monster"; be more specific */
dynamic_multi_reason(mon, "frozen", FALSE);
exercise(A_DEX, FALSE);
}
break;