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

@@ -472,7 +472,7 @@ if a branch has only one level (Fort Ludios), prevent creation of any level
wishing could attempt to place one)
opening/unlocking magic zapped at monster holding the hero will release hold
(zap at engulfer already expels hero); zapping at self has same effect
when riding, allow scroll of remove curse to affect to affect steed's saddle
when riding, allow scroll of remove curse read by hero to affect steed's saddle
the 'scores' option for final top ten display left default values in place if
only some of the three settings were set; 'scores:own' should have
produced '0 top/0 around/own' but ended up as '3 top/2 around/own'
@@ -488,6 +488,9 @@ when swallowed or underwater, player could be told about events (such as a
were not shown on the screen; treat being swallowed or underwater as
situations which block telepathy, extended monster detection, warning
some rolling boulder trap feedback was inconsistent
change "killed by <a foo>, while {paralyzed|frozen} by <a foo>" into
"killed by <a foo>, while {paralyzed|frozen}" if the killer caused
hero's helplessness
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -717,6 +717,7 @@ struct instance_globals {
char command_line[COLNO];
long command_count;
const char *multi_reason;
char multireasonbuf[QBUFSZ]; /* note: smaller than usual [BUFSZ] */
int nroom;
int nsubroom;
int occtime;

View File

@@ -2637,6 +2637,7 @@ extern void u_init(void);
/* ### uhitm.c ### */
extern void dynamic_multi_reason(struct monst *, const char *, boolean);
extern void erode_armor(struct monst *, int);
extern boolean attack_checks(struct monst *, struct obj *);
extern void check_caitiff(struct monst *);

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;