diff options
Diffstat (limited to 'src/hexen/p_floor.c')
-rw-r--r-- | src/hexen/p_floor.c | 952 |
1 files changed, 952 insertions, 0 deletions
diff --git a/src/hexen/p_floor.c b/src/hexen/p_floor.c new file mode 100644 index 00000000..40f9b934 --- /dev/null +++ b/src/hexen/p_floor.c @@ -0,0 +1,952 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2008 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. +// +//----------------------------------------------------------------------------- + + +#include "h2def.h" +#include "i_system.h" +#include "p_local.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; +} |