fix for #H9430 and github issue #1207 - gas clouds
Reported yesterday as issue #1207 by elunna and over four years ago in #H9430: monsters in gas clouds that should be shown by Warning aren't. And in some discussion of #H9430 back then: monsters adjacent to the hero while in gas clouds aren't shown on the map, but combat and other interaction describes them as if they were. There have been changes since then--to prevent seeing things on the far side of gas clouds as if there were no clouds in the way--but the basic problems with warning and adjacency weren't addressed. This is a band-aid (tm) that probably makes things livable. Don't allow gas region display to override monsters that are sensed via warning or when the hero is next to them. That part doesn't work correctly if the hero isn't blind and is inside the cloud while the monster is adjacent but outside. I think it will take more than a band-aid to deal with that sensibly. Closes #1207
This commit is contained in:
@@ -1861,6 +1861,11 @@ if an amulet of flying gets stolen while hero is over lava without other
|
||||
poison gas breath from green dragon or iron golem that hit and was reflected
|
||||
left target enveloped in a gas cloud (reflection now takes precedence;
|
||||
somewhat odd though: gas that misses still leaves target enveloped)
|
||||
Warning didn't show nearby monsters who were inside poison gas/steam/smoke
|
||||
regions
|
||||
map didn't show adjacent monsters if they were inside a gas region unless
|
||||
they were seen via telepathy or extended monster detection, but they
|
||||
were described as if visible in messages (combat, for instance)
|
||||
|
||||
|
||||
Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository
|
||||
|
||||
@@ -128,6 +128,7 @@ static void display_monster(coordxy, coordxy,
|
||||
struct monst *, int, boolean) NONNULLPTRS;
|
||||
static int swallow_to_glyph(int, int);
|
||||
static void display_warning(struct monst *) NONNULLARG1;
|
||||
static boolean next_to_gas(struct monst *) NONNULLARG1;
|
||||
|
||||
static int check_pos(coordxy, coordxy, int);
|
||||
static void get_bkglyph_and_framecolor(coordxy x, coordxy y, int *, uint32 *);
|
||||
@@ -650,6 +651,20 @@ warning_of(struct monst *mon)
|
||||
return wl;
|
||||
}
|
||||
|
||||
/* returns True if mon is adjacent and would be seen if vision wasn't
|
||||
blocked by being in a gas cloud (implicit; caller has already checked) */
|
||||
static boolean
|
||||
next_to_gas(struct monst *mon)
|
||||
{
|
||||
int r = (u.xray_range > 1) ? (u.xray_range + 1) : 2;
|
||||
|
||||
if (distu(mon->mx, mon->my) > r * (r - 1))
|
||||
return FALSE;
|
||||
if (!_mon_visible(mon) && !_see_with_infrared(mon))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* map or status window might not be ready for output during level creation
|
||||
or game restoration (something like u.usteed which affects display of
|
||||
the hero and also a status condition might not be set up yet) */
|
||||
@@ -907,14 +922,29 @@ newsym(coordxy x, coordxy y)
|
||||
* Normal region shown only on accessible positions, but
|
||||
* poison clouds and steam clouds also shown above lava,
|
||||
* pools and moats.
|
||||
* However, sensed monsters take precedence over all regions.
|
||||
* However, sensed monsters (via detection or telepathy or
|
||||
* warning) take precedence over all regions.
|
||||
* Adjacent monsters also take precedence if they would be
|
||||
* seen when there's no gas region.
|
||||
*
|
||||
* FIXME:
|
||||
* The adjacency checking here works when the hero is outside
|
||||
* the region and the monster is inside, and when they're both
|
||||
* inside, but not when the hero is inside and monster outside
|
||||
* (because 'reg' will be Null for mon's <x,y>). Checking
|
||||
* whether hero is inside a region for every newsym() seems
|
||||
* excessive. The hero is usually blind when in a gas cloud
|
||||
* so the problem is less noticeable then it might otherwise be.
|
||||
*/
|
||||
if (reg
|
||||
&& (ACCESSIBLE(lev->typ)
|
||||
|| (reg->visible && is_pool_or_lava(x, y)))
|
||||
&& (!mon || worm_tail || !sensemon(mon))) {
|
||||
show_region(reg, x, y);
|
||||
return;
|
||||
if (reg && (ACCESSIBLE(lev->typ)
|
||||
|| (reg->visible && is_pool_or_lava(x, y)))) {
|
||||
if (mon && !worm_tail && (sensemon(mon) || mon_warning(mon)
|
||||
|| next_to_gas(mon))) {
|
||||
; /* skip region; the 'if' is more comphrehensible this way */
|
||||
} else {
|
||||
show_region(reg, x, y);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (u_at(x, y)) {
|
||||
@@ -944,7 +974,7 @@ newsym(coordxy x, coordxy y)
|
||||
display_monster(x, y, mon,
|
||||
see_it ? PHYSICALLY_SEEN : DETECTED,
|
||||
worm_tail);
|
||||
} else if (mon && mon_warning(mon) && !is_worm_tail(mon)) {
|
||||
} else if (mon && mon_warning(mon) && !worm_tail) {
|
||||
display_warning(mon);
|
||||
} else if (glyph_is_invisible(lev->glyph)) {
|
||||
map_invisible(x, y);
|
||||
@@ -963,7 +993,7 @@ newsym(coordxy x, coordxy y)
|
||||
&& ((see_it = (tp_sensemon(mon) || MATCH_WARN_OF_MON(mon)
|
||||
|| (see_with_infrared(mon)
|
||||
&& mon_visible(mon)))) != 0
|
||||
|| Detect_monsters)) {
|
||||
|| (Detect_monsters && !is_worm_tail(mon)))) {
|
||||
/* Seen or sensed monsters are printed every time.
|
||||
This also gets rid of any invisibility glyph. */
|
||||
display_monster(x, y, mon, see_it ? 0 : DETECTED,
|
||||
|
||||
12
src/vision.c
12
src/vision.c
@@ -134,7 +134,10 @@ vision_init(void)
|
||||
/*
|
||||
* does_block()
|
||||
*
|
||||
* Returns true if something at (x,y) blocks sight.
|
||||
* Returns 0 if nothing at (x,y) blocks sight, 1 if anything other than
|
||||
* an opaque region (gas cloud rather than CLOUD terrain) blocks sight,
|
||||
* or 2 if an opaque region potions sight. [At present, the rest of the
|
||||
* code makes no distinction between 1 and 2, just between 0 and non-0.]
|
||||
*/
|
||||
int
|
||||
does_block(int x, int y, struct rm *lev)
|
||||
@@ -158,8 +161,7 @@ does_block(int x, int y, struct rm *lev)
|
||||
#ifdef DEBUG
|
||||
if (gs.seethru != 1) {
|
||||
#endif
|
||||
if (lev->typ == CLOUD || IS_WATERWALL(lev->typ)
|
||||
|| lev->typ == LAVAWALL
|
||||
if (lev->typ == CLOUD || IS_WATERWALL(lev->typ) || lev->typ == LAVAWALL
|
||||
|| (Underwater && is_moat(x, y)))
|
||||
return 1;
|
||||
#ifdef DEBUG
|
||||
@@ -181,7 +183,7 @@ does_block(int x, int y, struct rm *lev)
|
||||
#endif
|
||||
/* Clouds (poisonous or not) block light. */
|
||||
if (visible_region_at(x, y))
|
||||
return 1;
|
||||
return 2;
|
||||
#ifdef DEBUG
|
||||
} /* gs.seethru */
|
||||
#endif
|
||||
@@ -929,7 +931,7 @@ unblock_point(int x, int y)
|
||||
* + If you are a blocked spot, then your right will point to the
|
||||
* right-most blocked spot to your right that is connected to you.
|
||||
* This means that a right-edge (a blocked spot that has an open
|
||||
* spot on its right) will point to itself.
|
||||
* spot on its right) will point to itself.
|
||||
*/
|
||||
static void
|
||||
dig_point(int row, int col)
|
||||
|
||||
Reference in New Issue
Block a user