fix #HH5887 - Dark One / Eye message bug
Some roles' quest message when returning the nemesis lair refer to sensing the presence/aura/whatever of the quest artifact, but it might not be there anymore. In reported case, the nemesis had picked it up and later fled up the stairs to another level. Other situations are possible; it's feasible for the hero to already have it. So provide an alternate message, and some extra code to decide whether to use it. Other anomalous messages, such as looking down on the dead body of a nemesis who didn't leave a corpse, can still occur.
This commit is contained in:
18
src/quest.c
18
src/quest.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 quest.c $NHDT-Date: 1446191878 2015/10/30 07:57:58 $ $NHDT-Branch: master $:$NHDT-Revision: 1.20 $ */
|
||||
/* NetHack 3.6 quest.c $NHDT-Date: 1505170343 2017/09/11 22:52:23 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.21 $ */
|
||||
/* Copyright 1991, M. Stephenson */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -68,7 +68,20 @@ on_goal()
|
||||
qt_pager(QT_FIRSTGOAL);
|
||||
Qstat(made_goal) = 1;
|
||||
} else {
|
||||
qt_pager(QT_NEXTGOAL);
|
||||
/*
|
||||
* Some QT_NEXTGOAL messages reference the quest artifact;
|
||||
* find out if it is still present. If not, request an
|
||||
* alternate message (qt_pager() will revert to delivery
|
||||
* of QT_NEXTGOAL if current role doesn't have QT_ALTGOAL).
|
||||
* Note: if hero is already carrying it, it is treated as
|
||||
* being absent from the level for quest message purposes.
|
||||
*/
|
||||
unsigned whichobjchains = ((1 << OBJ_FLOOR)
|
||||
| (1 << OBJ_MINVENT)
|
||||
| (1 << OBJ_BURIED));
|
||||
struct obj *qarti = find_quest_artifact(whichobjchains);
|
||||
|
||||
qt_pager(qarti ? QT_NEXTGOAL : QT_ALTGOAL);
|
||||
if (Qstat(made_goal) < 7)
|
||||
Qstat(made_goal)++;
|
||||
}
|
||||
@@ -179,6 +192,7 @@ boolean seal;
|
||||
schedule_goto(dest, FALSE, FALSE, portal_flag, (char *) 0, (char *) 0);
|
||||
if (seal) { /* remove the portal to the quest - sealing it off */
|
||||
int reexpelled = u.uevent.qexpelled;
|
||||
|
||||
u.uevent.qexpelled = 1;
|
||||
remdun_mapseen(quest_dnum);
|
||||
/* Delete the near portal now; the far (main dungeon side)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 questpgr.c $NHDT-Date: 1448541043 2015/11/26 12:30:43 $ $NHDT-Branch: master $:$NHDT-Revision: 1.36 $ */
|
||||
/* NetHack 3.6 questpgr.c $NHDT-Date: 1505170344 2017/09/11 22:52:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.37 $ */
|
||||
/* Copyright 1991, M. Stephenson */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -22,6 +22,7 @@ static void NDECL(dump_qtlist);
|
||||
static void FDECL(Fread, (genericptr_t, int, int, dlb *));
|
||||
STATIC_DCL struct qtmsg *FDECL(construct_qtlist, (long));
|
||||
STATIC_DCL const char *NDECL(intermed);
|
||||
STATIC_DCL struct obj *FDECL(find_qarti, (struct obj *));
|
||||
STATIC_DCL const char *NDECL(neminame);
|
||||
STATIC_DCL const char *NDECL(guardname);
|
||||
STATIC_DCL const char *NDECL(homebase);
|
||||
@@ -196,6 +197,58 @@ struct obj *otmp;
|
||||
return (boolean) (otmp->oartifact == urole.questarti);
|
||||
}
|
||||
|
||||
STATIC_OVL struct obj *
|
||||
find_qarti(ochain)
|
||||
struct obj *ochain;
|
||||
{
|
||||
struct obj *otmp, *qarti;
|
||||
|
||||
for (otmp = ochain; otmp; otmp = otmp->nobj) {
|
||||
if (is_quest_artifact(otmp))
|
||||
return otmp;
|
||||
if (Has_contents(otmp) && (qarti = find_qarti(otmp->cobj)) != 0)
|
||||
return qarti;
|
||||
}
|
||||
return (struct obj *) 0;
|
||||
}
|
||||
|
||||
/* check several object chains for the quest artifact to determine
|
||||
whether it is present on the current level */
|
||||
struct obj *
|
||||
find_quest_artifact(whichchains)
|
||||
unsigned whichchains;
|
||||
{
|
||||
struct monst *mtmp;
|
||||
struct obj *qarti = 0;
|
||||
|
||||
if ((whichchains & (1 << OBJ_INVENT)) != 0)
|
||||
qarti = find_qarti(invent);
|
||||
if (!qarti && (whichchains & (1 << OBJ_FLOOR)) != 0)
|
||||
qarti = find_qarti(fobj);
|
||||
if (!qarti && (whichchains & (1 << OBJ_MINVENT)) != 0)
|
||||
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
|
||||
if (DEADMONSTER(mtmp))
|
||||
continue;
|
||||
if ((qarti = find_qarti(fmon->minvent)) != 0)
|
||||
break;
|
||||
}
|
||||
if (!qarti && (whichchains & (1 << OBJ_MIGRATING)) != 0) {
|
||||
/* check migrating objects and minvent of migrating monsters */
|
||||
for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
|
||||
if (DEADMONSTER(mtmp))
|
||||
continue;
|
||||
if ((qarti = find_qarti(fmon->minvent)) != 0)
|
||||
break;
|
||||
}
|
||||
if (!qarti)
|
||||
qarti = find_qarti(migrating_objs);
|
||||
}
|
||||
if (!qarti && (whichchains & (1 << OBJ_BURIED)) != 0)
|
||||
qarti = find_qarti(level.buriedobjlist);
|
||||
|
||||
return qarti;
|
||||
}
|
||||
|
||||
/* return your role nemesis' name */
|
||||
STATIC_OVL const char *
|
||||
neminame()
|
||||
@@ -573,7 +626,18 @@ int msgnum;
|
||||
if (skip_pager(FALSE))
|
||||
return;
|
||||
|
||||
if (!(qt_msg = msg_in(qt_list.chrole, msgnum))) {
|
||||
qt_msg = msg_in(qt_list.chrole, msgnum);
|
||||
if (!qt_msg) {
|
||||
/* some roles have an alternate message for return to the goal
|
||||
level when the quest artifact is absent (handled by caller)
|
||||
but some don't; for the latter, use the normal goal message;
|
||||
note: for first visit, artifact is assumed to always be
|
||||
present which might not be true for wizard mode but we don't
|
||||
worry about quest message references in that situation */
|
||||
if (msgnum == QT_ALTGOAL)
|
||||
qt_msg = msg_in(qt_list.chrole, QT_NEXTGOAL);
|
||||
}
|
||||
if (!qt_msg) {
|
||||
impossible("qt_pager: message %d not found.", msgnum);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user