monster missiles vs sinks

Missiles shot or thrown by monsters already stop at sinks; give
a message if they haven't exhausted their range and hero sees.
This commit is contained in:
PatR
2021-02-13 15:16:15 -08:00
parent 5a8c978b1e
commit 8c0e3b2a8d
+30 -24
View File
@@ -1,4 +1,4 @@
/* NetHack 3.7 mthrowu.c $NHDT-Date: 1605315160 2020/11/14 00:52:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.103 $ */ /* NetHack 3.7 mthrowu.c $NHDT-Date: 1613258169 2021/02/13 23:16:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.112 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2016. */ /*-Copyright (c) Pasi Kallinen, 2016. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -444,33 +444,32 @@ ohitmon(
return 0; return 0;
} }
#define MT_FLIGHTCHECK(pre) \ #define MT_FLIGHTCHECK(pre) \
(/* missile hits edge of screen */ \ (/* missile hits edge of screen */ \
!isok(g.bhitpos.x + dx, g.bhitpos.y + dy) \ !isok(g.bhitpos.x + dx, g.bhitpos.y + dy) \
/* missile hits the wall */ \ /* missile hits the wall */ \
|| IS_ROCK(levl[g.bhitpos.x + dx][g.bhitpos.y + dy].typ) \ || IS_ROCK(levl[g.bhitpos.x + dx][g.bhitpos.y + dy].typ) \
/* missile hit closed door */ \ /* missile hit closed door */ \
|| closed_door(g.bhitpos.x + dx, g.bhitpos.y + dy) \ || closed_door(g.bhitpos.x + dx, g.bhitpos.y + dy) \
/* missile might hit iron bars */ \ /* missile might hit iron bars */ \
/* the random chance for small objects hitting bars is */ \ /* the random chance for small objects hitting bars is */ \
/* skipped when reaching them at point blank range */ \ /* skipped when reaching them at point blank range */ \
|| (levl[g.bhitpos.x + dx][g.bhitpos.y + dy].typ == IRONBARS \ || (levl[g.bhitpos.x + dx][g.bhitpos.y + dy].typ == IRONBARS \
&& hits_bars(&singleobj, \ && hits_bars(&singleobj, \
g.bhitpos.x, g.bhitpos.y, \ g.bhitpos.x, g.bhitpos.y, \
g.bhitpos.x + dx, g.bhitpos.y + dy, \ g.bhitpos.x + dx, g.bhitpos.y + dy, \
((pre) ? 0 : !rn2(5)), 0)) \ ((pre) ? 0 : !rn2(5)), 0)) \
/* Thrown objects "sink" */ \ /* Thrown objects "sink" */ \
|| (!(pre) && IS_SINK(levl[g.bhitpos.x][g.bhitpos.y].typ))) || (!(pre) && IS_SINK(levl[g.bhitpos.x][g.bhitpos.y].typ)) \
)
void void
m_throw( m_throw(
struct monst *mon, /* launching monster */ struct monst *mon, /* launching monster */
int x, int x, int y, /* launch point */
int y, int dx, int dy, /* direction */
int dx, int range, /* maximum distance */
int dy, struct obj *obj) /* missile (or stack providing it) */
int range, /* launch point, direction, and range */
struct obj *obj) /* missile (or stack providing it) */
{ {
struct monst *mtmp; struct monst *mtmp;
struct obj *singleobj; struct obj *singleobj;
@@ -492,8 +491,8 @@ m_throw(
* The extract below does nothing. * The extract below does nothing.
*/ */
/* not possibly_unwield, which checks the object's */ /* not possibly_unwield(), which checks the object's location,
/* location, not its existence */ not its existence */
if (MON_WEP(mon) == obj) if (MON_WEP(mon) == obj)
setmnotwielded(mon, obj); setmnotwielded(mon, obj);
obj_extract_self(obj); obj_extract_self(obj);
@@ -658,14 +657,21 @@ m_throw(
break; break;
} }
} }
if (!range /* reached end of path */ if (!range || MT_FLIGHTCHECK(FALSE)) { /* end of path or blocked */
|| MT_FLIGHTCHECK(FALSE)) {
if (singleobj) { /* hits_bars might have destroyed it */ if (singleobj) { /* hits_bars might have destroyed it */
if (g.m_shot.n > 1 /* note: pline(The(missile)) rather than pline_The(missile)
&& (!g.mesg_given || g.bhitpos.x != u.ux || g.bhitpos.y != u.uy) in order to get "Grimtooth" rather than "The Grimtooth" */
&& (cansee(g.bhitpos.x, g.bhitpos.y) if (range && cansee(g.bhitpos.x, g.bhitpos.y)
|| (g.marcher && canseemon(g.marcher)))) && IS_SINK(levl[g.bhitpos.x][g.bhitpos.y].typ))
pline("%s %s onto the sink.", The(mshot_xname(singleobj)),
otense(singleobj, Hallucination ? "plop" : "drop"));
else if (g.m_shot.n > 1
&& (!g.mesg_given
|| g.bhitpos.x != u.ux || g.bhitpos.y != u.uy)
&& (cansee(g.bhitpos.x, g.bhitpos.y)
|| (g.marcher && canseemon(g.marcher))))
pline("%s misses.", The(mshot_xname(singleobj))); pline("%s misses.", The(mshot_xname(singleobj)));
(void) drop_throw(singleobj, 0, g.bhitpos.x, g.bhitpos.y); (void) drop_throw(singleobj, 0, g.bhitpos.x, g.bhitpos.y);
} }
break; break;