g_save.c (18283B)
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 */ 20 21 #include "g_local.h" 22 23 #define Function(f) {#f, f} 24 25 mmove_t mmove_reloc; 26 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}, 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}, 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}, 104 105 //need for item field in edict struct, FFL_SPAWNTEMP item will be skipped on saves 106 {"item", FOFS(item), F_ITEM}, 107 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}, 116 {"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP}, 117 118 {0, 0, 0, 0} 119 120 }; 121 122 field_t levelfields[] = 123 { 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}, 130 131 {NULL, 0, F_INT} 132 }; 133 134 field_t clientfields[] = 135 { 136 {"pers.weapon", CLOFS(pers.weapon), F_ITEM}, 137 {"pers.lastweapon", CLOFS(pers.lastweapon), F_ITEM}, 138 {"newweapon", CLOFS(newweapon), F_ITEM}, 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); 175 maxspectators = gi.cvar ("maxspectators", "4", CVAR_SERVERINFO); 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); 186 spectator_password = gi.cvar ("spectator_password", "", CVAR_USERINFO); 187 filterban = gi.cvar ("filterban", "1", 0); 188 189 g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE); 190 191 run_pitch = gi.cvar ("run_pitch", "0.002", 0); 192 run_roll = gi.cvar ("run_roll", "0.005", 0); 193 bob_up = gi.cvar ("bob_up", "0.005", 0); 194 bob_pitch = gi.cvar ("bob_pitch", "0.002", 0); 195 bob_roll = gi.cvar ("bob_roll", "0.002", 0); 196 197 // flood control 198 flood_msgs = gi.cvar ("flood_msgs", "4", 0); 199 flood_persecond = gi.cvar ("flood_persecond", "4", 0); 200 flood_waitdelay = gi.cvar ("flood_waitdelay", "10", 0); 201 202 // dm map list 203 sv_maplist = gi.cvar ("sv_maplist", "", 0); 204 205 // items 206 InitItems (); 207 208 Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), ""); 209 210 Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), ""); 211 212 // initialize all entities for this game 213 game.maxentities = maxentities->value; 214 g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME); 215 globals.edicts = g_edicts; 216 globals.max_edicts = game.maxentities; 217 218 // initialize all clients for this game 219 game.maxclients = maxclients->value; 220 game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME); 221 globals.num_edicts = game.maxclients+1; 222 } 223 224 //========================================================= 225 226 void WriteField1 (FILE *f, field_t *field, byte *base) 227 { 228 void *p; 229 int len; 230 int index; 231 232 if (field->flags & FFL_SPAWNTEMP) 233 return; 234 235 p = (void *)(base + field->ofs); 236 switch (field->type) 237 { 238 case F_INT: 239 case F_FLOAT: 240 case F_ANGLEHACK: 241 case F_VECTOR: 242 case F_IGNORE: 243 break; 244 245 case F_LSTRING: 246 case F_GSTRING: 247 if ( *(char **)p ) 248 len = strlen(*(char **)p) + 1; 249 else 250 len = 0; 251 *(int *)p = len; 252 break; 253 case F_EDICT: 254 if ( *(edict_t **)p == NULL) 255 index = -1; 256 else 257 index = *(edict_t **)p - g_edicts; 258 *(int *)p = index; 259 break; 260 case F_CLIENT: 261 if ( *(gclient_t **)p == NULL) 262 index = -1; 263 else 264 index = *(gclient_t **)p - game.clients; 265 *(int *)p = index; 266 break; 267 case F_ITEM: 268 if ( *(edict_t **)p == NULL) 269 index = -1; 270 else 271 index = *(gitem_t **)p - itemlist; 272 *(int *)p = index; 273 break; 274 275 //relative to code segment 276 case F_FUNCTION: 277 if (*(byte **)p == NULL) 278 index = 0; 279 else 280 index = *(byte **)p - ((byte *)InitGame); 281 *(int *)p = index; 282 break; 283 284 //relative to data segment 285 case F_MMOVE: 286 if (*(byte **)p == NULL) 287 index = 0; 288 else 289 index = *(byte **)p - (byte *)&mmove_reloc; 290 *(int *)p = index; 291 break; 292 293 default: 294 gi.error ("WriteEdict: unknown field type"); 295 } 296 } 297 298 299 void WriteField2 (FILE *f, field_t *field, byte *base) 300 { 301 int len; 302 void *p; 303 304 if (field->flags & FFL_SPAWNTEMP) 305 return; 306 307 p = (void *)(base + field->ofs); 308 switch (field->type) 309 { 310 case F_LSTRING: 311 if ( *(char **)p ) 312 { 313 len = strlen(*(char **)p) + 1; 314 fwrite (*(char **)p, len, 1, f); 315 } 316 break; 317 } 318 } 319 320 void ReadField (FILE *f, field_t *field, byte *base) 321 { 322 void *p; 323 int len; 324 int index; 325 326 if (field->flags & FFL_SPAWNTEMP) 327 return; 328 329 p = (void *)(base + field->ofs); 330 switch (field->type) 331 { 332 case F_INT: 333 case F_FLOAT: 334 case F_ANGLEHACK: 335 case F_VECTOR: 336 case F_IGNORE: 337 break; 338 339 case F_LSTRING: 340 len = *(int *)p; 341 if (!len) 342 *(char **)p = NULL; 343 else 344 { 345 *(char **)p = gi.TagMalloc (len, TAG_LEVEL); 346 fread (*(char **)p, len, 1, f); 347 } 348 break; 349 case F_EDICT: 350 index = *(int *)p; 351 if ( index == -1 ) 352 *(edict_t **)p = NULL; 353 else 354 *(edict_t **)p = &g_edicts[index]; 355 break; 356 case F_CLIENT: 357 index = *(int *)p; 358 if ( index == -1 ) 359 *(gclient_t **)p = NULL; 360 else 361 *(gclient_t **)p = &game.clients[index]; 362 break; 363 case F_ITEM: 364 index = *(int *)p; 365 if ( index == -1 ) 366 *(gitem_t **)p = NULL; 367 else 368 *(gitem_t **)p = &itemlist[index]; 369 break; 370 371 //relative to code segment 372 case F_FUNCTION: 373 index = *(int *)p; 374 if ( index == 0 ) 375 *(byte **)p = NULL; 376 else 377 *(byte **)p = ((byte *)InitGame) + index; 378 break; 379 380 //relative to data segment 381 case F_MMOVE: 382 index = *(int *)p; 383 if (index == 0) 384 *(byte **)p = NULL; 385 else 386 *(byte **)p = (byte *)&mmove_reloc + index; 387 break; 388 389 default: 390 gi.error ("ReadEdict: unknown field type"); 391 } 392 } 393 394 //========================================================= 395 396 /* 397 ============== 398 WriteClient 399 400 All pointer variables (except function pointers) must be handled specially. 401 ============== 402 */ 403 void WriteClient (FILE *f, gclient_t *client) 404 { 405 field_t *field; 406 gclient_t temp; 407 408 // all of the ints, floats, and vectors stay as they are 409 temp = *client; 410 411 // change the pointers to lengths or indexes 412 for (field=clientfields ; field->name ; field++) 413 { 414 WriteField1 (f, field, (byte *)&temp); 415 } 416 417 // write the block 418 fwrite (&temp, sizeof(temp), 1, f); 419 420 // now write any allocated data following the edict 421 for (field=clientfields ; field->name ; field++) 422 { 423 WriteField2 (f, field, (byte *)client); 424 } 425 } 426 427 /* 428 ============== 429 ReadClient 430 431 All pointer variables (except function pointers) must be handled specially. 432 ============== 433 */ 434 void ReadClient (FILE *f, gclient_t *client) 435 { 436 field_t *field; 437 438 fread (client, sizeof(*client), 1, f); 439 440 for (field=clientfields ; field->name ; field++) 441 { 442 ReadField (f, field, (byte *)client); 443 } 444 } 445 446 /* 447 ============ 448 WriteGame 449 450 This will be called whenever the game goes to a new level, 451 and when the user explicitly saves the game. 452 453 Game information include cross level data, like multi level 454 triggers, help computer info, and all client states. 455 456 A single player death will automatically restore from the 457 last save position. 458 ============ 459 */ 460 void WriteGame (char *filename, qboolean autosave) 461 { 462 FILE *f; 463 int i; 464 char str[16]; 465 466 if (!autosave) 467 SaveClientData (); 468 469 f = fopen (filename, "wb"); 470 if (!f) 471 gi.error ("Couldn't open %s", filename); 472 473 memset (str, 0, sizeof(str)); 474 strcpy (str, __DATE__); 475 fwrite (str, sizeof(str), 1, f); 476 477 game.autosaved = autosave; 478 fwrite (&game, sizeof(game), 1, f); 479 game.autosaved = false; 480 481 for (i=0 ; i<game.maxclients ; i++) 482 WriteClient (f, &game.clients[i]); 483 484 fclose (f); 485 } 486 487 void ReadGame (char *filename) 488 { 489 FILE *f; 490 int i; 491 char str[16]; 492 493 gi.FreeTags (TAG_GAME); 494 495 f = fopen (filename, "rb"); 496 if (!f) 497 gi.error ("Couldn't open %s", filename); 498 499 fread (str, sizeof(str), 1, f); 500 if (strcmp (str, __DATE__)) 501 { 502 fclose (f); 503 gi.error ("Savegame from an older version.\n"); 504 } 505 506 g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME); 507 globals.edicts = g_edicts; 508 509 fread (&game, sizeof(game), 1, f); 510 game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME); 511 for (i=0 ; i<game.maxclients ; i++) 512 ReadClient (f, &game.clients[i]); 513 514 fclose (f); 515 } 516 517 //========================================================== 518 519 520 /* 521 ============== 522 WriteEdict 523 524 All pointer variables (except function pointers) must be handled specially. 525 ============== 526 */ 527 void WriteEdict (FILE *f, edict_t *ent) 528 { 529 field_t *field; 530 edict_t temp; 531 532 // all of the ints, floats, and vectors stay as they are 533 temp = *ent; 534 535 // change the pointers to lengths or indexes 536 for (field=fields ; field->name ; field++) 537 { 538 WriteField1 (f, field, (byte *)&temp); 539 } 540 541 // write the block 542 fwrite (&temp, sizeof(temp), 1, f); 543 544 // now write any allocated data following the edict 545 for (field=fields ; field->name ; field++) 546 { 547 WriteField2 (f, field, (byte *)ent); 548 } 549 550 } 551 552 /* 553 ============== 554 WriteLevelLocals 555 556 All pointer variables (except function pointers) must be handled specially. 557 ============== 558 */ 559 void WriteLevelLocals (FILE *f) 560 { 561 field_t *field; 562 level_locals_t temp; 563 564 // all of the ints, floats, and vectors stay as they are 565 temp = level; 566 567 // change the pointers to lengths or indexes 568 for (field=levelfields ; field->name ; field++) 569 { 570 WriteField1 (f, field, (byte *)&temp); 571 } 572 573 // write the block 574 fwrite (&temp, sizeof(temp), 1, f); 575 576 // now write any allocated data following the edict 577 for (field=levelfields ; field->name ; field++) 578 { 579 WriteField2 (f, field, (byte *)&level); 580 } 581 } 582 583 584 /* 585 ============== 586 ReadEdict 587 588 All pointer variables (except function pointers) must be handled specially. 589 ============== 590 */ 591 void ReadEdict (FILE *f, edict_t *ent) 592 { 593 field_t *field; 594 595 fread (ent, sizeof(*ent), 1, f); 596 597 for (field=fields ; field->name ; field++) 598 { 599 ReadField (f, field, (byte *)ent); 600 } 601 } 602 603 /* 604 ============== 605 ReadLevelLocals 606 607 All pointer variables (except function pointers) must be handled specially. 608 ============== 609 */ 610 void ReadLevelLocals (FILE *f) 611 { 612 field_t *field; 613 614 fread (&level, sizeof(level), 1, f); 615 616 for (field=levelfields ; field->name ; field++) 617 { 618 ReadField (f, field, (byte *)&level); 619 } 620 } 621 622 /* 623 ================= 624 WriteLevel 625 626 ================= 627 */ 628 void WriteLevel (char *filename) 629 { 630 int i; 631 edict_t *ent; 632 FILE *f; 633 void *base; 634 635 f = fopen (filename, "wb"); 636 if (!f) 637 gi.error ("Couldn't open %s", filename); 638 639 // write out edict size for checking 640 i = sizeof(edict_t); 641 fwrite (&i, sizeof(i), 1, f); 642 643 // write out a function pointer for checking 644 base = (void *)InitGame; 645 fwrite (&base, sizeof(base), 1, f); 646 647 // write out level_locals_t 648 WriteLevelLocals (f); 649 650 // write out all the entities 651 for (i=0 ; i<globals.num_edicts ; i++) 652 { 653 ent = &g_edicts[i]; 654 if (!ent->inuse) 655 continue; 656 fwrite (&i, sizeof(i), 1, f); 657 WriteEdict (f, ent); 658 } 659 i = -1; 660 fwrite (&i, sizeof(i), 1, f); 661 662 fclose (f); 663 } 664 665 666 /* 667 ================= 668 ReadLevel 669 670 SpawnEntities will allready have been called on the 671 level the same way it was when the level was saved. 672 673 That is necessary to get the baselines 674 set up identically. 675 676 The server will have cleared all of the world links before 677 calling ReadLevel. 678 679 No clients are connected yet. 680 ================= 681 */ 682 void ReadLevel (char *filename) 683 { 684 int entnum; 685 FILE *f; 686 int i; 687 void *base; 688 edict_t *ent; 689 690 f = fopen (filename, "rb"); 691 if (!f) 692 gi.error ("Couldn't open %s", filename); 693 694 // free any dynamic memory allocated by loading the level 695 // base state 696 gi.FreeTags (TAG_LEVEL); 697 698 // wipe all the entities 699 memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0])); 700 globals.num_edicts = maxclients->value+1; 701 702 // check edict size 703 fread (&i, sizeof(i), 1, f); 704 if (i != sizeof(edict_t)) 705 { 706 fclose (f); 707 gi.error ("ReadLevel: mismatched edict size"); 708 } 709 710 // check function pointer base address 711 fread (&base, sizeof(base), 1, f); 712 #ifdef _WIN32 713 if (base != (void *)InitGame) 714 { 715 fclose (f); 716 gi.error ("ReadLevel: function pointers have moved"); 717 } 718 #else 719 gi.dprintf("Function offsets %d\n", ((byte *)base) - ((byte *)InitGame)); 720 #endif 721 722 // load the level locals 723 ReadLevelLocals (f); 724 725 // load all the entities 726 while (1) 727 { 728 if (fread (&entnum, sizeof(entnum), 1, f) != 1) 729 { 730 fclose (f); 731 gi.error ("ReadLevel: failed to read entnum"); 732 } 733 if (entnum == -1) 734 break; 735 if (entnum >= globals.num_edicts) 736 globals.num_edicts = entnum+1; 737 738 ent = &g_edicts[entnum]; 739 ReadEdict (f, ent); 740 741 // let the server rebuild world links for this ent 742 memset (&ent->area, 0, sizeof(ent->area)); 743 gi.linkentity (ent); 744 } 745 746 fclose (f); 747 748 // mark all clients as unconnected 749 for (i=0 ; i<maxclients->value ; i++) 750 { 751 ent = &g_edicts[i+1]; 752 ent->client = game.clients + i; 753 ent->client->pers.connected = false; 754 } 755 756 // do any load time things at this point 757 for (i=0 ; i<globals.num_edicts ; i++) 758 { 759 ent = &g_edicts[i]; 760 761 if (!ent->inuse) 762 continue; 763 764 // fire any cross-level triggers 765 if (ent->classname) 766 if (strcmp(ent->classname, "target_crosslevel_target") == 0) 767 ent->nextthink = level.time + ent->delay; 768 } 769 }