/* =========================================================================== Doom 3 BFG Edition GPL Source Code Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Doom 3 BFG Edition Source Code. If not, see . 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. 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. =========================================================================== */ #include "Precompiled.h" #include "globaldata.h" #include "z_zone.h" #include "doomdef.h" #include "p_local.h" #include "s_sound.h" // State. #include "doomstat.h" #include "r_state.h" // Data. #include "dstrings.h" #include "sounds.h" extern bool globalNetworking; // // VERTICAL DOORS // // // T_VerticalDoor // void T_VerticalDoor (vldoor_t* door) { result_e res; switch(door->direction) { case 0: // WAITING if (!--door->topcountdown) { switch(door->type) { case blazeRaise: door->direction = -1; // time to go back down S_StartSound( &door->sector->soundorg, sfx_bdcls); break; case normal: door->direction = -1; // time to go back down S_StartSound( &door->sector->soundorg, sfx_dorcls); break; case close30ThenOpen: door->direction = 1; S_StartSound( &door->sector->soundorg, sfx_doropn); break; default: break; } } break; case 2: // INITIAL WAIT if (!--door->topcountdown) { switch(door->type) { case raiseIn5Mins: door->direction = 1; door->type = normal; S_StartSound( &door->sector->soundorg, sfx_doropn); break; default: break; } } break; case -1: // DOWN res = T_MovePlane(door->sector, door->speed, door->sector->floorheight, false,1,door->direction); if (res == pastdest) { switch(door->type) { case blazeRaise: case blazeClose: door->sector->specialdata = NULL; P_RemoveThinker (&door->thinker); // unlink and free S_StartSound( &door->sector->soundorg, sfx_bdcls); break; case normal: case closed: door->sector->specialdata = NULL; P_RemoveThinker (&door->thinker); // unlink and free break; case close30ThenOpen: door->direction = 0; door->topcountdown = TICRATE*30; break; default: break; } } else if (res == crushed) { switch(door->type) { case blazeClose: case closed: // DO NOT GO BACK UP! break; default: door->direction = 1; S_StartSound( &door->sector->soundorg, sfx_doropn); break; } } break; case 1: // UP res = T_MovePlane(door->sector, door->speed, door->topheight, false,1,door->direction); if (res == pastdest) { switch(door->type) { case blazeRaise: case normal: door->direction = 0; // wait at top door->topcountdown = door->topwait; break; case close30ThenOpen: case blazeOpen: case opened: door->sector->specialdata = NULL; P_RemoveThinker (&door->thinker); // unlink and free break; default: break; } } break; } } // // EV_DoLockedDoor // Move a locked door up/down // int EV_DoLockedDoor ( line_t* line, vldoor_e type, mobj_t* thing ) { player_t* p; p = thing->player; if (!p) return 0; switch(line->special) { case 99: // Blue Lock case 133: if ( !p ) return 0; if (!p->cards[it_bluecard] && !p->cards[it_blueskull]) { p->message = PD_BLUEO; if (p == &::g->players[::g->consoleplayer]) S_StartSound(NULL,sfx_oof); return 0; } break; case 134: // Red Lock case 135: if ( !p ) return 0; if (!p->cards[it_redcard] && !p->cards[it_redskull]) { p->message = PD_REDO; if (p == &::g->players[::g->consoleplayer]) S_StartSound(NULL,sfx_oof); return 0; } break; case 136: // Yellow Lock case 137: if ( !p ) return 0; if (!p->cards[it_yellowcard] && !p->cards[it_yellowskull]) { p->message = PD_YELLOWO; if (p == &::g->players[::g->consoleplayer]) S_StartSound(NULL,sfx_oof); return 0; } break; } return EV_DoDoor(line,type); } int EV_DoDoor ( line_t* line, vldoor_e type ) { int secnum,rtn; sector_t* sec; vldoor_t* door; secnum = -1; rtn = 0; while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) { sec = &::g->sectors[secnum]; if (sec->specialdata) continue; // new door thinker rtn = 1; door = (vldoor_t*)DoomLib::Z_Malloc(sizeof(*door), PU_LEVEL, 0); P_AddThinker (&door->thinker); sec->specialdata = door; door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor; door->sector = sec; door->type = type; door->topwait = VDOORWAIT; door->speed = VDOORSPEED; switch(type) { case blazeClose: door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; door->direction = -1; door->speed = VDOORSPEED * 4; S_StartSound( &door->sector->soundorg, sfx_bdcls); break; case closed: door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; door->direction = -1; S_StartSound( &door->sector->soundorg, sfx_dorcls); break; case close30ThenOpen: door->topheight = sec->ceilingheight; door->direction = -1; S_StartSound( &door->sector->soundorg, sfx_dorcls); break; case blazeRaise: case blazeOpen: door->direction = 1; door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; door->speed = VDOORSPEED * 4; if (door->topheight != sec->ceilingheight) S_StartSound( &door->sector->soundorg, sfx_bdopn); break; case normal: case opened: door->direction = 1; door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; if (door->topheight != sec->ceilingheight) S_StartSound( &door->sector->soundorg, sfx_doropn); break; default: break; } } return rtn; } // // EV_VerticalDoor : open a door manually, no tag value // void EV_VerticalDoor ( line_t* line, mobj_t* thing ) { player_t* player; int secnum; sector_t* sec; vldoor_t* door; int side; side = 0; // only front ::g->sides can be used // Check for locks player = thing->player; switch(line->special) { case 26: // Blue Lock case 32: if ( !player ) return; if (!player->cards[it_bluecard] && !player->cards[it_blueskull]) { player->message = PD_BLUEK; if (globalNetworking || (player == &::g->players[::g->consoleplayer])) S_StartSound(player->mo,sfx_oof); return; } break; case 27: // Yellow Lock case 34: if ( !player ) return; if (!player->cards[it_yellowcard] && !player->cards[it_yellowskull]) { player->message = PD_YELLOWK; if (globalNetworking || (player == &::g->players[::g->consoleplayer])) S_StartSound(player->mo,sfx_oof); return; } break; case 28: // Red Lock case 33: if ( !player ) return; if (!player->cards[it_redcard] && !player->cards[it_redskull]) { player->message = PD_REDK; if (globalNetworking || (player == &::g->players[::g->consoleplayer])) S_StartSound(player->mo,sfx_oof); return; } break; } // if the sector has an active thinker, use it sec = ::g->sides[ line->sidenum[side^1]] .sector; secnum = sec-::g->sectors; if (sec->specialdata) { door = (vldoor_t*)sec->specialdata; switch(line->special) { case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s case 26: case 27: case 28: case 117: if (door->direction == -1) door->direction = 1; // go back up else { if (!thing->player) return; // JDC: bad guys never close doors door->direction = -1; // start going down immediately } return; } } // for proper sound if (globalNetworking || (player == &::g->players[::g->consoleplayer])) { switch(line->special) { case 117: // BLAZING DOOR RAISE case 118: // BLAZING DOOR OPEN S_StartSound( &sec->soundorg,sfx_bdopn); break; case 1: // NORMAL DOOR SOUND case 31: S_StartSound( &sec->soundorg,sfx_doropn); break; default: // LOCKED DOOR SOUND S_StartSound( &sec->soundorg,sfx_doropn); break; } } // new door thinker door = (vldoor_t*)DoomLib::Z_Malloc(sizeof(*door), PU_LEVEL, 0); P_AddThinker (&door->thinker); sec->specialdata = door; door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor; door->sector = sec; door->direction = 1; door->speed = VDOORSPEED; door->topwait = VDOORWAIT; switch(line->special) { case 1: case 26: case 27: case 28: door->type = normal; break; case 31: case 32: case 33: case 34: door->type = opened; line->special = 0; break; case 117: // blazing door raise door->type = blazeRaise; door->speed = VDOORSPEED*4; break; case 118: // blazing door open door->type = blazeOpen; line->special = 0; door->speed = VDOORSPEED*4; break; } // find the top and bottom of the movement range door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; } // // Spawn a door that closes after 30 seconds // void P_SpawnDoorCloseIn30 (sector_t* sec) { vldoor_t* door; door = (vldoor_t*)DoomLib::Z_Malloc( sizeof(*door), PU_LEVEL, 0); P_AddThinker (&door->thinker); sec->specialdata = door; sec->special = 0; door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; door->sector = sec; door->direction = 0; door->type = normal; door->speed = VDOORSPEED; door->topcountdown = 30 * TICRATE; } // // Spawn a door that opens after 5 minutes // void P_SpawnDoorRaiseIn5Mins ( sector_t* sec, int secnum ) { vldoor_t* door; door = (vldoor_t*)DoomLib::Z_Malloc( sizeof(*door), PU_LEVEL, 0); P_AddThinker (&door->thinker); sec->specialdata = door; sec->special = 0; door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; door->sector = sec; door->direction = 2; door->type = raiseIn5Mins; door->speed = VDOORSPEED; door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; door->topwait = VDOORWAIT; door->topcountdown = 5 * 60 * TICRATE; } // UNUSED // Separate into p_slidoor.c?