doom3-bfg/doomclassic/doom/p_plats.cpp
2022-09-05 22:25:33 +02:00

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!" );
}