DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

p_floor.cpp (12415B)


      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 "z_zone.h"
     34 #include "doomdef.h"
     35 #include "p_local.h"
     36 
     37 #include "s_sound.h"
     38 
     39 // State.
     40 #include "doomstat.h"
     41 #include "r_state.h"
     42 // Data.
     43 #include "sounds.h"
     44 
     45 
     46 //
     47 // FLOORS
     48 //
     49 
     50 //
     51 // Move a plane (floor or ceiling) and check for crushing
     52 //
     53 result_e
     54 T_MovePlane
     55 ( sector_t*	sector,
     56   fixed_t	speed,
     57   fixed_t	dest,
     58   qboolean	crush,
     59   int		floorOrCeiling,
     60   int		direction )
     61 {
     62     qboolean	flag;
     63     fixed_t	lastpos;
     64 	
     65     switch(floorOrCeiling)
     66     {
     67       case 0:
     68 	// FLOOR
     69 	switch(direction)
     70 	{
     71 	  case -1:
     72 	    // DOWN
     73 	    if (sector->floorheight - speed < dest)
     74 	    {
     75 		lastpos = sector->floorheight;
     76 		sector->floorheight = dest;
     77 		flag = P_ChangeSector(sector,crush);
     78 		if (flag == true)
     79 		{
     80 		    sector->floorheight =lastpos;
     81 		    P_ChangeSector(sector,crush);
     82 		    //return crushed;
     83 		}
     84 		return pastdest;
     85 	    }
     86 	    else
     87 	    {
     88 		lastpos = sector->floorheight;
     89 		sector->floorheight -= speed;
     90 		flag = P_ChangeSector(sector,crush);
     91 		if (flag == true)
     92 		{
     93 		    sector->floorheight = lastpos;
     94 		    P_ChangeSector(sector,crush);
     95 		    return crushed;
     96 		}
     97 	    }
     98 	    break;
     99 						
    100 	  case 1:
    101 	    // UP
    102 	    if (sector->floorheight + speed > dest)
    103 	    {
    104 		lastpos = sector->floorheight;
    105 		sector->floorheight = dest;
    106 		flag = P_ChangeSector(sector,crush);
    107 		if (flag == true)
    108 		{
    109 		    sector->floorheight = lastpos;
    110 		    P_ChangeSector(sector,crush);
    111 		    //return crushed;
    112 		}
    113 		return pastdest;
    114 	    }
    115 	    else
    116 	    {
    117 		// COULD GET CRUSHED
    118 		lastpos = sector->floorheight;
    119 		sector->floorheight += speed;
    120 		flag = P_ChangeSector(sector,crush);
    121 		if (flag == true)
    122 		{
    123 		    if (crush == true)
    124 			return crushed;
    125 		    sector->floorheight = lastpos;
    126 		    P_ChangeSector(sector,crush);
    127 		    return crushed;
    128 		}
    129 	    }
    130 	    break;
    131 	}
    132 	break;
    133 									
    134       case 1:
    135 	// CEILING
    136 	switch(direction)
    137 	{
    138 	  case -1:
    139 	    // DOWN
    140 	    if (sector->ceilingheight - speed < dest)
    141 	    {
    142 		lastpos = sector->ceilingheight;
    143 		sector->ceilingheight = dest;
    144 		flag = P_ChangeSector(sector,crush);
    145 
    146 		if (flag == true)
    147 		{
    148 		    sector->ceilingheight = lastpos;
    149 		    P_ChangeSector(sector,crush);
    150 		    //return crushed;
    151 		}
    152 		return pastdest;
    153 	    }
    154 	    else
    155 	    {
    156 		// COULD GET CRUSHED
    157 		lastpos = sector->ceilingheight;
    158 		sector->ceilingheight -= speed;
    159 		flag = P_ChangeSector(sector,crush);
    160 
    161 		if (flag == true)
    162 		{
    163 		    if (crush == true)
    164 			return crushed;
    165 		    sector->ceilingheight = lastpos;
    166 		    P_ChangeSector(sector,crush);
    167 		    return crushed;
    168 		}
    169 	    }
    170 	    break;
    171 						
    172 	  case 1:
    173 	    // UP
    174 	    if (sector->ceilingheight + speed > dest)
    175 	    {
    176 		lastpos = sector->ceilingheight;
    177 		sector->ceilingheight = dest;
    178 		flag = P_ChangeSector(sector,crush);
    179 		if (flag == true)
    180 		{
    181 		    sector->ceilingheight = lastpos;
    182 		    P_ChangeSector(sector,crush);
    183 		    //return crushed;
    184 		}
    185 		return pastdest;
    186 	    }
    187 	    else
    188 	    {
    189 		lastpos = sector->ceilingheight;
    190 		sector->ceilingheight += speed;
    191 		flag = P_ChangeSector(sector,crush);
    192 // UNUSED
    193 #if 0
    194 		if (flag == true)
    195 		{
    196 		    sector->ceilingheight = lastpos;
    197 		    P_ChangeSector(sector,crush);
    198 		    return crushed;
    199 		}
    200 #endif
    201 	    }
    202 	    break;
    203 	}
    204 	break;
    205 		
    206     }
    207     return ok;
    208 }
    209 
    210 
    211 //
    212 // MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN)
    213 //
    214 void T_MoveFloor(floormove_t* floor)
    215 {
    216     result_e	res;
    217 	
    218     res = T_MovePlane(floor->sector,
    219 		      floor->speed,
    220 		      floor->floordestheight,
    221 		      floor->crush,0,floor->direction);
    222     
    223     if (!(::g->leveltime&7))
    224 	S_StartSound( &floor->sector->soundorg,
    225 		     sfx_stnmov);
    226     
    227     if (res == pastdest)
    228     {
    229 	floor->sector->specialdata = NULL;
    230 
    231 	if (floor->direction == 1)
    232 	{
    233 	    switch(floor->type)
    234 	    {
    235 	      case donutRaise:
    236 		floor->sector->special = floor->newspecial;
    237 		floor->sector->floorpic = floor->texture;
    238 	      default:
    239 		break;
    240 	    }
    241 	}
    242 	else if (floor->direction == -1)
    243 	{
    244 	    switch(floor->type)
    245 	    {
    246 	      case lowerAndChange:
    247 		floor->sector->special = floor->newspecial;
    248 		floor->sector->floorpic = floor->texture;
    249 	      default:
    250 		break;
    251 	    }
    252 	}
    253 	P_RemoveThinker(&floor->thinker);
    254 
    255 	S_StartSound( &floor->sector->soundorg,
    256 		     sfx_pstop);
    257     }
    258 
    259 }
    260 
    261 //
    262 // HANDLE FLOOR TYPES
    263 //
    264 int
    265 EV_DoFloor
    266 ( line_t*	line,
    267   floor_e	floortype )
    268 {
    269     int			secnum;
    270     int			rtn;
    271     int			i;
    272     sector_t*		sec;
    273     floormove_t*	floor;
    274 
    275     secnum = -1;
    276     rtn = 0;
    277     while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
    278     {
    279 	sec = &::g->sectors[secnum];
    280 		
    281 	// ALREADY MOVING?  IF SO, KEEP GOING...
    282 	if (sec->specialdata)
    283 	    continue;
    284 	
    285 	// new floor thinker
    286 	rtn = 1;
    287 	floor = (floormove_t*)DoomLib::Z_Malloc(sizeof(*floor), PU_LEVEL, 0);
    288 	P_AddThinker (&floor->thinker);
    289 	sec->specialdata = floor;
    290 	floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
    291 	floor->type = floortype;
    292 	floor->crush = false;
    293 
    294 	switch(floortype)
    295 	{
    296 	  case lowerFloor:
    297 	    floor->direction = -1;
    298 	    floor->sector = sec;
    299 	    floor->speed = FLOORSPEED;
    300 	    floor->floordestheight = 
    301 		P_FindHighestFloorSurrounding(sec);
    302 	    break;
    303 
    304 	  case lowerFloorToLowest:
    305 	    floor->direction = -1;
    306 	    floor->sector = sec;
    307 	    floor->speed = FLOORSPEED;
    308 	    floor->floordestheight = 
    309 		P_FindLowestFloorSurrounding(sec);
    310 	    break;
    311 
    312 	  case turboLower:
    313 	    floor->direction = -1;
    314 	    floor->sector = sec;
    315 	    floor->speed = FLOORSPEED * 4;
    316 	    floor->floordestheight = 
    317 		P_FindHighestFloorSurrounding(sec);
    318 	    if (floor->floordestheight != sec->floorheight)
    319 		floor->floordestheight += 8*FRACUNIT;
    320 	    break;
    321 
    322 	  case raiseFloorCrush:
    323 	    floor->crush = true;
    324 	  case raiseFloor:
    325 	    floor->direction = 1;
    326 	    floor->sector = sec;
    327 	    floor->speed = FLOORSPEED;
    328 	    floor->floordestheight = 
    329 		P_FindLowestCeilingSurrounding(sec);
    330 	    if (floor->floordestheight > sec->ceilingheight)
    331 		floor->floordestheight = sec->ceilingheight;
    332 	    floor->floordestheight -= (8*FRACUNIT)*
    333 		(floortype == raiseFloorCrush);
    334 	    break;
    335 
    336 	  case raiseFloorTurbo:
    337 	    floor->direction = 1;
    338 	    floor->sector = sec;
    339 	    floor->speed = FLOORSPEED*4;
    340 	    floor->floordestheight = 
    341 		P_FindNextHighestFloor(sec,sec->floorheight);
    342 	    break;
    343 
    344 	  case raiseFloorToNearest:
    345 	    floor->direction = 1;
    346 	    floor->sector = sec;
    347 	    floor->speed = FLOORSPEED;
    348 	    floor->floordestheight = 
    349 		P_FindNextHighestFloor(sec,sec->floorheight);
    350 	    break;
    351 
    352 	  case raiseFloor24:
    353 	    floor->direction = 1;
    354 	    floor->sector = sec;
    355 	    floor->speed = FLOORSPEED;
    356 	    floor->floordestheight = floor->sector->floorheight +
    357 		24 * FRACUNIT;
    358 	    break;
    359 	  case raiseFloor512:
    360 	    floor->direction = 1;
    361 	    floor->sector = sec;
    362 	    floor->speed = FLOORSPEED;
    363 	    floor->floordestheight = floor->sector->floorheight +
    364 		512 * FRACUNIT;
    365 	    break;
    366 
    367 	  case raiseFloor24AndChange:
    368 	    floor->direction = 1;
    369 	    floor->sector = sec;
    370 	    floor->speed = FLOORSPEED;
    371 	    floor->floordestheight = floor->sector->floorheight +
    372 		24 * FRACUNIT;
    373 	    sec->floorpic = line->frontsector->floorpic;
    374 	    sec->special = line->frontsector->special;
    375 	    break;
    376 
    377 	  case raiseToTexture:
    378 	  {
    379 	      int	minsize = MAXINT;
    380 	      side_t*	side;
    381 				
    382 	      floor->direction = 1;
    383 	      floor->sector = sec;
    384 	      floor->speed = FLOORSPEED;
    385 	      for (i = 0; i < sec->linecount; i++)
    386 	      {
    387 		  if (twoSided (secnum, i) )
    388 		  {
    389 		      side = getSide(secnum,i,0);
    390 		      if (side->bottomtexture >= 0)
    391 			  if (::g->s_textureheight[side->bottomtexture] < 
    392 			      minsize)
    393 			      minsize = 
    394 				  ::g->s_textureheight[side->bottomtexture];
    395 		      side = getSide(secnum,i,1);
    396 		      if (side->bottomtexture >= 0)
    397 			  if (::g->s_textureheight[side->bottomtexture] < 
    398 			      minsize)
    399 			      minsize = 
    400 				 ::g->s_textureheight[side->bottomtexture];
    401 		  }
    402 	      }
    403 	      floor->floordestheight =
    404 		  floor->sector->floorheight + minsize;
    405 	  }
    406 	  break;
    407 	  
    408 	  case lowerAndChange:
    409 	    floor->direction = -1;
    410 	    floor->sector = sec;
    411 	    floor->speed = FLOORSPEED;
    412 	    floor->floordestheight = 
    413 		P_FindLowestFloorSurrounding(sec);
    414 	    floor->texture = sec->floorpic;
    415 
    416 	    for (i = 0; i < sec->linecount; i++)
    417 	    {
    418 		if ( twoSided(secnum, i) )
    419 		{
    420 		    if (getSide(secnum,i,0)->sector-::g->sectors == secnum)
    421 		    {
    422 			sec = getSector(secnum,i,1);
    423 
    424 			if (sec->floorheight == floor->floordestheight)
    425 			{
    426 			    floor->texture = sec->floorpic;
    427 			    floor->newspecial = sec->special;
    428 			    break;
    429 			}
    430 		    }
    431 		    else
    432 		    {
    433 			sec = getSector(secnum,i,0);
    434 
    435 			if (sec->floorheight == floor->floordestheight)
    436 			{
    437 			    floor->texture = sec->floorpic;
    438 			    floor->newspecial = sec->special;
    439 			    break;
    440 			}
    441 		    }
    442 		}
    443 	    }
    444 	  default:
    445 	    break;
    446 	}
    447     }
    448     return rtn;
    449 }
    450 
    451 
    452 
    453 
    454 //
    455 // BUILD A STAIRCASE!
    456 //
    457 int
    458 EV_BuildStairs
    459 ( line_t*	line,
    460   stair_e	type )
    461 {
    462     int			secnum;
    463     int			height;
    464     int			i;
    465     int			newsecnum;
    466     int			texture;
    467     int			ok;
    468     int			rtn;
    469     
    470     sector_t*		sec;
    471     sector_t*		tsec;
    472 
    473     floormove_t*	floor;
    474     
    475     fixed_t		stairsize = 0;
    476     fixed_t		speed = 0;
    477 
    478     secnum = -1;
    479     rtn = 0;
    480     while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
    481     {
    482 	sec = &::g->sectors[secnum];
    483 		
    484 	// ALREADY MOVING?  IF SO, KEEP GOING...
    485 	if (sec->specialdata)
    486 	    continue;
    487 	
    488 	// new floor thinker
    489 	rtn = 1;
    490 	floor = (floormove_t*)DoomLib::Z_Malloc(sizeof(*floor), PU_LEVEL, 0);
    491 	P_AddThinker (&floor->thinker);
    492 	sec->specialdata = floor;
    493 	floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
    494 	floor->direction = 1;
    495 	floor->sector = sec;
    496 	switch(type)
    497 	{
    498 	  case build8:
    499 	    speed = FLOORSPEED/4;
    500 	    stairsize = 8*FRACUNIT;
    501 	    break;
    502 	  case turbo16:
    503 	    speed = FLOORSPEED*4;
    504 	    stairsize = 16*FRACUNIT;
    505 	    break;
    506 	}
    507 	floor->speed = speed;
    508 	height = sec->floorheight + stairsize;
    509 	floor->floordestheight = height;
    510 		
    511 	texture = sec->floorpic;
    512 	
    513 	// Find next sector to raise
    514 	// 1.	Find 2-sided line with same sector side[0]
    515 	// 2.	Other side is the next sector to raise
    516 	do
    517 	{
    518 	    ok = 0;
    519 	    for (i = 0;i < sec->linecount;i++)
    520 	    {
    521 		if ( !((sec->lines[i])->flags & ML_TWOSIDED) )
    522 		    continue;
    523 					
    524 		tsec = (sec->lines[i])->frontsector;
    525 		newsecnum = tsec-::g->sectors;
    526 		
    527 		if (secnum != newsecnum)
    528 		    continue;
    529 
    530 		tsec = (sec->lines[i])->backsector;
    531 		newsecnum = tsec - ::g->sectors;
    532 
    533 		if (tsec->floorpic != texture)
    534 		    continue;
    535 					
    536 		height += stairsize;
    537 
    538 		if (tsec->specialdata)
    539 		    continue;
    540 					
    541 		sec = tsec;
    542 		secnum = newsecnum;
    543 		floor = (floormove_t*)DoomLib::Z_Malloc(sizeof(*floor), PU_LEVEL, 0);
    544 
    545 		P_AddThinker (&floor->thinker);
    546 
    547 		sec->specialdata = floor;
    548 		floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
    549 		floor->direction = 1;
    550 		floor->sector = sec;
    551 		floor->speed = speed;
    552 		floor->floordestheight = height;
    553 		ok = 1;
    554 		break;
    555 	    }
    556 	} while(ok);
    557     }
    558     return rtn;
    559 }
    560 
    561