Split kicking non-door terrain out of dokick
This commit is contained in:
+216
-208
@@ -23,6 +23,7 @@ static boolean watchman_door_damage(struct monst *,
|
|||||||
static void kick_dumb(coordxy, coordxy);
|
static void kick_dumb(coordxy, coordxy);
|
||||||
static void kick_ouch(coordxy, coordxy, const char *) NONNULLARG3;
|
static void kick_ouch(coordxy, coordxy, const char *) NONNULLARG3;
|
||||||
static void kick_door(coordxy, coordxy, int);
|
static void kick_door(coordxy, coordxy, int);
|
||||||
|
static int kick_nondoor(coordxy, coordxy, int);
|
||||||
static void otransit_msg(struct obj *, boolean, boolean, long);
|
static void otransit_msg(struct obj *, boolean, boolean, long);
|
||||||
static void drop_to(coord *, schar, coordxy, coordxy) NONNULLARG1;
|
static void drop_to(coord *, schar, coordxy, coordxy) NONNULLARG1;
|
||||||
|
|
||||||
@@ -897,6 +898,7 @@ kick_ouch(coordxy x, coordxy y, const char *kickobjnam)
|
|||||||
hurtle(-u.dx, -u.dy, rn1(2, 4), TRUE); /* assume it's heavy */
|
hurtle(-u.dx, -u.dy, rn1(2, 4), TRUE); /* assume it's heavy */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* kick a door */
|
||||||
static void
|
static void
|
||||||
kick_door(coordxy x, coordxy y, int avrg_attrib)
|
kick_door(coordxy x, coordxy y, int avrg_attrib)
|
||||||
{
|
{
|
||||||
@@ -955,215 +957,10 @@ kick_door(coordxy x, coordxy y, int avrg_attrib)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the #kick command */
|
/* kick non-door terrain */
|
||||||
int
|
static int
|
||||||
dokick(void)
|
kick_nondoor(coordxy x, coordxy y, int avrg_attrib)
|
||||||
{
|
{
|
||||||
coordxy x, y;
|
|
||||||
int avrg_attrib;
|
|
||||||
int glyph, oldglyph = -1;
|
|
||||||
register struct monst *mtmp;
|
|
||||||
boolean no_kick = FALSE;
|
|
||||||
|
|
||||||
if (nolimbs(gy.youmonst.data) || slithy(gy.youmonst.data)) {
|
|
||||||
You("have no legs to kick with.");
|
|
||||||
no_kick = TRUE;
|
|
||||||
} else if (verysmall(gy.youmonst.data)) {
|
|
||||||
You("are too small to do any kicking.");
|
|
||||||
no_kick = TRUE;
|
|
||||||
} else if (u.usteed) {
|
|
||||||
if (yn_function("Kick your steed?", ynchars, 'y', TRUE) == 'y') {
|
|
||||||
You("kick %s.", mon_nam(u.usteed));
|
|
||||||
kick_steed();
|
|
||||||
return ECMD_TIME;
|
|
||||||
} else {
|
|
||||||
return ECMD_OK;
|
|
||||||
}
|
|
||||||
} else if (Wounded_legs) {
|
|
||||||
legs_in_no_shape("kicking", FALSE);
|
|
||||||
no_kick = TRUE;
|
|
||||||
} else if (near_capacity() > SLT_ENCUMBER) {
|
|
||||||
Your("load is too heavy to balance yourself for a kick.");
|
|
||||||
no_kick = TRUE;
|
|
||||||
} else if (gy.youmonst.data->mlet == S_LIZARD) {
|
|
||||||
Your("legs cannot kick effectively.");
|
|
||||||
no_kick = TRUE;
|
|
||||||
} else if (u.uinwater && !rn2(2)) {
|
|
||||||
Your("slow motion kick doesn't hit anything.");
|
|
||||||
no_kick = TRUE;
|
|
||||||
} else if (u.utrap) {
|
|
||||||
no_kick = TRUE;
|
|
||||||
switch (u.utraptype) {
|
|
||||||
case TT_PIT:
|
|
||||||
if (!Passes_walls)
|
|
||||||
pline("There's not enough room to kick down here.");
|
|
||||||
else
|
|
||||||
no_kick = FALSE;
|
|
||||||
break;
|
|
||||||
case TT_WEB:
|
|
||||||
case TT_BEARTRAP:
|
|
||||||
You_cant("move your %s!", body_part(LEG));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (sobj_at(BOULDER, u.ux, u.uy) && !Passes_walls) {
|
|
||||||
pline("There's not enough room to kick in here.");
|
|
||||||
no_kick = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (no_kick) {
|
|
||||||
/* ignore direction typed before player notices kick failed */
|
|
||||||
display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
|
|
||||||
return ECMD_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!getdir((char *) 0))
|
|
||||||
return ECMD_CANCEL;
|
|
||||||
if (!u.dx && !u.dy)
|
|
||||||
return ECMD_CANCEL;
|
|
||||||
|
|
||||||
x = u.ux + u.dx;
|
|
||||||
y = u.uy + u.dy;
|
|
||||||
|
|
||||||
/* KMH -- Kicking boots always succeed */
|
|
||||||
if (uarmf && uarmf->otyp == KICKING_BOOTS)
|
|
||||||
avrg_attrib = 99;
|
|
||||||
else
|
|
||||||
avrg_attrib = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 3;
|
|
||||||
|
|
||||||
if (u.uswallow) {
|
|
||||||
switch (rn2(3)) {
|
|
||||||
case 0:
|
|
||||||
You_cant("move your %s!", body_part(LEG));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if (digests(u.ustuck->data)) {
|
|
||||||
pline("%s burps loudly.", Monnam(u.ustuck));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/*FALLTHRU*/
|
|
||||||
default:
|
|
||||||
Your("feeble kick has no effect.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ECMD_TIME;
|
|
||||||
} else if (u.utrap && u.utraptype == TT_PIT) {
|
|
||||||
/* must be Passes_walls */
|
|
||||||
You("kick at the side of the pit.");
|
|
||||||
return ECMD_TIME;
|
|
||||||
}
|
|
||||||
if (Levitation) {
|
|
||||||
coordxy xx, yy;
|
|
||||||
|
|
||||||
xx = u.ux - u.dx;
|
|
||||||
yy = u.uy - u.dy;
|
|
||||||
/* doors can be opened while levitating, so they must be
|
|
||||||
* reachable for bracing purposes
|
|
||||||
* Possible extension: allow bracing against stuff on the side?
|
|
||||||
*/
|
|
||||||
if (isok(xx, yy) && !IS_ROCK(levl[xx][yy].typ)
|
|
||||||
&& !IS_DOOR(levl[xx][yy].typ)
|
|
||||||
&& (!Is_airlevel(&u.uz) || !OBJ_AT(xx, yy))) {
|
|
||||||
You("have nothing to brace yourself against.");
|
|
||||||
return ECMD_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mtmp = isok(x, y) ? m_at(x, y) : 0;
|
|
||||||
/* might not kick monster if it is hidden and becomes revealed,
|
|
||||||
if it is peaceful and player declines to attack, or if the
|
|
||||||
hero passes out due to encumbrance with low hp; gc.context.move
|
|
||||||
will be 1 unless player declines to kick peaceful monster */
|
|
||||||
if (mtmp) {
|
|
||||||
oldglyph = glyph_at(x, y);
|
|
||||||
if (!maybe_kick_monster(mtmp, x, y))
|
|
||||||
return (gc.context.move ? ECMD_TIME : ECMD_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
wake_nearby();
|
|
||||||
u_wipe_engr(2);
|
|
||||||
|
|
||||||
if (!isok(x, y)) {
|
|
||||||
gm.maploc = &gn.nowhere;
|
|
||||||
kick_ouch(x, y, "");
|
|
||||||
return ECMD_TIME;
|
|
||||||
}
|
|
||||||
gm.maploc = &levl[x][y];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The next five tests should stay in their present order:
|
|
||||||
* monsters, pools, objects, non-doors, doors.
|
|
||||||
*
|
|
||||||
* [FIXME: Monsters who are hidden underneath objects or
|
|
||||||
* in pools should lead to hero kicking the concealment
|
|
||||||
* rather than the monster, probably exposing the hidden
|
|
||||||
* monster in the process. And monsters who are hidden on
|
|
||||||
* ceiling shouldn't be kickable (unless hero is flying?);
|
|
||||||
* kicking toward them should just target whatever is on
|
|
||||||
* the floor at that spot.]
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (mtmp) {
|
|
||||||
/* save mtmp->data (for recoil) in case mtmp gets killed */
|
|
||||||
struct permonst *mdat = mtmp->data;
|
|
||||||
|
|
||||||
kick_monster(mtmp, x, y);
|
|
||||||
glyph = glyph_at(x, y);
|
|
||||||
/* see comment in attack_checks() */
|
|
||||||
if (DEADMONSTER(mtmp)) { /* DEADMONSTER() */
|
|
||||||
/* if we mapped an invisible monster and immediately
|
|
||||||
killed it, we don't want to forget what we thought
|
|
||||||
was there before the kick */
|
|
||||||
if (glyph != oldglyph && glyph_is_invisible(glyph))
|
|
||||||
show_glyph(x, y, oldglyph);
|
|
||||||
} else if (!canspotmon(mtmp)
|
|
||||||
/* check <x,y>; monster that evades kick by jumping
|
|
||||||
to an unseen square doesn't leave an I behind */
|
|
||||||
&& mtmp->mx == x && mtmp->my == y
|
|
||||||
&& !glyph_is_invisible(glyph)
|
|
||||||
&& !engulfing_u(mtmp)) {
|
|
||||||
map_invisible(x, y);
|
|
||||||
}
|
|
||||||
/* recoil if floating */
|
|
||||||
if ((Is_airlevel(&u.uz) || Levitation) && gc.context.move) {
|
|
||||||
int range;
|
|
||||||
|
|
||||||
range =
|
|
||||||
((int) gy.youmonst.data->cwt + (weight_cap() + inv_weight()));
|
|
||||||
if (range < 1)
|
|
||||||
range = 1; /* divide by zero avoidance */
|
|
||||||
range = (3 * (int) mdat->cwt) / range;
|
|
||||||
|
|
||||||
if (range < 1)
|
|
||||||
range = 1;
|
|
||||||
hurtle(-u.dx, -u.dy, range, TRUE);
|
|
||||||
}
|
|
||||||
return ECMD_TIME;
|
|
||||||
}
|
|
||||||
(void) unmap_invisible(x, y);
|
|
||||||
if ((is_pool(x, y) || gm.maploc->typ == LAVAWALL) ^ !!u.uinwater) {
|
|
||||||
/* objects normally can't be removed from water by kicking */
|
|
||||||
You("splash some %s around.",
|
|
||||||
hliquid(is_pool(x, y) ? "water" : "lava"));
|
|
||||||
/* pretend the kick is fast enough for lava not to burn */
|
|
||||||
return ECMD_TIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OBJ_AT(x, y) && (!Levitation || Is_airlevel(&u.uz)
|
|
||||||
|| Is_waterlevel(&u.uz) || sobj_at(BOULDER, x, y))) {
|
|
||||||
char kickobjnam[BUFSZ];
|
|
||||||
|
|
||||||
if (kick_object(x, y, kickobjnam)) {
|
|
||||||
if (Is_airlevel(&u.uz))
|
|
||||||
hurtle(-u.dx, -u.dy, 1, TRUE); /* assume it's light */
|
|
||||||
return ECMD_TIME;
|
|
||||||
}
|
|
||||||
kick_ouch(x, y, kickobjnam);
|
|
||||||
return ECMD_TIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IS_DOOR(gm.maploc->typ)) {
|
|
||||||
if (gm.maploc->typ == SDOOR) {
|
if (gm.maploc->typ == SDOOR) {
|
||||||
if (!Levitation && rn2(30) < avrg_attrib) {
|
if (!Levitation && rn2(30) < avrg_attrib) {
|
||||||
cvt_sdoor_to_door(gm.maploc); /* ->typ = DOOR */
|
cvt_sdoor_to_door(gm.maploc); /* ->typ = DOOR */
|
||||||
@@ -1443,7 +1240,218 @@ dokick(void)
|
|||||||
return ECMD_TIME;
|
return ECMD_TIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* the #kick command */
|
||||||
|
int
|
||||||
|
dokick(void)
|
||||||
|
{
|
||||||
|
coordxy x, y;
|
||||||
|
int avrg_attrib;
|
||||||
|
int glyph, oldglyph = -1;
|
||||||
|
register struct monst *mtmp;
|
||||||
|
boolean no_kick = FALSE;
|
||||||
|
|
||||||
|
if (nolimbs(gy.youmonst.data) || slithy(gy.youmonst.data)) {
|
||||||
|
You("have no legs to kick with.");
|
||||||
|
no_kick = TRUE;
|
||||||
|
} else if (verysmall(gy.youmonst.data)) {
|
||||||
|
You("are too small to do any kicking.");
|
||||||
|
no_kick = TRUE;
|
||||||
|
} else if (u.usteed) {
|
||||||
|
if (yn_function("Kick your steed?", ynchars, 'y', TRUE) == 'y') {
|
||||||
|
You("kick %s.", mon_nam(u.usteed));
|
||||||
|
kick_steed();
|
||||||
|
return ECMD_TIME;
|
||||||
|
} else {
|
||||||
|
return ECMD_OK;
|
||||||
|
}
|
||||||
|
} else if (Wounded_legs) {
|
||||||
|
legs_in_no_shape("kicking", FALSE);
|
||||||
|
no_kick = TRUE;
|
||||||
|
} else if (near_capacity() > SLT_ENCUMBER) {
|
||||||
|
Your("load is too heavy to balance yourself for a kick.");
|
||||||
|
no_kick = TRUE;
|
||||||
|
} else if (gy.youmonst.data->mlet == S_LIZARD) {
|
||||||
|
Your("legs cannot kick effectively.");
|
||||||
|
no_kick = TRUE;
|
||||||
|
} else if (u.uinwater && !rn2(2)) {
|
||||||
|
Your("slow motion kick doesn't hit anything.");
|
||||||
|
no_kick = TRUE;
|
||||||
|
} else if (u.utrap) {
|
||||||
|
no_kick = TRUE;
|
||||||
|
switch (u.utraptype) {
|
||||||
|
case TT_PIT:
|
||||||
|
if (!Passes_walls)
|
||||||
|
pline("There's not enough room to kick down here.");
|
||||||
|
else
|
||||||
|
no_kick = FALSE;
|
||||||
|
break;
|
||||||
|
case TT_WEB:
|
||||||
|
case TT_BEARTRAP:
|
||||||
|
You_cant("move your %s!", body_part(LEG));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (sobj_at(BOULDER, u.ux, u.uy) && !Passes_walls) {
|
||||||
|
pline("There's not enough room to kick in here.");
|
||||||
|
no_kick = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no_kick) {
|
||||||
|
/* ignore direction typed before player notices kick failed */
|
||||||
|
display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
|
||||||
|
return ECMD_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!getdir((char *) 0))
|
||||||
|
return ECMD_CANCEL;
|
||||||
|
if (!u.dx && !u.dy)
|
||||||
|
return ECMD_CANCEL;
|
||||||
|
|
||||||
|
x = u.ux + u.dx;
|
||||||
|
y = u.uy + u.dy;
|
||||||
|
|
||||||
|
/* KMH -- Kicking boots always succeed */
|
||||||
|
if (uarmf && uarmf->otyp == KICKING_BOOTS)
|
||||||
|
avrg_attrib = 99;
|
||||||
|
else
|
||||||
|
avrg_attrib = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 3;
|
||||||
|
|
||||||
|
if (u.uswallow) {
|
||||||
|
switch (rn2(3)) {
|
||||||
|
case 0:
|
||||||
|
You_cant("move your %s!", body_part(LEG));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (digests(u.ustuck->data)) {
|
||||||
|
pline("%s burps loudly.", Monnam(u.ustuck));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*FALLTHRU*/
|
||||||
|
default:
|
||||||
|
Your("feeble kick has no effect.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ECMD_TIME;
|
||||||
|
} else if (u.utrap && u.utraptype == TT_PIT) {
|
||||||
|
/* must be Passes_walls */
|
||||||
|
You("kick at the side of the pit.");
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
if (Levitation) {
|
||||||
|
coordxy xx, yy;
|
||||||
|
|
||||||
|
xx = u.ux - u.dx;
|
||||||
|
yy = u.uy - u.dy;
|
||||||
|
/* doors can be opened while levitating, so they must be
|
||||||
|
* reachable for bracing purposes
|
||||||
|
* Possible extension: allow bracing against stuff on the side?
|
||||||
|
*/
|
||||||
|
if (isok(xx, yy) && !IS_ROCK(levl[xx][yy].typ)
|
||||||
|
&& !IS_DOOR(levl[xx][yy].typ)
|
||||||
|
&& (!Is_airlevel(&u.uz) || !OBJ_AT(xx, yy))) {
|
||||||
|
You("have nothing to brace yourself against.");
|
||||||
|
return ECMD_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mtmp = isok(x, y) ? m_at(x, y) : 0;
|
||||||
|
/* might not kick monster if it is hidden and becomes revealed,
|
||||||
|
if it is peaceful and player declines to attack, or if the
|
||||||
|
hero passes out due to encumbrance with low hp; gc.context.move
|
||||||
|
will be 1 unless player declines to kick peaceful monster */
|
||||||
|
if (mtmp) {
|
||||||
|
oldglyph = glyph_at(x, y);
|
||||||
|
if (!maybe_kick_monster(mtmp, x, y))
|
||||||
|
return (gc.context.move ? ECMD_TIME : ECMD_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
wake_nearby();
|
||||||
|
u_wipe_engr(2);
|
||||||
|
|
||||||
|
if (!isok(x, y)) {
|
||||||
|
gm.maploc = &gn.nowhere;
|
||||||
|
kick_ouch(x, y, "");
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
gm.maploc = &levl[x][y];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The next five tests should stay in their present order:
|
||||||
|
* monsters, pools, objects, non-doors, doors.
|
||||||
|
*
|
||||||
|
* [FIXME: Monsters who are hidden underneath objects or
|
||||||
|
* in pools should lead to hero kicking the concealment
|
||||||
|
* rather than the monster, probably exposing the hidden
|
||||||
|
* monster in the process. And monsters who are hidden on
|
||||||
|
* ceiling shouldn't be kickable (unless hero is flying?);
|
||||||
|
* kicking toward them should just target whatever is on
|
||||||
|
* the floor at that spot.]
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (mtmp) {
|
||||||
|
/* save mtmp->data (for recoil) in case mtmp gets killed */
|
||||||
|
struct permonst *mdat = mtmp->data;
|
||||||
|
|
||||||
|
kick_monster(mtmp, x, y);
|
||||||
|
glyph = glyph_at(x, y);
|
||||||
|
/* see comment in attack_checks() */
|
||||||
|
if (DEADMONSTER(mtmp)) { /* DEADMONSTER() */
|
||||||
|
/* if we mapped an invisible monster and immediately
|
||||||
|
killed it, we don't want to forget what we thought
|
||||||
|
was there before the kick */
|
||||||
|
if (glyph != oldglyph && glyph_is_invisible(glyph))
|
||||||
|
show_glyph(x, y, oldglyph);
|
||||||
|
} else if (!canspotmon(mtmp)
|
||||||
|
/* check <x,y>; monster that evades kick by jumping
|
||||||
|
to an unseen square doesn't leave an I behind */
|
||||||
|
&& mtmp->mx == x && mtmp->my == y
|
||||||
|
&& !glyph_is_invisible(glyph)
|
||||||
|
&& !engulfing_u(mtmp)) {
|
||||||
|
map_invisible(x, y);
|
||||||
|
}
|
||||||
|
/* recoil if floating */
|
||||||
|
if ((Is_airlevel(&u.uz) || Levitation) && gc.context.move) {
|
||||||
|
int range;
|
||||||
|
|
||||||
|
range =
|
||||||
|
((int) gy.youmonst.data->cwt + (weight_cap() + inv_weight()));
|
||||||
|
if (range < 1)
|
||||||
|
range = 1; /* divide by zero avoidance */
|
||||||
|
range = (3 * (int) mdat->cwt) / range;
|
||||||
|
|
||||||
|
if (range < 1)
|
||||||
|
range = 1;
|
||||||
|
hurtle(-u.dx, -u.dy, range, TRUE);
|
||||||
|
}
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
(void) unmap_invisible(x, y);
|
||||||
|
if ((is_pool(x, y) || gm.maploc->typ == LAVAWALL) ^ !!u.uinwater) {
|
||||||
|
/* objects normally can't be removed from water by kicking */
|
||||||
|
You("splash some %s around.",
|
||||||
|
hliquid(is_pool(x, y) ? "water" : "lava"));
|
||||||
|
/* pretend the kick is fast enough for lava not to burn */
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OBJ_AT(x, y) && (!Levitation || Is_airlevel(&u.uz)
|
||||||
|
|| Is_waterlevel(&u.uz) || sobj_at(BOULDER, x, y))) {
|
||||||
|
char kickobjnam[BUFSZ];
|
||||||
|
|
||||||
|
if (kick_object(x, y, kickobjnam)) {
|
||||||
|
if (Is_airlevel(&u.uz))
|
||||||
|
hurtle(-u.dx, -u.dy, 1, TRUE); /* assume it's light */
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
kick_ouch(x, y, kickobjnam);
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_DOOR(gm.maploc->typ))
|
||||||
kick_door(x, y, avrg_attrib);
|
kick_door(x, y, avrg_attrib);
|
||||||
|
else
|
||||||
|
return kick_nondoor(x, y, avrg_attrib);
|
||||||
return ECMD_TIME;
|
return ECMD_TIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user