DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

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