p_doors.cpp (11785B)
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 40 // State. 41 #include "doomstat.h" 42 #include "r_state.h" 43 44 // Data. 45 #include "dstrings.h" 46 #include "sounds.h" 47 48 49 extern bool globalNetworking; 50 51 // 52 // VERTICAL DOORS 53 // 54 55 // 56 // T_VerticalDoor 57 // 58 void T_VerticalDoor (vldoor_t* door) 59 { 60 result_e res; 61 62 switch(door->direction) 63 { 64 case 0: 65 // WAITING 66 if (!--door->topcountdown) 67 { 68 switch(door->type) 69 { 70 case blazeRaise: 71 door->direction = -1; // time to go back down 72 S_StartSound( &door->sector->soundorg, 73 sfx_bdcls); 74 break; 75 76 case normal: 77 door->direction = -1; // time to go back down 78 S_StartSound( &door->sector->soundorg, 79 sfx_dorcls); 80 break; 81 82 case close30ThenOpen: 83 door->direction = 1; 84 S_StartSound( &door->sector->soundorg, 85 sfx_doropn); 86 break; 87 88 default: 89 break; 90 } 91 } 92 break; 93 94 case 2: 95 // INITIAL WAIT 96 if (!--door->topcountdown) 97 { 98 switch(door->type) 99 { 100 case raiseIn5Mins: 101 door->direction = 1; 102 door->type = normal; 103 S_StartSound( &door->sector->soundorg, 104 sfx_doropn); 105 break; 106 107 default: 108 break; 109 } 110 } 111 break; 112 113 case -1: 114 // DOWN 115 res = T_MovePlane(door->sector, 116 door->speed, 117 door->sector->floorheight, 118 false,1,door->direction); 119 if (res == pastdest) 120 { 121 switch(door->type) 122 { 123 case blazeRaise: 124 case blazeClose: 125 door->sector->specialdata = NULL; 126 P_RemoveThinker (&door->thinker); // unlink and free 127 S_StartSound( &door->sector->soundorg, 128 sfx_bdcls); 129 break; 130 131 case normal: 132 case closed: 133 door->sector->specialdata = NULL; 134 P_RemoveThinker (&door->thinker); // unlink and free 135 break; 136 137 case close30ThenOpen: 138 door->direction = 0; 139 door->topcountdown = TICRATE*30; 140 break; 141 142 default: 143 break; 144 } 145 } 146 else if (res == crushed) 147 { 148 switch(door->type) 149 { 150 case blazeClose: 151 case closed: // DO NOT GO BACK UP! 152 break; 153 154 default: 155 door->direction = 1; 156 S_StartSound( &door->sector->soundorg, 157 sfx_doropn); 158 break; 159 } 160 } 161 break; 162 163 case 1: 164 // UP 165 res = T_MovePlane(door->sector, 166 door->speed, 167 door->topheight, 168 false,1,door->direction); 169 170 if (res == pastdest) 171 { 172 switch(door->type) 173 { 174 case blazeRaise: 175 case normal: 176 door->direction = 0; // wait at top 177 door->topcountdown = door->topwait; 178 break; 179 180 case close30ThenOpen: 181 case blazeOpen: 182 case opened: 183 door->sector->specialdata = NULL; 184 P_RemoveThinker (&door->thinker); // unlink and free 185 break; 186 187 default: 188 break; 189 } 190 } 191 break; 192 } 193 } 194 195 196 // 197 // EV_DoLockedDoor 198 // Move a locked door up/down 199 // 200 201 int 202 EV_DoLockedDoor 203 ( line_t* line, 204 vldoor_e type, 205 mobj_t* thing ) 206 { 207 player_t* p; 208 209 p = thing->player; 210 211 if (!p) 212 return 0; 213 214 switch(line->special) 215 { 216 case 99: // Blue Lock 217 case 133: 218 if ( !p ) 219 return 0; 220 if (!p->cards[it_bluecard] && !p->cards[it_blueskull]) 221 { 222 p->message = PD_BLUEO; 223 if (p == &::g->players[::g->consoleplayer]) 224 S_StartSound(NULL,sfx_oof); 225 return 0; 226 } 227 break; 228 229 case 134: // Red Lock 230 case 135: 231 if ( !p ) 232 return 0; 233 if (!p->cards[it_redcard] && !p->cards[it_redskull]) 234 { 235 p->message = PD_REDO; 236 if (p == &::g->players[::g->consoleplayer]) 237 S_StartSound(NULL,sfx_oof); 238 return 0; 239 } 240 break; 241 242 case 136: // Yellow Lock 243 case 137: 244 if ( !p ) 245 return 0; 246 if (!p->cards[it_yellowcard] && 247 !p->cards[it_yellowskull]) 248 { 249 p->message = PD_YELLOWO; 250 if (p == &::g->players[::g->consoleplayer]) 251 S_StartSound(NULL,sfx_oof); 252 return 0; 253 } 254 break; 255 } 256 257 return EV_DoDoor(line,type); 258 } 259 260 261 int 262 EV_DoDoor 263 ( line_t* line, 264 vldoor_e type ) 265 { 266 int secnum,rtn; 267 sector_t* sec; 268 vldoor_t* door; 269 270 secnum = -1; 271 rtn = 0; 272 273 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 274 { 275 sec = &::g->sectors[secnum]; 276 if (sec->specialdata) 277 continue; 278 279 280 // new door thinker 281 rtn = 1; 282 door = (vldoor_t*)DoomLib::Z_Malloc(sizeof(*door), PU_LEVEL, 0); 283 P_AddThinker (&door->thinker); 284 sec->specialdata = door; 285 286 door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor; 287 door->sector = sec; 288 door->type = type; 289 door->topwait = VDOORWAIT; 290 door->speed = VDOORSPEED; 291 292 switch(type) 293 { 294 case blazeClose: 295 door->topheight = P_FindLowestCeilingSurrounding(sec); 296 door->topheight -= 4*FRACUNIT; 297 door->direction = -1; 298 door->speed = VDOORSPEED * 4; 299 S_StartSound( &door->sector->soundorg, 300 sfx_bdcls); 301 break; 302 303 case closed: 304 door->topheight = P_FindLowestCeilingSurrounding(sec); 305 door->topheight -= 4*FRACUNIT; 306 door->direction = -1; 307 S_StartSound( &door->sector->soundorg, 308 sfx_dorcls); 309 break; 310 311 case close30ThenOpen: 312 door->topheight = sec->ceilingheight; 313 door->direction = -1; 314 S_StartSound( &door->sector->soundorg, 315 sfx_dorcls); 316 break; 317 318 case blazeRaise: 319 case blazeOpen: 320 door->direction = 1; 321 door->topheight = P_FindLowestCeilingSurrounding(sec); 322 door->topheight -= 4*FRACUNIT; 323 door->speed = VDOORSPEED * 4; 324 if (door->topheight != sec->ceilingheight) 325 S_StartSound( &door->sector->soundorg, 326 sfx_bdopn); 327 break; 328 329 case normal: 330 case opened: 331 door->direction = 1; 332 door->topheight = P_FindLowestCeilingSurrounding(sec); 333 door->topheight -= 4*FRACUNIT; 334 if (door->topheight != sec->ceilingheight) 335 S_StartSound( &door->sector->soundorg, 336 sfx_doropn); 337 break; 338 339 default: 340 break; 341 } 342 343 } 344 return rtn; 345 } 346 347 348 // 349 // EV_VerticalDoor : open a door manually, no tag value 350 // 351 void 352 EV_VerticalDoor 353 ( line_t* line, 354 mobj_t* thing ) 355 { 356 player_t* player; 357 int secnum; 358 sector_t* sec; 359 vldoor_t* door; 360 int side; 361 362 side = 0; // only front ::g->sides can be used 363 364 // Check for locks 365 player = thing->player; 366 367 switch(line->special) 368 { 369 case 26: // Blue Lock 370 case 32: 371 if ( !player ) 372 return; 373 374 if (!player->cards[it_bluecard] && !player->cards[it_blueskull]) 375 { 376 player->message = PD_BLUEK; 377 if (globalNetworking || (player == &::g->players[::g->consoleplayer])) 378 S_StartSound(player->mo,sfx_oof); 379 return; 380 } 381 break; 382 383 case 27: // Yellow Lock 384 case 34: 385 if ( !player ) 386 return; 387 388 if (!player->cards[it_yellowcard] && 389 !player->cards[it_yellowskull]) 390 { 391 player->message = PD_YELLOWK; 392 if (globalNetworking || (player == &::g->players[::g->consoleplayer])) 393 S_StartSound(player->mo,sfx_oof); 394 return; 395 } 396 break; 397 398 case 28: // Red Lock 399 case 33: 400 if ( !player ) 401 return; 402 403 if (!player->cards[it_redcard] && !player->cards[it_redskull]) 404 { 405 player->message = PD_REDK; 406 if (globalNetworking || (player == &::g->players[::g->consoleplayer])) 407 S_StartSound(player->mo,sfx_oof); 408 return; 409 } 410 break; 411 } 412 413 // if the sector has an active thinker, use it 414 sec = ::g->sides[ line->sidenum[side^1]] .sector; 415 secnum = sec-::g->sectors; 416 417 if (sec->specialdata) 418 { 419 door = (vldoor_t*)sec->specialdata; 420 switch(line->special) 421 { 422 case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s 423 case 26: 424 case 27: 425 case 28: 426 case 117: 427 if (door->direction == -1) 428 door->direction = 1; // go back up 429 else 430 { 431 if (!thing->player) 432 return; // JDC: bad guys never close doors 433 434 door->direction = -1; // start going down immediately 435 } 436 return; 437 } 438 } 439 440 // for proper sound 441 if (globalNetworking || (player == &::g->players[::g->consoleplayer])) { 442 switch(line->special) 443 { 444 case 117: // BLAZING DOOR RAISE 445 case 118: // BLAZING DOOR OPEN 446 S_StartSound( &sec->soundorg,sfx_bdopn); 447 break; 448 449 case 1: // NORMAL DOOR SOUND 450 case 31: 451 S_StartSound( &sec->soundorg,sfx_doropn); 452 break; 453 454 default: // LOCKED DOOR SOUND 455 S_StartSound( &sec->soundorg,sfx_doropn); 456 break; 457 } 458 } 459 460 461 // new door thinker 462 door = (vldoor_t*)DoomLib::Z_Malloc(sizeof(*door), PU_LEVEL, 0); 463 P_AddThinker (&door->thinker); 464 sec->specialdata = door; 465 door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor; 466 door->sector = sec; 467 door->direction = 1; 468 door->speed = VDOORSPEED; 469 door->topwait = VDOORWAIT; 470 471 switch(line->special) 472 { 473 case 1: 474 case 26: 475 case 27: 476 case 28: 477 door->type = normal; 478 break; 479 480 case 31: 481 case 32: 482 case 33: 483 case 34: 484 door->type = opened; 485 line->special = 0; 486 break; 487 488 case 117: // blazing door raise 489 door->type = blazeRaise; 490 door->speed = VDOORSPEED*4; 491 break; 492 case 118: // blazing door open 493 door->type = blazeOpen; 494 line->special = 0; 495 door->speed = VDOORSPEED*4; 496 break; 497 } 498 499 // find the top and bottom of the movement range 500 door->topheight = P_FindLowestCeilingSurrounding(sec); 501 door->topheight -= 4*FRACUNIT; 502 } 503 504 505 // 506 // Spawn a door that closes after 30 seconds 507 // 508 void P_SpawnDoorCloseIn30 (sector_t* sec) 509 { 510 vldoor_t* door; 511 512 door = (vldoor_t*)DoomLib::Z_Malloc( sizeof(*door), PU_LEVEL, 0); 513 514 P_AddThinker (&door->thinker); 515 516 sec->specialdata = door; 517 sec->special = 0; 518 519 door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; 520 door->sector = sec; 521 door->direction = 0; 522 door->type = normal; 523 door->speed = VDOORSPEED; 524 door->topcountdown = 30 * TICRATE; 525 } 526 527 // 528 // Spawn a door that opens after 5 minutes 529 // 530 void 531 P_SpawnDoorRaiseIn5Mins 532 ( sector_t* sec, 533 int secnum ) 534 { 535 vldoor_t* door; 536 537 door = (vldoor_t*)DoomLib::Z_Malloc( sizeof(*door), PU_LEVEL, 0); 538 539 P_AddThinker (&door->thinker); 540 541 sec->specialdata = door; 542 sec->special = 0; 543 544 door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; 545 door->sector = sec; 546 door->direction = 2; 547 door->type = raiseIn5Mins; 548 door->speed = VDOORSPEED; 549 door->topheight = P_FindLowestCeilingSurrounding(sec); 550 door->topheight -= 4*FRACUNIT; 551 door->topwait = VDOORWAIT; 552 door->topcountdown = 5 * 60 * TICRATE; 553 } 554 555 556 557 // UNUSED 558 // Separate into p_slidoor.c? 559 560