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

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

unix.superglobalmegacorp.com

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