1998-04-07 00:00:00 +00:00
|
|
|
// Emacs style mode select -*- C++ -*-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// $Id:$
|
|
|
|
//
|
|
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
|
|
//
|
|
|
|
// This source is available for distribution and/or modification
|
|
|
|
// only under the terms of the DOOM Source Code License as
|
|
|
|
// published by id Software. All rights reserved.
|
|
|
|
//
|
|
|
|
// The source is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
|
|
|
// for more details.
|
|
|
|
//
|
|
|
|
// $Log:$
|
|
|
|
//
|
|
|
|
// DESCRIPTION:
|
|
|
|
// Implements special effects:
|
|
|
|
// Texture animation, height or lighting changes
|
|
|
|
// according to adjacent sectors, respective
|
|
|
|
// utility functions, etc.
|
|
|
|
// Line Tag handling. Line and Sector triggers.
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
#include "m_alloc.h"
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "z_zone.h"
|
|
|
|
#include "m_argv.h"
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "w_wad.h"
|
|
|
|
|
|
|
|
#include "r_local.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
|
|
|
|
#include "g_game.h"
|
|
|
|
|
|
|
|
#include "s_sound.h"
|
|
|
|
|
|
|
|
// State.
|
|
|
|
#include "r_state.h"
|
|
|
|
|
|
|
|
// Data.
|
|
|
|
#include "sounds.h"
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
#include "c_consol.h"
|
|
|
|
|
|
|
|
// [RH] Needed for sky scrolling
|
|
|
|
#include "r_sky.h"
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Animating textures and planes
|
|
|
|
// There is another anim_t used in wi_stuff, unrelated.
|
|
|
|
//
|
|
|
|
typedef struct
|
|
|
|
{
|
1998-07-14 00:00:00 +00:00
|
|
|
BOOL istexture;
|
1998-07-26 00:00:00 +00:00
|
|
|
int picnum;
|
|
|
|
int basepic;
|
|
|
|
int numpics;
|
|
|
|
int speed;
|
1998-04-07 00:00:00 +00:00
|
|
|
} anim_t;
|
|
|
|
|
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
// source animation definition
|
|
|
|
//
|
|
|
|
// [RH] Note that in BOOM's ANIMATED lump, this is an array packed to
|
|
|
|
// byte boundaries. Total size: 23 bytes per entry.
|
1998-04-07 00:00:00 +00:00
|
|
|
//
|
|
|
|
typedef struct
|
|
|
|
{
|
1998-07-26 00:00:00 +00:00
|
|
|
byte istexture; // if false, it is a flat
|
|
|
|
char endname[9];
|
|
|
|
char startname[9];
|
|
|
|
int speed;
|
1998-04-07 00:00:00 +00:00
|
|
|
} animdef_t;
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
static anim_t* lastanim;
|
|
|
|
static anim_t* anims;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
// killough 3/7/98: Initialize generalized scrolling
|
|
|
|
static void P_SpawnScrollers(void);
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
// Animating line specials
|
1998-04-07 00:00:00 +00:00
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
//#define MAXLINEANIMS 64
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
//extern short numlinespecials;
|
|
|
|
//extern line_t* linespeciallist[MAXLINEANIMS];
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
// P_InitPicAnims
|
|
|
|
//
|
|
|
|
// Load the table of animation definitions, checking for existence of
|
|
|
|
// the start and end of each frame. If the start doesn't exist the sequence
|
|
|
|
// is skipped, if the last doesn't exist, BOOM exits.
|
1998-04-07 00:00:00 +00:00
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
// Wall/Flat animation sequences, defined by name of first and last frame,
|
|
|
|
// The full animation sequence is given using all lumps between the start
|
|
|
|
// and end entry, in the order found in the WAD file.
|
|
|
|
//
|
|
|
|
// This routine modified to read its data from a predefined lump or
|
|
|
|
// PWAD lump called ANIMATED rather than a static table in this module to
|
|
|
|
// allow wad designers to insert or modify animation sequences.
|
|
|
|
//
|
|
|
|
// Lump format is an array of byte packed animdef_t structures, terminated
|
|
|
|
// by a structure with istexture == -1. The lump can be generated from a
|
|
|
|
// text source file using SWANTBLS.EXE, distributed with the BOOM utils.
|
|
|
|
// The standard list of switches and animations is contained in the example
|
|
|
|
// source text file DEFSWANI.DAT also in the BOOM util distribution.
|
|
|
|
//
|
|
|
|
// [RH] Rewritten to support BOOM ANIMATED lump but also make absolutely
|
|
|
|
// no assumptions about how the compiler packs the animdefs array.
|
|
|
|
//
|
|
|
|
void P_InitPicAnims (void)
|
|
|
|
{
|
|
|
|
byte *animdefs = W_CacheLumpName ("ANIMATED", PU_STATIC);
|
|
|
|
byte *anim_p;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
// Init animation
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
// [RH] Figure out maximum size of anims array
|
|
|
|
{
|
|
|
|
int i;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
for (i = 0, anim_p = animdefs; *anim_p != 255; anim_p += 23, i++)
|
|
|
|
;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
if (i == 0) {
|
|
|
|
// No animdefs
|
|
|
|
anims = lastanim = NULL;
|
|
|
|
Z_Free (animdefs);
|
|
|
|
return;
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
lastanim = anims = Z_Malloc (i*sizeof(*anims), PU_STATIC, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (anim_p = animdefs; *anim_p != 255; anim_p += 23)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
1998-07-26 00:00:00 +00:00
|
|
|
if (*anim_p /* .istexture */)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
// different episode ?
|
1998-07-26 00:00:00 +00:00
|
|
|
if (R_CheckTextureNumForName (anim_p + 10 /* .startname */) == -1)
|
1998-04-07 00:00:00 +00:00
|
|
|
continue;
|
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
lastanim->picnum = R_TextureNumForName (anim_p + 1 /* .endname */);
|
|
|
|
lastanim->basepic = R_TextureNumForName (anim_p + 10 /* .startname */);
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1998-07-26 00:00:00 +00:00
|
|
|
if ((W_CheckNumForName)(anim_p + 10 /* .startname */, ns_flats) == -1)
|
1998-04-07 00:00:00 +00:00
|
|
|
continue;
|
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
lastanim->picnum = R_FlatNumForName (anim_p + 1 /* .endname */);
|
|
|
|
lastanim->basepic = R_FlatNumForName (anim_p + 10 /* .startname */);
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
lastanim->istexture = *anim_p /* .istexture */;
|
1998-04-07 00:00:00 +00:00
|
|
|
lastanim->numpics = lastanim->picnum - lastanim->basepic + 1;
|
|
|
|
|
|
|
|
if (lastanim->numpics < 2)
|
|
|
|
I_Error ("P_InitPicAnims: bad cycle from %s to %s",
|
1998-07-26 00:00:00 +00:00
|
|
|
anim_p + 10 /* .startname */,
|
|
|
|
anim_p + 1 /* .endname */);
|
|
|
|
|
|
|
|
lastanim->speed = /* .speed */
|
|
|
|
(anim_p[19] << 0) |
|
|
|
|
(anim_p[20] << 8) |
|
|
|
|
(anim_p[21] << 16) |
|
|
|
|
(anim_p[22] << 24);
|
1998-04-07 00:00:00 +00:00
|
|
|
lastanim++;
|
|
|
|
}
|
1998-07-26 00:00:00 +00:00
|
|
|
Z_Free (animdefs);
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
// [RH] Check dmflags for noexit and respond accordingly
|
|
|
|
BOOL CheckIfExitIsGood (mobj_t *self)
|
|
|
|
{
|
|
|
|
if (deathmatch->value && dmflags & DF_NO_EXIT && self) {
|
|
|
|
while (self->health > 0)
|
|
|
|
P_DamageMobj (self, self, self, 10000, MOD_EXIT);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Printf ("%s exited the level.\n", self->player->userinfo->netname);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// UTILITIES
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// getSide()
|
|
|
|
// Will return a side_t*
|
|
|
|
// given the number of the current sector,
|
|
|
|
// the line number, and the side (0/1) that you want.
|
|
|
|
//
|
1998-07-14 00:00:00 +00:00
|
|
|
side_t *getSide (int currentSector, int line, int side)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// getSector()
|
|
|
|
// Will return a sector_t*
|
|
|
|
// given the number of the current sector,
|
|
|
|
// the line number and the side (0/1) that you want.
|
|
|
|
//
|
1998-07-14 00:00:00 +00:00
|
|
|
sector_t *getSector (int currentSector, int line, int side)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// twoSided()
|
|
|
|
// Given the sector number and the line number,
|
|
|
|
// it will tell you whether the line is two-sided or not.
|
|
|
|
//
|
1998-07-14 00:00:00 +00:00
|
|
|
int twoSided (int sector, int line)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
return (sectors[sector].lines[line])->flags & ML_TWOSIDED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// getNextSector()
|
|
|
|
// Return sector_t * of sector next to current.
|
|
|
|
// NULL if not two-sided line
|
|
|
|
//
|
1998-07-14 00:00:00 +00:00
|
|
|
sector_t *getNextSector (line_t *line, sector_t *sec)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
if (!(line->flags & ML_TWOSIDED))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (line->frontsector == sec)
|
|
|
|
return line->backsector;
|
|
|
|
|
|
|
|
return line->frontsector;
|
|
|
|
}
|
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
//
|
|
|
|
// P_SectorActive()
|
|
|
|
//
|
|
|
|
// Passed a linedef special class (floor, ceiling, lighting) and a sector
|
|
|
|
// returns whether the sector is already busy with a linedef special of the
|
|
|
|
// same class. If old demo compatibility true, all linedef special classes
|
|
|
|
// are the same.
|
|
|
|
//
|
|
|
|
// jff 2/23/98 added to prevent old demos from
|
|
|
|
// succeeding in starting multiple specials on one sector
|
|
|
|
//
|
|
|
|
int P_SectorActive(special_e t,sector_t *sec)
|
|
|
|
{
|
|
|
|
if (olddemo) { // return whether any thinker is active
|
|
|
|
return sec->floordata || sec->ceilingdata || sec->lightingdata;
|
|
|
|
} else {
|
|
|
|
switch (t) // return whether thinker of same type is active
|
|
|
|
{
|
|
|
|
case floor_special:
|
|
|
|
return (int)sec->floordata;
|
|
|
|
case ceiling_special:
|
|
|
|
return (int)sec->ceilingdata;
|
|
|
|
case lighting_special:
|
|
|
|
return (int)sec->lightingdata;
|
|
|
|
}
|
|
|
|
return 1; // don't know which special, must be active, shouldn't be here
|
|
|
|
}
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_FindLowestFloorSurrounding()
|
|
|
|
// FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS
|
|
|
|
//
|
|
|
|
fixed_t P_FindLowestFloorSurrounding(sector_t* sec)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
line_t* check;
|
|
|
|
sector_t* other;
|
|
|
|
fixed_t floor = sec->floorheight;
|
|
|
|
|
|
|
|
for (i=0 ;i < sec->linecount ; i++)
|
|
|
|
{
|
|
|
|
check = sec->lines[i];
|
|
|
|
other = getNextSector(check,sec);
|
|
|
|
|
|
|
|
if (!other)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (other->floorheight < floor)
|
|
|
|
floor = other->floorheight;
|
|
|
|
}
|
|
|
|
return floor;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_FindHighestFloorSurrounding()
|
|
|
|
// FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS
|
|
|
|
//
|
|
|
|
fixed_t P_FindHighestFloorSurrounding(sector_t *sec)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
line_t* check;
|
|
|
|
sector_t* other;
|
1998-07-14 00:00:00 +00:00
|
|
|
fixed_t floor = MININT;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
for (i=0 ;i < sec->linecount ; i++)
|
|
|
|
{
|
|
|
|
check = sec->lines[i];
|
|
|
|
other = getNextSector(check,sec);
|
|
|
|
|
|
|
|
if (!other)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (other->floorheight > floor)
|
|
|
|
floor = other->floorheight;
|
|
|
|
}
|
|
|
|
return floor;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
// P_FindNextHighestFloor()
|
|
|
|
//
|
|
|
|
// Passed a sector and a floor height, returns the fixed point value
|
|
|
|
// of the smallest floor height in a surrounding sector larger than
|
|
|
|
// the floor height passed. If no such height exists the floorheight
|
|
|
|
// passed is returned.
|
|
|
|
//
|
|
|
|
// Rewritten by Lee Killough to avoid fixed array and to be faster
|
|
|
|
//
|
|
|
|
fixed_t P_FindNextHighestFloor(sector_t *sec, int currentheight)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
1998-07-26 00:00:00 +00:00
|
|
|
sector_t *other;
|
|
|
|
int i;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
for (i = 0; i < sec->linecount; i++) {
|
1998-07-26 00:00:00 +00:00
|
|
|
if ((other = getNextSector(sec->lines[i],sec)) &&
|
|
|
|
other->floorheight > currentheight) {
|
|
|
|
int height = other->floorheight;
|
|
|
|
|
|
|
|
while (++i < sec->linecount) {
|
|
|
|
if ((other = getNextSector(sec->lines[i],sec)) &&
|
|
|
|
other->floorheight < height &&
|
|
|
|
other->floorheight > currentheight) {
|
|
|
|
height = other->floorheight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return currentheight;
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
//
|
|
|
|
// P_FindNextLowestFloor()
|
|
|
|
//
|
|
|
|
// Passed a sector and a floor height, returns the fixed point value
|
|
|
|
// of the largest floor height in a surrounding sector smaller than
|
|
|
|
// the floor height passed. If no such height exists the floorheight
|
|
|
|
// passed is returned.
|
|
|
|
//
|
|
|
|
// jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this
|
|
|
|
//
|
|
|
|
fixed_t P_FindNextLowestFloor(sector_t *sec, int currentheight)
|
|
|
|
{
|
|
|
|
sector_t *other;
|
|
|
|
int i;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
for (i = 0; i < sec->linecount; i++)
|
|
|
|
if ((other = getNextSector(sec->lines[i],sec)) &&
|
|
|
|
other->floorheight < currentheight) {
|
|
|
|
int height = other->floorheight;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
while (++i < sec->linecount) {
|
|
|
|
if ((other = getNextSector(sec->lines[i],sec)) &&
|
|
|
|
other->floorheight > height &&
|
|
|
|
other->floorheight < currentheight) {
|
|
|
|
height = other->floorheight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return height;
|
|
|
|
}
|
|
|
|
return currentheight;
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// FIND LOWEST CEILING IN THE SURROUNDING SECTORS
|
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
fixed_t P_FindLowestCeilingSurrounding (sector_t *sec)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
line_t* check;
|
|
|
|
sector_t* other;
|
|
|
|
fixed_t height = MAXINT;
|
|
|
|
|
|
|
|
for (i=0 ;i < sec->linecount ; i++)
|
|
|
|
{
|
|
|
|
check = sec->lines[i];
|
|
|
|
other = getNextSector(check,sec);
|
|
|
|
|
|
|
|
if (!other)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (other->ceilingheight < height)
|
|
|
|
height = other->ceilingheight;
|
|
|
|
}
|
|
|
|
return height;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS
|
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
fixed_t P_FindHighestCeilingSurrounding (sector_t *sec)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
line_t* check;
|
|
|
|
sector_t* other;
|
1998-07-14 00:00:00 +00:00
|
|
|
fixed_t height = MININT;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
for (i=0 ;i < sec->linecount ; i++)
|
|
|
|
{
|
|
|
|
check = sec->lines[i];
|
|
|
|
other = getNextSector(check,sec);
|
|
|
|
|
|
|
|
if (!other)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (other->ceilingheight > height)
|
|
|
|
height = other->ceilingheight;
|
|
|
|
}
|
|
|
|
return height;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
|
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
int P_FindSectorFromLineTag (line_t *line, int start)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=start+1;i<numsectors;i++)
|
|
|
|
if (sectors[i].tag == line->tag)
|
|
|
|
return i;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
int P_FindLineFromLineTag (line_t *line, int start)
|
|
|
|
{
|
|
|
|
int i;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-26 00:00:00 +00:00
|
|
|
for (i = start+1; i < numlines; i++)
|
|
|
|
if (lines[i].tag == line->tag)
|
|
|
|
return i;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Find minimum light from an adjacent sector
|
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
int P_FindMinSurroundingLight (sector_t *sector, int max)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int min;
|
|
|
|
line_t* line;
|
|
|
|
sector_t* check;
|
|
|
|
|
|
|
|
min = max;
|
|
|
|
for (i=0 ; i < sector->linecount ; i++)
|
|
|
|
{
|
|
|
|
line = sector->lines[i];
|
|
|
|
check = getNextSector(line,sector);
|
|
|
|
|
|
|
|
if (!check)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (check->lightlevel < min)
|
|
|
|
min = check->lightlevel;
|
|
|
|
}
|
|
|
|
return min;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// EVENTS
|
|
|
|
// Events are operations triggered by using, crossing,
|
|
|
|
// or shooting special lines, or by timed thinkers.
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_CrossSpecialLine - TRIGGER
|
|
|
|
// Called every time a thing origin is about
|
|
|
|
// to cross a line with a non 0 special.
|
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
void P_CrossSpecialLine (int linenum, int side, mobj_t *thing)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
line_t* line;
|
|
|
|
int ok;
|
|
|
|
|
|
|
|
line = &lines[linenum];
|
|
|
|
|
|
|
|
// Triggers that other things can activate
|
|
|
|
if (!thing->player)
|
|
|
|
{
|
|
|
|
// Things that should NOT trigger specials...
|
|
|
|
switch(thing->type)
|
|
|
|
{
|
|
|
|
case MT_ROCKET:
|
|
|
|
case MT_PLASMA:
|
|
|
|
case MT_BFG:
|
|
|
|
case MT_TROOPSHOT:
|
|
|
|
case MT_HEADSHOT:
|
|
|
|
case MT_BRUISERSHOT:
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ok = 0;
|
|
|
|
switch(line->special)
|
|
|
|
{
|
|
|
|
case 39: // TELEPORT TRIGGER
|
|
|
|
case 97: // TELEPORT RETRIGGER
|
|
|
|
case 125: // TELEPORT MONSTERONLY TRIGGER
|
|
|
|
case 126: // TELEPORT MONSTERONLY RETRIGGER
|
|
|
|
case 4: // RAISE DOOR
|
|
|
|
case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER
|
|
|
|
case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER
|
|
|
|
ok = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!ok)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Note: could use some const's here.
|
|
|
|
switch (line->special)
|
|
|
|
{
|
|
|
|
// TRIGGERS.
|
|
|
|
// All from here to RETRIGGERS.
|
|
|
|
case 2:
|
|
|
|
// Open Door
|
|
|
|
EV_DoDoor(line,open);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
// Close Door
|
|
|
|
EV_DoDoor(line,close);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
// Raise Door
|
|
|
|
EV_DoDoor(line,normal);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 5:
|
|
|
|
// Raise Floor
|
|
|
|
EV_DoFloor(line,raiseFloor);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
// Fast Ceiling Crush & Raise
|
|
|
|
EV_DoCeiling(line,fastCrushAndRaise);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
// Build Stairs
|
|
|
|
EV_BuildStairs(line,build8);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 10:
|
|
|
|
// PlatDownWaitUp
|
|
|
|
EV_DoPlat(line,downWaitUpStay,0);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 12:
|
|
|
|
// Light Turn On - brightest near
|
|
|
|
EV_LightTurnOn(line,0);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 13:
|
|
|
|
// Light Turn On 255
|
|
|
|
EV_LightTurnOn(line,255);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 16:
|
|
|
|
// Close Door 30
|
|
|
|
EV_DoDoor(line,close30ThenOpen);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 17:
|
|
|
|
// Start Light Strobing
|
|
|
|
EV_StartLightStrobing(line);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 19:
|
|
|
|
// Lower Floor
|
|
|
|
EV_DoFloor(line,lowerFloor);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 22:
|
|
|
|
// Raise floor to nearest height and change texture
|
|
|
|
EV_DoPlat(line,raiseToNearestAndChange,0);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 25:
|
|
|
|
// Ceiling Crush and Raise
|
|
|
|
EV_DoCeiling(line,crushAndRaise);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 30:
|
|
|
|
// Raise floor to shortest texture height
|
|
|
|
// on either side of lines.
|
|
|
|
EV_DoFloor(line,raiseToTexture);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 35:
|
|
|
|
// Lights Very Dark
|
|
|
|
EV_LightTurnOn(line,35);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 36:
|
|
|
|
// Lower Floor (TURBO)
|
|
|
|
EV_DoFloor(line,turboLower);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 37:
|
|
|
|
// LowerAndChange
|
|
|
|
EV_DoFloor(line,lowerAndChange);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 38:
|
|
|
|
// Lower Floor To Lowest
|
|
|
|
EV_DoFloor( line, lowerFloorToLowest );
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 39:
|
|
|
|
// TELEPORT!
|
|
|
|
EV_Teleport( line, side, thing );
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 40:
|
|
|
|
// RaiseCeilingLowerFloor
|
|
|
|
EV_DoCeiling( line, raiseToHighest );
|
|
|
|
EV_DoFloor( line, lowerFloorToLowest );
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 44:
|
|
|
|
// Ceiling Crush
|
|
|
|
EV_DoCeiling( line, lowerAndCrush );
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 52:
|
|
|
|
// EXIT!
|
1998-07-14 00:00:00 +00:00
|
|
|
if (CheckIfExitIsGood (thing))
|
|
|
|
G_ExitLevel ();
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 53:
|
|
|
|
// Perpetual Platform Raise
|
|
|
|
EV_DoPlat(line,perpetualRaise,0);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 54:
|
|
|
|
// Platform Stop
|
|
|
|
EV_StopPlat(line);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 56:
|
|
|
|
// Raise Floor Crush
|
|
|
|
EV_DoFloor(line,raiseFloorCrush);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 57:
|
|
|
|
// Ceiling Crush Stop
|
|
|
|
EV_CeilingCrushStop(line);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 58:
|
|
|
|
// Raise Floor 24
|
|
|
|
EV_DoFloor(line,raiseFloor24);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 59:
|
|
|
|
// Raise Floor 24 And Change
|
|
|
|
EV_DoFloor(line,raiseFloor24AndChange);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 104:
|
|
|
|
// Turn lights off in sector(tag)
|
|
|
|
EV_TurnTagLightsOff(line);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 108:
|
|
|
|
// Blazing Door Raise (faster than TURBO!)
|
|
|
|
EV_DoDoor (line,blazeRaise);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 109:
|
|
|
|
// Blazing Door Open (faster than TURBO!)
|
|
|
|
EV_DoDoor (line,blazeOpen);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 100:
|
|
|
|
// Build Stairs Turbo 16
|
|
|
|
EV_BuildStairs(line,turbo16);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 110:
|
|
|
|
// Blazing Door Close (faster than TURBO!)
|
|
|
|
EV_DoDoor (line,blazeClose);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 119:
|
|
|
|
// Raise floor to nearest surr. floor
|
|
|
|
EV_DoFloor(line,raiseFloorToNearest);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 121:
|
|
|
|
// Blazing PlatDownWaitUpStay
|
|
|
|
EV_DoPlat(line,blazeDWUS,0);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 124:
|
|
|
|
// Secret EXIT
|
1998-07-14 00:00:00 +00:00
|
|
|
if (CheckIfExitIsGood (thing))
|
|
|
|
G_SecretExitLevel ();
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 125:
|
|
|
|
// TELEPORT MonsterONLY
|
|
|
|
if (!thing->player)
|
|
|
|
{
|
|
|
|
EV_Teleport( line, side, thing );
|
|
|
|
line->special = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 130:
|
|
|
|
// Raise Floor Turbo
|
|
|
|
EV_DoFloor(line,raiseFloorTurbo);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 141:
|
|
|
|
// Silent Ceiling Crush & Raise
|
|
|
|
EV_DoCeiling(line,silentCrushAndRaise);
|
|
|
|
line->special = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// RETRIGGERS. All from here till end.
|
|
|
|
case 72:
|
|
|
|
// Ceiling Crush
|
|
|
|
EV_DoCeiling( line, lowerAndCrush );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 73:
|
|
|
|
// Ceiling Crush and Raise
|
|
|
|
EV_DoCeiling(line,crushAndRaise);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 74:
|
|
|
|
// Ceiling Crush Stop
|
|
|
|
EV_CeilingCrushStop(line);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 75:
|
|
|
|
// Close Door
|
|
|
|
EV_DoDoor(line,close);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 76:
|
|
|
|
// Close Door 30
|
|
|
|
EV_DoDoor(line,close30ThenOpen);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 77:
|
|
|
|
// Fast Ceiling Crush & Raise
|
|
|
|
EV_DoCeiling(line,fastCrushAndRaise);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 79:
|
|
|
|
// Lights Very Dark
|
|
|
|
EV_LightTurnOn(line,35);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 80:
|
|
|
|
// Light Turn On - brightest near
|
|
|
|
EV_LightTurnOn(line,0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 81:
|
|
|
|
// Light Turn On 255
|
|
|
|
EV_LightTurnOn(line,255);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 82:
|
|
|
|
// Lower Floor To Lowest
|
|
|
|
EV_DoFloor( line, lowerFloorToLowest );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 83:
|
|
|
|
// Lower Floor
|
|
|
|
EV_DoFloor(line,lowerFloor);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 84:
|
|
|
|
// LowerAndChange
|
|
|
|
EV_DoFloor(line,lowerAndChange);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 86:
|
|
|
|
// Open Door
|
|
|
|
EV_DoDoor(line,open);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 87:
|
|
|
|
// Perpetual Platform Raise
|
|
|
|
EV_DoPlat(line,perpetualRaise,0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 88:
|
|
|
|
// PlatDownWaitUp
|
|
|
|
EV_DoPlat(line,downWaitUpStay,0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 89:
|
|
|
|
// Platform Stop
|
|
|
|
EV_StopPlat(line);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 90:
|
|
|
|
// Raise Door
|
|
|
|
EV_DoDoor(line,normal);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 91:
|
|
|
|
// Raise Floor
|
|
|
|
EV_DoFloor(line,raiseFloor);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 92:
|
|
|
|
// Raise Floor 24
|
|
|
|
EV_DoFloor(line,raiseFloor24);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 93:
|
|
|
|
// Raise Floor 24 And Change
|
|
|
|
EV_DoFloor(line,raiseFloor24AndChange);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 94:
|
|
|
|
// Raise Floor Crush
|
|
|
|
EV_DoFloor(line,raiseFloorCrush);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 95:
|
|
|
|
// Raise floor to nearest height
|
|
|
|
// and change texture.
|
|
|
|
EV_DoPlat(line,raiseToNearestAndChange,0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 96:
|
|
|
|
// Raise floor to shortest texture height
|
|
|
|
// on either side of lines.
|
|
|
|
EV_DoFloor(line,raiseToTexture);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 97:
|
|
|
|
// TELEPORT!
|
|
|
|
EV_Teleport( line, side, thing );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 98:
|
|
|
|
// Lower Floor (TURBO)
|
|
|
|
EV_DoFloor(line,turboLower);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 105:
|
|
|
|
// Blazing Door Raise (faster than TURBO!)
|
|
|
|
EV_DoDoor (line,blazeRaise);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 106:
|
|
|
|
// Blazing Door Open (faster than TURBO!)
|
|
|
|
EV_DoDoor (line,blazeOpen);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 107:
|
|
|
|
// Blazing Door Close (faster than TURBO!)
|
|
|
|
EV_DoDoor (line,blazeClose);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 120:
|
|
|
|
// Blazing PlatDownWaitUpStay.
|
|
|
|
EV_DoPlat(line,blazeDWUS,0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 126:
|
|
|
|
// TELEPORT MonsterONLY.
|
|
|
|
if (!thing->player)
|
|
|
|
EV_Teleport( line, side, thing );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 128:
|
|
|
|
// Raise To Nearest Floor
|
|
|
|
EV_DoFloor(line,raiseFloorToNearest);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 129:
|
|
|
|
// Raise Floor Turbo
|
|
|
|
EV_DoFloor(line,raiseFloorTurbo);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_ShootSpecialLine - IMPACT SPECIALS
|
|
|
|
// Called when a thing shoots a special line.
|
|
|
|
//
|
1998-07-26 00:00:00 +00:00
|
|
|
void P_ShootSpecialLine (mobj_t *thing, line_t *line)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
1998-07-26 00:00:00 +00:00
|
|
|
int ok;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
// Impacts that other things can activate.
|
|
|
|
if (!thing->player)
|
|
|
|
{
|
|
|
|
ok = 0;
|
|
|
|
switch(line->special)
|
|
|
|
{
|
|
|
|
case 46:
|
|
|
|
// OPEN DOOR IMPACT
|
|
|
|
ok = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!ok)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(line->special)
|
|
|
|
{
|
|
|
|
case 24:
|
|
|
|
// RAISE FLOOR
|
|
|
|
EV_DoFloor(line,raiseFloor);
|
|
|
|
P_ChangeSwitchTexture(line,0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 46:
|
|
|
|
// OPEN DOOR
|
|
|
|
EV_DoDoor(line,open);
|
|
|
|
P_ChangeSwitchTexture(line,1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 47:
|
|
|
|
// RAISE FLOOR NEAR AND CHANGE
|
|
|
|
EV_DoPlat(line,raiseToNearestAndChange,0);
|
|
|
|
P_ChangeSwitchTexture(line,0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_PlayerInSpecialSector
|
|
|
|
// Called every tic frame
|
|
|
|
// that the player origin is in a special sector
|
|
|
|
//
|
|
|
|
void P_PlayerInSpecialSector (player_t* player)
|
|
|
|
{
|
|
|
|
sector_t* sector;
|
|
|
|
|
|
|
|
sector = player->mo->subsector->sector;
|
|
|
|
|
|
|
|
// Falling, not all the way down yet?
|
|
|
|
if (player->mo->z != sector->floorheight)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Has hitten ground.
|
|
|
|
switch (sector->special)
|
|
|
|
{
|
|
|
|
case 5:
|
|
|
|
// HELLSLIME DAMAGE
|
|
|
|
if (!player->powers[pw_ironfeet])
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!(level.time&0x1f))
|
1998-07-14 00:00:00 +00:00
|
|
|
P_DamageMobj (player->mo, NULL, NULL, 10, MOD_SLIME);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
// NUKAGE DAMAGE
|
|
|
|
if (!player->powers[pw_ironfeet])
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!(level.time&0x1f))
|
1998-07-14 00:00:00 +00:00
|
|
|
P_DamageMobj (player->mo, NULL, NULL, 5, MOD_LAVA);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 16:
|
|
|
|
// SUPER HELLSLIME DAMAGE
|
|
|
|
case 4:
|
|
|
|
// STROBE HURT
|
|
|
|
if (!player->powers[pw_ironfeet]
|
1998-07-14 00:00:00 +00:00
|
|
|
|| (P_Random (pr_playerinspecialsector)<5) )
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!(level.time&0x1f))
|
1998-07-14 00:00:00 +00:00
|
|
|
P_DamageMobj (player->mo, NULL, NULL, 20, MOD_SLIME);
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 9:
|
|
|
|
// SECRET SECTOR
|
|
|
|
player->secretcount++;
|
1998-04-07 00:00:00 +00:00
|
|
|
level.found_secrets++;
|
1998-04-07 00:00:00 +00:00
|
|
|
sector->special = 0;
|
|
|
|
if (player == &players[displayplayer]) {
|
|
|
|
C_MidPrint ("You found a secret area!");
|
|
|
|
S_StartSound (ORIGIN_AMBIENT2, sfx_secret);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 11:
|
|
|
|
// EXIT SUPER DAMAGE! (for E1M8 finale)
|
|
|
|
player->cheats &= ~CF_GODMODE;
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
if (!(level.time & 0x1f))
|
|
|
|
P_DamageMobj (player->mo, NULL, NULL, 20, MOD_UNKNOWN);
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
if (player->health <= 10 && (!deathmatch->value || !(dmflags & DF_NO_EXIT)))
|
1998-04-07 00:00:00 +00:00
|
|
|
G_ExitLevel();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
1998-07-14 00:00:00 +00:00
|
|
|
DPrintf ("P_PlayerInSpecialSector: %i unknown\n", sector->special);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_UpdateSpecials
|
|
|
|
// Animate planes, scroll walls, etc.
|
|
|
|
//
|
1998-07-14 00:00:00 +00:00
|
|
|
extern cvar_t *timelimit;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
void P_UpdateSpecials (void)
|
|
|
|
{
|
|
|
|
anim_t* anim;
|
|
|
|
int pic;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
// LEVEL TIMER
|
1998-07-14 00:00:00 +00:00
|
|
|
if (timelimit->value)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
1998-07-14 00:00:00 +00:00
|
|
|
if (level.time >= (int)(timelimit->value * TICRATE * 60)) {
|
|
|
|
Printf ("Timelimit exceeded\n");
|
1998-04-07 00:00:00 +00:00
|
|
|
G_ExitLevel();
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ANIMATE FLATS AND TEXTURES GLOBALLY
|
|
|
|
for (anim = anims ; anim < lastanim ; anim++)
|
|
|
|
{
|
|
|
|
for (i=anim->basepic ; i<anim->basepic+anim->numpics ; i++)
|
|
|
|
{
|
1998-04-07 00:00:00 +00:00
|
|
|
pic = anim->basepic + ( (level.time/anim->speed + i)%anim->numpics );
|
1998-04-07 00:00:00 +00:00
|
|
|
if (anim->istexture)
|
|
|
|
texturetranslation[i] = pic;
|
|
|
|
else
|
|
|
|
flattranslation[i] = pic;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
// [RH] Scroll the sky
|
|
|
|
sky1pos = (sky1pos + level.skyspeed1) & 0xffffff;
|
|
|
|
sky2pos = (sky2pos + level.skyspeed2) & 0xffffff;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
// DO BUTTONS
|
|
|
|
for (i = 0; i < MAXBUTTONS; i++)
|
|
|
|
if (buttonlist[i].btimer)
|
|
|
|
{
|
|
|
|
buttonlist[i].btimer--;
|
|
|
|
if (!buttonlist[i].btimer)
|
|
|
|
{
|
|
|
|
switch(buttonlist[i].where)
|
|
|
|
{
|
|
|
|
case top:
|
|
|
|
sides[buttonlist[i].line->sidenum[0]].toptexture =
|
|
|
|
buttonlist[i].btexture;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case middle:
|
|
|
|
sides[buttonlist[i].line->sidenum[0]].midtexture =
|
|
|
|
buttonlist[i].btexture;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case bottom:
|
|
|
|
sides[buttonlist[i].line->sidenum[0]].bottomtexture =
|
|
|
|
buttonlist[i].btexture;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
S_StartSound((mobj_t *)&buttonlist[i].soundorg,sfx_swtchn);
|
|
|
|
memset(&buttonlist[i],0,sizeof(button_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Special Stuff that can not be categorized
|
|
|
|
//
|
|
|
|
int EV_DoDonut(line_t* line)
|
|
|
|
{
|
|
|
|
sector_t* s1;
|
|
|
|
sector_t* s2;
|
|
|
|
sector_t* s3;
|
|
|
|
int secnum;
|
|
|
|
int rtn;
|
|
|
|
int i;
|
|
|
|
floormove_t* floor;
|
|
|
|
|
|
|
|
secnum = -1;
|
|
|
|
rtn = 0;
|
|
|
|
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
|
|
|
|
{
|
1998-07-26 00:00:00 +00:00
|
|
|
s1 = §ors[secnum]; // s1 is pillar's sector
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
// ALREADY MOVING? IF SO, KEEP GOING...
|
1998-07-26 00:00:00 +00:00
|
|
|
if (P_SectorActive (floor_special, s1)) //jff 2/22/98
|
1998-04-07 00:00:00 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
rtn = 1;
|
1998-07-26 00:00:00 +00:00
|
|
|
s2 = getNextSector(s1->lines[0],s1); // s2 is pool's sector
|
|
|
|
if (!s2) // note lowest numbered line around
|
|
|
|
continue; // pillar must be two-sided
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
for (i = 0;i < s2->linecount;i++)
|
|
|
|
{
|
|
|
|
if ((!s2->lines[i]->flags & ML_TWOSIDED) ||
|
|
|
|
(s2->lines[i]->backsector == s1))
|
|
|
|
continue;
|
|
|
|
s3 = s2->lines[i]->backsector;
|
|
|
|
|
|
|
|
// Spawn rising slime
|
|
|
|
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
|
|
|
|
P_AddThinker (&floor->thinker);
|
1998-07-26 00:00:00 +00:00
|
|
|
s2->floordata = floor; //jff 2/22/98
|
1998-04-07 00:00:00 +00:00
|
|
|
floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
|
|
|
|
floor->type = donutRaise;
|
|
|
|
floor->crush = false;
|
|
|
|
floor->direction = 1;
|
|
|
|
floor->sector = s2;
|
|
|
|
floor->speed = FLOORSPEED / 2;
|
|
|
|
floor->texture = s3->floorpic;
|
|
|
|
floor->newspecial = 0;
|
|
|
|
floor->floordestheight = s3->floorheight;
|
|
|
|
|
|
|
|
// Spawn lowering donut-hole
|
|
|
|
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
|
|
|
|
P_AddThinker (&floor->thinker);
|
1998-07-26 00:00:00 +00:00
|
|
|
s1->floordata = floor; //jff 2/22/98
|
1998-04-07 00:00:00 +00:00
|
|
|
floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
|
|
|
|
floor->type = lowerFloor;
|
|
|
|
floor->crush = false;
|
|
|
|
floor->direction = -1;
|
|
|
|
floor->sector = s1;
|
|
|
|
floor->speed = FLOORSPEED / 2;
|
|
|
|
floor->floordestheight = s3->floorheight;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rtn;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// SPECIAL SPAWNING
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_SpawnSpecials
|
|
|
|
// After the map has been loaded, scan for specials
|
|
|
|
// that spawn thinkers
|
|
|
|
//
|
|
|
|
|
|
|
|
void P_SpawnSpecials (void)
|
|
|
|
{
|
|
|
|
sector_t* sector;
|
|
|
|
int i;
|
|
|
|
int episode;
|
|
|
|
|
|
|
|
episode = 1;
|
|
|
|
if (W_CheckNumForName("texture2") >= 0)
|
|
|
|
episode = 2;
|
|
|
|
|
|
|
|
|
|
|
|
// Init special SECTORs.
|
|
|
|
sector = sectors;
|
|
|
|
for (i=0 ; i<numsectors ; i++, sector++)
|
|
|
|
{
|
|
|
|
if (!sector->special)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (sector->special)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
// FLICKERING LIGHTS
|
|
|
|
P_SpawnLightFlash (sector);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
// STROBE FAST
|
|
|
|
P_SpawnStrobeFlash(sector,FASTDARK,0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
// STROBE SLOW
|
|
|
|
P_SpawnStrobeFlash(sector,SLOWDARK,0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
// STROBE FAST/DEATH SLIME
|
|
|
|
P_SpawnStrobeFlash(sector,FASTDARK,0);
|
|
|
|
sector->special = 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
// GLOWING LIGHT
|
|
|
|
P_SpawnGlowingLight(sector);
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
// SECRET SECTOR
|
1998-04-07 00:00:00 +00:00
|
|
|
level.total_secrets++;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 10:
|
|
|
|
// DOOR CLOSE IN 30 SECONDS
|
|
|
|
P_SpawnDoorCloseIn30 (sector);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 12:
|
|
|
|
// SYNC STROBE SLOW
|
|
|
|
P_SpawnStrobeFlash (sector, SLOWDARK, 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 13:
|
|
|
|
// SYNC STROBE FAST
|
|
|
|
P_SpawnStrobeFlash (sector, FASTDARK, 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 14:
|
|
|
|
// DOOR RAISE IN 5 MINUTES
|
|
|
|
P_SpawnDoorRaiseIn5Mins (sector, i);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 17:
|
1998-07-26 00:00:00 +00:00
|
|
|
// fire flickering
|
1998-04-07 00:00:00 +00:00
|
|
|
P_SpawnFireFlicker(sector);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Init other misc stuff
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!activeceilings) {
|
|
|
|
MaxCeilings = 30; // [RH] Default. Increased as needed.
|
|
|
|
activeceilings = Malloc (MaxCeilings * sizeof(ceiling_t *));
|
|
|
|
}
|
|
|
|
for (i = 0;i < MaxCeilings;i++)
|
1998-04-07 00:00:00 +00:00
|
|
|
activeceilings[i] = NULL;
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!activeplats) {
|
|
|
|
MaxPlats = 30; // [RH] Default. Increased as needed.
|
|
|
|
activeplats = Malloc (MaxPlats * sizeof(plat_t *));
|
|
|
|
}
|
|
|
|
for (i = 0;i < MaxPlats;i++)
|
1998-04-07 00:00:00 +00:00
|
|
|
activeplats[i] = NULL;
|
|
|
|
|
|
|
|
for (i = 0;i < MAXBUTTONS;i++)
|
|
|
|
memset(&buttonlist[i],0,sizeof(button_t));
|
|
|
|
|
|
|
|
// UNUSED: no horizonal sliders.
|
|
|
|
// P_InitSlidingDoorFrames();
|
1998-07-26 00:00:00 +00:00
|
|
|
|
|
|
|
P_SpawnScrollers(); // killough 3/7/98: Add generalized scrollers
|
|
|
|
|
|
|
|
for (i=0; i<numlines; i++)
|
|
|
|
switch (lines[i].special)
|
|
|
|
{
|
|
|
|
int s, sec;
|
|
|
|
|
|
|
|
// killough 3/7/98:
|
|
|
|
// support for drawn heights coming from different sector
|
|
|
|
case 242:
|
|
|
|
sec = sides[*lines[i].sidenum].sector-sectors;
|
|
|
|
for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
|
|
|
|
sectors[s].heightsec = sec;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// killough 3/16/98: Add support for setting
|
|
|
|
// floor lighting independently (e.g. lava)
|
|
|
|
case 213:
|
|
|
|
sec = sides[*lines[i].sidenum].sector-sectors;
|
|
|
|
for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
|
|
|
|
sectors[s].floorlightsec = sec;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// killough 4/11/98: Add support for setting
|
|
|
|
// ceiling lighting independently
|
|
|
|
case 261:
|
|
|
|
sec = sides[*lines[i].sidenum].sector-sectors;
|
|
|
|
for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
|
|
|
|
sectors[s].ceilinglightsec = sec;
|
|
|
|
break;
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
1998-07-26 00:00:00 +00:00
|
|
|
|
|
|
|
// killough 2/28/98:
|
|
|
|
//
|
|
|
|
// This function, with the help of r_plane.c and r_bsp.c, supports generalized
|
|
|
|
// scrolling floors and walls, with optional mobj-carrying properties, e.g.
|
|
|
|
// conveyor belts, rivers, etc. A linedef with a special type affects all
|
|
|
|
// tagged sectors the same way, by creating scrolling and/or object-carrying
|
|
|
|
// properties. Multiple linedefs may be used on the same sector and are
|
|
|
|
// cumulative, although the special case of scrolling a floor and carrying
|
|
|
|
// things on it, requires only one linedef. The linedef's direction determines
|
|
|
|
// the scrolling direction, and the linedef's length determines the scrolling
|
|
|
|
// speed. This was designed so that an edge around the sector could be used to
|
|
|
|
// control the direction of the sector's scrolling, which is usually what is
|
|
|
|
// desired.
|
|
|
|
//
|
|
|
|
// Process the active scrollers.
|
|
|
|
//
|
|
|
|
// This is the main scrolling code
|
|
|
|
// killough 3/7/98
|
|
|
|
|
|
|
|
void T_Scroll(scroll_t *s)
|
|
|
|
{
|
|
|
|
fixed_t dx = s->dx, dy = s->dy;
|
|
|
|
|
|
|
|
if (s->control != -1)
|
|
|
|
{ // compute scroll amounts based on a sector's height changes
|
|
|
|
fixed_t height = sectors[s->control].floorheight +
|
|
|
|
sectors[s->control].ceilingheight;
|
|
|
|
fixed_t delta = height - s->last_height;
|
|
|
|
s->last_height = height;
|
|
|
|
dx = FixedMul(dx, delta);
|
|
|
|
dy = FixedMul(dy, delta);
|
|
|
|
}
|
|
|
|
|
|
|
|
// killough 3/14/98: Add acceleration
|
|
|
|
if (s->accel)
|
|
|
|
{
|
|
|
|
s->vdx = dx += s->vdx;
|
|
|
|
s->vdy = dy += s->vdy;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(dx | dy)) // no-op if both (x,y) offsets 0
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (s->type)
|
|
|
|
{
|
|
|
|
side_t *side;
|
|
|
|
sector_t *sec;
|
|
|
|
fixed_t height, waterheight; // killough 4/4/98: add waterheight
|
|
|
|
msecnode_t *node;
|
|
|
|
mobj_t *thing;
|
|
|
|
|
|
|
|
case sc_side: // killough 3/7/98: Scroll wall texture
|
|
|
|
side = sides + s->affectee;
|
|
|
|
side->textureoffset += dx;
|
|
|
|
side->rowoffset += dy;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case sc_floor: // killough 3/7/98: Scroll floor texture
|
|
|
|
sec = sectors + s->affectee;
|
|
|
|
sec->floor_xoffs += dx;
|
|
|
|
sec->floor_yoffs += dy;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case sc_ceiling: // killough 3/7/98: Scroll ceiling texture
|
|
|
|
sec = sectors + s->affectee;
|
|
|
|
sec->ceiling_xoffs += dx;
|
|
|
|
sec->ceiling_yoffs += dy;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case sc_carry:
|
|
|
|
|
|
|
|
// killough 3/7/98: Carry things on floor
|
|
|
|
// killough 3/20/98: use new sector list which reflects true members
|
|
|
|
// killough 3/27/98: fix carrier bug
|
|
|
|
// killough 4/4/98: Underwater, carry things even w/o gravity
|
|
|
|
|
|
|
|
sec = sectors + s->affectee;
|
|
|
|
height = sec->floorheight;
|
|
|
|
waterheight = sec->heightsec != -1 &&
|
|
|
|
sectors[sec->heightsec].floorheight > height ?
|
|
|
|
sectors[sec->heightsec].floorheight : MININT;
|
|
|
|
|
|
|
|
for (node = sec->touching_thinglist; node; node = node->m_snext)
|
|
|
|
if (!((thing = node->m_thing)->flags & MF_NOCLIP) &&
|
|
|
|
(!(thing->flags & MF_NOGRAVITY || thing->z > height) ||
|
|
|
|
thing->z < waterheight))
|
|
|
|
{
|
|
|
|
// Move objects only if on floor or underwater,
|
|
|
|
// non-floating, and clipped.
|
|
|
|
thing->momx += dx;
|
|
|
|
thing->momy += dy;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case sc_carry_ceiling: // to be added later
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Add_Scroller()
|
|
|
|
//
|
|
|
|
// Add a generalized scroller to the thinker list.
|
|
|
|
//
|
|
|
|
// type: the enumerated type of scrolling: floor, ceiling, floor carrier,
|
|
|
|
// wall, floor carrier & scroller
|
|
|
|
//
|
|
|
|
// (dx,dy): the direction and speed of the scrolling or its acceleration
|
|
|
|
//
|
|
|
|
// control: the sector whose heights control this scroller's effect
|
|
|
|
// remotely, or -1 if no control sector
|
|
|
|
//
|
|
|
|
// affectee: the index of the affected object (sector or sidedef)
|
|
|
|
//
|
|
|
|
// accel: non-zero if this is an accelerative effect
|
|
|
|
//
|
|
|
|
|
|
|
|
static void Add_Scroller(int type, fixed_t dx, fixed_t dy,
|
|
|
|
int control, int affectee, int accel)
|
|
|
|
{
|
|
|
|
scroll_t *s = Z_Malloc(sizeof *s, PU_LEVSPEC, 0);
|
|
|
|
s->thinker.function.acp1 = (actionf_p1) T_Scroll;
|
|
|
|
s->type = type;
|
|
|
|
s->dx = dx;
|
|
|
|
s->dy = dy;
|
|
|
|
s->accel = accel;
|
|
|
|
s->vdx = s->vdy = 0;
|
|
|
|
if ((s->control = control) != -1)
|
|
|
|
s->last_height =
|
|
|
|
sectors[control].floorheight + sectors[control].ceilingheight;
|
|
|
|
s->affectee = affectee;
|
|
|
|
P_AddThinker(&s->thinker);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adds wall scroller. Scroll amount is rotated with respect to wall's
|
|
|
|
// linedef first, so that scrolling towards the wall in a perpendicular
|
|
|
|
// direction is translated into vertical motion, while scrolling along
|
|
|
|
// the wall in a parallel direction is translated into horizontal motion.
|
|
|
|
//
|
|
|
|
// killough 5/25/98: cleaned up arithmetic to avoid drift due to roundoff
|
|
|
|
|
|
|
|
static void Add_WallScroller(fixed_t dx, fixed_t dy, const line_t *l,
|
|
|
|
int control, int accel)
|
|
|
|
{
|
|
|
|
fixed_t x = abs(l->dx), y = abs(l->dy), d;
|
|
|
|
if (y > x)
|
|
|
|
d = x, x = y, y = d;
|
|
|
|
d = FixedDiv(x, finesine[(tantoangle[FixedDiv(y,x) >> DBITS] + ANG90)
|
|
|
|
>> ANGLETOFINESHIFT]);
|
|
|
|
x = -FixedDiv(FixedMul(dy, l->dy) + FixedMul(dx, l->dx), d);
|
|
|
|
y = -FixedDiv(FixedMul(dx, l->dy) - FixedMul(dy, l->dx), d);
|
|
|
|
Add_Scroller(sc_side, x, y, control, *l->sidenum, accel);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Amount (dx,dy) vector linedef is shifted right to get scroll amount
|
|
|
|
#define SCROLL_SHIFT 5
|
|
|
|
|
|
|
|
// Factor to scale scrolling effect into mobj-carrying properties = 3/32.
|
|
|
|
// (This is so scrolling floors and objects on them can move at same speed.)
|
|
|
|
#define CARRYFACTOR ((fixed_t)(FRACUNIT*.09375))
|
|
|
|
|
|
|
|
// Initialize the scrollers
|
|
|
|
static void P_SpawnScrollers(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
line_t *l = lines;
|
|
|
|
|
|
|
|
for (i=0;i<numlines;i++,l++)
|
|
|
|
{
|
|
|
|
fixed_t dx = l->dx >> SCROLL_SHIFT; // direction and speed of scrolling
|
|
|
|
fixed_t dy = l->dy >> SCROLL_SHIFT;
|
|
|
|
int control = -1, accel = 0; // no control sector or acceleration
|
|
|
|
int special = l->special;
|
|
|
|
|
|
|
|
// killough 3/7/98: Types 245-249 are same as 250-254 except that the
|
|
|
|
// first side's sector's heights cause scrolling when they change, and
|
|
|
|
// this linedef controls the direction and speed of the scrolling. The
|
|
|
|
// most complicated linedef since donuts, but powerful :)
|
|
|
|
//
|
|
|
|
// killough 3/15/98: Add acceleration. Types 214-218 are the same but
|
|
|
|
// are accelerative.
|
|
|
|
|
|
|
|
if (special >= 245 && special <= 249) // displacement scrollers
|
|
|
|
{
|
|
|
|
special += 250-245;
|
|
|
|
control = sides[*l->sidenum].sector - sectors;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (special >= 214 && special <= 218) // accelerative scrollers
|
|
|
|
{
|
|
|
|
accel = 1;
|
|
|
|
special += 250-214;
|
|
|
|
control = sides[*l->sidenum].sector - sectors;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (special)
|
|
|
|
{
|
|
|
|
register int s;
|
|
|
|
|
|
|
|
case 250: // scroll effect ceiling
|
|
|
|
for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
|
|
|
|
Add_Scroller(sc_ceiling, -dx, dy, control, s, accel);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 251: // scroll effect floor
|
|
|
|
case 253: // scroll and carry objects on floor
|
|
|
|
for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
|
|
|
|
Add_Scroller(sc_floor, -dx, dy, control, s, accel);
|
|
|
|
if (special != 253)
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 252: // carry objects on floor
|
|
|
|
dx = FixedMul(dx,CARRYFACTOR);
|
|
|
|
dy = FixedMul(dy,CARRYFACTOR);
|
|
|
|
for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
|
|
|
|
Add_Scroller(sc_carry, dx, dy, control, s, accel);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// killough 3/1/98: scroll wall according to linedef
|
|
|
|
// (same direction and speed as scrolling floors)
|
|
|
|
case 254:
|
|
|
|
for (s=-1; (s = P_FindLineFromLineTag(l,s)) >= 0;)
|
|
|
|
if (s != i)
|
|
|
|
Add_WallScroller(dx, dy, lines+s, control, accel);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 255: // killough 3/2/98: scroll according to sidedef offsets
|
|
|
|
s = lines[i].sidenum[0];
|
|
|
|
Add_Scroller(sc_side, -sides[s].textureoffset,
|
|
|
|
sides[s].rowoffset, -1, s, accel);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 48: // scroll first side
|
|
|
|
Add_Scroller(sc_side, FRACUNIT, 0, -1, lines[i].sidenum[0], accel);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 85: // jff 1/30/98 2-way scroll
|
|
|
|
Add_Scroller(sc_side, -FRACUNIT, 0, -1, lines[i].sidenum[0], accel);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// killough 3/7/98 -- end generalized scroll effects
|