-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
-----------------------------------
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
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
extern int doinvbill(int);
extern struct monst *shkcatch(struct obj *, xchar, xchar);
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 void after_shk_move(struct monst *);
extern boolean is_fshk(struct monst *);
g.context.botlx = TRUE; /* for STATUS_HILITES */
if (resuming) { /* restoring old game */
read_engr_at(u.ux, u.uy); /* subset of pickup() */
+ fix_shop_damage();
}
(void) encumber_msg(); /* in case they auto-picked up something */
}
resetobjs(fobj, TRUE);
resetobjs(g.level.buriedobjlist, TRUE);
+ fix_shop_damage();
}
}
close_nhfile(nhfp);
/* assume this will always return TRUE when changing level */
(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? */
if (do_fall_dmg) {
boolean ghostly = (nhfp->ftype == NHF_BONESFILE);
if (nhfp->structlevel)
- mread(nhfp->fd, (genericptr_t) &dmgcount, sizeof(dmgcount));
+ mread(nhfp->fd, (genericptr_t) &dmgcount, sizeof dmgcount);
counter = (int) dmgcount;
if (!counter)
return;
- tmp_dam = (struct damage *) alloc(sizeof(struct damage));
- while (--counter >= 0) {
- char damaged_shops[5], *shp = (char *) 0;
-
+ do {
+ tmp_dam = (struct damage *) alloc(sizeof *tmp_dam);
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)
tmp_dam->when += (g.moves - g.omoves);
- /*
- * This should be removed and handled separately when returning
- * to a level. It's a holdover from when restore would catch up
- * 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);
+ tmp_dam->next = g.level.damagelist;
+ g.level.damagelist = tmp_dam;
+ } while (--counter > 0);
}
/* restore one object */
}
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) {
if (DEADMONSTER(shkp))
/* 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. */
long
-get_cost_of_shop_item(register struct obj* obj, int* nochrg)
- /* alternate return value: 1: no charge, 0: shop owned, */
-{ /* -1: not in a shop (so should't be formatted as "no charge") */
+get_cost_of_shop_item(
+ struct obj *obj,
+ 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 obj *top;
xchar x, y;
/* Shopkeeper tries to repair damage belonging to them */
static void
-shk_fixes_damage(struct monst* shkp)
+shk_fixes_damage(struct monst *shkp)
{
struct damage *dam = find_damage(shkp);
boolean shk_closeby;
else if (!Deaf && shk_closeby)
You_hear("someone muttering an incantation.");
- (void) repair_damage(shkp, dam, FALSE);
+ (void) repair_damage(shkp, dam);
discard_damage_struct(dam);
}
int
repair_damage(
struct monst *shkp,
- struct damage *tmp_dam,
- boolean catchup) /* restoring a level */
+ struct damage *tmp_dam)
{
xchar x, y;
xchar *litter;
struct obj *otmp;
struct trap *ttmp;
int k, disposition = 1;
- boolean stop_picking = FALSE;
+ boolean catchup, stop_picking = FALSE;
if (!repairable_damage(tmp_dam, shkp))
return 0;
+ catchup = g.moves > tmp_dam->when + REPAIR_DELAY;
x = tmp_dam->place.x;
y = tmp_dam->place.y;
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
*/
int
-shk_move(struct monst* shkp)
+shk_move(struct monst *shkp)
{
xchar gx, gy, omx, omy;
int udist;