From 166affb0f91e5edd21d66906f192cfb8b01c8127 Mon Sep 17 00:00:00 2001 From: arromdee Date: Mon, 21 Jan 2002 22:15:22 +0000 Subject: [PATCH] polymorphed quest leader 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 | 1 + include/extern.h | 1 - include/quest.h | 5 +++++ src/do.c | 2 +- src/dog.c | 3 +++ src/makemon.c | 2 ++ src/mon.c | 9 +++++++-- src/quest.c | 10 ++++++++-- src/questpgr.c | 9 --------- src/restore.c | 8 +++++++- src/zap.c | 10 +++++++++- 11 files changed, 43 insertions(+), 17 deletions(-) diff --git a/doc/fixes33.2 b/doc/fixes33.2 index 2549f1d42..4409cbce1 100644 --- a/doc/fixes33.2 +++ b/doc/fixes33.2 @@ -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 diff --git a/include/extern.h b/include/extern.h index 7b2e43a51..f29615576 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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); diff --git a/include/quest.h b/include/quest.h index 60f872e4d..0b9d96936 100644 --- a/include/quest.h +++ b/include/quest.h @@ -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" */ diff --git a/src/do.c b/src/do.c index 7014d5275..3af8262a4 100644 --- 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); diff --git a/src/dog.c b/src/dog.c index 55f7b6b64..8ded6360d 100644 --- 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; diff --git a/src/makemon.c b/src/makemon.c index f25e118d7..ae95f47c7 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -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; diff --git a/src/mon.c b/src/mon.c index 0e2d1e9bf..4f02e0bfc 100644 --- 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 " : ""); diff --git a/src/quest.c b/src/quest.c index 2ae278b25..b07dc776b 100644 --- a/src/quest.c +++ b/src/quest.c @@ -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; diff --git a/src/questpgr.c b/src/questpgr.c index 93351a6a3..357de8f29 100644 --- a/src/questpgr.c +++ b/src/questpgr.c @@ -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; diff --git a/src/restore.c b/src/restore.c index 1bc845c0f..cc44f2752 100644 --- a/src/restore.c +++ b/src/restore.c @@ -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; } + } } diff --git a/src/zap.c b/src/zap.c index a19d81c8b..bd241dfcf 100644 --- 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) {