mirror of
https://github.com/yquake2/ctf.git
synced 2024-11-22 20:01:03 +00:00
Reformat g_save.c
This commit is contained in:
parent
0f1fbc8290
commit
f13b82939e
1 changed files with 508 additions and 452 deletions
410
src/g_save.c
410
src/g_save.c
|
@ -1,21 +1,29 @@
|
|||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
* Copyright (C) 1997-2001 Id Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* The savegame system. Unused by the CTF game but nevertheless called
|
||||
* during game initialization. Therefor no new savegame code ist
|
||||
* imported.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#include "header/local.h"
|
||||
|
@ -54,7 +62,7 @@ field_t fields[] = {
|
|||
{"attenuation", FOFS(attenuation), F_FLOAT},
|
||||
{"map", FOFS(map), F_LSTRING},
|
||||
|
||||
// temp spawn vars -- only valid when the spawn function is called
|
||||
/* temp spawn vars -- only valid when the spawn function is called */
|
||||
{"lip", STOFS(lip), F_INT, FFL_SPAWNTEMP},
|
||||
{"distance", STOFS(distance), F_INT, FFL_SPAWNTEMP},
|
||||
{"height", STOFS(height), F_INT, FFL_SPAWNTEMP},
|
||||
|
@ -72,16 +80,7 @@ field_t fields[] = {
|
|||
{"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP}
|
||||
};
|
||||
|
||||
// -------- just for savegames ----------
|
||||
// all pointer fields should be listed here, or savegames
|
||||
// won't work properly (they will crash and burn).
|
||||
// this wasn't just tacked on to the fields array, because
|
||||
// these don't need names, we wouldn't want map fields using
|
||||
// some of these, and if one were accidentally present twice
|
||||
// it would double swizzle (fuck) the pointer.
|
||||
|
||||
field_t savefields[] =
|
||||
{
|
||||
field_t savefields[] = {
|
||||
{"", FOFS(classname), F_LSTRING},
|
||||
{"", FOFS(target), F_LSTRING},
|
||||
{"", FOFS(targetname), F_LSTRING},
|
||||
|
@ -114,8 +113,7 @@ field_t savefields[] =
|
|||
{NULL, 0, F_INT}
|
||||
};
|
||||
|
||||
field_t levelfields[] =
|
||||
{
|
||||
field_t levelfields[] = {
|
||||
{"", LLOFS(changemap), F_LSTRING},
|
||||
|
||||
{"", LLOFS(sight_client), F_EDICT},
|
||||
|
@ -126,8 +124,7 @@ field_t levelfields[] =
|
|||
{NULL, 0, F_INT}
|
||||
};
|
||||
|
||||
field_t clientfields[] =
|
||||
{
|
||||
field_t clientfields[] = {
|
||||
{"", CLOFS(pers.weapon), F_ITEM},
|
||||
{"", CLOFS(pers.lastweapon), F_ITEM},
|
||||
{"", CLOFS(newweapon), F_ITEM},
|
||||
|
@ -136,15 +133,12 @@ field_t clientfields[] =
|
|||
};
|
||||
|
||||
/*
|
||||
============
|
||||
InitGame
|
||||
|
||||
This will be called when the dll is first loaded, which
|
||||
only happens when a new game is started or a save game
|
||||
is loaded.
|
||||
============
|
||||
* This will be called when the dll is first loaded, which
|
||||
* only happens when a new game is started or a save game
|
||||
* is loaded.
|
||||
*/
|
||||
void InitGame (void)
|
||||
void
|
||||
InitGame(void)
|
||||
{
|
||||
gi.dprintf("Game is starting up.\n");
|
||||
gi.dprintf("Game is ctf.\n");
|
||||
|
@ -152,98 +146,91 @@ void InitGame (void)
|
|||
gun_x = gi.cvar("gun_x", "0", 0);
|
||||
gun_y = gi.cvar("gun_y", "0", 0);
|
||||
gun_z = gi.cvar("gun_z", "0", 0);
|
||||
|
||||
//FIXME: sv_ prefix is wrong for these
|
||||
sv_rollspeed = gi.cvar("sv_rollspeed", "200", 0);
|
||||
sv_rollangle = gi.cvar("sv_rollangle", "2", 0);
|
||||
sv_maxvelocity = gi.cvar("sv_maxvelocity", "2000", 0);
|
||||
sv_gravity = gi.cvar("sv_gravity", "800", 0);
|
||||
|
||||
// noset vars
|
||||
/* noset vars */
|
||||
dedicated = gi.cvar("dedicated", "0", CVAR_NOSET);
|
||||
|
||||
// latched vars
|
||||
/* latched vars */
|
||||
sv_cheats = gi.cvar("cheats", "0", CVAR_SERVERINFO | CVAR_LATCH);
|
||||
gi.cvar("gamename", GAMEVERSION, CVAR_SERVERINFO | CVAR_LATCH);
|
||||
gi.cvar("gamedate", __DATE__, CVAR_SERVERINFO | CVAR_LATCH);
|
||||
|
||||
maxclients = gi.cvar("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH);
|
||||
deathmatch = gi.cvar("deathmatch", "0", CVAR_LATCH);
|
||||
coop = gi.cvar("coop", "0", CVAR_LATCH);
|
||||
skill = gi.cvar("skill", "1", CVAR_LATCH);
|
||||
maxentities = gi.cvar("maxentities", "1024", CVAR_LATCH);
|
||||
|
||||
//ZOID
|
||||
//This game.dll only supports deathmatch
|
||||
if (!deathmatch->value) {
|
||||
/* This game.dll only supports deathmatch */
|
||||
if (!deathmatch->value)
|
||||
{
|
||||
gi.dprintf("Forcing deathmatch.\n");
|
||||
gi.cvar_set("deathmatch", "1");
|
||||
}
|
||||
//force coop off
|
||||
|
||||
/* force coop off */
|
||||
if (coop->value)
|
||||
{
|
||||
gi.cvar_set("coop", "0");
|
||||
//ZOID
|
||||
}
|
||||
|
||||
|
||||
// change anytime vars
|
||||
/* change anytime vars */
|
||||
dmflags = gi.cvar("dmflags", "0", CVAR_SERVERINFO);
|
||||
fraglimit = gi.cvar("fraglimit", "0", CVAR_SERVERINFO);
|
||||
timelimit = gi.cvar("timelimit", "0", CVAR_SERVERINFO);
|
||||
//ZOID
|
||||
capturelimit = gi.cvar("capturelimit", "0", CVAR_SERVERINFO);
|
||||
instantweap = gi.cvar("instantweap", "0", CVAR_SERVERINFO);
|
||||
//ZOID
|
||||
password = gi.cvar("password", "", CVAR_USERINFO);
|
||||
filterban = gi.cvar("filterban", "1", 0);
|
||||
|
||||
g_select_empty = gi.cvar("g_select_empty", "0", CVAR_ARCHIVE);
|
||||
|
||||
run_pitch = gi.cvar("run_pitch", "0.002", 0);
|
||||
run_roll = gi.cvar("run_roll", "0.005", 0);
|
||||
bob_up = gi.cvar("bob_up", "0.005", 0);
|
||||
bob_pitch = gi.cvar("bob_pitch", "0.002", 0);
|
||||
bob_roll = gi.cvar("bob_roll", "0.002", 0);
|
||||
|
||||
// flood control
|
||||
/* flood control */
|
||||
flood_msgs = gi.cvar("flood_msgs", "4", 0);
|
||||
flood_persecond = gi.cvar("flood_persecond", "4", 0);
|
||||
flood_waitdelay = gi.cvar("flood_waitdelay", "10", 0);
|
||||
|
||||
// dm map list
|
||||
/* dm map list */
|
||||
sv_maplist = gi.cvar("sv_maplist", "", 0);
|
||||
|
||||
// items
|
||||
/* items */
|
||||
InitItems();
|
||||
|
||||
Com_sprintf(game.helpmessage1, sizeof(game.helpmessage1), "");
|
||||
|
||||
Com_sprintf(game.helpmessage2, sizeof(game.helpmessage2), "");
|
||||
|
||||
// initialize all entities for this game
|
||||
/* initialize all entities for this game */
|
||||
game.maxentities = maxentities->value;
|
||||
g_edicts = gi.TagMalloc(game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
|
||||
globals.edicts = g_edicts;
|
||||
globals.max_edicts = game.maxentities;
|
||||
|
||||
// initialize all clients for this game
|
||||
/* initialize all clients for this game */
|
||||
game.maxclients = maxclients->value;
|
||||
game.clients = gi.TagMalloc(game.maxclients * sizeof(game.clients[0]), TAG_GAME);
|
||||
globals.num_edicts = game.maxclients + 1;
|
||||
|
||||
//ZOID
|
||||
CTFInit();
|
||||
//ZOID
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
/* ========================================================= */
|
||||
|
||||
void WriteField1 (FILE *f, field_t *field, byte *base)
|
||||
void
|
||||
WriteField1(FILE *f, field_t *field, byte *base)
|
||||
{
|
||||
void *p;
|
||||
int len;
|
||||
int index;
|
||||
|
||||
p = (void *)(base + field->ofs);
|
||||
|
||||
switch (field->type)
|
||||
{
|
||||
case F_INT:
|
||||
|
@ -255,31 +242,55 @@ void WriteField1 (FILE *f, field_t *field, byte *base)
|
|||
|
||||
case F_LSTRING:
|
||||
case F_GSTRING:
|
||||
|
||||
if (*(char **)p)
|
||||
{
|
||||
len = strlen(*(char **)p) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = 0;
|
||||
}
|
||||
|
||||
*(int *)p = len;
|
||||
break;
|
||||
case F_EDICT:
|
||||
|
||||
if (*(edict_t **)p == NULL)
|
||||
{
|
||||
index = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = *(edict_t **)p - g_edicts;
|
||||
}
|
||||
|
||||
*(int *)p = index;
|
||||
break;
|
||||
case F_CLIENT:
|
||||
|
||||
if (*(gclient_t **)p == NULL)
|
||||
{
|
||||
index = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = *(gclient_t **)p - game.clients;
|
||||
}
|
||||
|
||||
*(int *)p = index;
|
||||
break;
|
||||
case F_ITEM:
|
||||
|
||||
if (*(edict_t **)p == NULL)
|
||||
{
|
||||
index = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = *(gitem_t **)p - itemlist;
|
||||
}
|
||||
|
||||
*(int *)p = index;
|
||||
break;
|
||||
|
||||
|
@ -288,34 +299,40 @@ void WriteField1 (FILE *f, field_t *field, byte *base)
|
|||
}
|
||||
}
|
||||
|
||||
void WriteField2 (FILE *f, field_t *field, byte *base)
|
||||
void
|
||||
WriteField2(FILE *f, field_t *field, byte *base)
|
||||
{
|
||||
int len;
|
||||
void *p;
|
||||
|
||||
p = (void *)(base + field->ofs);
|
||||
|
||||
switch (field->type)
|
||||
{
|
||||
case F_LSTRING:
|
||||
case F_GSTRING:
|
||||
|
||||
if (*(char **)p)
|
||||
{
|
||||
len = strlen(*(char **)p) + 1;
|
||||
fwrite(*(char **)p, len, 1, f);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadField (FILE *f, field_t *field, byte *base)
|
||||
void
|
||||
ReadField(FILE *f, field_t *field, byte *base)
|
||||
{
|
||||
void *p;
|
||||
int len;
|
||||
int index;
|
||||
|
||||
p = (void *)(base + field->ofs);
|
||||
|
||||
switch (field->type)
|
||||
{
|
||||
case F_INT:
|
||||
|
@ -327,44 +344,70 @@ void ReadField (FILE *f, field_t *field, byte *base)
|
|||
|
||||
case F_LSTRING:
|
||||
len = *(int *)p;
|
||||
|
||||
if (!len)
|
||||
{
|
||||
*(char **)p = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(char **)p = gi.TagMalloc(len, TAG_LEVEL);
|
||||
fread(*(char **)p, len, 1, f);
|
||||
}
|
||||
|
||||
break;
|
||||
case F_GSTRING:
|
||||
len = *(int *)p;
|
||||
|
||||
if (!len)
|
||||
{
|
||||
*(char **)p = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(char **)p = gi.TagMalloc(len, TAG_GAME);
|
||||
fread(*(char **)p, len, 1, f);
|
||||
}
|
||||
|
||||
break;
|
||||
case F_EDICT:
|
||||
index = *(int *)p;
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
*(edict_t **)p = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(edict_t **)p = &g_edicts[index];
|
||||
}
|
||||
|
||||
break;
|
||||
case F_CLIENT:
|
||||
index = *(int *)p;
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
*(gclient_t **)p = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(gclient_t **)p = &game.clients[index];
|
||||
}
|
||||
|
||||
break;
|
||||
case F_ITEM:
|
||||
index = *(int *)p;
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
*(gitem_t **)p = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(gitem_t **)p = &itemlist[index];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -372,33 +415,31 @@ void ReadField (FILE *f, field_t *field, byte *base)
|
|||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
/* ========================================================= */
|
||||
|
||||
/*
|
||||
==============
|
||||
WriteClient
|
||||
|
||||
All pointer variables (except function pointers) must be handled specially.
|
||||
==============
|
||||
* All pointer variables (except function
|
||||
* pointers) must be handled specially.
|
||||
*/
|
||||
void WriteClient (FILE *f, gclient_t *client)
|
||||
void
|
||||
WriteClient(FILE *f, gclient_t *client)
|
||||
{
|
||||
field_t *field;
|
||||
gclient_t temp;
|
||||
|
||||
// all of the ints, floats, and vectors stay as they are
|
||||
/* all of the ints, floats, and vectors stay as they are */
|
||||
temp = *client;
|
||||
|
||||
// change the pointers to lengths or indexes
|
||||
/* change the pointers to lengths or indexes */
|
||||
for (field = clientfields; field->name; field++)
|
||||
{
|
||||
WriteField1(f, field, (byte *)&temp);
|
||||
}
|
||||
|
||||
// write the block
|
||||
/* write the block */
|
||||
fwrite(&temp, sizeof(temp), 1, f);
|
||||
|
||||
// now write any allocated data following the edict
|
||||
/* now write any allocated data following the edict */
|
||||
for (field = clientfields; field->name; field++)
|
||||
{
|
||||
WriteField2(f, field, (byte *)client);
|
||||
|
@ -406,13 +447,11 @@ void WriteClient (FILE *f, gclient_t *client)
|
|||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
ReadClient
|
||||
|
||||
All pointer variables (except function pointers) must be handled specially.
|
||||
==============
|
||||
* All pointer variables (except function
|
||||
* pointers) must be handled specially.
|
||||
*/
|
||||
void ReadClient (FILE *f, gclient_t *client)
|
||||
void
|
||||
ReadClient(FILE *f, gclient_t *client)
|
||||
{
|
||||
field_t *field;
|
||||
|
||||
|
@ -425,31 +464,33 @@ void ReadClient (FILE *f, gclient_t *client)
|
|||
}
|
||||
|
||||
/*
|
||||
============
|
||||
WriteGame
|
||||
|
||||
This will be called whenever the game goes to a new level,
|
||||
and when the user explicitly saves the game.
|
||||
|
||||
Game information include cross level data, like multi level
|
||||
triggers, help computer info, and all client states.
|
||||
|
||||
A single player death will automatically restore from the
|
||||
last save position.
|
||||
============
|
||||
* This will be called whenever the game goes to a new level,
|
||||
* and when the user explicitly saves the game.
|
||||
*
|
||||
* Game information include cross level data, like multi level
|
||||
* triggers, help computer info, and all client states.
|
||||
*
|
||||
* A single player death will automatically restore from the
|
||||
* last save position.
|
||||
*/
|
||||
void WriteGame (char *filename, qboolean autosave)
|
||||
void
|
||||
WriteGame(char *filename, qboolean autosave)
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
char str[16];
|
||||
|
||||
if (!autosave)
|
||||
{
|
||||
SaveClientData();
|
||||
}
|
||||
|
||||
f = fopen(filename, "wb");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
gi.error("Couldn't open %s", filename);
|
||||
}
|
||||
|
||||
memset(str, 0, sizeof(str));
|
||||
strcpy(str, __DATE__);
|
||||
|
@ -460,12 +501,15 @@ void WriteGame (char *filename, qboolean autosave)
|
|||
game.autosaved = false;
|
||||
|
||||
for (i = 0; i < game.maxclients; i++)
|
||||
{
|
||||
WriteClient(f, &game.clients[i]);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void ReadGame (char *filename)
|
||||
void
|
||||
ReadGame(char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
|
@ -474,10 +518,14 @@ void ReadGame (char *filename)
|
|||
gi.FreeTags(TAG_GAME);
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
gi.error("Couldn't open %s", filename);
|
||||
}
|
||||
|
||||
fread(str, sizeof(str), 1, f);
|
||||
|
||||
if (strcmp(str, __DATE__))
|
||||
{
|
||||
fclose(f);
|
||||
|
@ -489,87 +537,81 @@ void ReadGame (char *filename)
|
|||
|
||||
fread(&game, sizeof(game), 1, f);
|
||||
game.clients = gi.TagMalloc(game.maxclients * sizeof(game.clients[0]), TAG_GAME);
|
||||
|
||||
for (i = 0; i < game.maxclients; i++)
|
||||
{
|
||||
ReadClient(f, &game.clients[i]);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
/* ========================================================== */
|
||||
|
||||
/*
|
||||
==============
|
||||
WriteEdict
|
||||
|
||||
All pointer variables (except function pointers) must be handled specially.
|
||||
==============
|
||||
* All pointer variables (except function
|
||||
* pointers) must be handled specially.
|
||||
*/
|
||||
void WriteEdict (FILE *f, edict_t *ent)
|
||||
void
|
||||
WriteEdict(FILE *f, edict_t *ent)
|
||||
{
|
||||
field_t *field;
|
||||
edict_t temp;
|
||||
|
||||
// all of the ints, floats, and vectors stay as they are
|
||||
/* all of the ints, floats, and vectors stay as they are */
|
||||
temp = *ent;
|
||||
|
||||
// change the pointers to lengths or indexes
|
||||
/* change the pointers to lengths or indexes */
|
||||
for (field = savefields; field->name; field++)
|
||||
{
|
||||
WriteField1(f, field, (byte *)&temp);
|
||||
}
|
||||
|
||||
// write the block
|
||||
/* write the block */
|
||||
fwrite(&temp, sizeof(temp), 1, f);
|
||||
|
||||
// now write any allocated data following the edict
|
||||
/* now write any allocated data following the edict */
|
||||
for (field = savefields; field->name; field++)
|
||||
{
|
||||
WriteField2(f, field, (byte *)ent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
WriteLevelLocals
|
||||
|
||||
All pointer variables (except function pointers) must be handled specially.
|
||||
==============
|
||||
* All pointer variables (except function
|
||||
* pointers) must be handled specially.
|
||||
*/
|
||||
void WriteLevelLocals (FILE *f)
|
||||
void
|
||||
WriteLevelLocals(FILE *f)
|
||||
{
|
||||
field_t *field;
|
||||
level_locals_t temp;
|
||||
|
||||
// all of the ints, floats, and vectors stay as they are
|
||||
/* all of the ints, floats, and vectors stay as they are */
|
||||
temp = level;
|
||||
|
||||
// change the pointers to lengths or indexes
|
||||
/* change the pointers to lengths or indexes */
|
||||
for (field = levelfields; field->name; field++)
|
||||
{
|
||||
WriteField1(f, field, (byte *)&temp);
|
||||
}
|
||||
|
||||
// write the block
|
||||
/* write the block */
|
||||
fwrite(&temp, sizeof(temp), 1, f);
|
||||
|
||||
// now write any allocated data following the edict
|
||||
/* now write any allocated data following the edict */
|
||||
for (field = levelfields; field->name; field++)
|
||||
{
|
||||
WriteField2(f, field, (byte *)&level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
ReadEdict
|
||||
|
||||
All pointer variables (except function pointers) must be handled specially.
|
||||
==============
|
||||
* All pointer variables (except function
|
||||
* pointers) must be handled specially.
|
||||
*/
|
||||
void ReadEdict (FILE *f, edict_t *ent)
|
||||
void
|
||||
ReadEdict(FILE *f, edict_t *ent)
|
||||
{
|
||||
field_t *field;
|
||||
|
||||
|
@ -582,13 +624,11 @@ void ReadEdict (FILE *f, edict_t *ent)
|
|||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
ReadLevelLocals
|
||||
|
||||
All pointer variables (except function pointers) must be handled specially.
|
||||
==============
|
||||
* All pointer variables (except function
|
||||
* pointers) must be handled specially.
|
||||
*/
|
||||
void ReadLevelLocals (FILE *f)
|
||||
void
|
||||
ReadLevelLocals(FILE *f)
|
||||
{
|
||||
field_t *field;
|
||||
|
||||
|
@ -600,13 +640,8 @@ void ReadLevelLocals (FILE *f)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
WriteLevel
|
||||
|
||||
=================
|
||||
*/
|
||||
void WriteLevel (char *filename)
|
||||
void
|
||||
WriteLevel(char *filename)
|
||||
{
|
||||
int i;
|
||||
edict_t *ent;
|
||||
|
@ -614,53 +649,57 @@ void WriteLevel (char *filename)
|
|||
void *base;
|
||||
|
||||
f = fopen(filename, "wb");
|
||||
if (!f)
|
||||
gi.error ("Couldn't open %s", filename);
|
||||
|
||||
// write out edict size for checking
|
||||
if (!f)
|
||||
{
|
||||
gi.error("Couldn't open %s", filename);
|
||||
}
|
||||
|
||||
/* write out edict size for checking */
|
||||
i = sizeof(edict_t);
|
||||
fwrite(&i, sizeof(i), 1, f);
|
||||
|
||||
// write out a function pointer for checking
|
||||
/* write out a function pointer for checking */
|
||||
base = (void *)InitGame;
|
||||
fwrite(&base, sizeof(base), 1, f);
|
||||
|
||||
// write out level_locals_t
|
||||
/* write out level_locals_t */
|
||||
WriteLevelLocals(f);
|
||||
|
||||
// write out all the entities
|
||||
/* write out all the entities */
|
||||
for (i = 0; i < globals.num_edicts; i++)
|
||||
{
|
||||
ent = &g_edicts[i];
|
||||
|
||||
if (!ent->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fwrite(&i, sizeof(i), 1, f);
|
||||
WriteEdict(f, ent);
|
||||
}
|
||||
|
||||
i = -1;
|
||||
fwrite(&i, sizeof(i), 1, f);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
ReadLevel
|
||||
|
||||
SpawnEntities will allready have been called on the
|
||||
level the same way it was when the level was saved.
|
||||
|
||||
That is necessary to get the baselines
|
||||
set up identically.
|
||||
|
||||
The server will have cleared all of the world links before
|
||||
calling ReadLevel.
|
||||
|
||||
No clients are connected yet.
|
||||
=================
|
||||
* SpawnEntities will allready have been called on the
|
||||
* level the same way it was when the level was saved.
|
||||
*
|
||||
* That is necessary to get the baselines
|
||||
* set up identically.
|
||||
*
|
||||
* The server will have cleared all of the world links before
|
||||
* calling ReadLevel.
|
||||
*
|
||||
* No clients are connected yet.
|
||||
*/
|
||||
void ReadLevel (char *filename)
|
||||
void
|
||||
ReadLevel(char *filename)
|
||||
{
|
||||
int entnum;
|
||||
FILE *f;
|
||||
|
@ -669,37 +708,42 @@ void ReadLevel (char *filename)
|
|||
edict_t *ent;
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
if (!f)
|
||||
gi.error ("Couldn't open %s", filename);
|
||||
|
||||
// free any dynamic memory allocated by loading the level
|
||||
// base state
|
||||
if (!f)
|
||||
{
|
||||
gi.error("Couldn't open %s", filename);
|
||||
}
|
||||
|
||||
/* free any dynamic memory allocated by
|
||||
loading the level base state */
|
||||
gi.FreeTags(TAG_LEVEL);
|
||||
|
||||
// wipe all the entities
|
||||
/* wipe all the entities */
|
||||
memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0]));
|
||||
globals.num_edicts = maxclients->value + 1;
|
||||
|
||||
// check edict size
|
||||
/* check edict size */
|
||||
fread(&i, sizeof(i), 1, f);
|
||||
|
||||
if (i != sizeof(edict_t))
|
||||
{
|
||||
fclose(f);
|
||||
gi.error("ReadLevel: mismatched edict size");
|
||||
}
|
||||
|
||||
// check function pointer base address
|
||||
/* check function pointer base address */
|
||||
fread(&base, sizeof(base), 1, f);
|
||||
|
||||
if (base != (void *)InitGame)
|
||||
{
|
||||
fclose(f);
|
||||
gi.error("ReadLevel: function pointers have moved");
|
||||
}
|
||||
|
||||
// load the level locals
|
||||
/* load the level locals */
|
||||
ReadLevelLocals(f);
|
||||
|
||||
// load all the entities
|
||||
/* load all the entities */
|
||||
while (1)
|
||||
{
|
||||
if (fread(&entnum, sizeof(entnum), 1, f) != 1)
|
||||
|
@ -707,22 +751,28 @@ void ReadLevel (char *filename)
|
|||
fclose(f);
|
||||
gi.error("ReadLevel: failed to read entnum");
|
||||
}
|
||||
|
||||
if (entnum == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (entnum >= globals.num_edicts)
|
||||
{
|
||||
globals.num_edicts = entnum + 1;
|
||||
}
|
||||
|
||||
ent = &g_edicts[entnum];
|
||||
ReadEdict(f, ent);
|
||||
|
||||
// let the server rebuild world links for this ent
|
||||
/* let the server rebuild world links for this ent */
|
||||
memset(&ent->area, 0, sizeof(ent->area));
|
||||
gi.linkentity(ent);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
// mark all clients as unconnected
|
||||
/* mark all clients as unconnected */
|
||||
for (i = 0; i < maxclients->value; i++)
|
||||
{
|
||||
ent = &g_edicts[i + 1];
|
||||
|
@ -730,18 +780,24 @@ void ReadLevel (char *filename)
|
|||
ent->client->pers.connected = false;
|
||||
}
|
||||
|
||||
// do any load time things at this point
|
||||
/* do any load time things at this point */
|
||||
for (i = 0; i < globals.num_edicts; i++)
|
||||
{
|
||||
ent = &g_edicts[i];
|
||||
|
||||
if (!ent->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// fire any cross-level triggers
|
||||
/* fire any cross-level triggers */
|
||||
if (ent->classname)
|
||||
{
|
||||
if (strcmp(ent->classname, "target_crosslevel_target") == 0)
|
||||
{
|
||||
ent->nextthink = level.time + ent->delay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue