summaryrefslogtreecommitdiff
path: root/src/strife/p_saveg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/strife/p_saveg.c')
-rw-r--r--src/strife/p_saveg.c2215
1 files changed, 2215 insertions, 0 deletions
diff --git a/src/strife/p_saveg.c b/src/strife/p_saveg.c
new file mode 100644
index 00000000..2dc779f9
--- /dev/null
+++ b/src/strife/p_saveg.c
@@ -0,0 +1,2215 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Archiving: SaveGame I/O.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dstrings.h"
+#include "deh_main.h"
+#include "i_system.h"
+#include "z_zone.h"
+#include "p_local.h"
+#include "p_saveg.h"
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+
+#define SAVEGAME_EOF 0x1d
+
+// haleyjd 09/28/10: [STRIFE] VERSIONSIZE == 8
+#define VERSIONSIZE 8
+
+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 = malloc(strlen(savegamedir) + 32);
+ }
+
+ sprintf(filename, "%stemp.dsg", savegamedir);
+
+ 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;
+ char basename[32];
+
+ if (filename == NULL)
+ {
+ filename = malloc(strlen(savegamedir) + 32);
+ }
+
+ DEH_snprintf(basename, 32, SAVEGAMENAME "%d.dsg", slot);
+
+ sprintf(filename, "%s%s", savegamedir, basename);
+
+ return filename;
+}
+
+// Endian-safe integer read/write functions
+
+static byte saveg_read8(void)
+{
+ byte result;
+
+ if (fread(&result, 1, 1, save_stream) < 1)
+ {
+ if (!savegame_error)
+ {
+ fprintf(stderr, "saveg_read8: Unexpected end of file while "
+ "reading save game\n");
+
+ savegame_error = true;
+ }
+ }
+
+ return result;
+}
+
+static void saveg_write8(byte value)
+{
+ if (fwrite(&value, 1, 1, save_stream) < 1)
+ {
+ if (!savegame_error)
+ {
+ fprintf(stderr, "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 = 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 = 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 *) saveg_read32();
+}
+
+static void saveg_writep(void *p)
+{
+ saveg_write32((int) 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
+//
+// haleyjd 09/28/10: [STRIFE] Changed to match Strife binary mobj_t structure.
+//
+
+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();
+
+ // byte miscdata;
+ str->miscdata = saveg_read8(); // [STRIFE] Only change to mobj_t.
+}
+
+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);
+
+ // byte miscdata;
+ saveg_write8(str->miscdata); // [STRIFE] Only change to mobj_t.
+}
+
+
+//
+// ticcmd_t
+//
+// haleyjd 09/28/10: [STRIFE] Modified for Strife binary ticcmd_t structure.
+//
+
+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;
+ // STRIFE-FIXME: throwing away top byte of consistancy until
+ // the true Strife ticcmd_t structure is available.
+ str->consistancy = (byte)saveg_read16();
+
+ // byte chatchar;
+ str->chatchar = saveg_read8();
+
+ // byte buttons;
+ str->buttons = saveg_read8();
+
+ // byte buttons2;
+ str->buttons2 = saveg_read8(); // [STRIFE]
+
+ // int inventory;
+ str->inventory = saveg_read32(); // [STRIFE]
+}
+
+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);
+
+ // byte buttons2;
+ saveg_write8(str->buttons2); // [STRIFE]
+
+ // int inventory;
+ saveg_write32(str->inventory); // [STRIFE]
+}
+
+//
+// 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);
+}
+
+//
+// inventory_t
+//
+// haleyjd 09/28/10: [STRIFE] handle inventory input/output
+//
+
+static void saveg_read_inventory_t(inventory_t *str)
+{
+ //int sprite;
+ str->sprite = saveg_read32();
+
+ //int type;
+ str->type = saveg_read32();
+
+ //int amount;
+ str->amount = saveg_read32();
+}
+
+static void saveg_write_inventory_t(inventory_t *str)
+{
+ saveg_write32(str->sprite);
+ saveg_write32(str->type);
+ saveg_write32(str->amount);
+}
+
+//
+// player_t
+//
+// haleyjd 09/28/10: [STRIFE] Modified for Strife binary player_t structure.
+//
+
+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_read16(); // [STRIFE] 32 -> 16
+
+ // int armortype;
+ str->armortype = saveg_read16(); // [STRIFE] 32 -> 16
+
+ // int powers[NUMPOWERS];
+ for (i=0; i<NUMPOWERS; ++i)
+ {
+ str->powers[i] = saveg_read32();
+ }
+
+ // int sigiltype;
+ str->sigiltype = saveg_read32(); // [STRIFE]
+
+ // int nukagecount;
+ str->nukagecount = saveg_read32(); // [STRIFE]
+
+ // int questflags;
+ str->questflags = saveg_read32(); // [STRIFE]
+
+ // int pitch;
+ str->pitch = saveg_read32(); // [STRIFE]
+
+ // int centerview;
+ str->centerview = saveg_read32(); // [STRIFE]
+
+ // inventory_t inventory[NUMINVENTORY];
+ for(i = 0; i < NUMINVENTORY; i++)
+ {
+ saveg_read_inventory_t(&(str->inventory[i])); // [STRIFE]
+ }
+
+ // int st_update;
+ str->st_update = saveg_read32(); // [STRIFE]
+
+ // short numinventory;
+ str->numinventory = saveg_read16(); // [STRIFE]
+
+ // short inventorycursor;
+ str->inventorycursor = saveg_read16(); // [STRIFE]
+
+ // short accuracy;
+ str->accuracy = saveg_read16(); // [STRIFE]
+
+ // short stamina;
+ str->stamina = saveg_read16(); // [STRIFE]
+
+ // boolean cards[NUMCARDS];
+ for (i=0; i<NUMCARDS; ++i)
+ {
+ str->cards[i] = saveg_read32();
+ }
+
+ // boolean backpack;
+ str->backpack = saveg_read32();
+
+ // int attackdown;
+ str->attackdown = saveg_read32();
+
+ // int usedown;
+ str->usedown = saveg_read32();
+
+ // int inventorydown;
+ str->inventorydown = saveg_read32(); // [STRIFE]
+
+ // 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 cheats;
+ str->cheats = saveg_read32();
+
+ // int refire;
+ str->refire = saveg_read32();
+
+ // short killcount;
+ str->killcount = saveg_read16(); // [STRIFE] 32 -> 16
+
+ // haleyjd 08/30/10 [STRIFE] No itemcount.
+ // int itemcount;
+ //str->itemcount = saveg_read32();
+
+ // haleyjd 08/30/10 [STRIFE] No secretcount.
+ // 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; - [STRIFE] no such field
+ //str->colormap = saveg_read32();
+
+ // short allegiance;
+ str->allegiance = saveg_read16(); // [STRIFE]
+
+ // pspdef_t psprites[NUMPSPRITES];
+ for (i=0; i<NUMPSPRITES; ++i)
+ {
+ saveg_read_pspdef_t(&str->psprites[i]);
+ }
+
+ // int mapstate[40];
+ for(i = 0; i < 40; ++i) // [STRIFE]
+ {
+ str->mapstate[i] = saveg_read32();
+ }
+
+ // haleyjd 08/30/10: [STRIFE] No intermission, no didsecret.
+ // 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_write16(str->armorpoints); // [STRIFE] 32 -> 16
+
+ // int armortype;
+ saveg_write16(str->armortype); // [STRIFE] 32 -> 16
+
+ // int powers[NUMPOWERS];
+ for (i=0; i<NUMPOWERS; ++i)
+ {
+ saveg_write32(str->powers[i]);
+ }
+
+ // int sigiltype;
+ saveg_write32(str->sigiltype); // [STRIFE]
+
+ // int nukagecount;
+ saveg_write32(str->nukagecount); // [STRIFE]
+
+ // int questflags;
+ saveg_write32(str->questflags); // [STRIFE]
+
+ // int pitch;
+ saveg_write32(str->pitch); // [STRIFE]
+
+ // int centerview;
+ saveg_write32(str->centerview); // [STRIFE]
+
+ // inventory_t inventory[NUMINVENTORY];
+ for(i = 0; i < NUMINVENTORY; ++i) // [STRIFE]
+ {
+ saveg_write_inventory_t(&str->inventory[i]);
+ }
+
+ // int st_update;
+ saveg_write32(str->st_update); // [STRIFE]
+
+ // short numinventory;
+ saveg_write16(str->numinventory); // [STRIFE]
+
+ // short inventorycursor;
+ saveg_write16(str->inventorycursor); // [STRIFE]
+
+ // short accuracy;
+ saveg_write16(str->accuracy); // [STRIFE]
+
+ // short stamina;
+ saveg_write16(str->stamina); // [STRIFE]
+
+ // boolean cards[NUMCARDS];
+ for (i=0; i<NUMCARDS; ++i)
+ {
+ saveg_write32(str->cards[i]);
+ }
+
+ // boolean backpack;
+ saveg_write32(str->backpack);
+
+ // int attackdown;
+ saveg_write32(str->attackdown);
+
+ // int usedown;
+ saveg_write32(str->usedown);
+
+ // int inventorydown;
+ saveg_write32(str->inventorydown); // [STRIFE]
+
+ // 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 cheats;
+ saveg_write32(str->cheats);
+
+ // int refire;
+ saveg_write32(str->refire);
+
+ // short killcount;
+ saveg_write16(str->killcount); // [STRIFE] 32 -> 16
+
+ // haleyjd 08/30/10 [STRIFE] No itemcount
+ // int itemcount;
+ //saveg_write32(str->itemcount);
+
+ // haleyjd 08/30/10 [STRIFE] No secretcount
+ // 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; [STRIFE] no such field
+ //saveg_write32(str->colormap);
+
+ // short allegiance;
+ saveg_write16(str->allegiance); // [STRIFE]
+
+ // pspdef_t psprites[NUMPSPRITES];
+ for (i=0; i<NUMPSPRITES; ++i)
+ {
+ saveg_write_pspdef_t(&str->psprites[i]);
+ }
+
+ // int mapstate[40];
+ for(i = 0; i < 40; ++i) // [STRIFE]
+ {
+ saveg_write32(str->mapstate[i]);
+ }
+
+ // haleyjd 08/30/10: [STRIFE] No intermission, no secret.
+ // 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 = &sectors[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
+//
+// haleyjd 09/28/10: [STRIFE] Modified for Strife binary vldoor_t structure.
+//
+
+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 = &sectors[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();
+
+ // villsa [STRIFE] new field - sound to play when opening
+ //int opensound;
+ str->opensound = saveg_read32();
+
+ // villsa [STRIFE] new field - sound to play when closing
+ //int closesound;
+ str->closesound = 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);
+
+ // villsa [STRIFE] new field - sound to play when opening
+ //int opensound;
+ saveg_write32(str->opensound);
+
+ // villsa [STRIFE] new field - sound to play when closing
+ //int closesound;
+ saveg_write32(str->closesound);
+}
+
+//
+// slidedoor_t [STRIFE]: new thinker type
+//
+
+static void saveg_read_slidedoor_t(slidedoor_t *str)
+{
+ int sector;
+ int line;
+
+ // thinker_t thinker;
+ saveg_read_thinker_t(&str->thinker);
+
+ // sdt_e type;
+ str->type = saveg_read_enum();
+
+ // line_t *line1;
+ line = saveg_read32();
+ str->line1 = &lines[line];
+
+ // line_t *line2;
+ line = saveg_read32();
+ str->line2 = &lines[line];
+
+ // int frame;
+ str->frame = saveg_read32();
+
+ // int whichDoorIndex;
+ str->whichDoorIndex = saveg_read32();
+
+ // int timer;
+ str->timer = saveg_read32();
+
+ // sector_t *frontsector;
+ sector = saveg_read32();
+ str->frontsector = &sectors[sector];
+
+ // sd_e status;
+ str->status = saveg_read_enum();
+}
+
+static void saveg_write_slidedoor_t(slidedoor_t *str)
+{
+ // thinker_t thinker;
+ saveg_write_thinker_t(&str->thinker);
+
+ // sdt_e type;
+ saveg_write_enum(str->type);
+
+ // line_t *line1;
+ saveg_write32(str->line1 - lines);
+
+ // line_t *line2;
+ saveg_write32(str->line2 - lines);
+
+ // int frame;
+ saveg_write32(str->frame);
+
+ // int whichDoorIndex;
+ saveg_write32(str->whichDoorIndex);
+
+ // int timer;
+ saveg_write32(str->timer);
+
+ // sector_t *frontsector;
+ saveg_write32(str->frontsector - sectors);
+
+ // sd_e status;
+ saveg_write_enum(str->status);
+}
+
+//
+// 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 = &sectors[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 = &sectors[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 = &sectors[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 = &sectors[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 = &sectors[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
+//
+// haleyjd 09/28/10: [STRIFE] numerous modifications.
+//
+
+void P_WriteSaveGameHeader(char *description)
+{
+ char name[VERSIONSIZE];
+ int i;
+
+ /*
+ [STRIFE] This is in the "NAME" file in a Strife save directory.
+ for (i=0; description[i] != '\0'; ++i)
+ saveg_write8(description[i]);
+ for (; i<SAVESTRINGSIZE; ++i)
+ saveg_write8(0);
+ */
+
+ memset (name,0,sizeof(name));
+ sprintf (name,"ver %i",STRIFE_VERSION);
+
+ for (i=0; i<VERSIONSIZE; ++i)
+ saveg_write8(name[i]);
+
+ saveg_write8(gameskill);
+
+ // [STRIFE] This information is implicit in the file being loaded.
+ //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();
+
+ memset (vcheck,0,sizeof(vcheck));
+ sprintf (vcheck,"ver %i",STRIFE_VERSION);
+ if (strcmp(read_vcheck, vcheck) != 0)
+ return false; // bad version
+
+ gameskill = saveg_read8();
+
+ // [STRIFE] This info is implicit in the file being read.
+ //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
+//
+// [STRIFE] Verified unmodified.
+//
+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
+//
+// [STRIFE] Verified unmodified.
+//
+void P_UnArchivePlayers (boolean userload)
+{
+ int i;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ player_t dummy;
+
+ if (!playeringame[i])
+ continue;
+
+ saveg_read_pad();
+
+ // haleyjd [STRIFE]: not exactly how vanilla did it, but this is
+ // necessary because of Choco's change to the savegame code which
+ // reads it directly from file. When not a userload, all the player_t
+ // data loaded from the save is thrown away.
+ if(userload)
+ {
+ saveg_read_player_t(&players[i]);
+ players[i].mo = NULL;
+ }
+ else
+ saveg_read_player_t(&dummy);
+
+ // will be set when unarc thinker
+ players[i].message = NULL;
+ players[i].attacker = NULL;
+ }
+}
+
+
+//
+// P_ArchiveWorld
+//
+// haleyjd 09/28/10: [STRIFE] Minor modifications.
+//
+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); [STRIFE] not saved.
+ saveg_write16(sec->lightlevel);
+ saveg_write16(sec->special); // needed?
+ //saveg_write16(sec->tag); // needed? [STRIFE] not saved.
+ }
+
+
+ // do lines
+ for (i=0, li = lines ; i<numlines ; i++,li++)
+ {
+ saveg_write16(li->flags);
+ saveg_write16(li->special);
+ //saveg_write16(li->tag); [STRIFE] not saved.
+ for (j=0 ; j<2 ; j++)
+ {
+ if (li->sidenum[j] == -1)
+ continue;
+
+ si = &sides[li->sidenum[j]];
+
+ // [STRIFE] offsets not saved.
+ //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(); [STRIFE] not saved
+ sec->lightlevel = saveg_read16();
+ sec->special = saveg_read16(); // needed?
+ //sec->tag = saveg_read16(); // needed? [STRIFE] not saved
+ 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(); [STRIFE] not saved
+ for (j=0 ; j<2 ; j++)
+ {
+ if (li->sidenum[j] == -1)
+ continue;
+ si = &sides[li->sidenum[j]];
+ // [STRIFE] offsets not saved.
+ //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
+//
+// [STRIFE] Verified unmodified.
+//
+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;
+ }
+
+ // haleyjd: This may seem mysterious but in the DOOM prebeta,
+ // different types of things used different thinker functions.
+ // Those would have all been handled here and this message is
+ // probably a relic of that old system, not to mention the odd
+ // name of this function, and use of an enumeration with only
+ // two values in it.
+
+ // 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);
+
+ // haleyjd 09/29/10: Strife sets the targets of non-allied creatures
+ // who had a non-NULL target at save time to players[0].mo so that
+ // they won't fall back asleep.
+ //
+ // BUG: As the player may not have been spawned yet, we could be
+ // setting monsters' targets to the mobj which was spawned by
+ // P_SetupLevel and then removed just above. Due to a subtle glitch
+ // in the DOOM engine whereby all things removed in this function
+ // are leaked until the next time P_SetupLevel is called, this is a
+ // safe operation - the call to P_InitThinkers above stops any of
+ // the objects removed, including the player's previous body, from
+ // being passed to Z_Free. One glitch relying on another!
+
+ if(mobj->target != NULL && (mobj->flags & MF_ALLY) != MF_ALLY)
+ mobj->target = players[0].mo;
+ else
+ mobj->target = NULL;
+
+ // WARNING! Strife does not seem to set tracer! I am leaving it be
+ // for now because so far no crashes have been observed, and failing
+ // to set this here will almost certainly crash Choco.
+ mobj->tracer = NULL;
+ P_SetThingPosition (mobj);
+ mobj->info = &mobjinfo[mobj->type];
+ // [STRIFE]: doesn't set these
+ //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_slidingdoor, // [STRIFE]
+ tc_endspecials
+
+} specials_e;
+
+
+
+//
+// Things to handle:
+//
+// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
+// T_VerticalDoor, (vldoor_t: sector_t * swizzle),
+// T_SlidingDoor, (slidedoor_t: sector_t *, line_t * x 2 swizzle) [STRIFE]
+// 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_SlidingDoor)
+ {
+ saveg_write8(tc_slidingdoor);
+ saveg_write_pad();
+ saveg_write_slidedoor_t((slidedoor_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;
+ slidedoor_t* slidedoor; // haleyjd [STRIFE]
+ 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_slidingdoor:
+ // haleyjd 09/29/10: [STRIFE] New thinker type for sliding doors
+ saveg_read_pad();
+ slidedoor = Z_Malloc(sizeof(*slidedoor), PU_LEVEL, NULL);
+ saveg_read_slidedoor_t(slidedoor);
+ slidedoor->frontsector->specialdata = slidedoor;
+ slidedoor->thinker.function.acp1 = (actionf_p1)T_SlidingDoor;
+ P_AddThinker(&slidedoor->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);
+ }
+ }
+}
+