mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
And remove their dependency on a line_t existing. One step towards implementing linedef executor functions into ACS.
705 lines
16 KiB
C
705 lines
16 KiB
C
// SONIC ROBO BLAST 2
|
|
//-----------------------------------------------------------------------------
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
|
//
|
|
// This program is free software distributed under the
|
|
// terms of the GNU General Public License, version 2.
|
|
// See the 'LICENSE' file for more details.
|
|
//-----------------------------------------------------------------------------
|
|
/// \file p_ceilng.c
|
|
/// \brief Ceiling aninmation (lowering, crushing, raising)
|
|
|
|
#include "doomdef.h"
|
|
#include "p_local.h"
|
|
#include "r_fps.h"
|
|
#include "r_main.h"
|
|
#include "s_sound.h"
|
|
#include "z_zone.h"
|
|
#include "d_netcmd.h"
|
|
|
|
// ==========================================================================
|
|
// CEILINGS
|
|
// ==========================================================================
|
|
|
|
// the list of ceilings moving currently, including crushers
|
|
INT32 ceilmovesound = sfx_None;
|
|
|
|
/** Moves a moving ceiling.
|
|
*
|
|
* \param ceiling Thinker for the ceiling to be moved.
|
|
* \sa EV_DoCeiling
|
|
* \todo Split up into multiple functions.
|
|
*/
|
|
void T_MoveCeiling(ceiling_t *ceiling)
|
|
{
|
|
result_e res;
|
|
|
|
if (ceiling->delaytimer)
|
|
{
|
|
ceiling->delaytimer--;
|
|
return;
|
|
}
|
|
|
|
res = T_MovePlane(ceiling->sector, ceiling->speed, (ceiling->direction == 1) ? ceiling->topheight : ceiling->bottomheight, false, true, ceiling->direction);
|
|
|
|
if (ceiling->type == bounceCeiling)
|
|
{
|
|
const fixed_t origspeed = FixedDiv(ceiling->origspeed, (ELEVATORSPEED/2));
|
|
const fixed_t fs = abs(ceiling->sector->ceilingheight - ceiling->crushHeight);
|
|
const fixed_t bs = abs(ceiling->sector->ceilingheight - ceiling->returnHeight);
|
|
if (fs < bs)
|
|
ceiling->speed = FixedDiv(fs, 25*FRACUNIT) + FRACUNIT/4;
|
|
else
|
|
ceiling->speed = FixedDiv(bs, 25*FRACUNIT) + FRACUNIT/4;
|
|
ceiling->speed = FixedMul(ceiling->speed, origspeed);
|
|
}
|
|
|
|
if (res == pastdest)
|
|
{
|
|
switch (ceiling->type)
|
|
{
|
|
case instantMoveCeilingByFrontSector:
|
|
if (ceiling->texture > -1) // flat changing
|
|
ceiling->sector->ceilingpic = ceiling->texture;
|
|
ceiling->sector->ceilingdata = NULL;
|
|
ceiling->sector->ceilspeed = 0;
|
|
P_RemoveThinker(&ceiling->thinker);
|
|
return;
|
|
case moveCeilingByFrontSector:
|
|
if (ceiling->tag) // chained linedef executing
|
|
P_LinedefExecute(ceiling->tag, NULL, NULL);
|
|
if (ceiling->texture > -1) // flat changing
|
|
ceiling->sector->ceilingpic = ceiling->texture;
|
|
/* FALLTHRU */
|
|
case raiseToHighest:
|
|
case moveCeilingByDistance:
|
|
ceiling->sector->ceilingdata = NULL;
|
|
ceiling->sector->ceilspeed = 0;
|
|
P_RemoveThinker(&ceiling->thinker);
|
|
return;
|
|
case bounceCeiling:
|
|
case bounceCeilingCrush:
|
|
{
|
|
fixed_t dest = (ceiling->direction == 1) ? ceiling->topheight : ceiling->bottomheight;
|
|
|
|
if (dest == ceiling->crushHeight)
|
|
{
|
|
dest = ceiling->returnHeight;
|
|
ceiling->origspeed = ceiling->returnSpeed; // return trip, use args[3]
|
|
}
|
|
else
|
|
{
|
|
dest = ceiling->crushHeight;
|
|
ceiling->origspeed = ceiling->crushSpeed; // going frontways, use args[2]
|
|
}
|
|
|
|
if (ceiling->type == bounceCeilingCrush)
|
|
ceiling->speed = ceiling->origspeed;
|
|
|
|
if (dest < ceiling->sector->ceilingheight) // must move down
|
|
{
|
|
ceiling->direction = -1;
|
|
ceiling->bottomheight = dest;
|
|
}
|
|
else // must move up
|
|
{
|
|
ceiling->direction = 1;
|
|
ceiling->topheight = dest;
|
|
}
|
|
|
|
ceiling->delaytimer = ceiling->delay;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
ceiling->sector->ceilspeed = ceiling->speed*ceiling->direction;
|
|
}
|
|
|
|
/** Moves a ceiling crusher.
|
|
*
|
|
* \param ceiling Thinker for the crusher to be moved.
|
|
* \sa EV_DoCrush
|
|
*/
|
|
void T_CrushCeiling(ceiling_t *ceiling)
|
|
{
|
|
result_e res;
|
|
|
|
switch (ceiling->direction)
|
|
{
|
|
case 0: // IN STASIS
|
|
break;
|
|
case 1: // UP
|
|
if (ceiling->type == crushBothOnce)
|
|
{
|
|
// Move the floor
|
|
T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight-(ceiling->topheight-ceiling->bottomheight), false, false, -ceiling->direction);
|
|
}
|
|
|
|
res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight, false, true, ceiling->direction);
|
|
|
|
if (res == pastdest)
|
|
{
|
|
ceiling->direction = -1;
|
|
ceiling->speed = ceiling->crushSpeed;
|
|
|
|
if (ceiling->type == crushCeilOnce
|
|
|| ceiling->type == crushBothOnce)
|
|
{
|
|
// Remove
|
|
switch(ceiling->type)
|
|
{
|
|
case crushCeilOnce:
|
|
ceiling->sector->ceilspeed = 0;
|
|
ceiling->sector->ceilingdata = NULL;
|
|
break;
|
|
case crushBothOnce:
|
|
ceiling->sector->floorspeed = 0;
|
|
ceiling->sector->ceilspeed = 0;
|
|
ceiling->sector->ceilingdata = NULL;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
P_RemoveThinker(&ceiling->thinker);
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case -1: // DOWN
|
|
if (ceiling->type == crushBothOnce)
|
|
{
|
|
// Move the floor
|
|
T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, false, -ceiling->direction);
|
|
}
|
|
|
|
res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, true, ceiling->direction);
|
|
|
|
if (res == pastdest)
|
|
{
|
|
mobj_t *mp = (void *)&ceiling->sector->soundorg;
|
|
ceiling->sector->soundorg.z = ceiling->sector->floorheight;
|
|
S_StartSound(mp,sfx_pstop);
|
|
|
|
ceiling->direction = 1;
|
|
ceiling->speed = ceiling->returnSpeed;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (ceiling->type == crushBothOnce)
|
|
ceiling->sector->floorspeed = ceiling->speed*(-ceiling->direction);
|
|
|
|
ceiling->sector->ceilspeed = ceiling->speed*ceiling->direction;
|
|
}
|
|
|
|
/** Starts a ceiling mover.
|
|
*
|
|
* \param tag Tag.
|
|
* \param line The source line.
|
|
* \param type The type of ceiling movement.
|
|
* \return 1 if at least one ceiling mover was started, 0 otherwise.
|
|
* \sa EV_DoCrush, EV_DoFloor, EV_DoElevator, T_MoveCeiling
|
|
*/
|
|
INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type)
|
|
{
|
|
// This function is deprecated.
|
|
// Use any of the following functions directly, instead.
|
|
|
|
switch (type)
|
|
{
|
|
default:
|
|
return 0;
|
|
|
|
case raiseToHighest:
|
|
return (INT32)EV_DoRaiseCeilingToHighest(tag);
|
|
|
|
case lowerToLowestFast:
|
|
return (INT32)EV_DoLowerCeilingToLowestFast(tag);
|
|
|
|
case instantRaise:
|
|
return (INT32)EV_DoInstantRaiseCeiling(tag);
|
|
|
|
case moveCeilingByFrontSector:
|
|
return (INT32)EV_DoMoveCeilingByHeight(
|
|
tag,
|
|
line->frontsector->ceilingheight,
|
|
line->args[2] << (FRACBITS - 3),
|
|
(line->args[1] == TMP_CEILING) ? line->args[3] : 0,
|
|
line->args[4] ? line->frontsector->ceilingpic : -1
|
|
);
|
|
|
|
case instantMoveCeilingByFrontSector:
|
|
return (INT32)EV_DoInstantMoveCeilingByHeight(
|
|
tag,
|
|
line->frontsector->ceilingheight,
|
|
line->args[2] ? line->frontsector->ceilingpic : -1
|
|
);
|
|
|
|
case moveCeilingByDistance:
|
|
return (INT32)EV_DoMoveCeilingByDistance(
|
|
tag,
|
|
line->args[2] << FRACBITS,
|
|
line->args[3] << (FRACBITS - 3),
|
|
line->args[4]
|
|
);
|
|
|
|
case bounceCeiling:
|
|
case bounceCeilingCrush:
|
|
return (INT32)EV_DoBounceCeiling(
|
|
tag,
|
|
(type == bounceCeilingCrush),
|
|
line->frontsector->ceilingheight,
|
|
line->args[2] << (FRACBITS - 2),
|
|
line->backsector->ceilingheight,
|
|
line->args[3] << (FRACBITS - 2),
|
|
line->args[4],
|
|
line->args[5]
|
|
);
|
|
}
|
|
}
|
|
|
|
static ceiling_t *CreateCeilingThinker(sector_t *sec)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
|
|
if (sec->ceilingdata)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL);
|
|
P_AddThinker(THINK_MAIN, &ceiling->thinker);
|
|
|
|
sec->ceilingdata = ceiling;
|
|
|
|
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
|
|
ceiling->sector = sec;
|
|
ceiling->crush = false;
|
|
|
|
// interpolation
|
|
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
|
|
|
|
return ceiling;
|
|
}
|
|
|
|
boolean EV_DoRaiseCeilingToHighest(mtag_t tag)
|
|
{
|
|
boolean rtn = false;
|
|
INT32 secnum = -1;
|
|
sector_t *sec;
|
|
|
|
TAG_ITER_SECTORS(tag, secnum)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
sec = §ors[secnum];
|
|
|
|
ceiling = CreateCeilingThinker(sec);
|
|
if (ceiling == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ceiling->type = raiseToHighest;
|
|
|
|
ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
|
|
ceiling->direction = 1;
|
|
ceiling->speed = CEILSPEED;
|
|
|
|
rtn = true;
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
|
|
boolean EV_DoLowerCeilingToLowestFast(mtag_t tag)
|
|
{
|
|
boolean rtn = false;
|
|
INT32 secnum = -1;
|
|
sector_t *sec;
|
|
|
|
TAG_ITER_SECTORS(tag, secnum)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
sec = §ors[secnum];
|
|
|
|
ceiling = CreateCeilingThinker(sec);
|
|
if (ceiling == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ceiling->type = lowerToLowestFast;
|
|
|
|
ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec);
|
|
ceiling->direction = -1;
|
|
ceiling->speed = 4*FRACUNIT;
|
|
|
|
rtn = true;
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
|
|
boolean EV_DoInstantRaiseCeiling(mtag_t tag)
|
|
{
|
|
boolean rtn = false;
|
|
INT32 secnum = -1;
|
|
sector_t *sec;
|
|
|
|
TAG_ITER_SECTORS(tag, secnum)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
sec = §ors[secnum];
|
|
|
|
ceiling = CreateCeilingThinker(sec);
|
|
if (ceiling == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ceiling->type = instantRaise;
|
|
|
|
ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
|
|
ceiling->direction = 1;
|
|
ceiling->speed = INT32_MAX/2;
|
|
|
|
rtn = true;
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
|
|
boolean EV_DoMoveCeilingByHeight(mtag_t tag, fixed_t height, fixed_t speed, mtag_t chain, INT32 texture)
|
|
{
|
|
boolean rtn = false;
|
|
boolean firstone = true;
|
|
INT32 secnum = -1;
|
|
sector_t *sec;
|
|
|
|
TAG_ITER_SECTORS(tag, secnum)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
sec = §ors[secnum];
|
|
|
|
ceiling = CreateCeilingThinker(sec);
|
|
if (ceiling == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ceiling->type = moveCeilingByFrontSector;
|
|
|
|
ceiling->speed = speed;
|
|
if (height >= sec->ceilingheight) // Move up
|
|
{
|
|
ceiling->direction = 1;
|
|
ceiling->topheight = height;
|
|
}
|
|
else // Move down
|
|
{
|
|
ceiling->direction = -1;
|
|
ceiling->bottomheight = height;
|
|
}
|
|
|
|
// chained linedef executing ability
|
|
// only set it on ONE of the moving sectors (the smallest numbered)
|
|
if (chain)
|
|
ceiling->tag = firstone ? (INT16)chain : 0;
|
|
|
|
// flat changing ability
|
|
ceiling->texture = texture;
|
|
|
|
firstone = false;
|
|
rtn = true;
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
|
|
boolean EV_DoInstantMoveCeilingByHeight(mtag_t tag, fixed_t height, INT32 texture)
|
|
{
|
|
boolean rtn = false;
|
|
INT32 secnum = -1;
|
|
sector_t *sec;
|
|
|
|
TAG_ITER_SECTORS(tag, secnum)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
sec = §ors[secnum];
|
|
|
|
ceiling = CreateCeilingThinker(sec);
|
|
if (ceiling == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ceiling->type = instantMoveCeilingByFrontSector;
|
|
|
|
ceiling->speed = INT32_MAX/2;
|
|
if (height >= sec->ceilingheight) // Move up
|
|
{
|
|
ceiling->direction = 1;
|
|
ceiling->topheight = height;
|
|
}
|
|
else // Move down
|
|
{
|
|
ceiling->direction = -1;
|
|
ceiling->bottomheight = height;
|
|
}
|
|
|
|
// flat changing ability
|
|
ceiling->texture = texture;
|
|
|
|
rtn = true;
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
|
|
boolean EV_DoMoveCeilingByDistance(mtag_t tag, fixed_t distance, fixed_t speed, boolean instant)
|
|
{
|
|
boolean rtn = false;
|
|
INT32 secnum = -1;
|
|
sector_t *sec;
|
|
|
|
TAG_ITER_SECTORS(tag, secnum)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
sec = §ors[secnum];
|
|
|
|
ceiling = CreateCeilingThinker(sec);
|
|
if (ceiling == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ceiling->type = moveCeilingByDistance;
|
|
|
|
if (instant)
|
|
ceiling->speed = INT32_MAX/2; // as above, "instant" is one tic
|
|
else
|
|
ceiling->speed = speed;
|
|
|
|
if (distance > 0)
|
|
{
|
|
ceiling->direction = 1; // up
|
|
ceiling->topheight = sec->ceilingheight + distance;
|
|
}
|
|
else
|
|
{
|
|
ceiling->direction = -1; // down
|
|
ceiling->bottomheight = sec->ceilingheight + distance;
|
|
}
|
|
|
|
rtn = true;
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
|
|
boolean EV_DoBounceCeiling(mtag_t tag, boolean crush, fixed_t crushHeight, fixed_t crushSpeed, fixed_t returnHeight, fixed_t returnSpeed, INT32 delayInit, INT32 delay)
|
|
{
|
|
boolean rtn = false;
|
|
INT32 secnum = -1;
|
|
sector_t *sec;
|
|
|
|
TAG_ITER_SECTORS(tag, secnum)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
sec = §ors[secnum];
|
|
|
|
ceiling = CreateCeilingThinker(sec);
|
|
if (ceiling == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ceiling->type = crush ? bounceCeilingCrush : bounceCeiling;
|
|
|
|
ceiling->crushHeight = crushHeight;
|
|
ceiling->crushSpeed = crushSpeed; // same speed as elevateContinuous
|
|
|
|
ceiling->returnHeight = returnHeight;
|
|
ceiling->returnSpeed = returnSpeed;
|
|
|
|
ceiling->speed = ceiling->crushSpeed;
|
|
ceiling->origspeed = ceiling->speed;
|
|
|
|
if (ceiling->crushHeight >= sec->ceilingheight) // Move up
|
|
{
|
|
ceiling->direction = 1;
|
|
ceiling->topheight = ceiling->crushHeight;
|
|
}
|
|
else // Move down
|
|
{
|
|
ceiling->direction = -1;
|
|
ceiling->bottomheight = ceiling->crushHeight;
|
|
}
|
|
|
|
// Any delay?
|
|
ceiling->delay = delay;
|
|
ceiling->delaytimer = delayInit; // Initial delay
|
|
|
|
rtn = true;
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
|
|
/** Starts a ceiling crusher.
|
|
*
|
|
* \param tag Tag.
|
|
* \param line The source line.
|
|
* \param type The type of ceiling, either ::crushAndRaise or
|
|
* ::fastCrushAndRaise.
|
|
* \return 1 if at least one crusher was started, 0 otherwise.
|
|
* \sa EV_DoCeiling, EV_DoFloor, EV_DoElevator, T_CrushCeiling
|
|
*/
|
|
INT32 EV_DoCrush(mtag_t tag, line_t *line, ceiling_e type)
|
|
{
|
|
// This function is deprecated.
|
|
// Use any of the following functions directly, instead.
|
|
|
|
fixed_t speed = line->args[2] << (FRACBITS - 2);
|
|
|
|
switch (type)
|
|
{
|
|
default:
|
|
return 0;
|
|
|
|
case raiseAndCrush:
|
|
return (INT32)EV_DoRaiseAndCrushCeiling(tag, speed,
|
|
// Retain stupid behavior for backwards compatibility
|
|
(!udmf && !(line->flags & ML_MIDSOLID)) ? (speed / 2)
|
|
: (line->args[3] << (FRACBITS - 2))
|
|
);
|
|
|
|
case crushBothOnce:
|
|
return (INT32)EV_DoCrushBothOnce(tag, speed);
|
|
|
|
case crushCeilOnce:
|
|
return (INT32)EV_DoCrushCeilingOnce(tag, speed);
|
|
}
|
|
}
|
|
|
|
static ceiling_t *CreateCrushThinker(sector_t *sec)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
|
|
if (sec->ceilingdata)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL);
|
|
P_AddThinker(THINK_MAIN, &ceiling->thinker);
|
|
|
|
sec->ceilingdata = ceiling;
|
|
|
|
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
|
|
ceiling->sector = sec;
|
|
ceiling->crush = true;
|
|
|
|
// interpolation
|
|
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
|
|
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, false);
|
|
|
|
return ceiling;
|
|
}
|
|
|
|
boolean EV_DoRaiseAndCrushCeiling(mtag_t tag, fixed_t speed, fixed_t returnSpeed)
|
|
{
|
|
boolean rtn = false;
|
|
INT32 secnum = -1;
|
|
sector_t *sec;
|
|
|
|
TAG_ITER_SECTORS(tag, secnum)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
sec = §ors[secnum];
|
|
|
|
ceiling = CreateCrushThinker(sec);
|
|
if (ceiling == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ceiling->type = raiseAndCrush;
|
|
ceiling->speed = ceiling->origspeed = speed;
|
|
|
|
ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
|
|
ceiling->direction = 1;
|
|
|
|
ceiling->speed = returnSpeed;
|
|
ceiling->bottomheight = sec->floorheight + FRACUNIT;
|
|
|
|
rtn = true;
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
|
|
boolean EV_DoCrushBothOnce(mtag_t tag, fixed_t speed)
|
|
{
|
|
boolean rtn = false;
|
|
INT32 secnum = -1;
|
|
sector_t *sec;
|
|
|
|
TAG_ITER_SECTORS(tag, secnum)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
sec = §ors[secnum];
|
|
|
|
ceiling = CreateCrushThinker(sec);
|
|
if (ceiling == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ceiling->type = crushBothOnce;
|
|
ceiling->speed = ceiling->origspeed = speed;
|
|
|
|
ceiling->topheight = sec->ceilingheight;
|
|
ceiling->bottomheight = sec->floorheight + (sec->ceilingheight - sec->floorheight) / 2;
|
|
ceiling->direction = -1;
|
|
|
|
rtn = true;
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
|
|
boolean EV_DoCrushCeilingOnce(mtag_t tag, fixed_t speed)
|
|
{
|
|
boolean rtn = false;
|
|
INT32 secnum = -1;
|
|
sector_t *sec;
|
|
|
|
TAG_ITER_SECTORS(tag, secnum)
|
|
{
|
|
ceiling_t *ceiling = NULL;
|
|
sec = §ors[secnum];
|
|
|
|
ceiling = CreateCrushThinker(sec);
|
|
if (ceiling == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ceiling->type = crushBothOnce;
|
|
ceiling->speed = ceiling->origspeed = speed;
|
|
|
|
ceiling->topheight = sec->ceilingheight;
|
|
ceiling->direction = -1;
|
|
ceiling->bottomheight = sec->floorheight + FRACUNIT;
|
|
|
|
rtn = true;
|
|
}
|
|
|
|
return rtn;
|
|
}
|