Fix: monster hurtling and liquid
A monster hurtling over liquid would drown immediately the instant it touched the first square of water, even if normally it would have kept moving (e.g. hurtling over a short moat). Additionally, its placement on liquid would not take into consideration other monsters, so it could overwrite an existing monster on that spot and lead to an impossible, and/or two monsters occupying a single position. Fix these issues, so that liquid effects like drowning only happen if the monster ends up in liquid at the end of the hurtle, and so that other monsters in the way will stop it early even if they're floating over or swimming on a pool/water/lava square. Also use canspotmon instead of canseemon for the wiztelekinesis debug command.
This commit is contained in:
committed by
Pasi Kallinen
parent
8e91320d2f
commit
1e951db9bc
@@ -297,6 +297,7 @@ typedef struct sortloot_item Loot;
|
||||
* to make an extra call to goodpos()] */
|
||||
#define GP_ALLOW_U 0x100000L /* don't reject hero's location */
|
||||
#define MM_NOEXCLAM 0x200000L /* more sedate "<mon> appears." mesg for ^G */
|
||||
#define MM_IGNORELAVA 0x400000L /* ignore lava when positioning */
|
||||
|
||||
/* flags for make_corpse() and mkcorpstat(); 0..7 are recorded in obj->spe */
|
||||
#define CORPSTAT_NONE 0x00
|
||||
|
||||
@@ -1236,7 +1236,7 @@ wiz_telekinesis(void)
|
||||
|
||||
pline("Pick a monster to hurtle.");
|
||||
do {
|
||||
if (mtmp && !DEADMONSTER(mtmp) && canseemon(mtmp)) {
|
||||
if (mtmp && !DEADMONSTER(mtmp) && canspotmon(mtmp)) {
|
||||
cc.x = mtmp->mx;
|
||||
cc.y = mtmp->my;
|
||||
}
|
||||
@@ -1245,7 +1245,7 @@ wiz_telekinesis(void)
|
||||
if (ans < 0 || cc.x < 0)
|
||||
return ECMD_CANCEL;
|
||||
|
||||
if (((mtmp = m_at(cc.x, cc.y)) != 0) && canseemon(mtmp)) {
|
||||
if (((mtmp = m_at(cc.x, cc.y)) != 0) && canspotmon(mtmp)) {
|
||||
if (!getdir("which direction?"))
|
||||
return ECMD_CANCEL;
|
||||
|
||||
|
||||
@@ -907,21 +907,11 @@ mhurtle_step(genericptr_t arg, int x, int y)
|
||||
struct monst *mon = (struct monst *) arg;
|
||||
struct monst *mtmp;
|
||||
|
||||
if (is_pool(x, y) || is_lava(x, y)) {
|
||||
remove_monster(mon->mx, mon->my);
|
||||
newsym(mon->mx, mon->my);
|
||||
place_monster(mon, x, y);
|
||||
newsym(mon->mx, mon->my);
|
||||
set_apparxy(mon);
|
||||
if (minliquid(mon))
|
||||
return FALSE;
|
||||
return is_waterwall(x, y) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
/* TODO: Treat walls, doors, iron bars, etc. specially
|
||||
* rather than just stopping before.
|
||||
*/
|
||||
if (goodpos(x, y, mon, 0) && m_in_out_region(mon, x, y)) {
|
||||
if (goodpos(x, y, mon, MM_IGNOREWATER | MM_IGNORELAVA)
|
||||
&& m_in_out_region(mon, x, y)) {
|
||||
int res;
|
||||
|
||||
remove_monster(mon->mx, mon->my);
|
||||
@@ -929,6 +919,8 @@ mhurtle_step(genericptr_t arg, int x, int y)
|
||||
place_monster(mon, x, y);
|
||||
newsym(mon->mx, mon->my);
|
||||
set_apparxy(mon);
|
||||
if (is_waterwall(x, y))
|
||||
return FALSE;
|
||||
++g.force_mintrap;
|
||||
res = mintrap(mon);
|
||||
--g.force_mintrap;
|
||||
@@ -1047,6 +1039,7 @@ mhurtle(struct monst *mon, int dx, int dy, int range)
|
||||
cc.x = mon->mx + (dx * range);
|
||||
cc.y = mon->my + (dy * range);
|
||||
(void) walk_path(&mc, &cc, mhurtle_step, (genericptr_t) mon);
|
||||
(void) minliquid(mon);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ goodpos(int x, int y, struct monst* mtmp, long gpflags)
|
||||
{
|
||||
struct permonst *mdat = (struct permonst *) 0;
|
||||
boolean ignorewater = ((gpflags & MM_IGNOREWATER) != 0),
|
||||
ignorelava = ((gpflags & MM_IGNORELAVA) != 0),
|
||||
allow_u = ((gpflags & GP_ALLOW_U) != 0);
|
||||
|
||||
if (!isok(x, y))
|
||||
@@ -94,7 +95,7 @@ goodpos(int x, int y, struct monst* mtmp, long gpflags)
|
||||
&& !grounded(mdat)));
|
||||
} else if (mdat->mlet == S_EEL && rn2(13) && !ignorewater) {
|
||||
return FALSE;
|
||||
} else if (is_lava(x, y)) {
|
||||
} else if (is_lava(x, y) && !ignorelava) {
|
||||
/* 3.6.3: floating eye can levitate over lava but it avoids
|
||||
that due the effect of the heat causing it to dry out */
|
||||
if (mdat == &mons[PM_FLOATING_EYE])
|
||||
@@ -114,7 +115,8 @@ goodpos(int x, int y, struct monst* mtmp, long gpflags)
|
||||
return TRUE;
|
||||
}
|
||||
if (!accessible(x, y)) {
|
||||
if (!(is_pool(x, y) && ignorewater))
|
||||
if (!(is_pool(x, y) && ignorewater)
|
||||
&& !(is_lava(x, y) && ignorelava))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user