p_floor.cpp (12415B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #include "Precompiled.h" 30 #include "globaldata.h" 31 32 33 #include "z_zone.h" 34 #include "doomdef.h" 35 #include "p_local.h" 36 37 #include "s_sound.h" 38 39 // State. 40 #include "doomstat.h" 41 #include "r_state.h" 42 // Data. 43 #include "sounds.h" 44 45 46 // 47 // FLOORS 48 // 49 50 // 51 // Move a plane (floor or ceiling) and check for crushing 52 // 53 result_e 54 T_MovePlane 55 ( sector_t* sector, 56 fixed_t speed, 57 fixed_t dest, 58 qboolean crush, 59 int floorOrCeiling, 60 int direction ) 61 { 62 qboolean flag; 63 fixed_t lastpos; 64 65 switch(floorOrCeiling) 66 { 67 case 0: 68 // FLOOR 69 switch(direction) 70 { 71 case -1: 72 // DOWN 73 if (sector->floorheight - speed < dest) 74 { 75 lastpos = sector->floorheight; 76 sector->floorheight = dest; 77 flag = P_ChangeSector(sector,crush); 78 if (flag == true) 79 { 80 sector->floorheight =lastpos; 81 P_ChangeSector(sector,crush); 82 //return crushed; 83 } 84 return pastdest; 85 } 86 else 87 { 88 lastpos = sector->floorheight; 89 sector->floorheight -= speed; 90 flag = P_ChangeSector(sector,crush); 91 if (flag == true) 92 { 93 sector->floorheight = lastpos; 94 P_ChangeSector(sector,crush); 95 return crushed; 96 } 97 } 98 break; 99 100 case 1: 101 // UP 102 if (sector->floorheight + speed > dest) 103 { 104 lastpos = sector->floorheight; 105 sector->floorheight = dest; 106 flag = P_ChangeSector(sector,crush); 107 if (flag == true) 108 { 109 sector->floorheight = lastpos; 110 P_ChangeSector(sector,crush); 111 //return crushed; 112 } 113 return pastdest; 114 } 115 else 116 { 117 // COULD GET CRUSHED 118 lastpos = sector->floorheight; 119 sector->floorheight += speed; 120 flag = P_ChangeSector(sector,crush); 121 if (flag == true) 122 { 123 if (crush == true) 124 return crushed; 125 sector->floorheight = lastpos; 126 P_ChangeSector(sector,crush); 127 return crushed; 128 } 129 } 130 break; 131 } 132 break; 133 134 case 1: 135 // CEILING 136 switch(direction) 137 { 138 case -1: 139 // DOWN 140 if (sector->ceilingheight - speed < dest) 141 { 142 lastpos = sector->ceilingheight; 143 sector->ceilingheight = dest; 144 flag = P_ChangeSector(sector,crush); 145 146 if (flag == true) 147 { 148 sector->ceilingheight = lastpos; 149 P_ChangeSector(sector,crush); 150 //return crushed; 151 } 152 return pastdest; 153 } 154 else 155 { 156 // COULD GET CRUSHED 157 lastpos = sector->ceilingheight; 158 sector->ceilingheight -= speed; 159 flag = P_ChangeSector(sector,crush); 160 161 if (flag == true) 162 { 163 if (crush == true) 164 return crushed; 165 sector->ceilingheight = lastpos; 166 P_ChangeSector(sector,crush); 167 return crushed; 168 } 169 } 170 break; 171 172 case 1: 173 // UP 174 if (sector->ceilingheight + speed > dest) 175 { 176 lastpos = sector->ceilingheight; 177 sector->ceilingheight = dest; 178 flag = P_ChangeSector(sector,crush); 179 if (flag == true) 180 { 181 sector->ceilingheight = lastpos; 182 P_ChangeSector(sector,crush); 183 //return crushed; 184 } 185 return pastdest; 186 } 187 else 188 { 189 lastpos = sector->ceilingheight; 190 sector->ceilingheight += speed; 191 flag = P_ChangeSector(sector,crush); 192 // UNUSED 193 #if 0 194 if (flag == true) 195 { 196 sector->ceilingheight = lastpos; 197 P_ChangeSector(sector,crush); 198 return crushed; 199 } 200 #endif 201 } 202 break; 203 } 204 break; 205 206 } 207 return ok; 208 } 209 210 211 // 212 // MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) 213 // 214 void T_MoveFloor(floormove_t* floor) 215 { 216 result_e res; 217 218 res = T_MovePlane(floor->sector, 219 floor->speed, 220 floor->floordestheight, 221 floor->crush,0,floor->direction); 222 223 if (!(::g->leveltime&7)) 224 S_StartSound( &floor->sector->soundorg, 225 sfx_stnmov); 226 227 if (res == pastdest) 228 { 229 floor->sector->specialdata = NULL; 230 231 if (floor->direction == 1) 232 { 233 switch(floor->type) 234 { 235 case donutRaise: 236 floor->sector->special = floor->newspecial; 237 floor->sector->floorpic = floor->texture; 238 default: 239 break; 240 } 241 } 242 else if (floor->direction == -1) 243 { 244 switch(floor->type) 245 { 246 case lowerAndChange: 247 floor->sector->special = floor->newspecial; 248 floor->sector->floorpic = floor->texture; 249 default: 250 break; 251 } 252 } 253 P_RemoveThinker(&floor->thinker); 254 255 S_StartSound( &floor->sector->soundorg, 256 sfx_pstop); 257 } 258 259 } 260 261 // 262 // HANDLE FLOOR TYPES 263 // 264 int 265 EV_DoFloor 266 ( line_t* line, 267 floor_e floortype ) 268 { 269 int secnum; 270 int rtn; 271 int i; 272 sector_t* sec; 273 floormove_t* floor; 274 275 secnum = -1; 276 rtn = 0; 277 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 278 { 279 sec = &::g->sectors[secnum]; 280 281 // ALREADY MOVING? IF SO, KEEP GOING... 282 if (sec->specialdata) 283 continue; 284 285 // new floor thinker 286 rtn = 1; 287 floor = (floormove_t*)DoomLib::Z_Malloc(sizeof(*floor), PU_LEVEL, 0); 288 P_AddThinker (&floor->thinker); 289 sec->specialdata = floor; 290 floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; 291 floor->type = floortype; 292 floor->crush = false; 293 294 switch(floortype) 295 { 296 case lowerFloor: 297 floor->direction = -1; 298 floor->sector = sec; 299 floor->speed = FLOORSPEED; 300 floor->floordestheight = 301 P_FindHighestFloorSurrounding(sec); 302 break; 303 304 case lowerFloorToLowest: 305 floor->direction = -1; 306 floor->sector = sec; 307 floor->speed = FLOORSPEED; 308 floor->floordestheight = 309 P_FindLowestFloorSurrounding(sec); 310 break; 311 312 case turboLower: 313 floor->direction = -1; 314 floor->sector = sec; 315 floor->speed = FLOORSPEED * 4; 316 floor->floordestheight = 317 P_FindHighestFloorSurrounding(sec); 318 if (floor->floordestheight != sec->floorheight) 319 floor->floordestheight += 8*FRACUNIT; 320 break; 321 322 case raiseFloorCrush: 323 floor->crush = true; 324 case raiseFloor: 325 floor->direction = 1; 326 floor->sector = sec; 327 floor->speed = FLOORSPEED; 328 floor->floordestheight = 329 P_FindLowestCeilingSurrounding(sec); 330 if (floor->floordestheight > sec->ceilingheight) 331 floor->floordestheight = sec->ceilingheight; 332 floor->floordestheight -= (8*FRACUNIT)* 333 (floortype == raiseFloorCrush); 334 break; 335 336 case raiseFloorTurbo: 337 floor->direction = 1; 338 floor->sector = sec; 339 floor->speed = FLOORSPEED*4; 340 floor->floordestheight = 341 P_FindNextHighestFloor(sec,sec->floorheight); 342 break; 343 344 case raiseFloorToNearest: 345 floor->direction = 1; 346 floor->sector = sec; 347 floor->speed = FLOORSPEED; 348 floor->floordestheight = 349 P_FindNextHighestFloor(sec,sec->floorheight); 350 break; 351 352 case raiseFloor24: 353 floor->direction = 1; 354 floor->sector = sec; 355 floor->speed = FLOORSPEED; 356 floor->floordestheight = floor->sector->floorheight + 357 24 * FRACUNIT; 358 break; 359 case raiseFloor512: 360 floor->direction = 1; 361 floor->sector = sec; 362 floor->speed = FLOORSPEED; 363 floor->floordestheight = floor->sector->floorheight + 364 512 * FRACUNIT; 365 break; 366 367 case raiseFloor24AndChange: 368 floor->direction = 1; 369 floor->sector = sec; 370 floor->speed = FLOORSPEED; 371 floor->floordestheight = floor->sector->floorheight + 372 24 * FRACUNIT; 373 sec->floorpic = line->frontsector->floorpic; 374 sec->special = line->frontsector->special; 375 break; 376 377 case raiseToTexture: 378 { 379 int minsize = MAXINT; 380 side_t* side; 381 382 floor->direction = 1; 383 floor->sector = sec; 384 floor->speed = FLOORSPEED; 385 for (i = 0; i < sec->linecount; i++) 386 { 387 if (twoSided (secnum, i) ) 388 { 389 side = getSide(secnum,i,0); 390 if (side->bottomtexture >= 0) 391 if (::g->s_textureheight[side->bottomtexture] < 392 minsize) 393 minsize = 394 ::g->s_textureheight[side->bottomtexture]; 395 side = getSide(secnum,i,1); 396 if (side->bottomtexture >= 0) 397 if (::g->s_textureheight[side->bottomtexture] < 398 minsize) 399 minsize = 400 ::g->s_textureheight[side->bottomtexture]; 401 } 402 } 403 floor->floordestheight = 404 floor->sector->floorheight + minsize; 405 } 406 break; 407 408 case lowerAndChange: 409 floor->direction = -1; 410 floor->sector = sec; 411 floor->speed = FLOORSPEED; 412 floor->floordestheight = 413 P_FindLowestFloorSurrounding(sec); 414 floor->texture = sec->floorpic; 415 416 for (i = 0; i < sec->linecount; i++) 417 { 418 if ( twoSided(secnum, i) ) 419 { 420 if (getSide(secnum,i,0)->sector-::g->sectors == secnum) 421 { 422 sec = getSector(secnum,i,1); 423 424 if (sec->floorheight == floor->floordestheight) 425 { 426 floor->texture = sec->floorpic; 427 floor->newspecial = sec->special; 428 break; 429 } 430 } 431 else 432 { 433 sec = getSector(secnum,i,0); 434 435 if (sec->floorheight == floor->floordestheight) 436 { 437 floor->texture = sec->floorpic; 438 floor->newspecial = sec->special; 439 break; 440 } 441 } 442 } 443 } 444 default: 445 break; 446 } 447 } 448 return rtn; 449 } 450 451 452 453 454 // 455 // BUILD A STAIRCASE! 456 // 457 int 458 EV_BuildStairs 459 ( line_t* line, 460 stair_e type ) 461 { 462 int secnum; 463 int height; 464 int i; 465 int newsecnum; 466 int texture; 467 int ok; 468 int rtn; 469 470 sector_t* sec; 471 sector_t* tsec; 472 473 floormove_t* floor; 474 475 fixed_t stairsize = 0; 476 fixed_t speed = 0; 477 478 secnum = -1; 479 rtn = 0; 480 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 481 { 482 sec = &::g->sectors[secnum]; 483 484 // ALREADY MOVING? IF SO, KEEP GOING... 485 if (sec->specialdata) 486 continue; 487 488 // new floor thinker 489 rtn = 1; 490 floor = (floormove_t*)DoomLib::Z_Malloc(sizeof(*floor), PU_LEVEL, 0); 491 P_AddThinker (&floor->thinker); 492 sec->specialdata = floor; 493 floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; 494 floor->direction = 1; 495 floor->sector = sec; 496 switch(type) 497 { 498 case build8: 499 speed = FLOORSPEED/4; 500 stairsize = 8*FRACUNIT; 501 break; 502 case turbo16: 503 speed = FLOORSPEED*4; 504 stairsize = 16*FRACUNIT; 505 break; 506 } 507 floor->speed = speed; 508 height = sec->floorheight + stairsize; 509 floor->floordestheight = height; 510 511 texture = sec->floorpic; 512 513 // Find next sector to raise 514 // 1. Find 2-sided line with same sector side[0] 515 // 2. Other side is the next sector to raise 516 do 517 { 518 ok = 0; 519 for (i = 0;i < sec->linecount;i++) 520 { 521 if ( !((sec->lines[i])->flags & ML_TWOSIDED) ) 522 continue; 523 524 tsec = (sec->lines[i])->frontsector; 525 newsecnum = tsec-::g->sectors; 526 527 if (secnum != newsecnum) 528 continue; 529 530 tsec = (sec->lines[i])->backsector; 531 newsecnum = tsec - ::g->sectors; 532 533 if (tsec->floorpic != texture) 534 continue; 535 536 height += stairsize; 537 538 if (tsec->specialdata) 539 continue; 540 541 sec = tsec; 542 secnum = newsecnum; 543 floor = (floormove_t*)DoomLib::Z_Malloc(sizeof(*floor), PU_LEVEL, 0); 544 545 P_AddThinker (&floor->thinker); 546 547 sec->specialdata = floor; 548 floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; 549 floor->direction = 1; 550 floor->sector = sec; 551 floor->speed = speed; 552 floor->floordestheight = height; 553 ok = 1; 554 break; 555 } 556 } while(ok); 557 } 558 return rtn; 559 } 560 561