DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

p_spec.cpp (26591B)


      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 #include "Main.h"
     32 
     33 #include <stdlib.h>
     34 
     35 #include "doomdef.h"
     36 #include "doomstat.h"
     37 
     38 #include "i_system.h"
     39 #include "z_zone.h"
     40 #include "m_argv.h"
     41 #include "m_random.h"
     42 #include "w_wad.h"
     43 
     44 #include "r_local.h"
     45 #include "p_local.h"
     46 
     47 #include "g_game.h"
     48 
     49 #include "s_sound.h"
     50 
     51 // State.
     52 #include "r_state.h"
     53 
     54 // Data.
     55 #include "sounds.h"
     56 
     57 #include "../../neo/d3xp/Game_Local.h"
     58 
     59 //
     60 // Animating textures and planes
     61 // There is another anim_t used in wi_stuff, unrelated. BLAH!
     62 // we now use anim_t2
     63 //
     64 
     65 //
     66 //      source animation definition
     67 //
     68 
     69 
     70 
     71 
     72 
     73 //
     74 // P_InitPicAnims
     75 //
     76 
     77 // Floor/ceiling animation sequences,
     78 //  defined by first and last frame,
     79 //  i.e. the flat (64x64 tile) name to
     80 //  be used.
     81 // The full animation sequence is given
     82 //  using all the flats between the start
     83 //  and end entry, in the order found in
     84 //  the WAD file.
     85 //
     86 const animdef_t		animdefs[] =
     87 {
     88 	{false,	"NUKAGE3",	"NUKAGE1",	8},
     89 	{false,	"FWATER4",	"FWATER1",	8},
     90 	{false,	"SWATER4",	"SWATER1", 	8},
     91 	{false,	"LAVA4",	"LAVA1",	8},
     92 	{false,	"BLOOD3",	"BLOOD1",	8},
     93 
     94 	// DOOM II flat animations.
     95 	{false,	"RROCK08",	"RROCK05",	8},		
     96 	{false,	"SLIME04",	"SLIME01",	8},
     97 	{false,	"SLIME08",	"SLIME05",	8},
     98 	{false,	"SLIME12",	"SLIME09",	8},
     99 
    100 	{true,	"BLODGR4",	"BLODGR1",	8},
    101 	{true,	"SLADRIP3",	"SLADRIP1",	8},
    102 
    103 	{true,	"BLODRIP4",	"BLODRIP1",	8},
    104 	{true,	"FIREWALL",	"FIREWALA",	8},
    105 	{true,	"GSTFONT3",	"GSTFONT1",	8},
    106 	{true,	"FIRELAVA",	"FIRELAV3",	8},
    107 	{true,	"FIREMAG3",	"FIREMAG1",	8},
    108 	{true,	"FIREBLU2",	"FIREBLU1",	8},
    109 	{true,	"ROCKRED3",	"ROCKRED1",	8},
    110 
    111 	{true,	"BFALL4",	"BFALL1",	8},
    112 	{true,	"SFALL4",	"SFALL1",	8},
    113 	{true,	"WFALL4",	"WFALL1",	8},
    114 	{true,	"DBRAIN4",	"DBRAIN1",	8},
    115 
    116 	{-1}
    117 };
    118 
    119 
    120 
    121 //
    122 //      Animating line specials
    123 //
    124 
    125 
    126 
    127 
    128 void P_InitPicAnims (void)
    129 {
    130 	int		i;
    131 
    132 
    133 	//	Init animation
    134 	::g->lastanim = ::g->anims;
    135 	for (i=0 ; animdefs[i].istexture != (qboolean)-1 ; i++)
    136 	{
    137 		if (animdefs[i].istexture)
    138 		{
    139 			// different episode ?
    140 			if (R_CheckTextureNumForName(animdefs[i].startname) == -1)
    141 				continue;	
    142 
    143 			::g->lastanim->picnum = R_TextureNumForName (animdefs[i].endname);
    144 			::g->lastanim->basepic = R_TextureNumForName (animdefs[i].startname);
    145 		}
    146 		else
    147 		{
    148 			if (W_CheckNumForName(animdefs[i].startname) == -1)
    149 				continue;
    150 
    151 			::g->lastanim->picnum = R_FlatNumForName (animdefs[i].endname);
    152 			::g->lastanim->basepic = R_FlatNumForName (animdefs[i].startname);
    153 		}
    154 
    155 		::g->lastanim->istexture = animdefs[i].istexture;
    156 		::g->lastanim->numpics = ::g->lastanim->picnum - ::g->lastanim->basepic + 1;
    157 
    158 		if (::g->lastanim->numpics < 2)
    159 			I_Error ("P_InitPicAnims: bad cycle from %s to %s",
    160 			animdefs[i].startname,
    161 			animdefs[i].endname);
    162 
    163 		::g->lastanim->speed = animdefs[i].speed;
    164 		::g->lastanim++;
    165 	}
    166 
    167 }
    168 
    169 
    170 
    171 //
    172 // UTILITIES
    173 //
    174 
    175 
    176 
    177 //
    178 // getSide()
    179 // Will return a side_t*
    180 //  given the number of the current sector,
    181 //  the line number, and the side (0/1) that you want.
    182 //
    183 side_t*
    184 getSide
    185 ( int		currentSector,
    186  int		line,
    187  int		side )
    188 {
    189 	return &::g->sides[ (::g->sectors[currentSector].lines[line])->sidenum[side] ];
    190 }
    191 
    192 
    193 //
    194 // getSector()
    195 // Will return a sector_t*
    196 //  given the number of the current sector,
    197 //  the line number and the side (0/1) that you want.
    198 //
    199 sector_t*
    200 getSector
    201 ( int		currentSector,
    202  int		line,
    203  int		side )
    204 {
    205 	return ::g->sides[ (::g->sectors[currentSector].lines[line])->sidenum[side] ].sector;
    206 }
    207 
    208 
    209 //
    210 // twoSided()
    211 // Given the sector number and the line number,
    212 //  it will tell you whether the line is two-sided or not.
    213 //
    214 int
    215 twoSided
    216 ( int	sector,
    217  int	line )
    218 {
    219 	return (::g->sectors[sector].lines[line])->flags & ML_TWOSIDED;
    220 }
    221 
    222 
    223 
    224 
    225 //
    226 // getNextSector()
    227 // Return sector_t * of sector next to current.
    228 // NULL if not two-sided line
    229 //
    230 sector_t*
    231 getNextSector
    232 ( line_t*	line,
    233  sector_t*	sec )
    234 {
    235 	if (!(line->flags & ML_TWOSIDED))
    236 		return NULL;
    237 
    238 	if (line->frontsector == sec)
    239 		return line->backsector;
    240 
    241 	return line->frontsector;
    242 }
    243 
    244 
    245 
    246 //
    247 // P_FindLowestFloorSurrounding()
    248 // FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS
    249 //
    250 fixed_t	P_FindLowestFloorSurrounding(sector_t* sec)
    251 {
    252 	int			i;
    253 	line_t*		check;
    254 	sector_t*		other;
    255 	fixed_t		floor = sec->floorheight;
    256 
    257 	for (i=0 ;i < sec->linecount ; i++)
    258 	{
    259 		check = sec->lines[i];
    260 		other = getNextSector(check,sec);
    261 
    262 		if (!other)
    263 			continue;
    264 
    265 		if (other->floorheight < floor)
    266 			floor = other->floorheight;
    267 	}
    268 	return floor;
    269 }
    270 
    271 
    272 
    273 //
    274 // P_FindHighestFloorSurrounding()
    275 // FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS
    276 //
    277 fixed_t	P_FindHighestFloorSurrounding(sector_t *sec)
    278 {
    279 	int			i;
    280 	line_t*		check;
    281 	sector_t*		other;
    282 	fixed_t		floor = -500*FRACUNIT;
    283 
    284 	for (i=0 ;i < sec->linecount ; i++)
    285 	{
    286 		check = sec->lines[i];
    287 		other = getNextSector(check,sec);
    288 
    289 		if (!other)
    290 			continue;
    291 
    292 		if (other->floorheight > floor)
    293 			floor = other->floorheight;
    294 	}
    295 	return floor;
    296 }
    297 
    298 
    299 
    300 //
    301 // P_FindNextHighestFloor
    302 // FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS
    303 // Note: this should be doable w/o a fixed array.
    304 
    305 // 20 adjoining ::g->sectors max!
    306 
    307 fixed_t
    308 P_FindNextHighestFloor
    309 ( sector_t*	sec,
    310  int		currentheight )
    311 {
    312 	int			i;
    313 	int			h;
    314 	int			min;
    315 	line_t*		check;
    316 	sector_t*		other;
    317 	fixed_t		height = currentheight;
    318 
    319 
    320 	fixed_t		heightlist[MAX_ADJOINING_SECTORS];		
    321 
    322 	for (i=0, h=0 ;i < sec->linecount ; i++)
    323 	{
    324 		check = sec->lines[i];
    325 		other = getNextSector(check,sec);
    326 
    327 		if (!other)
    328 			continue;
    329 
    330 		if (other->floorheight > height)
    331 			heightlist[h++] = other->floorheight;
    332 
    333 		// Check for overflow. Exit.
    334 		if ( h >= MAX_ADJOINING_SECTORS )
    335 		{
    336 			I_PrintfE("Sector with more than 20 adjoining sectors\n" );
    337 			break;
    338 		}
    339 	}
    340 
    341 	// Find lowest height in list
    342 	if (!h)
    343 		return currentheight;
    344 
    345 	min = heightlist[0];
    346 
    347 	// Range checking? 
    348 	for (i = 1;i < h;i++)
    349 		if (heightlist[i] < min)
    350 			min = heightlist[i];
    351 
    352 	return min;
    353 }
    354 
    355 
    356 //
    357 // FIND LOWEST CEILING IN THE SURROUNDING SECTORS
    358 //
    359 fixed_t
    360 P_FindLowestCeilingSurrounding(sector_t* sec)
    361 {
    362 	int			i;
    363 	line_t*		check;
    364 	sector_t*		other;
    365 	fixed_t		height = MAXINT;
    366 
    367 	for (i=0 ;i < sec->linecount ; i++)
    368 	{
    369 		check = sec->lines[i];
    370 		other = getNextSector(check,sec);
    371 
    372 		if (!other)
    373 			continue;
    374 
    375 		if (other->ceilingheight < height)
    376 			height = other->ceilingheight;
    377 	}
    378 	return height;
    379 }
    380 
    381 
    382 //
    383 // FIND HIGHEST CEILING IN THE SURROUNDING SECTORS
    384 //
    385 fixed_t	P_FindHighestCeilingSurrounding(sector_t* sec)
    386 {
    387 	int		i;
    388 	line_t*	check;
    389 	sector_t*	other;
    390 	fixed_t	height = 0;
    391 
    392 	for (i=0 ;i < sec->linecount ; i++)
    393 	{
    394 		check = sec->lines[i];
    395 		other = getNextSector(check,sec);
    396 
    397 		if (!other)
    398 			continue;
    399 
    400 		if (other->ceilingheight > height)
    401 			height = other->ceilingheight;
    402 	}
    403 	return height;
    404 }
    405 
    406 
    407 
    408 //
    409 // RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
    410 //
    411 int
    412 P_FindSectorFromLineTag
    413 ( line_t*	line,
    414  int		start )
    415 {
    416 	int	i;
    417 
    418 	for (i = start+1; i < ::g->numsectors; i++)
    419 		if (::g->sectors[i].tag == line->tag)
    420 			return i;
    421 
    422 	return -1;
    423 }
    424 
    425 
    426 
    427 
    428 //
    429 // Find minimum light from an adjacent sector
    430 //
    431 int
    432 P_FindMinSurroundingLight
    433 ( sector_t*	sector,
    434  int		max )
    435 {
    436 	int		i;
    437 	int		min;
    438 	line_t*	line;
    439 	sector_t*	check;
    440 
    441 	min = max;
    442 	for (i=0 ; i < sector->linecount ; i++)
    443 	{
    444 		line = sector->lines[i];
    445 		check = getNextSector(line,sector);
    446 
    447 		if (!check)
    448 			continue;
    449 
    450 		if (check->lightlevel < min)
    451 			min = check->lightlevel;
    452 	}
    453 	return min;
    454 }
    455 
    456 
    457 
    458 //
    459 // EVENTS
    460 // Events are operations triggered by using, crossing,
    461 // or shooting special ::g->lines, or by timed thinkers.
    462 //
    463 
    464 //
    465 // P_CrossSpecialLine - TRIGGER
    466 // Called every time a thing origin is about
    467 //  to cross a line with a non 0 special.
    468 //
    469 void
    470 P_CrossSpecialLine
    471 ( int		linenum,
    472  int		side,
    473  mobj_t*	thing )
    474 {
    475 	line_t*	line;
    476 	int		ok;
    477 
    478 	line = &::g->lines[linenum];
    479 
    480 	//	Triggers that other things can activate
    481 	if (!thing->player)
    482 	{
    483 		// Things that should NOT trigger specials...
    484 		switch(thing->type)
    485 		{
    486 		case MT_ROCKET:
    487 		case MT_PLASMA:
    488 		case MT_BFG:
    489 		case MT_TROOPSHOT:
    490 		case MT_HEADSHOT:
    491 		case MT_BRUISERSHOT:
    492 			return;
    493 			break;
    494 
    495 		default: break;
    496 		}
    497 
    498 		ok = 0;
    499 		switch(line->special)
    500 		{
    501 		case 39:	// TELEPORT TRIGGER
    502 		case 97:	// TELEPORT RETRIGGER
    503 		case 125:	// TELEPORT MONSTERONLY TRIGGER
    504 		case 126:	// TELEPORT MONSTERONLY RETRIGGER
    505 		case 4:	// RAISE DOOR
    506 		case 10:	// PLAT DOWN-WAIT-UP-STAY TRIGGER
    507 		case 88:	// PLAT DOWN-WAIT-UP-STAY RETRIGGER
    508 			ok = 1;
    509 			break;
    510 		}
    511 		if (!ok)
    512 			return;
    513 	}
    514 
    515 
    516 	// Note: could use some const's here.
    517 	switch (line->special)
    518 	{
    519 		// TRIGGERS.
    520 		// All from here to RETRIGGERS.
    521 	case 2:
    522 		// Open Door
    523 		EV_DoDoor(line,opened);
    524 		line->special = 0;
    525 		break;
    526 
    527 	case 3:
    528 		// Close Door
    529 		EV_DoDoor(line,closed);
    530 		line->special = 0;
    531 		break;
    532 
    533 	case 4:
    534 		// Raise Door
    535 		EV_DoDoor(line,normal);
    536 		line->special = 0;
    537 		break;
    538 
    539 	case 5:
    540 		// Raise Floor
    541 		EV_DoFloor(line,raiseFloor);
    542 		line->special = 0;
    543 		break;
    544 
    545 	case 6:
    546 		// Fast Ceiling Crush & Raise
    547 		EV_DoCeiling(line,fastCrushAndRaise);
    548 		line->special = 0;
    549 		break;
    550 
    551 	case 8:
    552 		// Build Stairs
    553 		EV_BuildStairs(line,build8);
    554 		line->special = 0;
    555 		break;
    556 
    557 	case 10:
    558 		// PlatDownWaitUp
    559 		EV_DoPlat(line,downWaitUpStay,0);
    560 		line->special = 0;
    561 		break;
    562 
    563 	case 12:
    564 		// Light Turn On - brightest near
    565 		EV_LightTurnOn(line,0);
    566 		line->special = 0;
    567 		break;
    568 
    569 	case 13:
    570 		// Light Turn On 255
    571 		EV_LightTurnOn(line,255);
    572 		line->special = 0;
    573 		break;
    574 
    575 	case 16:
    576 		// Close Door 30
    577 		EV_DoDoor(line,close30ThenOpen);
    578 		line->special = 0;
    579 		break;
    580 
    581 	case 17:
    582 		// Start Light Strobing
    583 		EV_StartLightStrobing(line);
    584 		line->special = 0;
    585 		break;
    586 
    587 	case 19:
    588 		// Lower Floor
    589 		EV_DoFloor(line,lowerFloor);
    590 		line->special = 0;
    591 		break;
    592 
    593 	case 22:
    594 		// Raise floor to nearest height and change texture
    595 		EV_DoPlat(line,raiseToNearestAndChange,0);
    596 		line->special = 0;
    597 		break;
    598 
    599 	case 25:
    600 		// Ceiling Crush and Raise
    601 		EV_DoCeiling(line,crushAndRaise);
    602 		line->special = 0;
    603 		break;
    604 
    605 	case 30:
    606 		// Raise floor to shortest texture height
    607 		//  on either side of ::g->lines.
    608 		EV_DoFloor(line,raiseToTexture);
    609 		line->special = 0;
    610 		break;
    611 
    612 	case 35:
    613 		// Lights Very Dark
    614 		EV_LightTurnOn(line,35);
    615 		line->special = 0;
    616 		break;
    617 
    618 	case 36:
    619 		// Lower Floor (TURBO)
    620 		EV_DoFloor(line,turboLower);
    621 		line->special = 0;
    622 		break;
    623 
    624 	case 37:
    625 		// LowerAndChange
    626 		EV_DoFloor(line,lowerAndChange);
    627 		line->special = 0;
    628 		break;
    629 
    630 	case 38:
    631 		// Lower Floor To Lowest
    632 		EV_DoFloor( line, lowerFloorToLowest );
    633 		line->special = 0;
    634 		break;
    635 
    636 	case 39:
    637 		// TELEPORT!
    638 		EV_Teleport( line, side, thing );
    639 		line->special = 0;
    640 		break;
    641 
    642 	case 40:
    643 		// RaiseCeilingLowerFloor
    644 		EV_DoCeiling( line, raiseToHighest );
    645 		EV_DoFloor( line, lowerFloorToLowest );
    646 		line->special = 0;
    647 		break;
    648 
    649 	case 44:
    650 		// Ceiling Crush
    651 		EV_DoCeiling( line, lowerAndCrush );
    652 		line->special = 0;
    653 		break;
    654 
    655 	case 52:
    656 		// EXIT!
    657 		// DHM - Nerve :: Don't exit level in death match, timelimit and fraglimit only
    658 		if ( !::g->deathmatch && ::g->gameaction != ga_completed ) {
    659 			G_ExitLevel();
    660 		}
    661 		break;
    662 
    663 	case 53:
    664 		// Perpetual Platform Raise
    665 		EV_DoPlat(line,perpetualRaise,0);
    666 		line->special = 0;
    667 		break;
    668 
    669 	case 54:
    670 		// Platform Stop
    671 		EV_StopPlat(line);
    672 		line->special = 0;
    673 		break;
    674 
    675 	case 56:
    676 		// Raise Floor Crush
    677 		EV_DoFloor(line,raiseFloorCrush);
    678 		line->special = 0;
    679 		break;
    680 
    681 	case 57:
    682 		// Ceiling Crush Stop
    683 		EV_CeilingCrushStop(line);
    684 		line->special = 0;
    685 		break;
    686 
    687 	case 58:
    688 		// Raise Floor 24
    689 		EV_DoFloor(line,raiseFloor24);
    690 		line->special = 0;
    691 		break;
    692 
    693 	case 59:
    694 		// Raise Floor 24 And Change
    695 		EV_DoFloor(line,raiseFloor24AndChange);
    696 		line->special = 0;
    697 		break;
    698 
    699 	case 104:
    700 		// Turn lights off in sector(tag)
    701 		EV_TurnTagLightsOff(line);
    702 		line->special = 0;
    703 		break;
    704 
    705 	case 108:
    706 		// Blazing Door Raise (faster than TURBO!)
    707 		EV_DoDoor (line,blazeRaise);
    708 		line->special = 0;
    709 		break;
    710 
    711 	case 109:
    712 		// Blazing Door Open (faster than TURBO!)
    713 		EV_DoDoor (line,blazeOpen);
    714 		line->special = 0;
    715 		break;
    716 
    717 	case 100:
    718 		// Build Stairs Turbo 16
    719 		EV_BuildStairs(line,turbo16);
    720 		line->special = 0;
    721 		break;
    722 
    723 	case 110:
    724 		// Blazing Door Close (faster than TURBO!)
    725 		EV_DoDoor (line,blazeClose);
    726 		line->special = 0;
    727 		break;
    728 
    729 	case 119:
    730 		// Raise floor to nearest surr. floor
    731 		EV_DoFloor(line,raiseFloorToNearest);
    732 		line->special = 0;
    733 		break;
    734 
    735 	case 121:
    736 		// Blazing PlatDownWaitUpStay
    737 		EV_DoPlat(line,blazeDWUS,0);
    738 		line->special = 0;
    739 		break;
    740 
    741 	case 124:
    742 		// Secret EXIT
    743 		if ( !::g->deathmatch && ::g->gameaction != ga_completed ) {
    744 			G_SecretExitLevel ();
    745 		}
    746 		break;
    747 
    748 	case 125:
    749 		// TELEPORT MonsterONLY
    750 		if (!thing->player)
    751 		{
    752 			EV_Teleport( line, side, thing );
    753 			line->special = 0;
    754 		}
    755 		break;
    756 
    757 	case 130:
    758 		// Raise Floor Turbo
    759 		EV_DoFloor(line,raiseFloorTurbo);
    760 		line->special = 0;
    761 		break;
    762 
    763 	case 141:
    764 		// Silent Ceiling Crush & Raise
    765 		EV_DoCeiling(line,silentCrushAndRaise);
    766 		line->special = 0;
    767 		break;
    768 
    769 		// RETRIGGERS.  All from here till end.
    770 	case 72:
    771 		// Ceiling Crush
    772 		EV_DoCeiling( line, lowerAndCrush );
    773 		break;
    774 
    775 	case 73:
    776 		// Ceiling Crush and Raise
    777 		EV_DoCeiling(line,crushAndRaise);
    778 		break;
    779 
    780 	case 74:
    781 		// Ceiling Crush Stop
    782 		EV_CeilingCrushStop(line);
    783 		break;
    784 
    785 	case 75:
    786 		// Close Door
    787 		EV_DoDoor(line,closed);
    788 		break;
    789 
    790 	case 76:
    791 		// Close Door 30
    792 		EV_DoDoor(line,close30ThenOpen);
    793 		break;
    794 
    795 	case 77:
    796 		// Fast Ceiling Crush & Raise
    797 		EV_DoCeiling(line,fastCrushAndRaise);
    798 		break;
    799 
    800 	case 79:
    801 		// Lights Very Dark
    802 		EV_LightTurnOn(line,35);
    803 		break;
    804 
    805 	case 80:
    806 		// Light Turn On - brightest near
    807 		EV_LightTurnOn(line,0);
    808 		break;
    809 
    810 	case 81:
    811 		// Light Turn On 255
    812 		EV_LightTurnOn(line,255);
    813 		break;
    814 
    815 	case 82:
    816 		// Lower Floor To Lowest
    817 		EV_DoFloor( line, lowerFloorToLowest );
    818 		break;
    819 
    820 	case 83:
    821 		// Lower Floor
    822 		EV_DoFloor(line,lowerFloor);
    823 		break;
    824 
    825 	case 84:
    826 		// LowerAndChange
    827 		EV_DoFloor(line,lowerAndChange);
    828 		break;
    829 
    830 	case 86:
    831 		// Open Door
    832 		EV_DoDoor(line,opened);
    833 		break;
    834 
    835 	case 87:
    836 		// Perpetual Platform Raise
    837 		EV_DoPlat(line,perpetualRaise,0);
    838 		break;
    839 
    840 	case 88:
    841 		// PlatDownWaitUp
    842 		EV_DoPlat(line,downWaitUpStay,0);
    843 		break;
    844 
    845 	case 89:
    846 		// Platform Stop
    847 		EV_StopPlat(line);
    848 		break;
    849 
    850 	case 90:
    851 		// Raise Door
    852 		EV_DoDoor(line,normal);
    853 		break;
    854 
    855 	case 91:
    856 		// Raise Floor
    857 		EV_DoFloor(line,raiseFloor);
    858 		break;
    859 
    860 	case 92:
    861 		// Raise Floor 24
    862 		EV_DoFloor(line,raiseFloor24);
    863 		break;
    864 
    865 	case 93:
    866 		// Raise Floor 24 And Change
    867 		EV_DoFloor(line,raiseFloor24AndChange);
    868 		break;
    869 
    870 	case 94:
    871 		// Raise Floor Crush
    872 		EV_DoFloor(line,raiseFloorCrush);
    873 		break;
    874 
    875 	case 95:
    876 		// Raise floor to nearest height
    877 		// and change texture.
    878 		EV_DoPlat(line,raiseToNearestAndChange,0);
    879 		break;
    880 
    881 	case 96:
    882 		// Raise floor to shortest texture height
    883 		// on either side of ::g->lines.
    884 		EV_DoFloor(line,raiseToTexture);
    885 		break;
    886 
    887 	case 97:
    888 		// TELEPORT!
    889 		EV_Teleport( line, side, thing );
    890 		break;
    891 
    892 	case 98:
    893 		// Lower Floor (TURBO)
    894 		EV_DoFloor(line,turboLower);
    895 		break;
    896 
    897 	case 105:
    898 		// Blazing Door Raise (faster than TURBO!)
    899 		EV_DoDoor (line,blazeRaise);
    900 		break;
    901 
    902 	case 106:
    903 		// Blazing Door Open (faster than TURBO!)
    904 		EV_DoDoor (line,blazeOpen);
    905 		break;
    906 
    907 	case 107:
    908 		// Blazing Door Close (faster than TURBO!)
    909 		EV_DoDoor (line,blazeClose);
    910 		break;
    911 
    912 	case 120:
    913 		// Blazing PlatDownWaitUpStay.
    914 		EV_DoPlat(line,blazeDWUS,0);
    915 		break;
    916 
    917 	case 126:
    918 		// TELEPORT MonsterONLY.
    919 		if (!thing->player)
    920 			EV_Teleport( line, side, thing );
    921 		break;
    922 
    923 	case 128:
    924 		// Raise To Nearest Floor
    925 		EV_DoFloor(line,raiseFloorToNearest);
    926 		break;
    927 
    928 	case 129:
    929 		// Raise Floor Turbo
    930 		EV_DoFloor(line,raiseFloorTurbo);
    931 		break;
    932 	}
    933 }
    934 
    935 
    936 
    937 //
    938 // P_ShootSpecialLine - IMPACT SPECIALS
    939 // Called when a thing shoots a special line.
    940 //
    941 void
    942 P_ShootSpecialLine
    943 ( mobj_t*	thing,
    944  line_t*	line )
    945 {
    946 	int		ok;
    947 
    948 	//	Impacts that other things can activate.
    949 	if (!thing->player)
    950 	{
    951 		ok = 0;
    952 		switch(line->special)
    953 		{
    954 		case 46:
    955 			// OPEN DOOR IMPACT
    956 			ok = 1;
    957 			break;
    958 		}
    959 		if (!ok)
    960 			return;
    961 	}
    962 
    963 	switch(line->special)
    964 	{
    965 	case 24:
    966 		// RAISE FLOOR
    967 		EV_DoFloor(line,raiseFloor);
    968 		P_ChangeSwitchTexture(line,0);
    969 		break;
    970 
    971 	case 46:
    972 		// OPEN DOOR
    973 		EV_DoDoor(line,opened);
    974 		P_ChangeSwitchTexture(line,1);
    975 		break;
    976 
    977 	case 47:
    978 		// RAISE FLOOR NEAR AND CHANGE
    979 		EV_DoPlat(line,raiseToNearestAndChange,0);
    980 		P_ChangeSwitchTexture(line,0);
    981 		break;
    982 	}
    983 }
    984 
    985 
    986 
    987 //
    988 // P_PlayerInSpecialSector
    989 // Called every tic frame
    990 //  that the player origin is in a special sector
    991 //
    992 void P_PlayerInSpecialSector (player_t* player)
    993 {
    994 	sector_t*	sector;
    995 
    996 	sector = player->mo->subsector->sector;
    997 
    998 	// Falling, not all the way down yet?
    999 	if (player->mo->z != sector->floorheight)
   1000 		return;	
   1001 
   1002 	// Has hitten ground.
   1003 	switch (sector->special)
   1004 	{
   1005 	case 5:
   1006 		// HELLSLIME DAMAGE
   1007 		if (!player->powers[pw_ironfeet])
   1008 			if (!(::g->leveltime&0x1f))
   1009 				P_DamageMobj (player->mo, NULL, NULL, 10);
   1010 		break;
   1011 
   1012 	case 7:
   1013 		// NUKAGE DAMAGE
   1014 		if (!player->powers[pw_ironfeet])
   1015 			if (!(::g->leveltime&0x1f))
   1016 				P_DamageMobj (player->mo, NULL, NULL, 5);
   1017 		break;
   1018 
   1019 	case 16:
   1020 		// SUPER HELLSLIME DAMAGE
   1021 	case 4:
   1022 		// STROBE HURT
   1023 		if (!player->powers[pw_ironfeet]
   1024 		|| (P_Random()<5) )
   1025 		{
   1026 			if (!(::g->leveltime&0x1f))
   1027 				P_DamageMobj (player->mo, NULL, NULL, 20);
   1028 		}
   1029 		break;
   1030 
   1031 	case 9:
   1032 		// SECRET SECTOR
   1033 		player->secretcount++;
   1034 		sector->special = 0;
   1035 
   1036 
   1037 		if ( !::g->demoplayback && ( ::g->usergame && !::g->netgame ) ) {
   1038 			// DHM - Nerve :: Let's give achievements in real time in Doom 2
   1039 			if ( !common->IsMultiplayer() ) {
   1040 				switch( DoomLib::GetGameSKU() ) {
   1041 					case GAME_SKU_DOOM1_BFG: {
   1042 						// Removing trophies for DOOM and DOOM II BFG due to point limit.
   1043 						//gameLocal->UnlockAchievement( Doom1BFG_Trophies::SCOUT_FIND_ANY_SECRET );
   1044 						break;
   1045 					}
   1046 					case GAME_SKU_DOOM2_BFG: {
   1047 						//gameLocal->UnlockAchievement( Doom2BFG_Trophies::IMPORTANT_LOOKING_DOOR_FIND_ANY_SECRET );
   1048 						idAchievementManager::LocalUser_CompleteAchievement(ACHIEVEMENT_DOOM2_IMPORTANT_LOOKING_DOOR_FIND_ANY_SECRET );
   1049 						break;
   1050 					}
   1051 					case GAME_SKU_DCC: {
   1052 						// Not on PC.
   1053 						//gameLocal->UnlockAchievement( DOOM_ACHIEVEMENT_FIND_SECRET );
   1054 						break;
   1055 					}
   1056 					default: {
   1057 						// No unlocks for other SKUs.
   1058 						break;
   1059 					}
   1060 				}
   1061 			}
   1062 		}
   1063 
   1064 
   1065 		break;
   1066 
   1067 	case 11:
   1068 		// EXIT SUPER DAMAGE! (for E1M8 finale)
   1069 		player->cheats &= ~CF_GODMODE;
   1070 
   1071 		if (!(::g->leveltime&0x1f))
   1072 			P_DamageMobj (player->mo, NULL, NULL, 20);
   1073 
   1074 		if (player->health <= 10)
   1075 			G_ExitLevel();
   1076 		break;
   1077 
   1078 	default:
   1079 		I_Error ("P_PlayerInSpecialSector: "
   1080 			"unknown special %i",
   1081 			sector->special);
   1082 		break;
   1083 	};
   1084 }
   1085 
   1086 
   1087 
   1088 
   1089 //
   1090 // P_UpdateSpecials
   1091 // Animate planes, scroll walls, etc.
   1092 //
   1093 int PlayerFrags( int playernum ) {
   1094 	int	frags = 0;
   1095 
   1096 	for( int i=0 ; i<MAXPLAYERS ; i++) {
   1097 		if ( i != playernum ) {
   1098 			frags += ::g->players[playernum].frags[i];
   1099 		}
   1100 	}
   1101 
   1102 	frags -= ::g->players[playernum].frags[playernum];
   1103 
   1104 	return frags;
   1105 }
   1106 
   1107 void P_UpdateSpecials (void)
   1108 {
   1109 	anim_t2*	anim;
   1110 	int		pic;
   1111 	int		i;
   1112 	line_t*	line;
   1113 
   1114 
   1115 	//	LEVEL TIMER
   1116 	if (::g->levelTimer == true)
   1117 	{
   1118 		::g->levelTimeCount--;
   1119 		if (!::g->levelTimeCount)
   1120 			G_ExitLevel();
   1121 	}
   1122 
   1123 	// DHM - Nerve :: FRAG COUNT
   1124 	if ( ::g->deathmatch && ::g->levelFragCount > 0 ) {
   1125 		bool fragCountHit = false;
   1126 
   1127 		for ( int i=0; i<MAXPLAYERS; i++ ) {
   1128 			if ( ::g->playeringame[i] ) {
   1129 				if ( PlayerFrags(i) >= ::g->levelFragCount ) {
   1130 					fragCountHit = true;
   1131 				}
   1132 			}
   1133 		}
   1134 
   1135 		if ( fragCountHit ) {
   1136 			G_ExitLevel();
   1137 		}
   1138 	}
   1139 
   1140 	//	ANIMATE FLATS AND TEXTURES GLOBALLY
   1141 	for (anim = ::g->anims ; anim < ::g->lastanim ; anim++)
   1142 	{
   1143 		for (i=anim->basepic ; i<anim->basepic+anim->numpics ; i++)
   1144 		{
   1145 			pic = anim->basepic + ( (::g->leveltime/anim->speed + i)%anim->numpics );
   1146 			if (anim->istexture)
   1147 				::g->texturetranslation[i] = pic;
   1148 			else
   1149 				::g->flattranslation[i] = pic;
   1150 		}
   1151 	}
   1152 
   1153 
   1154 	//	ANIMATE LINE SPECIALS
   1155 	for (i = 0; i < ::g->numlinespecials; i++)
   1156 	{
   1157 		line = ::g->linespeciallist[i];
   1158 		switch(line->special)
   1159 		{
   1160 		case 48:
   1161 			// EFFECT FIRSTCOL SCROLL +
   1162 			::g->sides[line->sidenum[0]].textureoffset += FRACUNIT;
   1163 			break;
   1164 		}
   1165 	}
   1166 
   1167 
   1168 	//	DO BUTTONS
   1169 	for (i = 0; i < MAXBUTTONS; i++)
   1170 		if (::g->buttonlist[i].btimer)
   1171 		{
   1172 			::g->buttonlist[i].btimer--;
   1173 			if (!::g->buttonlist[i].btimer)
   1174 			{
   1175 				switch(::g->buttonlist[i].where)
   1176 				{
   1177 				case top:
   1178 					::g->sides[::g->buttonlist[i].line->sidenum[0]].toptexture =
   1179 						::g->buttonlist[i].btexture;
   1180 					break;
   1181 
   1182 				case middle:
   1183 					::g->sides[::g->buttonlist[i].line->sidenum[0]].midtexture =
   1184 						::g->buttonlist[i].btexture;
   1185 					break;
   1186 
   1187 				case bottom:
   1188 					::g->sides[::g->buttonlist[i].line->sidenum[0]].bottomtexture =
   1189 						::g->buttonlist[i].btexture;
   1190 					break;
   1191 				}
   1192 				S_StartSound((mobj_t *)&::g->buttonlist[i].soundorg,sfx_swtchn);
   1193 				memset(&::g->buttonlist[i],0,sizeof(button_t));
   1194 			}
   1195 		}
   1196 
   1197 }
   1198 
   1199 
   1200 
   1201 //
   1202 // Special Stuff that can not be categorized
   1203 //
   1204 int EV_DoDonut(line_t*	line)
   1205 {
   1206 	sector_t*		s1;
   1207 	sector_t*		s2;
   1208 	sector_t*		s3;
   1209 	int			secnum;
   1210 	int			rtn;
   1211 	int			i;
   1212 	floormove_t*	floor;
   1213 
   1214 	secnum = -1;
   1215 	rtn = 0;
   1216 	while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
   1217 	{
   1218 		s1 = &::g->sectors[secnum];
   1219 
   1220 		// ALREADY MOVING?  IF SO, KEEP GOING...
   1221 		if (s1->specialdata)
   1222 			continue;
   1223 
   1224 		rtn = 1;
   1225 		s2 = getNextSector(s1->lines[0],s1);
   1226 		for (i = 0;i < s2->linecount;i++)
   1227 		{
   1228 			if ((!(s2->lines[i]->flags & ML_TWOSIDED)) ||
   1229 				(s2->lines[i]->backsector == s1))
   1230 				continue;
   1231 			s3 = s2->lines[i]->backsector;
   1232 
   1233 			//	Spawn rising slime
   1234 			floor = (floormove_t*)DoomLib::Z_Malloc (sizeof(*floor), PU_LEVEL, 0);
   1235 			P_AddThinker (&floor->thinker);
   1236 			s2->specialdata = floor;
   1237 			floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
   1238 			floor->type = donutRaise;
   1239 			floor->crush = false;
   1240 			floor->direction = 1;
   1241 			floor->sector = s2;
   1242 			floor->speed = FLOORSPEED / 2;
   1243 			floor->texture = s3->floorpic;
   1244 			floor->newspecial = 0;
   1245 			floor->floordestheight = s3->floorheight;
   1246 
   1247 			//	Spawn lowering donut-hole
   1248 			floor = (floormove_t*)DoomLib::Z_Malloc (sizeof(*floor), PU_LEVEL, 0);
   1249 			P_AddThinker (&floor->thinker);
   1250 			s1->specialdata = floor;
   1251 			floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
   1252 			floor->type = lowerFloor;
   1253 			floor->crush = false;
   1254 			floor->direction = -1;
   1255 			floor->sector = s1;
   1256 			floor->speed = FLOORSPEED / 2;
   1257 			floor->floordestheight = s3->floorheight;
   1258 			break;
   1259 		}
   1260 	}
   1261 	return rtn;
   1262 }
   1263 
   1264 
   1265 
   1266 //
   1267 // SPECIAL SPAWNING
   1268 //
   1269 
   1270 //
   1271 // P_SpawnSpecials
   1272 // After the map has been loaded, scan for specials
   1273 //  that spawn thinkers
   1274 //
   1275 
   1276 
   1277 // Parses command line parameters.
   1278 void P_SpawnSpecials (void)
   1279 {
   1280 	sector_t*	sector;
   1281 	int		i;
   1282 	int		episode;
   1283 
   1284 	episode = 1;
   1285 	if (W_CheckNumForName("texture2") >= 0)
   1286 		episode = 2;
   1287 
   1288 
   1289 	// See if -TIMER needs to be used.
   1290 	::g->levelTimer = false;
   1291 
   1292 	i = M_CheckParm("-avg");
   1293 	if (i && ::g->deathmatch)
   1294 	{
   1295 		::g->levelTimer = true;
   1296 		::g->levelTimeCount = 20 * 60 * TICRATE;
   1297 	}
   1298 
   1299 	//i = M_CheckParm("-timer");
   1300 	//if (i && ::g->deathmatch)
   1301 #ifdef ID_ENABLE_DOOM_CLASSIC_NETWORKING
   1302 	const int timeLimit = session->GetActingGameStateLobbyBase().GetMatchParms().gameTimeLimit;
   1303 #else
   1304 	const int timeLimit = 0;
   1305 #endif
   1306 	if (timeLimit != 0 && g->deathmatch)
   1307 	{
   1308 		int	time;
   1309 		//time = atoi(::g->myargv[i+1]) * 60 * 35;
   1310 		time = timeLimit * 60 * TICRATE;
   1311 		::g->levelTimer = true;
   1312 		::g->levelTimeCount = time;
   1313 	}
   1314 
   1315 	//i = M_CheckParm("-fraglimit");
   1316 	//if (i && ::g->deathmatch)
   1317 #ifdef ID_ENABLE_DOOM_CLASSIC_NETWORKING
   1318 	const int fragLimit = gameLocal->GetMatchParms().GetScoreLimit();
   1319 #else
   1320 	const int fragLimit = 0;
   1321 #endif
   1322 	if (fragLimit != 0 && ::g->deathmatch)
   1323 	{
   1324 		//::g->levelFragCount = atoi(::g->myargv[i+1]);
   1325 		::g->levelFragCount = fragLimit;
   1326 	} else {
   1327 		::g->levelFragCount = 0;
   1328 	}
   1329 
   1330 	//	Init special SECTORs.
   1331 	sector = ::g->sectors;
   1332 	for (i=0 ; i < ::g->numsectors ; i++, sector++)
   1333 	{
   1334 		if (!sector->special)
   1335 			continue;
   1336 
   1337 		switch (sector->special)
   1338 		{
   1339 		case 1:
   1340 			// FLICKERING LIGHTS
   1341 			P_SpawnLightFlash (sector);
   1342 			break;
   1343 
   1344 		case 2:
   1345 			// STROBE FAST
   1346 			P_SpawnStrobeFlash(sector,FASTDARK,0);
   1347 			break;
   1348 
   1349 		case 3:
   1350 			// STROBE SLOW
   1351 			P_SpawnStrobeFlash(sector,SLOWDARK,0);
   1352 			break;
   1353 
   1354 		case 4:
   1355 			// STROBE FAST/DEATH SLIME
   1356 			P_SpawnStrobeFlash(sector,FASTDARK,0);
   1357 			sector->special = 4;
   1358 			break;
   1359 
   1360 		case 8:
   1361 			// GLOWING LIGHT
   1362 			P_SpawnGlowingLight(sector);
   1363 			break;
   1364 		case 9:
   1365 			// SECRET SECTOR
   1366 			::g->totalsecret++;
   1367 			break;
   1368 
   1369 		case 10:
   1370 			// DOOR CLOSE IN 30 SECONDS
   1371 			P_SpawnDoorCloseIn30 (sector);
   1372 			break;
   1373 
   1374 		case 12:
   1375 			// SYNC STROBE SLOW
   1376 			P_SpawnStrobeFlash (sector, SLOWDARK, 1);
   1377 			break;
   1378 
   1379 		case 13:
   1380 			// SYNC STROBE FAST
   1381 			P_SpawnStrobeFlash (sector, FASTDARK, 1);
   1382 			break;
   1383 
   1384 		case 14:
   1385 			// DOOR RAISE IN 5 MINUTES
   1386 			P_SpawnDoorRaiseIn5Mins (sector, i);
   1387 			break;
   1388 
   1389 		case 17:
   1390 			P_SpawnFireFlicker(sector);
   1391 			break;
   1392 		}
   1393 	}
   1394 
   1395 
   1396 	//	Init line EFFECTs
   1397 	::g->numlinespecials = 0;
   1398 	for (i = 0;i < ::g->numlines; i++)
   1399 	{
   1400 		switch(::g->lines[i].special)
   1401 		{
   1402 		case 48:
   1403 			// EFFECT FIRSTCOL SCROLL+
   1404 			::g->linespeciallist[::g->numlinespecials] = &::g->lines[i];
   1405 			::g->numlinespecials++;
   1406 			break;
   1407 		}
   1408 	}
   1409 
   1410 
   1411 	//	Init other misc stuff
   1412 	for (i = 0;i < MAXCEILINGS;i++)
   1413 		::g->activeceilings[i] = NULL;
   1414 
   1415 	for (i = 0;i < MAXPLATS;i++)
   1416 		::g->activeplats[i] = NULL;
   1417 
   1418 	for (i = 0;i < MAXBUTTONS;i++)
   1419 		memset(&::g->buttonlist[i],0,sizeof(button_t));
   1420 
   1421 	// UNUSED: no horizonal sliders.
   1422 	//	P_InitSlidingDoorFrames();
   1423 }
   1424