ref: 6528c14df3fa13bd3d5aed1e715205975b724f14
dir: /src/strife/p_switch.c/
// 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:
// Switches, buttons. Two-state animation. Exits.
//
//-----------------------------------------------------------------------------
#include <stdio.h>
#include "i_system.h"
#include "deh_main.h"
#include "doomdef.h"
#include "p_local.h"
#include "g_game.h"
#include "d_main.h" // villsa [STRIFE]
#include "s_sound.h"
#include "m_random.h" // haleyjd [STRIFE]
#include "p_dialog.h"
// Data.
#include "sounds.h"
// State.
#include "doomstat.h"
#include "r_state.h"
#include "m_bbox.h" // villsa [STRIFE]
//
// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE
//
// villsa [STRIFE] new switch list
switchlist_t alphSwitchList[] =
{
{ "GLASS01", "GLASS02", 1, sfx_bglass },
{ "GLASS03", "GLASS04", 1, sfx_bglass },
{ "GLASS05", "GLASS06", 1, sfx_bglass },
{ "GLASS07", "GLASS08", 1, sfx_bglass },
{ "GLASS17", "GLASS18", 1, sfx_bglass },
{ "GLASS19", "GLASS20", 1, sfx_bglass },
{ "SWKNOB01", "SWKNOB02", 1, sfx_swknob },
{ "SWLITE01", "SWLITE02", 1, sfx_None },
{ "SWCHN01", "SWCHN02", 1, sfx_pulchn },
{ "COMP01", "COMP04B", 1, sfx_bglass },
{ "COMP05", "COMP12B", 1, sfx_bglass },
{ "COMP09", "COMP12B", 1, sfx_bglass },
{ "COMP12", "COMP04B", 1, sfx_bglass },
{ "COMP13", "COMP12B", 1, sfx_bglass },
{ "COMP17", "COMP20B", 1, sfx_bglass },
{ "COMP21", "COMP28B", 1, sfx_bglass },
{ "WALTEK09", "WALTEKB1", 1, sfx_None },
{ "WALTEK10", "WALTEKB1", 1, sfx_None },
{ "WALTEK15", "WALTEKB1", 1, sfx_None },
{ "SWFORC01", "SWFORC02", 1, sfx_None },
{ "SWEXIT01", "SWEXIT02", 1, sfx_None },
{ "DORSBK01", "DORSBK02", 1, sfx_swston },
{ "SWSLD01", "SWSLD02", 1, sfx_None },
{ "DORWS04", "DORWS05", 1, sfx_swbolt },
{ "SWIRON01", "SWIRON02", 1, sfx_None },
{ "GLASS09", "GLASS10", 2, sfx_bglass },
{ "GLASS11", "GLASS12", 2, sfx_bglass },
{ "GLASS13", "GLASS14", 2, sfx_bglass },
{ "GLASS15", "GLASS16", 2, sfx_bglass },
{ "SWFORC03", "SWFORC04", 2, sfx_None },
{ "SWCIT01", "SWCIT02", 2, sfx_None },
{ "SWTRMG01", "SWTRMG04", 2, sfx_None },
{ "SWMETL01", "SWMETL02", 2, sfx_None },
{ "SWWOOD01", "SWWOOD02", 2, sfx_None },
{ "SWTKBL01", "SWTKBL02", 2, sfx_None },
{ "AZWAL21", "AZWAL22", 2, sfx_None },
{ "SWINDT01", "SWINDT02", 2, sfx_None },
{ "SWRUST01", "SWRUST02", 2, sfx_None },
{ "SWCHAP01", "SWCHAP02", 2, sfx_None },
{ "SWALIN01", "SWALIN02", 2, sfx_None },
{ "SWWALG01", "SWWALG02", 2, sfx_None },
{ "SWWALG03", "SWWALG04", 2, sfx_None },
{ "SWTRAM01", "SWTRAM02", 2, sfx_None },
{ "SWTRAM03", "SWTRAM04", 2, sfx_None },
{ "SWORC01", "SWORC02", 2, sfx_None },
{ "SWBRIK01", "SWBRIK02", 2, sfx_None },
{ "SWIRON03", "SWIRON04", 2, sfx_None },
{ "SWIRON05", "SWIRON06", 2, sfx_None },
{ "SWIRON07", "SWIRON08", 2, sfx_None },
{ "SWCARD01", "SWCARD02", 2, sfx_keycrd },
{ "SWSIGN01", "SWSIGN02", 2, sfx_None },
{ "SWLEV01", "SWLEV02", 2, sfx_None },
{ "SWLEV03", "SWLEV04", 2, sfx_None },
{ "SWLEV05", "SWLEV06", 2, sfx_None },
{ "SWBRN01", "SWBRN02", 2, sfx_keycrd },
{ "SWPIP01", "SWPIP02", 2, sfx_valve },
{ "SWPALM01", "SWPALM02", 2, sfx_swscan },
{ "SWKNOB03", "SWKNOB04", 2, sfx_swknob },
{ "ALTSW01", "ALTSW02", 2, sfx_None },
{ "COMP25", "COMP28B", 2, sfx_bglass },
{ "COMP29", "COMP20B", 2, sfx_bglass },
{ "COMP33", "COMP50", 2, sfx_bglass },
{ "COMP42", "COMP51", 2, sfx_bglass },
{ "GODSCRN1", "GODSCRN2", 2, sfx_difool },
{ "ALIEN04", "ALIEN05", 2, sfx_None },
{ "CITADL04", "CITADL05", 2, sfx_None },
{ "SWITE03", "SWITE04", 2, sfx_None },
{ "SWTELP01", "SWTELP02", 2, sfx_None },
{ "BRNSCN01", "BRNSCN05", 2, sfx_firxpl },
{ "\0", "\0", 0, sfx_None }
};
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(isregistered)
episode = 2;
// villsa [STRIFE] unused
/*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)
{
switchlist[index++] = R_TextureNumForName(DEH_String(alphSwitchList[i].name1));
switchlist[index++] = R_TextureNumForName(DEH_String(alphSwitchList[i].name2));
}
}
}
//
// P_StartButton
// 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 = &line->frontsector->soundorg;
return;
}
}
I_Error("P_StartButton: no button slots left!");
}
//
// P_SpawnBrokenGlass
// villsa [STRIFE] new function
//
static void P_SpawnBrokenGlass(line_t* line)
{
fixed_t x1;
fixed_t x2;
fixed_t y1;
fixed_t y2;
int i;
mobj_t* glass;
angle_t an;
x1 = (line->v2->x + line->v1->x) / 2;
y1 = (line->v2->y + line->v1->y) / 2;
x2 = ((line->frontsector->soundorg.x - x1) / 5) + x1;
y2 = ((line->frontsector->soundorg.y - y1) / 5) + y1;
for(i = 0; i < 7; i++)
{
glass = P_SpawnMobj(x2, y2, ONFLOORZ, MT_JUNK);
glass->z += (24*FRACUNIT);
glass->flags |= (MF_SHADOW|MF_MVIS);
P_SetMobjState(glass, P_Random() % 3 + S_SHRD_03); // 284
an = ((P_Random() << 13) / 255);
glass->angle = (an << ANGLETOFINESHIFT);
glass->momx = FixedMul(finecosine[an], (P_Random() & 3) << FRACBITS);
glass->momy = FixedMul(finesine[an], (P_Random() & 3) << FRACBITS);
glass->momz = (P_Random() & 7) << FRACBITS;
glass->tics += (P_Random() + 7) & 7;
}
}
//
// 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;
boolean breakglass; // villsa [STRIFE]
switchlist_t* sl; // villsa [STRIFE]
breakglass = false; // villsa [STRIFE]
texTop = sides[line->sidenum[0]].toptexture;
texMid = sides[line->sidenum[0]].midtexture;
texBot = sides[line->sidenum[0]].bottomtexture;
sound = sfx_swtchn;
// EXIT SWITCH?
// villsa [STRIFE] check for linetype 182 (break glass)
if(line->special == 182)
{
line->flags &= ~ML_BLOCKING;
breakglass = true;
if(useAgain)
{
texMid = 0;
texTop = 0;
}
if(texBot)
useAgain = 0;
sound = sfx_bglass;
}
if(!useAgain)
line->special = 0;
for(i = 0; i < numswitches*2; i++)
{
sl = &alphSwitchList[i / 2]; // villsa [STRIFE]
if(switchlist[i] == texTop)
{
// villsa [STRIFE] set sound
if(sl->sound)
sound = sl->sound;
S_StartSound(buttonlist->soundorg,sound);
sides[line->sidenum[0]].toptexture = switchlist[i^1];
if(useAgain)
P_StartButton(line,top,switchlist[i],BUTTONTIME);
if(breakglass)
P_SpawnBrokenGlass(line);
return;
}
else
{
if(switchlist[i] == texMid)
{
// villsa [STRIFE] set sound
if(sl->sound)
sound = sl->sound;
S_StartSound(buttonlist->soundorg,sound);
sides[line->sidenum[0]].midtexture = switchlist[i^1];
// villsa [STRIFE] affect second side of line
if(line->flags & ML_TWOSIDED)
sides[line->sidenum[1]].midtexture = switchlist[i^1];
if(useAgain)
P_StartButton(line, middle,switchlist[i],BUTTONTIME);
// villsa [STRIFE]
if(sound == sfx_firxpl)
{
breakglass = true;
// give quest flag 29 to player
players[0].questflags |= QF_QUEST29;
// give stamina/accuracy items
if(!netgame)
{
P_GiveItemToPlayer(players, SPR_TOKN, MT_TOKEN_STAMINA);
P_GiveItemToPlayer(players, SPR_TOKN, MT_TOKEN_NEW_ACCURACY);
}
}
// villsa [STRIFE]
if(breakglass || sound == sfx_bglass)
P_SpawnBrokenGlass(line);
return;
}
else
{
if(switchlist[i] == texBot)
{
// villsa [STRIFE] set sound
if(sl->sound)
sound = sl->sound;
S_StartSound(buttonlist->soundorg,sound);
sides[line->sidenum[0]].bottomtexture = switchlist[i^1];
if(useAgain)
P_StartButton(line, bottom,switchlist[i],BUTTONTIME);
if(breakglass)
P_SpawnBrokenGlass(line);
return;
}
}
}
}
}
//
// P_MoveWall
//
// villsa [STRIFE] New function.
// Dynamically move a solid line. Unused in Strife
//
static void P_MoveWall(line_t *line, mobj_t *thing)
{
vertex_t *v2;
vertex_t *v1;
fixed_t x;
fixed_t y;
v1 = line->v1;
v2 = line->v2;
S_StartSound(thing, sfx_stnmov);
if (line->dx)
{
if (thing->x >= v1->x)
{
v1->y -= (8 * FRACUNIT);
v2->y -= (8 * FRACUNIT);
}
else
{
v1->y += (8 * FRACUNIT);
v2->y += (8 * FRACUNIT);
}
}
else
{
if (thing->y >= v1->y)
{
v1->x -= (8 * FRACUNIT);
v2->x -= (8 * FRACUNIT);
}
else
{
v1->x += (8 * FRACUNIT);
v2->x += (8 * FRACUNIT);
}
}
if (v1->x >= v2->x)
{
line->bbox[BOXLEFT] = v2->x;
x = v1->x;
}
else
{
line->bbox[BOXLEFT] = v1->x;
x = v2->x;
}
line->bbox[BOXRIGHT] = x;
if (v1->y >= v2->y)
{
line->bbox[BOXBOTTOM] = v2->y;
y = v1->y;
}
else
{
line->bbox[BOXBOTTOM] = v1->y;
y = v2->y;
}
line->bbox[BOXTOP] = y;
}
//
// 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 148: // haleyjd [STRIFE]
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 144: // haleyjd [STRIFE] Manual sliding door
break;
default:
return false;
break;
}
}
// [STRIFE] TODO: here on down mostly untouched so far,
// except for a few new types at the bottom.
// 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;
// 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 (0);
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 40:
// villsa [STRIFE] Split Open Door
if(EV_DoDoor(line, splitOpen))
P_ChangeSwitchTexture(line, 0);
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;
case 144:
// villsa [STRIFE] manual sliding door
EV_SlidingDoor(line, thing);
break;
case 148:
// haleyjd 09/16/10: [STRIFE] using forcefields hurts
P_DamageMobj(thing, NULL, NULL, 16);
P_Thrust(thing->player, thing->angle + ANG180, 125*FRACUNIT/16);
break;
case 207:
// villsa [STRIFE] remote sliding door
if(EV_RemoteSlidingDoor(line, thing))
P_ChangeSwitchTexture(line, 1);
break; // haleyjd
case 229:
// villsa [STRIFE] sigil sliding door
if(thing->player && thing->player->sigiltype == 4)
{
if(EV_RemoteSlidingDoor(line, thing))
P_ChangeSwitchTexture(line, 1);
}
break; // haleyjd
case 666:
// villsa [STRIFE] Move wall
P_MoveWall(line, thing);
break;
}
return true;
}