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:
@@ -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
|
||||
|
||||
@@ -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) */
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
5
src/do.c
5
src/do.c
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
32
src/dokick.c
32
src/dokick.c
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -2682,6 +2682,7 @@ kill_genocided_monsters()
|
||||
|
||||
kill_eggs(invent);
|
||||
kill_eggs(fobj);
|
||||
kill_eggs(migrating_objs);
|
||||
kill_eggs(level.buriedobjlist);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user