]> granicus.if.org Git - nethack/commitdiff
Stinking clouds block line of sight
authorPasi Kallinen <paxed@alt.org>
Mon, 31 Jan 2022 17:00:15 +0000 (19:00 +0200)
committerPasi Kallinen <paxed@alt.org>
Mon, 31 Jan 2022 17:00:19 +0000 (19:00 +0200)
... 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>

doc/fixes3-7-0.txt
include/decl.h
include/extern.h
src/decl.c
src/region.c
src/vision.c

index 507945cb763ba70e3419eb0923b85aa0368099c0..98289dcfdd1b58e35a56f720725e7b4e98c10e09 100644 (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
index 3f18f9db6362fdbd9c36bcfc073a8eb4d3007625..a46b0b8a8ec1c8b7cfe96442db03f2b0a65a3976 100644 (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;
index e855fddb1308ff2a75503a9caa0bab8daeabb4df..1285bf5e1aae86f3a7c94c48b7585cbeab9d226a 100644 (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);
index 12bf56252bd6d01babad73e35829defd77dea62f..8859919bcc7f4293b4eba8ae9c5297bc852387f0 100644 (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 */
index fbf5572bb6321df56f41bbeeba882afe281aeb85..bcae7c0d86bdbfce09bc8253cee7ec86998f0956 100644 (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! */
 }
 
index f819ecde684d25c36219a9a4bddb38710bd56756..de93a8ba25e83179ffdb31f950a1fda43a6b5022 100644 (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;
 }