buried punishment ball
Prevent burying a ball from ending your punishment. When you bury the ball, internally NetHack Punishment ceases, but a new trap type of TT_BURIEDBALL immediately kicks in (acting similar to TT_INFLOOR in some ways). You can eventually work the ball free (or teleport, etc.), but that will just return you back to normal Punishment.
This commit is contained in:
@@ -241,6 +241,9 @@ E void FDECL(bury_objs, (int,int));
|
||||
E void FDECL(unearth_objs, (int,int));
|
||||
E void FDECL(rot_organic, (genericptr_t, long));
|
||||
E void FDECL(rot_corpse, (genericptr_t, long));
|
||||
E struct obj *FDECL(buried_ball, (coord *));
|
||||
E void NDECL(buried_ball_to_punishment);
|
||||
E void NDECL(buried_ball_to_freedom);
|
||||
#if 0
|
||||
E void FDECL(bury_monst, (struct monst *));
|
||||
E void NDECL(bury_you);
|
||||
|
||||
@@ -250,6 +250,7 @@ struct you {
|
||||
#define TT_WEB 2
|
||||
#define TT_LAVA 3
|
||||
#define TT_INFLOOR 4
|
||||
#define TT_BURIEDBALL 5
|
||||
char urooms[5]; /* rooms (roomno + 3) occupied now */
|
||||
char urooms0[5]; /* ditto, for previous position */
|
||||
char uentered[5]; /* rooms (roomno + 3) entered this turn */
|
||||
|
||||
11
src/apply.c
11
src/apply.c
@@ -817,6 +817,10 @@ struct obj **optr;
|
||||
unpunish();
|
||||
res = 1;
|
||||
}
|
||||
else if (u.utrap && u.utraptype == TT_BURIEDBALL) {
|
||||
buried_ball_to_freedom();
|
||||
res = 1;
|
||||
}
|
||||
res += openit();
|
||||
switch (res) {
|
||||
case 0: pline(nothing_happens); break;
|
||||
@@ -1315,9 +1319,12 @@ int magic; /* 0=Physical, otherwise skill level */
|
||||
You("pull yourself above the lava!");
|
||||
u.utrap = 0;
|
||||
return 1;
|
||||
case TT_BURIEDBALL:
|
||||
case TT_INFLOOR:
|
||||
You("strain your %s, but you're still stuck in the floor.",
|
||||
makeplural(body_part(LEG)));
|
||||
You("strain your %s, but you're still %s.",
|
||||
makeplural(body_part(LEG)),
|
||||
(u.utraptype == TT_INFLOOR) ? "stuck in the floor" :
|
||||
"attached to the buried ball");
|
||||
set_wounded_legs(LEFT_SIDE, rn1(10, 11));
|
||||
set_wounded_legs(RIGHT_SIDE, rn1(10, 11));
|
||||
return 1;
|
||||
|
||||
@@ -653,7 +653,7 @@ xchar x, y;
|
||||
struct trap *t;
|
||||
const char *pullmsg = "The ball pulls you out of the %s!";
|
||||
|
||||
if (u.utrap && u.utraptype != TT_INFLOOR) {
|
||||
if (u.utrap && u.utraptype != TT_INFLOOR && u.utraptype != TT_BURIEDBALL) {
|
||||
switch(u.utraptype) {
|
||||
case TT_PIT:
|
||||
pline(pullmsg, "pit");
|
||||
|
||||
@@ -1039,6 +1039,7 @@ int final; /* 0 => still in progress; 1 => over, survived; 2 => dead */
|
||||
if (Lifesaved)
|
||||
enl_msg("Your life ", "will be", "would have been", " saved");
|
||||
if (u.twoweap) you_are("wielding two weapons at once");
|
||||
if (u.utraptype == TT_BURIEDBALL) you_are("fastened to a buried ball");
|
||||
|
||||
/*** Miscellany ***/
|
||||
if (Luck) {
|
||||
|
||||
113
src/dig.c
113
src/dig.c
@@ -492,6 +492,9 @@ int ttyp;
|
||||
boolean at_u = (x == u.ux) && (y == u.uy);
|
||||
boolean wont_fall = Levitation || Flying;
|
||||
|
||||
if (u.utrap && u.utraptype == TT_BURIEDBALL)
|
||||
buried_ball_to_punishment();
|
||||
|
||||
/* these furniture checks were in dighole(), but wand
|
||||
breaking bypasses that routine and calls us directly */
|
||||
if (IS_FOUNTAIN(lev->typ)) {
|
||||
@@ -1277,6 +1280,84 @@ zap_dig()
|
||||
return;
|
||||
}
|
||||
|
||||
struct obj *
|
||||
buried_ball(cc)
|
||||
coord *cc;
|
||||
{
|
||||
xchar check_x, check_y;
|
||||
struct obj *otmp, *otmp2;
|
||||
if (u.utraptype == TT_BURIEDBALL)
|
||||
for (otmp = level.buriedobjlist; otmp; otmp = otmp2) {
|
||||
otmp2 = otmp->nobj;
|
||||
if (otmp->otyp != HEAVY_IRON_BALL) continue;
|
||||
/* try the exact location first */
|
||||
if (otmp->ox == cc->x && otmp->oy == cc->y)
|
||||
return otmp;
|
||||
/* Now try the vicinity */
|
||||
/*
|
||||
* (x-2,y-2) (x+2,y-2)
|
||||
* (x,y)
|
||||
* (x-2,y+2) (x+2,y+2)
|
||||
*/
|
||||
for (check_x = cc->x-2; check_x <= cc->x+2; ++check_x)
|
||||
for (check_y = cc->y-2; check_y <= cc->y+2; ++check_y) {
|
||||
if (check_x == cc->x && check_y == cc->y) continue;
|
||||
if (isok(check_x, check_y) &&
|
||||
(otmp->ox == check_x && otmp->oy == check_y)) {
|
||||
cc->x = check_x;
|
||||
cc->y = check_y;
|
||||
return otmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (struct obj *)0;
|
||||
}
|
||||
|
||||
void
|
||||
buried_ball_to_punishment()
|
||||
{
|
||||
coord cc;
|
||||
struct obj *ball;
|
||||
cc.x = u.ux; cc.y = u.uy;
|
||||
ball = buried_ball(&cc);
|
||||
if (ball) {
|
||||
obj_extract_self(ball);
|
||||
#if 0
|
||||
/* rusting buried metallic objects is not implemented yet */
|
||||
if (ball->timed)
|
||||
(void) stop_timer(RUST_METAL, (genericptr_t)ball);
|
||||
#endif
|
||||
punish(ball); /* use ball as flag for unearthed buried ball */
|
||||
u.utrap = 0;
|
||||
u.utraptype = 0;
|
||||
del_engr_at(cc.x, cc.y);
|
||||
newsym(cc.x, cc.y);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
buried_ball_to_freedom()
|
||||
{
|
||||
coord cc;
|
||||
struct obj *ball;
|
||||
cc.x = u.ux; cc.y = u.uy;
|
||||
ball = buried_ball(&cc);
|
||||
if (ball) {
|
||||
obj_extract_self(ball);
|
||||
#if 0
|
||||
/* rusting buried metallic objects is not implemented yet */
|
||||
if (ball->timed)
|
||||
(void) stop_timer(RUST_METAL, (genericptr_t)ball);
|
||||
#endif
|
||||
place_object(ball, cc.x, cc.y);
|
||||
stackobj(ball);
|
||||
u.utrap = 0;
|
||||
u.utraptype = 0;
|
||||
del_engr_at(cc.x, cc.y);
|
||||
newsym(cc.x, cc.y);
|
||||
}
|
||||
}
|
||||
|
||||
/* move objects from fobj/nexthere lists to buriedobjlist, keeping position */
|
||||
/* information */
|
||||
struct obj *
|
||||
@@ -1289,8 +1370,12 @@ bury_an_obj(otmp)
|
||||
#ifdef DEBUG
|
||||
pline("bury_an_obj: %s", xname(otmp));
|
||||
#endif
|
||||
if (otmp == uball)
|
||||
if (otmp == uball) {
|
||||
unpunish();
|
||||
u.utrap = rn1(50,20);
|
||||
u.utraptype = TT_BURIEDBALL;
|
||||
pline_The("iron ball gets buried!");
|
||||
}
|
||||
/* after unpunish(), or might get deallocated chain */
|
||||
otmp2 = otmp->nexthere;
|
||||
/*
|
||||
@@ -1329,6 +1414,13 @@ bury_an_obj(otmp)
|
||||
(void) start_timer((under_ice ? 0L : 250L) + (long)rnd(250),
|
||||
TIMER_OBJECT, ROT_ORGANIC, (genericptr_t)otmp);
|
||||
}
|
||||
#if 0
|
||||
/* rusting of buried metal not yet implemented */
|
||||
else if (is_rustprone(otmp)) {
|
||||
(void) start_timer((long)rnd(otmp->otyp == HEAVY_IRON_BALL ? 1500 : 250),
|
||||
TIMER_OBJECT, RUST_METAL, (genericptr_t)otmp);
|
||||
}
|
||||
#endif
|
||||
add_to_buried(otmp);
|
||||
return(otmp2);
|
||||
}
|
||||
@@ -1356,19 +1448,26 @@ void
|
||||
unearth_objs(x, y)
|
||||
int x, y;
|
||||
{
|
||||
struct obj *otmp, *otmp2;
|
||||
struct obj *otmp, *otmp2, *bball;
|
||||
coord cc;
|
||||
|
||||
#ifdef DEBUG
|
||||
pline("unearth_objs: at %d, %d", x, y);
|
||||
#endif
|
||||
cc.x = x; cc.y = y;
|
||||
bball = buried_ball(&cc);
|
||||
for (otmp = level.buriedobjlist; otmp; otmp = otmp2) {
|
||||
otmp2 = otmp->nobj;
|
||||
if (otmp->ox == x && otmp->oy == y) {
|
||||
obj_extract_self(otmp);
|
||||
if (otmp->timed)
|
||||
(void) stop_timer(ROT_ORGANIC, (genericptr_t)otmp);
|
||||
place_object(otmp, x, y);
|
||||
stackobj(otmp);
|
||||
if (bball && otmp == bball && u.utraptype == TT_BURIEDBALL)
|
||||
buried_ball_to_punishment();
|
||||
else {
|
||||
obj_extract_self(otmp);
|
||||
if (otmp->timed)
|
||||
(void) stop_timer(ROT_ORGANIC, (genericptr_t)otmp);
|
||||
place_object(otmp, x, y);
|
||||
stackobj(otmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
del_engr_at(x, y);
|
||||
|
||||
@@ -1243,13 +1243,17 @@ boolean noisy;
|
||||
"rear hooves" which sounds odd */
|
||||
err++;
|
||||
} else if (u.utrap && (u.utraptype == TT_BEARTRAP ||
|
||||
u.utraptype == TT_INFLOOR)) {
|
||||
u.utraptype == TT_INFLOOR ||
|
||||
u.utraptype == TT_BURIEDBALL)) {
|
||||
if (u.utraptype == TT_BEARTRAP) {
|
||||
if (noisy) Your("%s is trapped!", body_part(FOOT));
|
||||
} else {
|
||||
} else if (u.utraptype == TT_INFLOOR) {
|
||||
if (noisy) Your("%s are stuck in the %s!",
|
||||
makeplural(body_part(FOOT)),
|
||||
surface(u.ux, u.uy));
|
||||
} else { /*TT_BURIEDBALL*/
|
||||
if (noisy) Your("%s is attached to the buried ball!",
|
||||
body_part(LEG));
|
||||
}
|
||||
err++;
|
||||
} else
|
||||
|
||||
@@ -598,7 +598,8 @@ hurtle(dx, dy, range, verbose)
|
||||
} else if (u.utrap) {
|
||||
You("are anchored by the %s.",
|
||||
u.utraptype == TT_WEB ? "web" : u.utraptype == TT_LAVA ? "lava" :
|
||||
u.utraptype == TT_INFLOOR ? surface(u.ux,u.uy) : "trap");
|
||||
u.utraptype == TT_INFLOOR ? surface(u.ux,u.uy) :
|
||||
u.utraptype == TT_BURIEDBALL ? "buried ball" : "trap");
|
||||
nomul(0);
|
||||
return;
|
||||
}
|
||||
|
||||
19
src/hack.c
19
src/hack.c
@@ -1178,19 +1178,24 @@ domove()
|
||||
#endif
|
||||
You("disentangle yourself.");
|
||||
}
|
||||
} else if (u.utraptype == TT_INFLOOR) {
|
||||
} else if (u.utraptype == TT_INFLOOR ||
|
||||
u.utraptype == TT_BURIEDBALL) {
|
||||
if(--u.utrap) {
|
||||
if(flags.verbose) {
|
||||
predicament = "stuck in the";
|
||||
predicament = (u.utraptype == TT_INFLOOR) ?
|
||||
"stuck in the" : "attached to the";
|
||||
#ifdef STEED
|
||||
if (u.usteed)
|
||||
Norep("%s is %s %s.",
|
||||
upstart(y_monnam(u.usteed)),
|
||||
predicament, surface(u.ux, u.uy));
|
||||
predicament,
|
||||
(u.utraptype == TT_INFLOOR) ?
|
||||
surface(u.ux, u.uy) : "buried ball");
|
||||
else
|
||||
#endif
|
||||
Norep("You are %s %s.", predicament,
|
||||
surface(u.ux, u.uy));
|
||||
(u.utraptype == TT_INFLOOR) ?
|
||||
surface(u.ux, u.uy) : "buried ball");
|
||||
}
|
||||
} else {
|
||||
#ifdef STEED
|
||||
@@ -1199,7 +1204,11 @@ domove()
|
||||
upstart(y_monnam(u.usteed)));
|
||||
else
|
||||
#endif
|
||||
You("finally wiggle free.");
|
||||
You("finally wiggle %s.",
|
||||
u.utraptype == TT_INFLOOR ?
|
||||
"free" : "the ball free");
|
||||
if (u.utraptype == TT_BURIEDBALL)
|
||||
buried_ball_to_punishment();
|
||||
}
|
||||
} else {
|
||||
if(flags.verbose) {
|
||||
|
||||
@@ -524,9 +524,15 @@ int mntmp;
|
||||
(is_pool(u.ux,u.uy) || is_lava(u.ux,u.uy))) ||
|
||||
(Underwater && !Swimming))
|
||||
spoteffects(TRUE);
|
||||
if (Passes_walls && u.utrap && u.utraptype == TT_INFLOOR) {
|
||||
if (Passes_walls && u.utrap &&
|
||||
(u.utraptype == TT_INFLOOR || u.utraptype == TT_BURIEDBALL)) {
|
||||
u.utrap = 0;
|
||||
pline_The("rock seems to no longer trap you.");
|
||||
if (u.utraptype == TT_INFLOOR)
|
||||
pline_The("rock seems to no longer trap you.");
|
||||
else {
|
||||
pline_The("buried ball is no longer bound to you.");
|
||||
buried_ball_to_freedom();
|
||||
}
|
||||
} else if (likes_lava(youmonst.data) && u.utrap && u.utraptype == TT_LAVA) {
|
||||
u.utrap = 0;
|
||||
pline_The("lava now feels soothing.");
|
||||
@@ -535,6 +541,9 @@ int mntmp;
|
||||
if (Punished) {
|
||||
You("slip out of the iron chain.");
|
||||
unpunish();
|
||||
} else if (u.utrap && u.utraptype == TT_BURIEDBALL) {
|
||||
You("slip free of the buried ball and chain.");
|
||||
buried_ball_to_freedom();
|
||||
}
|
||||
}
|
||||
if (u.utrap && (u.utraptype == TT_WEB || u.utraptype == TT_BEARTRAP) &&
|
||||
@@ -771,6 +780,11 @@ int
|
||||
doremove()
|
||||
{
|
||||
if (!Punished) {
|
||||
if (u.utrap && u.utraptype == TT_BURIEDBALL) {
|
||||
pline_The("ball and chain are buried firmly in the %s.",
|
||||
surface(u.ux, u.uy));
|
||||
return(0);
|
||||
}
|
||||
You("are not chained to anything!");
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -174,7 +174,8 @@ in_trouble()
|
||||
/*
|
||||
* minor troubles
|
||||
*/
|
||||
if(Punished) return(TROUBLE_PUNISHED);
|
||||
if(Punished || (u.utrap && u.utraptype == TT_BURIEDBALL))
|
||||
return(TROUBLE_PUNISHED);
|
||||
if (Cursed_obj(uarmg, GAUNTLETS_OF_FUMBLING) ||
|
||||
Cursed_obj(uarmf, FUMBLE_BOOTS))
|
||||
return TROUBLE_FUMBLING;
|
||||
@@ -372,7 +373,10 @@ register int trouble;
|
||||
*/
|
||||
case TROUBLE_PUNISHED:
|
||||
Your("chain disappears.");
|
||||
unpunish();
|
||||
if(u.utrap && u.utraptype == TT_BURIEDBALL)
|
||||
buried_ball_to_freedom();
|
||||
else
|
||||
unpunish();
|
||||
break;
|
||||
case TROUBLE_FUMBLING:
|
||||
if (Cursed_obj(uarmg, GAUNTLETS_OF_FUMBLING))
|
||||
|
||||
22
src/read.c
22
src/read.c
@@ -944,6 +944,11 @@ register struct obj *sobj;
|
||||
}
|
||||
}
|
||||
if(Punished && !confused) unpunish();
|
||||
if(u.utrap && u.utraptype == TT_BURIEDBALL) {
|
||||
buried_ball_to_freedom();
|
||||
pline_The("clasp on your %s vanishes.",
|
||||
body_part(LEG));
|
||||
}
|
||||
update_inventory();
|
||||
break;
|
||||
}
|
||||
@@ -1733,20 +1738,29 @@ void
|
||||
punish(sobj)
|
||||
register struct obj *sobj;
|
||||
{
|
||||
struct obj *reuse_ball = (sobj && sobj->otyp == HEAVY_IRON_BALL) ?
|
||||
sobj : (struct obj *)0;
|
||||
/* KMH -- Punishment is still okay when you are riding */
|
||||
You("are being punished for your misbehavior!");
|
||||
if (!reuse_ball) You("are being punished for your misbehavior!");
|
||||
if(Punished){
|
||||
Your("iron ball gets heavier.");
|
||||
uball->owt += 160 * (1 + sobj->cursed);
|
||||
return;
|
||||
}
|
||||
if (amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data)) {
|
||||
pline("A ball and chain appears, then falls away.");
|
||||
dropy(mkobj(BALL_CLASS, TRUE));
|
||||
if (!reuse_ball) {
|
||||
pline("A ball and chain appears, then falls away.");
|
||||
dropy(mkobj(BALL_CLASS, TRUE));
|
||||
} else {
|
||||
dropy(reuse_ball);
|
||||
}
|
||||
return;
|
||||
}
|
||||
setworn(mkobj(CHAIN_CLASS, TRUE), W_CHAIN);
|
||||
setworn(mkobj(BALL_CLASS, TRUE), W_BALL);
|
||||
if (!reuse_ball)
|
||||
setworn(mkobj(BALL_CLASS, TRUE), W_BALL);
|
||||
else
|
||||
setworn(reuse_ball, W_BALL);
|
||||
uball->spe = 1; /* special ball (see save) */
|
||||
|
||||
/*
|
||||
|
||||
@@ -91,7 +91,7 @@ dosit()
|
||||
You("sit in the lava!");
|
||||
u.utrap += rnd(4);
|
||||
losehp(d(2,10), "sitting in lava", KILLED_BY);
|
||||
} else if(u.utraptype == TT_INFLOOR) {
|
||||
} else if(u.utraptype == TT_INFLOOR || u.utraptype == TT_BURIEDBALL) {
|
||||
You_cant("maneuver to sit!");
|
||||
u.utrap++;
|
||||
}
|
||||
|
||||
@@ -231,9 +231,15 @@ teleds(nux, nuy, allow_drag)
|
||||
register int nux,nuy;
|
||||
boolean allow_drag;
|
||||
{
|
||||
boolean ball_active = (Punished && uball->where != OBJ_FREE),
|
||||
ball_still_in_range = FALSE;
|
||||
boolean ball_active, ball_still_in_range;
|
||||
|
||||
if (u.utraptype == TT_BURIEDBALL) {
|
||||
/* unearth it */
|
||||
buried_ball_to_punishment();
|
||||
}
|
||||
ball_active = (Punished && uball->where != OBJ_FREE),
|
||||
ball_still_in_range = FALSE;
|
||||
|
||||
/* If they have to move the ball, then drag if allow_drag is true;
|
||||
* otherwise they are teleporting, so unplacebc().
|
||||
* If they don't have to move the ball, then always "drag" whether or
|
||||
@@ -646,6 +652,9 @@ level_tele()
|
||||
}
|
||||
}
|
||||
|
||||
if (u.utrap && u.utraptype == TT_BURIEDBALL)
|
||||
buried_ball_to_punishment();
|
||||
|
||||
if (!next_to_u()) {
|
||||
You(shudder_for_moment);
|
||||
return;
|
||||
@@ -766,6 +775,9 @@ register struct trap *ttmp;
|
||||
{
|
||||
struct d_level target_level;
|
||||
|
||||
if (u.utrap && u.utraptype == TT_BURIEDBALL)
|
||||
buried_ball_to_punishment();
|
||||
|
||||
if (!next_to_u()) {
|
||||
You(shudder_for_moment);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user