# HG changeset patch # User John "Elwin" Edwards # Date 1396047103 25200 # Node ID 1cf517d5d2a8b02d4de5487c0a16bbdc07c31a01 # Parent a5433ba4cabfb923728f200ca88d49d1c6444c68 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. diff -r a5433ba4cabf -r 1cf517d5d2a8 arogue5/state.c --- 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)