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