From: cohrs Date: Sat, 18 Oct 2003 22:55:42 +0000 (+0000) Subject: breaking migrated objects X-Git-Tag: MOVE2GIT~1683 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b2ffe649682ec01d218fcbca9950df25ba222179;p=nethack 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 --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 796683f36..675fb7a18 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -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 diff --git a/include/dungeon.h b/include/dungeon.h index 24ba41367..d1da2657e 100644 --- a/include/dungeon.h +++ b/include/dungeon.h @@ -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) */ diff --git a/include/extern.h b/include/extern.h index 784ce7f32..ca03362fb 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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)); diff --git a/src/do.c b/src/do.c index 4e06a45bb..816065a35 100644 --- a/src/do.c +++ b/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)) { diff --git a/src/dog.c b/src/dog.c index 536a19a38..476404836 100644 --- a/src/dog.c +++ b/src/dog.c @@ -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); } } diff --git a/src/dokick.c b/src/dokick.c index 65dd15d62..b9f7e11d3 100644 --- a/src/dokick.c +++ b/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); + } } } } diff --git a/src/hack.c b/src/hack.c index ff4b2efb9..51f5c9d02 100644 --- a/src/hack.c +++ b/src/hack.c @@ -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; diff --git a/src/mkobj.c b/src/mkobj.c index 880e35251..73f5a8397 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -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) { diff --git a/src/mon.c b/src/mon.c index e87752656..960d98f94 100644 --- a/src/mon.c +++ b/src/mon.c @@ -2682,6 +2682,7 @@ kill_genocided_monsters() kill_eggs(invent); kill_eggs(fobj); + kill_eggs(migrating_objs); kill_eggs(level.buriedobjlist); } diff --git a/src/teleport.c b/src/teleport.c index 1c15e69a2..5b678be6b 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -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 */ diff --git a/src/trap.c b/src/trap.c index 1fec73bd7..063dfabf5 100644 --- a/src/trap.c +++ b/src/trap.c @@ -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; diff --git a/src/zap.c b/src/zap.c index b2c92111f..189f2f45c 100644 --- a/src/zap.c +++ b/src/zap.c @@ -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