more shop damage repair

Stop attempting to catch up for lost time for shop damage repair
when getlev() loads a previousl visited level.  Normal shopkeeper
behavior will take care of that.

Also, fixes the display related aspects of shop damage repair
interacting with ball and chain.  They don't happen when its done
while the map is being shown.
This commit is contained in:
PatR
2022-04-09 15:55:21 -07:00
parent dadbea1d8c
commit 593c3532fc
7 changed files with 45 additions and 48 deletions

View File

@@ -1,4 +1,4 @@
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.870 $ $NHDT-Date: 1649530942 2022/04/09 19:02:22 $ HDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.870 $ $NHDT-Date: 1649530942 2022/04/09 19:02:22 $
General Fixes and Modified Features General Fixes and Modified Features
----------------------------------- -----------------------------------
@@ -875,6 +875,8 @@ avoid "the Lord Surtur's corpse glows iridescently" when shk_your() or the()
restoring while attached ball or chain is on floor in a breach of a shop wall restoring while attached ball or chain is on floor in a breach of a shop wall
could have it be moved out of wall gap as that gets repaired, then could have it be moved out of wall gap as that gets repaired, then
might trigger an impossible about being positioned too far from hero might trigger an impossible about being positioned too far from hero
don't try to catch up for lost time for shop damage repair in restdamage()
called from getlev(); let normal shopkeeper movement take care of it
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -2436,7 +2436,8 @@ extern void sellobj(struct obj *, xchar, xchar);
extern int doinvbill(int); extern int doinvbill(int);
extern struct monst *shkcatch(struct obj *, xchar, xchar); extern struct monst *shkcatch(struct obj *, xchar, xchar);
extern void add_damage(xchar, xchar, long); extern void add_damage(xchar, xchar, long);
extern int repair_damage(struct monst *, struct damage *, boolean); extern int repair_damage(struct monst *, struct damage *);
extern void fix_shop_damage(void);
extern int shk_move(struct monst *); extern int shk_move(struct monst *);
extern void after_shk_move(struct monst *); extern void after_shk_move(struct monst *);
extern boolean is_fshk(struct monst *); extern boolean is_fshk(struct monst *);

View File

@@ -68,6 +68,7 @@ moveloop_preamble(boolean resuming)
g.context.botlx = TRUE; /* for STATUS_HILITES */ g.context.botlx = TRUE; /* for STATUS_HILITES */
if (resuming) { /* restoring old game */ if (resuming) { /* restoring old game */
read_engr_at(u.ux, u.uy); /* subset of pickup() */ read_engr_at(u.ux, u.uy); /* subset of pickup() */
fix_shop_damage();
} }
(void) encumber_msg(); /* in case they auto-picked up something */ (void) encumber_msg(); /* in case they auto-picked up something */

View File

@@ -660,6 +660,7 @@ getbones(void)
} }
resetobjs(fobj, TRUE); resetobjs(fobj, TRUE);
resetobjs(g.level.buriedobjlist, TRUE); resetobjs(g.level.buriedobjlist, TRUE);
fix_shop_damage();
} }
} }
close_nhfile(nhfp); close_nhfile(nhfp);

View File

@@ -1805,6 +1805,11 @@ goto_level(
/* assume this will always return TRUE when changing level */ /* assume this will always return TRUE when changing level */
(void) in_out_region(u.ux, u.uy); (void) in_out_region(u.ux, u.uy);
/* shop repair is normally done when shopkeepers move, but we may
need to catch up for lost time here; do this before maybe dying
so bones map will include it */
if (!new)
fix_shop_damage();
/* fall damage? */ /* fall damage? */
if (do_fall_dmg) { if (do_fall_dmg) {

View File

@@ -154,51 +154,22 @@ restdamage(NHFILE* nhfp)
boolean ghostly = (nhfp->ftype == NHF_BONESFILE); boolean ghostly = (nhfp->ftype == NHF_BONESFILE);
if (nhfp->structlevel) if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &dmgcount, sizeof(dmgcount)); mread(nhfp->fd, (genericptr_t) &dmgcount, sizeof dmgcount);
counter = (int) dmgcount; counter = (int) dmgcount;
if (!counter) if (!counter)
return; return;
tmp_dam = (struct damage *) alloc(sizeof(struct damage)); do {
while (--counter >= 0) { tmp_dam = (struct damage *) alloc(sizeof *tmp_dam);
char damaged_shops[5], *shp = (char *) 0;
if (nhfp->structlevel) if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) tmp_dam, sizeof(*tmp_dam)); mread(nhfp->fd, (genericptr_t) tmp_dam, sizeof *tmp_dam);
if (ghostly) if (ghostly)
tmp_dam->when += (g.moves - g.omoves); tmp_dam->when += (g.moves - g.omoves);
/* tmp_dam->next = g.level.damagelist;
* This should be removed and handled separately when returning g.level.damagelist = tmp_dam;
* to a level. It's a holdover from when restore would catch up } while (--counter > 0);
* for lost time on any level as it went through all the levels
* instead of just splitting the save file into individual level
* files.
*/
Strcpy(damaged_shops,
in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE));
if (u.uz.dlevel) {
/* when restoring, there are two passes over the current
* level. the first time, u.uz isn't set, so neither is
* shop_keeper(). just wait and process the damage on
* the second pass.
*/
for (shp = damaged_shops; *shp; shp++) {
struct monst *shkp = shop_keeper(*shp);
if (shkp && inhishop(shkp)
&& repair_damage(shkp, tmp_dam, TRUE))
break;
}
}
if (!shp || !*shp) {
tmp_dam->next = g.level.damagelist;
g.level.damagelist = tmp_dam;
tmp_dam = (struct damage *) alloc(sizeof(*tmp_dam));
}
}
free((genericptr_t) tmp_dam);
} }
/* restore one object */ /* restore one object */

