]> granicus.if.org Git - nethack/commitdiff
rolling boulder not in bones files
authornethack.allison <nethack.allison>
Mon, 23 Aug 2004 16:57:59 +0000 (16:57 +0000)
committernethack.allison <nethack.allison>
Mon, 23 Aug 2004 16:57:59 +0000 (16:57 +0000)
<Someone> Cced from rgrn:
  <email deleted> (<Someone>) writes:
  [killed by a boulder trap, left bones]

  > Then I realized... there's no boulder.  Did the boulder disappear
  > because I died from the attack, thus bypassing the code that moves the
  > boulder to its intended destination?  Did the creation of the bones
  > file destroy the boulder?  Do boulder traps sometimes get
  > "deactivated" when bones files are loaded?

  The first of these. If you look at launch_obj(), there's an
  obj_extract_self() early on, then all the tracking its trajectory,
  then a place_object() when it comes to rest; since the thitu() call
  kills you during the trajectory part, the boulder never gets re-placed
  onto the map. This is, I think, a bug (and one that will apply to any
  monster-thrown object that kills you, as well); reported to the
  DevTeam.

doc/fixes34.4
include/extern.h
src/end.c
src/trap.c

index f503f22c1aefbe591135b525d9a77179816a55ab..5382057bffe49155adfe4dc05666924761d57b4e 100644 (file)
@@ -49,6 +49,7 @@ fractured boulders or statues produced inconsistent object settings on the
 really fix rolling boulder bug C340-18, the previous "fix" reversed the test
 monster throwing greased weapon has same chance for slip/misfire as player
 killing a pet by displacing it into a trap now yields experience
+prevent a rolling boulder that is in motion from vanishing in bones files
 
 
 Platform- and/or Interface-Specific Fixes
index 3e0c4da9b96f83a7d094f68bacdf5eabec47853f..d88ffcd09b706bf209e19309562898b329176c17 100644 (file)
@@ -2102,6 +2102,8 @@ E boolean NDECL(unconscious);
 E boolean NDECL(lava_effects);
 E void FDECL(blow_up_landmine, (struct trap *));
 E int FDECL(launch_obj,(SHORT_P,int,int,int,int,int));
+E boolean NDECL(launch_in_progress);
+E void NDECL(force_launch_placement);
 E boolean FDECL(uteetering_at_seen_pit, (struct trap *));
 
 /* ### u_init.c ### */
index 9e7bb98e7f3c43df83c4cde7ed69f99f2573fb4a..4a3744a837190e3f99fd4aac23a24c4099814463 100644 (file)
--- a/src/end.c
+++ b/src/end.c
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)end.c      3.4     2003/03/10      */
+/*     SCCS Id: @(#)end.c      3.4     2004/08/23      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -668,6 +668,8 @@ die:
        if (how == TURNED_SLIME)
            u.ugrave_arise = PM_GREEN_SLIME;
 
+       if (bones_ok && launch_in_progress()) force_launch_placement();
+
        if (bones_ok && u.ugrave_arise < LOW_PM) {
            /* corpse gets burnt up too */
            if (how == BURNING)
index 63c3d4cc35e8639f4e30edae8daeb57fe59113a4..950b4c793285dc7a59c65bc09e374f76cb943b43 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)trap.c     3.4     2004/06/12      */
+/*     SCCS Id: @(#)trap.c     3.4     2004/08/23      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -21,6 +21,7 @@ STATIC_DCL int FDECL(disarm_shooting_trap, (struct trap *, int));
 STATIC_DCL int FDECL(try_lift, (struct monst *, struct trap *, int, BOOLEAN_P));
 STATIC_DCL int FDECL(help_monster_out, (struct monst *, struct trap *));
 STATIC_DCL boolean FDECL(thitm, (int,struct monst *,struct obj *,int,BOOLEAN_P));
+STATIC_DCL void FDECL(launch_drop_spot, (struct obj *, XCHAR_P, XCHAR_P));
 STATIC_DCL int FDECL(mkroll_launch,
                        (struct trap *,XCHAR_P,XCHAR_P,SHORT_P,long));
 STATIC_DCL boolean FDECL(isclearpath,(coord *, int, SCHAR_P, SCHAR_P));
@@ -1282,6 +1283,48 @@ struct trap *trap;
        seetrap(trap);                  /* and it isn't concealed */
 }
 
