|
|
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: // change anytime vars ! 157: dmflags = gi.cvar ("dmflags", "0", CVAR_SERVERINFO); ! 158: fraglimit = gi.cvar ("fraglimit", "0", CVAR_SERVERINFO); ! 159: timelimit = gi.cvar ("timelimit", "0", CVAR_SERVERINFO); ! 160: password = gi.cvar ("password", "", CVAR_USERINFO); ! 161: ! 162: g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE); ! 163: ! 164: run_pitch = gi.cvar ("run_pitch", "0.002", 0); ! 165: run_roll = gi.cvar ("run_roll", "0.005", 0); ! 166: bob_up = gi.cvar ("bob_up", "0.005", 0); ! 167: bob_pitch = gi.cvar ("bob_pitch", "0.002", 0); ! 168: bob_roll = gi.cvar ("bob_roll", "0.002", 0); ! 169: ! 170: // items ! 171: InitItems (); ! 172: ! 173: Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), ""); ! 174: ! 175: Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), ""); ! 176: ! 177: // initialize all entities for this game ! 178: game.maxentities = maxentities->value; ! 179: g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME); ! 180: globals.edicts = g_edicts; ! 181: globals.max_edicts = game.maxentities; ! 182: ! 183: // initialize all clients for this game ! 184: game.maxclients = maxclients->value; ! 185: game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME); ! 186: globals.num_edicts = game.maxclients+1; ! 187: } ! 188: ! 189: //========================================================= ! 190: ! 191: void WriteField1 (FILE *f, field_t *field, byte *base) ! 192: { ! 193: void *p; ! 194: int len; ! 195: int index; ! 196: ! 197: p = (void *)(base + field->ofs); ! 198: switch (field->type) ! 199: { ! 200: case F_INT: ! 201: case F_FLOAT: ! 202: case F_ANGLEHACK: ! 203: case F_VECTOR: ! 204: case F_IGNORE: ! 205: break; ! 206: ! 207: case F_LSTRING: ! 208: case F_GSTRING: ! 209: if ( *(char **)p ) ! 210: len = strlen(*(char **)p) + 1; ! 211: else ! 212: len = 0; ! 213: *(int *)p = len; ! 214: break; ! 215: case F_EDICT: ! 216: if ( *(edict_t **)p == NULL) ! 217: index = -1; ! 218: else ! 219: index = *(edict_t **)p - g_edicts; ! 220: *(int *)p = index; ! 221: break; ! 222: case F_CLIENT: ! 223: if ( *(gclient_t **)p == NULL) ! 224: index = -1; ! 225: else ! 226: index = *(gclient_t **)p - game.clients; ! 227: *(int *)p = index; ! 228: break; ! 229: case F_ITEM: ! 230: if ( *(edict_t **)p == NULL) ! 231: index = -1; ! 232: else ! 233: index = *(gitem_t **)p - itemlist; ! 234: *(int *)p = index; ! 235: break; ! 236: ! 237: default: ! 238: gi.error ("WriteEdict: unknown field type"); ! 239: } ! 240: } ! 241: ! 242: void WriteField2 (FILE *f, field_t *field, byte *base) ! 243: { ! 244: int len; ! 245: void *p; ! 246: ! 247: p = (void *)(base + field->ofs); ! 248: switch (field->type) ! 249: { ! 250: case F_LSTRING: ! 251: case F_GSTRING: ! 252: if ( *(char **)p ) ! 253: { ! 254: len = strlen(*(char **)p) + 1; ! 255: fwrite (*(char **)p, len, 1, f); ! 256: } ! 257: break; ! 258: } ! 259: } ! 260: ! 261: void ReadField (FILE *f, field_t *field, byte *base) ! 262: { ! 263: void *p; ! 264: int len; ! 265: int index; ! 266: ! 267: p = (void *)(base + field->ofs); ! 268: switch (field->type) ! 269: { ! 270: case F_INT: ! 271: case F_FLOAT: ! 272: case F_ANGLEHACK: ! 273: case F_VECTOR: ! 274: case F_IGNORE: ! 275: break; ! 276: ! 277: case F_LSTRING: ! 278: len = *(int *)p; ! 279: if (!len) ! 280: *(char **)p = NULL; ! 281: else ! 282: { ! 283: *(char **)p = gi.TagMalloc (len, TAG_LEVEL); ! 284: fread (*(char **)p, len, 1, f); ! 285: } ! 286: break; ! 287: case F_GSTRING: ! 288: len = *(int *)p; ! 289: if (!len) ! 290: *(char **)p = NULL; ! 291: else ! 292: { ! 293: *(char **)p = gi.TagMalloc (len, TAG_GAME); ! 294: fread (*(char **)p, len, 1, f); ! 295: } ! 296: break; ! 297: case F_EDICT: ! 298: index = *(int *)p; ! 299: if ( index == -1 ) ! 300: *(edict_t **)p = NULL; ! 301: else ! 302: *(edict_t **)p = &g_edicts[index]; ! 303: break; ! 304: case F_CLIENT: ! 305: index = *(int *)p; ! 306: if ( index == -1 ) ! 307: *(gclient_t **)p = NULL; ! 308: else ! 309: *(gclient_t **)p = &game.clients[index]; ! 310: break; ! 311: case F_ITEM: ! 312: index = *(int *)p; ! 313: if ( index == -1 ) ! 314: *(gitem_t **)p = NULL; ! 315: else ! 316: *(gitem_t **)p = &itemlist[index]; ! 317: break; ! 318: ! 319: default: ! 320: gi.error ("ReadEdict: unknown field type"); ! 321: } ! 322: } ! 323: ! 324: //========================================================= ! 325: ! 326: /* ! 327: ============== ! 328: WriteClient ! 329: ! 330: All pointer variables (except function pointers) must be handled specially. ! 331: ============== ! 332: */ ! 333: void WriteClient (FILE *f, gclient_t *client) ! 334: { ! 335: field_t *field; ! 336: gclient_t temp; ! 337: ! 338: // all of the ints, floats, and vectors stay as they are ! 339: temp = *client; ! 340: ! 341: // change the pointers to lengths or indexes ! 342: for (field=clientfields ; field->name ; field++) ! 343: { ! 344: WriteField1 (f, field, (byte *)&temp); ! 345: } ! 346: ! 347: // write the block ! 348: fwrite (&temp, sizeof(temp), 1, f); ! 349: ! 350: // now write any allocated data following the edict ! 351: for (field=clientfields ; field->name ; field++) ! 352: { ! 353: WriteField2 (f, field, (byte *)client); ! 354: } ! 355: } ! 356: ! 357: /* ! 358: ============== ! 359: ReadClient ! 360: ! 361: All pointer variables (except function pointers) must be handled specially. ! 362: ============== ! 363: */ ! 364: void ReadClient (FILE *f, gclient_t *client) ! 365: { ! 366: field_t *field; ! 367: ! 368: fread (client, sizeof(*client), 1, f); ! 369: ! 370: for (field=clientfields ; field->name ; field++) ! 371: { ! 372: ReadField (f, field, (byte *)client); ! 373: } ! 374: } ! 375: ! 376: /* ! 377: ============ ! 378: WriteGame ! 379: ! 380: This will be called whenever the game goes to a new level, ! 381: and when the user explicitly saves the game. ! 382: ! 383: Game information include cross level data, like multi level ! 384: triggers, help computer info, and all client states. ! 385: ! 386: A single player death will automatically restore from the ! 387: last save position. ! 388: ============ ! 389: */ ! 390: void WriteGame (char *filename, qboolean autosave) ! 391: { ! 392: FILE *f; ! 393: int i; ! 394: char str[16]; ! 395: ! 396: if (!autosave) ! 397: SaveClientData (); ! 398: ! 399: f = fopen (filename, "wb"); ! 400: if (!f) ! 401: gi.error ("Couldn't open %s", filename); ! 402: ! 403: memset (str, 0, sizeof(str)); ! 404: strcpy (str, __DATE__); ! 405: fwrite (str, sizeof(str), 1, f); ! 406: ! 407: game.autosaved = autosave; ! 408: fwrite (&game, sizeof(game), 1, f); ! 409: game.autosaved = false; ! 410: ! 411: for (i=0 ; i<game.maxclients ; i++) ! 412: WriteClient (f, &game.clients[i]); ! 413: ! 414: fclose (f); ! 415: } ! 416: ! 417: void ReadGame (char *filename) ! 418: { ! 419: FILE *f; ! 420: int i; ! 421: char str[16]; ! 422: ! 423: gi.FreeTags (TAG_GAME); ! 424: ! 425: f = fopen (filename, "rb"); ! 426: if (!f) ! 427: gi.error ("Couldn't open %s", filename); ! 428: ! 429: fread (str, sizeof(str), 1, f); ! 430: if (strcmp (str, __DATE__)) ! 431: { ! 432: fclose (f); ! 433: gi.error ("Savegame from an older version.\n"); ! 434: } ! 435: ! 436: g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME); ! 437: globals.edicts = g_edicts; ! 438: ! 439: fread (&game, sizeof(game), 1, f); ! 440: game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME); ! 441: for (i=0 ; i<game.maxclients ; i++) ! 442: ReadClient (f, &game.clients[i]); ! 443: ! 444: fclose (f); ! 445: } ! 446: ! 447: //========================================================== ! 448: ! 449: ! 450: /* ! 451: ============== ! 452: WriteEdict ! 453: ! 454: All pointer variables (except function pointers) must be handled specially. ! 455: ============== ! 456: */ ! 457: void WriteEdict (FILE *f, edict_t *ent) ! 458: { ! 459: field_t *field; ! 460: edict_t temp; ! 461: ! 462: // all of the ints, floats, and vectors stay as they are ! 463: temp = *ent; ! 464: ! 465: // change the pointers to lengths or indexes ! 466: for (field=savefields ; field->name ; field++) ! 467: { ! 468: WriteField1 (f, field, (byte *)&temp); ! 469: } ! 470: ! 471: // write the block ! 472: fwrite (&temp, sizeof(temp), 1, f); ! 473: ! 474: // now write any allocated data following the edict ! 475: for (field=savefields ; field->name ; field++) ! 476: { ! 477: WriteField2 (f, field, (byte *)ent); ! 478: } ! 479: ! 480: } ! 481: ! 482: /* ! 483: ============== ! 484: WriteLevelLocals ! 485: ! 486: All pointer variables (except function pointers) must be handled specially. ! 487: ============== ! 488: */ ! 489: void WriteLevelLocals (FILE *f) ! 490: { ! 491: field_t *field; ! 492: level_locals_t temp; ! 493: ! 494: // all of the ints, floats, and vectors stay as they are ! 495: temp = level; ! 496: ! 497: // change the pointers to lengths or indexes ! 498: for (field=levelfields ; field->name ; field++) ! 499: { ! 500: WriteField1 (f, field, (byte *)&temp); ! 501: } ! 502: ! 503: // write the block ! 504: fwrite (&temp, sizeof(temp), 1, f); ! 505: ! 506: // now write any allocated data following the edict ! 507: for (field=levelfields ; field->name ; field++) ! 508: { ! 509: WriteField2 (f, field, (byte *)&level); ! 510: } ! 511: } ! 512: ! 513: ! 514: /* ! 515: ============== ! 516: ReadEdict ! 517: ! 518: All pointer variables (except function pointers) must be handled specially. ! 519: ============== ! 520: */ ! 521: void ReadEdict (FILE *f, edict_t *ent) ! 522: { ! 523: field_t *field; ! 524: ! 525: fread (ent, sizeof(*ent), 1, f); ! 526: ! 527: for (field=savefields ; field->name ; field++) ! 528: { ! 529: ReadField (f, field, (byte *)ent); ! 530: } ! 531: } ! 532: ! 533: /* ! 534: ============== ! 535: ReadLevelLocals ! 536: ! 537: All pointer variables (except function pointers) must be handled specially. ! 538: ============== ! 539: */ ! 540: void ReadLevelLocals (FILE *f) ! 541: { ! 542: field_t *field; ! 543: ! 544: fread (&level, sizeof(level), 1, f); ! 545: ! 546: for (field=levelfields ; field->name ; field++) ! 547: { ! 548: ReadField (f, field, (byte *)&level); ! 549: } ! 550: } ! 551: ! 552: /* ! 553: ================= ! 554: WriteLevel ! 555: ! 556: ================= ! 557: */ ! 558: void WriteLevel (char *filename) ! 559: { ! 560: int i; ! 561: edict_t *ent; ! 562: FILE *f; ! 563: void *base; ! 564: ! 565: f = fopen (filename, "wb"); ! 566: if (!f) ! 567: gi.error ("Couldn't open %s", filename); ! 568: ! 569: // write out edict size for checking ! 570: i = sizeof(edict_t); ! 571: fwrite (&i, sizeof(i), 1, f); ! 572: ! 573: // write out a function pointer for checking ! 574: base = (void *)InitGame; ! 575: fwrite (&base, sizeof(base), 1, f); ! 576: ! 577: // write out level_locals_t ! 578: WriteLevelLocals (f); ! 579: ! 580: // write out all the entities ! 581: for (i=0 ; i<globals.num_edicts ; i++) ! 582: { ! 583: ent = &g_edicts[i]; ! 584: if (!ent->inuse) ! 585: continue; ! 586: fwrite (&i, sizeof(i), 1, f); ! 587: WriteEdict (f, ent); ! 588: } ! 589: i = -1; ! 590: fwrite (&i, sizeof(i), 1, f); ! 591: ! 592: fclose (f); ! 593: } ! 594: ! 595: ! 596: /* ! 597: ================= ! 598: ReadLevel ! 599: ! 600: SpawnEntities will already have been called on the ! 601: level the same way it was when the level was saved. ! 602: ! 603: That is necessary to get the baselines ! 604: set up identically. ! 605: ! 606: The server will have cleared all of the world links before ! 607: calling ReadLevel. ! 608: ! 609: No clients are connected yet. ! 610: ================= ! 611: */ ! 612: void ReadLevel (char *filename) ! 613: { ! 614: int entnum; ! 615: FILE *f; ! 616: int i; ! 617: void *base; ! 618: edict_t *ent; ! 619: ! 620: f = fopen (filename, "rb"); ! 621: if (!f) ! 622: gi.error ("Couldn't open %s", filename); ! 623: ! 624: // free any dynamic memory allocated by loading the level ! 625: // base state ! 626: gi.FreeTags (TAG_LEVEL); ! 627: ! 628: // wipe all the entities ! 629: memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0])); ! 630: globals.num_edicts = maxclients->value+1; ! 631: ! 632: // check edict size ! 633: fread (&i, sizeof(i), 1, f); ! 634: if (i != sizeof(edict_t)) ! 635: { ! 636: fclose (f); ! 637: gi.error ("ReadLevel: mismatched edict size"); ! 638: } ! 639: ! 640: // check function pointer base address ! 641: fread (&base, sizeof(base), 1, f); ! 642: if (base != (void *)InitGame) ! 643: { ! 644: fclose (f); ! 645: gi.error ("ReadLevel: function pointers have moved"); ! 646: } ! 647: ! 648: // load the level locals ! 649: ReadLevelLocals (f); ! 650: ! 651: // load all the entities ! 652: while (1) ! 653: { ! 654: if (fread (&entnum, sizeof(entnum), 1, f) != 1) ! 655: { ! 656: fclose (f); ! 657: gi.error ("ReadLevel: failed to read entnum"); ! 658: } ! 659: if (entnum == -1) ! 660: break; ! 661: if (entnum >= globals.num_edicts) ! 662: globals.num_edicts = entnum+1; ! 663: ! 664: ent = &g_edicts[entnum]; ! 665: ReadEdict (f, ent); ! 666: ! 667: // let the server rebuild world links for this ent ! 668: memset (&ent->area, 0, sizeof(ent->area)); ! 669: gi.linkentity (ent); ! 670: } ! 671: ! 672: fclose (f); ! 673: ! 674: // mark all clients as unconnected ! 675: for (i=0 ; i<maxclients->value ; i++) ! 676: { ! 677: ent = &g_edicts[i+1]; ! 678: ent->client = game.clients + i; ! 679: ent->client->pers.connected = false; ! 680: } ! 681: ! 682: // do any load time things at this point ! 683: for (i=0 ; i<globals.num_edicts ; i++) ! 684: { ! 685: ent = &g_edicts[i]; ! 686: ! 687: if (!ent->inuse) ! 688: continue; ! 689: ! 690: // fire any cross-level triggers ! 691: if (ent->classname) ! 692: if (strcmp(ent->classname, "target_crosslevel_target") == 0) ! 693: ent->nextthink = level.time + ent->delay; ! 694: } ! 695: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.