Stinking clouds block line of sight

... you will also get a message when a seen stinking cloud
or the one surrounding the hero dissipates.

Original feature comes from Fourk, but this version (with some
minor changes) comes from xnethack by copperwater <aosdict@gmail.com>
This commit is contained in:
Pasi Kallinen
2022-01-31 19:00:15 +02:00
parent 260e015067
commit 218c0d4a3b
6 changed files with 50 additions and 5 deletions

View File

@@ -762,6 +762,7 @@ when already at level 30 and gaining another level--which doesn't increase
don't stop running when next to a peaceful, unless it blocks the way
mindless monsters shouldn't cringe stepping on squeaky boards
falling down a hole or trapdoor will cause damage proportional to fall height
stinking gas clouds block line-of-sight
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -1113,6 +1113,8 @@ struct instance_globals {
NhRegion **regions;
int n_regions;
int max_regions;
boolean gas_cloud_diss_within;
int gas_cloud_diss_seen;
/* restore.c */
int n_ids_mapped;

View File

@@ -2220,6 +2220,7 @@ extern void split_rects(NhRect *, NhRect *);
/* ## region.c ### */
extern boolean inside_region(NhRegion *, int, int);
extern void clear_regions(void);
extern void run_regions(void);
extern boolean in_out_region(xchar, xchar);

View File

@@ -577,6 +577,8 @@ const struct instance_globals g_init = {
NULL, /* regions */
0, /* n_regions */
0, /* max_regions */
FALSE, /* gas_cloud_diss_within */
0, /* gas_cloud_diss_seen */
/* restore.c */
0, /* n_ids_mapped */

View File

@@ -15,7 +15,6 @@
boolean inside_gas_cloud(genericptr, genericptr);
boolean expire_gas_cloud(genericptr, genericptr);
boolean inside_rect(NhRect *, int, int);
boolean inside_region(NhRegion *, int, int);
NhRegion *create_region(NhRect *, int);
void add_rect_to_reg(NhRegion *, NhRect *);
void add_mon_to_reg(NhRegion *, struct monst *);
@@ -290,13 +289,16 @@ add_region(NhRegion *reg)
/* Check for monsters inside the region */
for (i = reg->bounding_box.lx; i <= reg->bounding_box.hx; i++)
for (j = reg->bounding_box.ly; j <= reg->bounding_box.hy; j++) {
boolean is_inside = inside_region(reg, i, j);
/* Some regions can cross the level boundaries */
if (!isok(i, j))
continue;
if (MON_AT(i, j) && inside_region(reg, i, j))
if (is_inside && MON_AT(i, j))
add_mon_to_reg(reg, g.level.monsters[i][j]);
if (reg->visible) {
/*block_point(i, j);*/
if (is_inside)
block_point(i, j);
if (cansee(i, j))
newsym(i, j);
}
@@ -371,6 +373,10 @@ run_regions(void)
register int i, j, k;
int f_indx;
/* reset some messaging variables */
g.gas_cloud_diss_within = FALSE;
g.gas_cloud_diss_seen = 0;
/* End of life ? */
/* Do it backward because the array will be modified */
for (i = g.n_regions - 1; i >= 0; i--) {
@@ -407,6 +413,13 @@ run_regions(void)
}
}
}
if (g.gas_cloud_diss_within)
pline_The("gas cloud around you dissipates.");
if (g.gas_cloud_diss_seen)
You_see("%s dissipate.",
g.gas_cloud_diss_seen == 1
? "a gas cloud" : "some gas clouds");
}
/*
@@ -952,6 +965,7 @@ expire_gas_cloud(genericptr_t p1, genericptr_t p2 UNUSED)
{
NhRegion *reg;
int damage;
xchar x, y;
reg = (NhRegion *) p1;
damage = reg->arg.a_int;
@@ -964,6 +978,21 @@ expire_gas_cloud(genericptr_t p1, genericptr_t p2 UNUSED)
reg->ttl = 2L; /* Here's the trick : reset ttl */
return FALSE; /* THEN return FALSE, means "still there" */
}
/* The cloud no longer blocks vision. */
for (x = reg->bounding_box.lx; x <= reg->bounding_box.hx; x++) {
for (y = reg->bounding_box.ly; y <= reg->bounding_box.hy; y++) {
if (inside_region(reg, x, y)) {
if (!does_block(x, y, &levl[x][y]))
unblock_point(x, y);
if (x == u.ux && y == u.uy)
g.gas_cloud_diss_within = TRUE;
if (cansee(x, y))
g.gas_cloud_diss_seen++;
}
}
}
return TRUE; /* OK, it's gone, you can free it! */
}

View File

@@ -134,14 +134,14 @@ vision_init(void)
/*
* does_block()
*
* Returns true if the level feature, object, or monster at (x,y) blocks
* sight.
* Returns true if something at (x,y) blocks sight.
*/
int
does_block(int x, int y, struct rm *lev)
{
struct obj *obj;
struct monst *mon;
int i;
/* Features that block . . */
if (IS_ROCK(lev->typ) || lev->typ == TREE
@@ -163,6 +163,16 @@ does_block(int x, int y, struct rm *lev)
&& is_lightblocker_mappear(mon))
return 1;
/* Clouds (poisonous or not) block light. */
for (i = 0; i < g.n_regions; i++) {
/* Ignore regions with ttl == 0 - expire_gas_cloud must unblock its
* points prior to being removed itself. */
if (g.regions[i]->ttl > 0 && g.regions[i]->visible
&& inside_region(g.regions[i], x, y)) {
return 1;
}
}
return 0;
}