Fix: thrown ball travel did not check for regions

This is an issue that we discovered in TNNT last year when we added a
custom region with effects that trigger upon entry: it was possible to
bypass those effects by entering the region via a thrown iron ball.

This can be demonstrated by creating a poison gas cloud and then
dragging oneself inside the cloud behind a thrown ball: you land in the
cloud and are surrounded by poisonous gas, but are unharmed by it.

This commit fixes the iron ball code to call in_out_region when
appropriate, which handles the side effects of entering and exiting
regions in addition to preventing travel into or out of a hypothetical
region that blocks entry or exit.
This commit is contained in:
copperwater
2026-06-19 09:35:23 -04:00
parent 118899a5f0
commit 7a23470c33
+8 -3
View File
@@ -808,7 +808,8 @@ drag_ball(coordxy x, coordxy y, int *bc_control,
miss(xname(uball), victim);
} /* now check again in case mon died */
if (!m_at(uchain->ox, uchain->oy)) {
if (!m_at(uchain->ox, uchain->oy)
&& in_out_region(uchain->ox, uchain->oy)) {
u.ux = uchain->ox;
u.uy = uchain->oy;
newsym(u.ux0, u.uy0);
@@ -820,6 +821,9 @@ drag_ball(coordxy x, coordxy y, int *bc_control,
*ballx = uchain->ox;
*bally = uchain->oy;
move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy);
/* weirdness: you were dragged back on account of the ball falling
* into the pit, but if you escape the pit, the ball is "on top of"
* the pit and does not hinder your movement further */
spoteffects(TRUE);
return FALSE;
}
@@ -932,10 +936,11 @@ drop_ball(coordxy x, coordxy y)
&& (is_pool(x, y)
|| ((t = t_at(x, y))
&& (is_pit(t->ttyp)
|| is_hole(t->ttyp))))) {
|| is_hole(t->ttyp))))
&& in_out_region(x, y)) {
u.ux = x;
u.uy = y;
} else {
} else if (in_out_region(x - u.dx, y - u.dy)) {
u.ux = x - u.dx;
u.uy = y - u.dy;
}