breaking migrated objects

Allow migrated objects to break on arrival.  Added code to obj_delivery to
cause this, along with a flag to keep breakage from occurring.  The new
flag isn't used yet, because all the current object migration involve
objects that were moving/dropping.  To help make this change, rloco now
returns whether the object was placed or not, so caller can know if an obj
pointer is still valid or not.

Making the breakage messages for MIGR_NEAR_PLAYER objects show up after the
new level is displayed required some effort (rather than while the old level
was still displayed, which was confusing), due to the needs of goto_level.
- obj_delivery now has 2 passes, one for before player arrives, another after,
allowing the two cases to be treated differently
- goto_level calls obj_delivery twice (run_timers is not called twice,
since the run required before the level is displayed will have already run
any timers on migrating object)
- kill_genocided_monsters now kills eggs on the migrating_objs list too
This commit is contained in:
cohrs
2003-10-18 22:55:42 +00:00
parent 4cbdae2d3b
commit b2ffe64968
12 changed files with 46 additions and 17 deletions

View File

@@ -39,6 +39,7 @@ hiding monsters don't hide under cockatrice/chickatrice corpses
"sound" option renamed to "acoustics"
deafness now a full-fledged attribute
water should flow into pits from broken wand of digging
objects that fall thru trapdoors, et al, can break on impact
Platform- and/or Interface-Specific Fixes

View File

@@ -142,6 +142,7 @@ typedef struct branch {
#define MIGR_SSTAIRS 7 /* dungeon branch */
#define MIGR_PORTAL 8 /* magic portal */
#define MIGR_NEAR_PLAYER 9 /* mon: followers; obj: trap door */
#define MIGR_NOBREAK 1024 /* bitmask: don't break on delivery */
/* level information (saved via ledger number) */

View File

@@ -429,7 +429,7 @@ E boolean FDECL(ghitm, (struct monst *,struct obj *));
E void FDECL(container_impact_dmg, (struct obj *));
E int NDECL(dokick);
E boolean FDECL(ship_object, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P));
E void NDECL(obj_delivery);
E void FDECL(obj_delivery, (BOOLEAN_P));
E schar FDECL(down_gate, (XCHAR_P,XCHAR_P));
E void FDECL(impact_drop, (struct obj *,XCHAR_P,XCHAR_P,XCHAR_P));
@@ -1955,7 +1955,7 @@ E boolean FDECL(rloc, (struct monst *, BOOLEAN_P));
E boolean FDECL(tele_restrict, (struct monst *));
E void FDECL(mtele_trap, (struct monst *, struct trap *,int));
E int FDECL(mlevel_tele_trap, (struct monst *, struct trap *,BOOLEAN_P,int));
E void FDECL(rloco, (struct obj *));
E boolean FDECL(rloco, (struct obj *));
E int NDECL(random_teleport_level);
E boolean FDECL(u_teleport_mon, (struct monst *,BOOLEAN_P));

View File