+/*
+ * The following are used to track launched objects to
+ * prevent them from vanishing if you are killed. They
+ * will reappear at the launchplace in bones files.
+ */
+static struct {
+       struct obj *obj;
+       xchar x,y;
+} launchplace;
+
+static void
+launch_drop_spot(obj,x,y)
+struct obj *obj;
+xchar x,y;
+{
+       if (!obj) {
+               launchplace.obj = (struct obj *)0;
+               launchplace.x = 0;
+               launchplace.y = 0;
+       } else {
+               launchplace.obj = obj;
+               launchplace.x = x;
+               launchplace.y = y;
+       }
+}
+
+boolean
+launch_in_progress()
+{
+       if (launchplace.obj) return TRUE;
+       return FALSE;
+}
+
+void
+force_launch_placement()
+{
+       if (launchplace.obj) {
+               launchplace.obj->otrapped = 0;
+               place_object(launchplace.obj, launchplace.x, launchplace.y);
+       }
+}
+
 /*
  * Move obj from (x1,y1) to (x2,y2)
  *
@@ -1366,6 +1409,15 @@ int style;
                        tmp_at(DISP_FLASH, obj_to_glyph(singleobj));
                        tmp_at(bhitpos.x, bhitpos.y);
        }
+       /* Mark a spot to place object in bones files to prevent
+        * loss of object. Use the starting spot to ensure that
+        * a rolling boulder will still launch, which it wouldn't
+        * do if left midstream. Unfortunately we can't use the
+        * target resting spot, because there are some things/situations
+        * that would prevent it from ever getting there (bars), and we
+        * can't tell that yet.
+        */
+       launch_drop_spot(singleobj, bhitpos.x, bhitpos.y);
 
        /* Set the object in motion */
        while(dist-- > 0 && !used_up) {
@@ -1389,12 +1441,14 @@ int style;
                                singleobj->otrapped = 0;
                                (void) mpickobj(mtmp, singleobj);
                                used_up = TRUE;
+                               launch_drop_spot((struct obj *)0, 0, 0);
                                break;
                            }
                        }
                        if (ohitmon(mtmp,singleobj,
                                        (style==ROLL) ? -1 : dist, FALSE)) {
                                used_up = TRUE;
+                               launch_drop_spot((struct obj *)0, 0, 0);
                                break;
                        }
                } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
@@ -1408,6 +1462,7 @@ int style;
                    if (down_gate(bhitpos.x, bhitpos.y) != -1) {
                        if(ship_object(singleobj, bhitpos.x, bhitpos.y, FALSE)){
                                used_up = TRUE;
+                               launch_drop_spot((struct obj *)0, 0, 0);
                                break;
                        }
                    }
@@ -1430,6 +1485,7 @@ int style;
                                if (cansee(bhitpos.x,bhitpos.y))
                                        newsym(bhitpos.x,bhitpos.y);
                                used_up = TRUE;
+                               launch_drop_spot((struct obj *)0, 0, 0);
                            }
                            break;              
                        case LEVEL_TELEP:
@@ -1455,6 +1511,7 @@ int style;
                            }
                            seetrap(t);
                            used_up = TRUE;
+                           launch_drop_spot((struct obj *)0, 0, 0);
                            break;
                        case PIT:
                        case SPIKED_PIT:
@@ -1463,8 +1520,10 @@ int style;
                            /* the boulder won't be used up if there is a
                               monster in the trap; stop rolling anyway */
                            x2 = bhitpos.x,  y2 = bhitpos.y;  /* stops here */
-                           if (flooreffects(singleobj, x2, y2, "fall"))
+                           if (flooreffects(singleobj, x2, y2, "fall")) {
                                used_up = TRUE;
+                               launch_drop_spot((struct obj *)0, 0, 0);
+                           }
                            dist = -1;  /* stop rolling immediately */
                            break;
                        }
@@ -1472,6 +1531,7 @@ int style;
                    }
                    if (flooreffects(singleobj, bhitpos.x, bhitpos.y, "fall")) {
                        used_up = TRUE;
+                       launch_drop_spot((struct obj *)0, 0, 0);
                        break;
                    }
                    if (otyp == BOULDER &&
@@ -1507,12 +1567,16 @@ int style;
                        levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS) {
                    x2 = bhitpos.x,  y2 = bhitpos.y;    /* object stops here */
                    if (hits_bars(&singleobj, x2, y2, !rn2(20), 0)) {
-                       if (!singleobj) used_up = TRUE;
+                       if (!singleobj) {
+                               used_up = TRUE;
+                               launch_drop_spot((struct obj *)0, 0, 0);
+                       }
                        break;
                    }
                }
        }
        tmp_at(DISP_END, 0);
+       launch_drop_spot((struct obj *)0, 0, 0);
        if (!used_up) {
                singleobj->otrapped = 0;
                place_object(singleobj, x2,y2);