diff --git a/src/g_save.c b/src/g_save.c index 0b77bf9..aeeb86c 100644 --- a/src/g_save.c +++ b/src/g_save.c @@ -1,22 +1,30 @@ /* -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,612 +133,671 @@ 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. -============ -*/ -void InitGame (void) + * 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) { - gi.dprintf ("Game is starting up.\n"); - gi.dprintf ("Game is ctf.\n"); + gi.dprintf("Game is starting up.\n"); + gi.dprintf("Game is ctf.\n"); - gun_x = gi.cvar ("gun_x", "0", 0); - gun_y = gi.cvar ("gun_y", "0", 0); - gun_z = gi.cvar ("gun_z", "0", 0); + gun_x = gi.cvar("gun_x", "0", 0); + gun_y = gi.cvar("gun_y", "0", 0); + gun_z = gi.cvar("gun_z", "0", 0); + 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); - //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 */ + dedicated = gi.cvar("dedicated", "0", CVAR_NOSET); - // noset vars - dedicated = gi.cvar ("dedicated", "0", CVAR_NOSET); + /* 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); - // 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 */ + dmflags = gi.cvar("dmflags", "0", CVAR_SERVERINFO); + fraglimit = gi.cvar("fraglimit", "0", CVAR_SERVERINFO); + timelimit = gi.cvar("timelimit", "0", CVAR_SERVERINFO); + capturelimit = gi.cvar("capturelimit", "0", CVAR_SERVERINFO); + instantweap = gi.cvar("instantweap", "0", CVAR_SERVERINFO); + 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); - // 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); + /* 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); - g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE); + /* dm map list */ + sv_maplist = gi.cvar("sv_maplist", "", 0); - 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); + /* items */ + InitItems(); - // 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); + Com_sprintf(game.helpmessage1, sizeof(game.helpmessage1), ""); + Com_sprintf(game.helpmessage2, sizeof(game.helpmessage2), ""); - // dm map list - sv_maplist = gi.cvar ("sv_maplist", "", 0); - - // 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); + 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; + 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; + void *p; + int len; + int index; p = (void *)(base + field->ofs); + switch (field->type) { - case F_INT: - case F_FLOAT: - case F_ANGLEHACK: - case F_VECTOR: - case F_IGNORE: - break; + case F_INT: + case F_FLOAT: + case F_ANGLEHACK: + case F_VECTOR: + case F_IGNORE: + break; - 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; + case F_LSTRING: + case F_GSTRING: - default: - gi.error ("WriteEdict: unknown field type"); + 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; + + default: + gi.error("WriteEdict: unknown field type"); } } -void WriteField2 (FILE *f, field_t *field, byte *base) +void +WriteField2(FILE *f, field_t *field, byte *base) { - int len; - void *p; + 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; + 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; + void *p; + int len; + int index; p = (void *)(base + field->ofs); + switch (field->type) { - case F_INT: - case F_FLOAT: - case F_ANGLEHACK: - case F_VECTOR: - case F_IGNORE: - break; + case F_INT: + case F_FLOAT: + case F_ANGLEHACK: + case F_VECTOR: + case F_IGNORE: + break; - 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; + case F_LSTRING: + len = *(int *)p; - default: - gi.error ("ReadEdict: unknown field type"); + 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: + gi.error("ReadEdict: unknown field type"); } } -//========================================================= +/* ========================================================= */ /* -============== -WriteClient - -All pointer variables (except function pointers) must be handled specially. -============== -*/ -void WriteClient (FILE *f, gclient_t *client) + * All pointer variables (except function + * pointers) must be handled specially. + */ +void +WriteClient(FILE *f, gclient_t *client) { - field_t *field; - gclient_t temp; - - // all of the ints, floats, and vectors stay as they are + field_t *field; + gclient_t temp; + + /* all of the ints, floats, and vectors stay as they are */ temp = *client; - // change the pointers to lengths or indexes - for (field=clientfields ; field->name ; field++) + /* change the pointers to lengths or indexes */ + for (field = clientfields; field->name; field++) { - WriteField1 (f, field, (byte *)&temp); + WriteField1(f, field, (byte *)&temp); } - // write the block - fwrite (&temp, sizeof(temp), 1, f); + /* write the block */ + fwrite(&temp, sizeof(temp), 1, f); - // now write any allocated data following the edict - for (field=clientfields ; field->name ; field++) + /* now write any allocated data following the edict */ + for (field = clientfields; field->name; field++) { - WriteField2 (f, field, (byte *)client); + WriteField2(f, field, (byte *)client); } } /* -============== -ReadClient - -All pointer variables (except function pointers) must be handled specially. -============== -*/ -void ReadClient (FILE *f, gclient_t *client) + * All pointer variables (except function + * pointers) must be handled specially. + */ +void +ReadClient(FILE *f, gclient_t *client) { - field_t *field; + field_t *field; - fread (client, sizeof(*client), 1, f); + fread(client, sizeof(*client), 1, f); - for (field=clientfields ; field->name ; field++) + for (field = clientfields; field->name; field++) { - ReadField (f, field, (byte *)client); + ReadField(f, field, (byte *)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. -============ -*/ -void WriteGame (char *filename, qboolean autosave) + * 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) { - FILE *f; - int i; - char str[16]; + FILE *f; + int i; + char str[16]; if (!autosave) - SaveClientData (); + { + SaveClientData(); + } + + f = fopen(filename, "wb"); - f = fopen (filename, "wb"); if (!f) - gi.error ("Couldn't open %s", filename); + { + gi.error("Couldn't open %s", filename); + } - memset (str, 0, sizeof(str)); - strcpy (str, __DATE__); - fwrite (str, sizeof(str), 1, f); + memset(str, 0, sizeof(str)); + strcpy(str, __DATE__); + fwrite(str, sizeof(str), 1, f); game.autosaved = autosave; - fwrite (&game, sizeof(game), 1, f); + fwrite(&game, sizeof(game), 1, f); game.autosaved = false; - for (i=0 ; iname ; field++) + /* change the pointers to lengths or indexes */ + for (field = savefields; field->name; field++) { - WriteField1 (f, field, (byte *)&temp); + WriteField1(f, field, (byte *)&temp); } - // write the block - fwrite (&temp, sizeof(temp), 1, f); + /* write the block */ + fwrite(&temp, sizeof(temp), 1, f); - // now write any allocated data following the edict - for (field=savefields ; field->name ; field++) + /* now write any allocated data following the edict */ + for (field = savefields; field->name; field++) { - WriteField2 (f, field, (byte *)ent); + WriteField2(f, field, (byte *)ent); } - } /* -============== -WriteLevelLocals - -All pointer variables (except function pointers) must be handled specially. -============== -*/ -void WriteLevelLocals (FILE *f) + * All pointer variables (except function + * pointers) must be handled specially. + */ +void +WriteLevelLocals(FILE *f) { - field_t *field; - level_locals_t temp; + 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 - for (field=levelfields ; field->name ; field++) + /* change the pointers to lengths or indexes */ + for (field = levelfields; field->name; field++) { - WriteField1 (f, field, (byte *)&temp); + WriteField1(f, field, (byte *)&temp); } - // write the block - fwrite (&temp, sizeof(temp), 1, f); + /* write the block */ + fwrite(&temp, sizeof(temp), 1, f); - // now write any allocated data following the edict - for (field=levelfields ; field->name ; field++) + /* 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. -============== -*/ -void ReadEdict (FILE *f, edict_t *ent) -{ - field_t *field; - - fread (ent, sizeof(*ent), 1, f); - - for (field=savefields ; field->name ; field++) - { - ReadField (f, field, (byte *)ent); + WriteField2(f, field, (byte *)&level); } } /* -============== -ReadLevelLocals - -All pointer variables (except function pointers) must be handled specially. -============== -*/ -void ReadLevelLocals (FILE *f) + * All pointer variables (except function + * pointers) must be handled specially. + */ +void +ReadEdict(FILE *f, edict_t *ent) { - field_t *field; + field_t *field; - fread (&level, sizeof(level), 1, f); + fread(ent, sizeof(*ent), 1, f); - for (field=levelfields ; field->name ; field++) + for (field = savefields; field->name; field++) { - ReadField (f, field, (byte *)&level); + ReadField(f, field, (byte *)ent); } } /* -================= -WriteLevel - -================= -*/ -void WriteLevel (char *filename) + * All pointer variables (except function + * pointers) must be handled specially. + */ +void +ReadLevelLocals(FILE *f) { - int i; - edict_t *ent; - FILE *f; - void *base; + field_t *field; + + fread(&level, sizeof(level), 1, f); + + for (field = levelfields; field->name; field++) + { + ReadField(f, field, (byte *)&level); + } +} + +void +WriteLevel(char *filename) +{ + int i; + edict_t *ent; + FILE *f; + void *base; + + f = fopen(filename, "wb"); - f = fopen (filename, "wb"); if (!f) - gi.error ("Couldn't open %s", filename); + { + gi.error("Couldn't open %s", filename); + } - // write out edict size for checking + /* write out edict size for checking */ i = sizeof(edict_t); - fwrite (&i, sizeof(i), 1, f); + 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); + fwrite(&base, sizeof(base), 1, f); - // write out level_locals_t - WriteLevelLocals (f); + /* write out level_locals_t */ + WriteLevelLocals(f); - // write out all the entities - for (i=0 ; iinuse) - continue; - fwrite (&i, sizeof(i), 1, f); - WriteEdict (f, ent); - } - i = -1; - fwrite (&i, sizeof(i), 1, f); - fclose (f); + 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. -================= -*/ -void ReadLevel (char *filename) + * 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) { - int entnum; - FILE *f; - int i; - void *base; - edict_t *ent; + int entnum; + FILE *f; + int i; + void *base; + edict_t *ent; + + f = fopen(filename, "rb"); - f = fopen (filename, "rb"); if (!f) - gi.error ("Couldn't open %s", filename); + { + gi.error("Couldn't open %s", filename); + } - // free any dynamic memory allocated by loading the level - // base state - gi.FreeTags (TAG_LEVEL); + /* free any dynamic memory allocated by + loading the level base state */ + gi.FreeTags(TAG_LEVEL); - // wipe all the entities - memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0])); - globals.num_edicts = maxclients->value+1; + /* wipe all the entities */ + memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0])); + globals.num_edicts = maxclients->value + 1; + + /* check edict size */ + fread(&i, sizeof(i), 1, f); - // check edict size - fread (&i, sizeof(i), 1, f); if (i != sizeof(edict_t)) { - fclose (f); - gi.error ("ReadLevel: mismatched edict size"); + fclose(f); + gi.error("ReadLevel: mismatched edict size"); } - // check function pointer base address - fread (&base, sizeof(base), 1, f); + /* check function pointer base address */ + fread(&base, sizeof(base), 1, f); + if (base != (void *)InitGame) { - fclose (f); - gi.error ("ReadLevel: function pointers have moved"); + fclose(f); + gi.error("ReadLevel: function pointers have moved"); } - // load the level locals - ReadLevelLocals (f); + /* load the level locals */ + ReadLevelLocals(f); - // load all the entities + /* load all the entities */ while (1) { - if (fread (&entnum, sizeof(entnum), 1, f) != 1) + if (fread(&entnum, sizeof(entnum), 1, f) != 1) { - fclose (f); - gi.error ("ReadLevel: failed to read entnum"); + fclose(f); + gi.error("ReadLevel: failed to read entnum"); } + if (entnum == -1) + { break; + } + if (entnum >= globals.num_edicts) - globals.num_edicts = entnum+1; + { + globals.num_edicts = entnum + 1; + } ent = &g_edicts[entnum]; - ReadEdict (f, ent); + ReadEdict(f, ent); - // let the server rebuild world links for this ent - memset (&ent->area, 0, sizeof(ent->area)); - gi.linkentity (ent); + /* let the server rebuild world links for this ent */ + memset(&ent->area, 0, sizeof(ent->area)); + gi.linkentity(ent); } - fclose (f); + fclose(f); - // mark all clients as unconnected - for (i=0 ; ivalue ; i++) + /* mark all clients as unconnected */ + for (i = 0; i < maxclients->value; i++) { - ent = &g_edicts[i+1]; + ent = &g_edicts[i + 1]; ent->client = game.clients + i; ent->client->pers.connected = false; } - // do any load time things at this point - for (i=0 ; iinuse) + { 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; + } + } } }