mirror of https://gitlab.com/nakst/essence
1887 lines
35 KiB
C
1887 lines
35 KiB
C
//
|
|
// Copyright(C) 1993-1996 Id Software, Inc.
|
|
// Copyright(C) 2005-2014 Simon Howard
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// DESCRIPTION:
|
|
// Archiving: SaveGame I/O.
|
|
//
|
|
|
|
#include "essence/include.h"
|
|
|
|
#include "dstrings.h"
|
|
#include "i_system.h"
|
|
#include "z_zone.h"
|
|
#include "p_local.h"
|
|
#include "p_saveg.h"
|
|
|
|
// State.
|
|
#include "doomstat.h"
|
|
#include "g_game.h"
|
|
#include "m_misc.h"
|
|
#include "r_state.h"
|
|
|
|
#define SAVEGAME_EOF 0x1d
|
|
#define VERSIONSIZE 16
|
|
|
|
ES_File *save_stream;
|
|
int savegamelength;
|
|
boolean savegame_error;
|
|
|
|
// Get the filename of a temporary file to write the savegame to. After
|
|
// the file has been successfully saved, it will be renamed to the
|
|
// real file.
|
|
|
|
char *P_TempSaveGameFile(void)
|
|
{
|
|
static char *filename = NULL;
|
|
|
|
if (filename == NULL)
|
|
{
|
|
filename = M_StringJoin(savegamedir, "temp.dsg", NULL);
|
|
}
|
|
|
|
return filename;
|
|
}
|
|
|
|
// Get the filename of the save game file to use for the specified slot.
|
|
|
|
char *P_SaveGameFile(int slot)
|
|
{
|
|
static char *filename = NULL;
|
|
static size_t filename_size = 0;
|
|
char basename[32];
|
|
|
|
if (filename == NULL)
|
|
{
|
|
filename_size = ES_strlen(savegamedir) + 32;
|
|
filename = ES_malloc(filename_size);
|
|
}
|
|
|
|
M_snprintf(basename, 32, SAVEGAMENAME "%d.dsg", slot);
|
|
M_snprintf(filename, filename_size, "%s%s", savegamedir, basename);
|
|
|
|
return filename;
|
|
}
|
|
|
|
// Endian-safe integer read/write functions
|
|
|
|
static byte saveg_read8(void)
|
|
{
|
|
byte result;
|
|
|
|
if (ES_fread(&result, 1, 1, save_stream) < 1)
|
|
{
|
|
if (!savegame_error)
|
|
{
|
|
ES_errorf("saveg_read8: Unexpected end of file while "
|
|
"reading save game\n");
|
|
|
|
savegame_error = true;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static void saveg_write8(byte value)
|
|
{
|
|
if (ES_fwrite(&value, 1, 1, save_stream) < 1)
|
|
{
|
|
if (!savegame_error)
|
|
{
|
|
ES_errorf("saveg_write8: Error while writing save game\n");
|
|
|
|
savegame_error = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
static short saveg_read16(void)
|
|
{
|
|
int result;
|
|
|
|
result = saveg_read8();
|
|
result |= saveg_read8() << 8;
|
|
|
|
return result;
|
|
}
|
|
|
|
static void saveg_write16(short value)
|
|
{
|
|
saveg_write8(value & 0xff);
|
|
saveg_write8((value >> 8) & 0xff);
|
|
}
|
|
|
|
static int saveg_read32(void)
|
|
{
|
|
int result;
|
|
|
|
result = saveg_read8();
|
|
result |= saveg_read8() << 8;
|
|
result |= saveg_read8() << 16;
|
|
result |= saveg_read8() << 24;
|
|
|
|
return result;
|
|
}
|
|
|
|
static void saveg_write32(int value)
|
|
{
|
|
saveg_write8(value & 0xff);
|
|
saveg_write8((value >> 8) & 0xff);
|
|
saveg_write8((value >> 16) & 0xff);
|
|
saveg_write8((value >> 24) & 0xff);
|
|
}
|
|
|
|
// Pad to 4-byte boundaries
|
|
|
|
static void saveg_read_pad(void)
|
|
{
|
|
unsigned long pos;
|
|
int padding;
|
|
int i;
|
|
|
|
pos = ES_ftell(save_stream);
|
|
|
|
padding = (4 - (pos & 3)) & 3;
|
|
|
|
for (i=0; i<padding; ++i)
|
|
{
|
|
saveg_read8();
|
|
}
|
|
}
|
|
|
|
static void saveg_write_pad(void)
|
|
{
|
|
unsigned long pos;
|
|
int padding;
|
|
int i;
|
|
|
|
pos = ES_ftell(save_stream);
|
|
|
|
padding = (4 - (pos & 3)) & 3;
|
|
|
|
for (i=0; i<padding; ++i)
|
|
{
|
|
saveg_write8(0);
|
|
}
|
|
}
|
|
|
|
|
|
// Pointers
|
|
|
|
static void *saveg_readp(void)
|
|
{
|
|
return (void *) (intptr_t) saveg_read32();
|
|
}
|
|
|
|
static void saveg_writep(void *p)
|
|
{
|
|
saveg_write32((intptr_t) p);
|
|
}
|
|
|
|
// Enum values are 32-bit integers.
|
|
|
|
#define saveg_read_enum saveg_read32
|
|
#define saveg_write_enum saveg_write32
|
|
|
|
//
|
|
// Structure read/write functions
|
|
//
|
|
|
|
//
|
|
// mapthing_t
|
|
//
|
|
|
|
static void saveg_read_mapthing_t(mapthing_t *str)
|
|
{
|
|
// short x;
|
|
str->x = saveg_read16();
|
|
|
|
// short y;
|
|
str->y = saveg_read16();
|
|
|
|
// short angle;
|
|
str->angle = saveg_read16();
|
|
|
|
// short type;
|
|
str->type = saveg_read16();
|
|
|
|
// short options;
|
|
str->options = saveg_read16();
|
|
}
|
|
|
|
static void saveg_write_mapthing_t(mapthing_t *str)
|
|
{
|
|
// short x;
|
|
saveg_write16(str->x);
|
|
|
|
// short y;
|
|
saveg_write16(str->y);
|
|
|
|
// short angle;
|
|
saveg_write16(str->angle);
|
|
|
|
// short type;
|
|
saveg_write16(str->type);
|
|
|
|
// short options;
|
|
saveg_write16(str->options);
|
|
}
|
|
|
|
//
|
|
// actionf_t
|
|
//
|
|
|
|
static void saveg_read_actionf_t(actionf_t *str)
|
|
{
|
|
// actionf_p1 acp1;
|
|
str->acp1 = saveg_readp();
|
|
}
|
|
|
|
static void saveg_write_actionf_t(actionf_t *str)
|
|
{
|
|
// actionf_p1 acp1;
|
|
saveg_writep(str->acp1);
|
|
}
|
|
|
|
//
|
|
// think_t
|
|
//
|
|
// This is just an actionf_t.
|
|
//
|
|
|
|
#define saveg_read_think_t saveg_read_actionf_t
|
|
#define saveg_write_think_t saveg_write_actionf_t
|
|
|
|
//
|
|
// thinker_t
|
|
//
|
|
|
|
static void saveg_read_thinker_t(thinker_t *str)
|
|
{
|
|
// struct thinker_s* prev;
|
|
str->prev = saveg_readp();
|
|
|
|
// struct thinker_s* next;
|
|
str->next = saveg_readp();
|
|
|
|
// think_t function;
|
|
saveg_read_think_t(&str->function);
|
|
}
|
|
|
|
static void saveg_write_thinker_t(thinker_t *str)
|
|
{
|
|
// struct thinker_s* prev;
|
|
saveg_writep(str->prev);
|
|
|
|
// struct thinker_s* next;
|
|
saveg_writep(str->next);
|
|
|
|
// think_t function;
|
|
saveg_write_think_t(&str->function);
|
|
}
|
|
|
|
//
|
|
// mobj_t
|
|
//
|
|
|
|
static void saveg_read_mobj_t(mobj_t *str)
|
|
{
|
|
int pl;
|
|
|
|
// thinker_t thinker;
|
|
saveg_read_thinker_t(&str->thinker);
|
|
|
|
// fixed_t x;
|
|
str->x = saveg_read32();
|
|
|
|
// fixed_t y;
|
|
str->y = saveg_read32();
|
|
|
|
// fixed_t z;
|
|
str->z = saveg_read32();
|
|
|
|
// struct mobj_s* snext;
|
|
str->snext = saveg_readp();
|
|
|
|
// struct mobj_s* sprev;
|
|
str->sprev = saveg_readp();
|
|
|
|
// angle_t angle;
|
|
str->angle = saveg_read32();
|
|
|
|
// spritenum_t sprite;
|
|
str->sprite = saveg_read_enum();
|
|
|
|
// int frame;
|
|
str->frame = saveg_read32();
|
|
|
|
// struct mobj_s* bnext;
|
|
str->bnext = saveg_readp();
|
|
|
|
// struct mobj_s* bprev;
|
|
str->bprev = saveg_readp();
|
|
|
|
// struct subsector_s* subsector;
|
|
str->subsector = saveg_readp();
|
|
|
|
// fixed_t floorz;
|
|
str->floorz = saveg_read32();
|
|
|
|
// fixed_t ceilingz;
|
|
str->ceilingz = saveg_read32();
|
|
|
|
// fixed_t radius;
|
|
str->radius = saveg_read32();
|
|
|
|
// fixed_t height;
|
|
str->height = saveg_read32();
|
|
|
|
// fixed_t momx;
|
|
str->momx = saveg_read32();
|
|
|
|
// fixed_t momy;
|
|
str->momy = saveg_read32();
|
|
|
|
// fixed_t momz;
|
|
str->momz = saveg_read32();
|
|
|
|
// int validcount;
|
|
str->validcount = saveg_read32();
|
|
|
|
// mobjtype_t type;
|
|
str->type = saveg_read_enum();
|
|
|
|
// mobjinfo_t* info;
|
|
str->info = saveg_readp();
|
|
|
|
// int tics;
|
|
str->tics = saveg_read32();
|
|
|
|
// state_t* state;
|
|
str->state = &states[saveg_read32()];
|
|
|
|
// int flags;
|
|
str->flags = saveg_read32();
|
|
|
|
// int health;
|
|
str->health = saveg_read32();
|
|
|
|
// int movedir;
|
|
str->movedir = saveg_read32();
|
|
|
|
// int movecount;
|
|
str->movecount = saveg_read32();
|
|
|
|
// struct mobj_s* target;
|
|
str->target = saveg_readp();
|
|
|
|
// int reactiontime;
|
|
str->reactiontime = saveg_read32();
|
|
|
|
// int threshold;
|
|
str->threshold = saveg_read32();
|
|
|
|
// struct player_s* player;
|
|
pl = saveg_read32();
|
|
|
|
if (pl > 0)
|
|
{
|
|
str->player = &players[pl - 1];
|
|
str->player->mo = str;
|
|
}
|
|
else
|
|
{
|
|
str->player = NULL;
|
|
}
|
|
|
|
// int lastlook;
|
|
str->lastlook = saveg_read32();
|
|
|
|
// mapthing_t spawnpoint;
|
|
saveg_read_mapthing_t(&str->spawnpoint);
|
|
|
|
// struct mobj_s* tracer;
|
|
str->tracer = saveg_readp();
|
|
}
|
|
|
|
static void saveg_write_mobj_t(mobj_t *str)
|
|
{
|
|
// thinker_t thinker;
|
|
saveg_write_thinker_t(&str->thinker);
|
|
|
|
// fixed_t x;
|
|
saveg_write32(str->x);
|
|
|
|
// fixed_t y;
|
|
saveg_write32(str->y);
|
|
|
|
// fixed_t z;
|
|
saveg_write32(str->z);
|
|
|
|
// struct mobj_s* snext;
|
|
saveg_writep(str->snext);
|
|
|
|
// struct mobj_s* sprev;
|
|
saveg_writep(str->sprev);
|
|
|
|
// angle_t angle;
|
|
saveg_write32(str->angle);
|
|
|
|
// spritenum_t sprite;
|
|
saveg_write_enum(str->sprite);
|
|
|
|
// int frame;
|
|
saveg_write32(str->frame);
|
|
|
|
// struct mobj_s* bnext;
|
|
saveg_writep(str->bnext);
|
|
|
|
// struct mobj_s* bprev;
|
|
saveg_writep(str->bprev);
|
|
|
|
// struct subsector_s* subsector;
|
|
saveg_writep(str->subsector);
|
|
|
|
// fixed_t floorz;
|
|
saveg_write32(str->floorz);
|
|
|
|
// fixed_t ceilingz;
|
|
saveg_write32(str->ceilingz);
|
|
|
|
// fixed_t radius;
|
|
saveg_write32(str->radius);
|
|
|
|
// fixed_t height;
|
|
saveg_write32(str->height);
|
|
|
|
// fixed_t momx;
|
|
saveg_write32(str->momx);
|
|
|
|
// fixed_t momy;
|
|
saveg_write32(str->momy);
|
|
|
|
// fixed_t momz;
|
|
saveg_write32(str->momz);
|
|
|
|
// int validcount;
|
|
saveg_write32(str->validcount);
|
|
|
|
// mobjtype_t type;
|
|
saveg_write_enum(str->type);
|
|
|
|
// mobjinfo_t* info;
|
|
saveg_writep(str->info);
|
|
|
|
// int tics;
|
|
saveg_write32(str->tics);
|
|
|
|
// state_t* state;
|
|
saveg_write32(str->state - states);
|
|
|
|
// int flags;
|
|
saveg_write32(str->flags);
|
|
|
|
// int health;
|
|
saveg_write32(str->health);
|
|
|
|
// int movedir;
|
|
saveg_write32(str->movedir);
|
|
|
|
// int movecount;
|
|
saveg_write32(str->movecount);
|
|
|
|
// struct mobj_s* target;
|
|
saveg_writep(str->target);
|
|
|
|
// int reactiontime;
|
|
saveg_write32(str->reactiontime);
|
|
|
|
// int threshold;
|
|
saveg_write32(str->threshold);
|
|
|
|
// struct player_s* player;
|
|
if (str->player)
|
|
{
|
|
saveg_write32(str->player - players + 1);
|
|
}
|
|
else
|
|
{
|
|
saveg_write32(0);
|
|
}
|
|
|
|
// int lastlook;
|
|
saveg_write32(str->lastlook);
|
|
|
|
// mapthing_t spawnpoint;
|
|
saveg_write_mapthing_t(&str->spawnpoint);
|
|
|
|
// struct mobj_s* tracer;
|
|
saveg_writep(str->tracer);
|
|
}
|
|
|
|
|
|
//
|
|
// ticcmd_t
|
|
//
|
|
|
|
static void saveg_read_ticcmd_t(ticcmd_t *str)
|
|
{
|
|
|
|
// signed char forwardmove;
|
|
str->forwardmove = saveg_read8();
|
|
|
|
// signed char sidemove;
|
|
str->sidemove = saveg_read8();
|
|
|
|
// short angleturn;
|
|
str->angleturn = saveg_read16();
|
|
|
|
// short consistancy;
|
|
str->consistancy = saveg_read16();
|
|
|
|
// byte chatchar;
|
|
str->chatchar = saveg_read8();
|
|
|
|
// byte buttons;
|
|
str->buttons = saveg_read8();
|
|
}
|
|
|
|
static void saveg_write_ticcmd_t(ticcmd_t *str)
|
|
{
|
|
|
|
// signed char forwardmove;
|
|
saveg_write8(str->forwardmove);
|
|
|
|
// signed char sidemove;
|
|
saveg_write8(str->sidemove);
|
|
|
|
// short angleturn;
|
|
saveg_write16(str->angleturn);
|
|
|
|
// short consistancy;
|
|
saveg_write16(str->consistancy);
|
|
|
|
// byte chatchar;
|
|
saveg_write8(str->chatchar);
|
|
|
|
// byte buttons;
|
|
saveg_write8(str->buttons);
|
|
}
|
|
|
|
//
|
|
// pspdef_t
|
|
//
|
|
|
|
static void saveg_read_pspdef_t(pspdef_t *str)
|
|
{
|
|
int state;
|
|
|
|
// state_t* state;
|
|
state = saveg_read32();
|
|
|
|
if (state > 0)
|
|
{
|
|
str->state = &states[state];
|
|
}
|
|
else
|
|
{
|
|
str->state = NULL;
|
|
}
|
|
|
|
// int tics;
|
|
str->tics = saveg_read32();
|
|
|
|
// fixed_t sx;
|
|
str->sx = saveg_read32();
|
|
|
|
// fixed_t sy;
|
|
str->sy = saveg_read32();
|
|
}
|
|
|
|
static void saveg_write_pspdef_t(pspdef_t *str)
|
|
{
|
|
// state_t* state;
|
|
if (str->state)
|
|
{
|
|
saveg_write32(str->state - states);
|
|
}
|
|
else
|
|
{
|
|
saveg_write32(0);
|
|
}
|
|
|
|
// int tics;
|
|
saveg_write32(str->tics);
|
|
|
|
// fixed_t sx;
|
|
saveg_write32(str->sx);
|
|
|
|
// fixed_t sy;
|
|
saveg_write32(str->sy);
|
|
}
|
|
|
|
//
|
|
// player_t
|
|
//
|
|
|
|
static void saveg_read_player_t(player_t *str)
|
|
{
|
|
int i;
|
|
|
|
// mobj_t* mo;
|
|
str->mo = saveg_readp();
|
|
|
|
// playerstate_t playerstate;
|
|
str->playerstate = saveg_read_enum();
|
|
|
|
// ticcmd_t cmd;
|
|
saveg_read_ticcmd_t(&str->cmd);
|
|
|
|
// fixed_t viewz;
|
|
str->viewz = saveg_read32();
|
|
|
|
// fixed_t viewheight;
|
|
str->viewheight = saveg_read32();
|
|
|
|
// fixed_t deltaviewheight;
|
|
str->deltaviewheight = saveg_read32();
|
|
|
|
// fixed_t bob;
|
|
str->bob = saveg_read32();
|
|
|
|
// int health;
|
|
str->health = saveg_read32();
|
|
|
|
// int armorpoints;
|
|
str->armorpoints = saveg_read32();
|
|
|
|
// int armortype;
|
|
str->armortype = saveg_read32();
|
|
|
|
// int powers[NUMPOWERS];
|
|
for (i=0; i<NUMPOWERS; ++i)
|
|
{
|
|
str->powers[i] = saveg_read32();
|
|
}
|
|
|
|
// boolean cards[NUMCARDS];
|
|
for (i=0; i<NUMCARDS; ++i)
|
|
{
|
|
str->cards[i] = saveg_read32();
|
|
}
|
|
|
|
// boolean backpack;
|
|
str->backpack = saveg_read32();
|
|
|
|
// int frags[MAXPLAYERS];
|
|
for (i=0; i<MAXPLAYERS; ++i)
|
|
{
|
|
str->frags[i] = saveg_read32();
|
|
}
|
|
|
|
// weapontype_t readyweapon;
|
|
str->readyweapon = saveg_read_enum();
|
|
|
|
// weapontype_t pendingweapon;
|
|
str->pendingweapon = saveg_read_enum();
|
|
|
|
// boolean weaponowned[NUMWEAPONS];
|
|
for (i=0; i<NUMWEAPONS; ++i)
|
|
{
|
|
str->weaponowned[i] = saveg_read32();
|
|
}
|
|
|
|
// int ammo[NUMAMMO];
|
|
for (i=0; i<NUMAMMO; ++i)
|
|
{
|
|
str->ammo[i] = saveg_read32();
|
|
}
|
|
|
|
// int maxammo[NUMAMMO];
|
|
for (i=0; i<NUMAMMO; ++i)
|
|
{
|
|
str->maxammo[i] = saveg_read32();
|
|
}
|
|
|
|
// int attackdown;
|
|
str->attackdown = saveg_read32();
|
|
|
|
// int usedown;
|
|
str->usedown = saveg_read32();
|
|
|
|
// int cheats;
|
|
str->cheats = saveg_read32();
|
|
|
|
// int refire;
|
|
str->refire = saveg_read32();
|
|
|
|
// int killcount;
|
|
str->killcount = saveg_read32();
|
|
|
|
// int itemcount;
|
|
str->itemcount = saveg_read32();
|
|
|
|
// int secretcount;
|
|
str->secretcount = saveg_read32();
|
|
|
|
// char* message;
|
|
str->message = saveg_readp();
|
|
|
|
// int damagecount;
|
|
str->damagecount = saveg_read32();
|
|
|
|
// int bonuscount;
|
|
str->bonuscount = saveg_read32();
|
|
|
|
// mobj_t* attacker;
|
|
str->attacker = saveg_readp();
|
|
|
|
// int extralight;
|
|
str->extralight = saveg_read32();
|
|
|
|
// int fixedcolormap;
|
|
str->fixedcolormap = saveg_read32();
|
|
|
|
// int colormap;
|
|
str->colormap = saveg_read32();
|
|
|
|
// pspdef_t psprites[NUMPSPRITES];
|
|
for (i=0; i<NUMPSPRITES; ++i)
|
|
{
|
|
saveg_read_pspdef_t(&str->psprites[i]);
|
|
}
|
|
|
|
// boolean didsecret;
|
|
str->didsecret = saveg_read32();
|
|
}
|
|
|
|
static void saveg_write_player_t(player_t *str)
|
|
{
|
|
int i;
|
|
|
|
// mobj_t* mo;
|
|
saveg_writep(str->mo);
|
|
|
|
// playerstate_t playerstate;
|
|
saveg_write_enum(str->playerstate);
|
|
|
|
// ticcmd_t cmd;
|
|
saveg_write_ticcmd_t(&str->cmd);
|
|
|
|
// fixed_t viewz;
|
|
saveg_write32(str->viewz);
|
|
|
|
// fixed_t viewheight;
|
|
saveg_write32(str->viewheight);
|
|
|
|
// fixed_t deltaviewheight;
|
|
saveg_write32(str->deltaviewheight);
|
|
|
|
// fixed_t bob;
|
|
saveg_write32(str->bob);
|
|
|
|
// int health;
|
|
saveg_write32(str->health);
|
|
|
|
// int armorpoints;
|
|
saveg_write32(str->armorpoints);
|
|
|
|
// int armortype;
|
|
saveg_write32(str->armortype);
|
|
|
|
// int powers[NUMPOWERS];
|
|
for (i=0; i<NUMPOWERS; ++i)
|
|
{
|
|
saveg_write32(str->powers[i]);
|
|
}
|
|
|
|
// boolean cards[NUMCARDS];
|
|
for (i=0; i<NUMCARDS; ++i)
|
|
{
|
|
saveg_write32(str->cards[i]);
|
|
}
|
|
|
|
// boolean backpack;
|
|
saveg_write32(str->backpack);
|
|
|
|
// int frags[MAXPLAYERS];
|
|
for (i=0; i<MAXPLAYERS; ++i)
|
|
{
|
|
saveg_write32(str->frags[i]);
|
|
}
|
|
|
|
// weapontype_t readyweapon;
|
|
saveg_write_enum(str->readyweapon);
|
|
|
|
// weapontype_t pendingweapon;
|
|
saveg_write_enum(str->pendingweapon);
|
|
|
|
// boolean weaponowned[NUMWEAPONS];
|
|
for (i=0; i<NUMWEAPONS; ++i)
|
|
{
|
|
saveg_write32(str->weaponowned[i]);
|
|
}
|
|
|
|
// int ammo[NUMAMMO];
|
|
for (i=0; i<NUMAMMO; ++i)
|
|
{
|
|
saveg_write32(str->ammo[i]);
|
|
}
|
|
|
|
// int maxammo[NUMAMMO];
|
|
for (i=0; i<NUMAMMO; ++i)
|
|
{
|
|
saveg_write32(str->maxammo[i]);
|
|
}
|
|
|
|
// int attackdown;
|
|
saveg_write32(str->attackdown);
|
|
|
|
// int usedown;
|
|
saveg_write32(str->usedown);
|
|
|
|
// int cheats;
|
|
saveg_write32(str->cheats);
|
|
|
|
// int refire;
|
|
saveg_write32(str->refire);
|
|
|
|
// int killcount;
|
|
saveg_write32(str->killcount);
|
|
|
|
// int itemcount;
|
|
saveg_write32(str->itemcount);
|
|
|
|
// int secretcount;
|
|
saveg_write32(str->secretcount);
|
|
|
|
// char* message;
|
|
saveg_writep(str->message);
|
|
|
|
// int damagecount;
|
|
saveg_write32(str->damagecount);
|
|
|
|
// int bonuscount;
|
|
saveg_write32(str->bonuscount);
|
|
|
|
// mobj_t* attacker;
|
|
saveg_writep(str->attacker);
|
|
|
|
// int extralight;
|
|
saveg_write32(str->extralight);
|
|
|
|
// int fixedcolormap;
|
|
saveg_write32(str->fixedcolormap);
|
|
|
|
// int colormap;
|
|
saveg_write32(str->colormap);
|
|
|
|
// pspdef_t psprites[NUMPSPRITES];
|
|
for (i=0; i<NUMPSPRITES; ++i)
|
|
{
|
|
saveg_write_pspdef_t(&str->psprites[i]);
|
|
}
|
|
|
|
// boolean didsecret;
|
|
saveg_write32(str->didsecret);
|
|
}
|
|
|
|
|
|
//
|
|
// ceiling_t
|
|
//
|
|
|
|
static void saveg_read_ceiling_t(ceiling_t *str)
|
|
{
|
|
int sector;
|
|
|
|
// thinker_t thinker;
|
|
saveg_read_thinker_t(&str->thinker);
|
|
|
|
// ceiling_e type;
|
|
str->type = saveg_read_enum();
|
|
|
|
// sector_t* sector;
|
|
sector = saveg_read32();
|
|
str->sector = §ors[sector];
|
|
|
|
// fixed_t bottomheight;
|
|
str->bottomheight = saveg_read32();
|
|
|
|
// fixed_t topheight;
|
|
str->topheight = saveg_read32();
|
|
|
|
// fixed_t speed;
|
|
str->speed = saveg_read32();
|
|
|
|
// boolean crush;
|
|
str->crush = saveg_read32();
|
|
|
|
// int direction;
|
|
str->direction = saveg_read32();
|
|
|
|
// int tag;
|
|
str->tag = saveg_read32();
|
|
|
|
// int olddirection;
|
|
str->olddirection = saveg_read32();
|
|
}
|
|
|
|
static void saveg_write_ceiling_t(ceiling_t *str)
|
|
{
|
|
// thinker_t thinker;
|
|
saveg_write_thinker_t(&str->thinker);
|
|
|
|
// ceiling_e type;
|
|
saveg_write_enum(str->type);
|
|
|
|
// sector_t* sector;
|
|
saveg_write32(str->sector - sectors);
|
|
|
|
// fixed_t bottomheight;
|
|
saveg_write32(str->bottomheight);
|
|
|
|
// fixed_t topheight;
|
|
saveg_write32(str->topheight);
|
|
|
|
// fixed_t speed;
|
|
saveg_write32(str->speed);
|
|
|
|
// boolean crush;
|
|
saveg_write32(str->crush);
|
|
|
|
// int direction;
|
|
saveg_write32(str->direction);
|
|
|
|
// int tag;
|
|
saveg_write32(str->tag);
|
|
|
|
// int olddirection;
|
|
saveg_write32(str->olddirection);
|
|
}
|
|
|
|
//
|
|
// vldoor_t
|
|
//
|
|
|
|
static void saveg_read_vldoor_t(vldoor_t *str)
|
|
{
|
|
int sector;
|
|
|
|
// thinker_t thinker;
|
|
saveg_read_thinker_t(&str->thinker);
|
|
|
|
// vldoor_e type;
|
|
str->type = saveg_read_enum();
|
|
|
|
// sector_t* sector;
|
|
sector = saveg_read32();
|
|
str->sector = §ors[sector];
|
|
|
|
// fixed_t topheight;
|
|
str->topheight = saveg_read32();
|
|
|
|
// fixed_t speed;
|
|
str->speed = saveg_read32();
|
|
|
|
// int direction;
|
|
str->direction = saveg_read32();
|
|
|
|
// int topwait;
|
|
str->topwait = saveg_read32();
|
|
|
|
// int topcountdown;
|
|
str->topcountdown = saveg_read32();
|
|
}
|
|
|
|
static void saveg_write_vldoor_t(vldoor_t *str)
|
|
{
|
|
// thinker_t thinker;
|
|
saveg_write_thinker_t(&str->thinker);
|
|
|
|
// vldoor_e type;
|
|
saveg_write_enum(str->type);
|
|
|
|
// sector_t* sector;
|
|
saveg_write32(str->sector - sectors);
|
|
|
|
// fixed_t topheight;
|
|
saveg_write32(str->topheight);
|
|
|
|
// fixed_t speed;
|
|
saveg_write32(str->speed);
|
|
|
|
// int direction;
|
|
saveg_write32(str->direction);
|
|
|
|
// int topwait;
|
|
saveg_write32(str->topwait);
|
|
|
|
// int topcountdown;
|
|
saveg_write32(str->topcountdown);
|
|
}
|
|
|
|
//
|
|
// floormove_t
|
|
//
|
|
|
|
static void saveg_read_floormove_t(floormove_t *str)
|
|
{
|
|
int sector;
|
|
|
|
// thinker_t thinker;
|
|
saveg_read_thinker_t(&str->thinker);
|
|
|
|
// floor_e type;
|
|
str->type = saveg_read_enum();
|
|
|
|
// boolean crush;
|
|
str->crush = saveg_read32();
|
|
|
|
// sector_t* sector;
|
|
sector = saveg_read32();
|
|
str->sector = §ors[sector];
|
|
|
|
// int direction;
|
|
str->direction = saveg_read32();
|
|
|
|
// int newspecial;
|
|
str->newspecial = saveg_read32();
|
|
|
|
// short texture;
|
|
str->texture = saveg_read16();
|
|
|
|
// fixed_t floordestheight;
|
|
str->floordestheight = saveg_read32();
|
|
|
|
// fixed_t speed;
|
|
str->speed = saveg_read32();
|
|
}
|
|
|
|
static void saveg_write_floormove_t(floormove_t *str)
|
|
{
|
|
// thinker_t thinker;
|
|
saveg_write_thinker_t(&str->thinker);
|
|
|
|
// floor_e type;
|
|
saveg_write_enum(str->type);
|
|
|
|
// boolean crush;
|
|
saveg_write32(str->crush);
|
|
|
|
// sector_t* sector;
|
|
saveg_write32(str->sector - sectors);
|
|
|
|
// int direction;
|
|
saveg_write32(str->direction);
|
|
|
|
// int newspecial;
|
|
saveg_write32(str->newspecial);
|
|
|
|
// short texture;
|
|
saveg_write16(str->texture);
|
|
|
|
// fixed_t floordestheight;
|
|
saveg_write32(str->floordestheight);
|
|
|
|
// fixed_t speed;
|
|
saveg_write32(str->speed);
|
|
}
|
|
|
|
//
|
|
// plat_t
|
|
//
|
|
|
|
static void saveg_read_plat_t(plat_t *str)
|
|
{
|
|
int sector;
|
|
|
|
// thinker_t thinker;
|
|
saveg_read_thinker_t(&str->thinker);
|
|
|
|
// sector_t* sector;
|
|
sector = saveg_read32();
|
|
str->sector = §ors[sector];
|
|
|
|
// fixed_t speed;
|
|
str->speed = saveg_read32();
|
|
|
|
// fixed_t low;
|
|
str->low = saveg_read32();
|
|
|
|
// fixed_t high;
|
|
str->high = saveg_read32();
|
|
|
|
// int wait;
|
|
str->wait = saveg_read32();
|
|
|
|
// int count;
|
|
str->count = saveg_read32();
|
|
|
|
// plat_e status;
|
|
str->status = saveg_read_enum();
|
|
|
|
// plat_e oldstatus;
|
|
str->oldstatus = saveg_read_enum();
|
|
|
|
// boolean crush;
|
|
str->crush = saveg_read32();
|
|
|
|
// int tag;
|
|
str->tag = saveg_read32();
|
|
|
|
// plattype_e type;
|
|
str->type = saveg_read_enum();
|
|
}
|
|
|
|
static void saveg_write_plat_t(plat_t *str)
|
|
{
|
|
// thinker_t thinker;
|
|
saveg_write_thinker_t(&str->thinker);
|
|
|
|
// sector_t* sector;
|
|
saveg_write32(str->sector - sectors);
|
|
|
|
// fixed_t speed;
|
|
saveg_write32(str->speed);
|
|
|
|
// fixed_t low;
|
|
saveg_write32(str->low);
|
|
|
|
// fixed_t high;
|
|
saveg_write32(str->high);
|
|
|
|
// int wait;
|
|
saveg_write32(str->wait);
|
|
|
|
// int count;
|
|
saveg_write32(str->count);
|
|
|
|
// plat_e status;
|
|
saveg_write_enum(str->status);
|
|
|
|
// plat_e oldstatus;
|
|
saveg_write_enum(str->oldstatus);
|
|
|
|
// boolean crush;
|
|
saveg_write32(str->crush);
|
|
|
|
// int tag;
|
|
saveg_write32(str->tag);
|
|
|
|
// plattype_e type;
|
|
saveg_write_enum(str->type);
|
|
}
|
|
|
|
//
|
|
// lightflash_t
|
|
//
|
|
|
|
static void saveg_read_lightflash_t(lightflash_t *str)
|
|
{
|
|
int sector;
|
|
|
|
// thinker_t thinker;
|
|
saveg_read_thinker_t(&str->thinker);
|
|
|
|
// sector_t* sector;
|
|
sector = saveg_read32();
|
|
str->sector = §ors[sector];
|
|
|
|
// int count;
|
|
str->count = saveg_read32();
|
|
|
|
// int maxlight;
|
|
str->maxlight = saveg_read32();
|
|
|
|
// int minlight;
|
|
str->minlight = saveg_read32();
|
|
|
|
// int maxtime;
|
|
str->maxtime = saveg_read32();
|
|
|
|
// int mintime;
|
|
str->mintime = saveg_read32();
|
|
}
|
|
|
|
static void saveg_write_lightflash_t(lightflash_t *str)
|
|
{
|
|
// thinker_t thinker;
|
|
saveg_write_thinker_t(&str->thinker);
|
|
|
|
// sector_t* sector;
|
|
saveg_write32(str->sector - sectors);
|
|
|
|
// int count;
|
|
saveg_write32(str->count);
|
|
|
|
// int maxlight;
|
|
saveg_write32(str->maxlight);
|
|
|
|
// int minlight;
|
|
saveg_write32(str->minlight);
|
|
|
|
// int maxtime;
|
|
saveg_write32(str->maxtime);
|
|
|
|
// int mintime;
|
|
saveg_write32(str->mintime);
|
|
}
|
|
|
|
//
|
|
// strobe_t
|
|
//
|
|
|
|
static void saveg_read_strobe_t(strobe_t *str)
|
|
{
|
|
int sector;
|
|
|
|
// thinker_t thinker;
|
|
saveg_read_thinker_t(&str->thinker);
|
|
|
|
// sector_t* sector;
|
|
sector = saveg_read32();
|
|
str->sector = §ors[sector];
|
|
|
|
// int count;
|
|
str->count = saveg_read32();
|
|
|
|
// int minlight;
|
|
str->minlight = saveg_read32();
|
|
|
|
// int maxlight;
|
|
str->maxlight = saveg_read32();
|
|
|
|
// int darktime;
|
|
str->darktime = saveg_read32();
|
|
|
|
// int brighttime;
|
|
str->brighttime = saveg_read32();
|
|
}
|
|
|
|
static void saveg_write_strobe_t(strobe_t *str)
|
|
{
|
|
// thinker_t thinker;
|
|
saveg_write_thinker_t(&str->thinker);
|
|
|
|
// sector_t* sector;
|
|
saveg_write32(str->sector - sectors);
|
|
|
|
// int count;
|
|
saveg_write32(str->count);
|
|
|
|
// int minlight;
|
|
saveg_write32(str->minlight);
|
|
|
|
// int maxlight;
|
|
saveg_write32(str->maxlight);
|
|
|
|
// int darktime;
|
|
saveg_write32(str->darktime);
|
|
|
|
// int brighttime;
|
|
saveg_write32(str->brighttime);
|
|
}
|
|
|
|
//
|
|
// glow_t
|
|
//
|
|
|
|
static void saveg_read_glow_t(glow_t *str)
|
|
{
|
|
int sector;
|
|
|
|
// thinker_t thinker;
|
|
saveg_read_thinker_t(&str->thinker);
|
|
|
|
// sector_t* sector;
|
|
sector = saveg_read32();
|
|
str->sector = §ors[sector];
|
|
|
|
// int minlight;
|
|
str->minlight = saveg_read32();
|
|
|
|
// int maxlight;
|
|
str->maxlight = saveg_read32();
|
|
|
|
// int direction;
|
|
str->direction = saveg_read32();
|
|
}
|
|
|
|
static void saveg_write_glow_t(glow_t *str)
|
|
{
|
|
// thinker_t thinker;
|
|
saveg_write_thinker_t(&str->thinker);
|
|
|
|
// sector_t* sector;
|
|
saveg_write32(str->sector - sectors);
|
|
|
|
// int minlight;
|
|
saveg_write32(str->minlight);
|
|
|
|
// int maxlight;
|
|
saveg_write32(str->maxlight);
|
|
|
|
// int direction;
|
|
saveg_write32(str->direction);
|
|
}
|
|
|
|
//
|
|
// Write the header for a savegame
|
|
//
|
|
|
|
void P_WriteSaveGameHeader(char *description)
|
|
{
|
|
char name[VERSIONSIZE];
|
|
int i;
|
|
|
|
for (i=0; description[i] != '\0'; ++i)
|
|
saveg_write8(description[i]);
|
|
for (; i<SAVESTRINGSIZE; ++i)
|
|
saveg_write8(0);
|
|
|
|
ES_memset(name, 0, sizeof(name));
|
|
M_snprintf(name, sizeof(name), "version %i", G_VanillaVersionCode());
|
|
|
|
for (i=0; i<VERSIONSIZE; ++i)
|
|
saveg_write8(name[i]);
|
|
|
|
saveg_write8(gameskill);
|
|
saveg_write8(gameepisode);
|
|
saveg_write8(gamemap);
|
|
|
|
for (i=0 ; i<MAXPLAYERS ; i++)
|
|
saveg_write8(playeringame[i]);
|
|
|
|
saveg_write8((leveltime >> 16) & 0xff);
|
|
saveg_write8((leveltime >> 8) & 0xff);
|
|
saveg_write8(leveltime & 0xff);
|
|
}
|
|
|
|
//
|
|
// Read the header for a savegame
|
|
//
|
|
|
|
boolean P_ReadSaveGameHeader(void)
|
|
{
|
|
int i;
|
|
byte a, b, c;
|
|
char vcheck[VERSIONSIZE];
|
|
char read_vcheck[VERSIONSIZE];
|
|
|
|
// skip the description field
|
|
|
|
for (i=0; i<SAVESTRINGSIZE; ++i)
|
|
saveg_read8();
|
|
|
|
for (i=0; i<VERSIONSIZE; ++i)
|
|
read_vcheck[i] = saveg_read8();
|
|
|
|
ES_memset(vcheck, 0, sizeof(vcheck));
|
|
M_snprintf(vcheck, sizeof(vcheck), "version %i", G_VanillaVersionCode());
|
|
if (ES_strcmp(read_vcheck, vcheck) != 0)
|
|
return false; // bad version
|
|
|
|
gameskill = saveg_read8();
|
|
gameepisode = saveg_read8();
|
|
gamemap = saveg_read8();
|
|
|
|
for (i=0 ; i<MAXPLAYERS ; i++)
|
|
playeringame[i] = saveg_read8();
|
|
|
|
// get the times
|
|
a = saveg_read8();
|
|
b = saveg_read8();
|
|
c = saveg_read8();
|
|
leveltime = (a<<16) + (b<<8) + c;
|
|
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Read the end of file marker. Returns true if read successfully.
|
|
//
|
|
|
|
boolean P_ReadSaveGameEOF(void)
|
|
{
|
|
int value;
|
|
|
|
value = saveg_read8();
|
|
|
|
return value == SAVEGAME_EOF;
|
|
}
|
|
|
|
//
|
|
// Write the end of file marker
|
|
//
|
|
|
|
void P_WriteSaveGameEOF(void)
|
|
{
|
|
saveg_write8(SAVEGAME_EOF);
|
|
}
|
|
|
|
//
|
|
// P_ArchivePlayers
|
|
//
|
|
void P_ArchivePlayers (void)
|
|
{
|
|
int i;
|
|
|
|
for (i=0 ; i<MAXPLAYERS ; i++)
|
|
{
|
|
if (!playeringame[i])
|
|
continue;
|
|
|
|
saveg_write_pad();
|
|
|
|
saveg_write_player_t(&players[i]);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// P_UnArchivePlayers
|
|
//
|
|
void P_UnArchivePlayers (void)
|
|
{
|
|
int i;
|
|
|
|
for (i=0 ; i<MAXPLAYERS ; i++)
|
|
{
|
|
if (!playeringame[i])
|
|
continue;
|
|
|
|
saveg_read_pad();
|
|
|
|
saveg_read_player_t(&players[i]);
|
|
|
|
// will be set when unarc thinker
|
|
players[i].mo = NULL;
|
|
players[i].message = NULL;
|
|
players[i].attacker = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// P_ArchiveWorld
|
|
//
|
|
void P_ArchiveWorld (void)
|
|
{
|
|
int i;
|
|
int j;
|
|
sector_t* sec;
|
|
line_t* li;
|
|
side_t* si;
|
|
|
|
// do sectors
|
|
for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
|
|
{
|
|
saveg_write16(sec->floorheight >> FRACBITS);
|
|
saveg_write16(sec->ceilingheight >> FRACBITS);
|
|
saveg_write16(sec->floorpic);
|
|
saveg_write16(sec->ceilingpic);
|
|
saveg_write16(sec->lightlevel);
|
|
saveg_write16(sec->special); // needed?
|
|
saveg_write16(sec->tag); // needed?
|
|
}
|
|
|
|
|
|
// do lines
|
|
for (i=0, li = lines ; i<numlines ; i++,li++)
|
|
{
|
|
saveg_write16(li->flags);
|
|
saveg_write16(li->special);
|
|
saveg_write16(li->tag);
|
|
for (j=0 ; j<2 ; j++)
|
|
{
|
|
if (li->sidenum[j] == -1)
|
|
continue;
|
|
|
|
si = &sides[li->sidenum[j]];
|
|
|
|
saveg_write16(si->textureoffset >> FRACBITS);
|
|
saveg_write16(si->rowoffset >> FRACBITS);
|
|
saveg_write16(si->toptexture);
|
|
saveg_write16(si->bottomtexture);
|
|
saveg_write16(si->midtexture);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// P_UnArchiveWorld
|
|
//
|
|
void P_UnArchiveWorld (void)
|
|
{
|
|
int i;
|
|
int j;
|
|
sector_t* sec;
|
|
line_t* li;
|
|
side_t* si;
|
|
|
|
// do sectors
|
|
for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
|
|
{
|
|
sec->floorheight = saveg_read16() << FRACBITS;
|
|
sec->ceilingheight = saveg_read16() << FRACBITS;
|
|
sec->floorpic = saveg_read16();
|
|
sec->ceilingpic = saveg_read16();
|
|
sec->lightlevel = saveg_read16();
|
|
sec->special = saveg_read16(); // needed?
|
|
sec->tag = saveg_read16(); // needed?
|
|
sec->specialdata = 0;
|
|
sec->soundtarget = 0;
|
|
}
|
|
|
|
// do lines
|
|
for (i=0, li = lines ; i<numlines ; i++,li++)
|
|
{
|
|
li->flags = saveg_read16();
|
|
li->special = saveg_read16();
|
|
li->tag = saveg_read16();
|
|
for (j=0 ; j<2 ; j++)
|
|
{
|
|
if (li->sidenum[j] == -1)
|
|
continue;
|
|
si = &sides[li->sidenum[j]];
|
|
si->textureoffset = saveg_read16() << FRACBITS;
|
|
si->rowoffset = saveg_read16() << FRACBITS;
|
|
si->toptexture = saveg_read16();
|
|
si->bottomtexture = saveg_read16();
|
|
si->midtexture = saveg_read16();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Thinkers
|
|
//
|
|
typedef enum
|
|
{
|
|
tc_end,
|
|
tc_mobj
|
|
|
|
} thinkerclass_t;
|
|
|
|
|
|
//
|
|
// P_ArchiveThinkers
|
|
//
|
|
void P_ArchiveThinkers (void)
|
|
{
|
|
thinker_t* th;
|
|
|
|
// save off the current thinkers
|
|
for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
|
|
{
|
|
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
|
{
|
|
saveg_write8(tc_mobj);
|
|
saveg_write_pad();
|
|
saveg_write_mobj_t((mobj_t *) th);
|
|
|
|
continue;
|
|
}
|
|
|
|
// I_Error ("P_ArchiveThinkers: Unknown thinker function");
|
|
}
|
|
|
|
// add a terminating marker
|
|
saveg_write8(tc_end);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// P_UnArchiveThinkers
|
|
//
|
|
void P_UnArchiveThinkers (void)
|
|
{
|
|
byte tclass;
|
|
thinker_t* currentthinker;
|
|
thinker_t* next;
|
|
mobj_t* mobj;
|
|
|
|
// remove all the current thinkers
|
|
currentthinker = thinkercap.next;
|
|
while (currentthinker != &thinkercap)
|
|
{
|
|
next = currentthinker->next;
|
|
|
|
if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
|
|
P_RemoveMobj ((mobj_t *)currentthinker);
|
|
else
|
|
Z_Free (currentthinker);
|
|
|
|
currentthinker = next;
|
|
}
|
|
P_InitThinkers ();
|
|
|
|
// read in saved thinkers
|
|
while (1)
|
|
{
|
|
tclass = saveg_read8();
|
|
switch (tclass)
|
|
{
|
|
case tc_end:
|
|
return; // end of list
|
|
|
|
case tc_mobj:
|
|
saveg_read_pad();
|
|
mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
|
|
saveg_read_mobj_t(mobj);
|
|
|
|
mobj->target = NULL;
|
|
mobj->tracer = NULL;
|
|
P_SetThingPosition (mobj);
|
|
mobj->info = &mobjinfo[mobj->type];
|
|
mobj->floorz = mobj->subsector->sector->floorheight;
|
|
mobj->ceilingz = mobj->subsector->sector->ceilingheight;
|
|
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
|
|
P_AddThinker (&mobj->thinker);
|
|
break;
|
|
|
|
default:
|
|
I_Error ("Unknown tclass %i in savegame",tclass);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// P_ArchiveSpecials
|
|
//
|
|
enum
|
|
{
|
|
tc_ceiling,
|
|
tc_door,
|
|
tc_floor,
|
|
tc_plat,
|
|
tc_flash,
|
|
tc_strobe,
|
|
tc_glow,
|
|
tc_endspecials
|
|
|
|
} specials_e;
|
|
|
|
|
|
|
|
//
|
|
// Things to handle:
|
|
//
|
|
// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
|
|
// T_VerticalDoor, (vldoor_t: sector_t * swizzle),
|
|
// T_MoveFloor, (floormove_t: sector_t * swizzle),
|
|
// T_LightFlash, (lightflash_t: sector_t * swizzle),
|
|
// T_StrobeFlash, (strobe_t: sector_t *),
|
|
// T_Glow, (glow_t: sector_t *),
|
|
// T_PlatRaise, (plat_t: sector_t *), - active list
|
|
//
|
|
void P_ArchiveSpecials (void)
|
|
{
|
|
thinker_t* th;
|
|
int i;
|
|
|
|
// save off the current thinkers
|
|
for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
|
|
{
|
|
if (th->function.acv == (actionf_v)NULL)
|
|
{
|
|
for (i = 0; i < MAXCEILINGS;i++)
|
|
if (activeceilings[i] == (ceiling_t *)th)
|
|
break;
|
|
|
|
if (i<MAXCEILINGS)
|
|
{
|
|
saveg_write8(tc_ceiling);
|
|
saveg_write_pad();
|
|
saveg_write_ceiling_t((ceiling_t *) th);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (th->function.acp1 == (actionf_p1)T_MoveCeiling)
|
|
{
|
|
saveg_write8(tc_ceiling);
|
|
saveg_write_pad();
|
|
saveg_write_ceiling_t((ceiling_t *) th);
|
|
continue;
|
|
}
|
|
|
|
if (th->function.acp1 == (actionf_p1)T_VerticalDoor)
|
|
{
|
|
saveg_write8(tc_door);
|
|
saveg_write_pad();
|
|
saveg_write_vldoor_t((vldoor_t *) th);
|
|
continue;
|
|
}
|
|
|
|
if (th->function.acp1 == (actionf_p1)T_MoveFloor)
|
|
{
|
|
saveg_write8(tc_floor);
|
|
saveg_write_pad();
|
|
saveg_write_floormove_t((floormove_t *) th);
|
|
continue;
|
|
}
|
|
|
|
if (th->function.acp1 == (actionf_p1)T_PlatRaise)
|
|
{
|
|
saveg_write8(tc_plat);
|
|
saveg_write_pad();
|
|
saveg_write_plat_t((plat_t *) th);
|
|
continue;
|
|
}
|
|
|
|
if (th->function.acp1 == (actionf_p1)T_LightFlash)
|
|
{
|
|
saveg_write8(tc_flash);
|
|
saveg_write_pad();
|
|
saveg_write_lightflash_t((lightflash_t *) th);
|
|
continue;
|
|
}
|
|
|
|
if (th->function.acp1 == (actionf_p1)T_StrobeFlash)
|
|
{
|
|
saveg_write8(tc_strobe);
|
|
saveg_write_pad();
|
|
saveg_write_strobe_t((strobe_t *) th);
|
|
continue;
|
|
}
|
|
|
|
if (th->function.acp1 == (actionf_p1)T_Glow)
|
|
{
|
|
saveg_write8(tc_glow);
|
|
saveg_write_pad();
|
|
saveg_write_glow_t((glow_t *) th);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// add a terminating marker
|
|
saveg_write8(tc_endspecials);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// P_UnArchiveSpecials
|
|
//
|
|
void P_UnArchiveSpecials (void)
|
|
{
|
|
byte tclass;
|
|
ceiling_t* ceiling;
|
|
vldoor_t* door;
|
|
floormove_t* floor;
|
|
plat_t* plat;
|
|
lightflash_t* flash;
|
|
strobe_t* strobe;
|
|
glow_t* glow;
|
|
|
|
|
|
// read in saved thinkers
|
|
while (1)
|
|
{
|
|
tclass = saveg_read8();
|
|
|
|
switch (tclass)
|
|
{
|
|
case tc_endspecials:
|
|
return; // end of list
|
|
|
|
case tc_ceiling:
|
|
saveg_read_pad();
|
|
ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL);
|
|
saveg_read_ceiling_t(ceiling);
|
|
ceiling->sector->specialdata = ceiling;
|
|
|
|
if (ceiling->thinker.function.acp1)
|
|
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
|
|
|
|
P_AddThinker (&ceiling->thinker);
|
|
P_AddActiveCeiling(ceiling);
|
|
break;
|
|
|
|
case tc_door:
|
|
saveg_read_pad();
|
|
door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL);
|
|
saveg_read_vldoor_t(door);
|
|
door->sector->specialdata = door;
|
|
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
|
|
P_AddThinker (&door->thinker);
|
|
break;
|
|
|
|
case tc_floor:
|
|
saveg_read_pad();
|
|
floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
|
|
saveg_read_floormove_t(floor);
|
|
floor->sector->specialdata = floor;
|
|
floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor;
|
|
P_AddThinker (&floor->thinker);
|
|
break;
|
|
|
|
case tc_plat:
|
|
saveg_read_pad();
|
|
plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
|
|
saveg_read_plat_t(plat);
|
|
plat->sector->specialdata = plat;
|
|
|
|
if (plat->thinker.function.acp1)
|
|
plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
|
|
|
|
P_AddThinker (&plat->thinker);
|
|
P_AddActivePlat(plat);
|
|
break;
|
|
|
|
case tc_flash:
|
|
saveg_read_pad();
|
|
flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
|
|
saveg_read_lightflash_t(flash);
|
|
flash->thinker.function.acp1 = (actionf_p1)T_LightFlash;
|
|
P_AddThinker (&flash->thinker);
|
|
break;
|
|
|
|
case tc_strobe:
|
|
saveg_read_pad();
|
|
strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
|
|
saveg_read_strobe_t(strobe);
|
|
strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash;
|
|
P_AddThinker (&strobe->thinker);
|
|
break;
|
|
|
|
case tc_glow:
|
|
saveg_read_pad();
|
|
glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
|
|
saveg_read_glow_t(glow);
|
|
glow->thinker.function.acp1 = (actionf_p1)T_Glow;
|
|
P_AddThinker (&glow->thinker);
|
|
break;
|
|
|
|
default:
|
|
I_Error ("P_UnarchiveSpecials:Unknown tclass %i "
|
|
"in savegame",tclass);
|
|
}
|
|
|
|
}
|
|
}
|