/* Emacs style mode select   -*- C++ -*- */
/*----------------------------------------------------------------------------- */
/* */
/* $Id:$ */
/* */
/* Copyright (C) 1993-1996 by id Software, Inc. */
/* */
/* 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:$ */
/* */
/* DESCRIPTION: */
/*	Switches, buttons. Two-state animation. Exits. */
/* */
/*----------------------------------------------------------------------------- */

static const char
        rcsid[] = "$Id: p_switch.c,v 1.3 1997/01/28 22:08:29 b1 Exp $";


#include "i_system.h"
#include "doomdef.h"
#include "p_local.h"

#include "g_game.h"

#include "s_sound.h"

/* Data. */
#include "sounds.h"

/* State. */
#include "doomstat.h"
#include "r_state.h"


/* */
/* CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE */
/* */
switchlist_t alphSwitchList[] =
{
	/* 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},

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

int switchlist[MAXSWITCHES * 2];
int numswitches;
button_t buttonlist[MAXBUTTONS];

/* */
/* P_InitSwitchList */
/* Only called at game initialization. */
/* */
void P_InitSwitchList(void)
{
        int i;
        int index;
        int episode;

        episode = 1;

        if (gamemode == registered)
		episode = 2;
        else
        if ( gamemode == commercial )
		episode = 3;

        for (index = 0,i = 0; i < MAXSWITCHES; i++)
        {
                if (!alphSwitchList[i].episode)
                {
                        numswitches = index/2;
                        switchlist[index] = -1;
                        break;
		}

                if (alphSwitchList[i].episode <= episode)
                {
#if 0   /* UNUSED - debug? */
                        int value;

                        if (R_CheckTextureNumForName(alphSwitchList[i].name1) < 0)
                        {
                                I_Error("Can't find switch texture '%s'!",
                                        alphSwitchList[i].name1);
                                continue;
			}

                        value = R_TextureNumForName(alphSwitchList[i].name1);
#endif
                        switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name1);
                        switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name2);
		}
	}
}


/* */
/* 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;
                        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;

        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. */
/* */
boolean
P_UseSpecialLine
        ( mobj_t*       thing,
        line_t*       line,
        int side )
{

        /* Err... */
        /* Use the back sides of VERY SPECIAL lines... */
        if (side)
        {
                switch(line->special)
                {
		case 124:
			/* Sliding door open&close */
			/* UNUSED? */
			break;

		default:
			return false;
			break;
		}
	}


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

                switch(line->special)
                {
		case 1: /* MANUAL DOOR RAISE */
		case 32: /* MANUAL BLUE */
		case 33: /* MANUAL RED */
		case 34: /* MANUAL YELLOW */
			break;

		default:
			return false;
			break;
		}
	}


        /* 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,build8))
			P_ChangeSwitchTexture(line,0);
		break;

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

	case 11:
		/* Exit level */
		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,normal))
			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,crushAndRaise))
			P_ChangeSwitchTexture(line,0);
		break;

	case 50:
		/* Close Door */
		if (EV_DoDoor(line,close))
			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,open))
			P_ChangeSwitchTexture(line,0);
		break;

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

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

	case 113:
		/* Blazing Door Close (faster than TURBO!) */
		if (EV_DoDoor (line,blazeClose))
			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))
			P_ChangeSwitchTexture(line,0);
		break;

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

	/* BUTTONS */
	case 42:
		/* Close Door */
		if (EV_DoDoor(line,close))
			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,open))
			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,normal))
			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))
			P_ChangeSwitchTexture(line,1);
		break;

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

	case 116:
		/* Blazing Door Close (faster than TURBO!) */
		if (EV_DoDoor (line,blazeClose))
			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:
	/* BlzOpenDoor BLUE */
	case 134:
	/* BlzOpenDoor RED */
	case 136:
		/* BlzOpenDoor YELLOW */
		if (EV_DoLockedDoor (line,blazeOpen,thing))
			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;

	}

        return true;
}

