Fix dangling chain bug.

If a punished player picks up the iron ball, gets engulfed and
saves, then the saved game will have missed saving the dangling
chain since it was not on the floor or in the inventory.  Upon
restoring the saved game, the game will be in a bad state since
the ball will be worn but the chain will be missing.
This commit is contained in:
Bart House
2019-06-23 21:39:22 -07:00
parent 87be6fad43
commit ed08938ada
3 changed files with 28 additions and 19 deletions
+1
View File
@@ -436,6 +436,7 @@ enum bodypart_types {
#define POTION_OCCUPANT_CHANCE(n) (13 + 2 * (n)) #define POTION_OCCUPANT_CHANCE(n) (13 + 2 * (n))
#define WAND_BACKFIRE_CHANCE 100 #define WAND_BACKFIRE_CHANCE 100
#define BALL_IN_MON (u.uswallow && uball && uball->where == OBJ_FREE) #define BALL_IN_MON (u.uswallow && uball && uball->where == OBJ_FREE)
#define CHAIN_IN_MON (u.uswallow && uchain && uchain->where == OBJ_FREE)
#define NODIAG(monnum) ((monnum) == PM_GRID_BUG) #define NODIAG(monnum) ((monnum) == PM_GRID_BUG)
/* Flags to control menus */ /* Flags to control menus */
+15 -12
View File
@@ -540,7 +540,8 @@ unsigned int *stuckid, *steedid;
struct sysflag newgamesysflags; struct sysflag newgamesysflags;
#endif #endif
struct context_info newgamecontext; /* all 0, but has some pointers */ struct context_info newgamecontext; /* all 0, but has some pointers */
struct obj *otmp, *tmp_bc; struct obj *otmp;
struct obj *bc_obj;
char timebuf[15]; char timebuf[15];
unsigned long uid; unsigned long uid;
boolean defer_perm_invent; boolean defer_perm_invent;
@@ -643,17 +644,15 @@ unsigned int *stuckid, *steedid;
restore_timers(fd, RANGE_GLOBAL, FALSE, 0L); restore_timers(fd, RANGE_GLOBAL, FALSE, 0L);
restore_light_sources(fd); restore_light_sources(fd);
invent = restobjchn(fd, FALSE, FALSE); invent = restobjchn(fd, FALSE, FALSE);
/* tmp_bc only gets set here if the ball & chain were orphaned
because you were swallowed; otherwise they will be on the floor /* restore dangling (not on floor or in inventory) ball and/or chain */
or in your inventory */ bc_obj = restobjchn(fd, FALSE, FALSE);
tmp_bc = restobjchn(fd, FALSE, FALSE); while(bc_obj) {
if (tmp_bc) { struct obj * nobj = bc_obj->nobj;
for (otmp = tmp_bc; otmp; otmp = otmp->nobj) { if (bc_obj->owornmask)
if (otmp->owornmask) setworn(bc_obj, bc_obj->owornmask);
setworn(otmp, otmp->owornmask); bc_obj->nobj = (struct obj *)0;
} bc_obj = nobj;
if (!uball || !uchain)
impossible("restgamestate: lost ball & chain");
} }
migrating_objs = restobjchn(fd, FALSE, FALSE); migrating_objs = restobjchn(fd, FALSE, FALSE);
@@ -671,6 +670,10 @@ unsigned int *stuckid, *steedid;
for (otmp = invent; otmp; otmp = otmp->nobj) for (otmp = invent; otmp; otmp = otmp->nobj)
if (otmp->owornmask) if (otmp->owornmask)
setworn(otmp, otmp->owornmask); setworn(otmp, otmp->owornmask);
if ((uball && !uchain) || (uchain && !uball))
impossible("restgamestate: lost ball & chain");
/* reset weapon so that player will get a reminder about "bashing" /* reset weapon so that player will get a reminder about "bashing"
during next fight when bare-handed or wielding an unconventional during next fight when bare-handed or wielding an unconventional
item; for pick-axe, we aren't able to distinguish between having item; for pick-axe, we aren't able to distinguish between having
+12 -7
View File
@@ -280,6 +280,7 @@ savegamestate(fd, mode)
register int fd, mode; register int fd, mode;
{ {
unsigned long uid; unsigned long uid;
struct obj * bc_objs = (struct obj *)0;
#ifdef MFLOPPY #ifdef MFLOPPY
count_only = (mode & COUNT_SAVE); count_only = (mode & COUNT_SAVE);
@@ -307,14 +308,18 @@ register int fd, mode;
save_light_sources(fd, mode, RANGE_GLOBAL); save_light_sources(fd, mode, RANGE_GLOBAL);
saveobjchn(fd, invent, mode); saveobjchn(fd, invent, mode);
if (BALL_IN_MON) {
/* prevent loss of ball & chain when swallowed */ /* save ball and chain if they are currently dangling free (i.e. not on
uball->nobj = uchain; floor or in inventory) */
uchain->nobj = (struct obj *) 0; if (CHAIN_IN_MON) {
saveobjchn(fd, uball, mode); uchain->nobj = bc_objs;
} else { bc_objs = uchain;
saveobjchn(fd, (struct obj *) 0, mode);
} }
if (BALL_IN_MON) {
uball->nobj = bc_objs;
bc_objs = uball;
}
saveobjchn(fd, bc_objs, mode);
saveobjchn(fd, migrating_objs, mode); saveobjchn(fd, migrating_objs, mode);
savemonchn(fd, migrating_mons, mode); savemonchn(fd, migrating_mons, mode);