mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-04-25 02:52:12 +00:00
333 lines
7.4 KiB
C++
333 lines
7.4 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 "i_system.h"
|
|
#include "z_zone.h"
|
|
#include "m_random.h"
|
|
|
|
#include "doomdef.h"
|
|
#include "p_local.h"
|
|
|
|
#include "s_sound.h"
|
|
|
|
// State.
|
|
#include "doomstat.h"
|
|
#include "r_state.h"
|
|
|
|
// Data.
|
|
#include "sounds.h"
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Move a plat up and down
|
|
//
|
|
void T_PlatRaise( plat_t* plat )
|
|
{
|
|
result_e res;
|
|
|
|
switch( plat->status )
|
|
{
|
|
case up:
|
|
res = T_MovePlane( plat->sector,
|
|
plat->speed,
|
|
plat->high,
|
|
plat->crush, 0, 1 );
|
|
|
|
if( plat->type == raiseAndChange
|
|
|| plat->type == raiseToNearestAndChange )
|
|
{
|
|
if( !( ::g->leveltime & 7 ) )
|
|
S_StartSound( &plat->sector->soundorg,
|
|
sfx_stnmov );
|
|
}
|
|
|
|
|
|
if( res == crushed && ( !plat->crush ) )
|
|
{
|
|
plat->count = plat->wait;
|
|
plat->status = down;
|
|
S_StartSound( &plat->sector->soundorg,
|
|
sfx_pstart );
|
|
}
|
|
else
|
|
{
|
|
if( res == pastdest )
|
|
{
|
|
plat->count = plat->wait;
|
|
plat->status = waiting;
|
|
S_StartSound( &plat->sector->soundorg,
|
|
sfx_pstop );
|
|
|
|
switch( plat->type )
|
|
{
|
|
case blazeDWUS:
|
|
case downWaitUpStay:
|
|
P_RemoveActivePlat( plat );
|
|
break;
|
|
|
|
case raiseAndChange:
|
|
case raiseToNearestAndChange:
|
|
P_RemoveActivePlat( plat );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case down:
|
|
res = T_MovePlane( plat->sector, plat->speed, plat->low, false, 0, -1 );
|
|
|
|
if( res == pastdest )
|
|
{
|
|
plat->count = plat->wait;
|
|
plat->status = waiting;
|
|
S_StartSound( &plat->sector->soundorg, sfx_pstop );
|
|
}
|
|
break;
|
|
|
|
case waiting:
|
|
if( !--plat->count )
|
|
{
|
|
if( plat->sector->floorheight == plat->low )
|
|
{
|
|
plat->status = up;
|
|
}
|
|
else
|
|
{
|
|
plat->status = down;
|
|
}
|
|
S_StartSound( &plat->sector->soundorg, sfx_pstart );
|
|
}
|
|
case in_stasis:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Do Platforms
|
|
// "amount" is only used for SOME platforms.
|
|
//
|
|
int
|
|
EV_DoPlat
|
|
( line_t* line,
|
|
plattype_e type,
|
|
int amount )
|
|
{
|
|
plat_t* plat;
|
|
int secnum;
|
|
int rtn;
|
|
sector_t* sec;
|
|
|
|
secnum = -1;
|
|
rtn = 0;
|
|
|
|
|
|
// Activate all <type> plats that are in_stasis
|
|
switch( type )
|
|
{
|
|
case perpetualRaise:
|
|
P_ActivateInStasis( line->tag );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
while( ( secnum = P_FindSectorFromLineTag( line, secnum ) ) >= 0 )
|
|
{
|
|
sec = &::g->sectors[secnum];
|
|
|
|
if( sec->specialdata )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Find lowest & highest floors around sector
|
|
rtn = 1;
|
|
plat = ( plat_t* )DoomLib::Z_Malloc( sizeof( *plat ), PU_LEVEL, 0 );
|
|
P_AddThinker( &plat->thinker );
|
|
|
|
plat->type = type;
|
|
plat->sector = sec;
|
|
plat->sector->specialdata = plat;
|
|
plat->thinker.function.acp1 = ( actionf_p1 ) T_PlatRaise;
|
|
plat->crush = false;
|
|
plat->tag = line->tag;
|
|
|
|
switch( type )
|
|
{
|
|
case raiseToNearestAndChange:
|
|
plat->speed = PLATSPEED / 2;
|
|
sec->floorpic = ::g->sides[line->sidenum[0]].sector->floorpic;
|
|
plat->high = P_FindNextHighestFloor( sec, sec->floorheight );
|
|
plat->wait = 0;
|
|
plat->status = up;
|
|
// NO MORE DAMAGE, IF APPLICABLE
|
|
sec->special = 0;
|
|
|
|
S_StartSound( &sec->soundorg, sfx_stnmov );
|
|
break;
|
|
|
|
case raiseAndChange:
|
|
plat->speed = PLATSPEED / 2;
|
|
sec->floorpic = ::g->sides[line->sidenum[0]].sector->floorpic;
|
|
plat->high = sec->floorheight + amount * FRACUNIT;
|
|
plat->wait = 0;
|
|
plat->status = up;
|
|
|
|
S_StartSound( &sec->soundorg, sfx_stnmov );
|
|
break;
|
|
|
|
case downWaitUpStay:
|
|
plat->speed = PLATSPEED * 4;
|
|
plat->low = P_FindLowestFloorSurrounding( sec );
|
|
|
|
if( plat->low > sec->floorheight )
|
|
{
|
|
plat->low = sec->floorheight;
|
|
}
|
|
|
|
plat->high = sec->floorheight;
|
|
plat->wait = TICRATE * PLATWAIT;
|
|
plat->status = down;
|
|
S_StartSound( &sec->soundorg, sfx_pstart );
|
|
break;
|
|
|
|
case blazeDWUS:
|
|
plat->speed = PLATSPEED * 8;
|
|
plat->low = P_FindLowestFloorSurrounding( sec );
|
|
|
|
if( plat->low > sec->floorheight )
|
|
{
|
|
plat->low = sec->floorheight;
|
|
}
|
|
|
|
plat->high = sec->floorheight;
|
|
plat->wait = TICRATE * PLATWAIT;
|
|
plat->status = down;
|
|
S_StartSound( &sec->soundorg, sfx_pstart );
|
|
break;
|
|
|
|
case perpetualRaise:
|
|
plat->speed = PLATSPEED;
|
|
plat->low = P_FindLowestFloorSurrounding( sec );
|
|
|
|
if( plat->low > sec->floorheight )
|
|
{
|
|
plat->low = sec->floorheight;
|
|
}
|
|
|
|
plat->high = P_FindHighestFloorSurrounding( sec );
|
|
|
|
if( plat->high < sec->floorheight )
|
|
{
|
|
plat->high = sec->floorheight;
|
|
}
|
|
|
|
plat->wait = TICRATE * PLATWAIT;
|
|
plat->status = ( plat_e )( P_Random() & 1 );
|
|
|
|
S_StartSound( &sec->soundorg, sfx_pstart );
|
|
break;
|
|
}
|
|
P_AddActivePlat( plat );
|
|
}
|
|
return rtn;
|
|
}
|
|
|
|
|
|
|
|
void P_ActivateInStasis( int tag )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < MAXPLATS; i++ )
|
|
if( ::g->activeplats[i]
|
|
&& ( ::g->activeplats[i] )->tag == tag
|
|
&& ( ::g->activeplats[i] )->status == in_stasis )
|
|
{
|
|
( ::g->activeplats[i] )->status = ( ::g->activeplats[i] )->oldstatus;
|
|
( ::g->activeplats[i] )->thinker.function.acp1
|
|
= ( actionf_p1 ) T_PlatRaise;
|
|
}
|
|
}
|
|
|
|
void EV_StopPlat( line_t* line )
|
|
{
|
|
int j;
|
|
|
|
for( j = 0; j < MAXPLATS; j++ )
|
|
if( ::g->activeplats[j]
|
|
&& ( ( ::g->activeplats[j] )->status != in_stasis )
|
|
&& ( ( ::g->activeplats[j] )->tag == line->tag ) )
|
|
{
|
|
( ::g->activeplats[j] )->oldstatus = ( ::g->activeplats[j] )->status;
|
|
( ::g->activeplats[j] )->status = in_stasis;
|
|
( ::g->activeplats[j] )->thinker.function.acv = ( actionf_v )NULL;
|
|
}
|
|
}
|
|
|
|
void P_AddActivePlat( plat_t* plat )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < MAXPLATS; i++ )
|
|
if( ::g->activeplats[i] == NULL )
|
|
{
|
|
::g->activeplats[i] = plat;
|
|
return;
|
|
}
|
|
I_Error( "P_AddActivePlat: no more plats!" );
|
|
}
|
|
|
|
void P_RemoveActivePlat( plat_t* plat )
|
|
{
|
|
int i;
|
|
for( i = 0; i < MAXPLATS; i++ )
|
|
if( plat == ::g->activeplats[i] )
|
|
{
|
|
( ::g->activeplats[i] )->sector->specialdata = NULL;
|
|
P_RemoveThinker( &( ::g->activeplats[i] )->thinker );
|
|
::g->activeplats[i] = NULL;
|
|
|
|
return;
|
|
}
|
|
I_Error( "P_RemoveActivePlat: can't find plat!" );
|
|
}
|
|
|