// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: p_switch.c 802 2011-03-06 18:56:56Z wesleyjohnson $
//
// Copyright (C) 1993-1996 by id Software, Inc.
// Portions Copyright (C) 1998-2000 by DooM Legacy Team.
//
// 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.
//
//
// $Log: p_switch.c,v $
// Revision 1.10  2001/04/18 21:00:22  metzgermeister
// fix crash bug
//
// Revision 1.9  2001/02/24 13:35:21  bpereira
// no message
//
// Revision 1.8  2001/01/25 22:15:44  bpereira
// added heretic support
//
// Revision 1.7  2000/11/02 17:50:09  stroggonmeth
// Big 3Dfloors & FraggleScript commit!!
//
// Revision 1.6  2000/09/28 20:57:17  bpereira
// no message
//
// Revision 1.5  2000/04/16 18:38:07  bpereira
// no message
//
// Revision 1.4  2000/04/06 20:40:22  hurdler
// Mostly remove warnings under windows
//
// Revision 1.3  2000/04/04 00:32:47  stroggonmeth
// Initial Boom compatability plus few misc changes all around.
//
// Revision 1.2  2000/02/27 00:42:10  hurdler
// fix CR+LF problem
//
// Revision 1.1.1.1  2000/02/22 20:32:32  hurdler
// Initial import into CVS (v1.29 pr3)
//
//
// DESCRIPTION:
//      Switches, buttons. Two-state animation. Exits.
//
//-----------------------------------------------------------------------------


#include "doomdef.h"
#include "g_game.h"
#include "p_local.h"
#include "s_sound.h"
#include "r_main.h"
#include "w_wad.h" //SoM: 3/22/2000
#include "z_zone.h"
#include "t_script.h"

//
// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE
//
switchlist_t oldalphSwitchList[] =
{
    // Doom shareware episode 1 switches
    {"SW1BRCOM","SW2BRCOM",     1},
    {"SW1BRN1", "SW2BRN1",      1},
    {"SW1BRN2", "SW2BRN2",      1},
    {"SW1BRNGN","SW2BRNGN",     1},
    {"SW1BROWN","SW2BROWN",     1},
    {"SW1COMM", "SW2COMM",      1},
    {"SW1COMP", "SW2COMP",      1},
    {"SW1DIRT", "SW2DIRT",      1},
    {"SW1EXIT", "SW2EXIT",      1},
    {"SW1GRAY", "SW2GRAY",      1},
    {"SW1GRAY1","SW2GRAY1",     1},
    {"SW1METAL","SW2METAL",     1},
    {"SW1PIPE", "SW2PIPE",      1},
    {"SW1SLAD", "SW2SLAD",      1},
    {"SW1STARG","SW2STARG",     1},
    {"SW1STON1","SW2STON1",     1},
    {"SW1STON2","SW2STON2",     1},
    {"SW1STONE","SW2STONE",     1},
    {"SW1STRTN","SW2STRTN",     1},

    // Doom registered episodes 2&3 switches
    {"SW1BLUE", "SW2BLUE",      2},
    {"SW1CMT",  "SW2CMT",       2},
    {"SW1GARG", "SW2GARG",      2},
    {"SW1GSTON","SW2GSTON",     2},
    {"SW1HOT",  "SW2HOT",       2},
    {"SW1LION", "SW2LION",      2},
    {"SW1SATYR","SW2SATYR",     2},
    {"SW1SKIN", "SW2SKIN",      2},
    {"SW1VINE", "SW2VINE",      2},
    {"SW1WOOD", "SW2WOOD",      2},

    // Doom II switches
    {"SW1PANEL","SW2PANEL",     3},
    {"SW1ROCK", "SW2ROCK",      3},
    {"SW1MET2", "SW2MET2",      3},
    {"SW1WDMET","SW2WDMET",     3},
    {"SW1BRIK", "SW2BRIK",      3},
    {"SW1MOD1", "SW2MOD1",      3},
    {"SW1ZIM",  "SW2ZIM",       3},
    {"SW1STON6","SW2STON6",     3},
    {"SW1TEK",  "SW2TEK",       3},
    {"SW1MARB", "SW2MARB",      3},
    {"SW1SKULL","SW2SKULL",     3},

    // heretic
    {"SW1OFF",  "SW1ON",        4},
    {"SW2OFF",  "SW2ON",        4},

    {"\0",      "\0",           0}
};

