]> granicus.if.org Git - nethack/commitdiff
polymorphed quest leader
authorarromdee <arromdee>
Mon, 21 Jan 2002 22:15:22 +0000 (22:15 +0000)
committerarromdee <arromdee>
Mon, 21 Jan 2002 22:15:22 +0000 (22:15 +0000)
Duuuh.  Of course adding objects already changed the editlevel.

Anyway, here's the fix I was working on.  It only matters in a very obscure
situation.  (Also, the quest leader still speaks no matter what he's
polymorphed into.)

doc/fixes33.2
include/extern.h
include/quest.h
src/do.c
src/dog.c
src/makemon.c
src/mon.c
src/quest.c
src/questpgr.c
src/restore.c
src/zap.c

index 2549f1d4227a844c1b05726ae54d3d1f14834bb8..4409cbce19312a661b17a39686cb6dae4d2addb5 100644 (file)
@@ -402,6 +402,7 @@ eating an unpaid tin should calculate cost before not after eating
 spells shouldn't do negative damage
 when reading spellbooks, don't "continue studying" wrong book if original one
        gets destroyed after previous reading attempt has been interrupted
+correctly handle polymorphed quest leader
 
 
 Platform- and/or Interface-Specific Fixes
index 7b2e43a51d19691ef3435a78813cc980ae7cd2dc..f29615576ca25a9812606a21c4437db7c4105728 100644 (file)
@@ -1553,7 +1553,6 @@ E void NDECL(unload_qtlist);
 E short FDECL(quest_info, (int));
 E const char *NDECL(ldrname);
 E boolean FDECL(is_quest_artifact, (struct obj*));
-E boolean NDECL(leaderless);
 E void FDECL(com_pager, (int));
 E void FDECL(qt_pager, (int));
 E struct permonst *NDECL(qt_montype);
index 60f872e4d3a2b52984306069aaa8a2f6f625fe45..0b9d969361944602ad726b392a4d74aaaec6a25b 100644 (file)
@@ -25,6 +25,11 @@ struct q_score {                     /* Quest "scorecard" */
        Bitfield(touched_artifact,1);   /* for a special message */
        Bitfield(offered_artifact,1);   /* offered to leader */
        Bitfield(got_thanks,1);         /* final message from leader */
+
+       /* keep track of leader presence/absence even if leader is
+          polymorphed, raised from dead, etc */
+       Bitfield(leader_is_dead,1);
+       unsigned leader_m_id;
 };
 
 #define MAX_QUEST_TRIES  7     /* exceed this and you "fail" */
index 7014d52756320b4ab4046bb7ea056b01ed20899d..3af8262a434157f220db103676720c44d7fc9d64 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -1303,7 +1303,7 @@ boolean at_stairs, falling, portal;
 
        /* the message from your quest leader */
        if (!In_quest(&u.uz0) && at_dgn_entrance("The Quest") &&
-               !(u.uevent.qexpelled || u.uevent.qcompleted || leaderless())) {
+               !(u.uevent.qexpelled || u.uevent.qcompleted || quest_status.leader_is_dead)) {
 
                if (u.uevent.qcalled) {
                        com_pager(Role_if(PM_ROGUE) ? 4 : 3);
index 55f7b6b6439428b014e4d4c547ba8cc0fa78d8bf..8ded6360debf42c37dc0d06ef79c99e6269c0b39 100644 (file)
--- a/src/dog.c
+++ b/src/dog.c
@@ -740,6 +740,9 @@ register struct obj *obj;
            (is_demon(mtmp->data) && !is_demon(youmonst.data)) ||
            (obj && dogfood(mtmp, obj) >= MANFOOD)) return (struct monst *)0;
 
+       if (mtmp->m_id == quest_status.leader_m_id)
+           return((struct monst *)0);
+
        /* make a new monster which has the pet extension */
        mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
        *mtmp2 = *mtmp;
index f25e118d7bbd5b398607c6bcdaf4002097fd7bf0..ae95f47c7ef0f9a4765da563c7b2f1e0efd20164 100644 (file)
@@ -845,6 +845,8 @@ register int        mmflags;
        mtmp->m_id = flags.ident++;
        if (!mtmp->m_id) mtmp->m_id = flags.ident++;    /* ident overflowed */
        set_mon_data(mtmp, ptr, 0);
+       if (mtmp->data->msound == MS_LEADER)
+           quest_status.leader_m_id = mtmp->m_id;
        mtmp->mxlth = xlth;
        mtmp->mnum = mndx;
 
index 0e2d1e9bfe5aea7af233fc8cfa599150af9bb5d6..4f02e0bfc1ae5e27b5a5a767e9a111162aee2cf4 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -104,7 +104,8 @@ STATIC_VAR short cham_to_pm[] = {
 #define REVIVER(ptr)   (is_rider(ptr) || ptr->mlet == S_TROLL)
 
 #define KEEPTRAITS(mon)        (mon->isshk || mon->mtame || \
-                        (mon->data->geno & G_UNIQ) || REVIVER(mon->data))
+                        (mon->data->geno & G_UNIQ) || REVIVER(mon->data) || \
+                        (mon->m_id == quest_status.leader_m_id))
 
 /* Creates a monster corpse, a "special" corpse, or nothing if it doesn't
  * leave corpses.  Monsters which leave "special" corpses should have
@@ -1352,6 +1353,10 @@ register struct monst *mtmp;
         */
        tmp = monsndx(mtmp->data);
        if (mvitals[tmp].died < 255) mvitals[tmp].died++;
