From 777d9d922d29420a2ce9eb7d3bfa1f40b172ae76 Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 5 Jul 2018 16:06:31 -0700 Subject: [PATCH] restore vs perm_invent Redo how updates of permanent inventory window are suppressed during restore. Reverses part of e9f1e032717921cb7a51c0f2822628355a35ec36 which included a simpler attempt to deal with this. It looks like we should have been getting impossible "unpaid_cost: object wasn't on any bill" but segfault was reported; I haven't tried to figure out why. The band in xname() ought to be redundant now but is included for bulletproofing. --- doc/fixes36.2 | 3 +++ src/objnam.c | 4 +++- src/restore.c | 24 ++++++++++++++++-------- src/wield.c | 7 ++++--- src/worn.c | 7 ++----- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index ff9b89d18..5e1d1ad9d 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -65,6 +65,9 @@ eating rings while polymorphed didn't handle bonus/penalty for increase damage, shopkeeper's position in front of shop door didn't correctly handle bottom edge of irregularly shaped shop due to typo or copy+paste error (latent bug; no such shops are present in 3.6.x) +attempting to update permanent inventory window during restore had problems + with unpaid items (needed shop bill before shop and its shopkeeper + were restored) and named fruit Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/objnam.c b/src/objnam.c index 5fa0ddd42..7de07963c 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1194,7 +1194,9 @@ unsigned doname_flags; Strcat(bp, " (at the ready)"); } } - if (!iflags.suppress_price && is_unpaid(obj)) { + /* treat 'restoring' like suppress_price because shopkeeper and + bill might not be available yet while restore is in progress */ + if (!iflags.suppress_price && !restoring && is_unpaid(obj)) { long quotedprice = unpaid_cost(obj, TRUE); Sprintf(eos(bp), " (%s, %ld %s)", diff --git a/src/restore.c b/src/restore.c index b967e1464..f7e92da76 100644 --- a/src/restore.c +++ b/src/restore.c @@ -35,8 +35,7 @@ STATIC_DCL struct monst *FDECL(restmonchn, (int, BOOLEAN_P)); STATIC_DCL struct fruit *FDECL(loadfruitchn, (int)); STATIC_DCL void FDECL(freefruitchn, (struct fruit *)); STATIC_DCL void FDECL(ghostfruit, (struct obj *)); -STATIC_DCL boolean -FDECL(restgamestate, (int, unsigned int *, unsigned int *)); +STATIC_DCL boolean FDECL(restgamestate, (int, unsigned int *, unsigned int *)); STATIC_DCL void FDECL(restlevelstate, (unsigned int, unsigned int)); STATIC_DCL int FDECL(restlevelfile, (int, XCHAR_P)); STATIC_OVL void FDECL(restore_msghistory, (int)); @@ -521,6 +520,7 @@ unsigned int *stuckid, *steedid; struct obj *otmp, *tmp_bc; char timebuf[15]; unsigned long uid; + boolean defer_perm_invent; mread(fd, (genericptr_t) &uid, sizeof uid); if (SYSOPT_CHECK_SAVE_UID @@ -531,7 +531,7 @@ unsigned int *stuckid, *steedid; if (!wizard) return FALSE; } - mread(fd, (genericptr_t) &context, sizeof(struct context_info)); + mread(fd, (genericptr_t) &context, sizeof (struct context_info)); if (context.warntype.speciesidx >= LOW_PM) context.warntype.species = &mons[context.warntype.speciesidx]; @@ -539,7 +539,13 @@ unsigned int *stuckid, *steedid; file option values instead of keeping old save file option values if partial restore fails and we resort to starting a new game */ newgameflags = flags; - mread(fd, (genericptr_t) &flags, sizeof(struct flag)); + mread(fd, (genericptr_t) &flags, sizeof (struct flag)); + /* avoid keeping permanent inventory window up to date during restore + (setworn() calls update_inventory); attempting to include the cost + of unpaid items before shopkeeper's bill is available is a no-no; + named fruit names aren't accessible yet either */ + defer_perm_invent = flags.perm_invent; + flags.perm_invent = FALSE; /* wizard and discover are actually flags.debug and flags.explore; player might be overriding the save file values for them; in the discover case, we don't want to set that for a normal @@ -645,14 +651,14 @@ unsigned int *stuckid, *steedid; restlevchn(fd); mread(fd, (genericptr_t) &moves, sizeof moves); mread(fd, (genericptr_t) &monstermoves, sizeof monstermoves); - mread(fd, (genericptr_t) &quest_status, sizeof(struct q_score)); - mread(fd, (genericptr_t) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); + mread(fd, (genericptr_t) &quest_status, sizeof (struct q_score)); + mread(fd, (genericptr_t) spl_book, (MAXSPELL + 1) * sizeof (struct spell)); restore_artifacts(fd); restore_oracles(fd); if (u.ustuck) - mread(fd, (genericptr_t) stuckid, sizeof(*stuckid)); + mread(fd, (genericptr_t) stuckid, sizeof *stuckid); if (u.usteed) - mread(fd, (genericptr_t) steedid, sizeof(*steedid)); + mread(fd, (genericptr_t) steedid, sizeof *steedid); mread(fd, (genericptr_t) pl_character, sizeof pl_character); mread(fd, (genericptr_t) pl_fruit, sizeof pl_fruit); @@ -665,6 +671,8 @@ unsigned int *stuckid, *steedid; /* must come after all mons & objs are restored */ relink_timers(FALSE); relink_light_sources(FALSE); + /* inventory display is now viable */ + flags.perm_invent = defer_perm_invent; return TRUE; } diff --git a/src/wield.c b/src/wield.c index c45282a14..1063e125b 100644 --- a/src/wield.c +++ b/src/wield.c @@ -112,7 +112,6 @@ register struct obj *obj; : !is_weptool(obj) && !is_wet_towel(obj); } else unweapon = TRUE; /* for "bare hands" message */ - update_inventory(); } STATIC_OVL boolean @@ -230,7 +229,9 @@ setuqwep(obj) register struct obj *obj; { setworn(obj, W_QUIVER); - update_inventory(); + /* no extra handling needed; this used to include a call to + update_inventory() but that's already performed by setworn() */ + return; } void @@ -238,7 +239,7 @@ setuswapwep(obj) register struct obj *obj; { setworn(obj, W_SWAPWEP); - update_inventory(); + return; } /*** Commands to change particular slot(s) ***/ diff --git a/src/worn.c b/src/worn.c index 828e6a902..e7860c655 100644 --- a/src/worn.c +++ b/src/worn.c @@ -106,8 +106,7 @@ long mask; } } } - if (!restoring) - update_inventory(); + update_inventory(); } /* called e.g. when obj is destroyed */ @@ -138,9 +137,7 @@ register struct obj *obj; if ((p = w_blocks(obj, wp->w_mask)) != 0) u.uprops[p].blocked &= ~wp->w_mask; } - /* setnotworn() isn't called during restore but parallel setworn() */ - if (!restoring) - update_inventory(); + update_inventory(); } /* return item worn in slot indiciated by wornmask; needed by poly_obj() */ -- 2.40.0