//SoM: 3/22/2000: Switch limit removal
//int             switchlist[MAXSWITCHES * 2];

static int             *switchlist=NULL;
static int             max_numswitches;
static int             numswitches;

button_t        buttonlist[MAXBUTTONS];

//
// P_InitSwitchList
// - this is now called at P_SetupLevel () time.
//
//SoM: 3/22/2000: Use boom code.
void P_InitSwitchList(void)
{
  int            i, index = 0;
  int            episode; 
  switchlist_t   *alphSwitchList;

  switch (gamemode){
      case doom_registered :
      case ultdoom_retail:
          episode = 2;
          break;
      case doom2_commercial :
          episode = 3;
          break;
      case heretic :
          episode = 4;
          break;
      default:
          episode = 1;
  }

  //SoM: 3/22/2000: No Switches lump? Use old table!
  if(W_CheckNumForName("SWITCHES") != -1)
  {
    alphSwitchList = (switchlist_t *)W_CacheLumpName("SWITCHES", PU_IN_USE);
#ifdef __BIG_ENDIAN__
    // [WDJ] Endian conversion, only when BIG_ENDIAN, when from wad,
    // and not when cache hit.
    if( lump_read )
    {
      // endian conversion only when loading from extra lump
      for (i=0;alphSwitchList[i].episode!=0;i++)
        alphSwitchList[i].episode = LE_SWAP16(alphSwitchList[i].episode);
    }
#endif
  }
  else 
    alphSwitchList = oldalphSwitchList;

  // initialization for artificial levels without switches (yes, they exist!)
  if(NULL == switchlist)
      switchlist = malloc(sizeof(*switchlist));
  
  for (i=0;alphSwitchList[i].episode!=0;i++)
  {
    if (index+1 >= max_numswitches)
      switchlist = realloc(switchlist, sizeof *switchlist *
          (max_numswitches = max_numswitches ? max_numswitches*2 : 8));

    if (alphSwitchList[i].episode <= episode && 
        (gamemode != heretic || alphSwitchList[i].episode == 4)) 
    {
      switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name1);
      switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name2);
    }
  }

  numswitches = index/2;
  switchlist[index] = -1;

  //SoM: 3/22/2000: Don't change tag if not from lump
  if(alphSwitchList != oldalphSwitchList)
    Z_ChangeTag(alphSwitchList,PU_CACHE);
}


//
// Start a button counting down till it turns off.
//
void P_StartButton ( line_t*       line,
                     bwhere_e      w,
                     int           texture,
                     int           time )
{
    int         i;

    // See if button is already pressed
    for (i = 0;i < MAXBUTTONS;i++)
      if (buttonlist[i].btimer && buttonlist[i].line == line)
        return;

    for (i = 0;i < MAXBUTTONS;i++)
        if (!buttonlist[i].btimer)
        {
            buttonlist[i].line = line;
            buttonlist[i].where = w;
            buttonlist[i].btexture = texture;
            buttonlist[i].btimer = time;
	    // Bug fix: Save button sound origin as sector
            buttonlist[i].soundorg = (mobj_t *)&line->frontsector->soundorg;
            return;
        }

    I_Error("P_StartButton: no button slots left!");
}





//
// Function that changes wall texture.
// Tell it if switch is ok to use again (1=yes, it's a button).
//
void P_ChangeSwitchTexture ( line_t*       line,
                             int           useAgain )
{
    int     texTop;
    int     texMid;
    int     texBot;
    int     i;
    int     sound;

    if (!useAgain)
        line->special = 0;

    // texture num are either 0=no-texture, or valid
    texTop = sides[line->sidenum[0]].toptexture;
    texMid = sides[line->sidenum[0]].midtexture;
    texBot = sides[line->sidenum[0]].bottomtexture;

    sound = sfx_swtchn;

    // EXIT SWITCH?
    if (line->special == 11)
        sound = sfx_swtchx;

    for (i = 0;i < numswitches*2;i++)
    {
        if (switchlist[i] == texTop)
        {
            S_StartSound(buttonlist->soundorg,sound);
            sides[line->sidenum[0]].toptexture = switchlist[i^1];

            if (useAgain)
                P_StartButton(line,top,switchlist[i],BUTTONTIME);

            return;
        }
        else
        {
            if (switchlist[i] == texMid)
            {
                S_StartSound(buttonlist->soundorg,sound);
                sides[line->sidenum[0]].midtexture = switchlist[i^1];
                if (useAgain)
                    P_StartButton(line, middle,switchlist[i],BUTTONTIME);

                return;
            }
            else
            {
                if (switchlist[i] == texBot)
                {
                    S_StartSound(buttonlist->soundorg,sound);
                    sides[line->sidenum[0]].bottomtexture = switchlist[i^1];

                    if (useAgain)
                        P_StartButton(line, bottom,switchlist[i],BUTTONTIME);

                    return;
                }
            }
        }
    }
}


