diff options
Diffstat (limited to 'src/strife/p_spec.c')
-rw-r--r-- | src/strife/p_spec.c | 2002 |
1 files changed, 2002 insertions, 0 deletions
diff --git a/src/strife/p_spec.c b/src/strife/p_spec.c new file mode 100644 index 00000000..e59a5b05 --- /dev/null +++ b/src/strife/p_spec.c @@ -0,0 +1,2002 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005 Simon Howard +// +// This program 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 2 +// of the License, or (at your option) any later version. +// +// This program 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 this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// +// DESCRIPTION: +// Implements special effects: +// Texture animation, height or lighting changes +// according to adjacent sectors, respective +// utility functions, etc. +// Line Tag handling. Line and Sector triggers. +// +//----------------------------------------------------------------------------- + + +#include <stdlib.h> + +#include "doomdef.h" +#include "doomstat.h" + +#include "deh_main.h" +#include "i_system.h" +#include "z_zone.h" +#include "m_argv.h" +#include "m_misc.h" +#include "m_random.h" +#include "w_wad.h" + +#include "r_local.h" +#include "p_local.h" + +#include "g_game.h" + +#include "s_sound.h" + +// State. +#include "r_state.h" + +// Data. +#include "sounds.h" + +// [STRIFE] +#include "hu_stuff.h" +#include "p_dialog.h" + + +// +// Animating textures and planes +// There is another anim_t used in wi_stuff, unrelated. +// +typedef struct +{ + boolean istexture; + int picnum; + int basepic; + int numpics; + int speed; + +} anim_t; + +// +// source animation definition +// +typedef struct +{ + int istexture; // if false, it is a flat + char endname[9]; + char startname[9]; + int speed; +} animdef_t; + + +// haleyjd 08/30/10: [STRIFE] MAXANIMS raised from 32 to 40 +#define MAXANIMS 40 + +// +// P_InitPicAnims +// + +// Floor/ceiling animation sequences, +// defined by first and last frame, +// i.e. the flat (64x64 tile) name to +// be used. +// The full animation sequence is given +// using all the flats between the start +// and end entry, in the order found in +// the WAD file. +// +// haleyjd 08/29/10: [STRIFE] Changed animdefs. +// +animdef_t animdefs[] = +{ + { false, "F_SCANR8", "F_SCANR5", 4}, + { false, "F_WATR03", "F_WATR01", 8}, + { false, "F_PWATR3", "F_PWATR1", 11}, + { false, "F_SCANR4", "F_SCANR1", 4}, + { true, "SCAN08", "SCAN05", 4}, + { true, "SWTRMG03", "SWTRMG01", 4}, + { true, "SCAN04", "SCAN01", 4}, + { true, "COMP04", "COMP01", 4}, + { true, "COMP08", "COMP05", 6}, + { true, "COMP12", "COMP09", 11}, + { true, "COMP16", "COMP13", 12}, + { true, "COMP20", "COMP17", 12}, + { true, "COMP24", "COMP21", 12}, + { true, "COMP28", "COMP25", 12}, + { true, "COMP32", "COMP29", 12}, + { true, "COMP37", "COMP33", 12}, + { true, "COMP41", "COMP38", 12}, + { true, "COMP49", "COMP42", 10}, + { true, "BRKGRY16", "BRKGRY13", 10}, + { true, "BRNSCN04", "BRNSCN01", 10}, + { true, "CONCRT12", "CONCRT09", 11}, + { true, "CONCRT25", "CONCRT22", 11}, + { true, "WALPMP02", "WALPMP01", 16}, + { true, "WALTEK17", "WALTEK16", 8}, + { true, "FORCE04", "FORCE01", 4}, + { true, "FORCE08", "FORCE05", 4}, + { true, "FAN02", "FAN01", 4}, + { false, "F_VWATR3", "P_VWATR1", 4}, + { false, "F_HWATR3", "F_HWATR1", 4}, + { false, "F_TELE2", "F_TELE1", 4}, + { false, "F_FAN2", "F_FAN1", 4}, + { false, "F_CONVY2", "F_CONVY1", 4}, + { false, "F_RDALN4", "F_RDALN1", 4}, + { -1, "", "", 0}, +}; + +anim_t anims[MAXANIMS]; +anim_t* lastanim; + +// +// Animating line specials +// +// haleyjd 08/29/10: [STRIFE] MAXLINEANIMS raised from 64 to 96 +#define MAXLINEANIMS 96 + +extern short numlinespecials; +extern line_t* linespeciallist[MAXLINEANIMS]; + + + +void P_InitPicAnims (void) +{ + int i; + + + // Init animation + lastanim = anims; + for (i=0 ; animdefs[i].istexture != -1 ; i++) + { + char *startname, *endname; + + startname = DEH_String(animdefs[i].startname); + endname = DEH_String(animdefs[i].endname); + + if (animdefs[i].istexture) + { + // different episode ? + if (R_CheckTextureNumForName(startname) == -1) + continue; + + lastanim->picnum = R_TextureNumForName(endname); + lastanim->basepic = R_TextureNumForName(startname); + } + else + { + if (W_CheckNumForName(startname) == -1) + continue; + + lastanim->picnum = R_FlatNumForName(endname); + lastanim->basepic = R_FlatNumForName(startname); + } + + lastanim->istexture = animdefs[i].istexture; + lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; + + if (lastanim->numpics < 2) + I_Error ("P_InitPicAnims: bad cycle from %s to %s", + startname, endname); + + lastanim->speed = animdefs[i].speed; + lastanim++; + } + +} + +// villsa [STRIFE] terrain type definitions +typedef struct +{ + char* flat; + int type; + int num; +} terraintype_t; + +terraintype_t terraintypes[] = +{ + { "F_WATR03", FLOOR_WATER, -1 }, + { "F_WATR02", FLOOR_WATER, -1 }, + { "F_WATR01", FLOOR_WATER, -1 }, + { "F_VWATR3", FLOOR_WATER, -1 }, + { "F_VWATR2", FLOOR_WATER, -1 }, + { "P_VWATR1", FLOOR_WATER, -1 }, + { "F_HWATR3", FLOOR_WATER, -1 }, + { "F_HWATR2", FLOOR_WATER, -1 }, + { "F_HWATR1", FLOOR_WATER, -1 }, + { "F_PWATR3", FLOOR_SLIME, -1 }, + { "F_PWATR2", FLOOR_SLIME, -1 }, + { "F_PWATR1", FLOOR_SLIME, -1 }, + { "END", FLOOR_END, -1 }, +}; + +// +// P_GetTerrainType +// villsa [STRIFE] new function +// + +terraintype_e P_GetTerrainType(mobj_t* mobj) +{ + int i = 0; + subsector_t* ss = mobj->subsector; + + if(mobj->z <= ss->sector->floorheight && + terraintypes[0].type != FLOOR_END) + { + while(ss->sector->floorpic != terraintypes[i].num) + { + if(terraintypes[i+1].type == FLOOR_END) + return FLOOR_SOLID; + + i++; + } + + return terraintypes[i].type; + } + + return FLOOR_SOLID; +} + +// +// P_InitTerrainTypes +// villsa [STRIFE] new function +// Initialize terrain types +// + +void P_InitTerrainTypes(void) +{ + int pic = 0; + int i = 0; + + if(terraintypes[0].type != FLOOR_END) + { + while(terraintypes[i].type != FLOOR_END) + { + terraintypes[i].num = R_FlatNumForName(terraintypes[i].flat); + i++; + } + } +} + + + +// +// UTILITIES +// + + + +// +// getSide() +// Will return a side_t* +// given the number of the current sector, +// the line number, and the side (0/1) that you want. +// +side_t* +getSide +( int currentSector, + int line, + int side ) +{ + return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ]; +} + + +// +// getSector() +// Will return a sector_t* +// given the number of the current sector, +// the line number and the side (0/1) that you want. +// +sector_t* +getSector +( int currentSector, + int line, + int side ) +{ + return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector; +} + + +// +// twoSided() +// Given the sector number and the line number, +// it will tell you whether the line is two-sided or not. +// +int +twoSided +( int sector, + int line ) +{ + return (sectors[sector].lines[line])->flags & ML_TWOSIDED; +} + + + + +// +// getNextSector() +// Return sector_t * of sector next to current. +// NULL if not two-sided line +// +sector_t* +getNextSector +( line_t* line, + sector_t* sec ) +{ + if (!(line->flags & ML_TWOSIDED)) + return NULL; + + if (line->frontsector == sec) + return line->backsector; + + return line->frontsector; +} + + + +// +// P_FindLowestFloorSurrounding() +// FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS +// +fixed_t P_FindLowestFloorSurrounding(sector_t* sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t floor = sec->floorheight; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->floorheight < floor) + floor = other->floorheight; + } + return floor; +} + + + +// +// P_FindHighestFloorSurrounding() +// FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS +// +fixed_t P_FindHighestFloorSurrounding(sector_t *sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t floor = -500*FRACUNIT; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->floorheight > floor) + floor = other->floorheight; + } + return floor; +} + + + +// +// P_FindNextHighestFloor +// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS +// Note: this should be doable w/o a fixed array. + +// Thanks to entryway for the Vanilla overflow emulation. + +// 20 adjoining sectors max! +#define MAX_ADJOINING_SECTORS 20 + +fixed_t +P_FindNextHighestFloor +( sector_t* sec, + int currentheight ) +{ + int i; + int h; + int min; + line_t* check; + sector_t* other; + fixed_t height = currentheight; + fixed_t heightlist[MAX_ADJOINING_SECTORS + 2]; + + for (i=0, h=0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->floorheight > height) + { + // Emulation of memory (stack) overflow + if (h == MAX_ADJOINING_SECTORS + 1) + { + height = other->floorheight; + } + else if (h == MAX_ADJOINING_SECTORS + 2) + { + // Fatal overflow: game crashes at 22 textures + I_Error("Sector with more than 22 adjoining sectors. " + "Vanilla will crash here"); + } + + heightlist[h++] = other->floorheight; + } + } + + // Find lowest height in list + if (!h) + { + return currentheight; + } + + min = heightlist[0]; + + // Range checking? + for (i = 1; i < h; i++) + { + if (heightlist[i] < min) + { + min = heightlist[i]; + } + } + + return min; +} + +// +// FIND LOWEST CEILING IN THE SURROUNDING SECTORS +// +fixed_t +P_FindLowestCeilingSurrounding(sector_t* sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t height = INT_MAX; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->ceilingheight < height) + height = other->ceilingheight; + } + return height; +} + + +// +// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS +// +fixed_t P_FindHighestCeilingSurrounding(sector_t* sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t height = 0; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->ceilingheight > height) + height = other->ceilingheight; + } + return height; +} + + + +// +// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO +// +int +P_FindSectorFromLineTag +( line_t* line, + int start ) +{ + int i; + + for (i=start+1;i<numsectors;i++) + if (sectors[i].tag == line->tag) + return i; + + return -1; +} + + + + +// +// Find minimum light from an adjacent sector +// +int +P_FindMinSurroundingLight +( sector_t* sector, + int max ) +{ + int i; + int min; + line_t* line; + sector_t* check; + + min = max; + for (i=0 ; i < sector->linecount ; i++) + { + line = sector->lines[i]; + check = getNextSector(line,sector); + + if (!check) + continue; + + if (check->lightlevel < min) + min = check->lightlevel; + } + return min; +} + + + +// +// EVENTS +// Events are operations triggered by using, crossing, +// or shooting special lines, or by timed thinkers. +// + +// [STRIFE] +static char crosslinestr[90]; + +// +// P_CrossSpecialLine - TRIGGER +// Called every time a thing origin is about +// to cross a line with a non 0 special. +// +void +P_CrossSpecialLine +( int linenum, + int side, + mobj_t* thing ) +{ + line_t* line; + side_t* sidedef; // [STRIFE] + int flag; // [STRIFE] + int ok; + + line = &lines[linenum]; + + // haleyjd 09/21/10: corpses and missiles cannot activate any cross-over + // line types, *except* 182 (which is for the sake of missiles). + if((thing->flags & (MF_MISSILE|MF_CORPSE)) && line->special != 182) + return; + + // Triggers that other things can activate + if (!thing->player) + { + // Things that should NOT trigger specials... + // villsa [STRIFE] unused + // haleyjd: removed dead switch. Strife only excludes missiles and + // corpses, which is handled above. + + ok = 0; + + // [STRIFE] Added several line types. Removed none. + switch(line->special) + { + case 97: // TELEPORT RETRIGGER + case 185: // haleyjd: [STRIFE] Silent Teleport (used for Converter) + case 195: // haleyjd: [STRIFE] Silent Teleport and Change Zombie + case 231: // haleyjd: [STRIFE] WR Teleport (Silent at Source) + case 125: // TELEPORT MONSTERONLY TRIGGER + case 126: // TELEPORT MONSTERONLY RETRIGGER + case 182: // haleyjd: [STRIFE] Break glass - it's a W1 type too! + case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER + case 39: // TELEPORT TRIGGER + case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER + case 4: // RAISE DOOR + ok = 1; + break; + } + if (!ok) + return; + } + + + // Note: could use some const's here. + switch (line->special) + { + // + // TRIGGERS. + // All from here to RETRIGGERS. + // + case 230: + // haleyjd 09/21/10: [STRIFE] W1 Open Door if Quest + sidedef = &sides[line->sidenum[0]]; + flag = (sidedef->rowoffset >> FRACBITS) - 1; + + if(!(thing->player->questflags & (1 << flag))) + break; + // fall-through: + case 2: + // Open Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,open); + line->special = 0; + break; + + case 227: + // haleyjd 09/21/10: [STRIFE] W1 Close Door if Quest + sidedef = &sides[line->sidenum[0]]; + flag = (sidedef->rowoffset >> FRACBITS) - 1; + + if(!(thing->player->questflags & (1 << flag))) + break; + // fall-through: + case 3: + // Close Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,close); + line->special = 0; + break; + + case 4: + // Raise Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,normal); + line->special = 0; + break; + + case 5: + // Raise Floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloor); + line->special = 0; + break; + + case 6: + // Fast Ceiling Crush & Raise - [STRIFE] Verified unmodified. + EV_DoCeiling(line,fastCrushAndRaise); + line->special = 0; + break; + + case 8: + // Build Stairs - [STRIFE] Verified unmodified. + EV_BuildStairs(line,build8); + line->special = 0; + break; + + case 10: + // PlatDownWaitUp - [STRIFE] Verified unmodified. + EV_DoPlat(line,downWaitUpStay,0); + line->special = 0; + break; + + case 12: + // Light Turn On - brightest near - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,0); + line->special = 0; + break; + + case 13: + // Light Turn On 255 - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,255); + line->special = 0; + break; + + case 16: + // Close Door 30 - [STRIFE] Verified unmodified. + EV_DoDoor(line,close30ThenOpen); + line->special = 0; + break; + + case 17: + // Start Light Strobing - [STRIFE] Verified unmodified. + EV_StartLightStrobing(line); + line->special = 0; + break; + + case 19: + // Lower Floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,lowerFloor); + line->special = 0; + break; + + case 22: + // villsa [STRIFE] Verified unmodified. + // Raise floor to nearest height and change texture + EV_DoPlat(line,raiseToNearestAndChange,0); + line->special = 0; + break; + + case 25: + // Ceiling Crush and Raise - [STRIFE] Verified unmodified. + EV_DoCeiling(line,crushAndRaise); + line->special = 0; + break; + + case 30: + // Raise floor to shortest texture height - [STRIFE] Verified unmodified. + // on either side of lines. + EV_DoFloor(line,raiseToTexture); + line->special = 0; + break; + + case 35: + // Lights Very Dark - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,35); + line->special = 0; + break; + + case 36: + // Lower Floor (TURBO) - [STRIFE] Verified unmodified. + EV_DoFloor(line,turboLower); + line->special = 0; + break; + + case 37: + // LowerAndChange - [STRIFE] Verified unmodified. + EV_DoFloor(line,lowerAndChange); + line->special = 0; + break; + + case 193: + // haleyjd 09/21/10: [STRIFE] W1 Floor Lower to Lowest if Quest + sidedef = &sides[line->sidenum[0]]; + flag = (sidedef->rowoffset >> FRACBITS) - 1; // note is fixed_t + + // must have the questflag indicated in the line's y offset + if(!(thing->player->questflags & (1 << flag))) + break; + // fall-through: + case 38: + // Lower Floor To Lowest - [STRIFE] Verified unmodified. + EV_DoFloor( line, lowerFloorToLowest ); + line->special = 0; + break; + + case 39: + // TELEPORT! - [STRIFE] Verified unmodified (except for 0 flags param) + EV_Teleport( line, side, thing, TF_NORMAL ); + line->special = 0; + break; + + /*case 40: + // RaiseCeilingLowerFloor + EV_DoCeiling( line, raiseToHighest ); + EV_DoFloor( line, lowerFloorToLowest ); + line->special = 0; + break;*/ + + case 44: + // Ceiling Crush - [STRIFE] Verified unmodified. + EV_DoCeiling( line, lowerAndCrush ); + line->special = 0; + break; + + case 52: + // EXIT! - haleyjd 09/21/10: [STRIFE] Exit to level tag/100 + G_ExitLevel (line->tag / 100); + break; + + case 53: + // Perpetual Platform Raise - [STRIFE] Verified unmodified. + EV_DoPlat(line,perpetualRaise,0); + line->special = 0; + break; + + case 54: + // Platform Stop - [STRIFE] Verified unmodified. + EV_StopPlat(line); + line->special = 0; + break; + + case 56: + // Raise Floor Crush - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorCrush); + line->special = 0; + break; + + case 57: + // Ceiling Crush Stop - [STRIFE] Verified unmodified. + EV_CeilingCrushStop(line); + line->special = 0; + break; + + case 58: + // [STRIFE] raiseFloor24 was modified into raiseFloor64 + // Raise Floor 64 + EV_DoFloor(line,raiseFloor64); + line->special = 0; + break; + + case 59: + // Raise Floor 24 And Change - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloor24AndChange); + line->special = 0; + break; + + case 104: + // Turn lights off in sector(tag) - [STRIFE] Verified unmodified. + EV_TurnTagLightsOff(line); + line->special = 0; + break; + + case 108: + // Blazing Door Raise (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,blazeRaise); + line->special = 0; + break; + + case 109: + // Blazing Door Open (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,blazeOpen); + line->special = 0; + break; + + case 100: + // Build Stairs Turbo 16 - [STRIFE] Verified unmodified. + EV_BuildStairs(line,turbo16); + line->special = 0; + break; + + case 197: + // haleyjd 09/21/10: [STRIFE] Blazing Door Close if Has Sigil B + if(thing->player->sigiltype <= 0) + break; + // fall-through: + case 110: + // Blazing Door Close (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,blazeClose); + line->special = 0; + break; + + case 119: + // Raise floor to nearest surr. floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorToNearest); + line->special = 0; + break; + + case 121: + // villsa [STRIFE] Verified unmodified. + // Blazing PlatDownWaitUpStay + EV_DoPlat(line,blazeDWUS,0); + line->special = 0; + break; + + case 124: + // haleyjd 09/21/10: [STRIFE] W1 Start Finale + // Altered from G_SecretExitLevel. + G_StartFinale(); + break; + + case 125: + // TELEPORT MonsterONLY - [STRIFE] Verified unmodified + // (except for 0 flags parameter) + if (!thing->player) + { + EV_Teleport( line, side, thing, TF_NORMAL ); + line->special = 0; + } + break; + + case 130: + // Raise Floor Turbo - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorTurbo); + line->special = 0; + break; + + case 141: + // Silent Ceiling Crush & Raise - [STRIFE] Verified unmodified. + EV_DoCeiling(line,silentCrushAndRaise); + line->special = 0; + break; + + case 174: + // villsa [STRIFE] Split Open + EV_DoDoor(line, splitOpen); + line->special = 0; + break; + + case 183: + // villsa [STRIFE] Split Raise Nearest + EV_DoDoor(line, splitRaiseNearest); + line->special = 0; + break; + + case 178: + // haleyjd 09/24/10: [STRIFE] W1 Build Stairs Down 16 + EV_BuildStairs(line, buildDown16); + line->special = 0; + break; + + case 179: + // haleyjd 09/25/10: [STRIFE] W1 Ceiling Lower to Floor + EV_DoCeiling(line, lowerToFloor); + line->special = 0; + break; + + case 182: + // haleyjd 09/21/10: [STRIFE] Break Glass + // 182 is a unique linetype in that it is both a G1 and a W1 linetype, + // but only missiles may activate it as a W1 type. + if(thing->flags & MF_MISSILE) + P_ChangeSwitchTexture(line, 1); // why 1? it will be cleared anyway. + break; + + case 187: + // haleyjd 09/21/10: [STRIFE] W1 Clear Force Fields if Quest + sidedef = &sides[line->sidenum[0]]; + flag = (sidedef->rowoffset >> FRACBITS) - 1; // note is fixed_t + + // must have the questflag indicated in the line's y offset + if(!(thing->player->questflags & (1 << flag))) + break; + + // Do it! + EV_ClearForceFields(line); + line->special = 0; + break; + + case 188: + // haleyjd 09/21/10: [STRIFE] W1 Open Door if Quest 16 (Gate Mechanism + // Destroyed) + if(!(thing->player->questflags & QF_QUEST16)) + break; + EV_DoDoor(line, open); + line->special = 0; + break; + + case 196: + // haleyjd 09/26/10: [STRIFE] W1 Floor Lower to Lowest if Sigil Type > 0 + if(thing->player->sigiltype > 0) + { + EV_DoFloor(line, lowerFloorToLowest); + line->special = 0; + } + break; + + case 200: + // haleyjd 09/21/10: [STRIFE] W1 Open Door if Sigil Owned + if(!(thing->player->weaponowned[wp_sigil])) + break; + EV_DoDoor(line, open); + line->special = 0; + break; + + case 201: + // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective (First Side Only) + if(side == 1) + break; + // fall-through: + case 202: + // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective (Tag = VOC/LOG #) + // must be consoleplayer + if(thing->player != &players[consoleplayer]) + break; + + // must have comm unit + if(!(thing->player->powers[pw_communicator])) + break; + + // load voice + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "voc%i", line->tag); + I_StartVoice(crosslinestr); + + // load objective + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "log%i", line->tag); + GiveObjective(crosslinestr, 0); + + // Put up a message + thing->player->message = DEH_String("Incoming Message..."); + line->special = 0; + break; + + case 210: + // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective if Flamethrower???? + // I don't think this is actually used anywhere o_O + // must be player 1... + if(thing->player != &players[0]) + break; + + // must have comm unit + if(!(thing->player->powers[pw_communicator])) + break; + + // must have... the flamethrower?! + if(!(thing->player->weaponowned[wp_flame])) + break; + + // load voice + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "voc%i", line->tag); + I_StartVoice(crosslinestr); + + // load objective + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "log%i", line->tag); + GiveObjective(crosslinestr, 0); + + // Put up a message + thing->player->message = DEH_String("Incoming Message from BlackBird..."); + line->special = 0; + break; + + case 212: + // haleyjd 09/25/10: [STRIFE] W1 Floor Lower to Lowest if Have Flamethrower + if(thing->player->weaponowned[wp_flame]) + { + EV_DoFloor(line, lowerFloorToLowest); + line->special = 0; + } + break; + + case 215: + // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective if Quest (Tag/100, Tag%100) + // must be player 1... + if(thing->player != &players[0]) + break; + + // must have comm unit + if(!(thing->player->powers[pw_communicator])) + break; + + if(line->tag != 0) + { + // test for questflag + if(!(thing->player->questflags & (1 << (line->tag % 100 - 1)))) + break; + } + + // start voice + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "voc%i", line->tag/100); + I_StartVoice(crosslinestr); + + // give objective + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "log%i", line->tag/100); + GiveObjective(crosslinestr, 0); + + // Put up a message + thing->player->message = DEH_String("Incoming Message from BlackBird..."); + line->special = 0; + break; + + case 204: + // haleyjd 09/21/10: [STRIFE] W1 Change Music (unused!) + if(thing->player != &players[0]) + break; + S_ChangeMusic(line->tag, 1); + line->special = 0; + break; + + case 228: + // haleyjd 09/21/10: [STRIFE] W1 Entity Voice? + if(!(thing->player->questflags & QF_QUEST24)) // Not killed Macil??? + break; // STRIFE-TODO: verify... + + if(!(thing->player->questflags & QF_QUEST28)) // ????? STRIFE-TODO + I_StartVoice(DEH_String("voc128")); + else + I_StartVoice(DEH_String("voc130")); + + line->special = 0; + break; + + // + // RETRIGGERS. All from here till end. + // + case 72: + // Ceiling Crush - [STRIFE] Verified unmodified. + EV_DoCeiling( line, lowerAndCrush ); + break; + + case 73: + // Ceiling Crush and Raise - [STRIFE] Verified unmodified. + EV_DoCeiling(line,crushAndRaise); + break; + + case 74: + // Ceiling Crush Stop - [STRIFE] Verified unmodified. + EV_CeilingCrushStop(line); + break; + + case 75: + // Close Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,close); + break; + + case 76: + // Close Door 30 - [STRIFE] Verified unmodified. + EV_DoDoor(line,close30ThenOpen); + break; + + case 77: + // Fast Ceiling Crush & Raise - [STRIFE] Verified unmodified. + EV_DoCeiling(line,fastCrushAndRaise); + break; + + case 79: + // Lights Very Dark - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,35); + break; + + case 80: + // Light Turn On - brightest near - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,0); + break; + + case 81: + // Light Turn On 255 - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,255); + break; + + case 82: + // Lower Floor To Lowest - [STRIFE] Verified unmodified. + EV_DoFloor( line, lowerFloorToLowest ); + break; + + case 83: + // Lower Floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,lowerFloor); + break; + + case 84: + // LowerAndChange - [STRIFE] Verified unmodified. + EV_DoFloor(line,lowerAndChange); + break; + + case 86: + // Open Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,open); + break; + + case 87: + // Perpetual Platform Raise - [STRIFE] Verified unmodified. + EV_DoPlat(line,perpetualRaise,0); + break; + + case 88: + // PlatDownWaitUp - [STRIFE] Verified unmodified. + EV_DoPlat(line,downWaitUpStay,0); + break; + + case 89: + // Platform Stop - [STRIFE] Verified unmodified. + EV_StopPlat(line); + break; + + case 216: + // haleyjd 09/21/10: [STRIFE] WR Raise Door if Quest + sidedef = &sides[line->sidenum[0]]; + flag = (sidedef->rowoffset >> FRACBITS) - 1; // note is fixed_t. + + if(!(thing->player->questflags & (1 << flag))) + break; + // fall-through: + case 90: + // Raise Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,normal); + break; + + case 91: + // Raise Floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloor); + break; + + case 92: + // [STRIFE] raiseFloor24 changed to raiseFloor64 + // Raise Floor 64 + EV_DoFloor(line,raiseFloor64); + break; + + case 93: + // Raise Floor 24 And Change - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloor24AndChange); + break; + + case 94: + // Raise Floor Crush - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorCrush); + break; + + case 95: + // villsa [STRIFE] Verified unmodified. + // Raise floor to nearest height + // and change texture. + EV_DoPlat(line,raiseToNearestAndChange,0); + break; + + case 96: + // Raise floor to shortest texture height - [STRIFE] Verified unmodified. + // on either side of lines. + EV_DoFloor(line,raiseToTexture); + break; + + case 97: + // TELEPORT! - [STRIFE] Verified unmodified (except for 0 flags param) + EV_Teleport( line, side, thing, TF_NORMAL ); + break; + + case 98: + // Lower Floor (TURBO) - [STRIFE] Verified unmodified. + EV_DoFloor(line,turboLower); + break; + + case 105: + // Blazing Door Raise (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,blazeRaise); + break; + + case 106: + // Blazing Door Open (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,blazeOpen); + break; + + case 107: + // Blazing Door Close (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,blazeClose); + break; + + case 120: + // villsa [STRIFE] Verified unmodified. + // Blazing PlatDownWaitUpStay. + EV_DoPlat(line,blazeDWUS,0); + break; + + case 126: + // TELEPORT MonsterONLY. - [STRIFE] Verified unmodified (except for 0 flags param) + if (!thing->player) + EV_Teleport( line, side, thing, TF_NORMAL ); + break; + + case 128: + // Raise To Nearest Floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorToNearest); + break; + + case 129: + // Raise Floor Turbo - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorTurbo); + break; + + case 186: + // haleyjd [STRIFE] Exit Level to Spot, First Side Only + if(side == 1) + break; + // fall-through: + case 145: + // haleyjd [STRIFE] Exit Level to Spot + thing->momx = thing->momy = thing->momz = 0; + { + int map = line->tag / 100; + int spot = line->tag % 100; + + if(thing->player->weaponowned[wp_sigil]) + { + if(map == 3) + map = 30; + else if(map == 7) + map = 10; + } + + DEH_snprintf(crosslinestr, sizeof(crosslinestr), + "Entering%s", + DEH_String(mapnames[map - 1]) + 8); + thing->player->message = crosslinestr; + + if(netgame && deathmatch) + { + if(levelTimer && levelTimeCount != 0) + { + DEH_snprintf(crosslinestr, sizeof(crosslinestr), + "%d min left", + (levelTimeCount/TICRATE)/60); + break; + } + + // raise switch from floor + EV_DoFloor(line, raiseFloor64); + } + else + { + // normal single-player exit + + // BUG: Here is the opening for a flaming player to cross past + // the exit line and hit a deathmatch switch ;) It's not so much + // that this is incorrect, as that they forgot to add such a + // check to the other kind of exit lines too ;) + if(thing->player->health <= 0) + break; + + G_RiftExitLevel(map, spot, thing->angle); + } + } + break; + + case 175: + // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if < 16 Above Floor + if(thing->z < thing->floorz + 16 * FRACUNIT) + P_NoiseAlert(thing->player->mo, thing->player->mo); + break; + + case 198: + // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if No Guard Uniform + if(P_PlayerHasItem(thing->player, MT_QUEST_GUARD_UNIFORM)) + break; + // fall-through: + case 150: + // haleyjd 09/21/10: [STRIFE] WR Raise Alarm + P_NoiseAlert(thing->player->mo, thing->player->mo); + break; + + case 208: + // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if Have Flamethrower + // O_o - this is definitely unused. Was an entire flamethrower quest + // cut out of the game before release? + if(thing->player->weaponowned[wp_flame]) + P_NoiseAlert(thing->player->mo, thing->player->mo); + break; + + case 206: + // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if Have Chalice + // This *is* used, inside the Tavern in Tarnhill. Oddly there is also + // one just randomly placed outside the entrance to the Power Station. + if(P_PlayerHasItem(thing->player, MT_INV_CHALICE)) + P_NoiseAlert(thing->player->mo, thing->player->mo); + break; + + case 184: + // villsa [STRIFE] plat up wait down stay + if(EV_DoPlat(line, upWaitDownStay, 0)) + P_ChangeSwitchTexture(line, 1); // In P_CrossSpecialLine? Copypasta error? + break; + + case 185: + // haleyjd 09/21/10: [STRIFE] Silent Teleport (used for Converter) + EV_Teleport(line, side, thing, TF_FULLSILENCE); + break; + + case 195: + // haleyjd 09/21/10: [STRIFE] Silent Teleport and Change Zombie + EV_Teleport(line, side, thing, TF_FULLSILENCE); + P_SetMobjState(thing, S_AGRD_00); // 419 + break; + + case 203: + // haleyjd 09/21/10: [STRIFE] WR Change Music + if(thing->player != &players[0]) + break; + S_ChangeMusic(line->tag, 1); + break; + + case 231: + // haleyjd 09/21/10: [STRIFE] WR Teleport (Silent at Source) + EV_Teleport(line, side, thing, TF_SRCSILENCE); + break; + + // haleyjd 09/21/10: Moved one-time-use lines up above with the others. + } +} + + + +// +// P_ShootSpecialLine - IMPACT SPECIALS +// Called when a thing shoots a special line. +// +void +P_ShootSpecialLine +( mobj_t* thing, + line_t* line ) +{ + int ok; + + // Impacts that other things can activate. + if (!thing->player) + { + ok = 0; + switch(line->special) + { + case 46: // OPEN DOOR IMPACT + case 182: // villsa [STRIFE] for windows + ok = 1; + break; + } + if (!ok) + return; + } + + switch(line->special) + { + case 24: + // RAISE FLOOR - [STRIFE] Verified unmodified + EV_DoFloor(line,raiseFloor); + P_ChangeSwitchTexture(line,0); + break; + + case 46: + // OPEN DOOR - [STRIFE] Verified unmodified. + EV_DoDoor(line,open); + P_ChangeSwitchTexture(line,1); + break; + + case 47: + // villsa [STRIFE] Verified unmodified. + // RAISE FLOOR NEAR AND CHANGE + EV_DoPlat(line,raiseToNearestAndChange,0); + P_ChangeSwitchTexture(line,0); + break; + + case 180: + // haleyjd 09/22/10: [STRIFE] G1 Raise Floor 512 & Change + EV_DoFloor(line, raiseFloor512AndChange); + P_ChangeSwitchTexture(line, 0); + break; + + case 182: + // villsa [STRIFE] G1 Break Glass + // haleyjd: note that 182 is also a W1 type in P_CrossSpecialLine, but + // can only be activated in that manner by an MF_MISSILE object. + P_ChangeSwitchTexture(line, 0); + break; + } +} + + + +// +// P_PlayerInSpecialSector +// Called every tic frame +// that the player origin is in a special sector +// +// [STRIFE] Modified for new sector types and changes to old ones. +// +void P_PlayerInSpecialSector (player_t* player) +{ + sector_t* sector; + + sector = player->mo->subsector->sector; + + // Falling, not all the way down yet? + if (player->mo->z != sector->floorheight) + return; + + // Has hitten ground. + switch (sector->special) + { + case 5: + // HELLSLIME DAMAGE + // [STRIFE] +2 to nukagecount + if(!player->powers[pw_ironfeet]) + player->nukagecount += 2; + break; + + case 16: + // [STRIFE] +4 to nukagecount + if(!player->powers[pw_ironfeet]) + player->nukagecount += 4; + break; + + case 4: + case 7: + // [STRIFE] Immediate 5 damage every 31 tics + if(!player->powers[pw_ironfeet]) + if(!(leveltime & 0x1f)) + P_DamageMobj(player->mo, NULL, NULL, 5); + break; + + case 9: + // SECRET SECTOR + //player->secretcount++; [STRIFE] Don't have a secret count. + sector->special = 0; + if(player - players == consoleplayer) + S_StartSound(NULL, sfx_yeah); + break; + + case 11: + // EXIT SUPER DAMAGE! (for E1M8 finale) + player->cheats &= ~CF_GODMODE; + + if (!(leveltime&0x1f)) + P_DamageMobj (player->mo, NULL, NULL, 20); + + if (player->health <= 10) + G_ExitLevel(0); + break; + + case 15: + // haleyjd 08/30/10: [STRIFE] "Instant" Death sector + P_DamageMobj(player->mo, NULL, NULL, 999); + break; + + + case 18: + // haleyjd 08/30/10: [STRIFE] Water current + { + int tagval = sector->tag - 100; + fixed_t force; + angle_t angle; + + if(player->cheats & CF_NOCLIP) + return; + + force = (tagval % 10) << 12; + angle = (tagval / 10) << 29; + + P_Thrust(player, angle, force); + } + break; + + default: + I_Error ("P_PlayerInSpecialSector: " + "unknown special %i", + sector->special); + break; + }; +} + + + + +// +// P_UpdateSpecials +// Animate planes, scroll walls, etc. +// +// [STRIFE] Modifications to support multiple scrolling line types. +// +boolean levelTimer; +int levelTimeCount; + +void P_UpdateSpecials (void) +{ + anim_t* anim; + int pic; + int i; + line_t* line; + + + // LEVEL TIMER + if (levelTimer == true) + { + if(levelTimeCount) // [STRIFE] Does not allow to go negative + levelTimeCount--; + + /* + // [STRIFE] Not done here. Exit lines check this manually instead. + if (!levelTimeCount) + G_ExitLevel(0); + */ + } + + // ANIMATE FLATS AND TEXTURES GLOBALLY + for (anim = anims ; anim < lastanim ; anim++) + { + for (i=anim->basepic ; i<anim->basepic+anim->numpics ; i++) + { + pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics ); + if (anim->istexture) + texturetranslation[i] = pic; + else + flattranslation[i] = pic; + } + } + + + // ANIMATE LINE SPECIALS + for (i = 0; i < numlinespecials; i++) + { + line = linespeciallist[i]; + switch(line->special) + { + case 48: + // EFFECT FIRSTCOL SCROLL + + sides[line->sidenum[0]].textureoffset += FRACUNIT; + break; + + case 142: + // haleyjd 09/25/10 [STRIFE] Scroll Up Slow + sides[line->sidenum[0]].rowoffset += FRACUNIT; + break; + + case 143: + // haleyjd 09/25/10 [STRIFE] Scroll Down Fast (3 Units/Tic) + sides[line->sidenum[0]].rowoffset -= 3*FRACUNIT; + break; + + case 149: + // haleyjd 09/25/10 [STRIFE] Scroll Down Slow + sides[line->sidenum[0]].rowoffset -= FRACUNIT; + break; + } + } + + + // DO BUTTONS + for (i = 0; i < MAXBUTTONS; i++) + if (buttonlist[i].btimer) + { + buttonlist[i].btimer--; + if (!buttonlist[i].btimer) + { + switch(buttonlist[i].where) + { + case top: + sides[buttonlist[i].line->sidenum[0]].toptexture = + buttonlist[i].btexture; + break; + + case middle: + sides[buttonlist[i].line->sidenum[0]].midtexture = + buttonlist[i].btexture; + break; + + case bottom: + sides[buttonlist[i].line->sidenum[0]].bottomtexture = + buttonlist[i].btexture; + break; + } + S_StartSound(&buttonlist[i].soundorg,sfx_swtchn); + memset(&buttonlist[i],0,sizeof(button_t)); + } + } +} + + +// +// Donut overrun emulation +// +// Derived from the code from PrBoom+. Thanks go to Andrey Budko (entryway) +// as usual :-) +// + +#define DONUT_FLOORHEIGHT_DEFAULT 0x00000000 +#define DONUT_FLOORPIC_DEFAULT 0x16 + +static void DonutOverrun(fixed_t *s3_floorheight, short *s3_floorpic, + line_t *line, sector_t *pillar_sector) +{ + static int first = 1; + static int tmp_s3_floorheight; + static int tmp_s3_floorpic; + + extern int numflats; + + if (first) + { + int p; + + // This is the first time we have had an overrun. + first = 0; + + // Default values + tmp_s3_floorheight = DONUT_FLOORHEIGHT_DEFAULT; + tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; + + //! + // @category compat + // @arg <x> <y> + // + // Use the specified magic values when emulating behavior caused + // by memory overruns from improperly constructed donuts. + // In Vanilla Doom this can differ depending on the operating + // system. The default (if this option is not specified) is to + // emulate the behavior when running under Windows 98. + + p = M_CheckParmWithArgs("-donut", 2); + + if (p > 0) + { + // Dump of needed memory: (fixed_t)0000:0000 and (short)0000:0008 + // + // C:\>debug + // -d 0:0 + // + // DOS 6.22: + // 0000:0000 (57 92 19 00) F4 06 70 00-(16 00) + // DOS 7.1: + // 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) + // Win98: + // 0000:0000 (00 00 00 00) 65 04 70 00-(16 00) + // DOSBox under XP: + // 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00) + + M_StrToInt(myargv[p + 1], &tmp_s3_floorheight); + M_StrToInt(myargv[p + 2], &tmp_s3_floorpic); + + if (tmp_s3_floorpic >= numflats) + { + fprintf(stderr, + "DonutOverrun: The second parameter for \"-donut\" " + "switch should be greater than 0 and less than number " + "of flats (%d). Using default value (%d) instead. \n", + numflats, DONUT_FLOORPIC_DEFAULT); + tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; + } + } + } + + /* + fprintf(stderr, + "Linedef: %d; Sector: %d; " + "New floor height: %d; New floor pic: %d\n", + line->iLineID, pillar_sector->iSectorID, + tmp_s3_floorheight >> 16, tmp_s3_floorpic); + */ + + *s3_floorheight = (fixed_t) tmp_s3_floorheight; + *s3_floorpic = (short) tmp_s3_floorpic; +} + + +// +// Special Stuff that can not be categorized +// +int EV_DoDonut(line_t* line) +{ + sector_t* s1; + sector_t* s2; + sector_t* s3; + int secnum; + int rtn; + int i; + floormove_t* floor; + fixed_t s3_floorheight; + short s3_floorpic; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + s1 = §ors[secnum]; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (s1->specialdata) + continue; + + rtn = 1; + s2 = getNextSector(s1->lines[0],s1); + + // Vanilla Doom does not check if the linedef is one sided. The + // game does not crash, but reads invalid memory and causes the + // sector floor to move "down" to some unknown height. + // DOSbox prints a warning about an invalid memory access. + // + // I'm not sure exactly what invalid memory is being read. This + // isn't something that should be done, anyway. + // Just print a warning and return. + + if (s2 == NULL) + { + fprintf(stderr, + "EV_DoDonut: linedef had no second sidedef! " + "Unexpected behavior may occur in Vanilla Doom. \n"); + break; + } + + for (i = 0; i < s2->linecount; i++) + { + s3 = s2->lines[i]->backsector; + + if (s3 == s1) + continue; + + if (s3 == NULL) + { + // e6y + // s3 is NULL, so + // s3->floorheight is an int at 0000:0000 + // s3->floorpic is a short at 0000:0008 + // Trying to emulate + + fprintf(stderr, + "EV_DoDonut: WARNING: emulating buffer overrun due to " + "NULL back sector. " + "Unexpected behavior may occur in Vanilla Doom.\n"); + + DonutOverrun(&s3_floorheight, &s3_floorpic, line, s1); + } + else + { + s3_floorheight = s3->floorheight; + s3_floorpic = s3->floorpic; + } + + // Spawn rising slime + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + s2->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->type = donutRaise; + floor->crush = false; + floor->direction = 1; + floor->sector = s2; + floor->speed = FLOORSPEED / 2; + floor->texture = s3_floorpic; + floor->newspecial = 0; + floor->floordestheight = s3_floorheight; + + // Spawn lowering donut-hole + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + s1->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->type = lowerFloor; + floor->crush = false; + floor->direction = -1; + floor->sector = s1; + floor->speed = FLOORSPEED / 2; + floor->floordestheight = s3_floorheight; + break; + } + } + return rtn; +} + + + +// +// SPECIAL SPAWNING +// + +// +// P_SpawnSpecials +// After the map has been loaded, scan for specials +// that spawn thinkers +// +short numlinespecials; +line_t* linespeciallist[MAXLINEANIMS]; + + +// Parses command line parameters. +// +// haleyjd 09/25/10: [STRIFE] Modifications for more scrolling line types and +// for initialization of sliding door resources. +// +void P_SpawnSpecials (void) +{ + sector_t* sector; + int i; + int episode; + + episode = 1; + if (W_CheckNumForName(DEH_String("texture2")) >= 0) + episode = 2; + + // See if -TIMER was specified. + + if (timelimit > 0 && deathmatch) + { + levelTimer = true; + levelTimeCount = timelimit * 60 * TICRATE; + } + else + { + levelTimer = false; + } + + // Init special SECTORs - [STRIFE] Verified unmodified. + sector = sectors; + for (i=0 ; i<numsectors ; i++, sector++) + { + if (!sector->special) + continue; + + switch (sector->special) + { + case 1: + // FLICKERING LIGHTS + P_SpawnLightFlash (sector); + break; + + case 2: + // STROBE FAST + P_SpawnStrobeFlash(sector,FASTDARK,0); + break; + + case 3: + // STROBE SLOW + P_SpawnStrobeFlash(sector,SLOWDARK,0); + break; + + case 4: + // STROBE FAST/DEATH SLIME + P_SpawnStrobeFlash(sector,FASTDARK,0); + sector->special = 4; + break; + + case 8: + // GLOWING LIGHT + P_SpawnGlowingLight(sector); + break; + case 9: + // SECRET SECTOR + totalsecret++; + break; + + case 10: + // DOOR CLOSE IN 30 SECONDS + P_SpawnDoorCloseIn30 (sector); + break; + + case 12: + // SYNC STROBE SLOW + P_SpawnStrobeFlash (sector, SLOWDARK, 1); + break; + + case 13: + // SYNC STROBE FAST + P_SpawnStrobeFlash (sector, FASTDARK, 1); + break; + + case 14: + // DOOR RAISE IN 5 MINUTES + P_SpawnDoorRaiseIn5Mins (sector, i); + break; + + case 17: + P_SpawnFireFlicker(sector); + break; + } + } + + + // Init line EFFECTs + numlinespecials = 0; + for (i = 0;i < numlines; i++) + { + switch(lines[i].special) + { + case 48: // EFFECT FIRSTCOL SCROLL+ + case 142: + case 143: + case 149: + linespeciallist[numlinespecials] = &lines[i]; + numlinespecials++; + break; + } + } + + // Init other misc stuff + for (i = 0;i < MAXCEILINGS;i++) + activeceilings[i] = NULL; + + for (i = 0;i < MAXPLATS;i++) + activeplats[i] = NULL; + + for (i = 0;i < MAXBUTTONS;i++) + memset(&buttonlist[i],0,sizeof(button_t)); + + // villsa [STRIFE] + P_InitSlidingDoorFrames(); +} |