+
+       /* if it's a (possibly polymorphed) quest leader, mark him as dead */
+       if (mtmp->m_id == quest_status.leader_m_id)
+           quest_status.leader_is_dead = TRUE;
 #ifdef MAIL
        /* if the mail daemon dies, no more mail delivery.  -3. */
        if (tmp == PM_MAIL_DAEMON) mvitals[tmp].mvflags |= G_GENOD;
@@ -1733,7 +1738,7 @@ cleanup:
        newexplevel();          /* will decide if you go up */
 
        /* adjust alignment points */
-       if (mdat->msound == MS_LEADER) {                /* REAL BAD! */
+       if (mtmp->m_id == quest_status.leader_m_id) {           /* REAL BAD! */
            adjalign(-(u.ualign.record+(int)ALIGNLIM/2));
            pline("That was %sa bad idea...",
                        u.uevent.qcompleted ? "probably " : "");
index 2ae278b250b8ea9c584f29b9ff489ef3f23d60a4..b07dc776bd33e4246cf1553557455cad98f270fa 100644 (file)
@@ -341,8 +341,11 @@ void
 quest_chat(mtmp)
        register struct monst *mtmp;
 {
+    if (mtmp->m_id == Qstat(leader_m_id)) {
+       chat_with_leader();
+       return;
+    }
     switch(mtmp->data->msound) {
-           case MS_LEADER:     chat_with_leader(); break;
            case MS_NEMESIS:    chat_with_nemesis(); break;
            case MS_GUARDIAN:   chat_with_guardian(); break;
            default:    impossible("quest_chat: Unknown quest character %s.",
@@ -354,8 +357,11 @@ void
 quest_talk(mtmp)
        register struct monst *mtmp;
 {
+    if (mtmp->m_id == Qstat(leader_m_id)) {
+       leader_speaks(mtmp);
+       return;
+    }
     switch(mtmp->data->msound) {
-           case MS_LEADER:     leader_speaks(mtmp); break;
            case MS_NEMESIS:    nemesis_speaks(); break;
            case MS_DJINNI:     prisoner_speaks(mtmp); break;
            default:            break;
index 93351a6a3922ff68c82443c4e3e824b5cfa9e7f0..357de8f2977ee4dd44865bbf5147654af3c90f10 100644 (file)
@@ -209,15 +209,6 @@ homebase() /* return your role leader's location */
        return(urole.homebase);
 }
 
-boolean
-leaderless()   /* return true iff leader is dead */
-{
-       int i = urole.ldrnum;
-       /* BUG: This doesn't take the possibility of resurrection
-               via wand or spell of undead turning into account. */
-       return (boolean)(mvitals[i].died > 0);
-}
-
 STATIC_OVL struct qtmsg *
 msg_in(qtm_list, msgnum)
 struct qtmsg *qtm_list;
index 1bc845c0f5500d8402be7816c99a2b2c31dec25f..cc44f2752077a5a7bb475c1aed497ae455144094 100644 (file)
@@ -943,7 +943,12 @@ boolean ghostly;
 {
     struct obj *otmp;
     unsigned oldid, nid;
-    for (otmp = fobj; otmp; otmp = otmp->nobj)
+    for (otmp = fobj; otmp; otmp = otmp->nobj) {
+       if (ghostly && otmp->oattached == OATTACHED_MONST && otmp->oxlth) {
+           struct monst *mtmp = (struct monst *)otmp->oextra;
+
+           mtmp->m_id = 0;
+       }
        if (ghostly && otmp->oattached == OATTACHED_M_ID) {
            (void) memcpy((genericptr_t)&oldid, (genericptr_t)otmp->oextra,
                                                                sizeof(oldid));
@@ -953,6 +958,7 @@ boolean ghostly;
            else
                otmp->oattached = OATTACHED_NOTHING;
        }
+    }
 }
 
 
index a19d81c8b734239e00d99d30884b89a1b5768c5d..bd241dfcf3c02b164dfd7b804078963fbe4e3b10 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -465,7 +465,11 @@ coord *cc;
                mtmp2->mhp = mtmp2->mhpmax;
                /* Get these ones from mtmp */
                mtmp2->minvent = mtmp->minvent; /*redundant*/
-               mtmp2->m_id = mtmp->m_id;
+               /* monster ID is available if the monster died in the current
+                  game, but should be zero if the corpse was in a bones level
+                  (we cleared it when loading bones) */
+               if (!mtmp2->m_id)
+                   mtmp2->m_id = mtmp->m_id;
                mtmp2->mx   = mtmp->mx;
                mtmp2->my   = mtmp->my;
                mtmp2->mux  = mtmp->mux;
@@ -642,6 +646,10 @@ register struct obj *obj;
                        /* Monster retains its name */
                        if (obj->onamelth)
                            mtmp = christen_monst(mtmp, ONAME(obj));
+                       /* flag the quest leader as alive. */
+                       if (mtmp->data->msound == MS_LEADER || mtmp->m_id ==
+                               quest_status.leader_m_id)
+                           quest_status.leader_is_dead = FALSE;
                    }
                }
                if (mtmp) {