Save and restore hero tracks

The tracks left by hero were cleared when player saved and
restored the game, or changed levels.  Now the tracks are
saved in the dungeon level, so changing levels keeps the tracks
left by hero in that level.

Also increased the length of tracks from 50 to 100, and
simplify the tracking function.

Thing not done: fade out old tracks when returning to a level.

Breaks saves and bones.
This commit is contained in:
Pasi Kallinen
2023-12-04 17:44:51 +02:00
parent 2713853f28
commit d8421aa219
9 changed files with 51 additions and 17 deletions

View File

@@ -1311,6 +1311,7 @@ if a monster fled from hero by intentionally jumping into a vault teleporter,
but the spot would remain a secret corridor and not become accessible
spellbooks weight 50 units but Book of the Dead only 20, and novels only 1;
the Book of the Dead has been changed to 50 and novels to 10
save and restore hero tracks, increase track length
Fixes to 3.7.0-x General Problems Exposed Via git Repository

View File

@@ -2919,6 +2919,9 @@ extern int tt_doppel(struct monst *);
extern void initrack(void);
extern void settrack(void);
extern coord *gettrack(coordxy, coordxy);
extern void save_track(NHFILE *);
extern void rest_track(NHFILE *);
extern void printtrack(void);
/* ### trap.c ### */

View File

@@ -17,7 +17,7 @@
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
#define EDITLEVEL 90
#define EDITLEVEL 91
/*
* Development status possibilities.

View File

@@ -77,6 +77,7 @@ moveloop_preamble(boolean resuming)
/* give hero initial movement points; new game only--for restore,
pending movement points were included in the save file */
u.umovement = NORMAL_SPEED;
initrack();
}
gc.context.botlx = TRUE; /* for STATUS_HILITES */
if (resuming) { /* restoring old game */
@@ -89,7 +90,6 @@ moveloop_preamble(boolean resuming)
gd.defer_see_monsters = FALSE;
see_monsters();
}
initrack();
u.uz0.dlevel = u.uz.dlevel;
gc.context.move = 0;

View File

@@ -1787,8 +1787,6 @@ goto_level(
if ((mtmp = m_at(u.ux, u.uy)) != 0)
u_collide_m(mtmp);
initrack();
/* initial movement of bubbles just before vision_recalc */
if (Is_waterlevel(&u.uz) || Is_airlevel(&u.uz))
movebubbles();

View File

@@ -1150,6 +1150,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
rest_regions(nhfp);
rest_bubbles(nhfp); /* for water and air; empty marker on other levels */
load_exclusions(nhfp);
rest_track(nhfp);
if (ghostly) {
stairway *stway = gs.stairs;

View File

@@ -554,6 +554,7 @@ savelev_core(NHFILE *nhfp, xint8 lev)
save_regions(nhfp);
save_bubbles(nhfp, lev); /* for water and air */
save_exclusions(nhfp);
save_track(nhfp);
if (nhfp->mode != FREEING) {
if (nhfp->structlevel)

View File

@@ -502,7 +502,6 @@ teleds(coordxy nux, coordxy nuy, int teleds_flags)
fill_pit(u.ux0, u.uy0);
if (ball_active && uchain && uchain->where == OBJ_FREE)
placebc(); /* put back the ball&chain if they were taken off map */
initrack(); /* teleports mess up tracking monsters without this */
update_player_regions();
/*
* Make sure the hero disappears from the old location. This will

View File

@@ -6,7 +6,7 @@
#include "hack.h"
#define UTSZ 50
#define UTSZ 100
static NEARDATA int utcnt, utpnt;
static NEARDATA coord utrack[UTSZ];
@@ -15,6 +15,7 @@ void
initrack(void)
{
utcnt = utpnt = 0;
(void) memset((genericptr_t) &utrack, 0, sizeof(utrack));
}
/* add to track */
@@ -30,6 +31,8 @@ settrack(void)
utpnt++;
}
/* get a track coord on or next to x,y and last tracked by hero,
returns null if no such track */
coord *
gettrack(coordxy x, coordxy y)
{
@@ -43,20 +46,48 @@ gettrack(coordxy x, coordxy y)
tc--;
ndist = distmin(x, y, tc->x, tc->y);
/* if far away, skip track entries til we're closer */
if (ndist > 2) {
ndist -= 2; /* be careful due to extra decrement at top of loop */
cnt -= ndist;
if (cnt <= 0)
return (coord *) 0; /* too far away, no matches possible */
if (tc < &utrack[ndist])
tc += (UTSZ - ndist);
else
tc -= ndist;
} else if (ndist <= 1)
if (ndist <= 1)
return (ndist ? tc : 0);
}
return (coord *) 0;
}
/* save the hero tracking info */
void
save_track(NHFILE *nhfp)
{
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel) {
int i;
bwrite(nhfp->fd, (genericptr_t) &utcnt, sizeof utcnt);
bwrite(nhfp->fd, (genericptr_t) &utpnt, sizeof utpnt);
for (i = 0; i < utcnt; i++) {
bwrite(nhfp->fd, (genericptr_t) &utrack[i].x, sizeof utrack[i].x);
bwrite(nhfp->fd, (genericptr_t) &utrack[i].y, sizeof utrack[i].y);
}
}
}
if (release_data(nhfp))
initrack();
}
/* restore the hero tracking info */
void
rest_track(NHFILE *nhfp)
{
if (nhfp->structlevel) {
int i;
mread(nhfp->fd, (genericptr_t) &utcnt, sizeof utcnt);
mread(nhfp->fd, (genericptr_t) &utpnt, sizeof utpnt);
if (utcnt > UTSZ || utpnt > UTSZ)
panic("rest_track: impossible pt counts");
for (i = 0; i < utcnt; i++) {
mread(nhfp->fd, (genericptr_t) &utrack[i].x, sizeof utrack[i].x);
mread(nhfp->fd, (genericptr_t) &utrack[i].y, sizeof utrack[i].y);
}
}
}
/*track.c*/