p_spec.cpp (26591B)
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 #include "Main.h" 32 33 #include <stdlib.h> 34 35 #include "doomdef.h" 36 #include "doomstat.h" 37 38 #include "i_system.h" 39 #include "z_zone.h" 40 #include "m_argv.h" 41 #include "m_random.h" 42 #include "w_wad.h" 43 44 #include "r_local.h" 45 #include "p_local.h" 46 47 #include "g_game.h" 48 49 #include "s_sound.h" 50 51 // State. 52 #include "r_state.h" 53 54 // Data. 55 #include "sounds.h" 56 57 #include "../../neo/d3xp/Game_Local.h" 58 59 // 60 // Animating textures and planes 61 // There is another anim_t used in wi_stuff, unrelated. BLAH! 62 // we now use anim_t2 63 // 64 65 // 66 // source animation definition 67 // 68 69 70 71 72 73 // 74 // P_InitPicAnims 75 // 76 77 // Floor/ceiling animation sequences, 78 // defined by first and last frame, 79 // i.e. the flat (64x64 tile) name to 80 // be used. 81 // The full animation sequence is given 82 // using all the flats between the start 83 // and end entry, in the order found in 84 // the WAD file. 85 // 86 const animdef_t animdefs[] = 87 { 88 {false, "NUKAGE3", "NUKAGE1", 8}, 89 {false, "FWATER4", "FWATER1", 8}, 90 {false, "SWATER4", "SWATER1", 8}, 91 {false, "LAVA4", "LAVA1", 8}, 92 {false, "BLOOD3", "BLOOD1", 8}, 93 94 // DOOM II flat animations. 95 {false, "RROCK08", "RROCK05", 8}, 96 {false, "SLIME04", "SLIME01", 8}, 97 {false, "SLIME08", "SLIME05", 8}, 98 {false, "SLIME12", "SLIME09", 8}, 99 100 {true, "BLODGR4", "BLODGR1", 8}, 101 {true, "SLADRIP3", "SLADRIP1", 8}, 102 103 {true, "BLODRIP4", "BLODRIP1", 8}, 104 {true, "FIREWALL", "FIREWALA", 8}, 105 {true, "GSTFONT3", "GSTFONT1", 8}, 106 {true, "FIRELAVA", "FIRELAV3", 8}, 107 {true, "FIREMAG3", "FIREMAG1", 8}, 108 {true, "FIREBLU2", "FIREBLU1", 8}, 109 {true, "ROCKRED3", "ROCKRED1", 8}, 110 111 {true, "BFALL4", "BFALL1", 8}, 112 {true, "SFALL4", "SFALL1", 8}, 113 {true, "WFALL4", "WFALL1", 8}, 114 {true, "DBRAIN4", "DBRAIN1", 8}, 115 116 {-1} 117 }; 118 119 120 121 // 122 // Animating line specials 123 // 124 125 126 127 128 void P_InitPicAnims (void) 129 { 130 int i; 131 132 133 // Init animation 134 ::g->lastanim = ::g->anims; 135 for (i=0 ; animdefs[i].istexture != (qboolean)-1 ; i++) 136 { 137 if (animdefs[i].istexture) 138 { 139 // different episode ? 140 if (R_CheckTextureNumForName(animdefs[i].startname) == -1) 141 continue; 142 143 ::g->lastanim->picnum = R_TextureNumForName (animdefs[i].endname); 144 ::g->lastanim->basepic = R_TextureNumForName (animdefs[i].startname); 145 } 146 else 147 { 148 if (W_CheckNumForName(animdefs[i].startname) == -1) 149 continue; 150 151 ::g->lastanim->picnum = R_FlatNumForName (animdefs[i].endname); 152 ::g->lastanim->basepic = R_FlatNumForName (animdefs[i].startname); 153 } 154 155 ::g->lastanim->istexture = animdefs[i].istexture; 156 ::g->lastanim->numpics = ::g->lastanim->picnum - ::g->lastanim->basepic + 1; 157 158 if (::g->lastanim->numpics < 2) 159 I_Error ("P_InitPicAnims: bad cycle from %s to %s", 160 animdefs[i].startname, 161 animdefs[i].endname); 162 163 ::g->lastanim->speed = animdefs[i].speed; 164 ::g->lastanim++; 165 } 166 167 } 168 169 170 171 // 172 // UTILITIES 173 // 174 175 176 177 // 178 // getSide() 179 // Will return a side_t* 180 // given the number of the current sector, 181 // the line number, and the side (0/1) that you want. 182 // 183 side_t* 184 getSide 185 ( int currentSector, 186 int line, 187 int side ) 188 { 189 return &::g->sides[ (::g->sectors[currentSector].lines[line])->sidenum[side] ]; 190 } 191 192 193 // 194 // getSector() 195 // Will return a sector_t* 196 // given the number of the current sector, 197 // the line number and the side (0/1) that you want. 198 // 199 sector_t* 200 getSector 201 ( int currentSector, 202 int line, 203 int side ) 204 { 205 return ::g->sides[ (::g->sectors[currentSector].lines[line])->sidenum[side] ].sector; 206 } 207 208 209 // 210 // twoSided() 211 // Given the sector number and the line number, 212 // it will tell you whether the line is two-sided or not. 213 // 214 int 215 twoSided 216 ( int sector, 217 int line ) 218 { 219 return (::g->sectors[sector].lines[line])->flags & ML_TWOSIDED; 220 } 221 222 223 224 225 // 226 // getNextSector() 227 // Return sector_t * of sector next to current. 228 // NULL if not two-sided line 229 // 230 sector_t* 231 getNextSector 232 ( line_t* line, 233 sector_t* sec ) 234 { 235 if (!(line->flags & ML_TWOSIDED)) 236 return NULL; 237 238 if (line->frontsector == sec) 239 return line->backsector; 240 241 return line->frontsector; 242 } 243 244 245 246 // 247 // P_FindLowestFloorSurrounding() 248 // FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS 249 // 250 fixed_t P_FindLowestFloorSurrounding(sector_t* sec) 251 { 252 int i; 253 line_t* check; 254 sector_t* other; 255 fixed_t floor = sec->floorheight; 256 257 for (i=0 ;i < sec->linecount ; i++) 258 { 259 check = sec->lines[i]; 260 other = getNextSector(check,sec); 261 262 if (!other) 263 continue; 264 265 if (other->floorheight < floor) 266 floor = other->floorheight; 267 } 268 return floor; 269 } 270 271 272 273 // 274 // P_FindHighestFloorSurrounding() 275 // FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS 276 // 277 fixed_t P_FindHighestFloorSurrounding(sector_t *sec) 278 { 279 int i; 280 line_t* check; 281 sector_t* other; 282 fixed_t floor = -500*FRACUNIT; 283 284 for (i=0 ;i < sec->linecount ; i++) 285 { 286 check = sec->lines[i]; 287 other = getNextSector(check,sec); 288 289 if (!other) 290 continue; 291 292 if (other->floorheight > floor) 293 floor = other->floorheight; 294 } 295 return floor; 296 } 297 298 299 300 // 301 // P_FindNextHighestFloor 302 // FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS 303 // Note: this should be doable w/o a fixed array. 304 305 // 20 adjoining ::g->sectors max! 306 307 fixed_t 308 P_FindNextHighestFloor 309 ( sector_t* sec, 310 int currentheight ) 311 { 312 int i; 313 int h; 314 int min; 315 line_t* check; 316 sector_t* other; 317 fixed_t height = currentheight; 318 319 320 fixed_t heightlist[MAX_ADJOINING_SECTORS]; 321 322 for (i=0, h=0 ;i < sec->linecount ; i++) 323 { 324 check = sec->lines[i]; 325 other = getNextSector(check,sec); 326 327 if (!other) 328 continue; 329 330 if (other->floorheight > height) 331 heightlist[h++] = other->floorheight; 332 333 // Check for overflow. Exit. 334 if ( h >= MAX_ADJOINING_SECTORS ) 335 { 336 I_PrintfE("Sector with more than 20 adjoining sectors\n" ); 337 break; 338 } 339 } 340 341 // Find lowest height in list 342 if (!h) 343 return currentheight; 344 345 min = heightlist[0]; 346 347 // Range checking? 348 for (i = 1;i < h;i++) 349 if (heightlist[i] < min) 350 min = heightlist[i]; 351 352 return min; 353 } 354 355 356 // 357 // FIND LOWEST CEILING IN THE SURROUNDING SECTORS 358 // 359 fixed_t 360 P_FindLowestCeilingSurrounding(sector_t* sec) 361 { 362 int i; 363 line_t* check; 364 sector_t* other; 365 fixed_t height = MAXINT; 366 367 for (i=0 ;i < sec->linecount ; i++) 368 { 369 check = sec->lines[i]; 370 other = getNextSector(check,sec); 371 372 if (!other) 373 continue; 374 375 if (other->ceilingheight < height) 376 height = other->ceilingheight; 377 } 378 return height; 379 } 380 381 382 // 383 // FIND HIGHEST CEILING IN THE SURROUNDING SECTORS 384 // 385 fixed_t P_FindHighestCeilingSurrounding(sector_t* sec) 386 { 387 int i; 388 line_t* check; 389 sector_t* other; 390 fixed_t height = 0; 391 392 for (i=0 ;i < sec->linecount ; i++) 393 { 394 check = sec->lines[i]; 395 other = getNextSector(check,sec); 396 397 if (!other) 398 continue; 399 400 if (other->ceilingheight > height) 401 height = other->ceilingheight; 402 } 403 return height; 404 } 405 406 407 408 // 409 // RETURN NEXT SECTOR # THAT LINE TAG REFERS TO 410 // 411 int 412 P_FindSectorFromLineTag 413 ( line_t* line, 414 int start ) 415 { 416 int i; 417 418 for (i = start+1; i < ::g->numsectors; i++) 419 if (::g->sectors[i].tag == line->tag) 420 return i; 421 422 return -1; 423 } 424 425 426 427 428 // 429 // Find minimum light from an adjacent sector 430 // 431 int 432 P_FindMinSurroundingLight 433 ( sector_t* sector, 434 int max ) 435 { 436 int i; 437 int min; 438 line_t* line; 439 sector_t* check; 440 441 min = max; 442 for (i=0 ; i < sector->linecount ; i++) 443 { 444 line = sector->lines[i]; 445 check = getNextSector(line,sector); 446 447 if (!check) 448 continue; 449 450 if (check->lightlevel < min) 451 min = check->lightlevel; 452 } 453 return min; 454 } 455 456 457 458 // 459 // EVENTS 460 // Events are operations triggered by using, crossing, 461 // or shooting special ::g->lines, or by timed thinkers. 462 // 463 464 // 465 // P_CrossSpecialLine - TRIGGER 466 // Called every time a thing origin is about 467 // to cross a line with a non 0 special. 468 // 469 void 470 P_CrossSpecialLine 471 ( int linenum, 472 int side, 473 mobj_t* thing ) 474 { 475 line_t* line; 476 int ok; 477 478 line = &::g->lines[linenum]; 479 480 // Triggers that other things can activate 481 if (!thing->player) 482 { 483 // Things that should NOT trigger specials... 484 switch(thing->type) 485 { 486 case MT_ROCKET: 487 case MT_PLASMA: 488 case MT_BFG: 489 case MT_TROOPSHOT: 490 case MT_HEADSHOT: 491 case MT_BRUISERSHOT: 492 return; 493 break; 494 495 default: break; 496 } 497 498 ok = 0; 499 switch(line->special) 500 { 501 case 39: // TELEPORT TRIGGER 502 case 97: // TELEPORT RETRIGGER 503 case 125: // TELEPORT MONSTERONLY TRIGGER 504 case 126: // TELEPORT MONSTERONLY RETRIGGER 505 case 4: // RAISE DOOR 506 case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER 507 case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER 508 ok = 1; 509 break; 510 } 511 if (!ok) 512 return; 513 } 514 515 516 // Note: could use some const's here. 517 switch (line->special) 518 { 519 // TRIGGERS. 520 // All from here to RETRIGGERS. 521 case 2: 522 // Open Door 523 EV_DoDoor(line,opened); 524 line->special = 0; 525 break; 526 527 case 3: 528 // Close Door 529 EV_DoDoor(line,closed); 530 line->special = 0; 531 break; 532 533 case 4: 534 // Raise Door 535 EV_DoDoor(line,normal); 536 line->special = 0; 537 break; 538 539 case 5: 540 // Raise Floor 541 EV_DoFloor(line,raiseFloor); 542 line->special = 0; 543 break; 544 545 case 6: 546 // Fast Ceiling Crush & Raise 547 EV_DoCeiling(line,fastCrushAndRaise); 548 line->special = 0; 549 break; 550 551 case 8: 552 // Build Stairs 553 EV_BuildStairs(line,build8); 554 line->special = 0; 555 break; 556 557 case 10: 558 // PlatDownWaitUp 559 EV_DoPlat(line,downWaitUpStay,0); 560 line->special = 0; 561 break; 562 563 case 12: 564 // Light Turn On - brightest near 565 EV_LightTurnOn(line,0); 566 line->special = 0; 567 break; 568 569 case 13: 570 // Light Turn On 255 571 EV_LightTurnOn(line,255); 572 line->special = 0; 573 break; 574 575 case 16: 576 // Close Door 30 577 EV_DoDoor(line,close30ThenOpen); 578 line->special = 0; 579 break; 580 581 case 17: 582 // Start Light Strobing 583 EV_StartLightStrobing(line); 584 line->special = 0; 585 break; 586 587 case 19: 588 // Lower Floor 589 EV_DoFloor(line,lowerFloor); 590 line->special = 0; 591 break; 592 593 case 22: 594 // Raise floor to nearest height and change texture 595 EV_DoPlat(line,raiseToNearestAndChange,0); 596 line->special = 0; 597 break; 598 599 case 25: 600 // Ceiling Crush and Raise 601 EV_DoCeiling(line,crushAndRaise); 602 line->special = 0; 603 break; 604 605 case 30: 606 // Raise floor to shortest texture height 607 // on either side of ::g->lines. 608 EV_DoFloor(line,raiseToTexture); 609 line->special = 0; 610 break; 611 612 case 35: 613 // Lights Very Dark 614 EV_LightTurnOn(line,35); 615 line->special = 0; 616 break; 617 618 case 36: 619 // Lower Floor (TURBO) 620 EV_DoFloor(line,turboLower); 621 line->special = 0; 622 break; 623 624 case 37: 625 // LowerAndChange 626 EV_DoFloor(line,lowerAndChange); 627 line->special = 0; 628 break; 629 630 case 38: 631 // Lower Floor To Lowest 632 EV_DoFloor( line, lowerFloorToLowest ); 633 line->special = 0; 634 break; 635 636 case 39: 637 // TELEPORT! 638 EV_Teleport( line, side, thing ); 639 line->special = 0; 640 break; 641 642 case 40: 643 // RaiseCeilingLowerFloor 644 EV_DoCeiling( line, raiseToHighest ); 645 EV_DoFloor( line, lowerFloorToLowest ); 646 line->special = 0; 647 break; 648 649 case 44: 650 // Ceiling Crush 651 EV_DoCeiling( line, lowerAndCrush ); 652 line->special = 0; 653 break; 654 655 case 52: 656 // EXIT! 657 // DHM - Nerve :: Don't exit level in death match, timelimit and fraglimit only 658 if ( !::g->deathmatch && ::g->gameaction != ga_completed ) { 659 G_ExitLevel(); 660 } 661 break; 662 663 case 53: 664 // Perpetual Platform Raise 665 EV_DoPlat(line,perpetualRaise,0); 666 line->special = 0; 667 break; 668 669 case 54: 670 // Platform Stop 671 EV_StopPlat(line); 672 line->special = 0; 673 break; 674 675 case 56: 676 // Raise Floor Crush 677 EV_DoFloor(line,raiseFloorCrush); 678 line->special = 0; 679 break; 680 681 case 57: 682 // Ceiling Crush Stop 683 EV_CeilingCrushStop(line); 684 line->special = 0; 685 break; 686 687 case 58: 688 // Raise Floor 24 689 EV_DoFloor(line,raiseFloor24); 690 line->special = 0; 691 break; 692 693 case 59: 694 // Raise Floor 24 And Change 695 EV_DoFloor(line,raiseFloor24AndChange); 696 line->special = 0; 697 break; 698 699 case 104: 700 // Turn lights off in sector(tag) 701 EV_TurnTagLightsOff(line); 702 line->special = 0; 703 break; 704 705 case 108: 706 // Blazing Door Raise (faster than TURBO!) 707 EV_DoDoor (line,blazeRaise); 708 line->special = 0; 709 break; 710 711 case 109: 712 // Blazing Door Open (faster than TURBO!) 713 EV_DoDoor (line,blazeOpen); 714 line->special = 0; 715 break; 716 717 case 100: 718 // Build Stairs Turbo 16 719 EV_BuildStairs(line,turbo16); 720 line->special = 0; 721 break; 722 723 case 110: 724 // Blazing Door Close (faster than TURBO!) 725 EV_DoDoor (line,blazeClose); 726 line->special = 0; 727 break; 728 729 case 119: 730 // Raise floor to nearest surr. floor 731 EV_DoFloor(line,raiseFloorToNearest); 732 line->special = 0; 733 break; 734 735 case 121: 736 // Blazing PlatDownWaitUpStay 737 EV_DoPlat(line,blazeDWUS,0); 738 line->special = 0; 739 break; 740 741 case 124: 742 // Secret EXIT 743 if ( !::g->deathmatch && ::g->gameaction != ga_completed ) { 744 G_SecretExitLevel (); 745 } 746 break; 747 748 case 125: 749 // TELEPORT MonsterONLY 750 if (!thing->player) 751 { 752 EV_Teleport( line, side, thing ); 753 line->special = 0; 754 } 755 break; 756 757 case 130: 758 // Raise Floor Turbo 759 EV_DoFloor(line,raiseFloorTurbo); 760 line->special = 0; 761 break; 762 763 case 141: 764 // Silent Ceiling Crush & Raise 765 EV_DoCeiling(line,silentCrushAndRaise); 766 line->special = 0; 767 break; 768 769 // RETRIGGERS. All from here till end. 770 case 72: 771 // Ceiling Crush 772 EV_DoCeiling( line, lowerAndCrush ); 773 break; 774 775 case 73: 776 // Ceiling Crush and Raise 777 EV_DoCeiling(line,crushAndRaise); 778 break; 779 780 case 74: 781 // Ceiling Crush Stop 782 EV_CeilingCrushStop(line); 783 break; 784 785 case 75: 786 // Close Door 787 EV_DoDoor(line,closed); 788 break; 789 790 case 76: 791 // Close Door 30 792 EV_DoDoor(line,close30ThenOpen); 793 break; 794 795 case 77: 796 // Fast Ceiling Crush & Raise 797 EV_DoCeiling(line,fastCrushAndRaise); 798 break; 799 800 case 79: 801 // Lights Very Dark 802 EV_LightTurnOn(line,35); 803 break; 804 805 case 80: 806 // Light Turn On - brightest near 807 EV_LightTurnOn(line,0); 808 break; 809 810 case 81: 811 // Light Turn On 255 812 EV_LightTurnOn(line,255); 813 break; 814 815 case 82: 816 // Lower Floor To Lowest 817 EV_DoFloor( line, lowerFloorToLowest ); 818 break; 819 820 case 83: 821 // Lower Floor 822 EV_DoFloor(line,lowerFloor); 823 break; 824 825 case 84: 826 // LowerAndChange 827 EV_DoFloor(line,lowerAndChange); 828 break; 829 830 case 86: 831 // Open Door 832 EV_DoDoor(line,opened); 833 break; 834 835 case 87: 836 // Perpetual Platform Raise 837 EV_DoPlat(line,perpetualRaise,0); 838 break; 839 840 case 88: 841 // PlatDownWaitUp 842 EV_DoPlat(line,downWaitUpStay,0); 843 break; 844 845 case 89: 846 // Platform Stop 847 EV_StopPlat(line); 848 break; 849 850 case 90: 851 // Raise Door 852 EV_DoDoor(line,normal); 853 break; 854 855 case 91: 856 // Raise Floor 857 EV_DoFloor(line,raiseFloor); 858 break; 859 860 case 92: 861 // Raise Floor 24 862 EV_DoFloor(line,raiseFloor24); 863 break; 864 865 case 93: 866 // Raise Floor 24 And Change 867 EV_DoFloor(line,raiseFloor24AndChange); 868 break; 869 870 case 94: 871 // Raise Floor Crush 872 EV_DoFloor(line,raiseFloorCrush); 873 break; 874 875 case 95: 876 // Raise floor to nearest height 877 // and change texture. 878 EV_DoPlat(line,raiseToNearestAndChange,0); 879 break; 880 881 case 96: 882 // Raise floor to shortest texture height 883 // on either side of ::g->lines. 884 EV_DoFloor(line,raiseToTexture); 885 break; 886 887 case 97: 888 // TELEPORT! 889 EV_Teleport( line, side, thing ); 890 break; 891 892 case 98: 893 // Lower Floor (TURBO) 894 EV_DoFloor(line,turboLower); 895 break; 896 897 case 105: 898 // Blazing Door Raise (faster than TURBO!) 899 EV_DoDoor (line,blazeRaise); 900 break; 901 902 case 106: 903 // Blazing Door Open (faster than TURBO!) 904 EV_DoDoor (line,blazeOpen); 905 break; 906 907 case 107: 908 // Blazing Door Close (faster than TURBO!) 909 EV_DoDoor (line,blazeClose); 910 break; 911 912 case 120: 913 // Blazing PlatDownWaitUpStay. 914 EV_DoPlat(line,blazeDWUS,0); 915 break; 916 917 case 126: 918 // TELEPORT MonsterONLY. 919 if (!thing->player) 920 EV_Teleport( line, side, thing ); 921 break; 922 923 case 128: 924 // Raise To Nearest Floor 925 EV_DoFloor(line,raiseFloorToNearest); 926 break; 927 928 case 129: 929 // Raise Floor Turbo 930 EV_DoFloor(line,raiseFloorTurbo); 931 break; 932 } 933 } 934 935 936 937 // 938 // P_ShootSpecialLine - IMPACT SPECIALS 939 // Called when a thing shoots a special line. 940 // 941 void 942 P_ShootSpecialLine 943 ( mobj_t* thing, 944 line_t* line ) 945 { 946 int ok; 947 948 // Impacts that other things can activate. 949 if (!thing->player) 950 { 951 ok = 0; 952 switch(line->special) 953 { 954 case 46: 955 // OPEN DOOR IMPACT 956 ok = 1; 957 break; 958 } 959 if (!ok) 960 return; 961 } 962 963 switch(line->special) 964 { 965 case 24: 966 // RAISE FLOOR 967 EV_DoFloor(line,raiseFloor); 968 P_ChangeSwitchTexture(line,0); 969 break; 970 971 case 46: 972 // OPEN DOOR 973 EV_DoDoor(line,opened); 974 P_ChangeSwitchTexture(line,1); 975 break; 976 977 case 47: 978 // RAISE FLOOR NEAR AND CHANGE 979 EV_DoPlat(line,raiseToNearestAndChange,0); 980 P_ChangeSwitchTexture(line,0); 981 break; 982 } 983 } 984 985 986 987 // 988 // P_PlayerInSpecialSector 989 // Called every tic frame 990 // that the player origin is in a special sector 991 // 992 void P_PlayerInSpecialSector (player_t* player) 993 { 994 sector_t* sector; 995 996 sector = player->mo->subsector->sector; 997 998 // Falling, not all the way down yet? 999 if (player->mo->z != sector->floorheight) 1000 return; 1001 1002 // Has hitten ground. 1003 switch (sector->special) 1004 { 1005 case 5: 1006 // HELLSLIME DAMAGE 1007 if (!player->powers[pw_ironfeet]) 1008 if (!(::g->leveltime&0x1f)) 1009 P_DamageMobj (player->mo, NULL, NULL, 10); 1010 break; 1011 1012 case 7: 1013 // NUKAGE DAMAGE 1014 if (!player->powers[pw_ironfeet]) 1015 if (!(::g->leveltime&0x1f)) 1016 P_DamageMobj (player->mo, NULL, NULL, 5); 1017 break; 1018 1019 case 16: 1020 // SUPER HELLSLIME DAMAGE 1021 case 4: 1022 // STROBE HURT 1023 if (!player->powers[pw_ironfeet] 1024 || (P_Random()<5) ) 1025 { 1026 if (!(::g->leveltime&0x1f)) 1027 P_DamageMobj (player->mo, NULL, NULL, 20); 1028 } 1029 break; 1030 1031 case 9: 1032 // SECRET SECTOR 1033 player->secretcount++; 1034 sector->special = 0; 1035 1036 1037 if ( !::g->demoplayback && ( ::g->usergame && !::g->netgame ) ) { 1038 // DHM - Nerve :: Let's give achievements in real time in Doom 2 1039 if ( !common->IsMultiplayer() ) { 1040 switch( DoomLib::GetGameSKU() ) { 1041 case GAME_SKU_DOOM1_BFG: { 1042 // Removing trophies for DOOM and DOOM II BFG due to point limit. 1043 //gameLocal->UnlockAchievement( Doom1BFG_Trophies::SCOUT_FIND_ANY_SECRET ); 1044 break; 1045 } 1046 case GAME_SKU_DOOM2_BFG: { 1047 //gameLocal->UnlockAchievement( Doom2BFG_Trophies::IMPORTANT_LOOKING_DOOR_FIND_ANY_SECRET ); 1048 idAchievementManager::LocalUser_CompleteAchievement(ACHIEVEMENT_DOOM2_IMPORTANT_LOOKING_DOOR_FIND_ANY_SECRET ); 1049 break; 1050 } 1051 case GAME_SKU_DCC: { 1052 // Not on PC. 1053 //gameLocal->UnlockAchievement( DOOM_ACHIEVEMENT_FIND_SECRET ); 1054 break; 1055 } 1056 default: { 1057 // No unlocks for other SKUs. 1058 break; 1059 } 1060 } 1061 } 1062 } 1063 1064 1065 break; 1066 1067 case 11: 1068 // EXIT SUPER DAMAGE! (for E1M8 finale) 1069 player->cheats &= ~CF_GODMODE; 1070 1071 if (!(::g->leveltime&0x1f)) 1072 P_DamageMobj (player->mo, NULL, NULL, 20); 1073 1074 if (player->health <= 10) 1075 G_ExitLevel(); 1076 break; 1077 1078 default: 1079 I_Error ("P_PlayerInSpecialSector: " 1080 "unknown special %i", 1081 sector->special); 1082 break; 1083 }; 1084 } 1085 1086 1087 1088 1089 // 1090 // P_UpdateSpecials 1091 // Animate planes, scroll walls, etc. 1092 // 1093 int PlayerFrags( int playernum ) { 1094 int frags = 0; 1095 1096 for( int i=0 ; i<MAXPLAYERS ; i++) { 1097 if ( i != playernum ) { 1098 frags += ::g->players[playernum].frags[i]; 1099 } 1100 } 1101 1102 frags -= ::g->players[playernum].frags[playernum]; 1103 1104 return frags; 1105 } 1106 1107 void P_UpdateSpecials (void) 1108 { 1109 anim_t2* anim; 1110 int pic; 1111 int i; 1112 line_t* line; 1113 1114 1115 // LEVEL TIMER 1116 if (::g->levelTimer == true) 1117 { 1118 ::g->levelTimeCount--; 1119 if (!::g->levelTimeCount) 1120 G_ExitLevel(); 1121 } 1122 1123 // DHM - Nerve :: FRAG COUNT 1124 if ( ::g->deathmatch && ::g->levelFragCount > 0 ) { 1125 bool fragCountHit = false; 1126 1127 for ( int i=0; i<MAXPLAYERS; i++ ) { 1128 if ( ::g->playeringame[i] ) { 1129 if ( PlayerFrags(i) >= ::g->levelFragCount ) { 1130 fragCountHit = true; 1131 } 1132 } 1133 } 1134 1135 if ( fragCountHit ) { 1136 G_ExitLevel(); 1137 } 1138 } 1139 1140 // ANIMATE FLATS AND TEXTURES GLOBALLY 1141 for (anim = ::g->anims ; anim < ::g->lastanim ; anim++) 1142 { 1143 for (i=anim->basepic ; i<anim->basepic+anim->numpics ; i++) 1144 { 1145 pic = anim->basepic + ( (::g->leveltime/anim->speed + i)%anim->numpics ); 1146 if (anim->istexture) 1147 ::g->texturetranslation[i] = pic; 1148 else 1149 ::g->flattranslation[i] = pic; 1150 } 1151 } 1152 1153 1154 // ANIMATE LINE SPECIALS 1155 for (i = 0; i < ::g->numlinespecials; i++) 1156 { 1157 line = ::g->linespeciallist[i]; 1158 switch(line->special) 1159 { 1160 case 48: 1161 // EFFECT FIRSTCOL SCROLL + 1162 ::g->sides[line->sidenum[0]].textureoffset += FRACUNIT; 1163 break; 1164 } 1165 } 1166 1167 1168 // DO BUTTONS 1169 for (i = 0; i < MAXBUTTONS; i++) 1170 if (::g->buttonlist[i].btimer) 1171 { 1172 ::g->buttonlist[i].btimer--; 1173 if (!::g->buttonlist[i].btimer) 1174 { 1175 switch(::g->buttonlist[i].where) 1176 { 1177 case top: 1178 ::g->sides[::g->buttonlist[i].line->sidenum[0]].toptexture = 1179 ::g->buttonlist[i].btexture; 1180 break; 1181 1182 case middle: 1183 ::g->sides[::g->buttonlist[i].line->sidenum[0]].midtexture = 1184 ::g->buttonlist[i].btexture; 1185 break; 1186 1187 case bottom: 1188 ::g->sides[::g->buttonlist[i].line->sidenum[0]].bottomtexture = 1189 ::g->buttonlist[i].btexture; 1190 break; 1191 } 1192 S_StartSound((mobj_t *)&::g->buttonlist[i].soundorg,sfx_swtchn); 1193 memset(&::g->buttonlist[i],0,sizeof(button_t)); 1194 } 1195 } 1196 1197 } 1198 1199 1200 1201 // 1202 // Special Stuff that can not be categorized 1203 // 1204 int EV_DoDonut(line_t* line) 1205 { 1206 sector_t* s1; 1207 sector_t* s2; 1208 sector_t* s3; 1209 int secnum; 1210 int rtn; 1211 int i; 1212 floormove_t* floor; 1213 1214 secnum = -1; 1215 rtn = 0; 1216 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 1217 { 1218 s1 = &::g->sectors[secnum]; 1219 1220 // ALREADY MOVING? IF SO, KEEP GOING... 1221 if (s1->specialdata) 1222 continue; 1223 1224 rtn = 1; 1225 s2 = getNextSector(s1->lines[0],s1); 1226 for (i = 0;i < s2->linecount;i++) 1227 { 1228 if ((!(s2->lines[i]->flags & ML_TWOSIDED)) || 1229 (s2->lines[i]->backsector == s1)) 1230 continue; 1231 s3 = s2->lines[i]->backsector; 1232 1233 // Spawn rising slime 1234 floor = (floormove_t*)DoomLib::Z_Malloc (sizeof(*floor), PU_LEVEL, 0); 1235 P_AddThinker (&floor->thinker); 1236 s2->specialdata = floor; 1237 floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; 1238 floor->type = donutRaise; 1239 floor->crush = false; 1240 floor->direction = 1; 1241 floor->sector = s2; 1242 floor->speed = FLOORSPEED / 2; 1243 floor->texture = s3->floorpic; 1244 floor->newspecial = 0; 1245 floor->floordestheight = s3->floorheight; 1246 1247 // Spawn lowering donut-hole 1248 floor = (floormove_t*)DoomLib::Z_Malloc (sizeof(*floor), PU_LEVEL, 0); 1249 P_AddThinker (&floor->thinker); 1250 s1->specialdata = floor; 1251 floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; 1252 floor->type = lowerFloor; 1253 floor->crush = false; 1254 floor->direction = -1; 1255 floor->sector = s1; 1256 floor->speed = FLOORSPEED / 2; 1257 floor->floordestheight = s3->floorheight; 1258 break; 1259 } 1260 } 1261 return rtn; 1262 } 1263 1264 1265 1266 // 1267 // SPECIAL SPAWNING 1268 // 1269 1270 // 1271 // P_SpawnSpecials 1272 // After the map has been loaded, scan for specials 1273 // that spawn thinkers 1274 // 1275 1276 1277 // Parses command line parameters. 1278 void P_SpawnSpecials (void) 1279 { 1280 sector_t* sector; 1281 int i; 1282 int episode; 1283 1284 episode = 1; 1285 if (W_CheckNumForName("texture2") >= 0) 1286 episode = 2; 1287 1288 1289 // See if -TIMER needs to be used. 1290 ::g->levelTimer = false; 1291 1292 i = M_CheckParm("-avg"); 1293 if (i && ::g->deathmatch) 1294 { 1295 ::g->levelTimer = true; 1296 ::g->levelTimeCount = 20 * 60 * TICRATE; 1297 } 1298 1299 //i = M_CheckParm("-timer"); 1300 //if (i && ::g->deathmatch) 1301 #ifdef ID_ENABLE_DOOM_CLASSIC_NETWORKING 1302 const int timeLimit = session->GetActingGameStateLobbyBase().GetMatchParms().gameTimeLimit; 1303 #else 1304 const int timeLimit = 0; 1305 #endif 1306 if (timeLimit != 0 && g->deathmatch) 1307 { 1308 int time; 1309 //time = atoi(::g->myargv[i+1]) * 60 * 35; 1310 time = timeLimit * 60 * TICRATE; 1311 ::g->levelTimer = true; 1312 ::g->levelTimeCount = time; 1313 } 1314 1315 //i = M_CheckParm("-fraglimit"); 1316 //if (i && ::g->deathmatch) 1317 #ifdef ID_ENABLE_DOOM_CLASSIC_NETWORKING 1318 const int fragLimit = gameLocal->GetMatchParms().GetScoreLimit(); 1319 #else 1320 const int fragLimit = 0; 1321 #endif 1322 if (fragLimit != 0 && ::g->deathmatch) 1323 { 1324 //::g->levelFragCount = atoi(::g->myargv[i+1]); 1325 ::g->levelFragCount = fragLimit; 1326 } else { 1327 ::g->levelFragCount = 0; 1328 } 1329 1330 // Init special SECTORs. 1331 sector = ::g->sectors; 1332 for (i=0 ; i < ::g->numsectors ; i++, sector++) 1333 { 1334 if (!sector->special) 1335 continue; 1336 1337 switch (sector->special) 1338 { 1339 case 1: 1340 // FLICKERING LIGHTS 1341 P_SpawnLightFlash (sector); 1342 break; 1343 1344 case 2: 1345 // STROBE FAST 1346 P_SpawnStrobeFlash(sector,FASTDARK,0); 1347 break; 1348 1349 case 3: 1350 // STROBE SLOW 1351 P_SpawnStrobeFlash(sector,SLOWDARK,0); 1352 break; 1353 1354 case 4: 1355 // STROBE FAST/DEATH SLIME 1356 P_SpawnStrobeFlash(sector,FASTDARK,0); 1357 sector->special = 4; 1358 break; 1359 1360 case 8: 1361 // GLOWING LIGHT 1362 P_SpawnGlowingLight(sector); 1363 break; 1364 case 9: 1365 // SECRET SECTOR 1366 ::g->totalsecret++; 1367 break; 1368 1369 case 10: 1370 // DOOR CLOSE IN 30 SECONDS 1371 P_SpawnDoorCloseIn30 (sector); 1372 break; 1373 1374 case 12: 1375 // SYNC STROBE SLOW 1376 P_SpawnStrobeFlash (sector, SLOWDARK, 1); 1377 break; 1378 1379 case 13: 1380 // SYNC STROBE FAST 1381 P_SpawnStrobeFlash (sector, FASTDARK, 1); 1382 break; 1383 1384 case 14: 1385 // DOOR RAISE IN 5 MINUTES 1386 P_SpawnDoorRaiseIn5Mins (sector, i); 1387 break; 1388 1389 case 17: 1390 P_SpawnFireFlicker(sector); 1391 break; 1392 } 1393 } 1394 1395 1396 // Init line EFFECTs 1397 ::g->numlinespecials = 0; 1398 for (i = 0;i < ::g->numlines; i++) 1399 { 1400 switch(::g->lines[i].special) 1401 { 1402 case 48: 1403 // EFFECT FIRSTCOL SCROLL+ 1404 ::g->linespeciallist[::g->numlinespecials] = &::g->lines[i]; 1405 ::g->numlinespecials++; 1406 break; 1407 } 1408 } 1409 1410 1411 // Init other misc stuff 1412 for (i = 0;i < MAXCEILINGS;i++) 1413 ::g->activeceilings[i] = NULL; 1414 1415 for (i = 0;i < MAXPLATS;i++) 1416 ::g->activeplats[i] = NULL; 1417 1418 for (i = 0;i < MAXBUTTONS;i++) 1419 memset(&::g->buttonlist[i],0,sizeof(button_t)); 1420 1421 // UNUSED: no horizonal sliders. 1422 // P_InitSlidingDoorFrames(); 1423 } 1424