]> granicus.if.org Git - nethack/commitdiff
breaking migrated objects
authorcohrs <cohrs>
Sat, 18 Oct 2003 22:55:42 +0000 (22:55 +0000)
committercohrs <cohrs>
Sat, 18 Oct 2003 22:55:42 +0000 (22:55 +0000)
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

12 files changed:
doc/fixes35.0
include/dungeon.h
include/extern.h
src/do.c
src/dog.c
src/dokick.c
src/hack.c
src/mkobj.c
src/mon.c
src/teleport.c
src/trap.c
src/zap.c

index 796683f36fe383e54665ea13cf7e67672ba0155b..675fb7a1826380386ce554e75d6ec1f9841b9138 100644 (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
index 24ba413672366c6bea3821336b29de083206cf8f..d1da2657e65e09e5027522cc9fcafa28a8cfdadc 100644 (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) */
 
index 784ce7f32645fff113f892a7d66ddea35ca50b94..ca03362fb32a89102317641ef00410ba68d33227 100644 (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));
 
index 4e06a45bb0110d9a0dc533a57abc2aea16ce1559..816065a357a78abcc2a7c89fd4f615671e3f322f 100644 (file)
--- 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)) {
index 536a19a38e2fa6799c204d2206a3f8cc438458db..476404836dfbe4feb7c751258dfcd2c6b2f984f9 100644 (file)
--- 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);
                    }
                }
index 65dd15d6227c9f96a7728881f11a7f24e3543a10..b9f7e11d3b7ccf58de1125106da7d66ee1826341 100644 (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);
+               }
            }
        }
 }
index ff4b2efb9856ac12e5c216c046d5fc2fd635e204..51f5c9d02f97c8ffb58118b8fbb6999ac54d503d 100644 (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;
index 880e35251d60e82f15b0a7653036438575c9a8fc..73f5a8397a2466f71b68fa2d9d6171c7d6aea36d 100644 (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) {
index e877526563f24e60a48d4794a56c7f14f9a1aaf3..960d98f94801b247777f7642950ee739f16f02db 100644 (file)
--- 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);
 }
 
index 1c15e69a215181db3dba6d05be1c00a7e7013732..5b678be6bc295f321e3d87c21508032996c36924 100644 (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 */
index 1fec73bd7d8994161275824038eef35bde085fc1..063dfabf538f0f37704360646f0195795bd0a85a 100644 (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;
index b2c92111f0035f1b6de0161ec64bbd3939586096..189f2f45c1e9ee0dcd514e8601782ea5620887b3 100644 (file)
--- 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