summaryrefslogtreecommitdiff
path: root/src/strife/p_doors.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/strife/p_doors.c')
-rw-r--r--src/strife/p_doors.c1383
1 files changed, 1383 insertions, 0 deletions
diff --git a/src/strife/p_doors.c b/src/strife/p_doors.c
new file mode 100644
index 00000000..850baac6
--- /dev/null
+++ b/src/strife/p_doors.c
@@ -0,0 +1,1383 @@
+// 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: Door animation code (opening/closing)
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "z_zone.h"
+#include "doomdef.h"
+#include "deh_main.h"
+#include "p_local.h"
+
+#include "s_sound.h"
+
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+
+// Data.
+#include "dstrings.h"
+#include "sounds.h"
+
+// [STRIFE]
+#include "p_dialog.h"
+#include "i_system.h"
+
+
+//
+// VERTICAL DOORS
+//
+
+//
+// T_VerticalDoor
+//
+void T_VerticalDoor(vldoor_t* door)
+{
+ result_e res1;
+ result_e res2;
+
+ switch(door->direction)
+ {
+ case 0:
+ // WAITING
+ if (!--door->topcountdown)
+ {
+ switch(door->type)
+ {
+ case blazeRaise:
+ door->direction = -1; // time to go back down
+ S_StartSound(&door->sector->soundorg, sfx_bdcls);
+ break;
+
+ case normal:
+ door->direction = -1; // time to go back down
+ // villsa [STRIFE] closesound added
+ S_StartSound(&door->sector->soundorg, door->closesound);
+ break;
+
+ // villsa [STRIFE]
+ case shopClose:
+ door->direction = 1;
+ door->speed = (2*FRACUNIT);
+ S_StartSound(&door->sector->soundorg, door->opensound);
+ break;
+
+ case close30ThenOpen:
+ door->direction = 1;
+
+ // villsa [STRIFE] opensound added
+ S_StartSound(&door->sector->soundorg, door->opensound);
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case 2:
+ // INITIAL WAIT
+ if (!--door->topcountdown)
+ {
+ switch(door->type)
+ {
+ case raiseIn5Mins:
+ door->direction = 1;
+ door->type = normal;
+
+ // villsa [STRIFE] opensound added
+ S_StartSound(&door->sector->soundorg, door->opensound);
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ // villsa [STRIFE]
+ case -2:
+ // SPLIT
+ res1 = T_MovePlane(door->sector, door->speed, door->topheight, 0, 1, 1);
+ res2 = T_MovePlane(door->sector, door->speed, door->topwait, 0, 0, -1);
+
+ if(res1 == pastdest && res2 == pastdest)
+ {
+ door->sector->specialdata = NULL;
+ P_RemoveThinker(&door->thinker); // unlink and free
+ }
+
+ break;
+
+ case -1:
+ // DOWN
+ res1 = T_MovePlane(door->sector, door->speed, door->sector->floorheight, false, 1, door->direction);
+ if(res1 == pastdest)
+ {
+ switch(door->type)
+ {
+ case normal:
+ case close:
+ case blazeRaise:
+ case blazeClose:
+ door->sector->specialdata = NULL;
+ P_RemoveThinker (&door->thinker); // unlink and free
+ // villsa [STRIFE] no sounds
+ break;
+
+ case close30ThenOpen:
+ door->direction = 0;
+ door->topcountdown = TICRATE*30;
+ break;
+
+ // villsa [STRIFE]
+ case shopClose:
+ door->direction = 0;
+ door->topcountdown = TICRATE*120;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if(res1 == crushed)
+ {
+ switch(door->type)
+ {
+ case blazeClose:
+ case close: // DO NOT GO BACK UP!
+ case shopClose: // villsa [STRIFE]
+ break;
+
+ default:
+ door->direction = 1;
+ // villsa [STRIFE] opensound added
+ S_StartSound(&door->sector->soundorg, door->opensound);
+ break;
+ }
+ }
+ break;
+
+ case 1:
+ // UP
+ res1 = T_MovePlane(door->sector,
+ door->speed,
+ door->topheight,
+ false,1,door->direction);
+
+ if(res1 == pastdest)
+ {
+ switch(door->type)
+ {
+ case blazeRaise:
+ case normal:
+ door->direction = 0; // wait at top
+ door->topcountdown = door->topwait;
+ break;
+
+ case close30ThenOpen:
+ case blazeOpen:
+ case open:
+ case shopClose: // villsa [STRIFE]
+ door->sector->specialdata = NULL;
+ P_RemoveThinker (&door->thinker); // unlink and free
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+ }
+}
+
+
+//
+// EV_DoLockedDoor
+// Move a locked door up/down
+//
+// [STRIFE] This game has a crap load of keys. And this function doesn't even
+// deal with all of them...
+//
+int EV_DoLockedDoor(line_t* line, vldoor_e type, mobj_t* thing)
+{
+ player_t* p;
+
+ p = thing->player;
+
+ if(!p)
+ return 0;
+
+ switch(line->special)
+ {
+ case 99:
+ case 133:
+ if(!p->cards[key_IDCard])
+ {
+ p->message = DEH_String("You need an id card");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 134:
+ case 135:
+ if(!p->cards[key_IDBadge])
+ {
+ p->message = DEH_String("You need an id badge");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 136:
+ case 137:
+ if(!p->cards[key_Passcard])
+ {
+ p->message = DEH_String("You need a pass card");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 151:
+ case 164:
+ if(!p->cards[key_GoldKey])
+ {
+ p->message = DEH_String("You need a gold key");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 153:
+ case 163:
+ if(!p->cards[key_SilverKey])
+ {
+ p->message = DEH_String("You need a silver key");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 152:
+ case 162:
+ if(!p->cards[key_BrassKey])
+ {
+ p->message = DEH_String("You need a brass key");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 167:
+ case 168:
+ if(!p->cards[key_SeveredHand])
+ {
+ p->message = DEH_String("Hand print not on file");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 171:
+ if(!p->cards[key_PrisonKey])
+ {
+ p->message = DEH_String("You don't have the key to the prison");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 172:
+ if(!p->cards[key_Power1Key])
+ {
+ p->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 173:
+ if(!p->cards[key_Power2Key])
+ {
+ p->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 176:
+ if(!p->cards[key_Power3Key])
+ {
+ p->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 189:
+ if(!p->cards[key_OracleKey])
+ {
+ p->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 191:
+ if(!p->cards[key_MilitaryID])
+ {
+ p->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 192:
+ if(!p->cards[key_WarehouseKey])
+ {
+ p->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+
+ case 223:
+ if(!p->cards[key_MineKey])
+ {
+ p->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return 0;
+ }
+ break;
+ }
+
+ return EV_DoDoor(line,type);
+}
+
+
+//
+// EV_DoDoor
+//
+
+int EV_DoDoor(line_t* line, vldoor_e type)
+{
+ int secnum, rtn;
+ sector_t* sec;
+ vldoor_t* door;
+
+ secnum = -1;
+ rtn = 0;
+
+ while((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
+ {
+ sec = &sectors[secnum];
+ if(sec->specialdata)
+ continue;
+
+
+ // new door thinker
+ rtn = 1;
+ door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
+ P_AddThinker (&door->thinker);
+ sec->specialdata = door;
+
+ door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
+ door->sector = sec;
+ door->type = type;
+ door->topwait = VDOORWAIT;
+ door->speed = VDOORSPEED;
+ R_SoundNumForDoor(door); // villsa [STRIFE] set door sounds
+
+ switch(type)
+ {
+ // villsa [STRIFE] new door type
+ case splitOpen:
+ door->direction = -2;
+ door->topheight = P_FindLowestCeilingSurrounding(sec);
+ door->topheight -= 4*FRACUNIT;
+ door->speed = FRACUNIT;
+ // yes, it using topwait to get the floor height
+ door->topwait = P_FindLowestFloorSurrounding(sec);
+ if(door->topheight == sec->ceilingheight)
+ continue;
+
+ S_StartSound(&sec->soundorg, door->opensound);
+ break;
+
+ // villsa [STRIFE] new door type
+ case splitRaiseNearest:
+ door->direction = -2;
+ door->topheight = P_FindLowestCeilingSurrounding(sec);
+ door->topheight -= 4*FRACUNIT;
+ door->speed = FRACUNIT;
+ // yes, it using topwait to get the floor height
+ door->topwait = P_FindHighestFloorSurrounding(sec);
+ if(door->topheight == sec->ceilingheight)
+ continue;
+
+ S_StartSound(&sec->soundorg, door->opensound);
+ break;
+
+ case blazeClose:
+ case shopClose: // villsa [STRIFE]
+ door->topheight = P_FindLowestCeilingSurrounding(sec);
+ door->topheight -= 4*FRACUNIT;
+ door->direction = -1;
+ door->speed = VDOORSPEED * 4;
+ S_StartSound(&door->sector->soundorg, sfx_bdcls);
+ break;
+
+ case close:
+ door->topheight = P_FindLowestCeilingSurrounding(sec);
+ door->topheight -= 4*FRACUNIT;
+ door->direction = -1;
+
+ // villsa [STRIFE] set door sounds
+ S_StartSound(&door->sector->soundorg, door->opensound);
+ break;
+
+ case close30ThenOpen:
+ door->topheight = sec->ceilingheight;
+ door->direction = -1;
+
+ // villsa [STRIFE] set door sounds
+ S_StartSound(&door->sector->soundorg, door->closesound);
+ break;
+
+ case blazeRaise:
+ case blazeOpen:
+ door->direction = 1;
+ door->topheight = P_FindLowestCeilingSurrounding(sec);
+ door->topheight -= 4*FRACUNIT;
+ door->speed = VDOORSPEED * 4;
+ if (door->topheight != sec->ceilingheight)
+ S_StartSound(&door->sector->soundorg, sfx_bdopn);
+ break;
+
+ case normal:
+ case open:
+ door->direction = 1;
+ door->topheight = P_FindLowestCeilingSurrounding(sec);
+ door->topheight -= 4*FRACUNIT;
+
+ if(door->topheight != sec->ceilingheight)
+ S_StartSound(&door->sector->soundorg, door->opensound);
+ break;
+
+ default:
+ break;
+ }
+
+ }
+ return rtn;
+}
+
+//
+// EV_ClearForceFields
+//
+// villsa [STRIFE] new function
+//
+boolean EV_ClearForceFields(line_t* line)
+{
+ int secnum;
+ int rtn;
+ sector_t* sec;
+ int i;
+ line_t* secline;
+ boolean ret = false;
+
+ secnum = -1;
+ rtn = 0;
+
+ while((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
+ {
+ sec = &sectors[secnum];
+ rtn = 1;
+
+ line->special = 0;
+ ret = true;
+
+ // haleyjd 09/18/10: fixed to continue w/linecount == 0, not return
+ for(i = 0; i < sec->linecount; i++)
+ {
+ secline = sec->lines[i];
+ if(!(secline->flags & ML_TWOSIDED))
+ continue;
+ if(secline->special != 148)
+ continue;
+
+ secline->flags &= ~ML_BLOCKING;
+ secline->special = 0;
+ sides[secline->sidenum[0]].midtexture = 0;
+ sides[secline->sidenum[1]].midtexture = 0;
+ }
+ }
+
+ return ret;
+}
+
+
+//
+// EV_VerticalDoor : open a door manually, no tag value
+//
+// [STRIFE] Tons of new door types were added.
+//
+void EV_VerticalDoor(line_t* line, mobj_t* thing)
+{
+ player_t* player;
+ int secnum;
+ sector_t* sec;
+ vldoor_t* door;
+ int side;
+
+ side = 0; // only front sides can be used
+
+ // Check for locks
+ player = thing->player;
+
+ // haleyjd 09/15/10: [STRIFE] myriad checks here...
+ switch(line->special)
+ {
+ case 26: // DR ID Card door
+ case 32: // D1 ID Card door
+ if(!player->cards[key_IDCard])
+ {
+ player->message = DEH_String("You need an id card to open this door");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 27: // DR Pass Card door
+ case 34: // D1 Pass Card door
+ if(!player->cards[key_Passcard])
+ {
+ player->message = DEH_String("You need a pass card key to open this door");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 28: // DR ID Badge door
+ case 33: // D1 ID Badge door
+ if(!player->cards[key_IDBadge])
+ {
+ player->message = DEH_String("You need an id badge to open this door");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 156: // D1 brass key door
+ case 161: // DR brass key door
+ if(!player->cards[key_BrassKey])
+ {
+ player->message = DEH_String("You need a brass key");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 157: // D1 silver key door
+ case 160: // DR silver key door
+ if(!player->cards[key_SilverKey])
+ {
+ player->message = DEH_String("You need a silver key");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 158: // D1 gold key door
+ case 159: // DR gold key door
+ if(!player->cards[key_GoldKey])
+ {
+ player->message = DEH_String("You need a gold key");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ // villsa [STRIFE] added 09/15/10
+ case 165:
+ player->message = DEH_String("That doesn't seem to work");
+ S_StartSound(NULL, sfx_oof);
+ return;
+
+ case 166: // DR Hand Print door
+ if(!player->cards[key_SeveredHand])
+ {
+ player->message = DEH_String("Hand print not on file");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 169: // DR Base key door
+ if(!player->cards[key_BaseKey])
+ {
+ player->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 170: // DR Gov's Key door
+ if(!player->cards[key_GovsKey])
+ {
+ player->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 190: // DR Order Key door
+ if(!player->cards[key_OrderKey])
+ {
+ player->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 205: // DR "Only in retail"
+ player->message = DEH_String("THIS AREA IS ONLY AVAILABLE IN THE "
+ "RETAIL VERSION OF STRIFE");
+ S_StartSound(NULL, sfx_oof);
+ return;
+
+ case 213: // DR Chalice door
+ if(!P_PlayerHasItem(player, MT_INV_CHALICE))
+ {
+ player->message = DEH_String("You need the chalice!");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 217: // DR Core Key door
+ if(!player->cards[key_CoreKey])
+ {
+ player->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 221: // DR Mauler Key door
+ if(!player->cards[key_MaulerKey])
+ {
+ player->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 224: // DR Chapel Key door
+ if(!player->cards[key_ChapelKey])
+ {
+ player->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 225: // DR Catacomb Key door
+ if(!player->cards[key_CatacombKey])
+ {
+ player->message = DEH_String("You don't have the key");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ case 232: // DR Oracle Pass door
+ if(!(player->questflags & QF_QUEST18))
+ {
+ player->message = DEH_String("You need the Oracle Pass!");
+ S_StartSound(NULL, sfx_oof);
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // if the sector has an active thinker, use it
+ sec = sides[ line->sidenum[side^1]] .sector;
+ secnum = sec-sectors;
+
+ if (sec->specialdata)
+ {
+ door = sec->specialdata;
+ // [STRIFE] Adjusted to handle linetypes handled here by Strife.
+ // BUG: Not all door types are checked here. This means that certain
+ // door lines are allowed to fall through and start a new thinker on the
+ // sector! This is why some doors can become jammed in Strife - stuck in
+ // midair, or unable to be opened at all. Multiple thinkers will fight
+ // over how to move the door. They should have added a default return if
+ // they weren't going to handle this unconditionally...
+ switch(line->special)
+ {
+ case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s
+ case 26:
+ case 27:
+ case 28:
+ case 117:
+ case 159: // villsa
+ case 160: // haleyjd
+ case 161: // villsa
+ case 166: // villsa
+ case 169: // villsa
+ case 170: // villsa
+ case 190: // villsa
+ case 213: // villsa
+ case 232: // villsa
+ if(door->direction == -1)
+ door->direction = 1; // go back up
+ else
+ {
+ if (!thing->player)
+ return;
+
+ // When is a door not a door?
+ // In Vanilla, door->direction is set, even though
+ // "specialdata" might not actually point at a door.
+
+ if (door->thinker.function.acp1 == (actionf_p1) T_VerticalDoor)
+ {
+ door->direction = -1; // start going down immediately
+ }
+ else if (door->thinker.function.acp1 == (actionf_p1) T_PlatRaise)
+ {
+ // Erm, this is a plat, not a door.
+ // This notably causes a problem in ep1-0500.lmp where
+ // a plat and a door are cross-referenced; the door
+ // doesn't open on 64-bit.
+ // The direction field in vldoor_t corresponds to the wait
+ // field in plat_t. Let's set that to -1 instead.
+
+ plat_t *plat;
+
+ plat = (plat_t *) door;
+ plat->wait = -1;
+ }
+ else
+ {
+ // This isn't a door OR a plat. Now we're in trouble.
+
+ fprintf(stderr, "EV_VerticalDoor: Tried to close "
+ "something that wasn't a door.\n");
+
+ // Try closing it anyway. At least it will work on 32-bit
+ // machines.
+
+ door->direction = -1;
+ }
+ }
+ return;
+ default:
+ break;
+ }
+ }
+
+ // haleyjd 09/15/10: [STRIFE] Removed DOOM door sounds
+
+ // new door thinker
+ door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
+ P_AddThinker (&door->thinker);
+ sec->specialdata = door;
+ door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
+ door->sector = sec;
+ door->direction = 1;
+ door->speed = VDOORSPEED;
+ door->topwait = VDOORWAIT;
+ R_SoundNumForDoor(door); // haleyjd 09/15/10: [STRIFE] Get door sounds
+
+ // for proper sound - [STRIFE] - verified complete
+ switch(line->special)
+ {
+ case 117: // BLAZING DOOR RAISE
+ case 118: // BLAZING DOOR OPEN
+ S_StartSound(&sec->soundorg, sfx_bdopn);
+ break;
+
+ default: // NORMAL DOOR SOUND
+ S_StartSound(&sec->soundorg, door->opensound);
+ break;
+ }
+
+ // haleyjd: [STRIFE] - verified all.
+ switch(line->special)
+ {
+ case 1:
+ case 26:
+ case 27:
+ case 28:
+ door->type = normal;
+ break;
+
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 156: // villsa [STRIFE]
+ case 157: // villsa [STRIFE]
+ case 158: // villsa [STRIFE]
+ door->type = open;
+ line->special = 0;
+ break;
+
+ case 117: // blazing door raise
+ door->type = blazeRaise;
+ door->speed = VDOORSPEED*4;
+ break;
+
+ case 118: // blazing door open
+ door->type = blazeOpen;
+ line->special = 0;
+ door->speed = VDOORSPEED*4;
+ break;
+
+ default:
+ // haleyjd: [STRIFE] pretty important to have this here!
+ door->type = normal;
+ break;
+ }
+
+ // find the top and bottom of the movement range
+ door->topheight = P_FindLowestCeilingSurrounding(sec);
+ door->topheight -= 4*FRACUNIT;
+}
+
+
+//
+// Spawn a door that closes after 30 seconds
+//
+void P_SpawnDoorCloseIn30 (sector_t* sec)
+{
+ vldoor_t* door;
+
+ door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
+
+ P_AddThinker (&door->thinker);
+
+ sec->specialdata = door;
+ sec->special = 0;
+
+ door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
+ door->sector = sec;
+ door->direction = 0;
+ door->type = normal;
+ door->speed = VDOORSPEED;
+ door->topcountdown = 30 * TICRATE;
+}
+
+//
+// Spawn a door that opens after 5 minutes
+//
+void
+P_SpawnDoorRaiseIn5Mins
+( sector_t* sec,
+ int secnum )
+{
+ vldoor_t* door;
+
+ door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
+
+ P_AddThinker (&door->thinker);
+
+ sec->specialdata = door;
+ sec->special = 0;
+
+ door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
+ door->sector = sec;
+ door->direction = 2;
+ door->type = raiseIn5Mins;
+ door->speed = VDOORSPEED;
+ door->topheight = P_FindLowestCeilingSurrounding(sec);
+ door->topheight -= 4*FRACUNIT;
+ door->topwait = VDOORWAIT;
+ door->topcountdown = 5 * 60 * TICRATE;
+}
+
+
+// villsa [STRIFE] resurrected sliding doors
+//
+
+//
+// villsa [STRIFE]
+//
+// Sliding door name information
+//
+static slidename_t slideFrameNames[MAXSLIDEDOORS] =
+{
+ // SIGLDR
+ {
+ "SIGLDR01", // frame1
+ "SIGLDR02", // frame2
+ "SIGLDR03", // frame3
+ "SIGLDR04", // frame4
+ "SIGLDR05", // frame5
+ "SIGLDR06", // frame6
+ "SIGLDR07", // frame7
+ "SIGLDR08" // frame8
+ },
+ // DORSTN
+ {
+ "DORSTN01", // frame1
+ "DORSTN02", // frame2
+ "DORSTN03", // frame3
+ "DORSTN04", // frame4
+ "DORSTN05", // frame5
+ "DORSTN06", // frame6
+ "DORSTN07", // frame7
+ "DORSTN08" // frame8
+ },
+
+ // DORQTR
+ {
+ "DORQTR01", // frame1
+ "DORQTR02", // frame2
+ "DORQTR03", // frame3
+ "DORQTR04", // frame4
+ "DORQTR05", // frame5
+ "DORQTR06", // frame6
+ "DORQTR07", // frame7
+ "DORQTR08" // frame8
+ },
+
+ // DORCRG
+ {
+ "DORCRG01", // frame1
+ "DORCRG02", // frame2
+ "DORCRG03", // frame3
+ "DORCRG04", // frame4
+ "DORCRG05", // frame5
+ "DORCRG06", // frame6
+ "DORCRG07", // frame7
+ "DORCRG08" // frame8
+ },
+
+ // DORCHN
+ {
+ "DORCHN01", // frame1
+ "DORCHN02", // frame2
+ "DORCHN03", // frame3
+ "DORCHN04", // frame4
+ "DORCHN05", // frame5
+ "DORCHN06", // frame6
+ "DORCHN07", // frame7
+ "DORCHN08" // frame8
+ },
+
+ // DORIRS
+ {
+ "DORIRS01", // frame1
+ "DORIRS02", // frame2
+ "DORIRS03", // frame3
+ "DORIRS04", // frame4
+ "DORIRS05", // frame5
+ "DORIRS06", // frame6
+ "DORIRS07", // frame7
+ "DORIRS08" // frame8
+ },
+
+ // DORALN
+ {
+ "DORALN01", // frame1
+ "DORALN02", // frame2
+ "DORALN03", // frame3
+ "DORALN04", // frame4
+ "DORALN05", // frame5
+ "DORALN06", // frame6
+ "DORALN07", // frame7
+ "DORALN08" // frame8
+ },
+
+ {"\0","\0","\0","\0","\0","\0","\0","\0"}
+};
+
+//
+// villsa [STRIFE]
+//
+// Sliding door open sounds
+//
+static sfxenum_t slideOpenSounds[MAXSLIDEDOORS] =
+{
+ sfx_drlmto, sfx_drston, sfx_airlck, sfx_drsmto,
+ sfx_drchno, sfx_airlck, sfx_airlck, sfx_None
+};
+
+//
+// villsa [STRIFE]
+//
+// Sliding door close sounds
+//
+static sfxenum_t slideCloseSounds[MAXSLIDEDOORS] =
+{
+ sfx_drlmtc, sfx_drston, sfx_airlck, sfx_drsmtc,
+ sfx_drchnc, sfx_airlck, sfx_airlck, sfx_None
+};
+
+slideframe_t slideFrames[MAXSLIDEDOORS];
+
+//
+// P_InitSlidingDoorFrames
+//
+// villsa [STRIFE] resurrected
+//
+void P_InitSlidingDoorFrames(void)
+{
+ int i;
+ int f1;
+ int f2;
+ int f3;
+ int f4;
+
+ memset(slideFrames, 0, sizeof(slideframe_t) * MAXSLIDEDOORS);
+
+ for(i = 0; i < MAXSLIDEDOORS; i++)
+ {
+ if(!slideFrameNames[i].frame1[0])
+ break;
+
+ f1 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame1));
+ f2 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame2));
+ f3 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame3));
+ f4 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame4));
+
+ slideFrames[i].frames[0] = f1;
+ slideFrames[i].frames[1] = f2;
+ slideFrames[i].frames[2] = f3;
+ slideFrames[i].frames[3] = f4;
+
+ f1 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame5));
+ f2 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame6));
+ f3 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame7));
+ f4 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame8));
+
+ slideFrames[i].frames[4] = f1;
+ slideFrames[i].frames[5] = f2;
+ slideFrames[i].frames[6] = f3;
+ slideFrames[i].frames[7] = f4;
+ }
+}
+
+
+//
+// P_FindSlidingDoorType
+//
+// Return index into "slideFrames" array
+// for which door type to use
+//
+// villsa [STRIFE] resurrected
+//
+int P_FindSlidingDoorType(line_t* line)
+{
+ int i;
+ int val;
+
+ for(i = 0; i < MAXSLIDEDOORS-1; i++)
+ {
+ val = sides[line->sidenum[0]].toptexture;
+ if(val == slideFrames[i].frames[0])
+ return i;
+ }
+
+ return -1;
+}
+
+//
+// T_SlidingDoor
+//
+// villsa [STRIFE] resurrected
+//
+void T_SlidingDoor(slidedoor_t* door)
+{
+ sector_t* sec;
+
+ sec = door->frontsector;
+
+ switch(door->status)
+ {
+ case sd_opening:
+ if(!door->timer--)
+ {
+ if(++door->frame == SNUMFRAMES)
+ {
+ // IF DOOR IS DONE OPENING...
+ door->line1->flags &= ~ML_BLOCKING;
+ door->line2->flags &= ~ML_BLOCKING;
+
+ if(door->type == sdt_openOnly)
+ {
+ door->frontsector->specialdata = NULL;
+ P_RemoveThinker (&door->thinker);
+ return;
+ }
+
+ door->timer = SDOORWAIT;
+ door->status = sd_waiting;
+ }
+ else
+ {
+ // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME...
+ door->timer = SWAITTICS;
+
+ sides[door->line2->sidenum[0]].midtexture =
+ slideFrames[door->whichDoorIndex].frames[door->frame];
+
+ sides[door->line2->sidenum[1]].midtexture =
+ slideFrames[door->whichDoorIndex].frames[door->frame];
+
+ sides[door->line1->sidenum[0]].midtexture =
+ slideFrames[door->whichDoorIndex].frames[door->frame];
+
+ sides[door->line1->sidenum[1]].midtexture =
+ slideFrames[door->whichDoorIndex].frames[door->frame];
+ }
+ }
+
+ return;
+
+ case sd_waiting:
+ // IF DOOR IS DONE WAITING...
+ if(!door->timer--)
+ {
+ fixed_t speed;
+ fixed_t cheight;
+
+ sec = door->frontsector;
+
+ // CAN DOOR CLOSE?
+ if(sec->thinglist != NULL)
+ {
+ door->timer = SDOORWAIT;
+ return;
+ }
+ else
+ {
+
+ cheight = sec->ceilingheight;
+ speed = cheight - sec->floorheight - (10*FRACUNIT);
+
+ // something blocking it?
+ if(T_MovePlane(sec, speed, sec->floorheight, 0, 1, -1) == crushed)
+ {
+ door->timer = SDOORWAIT;
+ return;
+ }
+ else
+ {
+ // Instantly move plane
+ T_MovePlane(sec, (128*FRACUNIT), cheight, 0, 1, 1);
+
+ // turn line blocking back on
+ door->line1->flags |= ML_BLOCKING;
+ door->line2->flags |= ML_BLOCKING;
+
+ // play close sound
+ S_StartSound(&sec->soundorg, slideCloseSounds[door->whichDoorIndex]);
+
+ door->status = sd_closing;
+ door->timer = SWAITTICS;
+ }
+ }
+ }
+
+ return;
+
+ case sd_closing:
+ if (!door->timer--)
+ {
+ if(--door->frame < 0)
+ {
+ // IF DOOR IS DONE CLOSING...
+ T_MovePlane(sec, (128*FRACUNIT), sec->floorheight, 0, 1, -1);
+ door->frontsector->specialdata = NULL;
+ P_RemoveThinker (&door->thinker);
+ return;
+ }
+ else
+ {
+ // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME...
+ door->timer = SWAITTICS;
+
+ sides[door->line2->sidenum[0]].midtexture =
+ slideFrames[door->whichDoorIndex].frames[door->frame];
+
+ sides[door->line2->sidenum[1]].midtexture =
+ slideFrames[door->whichDoorIndex].frames[door->frame];
+
+ sides[door->line1->sidenum[0]].midtexture =
+ slideFrames[door->whichDoorIndex].frames[door->frame];
+
+ sides[door->line1->sidenum[1]].midtexture =
+ slideFrames[door->whichDoorIndex].frames[door->frame];
+ }
+ }
+
+ return;
+ }
+}
+
+//
+// EV_RemoteSlidingDoor
+//
+// villsa [STRIFE] new function
+//
+int EV_RemoteSlidingDoor(line_t* line, mobj_t* thing)
+{
+ int secnum;
+ sector_t* sec;
+ int i;
+ int rtn;
+ line_t* secline;
+
+ secnum = -1;
+ rtn = 0;
+
+ while((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
+ {
+ sec = &sectors[secnum];
+ if(sec->specialdata)
+ continue;
+
+ for(i = 0; i < 4; i++)
+ {
+ secline = sec->lines[i];
+
+ if(P_FindSlidingDoorType(secline) < 0)
+ continue;
+
+ EV_SlidingDoor(secline, thing);
+ rtn = 1;
+ }
+ }
+
+ return rtn;
+}
+
+
+//
+// EV_SlidingDoor
+//
+// villsa [STRIFE]
+//
+void EV_SlidingDoor(line_t* line, mobj_t* thing)
+{
+ sector_t* sec;
+ slidedoor_t* door;
+ int i;
+ line_t* secline;
+
+ // Make sure door isn't already being animated
+ sec = sides[line->sidenum[1]].sector;
+ door = NULL;
+ if(sec->specialdata)
+ {
+ if (!thing->player)
+ return;
+
+ door = sec->specialdata;
+ if(door->type == sdt_openAndClose)
+ {
+ if(door->status == sd_waiting)
+ {
+ door->status = sd_closing;
+ door->timer = SWAITTICS; // villsa [STRIFE]
+ }
+ }
+ else
+ return;
+ }
+
+ // Init sliding door vars
+ if(!door)
+ {
+ door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
+ P_AddThinker (&door->thinker);
+
+ sec->specialdata = door;
+
+ door->type = sdt_openAndClose;
+ door->status = sd_opening;
+ door->whichDoorIndex = P_FindSlidingDoorType(line);
+
+ // villsa [STRIFE] different error message
+ if(door->whichDoorIndex < 0)
+ I_Error(DEH_String("EV_SlidingDoor: Textures are not defined for sliding door!"));
+
+ sides[line->sidenum[0]].midtexture = sides[line->sidenum[0]].toptexture;
+
+ // villsa [STRIFE]
+ door->line1 = line;
+ door->line2 = line;
+
+ // villsa [STRIFE] this loop assumes that the sliding door is made up
+ // of only four linedefs!
+ for(i = 0; i < 4; i++)
+ {
+ secline = sec->lines[i];
+ if(secline != line)
+ {
+ side_t* side1;
+ side_t* side2;
+
+ side1 = &sides[secline->sidenum[0]];
+ side2 = &sides[line->sidenum[0]];
+
+ if(side1->toptexture == side2->toptexture)
+ door->line2 = secline;
+ }
+ }
+
+ door->thinker.function.acp1 = (actionf_p1)T_SlidingDoor;
+ door->timer = SWAITTICS;
+ door->frontsector = sec;
+ door->frame = 0;
+
+ // villsa [STRIFE] preset flags
+ door->line1->flags |= ML_BLOCKING;
+ door->line2->flags |= ML_BLOCKING;
+
+ // villsa [STRIFE] set the closing sector
+ T_MovePlane(
+ door->frontsector,
+ (128*FRACUNIT),
+ P_FindLowestCeilingSurrounding(door->frontsector),
+ 0,
+ 1,
+ 1);
+
+ // villsa [STRIFE] play open sound
+ S_StartSound(&door->frontsector->soundorg, slideOpenSounds[door->whichDoorIndex]);
+ }
+}
+