mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-11-25 13:31:12 +00:00
561 lines
12 KiB
C++
561 lines
12 KiB
C++
|
/*
|
||
|
===========================================================================
|
||
|
|
||
|
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 <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
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?
|
||
|
|
||
|
|