//
// P_UseSpecialLine
// Called when a thing uses a special line.
// Only the front sides of lines are usable.
//
// For monsters, return true when is a door that actor can use ??
// (is actually when any monster operated switch).
// For players, return true when switch is activated.
boolean P_UseSpecialLine ( mobj_t*       thing,
                           line_t*       line,
                           int           side )
{

    // Err...
    // Use the back sides of VERY SPECIAL lines...
    if (side)  goto nopass;

    //SoM: 3/18/2000: Add check for Generalized linedefs.
    if (boomsupport)
    {
      // pointer to line function is NULL by default, set non-null if
      // line special is push or switch generalized linedef type
      int (*linefunc)(line_t *line)=NULL;

      // check each range of generalized linedefs
      if ((unsigned)line->special >= (GenFloorBase+0x2000))
      {} // not boom generalized
      else if ((unsigned)line->special >= GenFloorBase)
      {
        if (!thing->player)
          if ((line->special & FloorChange) || !(line->special & FloorModel))
            goto nopass; // FloorModel is "Allow Monsters" if FloorChange is 0
        if (!line->tag && ((line->special&6)!=6)) //all non-manual
          goto nopass;  //generalized types require tag
        linefunc = EV_DoGenFloor;
      }
      else if ((unsigned)line->special >= GenCeilingBase)
      {
        if (!thing->player)
          if ((line->special & CeilingChange) || !(line->special & CeilingModel))
            goto nopass;   // CeilingModel is "Allow Monsters" if CeilingChange is 0
        if (!line->tag && ((line->special&6)!=6)) //all non-manual
          goto nopass;  //generalized types require tag
        linefunc = EV_DoGenCeiling;
      }
      else if ((unsigned)line->special >= GenDoorBase)
      {
        if (!thing->player)
        {
          if (!(line->special & DoorMonster))
            goto nopass;  // monsters disallowed from this door
          if (line->flags & ML_SECRET) // they can't open secret doors either
            goto nopass;
        }
        if (!line->tag && ((line->special&6)!=6)) //all non-manual
          goto nopass;  //generalized types require tag
        linefunc = EV_DoGenDoor;
      }
      else if ((unsigned)line->special >= GenLockedBase)
      {
        if (!thing->player)
          goto nopass;  // monsters disallowed from unlocking doors
        if (!P_CanUnlockGenDoor(line,thing->player))
          goto nopass;
        if (!line->tag && ((line->special&6)!=6)) //all non-manual
          goto nopass;  //generalized types require tag

        linefunc = EV_DoGenLockedDoor;
      }
      else if ((unsigned)line->special >= GenLiftBase)
      {
        if (!thing->player)
          if (!(line->special & LiftMonster))
            goto nopass;  // monsters disallowed
        if (!line->tag && ((line->special&6)!=6)) //all non-manual
          goto nopass;  //generalized types require tag
        linefunc = EV_DoGenLift;
      }
      else if ((unsigned)line->special >= GenStairsBase)
      {
        if (!thing->player)
          if (!(line->special & StairMonster))
            goto nopass;  // monsters disallowed
        if (!line->tag && ((line->special&6)!=6)) //all non-manual
          goto nopass;  //generalized types require tag
        linefunc = EV_DoGenStairs;
      }
      else if ((unsigned)line->special >= GenCrusherBase)
      {
        if (!thing->player)
          if (!(line->special & CrusherMonster))
            goto nopass;  // monsters disallowed
        if (!line->tag && ((line->special&6)!=6)) //all non-manual
          goto nopass;  //generalized types require tag
        linefunc = EV_DoGenCrusher;
      }

      if (linefunc)
      {
        switch((line->special & TriggerType) >> TriggerTypeShift)
        {
          case PushOnce:
            if (!side)
              if (linefunc(line))
                line->special = 0;
            goto pass;
          case PushMany:
            if (!side)
              linefunc(line);
            goto pass;
          case SwitchOnce:
            if (linefunc(line))
              P_ChangeSwitchTexture(line,0);
            goto pass;
          case SwitchMany:
            if (linefunc(line))
              P_ChangeSwitchTexture(line,1);
            goto pass;
          default:  // if not a switch/push type, do nothing here
            goto nopass;
        }
      }
    }



    // Switches that other things can activate.
    if (!thing->player)
    {
        // monsters never open secret doors
        if (line->flags & ML_SECRET)
            goto nopass;

        // the only doors and switches that monsters can activate
        switch(line->special)
        {
          case 1:       // MANUAL DOOR RAISE
          case 32:      // MANUAL BLUE
          case 33:      // MANUAL RED
          case 34:      // MANUAL YELLOW
          //SoM: 3/18/2000: add ability to use teleporters for monsters
          case 195:       // switch teleporters
          case 174:
          case 210:       // silent switch teleporters
          case 209:
            break;

          default:
            goto nopass;  // monsters exit
        }
    }
    // monsters past this point have been checked OK for using the switch

    if (!P_CheckTag(line) && boomsupport)  //disallow zero tag on some types
      goto nopass;

    // do something
    switch (line->special)
    {
        // MANUALS
      case 1:           // Vertical Door
      case 26:          // Blue Door/Locked
      case 27:          // Yellow Door /Locked
      case 28:          // Red Door /Locked

      case 31:          // Manual door open
      case 32:          // Blue locked door open
      case 33:          // Red locked door open
      case 34:          // Yellow locked door open

      case 117:         // Blazing door raise
      case 118:         // Blazing door open
        EV_VerticalDoor (line, thing);
        break;

        //UNUSED - Door Slide Open&Close
        // case 124:
        // EV_SlidingDoor (line, thing);
        // break;

        // SWITCHES
      case 7:
        // Build Stairs
        if (EV_BuildStairs(line,gamemode == heretic ? 8*FRACUNIT : build8))
            P_ChangeSwitchTexture(line,0);
        break;

      case 107:
        if( gamemode == heretic )
        {
            if (EV_BuildStairs (line, 16 * FRACUNIT))
                P_ChangeSwitchTexture (line, 0);
        }
        break;

      case 9:
        // Change Donut
        if (EV_DoDonut(line))
            P_ChangeSwitchTexture(line,0);
        break;

      case 11:
        // Exit level
        if(cv_allowexitlevel.value)
        {
            P_ChangeSwitchTexture(line,0);
            G_ExitLevel ();
        }
        break;

      case 14:
        // Raise Floor 32 and change texture
        if (EV_DoPlat(line,raiseAndChange,32))
            P_ChangeSwitchTexture(line,0);
        break;

      case 15:
        // Raise Floor 24 and change texture
        if (EV_DoPlat(line,raiseAndChange,24))
            P_ChangeSwitchTexture(line,0);
        break;

      case 18:
        // Raise Floor to next highest floor
        if (EV_DoFloor(line, raiseFloorToNearest))
            P_ChangeSwitchTexture(line,0);
        break;

      case 20:
        // Raise Plat next highest floor and change texture
        if (EV_DoPlat(line,raiseToNearestAndChange,0))
            P_ChangeSwitchTexture(line,0);
        break;

      case 21:
        // PlatDownWaitUpStay
        if (EV_DoPlat(line,downWaitUpStay,0))
            P_ChangeSwitchTexture(line,0);
        break;

      case 23:
        // Lower Floor to Lowest
        if (EV_DoFloor(line,lowerFloorToLowest))
            P_ChangeSwitchTexture(line,0);
        break;

      case 29:
        // Raise Door
        if (EV_DoDoor(line,normalDoor,VDOORSPEED))
            P_ChangeSwitchTexture(line,0);
        break;

      case 41:
        // Lower Ceiling to Floor
        if (EV_DoCeiling(line,lowerToFloor))
            P_ChangeSwitchTexture(line,0);
        break;

      case 71:
        // Turbo Lower Floor
        if (EV_DoFloor(line,turboLower))
            P_ChangeSwitchTexture(line,0);
        break;

      case 49:
        // Ceiling Crush And Raise
        if (EV_DoCeiling(line,gamemode==heretic ? lowerAndCrush : crushAndRaise))
            P_ChangeSwitchTexture(line,0);
        break;

      case 50:
        // Close Door
        if (EV_DoDoor(line,doorclose,VDOORSPEED))
            P_ChangeSwitchTexture(line,0);
        break;

      case 51:
        // Secret EXIT
        P_ChangeSwitchTexture(line,0);
        G_SecretExitLevel ();
        break;

      case 55:
        // Raise Floor Crush
        if (EV_DoFloor(line,raiseFloorCrush))
            P_ChangeSwitchTexture(line,0);
        break;

      case 101:
        // Raise Floor
        if (EV_DoFloor(line,raiseFloor))
            P_ChangeSwitchTexture(line,0);
        break;

      case 102:
        // Lower Floor to Surrounding floor height
        if (EV_DoFloor(line,lowerFloor))
            P_ChangeSwitchTexture(line,0);
        break;

      case 103:
        // Open Door
        if (EV_DoDoor(line,dooropen,VDOORSPEED))
            P_ChangeSwitchTexture(line,0);
        break;

      case 111:
        // Blazing Door Raise (faster than TURBO!)
        if (EV_DoDoor (line,blazeRaise,4*VDOORSPEED))
            P_ChangeSwitchTexture(line,0);
        break;

      case 112:
        // Blazing Door Open (faster than TURBO!)
        if (EV_DoDoor (line,blazeOpen,4*VDOORSPEED))
            P_ChangeSwitchTexture(line,0);
        break;

      case 113:
        // Blazing Door Close (faster than TURBO!)
        if (EV_DoDoor (line,blazeClose,4*VDOORSPEED))
            P_ChangeSwitchTexture(line,0);
        break;

      case 122:
        // Blazing PlatDownWaitUpStay
        if (EV_DoPlat(line,blazeDWUS,0))
            P_ChangeSwitchTexture(line,0);
        break;

      case 127:
        // Build Stairs Turbo 16
        if (EV_BuildStairs(line,turbo16))
            P_ChangeSwitchTexture(line,0);
        break;

      case 131:
        // Raise Floor Turbo
        if (EV_DoFloor(line,raiseFloorTurbo))
            P_ChangeSwitchTexture(line,0);
        break;

      case 133:
        // BlzOpenDoor BLUE
      case 135:
        // BlzOpenDoor RED
      case 137:
        // BlzOpenDoor YELLOW
        if (EV_DoLockedDoor (line,blazeOpen,thing,4*VDOORSPEED))
            P_ChangeSwitchTexture(line,0);
        break;

      case 140:
        // Raise Floor 512
        if (EV_DoFloor(line,raiseFloor512))
            P_ChangeSwitchTexture(line,0);
        break;

      //SoM: FraggleScript!
      case 276:
      case 277:
        T_RunScript(line->tag, thing);
        if(line->special == 277)
        {
          line->special = 0;         // clear tag
          P_ChangeSwitchTexture(line,0);
        }
        else
          P_ChangeSwitchTexture(line,1);
        break;

      default:
        if (boomsupport)
        {
          switch (line->special)
          {
            // added linedef types to fill all functions out so that
            // all possess SR, S1, WR, W1 types

            case 158:
              // Raise Floor to shortest lower texture
              if (EV_DoFloor(line,raiseToTexture))
                P_ChangeSwitchTexture(line,0);
              break;
  
            case 159:
              // Raise Floor to shortest lower texture
              if (EV_DoFloor(line,lowerAndChange))
                P_ChangeSwitchTexture(line,0);
              break;
        
            case 160:
              // Raise Floor 24 and change
              if (EV_DoFloor(line,raiseFloor24AndChange))
                P_ChangeSwitchTexture(line,0);
              break;

            case 161:
              // Raise Floor 24
              if (EV_DoFloor(line,raiseFloor24))
                P_ChangeSwitchTexture(line,0);
              break;

            case 162:
              // Moving floor min n to max n
              if (EV_DoPlat(line,perpetualRaise,0))
                P_ChangeSwitchTexture(line,0);
              break;

            case 163:
              // Stop Moving floor
              EV_StopPlat(line);
              P_ChangeSwitchTexture(line,0);
              break;

            case 164:
              // Start fast crusher
              if (EV_DoCeiling(line,fastCrushAndRaise))
                P_ChangeSwitchTexture(line,0);
              break;

            case 165:
              // Start slow silent crusher
              if (EV_DoCeiling(line,silentCrushAndRaise))
                P_ChangeSwitchTexture(line,0);
              break;

            case 166:
              // Raise ceiling, Lower floor
              if (EV_DoCeiling(line, raiseToHighest) ||
                  EV_DoFloor(line, lowerFloorToLowest))
                P_ChangeSwitchTexture(line,0);
              break;

            case 167:
              // Lower floor and Crush
              if (EV_DoCeiling(line, lowerAndCrush))
                P_ChangeSwitchTexture(line,0);
              break;

            case 168:
              // Stop crusher
              if (EV_CeilingCrushStop(line))
                P_ChangeSwitchTexture(line,0);
              break;

            case 169:
              // Lights to brightest neighbor sector
              EV_LightTurnOn(line,0);
              P_ChangeSwitchTexture(line,0);
              break;

            case 170:
              // Lights to near dark
              EV_LightTurnOn(line,35);
              P_ChangeSwitchTexture(line,0);
              break;

            case 171:
              // Lights on full
              EV_LightTurnOn(line,255);
              P_ChangeSwitchTexture(line,0);
              break;

            case 172:
              // Start Lights Strobing
              EV_StartLightStrobing(line);
              P_ChangeSwitchTexture(line,0);
              break;

            case 173:
              // Lights to Dimmest Near
              EV_TurnTagLightsOff(line);
              P_ChangeSwitchTexture(line,0);
              break;

            case 174:
              // Teleport
              if (EV_Teleport(line,side,thing))
                P_ChangeSwitchTexture(line,0);
              break;

            case 175:
              // Close Door, Open in 30 secs
              if (EV_DoDoor(line,close30ThenOpen,VDOORSPEED))
                P_ChangeSwitchTexture(line,0);
              break;

            case 189: //create texture change no motion type
              // Texture Change Only (Trigger)
              if (EV_DoChange(line,trigChangeOnly))
                P_ChangeSwitchTexture(line,0);
              break;

            case 203:
              // Lower ceiling to lowest surrounding ceiling
              if (EV_DoCeiling(line,lowerToLowest))
                P_ChangeSwitchTexture(line,0);
              break;

            case 204:
              // Lower ceiling to highest surrounding floor
              if (EV_DoCeiling(line,lowerToMaxFloor))
                P_ChangeSwitchTexture(line,0);
              break;

            case 209:
              // killough 1/31/98: silent teleporter
              if (EV_SilentTeleport(line, side, thing))
                P_ChangeSwitchTexture(line,0);
              break;

            case 241: //jff 3/15/98 create texture change no motion type
              // Texture Change Only (Numeric)
              if (EV_DoChange(line,numChangeOnly))
                P_ChangeSwitchTexture(line,0);
              break;

            case 221:
              // Lower floor to next lowest floor
              if (EV_DoFloor(line,lowerFloorToNearest))
                P_ChangeSwitchTexture(line,0);
              break;

            case 229:
              // Raise elevator next floor
              if (EV_DoElevator(line,elevateUp))
                P_ChangeSwitchTexture(line,0);
              break;

            case 233:
              // Lower elevator next floor
              if (EV_DoElevator(line,elevateDown))
                P_ChangeSwitchTexture(line,0);
              break;

            case 237:
              // Elevator to current floor
              if (EV_DoElevator(line,elevateCurrent))
                P_ChangeSwitchTexture(line,0);
              break;


            //end of added S1 linedef types

            //added linedef types to fill all functions out so that
            //all possess SR, S1, WR, W1 types
            
            case 78:
              // Texture/type Change Only (Numeric)
              if (EV_DoChange(line,numChangeOnly))
                P_ChangeSwitchTexture(line,1);
              break;

            case 176:
              // Raise Floor to shortest lower texture
              if (EV_DoFloor(line,raiseToTexture))
                P_ChangeSwitchTexture(line,1);
              break;

            case 177:
              // Raise Floor to shortest lower texture
              if (EV_DoFloor(line,lowerAndChange))
                P_ChangeSwitchTexture(line,1);
              break;

            case 178:
              // Raise Floor 512
              if (EV_DoFloor(line,raiseFloor512))
                P_ChangeSwitchTexture(line,1);
              break;

            case 179:
              // Raise Floor 24 and change
              if (EV_DoFloor(line,raiseFloor24AndChange))
                P_ChangeSwitchTexture(line,1);
              break;

            case 180:
              // Raise Floor 24
              if (EV_DoFloor(line,raiseFloor24))
                P_ChangeSwitchTexture(line,1);
              break;

            case 181:
              // Moving floor min n to max n
              EV_DoPlat(line,perpetualRaise,0);
              P_ChangeSwitchTexture(line,1);
              break;

            case 182:
              // Stop Moving floor
              EV_StopPlat(line);
              P_ChangeSwitchTexture(line,1);
              break;

            case 183:
              // Start fast crusher
              if (EV_DoCeiling(line,fastCrushAndRaise))
                P_ChangeSwitchTexture(line,1);
              break;

            case 184:
              // Start slow crusher
              if (EV_DoCeiling(line,crushAndRaise))
                P_ChangeSwitchTexture(line,1);
              break;

            case 185:
              // Start slow silent crusher
              if (EV_DoCeiling(line,silentCrushAndRaise))
                P_ChangeSwitchTexture(line,1);
              break;

            case 186:
              // Raise ceiling, Lower floor
              if (EV_DoCeiling(line, raiseToHighest) ||
                  EV_DoFloor(line, lowerFloorToLowest))
                P_ChangeSwitchTexture(line,1);
              break;

            case 187:
              // Lower floor and Crush
              if (EV_DoCeiling(line, lowerAndCrush))
                P_ChangeSwitchTexture(line,1);
              break;

            case 188:
              // Stop crusher
              if (EV_CeilingCrushStop(line))
                P_ChangeSwitchTexture(line,1);
              break;

            case 190: //jff 3/15/98 create texture change no motion type
              // Texture Change Only (Trigger)
              if (EV_DoChange(line,trigChangeOnly))
                P_ChangeSwitchTexture(line,1);
              break;

            case 191:
              // Lower Pillar, Raise Donut
              if (EV_DoDonut(line))
                P_ChangeSwitchTexture(line,1);
              break;

            case 192:
              // Lights to brightest neighbor sector
              EV_LightTurnOn(line,0);
              P_ChangeSwitchTexture(line,1);
              break;

            case 193:
              // Start Lights Strobing
              EV_StartLightStrobing(line);
              P_ChangeSwitchTexture(line,1);
              break;

            case 194:
              // Lights to Dimmest Near
              EV_TurnTagLightsOff(line);
              P_ChangeSwitchTexture(line,1);
              break;

            case 195:
              // Teleport
              if (EV_Teleport(line,side,thing))
                P_ChangeSwitchTexture(line,1);
              break;

            case 196:
              // Close Door, Open in 30 secs
              if (EV_DoDoor(line,close30ThenOpen,VDOORSPEED))
                P_ChangeSwitchTexture(line,1);
              break;

            case 205:
              // Lower ceiling to lowest surrounding ceiling
              if (EV_DoCeiling(line,lowerToLowest))
                P_ChangeSwitchTexture(line,1);
              break;

            case 206:
              // Lower ceiling to highest surrounding floor
              if (EV_DoCeiling(line,lowerToMaxFloor))
                P_ChangeSwitchTexture(line,1);
              break;

            case 210:
              // Silent teleporter
              if (EV_SilentTeleport(line, side, thing))
                P_ChangeSwitchTexture(line,1);
              break;

            case 211:
              // Toggle Floor Between C and F Instantly
              if (EV_DoPlat(line,toggleUpDn,0))
                P_ChangeSwitchTexture(line,1);
              break;

            case 222:
              // Lower floor to next lowest floor
              if (EV_DoFloor(line,lowerFloorToNearest))
                P_ChangeSwitchTexture(line,1);
              break;

            case 230:
              // Raise elevator next floor
              if (EV_DoElevator(line,elevateUp))
                P_ChangeSwitchTexture(line,1);
              break;

            case 234:
              // Lower elevator next floor
              if (EV_DoElevator(line,elevateDown))
                P_ChangeSwitchTexture(line,1);
              break;

            case 238:
              // Elevator to current floor
              if (EV_DoElevator(line,elevateCurrent))
                P_ChangeSwitchTexture(line,1);
              break;

            case 258:
              // Build stairs, step 8
              if (EV_BuildStairs(line,build8))
                P_ChangeSwitchTexture(line,1);
              break;

            case 259:
              // Build stairs, step 16
              if (EV_BuildStairs(line,turbo16))
                P_ChangeSwitchTexture(line,1);
              break;

            // end of added SR linedef types

          }
	}
        break;


        // BUTTONS
      case 42:
        // Close Door
        if (EV_DoDoor(line,doorclose,VDOORSPEED))
            P_ChangeSwitchTexture(line,1);
        break;

      case 43:
        // Lower Ceiling to Floor
        if (EV_DoCeiling(line,lowerToFloor))
            P_ChangeSwitchTexture(line,1);
        break;

      case 45:
        // Lower Floor to Surrounding floor height
        if (EV_DoFloor(line,lowerFloor))
            P_ChangeSwitchTexture(line,1);
        break;

      case 60:
        // Lower Floor to Lowest
        if (EV_DoFloor(line,lowerFloorToLowest))
            P_ChangeSwitchTexture(line,1);
        break;

      case 61:
        // Open Door
        if (EV_DoDoor(line,dooropen,VDOORSPEED))
            P_ChangeSwitchTexture(line,1);
        break;

      case 62:
        // PlatDownWaitUpStay
        if (EV_DoPlat(line,downWaitUpStay,1))
            P_ChangeSwitchTexture(line,1);
        break;

      case 63:
        // Raise Door
        if (EV_DoDoor(line,normalDoor,VDOORSPEED))
            P_ChangeSwitchTexture(line,1);
        break;

      case 64:
        // Raise Floor to ceiling
        if (EV_DoFloor(line,raiseFloor))
            P_ChangeSwitchTexture(line,1);
        break;

      case 66:
        // Raise Floor 24 and change texture
        if (EV_DoPlat(line,raiseAndChange,24))
            P_ChangeSwitchTexture(line,1);
        break;

      case 67:
        // Raise Floor 32 and change texture
        if (EV_DoPlat(line,raiseAndChange,32))
            P_ChangeSwitchTexture(line,1);
        break;

      case 65:
        // Raise Floor Crush
        if (EV_DoFloor(line,raiseFloorCrush))
            P_ChangeSwitchTexture(line,1);
        break;

      case 68:
        // Raise Plat to next highest floor and change texture
        if (EV_DoPlat(line,raiseToNearestAndChange,0))
            P_ChangeSwitchTexture(line,1);
        break;

      case 69:
        // Raise Floor to next highest floor
        if (EV_DoFloor(line, raiseFloorToNearest))
            P_ChangeSwitchTexture(line,1);
        break;

      case 70:
        // Turbo Lower Floor
        if (EV_DoFloor(line,turboLower))
            P_ChangeSwitchTexture(line,1);
        break;

      case 114:
        // Blazing Door Raise (faster than TURBO!)
        if (EV_DoDoor (line,blazeRaise,4*VDOORSPEED))
            P_ChangeSwitchTexture(line,1);
        break;

      case 115:
        // Blazing Door Open (faster than TURBO!)
        if (EV_DoDoor (line,blazeOpen,4*VDOORSPEED))
            P_ChangeSwitchTexture(line,1);
        break;

      case 116:
        // Blazing Door Close (faster than TURBO!)
        if (EV_DoDoor (line,blazeClose,4*VDOORSPEED))
            P_ChangeSwitchTexture(line,1);
        break;

      case 123:
        // Blazing PlatDownWaitUpStay
        if (EV_DoPlat(line,blazeDWUS,0))
            P_ChangeSwitchTexture(line,1);
        break;

      case 132:
        // Raise Floor Turbo
        if (EV_DoFloor(line,raiseFloorTurbo))
            P_ChangeSwitchTexture(line,1);
        break;

      case 99:
        if( gamemode == heretic ) // used for right scrolling texture
            break;
        // BlzOpenDoor BLUE
      case 134:
        // BlzOpenDoor RED
      case 136:
        // BlzOpenDoor YELLOW
        if (EV_DoLockedDoor (line,blazeOpen,thing,4*VDOORSPEED))
            P_ChangeSwitchTexture(line,1);
        break;

      case 138:
        // Light Turn On
        EV_LightTurnOn(line,255);
        P_ChangeSwitchTexture(line,1);
        break;

      case 139:
        // Light Turn Off
        EV_LightTurnOn(line,35);
        P_ChangeSwitchTexture(line,1);
        break;

    }

pass:
    return true;  // monster can open this door, or operate this switch

nopass:
    return false;
}
