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:
@@ -436,6 +436,7 @@ enum bodypart_types {
|
||||
#define POTION_OCCUPANT_CHANCE(n) (13 + 2 * (n))
|
||||
#define WAND_BACKFIRE_CHANCE 100
|
||||
#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)
|
||||
|
||||
/* Flags to control menus */
|
||||
|
||||
@@ -540,7 +540,8 @@ unsigned int *stuckid, *steedid;
|
||||
struct sysflag newgamesysflags;
|
||||
#endif
|
||||
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];
|
||||
unsigned long uid;
|
||||
boolean defer_perm_invent;
|
||||
@@ -643,17 +644,15 @@ unsigned int *stuckid, *steedid;
|
||||
restore_timers(fd, RANGE_GLOBAL, FALSE, 0L);
|
||||
restore_light_sources(fd);
|
||||
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
|
||||
or in your inventory */
|
||||
tmp_bc = restobjchn(fd, FALSE, FALSE);
|
||||
if (tmp_bc) {
|
||||
for (otmp = tmp_bc; otmp; otmp = otmp->nobj) {
|
||||
if (otmp->owornmask)
|
||||
setworn(otmp, otmp->owornmask);
|
||||
}
|
||||
if (!uball || !uchain)
|
||||
impossible("restgamestate: lost ball & chain");
|
||||
|
||||
/* restore dangling (not on floor or in inventory) ball and/or chain */
|
||||
bc_obj = restobjchn(fd, FALSE, FALSE);
|
||||
while(bc_obj) {
|
||||
struct obj * nobj = bc_obj->nobj;
|
||||
if (bc_obj->owornmask)
|
||||
setworn(bc_obj, bc_obj->owornmask);
|
||||
bc_obj->nobj = (struct obj *)0;
|
||||
bc_obj = nobj;
|
||||
}
|
||||
|
||||
migrating_objs = restobjchn(fd, FALSE, FALSE);
|
||||
@@ -671,6 +670,10 @@ unsigned int *stuckid, *steedid;
|
||||
for (otmp = invent; otmp; otmp = otmp->nobj)
|
||||
if (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"
|
||||
during next fight when bare-handed or wielding an unconventional
|
||||
item; for pick-axe, we aren't able to distinguish between having
|
||||
|
||||
19
src/save.c
19
src/save.c
@@ -280,6 +280,7 @@ savegamestate(fd, mode)
|
||||
register int fd, mode;
|
||||
{
|
||||
unsigned long uid;
|
||||
struct obj * bc_objs = (struct obj *)0;
|
||||
|
||||
#ifdef MFLOPPY
|
||||
count_only = (mode & COUNT_SAVE);
|
||||
@@ -307,14 +308,18 @@ register int fd, mode;
|
||||
save_light_sources(fd, mode, RANGE_GLOBAL);
|
||||
|
||||
saveobjchn(fd, invent, mode);
|
||||
if (BALL_IN_MON) {
|
||||
/* prevent loss of ball & chain when swallowed */
|
||||
uball->nobj = uchain;
|
||||
uchain->nobj = (struct obj *) 0;
|
||||
saveobjchn(fd, uball, mode);
|
||||
} else {
|
||||
saveobjchn(fd, (struct obj *) 0, mode);
|
||||
|
||||
/* save ball and chain if they are currently dangling free (i.e. not on
|
||||
floor or in inventory) */
|
||||
if (CHAIN_IN_MON) {
|
||||
uchain->nobj = bc_objs;
|
||||
bc_objs = uchain;
|
||||
}
|
||||
if (BALL_IN_MON) {
|
||||
uball->nobj = bc_objs;
|
||||
bc_objs = uball;
|
||||
}
|
||||
saveobjchn(fd, bc_objs, mode);
|
||||
|
||||
saveobjchn(fd, migrating_objs, mode);
|
||||
savemonchn(fd, migrating_mons, mode);
|
||||
|
||||
Reference in New Issue
Block a user