fix issue #339 - duplicate feature messages
while 'mention_decor' is enabled. When stepping onto different terrain and one or more objects remained on the new spot after autopickup, describe_decor() was issuing its new-terrain message right before look_here()'s similar under-the-objects message. If autopickup grabbed everything or there weren't any objects to begin with, look_here() doesn't issue any dfeature (terrain) message. describe_decor() isn't smart enought to know whether that is going to happen. Give look_here() a new flag argument so that its caller can ask for the dfeature message to be skipped for the case where a similar message has already been given.
This commit is contained in:
@@ -211,6 +211,8 @@ fix crash in water_damage_chain
|
||||
teleport feedback "you materialize at another location" was given too soon
|
||||
'mention_decore' was repeatedly reporting "you are back on bottom" when
|
||||
moving around underwater
|
||||
revised 'mention_decor' was describing furniture or ice right before look-here
|
||||
described the same thing when stepping onto object(s)
|
||||
poison gas clouds located over known but unlit pools were visible as known
|
||||
clouds but steam clouds in that situation were not
|
||||
after the wish parsing change, wishing for "<something of monster>" or for
|
||||
|
||||
@@ -1075,7 +1075,7 @@ E struct obj *FDECL(display_cinventory, (struct obj *));
|
||||
E struct obj *FDECL(display_minventory, (struct monst *, int, char *));
|
||||
E int NDECL(dotypeinv);
|
||||
E const char *FDECL(dfeature_at, (int, int, char *));
|
||||
E int FDECL(look_here, (int, BOOLEAN_P));
|
||||
E int FDECL(look_here, (int, unsigned));
|
||||
E int NDECL(dolook);
|
||||
E boolean FDECL(will_feel_cockatrice, (struct obj *, BOOLEAN_P));
|
||||
E void FDECL(feel_cockatrice, (struct obj *, BOOLEAN_P));
|
||||
|
||||
@@ -134,6 +134,10 @@ enum cost_alteration_types {
|
||||
#define CXN_ARTICLE 8 /* include a/an/the prefix */
|
||||
#define CXN_NOCORPSE 16 /* suppress " corpse" suffix */
|
||||
|
||||
/* flags for look_here() */
|
||||
#define LOOKHERE_PICKED_SOME 1
|
||||
#define LOOKHERE_SKIP_DFEATURE 2
|
||||
|
||||
/* getpos() return values */
|
||||
enum getpos_retval {
|
||||
LOOK_TRADITIONAL = 0, /* '.' -- ask about "more info?" */
|
||||
@@ -255,13 +259,12 @@ struct sortloot_item {
|
||||
};
|
||||
typedef struct sortloot_item Loot;
|
||||
|
||||
#define MATCH_WARN_OF_MON(mon) \
|
||||
(Warn_of_mon && ((g.context.warntype.obj \
|
||||
&& (g.context.warntype.obj & (mon)->data->mflags2)) \
|
||||
|| (g.context.warntype.polyd \
|
||||
&& (g.context.warntype.polyd & (mon)->data->mflags2)) \
|
||||
|| (g.context.warntype.species \
|
||||
&& (g.context.warntype.species == (mon)->data))))
|
||||
#define MATCH_WARN_OF_MON(mon) \
|
||||
(Warn_of_mon \
|
||||
&& ((g.context.warntype.obj & (mon)->data->mflags2) != 0 \
|
||||
|| (g.context.warntype.polyd & (mon)->data->mflags2) != 0 \
|
||||
|| (g.context.warntype.species \
|
||||
&& (g.context.warntype.species == (mon)->data))))
|
||||
|
||||
#include "trap.h"
|
||||
#include "flag.h"
|
||||
|
||||
21
src/invent.c
21
src/invent.c
@@ -3414,9 +3414,9 @@ char *buf;
|
||||
/* look at what is here; if there are many objects (pile_limit or more),
|
||||
don't show them unless obj_cnt is 0 */
|
||||
int
|
||||
look_here(obj_cnt, picked_some)
|
||||
look_here(obj_cnt, lookhere_flags)
|
||||
int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progress */
|
||||
boolean picked_some;
|
||||
unsigned lookhere_flags;
|
||||
{
|
||||
struct obj *otmp;
|
||||
struct trap *trap;
|
||||
@@ -3424,12 +3424,15 @@ boolean picked_some;
|
||||
const char *dfeature = (char *) 0;
|
||||
char fbuf[BUFSZ], fbuf2[BUFSZ];
|
||||
winid tmpwin;
|
||||
boolean skip_objects, felt_cockatrice = FALSE;
|
||||
boolean skip_objects, felt_cockatrice = FALSE,
|
||||
picked_some = (lookhere_flags & LOOKHERE_PICKED_SOME) != 0,
|
||||
/* skip 'dfeature' if caller used describe_decor() to show it */
|
||||
skip_dfeature = (lookhere_flags & LOOKHERE_SKIP_DFEATURE) != 0;
|
||||
|
||||
/* default pile_limit is 5; a value of 0 means "never skip"
|
||||
(and 1 effectively forces "always skip") */
|
||||
skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
|
||||
if (u.uswallow && u.ustuck) {
|
||||
if (u.uswallow) {
|
||||
struct monst *mtmp = u.ustuck;
|
||||
|
||||
/*
|
||||
@@ -3502,12 +3505,12 @@ boolean picked_some;
|
||||
}
|
||||
}
|
||||
|
||||
if (dfeature)
|
||||
if (dfeature && !skip_dfeature)
|
||||
Sprintf(fbuf, "There is %s here.", an(dfeature));
|
||||
|
||||
if (!otmp || is_lava(u.ux, u.uy)
|
||||
|| (is_pool(u.ux, u.uy) && !Underwater)) {
|
||||
if (dfeature)
|
||||
if (dfeature && !skip_dfeature)
|
||||
pline1(fbuf);
|
||||
read_engr_at(u.ux, u.uy); /* Eric Backus */
|
||||
if (!skip_objects && (Blind || !dfeature))
|
||||
@@ -3517,7 +3520,7 @@ boolean picked_some;
|
||||
/* we know there is something here */
|
||||
|
||||
if (skip_objects) {
|
||||
if (dfeature)
|
||||
if (dfeature && !skip_dfeature)
|
||||
pline1(fbuf);
|
||||
read_engr_at(u.ux, u.uy); /* Eric Backus */
|
||||
if (obj_cnt == 1 && otmp->quan == 1L)
|
||||
@@ -3547,7 +3550,7 @@ boolean picked_some;
|
||||
}
|
||||
} else if (!otmp->nexthere) {
|
||||
/* only one object */
|
||||
if (dfeature)
|
||||
if (dfeature && !skip_dfeature)
|
||||
pline1(fbuf);
|
||||
read_engr_at(u.ux, u.uy); /* Eric Backus */
|
||||
You("%s here %s.", verb, doname_with_price(otmp));
|
||||
@@ -3559,7 +3562,7 @@ boolean picked_some;
|
||||
|
||||
display_nhwindow(WIN_MESSAGE, FALSE);
|
||||
tmpwin = create_nhwindow(NHW_MENU);
|
||||
if (dfeature) {
|
||||
if (dfeature && !skip_dfeature) {
|
||||
putstr(tmpwin, 0, fbuf);
|
||||
putstr(tmpwin, 0, "");
|
||||
}
|
||||
|
||||
49
src/pickup.c
49
src/pickup.c
@@ -16,7 +16,7 @@ static boolean FDECL(query_classes, (char *, boolean *, boolean *,
|
||||
const char *, struct obj *,
|
||||
BOOLEAN_P, int *));
|
||||
static boolean FDECL(fatal_corpse_mistake, (struct obj *, BOOLEAN_P));
|
||||
static void NDECL(describe_decor);
|
||||
static boolean NDECL(describe_decor);
|
||||
static void FDECL(check_here, (BOOLEAN_P));
|
||||
static boolean FDECL(n_or_more, (struct obj *));
|
||||
static boolean FDECL(all_but_uchain, (struct obj *));
|
||||
@@ -295,32 +295,31 @@ boolean setup; /* True: deferring, False: catching up */
|
||||
if (setup) {
|
||||
iflags.defer_decor = TRUE;
|
||||
} else {
|
||||
describe_decor();
|
||||
(void) describe_decor();
|
||||
iflags.defer_decor = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle 'mention_decor' (when walking onto a dungeon feature such as
|
||||
stairs or altar, describe it even if it isn't covered up by an object) */
|
||||
static void
|
||||
static boolean
|
||||
describe_decor()
|
||||
{
|
||||
char outbuf[BUFSZ], fbuf[QBUFSZ];
|
||||
boolean doorhere, waterhere, do_norep;
|
||||
boolean doorhere, waterhere, res = TRUE;
|
||||
const char *dfeature;
|
||||
int ltyp;
|
||||
|
||||
if (Fumbling && !iflags.defer_decor) {
|
||||
if ((HFumbling & TIMEOUT) == 1L && !iflags.defer_decor) {
|
||||
/*
|
||||
* In case Fumbling is due to walking on ice.
|
||||
* Work around a message sequencing issue: avoid
|
||||
* |You are back on floor.
|
||||
* |You trip over <object>.
|
||||
* |You trip over <object>. or You flounder.
|
||||
* when the trip is being caused by moving on ice as hero
|
||||
* steps off ice onto non-ice.
|
||||
*/
|
||||
deferred_decor(TRUE);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ltyp = levl[u.ux][u.uy].typ;
|
||||
@@ -328,7 +327,8 @@ describe_decor()
|
||||
ltyp = db_under_typ(levl[u.ux][u.uy].drawbridgemask);
|
||||
dfeature = dfeature_at(u.ux, u.uy, fbuf);
|
||||
|
||||
/* we don't mention "ordinary" doors but do mention broken ones */
|
||||
/* we don't mention "ordinary" doors but do mention broken ones (and
|
||||
closed ones, which will only happen for Passes_walls) */
|
||||
doorhere = dfeature && (!strcmp(dfeature, "open door")
|
||||
|| !strcmp(dfeature, "doorway"));
|
||||
waterhere = dfeature && !strcmp(dfeature, "pool of water");
|
||||
@@ -337,7 +337,7 @@ describe_decor()
|
||||
dfeature = 0;
|
||||
|
||||
if (ltyp == iflags.prev_decor && !IS_FURNITURE(ltyp)) {
|
||||
;
|
||||
res = FALSE;
|
||||
} else if (dfeature) {
|
||||
if (waterhere)
|
||||
dfeature = strcpy(fbuf, waterbody_name(u.ux, u.uy));
|
||||
@@ -351,14 +351,7 @@ describe_decor()
|
||||
Strcpy(fbuf, dfeature);
|
||||
Sprintf(outbuf, "%s.", upstart(fbuf));
|
||||
}
|
||||
do_norep = (ltyp == iflags.prev_decor
|
||||
&& (waterhere
|
||||
|| !strcmp(dfeature, "molten lava")
|
||||
|| !strcmp(dfeature, "ice")));
|
||||
if (!do_norep)
|
||||
pline("%s", outbuf);
|
||||
else
|
||||
Norep("%s", outbuf);
|
||||
pline("%s", outbuf);
|
||||
} else if (!Underwater) {
|
||||
if (IS_POOL(iflags.prev_decor)
|
||||
|| iflags.prev_decor == LAVAPOOL
|
||||
@@ -373,6 +366,7 @@ describe_decor()
|
||||
}
|
||||
}
|
||||
iflags.prev_decor = ltyp;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* look at the objects at our location, unless there are too many of them */
|
||||
@@ -382,9 +376,12 @@ boolean picked_some;
|
||||
{
|
||||
register struct obj *obj;
|
||||
register int ct = 0;
|
||||
unsigned lhflags = picked_some ? LOOKHERE_PICKED_SOME : 0;
|
||||
|
||||
if (flags.mention_decor)
|
||||
describe_decor();
|
||||
if (flags.mention_decor) {
|
||||
if (describe_decor())
|
||||
lhflags |= LOOKHERE_SKIP_DFEATURE;
|
||||
}
|
||||
|
||||
/* count the objects here */
|
||||
for (obj = g.level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) {
|
||||
@@ -397,9 +394,7 @@ boolean picked_some;
|
||||
if (g.context.run)
|
||||
nomul(0);
|
||||
flush_screen(1);
|
||||
(void) look_here(ct, picked_some);
|
||||
|
||||
iflags.prev_decor = STONE;
|
||||
(void) look_here(ct, lhflags);
|
||||
} else {
|
||||
read_engr_at(u.ux, u.uy);
|
||||
}
|
||||
@@ -599,13 +594,13 @@ int what; /* should be a long */
|
||||
|| (is_pool(u.ux, u.uy) && !Underwater)
|
||||
|| is_lava(u.ux, u.uy))) {
|
||||
if (flags.mention_decor)
|
||||
describe_decor();
|
||||
(void) describe_decor();
|
||||
read_engr_at(u.ux, u.uy);
|
||||
return 0;
|
||||
}
|
||||
/* no pickup if levitating & not on air or water level */
|
||||
if (!can_reach_floor(TRUE)) {
|
||||
describe_decor(); /* even when !flags.mention_decor */
|
||||
(void) describe_decor(); /* even when !flags.mention_decor */
|
||||
if ((g.multi && !g.context.run) || (autopickup && !flags.pickup)
|
||||
|| ((t = t_at(u.ux, u.uy)) != 0
|
||||
&& (uteetering_at_seen_pit(t) || uescaped_shaft(t))))
|
||||
@@ -631,8 +626,6 @@ int what; /* should be a long */
|
||||
&& !g.context.nopick)
|
||||
nomul(0);
|
||||
}
|
||||
/* for describe_decor()'s Norep handling */
|
||||
iflags.prev_decor = STONE;
|
||||
|
||||
add_valid_menu_class(0); /* reset */
|
||||
if (!u.uswallow) {
|
||||
@@ -988,7 +981,7 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
|
||||
if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE
|
||||
&& will_feel_cockatrice(curr, FALSE)) {
|
||||
destroy_nhwindow(win); /* stop the menu and revert */
|
||||
(void) look_here(0, FALSE);
|
||||
(void) look_here(0, 0);
|
||||
unsortloot(&sortedolist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -737,18 +737,8 @@ nh_timeout()
|
||||
incr_itimeout(&HFumbling, rnd(20));
|
||||
|
||||
if (iflags.defer_decor) {
|
||||
/*
|
||||
* describe_decor() is attempting to work around a
|
||||
* message sequencing issue: avoid
|
||||
* |You are back on floor.
|
||||
* |You trip over <object>.
|
||||
* if the trip is being caused by moving on ice
|
||||
* that the hero just left. A trip message has
|
||||
* just been given, now give change-in-terrain one.
|
||||
* Operate this way even for non-ice Fumbling so
|
||||
* that describe_decor() doesn't need to know any
|
||||
* details about that.
|
||||
*/
|
||||
/* 'mention_decor' was deferred for message sequencing
|
||||
reasons; catch up now */
|
||||
deferred_decor(FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user