Annotation of quake2/ctf/g_save.c, revision 1.1.1.1

1.1       root        1: 
                      2: #include "g_local.h"
                      3: 
                      4: field_t fields[] = {
                      5:        {"classname", FOFS(classname), F_LSTRING},
                      6:        {"origin", FOFS(s.origin), F_VECTOR},
                      7:        {"model", FOFS(model), F_LSTRING},
                      8:        {"spawnflags", FOFS(spawnflags), F_INT},
                      9:        {"speed", FOFS(speed), F_FLOAT},
                     10:        {"accel", FOFS(accel), F_FLOAT},
                     11:        {"decel", FOFS(decel), F_FLOAT},
                     12:        {"target", FOFS(target), F_LSTRING},
                     13:        {"targetname", FOFS(targetname), F_LSTRING},
                     14:        {"pathtarget", FOFS(pathtarget), F_LSTRING},
                     15:        {"deathtarget", FOFS(deathtarget), F_LSTRING},
                     16:        {"killtarget", FOFS(killtarget), F_LSTRING},
                     17:        {"combattarget", FOFS(combattarget), F_LSTRING},
                     18:        {"message", FOFS(message), F_LSTRING},
                     19:        {"team", FOFS(team), F_LSTRING},
                     20:        {"wait", FOFS(wait), F_FLOAT},
                     21:        {"delay", FOFS(delay), F_FLOAT},
                     22:        {"random", FOFS(random), F_FLOAT},
                     23:        {"move_origin", FOFS(move_origin), F_VECTOR},
                     24:        {"move_angles", FOFS(move_angles), F_VECTOR},
                     25:        {"style", FOFS(style), F_INT},
                     26:        {"count", FOFS(count), F_INT},
                     27:        {"health", FOFS(health), F_INT},
                     28:        {"sounds", FOFS(sounds), F_INT},
                     29:        {"light", 0, F_IGNORE},
                     30:        {"dmg", FOFS(dmg), F_INT},
                     31:        {"angles", FOFS(s.angles), F_VECTOR},
                     32:        {"angle", FOFS(s.angles), F_ANGLEHACK},
                     33:        {"mass", FOFS(mass), F_INT},
                     34:        {"volume", FOFS(volume), F_FLOAT},
                     35:        {"attenuation", FOFS(attenuation), F_FLOAT},
                     36:        {"map", FOFS(map), F_LSTRING},
                     37: 
                     38:        // temp spawn vars -- only valid when the spawn function is called
                     39:        {"lip", STOFS(lip), F_INT, FFL_SPAWNTEMP},
                     40:        {"distance", STOFS(distance), F_INT, FFL_SPAWNTEMP},
                     41:        {"height", STOFS(height), F_INT, FFL_SPAWNTEMP},
                     42:        {"noise", STOFS(noise), F_LSTRING, FFL_SPAWNTEMP},
                     43:        {"pausetime", STOFS(pausetime), F_FLOAT, FFL_SPAWNTEMP},
                     44:        {"item", STOFS(item), F_LSTRING, FFL_SPAWNTEMP},
                     45:        {"gravity", STOFS(gravity), F_LSTRING, FFL_SPAWNTEMP},
                     46:        {"sky", STOFS(sky), F_LSTRING, FFL_SPAWNTEMP},
                     47:        {"skyrotate", STOFS(skyrotate), F_FLOAT, FFL_SPAWNTEMP},
                     48:        {"skyaxis", STOFS(skyaxis), F_VECTOR, FFL_SPAWNTEMP},
                     49:        {"minyaw", STOFS(minyaw), F_FLOAT, FFL_SPAWNTEMP},
                     50:        {"maxyaw", STOFS(maxyaw), F_FLOAT, FFL_SPAWNTEMP},
                     51:        {"minpitch", STOFS(minpitch), F_FLOAT, FFL_SPAWNTEMP},
                     52:        {"maxpitch", STOFS(maxpitch), F_FLOAT, FFL_SPAWNTEMP},
                     53:        {"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP}
                     54: };
                     55: 
                     56: // -------- just for savegames ----------
                     57: // all pointer fields should be listed here, or savegames
                     58: // won't work properly (they will crash and burn).
                     59: // this wasn't just tacked on to the fields array, because
                     60: // these don't need names, we wouldn't want map fields using
                     61: // some of these, and if one were accidentally present twice
                     62: // it would double swizzle (fuck) the pointer.
                     63: 
                     64: field_t                savefields[] =
                     65: {
                     66:        {"", FOFS(classname), F_LSTRING},
                     67:        {"", FOFS(target), F_LSTRING},
                     68:        {"", FOFS(targetname), F_LSTRING},
                     69:        {"", FOFS(killtarget), F_LSTRING},
                     70:        {"", FOFS(team), F_LSTRING},
                     71:        {"", FOFS(pathtarget), F_LSTRING},
                     72:        {"", FOFS(deathtarget), F_LSTRING},
                     73:        {"", FOFS(combattarget), F_LSTRING},
                     74:        {"", FOFS(model), F_LSTRING},
                     75:        {"", FOFS(map), F_LSTRING},
                     76:        {"", FOFS(message), F_LSTRING},
                     77: 
                     78:        {"", FOFS(client), F_CLIENT},
                     79:        {"", FOFS(item), F_ITEM},
                     80: 
                     81:        {"", FOFS(goalentity), F_EDICT},
                     82:        {"", FOFS(movetarget), F_EDICT},
                     83:        {"", FOFS(enemy), F_EDICT},
                     84:        {"", FOFS(oldenemy), F_EDICT},
                     85:        {"", FOFS(activator), F_EDICT},
                     86:        {"", FOFS(groundentity), F_EDICT},
                     87:        {"", FOFS(teamchain), F_EDICT},
                     88:        {"", FOFS(teammaster), F_EDICT},
                     89:        {"", FOFS(owner), F_EDICT},
                     90:        {"", FOFS(mynoise), F_EDICT},
                     91:        {"", FOFS(mynoise2), F_EDICT},
                     92:        {"", FOFS(target_ent), F_EDICT},
                     93:        {"", FOFS(chain), F_EDICT},
                     94: 
                     95:        {NULL, 0, F_INT}
                     96: };
                     97: 
                     98: field_t                levelfields[] =
                     99: {
                    100:        {"", LLOFS(changemap), F_LSTRING},
                    101: 
                    102:        {"", LLOFS(sight_client), F_EDICT},
                    103:        {"", LLOFS(sight_entity), F_EDICT},
                    104:        {"", LLOFS(sound_entity), F_EDICT},
                    105:        {"", LLOFS(sound2_entity), F_EDICT},
                    106: 
                    107:        {NULL, 0, F_INT}
                    108: };
                    109: 
                    110: field_t                clientfields[] =
                    111: {
                    112:        {"", CLOFS(pers.weapon), F_ITEM},
                    113:        {"", CLOFS(pers.lastweapon), F_ITEM},
                    114:        {"", CLOFS(newweapon), F_ITEM},
                    115: 
                    116:        {NULL, 0, F_INT}
                    117: };
                    118: 
                    119: /*
                    120: ============
                    121: InitGame
                    122: 
                    123: This will be called when the dll is first loaded, which
                    124: only happens when a new game is started or a save game
                    125: is loaded.
                    126: ============
                    127: */
                    128: void InitGame (void)
                    129: {
                    130:        gi.dprintf ("==== InitGame ====\n");
                    131: 
                    132:        gun_x = gi.cvar ("gun_x", "0", 0);
                    133:        gun_y = gi.cvar ("gun_y", "0", 0);
                    134:        gun_z = gi.cvar ("gun_z", "0", 0);
                    135: 
                    136:        //FIXME: sv_ prefix is wrong for these
                    137:        sv_rollspeed = gi.cvar ("sv_rollspeed", "200", 0);
                    138:        sv_rollangle = gi.cvar ("sv_rollangle", "2", 0);
                    139:        sv_maxvelocity = gi.cvar ("sv_maxvelocity", "2000", 0);
                    140:        sv_gravity = gi.cvar ("sv_gravity", "800", 0);
                    141: 
                    142:        // noset vars
                    143:        dedicated = gi.cvar ("dedicated", "0", CVAR_NOSET);
                    144: 
                    145:        // latched vars
                    146:        sv_cheats = gi.cvar ("cheats", "0", CVAR_SERVERINFO|CVAR_LATCH);
                    147:        gi.cvar ("gamename", GAMEVERSION , CVAR_SERVERINFO | CVAR_LATCH);
                    148:        gi.cvar ("gamedate", __DATE__ , CVAR_SERVERINFO | CVAR_LATCH);
                    149: 
                    150:        maxclients = gi.cvar ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH);
                    151:        deathmatch = gi.cvar ("deathmatch", "0", CVAR_LATCH);
                    152:        coop = gi.cvar ("coop", "0", CVAR_LATCH);
                    153:        skill = gi.cvar ("skill", "1", CVAR_LATCH);
                    154:        maxentities = gi.cvar ("maxentities", "1024", CVAR_LATCH);
                    155: 
                    156: //ZOID
                    157: //This game.dll only supports deathmatch
                    158:        if (!deathmatch->value) {
                    159:                gi.dprintf("Forcing deathmatch.");
                    160:                gi.cvar_set("deathmatch", "1");
                    161:        }
                    162:        //force coop off
                    163:        if (coop->value)
                    164:                gi.cvar_set("coop", "0");
                    165: //ZOID
                    166: 
                    167: 
                    168:        // change anytime vars
                    169:        dmflags = gi.cvar ("dmflags", "0", CVAR_SERVERINFO);
                    170:        fraglimit = gi.cvar ("fraglimit", "0", CVAR_SERVERINFO);
                    171:        timelimit = gi.cvar ("timelimit", "0", CVAR_SERVERINFO);
                    172: //ZOID
                    173:        capturelimit = gi.cvar ("capturelimit", "0", CVAR_SERVERINFO);
                    174:        instantweap = gi.cvar ("instantweap", "0", CVAR_SERVERINFO);
                    175: //ZOID
                    176:        password = gi.cvar ("password", "", CVAR_USERINFO);
                    177: 
                    178:        g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE);
                    179: 
                    180:        run_pitch = gi.cvar ("run_pitch", "0.002", 0);
                    181:        run_roll = gi.cvar ("run_roll", "0.005", 0);
                    182:        bob_up  = gi.cvar ("bob_up", "0.005", 0);
                    183:        bob_pitch = gi.cvar ("bob_pitch", "0.002", 0);
                    184:        bob_roll = gi.cvar ("bob_roll", "0.002", 0);
                    185: 
                    186:        // flood control
                    187:        flood_msgs = gi.cvar ("flood_msgs", "4", 0);
                    188:        flood_persecond = gi.cvar ("flood_persecond", "4", 0);
                    189:        flood_waitdelay = gi.cvar ("flood_waitdelay", "10", 0);
                    190: 
                    191:        // dm map list
                    192:        sv_maplist = gi.cvar ("sv_maplist", "", 0);
                    193: 
                    194:        // items
                    195:        InitItems ();
                    196: 
                    197:        Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), "");
                    198: 
                    199:        Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), "");
                    200: 
                    201:        // initialize all entities for this game
                    202:        game.maxentities = maxentities->value;
                    203:        g_edicts =  gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
                    204:        globals.edicts = g_edicts;
                    205:        globals.max_edicts = game.maxentities;
                    206: 
                    207:        // initialize all clients for this game
                    208:        game.maxclients = maxclients->value;
                    209:        game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
                    210:        globals.num_edicts = game.maxclients+1;
                    211: 
                    212: //ZOID
                    213:        CTFInit();
                    214: //ZOID
                    215: }
                    216: 
                    217: //=========================================================
                    218: 
                    219: void WriteField1 (FILE *f, field_t *field, byte *base)
                    220: {
                    221:        void            *p;
                    222:        int                     len;
                    223:        int                     index;
                    224: 
                    225:        p = (void *)(base + field->ofs);
                    226:        switch (field->type)
                    227:        {
                    228:        case F_INT:
                    229:        case F_FLOAT:
                    230:        case F_ANGLEHACK:
                    231:        case F_VECTOR:
                    232:        case F_IGNORE:
                    233:                break;
                    234: 
                    235:        case F_LSTRING:
                    236:        case F_GSTRING:
                    237:                if ( *(char **)p )
                    238:                        len = strlen(*(char **)p) + 1;
                    239:                else
                    240:                        len = 0;
                    241:                *(int *)p = len;
                    242:                break;
                    243:        case F_EDICT:
                    244:                if ( *(edict_t **)p == NULL)
                    245:                        index = -1;
                    246:                else
                    247:                        index = *(edict_t **)p - g_edicts;
                    248:                *(int *)p = index;
                    249:                break;
                    250:        case F_CLIENT:
                    251:                if ( *(gclient_t **)p == NULL)
                    252:                        index = -1;
                    253:                else
                    254:                        index = *(gclient_t **)p - game.clients;
                    255:                *(int *)p = index;
                    256:                break;
                    257:        case F_ITEM:
                    258:                if ( *(edict_t **)p == NULL)
                    259:                        index = -1;
                    260:                else
                    261:                        index = *(gitem_t **)p - itemlist;
                    262:                *(int *)p = index;
                    263:                break;
                    264: 
                    265:        default:
                    266:                gi.error ("WriteEdict: unknown field type");
                    267:        }
                    268: }
                    269: 
                    270: void WriteField2 (FILE *f, field_t *field, byte *base)
                    271: {
                    272:        int                     len;
                    273:        void            *p;
                    274: 
                    275:        p = (void *)(base + field->ofs);
                    276:        switch (field->type)
                    277:        {
                    278:        case F_LSTRING:
                    279:        case F_GSTRING:
                    280:                if ( *(char **)p )
                    281:                {
                    282:                        len = strlen(*(char **)p) + 1;
                    283:                        fwrite (*(char **)p, len, 1, f);
                    284:                }
                    285:                break;
                    286:        }
                    287: }
                    288: 
                    289: void ReadField (FILE *f, field_t *field, byte *base)
                    290: {
                    291:        void            *p;
                    292:        int                     len;
                    293:        int                     index;
                    294: 
                    295:        p = (void *)(base + field->ofs);
                    296:        switch (field->type)
                    297:        {
                    298:        case F_INT:
                    299:        case F_FLOAT:
                    300:        case F_ANGLEHACK:
                    301:        case F_VECTOR:
                    302:        case F_IGNORE:
                    303:                break;
                    304: 
                    305:        case F_LSTRING:
                    306:                len = *(int *)p;
                    307:                if (!len)
                    308:                        *(char **)p = NULL;
                    309:                else
                    310:                {
                    311:                        *(char **)p = gi.TagMalloc (len, TAG_LEVEL);
                    312:                        fread (*(char **)p, len, 1, f);
                    313:                }
                    314:                break;
                    315:        case F_GSTRING:
                    316:                len = *(int *)p;
                    317:                if (!len)
                    318:                        *(char **)p = NULL;
                    319:                else
                    320:                {
                    321:                        *(char **)p = gi.TagMalloc (len, TAG_GAME);
                    322:                        fread (*(char **)p, len, 1, f);
                    323:                }
                    324:                break;
                    325:        case F_EDICT:
                    326:                index = *(int *)p;
                    327:                if ( index == -1 )
                    328:                        *(edict_t **)p = NULL;
                    329:                else
                    330:                        *(edict_t **)p = &g_edicts[index];
                    331:                break;
                    332:        case F_CLIENT:
                    333:                index = *(int *)p;
                    334:                if ( index == -1 )
                    335:                        *(gclient_t **)p = NULL;
                    336:                else
                    337:                        *(gclient_t **)p = &game.clients[index];
                    338:                break;
                    339:        case F_ITEM:
                    340:                index = *(int *)p;
                    341:                if ( index == -1 )
                    342:                        *(gitem_t **)p = NULL;
                    343:                else
                    344:                        *(gitem_t **)p = &itemlist[index];
                    345:                break;
                    346: 
                    347:        default:
                    348:                gi.error ("ReadEdict: unknown field type");
                    349:        }
                    350: }
                    351: 
                    352: //=========================================================
                    353: 
                    354: /*
                    355: ==============
                    356: WriteClient
                    357: 
                    358: All pointer variables (except function pointers) must be handled specially.
                    359: ==============
                    360: */
                    361: void WriteClient (FILE *f, gclient_t *client)
                    362: {
                    363:        field_t         *field;
                    364:        gclient_t       temp;
                    365:        
                    366:        // all of the ints, floats, and vectors stay as they are
                    367:        temp = *client;
                    368: 
                    369:        // change the pointers to lengths or indexes
                    370:        for (field=clientfields ; field->name ; field++)
                    371:        {
                    372:                WriteField1 (f, field, (byte *)&temp);
                    373:        }
                    374: 
                    375:        // write the block
                    376:        fwrite (&temp, sizeof(temp), 1, f);
                    377: 
                    378:        // now write any allocated data following the edict
                    379:        for (field=clientfields ; field->name ; field++)
                    380:        {
                    381:                WriteField2 (f, field, (byte *)client);
                    382:        }
                    383: }
                    384: 
                    385: /*
                    386: ==============
                    387: ReadClient
                    388: 
                    389: All pointer variables (except function pointers) must be handled specially.
                    390: ==============
                    391: */
                    392: void ReadClient (FILE *f, gclient_t *client)
                    393: {
                    394:        field_t         *field;
                    395: 
                    396:        fread (client, sizeof(*client), 1, f);
                    397: 
                    398:        for (field=clientfields ; field->name ; field++)
                    399:        {
                    400:                ReadField (f, field, (byte *)client);
                    401:        }
                    402: }
                    403: 
                    404: /*
                    405: ============
                    406: WriteGame
                    407: 
                    408: This will be called whenever the game goes to a new level,
                    409: and when the user explicitly saves the game.
                    410: 
                    411: Game information include cross level data, like multi level
                    412: triggers, help computer info, and all client states.
                    413: 
                    414: A single player death will automatically restore from the
                    415: last save position.
                    416: ============
                    417: */
                    418: void WriteGame (char *filename, qboolean autosave)
                    419: {
                    420:        FILE    *f;
                    421:        int             i;
                    422:        char    str[16];
                    423: 
                    424:        if (!autosave)
                    425:                SaveClientData ();
                    426: 
                    427:        f = fopen (filename, "wb");
                    428:        if (!f)
                    429:                gi.error ("Couldn't open %s", filename);
                    430: 
                    431:        memset (str, 0, sizeof(str));
                    432:        strcpy (str, __DATE__);
                    433:        fwrite (str, sizeof(str), 1, f);
                    434: 
                    435:        game.autosaved = autosave;
                    436:        fwrite (&game, sizeof(game), 1, f);
                    437:        game.autosaved = false;
                    438: 
                    439:        for (i=0 ; i<game.maxclients ; i++)
                    440:                WriteClient (f, &game.clients[i]);
                    441: 
                    442:        fclose (f);
                    443: }
                    444: 
                    445: void ReadGame (char *filename)
                    446: {
                    447:        FILE    *f;
                    448:        int             i;
                    449:        char    str[16];
                    450: 
                    451:        gi.FreeTags (TAG_GAME);
                    452: 
                    453:        f = fopen (filename, "rb");
                    454:        if (!f)
                    455:                gi.error ("Couldn't open %s", filename);
                    456: 
                    457:        fread (str, sizeof(str), 1, f);
                    458:        if (strcmp (str, __DATE__))
                    459:        {
                    460:                fclose (f);
                    461:                gi.error ("Savegame from an older version.\n");
                    462:        }
                    463: 
                    464:        g_edicts =  gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
                    465:        globals.edicts = g_edicts;
                    466: 
                    467:        fread (&game, sizeof(game), 1, f);
                    468:        game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
                    469:        for (i=0 ; i<game.maxclients ; i++)
                    470:                ReadClient (f, &game.clients[i]);
                    471: 
                    472:        fclose (f);
                    473: }
                    474: 
                    475: //==========================================================
                    476: 
                    477: 
                    478: /*
                    479: ==============
                    480: WriteEdict
                    481: 
                    482: All pointer variables (except function pointers) must be handled specially.
                    483: ==============
                    484: */
                    485: void WriteEdict (FILE *f, edict_t *ent)
                    486: {
                    487:        field_t         *field;
                    488:        edict_t         temp;
                    489: 
                    490:        // all of the ints, floats, and vectors stay as they are
                    491:        temp = *ent;
                    492: 
                    493:        // change the pointers to lengths or indexes
                    494:        for (field=savefields ; field->name ; field++)
                    495:        {
                    496:                WriteField1 (f, field, (byte *)&temp);
                    497:        }
                    498: 
                    499:        // write the block
                    500:        fwrite (&temp, sizeof(temp), 1, f);
                    501: 
                    502:        // now write any allocated data following the edict
                    503:        for (field=savefields ; field->name ; field++)
                    504:        {
                    505:                WriteField2 (f, field, (byte *)ent);
                    506:        }
                    507: 
                    508: }
                    509: 
                    510: /*
                    511: ==============
                    512: WriteLevelLocals
                    513: 
                    514: All pointer variables (except function pointers) must be handled specially.
                    515: ==============
                    516: */
                    517: void WriteLevelLocals (FILE *f)
                    518: {
                    519:        field_t         *field;
                    520:        level_locals_t          temp;
                    521: 
                    522:        // all of the ints, floats, and vectors stay as they are
                    523:        temp = level;
                    524: 
                    525:        // change the pointers to lengths or indexes
                    526:        for (field=levelfields ; field->name ; field++)
                    527:        {
                    528:                WriteField1 (f, field, (byte *)&temp);
                    529:        }
                    530: 
                    531:        // write the block
                    532:        fwrite (&temp, sizeof(temp), 1, f);
                    533: 
                    534:        // now write any allocated data following the edict
                    535:        for (field=levelfields ; field->name ; field++)
                    536:        {
                    537:                WriteField2 (f, field, (byte *)&level);
                    538:        }
                    539: }
                    540: 
                    541: 
                    542: /*
                    543: ==============
                    544: ReadEdict
                    545: 
                    546: All pointer variables (except function pointers) must be handled specially.
                    547: ==============
                    548: */
                    549: void ReadEdict (FILE *f, edict_t *ent)
                    550: {
                    551:        field_t         *field;
                    552: 
                    553:        fread (ent, sizeof(*ent), 1, f);
                    554: 
                    555:        for (field=savefields ; field->name ; field++)
                    556:        {
                    557:                ReadField (f, field, (byte *)ent);
                    558:        }
                    559: }
                    560: 
                    561: /*
                    562: ==============
                    563: ReadLevelLocals
                    564: 
                    565: All pointer variables (except function pointers) must be handled specially.
                    566: ==============
                    567: */
                    568: void ReadLevelLocals (FILE *f)
                    569: {
                    570:        field_t         *field;
                    571: 
                    572:        fread (&level, sizeof(level), 1, f);
                    573: 
                    574:        for (field=levelfields ; field->name ; field++)
                    575:        {
                    576:                ReadField (f, field, (byte *)&level);
                    577:        }
                    578: }
                    579: 
                    580: /*
                    581: =================
                    582: WriteLevel
                    583: 
                    584: =================
                    585: */
                    586: void WriteLevel (char *filename)
                    587: {
                    588:        int             i;
                    589:        edict_t *ent;
                    590:        FILE    *f;
                    591:        void    *base;
                    592: 
                    593:        f = fopen (filename, "wb");
                    594:        if (!f)
                    595:                gi.error ("Couldn't open %s", filename);
                    596: 
                    597:        // write out edict size for checking
                    598:        i = sizeof(edict_t);
                    599:        fwrite (&i, sizeof(i), 1, f);
                    600: 
                    601:        // write out a function pointer for checking
                    602:        base = (void *)InitGame;
                    603:        fwrite (&base, sizeof(base), 1, f);
                    604: 
                    605:        // write out level_locals_t
                    606:        WriteLevelLocals (f);
                    607: 
                    608:        // write out all the entities
                    609:        for (i=0 ; i<globals.num_edicts ; i++)
                    610:        {
                    611:                ent = &g_edicts[i];
                    612:                if (!ent->inuse)
                    613:                        continue;
                    614:                fwrite (&i, sizeof(i), 1, f);
                    615:                WriteEdict (f, ent);
                    616:        }
                    617:        i = -1;
                    618:        fwrite (&i, sizeof(i), 1, f);
                    619: 
                    620:        fclose (f);
                    621: }
                    622: 
                    623: 
                    624: /*
                    625: =================
                    626: ReadLevel
                    627: 
                    628: SpawnEntities will allready have been called on the
                    629: level the same way it was when the level was saved.
                    630: 
                    631: That is necessary to get the baselines
                    632: set up identically.
                    633: 
                    634: The server will have cleared all of the world links before
                    635: calling ReadLevel.
                    636: 
                    637: No clients are connected yet.
                    638: =================
                    639: */
                    640: void ReadLevel (char *filename)
                    641: {
                    642:        int             entnum;
                    643:        FILE    *f;
                    644:        int             i;
                    645:        void    *base;
                    646:        edict_t *ent;
                    647: 
                    648:        f = fopen (filename, "rb");
                    649:        if (!f)
                    650:                gi.error ("Couldn't open %s", filename);
                    651: 
                    652:        // free any dynamic memory allocated by loading the level
                    653:        // base state
                    654:        gi.FreeTags (TAG_LEVEL);
                    655: 
                    656:        // wipe all the entities
                    657:        memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0]));
                    658:        globals.num_edicts = maxclients->value+1;
                    659: 
                    660:        // check edict size
                    661:        fread (&i, sizeof(i), 1, f);
                    662:        if (i != sizeof(edict_t))
                    663:        {
                    664:                fclose (f);
                    665:                gi.error ("ReadLevel: mismatched edict size");
                    666:        }
                    667: 
                    668:        // check function pointer base address
                    669:        fread (&base, sizeof(base), 1, f);
                    670:        if (base != (void *)InitGame)
                    671:        {
                    672:                fclose (f);
                    673:                gi.error ("ReadLevel: function pointers have moved");
                    674:        }
                    675: 
                    676:        // load the level locals
                    677:        ReadLevelLocals (f);
                    678: 
                    679:        // load all the entities
                    680:        while (1)
                    681:        {
                    682:                if (fread (&entnum, sizeof(entnum), 1, f) != 1)
                    683:                {
                    684:                        fclose (f);
                    685:                        gi.error ("ReadLevel: failed to read entnum");
                    686:                }
                    687:                if (entnum == -1)
                    688:                        break;
                    689:                if (entnum >= globals.num_edicts)
                    690:                        globals.num_edicts = entnum+1;
                    691: 
                    692:                ent = &g_edicts[entnum];
                    693:                ReadEdict (f, ent);
                    694: 
                    695:                // let the server rebuild world links for this ent
                    696:                memset (&ent->area, 0, sizeof(ent->area));
                    697:                gi.linkentity (ent);
                    698:        }
                    699: 
                    700:        fclose (f);
                    701: 
                    702:        // mark all clients as unconnected
                    703:        for (i=0 ; i<maxclients->value ; i++)
                    704:        {
                    705:                ent = &g_edicts[i+1];
                    706:                ent->client = game.clients + i;
                    707:                ent->client->pers.connected = false;
                    708:        }
                    709: 
                    710:        // do any load time things at this point
                    711:        for (i=0 ; i<globals.num_edicts ; i++)
                    712:        {
                    713:                ent = &g_edicts[i];
                    714: 
                    715:                if (!ent->inuse)
                    716:                        continue;
                    717: 
                    718:                // fire any cross-level triggers
                    719:                if (ent->classname)
                    720:                        if (strcmp(ent->classname, "target_crosslevel_target") == 0)
                    721:                                ent->nextthink = level.time + ent->delay;
                    722:        }
                    723: }
                    724: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.