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