changeset 115:1cf517d5d2a8

arogue5: make alchemy jugs survive a save and restore. Alchemy jugs are refilled by the alchemy() fuse, which takes a pointer to the jug object as an argument. When written to a save file and read back out, the pointer is unlikely to point anywhere useful. Instead, rs_write_daemons() now stores an index into the player's pack or the list of objects on the floor. rs_read_daemons() uses this number to locate the object when restoring. This change should not cause any new issues with old savefiles, but it is unable to make a broken alchemy jug work again.
author John "Elwin" Edwards
date Fri, 28 Mar 2014 15:51:43 -0700
parents a5433ba4cabf
children 97f8fdf9595c
files arogue5/state.c
diffstat 1 files changed, 73 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/arogue5/state.c	Fri Mar 28 10:57:03 2014 -0700
+++ b/arogue5/state.c	Fri Mar 28 15:51:43 2014 -0700
@@ -1341,6 +1341,69 @@
     return(READSTAT);
 }
 
+/* Assigns a number to an alchemy jug associated with a fuse, so it can be 
+ * found and reassociated when restoring.
+ * 1 - 31: slot in pack
+ * 32+   : on floor
+ * Hopefully monsters do not pick them up.
+ */
+int number_alchemy_jug(struct object *obj) {
+    struct object *tobj = NULL;
+    struct linked_list *item;
+    int i = 1;
+    for (item = player.t_pack; item != NULL; item = next(item), i++) {
+	tobj = OBJPTR(item);
+	if (tobj	 == obj		&& 
+	    tobj->o_type == MM		&& 
+	    tobj->o_which== MM_JUG)
+		break;
+    }
+    if (item == NULL) {
+	for (item = lvl_obj, i = 32; item != NULL; item = next(item), i++) {
+	    tobj = OBJPTR(item);
+	    if (tobj	     == obj		&& 
+		tobj->o_type == MM		&& 
+		tobj->o_which== MM_JUG)
+		    break;
+	}
+    }
+    if (item == NULL)
+      return 0;
+    return i;
+}
+
+/* Takes an alchemy jug number and tracks down the object. */
+struct object *find_alchemy_jug(int n) {
+    struct object *tobj;
+    struct linked_list *item;
+
+    if (n <= 0) {
+        return NULL;
+    }
+    else if (n < 32) {
+        item = player.t_pack;
+        n -= 1;
+    }
+    else if (n < 1024) {
+        item = lvl_obj;
+        n -= 32;
+    }
+    else {
+        /* This is likely a bug, not 1024 actual items on the floor. */
+        return NULL;
+    }
+    while (item != NULL && n > 0) {
+        item = next(item);
+        n--;
+    }
+    if (item == NULL)
+        return NULL;
+    tobj = OBJPTR(item);
+    if (tobj->o_type != MM || tobj->o_which != MM_JUG)
+        return NULL;
+    return tobj;
+}
+
 int
 rs_write_daemons(FILE *savef, struct delayed_action *d_list, int count)
 {
@@ -1421,7 +1484,10 @@
         rs_write_int(savef, d_list[i].d_type);
         rs_write_int(savef, func);
         /* d_arg is a pointer and can't actually be saved and restored. */
-        rs_write_int(savef, 0);
+        if (func == 19)
+            rs_write_int(savef, number_alchemy_jug(d_list[i].d_arg));
+        else
+            rs_write_int(savef, 0);
         rs_write_int(savef, d_list[i].d_time);
     }
     
@@ -1518,10 +1584,15 @@
                      break;
         }   
 
+        /* Most functions don't use the argument. */
         rs_read_int(inf, &dummy);
-        d_list[i].d_arg = NULL;
         if (func == 2)
             d_list[i].d_arg = &player;
+        else if (func == 19)
+            d_list[i].d_arg = find_alchemy_jug(dummy);
+        else
+            d_list[i].d_arg = NULL;
+
         rs_read_int(inf, &d_list[i].d_time);
 
 	if (d_list[i].d_func == NULL)