View File

@@ -156,7 +156,7 @@ money2u(struct monst* mon, long amount)
} }
static struct monst * static struct monst *
next_shkp(register struct monst* shkp, register boolean withbill) next_shkp(register struct monst *shkp, boolean withbill)
{ {
for (; shkp; shkp = shkp->nmon) { for (; shkp; shkp = shkp->nmon) {
if (DEADMONSTER(shkp)) if (DEADMONSTER(shkp))
@@ -1983,9 +1983,11 @@ find_oid(unsigned int id)
/* Returns the price of an arbitrary item in the shop, /* Returns the price of an arbitrary item in the shop,
0 if the item doesn't belong to a shopkeeper or hero is not in the shop. */ 0 if the item doesn't belong to a shopkeeper or hero is not in the shop. */
long long
get_cost_of_shop_item(register struct obj* obj, int* nochrg) get_cost_of_shop_item(
/* alternate return value: 1: no charge, 0: shop owned, */ struct obj *obj,
{ /* -1: not in a shop (so should't be formatted as "no charge") */ int *nochrg) /* alternate return value: 1: no charge, 0: shop owned,
* -1: not in a shop (so don't format as "no charge") */
{
struct monst *shkp; struct monst *shkp;
struct obj *top; struct obj *top;
xchar x, y; xchar x, y;
@@ -3632,7 +3634,7 @@ discard_damage_owned_by(struct monst *shkp)
/* Shopkeeper tries to repair damage belonging to them */ /* Shopkeeper tries to repair damage belonging to them */
static void static void
shk_fixes_damage(struct monst* shkp) shk_fixes_damage(struct monst *shkp)
{ {
struct damage *dam = find_damage(shkp); struct damage *dam = find_damage(shkp);
boolean shk_closeby; boolean shk_closeby;
@@ -3649,7 +3651,7 @@ shk_fixes_damage(struct monst* shkp)
else if (!Deaf && shk_closeby) else if (!Deaf && shk_closeby)
You_hear("someone muttering an incantation."); You_hear("someone muttering an incantation.");
(void) repair_damage(shkp, dam, FALSE); (void) repair_damage(shkp, dam);
discard_damage_struct(dam); discard_damage_struct(dam);
} }
@@ -3769,19 +3771,19 @@ litter_newsyms(xchar *litter, xchar x, xchar y)
int int
repair_damage( repair_damage(
struct monst *shkp, struct monst *shkp,
struct damage *tmp_dam, struct damage *tmp_dam)
boolean catchup) /* restoring a level */
{ {
xchar x, y; xchar x, y;
xchar *litter; xchar *litter;
struct obj *otmp; struct obj *otmp;
struct trap *ttmp; struct trap *ttmp;
int k, disposition = 1; int k, disposition = 1;
boolean stop_picking = FALSE; boolean catchup, stop_picking = FALSE;
if (!repairable_damage(tmp_dam, shkp)) if (!repairable_damage(tmp_dam, shkp))
return 0; return 0;
catchup = g.moves > tmp_dam->when + REPAIR_DELAY;
x = tmp_dam->place.x; x = tmp_dam->place.x;
y = tmp_dam->place.y; y = tmp_dam->place.y;
@@ -3873,11 +3875,25 @@ repair_damage(
return disposition; return disposition;
} }
/* normally repair is done when a shopkeeper moves, but we also try to
catch up for lost time when reloading a previously visited level */
void
fix_shop_damage(void)
{
struct monst *shkp;
for (shkp = next_shkp(fmon, FALSE); shkp;
shkp = next_shkp(shkp->nmon, FALSE)) {
if (shkp->mcanmove && inhishop(shkp))
shk_fixes_damage(shkp);
}
}
/* /*
* shk_move: return 1: moved 0: didn't -1: let m_move do it -2: died * shk_move: return 1: moved 0: didn't -1: let m_move do it -2: died
*/ */
int int
shk_move(struct monst* shkp) shk_move(struct monst *shkp)
{ {
xchar gx, gy, omx, omy; xchar gx, gy, omx, omy;
int udist; int udist;