A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1036 lines 35 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 * General plane mover and floor mover action routines 29 * Floor motion, pure changer types, raising stairs. donuts, elevators 30 * 31 *-----------------------------------------------------------------------------*/ 32 33#include "doomstat.h" 34#include "r_main.h" 35#include "p_map.h" 36#include "p_spec.h" 37#include "p_tick.h" 38#include "s_sound.h" 39#include "sounds.h" 40 41#include "rockmacros.h" 42 43/////////////////////////////////////////////////////////////////////// 44// 45// Plane (floor or ceiling), Floor motion and Elevator action routines 46// 47/////////////////////////////////////////////////////////////////////// 48 49// 50// T_MovePlane() 51// 52// Move a plane (floor or ceiling) and check for crushing. Called 53// every tick by all actions that move floors or ceilings. 54// 55// Passed the sector to move a plane in, the speed to move it at, 56// the dest height it is to achieve, whether it crushes obstacles, 57// whether it moves a floor or ceiling, and the direction up or down 58// to move. 59// 60// Returns a result_e: 61// ok - plane moved normally, has not achieved destination yet 62// pastdest - plane moved normally and is now at destination height 63// crushed - plane encountered an obstacle, is holding until removed 64// 65result_e T_MovePlane 66( sector_t* sector, 67 fixed_t speed, 68 fixed_t dest, 69 boolean crush, 70 int floorOrCeiling, 71 int direction ) 72{ 73 boolean flag; 74 fixed_t lastpos; 75 fixed_t destheight; //jff 02/04/98 used to keep floors/ceilings 76 // from moving thru each other 77 78 switch(floorOrCeiling) 79 { 80 case 0: 81 // Moving a floor 82 switch(direction) 83 { 84 case -1: 85 // Moving a floor down 86 if (sector->floorheight - speed < dest) 87 { 88 lastpos = sector->floorheight; 89 sector->floorheight = dest; 90 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 91 if (flag == true) 92 { 93 sector->floorheight =lastpos; 94 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 95 } 96 return pastdest; 97 } 98 else 99 { 100 lastpos = sector->floorheight; 101 sector->floorheight -= speed; 102 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 103 /* cph - make more compatible with original Doom, by 104 * reintroducing this code. This means floors can't lower 105 * if objects are stuck in the ceiling */ 106 if ((flag == true) && comp[comp_floors]) { 107 sector->floorheight = lastpos; 108 P_ChangeSector(sector,crush); 109 return crushed; 110 } 111 } 112 break; 113 114 case 1: 115 // Moving a floor up 116 // jff 02/04/98 keep floor from moving thru ceilings 117 // jff 2/22/98 weaken check to demo_compatibility 118 destheight = (comp[comp_floors] || dest<sector->ceilingheight)? 119 dest : sector->ceilingheight; 120 if (sector->floorheight + speed > destheight) 121 { 122 lastpos = sector->floorheight; 123 sector->floorheight = destheight; 124 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 125 if (flag == true) 126 { 127 sector->floorheight = lastpos; 128 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 129 } 130 return pastdest; 131 } 132 else 133 { 134 // crushing is possible 135 lastpos = sector->floorheight; 136 sector->floorheight += speed; 137 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 138 if (flag == true) 139 { 140 /* jff 1/25/98 fix floor crusher */ 141 if (comp[comp_floors]) { 142 if (crush == true) 143 return crushed; 144 } 145 sector->floorheight = lastpos; 146 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 147 return crushed; 148 } 149 } 150 break; 151 } 152 break; 153 154 case 1: 155 // moving a ceiling 156 switch(direction) 157 { 158 case -1: 159 // moving a ceiling down 160 // jff 02/04/98 keep ceiling from moving thru floors 161 // jff 2/22/98 weaken check to demo_compatibility 162 destheight = (comp[comp_floors] || dest>sector->floorheight)? 163 dest : sector->floorheight; 164 if (sector->ceilingheight - speed < destheight) 165 { 166 lastpos = sector->ceilingheight; 167 sector->ceilingheight = destheight; 168 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 169 170 if (flag == true) 171 { 172 sector->ceilingheight = lastpos; 173 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 174 } 175 return pastdest; 176 } 177 else 178 { 179 // crushing is possible 180 lastpos = sector->ceilingheight; 181 sector->ceilingheight -= speed; 182 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 183 184 if (flag == true) 185 { 186 if (crush == true) 187 return crushed; 188 sector->ceilingheight = lastpos; 189 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 190 return crushed; 191 } 192 } 193 break; 194 195 case 1: 196 // moving a ceiling up 197 if (sector->ceilingheight + speed > dest) 198 { 199 lastpos = sector->ceilingheight; 200 sector->ceilingheight = dest; 201 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 202 if (flag == true) 203 { 204 sector->ceilingheight = lastpos; 205 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 206 } 207 return pastdest; 208 } 209 else 210 { 211 lastpos = sector->ceilingheight; 212 sector->ceilingheight += speed; 213 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk 214 } 215 break; 216 } 217 break; 218 } 219 return ok; 220} 221 222// 223// T_MoveFloor() 224// 225// Move a floor to it's destination (up or down). 226// Called once per tick for each moving floor. 227// 228// Passed a floormove_t structure that contains all pertinent info about the 229// move. See P_SPEC.H for fields. 230// No return. 231// 232// jff 02/08/98 all cases with labels beginning with gen added to support 233// generalized line type behaviors. 234void T_MoveFloor(floormove_t* floor) 235{ 236 result_e res; 237 238 res = T_MovePlane // move the floor 239 ( 240 floor->sector, 241 floor->speed, 242 floor->floordestheight, 243 floor->crush, 244 0, 245 floor->direction 246 ); 247 248 if (!(leveltime&7)) // make the floormove sound 249 S_StartSound((mobj_t *)&floor->sector->soundorg, sfx_stnmov); 250 251 if (res == pastdest) // if destination height is reached 252 { 253 if (floor->direction == 1) // going up 254 { 255 switch(floor->type) // handle texture/type changes 256 { 257 case donutRaise: 258 floor->sector->special = floor->newspecial; 259 floor->sector->floorpic = floor->texture; 260 break; 261 case genFloorChgT: 262 case genFloorChg0: 263 floor->sector->special = floor->newspecial; 264 //jff add to fix bug in special transfers from changes 265 floor->sector->oldspecial = floor->oldspecial; 266 //fall thru 267 case genFloorChg: 268 floor->sector->floorpic = floor->texture; 269 break; 270 default: 271 break; 272 } 273 } 274 else if (floor->direction == -1) // going down 275 { 276 switch(floor->type) // handle texture/type changes 277 { 278 case lowerAndChange: 279 floor->sector->special = floor->newspecial; 280 //jff add to fix bug in special transfers from changes 281 floor->sector->oldspecial = floor->oldspecial; 282 floor->sector->floorpic = floor->texture; 283 break; 284 case genFloorChgT: 285 case genFloorChg0: 286 floor->sector->special = floor->newspecial; 287 //jff add to fix bug in special transfers from changes 288 floor->sector->oldspecial = floor->oldspecial; 289 //fall thru 290 case genFloorChg: 291 floor->sector->floorpic = floor->texture; 292 break; 293 default: 294 break; 295 } 296 } 297 298 floor->sector->floordata = NULL; //jff 2/22/98 299 P_RemoveThinker(&floor->thinker);//remove this floor from list of movers 300 301 //jff 2/26/98 implement stair retrigger lockout while still building 302 // note this only applies to the retriggerable generalized stairs 303 304 if (floor->sector->stairlock==-2) // if this sector is stairlocked 305 { 306 sector_t *sec = floor->sector; 307 sec->stairlock=-1; // thinker done, promote lock to -1 308 309 while (sec->prevsec!=-1 && sectors[sec->prevsec].stairlock!=-2) 310 sec = &sectors[sec->prevsec]; // search for a non-done thinker 311 if (sec->prevsec==-1) // if all thinkers previous are done 312 { 313 sec = floor->sector; // search forward 314 while (sec->nextsec!=-1 && sectors[sec->nextsec].stairlock!=-2) 315 sec = &sectors[sec->nextsec]; 316 if (sec->nextsec==-1) // if all thinkers ahead are done too 317 { 318 while (sec->prevsec!=-1) // clear all locks 319 { 320 sec->stairlock = 0; 321 sec = &sectors[sec->prevsec]; 322 } 323 sec->stairlock = 0; 324 } 325 } 326 } 327 328 // make floor stop sound 329 S_StartSound((mobj_t *)&floor->sector->soundorg, sfx_pstop); 330 } 331} 332 333// 334// T_MoveElevator() 335// 336// Move an elevator to it's destination (up or down) 337// Called once per tick for each moving floor. 338// 339// Passed an elevator_t structure that contains all pertinent info about the 340// move. See P_SPEC.H for fields. 341// No return. 342// 343// jff 02/22/98 added to support parallel floor/ceiling motion 344// 345void T_MoveElevator(elevator_t* elevator) 346{ 347 result_e res; 348 349 if (elevator->direction<0) // moving down 350 { 351 res = T_MovePlane //jff 4/7/98 reverse order of ceiling/floor 352 ( 353 elevator->sector, 354 elevator->speed, 355 elevator->ceilingdestheight, 356 0, 357 1, // move floor 358 elevator->direction 359 ); 360 if (res==ok || res==pastdest) // jff 4/7/98 don't move ceil if blocked 361 T_MovePlane 362 ( 363 elevator->sector, 364 elevator->speed, 365 elevator->floordestheight, 366 0, 367 0, // move ceiling 368 elevator->direction 369 ); 370 } 371 else // up 372 { 373 res = T_MovePlane //jff 4/7/98 reverse order of ceiling/floor 374 ( 375 elevator->sector, 376 elevator->speed, 377 elevator->floordestheight, 378 0, 379 0, // move ceiling 380 elevator->direction 381 ); 382 if (res==ok || res==pastdest) // jff 4/7/98 don't move floor if blocked 383 T_MovePlane 384 ( 385 elevator->sector, 386 elevator->speed, 387 elevator->ceilingdestheight, 388 0, 389 1, // move floor 390 elevator->direction 391 ); 392 } 393 394 // make floor move sound 395 if (!(leveltime&7)) 396 S_StartSound((mobj_t *)&elevator->sector->soundorg, sfx_stnmov); 397 398 if (res == pastdest) // if destination height acheived 399 { 400 elevator->sector->floordata = NULL; //jff 2/22/98 401 elevator->sector->ceilingdata = NULL; //jff 2/22/98 402 P_RemoveThinker(&elevator->thinker); // remove elevator from actives 403 404 // make floor stop sound 405 S_StartSound((mobj_t *)&elevator->sector->soundorg, sfx_pstop); 406 } 407} 408 409/////////////////////////////////////////////////////////////////////// 410// 411// Floor motion linedef handlers 412// 413/////////////////////////////////////////////////////////////////////// 414 415// 416// EV_DoFloor() 417// 418// Handle regular and extended floor types 419// 420// Passed the line that activated the floor and the type of floor motion 421// Returns true if a thinker was created. 422// 423int EV_DoFloor 424( line_t* line, 425 floor_e floortype ) 426{ 427 int secnum; 428 int rtn; 429 int i; 430 sector_t* sec; 431 floormove_t* floor; 432 433 secnum = -1; 434 rtn = 0; 435 // move all floors with the same tag as the linedef 436 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 437 { 438 sec = &sectors[secnum]; 439 440 // Don't start a second thinker on the same floor 441 if (P_SectorActive(floor_special,sec)) //jff 2/23/98 442 continue; 443 444 // new floor thinker 445 rtn = 1; 446 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); 447 P_AddThinker (&floor->thinker); 448 sec->floordata = floor; //jff 2/22/98 449 floor->thinker.function = T_MoveFloor; 450 floor->type = floortype; 451 floor->crush = false; 452 453 // setup the thinker according to the linedef type 454 switch(floortype) 455 { 456 case lowerFloor: 457 floor->direction = -1; 458 floor->sector = sec; 459 floor->speed = FLOORSPEED; 460 floor->floordestheight = P_FindHighestFloorSurrounding(sec); 461 break; 462 463 //jff 02/03/30 support lowering floor by 24 absolute 464 case lowerFloor24: 465 floor->direction = -1; 466 floor->sector = sec; 467 floor->speed = FLOORSPEED; 468 floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT; 469 break; 470 471 //jff 02/03/30 support lowering floor by 32 absolute (fast) 472 case lowerFloor32Turbo: 473 floor->direction = -1; 474 floor->sector = sec; 475 floor->speed = FLOORSPEED*4; 476 floor->floordestheight = floor->sector->floorheight + 32 * FRACUNIT; 477 break; 478 479 case lowerFloorToLowest: 480 floor->direction = -1; 481 floor->sector = sec; 482 floor->speed = FLOORSPEED; 483 floor->floordestheight = P_FindLowestFloorSurrounding(sec); 484 break; 485 486 //jff 02/03/30 support lowering floor to next lowest floor 487 case lowerFloorToNearest: 488 floor->direction = -1; 489 floor->sector = sec; 490 floor->speed = FLOORSPEED; 491 floor->floordestheight = 492 P_FindNextLowestFloor(sec,floor->sector->floorheight); 493 break; 494 495 case turboLower: 496 floor->direction = -1; 497 floor->sector = sec; 498 floor->speed = FLOORSPEED * 4; 499 floor->floordestheight = P_FindHighestFloorSurrounding(sec); 500 if (floor->floordestheight != sec->floorheight) 501 floor->floordestheight += 8*FRACUNIT; 502 break; 503 504 case raiseFloorCrush: 505 floor->crush = true; 506 /* fallthrough */ 507 case raiseFloor: 508 floor->direction = 1; 509 floor->sector = sec; 510 floor->speed = FLOORSPEED; 511 floor->floordestheight = P_FindLowestCeilingSurrounding(sec); 512 if (floor->floordestheight > sec->ceilingheight) 513 floor->floordestheight = sec->ceilingheight; 514 floor->floordestheight -= (8*FRACUNIT)*(floortype == raiseFloorCrush); 515 break; 516 517 case raiseFloorTurbo: 518 floor->direction = 1; 519 floor->sector = sec; 520 floor->speed = FLOORSPEED*4; 521 floor->floordestheight = P_FindNextHighestFloor(sec,sec->floorheight); 522 break; 523 524 case raiseFloorToNearest: 525 floor->direction = 1; 526 floor->sector = sec; 527 floor->speed = FLOORSPEED; 528 floor->floordestheight = P_FindNextHighestFloor(sec,sec->floorheight); 529 break; 530 531 case raiseFloor24: 532 floor->direction = 1; 533 floor->sector = sec; 534 floor->speed = FLOORSPEED; 535 floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT; 536 break; 537 538 // jff 2/03/30 support straight raise by 32 (fast) 539 case raiseFloor32Turbo: 540 floor->direction = 1; 541 floor->sector = sec; 542 floor->speed = FLOORSPEED*4; 543 floor->floordestheight = floor->sector->floorheight + 32 * FRACUNIT; 544 break; 545 546 case raiseFloor512: 547 floor->direction = 1; 548 floor->sector = sec; 549 floor->speed = FLOORSPEED; 550 floor->floordestheight = floor->sector->floorheight + 512 * FRACUNIT; 551 break; 552 553 case raiseFloor24AndChange: 554 floor->direction = 1; 555 floor->sector = sec; 556 floor->speed = FLOORSPEED; 557 floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT; 558 sec->floorpic = line->frontsector->floorpic; 559 sec->special = line->frontsector->special; 560 //jff 3/14/98 transfer both old and new special 561 sec->oldspecial = line->frontsector->oldspecial; 562 break; 563 564 case raiseToTexture: 565 { 566 int minsize = INT_MAX; 567 side_t* side; 568 569 /* jff 3/13/98 no ovf */ 570 if (!comp[comp_model]) minsize = 32000<<FRACBITS; 571 floor->direction = 1; 572 floor->sector = sec; 573 floor->speed = FLOORSPEED; 574 for (i = 0; i < sec->linecount; i++) 575 { 576 if (twoSided (secnum, i) ) 577 { 578 side = getSide(secnum,i,0); 579 // jff 8/14/98 don't scan texture 0, its not real 580 if (side->bottomtexture > 0 || 581 (comp[comp_model] && !side->bottomtexture)) 582 if (textureheight[side->bottomtexture] < minsize) 583 minsize = textureheight[side->bottomtexture]; 584 side = getSide(secnum,i,1); 585 // jff 8/14/98 don't scan texture 0, its not real 586 if (side->bottomtexture > 0 || 587 (comp[comp_model] && !side->bottomtexture)) 588 if (textureheight[side->bottomtexture] < minsize) 589 minsize = textureheight[side->bottomtexture]; 590 } 591 } 592 if (comp[comp_model]) 593 floor->floordestheight = floor->sector->floorheight + minsize; 594 else 595 { 596 floor->floordestheight = 597 (floor->sector->floorheight>>FRACBITS) + (minsize>>FRACBITS); 598 if (floor->floordestheight>32000) 599 floor->floordestheight = 32000; //jff 3/13/98 do not 600 floor->floordestheight<<=FRACBITS; // allow height overflow 601 } 602 } 603 break; 604 605 case lowerAndChange: 606 floor->direction = -1; 607 floor->sector = sec; 608 floor->speed = FLOORSPEED; 609 floor->floordestheight = P_FindLowestFloorSurrounding(sec); 610 floor->texture = sec->floorpic; 611 612 // jff 1/24/98 make sure floor->newspecial gets initialized 613 // in case no surrounding sector is at floordestheight 614 // --> should not affect compatibility <-- 615 floor->newspecial = sec->special; 616 //jff 3/14/98 transfer both old and new special 617 floor->oldspecial = sec->oldspecial; 618 619 //jff 5/23/98 use model subroutine to unify fixes and handling 620 sec = P_FindModelFloorSector(floor->floordestheight,sec-sectors); 621 if (sec) 622 { 623 floor->texture = sec->floorpic; 624 floor->newspecial = sec->special; 625 //jff 3/14/98 transfer both old and new special 626 floor->oldspecial = sec->oldspecial; 627 } 628 break; 629 default: 630 break; 631 } 632 } 633 return rtn; 634} 635 636// 637// EV_DoChange() 638// 639// Handle pure change types. These change floor texture and sector type 640// by trigger or numeric model without moving the floor. 641// 642// The linedef causing the change and the type of change is passed 643// Returns true if any sector changes 644// 645// jff 3/15/98 added to better support generalized sector types 646// 647int EV_DoChange 648( line_t* line, 649 change_e changetype ) 650{ 651 int secnum; 652 int rtn; 653 sector_t* sec; 654 sector_t* secm; 655 656 secnum = -1; 657 rtn = 0; 658 // change all sectors with the same tag as the linedef 659 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 660 { 661 sec = &sectors[secnum]; 662 663 rtn = 1; 664 665 // handle trigger or numeric change type 666 switch(changetype) 667 { 668 case trigChangeOnly: 669 sec->floorpic = line->frontsector->floorpic; 670 sec->special = line->frontsector->special; 671 sec->oldspecial = line->frontsector->oldspecial; 672 break; 673 case numChangeOnly: 674 secm = P_FindModelFloorSector(sec->floorheight,secnum); 675 if (secm) // if no model, no change 676 { 677 sec->floorpic = secm->floorpic; 678 sec->special = secm->special; 679 sec->oldspecial = secm->oldspecial; 680 } 681 break; 682 default: 683 break; 684 } 685 } 686 return rtn; 687} 688 689/* 690 * EV_BuildStairs() 691 * 692 * Handles staircase building. A sequence of sectors chosen by algorithm 693 * rise at a speed indicated to a height that increases by the stepsize 694 * each step. 695 * 696 * Passed the linedef triggering the stairs and the type of stair rise 697 * Returns true if any thinkers are created 698 * 699 * cph 2001/09/21 - compatibility nightmares again 700 * There are three different ways this function has, during its history, stepped 701 * through all the stairs to be triggered by the single switch 702 * - original Doom used a linear P_FindSectorFromLineTag, but failed to preserve 703 * the index of the previous sector found, so instead it would restart its 704 * linear search from the last sector of the previous staircase 705 * - MBF/PrBoom with comp_stairs fail to emulate this, because their 706 * P_FindSectorFromLineTag is a chained hash table implementation. Instead they 707 * start following the hash chain from the last sector of the previous 708 * staircase, which will (probably) have the wrong tag, so they miss any further 709 * stairs 710 * - Boom fixed the bug, and MBF/PrBoom without comp_stairs work right 711 */ 712static inline int P_FindSectorFromLineTagWithLowerBound 713(line_t* l, int start, int min) 714{ 715 /* Emulate original Doom's linear lower-bounded P_FindSectorFromLineTag 716 * as needed */ 717 do { 718 start = P_FindSectorFromLineTag(l,start); 719 } while (start >= 0 && start <= min); 720 return start; 721} 722 723int EV_BuildStairs 724( line_t* line, 725 stair_e type ) 726{ 727 /* cph 2001/09/22 - cleaned up this function to save my sanity. A separate 728 * outer loop index makes the logic much cleared, and local variables moved 729 * into the inner blocks helps too */ 730 int ssec = -1; 731 int minssec = -1; 732 int rtn = 0; 733 734 // start a stair at each sector tagged the same as the linedef 735 while ((ssec = P_FindSectorFromLineTagWithLowerBound(line,ssec,minssec)) >= 0) 736 { 737 int secnum = ssec; 738 sector_t* sec = &sectors[secnum]; 739 740 // don't start a stair if the first step's floor is already moving 741 if (!P_SectorActive(floor_special,sec)) { //jff 2/22/98 742 floormove_t* floor; 743 int texture, height; 744 fixed_t stairsize; 745 fixed_t speed; 746 int ok; 747 748 // create new floor thinker for first step 749 rtn = 1; 750 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); 751 P_AddThinker (&floor->thinker); 752 sec->floordata = floor; 753 floor->thinker.function = T_MoveFloor; 754 floor->direction = 1; 755 floor->sector = sec; 756 floor->type = buildStair; //jff 3/31/98 do not leave uninited 757 758 // set up the speed and stepsize according to the stairs type 759 switch(type) 760 { 761 default: // killough -- prevent compiler warning 762 case build8: 763 speed = FLOORSPEED/4; 764 stairsize = 8*FRACUNIT; 765 if (!demo_compatibility) 766 floor->crush = false; //jff 2/27/98 fix uninitialized crush field 767 break; 768 case turbo16: 769 speed = FLOORSPEED*4; 770 stairsize = 16*FRACUNIT; 771 if (!demo_compatibility) 772 floor->crush = true; //jff 2/27/98 fix uninitialized crush field 773 break; 774 } 775 floor->speed = speed; 776 height = sec->floorheight + stairsize; 777 floor->floordestheight = height; 778 779 texture = sec->floorpic; 780 781 // Find next sector to raise 782 // 1. Find 2-sided line with same sector side[0] (lowest numbered) 783 // 2. Other side is the next sector to raise 784 // 3. Unless already moving, or different texture, then stop building 785 do 786 { 787 int i; 788 ok = 0; 789 790 for (i = 0;i < sec->linecount;i++) 791 { 792 sector_t* tsec = (sec->lines[i])->frontsector; 793 int newsecnum; 794 if ( !((sec->lines[i])->flags & ML_TWOSIDED) ) 795 continue; 796 797 newsecnum = tsec-sectors; 798 799 if (secnum != newsecnum) 800 continue; 801 802 tsec = (sec->lines[i])->backsector; 803 if (!tsec) continue; //jff 5/7/98 if no backside, continue 804 newsecnum = tsec - sectors; 805 806 // if sector's floor is different texture, look for another 807 if (tsec->floorpic != texture) 808 continue; 809 810 /* jff 6/19/98 prevent double stepsize 811 * killough 10/98: intentionally left this way [MBF comment] 812 * cph 2001/02/06: stair bug fix should be controlled by comp_stairs, 813 * except if we're emulating MBF which perversly reverted the fix 814 */ 815 if (comp[comp_stairs] || (compatibility_level == mbf_compatibility)) 816 height += stairsize; // jff 6/28/98 change demo compatibility 817 818 // if sector's floor already moving, look for another 819 if (P_SectorActive(floor_special,tsec)) //jff 2/22/98 820 continue; 821 822 /* cph - see comment above - do this iff we didn't do so above */ 823 if (!comp[comp_stairs] && (compatibility_level != mbf_compatibility)) 824 height += stairsize; 825 826 sec = tsec; 827 secnum = newsecnum; 828 829 // create and initialize a thinker for the next step 830 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); 831 P_AddThinker (&floor->thinker); 832 833 sec->floordata = floor; //jff 2/22/98 834 floor->thinker.function = T_MoveFloor; 835 floor->direction = 1; 836 floor->sector = sec; 837 floor->speed = speed; 838 floor->floordestheight = height; 839 floor->type = buildStair; //jff 3/31/98 do not leave uninited 840 //jff 2/27/98 fix uninitialized crush field 841 if (!demo_compatibility) 842 floor->crush = type==build8? false : true; 843 ok = 1; 844 break; 845 } 846 } while(ok); // continue until no next step is found 847 848 } 849 /* killough 10/98: compatibility option */ 850 if (comp[comp_stairs]) { 851 /* cph 2001/09/22 - emulate buggy MBF comp_stairs for demos, with logic 852 * reversed since we now have a separate outer loop index. 853 * DEMOSYNC - what about boom_compatibility_compatibility? 854 */ 855 if ((compatibility_level >= mbf_compatibility) && (compatibility_level < 856 prboom_3_compatibility)) ssec = secnum; /* Trash outer loop index */ 857 else { 858 /* cph 2001/09/22 - now the correct comp_stairs - Doom used a linear 859 * search from the last secnum, so we set that as a minimum value and do 860 * a fresh tag search 861 */ 862 ssec = -1; minssec = secnum; 863 } 864 } 865 } 866 return rtn; 867} 868 869// 870// EV_DoDonut() 871// 872// Handle donut function: lower pillar, raise surrounding pool, both to height, 873// texture and type of the sector surrounding the pool. 874// 875// Passed the linedef that triggered the donut 876// Returns whether a thinker was created 877// 878int EV_DoDonut(line_t* line) 879{ 880 sector_t* s1; 881 sector_t* s2; 882 sector_t* s3; 883 int secnum; 884 int rtn; 885 int i; 886 floormove_t* floor; 887 888 secnum = -1; 889 rtn = 0; 890 // do function on all sectors with same tag as linedef 891 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 892 { 893 s1 = &sectors[secnum]; // s1 is pillar's sector 894 895 // do not start the donut if the pillar is already moving 896 if (P_SectorActive(floor_special,s1)) //jff 2/22/98 897 continue; 898 899 s2 = getNextSector(s1->lines[0],s1); // s2 is pool's sector 900 if (!s2) continue; // note lowest numbered line around 901 // pillar must be two-sided 902 903 /* do not start the donut if the pool is already moving 904 * cph - DEMOSYNC - was !compatibility */ 905 if (!comp[comp_floors] && P_SectorActive(floor_special,s2)) 906 continue; //jff 5/7/98 907 908 // find a two sided line around the pool whose other side isn't the pillar 909 for (i = 0;i < s2->linecount;i++) 910 { 911 //jff 3/29/98 use true two-sidedness, not the flag 912 // killough 4/5/98: changed demo_compatibility to compatibility 913 if (comp[comp_model]) 914 { 915 if (!(s2->lines[i]->flags & ML_TWOSIDED) || 916 (s2->lines[i]->backsector == s1)) 917 continue; 918 } 919 else if (!s2->lines[i]->backsector || s2->lines[i]->backsector == s1) 920 continue; 921 922 rtn = 1; //jff 1/26/98 no donut action - no switch change on return 923 924 s3 = s2->lines[i]->backsector; // s3 is model sector for changes 925 926 // Spawn rising slime 927 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); 928 P_AddThinker (&floor->thinker); 929 s2->floordata = floor; //jff 2/22/98 930 floor->thinker.function = T_MoveFloor; 931 floor->type = donutRaise; 932 floor->crush = false; 933 floor->direction = 1; 934 floor->sector = s2; 935 floor->speed = FLOORSPEED / 2; 936 floor->texture = s3->floorpic; 937 floor->newspecial = 0; 938 floor->floordestheight = s3->floorheight; 939 940 // Spawn lowering donut-hole pillar 941 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); 942 P_AddThinker (&floor->thinker); 943 s1->floordata = floor; //jff 2/22/98 944 floor->thinker.function = T_MoveFloor; 945 floor->type = lowerFloor; 946 floor->crush = false; 947 floor->direction = -1; 948 floor->sector = s1; 949 floor->speed = FLOORSPEED / 2; 950 floor->floordestheight = s3->floorheight; 951 break; 952 } 953 } 954 return rtn; 955} 956 957// 958// EV_DoElevator 959// 960// Handle elevator linedef types 961// 962// Passed the linedef that triggered the elevator and the elevator action 963// 964// jff 2/22/98 new type to move floor and ceiling in parallel 965// 966int EV_DoElevator 967( line_t* line, 968 elevator_e elevtype ) 969{ 970 int secnum; 971 int rtn; 972 sector_t* sec; 973 elevator_t* elevator; 974 975 secnum = -1; 976 rtn = 0; 977 // act on all sectors with the same tag as the triggering linedef 978 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 979 { 980 sec = &sectors[secnum]; 981 982 // If either floor or ceiling is already activated, skip it 983 if (sec->floordata || sec->ceilingdata) //jff 2/22/98 984 continue; 985 986 // create and initialize new elevator thinker 987 rtn = 1; 988 elevator = Z_Malloc (sizeof(*elevator), PU_LEVSPEC, 0); 989 P_AddThinker (&elevator->thinker); 990 sec->floordata = elevator; //jff 2/22/98 991 sec->ceilingdata = elevator; //jff 2/22/98 992 elevator->thinker.function = T_MoveElevator; 993 elevator->type = elevtype; 994 995 // set up the fields according to the type of elevator action 996 switch(elevtype) 997 { 998 // elevator down to next floor 999 case elevateDown: 1000 elevator->direction = -1; 1001 elevator->sector = sec; 1002 elevator->speed = ELEVATORSPEED; 1003 elevator->floordestheight = 1004 P_FindNextLowestFloor(sec,sec->floorheight); 1005 elevator->ceilingdestheight = 1006 elevator->floordestheight + sec->ceilingheight - sec->floorheight; 1007 break; 1008 1009 // elevator up to next floor 1010 case elevateUp: 1011 elevator->direction = 1; 1012 elevator->sector = sec; 1013 elevator->speed = ELEVATORSPEED; 1014 elevator->floordestheight = 1015 P_FindNextHighestFloor(sec,sec->floorheight); 1016 elevator->ceilingdestheight = 1017 elevator->floordestheight + sec->ceilingheight - sec->floorheight; 1018 break; 1019 1020 // elevator to floor height of activating switch's front sector 1021 case elevateCurrent: 1022 elevator->sector = sec; 1023 elevator->speed = ELEVATORSPEED; 1024 elevator->floordestheight = line->frontsector->floorheight; 1025 elevator->ceilingdestheight = 1026 elevator->floordestheight + sec->ceilingheight - sec->floorheight; 1027 elevator->direction = 1028 elevator->floordestheight>sec->floorheight? 1 : -1; 1029 break; 1030 1031 default: 1032 break; 1033 } 1034 } 1035 return rtn; 1036}