p_spec.c (16701B)
1 /* 2 * 3 * 4 * P_ShootSpecialLine funny 5 * 6 * 7 */ 8 #include <stdlib.h> 9 10 #include "doomdef.h" 11 #include "doomstat.h" 12 #include "i_system.h" 13 #include "z_zone.h" 14 #include "m_argv.h" 15 #include "m_random.h" 16 #include "w_wad.h" 17 #include "r_local.h" 18 #include "p_local.h" 19 #include "g_game.h" 20 #include "s_sound.h" 21 #include "r_state.h" 22 #include "sounds.h" 23 24 typedef struct { 25 boolean istexture; 26 int picnum; 27 int basepic; 28 int numpics; 29 int speed; 30 } anim_t; 31 32 typedef struct { 33 boolean istexture; 34 char endname[9]; 35 char startname[9]; 36 int speed; 37 } animdef_t; 38 39 #define MAXANIMS 32 40 41 extern anim_t anims[MAXANIMS]; 42 extern anim_t* lastanim; 43 44 animdef_t animdefs[] = { 45 {false, "NUKAGE3", "NUKAGE1", 8}, 46 {false, "FWATER4", "FWATER1", 8}, 47 {false, "SWATER4", "SWATER1", 8}, 48 {false, "LAVA4", "LAVA1", 8}, 49 {false, "BLOOD3", "BLOOD1", 8}, 50 {false, "RROCK08", "RROCK05", 8}, 51 {false, "SLIME04", "SLIME01", 8}, 52 {false, "SLIME08", "SLIME05", 8}, 53 {false, "SLIME12", "SLIME09", 8}, 54 {true, "BLODGR4", "BLODGR1", 8}, 55 {true, "SLADRIP3", "SLADRIP1", 8}, 56 {true, "BLODRIP4", "BLODRIP1", 8}, 57 {true, "FIREWALL", "FIREWALA", 8}, 58 {true, "GSTFONT3", "GSTFONT1", 8}, 59 {true, "FIRELAVA", "FIRELAV3", 8}, 60 {true, "FIREMAG3", "FIREMAG1", 8}, 61 {true, "FIREBLU2", "FIREBLU1", 8}, 62 {true, "ROCKRED3", "ROCKRED1", 8}, 63 {true, "BFALL4", "BFALL1", 8}, 64 {true, "SFALL4", "SFALL1", 8}, 65 {true, "WFALL4", "WFALL1", 8}, 66 {true, "DBRAIN4", "DBRAIN1", 8}, 67 {-1} 68 }; 69 70 anim_t anims[MAXANIMS]; 71 anim_t* lastanim; 72 73 #define MAXLINEANIMS 64 74 75 extern short numlinespecials; 76 extern line_t* linespeciallist[MAXLINEANIMS]; 77 78 void 79 P_InitPicAnims() 80 { 81 int i; 82 83 lastanim = anims; 84 for (i = 0; animdefs[i].istexture != -1 ; ++i) { 85 if (animdefs[i].istexture) { 86 if (R_CheckTextureNumForName(animdefs[i].startname) == -1) 87 continue; 88 lastanim->picnum = R_TextureNumForName (animdefs[i].endname); 89 lastanim->basepic = R_TextureNumForName (animdefs[i].startname); 90 } else { 91 if (W_CheckNumForName(animdefs[i].startname) == -1) 92 continue; 93 lastanim->picnum = R_FlatNumForName (animdefs[i].endname); 94 lastanim->basepic = R_FlatNumForName (animdefs[i].startname); 95 } 96 lastanim->istexture = animdefs[i].istexture; 97 lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; 98 if (lastanim->numpics < 2) 99 I_Error ("P_InitPicAnims: bad cycle from %s to %s", animdefs[i].startname, animdefs[i].endname); 100 lastanim->speed = animdefs[i].speed; 101 ++lastanim; 102 } 103 } 104 105 side_t* 106 getSide(int currentSector, int line, int side) 107 { 108 return &sides[(sectors[currentSector].lines[line])->sidenum[side]]; 109 } 110 111 sector_t* 112 getSector(int currentSector, int line, int side) 113 { 114 return sides[(sectors[currentSector].lines[line])->sidenum[side]].sector; 115 } 116 117 int 118 twoSided(int sector, int line) 119 { 120 return (sectors[sector].lines[line])->flags & ML_TWOSIDED; 121 } 122 123 sector_t* 124 getNextSector(line_t* line, sector_t* sec) 125 { 126 if (!(line->flags & ML_TWOSIDED)) 127 return NULL; 128 if (line->frontsector == sec) 129 return line->backsector; 130 return line->frontsector; 131 } 132 133 fixed_t 134 P_FindLowestFloorSurrounding(sector_t* sec) 135 { 136 line_t* check; 137 sector_t* other; 138 fixed_t floor; 139 int i; 140 141 floor = sec->floorheight; 142 for (i = 0; i < sec->linecount; ++i) { 143 check = sec->lines[i]; 144 other = getNextSector(check,sec); 145 if (!other) 146 continue; 147 if (other->floorheight < floor) 148 floor = other->floorheight; 149 } 150 return floor; 151 } 152 153 fixed_t 154 P_FindHighestFloorSurrounding(sector_t *sec) 155 { 156 line_t* check; 157 sector_t* other; 158 fixed_t floor; 159 int i; 160 161 floor = -500 * FRACUNIT; 162 for (i = 0; i < sec->linecount; ++i) { 163 check = sec->lines[i]; 164 other = getNextSector(check,sec); 165 if (!other) 166 continue; 167 if (other->floorheight > floor) 168 floor = other->floorheight; 169 } 170 return floor; 171 } 172 173 #define MAX_ADJOINING_SECTORS 20 174 175 fixed_t 176 P_FindNextHighestFloor(sector_t* sec, int currentheight) 177 { 178 line_t* check; 179 sector_t* other; 180 fixed_t height, heightlist[MAX_ADJOINING_SECTORS]; 181 int i, h, min; 182 183 height = currentheight; 184 for (i = 0, h = 0; i < sec->linecount; ++i) { 185 check = sec->lines[i]; 186 other = getNextSector(check,sec); 187 if (!other) 188 continue; 189 if (other->floorheight > height) 190 heightlist[h++] = other->floorheight; 191 if (h >= MAX_ADJOINING_SECTORS) { 192 fprintf(stderr, "Sector with more than 20 adjoining sectors\n"); 193 break; 194 } 195 } 196 if (!h) 197 return currentheight; 198 min = heightlist[0]; 199 for (i = 1; i < h; ++i) 200 if (heightlist[i] < min) 201 min = heightlist[i]; 202 return min; 203 } 204 205 fixed_t 206 P_FindLowestCeilingSurrounding(sector_t* sec) 207 { 208 line_t* check; 209 sector_t* other; 210 fixed_t height; 211 int i; 212 213 height = INT_MAX; 214 for (i = 0; i < sec->linecount; ++i) { 215 check = sec->lines[i]; 216 other = getNextSector(check,sec); 217 if (!other) 218 continue; 219 if (other->ceilingheight < height) 220 height = other->ceilingheight; 221 } 222 return height; 223 } 224 225 fixed_t 226 P_FindHighestCeilingSurrounding(sector_t* sec) 227 { 228 line_t* check; 229 sector_t* other; 230 fixed_t height; 231 int i; 232 233 height = 0; 234 for (i = 0; i < sec->linecount; ++i) { 235 check = sec->lines[i]; 236 other = getNextSector(check,sec); 237 if (!other) 238 continue; 239 if (other->ceilingheight > height) 240 height = other->ceilingheight; 241 } 242 return height; 243 } 244 245 int 246 P_FindSectorFromLineTag(line_t* line, int start) 247 { 248 int i; 249 250 for (i = start + 1; i < numsectors; ++i) 251 if (sectors[i].tag == line->tag) 252 return i; 253 return -1; 254 } 255 256 int 257 P_FindMinSurroundingLight(sector_t* sector, int max) 258 { 259 line_t* line; 260 sector_t* check; 261 int i, min; 262 263 min = max; 264 for (i = 0; i < sector->linecount; ++i) { 265 line = sector->lines[i]; 266 check = getNextSector(line,sector); 267 if (!check) 268 continue; 269 if (check->lightlevel < min) 270 min = check->lightlevel; 271 } 272 return min; 273 } 274 275 void 276 P_CrossSpecialLine(int linenum, int side, mobj_t* thing) 277 { 278 line_t* line; 279 int ok; 280 281 line = &lines[linenum]; 282 if (!thing->player) { 283 switch (thing->type) { 284 case MT_ROCKET: 285 case MT_PLASMA: 286 case MT_BFG: 287 case MT_TROOPSHOT: 288 case MT_HEADSHOT: 289 case MT_BRUISERSHOT: 290 return; 291 default: break; 292 } 293 ok = 0; 294 switch (line->special) { 295 case 39: 296 case 97: 297 case 125: 298 case 126: 299 case 4: 300 case 10: 301 case 88: 302 ok = 1; 303 break; 304 } 305 if (!ok) 306 return; 307 } 308 switch (line->special) { 309 case 2: 310 EV_DoDoor(line,open); 311 line->special = 0; 312 break; 313 314 case 3: 315 EV_DoDoor(line,close); 316 line->special = 0; 317 break; 318 case 4: 319 EV_DoDoor(line,normal); 320 line->special = 0; 321 break; 322 case 5: 323 EV_DoFloor(line,raiseFloor); 324 line->special = 0; 325 break; 326 case 6: 327 EV_DoCeiling(line,fastCrushAndRaise); 328 line->special = 0; 329 break; 330 case 8: 331 EV_BuildStairs(line,build8); 332 line->special = 0; 333 break; 334 case 10: 335 EV_DoPlat(line,downWaitUpStay,0); 336 line->special = 0; 337 break; 338 case 12: 339 EV_LightTurnOn(line,0); 340 line->special = 0; 341 break; 342 case 13: 343 EV_LightTurnOn(line,255); 344 line->special = 0; 345 break; 346 case 16: 347 EV_DoDoor(line,close30ThenOpen); 348 line->special = 0; 349 break; 350 case 17: 351 EV_StartLightStrobing(line); 352 line->special = 0; 353 break; 354 case 19: 355 EV_DoFloor(line,lowerFloor); 356 line->special = 0; 357 break; 358 case 22: 359 EV_DoPlat(line,raiseToNearestAndChange,0); 360 line->special = 0; 361 break; 362 case 25: 363 EV_DoCeiling(line,crushAndRaise); 364 line->special = 0; 365 break; 366 case 30: 367 EV_DoFloor(line,raiseToTexture); 368 line->special = 0; 369 break; 370 case 35: 371 EV_LightTurnOn(line,35); 372 line->special = 0; 373 break; 374 case 36: 375 EV_DoFloor(line,turboLower); 376 line->special = 0; 377 break; 378 case 37: 379 EV_DoFloor(line,lowerAndChange); 380 line->special = 0; 381 break; 382 case 38: 383 EV_DoFloor(line, lowerFloorToLowest); 384 line->special = 0; 385 break; 386 case 39: 387 EV_Teleport(line, side, thing); 388 line->special = 0; 389 break; 390 case 40: 391 EV_DoCeiling(line, raiseToHighest); 392 EV_DoFloor(line, lowerFloorToLowest); 393 line->special = 0; 394 break; 395 case 44: 396 EV_DoCeiling(line, lowerAndCrush); 397 line->special = 0; 398 break; 399 case 52: G_ExitLevel(); break; 400 case 53: 401 EV_DoPlat(line,perpetualRaise,0); 402 line->special = 0; 403 break; 404 case 54: 405 EV_StopPlat(line); 406 line->special = 0; 407 break; 408 case 56: 409 EV_DoFloor(line,raiseFloorCrush); 410 line->special = 0; 411 break; 412 case 57: 413 EV_CeilingCrushStop(line); 414 line->special = 0; 415 break; 416 case 58: 417 EV_DoFloor(line,raiseFloor24); 418 line->special = 0; 419 break; 420 case 59: 421 EV_DoFloor(line,raiseFloor24AndChange); 422 line->special = 0; 423 break; 424 case 104: 425 EV_TurnTagLightsOff(line); 426 line->special = 0; 427 break; 428 case 108: 429 EV_DoDoor (line,blazeRaise); 430 line->special = 0; 431 break; 432 case 109: 433 EV_DoDoor (line,blazeOpen); 434 line->special = 0; 435 break; 436 case 100: 437 EV_BuildStairs(line,turbo16); 438 line->special = 0; 439 break; 440 case 110: 441 EV_DoDoor (line,blazeClose); 442 line->special = 0; 443 break; 444 case 119: 445 EV_DoFloor(line,raiseFloorToNearest); 446 line->special = 0; 447 break; 448 case 121: 449 EV_DoPlat(line,blazeDWUS,0); 450 line->special = 0; 451 break; 452 case 124: G_SecretExitLevel (); break; 453 case 125: 454 if (!thing->player) { 455 EV_Teleport(line, side, thing); 456 line->special = 0; 457 } 458 break; 459 case 130: 460 EV_DoFloor(line,raiseFloorTurbo); 461 line->special = 0; 462 break; 463 case 141: 464 EV_DoCeiling(line,silentCrushAndRaise); 465 line->special = 0; 466 break; 467 case 72: EV_DoCeiling(line, lowerAndCrush); break; 468 case 73: EV_DoCeiling(line,crushAndRaise); break; 469 case 74: EV_CeilingCrushStop(line); break; 470 case 75: EV_DoDoor(line,close); break; 471 case 76: EV_DoDoor(line,close30ThenOpen); break; 472 case 77: EV_DoCeiling(line,fastCrushAndRaise); break; 473 case 79: EV_LightTurnOn(line,35); break; 474 case 80: EV_LightTurnOn(line,0); break; 475 case 81: EV_LightTurnOn(line,255); break; 476 case 82: EV_DoFloor(line, lowerFloorToLowest); break; 477 case 83: EV_DoFloor(line,lowerFloor); break; 478 case 84: EV_DoFloor(line,lowerAndChange); break; 479 case 86: EV_DoDoor(line,open); break; 480 case 87: EV_DoPlat(line,perpetualRaise,0); break; 481 case 88: EV_DoPlat(line,downWaitUpStay,0); break; 482 case 89: EV_StopPlat(line); break; 483 case 90: EV_DoDoor(line,normal); break; 484 case 91: EV_DoFloor(line,raiseFloor); break; 485 case 92: EV_DoFloor(line,raiseFloor24); break; 486 case 93: EV_DoFloor(line,raiseFloor24AndChange); break; 487 case 94: EV_DoFloor(line,raiseFloorCrush); break; 488 case 95: EV_DoPlat(line,raiseToNearestAndChange,0); break; 489 case 96: EV_DoFloor(line,raiseToTexture); break; 490 case 97: EV_Teleport(line, side, thing); break; 491 case 98: EV_DoFloor(line,turboLower); break; 492 case 105: EV_DoDoor(line,blazeRaise); break; 493 case 106: EV_DoDoor(line,blazeOpen); break; 494 case 107: EV_DoDoor(line,blazeClose); break; 495 case 120: EV_DoPlat(line,blazeDWUS,0); break; 496 case 126: 497 if (!thing->player) 498 EV_Teleport(line, side, thing); 499 break; 500 case 128: EV_DoFloor(line,raiseFloorToNearest); break; 501 case 129: EV_DoFloor(line,raiseFloorTurbo); break; 502 } 503 } 504 505 void 506 P_ShootSpecialLine(mobj_t* thing, line_t* line) 507 { 508 if (!thing->player && line->special != 46) 509 return; 510 switch (line->special) { 511 case 24: 512 EV_DoFloor(line,raiseFloor); 513 P_ChangeSwitchTexture(line,0); 514 break; 515 case 46: 516 EV_DoDoor(line,open); 517 P_ChangeSwitchTexture(line,1); 518 break; 519 case 47: 520 EV_DoPlat(line,raiseToNearestAndChange,0); 521 P_ChangeSwitchTexture(line,0); 522 break; 523 } 524 } 525 526 void 527 P_PlayerInSpecialSector(player_t* player) 528 { 529 sector_t* sector; 530 531 sector = player->mo->subsector->sector; 532 533 534 if (player->mo->z != sector->floorheight) 535 return; 536 537 538 switch (sector->special) 539 { 540 case 5: 541 542 if (!player->powers[pw_ironfeet]) 543 if (!(leveltime&0x1f)) 544 P_DamageMobj (player->mo, NULL, NULL, 10); 545 break; 546 547 case 7: 548 549 if (!player->powers[pw_ironfeet]) 550 if (!(leveltime&0x1f)) 551 P_DamageMobj (player->mo, NULL, NULL, 5); 552 break; 553 554 case 16: 555 556 case 4: 557 558 if (!player->powers[pw_ironfeet] 559 || (P_Random()<5)) 560 { 561 if (!(leveltime&0x1f)) 562 P_DamageMobj (player->mo, NULL, NULL, 20); 563 } 564 break; 565 566 case 9: 567 568 player->secretcount++; 569 sector->special = 0; 570 break; 571 572 case 11: 573 574 player->cheats &= ~CF_GODMODE; 575 576 if (!(leveltime&0x1f)) 577 P_DamageMobj (player->mo, NULL, NULL, 20); 578 579 if (player->health <= 10) 580 G_ExitLevel(); 581 break; 582 583 default: 584 I_Error ("P_PlayerInSpecialSector: " 585 "unknown special %i", 586 sector->special); 587 break; 588 }; 589 } 590 591 592 593 594 595 596 597 598 boolean levelTimer; 599 int levelTimeCount; 600 601 void P_UpdateSpecials (void) 602 { 603 anim_t* anim; 604 int pic; 605 int i; 606 line_t* line; 607 608 609 610 if (levelTimer == true) 611 { 612 levelTimeCount--; 613 if (!levelTimeCount) 614 G_ExitLevel(); 615 } 616 617 618 for (anim = anims ; anim < lastanim ; anim++) 619 { 620 for (i=anim->basepic ; i<anim->basepic+anim->numpics ; i++) 621 { 622 pic = anim->basepic + ((leveltime/anim->speed + i)%anim->numpics); 623 if (anim->istexture) 624 texturetranslation[i] = pic; 625 else 626 flattranslation[i] = pic; 627 } 628 } 629 630 631 632 for (i = 0; i < numlinespecials; i++) 633 { 634 line = linespeciallist[i]; 635 switch(line->special) 636 { 637 case 48: 638 639 sides[line->sidenum[0]].textureoffset += FRACUNIT; 640 break; 641 } 642 } 643 644 645 646 for (i = 0; i < MAXBUTTONS; i++) 647 if (buttonlist[i].btimer) 648 { 649 buttonlist[i].btimer--; 650 if (!buttonlist[i].btimer) 651 { 652 switch(buttonlist[i].where) 653 { 654 case top: 655 sides[buttonlist[i].line->sidenum[0]].toptexture = 656 buttonlist[i].btexture; 657 break; 658 659 case middle: 660 sides[buttonlist[i].line->sidenum[0]].midtexture = 661 buttonlist[i].btexture; 662 break; 663 664 case bottom: 665 sides[buttonlist[i].line->sidenum[0]].bottomtexture = 666 buttonlist[i].btexture; 667 break; 668 } 669 S_StartSound((mobj_t *)&buttonlist[i].soundorg,sfx_swtchn); 670 memset(&buttonlist[i],0,sizeof(button_t)); 671 } 672 } 673 674 } 675 676 677 678 679 680 681 int EV_DoDonut(line_t* line) 682 { 683 sector_t* s1; 684 sector_t* s2; 685 sector_t* s3; 686 int secnum; 687 int rtn; 688 int i; 689 floormove_t* floor; 690 691 secnum = -1; 692 rtn = 0; 693 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 694 { 695 s1 = §ors[secnum]; 696 697 698 if (s1->specialdata) 699 continue; 700 701 rtn = 1; 702 s2 = getNextSector(s1->lines[0],s1); 703 for (i = 0;i < s2->linecount;i++) 704 { 705 if (((!s2->lines[i]->flags) & ML_TWOSIDED) || (s2->lines[i]->backsector == s1)) continue; 706 s3 = s2->lines[i]->backsector; 707 708 709 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); 710 P_AddThinker (&floor->thinker); 711 s2->specialdata = floor; 712 floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; 713 floor->type = donutRaise; 714 floor->crush = false; 715 floor->direction = 1; 716 floor->sector = s2; 717 floor->speed = FLOORSPEED / 2; 718 floor->texture = s3->floorpic; 719 floor->newspecial = 0; 720 floor->floordestheight = s3->floorheight; 721 722 723 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); 724 P_AddThinker (&floor->thinker); 725 s1->specialdata = floor; 726 floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; 727 floor->type = lowerFloor; 728 floor->crush = false; 729 floor->direction = -1; 730 floor->sector = s1; 731 floor->speed = FLOORSPEED / 2; 732 floor->floordestheight = s3->floorheight; 733 break; 734 } 735 } 736 return rtn; 737 } 738 739 740 741 742 743 744 745 746 747 748 749 750 short numlinespecials; 751 line_t* linespeciallist[MAXLINEANIMS]; 752 753 754 755 void P_SpawnSpecials (void) 756 { 757 sector_t* sector; 758 int i; 759 760 if (W_CheckNumForName("texture2") >= 0) 761 762 763 764 levelTimer = false; 765 766 i = M_CheckParm("-avg"); 767 if (i && deathmatch) 768 { 769 levelTimer = true; 770 levelTimeCount = 20 * 60 * 35; 771 } 772 773 i = M_CheckParm("-timer"); 774 if (i && deathmatch) 775 { 776 int time; 777 time = atoi(myargv[i+1]) * 60 * 35; 778 levelTimer = true; 779 levelTimeCount = time; 780 } 781 782 783 sector = sectors; 784 for (i=0 ; i<numsectors ; i++, sector++) 785 { 786 if (!sector->special) 787 continue; 788 789 switch (sector->special) { 790 case 1: 791 P_SpawnLightFlash (sector); 792 break; 793 case 2: 794 P_SpawnStrobeFlash(sector,FASTDARK,0); 795 break; 796 case 3: 797 P_SpawnStrobeFlash(sector,SLOWDARK,0); 798 break; 799 case 4: 800 P_SpawnStrobeFlash(sector,FASTDARK,0); 801 sector->special = 4; 802 break; 803 case 8: 804 P_SpawnGlowingLight(sector); 805 break; 806 case 9: 807 totalsecret++; 808 break; 809 case 10: 810 P_SpawnDoorCloseIn30(sector); 811 break; 812 case 12: 813 P_SpawnStrobeFlash(sector, SLOWDARK, 1); 814 break; 815 case 13: 816 P_SpawnStrobeFlash(sector, FASTDARK, 1); 817 break; 818 case 14: 819 P_SpawnDoorRaiseIn5Mins(sector, i); 820 break; 821 case 17: 822 P_SpawnFireFlicker(sector); 823 break; 824 } 825 } 826 827 828 829 numlinespecials = 0; 830 for (i = 0;i < numlines; i++) 831 { 832 switch(lines[i].special) 833 { 834 case 48: 835 836 linespeciallist[numlinespecials] = &lines[i]; 837 numlinespecials++; 838 break; 839 } 840 } 841 842 843 844 for (i = 0;i < MAXCEILINGS;i++) 845 activeceilings[i] = NULL; 846 847 for (i = 0;i < MAXPLATS;i++) 848 activeplats[i] = NULL; 849 850 for (i = 0;i < MAXBUTTONS;i++) 851 memset(&buttonlist[i],0,sizeof(button_t)); 852 853 854 855 }