DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

p_plats.cpp (7464B)


      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 "i_system.h"
     34 #include "z_zone.h"
     35 #include "m_random.h"
     36 
     37 #include "doomdef.h"
     38 #include "p_local.h"
     39 
     40 #include "s_sound.h"
     41 
     42 // State.
     43 #include "doomstat.h"
     44 #include "r_state.h"
     45 
     46 // Data.
     47 #include "sounds.h"
     48 
     49 
     50 
     51 
     52 
     53 //
     54 // Move a plat up and down
     55 //
     56 void T_PlatRaise(plat_t* plat)
     57 {
     58     result_e	res;
     59 	
     60     switch(plat->status)
     61     {
     62       case up:
     63 	res = T_MovePlane(plat->sector,
     64 			  plat->speed,
     65 			  plat->high,
     66 			  plat->crush,0,1);
     67 					
     68 	if (plat->type == raiseAndChange
     69 	    || plat->type == raiseToNearestAndChange)
     70 	{
     71 	    if (!(::g->leveltime&7))
     72 		S_StartSound( &plat->sector->soundorg,
     73 			     sfx_stnmov);
     74 	}
     75 	
     76 				
     77 	if (res == crushed && (!plat->crush))
     78 	{
     79 	    plat->count = plat->wait;
     80 	    plat->status = down;
     81 	    S_StartSound( &plat->sector->soundorg,
     82 			 sfx_pstart);
     83 	}
     84 	else
     85 	{
     86 	    if (res == pastdest)
     87 	    {
     88 		plat->count = plat->wait;
     89 		plat->status = waiting;
     90 		S_StartSound( &plat->sector->soundorg,
     91 			     sfx_pstop);
     92 
     93 		switch(plat->type)
     94 		{
     95 		  case blazeDWUS:
     96 		  case downWaitUpStay:
     97 		    P_RemoveActivePlat(plat);
     98 		    break;
     99 		    
    100 		  case raiseAndChange:
    101 		  case raiseToNearestAndChange:
    102 		    P_RemoveActivePlat(plat);
    103 		    break;
    104 		    
    105 		  default:
    106 		    break;
    107 		}
    108 	    }
    109 	}
    110 	break;
    111 	
    112       case	down:
    113 	res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1);
    114 
    115 	if (res == pastdest)
    116 	{
    117 	    plat->count = plat->wait;
    118 	    plat->status = waiting;
    119 	    S_StartSound( &plat->sector->soundorg,sfx_pstop);
    120 	}
    121 	break;
    122 	
    123       case	waiting:
    124 	if (!--plat->count)
    125 	{
    126 	    if (plat->sector->floorheight == plat->low)
    127 		plat->status = up;
    128 	    else
    129 		plat->status = down;
    130 	    S_StartSound( &plat->sector->soundorg,sfx_pstart);
    131 	}
    132       case	in_stasis:
    133 	break;
    134     }
    135 }
    136 
    137 
    138 //
    139 // Do Platforms
    140 //  "amount" is only used for SOME platforms.
    141 //
    142 int
    143 EV_DoPlat
    144 ( line_t*	line,
    145   plattype_e	type,
    146   int		amount )
    147 {
    148     plat_t*	plat;
    149     int		secnum;
    150     int		rtn;
    151     sector_t*	sec;
    152 	
    153     secnum = -1;
    154     rtn = 0;
    155 
    156     
    157     //	Activate all <type> plats that are in_stasis
    158     switch(type)
    159     {
    160       case perpetualRaise:
    161 	P_ActivateInStasis(line->tag);
    162 	break;
    163 	
    164       default:
    165 	break;
    166     }
    167 	
    168     while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
    169     {
    170 	sec = &::g->sectors[secnum];
    171 
    172 	if (sec->specialdata)
    173 	    continue;
    174 	
    175 	// Find lowest & highest floors around sector
    176 	rtn = 1;
    177 	plat = (plat_t*)DoomLib::Z_Malloc( sizeof(*plat), PU_LEVEL, 0);
    178 	P_AddThinker(&plat->thinker);
    179 		
    180 	plat->type = type;
    181 	plat->sector = sec;
    182 	plat->sector->specialdata = plat;
    183 	plat->thinker.function.acp1 = (actionf_p1) T_PlatRaise;
    184 	plat->crush = false;
    185 	plat->tag = line->tag;
    186 	
    187 	switch(type)
    188 	{
    189 	  case raiseToNearestAndChange:
    190 	    plat->speed = PLATSPEED/2;
    191 	    sec->floorpic = ::g->sides[line->sidenum[0]].sector->floorpic;
    192 	    plat->high = P_FindNextHighestFloor(sec,sec->floorheight);
    193 	    plat->wait = 0;
    194 	    plat->status = up;
    195 	    // NO MORE DAMAGE, IF APPLICABLE
    196 	    sec->special = 0;		
    197 
    198 	    S_StartSound( &sec->soundorg,sfx_stnmov);
    199 	    break;
    200 	    
    201 	  case raiseAndChange:
    202 	    plat->speed = PLATSPEED/2;
    203 	    sec->floorpic = ::g->sides[line->sidenum[0]].sector->floorpic;
    204 	    plat->high = sec->floorheight + amount*FRACUNIT;
    205 	    plat->wait = 0;
    206 	    plat->status = up;
    207 
    208 	    S_StartSound( &sec->soundorg,sfx_stnmov);
    209 	    break;
    210 	    
    211 	  case downWaitUpStay:
    212 	    plat->speed = PLATSPEED * 4;
    213 	    plat->low = P_FindLowestFloorSurrounding(sec);
    214 
    215 	    if (plat->low > sec->floorheight)
    216 		plat->low = sec->floorheight;
    217 
    218 	    plat->high = sec->floorheight;
    219 	    plat->wait = TICRATE*PLATWAIT;
    220 	    plat->status = down;
    221 	    S_StartSound( &sec->soundorg,sfx_pstart);
    222 	    break;
    223 	    
    224 	  case blazeDWUS:
    225 	    plat->speed = PLATSPEED * 8;
    226 	    plat->low = P_FindLowestFloorSurrounding(sec);
    227 
    228 	    if (plat->low > sec->floorheight)
    229 		plat->low = sec->floorheight;
    230 
    231 	    plat->high = sec->floorheight;
    232 	    plat->wait = TICRATE*PLATWAIT;
    233 	    plat->status = down;
    234 	    S_StartSound( &sec->soundorg,sfx_pstart);
    235 	    break;
    236 	    
    237 	  case perpetualRaise:
    238 	    plat->speed = PLATSPEED;
    239 	    plat->low = P_FindLowestFloorSurrounding(sec);
    240 
    241 	    if (plat->low > sec->floorheight)
    242 		plat->low = sec->floorheight;
    243 
    244 	    plat->high = P_FindHighestFloorSurrounding(sec);
    245 
    246 	    if (plat->high < sec->floorheight)
    247 		plat->high = sec->floorheight;
    248 
    249 	    plat->wait = TICRATE*PLATWAIT;
    250 	    plat->status = (plat_e)(P_Random()&1);
    251 
    252 	    S_StartSound( &sec->soundorg,sfx_pstart);
    253 	    break;
    254 	}
    255 	P_AddActivePlat(plat);
    256     }
    257     return rtn;
    258 }
    259 
    260 
    261 
    262 void P_ActivateInStasis(int tag)
    263 {
    264     int		i;
    265 	
    266     for (i = 0;i < MAXPLATS;i++)
    267 	if (::g->activeplats[i]
    268 	    && (::g->activeplats[i])->tag == tag
    269 	    && (::g->activeplats[i])->status == in_stasis)
    270 	{
    271 	    (::g->activeplats[i])->status = (::g->activeplats[i])->oldstatus;
    272 	    (::g->activeplats[i])->thinker.function.acp1
    273 	      = (actionf_p1) T_PlatRaise;
    274 	}
    275 }
    276 
    277 void EV_StopPlat(line_t* line)
    278 {
    279     int		j;
    280 	
    281     for (j = 0;j < MAXPLATS;j++)
    282 	if (::g->activeplats[j]
    283 	    && ((::g->activeplats[j])->status != in_stasis)
    284 	    && ((::g->activeplats[j])->tag == line->tag))
    285 	{
    286 	    (::g->activeplats[j])->oldstatus = (::g->activeplats[j])->status;
    287 	    (::g->activeplats[j])->status = in_stasis;
    288 	    (::g->activeplats[j])->thinker.function.acv = (actionf_v)NULL;
    289 	}
    290 }
    291 
    292 void P_AddActivePlat(plat_t* plat)
    293 {
    294     int		i;
    295     
    296     for (i = 0;i < MAXPLATS;i++)
    297 	if (::g->activeplats[i] == NULL)
    298 	{
    299 	    ::g->activeplats[i] = plat;
    300 	    return;
    301 	}
    302     I_Error ("P_AddActivePlat: no more plats!");
    303 }
    304 
    305 void P_RemoveActivePlat(plat_t* plat)
    306 {
    307     int		i;
    308     for (i = 0;i < MAXPLATS;i++)
    309 	if (plat == ::g->activeplats[i])
    310 	{
    311 	    (::g->activeplats[i])->sector->specialdata = NULL;
    312 	    P_RemoveThinker(&(::g->activeplats[i])->thinker);
    313 	    ::g->activeplats[i] = NULL;
    314 	    
    315 	    return;
    316 	}
    317     I_Error ("P_RemoveActivePlat: can't find plat!");
    318 }
    319