⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sv_save.c

📁 使用Doom引擎开发的著名游戏《毁灭巫师》的源代码。
💻 C
📖 第 1 页 / 共 3 页
字号:
//**************************************************************************//**//** sv_save.c : Heretic 2 : Raven Software, Corp.//**//** $RCSfile: sv_save.c,v $//** $Revision: 1.36 $//** $Date: 95/10/17 00:10:02 $//** $Author: bgokey $//**//**************************************************************************// HEADER FILES ------------------------------------------------------------#include "h2def.h"#include "p_local.h"// MACROS ------------------------------------------------------------------#define MAX_TARGET_PLAYERS 512#define MOBJ_NULL -1#define MOBJ_XX_PLAYER -2#define GET_BYTE (*SavePtr.b++)#define GET_WORD (*SavePtr.w++)#define GET_LONG (*SavePtr.l++)#define MAX_MAPS 99#define BASE_SLOT 6#define REBORN_SLOT 7#define REBORN_DESCRIPTION "TEMP GAME"#define MAX_THINKER_SIZE 256// TYPES -------------------------------------------------------------------typedef enum{	ASEG_GAME_HEADER = 101,	ASEG_MAP_HEADER,	ASEG_WORLD,	ASEG_POLYOBJS,	ASEG_MOBJS,	ASEG_THINKERS,	ASEG_SCRIPTS,	ASEG_PLAYERS,	ASEG_SOUNDS,	ASEG_MISC,	ASEG_END} gameArchiveSegment_t;typedef enum{	TC_NULL,	TC_MOVE_CEILING,	TC_VERTICAL_DOOR,	TC_MOVE_FLOOR,	TC_PLAT_RAISE,	TC_INTERPRET_ACS,	TC_FLOOR_WAGGLE,	TC_LIGHT,	TC_PHASE,	TC_BUILD_PILLAR,	TC_ROTATE_POLY,	TC_MOVE_POLY,	TC_POLY_DOOR} thinkClass_t;typedef struct{	thinkClass_t tClass;	think_t thinkerFunc;	void (*mangleFunc)();	void (*restoreFunc)();	size_t size;} thinkInfo_t;typedef struct{	thinker_t thinker;	sector_t *sector;} ssthinker_t;// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------void P_SpawnPlayer(mapthing_t *mthing);// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------static void ArchiveWorld(void);static void UnarchiveWorld(void);static void ArchivePolyobjs(void);static void UnarchivePolyobjs(void);static void ArchiveMobjs(void);static void UnarchiveMobjs(void);static void ArchiveThinkers(void);static void UnarchiveThinkers(void);static void ArchiveScripts(void);static void UnarchiveScripts(void);static void ArchivePlayers(void);static void UnarchivePlayers(void);static void ArchiveSounds(void);static void UnarchiveSounds(void);static void ArchiveMisc(void);static void UnarchiveMisc(void);static void SetMobjArchiveNums(void);static void RemoveAllThinkers(void);static void MangleMobj(mobj_t *mobj);static void RestoreMobj(mobj_t *mobj);static int GetMobjNum(mobj_t *mobj);static void SetMobjPtr(int *archiveNum);static void MangleSSThinker(ssthinker_t *sst);static void RestoreSSThinker(ssthinker_t *sst);static void RestoreSSThinkerNoSD(ssthinker_t *sst);static void MangleScript(acs_t *script);static void RestoreScript(acs_t *script);static void RestorePlatRaise(plat_t *plat);static void RestoreMoveCeiling(ceiling_t *ceiling);static void AssertSegment(gameArchiveSegment_t segType);static void ClearSaveSlot(int slot);static void CopySaveSlot(int sourceSlot, int destSlot);static void CopyFile(char *sourceName, char *destName);static boolean ExistingFile(char *name);static void OpenStreamOut(char *fileName);static void CloseStreamOut(void);static void StreamOutBuffer(void *buffer, int size);static void StreamOutByte(byte val);static void StreamOutWord(unsigned short val);static void StreamOutLong(unsigned int val);// EXTERNAL DATA DECLARATIONS ----------------------------------------------extern int ACScriptCount;extern byte *ActionCodeBase;extern acsInfo_t *ACSInfo;// PUBLIC DATA DEFINITIONS -------------------------------------------------char *SavePath;// PRIVATE DATA DEFINITIONS ------------------------------------------------static int MobjCount;static mobj_t **MobjList;static int **TargetPlayerAddrs;static int TargetPlayerCount;static byte *SaveBuffer;static boolean SavingPlayers;static union{	byte *b;	short *w;	int *l;} SavePtr;static FILE *SavingFP;// This list has been prioritized using frequency estimatesstatic thinkInfo_t ThinkerInfo[] ={	{		TC_MOVE_FLOOR,		T_MoveFloor,		MangleSSThinker,		RestoreSSThinker,		sizeof(floormove_t)	},	{		TC_PLAT_RAISE,		T_PlatRaise,		MangleSSThinker,		RestorePlatRaise,		sizeof(plat_t)	},	{		TC_MOVE_CEILING,		T_MoveCeiling,		MangleSSThinker,		RestoreMoveCeiling,		sizeof(ceiling_t)	},	{		TC_LIGHT,		T_Light,		MangleSSThinker,		RestoreSSThinkerNoSD,		sizeof(light_t)	},	{		TC_VERTICAL_DOOR,		T_VerticalDoor,		MangleSSThinker,		RestoreSSThinker,		sizeof(vldoor_t)	},	{		TC_PHASE,		T_Phase,		MangleSSThinker,		RestoreSSThinkerNoSD,		sizeof(phase_t)	},	{		TC_INTERPRET_ACS,		T_InterpretACS,		MangleScript,		RestoreScript,		sizeof(acs_t)	},	{		TC_ROTATE_POLY,		T_RotatePoly,		NULL,		NULL,		sizeof(polyevent_t)	},	{		TC_BUILD_PILLAR,		T_BuildPillar,		MangleSSThinker,		RestoreSSThinker,		sizeof(pillar_t)	},	{		TC_MOVE_POLY,		T_MovePoly,		NULL,		NULL,		sizeof(polyevent_t)	},	{		TC_POLY_DOOR,		T_PolyDoor,		NULL,		NULL,		sizeof(polydoor_t)	},	{		TC_FLOOR_WAGGLE,		T_FloorWaggle,		MangleSSThinker,		RestoreSSThinker,		sizeof(floorWaggle_t)	},	{ // Terminator		TC_NULL, NULL, NULL, NULL, 0	}};// CODE --------------------------------------------------------------------//==========================================================================//// SV_SaveGame////==========================================================================void SV_SaveGame(int slot, char *description){	char fileName[100];	char versionText[HXS_VERSION_TEXT_LENGTH];	// Open the output file	sprintf(fileName, "%shex6.hxs", SavePath);	OpenStreamOut(fileName);	// Write game save description	StreamOutBuffer(description, HXS_DESCRIPTION_LENGTH);	// Write version info	memset(versionText, 0, HXS_VERSION_TEXT_LENGTH);	strcpy(versionText, HXS_VERSION_TEXT);	StreamOutBuffer(versionText, HXS_VERSION_TEXT_LENGTH);	// Place a header marker	StreamOutLong(ASEG_GAME_HEADER);	// Write current map and difficulty	StreamOutByte(gamemap);	StreamOutByte(gameskill);	// Write global script info	StreamOutBuffer(WorldVars, sizeof(WorldVars));	StreamOutBuffer(ACSStore, sizeof(ACSStore));	ArchivePlayers();	// Place a termination marker	StreamOutLong(ASEG_END);	// Close the output file	CloseStreamOut();	// Save out the current map	SV_SaveMap(true); // true = save player info	// Clear all save files at destination slot	ClearSaveSlot(slot);	// Copy base slot to destination slot	CopySaveSlot(BASE_SLOT, slot);}//==========================================================================//// SV_SaveMap////==========================================================================void SV_SaveMap(boolean savePlayers){	char fileName[100];	SavingPlayers = savePlayers;	// Open the output file	sprintf(fileName, "%shex6%02d.hxs", SavePath, gamemap);	OpenStreamOut(fileName);	// Place a header marker	StreamOutLong(ASEG_MAP_HEADER);	// Write the level timer	StreamOutLong(leveltime);	// Set the mobj archive numbers	SetMobjArchiveNums();	ArchiveWorld();	ArchivePolyobjs();	ArchiveMobjs();	ArchiveThinkers();	ArchiveScripts();	ArchiveSounds();	ArchiveMisc();	// Place a termination marker	StreamOutLong(ASEG_END);	// Close the output file	CloseStreamOut();}//==========================================================================//// SV_LoadGame////==========================================================================void SV_LoadGame(int slot){	int i;	char fileName[100];	player_t playerBackup[MAXPLAYERS];	mobj_t *mobj;	// Copy all needed save files to the base slot	if(slot != BASE_SLOT)	{		ClearSaveSlot(BASE_SLOT);		CopySaveSlot(slot, BASE_SLOT);	}	// Create the name	sprintf(fileName, "%shex6.hxs", SavePath);	// Load the file	M_ReadFile(fileName, &SaveBuffer);	// Set the save pointer and skip the description field	SavePtr.b = SaveBuffer+HXS_DESCRIPTION_LENGTH;	// Check the version text	if(strcmp(SavePtr.b, HXS_VERSION_TEXT))	{ // Bad version		return;	}	SavePtr.b += HXS_VERSION_TEXT_LENGTH;	AssertSegment(ASEG_GAME_HEADER);	gameepisode = 1;	gamemap = GET_BYTE;	gameskill = GET_BYTE;	// Read global script info	memcpy(WorldVars, SavePtr.b, sizeof(WorldVars));	SavePtr.b += sizeof(WorldVars);	memcpy(ACSStore, SavePtr.b, sizeof(ACSStore));	SavePtr.b += sizeof(ACSStore);	// Read the player structures	UnarchivePlayers();	AssertSegment(ASEG_END);	Z_Free(SaveBuffer);	// Save player structs	for(i = 0; i < MAXPLAYERS; i++)	{		playerBackup[i] = players[i];	}	// Load the current map	SV_LoadMap();	// Don't need the player mobj relocation info for load game	Z_Free(TargetPlayerAddrs);	// Restore player structs	inv_ptr = 0;	curpos = 0;	for(i = 0; i < MAXPLAYERS; i++)	{		mobj = players[i].mo;		players[i] = playerBackup[i];		players[i].mo = mobj;		if(i == consoleplayer)		{			players[i].readyArtifact = players[i].inventory[inv_ptr].type;		}	}}//==========================================================================//// SV_UpdateRebornSlot//// Copies the base slot to the reborn slot.////==========================================================================void SV_UpdateRebornSlot(void){	ClearSaveSlot(REBORN_SLOT);	CopySaveSlot(BASE_SLOT, REBORN_SLOT);}//==========================================================================//// SV_ClearRebornSlot////==========================================================================void SV_ClearRebornSlot(void){	ClearSaveSlot(REBORN_SLOT);}//==========================================================================//// SV_MapTeleport////==========================================================================void SV_MapTeleport(int map, int position){	int i;	int j;	char fileName[100];	player_t playerBackup[MAXPLAYERS];	mobj_t *targetPlayerMobj;	mobj_t *mobj;	int inventoryPtr;	int currentInvPos;	boolean rClass;	boolean playerWasReborn;	boolean oldWeaponowned[NUMWEAPONS];	int oldKeys;	int oldPieces;	int bestWeapon;	if(!deathmatch)	{		if(P_GetMapCluster(gamemap) == P_GetMapCluster(map))		{ // Same cluster - save map without saving player mobjs			SV_SaveMap(false);		}		else		{ // Entering new cluster - clear base slot			ClearSaveSlot(BASE_SLOT);		}	}	// Store player structs for later	rClass = randomclass;	randomclass = false;	for(i = 0; i < MAXPLAYERS; i++)	{		playerBackup[i] = players[i];	}	// Save some globals that get trashed during the load	inventoryPtr = inv_ptr;	currentInvPos = curpos;	// Only SV_LoadMap() uses TargetPlayerAddrs, so it's NULLed here	// for the following check (player mobj redirection)	TargetPlayerAddrs = NULL;	gamemap = map;	sprintf(fileName, "%shex6%02d.hxs", SavePath, gamemap);	if(!deathmatch && ExistingFile(fileName))	{ // Unarchive map		SV_LoadMap();	}	else	{ // New map		G_InitNew(gameskill, gameepisode, gamemap);		// Destroy all freshly spawned players		for(i = 0; i < MAXPLAYERS; i++)		{			if(playeringame[i])			{				P_RemoveMobj(players[i].mo);			}		}	}	// Restore player structs	targetPlayerMobj = NULL;	for(i = 0; i < MAXPLAYERS; i++)	{		if(!playeringame[i])		{			continue;		}		players[i] = playerBackup[i];		P_ClearMessage(&players[i]);		players[i].attacker = NULL;		players[i].poisoner = NULL;		if(netgame)		{			if(players[i].playerstate == PST_DEAD)			{ // In a network game, force all players to be alive				players[i].playerstate = PST_REBORN;			}			if(!deathmatch)			{ // Cooperative net-play, retain keys and weapons				oldKeys = players[i].keys;				oldPieces = players[i].pieces;				for(j = 0; j < NUMWEAPONS; j++)				{					oldWeaponowned[j] = players[i].weaponowned[j];				}			}		}		playerWasReborn = (players[i].playerstate == PST_REBORN);		if(deathmatch)		{			memset(players[i].frags, 0, sizeof(players[i].frags));			mobj = P_SpawnMobj(playerstarts[0][i].x<<16,				playerstarts[0][i].y<<16, 0, MT_PLAYER_FIGHTER);			players[i].mo = mobj;			G_DeathMatchSpawnPlayer(i);			P_RemoveMobj(mobj);		}		else		{			P_SpawnPlayer(&playerstarts[position][i]);		}		if(playerWasReborn && netgame && !deathmatch)		{ // Restore keys and weapons when reborn in co-op			players[i].keys = oldKeys;			players[i].pieces = oldPieces;			for(bestWeapon = 0, j = 0; j < NUMWEAPONS; j++)			{				if(oldWeaponowned[j])				{					bestWeapon = j;					players[i].weaponowned[j] = true;				}			}			players[i].mana[MANA_1] = 25;			players[i].mana[MANA_2] = 25;			if(bestWeapon)			{ // Bring up the best weapon				players[i].pendingweapon = bestWeapon;			}		}		if(targetPlayerMobj == NULL)		{ // The poor sap			targetPlayerMobj = players[i].mo;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -