From: PatR Date: Wed, 2 Mar 2022 00:51:41 +0000 (-0800) Subject: livelog: killing unique monsters X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=730f73d1c8f5ab7043656a992df083ed583b42c2;p=nethack livelog: killing unique monsters Treat the first kill of any unique monster as a major event (for inclusion in dumplog). Revival and repeat kill is not major but can still be seen during the game via the #chronicle command. Show the minor event more often: in addition to death #1 it was being shown on death 5, 10, 50, 100, 150, 200, and 250. Add 2, 3, and 25 to that list. --- diff --git a/src/mon.c b/src/mon.c index d3fef5322..948e80ffb 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 mon.c $NHDT-Date: 1646171625 2022/03/01 21:53:45 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.410 $ */ +/* NetHack 3.7 mon.c $NHDT-Date: 1646182267 2022/03/02 00:51:07 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.411 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -478,7 +478,7 @@ pm_to_cham(int mndx) || is_reviver((mon)->data) \ /* normally quest leader will be unique, */ \ /* but he or she might have been polymorphed */ \ - || (mon)->m_id == g.quest_status.leader_m_id \ + || (mon)->m_id == g.quest_status.leader_m_id \ /* special cancellation handling for these */ \ || (dmgtype((mon)->data, AD_SEDU) || dmgtype((mon)->data, AD_SSEX))) @@ -2441,7 +2441,7 @@ mondead(register struct monst* mtmp) { struct permonst *mptr; boolean be_sad; - int tmp; + int mndx; /* potential pet message; always clear global flag */ be_sad = iflags.sad_feeling; @@ -2453,12 +2453,11 @@ mondead(register struct monst* mtmp) return; if (is_vampshifter(mtmp)) { - int mndx = mtmp->cham; - int x = mtmp->mx, y = mtmp->my; - /* this only happens if shapeshifted */ + mndx = mtmp->cham; if (mndx >= LOW_PM && mndx != monsndx(mtmp->data) && !(g.mvitals[mndx].mvflags & G_GENOD)) { + coord new_xy; char buf[BUFSZ]; boolean in_door = (amorphous(mtmp->data) && closed_door(mtmp->mx, mtmp->my)), @@ -2469,6 +2468,7 @@ mondead(register struct monst* mtmp) spec_death = (g.disintegested /* disintegrated or digested */ || noncorporeal(mtmp->data) || amorphous(mtmp->data)); + int x = mtmp->mx, y = mtmp->my; /* construct a format string before transformation; will be capitalized when used, expects one %s arg */ @@ -2490,11 +2490,8 @@ mondead(register struct monst* mtmp) uunstick(); } if (in_door) { - coord new_xy; - - if (enexto(&new_xy, mtmp->mx, mtmp->my, &mons[mndx])) { + if (enexto(&new_xy, mtmp->mx, mtmp->my, &mons[mndx])) rloc_to(mtmp, new_xy.x, new_xy.y); - } } newcham(mtmp, &mons[mndx], FALSE, FALSE); if (mtmp->data == &mons[mndx]) @@ -2551,17 +2548,17 @@ mondead(register struct monst* mtmp) * based on only player kills probably opens more avenues of abuse * for rings of conflict and such. */ - tmp = monsndx(mtmp->data); - if (g.mvitals[tmp].died < 255) - g.mvitals[tmp].died++; + mndx = monsndx(mtmp->data); + if (g.mvitals[mndx].died < 255) + g.mvitals[mndx].died++; /* if it's a (possibly polymorphed) quest leader, mark him as dead */ if (mtmp->m_id == g.quest_status.leader_m_id) g.quest_status.leader_is_dead = TRUE; #ifdef MAIL_STRUCTURES /* if the mail daemon dies, no more mail delivery. -3. */ - if (tmp == PM_MAIL_DAEMON) - g.mvitals[tmp].mvflags |= G_GENOD; + if (mndx == PM_MAIL_DAEMON) + g.mvitals[mndx].mvflags |= G_GENOD; #endif if (mtmp->data->mlet == S_KOP) { @@ -2588,35 +2585,44 @@ mondead(register struct monst* mtmp) if (mtmp->data->msound == MS_NEMESIS) nemdead(); #endif - if (mtmp->data == &mons[PM_MEDUSA]) - record_achievement(ACH_MEDU); - else if (unique_corpstat(mtmp->data)) { - switch (g.mvitals[tmp].died) { - case 1: - livelog_printf(LL_UMONST, "%s %s", - nonliving(mtmp->data) ? "destroyed" : "killed", - livelog_mon_nam(mtmp)); - break; - case 5: - case 10: - case 50: - case 100: - case 150: - case 200: - case 250: - livelog_printf(LL_UMONST, "%s %s (%d times)", - nonliving(mtmp->data) ? "destroyed" : "killed", - livelog_mon_nam(mtmp), g.mvitals[tmp].died); - break; - default: - /* don't spam the log every time */ - break; + + if (mndx == PM_MEDUSA && g.mvitals[mndx].died == 1) { + record_achievement(ACH_MEDU); /* also generates a livelog event */ + } else if (unique_corpstat(mtmp->data)) { + /* + * livelog event; unique_corpstat() includes the Wizard and + * any High Priest even though they aren't actually unique. + * + * It would be nice to include shopkeepers. Their names are + * unique within each game but unfortunately for this potential + * usage their kill count is lumped together in a group total. + */ + int howmany = g.mvitals[mndx].died; + + /* 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) { + char xtra[40]; + + xtra[0] = '\0'; + if (howmany > 1) /* "(2nd time)" or "(50th time)" */ + Sprintf(xtra, " (%d%s time)", howmany, ordin(howmany)); + + livelog_printf(LL_UMONST | ((howmany == 1) ? LL_ACHIEVE : 0), + "%s %s%s", + nonliving(mtmp->data) ? "destroyed" : "killed", + livelog_mon_nam(mtmp), xtra); } } if (glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph)) unmap_object(mtmp->mx, mtmp->my); m_detach(mtmp, mptr); + return; } RESTORE_WARNING_FORMAT_NONLITERAL