Copy bones monster info to recorporealized ghost

This is a reimplementation of commit ec32748 in TNNT by entrez:

    If you use undead turning on a dead hero's corpse from a bones file,
    its ghost will get sucked back into its body when it comes back to
    life.  In such cases, treat the newly revived corpse/recorporealized
    ghost as a "former hero" for the purposes of livelogging bones
    monster kills.

Part of this change was to remove a bit of weirdness in the game - the
odd situation where you revive a corpse-ghost combo on a bones pile, and
get the messages:

    The human corpse glows iridescently.
    Foo's ghost is suddenly drawn into its former body!
    The human is resurrected!

and subsequently the monster is just a generic human (or elf, etc)
without anything indicating it used to be a player. With this change,
the monster will retain the name that the ghost had, and its struct
ebones prevents the player from renaming it.

This commit also adjusts the "resurrected" message to explicitly use the
monster's name if it has one, and to use YMonnam in the unrelated case
where the monster was a pet (so reviving an unnamed tame kitten will
print as "Your kitten is resurrected!")
This commit is contained in:
copperwater
2026-06-21 06:42:10 -04:00
parent 186d9524de
commit 43c302d927
+16 -2
View File
@@ -892,6 +892,10 @@ revive(struct obj *corpse, boolean by_hero)
mmflags_nht mmflags = NO_MINVENT | MM_NOWAIT | MM_NOMSG;
int montype, cgend, container_nesting = 0;
boolean is_zomb;
/* normally use the name on the corpse object, but don't if drawing a
* player's ghost back into its body, in which case use the ghost's
* (player's) name */
boolean use_corpse_name = TRUE;
if (corpse->otyp != CORPSE) {
impossible("Attempting to revive %s?", xname(corpse));
@@ -1085,6 +1089,16 @@ revive(struct obj *corpse, boolean by_hero)
mtmp->mtame = ghost->mtame;
}
}
/* copy over ghost's name and struct ebones to newly revived "hero";
* has_mgivenname should always be true because there are guards
* against renaming a ghost, but check it just to be sure */
if (has_mgivenname(ghost)) {
mtmp = christen_monst(mtmp, MGIVENNAME(ghost));
/* don't let player-provided name of corpse override actual
* name of ex-hero */
use_corpse_name = FALSE;
}
copy_mextra(mtmp, ghost); /* pass on struct ebones */
/* was ghost, now alive, it's all very confusing */
mtmp->mconf = 1;
/* separate ghost monster no longer exists */
@@ -1094,7 +1108,7 @@ revive(struct obj *corpse, boolean by_hero)
}
/* monster retains its name */
if (has_oname(corpse) && !unique_corpstat(mtmp->data))
if (use_corpse_name && has_oname(corpse) && !unique_corpstat(mtmp->data))
mtmp = christen_monst(mtmp, ONAME(corpse));
/* partially eaten corpse yields wounded monster */
if (corpse->oeaten)
@@ -2357,7 +2371,7 @@ bhito(struct obj *obj, struct obj *otmp)
if (cansee(ox, oy)) {
if (canspotmon(mtmp)) {
pline("%s is resurrected!",
upstart(noname_monnam(mtmp, ARTICLE_THE)));
mtmp->mtame ? YMonnam(mtmp) : Monnam(mtmp));
learn_it = by_u ? TRUE : gz.zap_oseen;
} else {
/* saw corpse but don't see monster: maybe