From c7229627137407d3056233f8e85b79830f0b6a57 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Fri, 28 Jan 2022 08:30:08 +0200 Subject: [PATCH] Cancellation explodes magical traps --- doc/fixes37.0 | 1 + include/objclass.h | 1 + include/trap.h | 7 +++++++ src/dig.c | 6 ++---- src/explode.c | 2 +- src/mkmaze.c | 2 +- src/sp_lev.c | 3 +-- src/trap.c | 4 ++-- src/zap.c | 36 ++++++++++++++++++++++++++++++++++++ 9 files changed, 52 insertions(+), 10 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 5bc61aa90..a56a947e1 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1365,6 +1365,7 @@ drinking blessed potion of full healing heals wounded legs, either hero's or steed's (when riding, wounded leg injury applies to steed, not hero) drinking uncursed potion of full healing or blessed potion of extra healing heal hero's wounded legs when not riding; no effect on steed if riding +cancellation explodes most magical traps Platform- and/or Interface-Specific New Features diff --git a/include/objclass.h b/include/objclass.h index 118001752..2eccd95fc 100644 --- a/include/objclass.h +++ b/include/objclass.h @@ -147,6 +147,7 @@ enum objclass_syms { #define BURNING_OIL (MAXOCLASSES + 1) /* Can be used as input to explode. */ #define MON_EXPLODE (MAXOCLASSES + 2) /* Exploding monster (e.g. gas spore) */ +#define TRAP_EXPLODE (MAXOCLASSES + 3) #if 0 /* moved to decl.h so that makedefs.c won't see them */ extern const struct class_sym diff --git a/include/trap.h b/include/trap.h index 59cb01f94..60e4aa9e4 100644 --- a/include/trap.h +++ b/include/trap.h @@ -84,6 +84,13 @@ enum trap_types { #define is_pit(ttyp) ((ttyp) == PIT || (ttyp) == SPIKED_PIT) #define is_hole(ttyp) ((ttyp) == HOLE || (ttyp) == TRAPDOOR) +#define undestroyable_trap(ttyp) ((ttyp) == MAGIC_PORTAL \ + || (ttyp) == VIBRATING_SQUARE) +#define is_magical_trap(ttyp) ((ttyp) == TELEP_TRAP \ + || (ttyp) == LEVEL_TELEP \ + || (ttyp) == MAGIC_TRAP \ + || (ttyp) == ANTI_MAGIC \ + || (ttyp) == POLY_TRAP) /* "transportation" traps */ #define is_xport(ttyp) ((ttyp) >= TELEP_TRAP && (ttyp) <= MAGIC_PORTAL) diff --git a/src/dig.c b/src/dig.c index e6a12c902..454d8cc51 100644 --- a/src/dig.c +++ b/src/dig.c @@ -207,8 +207,7 @@ dig_check(struct monst *madeby, boolean verbose, int x, int y) } else if ((IS_ROCK(levl[x][y].typ) && levl[x][y].typ != SDOOR && (levl[x][y].wall_info & W_NONDIGGABLE) != 0) || (ttmp - && (ttmp->ttyp == MAGIC_PORTAL - || ttmp->ttyp == VIBRATING_SQUARE + && (undestroyable_trap(ttmp->ttyp) || (!Can_dig_down(&u.uz) && !levl[x][y].candig)))) { if (verbose) pline_The("%s here is too hard to %s.", surface(x, y), verb); @@ -790,8 +789,7 @@ dighole(boolean pit_only, boolean by_magic, coord *cc) nohole = (!Can_dig_down(&u.uz) && !lev->candig); old_typ = lev->typ; - if ((ttmp && (ttmp->ttyp == MAGIC_PORTAL - || ttmp->ttyp == VIBRATING_SQUARE || nohole)) + if ((ttmp && (undestroyable_trap(ttmp->ttyp) || nohole)) || (IS_ROCK(old_typ) && old_typ != SDOOR && (lev->wall_info & W_NONDIGGABLE) != 0)) { pline_The("%s %shere is too hard to dig in.", surface(dig_x, dig_y), diff --git a/src/explode.c b/src/explode.c index c10eea024..84da15f95 100644 --- a/src/explode.c +++ b/src/explode.c @@ -314,7 +314,7 @@ explode( tmp_at(DISP_END, 0); /* clear the explosion */ } else { - if (olet == MON_EXPLODE) { + if (olet == MON_EXPLODE || olet == TRAP_EXPLODE) { str = "explosion"; generic = TRUE; } diff --git a/src/mkmaze.c b/src/mkmaze.c index 32ef3bc9b..f4aa66f3d 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -320,7 +320,7 @@ put_lregion_here( It might still fail if there's a dungeon feature here. */ struct trap *t = t_at(x, y); - if (t && t->ttyp != MAGIC_PORTAL && t->ttyp != VIBRATING_SQUARE) + if (t && !undestroyable_trap(t->ttyp)) deltrap(t); if (bad_location(x, y, nlx, nly, nhx, nhy)) return FALSE; diff --git a/src/sp_lev.c b/src/sp_lev.c index 0187679fa..7efbb091a 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -5256,8 +5256,7 @@ ensure_way_out(void) } while (ttmp) { - if ((ttmp->ttyp == MAGIC_PORTAL || ttmp->ttyp == VIBRATING_SQUARE - || is_hole(ttmp->ttyp)) + if ((undestroyable_trap(ttmp->ttyp) || is_hole(ttmp->ttyp)) && !selection_getpoint(ttmp->tx, ttmp->ty, ov)) selection_floodfill(ov, ttmp->tx, ttmp->ty, TRUE); ttmp = ttmp->ntrap; diff --git a/src/trap.c b/src/trap.c index 32ddde590..ba07f096e 100644 --- a/src/trap.c +++ b/src/trap.c @@ -346,7 +346,7 @@ maketrap(int x, int y, int typ) struct rm *lev = &levl[x][y]; if ((ttmp = t_at(x, y)) != 0) { - if (ttmp->ttyp == MAGIC_PORTAL || ttmp->ttyp == VIBRATING_SQUARE) + if (undestroyable_trap(ttmp->ttyp)) return (struct trap *) 0; oldplace = TRUE; if (u.utrap && x == u.ux && y == u.uy @@ -2441,7 +2441,7 @@ dotrap(register struct trap* trap, unsigned int trflags) trapname(ttype, FALSE)); return; } - if (!Fumbling && ttype != MAGIC_PORTAL && ttype != VIBRATING_SQUARE + if (!Fumbling && !undestroyable_trap(ttype) && ttype != ANTI_MAGIC && !forcebungle && !plunged && !conj_pit && !adj_pit && (!rn2(5) || (is_pit(ttype) diff --git a/src/zap.c b/src/zap.c index ae0080418..dcecbe39c 100644 --- a/src/zap.c +++ b/src/zap.c @@ -21,6 +21,7 @@ static void zhitu(int, int, const char *, xchar, xchar); static void revive_egg(struct obj *); static boolean zap_steed(struct obj *); static void skiprange(int, int *, int *); +static void maybe_explode_trap(struct trap *, struct obj *); static int zap_hit(int, int); static void disintegrate_mon(struct monst *, int, const char *); static int adtyp_to_prop(int); @@ -3138,6 +3139,10 @@ zap_updown(struct obj *obj) /* wand or spell */ break; } } + + maybe_explode_trap(ttmp, obj); + /* note: ttmp might be now gone */ + } else if (u.dz < 0) { /* zapping upward */ @@ -3335,6 +3340,34 @@ skiprange(int range, int *skipstart, int *skipend) *skipend = tmp - 1; } +/* maybe explode a trap hit by object otmp's effect; + cancellation beam hitting a magical trap causes an explosion. + might delete the trap. */ +static void +maybe_explode_trap(struct trap *ttmp, struct obj *otmp) +{ + if (!ttmp || !otmp) + return; + if (otmp->otyp == WAN_CANCELLATION || otmp->otyp == SPE_CANCELLATION) { + xchar x = ttmp->tx, y = ttmp->ty; + + if (undestroyable_trap(ttmp->ttyp)) { + shieldeff(x, y); + if (cansee(x, y)) { + ttmp->tseen = 1; + newsym(x, y); + } + } else if (is_magical_trap(ttmp->ttyp)) { + if (!Deaf) + pline("Kaboom!"); + explode(x, y, -WAN_CANCELLATION, + 20+d(3,6), TRAP_EXPLODE, EXPL_MAGICAL); + deltrap(ttmp); + newsym(x, y); + } + } +} + /* * Called for the following distance effects: * when a weapon is thrown (weapon == THROWN_WEAPON) @@ -3468,6 +3501,9 @@ bhit(int ddx, int ddy, int range, /* direction and range */ learnwand(obj); } + if (weapon == ZAPPED_WAND) + maybe_explode_trap(t_at(g.bhitpos.x, g.bhitpos.y), obj); + mtmp = m_at(g.bhitpos.x, g.bhitpos.y); /*