Most traps now require touching the floor to trigger

It was silly how some clearly mechanical traps didn't consider
flight or levitation when to trigger.  Do those checks in dotrap/mintrap
making hero and monster trap triggering match more closely.
This commit is contained in:
Pasi Kallinen
2022-02-24 18:55:14 +02:00
parent 2777f45bd5
commit 9ae2ec1f98
2 changed files with 64 additions and 19 deletions
+1
View File
@@ -818,6 +818,7 @@ discovering an object on first turn with persistent inventory enabled might
not update inventory info for that item (autopickup a blank scroll not update inventory info for that item (autopickup a blank scroll
or spellbook and read it as first action; it becomes discovered but or spellbook and read it as first action; it becomes discovered but
will still be shown as if undiscovered until next inventory update) will still be shown as if undiscovered until next inventory update)
most traps now require touching the floor to trigger
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
+63 -19
View File
@@ -11,6 +11,8 @@ static boolean keep_saddle_with_steedcorpse(unsigned, struct obj *,
struct obj *); struct obj *);
static boolean mu_maybe_destroy_web(struct monst *, boolean, struct trap *); static boolean mu_maybe_destroy_web(struct monst *, boolean, struct trap *);
static struct obj *t_missile(int, struct trap *); static struct obj *t_missile(int, struct trap *);
static boolean floor_trigger(int);
static boolean check_in_air(struct monst *, unsigned);
static int trapeffect_arrow_trap(struct monst *, struct trap *, unsigned); static int trapeffect_arrow_trap(struct monst *, struct trap *, unsigned);
static int trapeffect_dart_trap(struct monst *, struct trap *, unsigned); static int trapeffect_dart_trap(struct monst *, struct trap *, unsigned);
static int trapeffect_rocktrap(struct monst *, struct trap *, unsigned); static int trapeffect_rocktrap(struct monst *, struct trap *, unsigned);
@@ -930,6 +932,43 @@ reset_utrap(boolean msg)
} }
} }
/* is trap type ttyp triggered by touching the floor? */
static boolean
floor_trigger(int ttyp)
{
switch (ttyp) {
case ARROW_TRAP:
case DART_TRAP:
case ROCKTRAP:
case SQKY_BOARD:
case BEAR_TRAP:
case LANDMINE:
case ROLLING_BOULDER_TRAP:
case SLP_GAS_TRAP:
case RUST_TRAP:
case FIRE_TRAP:
case PIT:
case SPIKED_PIT:
case HOLE:
case TRAPDOOR:
return TRUE;
default:
return FALSE;
}
}
/* return TRUE if monster mtmp is up in the air, considering trap flags */
static boolean
check_in_air(struct monst *mtmp, unsigned trflags)
{
boolean plunged = (trflags & TOOKPLUNGE) != 0;
return (is_floater(mtmp->data)
|| (is_flyer(mtmp->data) && !plunged)
|| (mtmp == &g.youmonst ?
(Levitation || (Flying && !plunged)) : 0));
}
static int static int
trapeffect_arrow_trap( trapeffect_arrow_trap(
struct monst *mtmp, struct monst *mtmp,
@@ -2456,15 +2495,17 @@ dotrap(register struct trap* trap, unsigned int trflags)
a_your[trap->madeby_u], a_your[trap->madeby_u],
trapname(ttype, TRUE)); /* do force "pit" while hallucinating */ trapname(ttype, TRUE)); /* do force "pit" while hallucinating */
/* then proceed to normal trap effect */ /* then proceed to normal trap effect */
} else if (already_seen && !forcetrap) { } else if (!forcetrap) {
if ((Levitation || (Flying && !plunged)) if (floor_trigger(ttype) && check_in_air(&g.youmonst, trflags)) {
&& (is_pit(ttype) || ttype == HOLE || ttype == BEAR_TRAP)) { if (already_seen) {
You("%s over %s %s.", Levitation ? "float" : "fly", You("%s over %s %s.", Levitation ? "float" : "fly",
a_your[trap->madeby_u], (ttype == ARROW_TRAP && !trap->madeby_u)
trapname(ttype, FALSE)); ? "an" : a_your[trap->madeby_u],
trapname(ttype, FALSE));
}
return; return;
} }
if (!Fumbling && !undestroyable_trap(ttype) if (already_seen && !Fumbling && !undestroyable_trap(ttype)
&& ttype != ANTI_MAGIC && !forcebungle && !plunged && ttype != ANTI_MAGIC && !forcebungle && !plunged
&& !conj_pit && !adj_pit && !conj_pit && !adj_pit
&& (!rn2(5) || (is_pit(ttype) && (!rn2(5) || (is_pit(ttype)
@@ -3130,21 +3171,24 @@ mintrap(register struct monst *mtmp, long mintrapflags)
} else { } else {
register int tt = trap->ttyp; register int tt = trap->ttyp;
boolean forcetrap = ((mintrapflags & FORCETRAP) != 0); boolean forcetrap = ((mintrapflags & FORCETRAP) != 0);
boolean inescapable = (forcetrap /* monster has seen such a trap before */
|| ((tt == HOLE || tt == PIT) boolean already_seen = ((mtmp->mtrapseen & (1 << (tt - 1))) != 0
&& Sokoban && !trap->madeby_u)); || (tt == HOLE && !mindless(mptr)));
/* true when called from dotrap, inescapable is not an option */ if (mtmp == u.usteed) {
if (mtmp == u.usteed) /* true when called from dotrap, inescapable is not an option */
inescapable = TRUE; } else if (Sokoban && (is_pit(tt) || is_hole(tt)) && !trap->madeby_u) {
if (!inescapable && ((mtmp->mtrapseen & (1 << (tt - 1))) != 0 /* nothing here, the trap effects will handle messaging */
|| (tt == HOLE && !mindless(mptr)))) { } else if (!forcetrap) {
/* it has been in such a trap - perhaps it escapes */ if (floor_trigger(tt) && check_in_air(mtmp, mintrapflags)) {
if (rn2(4)) return Trap_Effect_Finished;
}
if (already_seen && rn2(4))
return Trap_Effect_Finished; return Trap_Effect_Finished;
} else {
mtmp->mtrapseen |= (1 << (tt - 1));
} }
mtmp->mtrapseen |= (1 << (tt - 1));
/* Monster is aggravated by being trapped by you. /* Monster is aggravated by being trapped by you.
Recognizing who made the trap isn't completely Recognizing who made the trap isn't completely
unreasonable; everybody has their own style. */ unreasonable; everybody has their own style. */