2014-03-15 16:59:03 +00:00
|
|
|
// SONIC ROBO BLAST 2
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
|
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
2023-03-31 12:53:31 +00:00
|
|
|
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
2014-03-15 16:59:03 +00:00
|
|
|
//
|
|
|
|
// This program is free software distributed under the
|
|
|
|
// terms of the GNU General Public License, version 2.
|
|
|
|
// See the 'LICENSE' file for more details.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/// \file p_saveg.c
|
|
|
|
/// \brief Archiving: SaveGame I/O
|
|
|
|
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "byteptr.h"
|
|
|
|
#include "d_main.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
#include "g_game.h"
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "m_misc.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
#include "p_setup.h"
|
|
|
|
#include "p_saveg.h"
|
2018-09-11 00:36:34 +00:00
|
|
|
#include "r_data.h"
|
2022-04-23 18:13:58 +00:00
|
|
|
#include "r_fps.h"
|
2020-01-07 15:35:10 +00:00
|
|
|
#include "r_textures.h"
|
2014-03-15 16:59:03 +00:00
|
|
|
#include "r_things.h"
|
2020-03-09 13:54:56 +00:00
|
|
|
#include "r_skins.h"
|
2014-03-15 16:59:03 +00:00
|
|
|
#include "r_state.h"
|
|
|
|
#include "w_wad.h"
|
|
|
|
#include "y_inter.h"
|
|
|
|
#include "z_zone.h"
|
|
|
|
#include "r_main.h"
|
|
|
|
#include "r_sky.h"
|
|
|
|
#include "p_polyobj.h"
|
|
|
|
#include "lua_script.h"
|
2015-08-03 23:06:42 +00:00
|
|
|
#include "p_slopes.h"
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
savedata_t savedata;
|
|
|
|
UINT8 *save_p;
|
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
// Block UINT32s to attempt to ensure that the correct data is
|
|
|
|
// being sent and received
|
2023-08-24 19:04:31 +00:00
|
|
|
#define ARCHIVEBLOCK_MISC 0x7FEEDEED
|
|
|
|
#define ARCHIVEBLOCK_PLAYERS 0x7F448008
|
|
|
|
#define ARCHIVEBLOCK_WORLD 0x7F8C08C0
|
|
|
|
#define ARCHIVEBLOCK_POBJS 0x7F928546
|
|
|
|
#define ARCHIVEBLOCK_THINKERS 0x7F37037C
|
|
|
|
#define ARCHIVEBLOCK_SPECIALS 0x7F228378
|
|
|
|
#define ARCHIVEBLOCK_EMBLEMS 0x7F4A5445
|
|
|
|
#define ARCHIVEBLOCK_SECPORTALS 0x7FBE34C9
|
2014-03-17 12:13:16 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// Note: This cannot be bigger
|
|
|
|
// than an UINT16
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
CAPSULE = 0x04,
|
|
|
|
AWAYVIEW = 0x08,
|
|
|
|
FIRSTAXIS = 0x10,
|
|
|
|
SECONDAXIS = 0x20,
|
2017-10-02 13:08:58 +00:00
|
|
|
FOLLOW = 0x40,
|
2018-08-10 23:25:49 +00:00
|
|
|
DRONE = 0x80,
|
2014-03-15 16:59:03 +00:00
|
|
|
} player_saveflags;
|
|
|
|
|
|
|
|
static inline void P_ArchivePlayer(void)
|
|
|
|
{
|
|
|
|
const player_t *player = &players[consoleplayer];
|
2017-08-17 23:58:16 +00:00
|
|
|
SINT8 pllives = player->lives;
|
|
|
|
if (pllives < startinglivesbalance[numgameovers]) // Bump up to 3 lives if the player
|
|
|
|
pllives = startinglivesbalance[numgameovers]; // has less than that.
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2021-05-06 21:41:43 +00:00
|
|
|
#ifdef NEWSKINSAVES
|
2021-05-08 00:13:16 +00:00
|
|
|
// Write a specific value into the old skininfo location.
|
|
|
|
// If we read something other than this, it's an older save file that used skin numbers.
|
2021-05-06 21:41:43 +00:00
|
|
|
WRITEUINT16(save_p, NEWSKINSAVES);
|
|
|
|
#endif
|
|
|
|
|
2021-05-08 00:13:16 +00:00
|
|
|
// Write skin names, so that loading skins in different orders
|
|
|
|
// doesn't change who the save file is for!
|
2021-08-09 18:57:07 +00:00
|
|
|
WRITESTRINGN(save_p, skins[player->skin]->name, SKINNAMESIZE);
|
2021-05-06 21:41:43 +00:00
|
|
|
|
|
|
|
if (botskin != 0)
|
|
|
|
{
|
2021-08-09 18:57:07 +00:00
|
|
|
WRITESTRINGN(save_p, skins[botskin-1]->name, SKINNAMESIZE);
|
2021-05-06 21:41:43 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-08 00:13:16 +00:00
|
|
|
WRITESTRINGN(save_p, "\0", SKINNAMESIZE);
|
2021-05-06 21:41:43 +00:00
|
|
|
}
|
|
|
|
|
2017-08-17 23:58:16 +00:00
|
|
|
WRITEUINT8(save_p, numgameovers);
|
|
|
|
WRITESINT8(save_p, pllives);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT32(save_p, player->score);
|
|
|
|
WRITEINT32(save_p, player->continues);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void P_UnArchivePlayer(void)
|
|
|
|
{
|
2021-05-06 21:41:43 +00:00
|
|
|
#ifdef NEWSKINSAVES
|
|
|
|
INT16 backwardsCompat = READUINT16(save_p);
|
|
|
|
|
|
|
|
if (backwardsCompat != NEWSKINSAVES)
|
|
|
|
{
|
2021-05-08 00:13:16 +00:00
|
|
|
// This is an older save file, which used direct skin numbers.
|
2021-05-06 21:41:43 +00:00
|
|
|
savedata.skin = backwardsCompat & ((1<<5) - 1);
|
|
|
|
savedata.botskin = backwardsCompat >> 5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
char ourSkinName[SKINNAMESIZE+1];
|
2021-05-08 00:13:16 +00:00
|
|
|
char botSkinName[SKINNAMESIZE+1];
|
2021-05-06 21:41:43 +00:00
|
|
|
|
|
|
|
READSTRINGN(save_p, ourSkinName, SKINNAMESIZE);
|
|
|
|
savedata.skin = R_SkinAvailable(ourSkinName);
|
|
|
|
|
2021-05-08 00:13:16 +00:00
|
|
|
READSTRINGN(save_p, botSkinName, SKINNAMESIZE);
|
|
|
|
savedata.botskin = R_SkinAvailable(botSkinName) + 1;
|
2021-05-06 21:41:43 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2017-08-17 23:58:16 +00:00
|
|
|
savedata.numgameovers = READUINT8(save_p);
|
|
|
|
savedata.lives = READSINT8(save_p);
|
|
|
|
savedata.score = READUINT32(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
savedata.continues = READINT32(save_p);
|
|
|
|
}
|
|
|
|
|
2016-05-27 03:39:08 +00:00
|
|
|
static void P_NetArchivePlayers(void)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
INT32 i, j;
|
|
|
|
UINT16 flags;
|
|
|
|
// size_t q;
|
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
WRITEUINT32(save_p, ARCHIVEBLOCK_PLAYERS);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
{
|
2020-01-31 14:29:22 +00:00
|
|
|
WRITESINT8(save_p, (SINT8)adminplayers[i]);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
if (!playeringame[i])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
flags = 0;
|
|
|
|
|
2020-01-31 14:29:22 +00:00
|
|
|
// no longer send ticcmds
|
2014-08-04 03:49:33 +00:00
|
|
|
|
2020-01-31 14:29:22 +00:00
|
|
|
WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME);
|
2020-05-28 09:03:35 +00:00
|
|
|
WRITEINT16(save_p, players[i].angleturn);
|
|
|
|
WRITEINT16(save_p, players[i].oldrelangleturn);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEANGLE(save_p, players[i].aiming);
|
2017-02-05 18:15:20 +00:00
|
|
|
WRITEANGLE(save_p, players[i].drawangle);
|
2020-01-18 00:32:13 +00:00
|
|
|
WRITEANGLE(save_p, players[i].viewrollangle);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEANGLE(save_p, players[i].awayviewaiming);
|
|
|
|
WRITEINT32(save_p, players[i].awayviewtics);
|
2018-06-03 21:41:54 +00:00
|
|
|
WRITEINT16(save_p, players[i].rings);
|
|
|
|
WRITEINT16(save_p, players[i].spheres);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
WRITESINT8(save_p, players[i].pity);
|
|
|
|
WRITEINT32(save_p, players[i].currentweapon);
|
|
|
|
WRITEINT32(save_p, players[i].ringweapons);
|
|
|
|
|
2019-08-26 23:07:17 +00:00
|
|
|
WRITEUINT16(save_p, players[i].ammoremoval);
|
|
|
|
WRITEUINT32(save_p, players[i].ammoremovaltimer);
|
|
|
|
WRITEINT32(save_p, players[i].ammoremovaltimer);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
for (j = 0; j < NUMPOWERS; j++)
|
|
|
|
WRITEUINT16(save_p, players[i].powers[j]);
|
|
|
|
|
|
|
|
WRITEUINT8(save_p, players[i].playerstate);
|
|
|
|
WRITEUINT32(save_p, players[i].pflags);
|
|
|
|
WRITEUINT8(save_p, players[i].panim);
|
2023-07-05 17:05:47 +00:00
|
|
|
WRITEUINT8(save_p, players[i].stronganim);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT8(save_p, players[i].spectator);
|
2024-02-27 10:58:59 +00:00
|
|
|
WRITEUINT8(save_p, players[i].muted);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
WRITEUINT16(save_p, players[i].flashpal);
|
|
|
|
WRITEUINT16(save_p, players[i].flashcount);
|
|
|
|
|
2023-10-29 17:43:40 +00:00
|
|
|
WRITEUINT16(save_p, players[i].skincolor);
|
2020-01-31 14:29:22 +00:00
|
|
|
WRITEINT32(save_p, players[i].skin);
|
|
|
|
WRITEUINT32(save_p, players[i].availabilities);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT32(save_p, players[i].score);
|
2022-03-02 22:47:15 +00:00
|
|
|
WRITEUINT32(save_p, players[i].recordscore);
|
2014-11-12 00:55:07 +00:00
|
|
|
WRITEFIXED(save_p, players[i].dashspeed);
|
2014-03-21 18:42:55 +00:00
|
|
|
WRITESINT8(save_p, players[i].lives);
|
|
|
|
WRITESINT8(save_p, players[i].continues);
|
|
|
|
WRITESINT8(save_p, players[i].xtralife);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT8(save_p, players[i].gotcontinue);
|
2014-11-12 00:55:07 +00:00
|
|
|
WRITEFIXED(save_p, players[i].speed);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT8(save_p, players[i].secondjump);
|
|
|
|
WRITEUINT8(save_p, players[i].fly1);
|
|
|
|
WRITEUINT8(save_p, players[i].scoreadd);
|
|
|
|
WRITEUINT32(save_p, players[i].glidetime);
|
|
|
|
WRITEUINT8(save_p, players[i].climbing);
|
|
|
|
WRITEINT32(save_p, players[i].deadtimer);
|
|
|
|
WRITEUINT32(save_p, players[i].exiting);
|
|
|
|
WRITEUINT8(save_p, players[i].homing);
|
2016-01-25 11:47:33 +00:00
|
|
|
WRITEUINT32(save_p, players[i].dashmode);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT32(save_p, players[i].skidtime);
|
|
|
|
|
2021-01-23 15:39:59 +00:00
|
|
|
//////////
|
|
|
|
// Bots //
|
|
|
|
//////////
|
|
|
|
WRITEUINT8(save_p, players[i].bot);
|
|
|
|
WRITEUINT8(save_p, players[i].botmem.lastForward);
|
|
|
|
WRITEUINT8(save_p, players[i].botmem.lastBlocked);
|
|
|
|
WRITEUINT8(save_p, players[i].botmem.catchup_tics);
|
|
|
|
WRITEUINT8(save_p, players[i].botmem.thinkstate);
|
2021-07-15 22:04:24 +00:00
|
|
|
WRITEUINT8(save_p, players[i].removing);
|
2022-11-12 01:38:52 +00:00
|
|
|
|
2021-01-23 15:39:59 +00:00
|
|
|
WRITEUINT8(save_p, players[i].blocked);
|
|
|
|
WRITEUINT16(save_p, players[i].lastbuttons);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
////////////////////////////
|
|
|
|
// Conveyor Belt Movement //
|
|
|
|
////////////////////////////
|
|
|
|
WRITEFIXED(save_p, players[i].cmomx); // Conveyor momx
|
|
|
|
WRITEFIXED(save_p, players[i].cmomy); // Conveyor momy
|
|
|
|
WRITEFIXED(save_p, players[i].rmomx); // "Real" momx (momx - cmomx)
|
|
|
|
WRITEFIXED(save_p, players[i].rmomy); // "Real" momy (momy - cmomy)
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
// Race Mode Stuff //
|
|
|
|
/////////////////////
|
2014-11-12 00:55:07 +00:00
|
|
|
WRITEINT16(save_p, players[i].numboxes);
|
|
|
|
WRITEINT16(save_p, players[i].totalring);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT32(save_p, players[i].realtime);
|
2014-03-21 18:42:55 +00:00
|
|
|
WRITEUINT8(save_p, players[i].laps);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
////////////////////
|
|
|
|
// CTF Mode Stuff //
|
|
|
|
////////////////////
|
|
|
|
WRITEINT32(save_p, players[i].ctfteam);
|
|
|
|
WRITEUINT16(save_p, players[i].gotflag);
|
|
|
|
|
|
|
|
WRITEINT32(save_p, players[i].weapondelay);
|
|
|
|
WRITEINT32(save_p, players[i].tossdelay);
|
|
|
|
|
|
|
|
WRITEUINT32(save_p, players[i].starposttime);
|
|
|
|
WRITEINT16(save_p, players[i].starpostx);
|
|
|
|
WRITEINT16(save_p, players[i].starposty);
|
|
|
|
WRITEINT16(save_p, players[i].starpostz);
|
|
|
|
WRITEINT32(save_p, players[i].starpostnum);
|
|
|
|
WRITEANGLE(save_p, players[i].starpostangle);
|
2019-09-07 21:11:33 +00:00
|
|
|
WRITEFIXED(save_p, players[i].starpostscale);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
WRITEANGLE(save_p, players[i].angle_pos);
|
|
|
|
WRITEANGLE(save_p, players[i].old_angle_pos);
|
|
|
|
|
|
|
|
WRITEINT32(save_p, players[i].flyangle);
|
|
|
|
WRITEUINT32(save_p, players[i].drilltimer);
|
|
|
|
WRITEINT32(save_p, players[i].linkcount);
|
|
|
|
WRITEUINT32(save_p, players[i].linktimer);
|
|
|
|
WRITEINT32(save_p, players[i].anotherflyangle);
|
|
|
|
WRITEUINT32(save_p, players[i].nightstime);
|
|
|
|
WRITEUINT32(save_p, players[i].bumpertime);
|
|
|
|
WRITEINT32(save_p, players[i].drillmeter);
|
|
|
|
WRITEUINT8(save_p, players[i].drilldelay);
|
|
|
|
WRITEUINT8(save_p, players[i].bonustime);
|
2018-08-11 04:49:28 +00:00
|
|
|
WRITEFIXED(save_p, players[i].oldscale);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT8(save_p, players[i].mare);
|
2018-03-30 18:36:49 +00:00
|
|
|
WRITEUINT8(save_p, players[i].marelap);
|
|
|
|
WRITEUINT8(save_p, players[i].marebonuslap);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT32(save_p, players[i].marebegunat);
|
2023-09-28 20:22:29 +00:00
|
|
|
WRITEUINT32(save_p, players[i].lastmaretime);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT32(save_p, players[i].startedtime);
|
|
|
|
WRITEUINT32(save_p, players[i].finishedtime);
|
2018-08-10 21:12:26 +00:00
|
|
|
WRITEUINT32(save_p, players[i].lapbegunat);
|
|
|
|
WRITEUINT32(save_p, players[i].lapstartedtime);
|
2018-06-03 21:41:54 +00:00
|
|
|
WRITEINT16(save_p, players[i].finishedspheres);
|
2014-11-12 00:55:07 +00:00
|
|
|
WRITEINT16(save_p, players[i].finishedrings);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT32(save_p, players[i].marescore);
|
|
|
|
WRITEUINT32(save_p, players[i].lastmarescore);
|
2018-08-12 23:59:34 +00:00
|
|
|
WRITEUINT32(save_p, players[i].totalmarescore);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT8(save_p, players[i].lastmare);
|
2018-08-10 20:30:49 +00:00
|
|
|
WRITEUINT8(save_p, players[i].lastmarelap);
|
|
|
|
WRITEUINT8(save_p, players[i].lastmarebonuslap);
|
2018-08-12 23:57:33 +00:00
|
|
|
WRITEUINT8(save_p, players[i].totalmarelap);
|
|
|
|
WRITEUINT8(save_p, players[i].totalmarebonuslap);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEINT32(save_p, players[i].maxlink);
|
|
|
|
WRITEUINT8(save_p, players[i].texttimer);
|
|
|
|
WRITEUINT8(save_p, players[i].textvar);
|
|
|
|
|
|
|
|
if (players[i].capsule)
|
|
|
|
flags |= CAPSULE;
|
|
|
|
|
|
|
|
if (players[i].awayviewmobj)
|
|
|
|
flags |= AWAYVIEW;
|
|
|
|
|
|
|
|
if (players[i].axis1)
|
|
|
|
flags |= FIRSTAXIS;
|
|
|
|
|
|
|
|
if (players[i].axis2)
|
|
|
|
flags |= SECONDAXIS;
|
|
|
|
|
2017-10-02 13:08:58 +00:00
|
|
|
if (players[i].followmobj)
|
|
|
|
flags |= FOLLOW;
|
|
|
|
|
2018-08-10 23:25:49 +00:00
|
|
|
if (players[i].drone)
|
|
|
|
flags |= DRONE;
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEINT16(save_p, players[i].lastsidehit);
|
|
|
|
WRITEINT16(save_p, players[i].lastlinehit);
|
|
|
|
|
|
|
|
WRITEUINT32(save_p, players[i].losstime);
|
|
|
|
|
|
|
|
WRITEUINT8(save_p, players[i].timeshit);
|
|
|
|
|
|
|
|
WRITEINT32(save_p, players[i].onconveyor);
|
|
|
|
|
|
|
|
WRITEUINT32(save_p, players[i].jointime);
|
2020-01-22 02:05:08 +00:00
|
|
|
WRITEUINT32(save_p, players[i].quittime);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
WRITEUINT16(save_p, flags);
|
|
|
|
|
|
|
|
if (flags & CAPSULE)
|
|
|
|
WRITEUINT32(save_p, players[i].capsule->mobjnum);
|
|
|
|
|
|
|
|
if (flags & FIRSTAXIS)
|
|
|
|
WRITEUINT32(save_p, players[i].axis1->mobjnum);
|
|
|
|
|
|
|
|
if (flags & SECONDAXIS)
|
|
|
|
WRITEUINT32(save_p, players[i].axis2->mobjnum);
|
|
|
|
|
|
|
|
if (flags & AWAYVIEW)
|
|
|
|
WRITEUINT32(save_p, players[i].awayviewmobj->mobjnum);
|
|
|
|
|
2017-10-02 13:08:58 +00:00
|
|
|
if (flags & FOLLOW)
|
|
|
|
WRITEUINT32(save_p, players[i].followmobj->mobjnum);
|
|
|
|
|
2018-08-10 23:25:49 +00:00
|
|
|
if (flags & DRONE)
|
|
|
|
WRITEUINT32(save_p, players[i].drone->mobjnum);
|
|
|
|
|
2016-09-25 17:21:52 +00:00
|
|
|
WRITEFIXED(save_p, players[i].camerascale);
|
|
|
|
WRITEFIXED(save_p, players[i].shieldscale);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT8(save_p, players[i].charability);
|
|
|
|
WRITEUINT8(save_p, players[i].charability2);
|
|
|
|
WRITEUINT32(save_p, players[i].charflags);
|
|
|
|
WRITEUINT32(save_p, (UINT32)players[i].thokitem);
|
|
|
|
WRITEUINT32(save_p, (UINT32)players[i].spinitem);
|
|
|
|
WRITEUINT32(save_p, (UINT32)players[i].revitem);
|
2017-10-02 13:08:58 +00:00
|
|
|
WRITEUINT32(save_p, (UINT32)players[i].followitem);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEFIXED(save_p, players[i].actionspd);
|
|
|
|
WRITEFIXED(save_p, players[i].mindash);
|
|
|
|
WRITEFIXED(save_p, players[i].maxdash);
|
|
|
|
WRITEFIXED(save_p, players[i].normalspeed);
|
|
|
|
WRITEFIXED(save_p, players[i].runspeed);
|
|
|
|
WRITEUINT8(save_p, players[i].thrustfactor);
|
|
|
|
WRITEUINT8(save_p, players[i].accelstart);
|
|
|
|
WRITEUINT8(save_p, players[i].acceleration);
|
|
|
|
WRITEFIXED(save_p, players[i].jumpfactor);
|
2016-09-25 17:21:52 +00:00
|
|
|
WRITEFIXED(save_p, players[i].height);
|
|
|
|
WRITEFIXED(save_p, players[i].spinheight);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-27 13:49:11 +00:00
|
|
|
static void P_NetUnArchivePlayers(void)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
INT32 i, j;
|
|
|
|
UINT16 flags;
|
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
if (READUINT32(save_p) != ARCHIVEBLOCK_PLAYERS)
|
|
|
|
I_Error("Bad $$$.sav at archive block Players");
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
{
|
2020-01-31 14:29:22 +00:00
|
|
|
adminplayers[i] = (INT32)READSINT8(save_p);
|
|
|
|
|
2014-08-04 03:49:33 +00:00
|
|
|
// Do NOT memset player struct to 0
|
|
|
|
// other areas may initialize data elsewhere
|
|
|
|
//memset(&players[i], 0, sizeof (player_t));
|
2014-03-15 16:59:03 +00:00
|
|
|
if (!playeringame[i])
|
|
|
|
continue;
|
|
|
|
|
2014-08-04 03:49:33 +00:00
|
|
|
// NOTE: sending tics should (hopefully) no longer be necessary
|
2014-03-21 18:42:55 +00:00
|
|
|
|
2020-01-31 14:29:22 +00:00
|
|
|
READSTRINGN(save_p, player_names[i], MAXPLAYERNAME);
|
2020-05-28 09:03:35 +00:00
|
|
|
players[i].angleturn = READINT16(save_p);
|
|
|
|
players[i].oldrelangleturn = READINT16(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].aiming = READANGLE(save_p);
|
2017-02-05 18:15:20 +00:00
|
|
|
players[i].drawangle = READANGLE(save_p);
|
2020-01-18 00:32:13 +00:00
|
|
|
players[i].viewrollangle = READANGLE(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].awayviewaiming = READANGLE(save_p);
|
|
|
|
players[i].awayviewtics = READINT32(save_p);
|
2018-06-03 21:41:54 +00:00
|
|
|
players[i].rings = READINT16(save_p);
|
|
|
|
players[i].spheres = READINT16(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
players[i].pity = READSINT8(save_p);
|
|
|
|
players[i].currentweapon = READINT32(save_p);
|
|
|
|
players[i].ringweapons = READINT32(save_p);
|
|
|
|
|
2019-08-26 23:07:17 +00:00
|
|
|
players[i].ammoremoval = READUINT16(save_p);
|
|
|
|
players[i].ammoremovaltimer = READUINT32(save_p);
|
|
|
|
players[i].ammoremovalweapon = READINT32(save_p);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
for (j = 0; j < NUMPOWERS; j++)
|
|
|
|
players[i].powers[j] = READUINT16(save_p);
|
|
|
|
|
|
|
|
players[i].playerstate = READUINT8(save_p);
|
|
|
|
players[i].pflags = READUINT32(save_p);
|
|
|
|
players[i].panim = READUINT8(save_p);
|
2023-07-05 17:05:47 +00:00
|
|
|
players[i].stronganim = READUINT8(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].spectator = READUINT8(save_p);
|
2024-02-27 10:58:59 +00:00
|
|
|
players[i].muted = READUINT8(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
players[i].flashpal = READUINT16(save_p);
|
|
|
|
players[i].flashcount = READUINT16(save_p);
|
|
|
|
|
2023-10-29 17:43:40 +00:00
|
|
|
players[i].skincolor = READUINT16(save_p);
|
2020-01-31 14:29:22 +00:00
|
|
|
players[i].skin = READINT32(save_p);
|
|
|
|
players[i].availabilities = READUINT32(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].score = READUINT32(save_p);
|
2022-03-02 22:47:15 +00:00
|
|
|
players[i].recordscore = READUINT32(save_p);
|
2014-11-12 00:55:07 +00:00
|
|
|
players[i].dashspeed = READFIXED(save_p); // dashing speed
|
2014-03-21 18:42:55 +00:00
|
|
|
players[i].lives = READSINT8(save_p);
|
|
|
|
players[i].continues = READSINT8(save_p); // continues that player has acquired
|
|
|
|
players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].gotcontinue = READUINT8(save_p); // got continue from stage
|
2014-11-12 00:55:07 +00:00
|
|
|
players[i].speed = READFIXED(save_p); // Player's speed (distance formula of MOMX and MOMY values)
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].secondjump = READUINT8(save_p);
|
|
|
|
players[i].fly1 = READUINT8(save_p); // Tails flying
|
|
|
|
players[i].scoreadd = READUINT8(save_p); // Used for multiple enemy attack bonus
|
|
|
|
players[i].glidetime = READUINT32(save_p); // Glide counter for thrust
|
|
|
|
players[i].climbing = READUINT8(save_p); // Climbing on the wall
|
|
|
|
players[i].deadtimer = READINT32(save_p); // End game if game over lasts too long
|
|
|
|
players[i].exiting = READUINT32(save_p); // Exitlevel timer
|
|
|
|
players[i].homing = READUINT8(save_p); // Are you homing?
|
2016-01-25 11:47:33 +00:00
|
|
|
players[i].dashmode = READUINT32(save_p); // counter for dashmode ability
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].skidtime = READUINT32(save_p); // Skid timer
|
|
|
|
|
2021-01-23 15:39:59 +00:00
|
|
|
//////////
|
|
|
|
// Bots //
|
|
|
|
//////////
|
|
|
|
players[i].bot = READUINT8(save_p);
|
2022-11-12 01:38:52 +00:00
|
|
|
|
2021-01-23 15:39:59 +00:00
|
|
|
players[i].botmem.lastForward = READUINT8(save_p);
|
|
|
|
players[i].botmem.lastBlocked = READUINT8(save_p);
|
|
|
|
players[i].botmem.catchup_tics = READUINT8(save_p);
|
|
|
|
players[i].botmem.thinkstate = READUINT8(save_p);
|
2021-07-15 22:04:24 +00:00
|
|
|
players[i].removing = READUINT8(save_p);
|
2021-01-23 15:39:59 +00:00
|
|
|
|
|
|
|
players[i].blocked = READUINT8(save_p);
|
|
|
|
players[i].lastbuttons = READUINT16(save_p);
|
2022-11-12 01:38:52 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
////////////////////////////
|
|
|
|
// Conveyor Belt Movement //
|
|
|
|
////////////////////////////
|
|
|
|
players[i].cmomx = READFIXED(save_p); // Conveyor momx
|
|
|
|
players[i].cmomy = READFIXED(save_p); // Conveyor momy
|
|
|
|
players[i].rmomx = READFIXED(save_p); // "Real" momx (momx - cmomx)
|
|
|
|
players[i].rmomy = READFIXED(save_p); // "Real" momy (momy - cmomy)
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
// Race Mode Stuff //
|
|
|
|
/////////////////////
|
2014-11-12 00:55:07 +00:00
|
|
|
players[i].numboxes = READINT16(save_p); // Number of item boxes obtained for Race Mode
|
|
|
|
players[i].totalring = READINT16(save_p); // Total number of rings obtained for Race Mode
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].realtime = READUINT32(save_p); // integer replacement for leveltime
|
2014-03-21 18:42:55 +00:00
|
|
|
players[i].laps = READUINT8(save_p); // Number of laps (optional)
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
////////////////////
|
|
|
|
// CTF Mode Stuff //
|
|
|
|
////////////////////
|
|
|
|
players[i].ctfteam = READINT32(save_p); // 1 == Red, 2 == Blue
|
|
|
|
players[i].gotflag = READUINT16(save_p); // 1 == Red, 2 == Blue Do you have the flag?
|
|
|
|
|
|
|
|
players[i].weapondelay = READINT32(save_p);
|
|
|
|
players[i].tossdelay = READINT32(save_p);
|
|
|
|
|
|
|
|
players[i].starposttime = READUINT32(save_p);
|
|
|
|
players[i].starpostx = READINT16(save_p);
|
|
|
|
players[i].starposty = READINT16(save_p);
|
|
|
|
players[i].starpostz = READINT16(save_p);
|
|
|
|
players[i].starpostnum = READINT32(save_p);
|
|
|
|
players[i].starpostangle = READANGLE(save_p);
|
2019-09-07 21:11:33 +00:00
|
|
|
players[i].starpostscale = READFIXED(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
players[i].angle_pos = READANGLE(save_p);
|
|
|
|
players[i].old_angle_pos = READANGLE(save_p);
|
|
|
|
|
|
|
|
players[i].flyangle = READINT32(save_p);
|
|
|
|
players[i].drilltimer = READUINT32(save_p);
|
|
|
|
players[i].linkcount = READINT32(save_p);
|
|
|
|
players[i].linktimer = READUINT32(save_p);
|
|
|
|
players[i].anotherflyangle = READINT32(save_p);
|
|
|
|
players[i].nightstime = READUINT32(save_p);
|
|
|
|
players[i].bumpertime = READUINT32(save_p);
|
|
|
|
players[i].drillmeter = READINT32(save_p);
|
|
|
|
players[i].drilldelay = READUINT8(save_p);
|
|
|
|
players[i].bonustime = (boolean)READUINT8(save_p);
|
2018-08-11 04:49:28 +00:00
|
|
|
players[i].oldscale = READFIXED(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].mare = READUINT8(save_p);
|
2018-03-30 18:36:49 +00:00
|
|
|
players[i].marelap = READUINT8(save_p);
|
|
|
|
players[i].marebonuslap = READUINT8(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].marebegunat = READUINT32(save_p);
|
2023-09-28 20:22:29 +00:00
|
|
|
players[i].lastmaretime = READUINT32(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].startedtime = READUINT32(save_p);
|
|
|
|
players[i].finishedtime = READUINT32(save_p);
|
2018-08-10 21:12:26 +00:00
|
|
|
players[i].lapbegunat = READUINT32(save_p);
|
|
|
|
players[i].lapstartedtime = READUINT32(save_p);
|
2018-06-03 21:41:54 +00:00
|
|
|
players[i].finishedspheres = READINT16(save_p);
|
2014-11-12 00:55:07 +00:00
|
|
|
players[i].finishedrings = READINT16(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].marescore = READUINT32(save_p);
|
|
|
|
players[i].lastmarescore = READUINT32(save_p);
|
2018-08-12 23:59:34 +00:00
|
|
|
players[i].totalmarescore = READUINT32(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].lastmare = READUINT8(save_p);
|
2018-08-10 20:30:49 +00:00
|
|
|
players[i].lastmarelap = READUINT8(save_p);
|
|
|
|
players[i].lastmarebonuslap = READUINT8(save_p);
|
2018-08-12 23:57:33 +00:00
|
|
|
players[i].totalmarelap = READUINT8(save_p);
|
|
|
|
players[i].totalmarebonuslap = READUINT8(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].maxlink = READINT32(save_p);
|
|
|
|
players[i].texttimer = READUINT8(save_p);
|
|
|
|
players[i].textvar = READUINT8(save_p);
|
|
|
|
|
|
|
|
players[i].lastsidehit = READINT16(save_p);
|
|
|
|
players[i].lastlinehit = READINT16(save_p);
|
|
|
|
|
|
|
|
players[i].losstime = READUINT32(save_p);
|
|
|
|
|
|
|
|
players[i].timeshit = READUINT8(save_p);
|
|
|
|
|
|
|
|
players[i].onconveyor = READINT32(save_p);
|
|
|
|
|
|
|
|
players[i].jointime = READUINT32(save_p);
|
2020-01-22 02:05:08 +00:00
|
|
|
players[i].quittime = READUINT32(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
flags = READUINT16(save_p);
|
|
|
|
|
|
|
|
if (flags & CAPSULE)
|
|
|
|
players[i].capsule = (mobj_t *)(size_t)READUINT32(save_p);
|
|
|
|
|
|
|
|
if (flags & FIRSTAXIS)
|
|
|
|
players[i].axis1 = (mobj_t *)(size_t)READUINT32(save_p);
|
|
|
|
|
|
|
|
if (flags & SECONDAXIS)
|
|
|
|
players[i].axis2 = (mobj_t *)(size_t)READUINT32(save_p);
|
|
|
|
|
|
|
|
if (flags & AWAYVIEW)
|
|
|
|
players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save_p);
|
|
|
|
|
2017-10-02 13:08:58 +00:00
|
|
|
if (flags & FOLLOW)
|
|
|
|
players[i].followmobj = (mobj_t *)(size_t)READUINT32(save_p);
|
|
|
|
|
2018-08-10 23:25:49 +00:00
|
|
|
if (flags & DRONE)
|
|
|
|
players[i].drone = (mobj_t *)(size_t)READUINT32(save_p);
|
|
|
|
|
2016-09-25 17:21:52 +00:00
|
|
|
players[i].camerascale = READFIXED(save_p);
|
|
|
|
players[i].shieldscale = READFIXED(save_p);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
//SetPlayerSkinByNum(i, players[i].skin);
|
|
|
|
players[i].charability = READUINT8(save_p);
|
|
|
|
players[i].charability2 = READUINT8(save_p);
|
|
|
|
players[i].charflags = READUINT32(save_p);
|
|
|
|
players[i].thokitem = (mobjtype_t)READUINT32(save_p);
|
|
|
|
players[i].spinitem = (mobjtype_t)READUINT32(save_p);
|
|
|
|
players[i].revitem = (mobjtype_t)READUINT32(save_p);
|
2017-10-02 13:08:58 +00:00
|
|
|
players[i].followitem = (mobjtype_t)READUINT32(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].actionspd = READFIXED(save_p);
|
|
|
|
players[i].mindash = READFIXED(save_p);
|
2014-03-17 12:13:16 +00:00
|
|
|
players[i].maxdash = READFIXED(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
players[i].normalspeed = READFIXED(save_p);
|
|
|
|
players[i].runspeed = READFIXED(save_p);
|
|
|
|
players[i].thrustfactor = READUINT8(save_p);
|
|
|
|
players[i].accelstart = READUINT8(save_p);
|
|
|
|
players[i].acceleration = READUINT8(save_p);
|
|
|
|
players[i].jumpfactor = READFIXED(save_p);
|
2016-09-25 17:21:52 +00:00
|
|
|
players[i].height = READFIXED(save_p);
|
|
|
|
players[i].spinheight = READFIXED(save_p);
|
2017-11-02 19:38:21 +00:00
|
|
|
|
|
|
|
players[i].viewheight = 41*players[i].height/48; // scale cannot be factored in at this point
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
///
|
|
|
|
/// Colormaps
|
|
|
|
///
|
|
|
|
|
|
|
|
static extracolormap_t *net_colormaps = NULL;
|
|
|
|
static UINT32 num_net_colormaps = 0;
|
2018-09-17 14:38:09 +00:00
|
|
|
static UINT32 num_ffloors = 0; // for loading
|
2018-09-17 00:02:29 +00:00
|
|
|
|
|
|
|
// Copypasta from r_data.c AddColormapToList
|
|
|
|
// But also check for equality and return the matching index
|
|
|
|
static UINT32 CheckAddNetColormapToList(extracolormap_t *extra_colormap)
|
2018-09-12 02:44:31 +00:00
|
|
|
{
|
2018-11-21 02:54:20 +00:00
|
|
|
extracolormap_t *exc, *exc_prev = NULL;
|
2018-09-17 00:02:29 +00:00
|
|
|
UINT32 i = 0;
|
2018-09-12 15:01:12 +00:00
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
if (!net_colormaps)
|
|
|
|
{
|
2018-09-17 02:41:08 +00:00
|
|
|
net_colormaps = R_CopyColormap(extra_colormap, false);
|
2018-09-17 00:02:29 +00:00
|
|
|
net_colormaps->next = 0;
|
|
|
|
net_colormaps->prev = 0;
|
2018-09-17 02:41:08 +00:00
|
|
|
num_net_colormaps = i+1;
|
2018-09-17 00:02:29 +00:00
|
|
|
return i;
|
|
|
|
}
|
2018-09-12 02:44:31 +00:00
|
|
|
|
2018-09-17 02:41:08 +00:00
|
|
|
for (exc = net_colormaps; exc; exc_prev = exc, exc = exc->next)
|
2018-09-17 00:02:29 +00:00
|
|
|
{
|
|
|
|
if (R_CheckEqualColormaps(exc, extra_colormap, true, true, true))
|
|
|
|
return i;
|
|
|
|
i++;
|
|
|
|
}
|
2018-09-12 02:44:31 +00:00
|
|
|
|
2018-09-17 02:41:08 +00:00
|
|
|
exc_prev->next = R_CopyColormap(extra_colormap, false);
|
|
|
|
extra_colormap->prev = exc_prev;
|
2018-09-17 00:02:29 +00:00
|
|
|
extra_colormap->next = 0;
|
|
|
|
|
2018-09-17 02:41:08 +00:00
|
|
|
num_net_colormaps = i+1;
|
2018-09-17 00:02:29 +00:00
|
|
|
return i;
|
2018-09-12 02:44:31 +00:00
|
|
|
}
|
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
static extracolormap_t *GetNetColormapFromList(UINT32 index)
|
2018-09-12 02:44:31 +00:00
|
|
|
{
|
2018-09-17 00:02:29 +00:00
|
|
|
// For loading, we have to be tricky:
|
|
|
|
// We load the sectors BEFORE knowing the colormap values
|
|
|
|
// So if an index doesn't exist, fill our list with dummy colormaps
|
|
|
|
// until we get the index we want
|
|
|
|
// Then when we load the color data, we set up the dummy colormaps
|
2018-09-12 02:44:31 +00:00
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
extracolormap_t *exc, *last_exc = NULL;
|
|
|
|
UINT32 i = 0;
|
2018-09-12 02:44:31 +00:00
|
|
|
|
2018-09-17 02:41:08 +00:00
|
|
|
if (!net_colormaps) // initialize our list
|
|
|
|
net_colormaps = R_CreateDefaultColormap(false);
|
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
for (exc = net_colormaps; exc; last_exc = exc, exc = exc->next)
|
|
|
|
{
|
|
|
|
if (i++ == index)
|
|
|
|
return exc;
|
|
|
|
}
|
2018-09-12 02:44:31 +00:00
|
|
|
|
2018-09-17 02:41:08 +00:00
|
|
|
|
|
|
|
// LET'S HOPE that index is a sane value, because we create up to [index]
|
|
|
|
// entries in net_colormaps. At this point, we don't know
|
|
|
|
// what the total colormap count is
|
2018-09-17 14:38:09 +00:00
|
|
|
if (index >= numsectors*3 + num_ffloors)
|
|
|
|
// if every sector had a unique colormap change AND a fade color thinker which has two colormap entries
|
|
|
|
// AND every ffloor had a fade FOF thinker with one colormap entry
|
2018-09-17 12:05:51 +00:00
|
|
|
I_Error("Colormap %d from server is too high for sectors %d", index, (UINT32)numsectors);
|
2018-09-17 02:41:08 +00:00
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
// our index doesn't exist, so just make the entry
|
2018-09-17 02:41:08 +00:00
|
|
|
for (; i <= index; i++)
|
2018-09-17 00:02:29 +00:00
|
|
|
{
|
|
|
|
exc = R_CreateDefaultColormap(false);
|
|
|
|
if (last_exc)
|
|
|
|
last_exc->next = exc;
|
|
|
|
exc->prev = last_exc;
|
|
|
|
exc->next = NULL;
|
|
|
|
last_exc = exc;
|
|
|
|
}
|
|
|
|
return exc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ClearNetColormaps(void)
|
|
|
|
{
|
|
|
|
// We're actually Z_Freeing each entry here,
|
|
|
|
// so don't call this in P_NetUnArchiveColormaps (where entries will be used in-game)
|
|
|
|
extracolormap_t *exc, *exc_next;
|
|
|
|
|
|
|
|
for (exc = net_colormaps; exc; exc = exc_next)
|
|
|
|
{
|
|
|
|
exc_next = exc->next;
|
|
|
|
Z_Free(exc);
|
|
|
|
}
|
|
|
|
num_net_colormaps = 0;
|
2018-09-17 14:38:09 +00:00
|
|
|
num_ffloors = 0;
|
2018-09-17 00:02:29 +00:00
|
|
|
net_colormaps = NULL;
|
|
|
|
}
|
|
|
|
|
2018-09-17 02:41:08 +00:00
|
|
|
static void P_NetArchiveColormaps(void)
|
2018-09-17 00:02:29 +00:00
|
|
|
{
|
|
|
|
// We save and then we clean up our colormap mess
|
|
|
|
extracolormap_t *exc, *exc_next;
|
2018-09-17 02:41:08 +00:00
|
|
|
UINT32 i = 0;
|
2018-09-17 00:02:29 +00:00
|
|
|
WRITEUINT32(save_p, num_net_colormaps); // save for safety
|
|
|
|
|
2018-09-17 02:41:08 +00:00
|
|
|
for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
|
2018-09-17 00:02:29 +00:00
|
|
|
{
|
2018-09-17 02:41:08 +00:00
|
|
|
// We must save num_net_colormaps worth of data
|
|
|
|
// So fill non-existent entries with default.
|
|
|
|
if (!exc)
|
|
|
|
exc = R_CreateDefaultColormap(false);
|
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
WRITEUINT8(save_p, exc->fadestart);
|
|
|
|
WRITEUINT8(save_p, exc->fadeend);
|
2020-02-16 19:19:24 +00:00
|
|
|
WRITEUINT8(save_p, exc->flags);
|
2018-09-12 02:44:31 +00:00
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
WRITEINT32(save_p, exc->rgba);
|
|
|
|
WRITEINT32(save_p, exc->fadergba);
|
|
|
|
|
|
|
|
#ifdef EXTRACOLORMAPLUMPS
|
|
|
|
WRITESTRINGN(save_p, exc->lumpname, 9);
|
2018-09-12 02:44:31 +00:00
|
|
|
#endif
|
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
exc_next = exc->next;
|
|
|
|
Z_Free(exc); // don't need anymore
|
|
|
|
}
|
|
|
|
|
|
|
|
num_net_colormaps = 0;
|
2018-09-17 14:38:09 +00:00
|
|
|
num_ffloors = 0;
|
2018-09-17 02:41:08 +00:00
|
|
|
net_colormaps = NULL;
|
2018-09-17 00:02:29 +00:00
|
|
|
}
|
|
|
|
|
2018-09-17 02:41:08 +00:00
|
|
|
static void P_NetUnArchiveColormaps(void)
|
2018-09-17 00:02:29 +00:00
|
|
|
{
|
|
|
|
// When we reach this point, we already populated our list with
|
|
|
|
// dummy colormaps. Now that we are loading the color data,
|
|
|
|
// set up the dummies.
|
2018-09-17 02:41:08 +00:00
|
|
|
extracolormap_t *exc, *existing_exc, *exc_next = NULL;
|
|
|
|
UINT32 i = 0;
|
2018-09-17 00:02:29 +00:00
|
|
|
|
2018-09-17 04:26:58 +00:00
|
|
|
num_net_colormaps = READUINT32(save_p);
|
|
|
|
|
2018-09-17 02:41:08 +00:00
|
|
|
for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
|
2018-09-12 02:44:31 +00:00
|
|
|
{
|
2020-02-16 19:19:24 +00:00
|
|
|
UINT8 fadestart, fadeend, flags;
|
2018-09-17 02:41:08 +00:00
|
|
|
INT32 rgba, fadergba;
|
|
|
|
#ifdef EXTRACOLORMAPLUMPS
|
|
|
|
char lumpname[9];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
fadestart = READUINT8(save_p);
|
|
|
|
fadeend = READUINT8(save_p);
|
2020-02-16 19:19:24 +00:00
|
|
|
flags = READUINT8(save_p);
|
2018-09-17 00:02:29 +00:00
|
|
|
|
2018-09-17 02:41:08 +00:00
|
|
|
rgba = READINT32(save_p);
|
|
|
|
fadergba = READINT32(save_p);
|
2018-09-12 02:44:31 +00:00
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
#ifdef EXTRACOLORMAPLUMPS
|
|
|
|
READSTRINGN(save_p, lumpname, 9);
|
|
|
|
|
|
|
|
if (lumpname[0])
|
|
|
|
{
|
2018-09-17 02:41:08 +00:00
|
|
|
if (!exc)
|
|
|
|
// no point making a new entry since nothing points to it,
|
|
|
|
// but we needed to read the data so now continue
|
|
|
|
continue;
|
|
|
|
|
|
|
|
exc_next = exc->next; // this gets overwritten during our operations here, so get it now
|
2018-09-17 00:02:29 +00:00
|
|
|
existing_exc = R_ColormapForName(lumpname);
|
|
|
|
*exc = *existing_exc;
|
|
|
|
R_AddColormapToList(exc); // see HACK note below on why we're adding duplicates
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
2018-09-12 02:44:31 +00:00
|
|
|
|
2018-09-17 02:41:08 +00:00
|
|
|
if (!exc)
|
|
|
|
// no point making a new entry since nothing points to it,
|
|
|
|
// but we needed to read the data so now continue
|
|
|
|
continue;
|
|
|
|
|
|
|
|
exc_next = exc->next; // this gets overwritten during our operations here, so get it now
|
|
|
|
|
2018-09-12 02:44:31 +00:00
|
|
|
exc->fadestart = fadestart;
|
|
|
|
exc->fadeend = fadeend;
|
2020-02-16 19:19:24 +00:00
|
|
|
exc->flags = flags;
|
2018-09-12 02:44:31 +00:00
|
|
|
|
|
|
|
exc->rgba = rgba;
|
|
|
|
exc->fadergba = fadergba;
|
|
|
|
|
|
|
|
#ifdef EXTRACOLORMAPLUMPS
|
|
|
|
exc->lump = LUMPERROR;
|
|
|
|
exc->lumpname[0] = 0;
|
|
|
|
#endif
|
2018-09-12 15:01:12 +00:00
|
|
|
|
2020-02-16 19:19:24 +00:00
|
|
|
existing_exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags);
|
2018-09-17 00:02:29 +00:00
|
|
|
|
|
|
|
if (existing_exc)
|
|
|
|
exc->colormap = existing_exc->colormap;
|
2018-09-12 15:01:12 +00:00
|
|
|
else
|
2018-09-17 00:02:29 +00:00
|
|
|
// CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
|
|
|
|
// R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba),
|
|
|
|
// R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba));
|
|
|
|
exc->colormap = R_CreateLightTable(exc);
|
|
|
|
|
|
|
|
// HACK: If this dummy is a duplicate, we're going to add it
|
|
|
|
// to the extra_colormaps list anyway. I think this is faster
|
|
|
|
// than going through every loaded sector and correcting their
|
|
|
|
// colormap address to the pre-existing one, PER net_colormap entry
|
|
|
|
R_AddColormapToList(exc);
|
2018-09-17 02:41:08 +00:00
|
|
|
|
|
|
|
if (i < num_net_colormaps-1 && !exc_next)
|
|
|
|
exc_next = R_CreateDefaultColormap(false);
|
2018-09-12 02:44:31 +00:00
|
|
|
}
|
|
|
|
|
2018-09-17 14:24:55 +00:00
|
|
|
// if we still have a valid net_colormap after iterating up to num_net_colormaps,
|
|
|
|
// some sector had a colormap index higher than num_net_colormaps. We done goofed or $$$ was corrupted.
|
|
|
|
// In any case, add them to the colormap list too so that at least the sectors' colormap
|
|
|
|
// addresses are valid and accounted properly
|
|
|
|
if (exc_next)
|
|
|
|
{
|
|
|
|
existing_exc = R_GetDefaultColormap();
|
|
|
|
for (exc = exc_next; exc; exc = exc->next)
|
|
|
|
{
|
|
|
|
exc->colormap = existing_exc->colormap; // all our dummies are default values
|
|
|
|
R_AddColormapToList(exc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
// Don't need these anymore
|
|
|
|
num_net_colormaps = 0;
|
2018-09-17 14:38:09 +00:00
|
|
|
num_ffloors = 0;
|
2018-09-17 00:02:29 +00:00
|
|
|
net_colormaps = NULL;
|
2018-09-12 02:44:31 +00:00
|
|
|
}
|
|
|
|
|
2020-05-31 20:44:25 +00:00
|
|
|
static void P_NetArchiveWaypoints(void)
|
|
|
|
{
|
|
|
|
INT32 i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
|
|
|
|
{
|
|
|
|
WRITEUINT16(save_p, numwaypoints[i]);
|
|
|
|
for (j = 0; j < numwaypoints[i]; j++)
|
2020-05-31 20:58:14 +00:00
|
|
|
WRITEUINT32(save_p, waypoints[i][j] ? waypoints[i][j]->mobjnum : 0);
|
2020-05-31 20:44:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void P_NetUnArchiveWaypoints(void)
|
|
|
|
{
|
|
|
|
INT32 i, j;
|
|
|
|
UINT32 mobjnum;
|
|
|
|
|
|
|
|
for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
|
|
|
|
{
|
|
|
|
numwaypoints[i] = READUINT16(save_p);
|
|
|
|
for (j = 0; j < numwaypoints[i]; j++)
|
|
|
|
{
|
|
|
|
mobjnum = READUINT32(save_p);
|
2020-05-31 20:58:14 +00:00
|
|
|
waypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum);
|
2020-05-31 20:44:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-17 00:02:29 +00:00
|
|
|
///
|
|
|
|
/// World Archiving
|
|
|
|
///
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
#define SD_FLOORHT 0x01
|
|
|
|
#define SD_CEILHT 0x02
|
|
|
|
#define SD_FLOORPIC 0x04
|
|
|
|
#define SD_CEILPIC 0x08
|
|
|
|
#define SD_LIGHT 0x10
|
|
|
|
#define SD_SPECIAL 0x20
|
|
|
|
#define SD_DIFF2 0x40
|
2014-11-12 00:55:07 +00:00
|
|
|
#define SD_FFLOORS 0x80
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
// diff2 flags
|
|
|
|
#define SD_FXOFFS 0x01
|
|
|
|
#define SD_FYOFFS 0x02
|
|
|
|
#define SD_CXOFFS 0x04
|
|
|
|
#define SD_CYOFFS 0x08
|
2018-09-09 16:01:50 +00:00
|
|
|
#define SD_FLOORANG 0x10
|
|
|
|
#define SD_CEILANG 0x20
|
|
|
|
#define SD_TAG 0x40
|
|
|
|
#define SD_DIFF3 0x80
|
|
|
|
|
|
|
|
// diff3 flags
|
2023-08-24 19:04:31 +00:00
|
|
|
#define SD_TAGLIST 0x01
|
|
|
|
#define SD_COLORMAP 0x02
|
2020-04-24 15:53:54 +00:00
|
|
|
#define SD_CRUMBLESTATE 0x04
|
2023-08-24 19:04:31 +00:00
|
|
|
#define SD_FLOORLIGHT 0x08
|
|
|
|
#define SD_CEILLIGHT 0x10
|
|
|
|
#define SD_FLAG 0x20
|
|
|
|
#define SD_SPECIALFLAG 0x40
|
|
|
|
#define SD_DIFF4 0x80
|
2021-12-31 07:53:00 +00:00
|
|
|
|
2023-12-28 02:46:16 +00:00
|
|
|
// diff4 flags
|
2021-12-31 07:53:00 +00:00
|
|
|
#define SD_DAMAGETYPE 0x01
|
2021-12-31 10:39:34 +00:00
|
|
|
#define SD_TRIGGERTAG 0x02
|
|
|
|
#define SD_TRIGGERER 0x04
|
2023-12-28 02:46:16 +00:00
|
|
|
#define SD_FXSCALE 0x08
|
|
|
|
#define SD_FYSCALE 0x10
|
|
|
|
#define SD_CXSCALE 0x20
|
|
|
|
#define SD_CYSCALE 0x40
|
|
|
|
#define SD_DIFF5 0x80
|
|
|
|
|
|
|
|
// diff5 flags
|
|
|
|
#define SD_GRAVITY 0x01
|
|
|
|
#define SD_FLOORPORTAL 0x02
|
|
|
|
#define SD_CEILPORTAL 0x04
|
|
|
|
|
|
|
|
// diff1 flags
|
2023-11-24 00:56:18 +00:00
|
|
|
#define LD_FLAG 0x01
|
|
|
|
#define LD_SPECIAL 0x02
|
|
|
|
#define LD_CLLCOUNT 0x04
|
|
|
|
#define LD_ARGS 0x08
|
|
|
|
#define LD_STRINGARGS 0x10
|
2023-12-28 02:46:16 +00:00
|
|
|
#define LD_SIDE1 0x20
|
|
|
|
#define LD_SIDE2 0x40
|
|
|
|
#define LD_DIFF2 0x80
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
// diff2 flags
|
2023-12-28 02:46:16 +00:00
|
|
|
#define LD_EXECUTORDELAY 0x01
|
|
|
|
#define LD_TRANSFPORTAL 0x02
|
2023-11-24 00:56:18 +00:00
|
|
|
|
|
|
|
// sidedef flags
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
LD_SDTEXOFFX = 1,
|
|
|
|
LD_SDTEXOFFY = 1<<1,
|
|
|
|
LD_SDTOPTEX = 1<<2,
|
|
|
|
LD_SDBOTTEX = 1<<3,
|
|
|
|
LD_SDMIDTEX = 1<<4,
|
|
|
|
LD_SDTOPOFFX = 1<<5,
|
|
|
|
LD_SDTOPOFFY = 1<<6,
|
|
|
|
LD_SDMIDOFFX = 1<<7,
|
|
|
|
LD_SDMIDOFFY = 1<<8,
|
|
|
|
LD_SDBOTOFFX = 1<<9,
|
|
|
|
LD_SDBOTOFFY = 1<<10,
|
|
|
|
LD_SDTOPSCALEX = 1<<11,
|
|
|
|
LD_SDTOPSCALEY = 1<<12,
|
|
|
|
LD_SDMIDSCALEX = 1<<13,
|
|
|
|
LD_SDMIDSCALEY = 1<<14,
|
|
|
|
LD_SDBOTSCALEX = 1<<15,
|
|
|
|
LD_SDBOTSCALEY = 1<<16,
|
|
|
|
LD_SDLIGHT = 1<<17,
|
|
|
|
LD_SDTOPLIGHT = 1<<18,
|
|
|
|
LD_SDMIDLIGHT = 1<<19,
|
|
|
|
LD_SDBOTLIGHT = 1<<20,
|
|
|
|
LD_SDREPEATCNT = 1<<21,
|
2024-06-12 12:25:45 +00:00
|
|
|
LD_SDFLAGS = 1<<22,
|
|
|
|
LD_SDLIGHTABS = 1<<23,
|
|
|
|
LD_SDTOPLIGHTABS = 1<<24,
|
|
|
|
LD_SDMIDLIGHTABS = 1<<25,
|
|
|
|
LD_SDBOTLIGHTABS = 1<<26
|
2023-11-24 00:56:18 +00:00
|
|
|
};
|
2020-01-08 07:42:35 +00:00
|
|
|
|
|
|
|
static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli)
|
2020-01-02 11:23:14 +00:00
|
|
|
{
|
|
|
|
UINT8 i;
|
|
|
|
for (i = 0; i < NUMLINEARGS; i++)
|
2020-01-08 07:42:35 +00:00
|
|
|
if (li->args[i] != spawnli->args[i])
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean P_AreStringArgsEqual(const line_t *li, const line_t *spawnli)
|
|
|
|
{
|
|
|
|
UINT8 i;
|
|
|
|
for (i = 0; i < NUMLINESTRINGARGS; i++)
|
2020-04-18 10:23:01 +00:00
|
|
|
{
|
|
|
|
if (!li->stringargs[i])
|
|
|
|
return !spawnli->stringargs[i];
|
|
|
|
|
2020-01-08 07:42:35 +00:00
|
|
|
if (strcmp(li->stringargs[i], spawnli->stringargs[i]))
|
2020-01-02 11:23:14 +00:00
|
|
|
return false;
|
2020-04-18 10:23:01 +00:00
|
|
|
}
|
2020-01-02 11:23:14 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-04-24 19:26:57 +00:00
|
|
|
#define FD_FLAGS 0x01
|
|
|
|
#define FD_ALPHA 0x02
|
|
|
|
|
|
|
|
// Check if any of the sector's FOFs differ from how they spawned
|
2020-04-29 14:24:28 +00:00
|
|
|
static boolean CheckFFloorDiff(const sector_t *ss)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2020-04-24 19:26:57 +00:00
|
|
|
ffloor_t *rover;
|
|
|
|
|
|
|
|
for (rover = ss->ffloors; rover; rover = rover->next)
|
|
|
|
{
|
2022-07-31 10:04:42 +00:00
|
|
|
if (rover->fofflags != rover->spawnflags
|
2020-04-24 19:26:57 +00:00
|
|
|
|| rover->alpha != rover->spawnalpha)
|
|
|
|
{
|
|
|
|
return true; // we found an FOF that changed!
|
|
|
|
// don't bother checking for more, we do that later
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Special case: save the stats of all modified ffloors along with their ffloor "number"s
|
|
|
|
// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
|
2020-04-29 14:24:28 +00:00
|
|
|
static void ArchiveFFloors(const sector_t *ss)
|
2020-04-24 19:26:57 +00:00
|
|
|
{
|
|
|
|
size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc
|
|
|
|
ffloor_t *rover;
|
|
|
|
UINT8 fflr_diff;
|
|
|
|
for (rover = ss->ffloors; rover; rover = rover->next)
|
|
|
|
{
|
|
|
|
fflr_diff = 0; // reset diff flags
|
2022-07-31 10:04:42 +00:00
|
|
|
if (rover->fofflags != rover->spawnflags)
|
2020-04-24 19:26:57 +00:00
|
|
|
fflr_diff |= FD_FLAGS;
|
|
|
|
if (rover->alpha != rover->spawnalpha)
|
|
|
|
fflr_diff |= FD_ALPHA;
|
|
|
|
|
|
|
|
if (fflr_diff)
|
|
|
|
{
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEUINT16(save_p, j); // save ffloor "number"
|
|
|
|
WRITEUINT8(save_p, fflr_diff);
|
2020-04-24 19:26:57 +00:00
|
|
|
if (fflr_diff & FD_FLAGS)
|
2022-07-31 10:04:42 +00:00
|
|
|
WRITEUINT32(save_p, rover->fofflags);
|
2020-04-24 19:26:57 +00:00
|
|
|
if (fflr_diff & FD_ALPHA)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEINT16(save_p, rover->alpha);
|
2020-04-24 19:26:57 +00:00
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEUINT16(save_p, 0xffff);
|
2020-04-24 19:26:57 +00:00
|
|
|
}
|
|
|
|
|
2020-04-29 14:24:28 +00:00
|
|
|
static void UnArchiveFFloors(const sector_t *ss)
|
2020-04-24 19:26:57 +00:00
|
|
|
{
|
|
|
|
UINT16 j = 0; // number of current ffloor in loop
|
|
|
|
UINT16 fflr_i; // saved ffloor "number" of next modified ffloor
|
|
|
|
UINT16 fflr_diff; // saved ffloor diff
|
|
|
|
ffloor_t *rover;
|
|
|
|
|
|
|
|
rover = ss->ffloors;
|
|
|
|
if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case...
|
|
|
|
I_Error("Sector does not have any ffloors!");
|
|
|
|
|
2020-04-24 19:57:48 +00:00
|
|
|
fflr_i = READUINT16(save_p); // get first modified ffloor's number ready
|
2020-04-24 19:26:57 +00:00
|
|
|
for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here?
|
|
|
|
{
|
|
|
|
if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already
|
|
|
|
break;
|
|
|
|
// should NEVER need to be checked
|
|
|
|
//if (rover == NULL)
|
|
|
|
//break;
|
|
|
|
if (j != fflr_i) // this ffloor was not modified
|
|
|
|
{
|
|
|
|
j++;
|
|
|
|
rover = rover->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-04-24 19:57:48 +00:00
|
|
|
fflr_diff = READUINT8(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-04-24 19:26:57 +00:00
|
|
|
if (fflr_diff & FD_FLAGS)
|
2022-07-31 10:04:42 +00:00
|
|
|
rover->fofflags = READUINT32(save_p);
|
2020-04-24 19:26:57 +00:00
|
|
|
if (fflr_diff & FD_ALPHA)
|
2020-04-24 19:57:48 +00:00
|
|
|
rover->alpha = READINT16(save_p);
|
2020-04-24 19:26:57 +00:00
|
|
|
|
2020-04-24 19:57:48 +00:00
|
|
|
fflr_i = READUINT16(save_p); // get next ffloor "number" ready
|
2020-04-24 19:26:57 +00:00
|
|
|
|
|
|
|
j++;
|
|
|
|
rover = rover->next;
|
|
|
|
}
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-04-24 19:57:48 +00:00
|
|
|
static void ArchiveSectors(void)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2020-07-10 14:51:11 +00:00
|
|
|
size_t i, j;
|
2014-03-15 16:59:03 +00:00
|
|
|
const sector_t *ss = sectors;
|
2019-12-23 11:42:38 +00:00
|
|
|
const sector_t *spawnss = spawnsectors;
|
2023-12-28 02:46:16 +00:00
|
|
|
UINT8 diff, diff2, diff3, diff4, diff5;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-12-23 11:42:38 +00:00
|
|
|
for (i = 0; i < numsectors; i++, ss++, spawnss++)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2023-12-28 02:46:16 +00:00
|
|
|
diff = diff2 = diff3 = diff4 = diff5 = 0;
|
2019-12-23 11:42:38 +00:00
|
|
|
if (ss->floorheight != spawnss->floorheight)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff |= SD_FLOORHT;
|
2019-12-23 11:42:38 +00:00
|
|
|
if (ss->ceilingheight != spawnss->ceilingheight)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff |= SD_CEILHT;
|
|
|
|
//
|
|
|
|
// flats
|
|
|
|
//
|
2019-12-23 11:42:38 +00:00
|
|
|
if (ss->floorpic != spawnss->floorpic)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff |= SD_FLOORPIC;
|
2019-12-23 11:42:38 +00:00
|
|
|
if (ss->ceilingpic != spawnss->ceilingpic)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff |= SD_CEILPIC;
|
|
|
|
|
2019-12-23 11:42:38 +00:00
|
|
|
if (ss->lightlevel != spawnss->lightlevel)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff |= SD_LIGHT;
|
2019-12-23 11:42:38 +00:00
|
|
|
if (ss->special != spawnss->special)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff |= SD_SPECIAL;
|
|
|
|
|
2022-11-25 23:01:27 +00:00
|
|
|
if (ss->floorxoffset != spawnss->floorxoffset)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff2 |= SD_FXOFFS;
|
2022-11-25 23:01:27 +00:00
|
|
|
if (ss->flooryoffset != spawnss->flooryoffset)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff2 |= SD_FYOFFS;
|
2022-11-25 23:01:27 +00:00
|
|
|
if (ss->ceilingxoffset != spawnss->ceilingxoffset)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff2 |= SD_CXOFFS;
|
2022-11-25 23:01:27 +00:00
|
|
|
if (ss->ceilingyoffset != spawnss->ceilingyoffset)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff2 |= SD_CYOFFS;
|
2023-11-24 04:52:57 +00:00
|
|
|
if (ss->floorxscale != spawnss->floorxscale)
|
|
|
|
diff2 |= SD_FXSCALE;
|
|
|
|
if (ss->flooryscale != spawnss->flooryscale)
|
|
|
|
diff2 |= SD_FYSCALE;
|
|
|
|
if (ss->ceilingxscale != spawnss->ceilingxscale)
|
|
|
|
diff2 |= SD_CXSCALE;
|
|
|
|
if (ss->ceilingyscale != spawnss->ceilingyscale)
|
|
|
|
diff2 |= SD_CYSCALE;
|
2022-11-25 23:01:27 +00:00
|
|
|
if (ss->floorangle != spawnss->floorangle)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff2 |= SD_FLOORANG;
|
2022-11-25 23:01:27 +00:00
|
|
|
if (ss->ceilingangle != spawnss->ceilingangle)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff2 |= SD_CEILANG;
|
|
|
|
|
2020-04-17 20:29:26 +00:00
|
|
|
if (!Tag_Compare(&ss->tags, &spawnss->tags))
|
2014-03-15 16:59:03 +00:00
|
|
|
diff2 |= SD_TAG;
|
2018-09-12 21:28:22 +00:00
|
|
|
|
2019-12-23 11:42:38 +00:00
|
|
|
if (ss->extra_colormap != spawnss->extra_colormap)
|
2018-09-11 00:36:34 +00:00
|
|
|
diff3 |= SD_COLORMAP;
|
2020-04-24 15:40:09 +00:00
|
|
|
if (ss->crumblestate)
|
|
|
|
diff3 |= SD_CRUMBLESTATE;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2021-09-19 07:20:00 +00:00
|
|
|
if (ss->floorlightlevel != spawnss->floorlightlevel || ss->floorlightabsolute != spawnss->floorlightabsolute)
|
|
|
|
diff3 |= SD_FLOORLIGHT;
|
|
|
|
if (ss->ceilinglightlevel != spawnss->ceilinglightlevel || ss->ceilinglightabsolute != spawnss->ceilinglightabsolute)
|
|
|
|
diff3 |= SD_CEILLIGHT;
|
2021-12-30 13:33:24 +00:00
|
|
|
if (ss->flags != spawnss->flags)
|
|
|
|
diff3 |= SD_FLAG;
|
2021-12-30 23:03:24 +00:00
|
|
|
if (ss->specialflags != spawnss->specialflags)
|
|
|
|
diff3 |= SD_SPECIALFLAG;
|
2021-12-31 07:53:00 +00:00
|
|
|
if (ss->damagetype != spawnss->damagetype)
|
|
|
|
diff4 |= SD_DAMAGETYPE;
|
2021-12-31 10:39:34 +00:00
|
|
|
if (ss->triggertag != spawnss->triggertag)
|
|
|
|
diff4 |= SD_TRIGGERTAG;
|
|
|
|
if (ss->triggerer != spawnss->triggerer)
|
|
|
|
diff4 |= SD_TRIGGERER;
|
2021-12-30 17:19:42 +00:00
|
|
|
if (ss->gravity != spawnss->gravity)
|
2023-12-28 02:46:16 +00:00
|
|
|
diff5 |= SD_GRAVITY;
|
2023-08-24 19:04:31 +00:00
|
|
|
if (ss->portal_floor != spawnss->portal_floor)
|
2023-12-28 02:46:16 +00:00
|
|
|
diff5 |= SD_FLOORPORTAL;
|
2023-08-24 19:04:31 +00:00
|
|
|
if (ss->portal_ceiling != spawnss->portal_ceiling)
|
2023-12-28 02:46:16 +00:00
|
|
|
diff5 |= SD_CEILPORTAL;
|
2021-09-19 07:20:00 +00:00
|
|
|
|
2020-04-24 19:26:57 +00:00
|
|
|
if (ss->ffloors && CheckFFloorDiff(ss))
|
|
|
|
diff |= SD_FFLOORS;
|
2014-11-12 00:55:07 +00:00
|
|
|
|
2023-12-28 02:46:16 +00:00
|
|
|
if (diff5)
|
|
|
|
diff4 |= SD_DIFF5;
|
|
|
|
|
2021-12-31 07:53:00 +00:00
|
|
|
if (diff4)
|
|
|
|
diff3 |= SD_DIFF4;
|
|
|
|
|
2018-09-09 16:01:50 +00:00
|
|
|
if (diff3)
|
|
|
|
diff2 |= SD_DIFF3;
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff2)
|
|
|
|
diff |= SD_DIFF2;
|
|
|
|
|
|
|
|
if (diff)
|
|
|
|
{
|
2023-09-21 05:06:06 +00:00
|
|
|
WRITEUINT32(save_p, i);
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEUINT8(save_p, diff);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & SD_DIFF2)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEUINT8(save_p, diff2);
|
2018-09-09 16:01:50 +00:00
|
|
|
if (diff2 & SD_DIFF3)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEUINT8(save_p, diff3);
|
2021-12-31 07:53:00 +00:00
|
|
|
if (diff3 & SD_DIFF4)
|
|
|
|
WRITEUINT8(save_p, diff4);
|
2023-12-28 02:46:16 +00:00
|
|
|
if (diff4 & SD_DIFF5)
|
|
|
|
WRITEUINT8(save_p, diff5);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & SD_FLOORHT)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEFIXED(save_p, ss->floorheight);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & SD_CEILHT)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEFIXED(save_p, ss->ceilingheight);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & SD_FLOORPIC)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEMEM(save_p, levelflats[ss->floorpic].name, 8);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & SD_CEILPIC)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEMEM(save_p, levelflats[ss->ceilingpic].name, 8);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & SD_LIGHT)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEINT16(save_p, ss->lightlevel);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & SD_SPECIAL)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEINT16(save_p, ss->special);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff2 & SD_FXOFFS)
|
2022-11-25 23:01:27 +00:00
|
|
|
WRITEFIXED(save_p, ss->floorxoffset);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff2 & SD_FYOFFS)
|
2022-11-25 23:01:27 +00:00
|
|
|
WRITEFIXED(save_p, ss->flooryoffset);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff2 & SD_CXOFFS)
|
2022-11-25 23:01:27 +00:00
|
|
|
WRITEFIXED(save_p, ss->ceilingxoffset);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff2 & SD_CYOFFS)
|
2022-11-25 23:01:27 +00:00
|
|
|
WRITEFIXED(save_p, ss->ceilingyoffset);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff2 & SD_FLOORANG)
|
2022-11-25 23:01:27 +00:00
|
|
|
WRITEANGLE(save_p, ss->floorangle);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff2 & SD_CEILANG)
|
2022-11-25 23:01:27 +00:00
|
|
|
WRITEANGLE(save_p, ss->ceilingangle);
|
2020-04-17 20:29:26 +00:00
|
|
|
if (diff2 & SD_TAG)
|
|
|
|
{
|
2020-07-10 14:51:11 +00:00
|
|
|
WRITEUINT32(save_p, ss->tags.count);
|
2020-04-17 20:29:26 +00:00
|
|
|
for (j = 0; j < ss->tags.count; j++)
|
2020-07-10 14:51:11 +00:00
|
|
|
WRITEINT16(save_p, ss->tags.tags[j]);
|
2017-01-03 20:48:39 +00:00
|
|
|
}
|
2018-09-11 00:36:34 +00:00
|
|
|
|
|
|
|
if (diff3 & SD_COLORMAP)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap));
|
2018-09-17 00:02:29 +00:00
|
|
|
// returns existing index if already added, or appends to net_colormaps and returns new index
|
2020-04-24 15:40:09 +00:00
|
|
|
if (diff3 & SD_CRUMBLESTATE)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEINT32(save_p, ss->crumblestate);
|
2021-09-19 07:20:00 +00:00
|
|
|
if (diff3 & SD_FLOORLIGHT)
|
|
|
|
{
|
|
|
|
WRITEINT16(save_p, ss->floorlightlevel);
|
|
|
|
WRITEUINT8(save_p, ss->floorlightabsolute);
|
|
|
|
}
|
|
|
|
if (diff3 & SD_CEILLIGHT)
|
|
|
|
{
|
|
|
|
WRITEINT16(save_p, ss->ceilinglightlevel);
|
|
|
|
WRITEUINT8(save_p, ss->ceilinglightabsolute);
|
|
|
|
}
|
2021-12-30 13:33:24 +00:00
|
|
|
if (diff3 & SD_FLAG)
|
|
|
|
WRITEUINT32(save_p, ss->flags);
|
2021-12-30 23:03:24 +00:00
|
|
|
if (diff3 & SD_SPECIALFLAG)
|
|
|
|
WRITEUINT32(save_p, ss->specialflags);
|
2021-12-31 07:53:00 +00:00
|
|
|
if (diff4 & SD_DAMAGETYPE)
|
|
|
|
WRITEUINT8(save_p, ss->damagetype);
|
2021-12-31 10:39:34 +00:00
|
|
|
if (diff4 & SD_TRIGGERTAG)
|
|
|
|
WRITEINT16(save_p, ss->triggertag);
|
|
|
|
if (diff4 & SD_TRIGGERER)
|
|
|
|
WRITEUINT8(save_p, ss->triggerer);
|
2023-11-24 04:52:57 +00:00
|
|
|
if (diff4 & SD_FXSCALE)
|
|
|
|
WRITEFIXED(save_p, ss->floorxscale);
|
|
|
|
if (diff4 & SD_FYSCALE)
|
|
|
|
WRITEFIXED(save_p, ss->flooryscale);
|
|
|
|
if (diff4 & SD_CXSCALE)
|
|
|
|
WRITEFIXED(save_p, ss->ceilingxscale);
|
|
|
|
if (diff4 & SD_CYSCALE)
|
|
|
|
WRITEFIXED(save_p, ss->ceilingyscale);
|
2023-12-28 02:46:16 +00:00
|
|
|
if (diff5 & SD_GRAVITY)
|
2021-12-30 17:19:42 +00:00
|
|
|
WRITEFIXED(save_p, ss->gravity);
|
2023-12-28 02:46:16 +00:00
|
|
|
if (diff5 & SD_FLOORPORTAL)
|
2023-08-24 19:04:31 +00:00
|
|
|
WRITEUINT32(save_p, ss->portal_floor);
|
2023-12-28 02:46:16 +00:00
|
|
|
if (diff5 & SD_CEILPORTAL)
|
2023-08-24 19:04:31 +00:00
|
|
|
WRITEUINT32(save_p, ss->portal_ceiling);
|
2014-11-12 00:55:07 +00:00
|
|
|
if (diff & SD_FFLOORS)
|
2020-04-29 13:45:52 +00:00
|
|
|
ArchiveFFloors(ss);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
}
|
2014-11-12 00:55:07 +00:00
|
|
|
|
2023-09-21 05:06:06 +00:00
|
|
|
WRITEUINT32(save_p, 0xffffffff);
|
2020-04-24 19:40:50 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 19:57:48 +00:00
|
|
|
static void UnArchiveSectors(void)
|
2020-04-24 19:40:50 +00:00
|
|
|
{
|
2023-09-21 05:06:06 +00:00
|
|
|
UINT32 i;
|
|
|
|
UINT16 j;
|
2023-12-28 02:46:16 +00:00
|
|
|
UINT8 diff, diff2, diff3, diff4, diff5;
|
2020-04-24 19:40:50 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
2023-09-21 05:06:06 +00:00
|
|
|
i = READUINT32(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
|
2023-09-21 05:06:06 +00:00
|
|
|
if (i == 0xffffffff)
|
2020-04-24 19:40:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
if (i > numsectors)
|
|
|
|
I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors));
|
|
|
|
|
2020-04-24 19:57:48 +00:00
|
|
|
diff = READUINT8(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff & SD_DIFF2)
|
2020-04-24 19:57:48 +00:00
|
|
|
diff2 = READUINT8(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
else
|
|
|
|
diff2 = 0;
|
|
|
|
if (diff2 & SD_DIFF3)
|
2020-04-24 19:57:48 +00:00
|
|
|
diff3 = READUINT8(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
else
|
|
|
|
diff3 = 0;
|
2021-12-31 07:53:00 +00:00
|
|
|
if (diff3 & SD_DIFF4)
|
|
|
|
diff4 = READUINT8(save_p);
|
|
|
|
else
|
|
|
|
diff4 = 0;
|
2023-12-28 02:46:16 +00:00
|
|
|
if (diff4 & SD_DIFF5)
|
|
|
|
diff5 = READUINT8(save_p);
|
|
|
|
else
|
|
|
|
diff5 = 0;
|
2020-04-24 19:40:50 +00:00
|
|
|
|
|
|
|
if (diff & SD_FLOORHT)
|
2020-04-24 19:57:48 +00:00
|
|
|
sectors[i].floorheight = READFIXED(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff & SD_CEILHT)
|
2020-04-24 19:57:48 +00:00
|
|
|
sectors[i].ceilingheight = READFIXED(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff & SD_FLOORPIC)
|
|
|
|
{
|
2020-04-24 19:57:48 +00:00
|
|
|
sectors[i].floorpic = P_AddLevelFlatRuntime((char *)save_p);
|
|
|
|
save_p += 8;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff & SD_CEILPIC)
|
|
|
|
{
|
2020-04-24 19:57:48 +00:00
|
|
|
sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)save_p);
|
|
|
|
save_p += 8;
|
2020-04-24 19:40:50 +00:00
|
|
|
}
|
|
|
|
if (diff & SD_LIGHT)
|
2020-04-24 19:57:48 +00:00
|
|
|
sectors[i].lightlevel = READINT16(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff & SD_SPECIAL)
|
2020-04-24 19:57:48 +00:00
|
|
|
sectors[i].special = READINT16(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
|
|
|
|
if (diff2 & SD_FXOFFS)
|
2022-11-25 23:01:27 +00:00
|
|
|
sectors[i].floorxoffset = READFIXED(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff2 & SD_FYOFFS)
|
2022-11-25 23:01:27 +00:00
|
|
|
sectors[i].flooryoffset = READFIXED(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff2 & SD_CXOFFS)
|
2022-11-25 23:01:27 +00:00
|
|
|
sectors[i].ceilingxoffset = READFIXED(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff2 & SD_CYOFFS)
|
2022-11-25 23:01:27 +00:00
|
|
|
sectors[i].ceilingyoffset = READFIXED(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff2 & SD_FLOORANG)
|
2022-11-25 23:01:27 +00:00
|
|
|
sectors[i].floorangle = READANGLE(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff2 & SD_CEILANG)
|
2022-11-25 23:01:27 +00:00
|
|
|
sectors[i].ceilingangle = READANGLE(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff2 & SD_TAG)
|
|
|
|
{
|
2020-07-10 14:51:11 +00:00
|
|
|
size_t ncount = READUINT32(save_p);
|
|
|
|
|
|
|
|
// Remove entries from global lists.
|
|
|
|
for (j = 0; j < sectors[i].tags.count; j++)
|
|
|
|
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
|
|
|
|
|
|
|
|
// Reallocate if size differs.
|
|
|
|
if (ncount != sectors[i].tags.count)
|
|
|
|
{
|
|
|
|
sectors[i].tags.count = ncount;
|
|
|
|
sectors[i].tags.tags = Z_Realloc(sectors[i].tags.tags, ncount*sizeof(mtag_t), PU_LEVEL, NULL);
|
2014-11-12 00:55:07 +00:00
|
|
|
}
|
2020-07-10 14:51:11 +00:00
|
|
|
|
|
|
|
for (j = 0; j < ncount; j++)
|
|
|
|
sectors[i].tags.tags[j] = READINT16(save_p);
|
|
|
|
|
|
|
|
// Add new entries.
|
|
|
|
for (j = 0; j < sectors[i].tags.count; j++)
|
|
|
|
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
|
2020-04-24 19:40:50 +00:00
|
|
|
}
|
|
|
|
|
2020-07-10 14:51:11 +00:00
|
|
|
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff3 & SD_COLORMAP)
|
2020-04-24 19:57:48 +00:00
|
|
|
sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p));
|
2020-04-24 19:40:50 +00:00
|
|
|
if (diff3 & SD_CRUMBLESTATE)
|
2020-04-24 19:57:48 +00:00
|
|
|
sectors[i].crumblestate = READINT32(save_p);
|
2021-09-19 07:20:00 +00:00
|
|
|
if (diff3 & SD_FLOORLIGHT)
|
|
|
|
{
|
|
|
|
sectors[i].floorlightlevel = READINT16(save_p);
|
|
|
|
sectors[i].floorlightabsolute = READUINT8(save_p);
|
|
|
|
}
|
|
|
|
if (diff3 & SD_CEILLIGHT)
|
|
|
|
{
|
|
|
|
sectors[i].ceilinglightlevel = READINT16(save_p);
|
|
|
|
sectors[i].ceilinglightabsolute = READUINT8(save_p);
|
|
|
|
}
|
2021-12-30 13:33:24 +00:00
|
|
|
if (diff3 & SD_FLAG)
|
2021-12-30 17:50:02 +00:00
|
|
|
{
|
2021-12-30 13:33:24 +00:00
|
|
|
sectors[i].flags = READUINT32(save_p);
|
2021-12-30 17:50:02 +00:00
|
|
|
CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP);
|
|
|
|
}
|
2021-12-30 23:03:24 +00:00
|
|
|
if (diff3 & SD_SPECIALFLAG)
|
|
|
|
sectors[i].specialflags = READUINT32(save_p);
|
2021-12-31 07:53:00 +00:00
|
|
|
if (diff4 & SD_DAMAGETYPE)
|
|
|
|
sectors[i].damagetype = READUINT8(save_p);
|
2021-12-31 10:39:34 +00:00
|
|
|
if (diff4 & SD_TRIGGERTAG)
|
|
|
|
sectors[i].triggertag = READINT16(save_p);
|
|
|
|
if (diff4 & SD_TRIGGERER)
|
|
|
|
sectors[i].triggerer = READUINT8(save_p);
|
2023-11-24 04:52:57 +00:00
|
|
|
if (diff4 & SD_FXSCALE)
|
|
|
|
sectors[i].floorxscale = READFIXED(save_p);
|
|
|
|
if (diff4 & SD_FYSCALE)
|
|
|
|
sectors[i].flooryscale = READFIXED(save_p);
|
|
|
|
if (diff4 & SD_CXSCALE)
|
|
|
|
sectors[i].ceilingxscale = READFIXED(save_p);
|
|
|
|
if (diff4 & SD_CYSCALE)
|
|
|
|
sectors[i].ceilingyscale = READFIXED(save_p);
|
2023-12-28 02:46:16 +00:00
|
|
|
if (diff5 & SD_GRAVITY)
|
2021-12-30 17:19:42 +00:00
|
|
|
sectors[i].gravity = READFIXED(save_p);
|
2023-12-28 02:46:16 +00:00
|
|
|
if (diff5 & SD_FLOORPORTAL)
|
2023-08-24 19:04:31 +00:00
|
|
|
sectors[i].portal_floor = READUINT32(save_p);
|
2023-12-28 02:46:16 +00:00
|
|
|
if (diff5 & SD_CEILPORTAL)
|
2023-08-24 19:04:31 +00:00
|
|
|
sectors[i].portal_ceiling = READUINT32(save_p);
|
2020-04-24 19:40:50 +00:00
|
|
|
|
|
|
|
if (diff & SD_FFLOORS)
|
2020-04-29 14:24:28 +00:00
|
|
|
UnArchiveFFloors(§ors[i]);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2020-04-24 19:40:50 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2023-11-24 00:56:18 +00:00
|
|
|
static UINT32 GetSideDiff(const side_t *si, const side_t *spawnsi)
|
|
|
|
{
|
|
|
|
UINT32 diff = 0;
|
|
|
|
if (si->textureoffset != spawnsi->textureoffset)
|
|
|
|
diff |= LD_SDTEXOFFX;
|
|
|
|
if (si->rowoffset != spawnsi->rowoffset)
|
|
|
|
diff |= LD_SDTEXOFFY;
|
|
|
|
//SoM: 4/1/2000: Some textures are colormaps. Don't worry about invalid textures.
|
|
|
|
if (si->toptexture != spawnsi->toptexture)
|
|
|
|
diff |= LD_SDTOPTEX;
|
|
|
|
if (si->bottomtexture != spawnsi->bottomtexture)
|
|
|
|
diff |= LD_SDBOTTEX;
|
|
|
|
if (si->midtexture != spawnsi->midtexture)
|
|
|
|
diff |= LD_SDMIDTEX;
|
|
|
|
if (si->offsetx_top != spawnsi->offsetx_top)
|
|
|
|
diff |= LD_SDTOPOFFX;
|
|
|
|
if (si->offsetx_mid != spawnsi->offsetx_mid)
|
|
|
|
diff |= LD_SDMIDOFFX;
|
|
|
|
if (si->offsetx_bottom != spawnsi->offsetx_bottom)
|
|
|
|
diff |= LD_SDBOTOFFX;
|
|
|
|
if (si->offsety_top != spawnsi->offsety_top)
|
|
|
|
diff |= LD_SDTOPOFFY;
|
|
|
|
if (si->offsety_mid != spawnsi->offsety_mid)
|
|
|
|
diff |= LD_SDMIDOFFY;
|
|
|
|
if (si->offsety_bottom != spawnsi->offsety_bottom)
|
|
|
|
diff |= LD_SDBOTOFFY;
|
|
|
|
if (si->scalex_top != spawnsi->scalex_top)
|
|
|
|
diff |= LD_SDTOPSCALEX;
|
|
|
|
if (si->scalex_mid != spawnsi->scalex_mid)
|
|
|
|
diff |= LD_SDMIDSCALEX;
|
|
|
|
if (si->scalex_bottom != spawnsi->scalex_bottom)
|
|
|
|
diff |= LD_SDBOTSCALEX;
|
|
|
|
if (si->scaley_top != spawnsi->scaley_top)
|
|
|
|
diff |= LD_SDTOPSCALEY;
|
|
|
|
if (si->scaley_mid != spawnsi->scaley_mid)
|
|
|
|
diff |= LD_SDMIDSCALEY;
|
|
|
|
if (si->scaley_bottom != spawnsi->scaley_bottom)
|
|
|
|
diff |= LD_SDBOTSCALEY;
|
|
|
|
if (si->repeatcnt != spawnsi->repeatcnt)
|
|
|
|
diff |= LD_SDREPEATCNT;
|
2024-06-12 12:25:45 +00:00
|
|
|
if (si->light != spawnsi->light)
|
|
|
|
diff |= LD_SDLIGHT;
|
|
|
|
if (si->light_top != spawnsi->light_top)
|
|
|
|
diff |= LD_SDTOPLIGHT;
|
|
|
|
if (si->light_mid != spawnsi->light_mid)
|
|
|
|
diff |= LD_SDMIDLIGHT;
|
|
|
|
if (si->light_bottom != spawnsi->light_bottom)
|
|
|
|
diff |= LD_SDBOTLIGHT;
|
|
|
|
if (si->lightabsolute != spawnsi->lightabsolute)
|
|
|
|
diff |= LD_SDLIGHTABS;
|
2024-06-12 13:38:52 +00:00
|
|
|
if (si->lightabsolute_top != spawnsi->lightabsolute_top)
|
|
|
|
diff |= LD_SDTOPLIGHTABS;
|
|
|
|
if (si->lightabsolute_mid != spawnsi->lightabsolute_mid)
|
|
|
|
diff |= LD_SDMIDLIGHTABS;
|
|
|
|
if (si->lightabsolute_bottom != spawnsi->lightabsolute_bottom)
|
|
|
|
diff |= LD_SDBOTLIGHTABS;
|
2023-11-24 00:56:18 +00:00
|
|
|
return diff;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ArchiveSide(const side_t *si, UINT32 diff)
|
|
|
|
{
|
|
|
|
WRITEUINT32(save_p, diff);
|
|
|
|
|
|
|
|
if (diff & LD_SDTEXOFFX)
|
|
|
|
WRITEFIXED(save_p, si->textureoffset);
|
|
|
|
if (diff & LD_SDTEXOFFY)
|
|
|
|
WRITEFIXED(save_p, si->rowoffset);
|
|
|
|
if (diff & LD_SDTOPTEX)
|
|
|
|
WRITEINT32(save_p, si->toptexture);
|
|
|
|
if (diff & LD_SDBOTTEX)
|
|
|
|
WRITEINT32(save_p, si->bottomtexture);
|
|
|
|
if (diff & LD_SDMIDTEX)
|
|
|
|
WRITEINT32(save_p, si->midtexture);
|
|
|
|
if (diff & LD_SDTOPOFFX)
|
|
|
|
WRITEFIXED(save_p, si->offsetx_top);
|
|
|
|
if (diff & LD_SDMIDOFFX)
|
|
|
|
WRITEFIXED(save_p, si->offsetx_mid);
|
|
|
|
if (diff & LD_SDBOTOFFX)
|
|
|
|
WRITEFIXED(save_p, si->offsetx_bottom);
|
|
|
|
if (diff & LD_SDTOPOFFY)
|
|
|
|
WRITEFIXED(save_p, si->offsety_top);
|
|
|
|
if (diff & LD_SDMIDOFFY)
|
|
|
|
WRITEFIXED(save_p, si->offsety_mid);
|
|
|
|
if (diff & LD_SDBOTOFFY)
|
|
|
|
WRITEFIXED(save_p, si->offsety_bottom);
|
|
|
|
if (diff & LD_SDTOPSCALEX)
|
|
|
|
WRITEFIXED(save_p, si->scalex_top);
|
|
|
|
if (diff & LD_SDMIDSCALEX)
|
|
|
|
WRITEFIXED(save_p, si->scalex_mid);
|
|
|
|
if (diff & LD_SDBOTSCALEX)
|
|
|
|
WRITEFIXED(save_p, si->scalex_bottom);
|
|
|
|
if (diff & LD_SDTOPSCALEY)
|
|
|
|
WRITEFIXED(save_p, si->scaley_top);
|
|
|
|
if (diff & LD_SDMIDSCALEY)
|
|
|
|
WRITEFIXED(save_p, si->scaley_mid);
|
|
|
|
if (diff & LD_SDBOTSCALEY)
|
|
|
|
WRITEFIXED(save_p, si->scaley_bottom);
|
|
|
|
if (diff & LD_SDREPEATCNT)
|
|
|
|
WRITEINT16(save_p, si->repeatcnt);
|
2024-06-12 12:25:45 +00:00
|
|
|
if (diff & LD_SDLIGHT)
|
|
|
|
WRITEINT16(save_p, si->light);
|
2024-06-12 13:38:52 +00:00
|
|
|
if (diff & LD_SDTOPLIGHT)
|
|
|
|
WRITEINT16(save_p, si->light_top);
|
|
|
|
if (diff & LD_SDMIDLIGHT)
|
|
|
|
WRITEINT16(save_p, si->light_mid);
|
|
|
|
if (diff & LD_SDBOTLIGHT)
|
|
|
|
WRITEINT16(save_p, si->light_bottom);
|
2024-06-12 12:25:45 +00:00
|
|
|
if (diff & LD_SDLIGHTABS)
|
2024-06-12 13:38:52 +00:00
|
|
|
WRITEUINT8(save_p, si->lightabsolute);
|
|
|
|
if (diff & LD_SDTOPLIGHTABS)
|
|
|
|
WRITEUINT8(save_p, si->lightabsolute_top);
|
|
|
|
if (diff & LD_SDMIDLIGHTABS)
|
|
|
|
WRITEUINT8(save_p, si->lightabsolute_mid);
|
|
|
|
if (diff & LD_SDBOTLIGHTABS)
|
|
|
|
WRITEUINT8(save_p, si->lightabsolute_bottom);
|
2023-11-24 00:56:18 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 19:57:48 +00:00
|
|
|
static void ArchiveLines(void)
|
2020-04-24 19:40:50 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
const line_t *li = lines;
|
|
|
|
const line_t *spawnli = spawnlines;
|
2023-12-28 02:46:16 +00:00
|
|
|
UINT8 diff, diff2;
|
|
|
|
UINT32 side1diff;
|
|
|
|
UINT32 side2diff;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-12-23 11:47:40 +00:00
|
|
|
for (i = 0; i < numlines; i++, spawnli++, li++)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2020-04-24 19:58:38 +00:00
|
|
|
diff = diff2 = 0;
|
2023-12-28 02:46:16 +00:00
|
|
|
side1diff = side2diff = 0;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-12-23 11:47:40 +00:00
|
|
|
if (li->special != spawnli->special)
|
2014-03-15 16:59:03 +00:00
|
|
|
diff |= LD_SPECIAL;
|
|
|
|
|
2019-12-23 11:47:40 +00:00
|
|
|
if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved
|
2014-11-12 00:55:07 +00:00
|
|
|
diff |= LD_CLLCOUNT;
|
|
|
|
|
2020-01-08 07:42:35 +00:00
|
|
|
if (!P_AreArgsEqual(li, spawnli))
|
2023-11-24 00:56:18 +00:00
|
|
|
diff |= LD_ARGS;
|
2020-01-02 11:23:14 +00:00
|
|
|
|
2020-01-08 07:42:35 +00:00
|
|
|
if (!P_AreStringArgsEqual(li, spawnli))
|
2023-11-24 00:56:18 +00:00
|
|
|
diff |= LD_STRINGARGS;
|
2020-01-08 07:42:35 +00:00
|
|
|
|
2020-05-03 18:41:37 +00:00
|
|
|
if (li->executordelay != spawnli->executordelay)
|
|
|
|
diff2 |= LD_EXECUTORDELAY;
|
|
|
|
|
2023-08-24 20:36:38 +00:00
|
|
|
if (li->secportal != spawnli->secportal)
|
|
|
|
diff2 |= LD_TRANSFPORTAL;
|
2020-05-03 18:41:37 +00:00
|
|
|
|
2023-09-21 05:06:06 +00:00
|
|
|
if (li->sidenum[0] != NO_SIDEDEF)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2023-12-28 02:46:16 +00:00
|
|
|
side1diff = GetSideDiff(&sides[li->sidenum[0]], &spawnsides[li->sidenum[0]]);
|
|
|
|
if (side1diff)
|
2023-11-24 00:56:18 +00:00
|
|
|
diff |= LD_SIDE1;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2023-09-21 05:06:06 +00:00
|
|
|
if (li->sidenum[1] != NO_SIDEDEF)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2023-12-28 02:46:16 +00:00
|
|
|
side2diff = GetSideDiff(&sides[li->sidenum[1]], &spawnsides[li->sidenum[1]]);
|
|
|
|
if (side2diff)
|
2023-11-24 00:56:18 +00:00
|
|
|
diff |= LD_SIDE2;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2020-01-02 11:23:14 +00:00
|
|
|
if (diff2)
|
|
|
|
diff |= LD_DIFF2;
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff)
|
|
|
|
{
|
2023-09-21 05:06:06 +00:00
|
|
|
WRITEUINT32(save_p, i);
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEUINT8(save_p, diff);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & LD_DIFF2)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEUINT8(save_p, diff2);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & LD_FLAG)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEINT16(save_p, li->flags);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & LD_SPECIAL)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEINT16(save_p, li->special);
|
2014-11-12 00:55:07 +00:00
|
|
|
if (diff & LD_CLLCOUNT)
|
2020-04-24 19:57:48 +00:00
|
|
|
WRITEINT16(save_p, li->callcount);
|
2023-11-24 00:56:18 +00:00
|
|
|
if (diff & LD_ARGS)
|
2020-01-02 11:23:14 +00:00
|
|
|
{
|
|
|
|
UINT8 j;
|
|
|
|
for (j = 0; j < NUMLINEARGS; j++)
|
2020-05-01 10:44:39 +00:00
|
|
|
WRITEINT32(save_p, li->args[j]);
|
2020-01-02 11:23:14 +00:00
|
|
|
}
|
2023-11-24 00:56:18 +00:00
|
|
|
if (diff & LD_STRINGARGS)
|
2020-01-08 07:42:35 +00:00
|
|
|
{
|
|
|
|
UINT8 j;
|
|
|
|
for (j = 0; j < NUMLINESTRINGARGS; j++)
|
|
|
|
{
|
|
|
|
size_t len, k;
|
|
|
|
|
|
|
|
if (!li->stringargs[j])
|
|
|
|
{
|
2020-05-01 10:44:39 +00:00
|
|
|
WRITEINT32(save_p, 0);
|
2020-01-08 07:42:35 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = strlen(li->stringargs[j]);
|
2020-05-01 10:44:39 +00:00
|
|
|
WRITEINT32(save_p, len);
|
2020-01-08 07:42:35 +00:00
|
|
|
for (k = 0; k < len; k++)
|
2020-05-01 10:44:39 +00:00
|
|
|
WRITECHAR(save_p, li->stringargs[j][k]);
|
2020-01-08 07:42:35 +00:00
|
|
|
}
|
|
|
|
}
|
2023-11-24 00:56:18 +00:00
|
|
|
if (diff & LD_SIDE1)
|
2023-12-28 02:46:16 +00:00
|
|
|
ArchiveSide(&sides[li->sidenum[0]], side1diff);
|
2023-11-24 00:56:18 +00:00
|
|
|
if (diff & LD_SIDE2)
|
2023-12-28 02:46:16 +00:00
|
|
|
ArchiveSide(&sides[li->sidenum[1]], side2diff);
|
2020-05-03 18:41:37 +00:00
|
|
|
if (diff2 & LD_EXECUTORDELAY)
|
|
|
|
WRITEINT32(save_p, li->executordelay);
|
2023-08-24 20:36:38 +00:00
|
|
|
if (diff2 & LD_TRANSFPORTAL)
|
|
|
|
WRITEUINT32(save_p, li->secportal);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
}
|
2023-09-21 05:06:06 +00:00
|
|
|
WRITEUINT32(save_p, 0xffffffff);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2023-11-24 00:56:18 +00:00
|
|
|
static void UnArchiveSide(side_t *si)
|
|
|
|
{
|
|
|
|
UINT32 diff = READUINT32(save_p);
|
|
|
|
|
|
|
|
if (diff & LD_SDTEXOFFX)
|
|
|
|
si->textureoffset = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDTEXOFFY)
|
|
|
|
si->rowoffset = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDTOPTEX)
|
|
|
|
si->toptexture = READINT32(save_p);
|
|
|
|
if (diff & LD_SDBOTTEX)
|
|
|
|
si->bottomtexture = READINT32(save_p);
|
|
|
|
if (diff & LD_SDMIDTEX)
|
|
|
|
si->midtexture = READINT32(save_p);
|
|
|
|
if (diff & LD_SDTOPOFFX)
|
|
|
|
si->offsetx_top = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDMIDOFFX)
|
|
|
|
si->offsetx_mid = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDBOTOFFX)
|
|
|
|
si->offsetx_bottom = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDTOPOFFY)
|
|
|
|
si->offsety_top = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDMIDOFFY)
|
|
|
|
si->offsety_mid = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDBOTOFFY)
|
|
|
|
si->offsety_bottom = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDTOPSCALEX)
|
|
|
|
si->scalex_top = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDMIDSCALEX)
|
|
|
|
si->scalex_mid = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDBOTSCALEX)
|
|
|
|
si->scalex_bottom = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDTOPSCALEY)
|
|
|
|
si->scaley_top = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDMIDSCALEY)
|
|
|
|
si->scaley_mid = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDBOTSCALEY)
|
|
|
|
si->scaley_bottom = READFIXED(save_p);
|
|
|
|
if (diff & LD_SDREPEATCNT)
|
|
|
|
si->repeatcnt = READINT16(save_p);
|
2024-06-12 12:25:45 +00:00
|
|
|
if (diff & LD_SDLIGHT)
|
|
|
|
si->light = READINT16(save_p);
|
2024-06-12 13:38:52 +00:00
|
|
|
if (diff & LD_SDTOPLIGHT)
|
|
|
|
si->light_top = READINT16(save_p);
|
|
|
|
if (diff & LD_SDMIDLIGHT)
|
|
|
|
si->light_mid = READINT16(save_p);
|
|
|
|
if (diff & LD_SDBOTLIGHT)
|
|
|
|
si->light_bottom = READINT16(save_p);
|
2024-06-12 12:25:45 +00:00
|
|
|
if (diff & LD_SDLIGHTABS)
|
2024-06-12 13:38:52 +00:00
|
|
|
si->lightabsolute = READUINT8(save_p);
|
|
|
|
if (diff & LD_SDTOPLIGHTABS)
|
|
|
|
si->lightabsolute_top = READUINT8(save_p);
|
|
|
|
if (diff & LD_SDMIDLIGHTABS)
|
|
|
|
si->lightabsolute_mid = READUINT8(save_p);
|
|
|
|
if (diff & LD_SDBOTLIGHTABS)
|
|
|
|
si->lightabsolute_bottom = READUINT8(save_p);
|
2023-11-24 00:56:18 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 19:57:48 +00:00
|
|
|
static void UnArchiveLines(void)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2023-09-21 05:06:06 +00:00
|
|
|
UINT32 i;
|
2014-03-15 16:59:03 +00:00
|
|
|
line_t *li;
|
2023-12-28 02:46:16 +00:00
|
|
|
UINT8 diff, diff2;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
2023-09-21 05:06:06 +00:00
|
|
|
i = READUINT32(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2023-09-21 05:06:06 +00:00
|
|
|
if (i == 0xffffffff)
|
2014-03-15 16:59:03 +00:00
|
|
|
break;
|
|
|
|
if (i > numlines)
|
|
|
|
I_Error("Invalid line number %u from server", i);
|
|
|
|
|
2020-04-24 19:57:48 +00:00
|
|
|
diff = READUINT8(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & LD_DIFF2)
|
2020-04-24 19:57:48 +00:00
|
|
|
diff2 = READUINT8(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
else
|
|
|
|
diff2 = 0;
|
|
|
|
li = &lines[i];
|
|
|
|
|
|
|
|
if (diff & LD_FLAG)
|
2020-04-24 19:57:48 +00:00
|
|
|
li->flags = READINT16(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (diff & LD_SPECIAL)
|
2020-04-24 19:57:48 +00:00
|
|
|
li->special = READINT16(save_p);
|
2014-11-12 00:55:07 +00:00
|
|
|
if (diff & LD_CLLCOUNT)
|
2020-04-24 19:57:48 +00:00
|
|
|
li->callcount = READINT16(save_p);
|
2023-11-24 00:56:18 +00:00
|
|
|
if (diff & LD_ARGS)
|
2020-01-02 11:23:14 +00:00
|
|
|
{
|
|
|
|
UINT8 j;
|
|
|
|
for (j = 0; j < NUMLINEARGS; j++)
|
2020-05-01 10:44:39 +00:00
|
|
|
li->args[j] = READINT32(save_p);
|
2020-01-02 11:23:14 +00:00
|
|
|
}
|
2023-11-24 00:56:18 +00:00
|
|
|
if (diff & LD_STRINGARGS)
|
2020-01-08 07:42:35 +00:00
|
|
|
{
|
|
|
|
UINT8 j;
|
|
|
|
for (j = 0; j < NUMLINESTRINGARGS; j++)
|
|
|
|
{
|
2020-05-01 10:44:39 +00:00
|
|
|
size_t len = READINT32(save_p);
|
2020-01-08 07:42:35 +00:00
|
|
|
size_t k;
|
2020-01-02 11:23:14 +00:00
|
|
|
|
2020-01-08 07:42:35 +00:00
|
|
|
if (!len)
|
|
|
|
{
|
|
|
|
Z_Free(li->stringargs[j]);
|
|
|
|
li->stringargs[j] = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL);
|
|
|
|
for (k = 0; k < len; k++)
|
2020-05-01 10:44:39 +00:00
|
|
|
li->stringargs[j][k] = READCHAR(save_p);
|
2020-01-08 07:42:35 +00:00
|
|
|
li->stringargs[j][len] = '\0';
|
|
|
|
}
|
|
|
|
}
|
2023-11-24 00:56:18 +00:00
|
|
|
if (diff & LD_SIDE1)
|
|
|
|
UnArchiveSide(&sides[li->sidenum[0]]);
|
|
|
|
if (diff & LD_SIDE2)
|
|
|
|
UnArchiveSide(&sides[li->sidenum[1]]);
|
2020-05-03 18:41:37 +00:00
|
|
|
if (diff2 & LD_EXECUTORDELAY)
|
|
|
|
li->executordelay = READINT32(save_p);
|
2023-08-24 20:36:38 +00:00
|
|
|
if (diff2 & LD_TRANSFPORTAL)
|
|
|
|
li->secportal = READUINT32(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2020-04-24 19:40:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void P_NetArchiveWorld(void)
|
|
|
|
{
|
|
|
|
// initialize colormap vars because paranoia
|
|
|
|
ClearNetColormaps();
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-04-24 19:40:50 +00:00
|
|
|
WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
|
|
|
|
|
2020-04-24 19:57:48 +00:00
|
|
|
ArchiveSectors();
|
|
|
|
ArchiveLines();
|
2020-04-24 19:40:50 +00:00
|
|
|
R_ClearTextureNumCache(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void P_NetUnArchiveWorld(void)
|
|
|
|
{
|
|
|
|
UINT16 i;
|
|
|
|
|
|
|
|
if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD)
|
|
|
|
I_Error("Bad $$$.sav at archive block World");
|
|
|
|
|
|
|
|
// initialize colormap vars because paranoia
|
|
|
|
ClearNetColormaps();
|
|
|
|
|
|
|
|
// count the level's ffloors so that colormap loading can have an upper limit
|
|
|
|
for (i = 0; i < numsectors; i++)
|
|
|
|
{
|
|
|
|
ffloor_t *rover;
|
|
|
|
for (rover = sectors[i].ffloors; rover; rover = rover->next)
|
|
|
|
num_ffloors++;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 19:57:48 +00:00
|
|
|
UnArchiveSectors();
|
|
|
|
UnArchiveLines();
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Thinkers
|
|
|
|
//
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
MD_SPAWNPOINT = 1,
|
|
|
|
MD_POS = 1<<1,
|
|
|
|
MD_TYPE = 1<<2,
|
|
|
|
MD_MOM = 1<<3,
|
|
|
|
MD_RADIUS = 1<<4,
|
|
|
|
MD_HEIGHT = 1<<5,
|
|
|
|
MD_FLAGS = 1<<6,
|
|
|
|
MD_HEALTH = 1<<7,
|
|
|
|
MD_RTIME = 1<<8,
|
|
|
|
MD_STATE = 1<<9,
|
|
|
|
MD_TICS = 1<<10,
|
|
|
|
MD_SPRITE = 1<<11,
|
|
|
|
MD_FRAME = 1<<12,
|
|
|
|
MD_EFLAGS = 1<<13,
|
|
|
|
MD_PLAYER = 1<<14,
|
|
|
|
MD_MOVEDIR = 1<<15,
|
|
|
|
MD_MOVECOUNT = 1<<16,
|
|
|
|
MD_THRESHOLD = 1<<17,
|
|
|
|
MD_LASTLOOK = 1<<18,
|
|
|
|
MD_TARGET = 1<<19,
|
|
|
|
MD_TRACER = 1<<20,
|
|
|
|
MD_FRICTION = 1<<21,
|
|
|
|
MD_MOVEFACTOR = 1<<22,
|
|
|
|
MD_FLAGS2 = 1<<23,
|
|
|
|
MD_FUSE = 1<<24,
|
|
|
|
MD_WATERTOP = 1<<25,
|
|
|
|
MD_WATERBOTTOM = 1<<26,
|
|
|
|
MD_SCALE = 1<<27,
|
|
|
|
MD_DSCALE = 1<<28,
|
|
|
|
MD_BLUEFLAG = 1<<29,
|
|
|
|
MD_REDFLAG = 1<<30,
|
|
|
|
MD_MORE = 1<<31
|
|
|
|
} mobj_diff_t;
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
2023-06-29 22:09:20 +00:00
|
|
|
MD2_CUSVAL = 1,
|
|
|
|
MD2_CVMEM = 1<<1,
|
|
|
|
MD2_SKIN = 1<<2,
|
|
|
|
MD2_COLOR = 1<<3,
|
|
|
|
MD2_SCALESPEED = 1<<4,
|
|
|
|
MD2_EXTVAL1 = 1<<5,
|
|
|
|
MD2_EXTVAL2 = 1<<6,
|
|
|
|
MD2_HNEXT = 1<<7,
|
|
|
|
MD2_HPREV = 1<<8,
|
|
|
|
MD2_FLOORROVER = 1<<9,
|
|
|
|
MD2_CEILINGROVER = 1<<10,
|
|
|
|
MD2_SLOPE = 1<<11,
|
|
|
|
MD2_COLORIZED = 1<<12,
|
|
|
|
MD2_MIRRORED = 1<<13,
|
|
|
|
MD2_SPRITEROLL = 1<<14,
|
|
|
|
MD2_SHADOWSCALE = 1<<15,
|
|
|
|
MD2_RENDERFLAGS = 1<<16,
|
|
|
|
MD2_BLENDMODE = 1<<17,
|
|
|
|
MD2_SPRITEXSCALE = 1<<18,
|
|
|
|
MD2_SPRITEYSCALE = 1<<19,
|
|
|
|
MD2_SPRITEXOFFSET = 1<<20,
|
|
|
|
MD2_SPRITEYOFFSET = 1<<21,
|
|
|
|
MD2_FLOORSPRITESLOPE = 1<<22,
|
|
|
|
MD2_DISPOFFSET = 1<<23,
|
|
|
|
MD2_DRAWONLYFORPLAYER = 1<<24,
|
2023-10-30 02:34:18 +00:00
|
|
|
MD2_DONTDRAWFORVIEWMOBJ = 1<<25,
|
2024-02-25 01:04:48 +00:00
|
|
|
MD2_TRANSLATION = 1<<26,
|
2024-03-01 21:29:39 +00:00
|
|
|
MD2_ALPHA = 1<<27
|
2014-03-15 16:59:03 +00:00
|
|
|
} mobj_diff2_t;
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
tc_mobj,
|
|
|
|
tc_ceiling,
|
|
|
|
tc_floor,
|
|
|
|
tc_flash,
|
|
|
|
tc_strobe,
|
|
|
|
tc_glow,
|
|
|
|
tc_fireflicker,
|
|
|
|
tc_thwomp,
|
|
|
|
tc_camerascanner,
|
|
|
|
tc_elevator,
|
|
|
|
tc_continuousfalling,
|
|
|
|
tc_bouncecheese,
|
|
|
|
tc_startcrumble,
|
|
|
|
tc_marioblock,
|
2018-09-14 20:01:07 +00:00
|
|
|
tc_marioblockchecker,
|
2014-03-15 16:59:03 +00:00
|
|
|
tc_floatsector,
|
|
|
|
tc_crushceiling,
|
|
|
|
tc_scroll,
|
|
|
|
tc_friction,
|
|
|
|
tc_pusher,
|
|
|
|
tc_laserflash,
|
|
|
|
tc_lightfade,
|
|
|
|
tc_executor,
|
|
|
|
tc_raisesector,
|
|
|
|
tc_noenemies,
|
|
|
|
tc_eachtime,
|
|
|
|
tc_disappear,
|
2018-03-30 19:27:37 +00:00
|
|
|
tc_fade,
|
2018-09-12 13:06:38 +00:00
|
|
|
tc_fadecolormap,
|
2017-01-20 20:17:40 +00:00
|
|
|
tc_planedisplace,
|
2019-04-19 12:14:43 +00:00
|
|
|
tc_dynslopeline,
|
|
|
|
tc_dynslopevert,
|
2014-03-15 16:59:03 +00:00
|
|
|
tc_polyrotate, // haleyjd 03/26/06: polyobjects
|
|
|
|
tc_polymove,
|
|
|
|
tc_polywaypoint,
|
|
|
|
tc_polyslidedoor,
|
|
|
|
tc_polyswingdoor,
|
|
|
|
tc_polyflag,
|
2014-11-12 00:55:07 +00:00
|
|
|
tc_polydisplace,
|
2019-04-05 09:50:59 +00:00
|
|
|
tc_polyrotdisplace,
|
2018-09-07 19:27:18 +00:00
|
|
|
tc_polyfade,
|
2014-03-15 16:59:03 +00:00
|
|
|
tc_end
|
|
|
|
} specials_e;
|
|
|
|
|
|
|
|
static inline UINT32 SaveMobjnum(const mobj_t *mobj)
|
|
|
|
{
|
|
|
|
if (mobj) return mobj->mobjnum;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static UINT32 SaveSector(const sector_t *sector)
|
|
|
|
{
|
|
|
|
if (sector) return (UINT32)(sector - sectors);
|
|
|
|
return 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
static UINT32 SaveLine(const line_t *line)
|
|
|
|
{
|
|
|
|
if (line) return (UINT32)(line - lines);
|
|
|
|
return 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline UINT32 SavePlayer(const player_t *player)
|
|
|
|
{
|
|
|
|
if (player) return (UINT32)(player - players);
|
|
|
|
return 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
|
2019-04-19 12:14:43 +00:00
|
|
|
static UINT32 SaveSlope(const pslope_t *slope)
|
|
|
|
{
|
|
|
|
if (slope) return (UINT32)(slope->id);
|
|
|
|
return 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
|
2015-01-01 19:50:31 +00:00
|
|
|
static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const mobj_t *mobj = (const mobj_t *)th;
|
|
|
|
UINT32 diff;
|
2020-12-06 20:29:20 +00:00
|
|
|
UINT32 diff2;
|
2015-01-01 19:50:31 +00:00
|
|
|
|
|
|
|
// Ignore stationary hoops - these will be respawned from mapthings.
|
|
|
|
if (mobj->type == MT_HOOP)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// These are NEVER saved.
|
|
|
|
if (mobj->type == MT_HOOPCOLLIDE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// This hoop has already been collected.
|
|
|
|
if (mobj->type == MT_HOOPCENTER && mobj->threshold == 4242)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (mobj->spawnpoint && mobj->info->doomednum != -1)
|
|
|
|
{
|
|
|
|
// spawnpoint is not modified but we must save it since it is an identifier
|
|
|
|
diff = MD_SPAWNPOINT;
|
|
|
|
|
|
|
|
if ((mobj->x != mobj->spawnpoint->x << FRACBITS) ||
|
|
|
|
(mobj->y != mobj->spawnpoint->y << FRACBITS) ||
|
2020-04-19 12:39:16 +00:00
|
|
|
(mobj->angle != FixedAngle(mobj->spawnpoint->angle*FRACUNIT)) ||
|
|
|
|
(mobj->pitch != FixedAngle(mobj->spawnpoint->pitch*FRACUNIT)) ||
|
|
|
|
(mobj->roll != FixedAngle(mobj->spawnpoint->roll*FRACUNIT)) )
|
2015-01-01 19:50:31 +00:00
|
|
|
diff |= MD_POS;
|
|
|
|
|
|
|
|
if (mobj->info->doomednum != mobj->spawnpoint->type)
|
|
|
|
diff |= MD_TYPE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
diff = MD_POS | MD_TYPE; // not a map spawned thing so make it from scratch
|
|
|
|
|
|
|
|
diff2 = 0;
|
|
|
|
|
|
|
|
// not the default but the most probable
|
2021-12-09 08:42:06 +00:00
|
|
|
if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0 || mobj->pmomz !=0)
|
2015-01-01 19:50:31 +00:00
|
|
|
diff |= MD_MOM;
|
|
|
|
if (mobj->radius != mobj->info->radius)
|
|
|
|
diff |= MD_RADIUS;
|
|
|
|
if (mobj->height != mobj->info->height)
|
|
|
|
diff |= MD_HEIGHT;
|
|
|
|
if (mobj->flags != mobj->info->flags)
|
|
|
|
diff |= MD_FLAGS;
|
|
|
|
if (mobj->flags2)
|
|
|
|
diff |= MD_FLAGS2;
|
|
|
|
if (mobj->health != mobj->info->spawnhealth)
|
|
|
|
diff |= MD_HEALTH;
|
|
|
|
if (mobj->reactiontime != mobj->info->reactiontime)
|
|
|
|
diff |= MD_RTIME;
|
|
|
|
if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate)
|
|
|
|
diff |= MD_STATE;
|
|
|
|
if (mobj->tics != mobj->state->tics)
|
|
|
|
diff |= MD_TICS;
|
|
|
|
if (mobj->sprite != mobj->state->sprite)
|
|
|
|
diff |= MD_SPRITE;
|
2023-11-13 00:46:49 +00:00
|
|
|
if (mobj->sprite == SPR_PLAY && mobj->sprite2 != P_GetStateSprite2(mobj->state))
|
2015-05-29 18:26:39 +00:00
|
|
|
diff |= MD_SPRITE;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (mobj->frame != mobj->state->frame)
|
|
|
|
diff |= MD_FRAME;
|
2016-02-09 10:39:16 +00:00
|
|
|
if (mobj->anim_duration != (UINT16)mobj->state->var2)
|
|
|
|
diff |= MD_FRAME;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (mobj->eflags)
|
|
|
|
diff |= MD_EFLAGS;
|
|
|
|
if (mobj->player)
|
|
|
|
diff |= MD_PLAYER;
|
|
|
|
|
|
|
|
if (mobj->movedir)
|
|
|
|
diff |= MD_MOVEDIR;
|
|
|
|
if (mobj->movecount)
|
|
|
|
diff |= MD_MOVECOUNT;
|
|
|
|
if (mobj->threshold)
|
|
|
|
diff |= MD_THRESHOLD;
|
|
|
|
if (mobj->lastlook != -1)
|
|
|
|
diff |= MD_LASTLOOK;
|
|
|
|
if (mobj->target)
|
|
|
|
diff |= MD_TARGET;
|
|
|
|
if (mobj->tracer)
|
|
|
|
diff |= MD_TRACER;
|
|
|
|
if (mobj->friction != ORIG_FRICTION)
|
|
|
|
diff |= MD_FRICTION;
|
2016-08-09 23:31:16 +00:00
|
|
|
if (mobj->movefactor != FRACUNIT)
|
2015-01-01 19:50:31 +00:00
|
|
|
diff |= MD_MOVEFACTOR;
|
|
|
|
if (mobj->fuse)
|
|
|
|
diff |= MD_FUSE;
|
|
|
|
if (mobj->watertop)
|
|
|
|
diff |= MD_WATERTOP;
|
|
|
|
if (mobj->waterbottom)
|
|
|
|
diff |= MD_WATERBOTTOM;
|
|
|
|
if (mobj->scale != FRACUNIT)
|
|
|
|
diff |= MD_SCALE;
|
|
|
|
if (mobj->destscale != mobj->scale)
|
|
|
|
diff |= MD_DSCALE;
|
|
|
|
if (mobj->scalespeed != FRACUNIT/12)
|
|
|
|
diff2 |= MD2_SCALESPEED;
|
|
|
|
|
|
|
|
if (mobj == redflag)
|
|
|
|
diff |= MD_REDFLAG;
|
|
|
|
if (mobj == blueflag)
|
|
|
|
diff |= MD_BLUEFLAG;
|
|
|
|
|
|
|
|
if (mobj->cusval)
|
|
|
|
diff2 |= MD2_CUSVAL;
|
|
|
|
if (mobj->cvmem)
|
|
|
|
diff2 |= MD2_CVMEM;
|
|
|
|
if (mobj->color)
|
|
|
|
diff2 |= MD2_COLOR;
|
2023-10-30 02:34:18 +00:00
|
|
|
if (mobj->translation)
|
|
|
|
diff2 |= MD2_TRANSLATION;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (mobj->skin)
|
|
|
|
diff2 |= MD2_SKIN;
|
|
|
|
if (mobj->extravalue1)
|
|
|
|
diff2 |= MD2_EXTVAL1;
|
|
|
|
if (mobj->extravalue2)
|
|
|
|
diff2 |= MD2_EXTVAL2;
|
|
|
|
if (mobj->hnext)
|
|
|
|
diff2 |= MD2_HNEXT;
|
|
|
|
if (mobj->hprev)
|
|
|
|
diff2 |= MD2_HPREV;
|
2018-09-10 03:48:14 +00:00
|
|
|
if (mobj->floorrover)
|
|
|
|
diff2 |= MD2_FLOORROVER;
|
|
|
|
if (mobj->ceilingrover)
|
|
|
|
diff2 |= MD2_CEILINGROVER;
|
2015-08-03 23:06:42 +00:00
|
|
|
if (mobj->standingslope)
|
|
|
|
diff2 |= MD2_SLOPE;
|
2019-06-18 16:55:57 +00:00
|
|
|
if (mobj->colorized)
|
|
|
|
diff2 |= MD2_COLORIZED;
|
2020-06-07 20:11:36 +00:00
|
|
|
if (mobj->mirrored)
|
|
|
|
diff2 |= MD2_MIRRORED;
|
2020-10-30 06:15:49 +00:00
|
|
|
if (mobj->spriteroll)
|
|
|
|
diff2 |= MD2_SPRITEROLL;
|
2020-10-14 03:57:13 +00:00
|
|
|
if (mobj->shadowscale)
|
|
|
|
diff2 |= MD2_SHADOWSCALE;
|
|
|
|
if (mobj->renderflags)
|
|
|
|
diff2 |= MD2_RENDERFLAGS;
|
2020-12-06 20:29:20 +00:00
|
|
|
if (mobj->blendmode != AST_TRANSLUCENT)
|
2020-10-27 03:03:41 +00:00
|
|
|
diff2 |= MD2_BLENDMODE;
|
2020-10-12 03:13:22 +00:00
|
|
|
if (mobj->spritexscale != FRACUNIT)
|
|
|
|
diff2 |= MD2_SPRITEXSCALE;
|
|
|
|
if (mobj->spriteyscale != FRACUNIT)
|
|
|
|
diff2 |= MD2_SPRITEYSCALE;
|
2020-10-13 15:57:36 +00:00
|
|
|
if (mobj->spritexoffset)
|
|
|
|
diff2 |= MD2_SPRITEXOFFSET;
|
2020-12-06 20:29:20 +00:00
|
|
|
if (mobj->spriteyoffset)
|
|
|
|
diff2 |= MD2_SPRITEYOFFSET;
|
2020-10-14 16:07:02 +00:00
|
|
|
if (mobj->floorspriteslope)
|
2020-10-14 03:57:13 +00:00
|
|
|
{
|
|
|
|
pslope_t *slope = mobj->floorspriteslope;
|
|
|
|
if (slope->zangle || slope->zdelta || slope->xydirection
|
|
|
|
|| slope->o.x || slope->o.y || slope->o.z
|
|
|
|
|| slope->d.x || slope->d.y
|
|
|
|
|| slope->normal.x || slope->normal.y
|
|
|
|
|| (slope->normal.z != FRACUNIT))
|
|
|
|
diff2 |= MD2_FLOORSPRITESLOPE;
|
|
|
|
}
|
2023-06-29 22:09:20 +00:00
|
|
|
if (mobj->drawonlyforplayer)
|
|
|
|
diff2 |= MD2_DRAWONLYFORPLAYER;
|
|
|
|
if (mobj->dontdrawforviewmobj)
|
|
|
|
diff2 |= MD2_DONTDRAWFORVIEWMOBJ;
|
2022-01-13 07:53:26 +00:00
|
|
|
if (mobj->dispoffset != mobj->info->dispoffset)
|
|
|
|
diff2 |= MD2_DISPOFFSET;
|
2024-05-20 02:21:09 +00:00
|
|
|
if (mobj->alpha != FRACUNIT)
|
2024-02-25 01:04:48 +00:00
|
|
|
diff2 |= MD2_ALPHA;
|
2020-10-14 03:57:13 +00:00
|
|
|
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff2 != 0)
|
|
|
|
diff |= MD_MORE;
|
|
|
|
|
|
|
|
// Scrap all of that. If we're a hoop center, this is ALL we're saving.
|
|
|
|
if (mobj->type == MT_HOOPCENTER)
|
|
|
|
diff = MD_SPAWNPOINT;
|
|
|
|
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, diff);
|
|
|
|
if (diff & MD_MORE)
|
2020-12-06 20:29:20 +00:00
|
|
|
WRITEUINT32(save_p, diff2);
|
2015-01-01 19:50:31 +00:00
|
|
|
|
|
|
|
// save pointer, at load time we will search this pointer to reinitilize pointers
|
|
|
|
WRITEUINT32(save_p, (size_t)mobj);
|
|
|
|
|
|
|
|
WRITEFIXED(save_p, mobj->z); // Force this so 3dfloor problems don't arise.
|
|
|
|
WRITEFIXED(save_p, mobj->floorz);
|
|
|
|
WRITEFIXED(save_p, mobj->ceilingz);
|
|
|
|
|
2018-09-10 04:07:22 +00:00
|
|
|
if (diff2 & MD2_FLOORROVER)
|
2018-09-10 03:48:14 +00:00
|
|
|
{
|
2020-04-24 21:29:41 +00:00
|
|
|
WRITEUINT32(save_p, SaveSector(mobj->floorrover->target));
|
|
|
|
WRITEUINT16(save_p, P_GetFFloorID(mobj->floorrover));
|
2018-09-10 03:48:14 +00:00
|
|
|
}
|
|
|
|
|
2018-09-10 04:07:22 +00:00
|
|
|
if (diff2 & MD2_CEILINGROVER)
|
2018-09-10 03:48:14 +00:00
|
|
|
{
|
2020-04-24 21:29:41 +00:00
|
|
|
WRITEUINT32(save_p, SaveSector(mobj->ceilingrover->target));
|
|
|
|
WRITEUINT16(save_p, P_GetFFloorID(mobj->ceilingrover));
|
2018-09-10 03:48:14 +00:00
|
|
|
}
|
2015-01-01 19:50:31 +00:00
|
|
|
|
|
|
|
if (diff & MD_SPAWNPOINT)
|
|
|
|
{
|
|
|
|
size_t z;
|
|
|
|
|
|
|
|
for (z = 0; z < nummapthings; z++)
|
|
|
|
if (&mapthings[z] == mobj->spawnpoint)
|
|
|
|
WRITEUINT16(save_p, z);
|
|
|
|
if (mobj->type == MT_HOOPCENTER)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (diff & MD_TYPE)
|
|
|
|
WRITEUINT32(save_p, mobj->type);
|
|
|
|
if (diff & MD_POS)
|
|
|
|
{
|
|
|
|
WRITEFIXED(save_p, mobj->x);
|
|
|
|
WRITEFIXED(save_p, mobj->y);
|
|
|
|
WRITEANGLE(save_p, mobj->angle);
|
2020-04-19 12:39:16 +00:00
|
|
|
WRITEANGLE(save_p, mobj->pitch);
|
|
|
|
WRITEANGLE(save_p, mobj->roll);
|
2015-01-01 19:50:31 +00:00
|
|
|
}
|
|
|
|
if (diff & MD_MOM)
|
|
|
|
{
|
|
|
|
WRITEFIXED(save_p, mobj->momx);
|
|
|
|
WRITEFIXED(save_p, mobj->momy);
|
|
|
|
WRITEFIXED(save_p, mobj->momz);
|
2021-12-09 08:42:06 +00:00
|
|
|
WRITEFIXED(save_p, mobj->pmomz);
|
2015-01-01 19:50:31 +00:00
|
|
|
}
|
|
|
|
if (diff & MD_RADIUS)
|
|
|
|
WRITEFIXED(save_p, mobj->radius);
|
|
|
|
if (diff & MD_HEIGHT)
|
|
|
|
WRITEFIXED(save_p, mobj->height);
|
|
|
|
if (diff & MD_FLAGS)
|
|
|
|
WRITEUINT32(save_p, mobj->flags);
|
|
|
|
if (diff & MD_FLAGS2)
|
|
|
|
WRITEUINT32(save_p, mobj->flags2);
|
|
|
|
if (diff & MD_HEALTH)
|
|
|
|
WRITEINT32(save_p, mobj->health);
|
|
|
|
if (diff & MD_RTIME)
|
|
|
|
WRITEINT32(save_p, mobj->reactiontime);
|
|
|
|
if (diff & MD_STATE)
|
|
|
|
WRITEUINT16(save_p, mobj->state-states);
|
|
|
|
if (diff & MD_TICS)
|
|
|
|
WRITEINT32(save_p, mobj->tics);
|
2015-01-22 15:23:45 +00:00
|
|
|
if (diff & MD_SPRITE) {
|
2015-01-01 19:50:31 +00:00
|
|
|
WRITEUINT16(save_p, mobj->sprite);
|
2015-01-22 15:23:45 +00:00
|
|
|
if (mobj->sprite == SPR_PLAY)
|
2023-11-13 14:46:55 +00:00
|
|
|
WRITEUINT16(save_p, mobj->sprite2);
|
2015-01-22 15:23:45 +00:00
|
|
|
}
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_FRAME)
|
2016-02-09 10:39:16 +00:00
|
|
|
{
|
2015-01-01 19:50:31 +00:00
|
|
|
WRITEUINT32(save_p, mobj->frame);
|
2016-02-09 10:39:16 +00:00
|
|
|
WRITEUINT16(save_p, mobj->anim_duration);
|
|
|
|
}
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_EFLAGS)
|
2015-02-11 20:54:11 +00:00
|
|
|
WRITEUINT16(save_p, mobj->eflags);
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_PLAYER)
|
|
|
|
WRITEUINT8(save_p, mobj->player-players);
|
|
|
|
if (diff & MD_MOVEDIR)
|
|
|
|
WRITEANGLE(save_p, mobj->movedir);
|
|
|
|
if (diff & MD_MOVECOUNT)
|
|
|
|
WRITEINT32(save_p, mobj->movecount);
|
|
|
|
if (diff & MD_THRESHOLD)
|
|
|
|
WRITEINT32(save_p, mobj->threshold);
|
|
|
|
if (diff & MD_LASTLOOK)
|
|
|
|
WRITEINT32(save_p, mobj->lastlook);
|
|
|
|
if (diff & MD_TARGET)
|
|
|
|
WRITEUINT32(save_p, mobj->target->mobjnum);
|
|
|
|
if (diff & MD_TRACER)
|
|
|
|
WRITEUINT32(save_p, mobj->tracer->mobjnum);
|
|
|
|
if (diff & MD_FRICTION)
|
|
|
|
WRITEFIXED(save_p, mobj->friction);
|
|
|
|
if (diff & MD_MOVEFACTOR)
|
|
|
|
WRITEFIXED(save_p, mobj->movefactor);
|
|
|
|
if (diff & MD_FUSE)
|
|
|
|
WRITEINT32(save_p, mobj->fuse);
|
|
|
|
if (diff & MD_WATERTOP)
|
|
|
|
WRITEFIXED(save_p, mobj->watertop);
|
|
|
|
if (diff & MD_WATERBOTTOM)
|
|
|
|
WRITEFIXED(save_p, mobj->waterbottom);
|
|
|
|
if (diff & MD_SCALE)
|
|
|
|
WRITEFIXED(save_p, mobj->scale);
|
|
|
|
if (diff & MD_DSCALE)
|
|
|
|
WRITEFIXED(save_p, mobj->destscale);
|
|
|
|
if (diff2 & MD2_SCALESPEED)
|
|
|
|
WRITEFIXED(save_p, mobj->scalespeed);
|
|
|
|
if (diff2 & MD2_CUSVAL)
|
|
|
|
WRITEINT32(save_p, mobj->cusval);
|
|
|
|
if (diff2 & MD2_CVMEM)
|
|
|
|
WRITEINT32(save_p, mobj->cvmem);
|
|
|
|
if (diff2 & MD2_SKIN)
|
2021-08-09 18:57:07 +00:00
|
|
|
WRITEUINT8(save_p, (UINT8)(((skin_t *)mobj->skin)->skinnum));
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff2 & MD2_COLOR)
|
2020-05-24 00:29:07 +00:00
|
|
|
WRITEUINT16(save_p, mobj->color);
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff2 & MD2_EXTVAL1)
|
|
|
|
WRITEINT32(save_p, mobj->extravalue1);
|
|
|
|
if (diff2 & MD2_EXTVAL2)
|
|
|
|
WRITEINT32(save_p, mobj->extravalue2);
|
|
|
|
if (diff2 & MD2_HNEXT)
|
|
|
|
WRITEUINT32(save_p, mobj->hnext->mobjnum);
|
|
|
|
if (diff2 & MD2_HPREV)
|
|
|
|
WRITEUINT32(save_p, mobj->hprev->mobjnum);
|
2015-08-03 23:06:42 +00:00
|
|
|
if (diff2 & MD2_SLOPE)
|
|
|
|
WRITEUINT16(save_p, mobj->standingslope->id);
|
2019-06-18 16:55:57 +00:00
|
|
|
if (diff2 & MD2_COLORIZED)
|
|
|
|
WRITEUINT8(save_p, mobj->colorized);
|
2020-06-07 20:11:36 +00:00
|
|
|
if (diff2 & MD2_MIRRORED)
|
|
|
|
WRITEUINT8(save_p, mobj->mirrored);
|
2020-10-30 06:15:49 +00:00
|
|
|
if (diff2 & MD2_SPRITEROLL)
|
|
|
|
WRITEANGLE(save_p, mobj->spriteroll);
|
2020-10-14 03:57:13 +00:00
|
|
|
if (diff2 & MD2_SHADOWSCALE)
|
|
|
|
WRITEFIXED(save_p, mobj->shadowscale);
|
|
|
|
if (diff2 & MD2_RENDERFLAGS)
|
|
|
|
WRITEUINT32(save_p, mobj->renderflags);
|
2020-10-27 03:03:41 +00:00
|
|
|
if (diff2 & MD2_BLENDMODE)
|
|
|
|
WRITEINT32(save_p, mobj->blendmode);
|
2020-10-12 03:13:22 +00:00
|
|
|
if (diff2 & MD2_SPRITEXSCALE)
|
|
|
|
WRITEFIXED(save_p, mobj->spritexscale);
|
|
|
|
if (diff2 & MD2_SPRITEYSCALE)
|
|
|
|
WRITEFIXED(save_p, mobj->spriteyscale);
|
2020-10-13 15:57:36 +00:00
|
|
|
if (diff2 & MD2_SPRITEXOFFSET)
|
|
|
|
WRITEFIXED(save_p, mobj->spritexoffset);
|
|
|
|
if (diff2 & MD2_SPRITEYOFFSET)
|
|
|
|
WRITEFIXED(save_p, mobj->spriteyoffset);
|
2020-10-14 03:57:13 +00:00
|
|
|
if (diff2 & MD2_FLOORSPRITESLOPE)
|
|
|
|
{
|
|
|
|
pslope_t *slope = mobj->floorspriteslope;
|
|
|
|
|
|
|
|
WRITEFIXED(save_p, slope->zdelta);
|
|
|
|
WRITEANGLE(save_p, slope->zangle);
|
|
|
|
WRITEANGLE(save_p, slope->xydirection);
|
|
|
|
|
|
|
|
WRITEFIXED(save_p, slope->o.x);
|
|
|
|
WRITEFIXED(save_p, slope->o.y);
|
|
|
|
WRITEFIXED(save_p, slope->o.z);
|
|
|
|
|
|
|
|
WRITEFIXED(save_p, slope->d.x);
|
|
|
|
WRITEFIXED(save_p, slope->d.y);
|
|
|
|
|
|
|
|
WRITEFIXED(save_p, slope->normal.x);
|
|
|
|
WRITEFIXED(save_p, slope->normal.y);
|
|
|
|
WRITEFIXED(save_p, slope->normal.z);
|
|
|
|
}
|
2023-06-29 22:09:20 +00:00
|
|
|
if (diff2 & MD2_DRAWONLYFORPLAYER)
|
|
|
|
WRITEUINT8(save_p, mobj->drawonlyforplayer-players);
|
|
|
|
if (diff2 & MD2_DONTDRAWFORVIEWMOBJ)
|
|
|
|
WRITEUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum);
|
2022-01-13 07:53:26 +00:00
|
|
|
if (diff2 & MD2_DISPOFFSET)
|
|
|
|
WRITEINT32(save_p, mobj->dispoffset);
|
2023-10-30 02:34:18 +00:00
|
|
|
if (diff2 & MD2_TRANSLATION)
|
|
|
|
WRITEUINT16(save_p, mobj->translation);
|
2024-02-25 01:04:48 +00:00
|
|
|
if (diff2 & MD2_ALPHA)
|
2024-03-01 21:29:39 +00:00
|
|
|
WRITEFIXED(save_p, mobj->alpha);
|
2015-01-01 19:50:31 +00:00
|
|
|
|
|
|
|
WRITEUINT32(save_p, mobj->mobjnum);
|
|
|
|
}
|
|
|
|
|
2020-04-18 07:21:04 +00:00
|
|
|
static void SaveNoEnemiesThinker(const thinker_t *th, const UINT8 type)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2020-04-18 07:21:04 +00:00
|
|
|
const noenemies_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
|
|
|
}
|
|
|
|
|
2020-04-18 08:45:21 +00:00
|
|
|
static void SaveBounceCheeseThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const bouncecheese_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEFIXED(save_p, ht->speed);
|
|
|
|
WRITEFIXED(save_p, ht->distance);
|
|
|
|
WRITEFIXED(save_p, ht->floorwasheight);
|
|
|
|
WRITEFIXED(save_p, ht->ceilingwasheight);
|
|
|
|
WRITECHAR(save_p, ht->low);
|
|
|
|
}
|
|
|
|
|
2020-04-17 23:42:13 +00:00
|
|
|
static void SaveContinuousFallThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const continuousfall_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEFIXED(save_p, ht->speed);
|
|
|
|
WRITEINT32(save_p, ht->direction);
|
|
|
|
WRITEFIXED(save_p, ht->floorstartheight);
|
|
|
|
WRITEFIXED(save_p, ht->ceilingstartheight);
|
|
|
|
WRITEFIXED(save_p, ht->destheight);
|
|
|
|
}
|
|
|
|
|
2020-04-18 00:05:23 +00:00
|
|
|
static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const mariothink_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEFIXED(save_p, ht->speed);
|
|
|
|
WRITEINT32(save_p, ht->direction);
|
|
|
|
WRITEFIXED(save_p, ht->floorstartheight);
|
|
|
|
WRITEFIXED(save_p, ht->ceilingstartheight);
|
|
|
|
WRITEINT16(save_p, ht->tag);
|
|
|
|
}
|
|
|
|
|
2020-04-18 09:05:58 +00:00
|
|
|
static void SaveMarioCheckThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const mariocheck_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
}
|
|
|
|
|
2020-04-18 08:26:03 +00:00
|
|
|
static void SaveThwompThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const thwomp_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEFIXED(save_p, ht->crushspeed);
|
|
|
|
WRITEFIXED(save_p, ht->retractspeed);
|
|
|
|
WRITEINT32(save_p, ht->direction);
|
|
|
|
WRITEFIXED(save_p, ht->floorstartheight);
|
|
|
|
WRITEFIXED(save_p, ht->ceilingstartheight);
|
|
|
|
WRITEINT32(save_p, ht->delay);
|
|
|
|
WRITEINT16(save_p, ht->tag);
|
|
|
|
WRITEUINT16(save_p, ht->sound);
|
|
|
|
}
|
|
|
|
|
2020-04-17 22:26:49 +00:00
|
|
|
static void SaveFloatThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const floatthink_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEINT16(save_p, ht->tag);
|
|
|
|
}
|
|
|
|
|
2020-04-17 12:00:48 +00:00
|
|
|
static void SaveEachTimeThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const eachtime_t *ht = (const void *)th;
|
2014-03-15 16:59:03 +00:00
|
|
|
size_t i;
|
|
|
|
WRITEUINT8(save_p, type);
|
2020-04-17 12:00:48 +00:00
|
|
|
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
2018-09-17 18:12:16 +00:00
|
|
|
{
|
2020-04-17 12:00:48 +00:00
|
|
|
WRITECHAR(save_p, ht->playersInArea[i]);
|
2018-09-17 18:12:16 +00:00
|
|
|
}
|
2020-04-17 12:00:48 +00:00
|
|
|
WRITECHAR(save_p, ht->triggerOnExit);
|
|
|
|
}
|
|
|
|
|
2020-04-17 07:58:53 +00:00
|
|
|
static void SaveRaiseThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const raise_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
2020-04-27 10:54:08 +00:00
|
|
|
WRITEINT16(save_p, ht->tag);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
2020-04-17 07:58:53 +00:00
|
|
|
WRITEFIXED(save_p, ht->ceilingbottom);
|
|
|
|
WRITEFIXED(save_p, ht->ceilingtop);
|
|
|
|
WRITEFIXED(save_p, ht->basespeed);
|
|
|
|
WRITEFIXED(save_p, ht->extraspeed);
|
|
|
|
WRITEUINT8(save_p, ht->shaketimer);
|
|
|
|
WRITEUINT8(save_p, ht->flags);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void SaveCeilingThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const ceiling_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT8(save_p, ht->type);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEFIXED(save_p, ht->bottomheight);
|
|
|
|
WRITEFIXED(save_p, ht->topheight);
|
|
|
|
WRITEFIXED(save_p, ht->speed);
|
|
|
|
WRITEFIXED(save_p, ht->delay);
|
|
|
|
WRITEFIXED(save_p, ht->delaytimer);
|
|
|
|
WRITEUINT8(save_p, ht->crush);
|
|
|
|
WRITEINT32(save_p, ht->texture);
|
|
|
|
WRITEINT32(save_p, ht->direction);
|
2021-06-26 13:28:28 +00:00
|
|
|
WRITEINT16(save_p, ht->tag);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEFIXED(save_p, ht->origspeed);
|
|
|
|
WRITEFIXED(save_p, ht->sourceline);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const floormove_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT8(save_p, ht->type);
|
|
|
|
WRITEUINT8(save_p, ht->crush);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEINT32(save_p, ht->direction);
|
|
|
|
WRITEINT32(save_p, ht->texture);
|
|
|
|
WRITEFIXED(save_p, ht->floordestheight);
|
|
|
|
WRITEFIXED(save_p, ht->speed);
|
|
|
|
WRITEFIXED(save_p, ht->origspeed);
|
|
|
|
WRITEFIXED(save_p, ht->delay);
|
|
|
|
WRITEFIXED(save_p, ht->delaytimer);
|
2021-06-26 13:28:28 +00:00
|
|
|
WRITEINT16(save_p, ht->tag);
|
2021-06-26 14:25:14 +00:00
|
|
|
WRITEFIXED(save_p, ht->sourceline);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void SaveLightflashThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const lightflash_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEINT32(save_p, ht->maxlight);
|
|
|
|
WRITEINT32(save_p, ht->minlight);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SaveStrobeThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const strobe_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEINT32(save_p, ht->count);
|
2021-09-19 14:25:27 +00:00
|
|
|
WRITEINT16(save_p, ht->minlight);
|
|
|
|
WRITEINT16(save_p, ht->maxlight);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEINT32(save_p, ht->darktime);
|
|
|
|
WRITEINT32(save_p, ht->brighttime);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SaveGlowThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const glow_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
2021-09-19 14:25:27 +00:00
|
|
|
WRITEINT16(save_p, ht->minlight);
|
|
|
|
WRITEINT16(save_p, ht->maxlight);
|
|
|
|
WRITEINT16(save_p, ht->direction);
|
|
|
|
WRITEINT16(save_p, ht->speed);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2020-05-01 09:25:32 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const fireflicker_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEINT32(save_p, ht->count);
|
|
|
|
WRITEINT32(save_p, ht->resetcount);
|
2021-09-19 14:25:27 +00:00
|
|
|
WRITEINT16(save_p, ht->maxlight);
|
|
|
|
WRITEINT16(save_p, ht->minlight);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2020-05-01 09:25:32 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
static void SaveElevatorThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const elevator_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT8(save_p, ht->type);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->actionsector));
|
|
|
|
WRITEINT32(save_p, ht->direction);
|
|
|
|
WRITEFIXED(save_p, ht->floordestheight);
|
|
|
|
WRITEFIXED(save_p, ht->ceilingdestheight);
|
|
|
|
WRITEFIXED(save_p, ht->speed);
|
|
|
|
WRITEFIXED(save_p, ht->origspeed);
|
|
|
|
WRITEFIXED(save_p, ht->low);
|
|
|
|
WRITEFIXED(save_p, ht->high);
|
|
|
|
WRITEFIXED(save_p, ht->distance);
|
|
|
|
WRITEFIXED(save_p, ht->delay);
|
|
|
|
WRITEFIXED(save_p, ht->delaytimer);
|
|
|
|
WRITEFIXED(save_p, ht->floorwasheight);
|
|
|
|
WRITEFIXED(save_p, ht->ceilingwasheight);
|
|
|
|
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
|
|
|
}
|
|
|
|
|
2020-04-26 09:55:10 +00:00
|
|
|
static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const crumble_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
2020-04-26 14:51:14 +00:00
|
|
|
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
2020-04-26 09:55:10 +00:00
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->actionsector));
|
2020-04-26 14:51:14 +00:00
|
|
|
WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy
|
2020-04-26 09:55:10 +00:00
|
|
|
WRITEINT32(save_p, ht->direction);
|
2020-04-26 14:51:14 +00:00
|
|
|
WRITEINT32(save_p, ht->origalpha);
|
|
|
|
WRITEINT32(save_p, ht->timer);
|
2020-04-26 09:55:10 +00:00
|
|
|
WRITEFIXED(save_p, ht->speed);
|
|
|
|
WRITEFIXED(save_p, ht->floorwasheight);
|
|
|
|
WRITEFIXED(save_p, ht->ceilingwasheight);
|
2020-04-26 14:51:14 +00:00
|
|
|
WRITEUINT8(save_p, ht->flags);
|
2020-04-26 09:55:10 +00:00
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
static inline void SaveScrollThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const scroll_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEFIXED(save_p, ht->dx);
|
|
|
|
WRITEFIXED(save_p, ht->dy);
|
|
|
|
WRITEINT32(save_p, ht->affectee);
|
|
|
|
WRITEINT32(save_p, ht->control);
|
|
|
|
WRITEFIXED(save_p, ht->last_height);
|
|
|
|
WRITEFIXED(save_p, ht->vdx);
|
|
|
|
WRITEFIXED(save_p, ht->vdy);
|
|
|
|
WRITEINT32(save_p, ht->accel);
|
|
|
|
WRITEINT32(save_p, ht->exclusive);
|
|
|
|
WRITEUINT8(save_p, ht->type);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void SaveFrictionThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const friction_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEINT32(save_p, ht->friction);
|
|
|
|
WRITEINT32(save_p, ht->movefactor);
|
|
|
|
WRITEINT32(save_p, ht->affectee);
|
|
|
|
WRITEINT32(save_p, ht->referrer);
|
|
|
|
WRITEUINT8(save_p, ht->roverfriction);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void SavePusherThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const pusher_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT8(save_p, ht->type);
|
2021-07-01 18:05:23 +00:00
|
|
|
WRITEFIXED(save_p, ht->x_mag);
|
|
|
|
WRITEFIXED(save_p, ht->y_mag);
|
|
|
|
WRITEFIXED(save_p, ht->z_mag);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEINT32(save_p, ht->affectee);
|
|
|
|
WRITEUINT8(save_p, ht->roverpusher);
|
|
|
|
WRITEINT32(save_p, ht->referrer);
|
|
|
|
WRITEINT32(save_p, ht->exclusive);
|
|
|
|
WRITEINT32(save_p, ht->slider);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SaveLaserThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const laserthink_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
2020-05-02 08:03:16 +00:00
|
|
|
WRITEINT16(save_p, ht->tag);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
2020-04-27 11:09:57 +00:00
|
|
|
WRITEUINT8(save_p, ht->nobosses);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const lightlevel_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
2018-09-11 14:05:25 +00:00
|
|
|
WRITEINT16(save_p, ht->sourcelevel);
|
|
|
|
WRITEINT16(save_p, ht->destlevel);
|
2018-09-15 10:21:25 +00:00
|
|
|
WRITEFIXED(save_p, ht->fixedcurlevel);
|
|
|
|
WRITEFIXED(save_p, ht->fixedpertic);
|
2018-09-10 00:18:43 +00:00
|
|
|
WRITEINT32(save_p, ht->timer);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void SaveExecutorThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const executor_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveLine(ht->line));
|
|
|
|
WRITEUINT32(save_p, SaveMobjnum(ht->caller));
|
2014-11-12 00:55:07 +00:00
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEINT32(save_p, ht->timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SaveDisappearThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const disappear_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, ht->appeartime);
|
|
|
|
WRITEUINT32(save_p, ht->disappeartime);
|
|
|
|
WRITEUINT32(save_p, ht->offset);
|
|
|
|
WRITEUINT32(save_p, ht->timer);
|
|
|
|
WRITEINT32(save_p, ht->affectee);
|
|
|
|
WRITEINT32(save_p, ht->sourceline);
|
|
|
|
WRITEINT32(save_p, ht->exists);
|
|
|
|
}
|
|
|
|
|
2018-03-30 19:27:37 +00:00
|
|
|
static void SaveFadeThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const fade_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
2018-09-17 04:34:03 +00:00
|
|
|
WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
|
2018-09-10 03:52:36 +00:00
|
|
|
WRITEUINT32(save_p, ht->sectornum);
|
|
|
|
WRITEUINT32(save_p, ht->ffloornum);
|
2018-08-17 20:27:32 +00:00
|
|
|
WRITEINT32(save_p, ht->alpha);
|
2018-09-11 14:28:24 +00:00
|
|
|
WRITEINT16(save_p, ht->sourcevalue);
|
2018-04-07 11:09:04 +00:00
|
|
|
WRITEINT16(save_p, ht->destvalue);
|
2018-09-09 21:19:49 +00:00
|
|
|
WRITEINT16(save_p, ht->destlightlevel);
|
2018-04-07 11:09:04 +00:00
|
|
|
WRITEINT16(save_p, ht->speed);
|
2018-09-10 00:45:12 +00:00
|
|
|
WRITEUINT8(save_p, (UINT8)ht->ticbased);
|
|
|
|
WRITEINT32(save_p, ht->timer);
|
2018-04-07 03:14:48 +00:00
|
|
|
WRITEUINT8(save_p, ht->doexists);
|
|
|
|
WRITEUINT8(save_p, ht->dotranslucent);
|
2018-09-09 00:41:45 +00:00
|
|
|
WRITEUINT8(save_p, ht->dolighting);
|
2018-09-12 20:57:35 +00:00
|
|
|
WRITEUINT8(save_p, ht->docolormap);
|
2018-09-09 21:19:49 +00:00
|
|
|
WRITEUINT8(save_p, ht->docollision);
|
2018-08-14 14:18:08 +00:00
|
|
|
WRITEUINT8(save_p, ht->doghostfade);
|
2018-08-17 19:13:05 +00:00
|
|
|
WRITEUINT8(save_p, ht->exactalpha);
|
2018-03-30 19:27:37 +00:00
|
|
|
}
|
|
|
|
|
2018-09-12 13:06:38 +00:00
|
|
|
static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const fadecolormap_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->sector));
|
2018-09-17 00:27:24 +00:00
|
|
|
WRITEUINT32(save_p, CheckAddNetColormapToList(ht->source_exc));
|
|
|
|
WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
|
2018-09-13 14:38:15 +00:00
|
|
|
WRITEUINT8(save_p, (UINT8)ht->ticbased);
|
2018-09-12 13:06:38 +00:00
|
|
|
WRITEINT32(save_p, ht->duration);
|
|
|
|
WRITEINT32(save_p, ht->timer);
|
|
|
|
}
|
|
|
|
|
2017-01-20 20:17:40 +00:00
|
|
|
static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const planedisplace_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEINT32(save_p, ht->affectee);
|
|
|
|
WRITEINT32(save_p, ht->control);
|
|
|
|
WRITEFIXED(save_p, ht->last_height);
|
|
|
|
WRITEFIXED(save_p, ht->speed);
|
|
|
|
WRITEUINT8(save_p, ht->type);
|
|
|
|
}
|
2020-03-20 17:55:29 +00:00
|
|
|
|
2021-12-29 12:53:38 +00:00
|
|
|
static inline void SaveDynamicLineSlopeThinker(const thinker_t *th, const UINT8 type)
|
2019-04-19 12:14:43 +00:00
|
|
|
{
|
2021-12-29 12:53:38 +00:00
|
|
|
const dynlineplanethink_t* ht = (const void*)th;
|
2019-04-19 12:14:43 +00:00
|
|
|
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT8(save_p, ht->type);
|
|
|
|
WRITEUINT32(save_p, SaveSlope(ht->slope));
|
|
|
|
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
|
|
|
WRITEFIXED(save_p, ht->extent);
|
2021-12-29 12:53:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void SaveDynamicVertexSlopeThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
2021-12-29 14:29:59 +00:00
|
|
|
size_t i;
|
2021-12-29 12:53:38 +00:00
|
|
|
const dynvertexplanethink_t* ht = (const void*)th;
|
2019-04-19 12:14:43 +00:00
|
|
|
|
2021-12-29 12:53:38 +00:00
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEUINT32(save_p, SaveSlope(ht->slope));
|
2021-12-29 14:29:59 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->secs[i]));
|
|
|
|
WRITEMEM(save_p, ht->vex, sizeof(ht->vex));
|
|
|
|
WRITEMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights));
|
|
|
|
WRITEMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights));
|
|
|
|
WRITEUINT8(save_p, ht->relative);
|
2019-04-19 12:14:43 +00:00
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const polyrotate_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEINT32(save_p, ht->polyObjNum);
|
|
|
|
WRITEINT32(save_p, ht->speed);
|
|
|
|
WRITEINT32(save_p, ht->distance);
|
2020-06-04 20:31:26 +00:00
|
|
|
WRITEUINT8(save_p, ht->turnobjs);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void SavePolymoveThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const polymove_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEINT32(save_p, ht->polyObjNum);
|
|
|
|
WRITEINT32(save_p, ht->speed);
|
|
|
|
WRITEFIXED(save_p, ht->momx);
|
|
|
|
WRITEFIXED(save_p, ht->momy);
|
|
|
|
WRITEINT32(save_p, ht->distance);
|
|
|
|
WRITEANGLE(save_p, ht->angle);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SavePolywaypointThinker(const thinker_t *th, UINT8 type)
|
|
|
|
{
|
|
|
|
const polywaypoint_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEINT32(save_p, ht->polyObjNum);
|
|
|
|
WRITEINT32(save_p, ht->speed);
|
|
|
|
WRITEINT32(save_p, ht->sequence);
|
|
|
|
WRITEINT32(save_p, ht->pointnum);
|
|
|
|
WRITEINT32(save_p, ht->direction);
|
2020-05-13 14:21:47 +00:00
|
|
|
WRITEUINT8(save_p, ht->returnbehavior);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT8(save_p, ht->continuous);
|
|
|
|
WRITEUINT8(save_p, ht->stophere);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const polyslidedoor_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEINT32(save_p, ht->polyObjNum);
|
|
|
|
WRITEINT32(save_p, ht->delay);
|
|
|
|
WRITEINT32(save_p, ht->delayCount);
|
|
|
|
WRITEINT32(save_p, ht->initSpeed);
|
|
|
|
WRITEINT32(save_p, ht->speed);
|
|
|
|
WRITEINT32(save_p, ht->initDistance);
|
|
|
|
WRITEINT32(save_p, ht->distance);
|
|
|
|
WRITEUINT32(save_p, ht->initAngle);
|
|
|
|
WRITEUINT32(save_p, ht->angle);
|
|
|
|
WRITEUINT32(save_p, ht->revAngle);
|
|
|
|
WRITEFIXED(save_p, ht->momx);
|
|
|
|
WRITEFIXED(save_p, ht->momy);
|
|
|
|
WRITEUINT8(save_p, ht->closing);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SavePolyswingdoorThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const polyswingdoor_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEINT32(save_p, ht->polyObjNum);
|
|
|
|
WRITEINT32(save_p, ht->delay);
|
|
|
|
WRITEINT32(save_p, ht->delayCount);
|
|
|
|
WRITEINT32(save_p, ht->initSpeed);
|
|
|
|
WRITEINT32(save_p, ht->speed);
|
|
|
|
WRITEINT32(save_p, ht->initDistance);
|
|
|
|
WRITEINT32(save_p, ht->distance);
|
|
|
|
WRITEUINT8(save_p, ht->closing);
|
|
|
|
}
|
|
|
|
|
2014-11-12 00:55:07 +00:00
|
|
|
static void SavePolydisplaceThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const polydisplace_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEINT32(save_p, ht->polyObjNum);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->controlSector));
|
|
|
|
WRITEFIXED(save_p, ht->dx);
|
|
|
|
WRITEFIXED(save_p, ht->dy);
|
|
|
|
WRITEFIXED(save_p, ht->oldHeights);
|
|
|
|
}
|
|
|
|
|
2019-04-05 09:50:59 +00:00
|
|
|
static void SavePolyrotdisplaceThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const polyrotdisplace_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEINT32(save_p, ht->polyObjNum);
|
|
|
|
WRITEUINT32(save_p, SaveSector(ht->controlSector));
|
|
|
|
WRITEFIXED(save_p, ht->rotscale);
|
|
|
|
WRITEUINT8(save_p, ht->turnobjs);
|
|
|
|
WRITEFIXED(save_p, ht->oldHeights);
|
|
|
|
}
|
|
|
|
|
2018-09-09 05:08:02 +00:00
|
|
|
static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type)
|
|
|
|
{
|
|
|
|
const polyfade_t *ht = (const void *)th;
|
|
|
|
WRITEUINT8(save_p, type);
|
|
|
|
WRITEINT32(save_p, ht->polyObjNum);
|
2018-09-13 04:04:50 +00:00
|
|
|
WRITEINT32(save_p, ht->sourcevalue);
|
2018-09-09 05:08:02 +00:00
|
|
|
WRITEINT32(save_p, ht->destvalue);
|
|
|
|
WRITEUINT8(save_p, (UINT8)ht->docollision);
|
|
|
|
WRITEUINT8(save_p, (UINT8)ht->doghostfade);
|
2018-09-13 04:04:50 +00:00
|
|
|
WRITEUINT8(save_p, (UINT8)ht->ticbased);
|
2018-09-16 00:00:04 +00:00
|
|
|
WRITEINT32(save_p, ht->duration);
|
2018-09-10 01:01:00 +00:00
|
|
|
WRITEINT32(save_p, ht->timer);
|
2018-09-09 05:08:02 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
static void P_NetArchiveThinkers(void)
|
|
|
|
{
|
|
|
|
const thinker_t *th;
|
2019-04-20 20:37:19 +00:00
|
|
|
UINT32 i;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
WRITEUINT32(save_p, ARCHIVEBLOCK_THINKERS);
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
for (i = 0; i < NUM_THINKERLISTS; i++)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2019-04-20 20:37:19 +00:00
|
|
|
UINT32 numsaved = 0;
|
|
|
|
// save off the current thinkers
|
|
|
|
for (th = thlist[i].next; th != &thlist[i]; th = th->next)
|
2017-01-20 20:17:40 +00:00
|
|
|
{
|
2019-04-20 20:37:19 +00:00
|
|
|
if (!(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed
|
|
|
|
|| th->function.acp1 == (actionf_p1)P_NullPrecipThinker))
|
|
|
|
numsaved++;
|
|
|
|
|
|
|
|
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
|
|
|
{
|
|
|
|
SaveMobjThinker(th, tc_mobj);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#ifdef PARANOIA
|
|
|
|
else if (th->function.acp1 == (actionf_p1)P_NullPrecipThinker);
|
|
|
|
#endif
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_MoveCeiling)
|
|
|
|
{
|
|
|
|
SaveCeilingThinker(th, tc_ceiling);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_CrushCeiling)
|
|
|
|
{
|
|
|
|
SaveCeilingThinker(th, tc_crushceiling);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_MoveFloor)
|
|
|
|
{
|
|
|
|
SaveFloormoveThinker(th, tc_floor);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_LightningFlash)
|
|
|
|
{
|
|
|
|
SaveLightflashThinker(th, tc_flash);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_StrobeFlash)
|
|
|
|
{
|
|
|
|
SaveStrobeThinker(th, tc_strobe);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_Glow)
|
|
|
|
{
|
|
|
|
SaveGlowThinker(th, tc_glow);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_FireFlicker)
|
|
|
|
{
|
|
|
|
SaveFireflickerThinker(th, tc_fireflicker);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_MoveElevator)
|
|
|
|
{
|
|
|
|
SaveElevatorThinker(th, tc_elevator);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling)
|
|
|
|
{
|
2020-04-17 23:42:13 +00:00
|
|
|
SaveContinuousFallThinker(th, tc_continuousfalling);
|
2019-04-20 20:37:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_ThwompSector)
|
|
|
|
{
|
2020-04-18 08:26:03 +00:00
|
|
|
SaveThwompThinker(th, tc_thwomp);
|
2019-04-20 20:37:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector)
|
|
|
|
{
|
2020-04-18 07:21:04 +00:00
|
|
|
SaveNoEnemiesThinker(th, tc_noenemies);
|
2019-04-20 20:37:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker)
|
|
|
|
{
|
2020-04-17 12:00:48 +00:00
|
|
|
SaveEachTimeThinker(th, tc_eachtime);
|
2019-04-20 20:37:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_RaiseSector)
|
|
|
|
{
|
2020-04-17 07:58:53 +00:00
|
|
|
SaveRaiseThinker(th, tc_raisesector);
|
2019-04-20 20:37:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_CameraScanner)
|
|
|
|
{
|
|
|
|
SaveElevatorThinker(th, tc_camerascanner);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_Scroll)
|
|
|
|
{
|
|
|
|
SaveScrollThinker(th, tc_scroll);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_Friction)
|
|
|
|
{
|
|
|
|
SaveFrictionThinker(th, tc_friction);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_Pusher)
|
|
|
|
{
|
|
|
|
SavePusherThinker(th, tc_pusher);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_BounceCheese)
|
|
|
|
{
|
2020-04-18 08:45:21 +00:00
|
|
|
SaveBounceCheeseThinker(th, tc_bouncecheese);
|
2019-04-20 20:37:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_StartCrumble)
|
|
|
|
{
|
2020-04-26 16:31:39 +00:00
|
|
|
SaveCrumbleThinker(th, tc_startcrumble);
|
2019-04-20 20:37:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_MarioBlock)
|
|
|
|
{
|
2020-04-18 00:05:23 +00:00
|
|
|
SaveMarioBlockThinker(th, tc_marioblock);
|
2019-04-20 20:37:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker)
|
|
|
|
{
|
2020-04-18 09:05:58 +00:00
|
|
|
SaveMarioCheckThinker(th, tc_marioblockchecker);
|
2019-04-20 20:37:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_FloatSector)
|
|
|
|
{
|
2020-04-17 22:26:49 +00:00
|
|
|
SaveFloatThinker(th, tc_floatsector);
|
2019-04-20 20:37:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_LaserFlash)
|
|
|
|
{
|
|
|
|
SaveLaserThinker(th, tc_laserflash);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_LightFade)
|
|
|
|
{
|
|
|
|
SaveLightlevelThinker(th, tc_lightfade);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay)
|
|
|
|
{
|
|
|
|
SaveExecutorThinker(th, tc_executor);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_Disappear)
|
|
|
|
{
|
|
|
|
SaveDisappearThinker(th, tc_disappear);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_Fade)
|
|
|
|
{
|
|
|
|
SaveFadeThinker(th, tc_fade);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_FadeColormap)
|
|
|
|
{
|
|
|
|
SaveFadeColormapThinker(th, tc_fadecolormap);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace)
|
|
|
|
{
|
|
|
|
SavePlaneDisplaceThinker(th, tc_planedisplace);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate)
|
|
|
|
{
|
|
|
|
SavePolyrotatetThinker(th, tc_polyrotate);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_PolyObjMove)
|
|
|
|
{
|
|
|
|
SavePolymoveThinker(th, tc_polymove);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint)
|
|
|
|
{
|
|
|
|
SavePolywaypointThinker(th, tc_polywaypoint);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide)
|
|
|
|
{
|
|
|
|
SavePolyslidedoorThinker(th, tc_polyslidedoor);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing)
|
|
|
|
{
|
|
|
|
SavePolyswingdoorThinker(th, tc_polyswingdoor);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag)
|
|
|
|
{
|
|
|
|
SavePolymoveThinker(th, tc_polyflag);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace)
|
|
|
|
{
|
|
|
|
SavePolydisplaceThinker(th, tc_polydisplace);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_PolyObjRotDisplace)
|
|
|
|
{
|
|
|
|
SavePolyrotdisplaceThinker(th, tc_polyrotdisplace);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_PolyObjFade)
|
|
|
|
{
|
|
|
|
SavePolyfadeThinker(th, tc_polyfade);
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-21 09:45:59 +00:00
|
|
|
else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine)
|
|
|
|
{
|
2021-12-29 12:53:38 +00:00
|
|
|
SaveDynamicLineSlopeThinker(th, tc_dynslopeline);
|
2019-04-21 09:45:59 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert)
|
|
|
|
{
|
2021-12-29 12:53:38 +00:00
|
|
|
SaveDynamicVertexSlopeThinker(th, tc_dynslopevert);
|
2019-04-21 09:45:59 +00:00
|
|
|
continue;
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
#ifdef PARANOIA
|
2023-08-01 02:29:45 +00:00
|
|
|
else
|
|
|
|
I_Assert(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed); // wait garbage collection
|
2014-03-15 16:59:03 +00:00
|
|
|
#endif
|
2019-04-20 20:37:19 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-07-12 23:42:03 +00:00
|
|
|
CONS_Debug(DBG_NETPLAY, "%u thinkers saved in list %d\n", numsaved, i);
|
2017-06-12 16:55:15 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
WRITEUINT8(save_p, tc_end);
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now save the pointers, tracer and target, but at load time we must
|
|
|
|
// relink to this; the savegame contains the old position in the pointer
|
|
|
|
// field copyed in the info field temporarily, but finally we just search
|
|
|
|
// for the old position and relink to it.
|
|
|
|
mobj_t *P_FindNewPosition(UINT32 oldposition)
|
|
|
|
{
|
|
|
|
thinker_t *th;
|
|
|
|
mobj_t *mobj;
|
|
|
|
|
2019-04-20 21:29:20 +00:00
|
|
|
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2019-07-12 23:42:03 +00:00
|
|
|
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
|
|
|
continue;
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
mobj = (mobj_t *)th;
|
2019-07-12 23:42:03 +00:00
|
|
|
if (mobj->mobjnum != oldposition)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
return mobj;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "mobj not found\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline mobj_t *LoadMobj(UINT32 mobjnum)
|
|
|
|
{
|
|
|
|
if (mobjnum == 0) return NULL;
|
|
|
|
return (mobj_t *)(size_t)mobjnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
static sector_t *LoadSector(UINT32 sector)
|
|
|
|
{
|
|
|
|
if (sector >= numsectors) return NULL;
|
|
|
|
return §ors[sector];
|
|
|
|
}
|
|
|
|
|
|
|
|
static line_t *LoadLine(UINT32 line)
|
|
|
|
{
|
|
|
|
if (line >= numlines) return NULL;
|
|
|
|
return &lines[line];
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline player_t *LoadPlayer(UINT32 player)
|
|
|
|
{
|
|
|
|
if (player >= MAXPLAYERS) return NULL;
|
|
|
|
return &players[player];
|
|
|
|
}
|
|
|
|
|
2019-04-19 12:14:43 +00:00
|
|
|
static inline pslope_t *LoadSlope(UINT32 slopeid)
|
|
|
|
{
|
|
|
|
pslope_t *p = slopelist;
|
|
|
|
if (slopeid > slopecount) return NULL;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (p->id == slopeid)
|
|
|
|
return p;
|
|
|
|
} while ((p = p->next));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static thinker_t* LoadMobjThinker(actionf_p1 thinker)
|
2015-01-01 19:50:31 +00:00
|
|
|
{
|
|
|
|
thinker_t *next;
|
|
|
|
mobj_t *mobj;
|
|
|
|
UINT32 diff;
|
2020-12-06 20:29:20 +00:00
|
|
|
UINT32 diff2;
|
2015-01-01 19:50:31 +00:00
|
|
|
INT32 i;
|
|
|
|
fixed_t z, floorz, ceilingz;
|
2018-09-10 03:48:14 +00:00
|
|
|
ffloor_t *floorrover = NULL, *ceilingrover = NULL;
|
2015-01-01 19:50:31 +00:00
|
|
|
|
|
|
|
diff = READUINT32(save_p);
|
|
|
|
if (diff & MD_MORE)
|
2020-12-06 20:29:20 +00:00
|
|
|
diff2 = READUINT32(save_p);
|
2015-01-01 19:50:31 +00:00
|
|
|
else
|
|
|
|
diff2 = 0;
|
|
|
|
|
|
|
|
next = (void *)(size_t)READUINT32(save_p);
|
|
|
|
|
|
|
|
z = READFIXED(save_p); // Force this so 3dfloor problems don't arise.
|
|
|
|
floorz = READFIXED(save_p);
|
|
|
|
ceilingz = READFIXED(save_p);
|
|
|
|
|
2018-09-10 03:48:14 +00:00
|
|
|
if (diff2 & MD2_FLOORROVER)
|
2018-09-10 03:12:37 +00:00
|
|
|
{
|
2020-04-24 21:29:41 +00:00
|
|
|
sector_t *sec = LoadSector(READUINT32(save_p));
|
|
|
|
UINT16 id = READUINT16(save_p);
|
|
|
|
floorrover = P_GetFFloorByID(sec, id);
|
2018-09-10 03:12:37 +00:00
|
|
|
}
|
|
|
|
|
2018-09-10 03:48:14 +00:00
|
|
|
if (diff2 & MD2_CEILINGROVER)
|
|
|
|
{
|
2020-04-24 21:29:41 +00:00
|
|
|
sector_t *sec = LoadSector(READUINT32(save_p));
|
|
|
|
UINT16 id = READUINT16(save_p);
|
|
|
|
ceilingrover = P_GetFFloorByID(sec, id);
|
2018-09-10 03:48:14 +00:00
|
|
|
}
|
2015-01-01 19:50:31 +00:00
|
|
|
|
|
|
|
if (diff & MD_SPAWNPOINT)
|
|
|
|
{
|
|
|
|
UINT16 spawnpointnum = READUINT16(save_p);
|
|
|
|
|
2021-12-19 09:16:03 +00:00
|
|
|
if (mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case
|
2015-01-01 19:50:31 +00:00
|
|
|
{
|
2019-12-24 09:50:49 +00:00
|
|
|
P_SpawnHoop(&mapthings[spawnpointnum]);
|
2019-04-20 20:37:19 +00:00
|
|
|
return NULL;
|
2015-01-01 19:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
|
|
|
|
|
|
|
|
mobj->spawnpoint = &mapthings[spawnpointnum];
|
|
|
|
mapthings[spawnpointnum].mobj = mobj;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
|
|
|
|
|
|
|
|
// declare this as a valid mobj as soon as possible.
|
|
|
|
mobj->thinker.function.acp1 = thinker;
|
|
|
|
|
|
|
|
mobj->z = z;
|
|
|
|
mobj->floorz = floorz;
|
|
|
|
mobj->ceilingz = ceilingz;
|
2018-09-10 03:48:14 +00:00
|
|
|
mobj->floorrover = floorrover;
|
|
|
|
mobj->ceilingrover = ceilingrover;
|
2015-01-01 19:50:31 +00:00
|
|
|
|
|
|
|
if (diff & MD_TYPE)
|
|
|
|
mobj->type = READUINT32(save_p);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < NUMMOBJTYPES; i++)
|
|
|
|
if (mobj->spawnpoint && mobj->spawnpoint->type == mobjinfo[i].doomednum)
|
|
|
|
break;
|
|
|
|
if (i == NUMMOBJTYPES)
|
|
|
|
{
|
|
|
|
if (mobj->spawnpoint)
|
|
|
|
CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type %d\n", mobj->spawnpoint->type);
|
|
|
|
else
|
|
|
|
CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type NULL\n");
|
|
|
|
I_Error("Savegame corrupted");
|
|
|
|
}
|
|
|
|
mobj->type = i;
|
|
|
|
}
|
|
|
|
mobj->info = &mobjinfo[mobj->type];
|
|
|
|
if (diff & MD_POS)
|
|
|
|
{
|
|
|
|
mobj->x = READFIXED(save_p);
|
|
|
|
mobj->y = READFIXED(save_p);
|
|
|
|
mobj->angle = READANGLE(save_p);
|
2020-04-19 12:39:16 +00:00
|
|
|
mobj->pitch = READANGLE(save_p);
|
|
|
|
mobj->roll = READANGLE(save_p);
|
2015-01-01 19:50:31 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mobj->x = mobj->spawnpoint->x << FRACBITS;
|
|
|
|
mobj->y = mobj->spawnpoint->y << FRACBITS;
|
|
|
|
mobj->angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT);
|
2020-04-19 12:39:16 +00:00
|
|
|
mobj->pitch = FixedAngle(mobj->spawnpoint->pitch*FRACUNIT);
|
|
|
|
mobj->roll = FixedAngle(mobj->spawnpoint->roll*FRACUNIT);
|
2015-01-01 19:50:31 +00:00
|
|
|
}
|
|
|
|
if (diff & MD_MOM)
|
|
|
|
{
|
|
|
|
mobj->momx = READFIXED(save_p);
|
|
|
|
mobj->momy = READFIXED(save_p);
|
|
|
|
mobj->momz = READFIXED(save_p);
|
2021-12-09 08:42:06 +00:00
|
|
|
mobj->pmomz = READFIXED(save_p);
|
2015-01-01 19:50:31 +00:00
|
|
|
} // otherwise they're zero, and the memset took care of it
|
|
|
|
|
|
|
|
if (diff & MD_RADIUS)
|
|
|
|
mobj->radius = READFIXED(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->radius = mobj->info->radius;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_HEIGHT)
|
|
|
|
mobj->height = READFIXED(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->height = mobj->info->height;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_FLAGS)
|
|
|
|
mobj->flags = READUINT32(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->flags = mobj->info->flags;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_FLAGS2)
|
|
|
|
mobj->flags2 = READUINT32(save_p);
|
|
|
|
if (diff & MD_HEALTH)
|
|
|
|
mobj->health = READINT32(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->health = mobj->info->spawnhealth;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_RTIME)
|
|
|
|
mobj->reactiontime = READINT32(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->reactiontime = mobj->info->reactiontime;
|
2015-01-01 19:50:31 +00:00
|
|
|
|
|
|
|
if (diff & MD_STATE)
|
|
|
|
mobj->state = &states[READUINT16(save_p)];
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->state = &states[mobj->info->spawnstate];
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_TICS)
|
|
|
|
mobj->tics = READINT32(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->tics = mobj->state->tics;
|
2015-01-22 15:23:45 +00:00
|
|
|
if (diff & MD_SPRITE) {
|
2015-01-01 19:50:31 +00:00
|
|
|
mobj->sprite = READUINT16(save_p);
|
2015-01-22 15:23:45 +00:00
|
|
|
if (mobj->sprite == SPR_PLAY)
|
2023-11-13 14:46:55 +00:00
|
|
|
mobj->sprite2 = READUINT16(save_p);
|
2015-01-22 15:23:45 +00:00
|
|
|
}
|
|
|
|
else {
|
2015-01-01 19:50:31 +00:00
|
|
|
mobj->sprite = mobj->state->sprite;
|
2015-01-22 15:23:45 +00:00
|
|
|
if (mobj->sprite == SPR_PLAY)
|
2023-11-13 14:46:55 +00:00
|
|
|
mobj->sprite2 = P_GetStateSprite2(mobj->state);
|
2015-01-22 15:23:45 +00:00
|
|
|
}
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_FRAME)
|
2016-02-09 10:39:16 +00:00
|
|
|
{
|
2015-01-01 19:50:31 +00:00
|
|
|
mobj->frame = READUINT32(save_p);
|
2016-02-09 10:39:16 +00:00
|
|
|
mobj->anim_duration = READUINT16(save_p);
|
|
|
|
}
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
mobj->frame = mobj->state->frame;
|
|
|
|
mobj->anim_duration = (UINT16)mobj->state->var2;
|
|
|
|
}
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_EFLAGS)
|
2015-02-11 20:54:11 +00:00
|
|
|
mobj->eflags = READUINT16(save_p);
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_PLAYER)
|
|
|
|
{
|
|
|
|
i = READUINT8(save_p);
|
|
|
|
mobj->player = &players[i];
|
|
|
|
mobj->player->mo = mobj;
|
|
|
|
}
|
|
|
|
if (diff & MD_MOVEDIR)
|
|
|
|
mobj->movedir = READANGLE(save_p);
|
|
|
|
if (diff & MD_MOVECOUNT)
|
|
|
|
mobj->movecount = READINT32(save_p);
|
|
|
|
if (diff & MD_THRESHOLD)
|
|
|
|
mobj->threshold = READINT32(save_p);
|
|
|
|
if (diff & MD_LASTLOOK)
|
|
|
|
mobj->lastlook = READINT32(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->lastlook = -1;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_TARGET)
|
|
|
|
mobj->target = (mobj_t *)(size_t)READUINT32(save_p);
|
|
|
|
if (diff & MD_TRACER)
|
|
|
|
mobj->tracer = (mobj_t *)(size_t)READUINT32(save_p);
|
|
|
|
if (diff & MD_FRICTION)
|
|
|
|
mobj->friction = READFIXED(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->friction = ORIG_FRICTION;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_MOVEFACTOR)
|
|
|
|
mobj->movefactor = READFIXED(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->movefactor = FRACUNIT;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_FUSE)
|
|
|
|
mobj->fuse = READINT32(save_p);
|
|
|
|
if (diff & MD_WATERTOP)
|
|
|
|
mobj->watertop = READFIXED(save_p);
|
|
|
|
if (diff & MD_WATERBOTTOM)
|
|
|
|
mobj->waterbottom = READFIXED(save_p);
|
|
|
|
if (diff & MD_SCALE)
|
|
|
|
mobj->scale = READFIXED(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->scale = FRACUNIT;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff & MD_DSCALE)
|
|
|
|
mobj->destscale = READFIXED(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->destscale = mobj->scale;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff2 & MD2_SCALESPEED)
|
|
|
|
mobj->scalespeed = READFIXED(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->scalespeed = FRACUNIT/12;
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff2 & MD2_CUSVAL)
|
|
|
|
mobj->cusval = READINT32(save_p);
|
|
|
|
if (diff2 & MD2_CVMEM)
|
|
|
|
mobj->cvmem = READINT32(save_p);
|
|
|
|
if (diff2 & MD2_SKIN)
|
2021-08-09 18:57:07 +00:00
|
|
|
mobj->skin = skins[READUINT8(save_p)];
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff2 & MD2_COLOR)
|
2020-05-24 00:29:07 +00:00
|
|
|
mobj->color = READUINT16(save_p);
|
2015-01-01 19:50:31 +00:00
|
|
|
if (diff2 & MD2_EXTVAL1)
|
|
|
|
mobj->extravalue1 = READINT32(save_p);
|
|
|
|
if (diff2 & MD2_EXTVAL2)
|
|
|
|
mobj->extravalue2 = READINT32(save_p);
|
|
|
|
if (diff2 & MD2_HNEXT)
|
|
|
|
mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p);
|
|
|
|
if (diff2 & MD2_HPREV)
|
|
|
|
mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p);
|
2015-08-03 23:06:42 +00:00
|
|
|
if (diff2 & MD2_SLOPE)
|
|
|
|
mobj->standingslope = P_SlopeById(READUINT16(save_p));
|
2019-06-18 16:55:57 +00:00
|
|
|
if (diff2 & MD2_COLORIZED)
|
|
|
|
mobj->colorized = READUINT8(save_p);
|
2020-06-07 20:11:36 +00:00
|
|
|
if (diff2 & MD2_MIRRORED)
|
|
|
|
mobj->mirrored = READUINT8(save_p);
|
2020-10-30 06:15:49 +00:00
|
|
|
if (diff2 & MD2_SPRITEROLL)
|
|
|
|
mobj->spriteroll = READANGLE(save_p);
|
2020-10-14 03:57:13 +00:00
|
|
|
if (diff2 & MD2_SHADOWSCALE)
|
|
|
|
mobj->shadowscale = READFIXED(save_p);
|
|
|
|
if (diff2 & MD2_RENDERFLAGS)
|
|
|
|
mobj->renderflags = READUINT32(save_p);
|
2020-10-27 03:03:41 +00:00
|
|
|
if (diff2 & MD2_BLENDMODE)
|
|
|
|
mobj->blendmode = READINT32(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->blendmode = AST_TRANSLUCENT;
|
2020-10-12 03:13:22 +00:00
|
|
|
if (diff2 & MD2_SPRITEXSCALE)
|
|
|
|
mobj->spritexscale = READFIXED(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->spritexscale = FRACUNIT;
|
2020-10-12 03:13:22 +00:00
|
|
|
if (diff2 & MD2_SPRITEYSCALE)
|
|
|
|
mobj->spriteyscale = READFIXED(save_p);
|
2020-12-06 20:46:35 +00:00
|
|
|
else
|
|
|
|
mobj->spriteyscale = FRACUNIT;
|
2020-10-13 15:57:36 +00:00
|
|
|
if (diff2 & MD2_SPRITEXOFFSET)
|
|
|
|
mobj->spritexoffset = READFIXED(save_p);
|
|
|
|
if (diff2 & MD2_SPRITEYOFFSET)
|
|
|
|
mobj->spriteyoffset = READFIXED(save_p);
|
2020-10-14 03:57:13 +00:00
|
|
|
if (diff2 & MD2_FLOORSPRITESLOPE)
|
|
|
|
{
|
2020-10-14 16:07:02 +00:00
|
|
|
pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj);
|
2020-10-14 03:57:13 +00:00
|
|
|
|
|
|
|
slope->zdelta = READFIXED(save_p);
|
|
|
|
slope->zangle = READANGLE(save_p);
|
|
|
|
slope->xydirection = READANGLE(save_p);
|
|
|
|
|
|
|
|
slope->o.x = READFIXED(save_p);
|
|
|
|
slope->o.y = READFIXED(save_p);
|
|
|
|
slope->o.z = READFIXED(save_p);
|
|
|
|
|
|
|
|
slope->d.x = READFIXED(save_p);
|
|
|
|
slope->d.y = READFIXED(save_p);
|
|
|
|
|
|
|
|
slope->normal.x = READFIXED(save_p);
|
|
|
|
slope->normal.y = READFIXED(save_p);
|
|
|
|
slope->normal.z = READFIXED(save_p);
|
2024-01-30 17:29:38 +00:00
|
|
|
|
|
|
|
slope->moved = true;
|
2020-10-14 03:57:13 +00:00
|
|
|
}
|
2023-06-29 22:09:20 +00:00
|
|
|
if (diff2 & MD2_DRAWONLYFORPLAYER)
|
|
|
|
mobj->drawonlyforplayer = &players[READUINT8(save_p)];
|
|
|
|
if (diff2 & MD2_DONTDRAWFORVIEWMOBJ)
|
|
|
|
mobj->dontdrawforviewmobj = (mobj_t *)(size_t)READUINT32(save_p);
|
2022-01-13 07:53:26 +00:00
|
|
|
if (diff2 & MD2_DISPOFFSET)
|
|
|
|
mobj->dispoffset = READINT32(save_p);
|
|
|
|
else
|
|
|
|
mobj->dispoffset = mobj->info->dispoffset;
|
2023-10-30 02:34:18 +00:00
|
|
|
if (diff2 & MD2_TRANSLATION)
|
|
|
|
mobj->translation = READUINT16(save_p);
|
2024-02-25 01:04:48 +00:00
|
|
|
if (diff2 & MD2_ALPHA)
|
2024-03-01 21:29:39 +00:00
|
|
|
mobj->alpha = READFIXED(save_p);
|
2024-06-26 20:14:30 +00:00
|
|
|
else
|
|
|
|
mobj->alpha = FRACUNIT;
|
2015-01-01 19:50:31 +00:00
|
|
|
|
|
|
|
if (diff & MD_REDFLAG)
|
|
|
|
{
|
|
|
|
redflag = mobj;
|
|
|
|
rflagpoint = mobj->spawnpoint;
|
|
|
|
}
|
|
|
|
if (diff & MD_BLUEFLAG)
|
|
|
|
{
|
|
|
|
blueflag = mobj;
|
|
|
|
bflagpoint = mobj->spawnpoint;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set sprev, snext, bprev, bnext, subsector
|
|
|
|
P_SetThingPosition(mobj);
|
|
|
|
|
|
|
|
mobj->mobjnum = READUINT32(save_p);
|
|
|
|
|
|
|
|
if (mobj->player)
|
|
|
|
{
|
|
|
|
if (mobj->eflags & MFE_VERTICALFLIP)
|
|
|
|
mobj->player->viewz = mobj->z + mobj->height - mobj->player->viewheight;
|
|
|
|
else
|
|
|
|
mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight;
|
|
|
|
}
|
|
|
|
|
2022-11-12 23:20:03 +00:00
|
|
|
if (mobj->type == MT_SKYBOX && mobj->spawnpoint)
|
|
|
|
{
|
|
|
|
mtag_t tag = Tag_FGet(&mobj->spawnpoint->tags);
|
|
|
|
if (tag >= 0 && tag <= 15)
|
|
|
|
{
|
|
|
|
if (mobj->spawnpoint->args[0])
|
|
|
|
skyboxcenterpnts[tag] = mobj;
|
|
|
|
else
|
|
|
|
skyboxviewpnts[tag] = mobj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-01 19:50:31 +00:00
|
|
|
mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function
|
2019-04-20 20:37:19 +00:00
|
|
|
|
2022-04-23 18:13:58 +00:00
|
|
|
R_AddMobjInterpolator(mobj);
|
2022-04-23 17:49:54 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
return &mobj->thinker;
|
2015-01-01 19:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-04-18 07:21:04 +00:00
|
|
|
static thinker_t* LoadNoEnemiesThinker(actionf_p1 thinker)
|
|
|
|
{
|
|
|
|
noenemies_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sourceline = LoadLine(READUINT32(save_p));
|
|
|
|
return &ht->thinker;
|
|
|
|
}
|
|
|
|
|
2020-04-18 08:45:21 +00:00
|
|
|
static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker)
|
|
|
|
{
|
|
|
|
bouncecheese_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sourceline = LoadLine(READUINT32(save_p));
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->speed = READFIXED(save_p);
|
|
|
|
ht->distance = READFIXED(save_p);
|
|
|
|
ht->floorwasheight = READFIXED(save_p);
|
|
|
|
ht->ceilingwasheight = READFIXED(save_p);
|
|
|
|
ht->low = READCHAR(save_p);
|
2020-04-26 16:54:03 +00:00
|
|
|
|
|
|
|
if (ht->sector)
|
|
|
|
ht->sector->ceilingdata = ht;
|
|
|
|
|
2020-04-18 08:45:21 +00:00
|
|
|
return &ht->thinker;
|
|
|
|
}
|
|
|
|
|
2020-04-17 23:42:13 +00:00
|
|
|
static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2020-04-17 23:42:13 +00:00
|
|
|
continuousfall_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->speed = READFIXED(save_p);
|
|
|
|
ht->direction = READINT32(save_p);
|
|
|
|
ht->floorstartheight = READFIXED(save_p);
|
|
|
|
ht->ceilingstartheight = READFIXED(save_p);
|
|
|
|
ht->destheight = READFIXED(save_p);
|
2020-04-26 16:54:03 +00:00
|
|
|
|
|
|
|
if (ht->sector)
|
|
|
|
{
|
|
|
|
ht->sector->ceilingdata = ht;
|
|
|
|
ht->sector->floordata = ht;
|
|
|
|
}
|
|
|
|
|
2020-04-17 23:42:13 +00:00
|
|
|
return &ht->thinker;
|
|
|
|
}
|
|
|
|
|
2020-04-18 00:05:23 +00:00
|
|
|
static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker)
|
|
|
|
{
|
|
|
|
mariothink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->speed = READFIXED(save_p);
|
|
|
|
ht->direction = READINT32(save_p);
|
|
|
|
ht->floorstartheight = READFIXED(save_p);
|
|
|
|
ht->ceilingstartheight = READFIXED(save_p);
|
|
|
|
ht->tag = READINT16(save_p);
|
2020-04-26 16:54:03 +00:00
|
|
|
|
|
|
|
if (ht->sector)
|
|
|
|
{
|
|
|
|
ht->sector->ceilingdata = ht;
|
|
|
|
ht->sector->floordata = ht;
|
|
|
|
}
|
|
|
|
|
2020-04-18 00:05:23 +00:00
|
|
|
return &ht->thinker;
|
|
|
|
}
|
|
|
|
|
2020-04-18 09:05:58 +00:00
|
|
|
static thinker_t* LoadMarioCheckThinker(actionf_p1 thinker)
|
|
|
|
{
|
|
|
|
mariocheck_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
2014-03-15 16:59:03 +00:00
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sourceline = LoadLine(READUINT32(save_p));
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
2020-04-18 09:05:58 +00:00
|
|
|
return &ht->thinker;
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-04-18 08:26:03 +00:00
|
|
|
static thinker_t* LoadThwompThinker(actionf_p1 thinker)
|
|
|
|
{
|
|
|
|
thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sourceline = LoadLine(READUINT32(save_p));
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->crushspeed = READFIXED(save_p);
|
|
|
|
ht->retractspeed = READFIXED(save_p);
|
|
|
|
ht->direction = READINT32(save_p);
|
|
|
|
ht->floorstartheight = READFIXED(save_p);
|
|
|
|
ht->ceilingstartheight = READFIXED(save_p);
|
|
|
|
ht->delay = READINT32(save_p);
|
|
|
|
ht->tag = READINT16(save_p);
|
|
|
|
ht->sound = READUINT16(save_p);
|
2020-04-26 16:54:03 +00:00
|
|
|
|
|
|
|
if (ht->sector)
|
|
|
|
{
|
|
|
|
ht->sector->ceilingdata = ht;
|
|
|
|
ht->sector->floordata = ht;
|
|
|
|
}
|
|
|
|
|
2020-04-18 08:26:03 +00:00
|
|
|
return &ht->thinker;
|
|
|
|
}
|
|
|
|
|
2020-04-17 22:26:49 +00:00
|
|
|
static thinker_t* LoadFloatThinker(actionf_p1 thinker)
|
|
|
|
{
|
|
|
|
floatthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sourceline = LoadLine(READUINT32(save_p));
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->tag = READINT16(save_p);
|
|
|
|
return &ht->thinker;
|
|
|
|
}
|
|
|
|
|
2020-04-17 12:00:48 +00:00
|
|
|
static thinker_t* LoadEachTimeThinker(actionf_p1 thinker)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
eachtime_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sourceline = LoadLine(READUINT32(save_p));
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2020-04-17 12:00:48 +00:00
|
|
|
ht->playersInArea[i] = READCHAR(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2020-04-17 12:00:48 +00:00
|
|
|
ht->triggerOnExit = READCHAR(save_p);
|
|
|
|
return &ht->thinker;
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-04-17 07:58:53 +00:00
|
|
|
static thinker_t* LoadRaiseThinker(actionf_p1 thinker)
|
|
|
|
{
|
|
|
|
raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
2020-04-27 10:54:08 +00:00
|
|
|
ht->tag = READINT16(save_p);
|
2020-04-17 07:58:53 +00:00
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->ceilingbottom = READFIXED(save_p);
|
|
|
|
ht->ceilingtop = READFIXED(save_p);
|
|
|
|
ht->basespeed = READFIXED(save_p);
|
|
|
|
ht->extraspeed = READFIXED(save_p);
|
|
|
|
ht->shaketimer = READUINT8(save_p);
|
|
|
|
ht->flags = READUINT8(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static thinker_t* LoadCeilingThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
ceiling_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->type = READUINT8(save_p);
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->bottomheight = READFIXED(save_p);
|
|
|
|
ht->topheight = READFIXED(save_p);
|
|
|
|
ht->speed = READFIXED(save_p);
|
|
|
|
ht->delay = READFIXED(save_p);
|
|
|
|
ht->delaytimer = READFIXED(save_p);
|
|
|
|
ht->crush = READUINT8(save_p);
|
|
|
|
ht->texture = READINT32(save_p);
|
|
|
|
ht->direction = READINT32(save_p);
|
2021-06-26 13:28:28 +00:00
|
|
|
ht->tag = READINT16(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
ht->origspeed = READFIXED(save_p);
|
|
|
|
ht->sourceline = READFIXED(save_p);
|
|
|
|
if (ht->sector)
|
|
|
|
ht->sector->ceilingdata = ht;
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static thinker_t* LoadFloormoveThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
floormove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->type = READUINT8(save_p);
|
|
|
|
ht->crush = READUINT8(save_p);
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->direction = READINT32(save_p);
|
|
|
|
ht->texture = READINT32(save_p);
|
|
|
|
ht->floordestheight = READFIXED(save_p);
|
|
|
|
ht->speed = READFIXED(save_p);
|
|
|
|
ht->origspeed = READFIXED(save_p);
|
|
|
|
ht->delay = READFIXED(save_p);
|
|
|
|
ht->delaytimer = READFIXED(save_p);
|
2021-06-26 13:28:28 +00:00
|
|
|
ht->tag = READINT16(save_p);
|
2021-06-26 14:25:14 +00:00
|
|
|
ht->sourceline = READFIXED(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (ht->sector)
|
|
|
|
ht->sector->floordata = ht;
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static thinker_t* LoadLightflashThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
lightflash_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->maxlight = READINT32(save_p);
|
|
|
|
ht->minlight = READINT32(save_p);
|
|
|
|
if (ht->sector)
|
|
|
|
ht->sector->lightingdata = ht;
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static thinker_t* LoadStrobeThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
strobe_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->count = READINT32(save_p);
|
2021-09-19 14:25:27 +00:00
|
|
|
ht->minlight = READINT16(save_p);
|
|
|
|
ht->maxlight = READINT16(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
ht->darktime = READINT32(save_p);
|
|
|
|
ht->brighttime = READINT32(save_p);
|
|
|
|
if (ht->sector)
|
|
|
|
ht->sector->lightingdata = ht;
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static thinker_t* LoadGlowThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
2021-09-19 14:25:27 +00:00
|
|
|
ht->minlight = READINT16(save_p);
|
|
|
|
ht->maxlight = READINT16(save_p);
|
|
|
|
ht->direction = READINT16(save_p);
|
|
|
|
ht->speed = READINT16(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (ht->sector)
|
|
|
|
ht->sector->lightingdata = ht;
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2020-05-01 09:25:32 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static thinker_t* LoadFireflickerThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
fireflicker_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->count = READINT32(save_p);
|
|
|
|
ht->resetcount = READINT32(save_p);
|
2021-09-19 14:25:27 +00:00
|
|
|
ht->maxlight = READINT16(save_p);
|
|
|
|
ht->minlight = READINT16(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (ht->sector)
|
|
|
|
ht->sector->lightingdata = ht;
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2020-05-01 09:25:32 +00:00
|
|
|
|
2020-04-26 16:38:45 +00:00
|
|
|
static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->type = READUINT8(save_p);
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->actionsector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->direction = READINT32(save_p);
|
|
|
|
ht->floordestheight = READFIXED(save_p);
|
|
|
|
ht->ceilingdestheight = READFIXED(save_p);
|
|
|
|
ht->speed = READFIXED(save_p);
|
|
|
|
ht->origspeed = READFIXED(save_p);
|
|
|
|
ht->low = READFIXED(save_p);
|
|
|
|
ht->high = READFIXED(save_p);
|
|
|
|
ht->distance = READFIXED(save_p);
|
|
|
|
ht->delay = READFIXED(save_p);
|
|
|
|
ht->delaytimer = READFIXED(save_p);
|
|
|
|
ht->floorwasheight = READFIXED(save_p);
|
|
|
|
ht->ceilingwasheight = READFIXED(save_p);
|
|
|
|
ht->sourceline = LoadLine(READUINT32(save_p));
|
|
|
|
|
2020-04-26 16:38:45 +00:00
|
|
|
if (ht->sector && setplanedata)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2020-04-26 16:38:45 +00:00
|
|
|
ht->sector->ceilingdata = ht;
|
|
|
|
ht->sector->floordata = ht;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2020-04-26 09:55:10 +00:00
|
|
|
static thinker_t* LoadCrumbleThinker(actionf_p1 thinker)
|
|
|
|
{
|
|
|
|
crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
2020-04-26 14:51:14 +00:00
|
|
|
ht->sourceline = LoadLine(READUINT32(save_p));
|
2020-04-26 09:55:10 +00:00
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->actionsector = LoadSector(READUINT32(save_p));
|
2020-04-26 14:51:14 +00:00
|
|
|
ht->player = LoadPlayer(READUINT32(save_p));
|
2020-04-26 09:55:10 +00:00
|
|
|
ht->direction = READINT32(save_p);
|
2020-04-26 14:51:14 +00:00
|
|
|
ht->origalpha = READINT32(save_p);
|
|
|
|
ht->timer = READINT32(save_p);
|
2020-04-26 09:55:10 +00:00
|
|
|
ht->speed = READFIXED(save_p);
|
|
|
|
ht->floorwasheight = READFIXED(save_p);
|
|
|
|
ht->ceilingwasheight = READFIXED(save_p);
|
2020-04-26 14:51:14 +00:00
|
|
|
ht->flags = READUINT8(save_p);
|
2020-04-26 09:55:10 +00:00
|
|
|
|
|
|
|
if (ht->sector)
|
|
|
|
ht->sector->floordata = ht;
|
|
|
|
|
|
|
|
return &ht->thinker;
|
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static thinker_t* LoadScrollThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
scroll_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->dx = READFIXED(save_p);
|
|
|
|
ht->dy = READFIXED(save_p);
|
|
|
|
ht->affectee = READINT32(save_p);
|
|
|
|
ht->control = READINT32(save_p);
|
|
|
|
ht->last_height = READFIXED(save_p);
|
|
|
|
ht->vdx = READFIXED(save_p);
|
|
|
|
ht->vdy = READFIXED(save_p);
|
|
|
|
ht->accel = READINT32(save_p);
|
|
|
|
ht->exclusive = READINT32(save_p);
|
|
|
|
ht->type = READUINT8(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadFrictionThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->friction = READINT32(save_p);
|
|
|
|
ht->movefactor = READINT32(save_p);
|
|
|
|
ht->affectee = READINT32(save_p);
|
|
|
|
ht->referrer = READINT32(save_p);
|
|
|
|
ht->roverfriction = READUINT8(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static thinker_t* LoadPusherThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->type = READUINT8(save_p);
|
2021-07-01 18:05:23 +00:00
|
|
|
ht->x_mag = READFIXED(save_p);
|
|
|
|
ht->y_mag = READFIXED(save_p);
|
|
|
|
ht->z_mag = READFIXED(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
ht->affectee = READINT32(save_p);
|
|
|
|
ht->roverpusher = READUINT8(save_p);
|
|
|
|
ht->referrer = READINT32(save_p);
|
|
|
|
ht->exclusive = READINT32(save_p);
|
|
|
|
ht->slider = READINT32(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadLaserThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
2020-05-02 08:03:16 +00:00
|
|
|
ht->tag = READINT16(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
ht->sourceline = LoadLine(READUINT32(save_p));
|
2020-04-27 11:09:57 +00:00
|
|
|
ht->nobosses = READUINT8(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadLightlevelThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
2018-09-11 14:05:25 +00:00
|
|
|
ht->sourcelevel = READINT16(save_p);
|
|
|
|
ht->destlevel = READINT16(save_p);
|
2018-09-15 10:21:25 +00:00
|
|
|
ht->fixedcurlevel = READFIXED(save_p);
|
|
|
|
ht->fixedpertic = READFIXED(save_p);
|
2018-09-10 00:18:43 +00:00
|
|
|
ht->timer = READINT32(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
if (ht->sector)
|
|
|
|
ht->sector->lightingdata = ht;
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadExecutorThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->line = LoadLine(READUINT32(save_p));
|
|
|
|
ht->caller = LoadMobj(READUINT32(save_p));
|
2014-11-12 00:55:07 +00:00
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
2014-03-15 16:59:03 +00:00
|
|
|
ht->timer = READINT32(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadDisappearThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->appeartime = READUINT32(save_p);
|
|
|
|
ht->disappeartime = READUINT32(save_p);
|
|
|
|
ht->offset = READUINT32(save_p);
|
|
|
|
ht->timer = READUINT32(save_p);
|
|
|
|
ht->affectee = READINT32(save_p);
|
|
|
|
ht->sourceline = READINT32(save_p);
|
|
|
|
ht->exists = READINT32(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadFadeThinker(actionf_p1 thinker)
|
2018-03-30 19:27:37 +00:00
|
|
|
{
|
2018-09-15 05:04:15 +00:00
|
|
|
sector_t *ss;
|
2018-03-30 19:27:37 +00:00
|
|
|
fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
2018-09-17 04:34:03 +00:00
|
|
|
ht->dest_exc = GetNetColormapFromList(READUINT32(save_p));
|
2018-09-10 03:52:36 +00:00
|
|
|
ht->sectornum = READUINT32(save_p);
|
|
|
|
ht->ffloornum = READUINT32(save_p);
|
2018-08-17 20:27:32 +00:00
|
|
|
ht->alpha = READINT32(save_p);
|
2018-09-11 14:28:24 +00:00
|
|
|
ht->sourcevalue = READINT16(save_p);
|
2018-04-07 11:09:04 +00:00
|
|
|
ht->destvalue = READINT16(save_p);
|
2018-09-09 21:19:49 +00:00
|
|
|
ht->destlightlevel = READINT16(save_p);
|
2018-04-07 11:09:04 +00:00
|
|
|
ht->speed = READINT16(save_p);
|
2018-09-10 00:45:12 +00:00
|
|
|
ht->ticbased = (boolean)READUINT8(save_p);
|
|
|
|
ht->timer = READINT32(save_p);
|
2018-04-07 03:14:48 +00:00
|
|
|
ht->doexists = READUINT8(save_p);
|
|
|
|
ht->dotranslucent = READUINT8(save_p);
|
2018-09-09 00:41:45 +00:00
|
|
|
ht->dolighting = READUINT8(save_p);
|
2018-09-12 20:57:35 +00:00
|
|
|
ht->docolormap = READUINT8(save_p);
|
2018-09-09 21:19:49 +00:00
|
|
|
ht->docollision = READUINT8(save_p);
|
2018-08-14 14:18:08 +00:00
|
|
|
ht->doghostfade = READUINT8(save_p);
|
2018-08-17 19:13:05 +00:00
|
|
|
ht->exactalpha = READUINT8(save_p);
|
2018-03-31 04:40:41 +00:00
|
|
|
|
2018-09-15 05:04:15 +00:00
|
|
|
ss = LoadSector(ht->sectornum);
|
2018-08-17 06:28:52 +00:00
|
|
|
if (ss)
|
|
|
|
{
|
|
|
|
size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc
|
|
|
|
ffloor_t *rover;
|
|
|
|
for (rover = ss->ffloors; rover; rover = rover->next)
|
|
|
|
{
|
|
|
|
if (j == ht->ffloornum)
|
|
|
|
{
|
|
|
|
ht->rover = rover;
|
|
|
|
rover->fadingdata = ht;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2018-09-18 15:05:30 +00:00
|
|
|
}
|
2018-03-31 04:40:41 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadFadeColormapThinker(actionf_p1 thinker)
|
2018-09-12 13:06:38 +00:00
|
|
|
{
|
|
|
|
fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->sector = LoadSector(READUINT32(save_p));
|
2018-09-17 00:27:24 +00:00
|
|
|
ht->source_exc = GetNetColormapFromList(READUINT32(save_p));
|
|
|
|
ht->dest_exc = GetNetColormapFromList(READUINT32(save_p));
|
2018-09-13 14:38:15 +00:00
|
|
|
ht->ticbased = (boolean)READUINT8(save_p);
|
2018-09-12 13:06:38 +00:00
|
|
|
ht->duration = READINT32(save_p);
|
|
|
|
ht->timer = READINT32(save_p);
|
|
|
|
if (ht->sector)
|
|
|
|
ht->sector->fadecolormapdata = ht;
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2018-03-30 19:27:37 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker)
|
2017-01-20 20:17:40 +00:00
|
|
|
{
|
|
|
|
planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
2019-04-19 12:14:43 +00:00
|
|
|
|
2017-01-20 20:17:40 +00:00
|
|
|
ht->affectee = READINT32(save_p);
|
|
|
|
ht->control = READINT32(save_p);
|
|
|
|
ht->last_height = READFIXED(save_p);
|
|
|
|
ht->speed = READFIXED(save_p);
|
|
|
|
ht->type = READUINT8(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2017-01-20 20:17:40 +00:00
|
|
|
}
|
|
|
|
|
2021-12-29 12:53:38 +00:00
|
|
|
static inline thinker_t* LoadDynamicLineSlopeThinker(actionf_p1 thinker)
|
2019-04-19 12:14:43 +00:00
|
|
|
{
|
2021-12-29 12:53:38 +00:00
|
|
|
dynlineplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL);
|
2019-04-19 12:14:43 +00:00
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
|
|
|
|
ht->type = READUINT8(save_p);
|
|
|
|
ht->slope = LoadSlope(READUINT32(save_p));
|
|
|
|
ht->sourceline = LoadLine(READUINT32(save_p));
|
|
|
|
ht->extent = READFIXED(save_p);
|
2021-12-29 12:53:38 +00:00
|
|
|
return &ht->thinker;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline thinker_t* LoadDynamicVertexSlopeThinker(actionf_p1 thinker)
|
|
|
|
{
|
2021-12-29 14:29:59 +00:00
|
|
|
size_t i;
|
2021-12-29 12:53:38 +00:00
|
|
|
dynvertexplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
|
|
|
|
ht->slope = LoadSlope(READUINT32(save_p));
|
2021-12-29 14:29:59 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
ht->secs[i] = LoadSector(READUINT32(save_p));
|
2019-04-19 12:14:43 +00:00
|
|
|
READMEM(save_p, ht->vex, sizeof(ht->vex));
|
2021-12-29 14:29:59 +00:00
|
|
|
READMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights));
|
|
|
|
READMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights));
|
|
|
|
ht->relative = READUINT8(save_p);
|
2019-04-21 09:45:59 +00:00
|
|
|
return &ht->thinker;
|
2017-01-20 20:17:40 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->polyObjNum = READINT32(save_p);
|
|
|
|
ht->speed = READINT32(save_p);
|
|
|
|
ht->distance = READINT32(save_p);
|
2020-06-04 20:31:26 +00:00
|
|
|
ht->turnobjs = READUINT8(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static thinker_t* LoadPolymoveThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
polymove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->polyObjNum = READINT32(save_p);
|
|
|
|
ht->speed = READINT32(save_p);
|
|
|
|
ht->momx = READFIXED(save_p);
|
|
|
|
ht->momy = READFIXED(save_p);
|
|
|
|
ht->distance = READINT32(save_p);
|
|
|
|
ht->angle = READANGLE(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->polyObjNum = READINT32(save_p);
|
|
|
|
ht->speed = READINT32(save_p);
|
|
|
|
ht->sequence = READINT32(save_p);
|
|
|
|
ht->pointnum = READINT32(save_p);
|
|
|
|
ht->direction = READINT32(save_p);
|
2020-05-13 14:21:47 +00:00
|
|
|
ht->returnbehavior = READUINT8(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
ht->continuous = READUINT8(save_p);
|
|
|
|
ht->stophere = READUINT8(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadPolyslidedoorThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->polyObjNum = READINT32(save_p);
|
|
|
|
ht->delay = READINT32(save_p);
|
|
|
|
ht->delayCount = READINT32(save_p);
|
|
|
|
ht->initSpeed = READINT32(save_p);
|
|
|
|
ht->speed = READINT32(save_p);
|
|
|
|
ht->initDistance = READINT32(save_p);
|
|
|
|
ht->distance = READINT32(save_p);
|
|
|
|
ht->initAngle = READUINT32(save_p);
|
|
|
|
ht->angle = READUINT32(save_p);
|
|
|
|
ht->revAngle = READUINT32(save_p);
|
|
|
|
ht->momx = READFIXED(save_p);
|
|
|
|
ht->momy = READFIXED(save_p);
|
|
|
|
ht->closing = READUINT8(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadPolyswingdoorThinker(actionf_p1 thinker)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->polyObjNum = READINT32(save_p);
|
|
|
|
ht->delay = READINT32(save_p);
|
|
|
|
ht->delayCount = READINT32(save_p);
|
|
|
|
ht->initSpeed = READINT32(save_p);
|
|
|
|
ht->speed = READINT32(save_p);
|
|
|
|
ht->initDistance = READINT32(save_p);
|
|
|
|
ht->distance = READINT32(save_p);
|
|
|
|
ht->closing = READUINT8(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2014-11-12 00:55:07 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadPolydisplaceThinker(actionf_p1 thinker)
|
2014-11-12 00:55:07 +00:00
|
|
|
{
|
|
|
|
polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->polyObjNum = READINT32(save_p);
|
|
|
|
ht->controlSector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->dx = READFIXED(save_p);
|
|
|
|
ht->dy = READFIXED(save_p);
|
|
|
|
ht->oldHeights = READFIXED(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2014-11-12 00:55:07 +00:00
|
|
|
}
|
2018-09-07 19:27:18 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static inline thinker_t* LoadPolyrotdisplaceThinker(actionf_p1 thinker)
|
2019-04-05 09:50:59 +00:00
|
|
|
{
|
|
|
|
polyrotdisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->polyObjNum = READINT32(save_p);
|
|
|
|
ht->controlSector = LoadSector(READUINT32(save_p));
|
|
|
|
ht->rotscale = READFIXED(save_p);
|
|
|
|
ht->turnobjs = READUINT8(save_p);
|
|
|
|
ht->oldHeights = READFIXED(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2019-04-05 09:50:59 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
static thinker_t* LoadPolyfadeThinker(actionf_p1 thinker)
|
2018-09-07 19:27:18 +00:00
|
|
|
{
|
|
|
|
polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
|
|
|
ht->thinker.function.acp1 = thinker;
|
|
|
|
ht->polyObjNum = READINT32(save_p);
|
2018-09-13 04:04:50 +00:00
|
|
|
ht->sourcevalue = READINT32(save_p);
|
2018-09-09 05:08:02 +00:00
|
|
|
ht->destvalue = READINT32(save_p);
|
|
|
|
ht->docollision = (boolean)READUINT8(save_p);
|
|
|
|
ht->doghostfade = (boolean)READUINT8(save_p);
|
2018-09-13 04:04:50 +00:00
|
|
|
ht->ticbased = (boolean)READUINT8(save_p);
|
2018-09-16 00:00:04 +00:00
|
|
|
ht->duration = READINT32(save_p);
|
2018-09-10 01:01:00 +00:00
|
|
|
ht->timer = READINT32(save_p);
|
2019-04-20 20:37:19 +00:00
|
|
|
return &ht->thinker;
|
2018-09-07 19:27:18 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
static void P_NetUnArchiveThinkers(void)
|
|
|
|
{
|
|
|
|
thinker_t *currentthinker;
|
|
|
|
thinker_t *next;
|
|
|
|
UINT8 tclass;
|
|
|
|
UINT8 restoreNum = false;
|
2017-01-03 18:47:46 +00:00
|
|
|
UINT32 i;
|
2017-06-12 16:55:15 +00:00
|
|
|
UINT32 numloaded = 0;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
if (READUINT32(save_p) != ARCHIVEBLOCK_THINKERS)
|
|
|
|
I_Error("Bad $$$.sav at archive block Thinkers");
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// remove all the current thinkers
|
2019-04-20 20:37:19 +00:00
|
|
|
for (i = 0; i < NUM_THINKERLISTS; i++)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2019-04-20 20:37:19 +00:00
|
|
|
currentthinker = thlist[i].next;
|
|
|
|
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = next)
|
|
|
|
{
|
|
|
|
next = currentthinker->next;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2022-11-12 23:20:03 +00:00
|
|
|
if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker || currentthinker->function.acp1 == (actionf_p1)P_NullPrecipThinker)
|
2019-04-20 20:37:19 +00:00
|
|
|
P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it
|
|
|
|
else
|
2022-11-12 23:20:03 +00:00
|
|
|
{
|
|
|
|
(next->prev = currentthinker->prev)->next = next;
|
|
|
|
R_DestroyLevelInterpolators(currentthinker);
|
2019-04-20 20:37:19 +00:00
|
|
|
Z_Free(currentthinker);
|
2022-11-12 23:20:03 +00:00
|
|
|
}
|
2019-04-20 20:37:19 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// we don't want the removed mobjs to come back
|
|
|
|
iquetail = iquehead = 0;
|
|
|
|
P_InitThinkers();
|
|
|
|
|
2017-01-03 18:47:46 +00:00
|
|
|
// clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity
|
|
|
|
for (i = 0; i < numsectors; i++)
|
|
|
|
{
|
2018-09-12 13:06:38 +00:00
|
|
|
sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = sectors[i].fadecolormapdata = NULL;
|
2018-08-17 04:32:20 +00:00
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// read in saved thinkers
|
2019-04-20 20:37:19 +00:00
|
|
|
for (i = 0; i < NUM_THINKERLISTS; i++)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2019-04-20 20:37:19 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
2019-07-29 23:02:45 +00:00
|
|
|
thinker_t* th = NULL;
|
2019-04-20 20:37:19 +00:00
|
|
|
tclass = READUINT8(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
if (tclass == tc_end)
|
|
|
|
break; // leave the saved thinker reading loop
|
|
|
|
numloaded++;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
switch (tclass)
|
|
|
|
{
|
|
|
|
case tc_mobj:
|
|
|
|
th = LoadMobjThinker((actionf_p1)P_MobjThinker);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_ceiling:
|
|
|
|
th = LoadCeilingThinker((actionf_p1)T_MoveCeiling);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_crushceiling:
|
|
|
|
th = LoadCeilingThinker((actionf_p1)T_CrushCeiling);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_floor:
|
|
|
|
th = LoadFloormoveThinker((actionf_p1)T_MoveFloor);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_flash:
|
|
|
|
th = LoadLightflashThinker((actionf_p1)T_LightningFlash);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_strobe:
|
|
|
|
th = LoadStrobeThinker((actionf_p1)T_StrobeFlash);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_glow:
|
|
|
|
th = LoadGlowThinker((actionf_p1)T_Glow);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_fireflicker:
|
|
|
|
th = LoadFireflickerThinker((actionf_p1)T_FireFlicker);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_elevator:
|
2020-04-26 16:38:45 +00:00
|
|
|
th = LoadElevatorThinker((actionf_p1)T_MoveElevator, true);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_continuousfalling:
|
2020-04-17 23:42:13 +00:00
|
|
|
th = LoadContinuousFallThinker((actionf_p1)T_ContinuousFalling);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_thwomp:
|
2020-04-18 08:26:03 +00:00
|
|
|
th = LoadThwompThinker((actionf_p1)T_ThwompSector);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_noenemies:
|
2020-04-18 07:21:04 +00:00
|
|
|
th = LoadNoEnemiesThinker((actionf_p1)T_NoEnemiesSector);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_eachtime:
|
2020-04-17 12:00:48 +00:00
|
|
|
th = LoadEachTimeThinker((actionf_p1)T_EachTimeThinker);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_raisesector:
|
2020-04-17 07:58:53 +00:00
|
|
|
th = LoadRaiseThinker((actionf_p1)T_RaiseSector);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_camerascanner:
|
2020-04-26 16:38:45 +00:00
|
|
|
th = LoadElevatorThinker((actionf_p1)T_CameraScanner, false);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_bouncecheese:
|
2020-04-18 08:45:21 +00:00
|
|
|
th = LoadBounceCheeseThinker((actionf_p1)T_BounceCheese);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_startcrumble:
|
2020-04-26 09:55:10 +00:00
|
|
|
th = LoadCrumbleThinker((actionf_p1)T_StartCrumble);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_marioblock:
|
2020-04-18 00:05:23 +00:00
|
|
|
th = LoadMarioBlockThinker((actionf_p1)T_MarioBlock);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_marioblockchecker:
|
2020-04-18 09:05:58 +00:00
|
|
|
th = LoadMarioCheckThinker((actionf_p1)T_MarioBlockChecker);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_floatsector:
|
2020-04-17 22:26:49 +00:00
|
|
|
th = LoadFloatThinker((actionf_p1)T_FloatSector);
|
2019-04-20 20:37:19 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_laserflash:
|
|
|
|
th = LoadLaserThinker((actionf_p1)T_LaserFlash);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_lightfade:
|
|
|
|
th = LoadLightlevelThinker((actionf_p1)T_LightFade);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_executor:
|
|
|
|
th = LoadExecutorThinker((actionf_p1)T_ExecutorDelay);
|
|
|
|
restoreNum = true;
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_disappear:
|
|
|
|
th = LoadDisappearThinker((actionf_p1)T_Disappear);
|
|
|
|
break;
|
2017-01-20 20:17:40 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_fade:
|
|
|
|
th = LoadFadeThinker((actionf_p1)T_Fade);
|
|
|
|
break;
|
2018-03-30 19:27:37 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_fadecolormap:
|
|
|
|
th = LoadFadeColormapThinker((actionf_p1)T_FadeColormap);
|
|
|
|
break;
|
2018-09-12 13:06:38 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_planedisplace:
|
|
|
|
th = LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace);
|
|
|
|
break;
|
|
|
|
case tc_polyrotate:
|
|
|
|
th = LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_polymove:
|
|
|
|
th = LoadPolymoveThinker((actionf_p1)T_PolyObjMove);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_polywaypoint:
|
|
|
|
th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_polyslidedoor:
|
|
|
|
th = LoadPolyslidedoorThinker((actionf_p1)T_PolyDoorSlide);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_polyswingdoor:
|
|
|
|
th = LoadPolyswingdoorThinker((actionf_p1)T_PolyDoorSwing);
|
|
|
|
break;
|
2014-11-12 00:55:07 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_polyflag:
|
|
|
|
th = LoadPolymoveThinker((actionf_p1)T_PolyObjFlag);
|
|
|
|
break;
|
2014-11-12 00:55:07 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_polydisplace:
|
|
|
|
th = LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace);
|
|
|
|
break;
|
2018-09-07 19:27:18 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_polyrotdisplace:
|
|
|
|
th = LoadPolyrotdisplaceThinker((actionf_p1)T_PolyObjRotDisplace);
|
|
|
|
break;
|
2019-04-05 09:50:59 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_polyfade:
|
|
|
|
th = LoadPolyfadeThinker((actionf_p1)T_PolyObjFade);
|
|
|
|
break;
|
2020-03-20 17:55:29 +00:00
|
|
|
|
2019-04-21 09:45:59 +00:00
|
|
|
case tc_dynslopeline:
|
2021-12-29 12:53:38 +00:00
|
|
|
th = LoadDynamicLineSlopeThinker((actionf_p1)T_DynamicSlopeLine);
|
2019-04-21 09:45:59 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-21 09:45:59 +00:00
|
|
|
case tc_dynslopevert:
|
2021-12-29 12:53:38 +00:00
|
|
|
th = LoadDynamicVertexSlopeThinker((actionf_p1)T_DynamicSlopeVert);
|
2019-04-21 09:45:59 +00:00
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_scroll:
|
|
|
|
th = LoadScrollThinker((actionf_p1)T_Scroll);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_friction:
|
|
|
|
th = LoadFrictionThinker((actionf_p1)T_Friction);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
case tc_pusher:
|
|
|
|
th = LoadPusherThinker((actionf_p1)T_Pusher);
|
|
|
|
break;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-20 20:37:19 +00:00
|
|
|
default:
|
|
|
|
I_Error("P_UnarchiveSpecials: Unknown tclass %d in savegame", tclass);
|
|
|
|
}
|
|
|
|
if (th)
|
|
|
|
P_AddThinker(i, th);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2019-07-12 23:42:03 +00:00
|
|
|
CONS_Debug(DBG_NETPLAY, "%u thinkers loaded in list %d\n", numloaded, i);
|
|
|
|
}
|
2017-06-12 16:55:15 +00:00
|
|
|
|
2022-11-12 23:20:03 +00:00
|
|
|
// Set each skyboxmo to the first skybox (or NULL)
|
|
|
|
skyboxmo[0] = skyboxviewpnts[0];
|
|
|
|
skyboxmo[1] = skyboxcenterpnts[0];
|
|
|
|
|
2019-07-12 23:42:03 +00:00
|
|
|
if (restoreNum)
|
|
|
|
{
|
|
|
|
executor_t *delay = NULL;
|
|
|
|
UINT32 mobjnum;
|
2019-12-27 19:10:14 +00:00
|
|
|
for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2019-07-12 23:42:03 +00:00
|
|
|
if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay)
|
|
|
|
continue;
|
|
|
|
delay = (void *)currentthinker;
|
|
|
|
if (!(mobjnum = (UINT32)(size_t)delay->caller))
|
|
|
|
continue;
|
|
|
|
delay->caller = P_FindNewPosition(mobjnum);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// haleyjd 03/26/06: PolyObject saving code
|
|
|
|
//
|
2014-11-12 00:55:07 +00:00
|
|
|
#define PD_FLAGS 0x01
|
|
|
|
#define PD_TRANS 0x02
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
static inline void P_ArchivePolyObj(polyobj_t *po)
|
|
|
|
{
|
2014-11-12 00:55:07 +00:00
|
|
|
UINT8 diff = 0;
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEINT32(save_p, po->id);
|
|
|
|
WRITEANGLE(save_p, po->angle);
|
|
|
|
|
|
|
|
WRITEFIXED(save_p, po->spawnSpot.x);
|
|
|
|
WRITEFIXED(save_p, po->spawnSpot.y);
|
2014-11-12 00:55:07 +00:00
|
|
|
|
|
|
|
if (po->flags != po->spawnflags)
|
|
|
|
diff |= PD_FLAGS;
|
2015-01-22 19:24:40 +00:00
|
|
|
if (po->translucency != po->spawntrans)
|
2014-11-12 00:55:07 +00:00
|
|
|
diff |= PD_TRANS;
|
|
|
|
|
|
|
|
WRITEUINT8(save_p, diff);
|
|
|
|
|
|
|
|
if (diff & PD_FLAGS)
|
|
|
|
WRITEINT32(save_p, po->flags);
|
|
|
|
if (diff & PD_TRANS)
|
|
|
|
WRITEINT32(save_p, po->translucency);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void P_UnArchivePolyObj(polyobj_t *po)
|
|
|
|
{
|
|
|
|
INT32 id;
|
|
|
|
UINT32 angle;
|
|
|
|
fixed_t x, y;
|
2014-11-12 00:55:07 +00:00
|
|
|
UINT8 diff;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
// nullify all polyobject thinker pointers;
|
|
|
|
// the thinkers themselves will fight over who gets the field
|
|
|
|
// when they first start to run.
|
|
|
|
po->thinker = NULL;
|
|
|
|
|
|
|
|
id = READINT32(save_p);
|
|
|
|
|
|
|
|
angle = READANGLE(save_p);
|
|
|
|
|
|
|
|
x = READFIXED(save_p);
|
|
|
|
y = READFIXED(save_p);
|
|
|
|
|
2014-11-12 00:55:07 +00:00
|
|
|
diff = READUINT8(save_p);
|
|
|
|
|
|
|
|
if (diff & PD_FLAGS)
|
|
|
|
po->flags = READINT32(save_p);
|
|
|
|
if (diff & PD_TRANS)
|
|
|
|
po->translucency = READINT32(save_p);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// if the object is bad or isn't in the id hash, we can do nothing more
|
|
|
|
// with it, so return now
|
|
|
|
if (po->isBad || po != Polyobj_GetForNum(id))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// rotate and translate polyobject
|
|
|
|
Polyobj_MoveOnLoad(po, angle, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void P_ArchivePolyObjects(void)
|
|
|
|
{
|
|
|
|
INT32 i;
|
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
WRITEUINT32(save_p, ARCHIVEBLOCK_POBJS);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// save number of polyobjects
|
|
|
|
WRITEINT32(save_p, numPolyObjects);
|
|
|
|
|
|
|
|
for (i = 0; i < numPolyObjects; ++i)
|
|
|
|
P_ArchivePolyObj(&PolyObjects[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void P_UnArchivePolyObjects(void)
|
|
|
|
{
|
|
|
|
INT32 i, numSavedPolys;
|
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
if (READUINT32(save_p) != ARCHIVEBLOCK_POBJS)
|
|
|
|
I_Error("Bad $$$.sav at archive block Pobjs");
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
numSavedPolys = READINT32(save_p);
|
|
|
|
|
|
|
|
if (numSavedPolys != numPolyObjects)
|
|
|
|
I_Error("P_UnArchivePolyObjects: polyobj count inconsistency\n");
|
|
|
|
|
|
|
|
for (i = 0; i < numSavedPolys; ++i)
|
|
|
|
P_UnArchivePolyObj(&PolyObjects[i]);
|
|
|
|
}
|
2020-05-01 09:25:32 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
static inline void P_FinishMobjs(void)
|
|
|
|
{
|
|
|
|
thinker_t *currentthinker;
|
|
|
|
mobj_t *mobj;
|
|
|
|
|
|
|
|
// put info field there real value
|
2019-04-20 21:29:20 +00:00
|
|
|
for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ];
|
2014-03-15 16:59:03 +00:00
|
|
|
currentthinker = currentthinker->next)
|
|
|
|
{
|
2019-07-12 23:42:03 +00:00
|
|
|
if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
|
|
|
continue;
|
|
|
|
|
2019-04-21 14:39:57 +00:00
|
|
|
mobj = (mobj_t *)currentthinker;
|
|
|
|
mobj->info = &mobjinfo[mobj->type];
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void P_RelinkPointers(void)
|
|
|
|
{
|
|
|
|
thinker_t *currentthinker;
|
|
|
|
mobj_t *mobj;
|
|
|
|
UINT32 temp;
|
|
|
|
|
|
|
|
// use info field (value = oldposition) to relink mobjs
|
2019-04-20 21:29:20 +00:00
|
|
|
for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ];
|
2014-03-15 16:59:03 +00:00
|
|
|
currentthinker = currentthinker->next)
|
|
|
|
{
|
2019-07-12 23:42:03 +00:00
|
|
|
if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
|
|
|
continue;
|
|
|
|
|
2019-04-21 14:39:57 +00:00
|
|
|
mobj = (mobj_t *)currentthinker;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-04-21 14:39:57 +00:00
|
|
|
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER)
|
|
|
|
continue;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2023-06-29 22:09:20 +00:00
|
|
|
if (mobj->dontdrawforviewmobj)
|
|
|
|
{
|
|
|
|
temp = (UINT32)(size_t)mobj->dontdrawforviewmobj;
|
|
|
|
mobj->dontdrawforviewmobj = NULL;
|
|
|
|
if (!P_SetTarget(&mobj->dontdrawforviewmobj, P_FindNewPosition(temp)))
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "dontdrawforviewmobj not found on %d\n", mobj->type);
|
|
|
|
}
|
2019-04-21 14:39:57 +00:00
|
|
|
if (mobj->tracer)
|
|
|
|
{
|
|
|
|
temp = (UINT32)(size_t)mobj->tracer;
|
|
|
|
mobj->tracer = NULL;
|
|
|
|
if (!P_SetTarget(&mobj->tracer, P_FindNewPosition(temp)))
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "tracer not found on %d\n", mobj->type);
|
|
|
|
}
|
|
|
|
if (mobj->target)
|
|
|
|
{
|
|
|
|
temp = (UINT32)(size_t)mobj->target;
|
|
|
|
mobj->target = NULL;
|
|
|
|
if (!P_SetTarget(&mobj->target, P_FindNewPosition(temp)))
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "target not found on %d\n", mobj->type);
|
|
|
|
}
|
|
|
|
if (mobj->hnext)
|
|
|
|
{
|
|
|
|
temp = (UINT32)(size_t)mobj->hnext;
|
|
|
|
mobj->hnext = NULL;
|
|
|
|
if (!(mobj->hnext = P_FindNewPosition(temp)))
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "hnext not found on %d\n", mobj->type);
|
|
|
|
}
|
|
|
|
if (mobj->hprev)
|
|
|
|
{
|
|
|
|
temp = (UINT32)(size_t)mobj->hprev;
|
|
|
|
mobj->hprev = NULL;
|
|
|
|
if (!(mobj->hprev = P_FindNewPosition(temp)))
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "hprev not found on %d\n", mobj->type);
|
|
|
|
}
|
|
|
|
if (mobj->player && mobj->player->capsule)
|
|
|
|
{
|
|
|
|
temp = (UINT32)(size_t)mobj->player->capsule;
|
|
|
|
mobj->player->capsule = NULL;
|
|
|
|
if (!P_SetTarget(&mobj->player->capsule, P_FindNewPosition(temp)))
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "capsule not found on %d\n", mobj->type);
|
|
|
|
}
|
|
|
|
if (mobj->player && mobj->player->axis1)
|
|
|
|
{
|
|
|
|
temp = (UINT32)(size_t)mobj->player->axis1;
|
|
|
|
mobj->player->axis1 = NULL;
|
|
|
|
if (!P_SetTarget(&mobj->player->axis1, P_FindNewPosition(temp)))
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "axis1 not found on %d\n", mobj->type);
|
|
|
|
}
|
|
|
|
if (mobj->player && mobj->player->axis2)
|
|
|
|
{
|
|
|
|
temp = (UINT32)(size_t)mobj->player->axis2;
|
|
|
|
mobj->player->axis2 = NULL;
|
|
|
|
if (!P_SetTarget(&mobj->player->axis2, P_FindNewPosition(temp)))
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "axis2 not found on %d\n", mobj->type);
|
|
|
|
}
|
|
|
|
if (mobj->player && mobj->player->awayviewmobj)
|
|
|
|
{
|
|
|
|
temp = (UINT32)(size_t)mobj->player->awayviewmobj;
|
|
|
|
mobj->player->awayviewmobj = NULL;
|
|
|
|
if (!P_SetTarget(&mobj->player->awayviewmobj, P_FindNewPosition(temp)))
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type);
|
|
|
|
}
|
|
|
|
if (mobj->player && mobj->player->followmobj)
|
|
|
|
{
|
|
|
|
temp = (UINT32)(size_t)mobj->player->followmobj;
|
|
|
|
mobj->player->followmobj = NULL;
|
|
|
|
if (!P_SetTarget(&mobj->player->followmobj, P_FindNewPosition(temp)))
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "followmobj not found on %d\n", mobj->type);
|
|
|
|
}
|
|
|
|
if (mobj->player && mobj->player->drone)
|
|
|
|
{
|
|
|
|
temp = (UINT32)(size_t)mobj->player->drone;
|
|
|
|
mobj->player->drone = NULL;
|
|
|
|
if (!P_SetTarget(&mobj->player->drone, P_FindNewPosition(temp)))
|
|
|
|
CONS_Debug(DBG_GAMELOGIC, "drone not found on %d\n", mobj->type);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void P_NetArchiveSpecials(void)
|
|
|
|
{
|
|
|
|
size_t i, z;
|
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
WRITEUINT32(save_p, ARCHIVEBLOCK_SPECIALS);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// itemrespawn queue for deathmatch
|
|
|
|
i = iquetail;
|
|
|
|
while (iquehead != i)
|
|
|
|
{
|
|
|
|
for (z = 0; z < nummapthings; z++)
|
|
|
|
{
|
|
|
|
if (&mapthings[z] == itemrespawnque[i])
|
|
|
|
{
|
|
|
|
WRITEUINT32(save_p, z);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
WRITEUINT32(save_p, itemrespawntime[i]);
|
|
|
|
i = (i + 1) & (ITEMQUESIZE-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// end delimiter
|
|
|
|
WRITEUINT32(save_p, 0xffffffff);
|
|
|
|
|
|
|
|
// Sky number
|
|
|
|
WRITEINT32(save_p, globallevelskynum);
|
|
|
|
|
|
|
|
// Current global weather type
|
|
|
|
WRITEUINT8(save_p, globalweather);
|
2014-11-12 00:55:07 +00:00
|
|
|
|
|
|
|
if (metalplayback) // Is metal sonic running?
|
|
|
|
{
|
|
|
|
WRITEUINT8(save_p, 0x01);
|
|
|
|
G_SaveMetal(&save_p);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
WRITEUINT8(save_p, 0x00);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void P_NetUnArchiveSpecials(void)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
INT32 j;
|
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
if (READUINT32(save_p) != ARCHIVEBLOCK_SPECIALS)
|
|
|
|
I_Error("Bad $$$.sav at archive block Specials");
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// BP: added save itemrespawn queue for deathmatch
|
|
|
|
iquetail = iquehead = 0;
|
|
|
|
while ((i = READUINT32(save_p)) != 0xffffffff)
|
|
|
|
{
|
|
|
|
itemrespawnque[iquehead] = &mapthings[i];
|
|
|
|
itemrespawntime[iquehead++] = READINT32(save_p);
|
|
|
|
}
|
|
|
|
|
|
|
|
j = READINT32(save_p);
|
|
|
|
if (j != globallevelskynum)
|
|
|
|
P_SetupLevelSky(j, true);
|
|
|
|
|
|
|
|
globalweather = READUINT8(save_p);
|
|
|
|
|
|
|
|
if (globalweather)
|
|
|
|
{
|
|
|
|
if (curWeather == globalweather)
|
|
|
|
curWeather = PRECIP_NONE;
|
|
|
|
|
|
|
|
P_SwitchWeather(globalweather);
|
|
|
|
}
|
|
|
|
else // PRECIP_NONE
|
|
|
|
{
|
|
|
|
if (curWeather != PRECIP_NONE)
|
|
|
|
P_SwitchWeather(globalweather);
|
|
|
|
}
|
2014-11-12 00:55:07 +00:00
|
|
|
|
|
|
|
if (READUINT8(save_p) == 0x01) // metal sonic
|
|
|
|
G_LoadMetal(&save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// =======================================================================
|
|
|
|
// Misc
|
|
|
|
// =======================================================================
|
Special saves!
All this refactoring, just to resolve #162. Specifically, it engages savegame events not at level load (except for savefile start) but on level completion, just after you've gotten all the intermission bonuses but before the intermission actually starts.
Also fixes a never-before-discovered bug where if the titlemap has LF_SAVEGAME, your save file will be overwritten upon returning to the title screen. This game is a mess of hacks, I swear...
One unintended side effect: It may actually be faster in some speedrun circumstances in mods with cutscenes to complete the map, exit back to the title screen, and reload the file. It's a common feature of optimal runs in games with cutscenes, though, and Marathon Run has a toggle for cutscenes, so I'm not particularly bothered.
2020-06-22 18:00:47 +00:00
|
|
|
static inline void P_ArchiveMisc(INT16 mapnum)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
Special saves!
All this refactoring, just to resolve #162. Specifically, it engages savegame events not at level load (except for savefile start) but on level completion, just after you've gotten all the intermission bonuses but before the intermission actually starts.
Also fixes a never-before-discovered bug where if the titlemap has LF_SAVEGAME, your save file will be overwritten upon returning to the title screen. This game is a mess of hacks, I swear...
One unintended side effect: It may actually be faster in some speedrun circumstances in mods with cutscenes to complete the map, exit back to the title screen, and reload the file. It's a common feature of optimal runs in games with cutscenes, though, and Marathon Run has a toggle for cutscenes, so I'm not particularly bothered.
2020-06-22 18:00:47 +00:00
|
|
|
//lastmapsaved = mapnum;
|
|
|
|
lastmaploaded = mapnum;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
Special saves!
All this refactoring, just to resolve #162. Specifically, it engages savegame events not at level load (except for savefile start) but on level completion, just after you've gotten all the intermission bonuses but before the intermission actually starts.
Also fixes a never-before-discovered bug where if the titlemap has LF_SAVEGAME, your save file will be overwritten upon returning to the title screen. This game is a mess of hacks, I swear...
One unintended side effect: It may actually be faster in some speedrun circumstances in mods with cutscenes to complete the map, exit back to the title screen, and reload the file. It's a common feature of optimal runs in games with cutscenes, though, and Marathon Run has a toggle for cutscenes, so I'm not particularly bothered.
2020-06-22 18:00:47 +00:00
|
|
|
if (gamecomplete)
|
|
|
|
mapnum |= 8192;
|
2017-08-07 03:47:39 +00:00
|
|
|
|
Special saves!
All this refactoring, just to resolve #162. Specifically, it engages savegame events not at level load (except for savefile start) but on level completion, just after you've gotten all the intermission bonuses but before the intermission actually starts.
Also fixes a never-before-discovered bug where if the titlemap has LF_SAVEGAME, your save file will be overwritten upon returning to the title screen. This game is a mess of hacks, I swear...
One unintended side effect: It may actually be faster in some speedrun circumstances in mods with cutscenes to complete the map, exit back to the title screen, and reload the file. It's a common feature of optimal runs in games with cutscenes, though, and Marathon Run has a toggle for cutscenes, so I'm not particularly bothered.
2020-06-22 18:00:47 +00:00
|
|
|
WRITEINT16(save_p, mapnum);
|
2017-08-20 22:18:47 +00:00
|
|
|
WRITEUINT16(save_p, emeralds+357);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void P_UnArchiveSPGame(INT16 mapoverride)
|
|
|
|
{
|
|
|
|
char testname[sizeof(timeattackfolder)];
|
|
|
|
|
|
|
|
gamemap = READINT16(save_p);
|
|
|
|
|
|
|
|
if (mapoverride != 0)
|
|
|
|
{
|
|
|
|
gamemap = mapoverride;
|
Introducing Marathon Run. (I was going to call it Marathon Mode, but NiGHTS Mode being right next to it on the menu looked terrible.)
Basically a dedicated Record Attack-like experience for speedrunning the game as a continuous chunk rather than ILs. Has several quality of life features.
Benefits include:
* An unambiguous real-time bar across the bottom of the screen, always displaying the current time, ticking up until you reach the ending.
* Disable the console (pausing is still allowed, but the timer will still increment).
* Automatically skip intermissions as if you're holding down the spin button.
* Show centiseconds on HUD automatically, like record attack.
* "Live Event Backups" - a category of run fit for major events like GDQ, where recovery from crashes or chokes makes for better entertainment. Essentially a modified SP savefile, down to using the same basic functions, but has its own filename and tweaked internal layout.
* "spmarathon_start" MainCfg block parameter and "marathonnext" mapheader parameter, allowing for a customised flow (makes this fit for purpose for an eventual SUGOI port).
* Disabling inter-level custom cutscenes by default with a menu option to toggle this (won't show up if the mod doesn't *have* any custom cutscenes), although either way ending cutscenes (vanilla or custom) remain intact since is time is called before them.
* Won't show up if you have a mod that consists of only one level (determined by spmarathon_start's nextlevel; this won't trip if you manually set its marathonnext).
* Unconditional gratitude on the evaluation screen, instead of a negging "Try again..." if you didn't get all the emeralds (which you may not have been aiming for).
* Gorgeous new menu (no new assets required, unless you wanna give it a header later).
Changes which were required for the above but affect other areas of the game include:
* "useBlackRock" MainCFG block parameter, which can be used to disable the presence of the Black Rock or Egg Rock in both the Evaluation screen and the Marathon Run menu (for total conversions with different stories).
* Disabling Continues in NiGHTS mode, to match the most common singleplayer experience post 2.2.4's release (is reverted if useContinues is set to true).
* Hiding the exitmove "powerup" outside of multiplayer. (Okay, this isn't really related, I just saw this bug in action a lot while doing test runs and got annoyed enough to fix it here.)
* The ability to use V_DrawPromptBack (in hardcode only at the moment, but) to draw in terms of pixels rather than rows of text, by providing negative instead of positive inputs).
* A refactoring of redundant game saves smattered across the ending, credits, and evaluation - in addition to saving the game slightly earlier.
* Minor m_menu.c touchups and refactorings here and there.
Built using feedback from the official server's #speedruns channel, among other places.
2020-05-14 22:10:00 +00:00
|
|
|
gamecomplete = 1;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
else
|
Introducing Marathon Run. (I was going to call it Marathon Mode, but NiGHTS Mode being right next to it on the menu looked terrible.)
Basically a dedicated Record Attack-like experience for speedrunning the game as a continuous chunk rather than ILs. Has several quality of life features.
Benefits include:
* An unambiguous real-time bar across the bottom of the screen, always displaying the current time, ticking up until you reach the ending.
* Disable the console (pausing is still allowed, but the timer will still increment).
* Automatically skip intermissions as if you're holding down the spin button.
* Show centiseconds on HUD automatically, like record attack.
* "Live Event Backups" - a category of run fit for major events like GDQ, where recovery from crashes or chokes makes for better entertainment. Essentially a modified SP savefile, down to using the same basic functions, but has its own filename and tweaked internal layout.
* "spmarathon_start" MainCfg block parameter and "marathonnext" mapheader parameter, allowing for a customised flow (makes this fit for purpose for an eventual SUGOI port).
* Disabling inter-level custom cutscenes by default with a menu option to toggle this (won't show up if the mod doesn't *have* any custom cutscenes), although either way ending cutscenes (vanilla or custom) remain intact since is time is called before them.
* Won't show up if you have a mod that consists of only one level (determined by spmarathon_start's nextlevel; this won't trip if you manually set its marathonnext).
* Unconditional gratitude on the evaluation screen, instead of a negging "Try again..." if you didn't get all the emeralds (which you may not have been aiming for).
* Gorgeous new menu (no new assets required, unless you wanna give it a header later).
Changes which were required for the above but affect other areas of the game include:
* "useBlackRock" MainCFG block parameter, which can be used to disable the presence of the Black Rock or Egg Rock in both the Evaluation screen and the Marathon Run menu (for total conversions with different stories).
* Disabling Continues in NiGHTS mode, to match the most common singleplayer experience post 2.2.4's release (is reverted if useContinues is set to true).
* Hiding the exitmove "powerup" outside of multiplayer. (Okay, this isn't really related, I just saw this bug in action a lot while doing test runs and got annoyed enough to fix it here.)
* The ability to use V_DrawPromptBack (in hardcode only at the moment, but) to draw in terms of pixels rather than rows of text, by providing negative instead of positive inputs).
* A refactoring of redundant game saves smattered across the ending, credits, and evaluation - in addition to saving the game slightly earlier.
* Minor m_menu.c touchups and refactorings here and there.
Built using feedback from the official server's #speedruns channel, among other places.
2020-05-14 22:10:00 +00:00
|
|
|
gamecomplete = 0;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
// gamemap changed; we assume that its map header is always valid,
|
|
|
|
// so make it so
|
|
|
|
if(!mapheaderinfo[gamemap-1])
|
|
|
|
P_AllocMapHeader(gamemap-1);
|
|
|
|
|
2017-08-04 17:57:47 +00:00
|
|
|
//lastmapsaved = gamemap;
|
2017-08-04 00:27:31 +00:00
|
|
|
lastmaploaded = gamemap;
|
2017-08-07 03:47:39 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
tokenlist = 0;
|
|
|
|
token = 0;
|
|
|
|
|
|
|
|
savedata.emeralds = READUINT16(save_p)-357;
|
|
|
|
|
|
|
|
READSTRINGN(save_p, testname, sizeof(testname));
|
|
|
|
|
|
|
|
if (strcmp(testname, timeattackfolder))
|
|
|
|
{
|
|
|
|
if (modifiedgame)
|
|
|
|
I_Error("Save game not for this modification.");
|
|
|
|
else
|
|
|
|
I_Error("This save file is for a particular mod, it cannot be used with the regular game.");
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(playeringame, 0, sizeof(*playeringame));
|
|
|
|
playeringame[consoleplayer] = true;
|
|
|
|
}
|
|
|
|
|
2020-01-31 14:57:04 +00:00
|
|
|
static void P_NetArchiveMisc(boolean resending)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
INT32 i;
|
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
WRITEUINT32(save_p, ARCHIVEBLOCK_MISC);
|
|
|
|
|
2020-01-31 14:57:04 +00:00
|
|
|
if (resending)
|
|
|
|
WRITEUINT32(save_p, gametic);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEINT16(save_p, gamemap);
|
2023-06-13 02:34:42 +00:00
|
|
|
|
|
|
|
if (gamestate != GS_LEVEL)
|
|
|
|
WRITEINT16(save_p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers
|
|
|
|
else
|
|
|
|
WRITEINT16(save_p, gamestate);
|
2020-01-31 14:29:22 +00:00
|
|
|
WRITEINT16(save_p, gametype);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2019-11-08 15:47:12 +00:00
|
|
|
{
|
|
|
|
UINT32 pig = 0;
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
pig |= (playeringame[i] != 0)<<i;
|
|
|
|
WRITEUINT32(save_p, pig);
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
WRITEUINT32(save_p, P_GetRandSeed());
|
2014-03-17 12:13:16 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEUINT32(save_p, tokenlist);
|
|
|
|
|
|
|
|
WRITEUINT32(save_p, leveltime);
|
2018-06-03 21:41:54 +00:00
|
|
|
WRITEUINT32(save_p, ssspheres);
|
2014-03-15 16:59:03 +00:00
|
|
|
WRITEINT16(save_p, lastmap);
|
2019-07-31 22:17:17 +00:00
|
|
|
WRITEUINT16(save_p, bossdisabled);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
WRITEUINT16(save_p, emeralds);
|
2019-11-08 15:47:12 +00:00
|
|
|
{
|
|
|
|
UINT8 globools = 0;
|
|
|
|
if (stagefailed)
|
|
|
|
globools |= 1;
|
|
|
|
if (stoppedclock)
|
|
|
|
globools |= (1<<1);
|
|
|
|
WRITEUINT8(save_p, globools);
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
WRITEUINT32(save_p, token);
|
|
|
|
WRITEINT32(save_p, sstimer);
|
|
|
|
WRITEUINT32(save_p, bluescore);
|
|
|
|
WRITEUINT32(save_p, redscore);
|
2020-11-09 02:43:16 +00:00
|
|
|
|
|
|
|
WRITEUINT16(save_p, skincolor_redteam);
|
|
|
|
WRITEUINT16(save_p, skincolor_blueteam);
|
|
|
|
WRITEUINT16(save_p, skincolor_redring);
|
|
|
|
WRITEUINT16(save_p, skincolor_bluering);
|
|
|
|
|
2019-08-03 22:28:53 +00:00
|
|
|
WRITEINT32(save_p, modulothing);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
WRITEINT16(save_p, autobalance);
|
|
|
|
WRITEINT16(save_p, teamscramble);
|
|
|
|
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
WRITEINT16(save_p, scrambleplayers[i]);
|
|
|
|
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
WRITEINT16(save_p, scrambleteams[i]);
|
|
|
|
|
|
|
|
WRITEINT16(save_p, scrambletotal);
|
|
|
|
WRITEINT16(save_p, scramblecount);
|
|
|
|
|
|
|
|
WRITEUINT32(save_p, countdown);
|
|
|
|
WRITEUINT32(save_p, countdown2);
|
|
|
|
|
|
|
|
WRITEFIXED(save_p, gravity);
|
|
|
|
|
|
|
|
WRITEUINT32(save_p, countdowntimer);
|
|
|
|
WRITEUINT8(save_p, countdowntimeup);
|
|
|
|
|
|
|
|
WRITEUINT32(save_p, hidetime);
|
|
|
|
|
|
|
|
// Is it paused?
|
|
|
|
if (paused)
|
|
|
|
WRITEUINT8(save_p, 0x2f);
|
|
|
|
else
|
|
|
|
WRITEUINT8(save_p, 0x2e);
|
|
|
|
}
|
|
|
|
|
2020-01-31 14:57:04 +00:00
|
|
|
static inline boolean P_NetUnArchiveMisc(boolean reloading)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
INT32 i;
|
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
if (READUINT32(save_p) != ARCHIVEBLOCK_MISC)
|
|
|
|
I_Error("Bad $$$.sav at archive block Misc");
|
|
|
|
|
2020-01-31 14:57:04 +00:00
|
|
|
if (reloading)
|
|
|
|
gametic = READUINT32(save_p);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
gamemap = READINT16(save_p);
|
|
|
|
|
|
|
|
// gamemap changed; we assume that its map header is always valid,
|
|
|
|
// so make it so
|
|
|
|
if(!mapheaderinfo[gamemap-1])
|
|
|
|
P_AllocMapHeader(gamemap-1);
|
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
// tell the sound code to reset the music since we're skipping what
|
|
|
|
// normally sets this flag
|
2016-01-08 03:48:20 +00:00
|
|
|
mapmusflags |= MUSIC_RELOADRESET;
|
2014-03-17 12:13:16 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
G_SetGamestate(READINT16(save_p));
|
|
|
|
|
2020-01-31 14:29:22 +00:00
|
|
|
gametype = READINT16(save_p);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2019-11-08 15:47:12 +00:00
|
|
|
UINT32 pig = READUINT32(save_p);
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
{
|
|
|
|
playeringame[i] = (pig & (1<<i)) != 0;
|
|
|
|
// playerstate is set in unarchiveplayers
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
P_SetRandSeed(READUINT32(save_p));
|
|
|
|
|
|
|
|
tokenlist = READUINT32(save_p);
|
|
|
|
|
2020-01-31 14:57:04 +00:00
|
|
|
if (!P_LoadLevel(true, reloading))
|
2021-04-26 18:07:11 +00:00
|
|
|
{
|
|
|
|
CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n"));
|
2014-03-15 16:59:03 +00:00
|
|
|
return false;
|
2021-04-26 18:07:11 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
// get the time
|
|
|
|
leveltime = READUINT32(save_p);
|
2018-06-03 21:41:54 +00:00
|
|
|
ssspheres = READUINT32(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
lastmap = READINT16(save_p);
|
2019-07-31 22:17:17 +00:00
|
|
|
bossdisabled = READUINT16(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
emeralds = READUINT16(save_p);
|
2019-11-08 15:47:12 +00:00
|
|
|
{
|
|
|
|
UINT8 globools = READUINT8(save_p);
|
|
|
|
stagefailed = !!(globools & 1);
|
|
|
|
stoppedclock = !!(globools & (1<<1));
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
token = READUINT32(save_p);
|
|
|
|
sstimer = READINT32(save_p);
|
|
|
|
bluescore = READUINT32(save_p);
|
|
|
|
redscore = READUINT32(save_p);
|
2020-11-09 02:43:16 +00:00
|
|
|
|
|
|
|
skincolor_redteam = READUINT16(save_p);
|
|
|
|
skincolor_blueteam = READUINT16(save_p);
|
|
|
|
skincolor_redring = READUINT16(save_p);
|
|
|
|
skincolor_bluering = READUINT16(save_p);
|
|
|
|
|
2019-08-04 15:34:55 +00:00
|
|
|
modulothing = READINT32(save_p);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
autobalance = READINT16(save_p);
|
|
|
|
teamscramble = READINT16(save_p);
|
|
|
|
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
scrambleplayers[i] = READINT16(save_p);
|
|
|
|
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
scrambleteams[i] = READINT16(save_p);
|
|
|
|
|
|
|
|
scrambletotal = READINT16(save_p);
|
|
|
|
scramblecount = READINT16(save_p);
|
|
|
|
|
|
|
|
countdown = READUINT32(save_p);
|
|
|
|
countdown2 = READUINT32(save_p);
|
|
|
|
|
|
|
|
gravity = READFIXED(save_p);
|
|
|
|
|
|
|
|
countdowntimer = (tic_t)READUINT32(save_p);
|
|
|
|
countdowntimeup = (boolean)READUINT8(save_p);
|
|
|
|
|
|
|
|
hidetime = READUINT32(save_p);
|
|
|
|
|
|
|
|
// Is it paused?
|
|
|
|
if (READUINT8(save_p) == 0x2f)
|
|
|
|
paused = true;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-02-27 21:52:05 +00:00
|
|
|
static inline void P_NetArchiveEmblems(void)
|
|
|
|
{
|
|
|
|
gamedata_t *data = serverGamedata;
|
|
|
|
INT32 i, j;
|
|
|
|
UINT8 btemp;
|
|
|
|
INT32 curmare;
|
|
|
|
|
|
|
|
WRITEUINT32(save_p, ARCHIVEBLOCK_EMBLEMS);
|
|
|
|
|
|
|
|
// These should be synchronized before savegame loading by the wad files being the same anyway,
|
|
|
|
// but just in case, for now, we'll leave them here for testing. It would be very bad if they mismatch.
|
|
|
|
WRITEUINT8(save_p, (UINT8)savemoddata);
|
|
|
|
WRITEINT32(save_p, numemblems);
|
|
|
|
WRITEINT32(save_p, numextraemblems);
|
|
|
|
|
|
|
|
// The rest of this is lifted straight from G_SaveGameData in g_game.c
|
|
|
|
// TODO: Optimize this to only send information about emblems, unlocks, etc. which actually exist
|
|
|
|
// There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same.
|
|
|
|
|
|
|
|
WRITEUINT32(save_p, data->totalplaytime);
|
|
|
|
|
|
|
|
// TODO put another cipher on these things? meh, I don't care...
|
|
|
|
for (i = 0; i < NUMMAPS; i++)
|
|
|
|
WRITEUINT8(save_p, (data->mapvisited[i] & MV_MAX));
|
|
|
|
|
|
|
|
// To save space, use one bit per collected/achieved/unlocked flag
|
|
|
|
for (i = 0; i < MAXEMBLEMS;)
|
|
|
|
{
|
|
|
|
btemp = 0;
|
|
|
|
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
|
|
|
|
btemp |= (data->collected[j+i] << j);
|
|
|
|
WRITEUINT8(save_p, btemp);
|
|
|
|
i += j;
|
|
|
|
}
|
|
|
|
for (i = 0; i < MAXEXTRAEMBLEMS;)
|
|
|
|
{
|
|
|
|
btemp = 0;
|
|
|
|
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
|
|
|
|
btemp |= (data->extraCollected[j+i] << j);
|
|
|
|
WRITEUINT8(save_p, btemp);
|
|
|
|
i += j;
|
|
|
|
}
|
|
|
|
for (i = 0; i < MAXUNLOCKABLES;)
|
|
|
|
{
|
|
|
|
btemp = 0;
|
|
|
|
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
|
|
|
|
btemp |= (data->unlocked[j+i] << j);
|
|
|
|
WRITEUINT8(save_p, btemp);
|
|
|
|
i += j;
|
|
|
|
}
|
|
|
|
for (i = 0; i < MAXCONDITIONSETS;)
|
|
|
|
{
|
|
|
|
btemp = 0;
|
|
|
|
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
|
|
|
|
btemp |= (data->achieved[j+i] << j);
|
|
|
|
WRITEUINT8(save_p, btemp);
|
|
|
|
i += j;
|
|
|
|
}
|
|
|
|
|
|
|
|
WRITEUINT32(save_p, data->timesBeaten);
|
|
|
|
WRITEUINT32(save_p, data->timesBeatenWithEmeralds);
|
|
|
|
WRITEUINT32(save_p, data->timesBeatenUltimate);
|
|
|
|
|
|
|
|
// Main records
|
|
|
|
for (i = 0; i < NUMMAPS; i++)
|
|
|
|
{
|
|
|
|
if (data->mainrecords[i])
|
|
|
|
{
|
|
|
|
WRITEUINT32(save_p, data->mainrecords[i]->score);
|
|
|
|
WRITEUINT32(save_p, data->mainrecords[i]->time);
|
|
|
|
WRITEUINT16(save_p, data->mainrecords[i]->rings);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WRITEUINT32(save_p, 0);
|
|
|
|
WRITEUINT32(save_p, 0);
|
|
|
|
WRITEUINT16(save_p, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NiGHTS records
|
|
|
|
for (i = 0; i < NUMMAPS; i++)
|
|
|
|
{
|
|
|
|
if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares)
|
|
|
|
{
|
|
|
|
WRITEUINT8(save_p, 0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
WRITEUINT8(save_p, data->nightsrecords[i]->nummares);
|
|
|
|
|
|
|
|
for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare)
|
|
|
|
{
|
|
|
|
WRITEUINT32(save_p, data->nightsrecords[i]->score[curmare]);
|
|
|
|
WRITEUINT8(save_p, data->nightsrecords[i]->grade[curmare]);
|
|
|
|
WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]);
|
|
|
|
}
|
|
|
|
}
|
2022-03-02 22:47:15 +00:00
|
|
|
|
|
|
|
// Mid-map stuff
|
|
|
|
WRITEUINT32(save_p, unlocktriggers);
|
|
|
|
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
{
|
|
|
|
if (!ntemprecords[i].nummares)
|
|
|
|
{
|
|
|
|
WRITEUINT8(save_p, 0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
WRITEUINT8(save_p, ntemprecords[i].nummares);
|
|
|
|
|
|
|
|
for (curmare = 0; curmare < (ntemprecords[i].nummares + 1); ++curmare)
|
|
|
|
{
|
|
|
|
WRITEUINT32(save_p, ntemprecords[i].score[curmare]);
|
|
|
|
WRITEUINT8(save_p, ntemprecords[i].grade[curmare]);
|
|
|
|
WRITEUINT32(save_p, ntemprecords[i].time[curmare]);
|
|
|
|
}
|
|
|
|
}
|
2022-02-27 21:52:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void P_NetUnArchiveEmblems(void)
|
|
|
|
{
|
|
|
|
gamedata_t *data = serverGamedata;
|
|
|
|
INT32 i, j;
|
|
|
|
UINT8 rtemp;
|
|
|
|
UINT32 recscore;
|
|
|
|
tic_t rectime;
|
|
|
|
UINT16 recrings;
|
|
|
|
UINT8 recmares;
|
|
|
|
INT32 curmare;
|
|
|
|
|
|
|
|
if (READUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS)
|
|
|
|
I_Error("Bad $$$.sav at archive block Emblems");
|
|
|
|
|
|
|
|
savemoddata = (boolean)READUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason.
|
|
|
|
|
|
|
|
if (numemblems != READINT32(save_p))
|
2022-03-02 22:47:15 +00:00
|
|
|
I_Error("Bad $$$.sav dearchiving Emblems (numemblems mismatch)");
|
2022-02-27 21:52:05 +00:00
|
|
|
if (numextraemblems != READINT32(save_p))
|
2022-03-02 22:47:15 +00:00
|
|
|
I_Error("Bad $$$.sav dearchiving Emblems (numextraemblems mismatch)");
|
2022-02-27 21:52:05 +00:00
|
|
|
|
|
|
|
// This shouldn't happen, but if something really fucked up happens and you transfer
|
|
|
|
// the SERVER player's gamedata over your own CLIENT gamedata,
|
|
|
|
// then this prevents it from being saved over yours.
|
|
|
|
data->loaded = false;
|
|
|
|
|
|
|
|
M_ClearSecrets(data);
|
|
|
|
G_ClearRecords(data);
|
|
|
|
|
|
|
|
// The rest of this is lifted straight from G_LoadGameData in g_game.c
|
|
|
|
// TODO: Optimize this to only read information about emblems, unlocks, etc. which actually exist
|
|
|
|
// There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same.
|
|
|
|
|
|
|
|
data->totalplaytime = READUINT32(save_p);
|
|
|
|
|
|
|
|
// TODO put another cipher on these things? meh, I don't care...
|
|
|
|
for (i = 0; i < NUMMAPS; i++)
|
|
|
|
if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX)
|
2022-03-02 22:47:15 +00:00
|
|
|
I_Error("Bad $$$.sav dearchiving Emblems (invalid visit flags)");
|
2022-02-27 21:52:05 +00:00
|
|
|
|
|
|
|
// To save space, use one bit per collected/achieved/unlocked flag
|
|
|
|
for (i = 0; i < MAXEMBLEMS;)
|
|
|
|
{
|
|
|
|
rtemp = READUINT8(save_p);
|
|
|
|
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
|
|
|
|
data->collected[j+i] = ((rtemp >> j) & 1);
|
|
|
|
i += j;
|
|
|
|
}
|
|
|
|
for (i = 0; i < MAXEXTRAEMBLEMS;)
|
|
|
|
{
|
|
|
|
rtemp = READUINT8(save_p);
|
|
|
|
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
|
|
|
|
data->extraCollected[j+i] = ((rtemp >> j) & 1);
|
|
|
|
i += j;
|
|
|
|
}
|
|
|
|
for (i = 0; i < MAXUNLOCKABLES;)
|
|
|
|
{
|
|
|
|
rtemp = READUINT8(save_p);
|
|
|
|
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
|
|
|
|
data->unlocked[j+i] = ((rtemp >> j) & 1);
|
|
|
|
i += j;
|
|
|
|
}
|
|
|
|
for (i = 0; i < MAXCONDITIONSETS;)
|
|
|
|
{
|
|
|
|
rtemp = READUINT8(save_p);
|
|
|
|
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
|
|
|
|
data->achieved[j+i] = ((rtemp >> j) & 1);
|
|
|
|
i += j;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->timesBeaten = READUINT32(save_p);
|
|
|
|
data->timesBeatenWithEmeralds = READUINT32(save_p);
|
|
|
|
data->timesBeatenUltimate = READUINT32(save_p);
|
|
|
|
|
|
|
|
// Main records
|
|
|
|
for (i = 0; i < NUMMAPS; ++i)
|
|
|
|
{
|
|
|
|
recscore = READUINT32(save_p);
|
|
|
|
rectime = (tic_t)READUINT32(save_p);
|
|
|
|
recrings = READUINT16(save_p);
|
|
|
|
|
|
|
|
if (recrings > 10000 || recscore > MAXSCORE)
|
2022-03-02 22:47:15 +00:00
|
|
|
I_Error("Bad $$$.sav dearchiving Emblems (invalid score)");
|
2022-02-27 21:52:05 +00:00
|
|
|
|
|
|
|
if (recscore || rectime || recrings)
|
|
|
|
{
|
|
|
|
G_AllocMainRecordData((INT16)i, data);
|
|
|
|
data->mainrecords[i]->score = recscore;
|
|
|
|
data->mainrecords[i]->time = rectime;
|
|
|
|
data->mainrecords[i]->rings = recrings;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Nights records
|
|
|
|
for (i = 0; i < NUMMAPS; ++i)
|
|
|
|
{
|
|
|
|
if ((recmares = READUINT8(save_p)) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
G_AllocNightsRecordData((INT16)i, data);
|
|
|
|
|
|
|
|
for (curmare = 0; curmare < (recmares+1); ++curmare)
|
|
|
|
{
|
|
|
|
data->nightsrecords[i]->score[curmare] = READUINT32(save_p);
|
|
|
|
data->nightsrecords[i]->grade[curmare] = READUINT8(save_p);
|
|
|
|
data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p);
|
|
|
|
|
|
|
|
if (data->nightsrecords[i]->grade[curmare] > GRADE_S)
|
|
|
|
{
|
2022-03-02 22:47:15 +00:00
|
|
|
I_Error("Bad $$$.sav dearchiving Emblems (invalid grade)");
|
2022-02-27 21:52:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
data->nightsrecords[i]->nummares = recmares;
|
|
|
|
}
|
2022-03-02 22:47:15 +00:00
|
|
|
|
|
|
|
// Mid-map stuff
|
|
|
|
unlocktriggers = READUINT32(save_p);
|
|
|
|
|
|
|
|
for (i = 0; i < MAXPLAYERS; ++i)
|
|
|
|
{
|
|
|
|
if ((recmares = READUINT8(save_p)) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (curmare = 0; curmare < (recmares+1); ++curmare)
|
|
|
|
{
|
|
|
|
ntemprecords[i].score[curmare] = READUINT32(save_p);
|
|
|
|
ntemprecords[i].grade[curmare] = READUINT8(save_p);
|
|
|
|
ntemprecords[i].time[curmare] = (tic_t)READUINT32(save_p);
|
|
|
|
|
|
|
|
if (ntemprecords[i].grade[curmare] > GRADE_S)
|
|
|
|
{
|
|
|
|
I_Error("Bad $$$.sav dearchiving Emblems (invalid temp grade)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ntemprecords[i].nummares = recmares;
|
|
|
|
}
|
2022-02-27 21:52:05 +00:00
|
|
|
}
|
|
|
|
|
2023-08-24 19:04:31 +00:00
|
|
|
static void P_NetArchiveSectorPortals(void)
|
|
|
|
{
|
|
|
|
WRITEUINT32(save_p, ARCHIVEBLOCK_SECPORTALS);
|
|
|
|
|
|
|
|
WRITEUINT32(save_p, secportalcount);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < secportalcount; i++)
|
|
|
|
{
|
|
|
|
UINT8 type = secportals[i].type;
|
|
|
|
|
|
|
|
WRITEUINT8(save_p, type);
|
2023-08-25 03:18:20 +00:00
|
|
|
WRITEFIXED(save_p, secportals[i].origin.x);
|
|
|
|
WRITEFIXED(save_p, secportals[i].origin.y);
|
2023-08-24 19:04:31 +00:00
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case SECPORTAL_LINE:
|
|
|
|
WRITEUINT32(save_p, SaveLine(secportals[i].line.start));
|
|
|
|
WRITEUINT32(save_p, SaveLine(secportals[i].line.dest));
|
|
|
|
break;
|
|
|
|
case SECPORTAL_PLANE:
|
|
|
|
case SECPORTAL_HORIZON:
|
|
|
|
case SECPORTAL_FLOOR:
|
|
|
|
case SECPORTAL_CEILING:
|
|
|
|
WRITEUINT32(save_p, SaveSector(secportals[i].sector));
|
|
|
|
break;
|
|
|
|
case SECPORTAL_OBJECT:
|
|
|
|
if (secportals[i].mobj && !P_MobjWasRemoved(secportals[i].mobj))
|
|
|
|
SaveMobjnum(secportals[i].mobj);
|
|
|
|
else
|
|
|
|
WRITEUINT32(save_p, 0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void P_NetUnArchiveSectorPortals(void)
|
|
|
|
{
|
|
|
|
if (READUINT32(save_p) != ARCHIVEBLOCK_SECPORTALS)
|
|
|
|
I_Error("Bad $$$.sav at archive block Secportals");
|
|
|
|
|
|
|
|
Z_Free(secportals);
|
|
|
|
P_InitSectorPortals();
|
|
|
|
|
|
|
|
UINT32 count = READUINT32(save_p);
|
|
|
|
|
|
|
|
for (UINT32 i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
UINT32 id = P_NewSectorPortal();
|
|
|
|
|
|
|
|
sectorportal_t *secportal = &secportals[id];
|
|
|
|
|
|
|
|
secportal->type = READUINT8(save_p);
|
2023-08-25 03:18:20 +00:00
|
|
|
secportal->origin.x = READFIXED(save_p);
|
|
|
|
secportal->origin.y = READFIXED(save_p);
|
2023-08-24 19:04:31 +00:00
|
|
|
|
|
|
|
switch (secportal->type)
|
|
|
|
{
|
|
|
|
case SECPORTAL_LINE:
|
|
|
|
secportal->line.start = LoadLine(READUINT32(save_p));
|
|
|
|
secportal->line.dest = LoadLine(READUINT32(save_p));
|
|
|
|
break;
|
|
|
|
case SECPORTAL_PLANE:
|
|
|
|
case SECPORTAL_HORIZON:
|
|
|
|
case SECPORTAL_FLOOR:
|
|
|
|
case SECPORTAL_CEILING:
|
|
|
|
secportal->sector = LoadSector(READUINT32(save_p));
|
|
|
|
break;
|
|
|
|
case SECPORTAL_OBJECT:
|
|
|
|
id = READUINT32(save_p);
|
|
|
|
secportal->mobj = (id == 0) ? NULL : P_FindNewPosition(id);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-24 17:25:27 +00:00
|
|
|
static inline void P_ArchiveLuabanksAndConsistency(void)
|
|
|
|
{
|
|
|
|
UINT8 i, banksinuse = NUM_LUABANKS;
|
|
|
|
|
|
|
|
while (banksinuse && !luabanks[banksinuse-1])
|
|
|
|
banksinuse--; // get the last used bank
|
|
|
|
|
|
|
|
if (banksinuse)
|
|
|
|
{
|
|
|
|
WRITEUINT8(save_p, 0xb7); // luabanks marker
|
|
|
|
WRITEUINT8(save_p, banksinuse);
|
|
|
|
for (i = 0; i < banksinuse; i++)
|
|
|
|
WRITEINT32(save_p, luabanks[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
WRITEUINT8(save_p, 0x1d); // consistency marker
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline boolean P_UnArchiveLuabanksAndConsistency(void)
|
|
|
|
{
|
|
|
|
switch (READUINT8(save_p))
|
|
|
|
{
|
2021-04-26 18:07:11 +00:00
|
|
|
case 0xb7: // luabanks marker
|
2019-08-24 17:25:27 +00:00
|
|
|
{
|
|
|
|
UINT8 i, banksinuse = READUINT8(save_p);
|
|
|
|
if (banksinuse > NUM_LUABANKS)
|
2021-04-26 18:07:11 +00:00
|
|
|
{
|
|
|
|
CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Too many banks in use)\n"));
|
2019-08-24 17:25:27 +00:00
|
|
|
return false;
|
2021-04-26 18:07:11 +00:00
|
|
|
}
|
2019-08-24 17:25:27 +00:00
|
|
|
for (i = 0; i < banksinuse; i++)
|
|
|
|
luabanks[i] = READINT32(save_p);
|
2021-04-26 18:07:11 +00:00
|
|
|
if (READUINT8(save_p) != 0x1d) // consistency marker
|
|
|
|
{
|
|
|
|
CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Failed consistency check)\n"));
|
2019-08-24 17:25:27 +00:00
|
|
|
return false;
|
2021-04-26 18:07:11 +00:00
|
|
|
}
|
2019-08-24 17:25:27 +00:00
|
|
|
}
|
2021-04-26 18:07:11 +00:00
|
|
|
case 0x1d: // consistency marker
|
2019-08-24 17:25:27 +00:00
|
|
|
break;
|
2021-04-26 18:07:11 +00:00
|
|
|
default: // anything else is nonsense
|
|
|
|
CONS_Alert(CONS_ERROR, M_GetText("Failed consistency check (???)\n"));
|
2019-08-24 17:25:27 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Special saves!
All this refactoring, just to resolve #162. Specifically, it engages savegame events not at level load (except for savefile start) but on level completion, just after you've gotten all the intermission bonuses but before the intermission actually starts.
Also fixes a never-before-discovered bug where if the titlemap has LF_SAVEGAME, your save file will be overwritten upon returning to the title screen. This game is a mess of hacks, I swear...
One unintended side effect: It may actually be faster in some speedrun circumstances in mods with cutscenes to complete the map, exit back to the title screen, and reload the file. It's a common feature of optimal runs in games with cutscenes, though, and Marathon Run has a toggle for cutscenes, so I'm not particularly bothered.
2020-06-22 18:00:47 +00:00
|
|
|
void P_SaveGame(INT16 mapnum)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
Special saves!
All this refactoring, just to resolve #162. Specifically, it engages savegame events not at level load (except for savefile start) but on level completion, just after you've gotten all the intermission bonuses but before the intermission actually starts.
Also fixes a never-before-discovered bug where if the titlemap has LF_SAVEGAME, your save file will be overwritten upon returning to the title screen. This game is a mess of hacks, I swear...
One unintended side effect: It may actually be faster in some speedrun circumstances in mods with cutscenes to complete the map, exit back to the title screen, and reload the file. It's a common feature of optimal runs in games with cutscenes, though, and Marathon Run has a toggle for cutscenes, so I'm not particularly bothered.
2020-06-22 18:00:47 +00:00
|
|
|
P_ArchiveMisc(mapnum);
|
2014-03-15 16:59:03 +00:00
|
|
|
P_ArchivePlayer();
|
2019-08-24 17:25:27 +00:00
|
|
|
P_ArchiveLuabanksAndConsistency();
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2020-01-31 14:57:04 +00:00
|
|
|
void P_SaveNetGame(boolean resending)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
thinker_t *th;
|
|
|
|
mobj_t *mobj;
|
2017-01-01 17:03:13 +00:00
|
|
|
INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
CV_SaveNetVars(&save_p);
|
2020-01-31 14:57:04 +00:00
|
|
|
P_NetArchiveMisc(resending);
|
2022-02-27 21:52:05 +00:00
|
|
|
P_NetArchiveEmblems();
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
// Assign the mobjnumber for pointer tracking
|
2019-04-20 21:29:20 +00:00
|
|
|
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2019-07-12 23:42:03 +00:00
|
|
|
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
|
|
|
continue;
|
|
|
|
|
2019-04-21 14:39:57 +00:00
|
|
|
mobj = (mobj_t *)th;
|
|
|
|
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER)
|
|
|
|
continue;
|
|
|
|
mobj->mobjnum = i++;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
P_NetArchivePlayers();
|
|
|
|
if (gamestate == GS_LEVEL)
|
|
|
|
{
|
|
|
|
P_NetArchiveWorld();
|
|
|
|
P_ArchivePolyObjects();
|
|
|
|
P_NetArchiveThinkers();
|
|
|
|
P_NetArchiveSpecials();
|
2018-09-17 00:02:29 +00:00
|
|
|
P_NetArchiveColormaps();
|
2020-05-31 20:44:25 +00:00
|
|
|
P_NetArchiveWaypoints();
|
2023-08-24 19:04:31 +00:00
|
|
|
P_NetArchiveSectorPortals();
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
LUA_Archive();
|
|
|
|
|
2019-08-24 17:25:27 +00:00
|
|
|
P_ArchiveLuabanksAndConsistency();
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
boolean P_LoadGame(INT16 mapoverride)
|
|
|
|
{
|
|
|
|
if (gamestate == GS_INTERMISSION)
|
|
|
|
Y_EndIntermission();
|
|
|
|
G_SetGamestate(GS_NULL); // should be changed in P_UnArchiveMisc
|
|
|
|
|
|
|
|
P_UnArchiveSPGame(mapoverride);
|
|
|
|
P_UnArchivePlayer();
|
|
|
|
|
2019-08-24 17:25:27 +00:00
|
|
|
if (!P_UnArchiveLuabanksAndConsistency())
|
2014-03-15 16:59:03 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Only do this after confirming savegame is ok
|
|
|
|
G_DeferedInitNew(false, G_BuildMapName(gamemap), savedata.skin, false, true);
|
|
|
|
COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-01-31 14:57:04 +00:00
|
|
|
boolean P_LoadNetGame(boolean reloading)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
CV_LoadNetVars(&save_p);
|
2020-01-31 14:57:04 +00:00
|
|
|
if (!P_NetUnArchiveMisc(reloading))
|
2014-03-15 16:59:03 +00:00
|
|
|
return false;
|
2022-02-27 21:52:05 +00:00
|
|
|
P_NetUnArchiveEmblems();
|
2014-03-15 16:59:03 +00:00
|
|
|
P_NetUnArchivePlayers();
|
|
|
|
if (gamestate == GS_LEVEL)
|
|
|
|
{
|
|
|
|
P_NetUnArchiveWorld();
|
|
|
|
P_UnArchivePolyObjects();
|
|
|
|
P_NetUnArchiveThinkers();
|
|
|
|
P_NetUnArchiveSpecials();
|
2018-09-17 00:02:29 +00:00
|
|
|
P_NetUnArchiveColormaps();
|
2020-05-31 20:44:25 +00:00
|
|
|
P_NetUnArchiveWaypoints();
|
2023-08-24 19:04:31 +00:00
|
|
|
P_NetUnArchiveSectorPortals();
|
2014-03-15 16:59:03 +00:00
|
|
|
P_RelinkPointers();
|
|
|
|
P_FinishMobjs();
|
|
|
|
}
|
|
|
|
LUA_UnArchive();
|
|
|
|
|
2014-03-17 12:13:16 +00:00
|
|
|
// This is stupid and hacky, but maybe it'll work!
|
|
|
|
P_SetRandSeed(P_GetInitSeed());
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// The precipitation would normally be spawned in P_SetupLevel, which is called by
|
|
|
|
// P_NetUnArchiveMisc above. However, that would place it up before P_NetUnArchiveThinkers,
|
|
|
|
// so the thinkers would be deleted later. Therefore, P_SetupLevel will *not* spawn
|
|
|
|
// precipitation when loading a netgame save. Instead, precip has to be spawned here.
|
|
|
|
// This is done in P_NetUnArchiveSpecials now.
|
|
|
|
|
2019-08-24 17:25:27 +00:00
|
|
|
return P_UnArchiveLuabanksAndConsistency();
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|