*** empty log message ***
This commit is contained in:
618
src/ball.c
Normal file
618
src/ball.c
Normal file
@@ -0,0 +1,618 @@
|
||||
/* SCCS Id: @(#)ball.c 3.3 97/04/23 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
/* Ball & Chain =============================================================*/
|
||||
|
||||
#include "hack.h"
|
||||
|
||||
STATIC_DCL int NDECL(bc_order);
|
||||
STATIC_DCL void NDECL(litter);
|
||||
|
||||
void
|
||||
ballfall()
|
||||
{
|
||||
boolean gets_hit;
|
||||
|
||||
gets_hit = (((uball->ox != u.ux) || (uball->oy != u.uy)) &&
|
||||
((uwep == uball)? FALSE : (boolean)rn2(5)));
|
||||
if (carried(uball)) {
|
||||
pline("Startled, you drop the iron ball.");
|
||||
if (uwep == uball)
|
||||
setuwep((struct obj *)0);
|
||||
if (uswapwep == uball)
|
||||
setuswapwep((struct obj *)0);
|
||||
if (uquiver == uball)
|
||||
setuqwep((struct obj *)0);;
|
||||
if (uwep != uball)
|
||||
freeinv(uball);
|
||||
}
|
||||
if(gets_hit){
|
||||
int dmg = rn1(7,25);
|
||||
pline_The("iron ball falls on your %s.",
|
||||
body_part(HEAD));
|
||||
if (uarmh) {
|
||||
if(is_metallic(uarmh)) {
|
||||
pline("Fortunately, you are wearing a hard helmet.");
|
||||
dmg = 3;
|
||||
} else if (flags.verbose)
|
||||
Your("%s does not protect you.", xname(uarmh));
|
||||
}
|
||||
losehp(dmg, "Crunched in the head by an iron ball",
|
||||
NO_KILLER_PREFIX);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To make this work, we have to mess with the hero's mind. The rules for
|
||||
* ball&chain are:
|
||||
*
|
||||
* 1. If the hero can see them, fine.
|
||||
* 2. If the hero can't see either, it isn't seen.
|
||||
* 3. If either is felt it is seen.
|
||||
* 4. If either is felt and moved, it disappears.
|
||||
*
|
||||
* If the hero can see, then when a move is done, the ball and chain are
|
||||
* first picked up, the positions under them are corrected, then they
|
||||
* are moved after the hero moves. Not too bad.
|
||||
*
|
||||
* If the hero is blind, then she can "feel" the ball and/or chain at any
|
||||
* time. However, when the hero moves, the felt ball and/or chain become
|
||||
* unfelt and whatever was felt "under" the ball&chain appears. Pretty
|
||||
* nifty, but it requires that the ball&chain "remember" what was under
|
||||
* them --- i.e. they pick-up glyphs when they are felt and drop them when
|
||||
* moved (and felt). When swallowed, the ball&chain are pulled completely
|
||||
* off of the dungeon, but are still on the object chain. They are placed
|
||||
* under the hero when she is expelled.
|
||||
*/
|
||||
|
||||
/*
|
||||
* from you.h
|
||||
* int u.bglyph glyph under the ball
|
||||
* int u.cglyph glyph under the chain
|
||||
* int u.bc_felt mask for ball/chain being felt
|
||||
* #define BC_BALL 0x01 bit mask in u.bc_felt for ball
|
||||
* #define BC_CHAIN 0x02 bit mask in u.bc_felt for chain
|
||||
* int u.bc_order ball & chain order
|
||||
*
|
||||
* u.bc_felt is also manipulated in display.c and read.c, the others only
|
||||
* in this file. None of these variables are valid unless the player is
|
||||
* Blind.
|
||||
*/
|
||||
|
||||
/* values for u.bc_order */
|
||||
#define BCPOS_DIFFER 0 /* ball & chain at different positions */
|
||||
#define BCPOS_CHAIN 1 /* chain on top of ball */
|
||||
#define BCPOS_BALL 2 /* ball on top of chain */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Place the ball & chain under the hero. Make sure that the ball & chain
|
||||
* variables are set (actually only needed when blind, but what the heck).
|
||||
* It is assumed that when this is called, the ball and chain are NOT
|
||||
* attached to the object list.
|
||||
*
|
||||
* Should not be called while swallowed.
|
||||
*/
|
||||
void
|
||||
placebc()
|
||||
{
|
||||
if (!uchain || !uball) {
|
||||
impossible("Where are your ball and chain?");
|
||||
return;
|
||||
}
|
||||
|
||||
(void) flooreffects(uchain, u.ux, u.uy, ""); /* chain might rust */
|
||||
|
||||
if (carried(uball)) /* the ball is carried */
|
||||
u.bc_order = BCPOS_DIFFER;
|
||||
else {
|
||||
/* ball might rust -- already checked when carried */
|
||||
(void) flooreffects(uball, u.ux, u.uy, "");
|
||||
place_object(uball, u.ux, u.uy);
|
||||
u.bc_order = BCPOS_CHAIN;
|
||||
}
|
||||
|
||||
place_object(uchain, u.ux, u.uy);
|
||||
|
||||
u.bglyph = u.cglyph = levl[u.ux][u.uy].glyph; /* pick up glyph */
|
||||
|
||||
newsym(u.ux,u.uy);
|
||||
}
|
||||
|
||||
void
|
||||
unplacebc()
|
||||
{
|
||||
if (u.uswallow) return; /* ball&chain not placed while swallowed */
|
||||
|
||||
if (!carried(uball)) {
|
||||
obj_extract_self(uball);
|
||||
if (Blind && (u.bc_felt & BC_BALL)) /* drop glyph */
|
||||
levl[uball->ox][uball->oy].glyph = u.bglyph;
|
||||
|
||||
newsym(uball->ox,uball->oy);
|
||||
}
|
||||
obj_extract_self(uchain);
|
||||
if (Blind && (u.bc_felt & BC_CHAIN)) /* drop glyph */
|
||||
levl[uchain->ox][uchain->oy].glyph = u.cglyph;
|
||||
|
||||
newsym(uchain->ox,uchain->oy);
|
||||
u.bc_felt = 0; /* feel nothing */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the stacking of the hero's ball & chain. This assumes that the
|
||||
* hero is being punished.
|
||||
*/
|
||||
STATIC_OVL int
|
||||
bc_order()
|
||||
{
|
||||
struct obj *obj;
|
||||
|
||||
if (uchain->ox != uball->ox || uchain->oy != uball->oy || carried(uball)
|
||||
|| u.uswallow)
|
||||
return BCPOS_DIFFER;
|
||||
|
||||
for (obj = level.objects[uball->ox][uball->oy]; obj; obj = obj->nexthere) {
|
||||
if (obj == uchain) return BCPOS_CHAIN;
|
||||
if (obj == uball) return BCPOS_BALL;
|
||||
}
|
||||
impossible("bc_order: ball&chain not in same location!");
|
||||
return BCPOS_DIFFER;
|
||||
}
|
||||
|
||||
/*
|
||||
* set_bc()
|
||||
*
|
||||
* The hero is either about to go blind or already blind and just punished.
|
||||
* Set up the ball and chain variables so that the ball and chain are "felt".
|
||||
*/
|
||||
void
|
||||
set_bc(already_blind)
|
||||
int already_blind;
|
||||
{
|
||||
int ball_on_floor = !carried(uball);
|
||||
|
||||
u.bc_order = bc_order(); /* get the order */
|
||||
u.bc_felt = ball_on_floor ? BC_BALL|BC_CHAIN : BC_CHAIN; /* felt */
|
||||
|
||||
if (already_blind || u.uswallow) {
|
||||
u.cglyph = u.bglyph = levl[u.ux][u.uy].glyph;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we can still see, remove the ball&chain and get the glyph that
|
||||
* would be beneath them. Then put the ball&chain back. This is pretty
|
||||
* disgusting, but it will work.
|
||||
*/
|
||||
remove_object(uchain);
|
||||
if (ball_on_floor) remove_object(uball);
|
||||
|
||||
newsym(uchain->ox, uchain->oy);
|
||||
u.cglyph = levl[uchain->ox][uchain->oy].glyph;
|
||||
|
||||
if (u.bc_order == BCPOS_DIFFER) { /* different locations */
|
||||
place_object(uchain, uchain->ox, uchain->oy);
|
||||
newsym(uchain->ox, uchain->oy);
|
||||
if (ball_on_floor) {
|
||||
newsym(uball->ox, uball->oy); /* see under ball */
|
||||
u.bglyph = levl[uball->ox][uball->oy].glyph;
|
||||
place_object(uball, uball->ox, uball->oy);
|
||||
newsym(uball->ox, uball->oy); /* restore ball */
|
||||
}
|
||||
} else {
|
||||
u.bglyph = u.cglyph;
|
||||
if (u.bc_order == BCPOS_CHAIN) {
|
||||
place_object(uball, uball->ox, uball->oy);
|
||||
place_object(uchain, uchain->ox, uchain->oy);
|
||||
} else {
|
||||
place_object(uchain, uchain->ox, uchain->oy);
|
||||
place_object(uball, uball->ox, uball->oy);
|
||||
}
|
||||
newsym(uball->ox, uball->oy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* move_bc()
|
||||
*
|
||||
* Move the ball and chain. This is called twice for every move. The first
|
||||
* time to pick up the ball and chain before the move, the second time to
|
||||
* place the ball and chain after the move. If the ball is carried, this
|
||||
* function should never have BC_BALL as part of its control.
|
||||
*
|
||||
* Should not be called while swallowed.
|
||||
*/
|
||||
void
|
||||
move_bc(before, control, ballx, bally, chainx, chainy)
|
||||
int before, control;
|
||||
xchar ballx, bally, chainx, chainy; /* only matter !before */
|
||||
{
|
||||
if (Blind) {
|
||||
/*
|
||||
* The hero is blind. Time to work hard. The ball and chain that
|
||||
* are attached to the hero are very special. The hero knows that
|
||||
* they are attached, so when they move, the hero knows that they
|
||||
* aren't at the last position remembered. This is complicated
|
||||
* by the fact that the hero can "feel" the surrounding locations
|
||||
* at any time, hence, making one or both of them show up again.
|
||||
* So, we have to keep track of which is felt at any one time and
|
||||
* act accordingly.
|
||||
*/
|
||||
if (!before) {
|
||||
if ((control & BC_CHAIN) && (control & BC_BALL)) {
|
||||
/*
|
||||
* Both ball and chain moved. If felt, drop glyph.
|
||||
*/
|
||||
if (u.bc_felt & BC_BALL)
|
||||
levl[uball->ox][uball->oy].glyph = u.bglyph;
|
||||
if (u.bc_felt & BC_CHAIN)
|
||||
levl[uchain->ox][uchain->oy].glyph = u.cglyph;
|
||||
u.bc_felt = 0;
|
||||
|
||||
/* Pick up glyph at new location. */
|
||||
u.bglyph = levl[ballx][bally].glyph;
|
||||
u.cglyph = levl[chainx][chainy].glyph;
|
||||
|
||||
movobj(uball,ballx,bally);
|
||||
movobj(uchain,chainx,chainy);
|
||||
} else if (control & BC_BALL) {
|
||||
if (u.bc_felt & BC_BALL) {
|
||||
if (u.bc_order == BCPOS_DIFFER) { /* ball by itself */
|
||||
levl[uball->ox][uball->oy].glyph = u.bglyph;
|
||||
} else if (u.bc_order == BCPOS_BALL) {
|
||||
if (u.bc_felt & BC_CHAIN) { /* know chain is there */
|
||||
map_object(uchain, 0);
|
||||
} else {
|
||||
levl[uball->ox][uball->oy].glyph = u.bglyph;
|
||||
}
|
||||
}
|
||||
u.bc_felt &= ~BC_BALL; /* no longer feel the ball */
|
||||
}
|
||||
|
||||
/* Pick up glyph at new position. */
|
||||
u.bglyph = (ballx != chainx || bally != chainy) ?
|
||||
levl[ballx][bally].glyph : u.cglyph;
|
||||
|
||||
movobj(uball,ballx,bally);
|
||||
} else if (control & BC_CHAIN) {
|
||||
if (u.bc_felt & BC_CHAIN) {
|
||||
if (u.bc_order == BCPOS_DIFFER) {
|
||||
levl[uchain->ox][uchain->oy].glyph = u.cglyph;
|
||||
} else if (u.bc_order == BCPOS_CHAIN) {
|
||||
if (u.bc_felt & BC_BALL) {
|
||||
map_object(uball, 0);
|
||||
} else {
|
||||
levl[uchain->ox][uchain->oy].glyph = u.cglyph;
|
||||
}
|
||||
}
|
||||
u.bc_felt &= ~BC_CHAIN;
|
||||
}
|
||||
/* Pick up glyph at new position. */
|
||||
u.cglyph = (ballx != chainx || bally != chainy) ?
|
||||
levl[chainx][chainy].glyph : u.bglyph;
|
||||
|
||||
movobj(uchain,chainx,chainy);
|
||||
}
|
||||
|
||||
u.bc_order = bc_order(); /* reset the order */
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
* The hero is not blind. To make this work correctly, we need to
|
||||
* pick up the ball and chain before the hero moves, then put them
|
||||
* in their new positions after the hero moves.
|
||||
*/
|
||||
if (before) {
|
||||
if (!control) {
|
||||
/*
|
||||
* Neither ball nor chain is moving, so remember which was
|
||||
* on top until !before. Use the variable u.bc_order
|
||||
* since it is only valid when blind.
|
||||
*/
|
||||
u.bc_order = bc_order();
|
||||
}
|
||||
|
||||
remove_object(uchain);
|
||||
newsym(uchain->ox, uchain->oy);
|
||||
if (!carried(uball)) {
|
||||
remove_object(uball);
|
||||
newsym(uball->ox, uball->oy);
|
||||
}
|
||||
} else {
|
||||
int on_floor = !carried(uball);
|
||||
|
||||
if ((control & BC_CHAIN) ||
|
||||
(!control && u.bc_order == BCPOS_CHAIN)) {
|
||||
/* If the chain moved or nothing moved & chain on top. */
|
||||
if (on_floor) place_object(uball, ballx, bally);
|
||||
place_object(uchain, chainx, chainy); /* chain on top */
|
||||
} else {
|
||||
place_object(uchain, chainx, chainy);
|
||||
if (on_floor) place_object(uball, ballx, bally);
|
||||
/* ball on top */
|
||||
}
|
||||
newsym(chainx, chainy);
|
||||
if (on_floor) newsym(ballx, bally);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* return TRUE if ball could be dragged
|
||||
*
|
||||
* Should not be called while swallowed.
|
||||
*/
|
||||
boolean
|
||||
drag_ball(x, y, bc_control, ballx, bally, chainx, chainy, cause_delay)
|
||||
xchar x, y;
|
||||
int *bc_control;
|
||||
xchar *ballx, *bally, *chainx, *chainy;
|
||||
boolean *cause_delay;
|
||||
{
|
||||
struct trap *t = (struct trap *)0;
|
||||
|
||||
*ballx = uball->ox;
|
||||
*bally = uball->oy;
|
||||
*chainx = uchain->ox;
|
||||
*chainy = uchain->oy;
|
||||
*bc_control = 0;
|
||||
*cause_delay = FALSE;
|
||||
|
||||
if (dist2(x, y, uchain->ox, uchain->oy) <= 2) { /* nothing moved */
|
||||
move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (carried(uball) || dist2(x, y, uball->ox, uball->oy) < 3 ||
|
||||
(uball->ox == uchain->ox && uball->oy == uchain->oy)) {
|
||||
/*
|
||||
* Case where the ball doesn't move but the chain can't just move
|
||||
* to the player's position:
|
||||
* @ _
|
||||
* _ moving southwest becomes @_ and not @
|
||||
* 0 0 0
|
||||
*/
|
||||
*bc_control = BC_CHAIN;
|
||||
move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
|
||||
if (dist2(x, y, uball->ox, uball->oy) == 2 &&
|
||||
dist2(x, y, uchain->ox, uchain->oy) == 4) {
|
||||
if (uchain->oy == y)
|
||||
*chainx = uball->ox;
|
||||
else
|
||||
*chainy = uball->oy;
|
||||
} else {
|
||||
*chainx = u.ux;
|
||||
*chainy = u.uy;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (near_capacity() > SLT_ENCUMBER) {
|
||||
You("cannot %sdrag the heavy iron ball.",
|
||||
invent ? "carry all that and also " : "");
|
||||
nomul(0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((is_pool(uchain->ox, uchain->oy) &&
|
||||
/* water not mere continuation of previous water */
|
||||
(levl[uchain->ox][uchain->oy].typ == POOL ||
|
||||
!is_pool(uball->ox, uball->oy) ||
|
||||
levl[uball->ox][uball->oy].typ == POOL))
|
||||
|| ((t = t_at(uchain->ox, uchain->oy)) &&
|
||||
(t->ttyp == PIT ||
|
||||
t->ttyp == SPIKED_PIT ||
|
||||
t->ttyp == HOLE ||
|
||||
t->ttyp == TRAPDOOR)) ) {
|
||||
|
||||
if (Levitation) {
|
||||
You_feel("a tug from the iron ball.");
|
||||
if (t) t->tseen = 1;
|
||||
} else {
|
||||
struct monst *victim;
|
||||
|
||||
You("are jerked back by the iron ball!");
|
||||
if ((victim = m_at(uchain->ox, uchain->oy)) != 0) {
|
||||
int tmp;
|
||||
|
||||
tmp = -2 + Luck + find_mac(victim);
|
||||
tmp += omon_adj(victim, uball, TRUE);
|
||||
if (tmp >= rnd(20))
|
||||
(void) hmon(victim,uball,1);
|
||||
else
|
||||
miss(xname(uball), victim);
|
||||
|
||||
} /* now check again in case mon died */
|
||||
if (!m_at(uchain->ox, uchain->oy)) {
|
||||
u.ux = uchain->ox;
|
||||
u.uy = uchain->oy;
|
||||
newsym(u.ux0, u.uy0);
|
||||
}
|
||||
nomul(0);
|
||||
|
||||
*bc_control = BC_BALL;
|
||||
move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
|
||||
*ballx = uchain->ox;
|
||||
*bally = uchain->oy;
|
||||
move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy);
|
||||
spoteffects(TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
*bc_control = BC_BALL|BC_CHAIN;;
|
||||
|
||||
move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
|
||||
*ballx = uchain->ox;
|
||||
*bally = uchain->oy;
|
||||
*chainx = u.ux;
|
||||
*chainy = u.uy;
|
||||
*cause_delay = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* drop_ball()
|
||||
*
|
||||
* The punished hero drops or throws her iron ball. If the hero is
|
||||
* blind, we must reset the order and glyph. Check for side effects.
|
||||
* This routine expects the ball to be already placed.
|
||||
*
|
||||
* Should not be called while swallowed.
|
||||
*/
|
||||
void
|
||||
drop_ball(x, y)
|
||||
xchar x, y;
|
||||
{
|
||||
if (Blind) {
|
||||
u.bc_order = bc_order(); /* get the order */
|
||||
/* pick up glyph */
|
||||
u.bglyph = (u.bc_order) ? u.cglyph : levl[x][y].glyph;
|
||||
}
|
||||
|
||||
if (x != u.ux || y != u.uy) {
|
||||
struct trap *t;
|
||||
const char *pullmsg = "The ball pulls you out of the %s!";
|
||||
|
||||
if (u.utrap && u.utraptype != TT_INFLOOR) {
|
||||
switch(u.utraptype) {
|
||||
case TT_PIT:
|
||||
pline(pullmsg, "pit");
|
||||
break;
|
||||
case TT_WEB:
|
||||
pline(pullmsg, "web");
|
||||
pline_The("web is destroyed!");
|
||||
deltrap(t_at(u.ux,u.uy));
|
||||
break;
|
||||
case TT_LAVA:
|
||||
pline(pullmsg, "lava");
|
||||
break;
|
||||
case TT_BEARTRAP: {
|
||||
register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
|
||||
pline(pullmsg, "bear trap");
|
||||
set_wounded_legs(side, rn1(1000, 500));
|
||||
#ifdef STEED
|
||||
if (!u.usteed)
|
||||
#endif
|
||||
{
|
||||
Your("%s %s is severely damaged.",
|
||||
(side == LEFT_SIDE) ? "left" : "right",
|
||||
body_part(LEG));
|
||||
losehp(2, "leg damage from being pulled out of a bear trap",
|
||||
KILLED_BY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
u.utrap = 0;
|
||||
fill_pit(u.ux, u.uy);
|
||||
}
|
||||
|
||||
u.ux0 = u.ux;
|
||||
u.uy0 = u.uy;
|
||||
if (!Levitation && !MON_AT(x, y) && !u.utrap &&
|
||||
(is_pool(x, y) ||
|
||||
((t = t_at(x, y)) &&
|
||||
(t->ttyp == PIT || t->ttyp == SPIKED_PIT ||
|
||||
t->ttyp == TRAPDOOR || t->ttyp == HOLE)))) {
|
||||
u.ux = x;
|
||||
u.uy = y;
|
||||
} else {
|
||||
u.ux = x - u.dx;
|
||||
u.uy = y - u.dy;
|
||||
}
|
||||
vision_full_recalc = 1; /* hero has moved, recalculate vision later */
|
||||
|
||||
if (Blind) {
|
||||
/* drop glyph under the chain */
|
||||
if (u.bc_felt & BC_CHAIN)
|
||||
levl[uchain->ox][uchain->oy].glyph = u.cglyph;
|
||||
u.bc_felt = 0; /* feel nothing */
|
||||
/* pick up new glyph */
|
||||
u.cglyph = (u.bc_order) ? u.bglyph : levl[u.ux][u.uy].glyph;
|
||||
}
|
||||
movobj(uchain,u.ux,u.uy); /* has a newsym */
|
||||
if (Blind) {
|
||||
u.bc_order = bc_order();
|
||||
}
|
||||
newsym(u.ux0,u.uy0); /* clean up old position */
|
||||
if (u.ux0 != u.ux || u.uy0 != u.uy) {
|
||||
spoteffects(TRUE);
|
||||
if (In_sokoban(&u.uz))
|
||||
change_luck(-1); /* Sokoban guilt */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STATIC_OVL void
|
||||
litter()
|
||||
{
|
||||
struct obj *otmp = invent, *nextobj;
|
||||
int capacity = weight_cap();
|
||||
|
||||
while (otmp) {
|
||||
nextobj = otmp->nobj;
|
||||
if ((otmp != uball) && (rnd(capacity) <= (int)otmp->owt)) {
|
||||
if (otmp == uwep)
|
||||
setuwep((struct obj *)0);
|
||||
if ((otmp != uwep) && (canletgo(otmp, ""))) {
|
||||
Your("%s you down the stairs.",
|
||||
aobjnam(otmp, "follow"));
|
||||
dropx(otmp);
|
||||
}
|
||||
}
|
||||
otmp = nextobj;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
drag_down()
|
||||
{
|
||||
boolean forward;
|
||||
uchar dragchance = 3;
|
||||
|
||||
/*
|
||||
* Assume that the ball falls forward if:
|
||||
*
|
||||
* a) the character is wielding it, or
|
||||
* b) the character has both hands available to hold it (i.e. is
|
||||
* not wielding any weapon), or
|
||||
* c) (perhaps) it falls forward out of his non-weapon hand
|
||||
*/
|
||||
|
||||
forward = carried(uball) && (uwep == uball || !uwep || !rn2(3));
|
||||
|
||||
if (carried(uball))
|
||||
You("lose your grip on the iron ball.");
|
||||
|
||||
if (forward) {
|
||||
if(rn2(6)) {
|
||||
pline_The("iron ball drags you downstairs!");
|
||||
losehp(rnd(6), "dragged downstairs by an iron ball",
|
||||
NO_KILLER_PREFIX);
|
||||
litter();
|
||||
}
|
||||
} else {
|
||||
if(rn2(2)) {
|
||||
pline_The("iron ball smacks into you!");
|
||||
losehp(rnd(20), "iron ball collision", KILLED_BY_AN);
|
||||
exercise(A_STR, FALSE);
|
||||
dragchance -= 2;
|
||||
}
|
||||
if( (int) dragchance >= rnd(6)) {
|
||||
pline_The("iron ball drags you downstairs!");
|
||||
losehp(rnd(3), "dragged downstairs by an iron ball",
|
||||
NO_KILLER_PREFIX);
|
||||
exercise(A_STR, FALSE);
|
||||
litter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*ball.c*/
|
||||
Reference in New Issue
Block a user