From: PatR Date: Fri, 17 Apr 2020 21:56:47 +0000 (-0700) Subject: adopt pull request #328 - steam clouds X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=274321d4ecb7bda9ea433d6f023aa1727f8aee03;p=nethack adopt pull request #328 - steam clouds This adds a superset of the code from github pull request #328 to create a short-lived cloud of steam when fire hits a pool or fountain. The original code required C99; this doesn't. It also allowed vapor clouds on the Plane of Water where they don't work sanely becaure regions don't understand air bubble movement and/or vice versa. This inhibits the clouds there [the same ought to be done for scrolls of stinking cloud]. It also left as-is the code that reported when fountains got used up even though conceptually the steam should interfere with being able to see that. This adds a glyph-check hack to augment cansee() so that fountains that boil away entirely are hidden at the time. Regions that block line of slight should be calling block_point() when created and unblock_point() when removed but a naive attempt to introduce that didn't work as expected so I'm giving up on. Fixes #328 --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 681fc31a3..a88a79209 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -268,6 +268,7 @@ wizard mode #wizborn command include more skill information in ^X output when dual-wielding item-using monsters will zap wand of undead turning at corpse-wielding hero when the corpse is harmful +boiling a pool or fountain now creates a temporary cloud of steam Platform- and/or Interface-Specific New Features diff --git a/src/fountain.c b/src/fountain.c index 8d6d3de10..14b5a5a9f 100644 --- a/src/fountain.c +++ b/src/fountain.c @@ -204,15 +204,22 @@ boolean isyou; if (yn("Dry up fountain?") == 'n') return; } + /* FIXME: sight-blocking clouds should use block_point() when + being created and unblock_point() when going away, then this + glyph hackery wouldn't be necessary */ + if (cansee(x, y)) { + int glyph = glyph_at(x, y); + + if (!glyph_is_cmap(glyph) || glyph_to_cmap(glyph) != S_cloud) + pline_The("fountain dries up!"); + } /* replace the fountain with ordinary floor */ levl[x][y].typ = ROOM, levl[x][y].flags = 0; levl[x][y].blessedftn = 0; - if (cansee(x, y)) - pline_The("fountain dries up!"); + g.level.flags.nfountains--; /* The location is seen if the hero/monster is invisible or felt if the hero is blind. */ newsym(x, y); - g.level.flags.nfountains--; if (isyou && in_town(x, y)) (void) angry_guards(FALSE); } diff --git a/src/region.c b/src/region.c index b1fefd649..9dfe9150d 100644 --- a/src/region.c +++ b/src/region.c @@ -310,8 +310,11 @@ NhRegion *reg; continue; if (MON_AT(i, j) && inside_region(reg, i, j)) add_mon_to_reg(reg, g.level.monsters[i][j]); - if (reg->visible && cansee(i, j)) - newsym(i, j); + if (reg->visible) { + /*block_point(i, j);*/ + if (cansee(i, j)) + newsym(i, j); + } } /* Check for player now... */ if (inside_region(reg, u.ux, u.uy)) @@ -345,8 +348,12 @@ NhRegion *reg; if (reg->visible) 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 (isok(x, y) && inside_region(reg, x, y) && cansee(x, y)) - newsym(x, y); + if (isok(x, y) && inside_region(reg, x, y)) { + /*if (!sobj_at(BOULDER, x, y)) + unblock_point(x, y);*/ + if (cansee(x, y)) + newsym(x, y); + } free_region(reg); } @@ -532,7 +539,8 @@ update_player_regions() register int i; for (i = 0; i < g.n_regions; i++) - if (!g.regions[i]->attach_2_u && inside_region(g.regions[i], u.ux, u.uy)) + if (!g.regions[i]->attach_2_u + && inside_region(g.regions[i], u.ux, u.uy)) set_hero_inside(g.regions[i]); else clear_hero_inside(g.regions[i]); @@ -996,23 +1004,25 @@ genericptr_t p2 UNUSED; return TRUE; /* OK, it's gone, you can free it! */ } +/* returns True if p2 is killed by region p1, False otherwise */ boolean inside_gas_cloud(p1, p2) genericptr_t p1; genericptr_t p2; { - NhRegion *reg; - struct monst *mtmp; - int dam; + NhRegion *reg = (NhRegion *) p1; + struct monst *mtmp = (struct monst *) p2; + int dam = reg->arg.a_int; /* * Gas clouds can't be targetted at water locations, but they can * start next to water and spread over it. */ - reg = (NhRegion *) p1; - dam = reg->arg.a_int; - if (p2 == (genericptr_t) 0) { /* This means *YOU* Bozo! */ + if (dam < 1) + return FALSE; /* if no damage then there's nothing to do here... */ + + if (!mtmp) { /* hero is indicated by Null rather than by &youmonst */ if (m_poisongas_ok(&g.youmonst) == M_POISONGAS_OK) return FALSE; if (!Blind) { diff --git a/src/zap.c b/src/zap.c index 52c65cb34..a0d3807c1 100644 --- a/src/zap.c +++ b/src/zap.c @@ -4475,21 +4475,29 @@ short exploding_wand_typ; if (is_ice(x, y)) { melt_ice(x, y, (char *) 0); } else if (is_pool(x, y)) { + boolean on_water_level = Is_waterlevel(&u.uz); const char *msgtxt = (!Deaf) - ? "You hear hissing gas." /* Deaf-aware */ - : (type >= 0) - ? "That seemed remarkably uneventful." - : (const char *) 0; - - if (lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */ - if (see_it) + ? "You hear hissing gas." /* Deaf-aware */ + : (type >= 0) + ? "That seemed remarkably uneventful." + : (char *) 0; + + /* don't create steam clouds on Plane of Water; air bubble + movement and gas regions don't understand each other */ + if (!on_water_level) + create_gas_cloud(x, y, rnd(3), 0); /* radius 1..3, no damg */ + + if (lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP or WATER */ + if (on_water_level) + msgtxt = (see_it || !Deaf) ? "Some water boils." : 0; + else if (see_it) msgtxt = "Some water evaporates."; } else { rangemod -= 3; lev->typ = ROOM, lev->flags = 0; t = maketrap(x, y, PIT); - if (t) - t->tseen = 1; + /*if (t) -- this was before the vapor cloud was added -- + t->tseen = 1;*/ if (see_it) msgtxt = "The water evaporates."; } @@ -4498,6 +4506,7 @@ short exploding_wand_typ; if (lev->typ == ROOM) newsym(x, y); } else if (IS_FOUNTAIN(lev->typ)) { + create_gas_cloud(x, y, rnd(2), 0); /* radius 1..2, no damage */ if (see_it) pline("Steam billows from the fountain."); rangemod -= 1;