fix github issue #1017 - webs in/on water

Reported by copperwater, it was possible for a web to be created
at a water or lava location.  It would not be displayed even after
being discovered; showing the terrain superseded showing the trap.
But it functioned normally and could trap the hero.  Webs pull the
victim to the floor so hero would drown or burn up on next move
even if the spot had been reached while floating or flying.

A monster spider couldn't survive at a water or lava location, but
a poly'd hero could.  Creating a web via #monster or wizard mode
wish could result in it affecting some unsuspecting player via bones.

Disallow creation of webs at water, lava, and air or cloud spots.
(They're already disallowed at furniture spots.)

Fixes #1017
This commit is contained in:
PatR
2023-05-01 01:54:35 -07:00
parent 57b54664bd
commit b3580289be
3 changed files with 23 additions and 14 deletions

View File

@@ -1162,6 +1162,8 @@ fake player monsters in endgame had a 1 in 1000 chance to be given a stack
avoid "wall_angle: unknown hwall mode 4" when using #terrain command to
display a spot remembered as a wall but actually a secret door that
has been transformed into an open door while not in sight
it was possible to produce a web at a water or lava location; it would not be
visible but could trap the hero, resulting in drowning or incineration
Fixes to 3.7.0-x General Problems Exposed Via git Repository

View File

@@ -1422,11 +1422,17 @@ doremove(void)
int
dospinweb(void)
{
register struct trap *ttmp = t_at(u.ux, u.uy);
coordxy x = u.ux, y = u.uy;
struct trap *ttmp = t_at(x, y);
/* disallow webs on water, lava, air & cloud */
boolean reject_terrain = is_pool_or_lava(x, y) || IS_AIR(levl[x][y].typ);
if (Levitation || Is_airlevel(&u.uz) || Underwater
|| Is_waterlevel(&u.uz)) {
You("must be on the ground to spin a web.");
/* [at the time this was written, it was not possible to be both a
webmaker and a flyer, but with the advent of amulet of flying that
became a possibility; at present hero can spin a web while flying] */
if (Levitation || reject_terrain) {
You("must be on %s ground to spin a web.",
reject_terrain ? "solid" : "the");
return ECMD_OK;
}
if (u.uswallow) {
@@ -1476,13 +1482,13 @@ dospinweb(void)
case SPIKED_PIT:
You("spin a web, covering up the pit.");
deltrap(ttmp);
bury_objs(u.ux, u.uy);
newsym(u.ux, u.uy);
bury_objs(x, y);
newsym(x, y);
return ECMD_TIME;
case SQKY_BOARD:
pline_The("squeaky board is muffled.");
deltrap(ttmp);
newsym(u.ux, u.uy);
newsym(x, y);
return ECMD_TIME;
case TELEP_TRAP:
case LEVEL_TELEP:
@@ -1498,12 +1504,12 @@ dospinweb(void)
You("web over the %s.",
(ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole");
deltrap(ttmp);
newsym(u.ux, u.uy);
newsym(x, y);
return ECMD_TIME;
case ROLLING_BOULDER_TRAP:
You("spin a web, jamming the trigger.");
deltrap(ttmp);
newsym(u.ux, u.uy);
newsym(x, y);
return ECMD_TIME;
case ARROW_TRAP:
case DART_TRAP:
@@ -1523,19 +1529,19 @@ dospinweb(void)
impossible("Webbing over trap type %d?", ttmp->ttyp);
return ECMD_OK;
}
} else if (On_stairs(u.ux, u.uy)) {
} else if (On_stairs(x, y)) {
/* cop out: don't let them hide the stairs */
Your("web fails to impede access to the %s.",
(levl[u.ux][u.uy].typ == STAIRS) ? "stairs" : "ladder");
(levl[x][y].typ == STAIRS) ? "stairs" : "ladder");
return ECMD_TIME;
}
ttmp = maketrap(u.ux, u.uy, WEB);
ttmp = maketrap(x, y, WEB);
if (ttmp) {
You("spin a web.");
ttmp->madeby_u = 1;
feeltrap(ttmp);
if (*in_rooms(u.ux, u.uy, SHOPBASE))
add_damage(u.ux, u.uy, SHOP_WEB_COST);
if (*in_rooms(x, y, SHOPBASE))
add_damage(x, y, SHOP_WEB_COST);
}
return ECMD_TIME;
}

View File

@@ -438,6 +438,7 @@ maketrap(coordxy x, coordxy y, int typ)
/* old <tx,ty> remain valid */
} else if ((IS_FURNITURE(lev->typ)
&& (!IS_GRAVE(lev->typ) || (typ != PIT && typ != HOLE)))
|| (is_pool_or_lava(x, y) || IS_AIR(lev->typ))
|| (typ == LEVEL_TELEP && single_level_branch(&u.uz))) {
/* no trap on top of furniture (caller usually screens the
location to inhibit this, but wizard mode wishing doesn't)