Merge branch 'NetHack-3.7' into twitch-interact

This commit is contained in:
2026-04-15 18:02:20 -07:00
17 changed files with 138 additions and 63 deletions

View File

@@ -592,6 +592,26 @@ moverock_core(coordxy sx, coordxy sy)
}
seetrap(ttmp);
return sobj_at(BOULDER, sx, sy) ? -1 : 0;
case ROLLING_BOULDER_TRAP:
{
int tox = rx;
int toy = ry;
/* the boulder continues until it reaches one of
the trap's launch spots or hits a wall / out-of-bounds */
while (isok(tox + u.dx, toy + u.dy)) {
tox += u.dx;
toy += u.dy;
if (tox == ttmp->launch.x && toy == ttmp->launch.y)
break;
if (tox == ttmp->launch2.x && toy == ttmp->launch2.y)
break;
}
pline("%s away from you!",
Tobjnam(otmp, "suddenly roll"));
feeltrap(ttmp);
launch_obj(BOULDER, sx, sy, tox, toy, ROLL | LAUNCH_KNOWN);
return sobj_at(BOULDER, sx, sy) ? -1 : 0;
}
default:
break; /* boulder not affected by this trap */
}

View File

@@ -2131,8 +2131,10 @@ find_misc(struct monst *mtmp)
if ((t = t_at(xx, yy)) != 0
&& (ignore_boulders || !sobj_at(BOULDER, xx, yy))
&& !onscary(xx, yy, mtmp)) {
/* use trap if it's the correct type */
if (t->ttyp == POLY_TRAP) {
/* use trap if it's the correct type and will
polymorph the monster */
if (t->ttyp == POLY_TRAP &&
!wearing_iron_shoes(mtmp)) {
gt.trapx = xx;
gt.trapy = yy;
gm.m.has_misc = MUSE_POLY_TRAP;

View File

@@ -1176,9 +1176,20 @@ break_armor(void)
if ((otmp = uarmc) != 0
/* mummy wrapping adapts to small and very big sizes */
&& (otmp->otyp != MUMMY_WRAPPING || !WrappingAllowed(uptr))) {
pline_The("clasp on your %s breaks open!", cloak_simple_name(otmp));
(void) Cloak_off();
dropp(otmp);
if (otmp->otyp == MUMMY_WRAPPING) {
/* doesn't have a clasp to break open */
Your("%s tears apart!", cloak_simple_name(otmp));
(void) Cloak_off();
useup(otmp);
} else if (otmp->otyp == ALCHEMY_SMOCK) {
pline_The("knot on your %s is pulled apart!", cloak_simple_name(otmp));
(void) Cloak_off();
dropp(otmp);
} else {
pline_The("clasp on your %s breaks open!", cloak_simple_name(otmp));
(void) Cloak_off();
dropp(otmp);
}
}
if (uarmu) {
Your("shirt rips to shreds!");

View File

@@ -325,9 +325,13 @@ special_throne_effect(int effect) {
case 11:
/* polymorph effect (not blocked by magic resistance, but other things
that protect from polymorphs work) */
pline("This throne was not meant for those such as you!");
You_feel("a change coming over you.");
polyself(POLY_NOFLAGS);
if (is_vampire(gy.youmonst.data)) {
You_feel("unworthy.");
} else {
pline("This throne was not meant for those such as you!");
You_feel("a change coming over you.");
polyself(POLY_NOFLAGS);
}
break;
case 12:
/* acid damage */

View File

@@ -16,7 +16,6 @@ staticfn boolean mu_maybe_destroy_web(struct monst *, boolean, struct trap *);
staticfn struct obj *t_missile(int, struct trap *);
staticfn boolean floor_trigger(int);
staticfn boolean check_in_air(struct monst *, unsigned);
staticfn boolean wearing_iron_shoes(struct monst *);
staticfn int trapeffect_arrow_trap(struct monst *, struct trap *, unsigned);
staticfn int trapeffect_dart_trap(struct monst *, struct trap *, unsigned);
staticfn int trapeffect_rocktrap(struct monst *, struct trap *, unsigned);
@@ -1094,12 +1093,12 @@ check_in_air(struct monst *mtmp, unsigned trflags)
|| ((is_you ? Flying : is_flyer(mtmp->data)) && !plunged));
}
/* return TRUE if mtmp is wearing iron shoes */
staticfn boolean
/* return TRUE if mtmp is wearing shoes made of iron (iron/kicking) */
boolean
wearing_iron_shoes(struct monst *mtmp)
{
struct obj *armf = which_armor(mtmp, W_ARMF);
return armf && armf->otyp == IRON_SHOES;
return armf && objects[armf->otyp].oc_material == IRON;
}
/* is trap ttmp harmless to monster mtmp? */
@@ -2453,10 +2452,6 @@ trapeffect_poly_trap(
struct trap *trap,
unsigned int trflags)
{
static int possible_boots[] = {
ELVEN_BOOTS, KICKING_BOOTS, FUMBLE_BOOTS, LEVITATION_BOOTS,
JUMPING_BOOTS, SPEED_BOOTS, WATER_WALKING_BOOTS };
if (mtmp == &gy.youmonst) {
boolean viasitting = (trflags & VIASITTING) != 0;
int steed_article = ARTICLE_THE;
@@ -2480,7 +2475,8 @@ trapeffect_poly_trap(
if (wearing_iron_shoes(mtmp)) {
deltrap(trap);
pline("%s warps strangely.", Yname2(uarmf));
poly_obj(uarmf, ROLL_FROM(possible_boots));
poly_obj(
uarmf, uarmf->otyp == IRON_SHOES ? KICKING_BOOTS : IRON_SHOES);
update_inventory();
if (uarmf)
prinv(NULL, uarmf, 0);
@@ -2506,7 +2502,8 @@ trapeffect_poly_trap(
impossible("re-equipping iron shoes destroyed them?");
return Trap_Effect_Finished;
}
shoes = poly_obj(shoes, ROLL_FROM(possible_boots));
shoes = poly_obj(
shoes, shoes->otyp == IRON_SHOES ? KICKING_BOOTS : IRON_SHOES);
/* now equip them again */
if (shoes) {
mtmp->misc_worn_check |= W_ARMF;
@@ -2671,9 +2668,13 @@ trapeffect_rolling_boulder_trap(
!Deaf ? "Click! " : "");
if (!launch_obj(BOULDER, trap->launch.x, trap->launch.y,
trap->launch2.x, trap->launch2.y, style)) {
deltrap(trap);
newsym(u.ux, u.uy); /* get rid of trap symbol */
pline("Fortunately for you, no boulder was released.");
/* if this is a known trap, the player may have known there wasn't
a lined up boulder, so use a shorter message to avoid --More--
spam */
if (style & LAUNCH_KNOWN)
pline("No boulder was released.");
else
pline("Fortunately for you, no boulder was released.");
}
} else {
if (!m_in_air(mtmp)) {
@@ -2816,6 +2817,8 @@ immune_to_trap(struct monst *mon, unsigned ttype)
hanging to the ceiling */
if (Sokoban && (is_pit(ttype) || is_hole(ttype)))
return TRAP_NOT_IMMUNE;
if (In_sokoban(&u.uz) && ttype == ROLLING_BOULDER_TRAP)
return TRAP_CLEARLY_IMMUNE; /* not dangerous in Sokoban */
if (is_floater(pm) || is_flyer(pm)
|| (is_clinger(pm) && has_ceiling(&u.uz)))
return TRAP_CLEARLY_IMMUNE;
@@ -3585,7 +3588,7 @@ find_random_launch_coord(struct trap *ttmp, coord *cc)
coordxy dx, dy;
coordxy x, y;
if (!ttmp || !cc)
if (!ttmp || !cc || Sokoban)
return FALSE;
x = ttmp->tx;