|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.