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.)
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
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);
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" */
/* 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);
(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;
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;
#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
*/
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;
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 " : "");
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.",
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;
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;
{
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));
else
otmp->oattached = OATTACHED_NOTHING;
}
+ }
}
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;
/* 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) {