save/restore changes - part 3
This is the third of a series of savefile-related changes.
This adds early-days experimental support for a completely optional
'sfctool' utility (savefile conversion tool), to be able to export
a savefile's contents into a more portable format. There are likely
to be bugs at this stage. In this initial first-attempt, the export
format is a very simple ascii output.
NetHack can be built entirely, without also building this tool.
NetHack has no dependencies on the tool.
Attempts were made to minimize duplication of existing NetHack code.
To achieve that, unfortunately, #ifdef SFCTOOL and #ifndef SFCTOOL
had to be sprinkled around through some of the existing NetHack
source code, so that it could be re-used for building the utility.
The process for building the sfctool typically recompiles the source
files with #define SFCTOOL and a distinct object file with SF- is
produced.
sfctool notes:
Universal ctags is used and required to produce the sfctool utility.
Some targets were added to the Unix and Windows Makefiles to
facilitate the build process.
make sfctool
That should build a copy in util.
Note: At present, the Unix Makefiles do not copy sfctool over to the
NetHack playground during 'make install' or 'make update'.
Until that gets resolved by someone, The tool will
have to be manually copied there by the builder/admin if
desired.
cp util/sfctool ~/nh/install/games/lib/nethackdir/sfctool
Also, a separate Visual Studio sfctool.sln solution was written and
placed in sys/windows/vs. That has has only very limited testing.
Usage:
i) To convert an existing savefile to an exportascii format
that co-resides with the savefile:
sfctool -c savefile
That *must* be executed on the same platform / architecture /
data model that produced the save file in the first place.
ii) To unconvert an existing exportascii format export file to a
historical format savefile that can then be used by NetHack:
sfctool -u savefile
That must be executed on the same target platform / architecture /
data model that was used to build the NetHack that will
utilize the save file that results.
A Windows example:
sfctool -c Fred.NetHack-saved-game
That should result in creation of Fred.NetHack-saved-game.exportascii
from existing savefile:
%USERPROFILE%\AppData\Local\NetHack\3.7\Fred.NetHack-saved-game
A Unix example:
sfctool -c 1000wizard
That should result in creation of 1000wizard.exportascii.gz
from existing savefile in the playground save directory:
1000wizard.gz
Current Mechanics:
1. Makefile recipe, or script uses universal ctags to produce
util/sf.tags.
2. util/sftags is built and executed to read util/sf.tags and
generate: include/sfproto.h and src/sfdata.c.
3. util/sfctool is built from the following:
generated file compiled with -DSFCTOOL:
src/sfdata.c -> sfdata.o
existing files compiled with -DSFCTOOL:
util/sfctool.c -> sfctool.o
util/sfexpasc.c -> sfexpasc.o
src/alloc.c -> sf-alloc.o
src/monst.c -> sf-monst.o
src/objects.c -> sf-objects.o
src/sfbase.c -> sfbase.o
src/sfstruct.c -> sfstruct.o
src/nhlua.c -> sf-nhlua.o
util/panic.c -> panic.o
src/date.c -> sf-date.o
src/decl.c -> sf-decl.o
src/artifact.c -> sf-artifact.o
src/dungeon.c -> sf-dungeon.o
src/end.c -> sf-end.o
src/engrave.c -> sf-engrave.o
src/cfgfiles.c -> sf-cfgfiles.o
src/files.c -> sf-files.o
src/light.c -> sf-light.o
src/mdlib.c -> sf-mdlib.o
src/mkmaze.c -> sf-mkmaze.o
src/mkroom.c -> sf-mkroom.o
src/o_init.c -> sf-o_init.o
src/region.c -> sf-region.o
src/restore.c -> sf-restore.o
src/rumors.c -> sf-rumors.o
src/sys.c -> sf-sys.o
src/timeout.c -> sf-timeout.o
src/track.c -> sf-track.o
src/version.c -> sf-version.o
src/worm.c -> sf-worm.o
src/strutil.c -> strutil.o
This commit is contained in:
139
src/restore.c
139
src/restore.c
@@ -22,6 +22,7 @@ staticfn struct fruit *loadfruitchn(NHFILE *);
|
||||
staticfn void freefruitchn(struct fruit *);
|
||||
staticfn void rest_levl(NHFILE *);
|
||||
staticfn void rest_stairs(NHFILE *);
|
||||
#ifndef SFCTOOL
|
||||
staticfn void ghostfruit(struct obj *);
|
||||
staticfn boolean restgamestate(NHFILE *);
|
||||
staticfn void restlevelstate(void);
|
||||
@@ -29,10 +30,12 @@ staticfn int restlevelfile(xint8);
|
||||
staticfn void rest_bubbles(NHFILE *);
|
||||
staticfn void restore_gamelog(NHFILE *);
|
||||
staticfn void reset_oattached_mids(boolean);
|
||||
/* these ones are declared non-static in extern.h if SFCTOOL is defined */
|
||||
staticfn boolean restgamestate(NHFILE *);
|
||||
staticfn void rest_bubbles(NHFILE *);
|
||||
staticfn void restore_gamelog(NHFILE *);
|
||||
staticfn void restore_msghistory(NHFILE *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Save a mapping of IDs from ghost levels to the current level. This
|
||||
@@ -47,8 +50,10 @@ struct bucket {
|
||||
} map[N_PER_BUCKET];
|
||||
};
|
||||
|
||||
#ifndef SFCTOOL
|
||||
staticfn void clear_id_mapping(void);
|
||||
staticfn void add_id_mapping(unsigned, unsigned);
|
||||
#endif /* SFCTOOL */
|
||||
|
||||
#ifdef AMII_GRAPHICS
|
||||
void amii_setpens(int); /* use colors from save file */
|
||||
@@ -59,6 +64,7 @@ extern int amii_numcolors;
|
||||
|
||||
#define Is_IceBox(o) ((o)->otyp == ICE_BOX ? TRUE : FALSE)
|
||||
|
||||
#ifndef SFCTOOL
|
||||
/* Recalculate svl.level.objects[x][y], since this info was not saved. */
|
||||
|
||||
staticfn void
|
||||
@@ -118,6 +124,8 @@ inven_inuse(boolean quietly)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SFCTOOL */
|
||||
|
||||
staticfn void
|
||||
restlevchn(NHFILE *nhfp)
|
||||
{
|
||||
@@ -147,7 +155,9 @@ restdamage(NHFILE *nhfp)
|
||||
unsigned int dmgcount = 0;
|
||||
int counter;
|
||||
struct damage *tmp_dam;
|
||||
#ifndef SFCTOOL
|
||||
boolean ghostly = (nhfp->ftype == NHF_BONESFILE);
|
||||
#endif
|
||||
|
||||
Sfi_unsigned(nhfp, &dmgcount, "damage-damage_count");
|
||||
counter = (int) dmgcount;
|
||||
@@ -158,11 +168,13 @@ restdamage(NHFILE *nhfp)
|
||||
tmp_dam = (struct damage *) alloc(sizeof *tmp_dam);
|
||||
|
||||
Sfi_damage(nhfp, tmp_dam, "damage");
|
||||
#ifndef SFCTOOL
|
||||
if (ghostly)
|
||||
tmp_dam->when += (svm.moves - svo.omoves);
|
||||
|
||||
tmp_dam->next = svl.level.damagelist;
|
||||
svl.level.damagelist = tmp_dam;
|
||||
#endif /* !SFCTOOL */
|
||||
} while (--counter > 0);
|
||||
}
|
||||
|
||||
@@ -199,7 +211,7 @@ restobj(NHFILE *nhfp, struct obj *otmp)
|
||||
}
|
||||
|
||||
/* omailcmd - feedback mechanism for scroll of mail */
|
||||
Sfi_int(nhfp, &buflen, "obj-omail_length");
|
||||
Sfi_int(nhfp, &buflen, "obj-omailcmd_length");
|
||||
if (buflen > 0) {
|
||||
char *omailcmd = (char *) alloc(buflen);
|
||||
|
||||
@@ -210,7 +222,7 @@ restobj(NHFILE *nhfp, struct obj *otmp)
|
||||
|
||||
/* omid - monster id number, connecting corpse to ghost */
|
||||
newomid(otmp); /* superfluous; we're already allocated otmp->oextra */
|
||||
Sfi_unsigned(nhfp, &omid, "obj-omid_length");
|
||||
Sfi_unsigned(nhfp, &omid, "obj-omid");
|
||||
OMID(otmp) = omid;
|
||||
}
|
||||
}
|
||||
@@ -221,10 +233,15 @@ restobjchn(NHFILE *nhfp, boolean frozen)
|
||||
struct obj *otmp, *otmp2 = 0;
|
||||
struct obj *first = (struct obj *) 0;
|
||||
int buflen = 0;
|
||||
#ifndef SFCTOOL
|
||||
boolean ghostly = (nhfp->ftype == NHF_BONESFILE);
|
||||
#endif
|
||||
boolean trouble = FALSE;
|
||||
|
||||
while (1) {
|
||||
Sfi_int(nhfp, &buflen, "obj-obj_length");
|
||||
if (!(buflen != -1 || buflen != sizeof (struct obj)))
|
||||
trouble = TRUE;
|
||||
if (buflen == -1)
|
||||
break;
|
||||
|
||||
@@ -236,6 +253,7 @@ restobjchn(NHFILE *nhfp, boolean frozen)
|
||||
else
|
||||
otmp2->nobj = otmp;
|
||||
|
||||
#ifndef SFCTOOL
|
||||
if (ghostly) {
|
||||
unsigned nid = next_ident();
|
||||
|
||||
@@ -250,6 +268,7 @@ restobjchn(NHFILE *nhfp, boolean frozen)
|
||||
*/
|
||||
if (ghostly && !frozen && !age_is_relative(otmp))
|
||||
otmp->age = svm.moves - svo.omoves + otmp->age;
|
||||
#endif /* !SFCTOOL */
|
||||
|
||||
/* get contents of a container or statue */
|
||||
if (Has_contents(otmp)) {
|
||||
@@ -261,6 +280,7 @@ restobjchn(NHFILE *nhfp, boolean frozen)
|
||||
otmp3->ocontainer = otmp;
|
||||
}
|
||||
|
||||
#ifndef SFCTOOL
|
||||
if (otmp->bypass)
|
||||
otmp->bypass = 0;
|
||||
if (!ghostly) {
|
||||
@@ -272,12 +292,17 @@ restobjchn(NHFILE *nhfp, boolean frozen)
|
||||
if (otmp->o_id == svc.context.spbook.o_id)
|
||||
svc.context.spbook.book = otmp;
|
||||
}
|
||||
#endif /* !SFADUSTER */
|
||||
otmp2 = otmp;
|
||||
}
|
||||
if (first && otmp2->nobj) {
|
||||
impossible("Restobjchn: error reading objchn.");
|
||||
otmp2->nobj = 0;
|
||||
}
|
||||
#ifdef SFCTOOL
|
||||
nhUse(frozen);
|
||||
#endif
|
||||
nhUse(trouble);
|
||||
return first;
|
||||
}
|
||||
|
||||
@@ -353,8 +378,11 @@ restmonchn(NHFILE *nhfp)
|
||||
{
|
||||
struct monst *mtmp, *mtmp2 = 0;
|
||||
struct monst *first = (struct monst *) 0;
|
||||
int offset, buflen = 0;
|
||||
int buflen = 0;
|
||||
#ifndef SFCTOOL
|
||||
int offset;
|
||||
boolean ghostly = (nhfp->ftype == NHF_BONESFILE);
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
Sfi_int(nhfp, &buflen, "monst-monst_length");
|
||||
@@ -369,6 +397,7 @@ restmonchn(NHFILE *nhfp)
|
||||
else
|
||||
mtmp2->nmon = mtmp;
|
||||
|
||||
#ifndef SFCTOOL
|
||||
if (ghostly) {
|
||||
unsigned nid = next_ident();
|
||||
|
||||
@@ -386,13 +415,21 @@ restmonchn(NHFILE *nhfp)
|
||||
mtmp->mhpmax = DEFUNCT_MONSTER;
|
||||
}
|
||||
}
|
||||
#endif /* !SFCTOOL */
|
||||
|
||||
if (mtmp->minvent) {
|
||||
struct obj *obj;
|
||||
mtmp->minvent = restobjchn(nhfp, FALSE);
|
||||
#ifndef SFCTOOL
|
||||
/* restore monster back pointer */
|
||||
for (obj = mtmp->minvent; obj; obj = obj->nobj)
|
||||
obj->ocarry = mtmp;
|
||||
#else
|
||||
nhUse(obj);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef SFCTOOL
|
||||
if (mtmp->mw) {
|
||||
struct obj *obj;
|
||||
|
||||
@@ -416,12 +453,15 @@ restmonchn(NHFILE *nhfp)
|
||||
if (mtmp->m_id == svc.context.polearm.m_id)
|
||||
svc.context.polearm.hitmon = mtmp;
|
||||
}
|
||||
#endif /* !SFCTOOL */
|
||||
mtmp2 = mtmp;
|
||||
}
|
||||
#ifndef SFCTOOL
|
||||
if (first && mtmp2->nmon) {
|
||||
impossible("Restmonchn: error reading monchn.");
|
||||
mtmp2->nmon = 0;
|
||||
}
|
||||
#endif
|
||||
return first;
|
||||
}
|
||||
|
||||
@@ -456,6 +496,7 @@ freefruitchn(struct fruit *flist)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SFCTOOL
|
||||
staticfn void
|
||||
ghostfruit(struct obj *otmp)
|
||||
{
|
||||
@@ -470,6 +511,7 @@ ghostfruit(struct obj *otmp)
|
||||
else
|
||||
otmp->spe = fruitadd(oldf->fname, (struct fruit *) 0);
|
||||
}
|
||||
#endif /* !SFCTOOL */
|
||||
|
||||
#ifdef SYSCF
|
||||
#define SYSOPT_CHECK_SAVE_UID sysopt.check_save_uid
|
||||
@@ -477,7 +519,10 @@ ghostfruit(struct obj *otmp)
|
||||
#define SYSOPT_CHECK_SAVE_UID TRUE
|
||||
#endif
|
||||
|
||||
staticfn boolean
|
||||
#ifndef SFCTOOL
|
||||
staticfn
|
||||
#endif
|
||||
boolean
|
||||
restgamestate(NHFILE *nhfp)
|
||||
{
|
||||
int i;
|
||||
@@ -486,15 +531,18 @@ restgamestate(NHFILE *nhfp)
|
||||
struct obj *bc_obj;
|
||||
char timebuf[15];
|
||||
unsigned long uid = 0;
|
||||
#ifndef SFCTOOL
|
||||
boolean defer_perm_invent, restoring_special;
|
||||
struct obj *otmp;
|
||||
#endif
|
||||
|
||||
Sfi_ulong(nhfp, &uid, "gamestate-uid");
|
||||
#ifndef SFCTOOL
|
||||
if (SYSOPT_CHECK_SAVE_UID
|
||||
&& uid != (unsigned long) getuid()) { /* strange ... */
|
||||
if (!gc.converted_savefile_loaded)
|
||||
/* for wizard mode, issue a reminder; for others, treat it
|
||||
as an attempt to cheat and refuse to restore this file */
|
||||
* as an attempt to cheat and refuse to restore this file */
|
||||
pline("Saved game was not yours.");
|
||||
if (wizard || gc.converted_savefile_loaded) {
|
||||
if (gc.converted_savefile_loaded)
|
||||
@@ -503,7 +551,7 @@ restgamestate(NHFILE *nhfp)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SFCTOOL */
|
||||
newgamecontext = svc.context; /* copy statically init'd context */
|
||||
Sfi_context_info(nhfp, &svc.context, "gamestate-context");
|
||||
svc.context.warntype.species = (ismnum(svc.context.warntype.speciesidx))
|
||||
@@ -519,6 +567,7 @@ restgamestate(NHFILE *nhfp)
|
||||
newgameflags = flags;
|
||||
Sfi_flag(nhfp, &flags, "gamestate-flags");
|
||||
|
||||
#ifndef SFCTOOL
|
||||
/* 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;
|
||||
@@ -545,16 +594,18 @@ restgamestate(NHFILE *nhfp)
|
||||
#ifdef AMII_GRAPHICS
|
||||
amii_setpens(amii_numcolors); /* use colors from save file */
|
||||
#endif
|
||||
|
||||
#endif /* !SFCTOOL */
|
||||
Sfi_you(nhfp, &u, "gamestate-you");
|
||||
gy.youmonst.cham = u.mcham;
|
||||
|
||||
#ifndef SFCTOOL
|
||||
if (restoring_special && iflags.explore_error_flag) {
|
||||
/* savefile has wizard or explore mode, but player is no longer
|
||||
authorized to access either; can't downgrade mode any further, so
|
||||
fail restoration. */
|
||||
u.uhp = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
Sfi_char(nhfp, timebuf, "gamestate-ubirthday", 14);
|
||||
timebuf[14] = '\0';
|
||||
@@ -562,6 +613,7 @@ restgamestate(NHFILE *nhfp)
|
||||
Sfi_long(nhfp, &urealtime.realtime, "gamestate-realtime");
|
||||
Sfi_char(nhfp, timebuf, "gamestate-start_timing", 14);
|
||||
timebuf[14] = '\0';
|
||||
#ifndef SFCTOOL
|
||||
urealtime.start_timing = time_from_yyyymmddhhmmss(timebuf);
|
||||
|
||||
/* current time is the time to use for next urealtime.realtime update */
|
||||
@@ -590,6 +642,7 @@ restgamestate(NHFILE *nhfp)
|
||||
}
|
||||
/* in case hangup save occurred in midst of level change */
|
||||
assign_level(&u.uz0, &u.uz);
|
||||
#endif /* !SFCTOOL */
|
||||
|
||||
/* this stuff comes after potential aborted restore attempts */
|
||||
restore_killers(nhfp);
|
||||
@@ -600,7 +653,7 @@ restgamestate(NHFILE *nhfp)
|
||||
|
||||
/* restore dangling (not on floor or in inventory) ball and/or chain */
|
||||
bc_obj = restobjchn(nhfp, FALSE);
|
||||
|
||||
#ifndef SFCTOOL
|
||||
while (bc_obj) {
|
||||
struct obj *nobj = bc_obj->nobj;
|
||||
|
||||
@@ -609,13 +662,15 @@ restgamestate(NHFILE *nhfp)
|
||||
setworn(bc_obj, bc_obj->owornmask);
|
||||
bc_obj = nobj;
|
||||
}
|
||||
|
||||
#endif
|
||||
gm.migrating_objs = restobjchn(nhfp, FALSE);
|
||||
gm.migrating_mons = restmonchn(nhfp);
|
||||
|
||||
for (i = 0; i < NUMMONS; ++i) {
|
||||
Sfi_mvitals(nhfp, &svm.mvitals[i], "gamestate-mvitals");
|
||||
}
|
||||
|
||||
#ifndef SFCTOOL
|
||||
/*
|
||||
* There are some things after this that can have unintended display
|
||||
* side-effects too early in the game.
|
||||
@@ -637,6 +692,7 @@ restgamestate(NHFILE *nhfp)
|
||||
setuwep(otmp); /* (don't need any null check here) */
|
||||
if (!uwep || uwep->otyp == PICK_AXE || uwep->otyp == GRAPPLING_HOOK)
|
||||
gu.unweapon = TRUE;
|
||||
#endif /* !SFCTOOL */
|
||||
|
||||
restore_dungeon(nhfp);
|
||||
restlevchn(nhfp);
|
||||
@@ -660,15 +716,22 @@ restgamestate(NHFILE *nhfp)
|
||||
restore_msghistory(nhfp);
|
||||
restore_gamelog(nhfp);
|
||||
restore_luadata(nhfp);
|
||||
#ifndef SFCTOOL
|
||||
/* must come after all mons & objs are restored */
|
||||
relink_timers(FALSE);
|
||||
relink_light_sources(FALSE);
|
||||
adj_erinys(u.ualign.abuse);
|
||||
/* inventory display is now viable */
|
||||
iflags.perm_invent = defer_perm_invent;
|
||||
#else
|
||||
nhUse(bc_obj);
|
||||
nhUse(newgamecontext);
|
||||
nhUse(newgameflags);
|
||||
#endif /* !SFCTOOL */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifndef SFCTOOL
|
||||
/* update game state pointers to those valid for the current level (so we
|
||||
don't dereference a wild u.ustuck when saving game state, for instance) */
|
||||
staticfn void
|
||||
@@ -886,15 +949,20 @@ dorecover(NHFILE *nhfp)
|
||||
check_special_room(FALSE);
|
||||
return 1;
|
||||
}
|
||||
#endif /* !SFCTOOL */
|
||||
|
||||
staticfn void
|
||||
rest_stairs(NHFILE *nhfp)
|
||||
{
|
||||
int buflen = 0;
|
||||
stairway stway = UNDEFINED_VALUES;
|
||||
#ifndef SFCTOOL
|
||||
stairway *newst;
|
||||
#endif
|
||||
|
||||
#ifndef SFCTOOL
|
||||
stairway_free_all();
|
||||
#endif
|
||||
while (1) {
|
||||
Sfi_int(nhfp, &buflen, "stairs-staircount");
|
||||
if (buflen == -1)
|
||||
@@ -906,11 +974,13 @@ rest_stairs(NHFILE *nhfp)
|
||||
/* stairway dlevel is relative, make it absolute */
|
||||
stway.tolev.dlevel += u.uz.dlevel;
|
||||
}
|
||||
#ifndef SFCTOOL
|
||||
stairway_add(stway.sx, stway.sy, stway.up, stway.isladder,
|
||||
&(stway.tolev));
|
||||
newst = stairway_at(stway.sx, stway.sy);
|
||||
if (newst)
|
||||
newst->u_traversed = stway.u_traversed;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -932,7 +1002,8 @@ restcemetery(NHFILE *nhfp, struct cemetery **cemeteryaddr)
|
||||
} else {
|
||||
*cemeteryaddr = 0;
|
||||
}
|
||||
if ((nhfp->mode & CONVERTING) != 0) {
|
||||
if (((nhfp->mode & CONVERTING) != 0)
|
||||
|| ((nhfp->mode & UNCONVERTING) != 0)) {
|
||||
struct cemetery *thisbones, *nextbones;
|
||||
|
||||
/* free the memory */
|
||||
@@ -958,6 +1029,8 @@ rest_levl(NHFILE *nhfp)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SFCTOOL
|
||||
|
||||
void
|
||||
trickery(char *reason)
|
||||
{
|
||||
@@ -967,14 +1040,17 @@ trickery(char *reason)
|
||||
Strcpy(svk.killer.name, reason ? reason : "");
|
||||
done(TRICKED);
|
||||
}
|
||||
#endif /* !SFCTOOL */
|
||||
|
||||
void
|
||||
getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
{
|
||||
struct trap *trap;
|
||||
#ifndef SFCTOOL
|
||||
struct monst *mtmp;
|
||||
branch *br;
|
||||
int x, y;
|
||||
#endif
|
||||
long elapsed = 0L;
|
||||
int hpid = 0;
|
||||
xint8 dlvl = 0;
|
||||
@@ -986,9 +1062,11 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
#endif
|
||||
|
||||
program_state.in_getlev = TRUE;
|
||||
#ifndef SFCTOOL
|
||||
|
||||
if (ghostly)
|
||||
clear_id_mapping();
|
||||
#endif /* !SFCTOOL */
|
||||
|
||||
#if 0
|
||||
#if defined(MSDOS) || defined(OS2)
|
||||
@@ -1007,6 +1085,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
Sfi_int(nhfp, &hpid, "gamestate-hackpid");
|
||||
/* CHECK: This may prevent restoration */
|
||||
Sfi_xint8(nhfp, &dlvl, "gamestate-dlvl");
|
||||
#ifndef SFCTOOL
|
||||
if ((pid && pid != hpid) || (lev && dlvl != lev)) {
|
||||
char trickbuf[BUFSZ];
|
||||
|
||||
@@ -1019,6 +1098,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
pline1(trickbuf);
|
||||
trickery(trickbuf);
|
||||
}
|
||||
#endif
|
||||
restcemetery(nhfp, &svl.level.bonesinfo);
|
||||
rest_levl(nhfp);
|
||||
|
||||
@@ -1051,10 +1131,14 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
}
|
||||
rest_rooms(nhfp); /* No joke :-) */
|
||||
if (svn.nroom) {
|
||||
#ifndef SFCTOOL
|
||||
gd.doorindex = svr.rooms[svn.nroom - 1].fdoor
|
||||
+ svr.rooms[svn.nroom - 1].doorct;
|
||||
} else {
|
||||
gd.doorindex = 0;
|
||||
#else
|
||||
gd.doorindex = 0;
|
||||
#endif /* !SFCTOOL */
|
||||
}
|
||||
|
||||
restore_timers(nhfp, RANGE_LEVEL, elapsed);
|
||||
@@ -1080,14 +1164,16 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
dealloc_trap(trap);
|
||||
|
||||
fobj = restobjchn(nhfp, FALSE);
|
||||
#ifndef SFCTOOL
|
||||
find_lev_obj();
|
||||
#endif /* !SFCTOOL */
|
||||
/* restobjchn()'s `frozen' argument probably ought to be a callback
|
||||
routine so that we can check for objects being buried under ice */
|
||||
svl.level.buriedobjlist = restobjchn(nhfp, FALSE);
|
||||
gb.billobjs = restobjchn(nhfp, FALSE);
|
||||
rest_engravings(nhfp);
|
||||
|
||||
|
||||
#ifndef SFCTOOL
|
||||
/* reset level.monsters for new level */
|
||||
for (x = 0; x < COLNO; x++)
|
||||
for (y = 0; y < ROWNO; y++)
|
||||
@@ -1133,6 +1219,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
if (ghostly || (elapsed > 00 && elapsed > (long) rnd(10)))
|
||||
hide_monst(mtmp);
|
||||
}
|
||||
#endif /* !SFCTOOL */
|
||||
|
||||
restdamage(nhfp);
|
||||
rest_regions(nhfp);
|
||||
@@ -1140,6 +1227,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
load_exclusions(nhfp);
|
||||
rest_track(nhfp);
|
||||
|
||||
#ifndef SFCTOOL
|
||||
if (ghostly) {
|
||||
stairway *stway = gs.stairs;
|
||||
while (stway) {
|
||||
@@ -1215,6 +1303,11 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
if (ghostly)
|
||||
clear_id_mapping();
|
||||
program_state.in_getlev = FALSE;
|
||||
#else
|
||||
nhUse(pid);
|
||||
nhUse(lev);
|
||||
#endif /* !SFCTOOL */
|
||||
program_state.in_getlev = FALSE;
|
||||
}
|
||||
|
||||
/* "name-role-race-gend-algn" occurs very early in a save file; sometimes we
|
||||
@@ -1247,7 +1340,10 @@ get_plname_from_file(
|
||||
}
|
||||
|
||||
/* restore Plane of Water's air bubbles and Plane of Air's clouds */
|
||||
staticfn void
|
||||
#ifndef SFCTOOL
|
||||
staticfn
|
||||
#endif
|
||||
void
|
||||
rest_bubbles(NHFILE *nhfp)
|
||||
{
|
||||
xint8 bbubbly;
|
||||
@@ -1265,7 +1361,10 @@ rest_bubbles(NHFILE *nhfp)
|
||||
restore_waterlevel(nhfp);
|
||||
}
|
||||
|
||||
staticfn void
|
||||
#ifndef SFCTOOL
|
||||
staticfn
|
||||
#endif
|
||||
void
|
||||
restore_gamelog(NHFILE *nhfp)
|
||||
{
|
||||
int slen = 0;
|
||||
@@ -1281,11 +1380,16 @@ restore_gamelog(NHFILE *nhfp)
|
||||
Sfi_char(nhfp, msg, "gamelog-gamelog_text", slen);
|
||||
msg[slen] = '\0';
|
||||
Sfi_gamelog_line(nhfp, &tmp, "gamelog-gamelog_line");
|
||||
#ifndef SFCTOOL
|
||||
gamelog_add(tmp.flags, tmp.turn, msg);
|
||||
#endif /* !SFCTOOL */
|
||||
}
|
||||
}
|
||||
|
||||
staticfn void
|
||||
#ifndef SFCTOOL
|
||||
staticfn
|
||||
#endif
|
||||
void
|
||||
restore_msghistory(NHFILE *nhfp)
|
||||
{
|
||||
int msgsize = 0;
|
||||
@@ -1300,14 +1404,20 @@ restore_msghistory(NHFILE *nhfp)
|
||||
panic("restore_msghistory: msg too big (%d)", msgsize);
|
||||
Sfi_char(nhfp, msg, "msghistory-msg", msgsize);
|
||||
msg[msgsize] = '\0';
|
||||
#ifndef SFCTOOL
|
||||
putmsghistory(msg, TRUE);
|
||||
#endif /* !SFCTOOL */
|
||||
++msgcount;
|
||||
}
|
||||
#ifndef SFCTOOL
|
||||
if (msgcount)
|
||||
putmsghistory((char *) 0, TRUE);
|
||||
debugpline1("Read %d messages from savefile.", msgcount);
|
||||
#endif /* !SFCTOOL */
|
||||
}
|
||||
|
||||
#ifndef SFCTOOL
|
||||
|
||||
/* Clear all structures for object and monster ID mapping. */
|
||||
staticfn void
|
||||
clear_id_mapping(void)
|
||||
@@ -1483,5 +1593,6 @@ restore_menu(
|
||||
return (ch > 0) ? 1 : ch;
|
||||
}
|
||||
#endif /* SELECTSAVED */
|
||||
#endif /* !SFCTOOL */
|
||||
|
||||
/*restore.c*/
|
||||
|
||||
Reference in New Issue
Block a user