E int NDECL(dofire);
E void FDECL(hitfloor, (struct obj *));
E void FDECL(hurtle, (int,int,int,BOOLEAN_P));
+E void FDECL(mhurtle, (struct monst *,int,int,int,BOOLEAN_P));
E void FDECL(throwit, (struct obj *,long,BOOLEAN_P));
E int FDECL(omon_adj, (struct monst *,struct obj *,BOOLEAN_P));
E int FDECL(thitmonst, (struct monst *,struct obj *));
STATIC_DCL boolean FDECL(toss_up,(struct obj *, BOOLEAN_P));
STATIC_DCL boolean FDECL(throwing_weapon, (struct obj *));
STATIC_DCL void FDECL(sho_obj_return_to_u, (struct obj *obj));
+STATIC_DCL boolean FDECL(mhurtle_step, (genericptr_t,int,int));
static NEARDATA const char toss_objs[] =
* Single step for the hero flying through the air from jumping, flying,
* etc. Called from hurtle() and jump() via walk_path(). We expect the
* argument to be a pointer to an integer -- the range -- which is
- * used in the calculation of points off it we hit something.
+ * used in the calculation of points off if we hit something.
*
* Bumping into monsters won't cause damage but will wake them and make
* them angry. Auto-pickup isn't done, since you don't have control over
return TRUE;
}
+STATIC_OVL boolean
+mhurtle_step(arg, x, y)
+ genericptr_t arg;
+ int x, y;
+{
+ struct monst *mon = (struct monst *)arg;
+
+ /* TODO: Treat walls, doors, iron bars, pools, lava, etc. specially
+ * rather than just stopping before.
+ */
+ if (goodpos(x, y, mon) && m_in_out_region(mon, 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);
+ (void) mintrap(mon);
+ }
+}
+
/*
* The player moves through the air for a few squares as a result of
* throwing or kicking something.
(void) walk_path(&uc, &cc, hurtle_step, (genericptr_t)&range);
}
+/* Move a monster through the air for a few squares.
+ */
+void
+mhurtle(mon, dx, dy, range, verbose)
+ struct monst *mon;
+ int dx, dy, range;
+ boolean verbose;
+{
+ coord mc, cc;
+
+ /* At the very least, debilitate the monster */
+ mon->movement = 0;
+ mon->mstun = 1;
+
+ /* Is the monster stuck or too heavy to push?
+ * (very large monsters have too much inertia, even floaters and flyers)
+ */
+ if (mon->data->msize >= MZ_HUGE || mon == u.ustuck || mon->mtrapped)
+ return;
+
+ /* Make sure dx and dy are [-1,0,1] */
+ dx = sgn(dx);
+ dy = sgn(dy);
+ if(!range || (!dx && !dy)) return; /* paranoia */
+
+ /* Send the monster along the path */
+ mc.x = mon->mx;
+ mc.y = mon->my;
+ cc.x = mon->mx + (dx * range);
+ cc.y = mon->my + (dy * range);
+ (void) walk_path(&mc, &cc, mhurtle_step, (genericptr_t)mon);
+ return;
+}
+
STATIC_OVL void
check_shop_obj(obj, x, y, broken)
register struct obj *obj;
boolean get_dmg_bonus = TRUE;
boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE;
boolean silvermsg = FALSE;
+#ifdef STEED
+ boolean jousting = FALSE;
+#endif
boolean valid_weapon_attack = FALSE;
int wtype;
struct obj *monwep;
if (objects[obj->otyp].oc_material == SILVER
&& hates_silver(mdat))
silvermsg = TRUE;
+#ifdef STEED
+ if (u.usteed && !thrown &&
+ weapon_type(obj) == P_LANCE && mon != u.ustuck)
+ jousting = TRUE;
+#endif
if(!thrown && obj == uwep && obj->otyp == BOOMERANG &&
!rnl(3)) {
pline("As you hit %s, %s breaks into splinters.",
}
}
+#ifdef STEED
+ if (jousting) {
+ You("joust %s%s",
+ mon_nam(mon), canseemon(mon) ? exclam(tmp) : ".");
+ mhurtle(mon, u.dx, u.dy, 1, TRUE);
+ hittxt = TRUE;
+ } else
+#endif
+
/* VERY small chance of stunning opponent if unarmed. */
if (tmp > 1 && !thrown && !obj && !uwep && !uarm && !uarms && !Upolyd) {
if (rnd(100) < P_SKILL(P_BARE_HANDED_COMBAT) &&
if (canspotmon(mon))
pline("%s %s from your powerful strike!", Monnam(mon),
makeplural(stagger(mon->data, "stagger")));
- mon->mstun = 1;
+ mhurtle(mon, u.dx, u.dy, 1, TRUE);
hittxt = TRUE;
- if (mon->mcanmove && mon != u.ustuck && !mon->mtrapped) {
- xchar mdx, mdy;
-
- /* see if the monster has a place to move into */
- mdx = mon->mx + u.dx;
- mdy = mon->my + u.dy;
- if (goodpos(mdx, mdy, mon) &&
- m_in_out_region(mon, mdx, mdy)) {
- remove_monster(mon->mx, mon->my);
- newsym(mon->mx, mon->my);
- place_monster(mon, mdx, mdy);
- newsym(mon->mx, mon->my);
- set_apparxy(mon);
- (void) mintrap(mon);
- }
- }
}
}