@@ -1188,7 +1188,7 @@ boolean at_stairs, falling, portal;
}
if (Punished) placebc();
obj_delivery(); /* before killing geno'd monsters' eggs */
obj_delivery(FALSE);
losedogs();
kill_genocided_monsters(); /* for those wiped out while in limbo */
/*
@@ -1248,6 +1248,9 @@ boolean at_stairs, falling, portal;
/* give room entrance message, if any */
check_special_room(FALSE);
/* deliver objects traveling with player */
obj_delivery(TRUE);
/* Check whether we just entered Gehennom. */
if (!In_hell(&u.uz0) && Inhell) {
if (Is_valley(&u.uz)) {

View File

@@ -372,8 +372,7 @@ boolean with_you;
obj->owornmask = 0L;
if (xlocale && ylocale)
place_object(obj, xlocale, ylocale);
else {
rloco(obj);
else if (rloco(obj)) {
get_obj_location(obj, &xlocale, &ylocale, 0);
}
}

View File

@@ -1137,10 +1137,12 @@ schar loc;
}
}
/* player or missile impacts location, causing objects to fall down */
void
impact_drop(missile, x, y, dlev)
struct obj *missile;
xchar x, y, dlev;
struct obj *missile; /* caused impact, won't drop itself */
xchar x, y; /* location affected */
xchar dlev; /* if !0 send to dlev near player */
{
schar toloc;
register struct obj *obj, *obj2;
@@ -1379,18 +1381,26 @@ boolean shop_floor_obj;
}
void
obj_delivery()
obj_delivery(near_hero)
boolean near_hero;
{
register struct obj *otmp, *otmp2;
register int nx, ny;
long where;
boolean nobreak;
for (otmp = migrating_objs; otmp; otmp = otmp2) {
otmp2 = otmp->nobj;
if (otmp->ox != u.uz.dnum || otmp->oy != u.uz.dlevel) continue;
obj_extract_self(otmp);
where = otmp->owornmask; /* destination code */
nobreak = (where & MIGR_NOBREAK) != 0;
where &= ~MIGR_NOBREAK;
if ((!near_hero && where == MIGR_NEAR_PLAYER) ||
(near_hero && where != MIGR_NEAR_PLAYER)) continue;
obj_extract_self(otmp);
otmp->owornmask = 0L;
switch ((int)where) {
@@ -1408,13 +1418,25 @@ obj_delivery()
}
if (nx > 0) {
place_object(otmp, nx, ny);
if (!nobreak && !IS_SOFT(levl[nx][ny].typ)) {
if (where == MIGR_NEAR_PLAYER) {
if (breaks(otmp, nx, ny)) continue;
} else if (breaktest(otmp)) {
/* assume it broke before player arrived, no messages */
delobj(otmp);
continue;
}
}
stackobj(otmp);
(void)scatter(nx, ny, rnd(2), 0, otmp);
} else { /* random location */
/* set dummy coordinates because there's no
current position for rloco() to update */
otmp->ox = otmp->oy = 0;
rloco(otmp);
if (rloco(otmp) && !nobreak && breaktest(otmp)) {
/* assume it broke before player arrived, no messages */
delobj(otmp);
}
}
}
}

View File

@@ -185,7 +185,7 @@ moverock()
You("push %s and suddenly it disappears!",
the(xname(otmp)));
if (ttmp->ttyp == TELEP_TRAP)
rloco(otmp);
(void)rloco(otmp);
else {
int newlev = random_teleport_level();
d_level dest;

View File

@@ -896,7 +896,7 @@ boolean init;
impossible("making corpstat type %d", objtype);
if (x == 0 && y == 0) { /* special case - random placement */
otmp = mksobj(objtype, init, FALSE);
if (otmp) rloco(otmp);
if (otmp) (void)rloco(otmp);
} else
otmp = mksobj_at(objtype, x, y, init, FALSE);
if (otmp) {

View File

@@ -2682,6 +2682,7 @@ kill_genocided_monsters()
kill_eggs(invent);
kill_eggs(fobj);
kill_eggs(migrating_objs);
kill_eggs(level.buriedobjlist);
}

View File

@@ -1129,7 +1129,8 @@ int in_sight;
}
void
/* place object randomly, returns FALSE if it's gone (eg broken) as a result */
boolean
rloco(obj)
register struct obj *obj;
{
@@ -1138,7 +1139,7 @@ register struct obj *obj;
int try_limit = 4000;
if (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm])) {
if (revive_corpse(obj)) return;
if (revive_corpse(obj)) return FALSE;
}
obj_extract_self(obj);
@@ -1159,7 +1160,7 @@ register struct obj *obj;
dndest.nhx, dndest.nhy)))));
if (flooreffects(obj, tx, ty, "fall")) {
return;
return FALSE;
} else if (otx == 0 && oty == 0) {
; /* fell through a trap door; no update of old loc needed */
} else {
@@ -1175,6 +1176,7 @@ register struct obj *obj;
}
place_object(obj, tx, ty);
newsym(tx, ty);
return TRUE;
}
/* Returns an absolute depth */

View File

@@ -1436,7 +1436,7 @@ int style;
You_hear("a rumbling stop abruptly.");
singleobj->otrapped = 0;
if (t->ttyp == TELEP_TRAP)
rloco(singleobj);
(void)rloco(singleobj);
else {
int newlev = random_teleport_level();
d_level dest;

View File

@@ -1547,7 +1547,7 @@ struct obj *obj, *otmp;
break;
case WAN_TELEPORTATION:
case SPE_TELEPORT_AWAY:
rloco(obj);
(void) rloco(obj);
break;
case WAN_MAKE_INVISIBLE:
#ifdef INVISIBLE_OBJECTS