931 lines
23 KiB
C
931 lines
23 KiB
C
|
|
//**************************************************************************
|
|
//**
|
|
//** p_floor.c : Heretic 2 : Raven Software, Corp.
|
|
//**
|
|
//** $RCSfile: p_floor.c,v $
|
|
//** $Revision: 1.23 $
|
|
//** $Date: 95/10/06 16:53:19 $
|
|
//** $Author: paul $
|
|
//**
|
|
//**************************************************************************
|
|
|
|
#include "h2def.h"
|
|
#include "p_local.h"
|
|
#include "soundst.h"
|
|
|
|
extern fixed_t FloatBobOffsets[64];
|
|
|
|
//==================================================================
|
|
//==================================================================
|
|
//
|
|
// FLOORS
|
|
//
|
|
//==================================================================
|
|
//==================================================================
|
|
|
|
//==================================================================
|
|
//
|
|
// Move a plane (floor or ceiling) and check for crushing
|
|
//
|
|
//==================================================================
|
|
result_e T_MovePlane(sector_t *sector,fixed_t speed,
|
|
fixed_t dest, int crush,int floorOrCeiling,int direction)
|
|
{
|
|
boolean flag;
|
|
fixed_t lastpos;
|
|
|
|
switch(floorOrCeiling)
|
|
{
|
|
case 0: // FLOOR
|
|
switch(direction)
|
|
{
|
|
case -1: // DOWN
|
|
if (sector->floorheight - speed < dest)
|
|
{
|
|
lastpos = sector->floorheight;
|
|
sector->floorheight = dest;
|
|
flag = P_ChangeSector(sector,crush);
|
|
if (flag == true)
|
|
{
|
|
sector->floorheight =lastpos;
|
|
P_ChangeSector(sector,crush);
|
|
//return RES_CRUSHED;
|
|
}
|
|
return RES_PASTDEST;
|
|
}
|
|
else
|
|
{
|
|
lastpos = sector->floorheight;
|
|
sector->floorheight -= speed;
|
|
flag = P_ChangeSector(sector,crush);
|
|
if (flag == true)
|
|
{
|
|
sector->floorheight = lastpos;
|
|
P_ChangeSector(sector,crush);
|
|
return RES_CRUSHED;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 1: // UP
|
|
if (sector->floorheight + speed > dest)
|
|
{
|
|
lastpos = sector->floorheight;
|
|
sector->floorheight = dest;
|
|
flag = P_ChangeSector(sector,crush);
|
|
if (flag == true)
|
|
{
|
|
sector->floorheight = lastpos;
|
|
P_ChangeSector(sector,crush);
|
|
//return RES_CRUSHED;
|
|
}
|
|
return RES_PASTDEST;
|
|
}
|
|
else // COULD GET CRUSHED
|
|
{
|
|
lastpos = sector->floorheight;
|
|
sector->floorheight += speed;
|
|
flag = P_ChangeSector(sector,crush);
|
|
if (flag == true)
|
|
{
|
|
//if (crush == true)
|
|
//{
|
|
// return RES_CRUSHED;
|
|
//}
|
|
sector->floorheight = lastpos;
|
|
P_ChangeSector(sector,crush);
|
|
return RES_CRUSHED;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 1: // CEILING
|
|
switch(direction)
|
|
{
|
|
case -1: // DOWN
|
|
if (sector->ceilingheight - speed < dest)
|
|
{
|
|
lastpos = sector->ceilingheight;
|
|
sector->ceilingheight = dest;
|
|
flag = P_ChangeSector(sector,crush);
|
|
if (flag == true)
|
|
{
|
|
sector->ceilingheight = lastpos;
|
|
P_ChangeSector(sector,crush);
|
|
//return RES_CRUSHED;
|
|
}
|
|
return RES_PASTDEST;
|
|
}
|
|
else // COULD GET CRUSHED
|
|
{
|
|
lastpos = sector->ceilingheight;
|
|
sector->ceilingheight -= speed;
|
|
flag = P_ChangeSector(sector,crush);
|
|
if (flag == true)
|
|
{
|
|
//if (crush == true)
|
|
//{
|
|
// return RES_CRUSHED;
|
|
//}
|
|
sector->ceilingheight = lastpos;
|
|
P_ChangeSector(sector,crush);
|
|
return RES_CRUSHED;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 1: // UP
|
|
if (sector->ceilingheight + speed > dest)
|
|
{
|
|
lastpos = sector->ceilingheight;
|
|
sector->ceilingheight = dest;
|
|
flag = P_ChangeSector(sector,crush);
|
|
if (flag == true)
|
|
{
|
|
sector->ceilingheight = lastpos;
|
|
P_ChangeSector(sector,crush);
|
|
//return RES_CRUSHED;
|
|
}
|
|
return RES_PASTDEST;
|
|
}
|
|
else
|
|
{
|
|
lastpos = sector->ceilingheight;
|
|
sector->ceilingheight += speed;
|
|
flag = P_ChangeSector(sector,crush);
|
|
#if 0
|
|
if (flag == true)
|
|
{
|
|
sector->ceilingheight = lastpos;
|
|
P_ChangeSector(sector,crush);
|
|
return RES_CRUSHED;
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
}
|
|
return RES_OK;
|
|
}
|
|
|
|
//==================================================================
|
|
//
|
|
// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN)
|
|
//
|
|
//==================================================================
|
|
void T_MoveFloor(floormove_t *floor)
|
|
{
|
|
result_e res;
|
|
|
|
if(floor->resetDelayCount)
|
|
{
|
|
floor->resetDelayCount--;
|
|
if(!floor->resetDelayCount)
|
|
{
|
|
floor->floordestheight = floor->resetHeight;
|
|
floor->direction = -floor->direction;
|
|
floor->resetDelay = 0;
|
|
floor->delayCount = 0;
|
|
floor->delayTotal = 0;
|
|
}
|
|
}
|
|
if(floor->delayCount)
|
|
{
|
|
floor->delayCount--;
|
|
if(!floor->delayCount && floor->textureChange)
|
|
{
|
|
floor->sector->floorpic += floor->textureChange;
|
|
}
|
|
return;
|
|
}
|
|
|
|
res = T_MovePlane(floor->sector,floor->speed,
|
|
floor->floordestheight,floor->crush,0,floor->direction);
|
|
|
|
if(floor->type == FLEV_RAISEBUILDSTEP)
|
|
{
|
|
if((floor->direction == 1 && floor->sector->floorheight >=
|
|
floor->stairsDelayHeight) || (floor->direction == -1 &&
|
|
floor->sector->floorheight <= floor->stairsDelayHeight))
|
|
{
|
|
floor->delayCount = floor->delayTotal;
|
|
floor->stairsDelayHeight += floor->stairsDelayHeightDelta;
|
|
}
|
|
}
|
|
if (res == RES_PASTDEST)
|
|
{
|
|
SN_StopSequence((mobj_t *)&floor->sector->soundorg);
|
|
if(floor->delayTotal)
|
|
{
|
|
floor->delayTotal = 0;
|
|
}
|
|
if(floor->resetDelay)
|
|
{
|
|
// floor->resetDelayCount = floor->resetDelay;
|
|
// floor->resetDelay = 0;
|
|
return;
|
|
}
|
|
floor->sector->specialdata = NULL;
|
|
/*
|
|
if (floor->direction == 1)
|
|
switch(floor->type)
|
|
{
|
|
case donutRaise:
|
|
floor->sector->special = floor->newspecial;
|
|
floor->sector->floorpic = floor->texture;
|
|
default:
|
|
break;
|
|
}
|
|
else if (floor->direction == -1)
|
|
switch(floor->type)
|
|
{
|
|
case lowerAndChange:
|
|
floor->sector->special = floor->newspecial;
|
|
floor->sector->floorpic = floor->texture;
|
|
default:
|
|
break;
|
|
}
|
|
*/
|
|
if(floor->textureChange)
|
|
{
|
|
floor->sector->floorpic -= floor->textureChange;
|
|
}
|
|
P_TagFinished(floor->sector->tag);
|
|
P_RemoveThinker(&floor->thinker);
|
|
}
|
|
}
|
|
|
|
//==================================================================
|
|
//
|
|
// HANDLE FLOOR TYPES
|
|
//
|
|
//==================================================================
|
|
int EV_DoFloor(line_t *line, byte *args, floor_e floortype)
|
|
{
|
|
int secnum;
|
|
int rtn;
|
|
sector_t *sec;
|
|
floormove_t *floor=NULL;
|
|
|
|
secnum = -1;
|
|
rtn = 0;
|
|
while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
|
|
{
|
|
sec = §ors[secnum];
|
|
|
|
// ALREADY MOVING? IF SO, KEEP GOING...
|
|
if (sec->specialdata)
|
|
continue;
|
|
|
|
//
|
|
// new floor thinker
|
|
//
|
|
rtn = 1;
|
|
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
|
|
memset(floor, 0, sizeof(*floor));
|
|
P_AddThinker (&floor->thinker);
|
|
sec->specialdata = floor;
|
|
floor->thinker.function = T_MoveFloor;
|
|
floor->type = floortype;
|
|
floor->crush = 0;
|
|
floor->speed = args[1]*(FRACUNIT/8);
|
|
if(floortype == FLEV_LOWERTIMES8INSTANT ||
|
|
floortype == FLEV_RAISETIMES8INSTANT)
|
|
{
|
|
floor->speed = 2000<<FRACBITS;
|
|
}
|
|
switch(floortype)
|
|
{
|
|
case FLEV_LOWERFLOOR:
|
|
floor->direction = -1;
|
|
floor->sector = sec;
|
|
floor->floordestheight =
|
|
P_FindHighestFloorSurrounding(sec);
|
|
break;
|
|
case FLEV_LOWERFLOORTOLOWEST:
|
|
floor->direction = -1;
|
|
floor->sector = sec;
|
|
floor->floordestheight =
|
|
P_FindLowestFloorSurrounding(sec);
|
|
break;
|
|
case FLEV_LOWERFLOORBYVALUE:
|
|
floor->direction = -1;
|
|
floor->sector = sec;
|
|
floor->floordestheight = floor->sector->floorheight-
|
|
args[2]*FRACUNIT;
|
|
break;
|
|
case FLEV_LOWERTIMES8INSTANT:
|
|
case FLEV_LOWERBYVALUETIMES8:
|
|
floor->direction = -1;
|
|
floor->sector = sec;
|
|
floor->floordestheight = floor->sector->floorheight-
|
|
args[2]*FRACUNIT*8;
|
|
break;
|
|
case FLEV_RAISEFLOORCRUSH:
|
|
floor->crush = args[2]; // arg[2] = crushing value
|
|
floor->direction = 1;
|
|
floor->sector = sec;
|
|
floor->floordestheight = sec->ceilingheight-8*FRACUNIT;
|
|
break;
|
|
case FLEV_RAISEFLOOR:
|
|
floor->direction = 1;
|
|
floor->sector = sec;
|
|
floor->floordestheight =
|
|
P_FindLowestCeilingSurrounding(sec);
|
|
if (floor->floordestheight > sec->ceilingheight)
|
|
floor->floordestheight = sec->ceilingheight;
|
|
break;
|
|
case FLEV_RAISEFLOORTONEAREST:
|
|
floor->direction = 1;
|
|
floor->sector = sec;
|
|
floor->floordestheight =
|
|
P_FindNextHighestFloor(sec,sec->floorheight);
|
|
break;
|
|
case FLEV_RAISEFLOORBYVALUE:
|
|
floor->direction = 1;
|
|
floor->sector = sec;
|
|
floor->floordestheight = floor->sector->floorheight+
|
|
args[2]*FRACUNIT;
|
|
break;
|
|
case FLEV_RAISETIMES8INSTANT:
|
|
case FLEV_RAISEBYVALUETIMES8:
|
|
floor->direction = 1;
|
|
floor->sector = sec;
|
|
floor->floordestheight = floor->sector->floorheight+
|
|
args[2]*FRACUNIT*8;
|
|
break;
|
|
case FLEV_MOVETOVALUETIMES8:
|
|
floor->sector = sec;
|
|
floor->floordestheight = args[2]*FRACUNIT*8;
|
|
if(args[3])
|
|
{
|
|
floor->floordestheight = -floor->floordestheight;
|
|
}
|
|
if(floor->floordestheight > floor->sector->floorheight)
|
|
{
|
|
floor->direction = 1;
|
|
}
|
|
else if(floor->floordestheight < floor->sector->floorheight)
|
|
{
|
|
floor->direction = -1;
|
|
}
|
|
else
|
|
{ // already at lowest position
|
|
rtn = 0;
|
|
}
|
|
break;
|
|
default:
|
|
rtn = 0;
|
|
break;
|
|
}
|
|
}
|
|
if(rtn)
|
|
{
|
|
SN_StartSequence((mobj_t *)&floor->sector->soundorg,
|
|
SEQ_PLATFORM+floor->sector->seqType);
|
|
}
|
|
return rtn;
|
|
}
|
|
|
|
//============================================================================
|
|
//
|
|
// EV_DoFloorAndCeiling
|
|
//
|
|
//============================================================================
|
|
|
|
int EV_DoFloorAndCeiling(line_t *line, byte *args, boolean raise)
|
|
{
|
|
boolean floor, ceiling;
|
|
int secnum;
|
|
sector_t *sec;
|
|
|
|
if(raise)
|
|
{
|
|
floor = EV_DoFloor(line, args, FLEV_RAISEFLOORBYVALUE);
|
|
secnum = -1;
|
|
while((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
|
|
{
|
|
sec = §ors[secnum];
|
|
sec->specialdata = NULL;
|
|
}
|
|
ceiling = EV_DoCeiling(line, args, CLEV_RAISEBYVALUE);
|
|
}
|
|
else
|
|
{
|
|
floor = EV_DoFloor(line, args, FLEV_LOWERFLOORBYVALUE);
|
|
secnum = -1;
|
|
while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
|
|
{
|
|
sec = §ors[secnum];
|
|
sec->specialdata = NULL;
|
|
}
|
|
ceiling = EV_DoCeiling(line, args, CLEV_LOWERBYVALUE);
|
|
}
|
|
return (floor|ceiling);
|
|
}
|
|
|
|
// ===== Build Stairs Private Data =====
|
|
|
|
#define STAIR_SECTOR_TYPE 26
|
|
#define STAIR_QUEUE_SIZE 32
|
|
|
|
struct
|
|
{
|
|
sector_t *sector;
|
|
int type;
|
|
int height;
|
|
} StairQueue[STAIR_QUEUE_SIZE];
|
|
|
|
static int QueueHead;
|
|
static int QueueTail;
|
|
|
|
static int StepDelta;
|
|
static int Direction;
|
|
static int Speed;
|
|
static int Texture;
|
|
static int StartDelay;
|
|
static int StartDelayDelta;
|
|
static int TextureChange;
|
|
static int StartHeight;
|
|
|
|
//==========================================================================
|
|
//
|
|
// QueueStairSector
|
|
//
|
|
//==========================================================================
|
|
|
|
static void QueueStairSector(sector_t *sec, int type, int height)
|
|
{
|
|
if((QueueTail+1)%STAIR_QUEUE_SIZE == QueueHead)
|
|
{
|
|
I_Error("BuildStairs: Too many branches located.\n");
|
|
}
|
|
StairQueue[QueueTail].sector = sec;
|
|
StairQueue[QueueTail].type = type;
|
|
StairQueue[QueueTail].height = height;
|
|
|
|
QueueTail = (QueueTail+1)%STAIR_QUEUE_SIZE;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// DequeueStairSector
|
|
//
|
|
//==========================================================================
|
|
|
|
static sector_t *DequeueStairSector(int *type, int *height)
|
|
{
|
|
sector_t *sec;
|
|
|
|
if(QueueHead == QueueTail)
|
|
{ // queue is empty
|
|
return NULL;
|
|
}
|
|
*type = StairQueue[QueueHead].type;
|
|
*height = StairQueue[QueueHead].height;
|
|
sec = StairQueue[QueueHead].sector;
|
|
QueueHead = (QueueHead+1)%STAIR_QUEUE_SIZE;
|
|
|
|
return sec;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// ProcessStairSector
|
|
//
|
|
//==========================================================================
|
|
|
|
static void ProcessStairSector(sector_t *sec, int type, int height,
|
|
stairs_e stairsType, int delay, int resetDelay)
|
|
{
|
|
int i;
|
|
sector_t *tsec;
|
|
floormove_t *floor;
|
|
|
|
//
|
|
// new floor thinker
|
|
//
|
|
height += StepDelta;
|
|
floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0);
|
|
memset(floor, 0, sizeof(*floor));
|
|
P_AddThinker(&floor->thinker);
|
|
sec->specialdata = floor;
|
|
floor->thinker.function = T_MoveFloor;
|
|
floor->type = FLEV_RAISEBUILDSTEP;
|
|
floor->direction = Direction;
|
|
floor->sector = sec;
|
|
floor->floordestheight = height;
|
|
switch(stairsType)
|
|
{
|
|
case STAIRS_NORMAL:
|
|
floor->speed = Speed;
|
|
if(delay)
|
|
{
|
|
floor->delayTotal = delay;
|
|
floor->stairsDelayHeight = sec->floorheight+StepDelta;
|
|
floor->stairsDelayHeightDelta = StepDelta;
|
|
}
|
|
floor->resetDelay = resetDelay;
|
|
floor->resetDelayCount = resetDelay;
|
|
floor->resetHeight = sec->floorheight;
|
|
break;
|
|
case STAIRS_SYNC:
|
|
floor->speed = FixedMul(Speed, FixedDiv(height-StartHeight,
|
|
StepDelta));
|
|
floor->resetDelay = delay; //arg4
|
|
floor->resetDelayCount = delay;
|
|
floor->resetHeight = sec->floorheight;
|
|
break;
|
|
/*
|
|
case STAIRS_PHASED:
|
|
floor->floordestheight = sec->floorheight+StepDelta;
|
|
floor->speed = Speed;
|
|
floor->delayCount = StartDelay;
|
|
StartDelay += StartDelayDelta;
|
|
floor->textureChange = TextureChange;
|
|
floor->resetDelayCount = StartDelay;
|
|
break;
|
|
*/
|
|
default:
|
|
break;
|
|
}
|
|
SN_StartSequence((mobj_t *)&sec->soundorg, SEQ_PLATFORM+sec->seqType);
|
|
//
|
|
// Find next sector to raise
|
|
// Find nearby sector with sector special equal to type
|
|
//
|
|
for (i = 0; i < sec->linecount; i++)
|
|
{
|
|
if(!((sec->lines[i])->flags&ML_TWOSIDED))
|
|
{
|
|
continue;
|
|
}
|
|
tsec = (sec->lines[i])->frontsector;
|
|
if(tsec->special == type+STAIR_SECTOR_TYPE && !tsec->specialdata
|
|
&& tsec->floorpic == Texture && tsec->validcount != validcount)
|
|
{
|
|
QueueStairSector(tsec, type^1, height);
|
|
tsec->validcount = validcount;
|
|
//tsec->special = 0;
|
|
}
|
|
tsec = (sec->lines[i])->backsector;
|
|
if(tsec->special == type+STAIR_SECTOR_TYPE && !tsec->specialdata
|
|
&& tsec->floorpic == Texture && tsec->validcount != validcount)
|
|
{
|
|
QueueStairSector(tsec, type^1, height);
|
|
tsec->validcount = validcount;
|
|
//tsec->special = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//==================================================================
|
|
//
|
|
// BUILD A STAIRCASE!
|
|
//
|
|
// Direction is either positive or negative, denoting build stairs
|
|
// up or down.
|
|
//==================================================================
|
|
|
|
int EV_BuildStairs(line_t *line, byte *args, int direction,
|
|
stairs_e stairsType)
|
|
{
|
|
int secnum;
|
|
int height;
|
|
int delay;
|
|
int resetDelay;
|
|
sector_t *sec;
|
|
sector_t *qSec;
|
|
int type;
|
|
|
|
// Set global stairs variables
|
|
TextureChange = 0;
|
|
Direction = direction;
|
|
StepDelta = Direction*(args[2]*FRACUNIT);
|
|
Speed = args[1]*(FRACUNIT/8);
|
|
resetDelay = args[4];
|
|
delay = args[3];
|
|
if(stairsType == STAIRS_PHASED)
|
|
{
|
|
StartDelayDelta = args[3];
|
|
StartDelay = StartDelayDelta;
|
|
resetDelay = StartDelayDelta;
|
|
delay = 0;
|
|
TextureChange = args[4];
|
|
}
|
|
|
|
secnum = -1;
|
|
|
|
validcount++;
|
|
while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
|
|
{
|
|
sec = §ors[secnum];
|
|
|
|
Texture = sec->floorpic;
|
|
StartHeight = sec->floorheight;
|
|
|
|
// ALREADY MOVING? IF SO, KEEP GOING...
|
|
if (sec->specialdata)
|
|
continue;
|
|
|
|
QueueStairSector(sec, 0, sec->floorheight);
|
|
sec->special = 0;
|
|
}
|
|
while((qSec = DequeueStairSector(&type, &height)) != NULL)
|
|
{
|
|
ProcessStairSector(qSec, type, height, stairsType, delay, resetDelay);
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
//=========================================================================
|
|
//
|
|
// T_BuildPillar
|
|
//
|
|
//=========================================================================
|
|
|
|
void T_BuildPillar(pillar_t *pillar)
|
|
{
|
|
result_e res1;
|
|
result_e res2;
|
|
|
|
// First, raise the floor
|
|
res1 = T_MovePlane(pillar->sector, pillar->floorSpeed, pillar->floordest,
|
|
pillar->crush, 0, pillar->direction); // floorOrCeiling, direction
|
|
// Then, lower the ceiling
|
|
res2 = T_MovePlane(pillar->sector, pillar->ceilingSpeed,
|
|
pillar->ceilingdest, pillar->crush, 1, -pillar->direction);
|
|
if (res1 == RES_PASTDEST && res2 == RES_PASTDEST)
|
|
{
|
|
pillar->sector->specialdata = NULL;
|
|
SN_StopSequence((mobj_t *)&pillar->sector->soundorg);
|
|
P_TagFinished(pillar->sector->tag);
|
|
P_RemoveThinker(&pillar->thinker);
|
|
}
|
|
}
|
|
|
|
//=========================================================================
|
|
//
|
|
// EV_BuildPillar
|
|
//
|
|
//=========================================================================
|
|
|
|
int EV_BuildPillar(line_t *line, byte *args, boolean crush)
|
|
{
|
|
int secnum;
|
|
sector_t *sec;
|
|
pillar_t *pillar;
|
|
int newHeight;
|
|
int rtn;
|
|
|
|
rtn = 0;
|
|
secnum = -1;
|
|
while((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
|
|
{
|
|
sec = §ors[secnum];
|
|
if(sec->specialdata)
|
|
continue; // already moving
|
|
if(sec->floorheight == sec->ceilingheight)
|
|
{ // pillar is already closed
|
|
continue;
|
|
}
|
|
rtn = 1;
|
|
if(!args[2])
|
|
{
|
|
newHeight = sec->floorheight+
|
|
((sec->ceilingheight-sec->floorheight)/2);
|
|
}
|
|
else
|
|
{
|
|
newHeight = sec->floorheight+(args[2]<<FRACBITS);
|
|
}
|
|
|
|
pillar = Z_Malloc(sizeof(*pillar), PU_LEVSPEC, 0);
|
|
sec->specialdata = pillar;
|
|
P_AddThinker(&pillar->thinker);
|
|
pillar->thinker.function = T_BuildPillar;
|
|
pillar->sector = sec;
|
|
if(!args[2])
|
|
{
|
|
pillar->ceilingSpeed = pillar->floorSpeed = args[1]*(FRACUNIT/8);
|
|
}
|
|
else if(newHeight-sec->floorheight > sec->ceilingheight-newHeight)
|
|
{
|
|
pillar->floorSpeed = args[1]*(FRACUNIT/8);
|
|
pillar->ceilingSpeed = FixedMul(sec->ceilingheight-newHeight,
|
|
FixedDiv(pillar->floorSpeed, newHeight-sec->floorheight));
|
|
}
|
|
else
|
|
{
|
|
pillar->ceilingSpeed = args[1]*(FRACUNIT/8);
|
|
pillar->floorSpeed = FixedMul(newHeight-sec->floorheight,
|
|
FixedDiv(pillar->ceilingSpeed, sec->ceilingheight-newHeight));
|
|
}
|
|
pillar->floordest = newHeight;
|
|
pillar->ceilingdest = newHeight;
|
|
pillar->direction = 1;
|
|
pillar->crush = crush*args[3];
|
|
SN_StartSequence((mobj_t *)&pillar->sector->soundorg,
|
|
SEQ_PLATFORM+pillar->sector->seqType);
|
|
}
|
|
return rtn;
|
|
}
|
|
|
|
//=========================================================================
|
|
//
|
|
// EV_OpenPillar
|
|
//
|
|
//=========================================================================
|
|
|
|
int EV_OpenPillar(line_t *line, byte *args)
|
|
{
|
|
int secnum;
|
|
sector_t *sec;
|
|
pillar_t *pillar;
|
|
int rtn;
|
|
|
|
rtn = 0;
|
|
secnum = -1;
|
|
while((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
|
|
{
|
|
sec = §ors[secnum];
|
|
if(sec->specialdata)
|
|
continue; // already moving
|
|
if(sec->floorheight != sec->ceilingheight)
|
|
{ // pillar isn't closed
|
|
continue;
|
|
}
|
|
rtn = 1;
|
|
pillar = Z_Malloc(sizeof(*pillar), PU_LEVSPEC, 0);
|
|
sec->specialdata = pillar;
|
|
P_AddThinker(&pillar->thinker);
|
|
pillar->thinker.function = T_BuildPillar;
|
|
pillar->sector = sec;
|
|
if(!args[2])
|
|
{
|
|
pillar->floordest = P_FindLowestFloorSurrounding(sec);
|
|
}
|
|
else
|
|
{
|
|
pillar->floordest = sec->floorheight-(args[2]<<FRACBITS);
|
|
}
|
|
if(!args[3])
|
|
{
|
|
pillar->ceilingdest = P_FindHighestCeilingSurrounding(sec);
|
|
}
|
|
else
|
|
{
|
|
pillar->ceilingdest = sec->ceilingheight+(args[3]<<FRACBITS);
|
|
}
|
|
if(sec->floorheight-pillar->floordest >= pillar->ceilingdest-
|
|
sec->ceilingheight)
|
|
{
|
|
pillar->floorSpeed = args[1]*(FRACUNIT/8);
|
|
pillar->ceilingSpeed = FixedMul(sec->ceilingheight-
|
|
pillar->ceilingdest, FixedDiv(pillar->floorSpeed,
|
|
pillar->floordest-sec->floorheight));
|
|
}
|
|
else
|
|
{
|
|
pillar->ceilingSpeed = args[1]*(FRACUNIT/8);
|
|
pillar->floorSpeed = FixedMul(pillar->floordest-sec->floorheight,
|
|
FixedDiv(pillar->ceilingSpeed, sec->ceilingheight-
|
|
pillar->ceilingdest));
|
|
}
|
|
pillar->direction = -1; // open the pillar
|
|
SN_StartSequence((mobj_t *)&pillar->sector->soundorg,
|
|
SEQ_PLATFORM+pillar->sector->seqType);
|
|
}
|
|
return rtn;
|
|
}
|
|
|
|
//=========================================================================
|
|
//
|
|
// EV_FloorCrushStop
|
|
//
|
|
//=========================================================================
|
|
|
|
int EV_FloorCrushStop(line_t *line, byte *args)
|
|
{
|
|
thinker_t *think;
|
|
floormove_t *floor;
|
|
boolean rtn;
|
|
|
|
rtn = 0;
|
|
for(think = thinkercap.next; think != &thinkercap; think = think->next)
|
|
{
|
|
if(think->function != T_MoveFloor)
|
|
{
|
|
continue;
|
|
}
|
|
floor = (floormove_t *)think;
|
|
if(floor->type != FLEV_RAISEFLOORCRUSH)
|
|
{
|
|
continue;
|
|
}
|
|
// Completely remove the crushing floor
|
|
SN_StopSequence((mobj_t *)&floor->sector->soundorg);
|
|
floor->sector->specialdata = NULL;
|
|
P_TagFinished(floor->sector->tag);
|
|
P_RemoveThinker(&floor->thinker);
|
|
rtn = 1;
|
|
}
|
|
return rtn;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// T_FloorWaggle
|
|
//
|
|
//==========================================================================
|
|
|
|
#define WGLSTATE_EXPAND 1
|
|
#define WGLSTATE_STABLE 2
|
|
#define WGLSTATE_REDUCE 3
|
|
|
|
void T_FloorWaggle(floorWaggle_t *waggle)
|
|
{
|
|
switch(waggle->state)
|
|
{
|
|
case WGLSTATE_EXPAND:
|
|
if((waggle->scale += waggle->scaleDelta)
|
|
>= waggle->targetScale)
|
|
{
|
|
waggle->scale = waggle->targetScale;
|
|
waggle->state = WGLSTATE_STABLE;
|
|
}
|
|
break;
|
|
case WGLSTATE_REDUCE:
|
|
if((waggle->scale -= waggle->scaleDelta) <= 0)
|
|
{ // Remove
|
|
waggle->sector->floorheight = waggle->originalHeight;
|
|
P_ChangeSector(waggle->sector, true);
|
|
waggle->sector->specialdata = NULL;
|
|
P_TagFinished(waggle->sector->tag);
|
|
P_RemoveThinker(&waggle->thinker);
|
|
return;
|
|
}
|
|
break;
|
|
case WGLSTATE_STABLE:
|
|
if(waggle->ticker != -1)
|
|
{
|
|
if(!--waggle->ticker)
|
|
{
|
|
waggle->state = WGLSTATE_REDUCE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
waggle->accumulator += waggle->accDelta;
|
|
waggle->sector->floorheight = waggle->originalHeight
|
|
+FixedMul(FloatBobOffsets[(waggle->accumulator>>FRACBITS)&63],
|
|
waggle->scale);
|
|
P_ChangeSector(waggle->sector, true);
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// EV_StartFloorWaggle
|
|
//
|
|
//==========================================================================
|
|
|
|
boolean EV_StartFloorWaggle(int tag, int height, int speed, int offset,
|
|
int timer)
|
|
{
|
|
int sectorIndex;
|
|
sector_t *sector;
|
|
floorWaggle_t *waggle;
|
|
boolean retCode;
|
|
|
|
retCode = false;
|
|
sectorIndex = -1;
|
|
while((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
|
|
{
|
|
sector = §ors[sectorIndex];
|
|
if(sector->specialdata)
|
|
{ // Already busy with another thinker
|
|
continue;
|
|
}
|
|
retCode = true;
|
|
waggle = Z_Malloc(sizeof(*waggle), PU_LEVSPEC, 0);
|
|
sector->specialdata = waggle;
|
|
waggle->thinker.function = T_FloorWaggle;
|
|
waggle->sector = sector;
|
|
waggle->originalHeight = sector->floorheight;
|
|
waggle->accumulator = offset*FRACUNIT;
|
|
waggle->accDelta = speed<<10;
|
|
waggle->scale = 0;
|
|
waggle->targetScale = height<<10;
|
|
waggle->scaleDelta = waggle->targetScale
|
|
/(35+((3*35)*height)/255);
|
|
waggle->ticker = timer ? timer*35 : -1;
|
|
waggle->state = WGLSTATE_EXPAND;
|
|
P_AddThinker(&waggle->thinker);
|
|
}
|
|
return retCode;
|
|
}
|