p_saveg.cpp (26293B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #include "Precompiled.h" 30 #include "globaldata.h" 31 32 #include "i_system.h" 33 #include "z_zone.h" 34 #include "p_local.h" 35 36 // State. 37 #include "doomstat.h" 38 #include "r_state.h" 39 40 41 42 // Pads ::g->save_p to a 4-byte boundary 43 // so that the load/save works on SGI&Gecko. 44 45 46 47 // 48 // P_ArchivePlayers 49 // 50 void P_ArchivePlayers (void) 51 { 52 int i; 53 int j; 54 player_t* dest; 55 56 for (i=0 ; i<MAXPLAYERS ; i++) 57 { 58 if (!::g->playeringame[i]) 59 continue; 60 61 PADSAVEP(); 62 63 dest = (player_t *)::g->save_p; 64 memcpy (dest,&::g->players[i],sizeof(player_t)); 65 ::g->save_p += sizeof(player_t); 66 for (j=0 ; j<NUMPSPRITES ; j++) 67 { 68 if (dest->psprites[j].state) 69 { 70 dest->psprites[j].state 71 = (state_t *)(dest->psprites[j].state-::g->states); 72 } 73 } 74 } 75 } 76 77 78 79 // 80 // P_UnArchivePlayers 81 // 82 void P_UnArchivePlayers (void) 83 { 84 int i; 85 int j; 86 87 for (i=0 ; i<MAXPLAYERS ; i++) 88 { 89 if (!::g->playeringame[i]) 90 continue; 91 92 PADSAVEP(); 93 94 memcpy (&::g->players[i],::g->save_p, sizeof(player_t)); 95 ::g->save_p += sizeof(player_t); 96 97 // will be set when unarc thinker 98 ::g->players[i].mo = NULL; 99 ::g->players[i].message = NULL; 100 ::g->players[i].attacker = NULL; 101 102 for (j=0 ; j<NUMPSPRITES ; j++) 103 { 104 if (::g->players[i]. psprites[j].state) 105 { 106 ::g->players[i]. psprites[j].state 107 = &::g->states[ (int)::g->players[i].psprites[j].state ]; 108 } 109 } 110 } 111 } 112 113 114 // 115 // P_ArchiveWorld 116 // 117 void P_ArchiveWorld (void) 118 { 119 int i; 120 int j; 121 sector_t* sec; 122 line_t* li; 123 side_t* si; 124 short* put; 125 126 put = (short *)::g->save_p; 127 128 // do ::g->sectors 129 for (i=0, sec = ::g->sectors ; i < ::g->numsectors ; i++,sec++) 130 { 131 *put++ = sec->floorheight >> FRACBITS; 132 *put++ = sec->ceilingheight >> FRACBITS; 133 *put++ = sec->floorpic; 134 *put++ = sec->ceilingpic; 135 *put++ = sec->lightlevel; 136 *put++ = sec->special; // needed? 137 *put++ = sec->tag; // needed? 138 } 139 140 141 // do ::g->lines 142 for (i=0, li = ::g->lines ; i < ::g->numlines ; i++,li++) 143 { 144 *put++ = li->flags; 145 *put++ = li->special; 146 *put++ = li->tag; 147 for (j=0 ; j<2 ; j++) 148 { 149 if (li->sidenum[j] == -1) 150 continue; 151 152 si = &::g->sides[li->sidenum[j]]; 153 154 *put++ = si->textureoffset >> FRACBITS; 155 *put++ = si->rowoffset >> FRACBITS; 156 *put++ = si->toptexture; 157 *put++ = si->bottomtexture; 158 *put++ = si->midtexture; 159 } 160 } 161 162 // Doom 2 level 30 requires some global pointers, wheee! 163 *put++ = ::g->braintargeton; 164 *put++ = ::g->easy; 165 166 ::g->save_p = (byte *)put; 167 } 168 169 170 171 // 172 // P_UnArchiveWorld 173 // 174 void P_UnArchiveWorld (void) 175 { 176 int i; 177 int j; 178 sector_t* sec; 179 line_t* li; 180 side_t* si; 181 short* get; 182 183 get = (short *)::g->save_p; 184 185 // do ::g->sectors 186 for (i=0, sec = ::g->sectors ; i < ::g->numsectors ; i++,sec++) 187 { 188 sec->floorheight = *get++ << FRACBITS; 189 sec->ceilingheight = *get++ << FRACBITS; 190 sec->floorpic = *get++; 191 sec->ceilingpic = *get++; 192 sec->lightlevel = *get++; 193 sec->special = *get++; // needed? 194 sec->tag = *get++; // needed? 195 sec->specialdata = 0; 196 sec->soundtarget = 0; 197 } 198 199 // do ::g->lines 200 for (i=0, li = ::g->lines ; i < ::g->numlines ; i++,li++) 201 { 202 li->flags = *get++; 203 li->special = *get++; 204 li->tag = *get++; 205 for (j=0 ; j<2 ; j++) 206 { 207 if (li->sidenum[j] == -1) 208 continue; 209 si = &::g->sides[li->sidenum[j]]; 210 si->textureoffset = *get++ << FRACBITS; 211 si->rowoffset = *get++ << FRACBITS; 212 si->toptexture = *get++; 213 si->bottomtexture = *get++; 214 si->midtexture = *get++; 215 } 216 } 217 218 // Doom 2 level 30 requires some global pointers, wheee! 219 ::g->braintargeton = *get++; 220 ::g->easy = *get++; 221 222 ::g->save_p = (byte *)get; 223 } 224 225 226 227 228 229 // 230 // Thinkers 231 // 232 233 int GetMOIndex( mobj_t* findme ) { 234 thinker_t* th; 235 mobj_t* mobj; 236 int index = 0; 237 238 for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next) 239 { 240 if (th->function.acp1 == (actionf_p1)P_MobjThinker) { 241 index++; 242 mobj = (mobj_t*)th; 243 244 if ( mobj == findme ) { 245 return index; 246 } 247 } 248 } 249 250 return 0; 251 } 252 253 mobj_t* GetMO( int index ) { 254 thinker_t* th; 255 int testindex = 0; 256 257 if ( !index ) { 258 return NULL; 259 } 260 261 for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next) 262 { 263 if (th->function.acp1 == (actionf_p1)P_MobjThinker) { 264 testindex++; 265 266 if ( testindex == index ) { 267 return (mobj_t*)th; 268 } 269 } 270 } 271 272 return NULL; 273 } 274 275 // 276 // P_ArchiveThinkers 277 // 278 void P_ArchiveThinkers (void) 279 { 280 thinker_t* th; 281 mobj_t* mobj; 282 ceiling_t* ceiling; 283 vldoor_t* door; 284 floormove_t* floor; 285 plat_t* plat; 286 fireflicker_t* fire; 287 lightflash_t* flash; 288 strobe_t* strobe; 289 glow_t* glow; 290 291 int i; 292 293 // save off the current thinkers 294 //I_Printf( "Savegame on leveltime %d\n====================\n", ::g->leveltime ); 295 296 for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next) 297 { 298 //mobj_t* test = (mobj_t*)th; 299 //I_Printf( "%3d: %x == function\n", index++, th->function.acp1 ); 300 301 if (th->function.acp1 == (actionf_p1)P_MobjThinker) 302 { 303 *::g->save_p++ = tc_mobj; 304 PADSAVEP(); 305 306 mobj = (mobj_t *)::g->save_p; 307 memcpy (mobj, th, sizeof(*mobj)); 308 ::g->save_p += sizeof(*mobj); 309 mobj->state = (state_t *)(mobj->state - ::g->states); 310 311 if (mobj->player) 312 mobj->player = (player_t *)((mobj->player-::g->players) + 1); 313 314 // Save out 'target' 315 int moIndex = GetMOIndex( mobj->target ); 316 *::g->save_p++ = moIndex >> 8; 317 *::g->save_p++ = moIndex; 318 319 // Save out 'tracer' 320 moIndex = GetMOIndex( mobj->tracer ); 321 *::g->save_p++ = moIndex >> 8; 322 *::g->save_p++ = moIndex; 323 324 moIndex = GetMOIndex( mobj->snext ); 325 *::g->save_p++ = moIndex >> 8; 326 *::g->save_p++ = moIndex; 327 328 moIndex = GetMOIndex( mobj->sprev ); 329 *::g->save_p++ = moIndex >> 8; 330 *::g->save_p++ = moIndex; 331 332 // Is this the head of a sector list? 333 if ( mobj->subsector->sector->thinglist == (mobj_t*)th ) { 334 *::g->save_p++ = 1; 335 } 336 else { 337 *::g->save_p++ = 0; 338 } 339 340 moIndex = GetMOIndex( mobj->bnext ); 341 *::g->save_p++ = moIndex >> 8; 342 *::g->save_p++ = moIndex; 343 344 moIndex = GetMOIndex( mobj->bprev ); 345 *::g->save_p++ = moIndex >> 8; 346 *::g->save_p++ = moIndex; 347 348 // Is this the head of a block list? 349 int blockx = (mobj->x - ::g->bmaporgx)>>MAPBLOCKSHIFT; 350 int blocky = (mobj->y - ::g->bmaporgy)>>MAPBLOCKSHIFT; 351 if ( blockx >= 0 && blockx < ::g->bmapwidth && blocky >= 0 && blocky < ::g->bmapheight 352 && (mobj_t*)th == ::g->blocklinks[blocky*::g->bmapwidth+blockx] ) { 353 354 *::g->save_p++ = 1; 355 } 356 else { 357 *::g->save_p++ = 0; 358 } 359 continue; 360 } 361 362 if (th->function.acv == (actionf_v)NULL) 363 { 364 for (i = 0; i < MAXCEILINGS;i++) 365 if (::g->activeceilings[i] == (ceiling_t *)th) 366 break; 367 368 if (i<MAXCEILINGS) 369 { 370 *::g->save_p++ = tc_ceiling; 371 PADSAVEP(); 372 ceiling = (ceiling_t *)::g->save_p; 373 memcpy (ceiling, th, sizeof(*ceiling)); 374 ::g->save_p += sizeof(*ceiling); 375 ceiling->sector = (sector_t *)(ceiling->sector - ::g->sectors); 376 } 377 continue; 378 } 379 380 if (th->function.acp1 == (actionf_p1)T_MoveCeiling) 381 { 382 *::g->save_p++ = tc_ceiling; 383 PADSAVEP(); 384 ceiling = (ceiling_t *)::g->save_p; 385 memcpy (ceiling, th, sizeof(*ceiling)); 386 ::g->save_p += sizeof(*ceiling); 387 ceiling->sector = (sector_t *)(ceiling->sector - ::g->sectors); 388 continue; 389 } 390 391 if (th->function.acp1 == (actionf_p1)T_VerticalDoor) 392 { 393 *::g->save_p++ = tc_door; 394 PADSAVEP(); 395 door = (vldoor_t *)::g->save_p; 396 memcpy (door, th, sizeof(*door)); 397 ::g->save_p += sizeof(*door); 398 door->sector = (sector_t *)(door->sector - ::g->sectors); 399 continue; 400 } 401 402 if (th->function.acp1 == (actionf_p1)T_MoveFloor) 403 { 404 *::g->save_p++ = tc_floor; 405 PADSAVEP(); 406 floor = (floormove_t *)::g->save_p; 407 memcpy (floor, th, sizeof(*floor)); 408 ::g->save_p += sizeof(*floor); 409 floor->sector = (sector_t *)(floor->sector - ::g->sectors); 410 continue; 411 } 412 413 if (th->function.acp1 == (actionf_p1)T_PlatRaise) 414 { 415 *::g->save_p++ = tc_plat; 416 PADSAVEP(); 417 plat = (plat_t *)::g->save_p; 418 memcpy (plat, th, sizeof(*plat)); 419 ::g->save_p += sizeof(*plat); 420 plat->sector = (sector_t *)(plat->sector - ::g->sectors); 421 continue; 422 } 423 424 if (th->function.acp1 == (actionf_p1)T_FireFlicker) 425 { 426 *::g->save_p++ = tc_fire; 427 PADSAVEP(); 428 fire = (fireflicker_t *)::g->save_p; 429 memcpy (fire, th, sizeof(*fire)); 430 ::g->save_p += sizeof(*fire); 431 fire->sector = (sector_t *)(fire->sector - ::g->sectors); 432 continue; 433 } 434 435 if (th->function.acp1 == (actionf_p1)T_LightFlash) 436 { 437 *::g->save_p++ = tc_flash; 438 PADSAVEP(); 439 flash = (lightflash_t *)::g->save_p; 440 memcpy (flash, th, sizeof(*flash)); 441 ::g->save_p += sizeof(*flash); 442 flash->sector = (sector_t *)(flash->sector - ::g->sectors); 443 continue; 444 } 445 446 if (th->function.acp1 == (actionf_p1)T_StrobeFlash) 447 { 448 *::g->save_p++ = tc_strobe; 449 PADSAVEP(); 450 strobe = (strobe_t *)::g->save_p; 451 memcpy (strobe, th, sizeof(*strobe)); 452 ::g->save_p += sizeof(*strobe); 453 strobe->sector = (sector_t *)(strobe->sector - ::g->sectors); 454 continue; 455 } 456 457 if (th->function.acp1 == (actionf_p1)T_Glow) 458 { 459 *::g->save_p++ = tc_glow; 460 PADSAVEP(); 461 glow = (glow_t *)::g->save_p; 462 memcpy (glow, th, sizeof(*glow)); 463 ::g->save_p += sizeof(*glow); 464 glow->sector = (sector_t *)(glow->sector - ::g->sectors); 465 continue; 466 } 467 } 468 469 // add a terminating marker 470 *::g->save_p++ = tc_end; 471 472 sector_t* sec; 473 short* put = (short *)::g->save_p; 474 for (i=0, sec = ::g->sectors ; i < ::g->numsectors ; i++,sec++) { 475 *put++ = (short)GetMOIndex( sec->soundtarget ); 476 } 477 478 ::g->save_p = (byte *)put; 479 480 // add a terminating marker 481 *::g->save_p++ = tc_end; 482 } 483 484 485 486 // 487 // P_UnArchiveThinkers 488 // 489 void P_UnArchiveThinkers (void) 490 { 491 byte tclass; 492 thinker_t* currentthinker; 493 thinker_t* next; 494 mobj_t* mobj; 495 ceiling_t* ceiling; 496 vldoor_t* door; 497 floormove_t* floor; 498 plat_t* plat; 499 fireflicker_t* fire; 500 lightflash_t* flash; 501 strobe_t* strobe; 502 glow_t* glow; 503 504 thinker_t* th; 505 506 int count = 0; 507 sector_t* ss = NULL; 508 509 int mo_index = 0; 510 int mo_targets[1024]; 511 int mo_tracers[1024]; 512 int mo_snext[1024]; 513 int mo_sprev[1024]; 514 bool mo_shead[1024]; 515 int mo_bnext[1024]; 516 int mo_bprev[1024]; 517 bool mo_bhead[1024]; 518 519 // remove all the current thinkers 520 currentthinker = ::g->thinkercap.next; 521 while (currentthinker != &::g->thinkercap) 522 { 523 next = currentthinker->next; 524 525 if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) 526 P_RemoveMobj ((mobj_t *)currentthinker); 527 else 528 Z_Free(currentthinker); 529 530 currentthinker = next; 531 } 532 533 P_InitThinkers (); 534 535 // read in saved thinkers 536 while (1) 537 { 538 tclass = *::g->save_p++; 539 switch (tclass) 540 { 541 case tc_end: 542 543 // clear sector thing lists 544 ss = ::g->sectors; 545 for (int i=0 ; i < ::g->numsectors ; i++, ss++) { 546 ss->thinglist = NULL; 547 } 548 549 // clear blockmap thing lists 550 count = sizeof(*::g->blocklinks) * ::g->bmapwidth * ::g->bmapheight; 551 memset (::g->blocklinks, 0, count); 552 553 // Doom 2 level 30 requires some global pointers, wheee! 554 ::g->numbraintargets = 0; 555 556 // fixup mobj_t pointers now that all thinkers have been restored 557 mo_index = 0; 558 for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next) { 559 if (th->function.acp1 == (actionf_p1)P_MobjThinker) { 560 mobj = (mobj_t*)th; 561 562 mobj->target = GetMO( mo_targets[mo_index] ); 563 mobj->tracer = GetMO( mo_tracers[mo_index] ); 564 565 mobj->snext = GetMO( mo_snext[mo_index] ); 566 mobj->sprev = GetMO( mo_sprev[mo_index] ); 567 568 if ( mo_shead[mo_index] ) { 569 mobj->subsector->sector->thinglist = mobj; 570 } 571 572 mobj->bnext = GetMO( mo_bnext[mo_index] ); 573 mobj->bprev = GetMO( mo_bprev[mo_index] ); 574 575 if ( mo_bhead[mo_index] ) { 576 // Is this the head of a block list? 577 int blockx = (mobj->x - ::g->bmaporgx)>>MAPBLOCKSHIFT; 578 int blocky = (mobj->y - ::g->bmaporgy)>>MAPBLOCKSHIFT; 579 if ( blockx >= 0 && blockx < ::g->bmapwidth && blocky >= 0 && blocky < ::g->bmapheight ) { 580 ::g->blocklinks[blocky*::g->bmapwidth+blockx] = mobj; 581 } 582 } 583 584 // Doom 2 level 30 requires some global pointers, wheee! 585 if ( mobj->type == MT_BOSSTARGET ) { 586 ::g->braintargets[::g->numbraintargets] = mobj; 587 ::g->numbraintargets++; 588 } 589 590 mo_index++; 591 } 592 } 593 594 int i; 595 sector_t* sec; 596 short* get; 597 598 get = (short *)::g->save_p; 599 for (i=0, sec = ::g->sectors ; i < ::g->numsectors ; i++,sec++) 600 { 601 sec->soundtarget = GetMO( *get++ ); 602 } 603 ::g->save_p = (byte *)get; 604 605 tclass = *::g->save_p++; 606 if ( tclass != tc_end ) { 607 I_Error( "Savegame error after loading sector soundtargets." ); 608 } 609 610 // print the current thinkers 611 //I_Printf( "Loadgame on leveltime %d\n====================\n", ::g->leveltime ); 612 for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next) 613 { 614 //mobj_t* test = (mobj_t*)th; 615 //I_Printf( "%3d: %x == function\n", index++, th->function.acp1 ); 616 } 617 618 return; // end of list 619 620 case tc_mobj: 621 PADSAVEP(); 622 mobj = (mobj_t*)DoomLib::Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL); 623 memcpy (mobj, ::g->save_p, sizeof(*mobj)); 624 ::g->save_p += sizeof(*mobj); 625 mobj->state = &::g->states[(int)mobj->state]; 626 627 mobj->target = NULL; 628 mobj->tracer = NULL; 629 630 if (mobj->player) 631 { 632 mobj->player = &::g->players[(int)mobj->player-1]; 633 mobj->player->mo = mobj; 634 } 635 636 P_SetThingPosition (mobj); 637 638 mobj->info = &mobjinfo[mobj->type]; 639 mobj->floorz = mobj->subsector->sector->floorheight; 640 mobj->ceilingz = mobj->subsector->sector->ceilingheight; 641 mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; 642 643 // Read in 'target' and store for fixup 644 int a, b, foundIndex; 645 a = *::g->save_p++; 646 b = *::g->save_p++; 647 foundIndex = (a << 8) + b; 648 mo_targets[mo_index] = foundIndex; 649 650 // Read in 'tracer' and store for fixup 651 a = *::g->save_p++; 652 b = *::g->save_p++; 653 foundIndex = (a << 8) + b; 654 mo_tracers[mo_index] = foundIndex; 655 656 // Read in 'snext' and store for fixup 657 a = *::g->save_p++; 658 b = *::g->save_p++; 659 foundIndex = (a << 8) + b; 660 mo_snext[mo_index] = foundIndex; 661 662 // Read in 'sprev' and store for fixup 663 a = *::g->save_p++; 664 b = *::g->save_p++; 665 foundIndex = (a << 8) + b; 666 mo_sprev[mo_index] = foundIndex; 667 668 foundIndex = *::g->save_p++; 669 mo_shead[mo_index] = foundIndex == 1; 670 671 // Read in 'bnext' and store for fixup 672 a = *::g->save_p++; 673 b = *::g->save_p++; 674 foundIndex = (a << 8) + b; 675 mo_bnext[mo_index] = foundIndex; 676 677 // Read in 'bprev' and store for fixup 678 a = *::g->save_p++; 679 b = *::g->save_p++; 680 foundIndex = (a << 8) + b; 681 mo_bprev[mo_index] = foundIndex; 682 683 foundIndex = *::g->save_p++; 684 mo_bhead[mo_index] = foundIndex == 1; 685 686 mo_index++; 687 688 P_AddThinker (&mobj->thinker); 689 break; 690 691 case tc_ceiling: 692 PADSAVEP(); 693 ceiling = (ceiling_t*)DoomLib::Z_Malloc(sizeof(*ceiling), PU_LEVEL, NULL); 694 memcpy (ceiling, ::g->save_p, sizeof(*ceiling)); 695 ::g->save_p += sizeof(*ceiling); 696 ceiling->sector = &::g->sectors[(int)ceiling->sector]; 697 ceiling->sector->specialdata = ceiling; 698 699 if (ceiling->thinker.function.acp1) 700 ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; 701 702 P_AddThinker (&ceiling->thinker); 703 P_AddActiveCeiling(ceiling); 704 break; 705 706 case tc_door: 707 PADSAVEP(); 708 door = (vldoor_t*)DoomLib::Z_Malloc(sizeof(*door), PU_LEVEL, NULL); 709 memcpy (door, ::g->save_p, sizeof(*door)); 710 ::g->save_p += sizeof(*door); 711 door->sector = &::g->sectors[(int)door->sector]; 712 door->sector->specialdata = door; 713 door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; 714 P_AddThinker (&door->thinker); 715 break; 716 717 case tc_floor: 718 PADSAVEP(); 719 floor = (floormove_t*)DoomLib::Z_Malloc (sizeof(*floor), PU_LEVEL, NULL); 720 memcpy (floor, ::g->save_p, sizeof(*floor)); 721 ::g->save_p += sizeof(*floor); 722 floor->sector = &::g->sectors[(int)floor->sector]; 723 floor->sector->specialdata = floor; 724 floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor; 725 P_AddThinker (&floor->thinker); 726 break; 727 728 case tc_plat: 729 PADSAVEP(); 730 plat = (plat_t*)DoomLib::Z_Malloc (sizeof(*plat), PU_LEVEL, NULL); 731 memcpy (plat, ::g->save_p, sizeof(*plat)); 732 ::g->save_p += sizeof(*plat); 733 plat->sector = &::g->sectors[(int)plat->sector]; 734 plat->sector->specialdata = plat; 735 736 if (plat->thinker.function.acp1) 737 plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise; 738 739 P_AddThinker (&plat->thinker); 740 P_AddActivePlat(plat); 741 break; 742 743 case tc_fire: 744 PADSAVEP(); 745 fire = (fireflicker_t*)DoomLib::Z_Malloc (sizeof(*fire), PU_LEVEL, NULL); 746 memcpy (fire, ::g->save_p, sizeof(*fire)); 747 ::g->save_p += sizeof(*fire); 748 fire->sector = &::g->sectors[(int)fire->sector]; 749 fire->thinker.function.acp1 = (actionf_p1)T_FireFlicker; 750 P_AddThinker (&fire->thinker); 751 break; 752 753 case tc_flash: 754 PADSAVEP(); 755 flash = (lightflash_t*)DoomLib::Z_Malloc (sizeof(*flash), PU_LEVEL, NULL); 756 memcpy (flash, ::g->save_p, sizeof(*flash)); 757 ::g->save_p += sizeof(*flash); 758 flash->sector = &::g->sectors[(int)flash->sector]; 759 flash->thinker.function.acp1 = (actionf_p1)T_LightFlash; 760 P_AddThinker (&flash->thinker); 761 break; 762 763 case tc_strobe: 764 PADSAVEP(); 765 strobe = (strobe_t*)DoomLib::Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL); 766 memcpy (strobe, ::g->save_p, sizeof(*strobe)); 767 ::g->save_p += sizeof(*strobe); 768 strobe->sector = &::g->sectors[(int)strobe->sector]; 769 strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash; 770 P_AddThinker (&strobe->thinker); 771 break; 772 773 case tc_glow: 774 PADSAVEP(); 775 glow = (glow_t*)DoomLib::Z_Malloc (sizeof(*glow), PU_LEVEL, NULL); 776 memcpy (glow, ::g->save_p, sizeof(*glow)); 777 ::g->save_p += sizeof(*glow); 778 glow->sector = &::g->sectors[(int)glow->sector]; 779 glow->thinker.function.acp1 = (actionf_p1)T_Glow; 780 P_AddThinker (&glow->thinker); 781 break; 782 783 default: 784 I_Error ("Unknown tclass %i in savegame",tclass); 785 } 786 } 787 } 788 789 790 // 791 // P_ArchiveSpecials 792 // 793 794 795 796 // 797 // Things to handle: 798 // 799 // T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list 800 // T_VerticalDoor, (vldoor_t: sector_t * swizzle), 801 // T_MoveFloor, (floormove_t: sector_t * swizzle), 802 // T_LightFlash, (lightflash_t: sector_t * swizzle), 803 // T_StrobeFlash, (strobe_t: sector_t *), 804 // T_Glow, (glow_t: sector_t *), 805 // T_PlatRaise, (plat_t: sector_t *), - active list 806 // 807 void P_ArchiveSpecials (void) 808 { 809 thinker_t* th; 810 ceiling_t* ceiling; 811 vldoor_t* door; 812 floormove_t* floor; 813 plat_t* plat; 814 lightflash_t* flash; 815 strobe_t* strobe; 816 glow_t* glow; 817 int i; 818 819 // save off the current thinkers 820 for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next) 821 { 822 if (th->function.acv == (actionf_v)NULL) 823 { 824 for (i = 0; i < MAXCEILINGS;i++) 825 if (::g->activeceilings[i] == (ceiling_t *)th) 826 break; 827 828 if (i<MAXCEILINGS) 829 { 830 *::g->save_p++ = tc_ceiling; 831 PADSAVEP(); 832 ceiling = (ceiling_t *)::g->save_p; 833 memcpy (ceiling, th, sizeof(*ceiling)); 834 ::g->save_p += sizeof(*ceiling); 835 ceiling->sector = (sector_t *)(ceiling->sector - ::g->sectors); 836 } 837 continue; 838 } 839 840 if (th->function.acp1 == (actionf_p1)T_MoveCeiling) 841 { 842 *::g->save_p++ = tc_ceiling; 843 PADSAVEP(); 844 ceiling = (ceiling_t *)::g->save_p; 845 memcpy (ceiling, th, sizeof(*ceiling)); 846 ::g->save_p += sizeof(*ceiling); 847 ceiling->sector = (sector_t *)(ceiling->sector - ::g->sectors); 848 continue; 849 } 850 851 if (th->function.acp1 == (actionf_p1)T_VerticalDoor) 852 { 853 *::g->save_p++ = tc_door; 854 PADSAVEP(); 855 door = (vldoor_t *)::g->save_p; 856 memcpy (door, th, sizeof(*door)); 857 ::g->save_p += sizeof(*door); 858 door->sector = (sector_t *)(door->sector - ::g->sectors); 859 continue; 860 } 861 862 if (th->function.acp1 == (actionf_p1)T_MoveFloor) 863 { 864 *::g->save_p++ = tc_floor; 865 PADSAVEP(); 866 floor = (floormove_t *)::g->save_p; 867 memcpy (floor, th, sizeof(*floor)); 868 ::g->save_p += sizeof(*floor); 869 floor->sector = (sector_t *)(floor->sector - ::g->sectors); 870 continue; 871 } 872 873 if (th->function.acp1 == (actionf_p1)T_PlatRaise) 874 { 875 *::g->save_p++ = tc_plat; 876 PADSAVEP(); 877 plat = (plat_t *)::g->save_p; 878 memcpy (plat, th, sizeof(*plat)); 879 ::g->save_p += sizeof(*plat); 880 plat->sector = (sector_t *)(plat->sector - ::g->sectors); 881 continue; 882 } 883 884 if (th->function.acp1 == (actionf_p1)T_LightFlash) 885 { 886 *::g->save_p++ = tc_flash; 887 PADSAVEP(); 888 flash = (lightflash_t *)::g->save_p; 889 memcpy (flash, th, sizeof(*flash)); 890 ::g->save_p += sizeof(*flash); 891 flash->sector = (sector_t *)(flash->sector - ::g->sectors); 892 continue; 893 } 894 895 if (th->function.acp1 == (actionf_p1)T_StrobeFlash) 896 { 897 *::g->save_p++ = tc_strobe; 898 PADSAVEP(); 899 strobe = (strobe_t *)::g->save_p; 900 memcpy (strobe, th, sizeof(*strobe)); 901 ::g->save_p += sizeof(*strobe); 902 strobe->sector = (sector_t *)(strobe->sector - ::g->sectors); 903 continue; 904 } 905 906 if (th->function.acp1 == (actionf_p1)T_Glow) 907 { 908 *::g->save_p++ = tc_glow; 909 PADSAVEP(); 910 glow = (glow_t *)::g->save_p; 911 memcpy (glow, th, sizeof(*glow)); 912 ::g->save_p += sizeof(*glow); 913 glow->sector = (sector_t *)(glow->sector - ::g->sectors); 914 continue; 915 } 916 } 917 918 // add a terminating marker 919 *::g->save_p++ = tc_endspecials; 920 921 } 922 923 924 // 925 // P_UnArchiveSpecials 926 // 927 void P_UnArchiveSpecials (void) 928 { 929 byte tclass; 930 ceiling_t* ceiling; 931 vldoor_t* door; 932 floormove_t* floor; 933 plat_t* plat; 934 lightflash_t* flash; 935 strobe_t* strobe; 936 glow_t* glow; 937 938 // read in saved thinkers 939 while (1) 940 { 941 tclass = *::g->save_p++; 942 switch (tclass) 943 { 944 case tc_endspecials: 945 return; // end of list 946 947 case tc_ceiling: 948 PADSAVEP(); 949 ceiling = (ceiling_t*)DoomLib::Z_Malloc(sizeof(*ceiling), PU_LEVEL, NULL); 950 memcpy (ceiling, ::g->save_p, sizeof(*ceiling)); 951 ::g->save_p += sizeof(*ceiling); 952 ceiling->sector = &::g->sectors[(int)ceiling->sector]; 953 ceiling->sector->specialdata = ceiling; 954 955 if (ceiling->thinker.function.acp1) 956 ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; 957 958 P_AddThinker (&ceiling->thinker); 959 P_AddActiveCeiling(ceiling); 960 break; 961 962 case tc_door: 963 PADSAVEP(); 964 door = (vldoor_t*)DoomLib::Z_Malloc(sizeof(*door), PU_LEVEL, NULL); 965 memcpy (door, ::g->save_p, sizeof(*door)); 966 ::g->save_p += sizeof(*door); 967 door->sector = &::g->sectors[(int)door->sector]; 968 door->sector->specialdata = door; 969 door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; 970 P_AddThinker (&door->thinker); 971 break; 972 973 case tc_floor: 974 PADSAVEP(); 975 floor = (floormove_t*)DoomLib::Z_Malloc (sizeof(*floor), PU_LEVEL, NULL); 976 memcpy (floor, ::g->save_p, sizeof(*floor)); 977 ::g->save_p += sizeof(*floor); 978 floor->sector = &::g->sectors[(int)floor->sector]; 979 floor->sector->specialdata = floor; 980 floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor; 981 P_AddThinker (&floor->thinker); 982 break; 983 984 case tc_plat: 985 PADSAVEP(); 986 plat = (plat_t*)DoomLib::Z_Malloc (sizeof(*plat), PU_LEVEL, NULL); 987 memcpy (plat, ::g->save_p, sizeof(*plat)); 988 ::g->save_p += sizeof(*plat); 989 plat->sector = &::g->sectors[(int)plat->sector]; 990 plat->sector->specialdata = plat; 991 992 if (plat->thinker.function.acp1) 993 plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise; 994 995 P_AddThinker (&plat->thinker); 996 P_AddActivePlat(plat); 997 break; 998 999 case tc_flash: 1000 PADSAVEP(); 1001 flash = (lightflash_t*)DoomLib::Z_Malloc (sizeof(*flash), PU_LEVEL, NULL); 1002 memcpy (flash, ::g->save_p, sizeof(*flash)); 1003 ::g->save_p += sizeof(*flash); 1004 flash->sector = &::g->sectors[(int)flash->sector]; 1005 flash->thinker.function.acp1 = (actionf_p1)T_LightFlash; 1006 P_AddThinker (&flash->thinker); 1007 break; 1008 1009 case tc_strobe: 1010 PADSAVEP(); 1011 strobe = (strobe_t*)DoomLib::Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL); 1012 memcpy (strobe, ::g->save_p, sizeof(*strobe)); 1013 ::g->save_p += sizeof(*strobe); 1014 strobe->sector = &::g->sectors[(int)strobe->sector]; 1015 strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash; 1016 P_AddThinker (&strobe->thinker); 1017 break; 1018 1019 case tc_glow: 1020 PADSAVEP(); 1021 glow = (glow_t*)DoomLib::Z_Malloc (sizeof(*glow), PU_LEVEL, NULL); 1022 memcpy (glow, ::g->save_p, sizeof(*glow)); 1023 ::g->save_p += sizeof(*glow); 1024 glow->sector = &::g->sectors[(int)glow->sector]; 1025 glow->thinker.function.acp1 = (actionf_p1)T_Glow; 1026 P_AddThinker (&glow->thinker); 1027 break; 1028 1029 default: 1030 I_Error ("P_UnarchiveSpecials:Unknown tclass %i " 1031 "in savegame",tclass); 1032 } 1033 1034 } 1035 1036 } 1037 1038