A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1154 lines 34 kB view raw
1/* Emacs style mode select -*- C++ -*- 2 *----------------------------------------------------------------------------- 3 * 4 * 5 * PrBoom a Doom port merged with LxDoom and LSDLDoom 6 * based on BOOM, a modified and improved DOOM engine 7 * Copyright (C) 1999 by 8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman 9 * Copyright (C) 1999-2000 by 10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 25 * 02111-1307, USA. 26 * 27 * DESCRIPTION: 28 * Generalized linedef type handlers 29 * Floors, Ceilings, Doors, Locked Doors, Lifts, Stairs, Crushers 30 * 31 *-----------------------------------------------------------------------------*/ 32 33#include "doomstat.h" //jff 6/19/98 for demo_compatibility 34#include "r_main.h" 35#include "p_spec.h" 36#include "p_tick.h" 37#include "m_random.h" 38#include "s_sound.h" 39#include "sounds.h" 40 41////////////////////////////////////////////////////////// 42// 43// Generalized Linedef Type handlers 44// 45////////////////////////////////////////////////////////// 46 47// 48// EV_DoGenFloor() 49// 50// Handle generalized floor types 51// 52// Passed the line activating the generalized floor function 53// Returns true if a thinker is created 54// 55// jff 02/04/98 Added this routine (and file) to handle generalized 56// floor movers using bit fields in the line special type. 57// 58int EV_DoGenFloor 59( line_t* line ) 60{ 61 int secnum; 62 int rtn; 63 boolean manual; 64 sector_t* sec; 65 floormove_t* floor; 66 unsigned value = (unsigned)line->special - GenFloorBase; 67 68 // parse the bit fields in the line's special type 69 70 int Crsh = (value & FloorCrush) >> FloorCrushShift; 71 int ChgT = (value & FloorChange) >> FloorChangeShift; 72 int Targ = (value & FloorTarget) >> FloorTargetShift; 73 int Dirn = (value & FloorDirection) >> FloorDirectionShift; 74 int ChgM = (value & FloorModel) >> FloorModelShift; 75 int Sped = (value & FloorSpeed) >> FloorSpeedShift; 76 int Trig = (value & TriggerType) >> TriggerTypeShift; 77 78 rtn = 0; 79 80 // check if a manual trigger, if so do just the sector on the backside 81 manual = false; 82 if (Trig==PushOnce || Trig==PushMany) 83 { 84 if (!(sec = line->backsector)) 85 return rtn; 86 secnum = sec-sectors; 87 manual = true; 88 goto manual_floor; 89 } 90 91 secnum = -1; 92 // if not manual do all sectors tagged the same as the line 93 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 94 { 95 sec = &sectors[secnum]; 96 97manual_floor: 98 // Do not start another function if floor already moving 99 if (P_SectorActive(floor_special,sec)) 100 { 101 if (!manual) 102 continue; 103 else 104 return rtn; 105 } 106 107 // new floor thinker 108 rtn = 1; 109 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); 110 P_AddThinker (&floor->thinker); 111 sec->floordata = floor; 112 floor->thinker.function = T_MoveFloor; 113 floor->crush = Crsh; 114 floor->direction = Dirn? 1 : -1; 115 floor->sector = sec; 116 floor->texture = sec->floorpic; 117 floor->newspecial = sec->special; 118 //jff 3/14/98 transfer old special field too 119 floor->oldspecial = sec->oldspecial; 120 floor->type = genFloor; 121 122 // set the speed of motion 123 switch (Sped) 124 { 125 case SpeedSlow: 126 floor->speed = FLOORSPEED; 127 break; 128 case SpeedNormal: 129 floor->speed = FLOORSPEED*2; 130 break; 131 case SpeedFast: 132 floor->speed = FLOORSPEED*4; 133 break; 134 case SpeedTurbo: 135 floor->speed = FLOORSPEED*8; 136 break; 137 default: 138 break; 139 } 140 141 // set the destination height 142 switch(Targ) 143 { 144 case FtoHnF: 145 floor->floordestheight = P_FindHighestFloorSurrounding(sec); 146 break; 147 case FtoLnF: 148 floor->floordestheight = P_FindLowestFloorSurrounding(sec); 149 break; 150 case FtoNnF: 151 floor->floordestheight = Dirn? 152 P_FindNextHighestFloor(sec,sec->floorheight) : 153 P_FindNextLowestFloor(sec,sec->floorheight); 154 break; 155 case FtoLnC: 156 floor->floordestheight = P_FindLowestCeilingSurrounding(sec); 157 break; 158 case FtoC: 159 floor->floordestheight = sec->ceilingheight; 160 break; 161 case FbyST: 162 floor->floordestheight = (floor->sector->floorheight>>FRACBITS) + 163 floor->direction * (P_FindShortestTextureAround(secnum)>>FRACBITS); 164 if (floor->floordestheight>32000) //jff 3/13/98 prevent overflow 165 floor->floordestheight=32000; // wraparound in floor height 166 if (floor->floordestheight<-32000) 167 floor->floordestheight=-32000; 168 floor->floordestheight<<=FRACBITS; 169 break; 170 case Fby24: 171 floor->floordestheight = floor->sector->floorheight + 172 floor->direction * 24*FRACUNIT; 173 break; 174 case Fby32: 175 floor->floordestheight = floor->sector->floorheight + 176 floor->direction * 32*FRACUNIT; 177 break; 178 default: 179 break; 180 } 181 182 // set texture/type change properties 183 if (ChgT) // if a texture change is indicated 184 { 185 if (ChgM) // if a numeric model change 186 { 187 sector_t *sec; 188 189 //jff 5/23/98 find model with ceiling at target height if target 190 //is a ceiling type 191 sec = (Targ==FtoLnC || Targ==FtoC)? 192 P_FindModelCeilingSector(floor->floordestheight,secnum) : 193 P_FindModelFloorSector(floor->floordestheight,secnum); 194 if (sec) 195 { 196 floor->texture = sec->floorpic; 197 switch(ChgT) 198 { 199 case FChgZero: // zero type 200 floor->newspecial = 0; 201 //jff 3/14/98 change old field too 202 floor->oldspecial = 0; 203 floor->type = genFloorChg0; 204 break; 205 case FChgTyp: // copy type 206 floor->newspecial = sec->special; 207 //jff 3/14/98 change old field too 208 floor->oldspecial = sec->oldspecial; 209 floor->type = genFloorChgT; 210 break; 211 case FChgTxt: // leave type be 212 floor->type = genFloorChg; 213 break; 214 default: 215 break; 216 } 217 } 218 } 219 else // else if a trigger model change 220 { 221 floor->texture = line->frontsector->floorpic; 222 switch (ChgT) 223 { 224 case FChgZero: // zero type 225 floor->newspecial = 0; 226 //jff 3/14/98 change old field too 227 floor->oldspecial = 0; 228 floor->type = genFloorChg0; 229 break; 230 case FChgTyp: // copy type 231 floor->newspecial = line->frontsector->special; 232 //jff 3/14/98 change old field too 233 floor->oldspecial = line->frontsector->oldspecial; 234 floor->type = genFloorChgT; 235 break; 236 case FChgTxt: // leave type be 237 floor->type = genFloorChg; 238 default: 239 break; 240 } 241 } 242 } 243 if (manual) return rtn; 244 } 245 return rtn; 246} 247 248 249// 250// EV_DoGenCeiling() 251// 252// Handle generalized ceiling types 253// 254// Passed the linedef activating the ceiling function 255// Returns true if a thinker created 256// 257// jff 02/04/98 Added this routine (and file) to handle generalized 258// floor movers using bit fields in the line special type. 259// 260int EV_DoGenCeiling 261( line_t* line ) 262{ 263 int secnum; 264 int rtn; 265 boolean manual; 266 fixed_t targheight; 267 sector_t* sec; 268 ceiling_t* ceiling; 269 unsigned value = (unsigned)line->special - GenCeilingBase; 270 271 // parse the bit fields in the line's special type 272 273 int Crsh = (value & CeilingCrush) >> CeilingCrushShift; 274 int ChgT = (value & CeilingChange) >> CeilingChangeShift; 275 int Targ = (value & CeilingTarget) >> CeilingTargetShift; 276 int Dirn = (value & CeilingDirection) >> CeilingDirectionShift; 277 int ChgM = (value & CeilingModel) >> CeilingModelShift; 278 int Sped = (value & CeilingSpeed) >> CeilingSpeedShift; 279 int Trig = (value & TriggerType) >> TriggerTypeShift; 280 281 rtn = 0; 282 283 // check if a manual trigger, if so do just the sector on the backside 284 manual = false; 285 if (Trig==PushOnce || Trig==PushMany) 286 { 287 if (!(sec = line->backsector)) 288 return rtn; 289 secnum = sec-sectors; 290 manual = true; 291 goto manual_ceiling; 292 } 293 294 secnum = -1; 295 // if not manual do all sectors tagged the same as the line 296 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 297 { 298 sec = &sectors[secnum]; 299 300manual_ceiling: 301 // Do not start another function if ceiling already moving 302 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98 303 { 304 if (!manual) 305 continue; 306 else 307 return rtn; 308 } 309 310 // new ceiling thinker 311 rtn = 1; 312 ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); 313 P_AddThinker (&ceiling->thinker); 314 sec->ceilingdata = ceiling; //jff 2/22/98 315 ceiling->thinker.function = T_MoveCeiling; 316 ceiling->crush = Crsh; 317 ceiling->direction = Dirn? 1 : -1; 318 ceiling->sector = sec; 319 ceiling->texture = sec->ceilingpic; 320 ceiling->newspecial = sec->special; 321 //jff 3/14/98 change old field too 322 ceiling->oldspecial = sec->oldspecial; 323 ceiling->tag = sec->tag; 324 ceiling->type = genCeiling; 325 326 // set speed of motion 327 switch (Sped) 328 { 329 case SpeedSlow: 330 ceiling->speed = CEILSPEED; 331 break; 332 case SpeedNormal: 333 ceiling->speed = CEILSPEED*2; 334 break; 335 case SpeedFast: 336 ceiling->speed = CEILSPEED*4; 337 break; 338 case SpeedTurbo: 339 ceiling->speed = CEILSPEED*8; 340 break; 341 default: 342 break; 343 } 344 345 // set destination target height 346 targheight = sec->ceilingheight; 347 switch(Targ) 348 { 349 case CtoHnC: 350 targheight = P_FindHighestCeilingSurrounding(sec); 351 break; 352 case CtoLnC: 353 targheight = P_FindLowestCeilingSurrounding(sec); 354 break; 355 case CtoNnC: 356 targheight = Dirn? 357 P_FindNextHighestCeiling(sec,sec->ceilingheight) : 358 P_FindNextLowestCeiling(sec,sec->ceilingheight); 359 break; 360 case CtoHnF: 361 targheight = P_FindHighestFloorSurrounding(sec); 362 break; 363 case CtoF: 364 targheight = sec->floorheight; 365 break; 366 case CbyST: 367 targheight = (ceiling->sector->ceilingheight>>FRACBITS) + 368 ceiling->direction * (P_FindShortestUpperAround(secnum)>>FRACBITS); 369 if (targheight>32000) //jff 3/13/98 prevent overflow 370 targheight=32000; // wraparound in ceiling height 371 if (targheight<-32000) 372 targheight=-32000; 373 targheight<<=FRACBITS; 374 break; 375 case Cby24: 376 targheight = ceiling->sector->ceilingheight + 377 ceiling->direction * 24*FRACUNIT; 378 break; 379 case Cby32: 380 targheight = ceiling->sector->ceilingheight + 381 ceiling->direction * 32*FRACUNIT; 382 break; 383 default: 384 break; 385 } 386 if (Dirn) ceiling->topheight = targheight; 387 else ceiling->bottomheight = targheight; 388 389 // set texture/type change properties 390 if (ChgT) // if a texture change is indicated 391 { 392 if (ChgM) // if a numeric model change 393 { 394 sector_t *sec; 395 396 //jff 5/23/98 find model with floor at target height if target 397 //is a floor type 398 sec = (Targ==CtoHnF || Targ==CtoF)? 399 P_FindModelFloorSector(targheight,secnum) : 400 P_FindModelCeilingSector(targheight,secnum); 401 if (sec) 402 { 403 ceiling->texture = sec->ceilingpic; 404 switch (ChgT) 405 { 406 case CChgZero: // type is zeroed 407 ceiling->newspecial = 0; 408 //jff 3/14/98 change old field too 409 ceiling->oldspecial = 0; 410 ceiling->type = genCeilingChg0; 411 break; 412 case CChgTyp: // type is copied 413 ceiling->newspecial = sec->special; 414 //jff 3/14/98 change old field too 415 ceiling->oldspecial = sec->oldspecial; 416 ceiling->type = genCeilingChgT; 417 break; 418 case CChgTxt: // type is left alone 419 ceiling->type = genCeilingChg; 420 break; 421 default: 422 break; 423 } 424 } 425 } 426 else // else if a trigger model change 427 { 428 ceiling->texture = line->frontsector->ceilingpic; 429 switch (ChgT) 430 { 431 case CChgZero: // type is zeroed 432 ceiling->newspecial = 0; 433 //jff 3/14/98 change old field too 434 ceiling->oldspecial = 0; 435 ceiling->type = genCeilingChg0; 436 break; 437 case CChgTyp: // type is copied 438 ceiling->newspecial = line->frontsector->special; 439 //jff 3/14/98 change old field too 440 ceiling->oldspecial = line->frontsector->oldspecial; 441 ceiling->type = genCeilingChgT; 442 break; 443 case CChgTxt: // type is left alone 444 ceiling->type = genCeilingChg; 445 break; 446 default: 447 break; 448 } 449 } 450 } 451 P_AddActiveCeiling(ceiling); // add this ceiling to the active list 452 if (manual) return rtn; 453 } 454 return rtn; 455} 456 457// 458// EV_DoGenLift() 459// 460// Handle generalized lift types 461// 462// Passed the linedef activating the lift 463// Returns true if a thinker is created 464// 465int EV_DoGenLift 466( line_t* line ) 467{ 468 plat_t* plat; 469 int secnum; 470 int rtn; 471 boolean manual; 472 sector_t* sec; 473 unsigned value = (unsigned)line->special - GenLiftBase; 474 475 // parse the bit fields in the line's special type 476 477 int Targ = (value & LiftTarget) >> LiftTargetShift; 478 int Dely = (value & LiftDelay) >> LiftDelayShift; 479 int Sped = (value & LiftSpeed) >> LiftSpeedShift; 480 int Trig = (value & TriggerType) >> TriggerTypeShift; 481 482 secnum = -1; 483 rtn = 0; 484 485 // Activate all <type> plats that are in_stasis 486 487 if (Targ==LnF2HnF) 488 P_ActivateInStasis(line->tag); 489 490 // check if a manual trigger, if so do just the sector on the backside 491 manual = false; 492 if (Trig==PushOnce || Trig==PushMany) 493 { 494 if (!(sec = line->backsector)) 495 return rtn; 496 secnum = sec-sectors; 497 manual = true; 498 goto manual_lift; 499 } 500 501 // if not manual do all sectors tagged the same as the line 502 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 503 { 504 sec = &sectors[secnum]; 505 506manual_lift: 507 // Do not start another function if floor already moving 508 if (P_SectorActive(floor_special,sec)) 509 { 510 if (!manual) 511 continue; 512 else 513 return rtn; 514 } 515 516 // Setup the plat thinker 517 rtn = 1; 518 plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); 519 P_AddThinker(&plat->thinker); 520 521 plat->sector = sec; 522 plat->sector->floordata = plat; 523 plat->thinker.function = T_PlatRaise; 524 plat->crush = false; 525 plat->tag = line->tag; 526 527 plat->type = genLift; 528 plat->high = sec->floorheight; 529 plat->status = down; 530 531 // setup the target destination height 532 switch(Targ) 533 { 534 case F2LnF: 535 plat->low = P_FindLowestFloorSurrounding(sec); 536 if (plat->low > sec->floorheight) 537 plat->low = sec->floorheight; 538 break; 539 case F2NnF: 540 plat->low = P_FindNextLowestFloor(sec,sec->floorheight); 541 break; 542 case F2LnC: 543 plat->low = P_FindLowestCeilingSurrounding(sec); 544 if (plat->low > sec->floorheight) 545 plat->low = sec->floorheight; 546 break; 547 case LnF2HnF: 548 plat->type = genPerpetual; 549 plat->low = P_FindLowestFloorSurrounding(sec); 550 if (plat->low > sec->floorheight) 551 plat->low = sec->floorheight; 552 plat->high = P_FindHighestFloorSurrounding(sec); 553 if (plat->high < sec->floorheight) 554 plat->high = sec->floorheight; 555 plat->status = P_Random(pr_genlift)&1; 556 break; 557 default: 558 break; 559 } 560 561 // setup the speed of motion 562 switch(Sped) 563 { 564 case SpeedSlow: 565 plat->speed = PLATSPEED * 2; 566 break; 567 case SpeedNormal: 568 plat->speed = PLATSPEED * 4; 569 break; 570 case SpeedFast: 571 plat->speed = PLATSPEED * 8; 572 break; 573 case SpeedTurbo: 574 plat->speed = PLATSPEED * 16; 575 break; 576 default: 577 break; 578 } 579 580 // setup the delay time before the floor returns 581 switch(Dely) 582 { 583 case 0: 584 plat->wait = 1*35; 585 break; 586 case 1: 587 plat->wait = PLATWAIT*35; 588 break; 589 case 2: 590 plat->wait = 5*35; 591 break; 592 case 3: 593 plat->wait = 10*35; 594 break; 595 } 596 597 S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); 598 P_AddActivePlat(plat); // add this plat to the list of active plats 599 600 if (manual) 601 return rtn; 602 } 603 return rtn; 604} 605 606// 607// EV_DoGenStairs() 608// 609// Handle generalized stair building 610// 611// Passed the linedef activating the stairs 612// Returns true if a thinker is created 613// 614int EV_DoGenStairs 615( line_t* line ) 616{ 617 int secnum; 618 int osecnum; //jff 3/4/98 preserve loop index 619 int height; 620 int i; 621 int newsecnum; 622 int texture; 623 int ok; 624 int rtn; 625 boolean manual; 626 627 sector_t* sec; 628 sector_t* tsec; 629 630 floormove_t* floor; 631 632 fixed_t stairsize; 633 fixed_t speed; 634 635 unsigned value = (unsigned)line->special - GenStairsBase; 636 637 // parse the bit fields in the line's special type 638 639 int Igno = (value & StairIgnore) >> StairIgnoreShift; 640 int Dirn = (value & StairDirection) >> StairDirectionShift; 641 int Step = (value & StairStep) >> StairStepShift; 642 int Sped = (value & StairSpeed) >> StairSpeedShift; 643 int Trig = (value & TriggerType) >> TriggerTypeShift; 644 645 rtn = 0; 646 647 // check if a manual trigger, if so do just the sector on the backside 648 manual = false; 649 if (Trig==PushOnce || Trig==PushMany) 650 { 651 if (!(sec = line->backsector)) 652 return rtn; 653 secnum = sec-sectors; 654 manual = true; 655 goto manual_stair; 656 } 657 658 secnum = -1; 659 // if not manual do all sectors tagged the same as the line 660 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 661 { 662 sec = &sectors[secnum]; 663 664manual_stair: 665 //Do not start another function if floor already moving 666 //jff 2/26/98 add special lockout condition to wait for entire 667 //staircase to build before retriggering 668 if (P_SectorActive(floor_special,sec) || sec->stairlock) 669 { 670 if (!manual) 671 continue; 672 else 673 return rtn; 674 } 675 676 // new floor thinker 677 rtn = 1; 678 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); 679 P_AddThinker (&floor->thinker); 680 sec->floordata = floor; 681 floor->thinker.function = T_MoveFloor; 682 floor->direction = Dirn? 1 : -1; 683 floor->sector = sec; 684 685 // setup speed of stair building 686 switch(Sped) 687 { 688 default: 689 case SpeedSlow: 690 floor->speed = FLOORSPEED/4; 691 break; 692 case SpeedNormal: 693 floor->speed = FLOORSPEED/2; 694 break; 695 case SpeedFast: 696 floor->speed = FLOORSPEED*2; 697 break; 698 case SpeedTurbo: 699 floor->speed = FLOORSPEED*4; 700 break; 701 } 702 703 // setup stepsize for stairs 704 switch(Step) 705 { 706 default: 707 case 0: 708 stairsize = 4*FRACUNIT; 709 break; 710 case 1: 711 stairsize = 8*FRACUNIT; 712 break; 713 case 2: 714 stairsize = 16*FRACUNIT; 715 break; 716 case 3: 717 stairsize = 24*FRACUNIT; 718 break; 719 } 720 721 speed = floor->speed; 722 height = sec->floorheight + floor->direction * stairsize; 723 floor->floordestheight = height; 724 texture = sec->floorpic; 725 floor->crush = false; 726 floor->type = genBuildStair; // jff 3/31/98 do not leave uninited 727 728 sec->stairlock = -2; // jff 2/26/98 set up lock on current sector 729 sec->nextsec = -1; 730 sec->prevsec = -1; 731 732 osecnum = secnum; //jff 3/4/98 preserve loop index 733 // Find next sector to raise 734 // 1. Find 2-sided line with same sector side[0] 735 // 2. Other side is the next sector to raise 736 do 737 { 738 ok = 0; 739 for (i = 0;i < sec->linecount;i++) 740 { 741 if ( !((sec->lines[i])->backsector) ) 742 continue; 743 744 tsec = (sec->lines[i])->frontsector; 745 newsecnum = tsec-sectors; 746 747 if (secnum != newsecnum) 748 continue; 749 750 tsec = (sec->lines[i])->backsector; 751 newsecnum = tsec - sectors; 752 753 if (!Igno && tsec->floorpic != texture) 754 continue; 755 756 /* jff 6/19/98 prevent double stepsize */ 757 if (compatibility_level < boom_202_compatibility) 758 height += floor->direction * stairsize; 759 760 //jff 2/26/98 special lockout condition for retriggering 761 if (P_SectorActive(floor_special,tsec) || tsec->stairlock) 762 continue; 763 764 /* jff 6/19/98 increase height AFTER continue */ 765 if (compatibility_level >= boom_202_compatibility) 766 height += floor->direction * stairsize; 767 768 // jff 2/26/98 769 // link the stair chain in both directions 770 // lock the stair sector until building complete 771 sec->nextsec = newsecnum; // link step to next 772 tsec->prevsec = secnum; // link next back 773 tsec->nextsec = -1; // set next forward link as end 774 tsec->stairlock = -2; // lock the step 775 776 sec = tsec; 777 secnum = newsecnum; 778 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); 779 780 P_AddThinker (&floor->thinker); 781 782 sec->floordata = floor; 783 floor->thinker.function = T_MoveFloor; 784 floor->direction = Dirn? 1 : -1; 785 floor->sector = sec; 786 floor->speed = speed; 787 floor->floordestheight = height; 788 floor->crush = false; 789 floor->type = genBuildStair; // jff 3/31/98 do not leave uninited 790 791 ok = 1; 792 break; 793 } 794 } while(ok); 795 if (manual) 796 return rtn; 797 secnum = osecnum; //jff 3/4/98 restore old loop index 798 } 799 // retriggerable generalized stairs build up or down alternately 800 if (rtn) 801 line->special ^= StairDirection; // alternate dir on succ activations 802 return rtn; 803} 804 805// 806// EV_DoGenCrusher() 807// 808// Handle generalized crusher types 809// 810// Passed the linedef activating the crusher 811// Returns true if a thinker created 812// 813int EV_DoGenCrusher 814( line_t* line ) 815{ 816 int secnum; 817 int rtn; 818 boolean manual; 819 sector_t* sec; 820 ceiling_t* ceiling; 821 unsigned value = (unsigned)line->special - GenCrusherBase; 822 823 // parse the bit fields in the line's special type 824 825 int Slnt = (value & CrusherSilent) >> CrusherSilentShift; 826 int Sped = (value & CrusherSpeed) >> CrusherSpeedShift; 827 int Trig = (value & TriggerType) >> TriggerTypeShift; 828 829 //jff 2/22/98 Reactivate in-stasis ceilings...for certain types. 830 //jff 4/5/98 return if activated 831 rtn = P_ActivateInStasisCeiling(line); 832 833 // check if a manual trigger, if so do just the sector on the backside 834 manual = false; 835 if (Trig==PushOnce || Trig==PushMany) 836 { 837 if (!(sec = line->backsector)) 838 return rtn; 839 secnum = sec-sectors; 840 manual = true; 841 goto manual_crusher; 842 } 843 844 secnum = -1; 845 // if not manual do all sectors tagged the same as the line 846 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 847 { 848 sec = &sectors[secnum]; 849 850manual_crusher: 851 // Do not start another function if ceiling already moving 852 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98 853 { 854 if (!manual) 855 continue; 856 else 857 return rtn; 858 } 859 860 // new ceiling thinker 861 rtn = 1; 862 ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); 863 P_AddThinker (&ceiling->thinker); 864 sec->ceilingdata = ceiling; //jff 2/22/98 865 ceiling->thinker.function = T_MoveCeiling; 866 ceiling->crush = true; 867 ceiling->direction = -1; 868 ceiling->sector = sec; 869 ceiling->texture = sec->ceilingpic; 870 ceiling->newspecial = sec->special; 871 ceiling->tag = sec->tag; 872 ceiling->type = Slnt? genSilentCrusher : genCrusher; 873 ceiling->topheight = sec->ceilingheight; 874 ceiling->bottomheight = sec->floorheight + (8*FRACUNIT); 875 876 // setup ceiling motion speed 877 switch (Sped) 878 { 879 case SpeedSlow: 880 ceiling->speed = CEILSPEED; 881 break; 882 case SpeedNormal: 883 ceiling->speed = CEILSPEED*2; 884 break; 885 case SpeedFast: 886 ceiling->speed = CEILSPEED*4; 887 break; 888 case SpeedTurbo: 889 ceiling->speed = CEILSPEED*8; 890 break; 891 default: 892 break; 893 } 894 ceiling->oldspeed=ceiling->speed; 895 896 P_AddActiveCeiling(ceiling); // add to list of active ceilings 897 if (manual) return rtn; 898 } 899 return rtn; 900} 901 902// 903// EV_DoGenLockedDoor() 904// 905// Handle generalized locked door types 906// 907// Passed the linedef activating the generalized locked door 908// Returns true if a thinker created 909// 910int EV_DoGenLockedDoor 911( line_t* line ) 912{ 913 int secnum,rtn; 914 sector_t* sec; 915 vldoor_t* door; 916 boolean manual; 917 unsigned value = (unsigned)line->special - GenLockedBase; 918 919 // parse the bit fields in the line's special type 920 921 int Kind = (value & LockedKind) >> LockedKindShift; 922 int Sped = (value & LockedSpeed) >> LockedSpeedShift; 923 int Trig = (value & TriggerType) >> TriggerTypeShift; 924 925 rtn = 0; 926 927 // check if a manual trigger, if so do just the sector on the backside 928 manual = false; 929 if (Trig==PushOnce || Trig==PushMany) 930 { 931 if (!(sec = line->backsector)) 932 return rtn; 933 secnum = sec-sectors; 934 manual = true; 935 goto manual_locked; 936 } 937 938 secnum = -1; 939 rtn = 0; 940 941 // if not manual do all sectors tagged the same as the line 942 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 943 { 944 sec = &sectors[secnum]; 945manual_locked: 946 // Do not start another function if ceiling already moving 947 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98 948 { 949 if (!manual) 950 continue; 951 else 952 return rtn; 953 } 954 955 // new door thinker 956 rtn = 1; 957 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); 958 P_AddThinker (&door->thinker); 959 sec->ceilingdata = door; //jff 2/22/98 960 961 door->thinker.function = T_VerticalDoor; 962 door->sector = sec; 963 door->topwait = VDOORWAIT; 964 door->line = line; 965 door->topheight = P_FindLowestCeilingSurrounding(sec); 966 door->topheight -= 4*FRACUNIT; 967 door->direction = 1; 968 969 /* killough 10/98: implement gradual lighting */ 970 door->lighttag = !comp[comp_doorlight] && 971 (line->special&6) == 6 && 972 line->special > GenLockedBase ? line->tag : 0; 973 974 // setup speed of door motion 975 switch(Sped) 976 { 977 default: 978 case SpeedSlow: 979 door->type = Kind? genOpen : genRaise; 980 door->speed = VDOORSPEED; 981 break; 982 case SpeedNormal: 983 door->type = Kind? genOpen : genRaise; 984 door->speed = VDOORSPEED*2; 985 break; 986 case SpeedFast: 987 door->type = Kind? genBlazeOpen : genBlazeRaise; 988 door->speed = VDOORSPEED*4; 989 break; 990 case SpeedTurbo: 991 door->type = Kind? genBlazeOpen : genBlazeRaise; 992 door->speed = VDOORSPEED*8; 993 994 break; 995 } 996 997 // killough 4/15/98: fix generalized door opening sounds 998 // (previously they always had the blazing door close sound) 999 1000 S_StartSound((mobj_t *)&door->sector->soundorg, // killough 4/15/98 1001 door->speed >= VDOORSPEED*4 ? sfx_bdopn : sfx_doropn); 1002 1003 if (manual) 1004 return rtn; 1005 } 1006 return rtn; 1007} 1008 1009// 1010// EV_DoGenDoor() 1011// 1012// Handle generalized door types 1013// 1014// Passed the linedef activating the generalized door 1015// Returns true if a thinker created 1016// 1017int EV_DoGenDoor 1018( line_t* line ) 1019{ 1020 int secnum,rtn; 1021 sector_t* sec; 1022 boolean manual; 1023 vldoor_t* door; 1024 unsigned value = (unsigned)line->special - GenDoorBase; 1025 1026 // parse the bit fields in the line's special type 1027 1028 int Dely = (value & DoorDelay) >> DoorDelayShift; 1029 int Kind = (value & DoorKind) >> DoorKindShift; 1030 int Sped = (value & DoorSpeed) >> DoorSpeedShift; 1031 int Trig = (value & TriggerType) >> TriggerTypeShift; 1032 1033 rtn = 0; 1034 1035 // check if a manual trigger, if so do just the sector on the backside 1036 manual = false; 1037 if (Trig==PushOnce || Trig==PushMany) 1038 { 1039 if (!(sec = line->backsector)) 1040 return rtn; 1041 secnum = sec-sectors; 1042 manual = true; 1043 goto manual_door; 1044 } 1045 1046 1047 secnum = -1; 1048 rtn = 0; 1049 1050 // if not manual do all sectors tagged the same as the line 1051 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 1052 { 1053 sec = &sectors[secnum]; 1054manual_door: 1055 // Do not start another function if ceiling already moving 1056 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98 1057 { 1058 if (!manual) 1059 continue; 1060 else 1061 return rtn; 1062 } 1063 1064 // new door thinker 1065 rtn = 1; 1066 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); 1067 P_AddThinker (&door->thinker); 1068 sec->ceilingdata = door; //jff 2/22/98 1069 1070 door->thinker.function = T_VerticalDoor; 1071 door->sector = sec; 1072 // setup delay for door remaining open/closed 1073 switch(Dely) 1074 { 1075 default: 1076 case 0: 1077 door->topwait = 35; 1078 break; 1079 case 1: 1080 door->topwait = VDOORWAIT; 1081 break; 1082 case 2: 1083 door->topwait = 2*VDOORWAIT; 1084 break; 1085 case 3: 1086 door->topwait = 7*VDOORWAIT; 1087 break; 1088 } 1089 1090 // setup speed of door motion 1091 switch(Sped) 1092 { 1093 default: 1094 case SpeedSlow: 1095 door->speed = VDOORSPEED; 1096 break; 1097 case SpeedNormal: 1098 door->speed = VDOORSPEED*2; 1099 break; 1100 case SpeedFast: 1101 door->speed = VDOORSPEED*4; 1102 break; 1103 case SpeedTurbo: 1104 door->speed = VDOORSPEED*8; 1105 break; 1106 } 1107 door->line = line; // jff 1/31/98 remember line that triggered us 1108 1109 /* killough 10/98: implement gradual lighting */ 1110 door->lighttag = !comp[comp_doorlight] && 1111 (line->special&6) == 6 && 1112 line->special > GenLockedBase ? line->tag : 0; 1113 1114 // set kind of door, whether it opens then close, opens, closes etc. 1115 // assign target heights accordingly 1116 switch(Kind) 1117 { 1118 case OdCDoor: 1119 door->direction = 1; 1120 door->topheight = P_FindLowestCeilingSurrounding(sec); 1121 door->topheight -= 4*FRACUNIT; 1122 if (door->topheight != sec->ceilingheight) 1123 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast || comp[comp_sound] ? sfx_bdopn : sfx_doropn); 1124 door->type = Sped>=SpeedFast? genBlazeRaise : genRaise; 1125 break; 1126 case ODoor: 1127 door->direction = 1; 1128 door->topheight = P_FindLowestCeilingSurrounding(sec); 1129 door->topheight -= 4*FRACUNIT; 1130 if (door->topheight != sec->ceilingheight) 1131 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast || comp[comp_sound] ? sfx_bdopn : sfx_doropn); 1132 door->type = Sped>=SpeedFast? genBlazeOpen : genOpen; 1133 break; 1134 case CdODoor: 1135 door->topheight = sec->ceilingheight; 1136 door->direction = -1; 1137 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast && !comp[comp_sound] ? sfx_bdcls : sfx_dorcls); 1138 door->type = Sped>=SpeedFast? genBlazeCdO : genCdO; 1139 break; 1140 case CDoor: 1141 door->topheight = P_FindLowestCeilingSurrounding(sec); 1142 door->topheight -= 4*FRACUNIT; 1143 door->direction = -1; 1144 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast && !comp[comp_sound] ? sfx_bdcls : sfx_dorcls); 1145 door->type = Sped>=SpeedFast? genBlazeClose : genClose; 1146 break; 1147 default: 1148 break; 1149 } 1150 if (manual) 1151 return rtn; 1152 } 1153 return rtn; 1154}