From a8b96bbc3e75cef6db03306561795d1f58469321 Mon Sep 17 00:00:00 2001 From: "John \"Elwin\" Edwards" Date: Fri, 28 Mar 2014 15:51:43 -0700 Subject: [PATCH] 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. --- arogue5/state.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/arogue5/state.c b/arogue5/state.c index 43fdb11..d26c42c 100644 --- a/arogue5/state.c +++ b/arogue5/state.c @@ -1341,6 +1341,69 @@ rs_read_sticks(int inf) 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_daemons(FILE *savef, struct delayed_action *d_list, int count) 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 @@ rs_read_daemons(int inf, struct delayed_action *d_list, int count) 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)