1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165 |
- /* Emacs style mode select -*- C++ -*-
- *-----------------------------------------------------------------------------
- *
- *
- * PrBoom: a Doom port merged with LxDoom and LSDLDoom
- * based on BOOM, a modified and improved DOOM engine
- * Copyright (C) 1999 by
- * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
- * Copyright (C) 1999-2000 by
- * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
- * Copyright 2005, 2006 by
- * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * DESCRIPTION:
- * Generalized linedef type handlers
- * Floors, Ceilings, Doors, Locked Doors, Lifts, Stairs, Crushers
- *
- *-----------------------------------------------------------------------------*/
- #include "doomstat.h" //jff 6/19/98 for demo_compatibility
- #include "r_main.h"
- #include "p_spec.h"
- #include "p_tick.h"
- #include "m_random.h"
- #include "s_sound.h"
- #include "sounds.h"
- //////////////////////////////////////////////////////////
- //
- // Generalized Linedef Type handlers
- //
- //////////////////////////////////////////////////////////
- //
- // EV_DoGenFloor()
- //
- // Handle generalized floor types
- //
- // Passed the line activating the generalized floor function
- // Returns true if a thinker is created
- //
- // jff 02/04/98 Added this routine (and file) to handle generalized
- // floor movers using bit fields in the line special type.
- //
- int EV_DoGenFloor
- ( line_t* line )
- {
- int secnum;
- int rtn;
- boolean manual;
- sector_t* sec;
- floormove_t* floor;
- unsigned value = (unsigned)line->special - GenFloorBase;
- // parse the bit fields in the line's special type
- int Crsh = (value & FloorCrush) >> FloorCrushShift;
- int ChgT = (value & FloorChange) >> FloorChangeShift;
- int Targ = (value & FloorTarget) >> FloorTargetShift;
- int Dirn = (value & FloorDirection) >> FloorDirectionShift;
- int ChgM = (value & FloorModel) >> FloorModelShift;
- int Sped = (value & FloorSpeed) >> FloorSpeedShift;
- int Trig = (value & TriggerType) >> TriggerTypeShift;
- rtn = 0;
- // check if a manual trigger, if so do just the sector on the backside
- manual = false;
- if (Trig==PushOnce || Trig==PushMany)
- {
- if (!(sec = line->backsector))
- return rtn;
- secnum = sec-sectors;
- manual = true;
- goto manual_floor;
- }
- secnum = -1;
- // if not manual do all sectors tagged the same as the line
- while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
- {
- sec = §ors[secnum];
- manual_floor:
- // Do not start another function if floor already moving
- if (P_SectorActive(floor_special,sec))
- {
- if (!manual)
- continue;
- else
- return rtn;
- }
- // new floor thinker
- rtn = 1;
- floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
- memset(floor, 0, sizeof(*floor));
- P_AddThinker (&floor->thinker);
- sec->floordata = floor;
- floor->thinker.function = T_MoveFloor;
- floor->crush = Crsh;
- floor->direction = Dirn? 1 : -1;
- floor->sector = sec;
- floor->texture = sec->floorpic;
- floor->newspecial = sec->special;
- //jff 3/14/98 transfer old special field too
- floor->oldspecial = sec->oldspecial;
- floor->type = genFloor;
- // set the speed of motion
- switch (Sped)
- {
- case SpeedSlow:
- floor->speed = FLOORSPEED;
- break;
- case SpeedNormal:
- floor->speed = FLOORSPEED*2;
- break;
- case SpeedFast:
- floor->speed = FLOORSPEED*4;
- break;
- case SpeedTurbo:
- floor->speed = FLOORSPEED*8;
- break;
- default:
- break;
- }
- // set the destination height
- switch(Targ)
- {
- case FtoHnF:
- floor->floordestheight = P_FindHighestFloorSurrounding(sec);
- break;
- case FtoLnF:
- floor->floordestheight = P_FindLowestFloorSurrounding(sec);
- break;
- case FtoNnF:
- floor->floordestheight = Dirn?
- P_FindNextHighestFloor(sec,sec->floorheight) :
- P_FindNextLowestFloor(sec,sec->floorheight);
- break;
- case FtoLnC:
- floor->floordestheight = P_FindLowestCeilingSurrounding(sec);
- break;
- case FtoC:
- floor->floordestheight = sec->ceilingheight;
- break;
- case FbyST:
- floor->floordestheight = (floor->sector->floorheight>>FRACBITS) +
- floor->direction * (P_FindShortestTextureAround(secnum)>>FRACBITS);
- if (floor->floordestheight>32000) //jff 3/13/98 prevent overflow
- floor->floordestheight=32000; // wraparound in floor height
- if (floor->floordestheight<-32000)
- floor->floordestheight=-32000;
- floor->floordestheight<<=FRACBITS;
- break;
- case Fby24:
- floor->floordestheight = floor->sector->floorheight +
- floor->direction * 24*FRACUNIT;
- break;
- case Fby32:
- floor->floordestheight = floor->sector->floorheight +
- floor->direction * 32*FRACUNIT;
- break;
- default:
- break;
- }
- // set texture/type change properties
- if (ChgT) // if a texture change is indicated
- {
- if (ChgM) // if a numeric model change
- {
- sector_t *sec;
- //jff 5/23/98 find model with ceiling at target height if target
- //is a ceiling type
- sec = (Targ==FtoLnC || Targ==FtoC)?
- P_FindModelCeilingSector(floor->floordestheight,secnum) :
- P_FindModelFloorSector(floor->floordestheight,secnum);
- if (sec)
- {
- floor->texture = sec->floorpic;
- switch(ChgT)
- {
- case FChgZero: // zero type
- floor->newspecial = 0;
- //jff 3/14/98 change old field too
- floor->oldspecial = 0;
- floor->type = genFloorChg0;
- break;
- case FChgTyp: // copy type
- floor->newspecial = sec->special;
- //jff 3/14/98 change old field too
- floor->oldspecial = sec->oldspecial;
- floor->type = genFloorChgT;
- break;
- case FChgTxt: // leave type be
- floor->type = genFloorChg;
- break;
- default:
- break;
- }
- }
- }
- else // else if a trigger model change
- {
- floor->texture = line->frontsector->floorpic;
- switch (ChgT)
- {
- case FChgZero: // zero type
- floor->newspecial = 0;
- //jff 3/14/98 change old field too
- floor->oldspecial = 0;
- floor->type = genFloorChg0;
- break;
- case FChgTyp: // copy type
- floor->newspecial = line->frontsector->special;
- //jff 3/14/98 change old field too
- floor->oldspecial = line->frontsector->oldspecial;
- floor->type = genFloorChgT;
- break;
- case FChgTxt: // leave type be
- floor->type = genFloorChg;
- default:
- break;
- }
- }
- }
- if (manual) return rtn;
- }
- return rtn;
- }
- //
- // EV_DoGenCeiling()
- //
- // Handle generalized ceiling types
- //
- // Passed the linedef activating the ceiling function
- // Returns true if a thinker created
- //
- // jff 02/04/98 Added this routine (and file) to handle generalized
- // floor movers using bit fields in the line special type.
- //
- int EV_DoGenCeiling
- ( line_t* line )
- {
- int secnum;
- int rtn;
- boolean manual;
- fixed_t targheight;
- sector_t* sec;
- ceiling_t* ceiling;
- unsigned value = (unsigned)line->special - GenCeilingBase;
- // parse the bit fields in the line's special type
- int Crsh = (value & CeilingCrush) >> CeilingCrushShift;
- int ChgT = (value & CeilingChange) >> CeilingChangeShift;
- int Targ = (value & CeilingTarget) >> CeilingTargetShift;
- int Dirn = (value & CeilingDirection) >> CeilingDirectionShift;
- int ChgM = (value & CeilingModel) >> CeilingModelShift;
- int Sped = (value & CeilingSpeed) >> CeilingSpeedShift;
- int Trig = (value & TriggerType) >> TriggerTypeShift;
- rtn = 0;
- // check if a manual trigger, if so do just the sector on the backside
- manual = false;
- if (Trig==PushOnce || Trig==PushMany)
- {
- if (!(sec = line->backsector))
- return rtn;
- secnum = sec-sectors;
- manual = true;
- goto manual_ceiling;
- }
- secnum = -1;
- // if not manual do all sectors tagged the same as the line
- while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
- {
- sec = §ors[secnum];
- manual_ceiling:
- // Do not start another function if ceiling already moving
- if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
- {
- if (!manual)
- continue;
- else
- return rtn;
- }
- // new ceiling thinker
- rtn = 1;
- ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
- memset(ceiling, 0, sizeof(*ceiling));
- P_AddThinker (&ceiling->thinker);
- sec->ceilingdata = ceiling; //jff 2/22/98
- ceiling->thinker.function = T_MoveCeiling;
- ceiling->crush = Crsh;
- ceiling->direction = Dirn? 1 : -1;
- ceiling->sector = sec;
- ceiling->texture = sec->ceilingpic;
- ceiling->newspecial = sec->special;
- //jff 3/14/98 change old field too
- ceiling->oldspecial = sec->oldspecial;
- ceiling->tag = sec->tag;
- ceiling->type = genCeiling;
- // set speed of motion
- switch (Sped)
- {
- case SpeedSlow:
- ceiling->speed = CEILSPEED;
- break;
- case SpeedNormal:
- ceiling->speed = CEILSPEED*2;
- break;
- case SpeedFast:
- ceiling->speed = CEILSPEED*4;
- break;
- case SpeedTurbo:
- ceiling->speed = CEILSPEED*8;
- break;
- default:
- break;
- }
- // set destination target height
- targheight = sec->ceilingheight;
- switch(Targ)
- {
- case CtoHnC:
- targheight = P_FindHighestCeilingSurrounding(sec);
- break;
- case CtoLnC:
- targheight = P_FindLowestCeilingSurrounding(sec);
- break;
- case CtoNnC:
- targheight = Dirn?
- P_FindNextHighestCeiling(sec,sec->ceilingheight) :
- P_FindNextLowestCeiling(sec,sec->ceilingheight);
- break;
- case CtoHnF:
- targheight = P_FindHighestFloorSurrounding(sec);
- break;
- case CtoF:
- targheight = sec->floorheight;
- break;
- case CbyST:
- targheight = (ceiling->sector->ceilingheight>>FRACBITS) +
- ceiling->direction * (P_FindShortestUpperAround(secnum)>>FRACBITS);
- if (targheight>32000) //jff 3/13/98 prevent overflow
- targheight=32000; // wraparound in ceiling height
- if (targheight<-32000)
- targheight=-32000;
- targheight<<=FRACBITS;
- break;
- case Cby24:
- targheight = ceiling->sector->ceilingheight +
- ceiling->direction * 24*FRACUNIT;
- break;
- case Cby32:
- targheight = ceiling->sector->ceilingheight +
- ceiling->direction * 32*FRACUNIT;
- break;
- default:
- break;
- }
- if (Dirn) ceiling->topheight = targheight;
- else ceiling->bottomheight = targheight;
- // set texture/type change properties
- if (ChgT) // if a texture change is indicated
- {
- if (ChgM) // if a numeric model change
- {
- sector_t *sec;
- //jff 5/23/98 find model with floor at target height if target
- //is a floor type
- sec = (Targ==CtoHnF || Targ==CtoF)?
- P_FindModelFloorSector(targheight,secnum) :
- P_FindModelCeilingSector(targheight,secnum);
- if (sec)
- {
- ceiling->texture = sec->ceilingpic;
- switch (ChgT)
- {
- case CChgZero: // type is zeroed
- ceiling->newspecial = 0;
- //jff 3/14/98 change old field too
- ceiling->oldspecial = 0;
- ceiling->type = genCeilingChg0;
- break;
- case CChgTyp: // type is copied
- ceiling->newspecial = sec->special;
- //jff 3/14/98 change old field too
- ceiling->oldspecial = sec->oldspecial;
- ceiling->type = genCeilingChgT;
- break;
- case CChgTxt: // type is left alone
- ceiling->type = genCeilingChg;
- break;
- default:
- break;
- }
- }
- }
- else // else if a trigger model change
- {
- ceiling->texture = line->frontsector->ceilingpic;
- switch (ChgT)
- {
- case CChgZero: // type is zeroed
- ceiling->newspecial = 0;
- //jff 3/14/98 change old field too
- ceiling->oldspecial = 0;
- ceiling->type = genCeilingChg0;
- break;
- case CChgTyp: // type is copied
- ceiling->newspecial = line->frontsector->special;
- //jff 3/14/98 change old field too
- ceiling->oldspecial = line->frontsector->oldspecial;
- ceiling->type = genCeilingChgT;
- break;
- case CChgTxt: // type is left alone
- ceiling->type = genCeilingChg;
- break;
- default:
- break;
- }
- }
- }
- P_AddActiveCeiling(ceiling); // add this ceiling to the active list
- if (manual) return rtn;
- }
- return rtn;
- }
- //
- // EV_DoGenLift()
- //
- // Handle generalized lift types
- //
- // Passed the linedef activating the lift
- // Returns true if a thinker is created
- //
- int EV_DoGenLift
- ( line_t* line )
- {
- plat_t* plat;
- int secnum;
- int rtn;
- boolean manual;
- sector_t* sec;
- unsigned value = (unsigned)line->special - GenLiftBase;
- // parse the bit fields in the line's special type
- int Targ = (value & LiftTarget) >> LiftTargetShift;
- int Dely = (value & LiftDelay) >> LiftDelayShift;
- int Sped = (value & LiftSpeed) >> LiftSpeedShift;
- int Trig = (value & TriggerType) >> TriggerTypeShift;
- secnum = -1;
- rtn = 0;
- // Activate all <type> plats that are in_stasis
- if (Targ==LnF2HnF)
- P_ActivateInStasis(line->tag);
- // check if a manual trigger, if so do just the sector on the backside
- manual = false;
- if (Trig==PushOnce || Trig==PushMany)
- {
- if (!(sec = line->backsector))
- return rtn;
- secnum = sec-sectors;
- manual = true;
- goto manual_lift;
- }
- // if not manual do all sectors tagged the same as the line
- while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
- {
- sec = §ors[secnum];
- manual_lift:
- // Do not start another function if floor already moving
- if (P_SectorActive(floor_special,sec))
- {
- if (!manual)
- continue;
- else
- return rtn;
- }
- // Setup the plat thinker
- rtn = 1;
- plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0);
- memset(plat, 0, sizeof(*plat));
- P_AddThinker(&plat->thinker);
- plat->sector = sec;
- plat->sector->floordata = plat;
- plat->thinker.function = T_PlatRaise;
- plat->crush = false;
- plat->tag = line->tag;
- plat->type = genLift;
- plat->high = sec->floorheight;
- plat->status = down;
- // setup the target destination height
- switch(Targ)
- {
- case F2LnF:
- plat->low = P_FindLowestFloorSurrounding(sec);
- if (plat->low > sec->floorheight)
- plat->low = sec->floorheight;
- break;
- case F2NnF:
- plat->low = P_FindNextLowestFloor(sec,sec->floorheight);
- break;
- case F2LnC:
- plat->low = P_FindLowestCeilingSurrounding(sec);
- if (plat->low > sec->floorheight)
- plat->low = sec->floorheight;
- break;
- case LnF2HnF:
- plat->type = genPerpetual;
- plat->low = P_FindLowestFloorSurrounding(sec);
- if (plat->low > sec->floorheight)
- plat->low = sec->floorheight;
- plat->high = P_FindHighestFloorSurrounding(sec);
- if (plat->high < sec->floorheight)
- plat->high = sec->floorheight;
- plat->status = P_Random(pr_genlift)&1;
- break;
- default:
- break;
- }
- // setup the speed of motion
- switch(Sped)
- {
- case SpeedSlow:
- plat->speed = PLATSPEED * 2;
- break;
- case SpeedNormal:
- plat->speed = PLATSPEED * 4;
- break;
- case SpeedFast:
- plat->speed = PLATSPEED * 8;
- break;
- case SpeedTurbo:
- plat->speed = PLATSPEED * 16;
- break;
- default:
- break;
- }
- // setup the delay time before the floor returns
- switch(Dely)
- {
- case 0:
- plat->wait = 1*35;
- break;
- case 1:
- plat->wait = PLATWAIT*35;
- break;
- case 2:
- plat->wait = 5*35;
- break;
- case 3:
- plat->wait = 10*35;
- break;
- }
- S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
- P_AddActivePlat(plat); // add this plat to the list of active plats
- if (manual)
- return rtn;
- }
- return rtn;
- }
- //
- // EV_DoGenStairs()
- //
- // Handle generalized stair building
- //
- // Passed the linedef activating the stairs
- // Returns true if a thinker is created
- //
- int EV_DoGenStairs
- ( line_t* line )
- {
- int secnum;
- int osecnum; //jff 3/4/98 preserve loop index
- int height;
- int i;
- int newsecnum;
- int texture;
- int ok;
- int rtn;
- boolean manual;
- sector_t* sec;
- sector_t* tsec;
- floormove_t* floor;
- fixed_t stairsize;
- fixed_t speed;
- unsigned value = (unsigned)line->special - GenStairsBase;
- // parse the bit fields in the line's special type
- int Igno = (value & StairIgnore) >> StairIgnoreShift;
- int Dirn = (value & StairDirection) >> StairDirectionShift;
- int Step = (value & StairStep) >> StairStepShift;
- int Sped = (value & StairSpeed) >> StairSpeedShift;
- int Trig = (value & TriggerType) >> TriggerTypeShift;
- rtn = 0;
- // check if a manual trigger, if so do just the sector on the backside
- manual = false;
- if (Trig==PushOnce || Trig==PushMany)
- {
- if (!(sec = line->backsector))
- return rtn;
- secnum = sec-sectors;
- manual = true;
- goto manual_stair;
- }
- secnum = -1;
- // if not manual do all sectors tagged the same as the line
- while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
- {
- sec = §ors[secnum];
- manual_stair:
- //Do not start another function if floor already moving
- //jff 2/26/98 add special lockout condition to wait for entire
- //staircase to build before retriggering
- if (P_SectorActive(floor_special,sec) || sec->stairlock)
- {
- if (!manual)
- continue;
- else
- return rtn;
- }
- // new floor thinker
- rtn = 1;
- floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
- memset(floor, 0, sizeof(*floor));
- P_AddThinker (&floor->thinker);
- sec->floordata = floor;
- floor->thinker.function = T_MoveFloor;
- floor->direction = Dirn? 1 : -1;
- floor->sector = sec;
- // setup speed of stair building
- switch(Sped)
- {
- default:
- case SpeedSlow:
- floor->speed = FLOORSPEED/4;
- break;
- case SpeedNormal:
- floor->speed = FLOORSPEED/2;
- break;
- case SpeedFast:
- floor->speed = FLOORSPEED*2;
- break;
- case SpeedTurbo:
- floor->speed = FLOORSPEED*4;
- break;
- }
- // setup stepsize for stairs
- switch(Step)
- {
- default:
- case 0:
- stairsize = 4*FRACUNIT;
- break;
- case 1:
- stairsize = 8*FRACUNIT;
- break;
- case 2:
- stairsize = 16*FRACUNIT;
- break;
- case 3:
- stairsize = 24*FRACUNIT;
- break;
- }
- speed = floor->speed;
- height = sec->floorheight + floor->direction * stairsize;
- floor->floordestheight = height;
- texture = sec->floorpic;
- floor->crush = false;
- floor->type = genBuildStair; // jff 3/31/98 do not leave uninited
- sec->stairlock = -2; // jff 2/26/98 set up lock on current sector
- sec->nextsec = -1;
- sec->prevsec = -1;
- osecnum = secnum; //jff 3/4/98 preserve loop index
- // Find next sector to raise
- // 1. Find 2-sided line with same sector side[0]
- // 2. Other side is the next sector to raise
- do
- {
- ok = 0;
- for (i = 0;i < sec->linecount;i++)
- {
- if ( !((sec->lines[i])->backsector) )
- continue;
- tsec = (sec->lines[i])->frontsector;
- newsecnum = tsec-sectors;
- if (secnum != newsecnum)
- continue;
- tsec = (sec->lines[i])->backsector;
- newsecnum = tsec - sectors;
- if (!Igno && tsec->floorpic != texture)
- continue;
- /* jff 6/19/98 prevent double stepsize */
- if (compatibility_level < boom_202_compatibility)
- height += floor->direction * stairsize;
- //jff 2/26/98 special lockout condition for retriggering
- if (P_SectorActive(floor_special,tsec) || tsec->stairlock)
- continue;
- /* jff 6/19/98 increase height AFTER continue */
- if (compatibility_level >= boom_202_compatibility)
- height += floor->direction * stairsize;
- // jff 2/26/98
- // link the stair chain in both directions
- // lock the stair sector until building complete
- sec->nextsec = newsecnum; // link step to next
- tsec->prevsec = secnum; // link next back
- tsec->nextsec = -1; // set next forward link as end
- tsec->stairlock = -2; // lock the step
- sec = tsec;
- secnum = newsecnum;
- floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
- memset(floor, 0, sizeof(*floor));
- P_AddThinker (&floor->thinker);
- sec->floordata = floor;
- floor->thinker.function = T_MoveFloor;
- floor->direction = Dirn? 1 : -1;
- floor->sector = sec;
- floor->speed = speed;
- floor->floordestheight = height;
- floor->crush = false;
- floor->type = genBuildStair; // jff 3/31/98 do not leave uninited
- ok = 1;
- break;
- }
- } while(ok);
- if (manual)
- return rtn;
- secnum = osecnum; //jff 3/4/98 restore old loop index
- }
- // retriggerable generalized stairs build up or down alternately
- if (rtn)
- line->special ^= StairDirection; // alternate dir on succ activations
- return rtn;
- }
- //
- // EV_DoGenCrusher()
- //
- // Handle generalized crusher types
- //
- // Passed the linedef activating the crusher
- // Returns true if a thinker created
- //
- int EV_DoGenCrusher
- ( line_t* line )
- {
- int secnum;
- int rtn;
- boolean manual;
- sector_t* sec;
- ceiling_t* ceiling;
- unsigned value = (unsigned)line->special - GenCrusherBase;
- // parse the bit fields in the line's special type
- int Slnt = (value & CrusherSilent) >> CrusherSilentShift;
- int Sped = (value & CrusherSpeed) >> CrusherSpeedShift;
- int Trig = (value & TriggerType) >> TriggerTypeShift;
- //jff 2/22/98 Reactivate in-stasis ceilings...for certain types.
- //jff 4/5/98 return if activated
- rtn = P_ActivateInStasisCeiling(line);
- // check if a manual trigger, if so do just the sector on the backside
- manual = false;
- if (Trig==PushOnce || Trig==PushMany)
- {
- if (!(sec = line->backsector))
- return rtn;
- secnum = sec-sectors;
- manual = true;
- goto manual_crusher;
- }
- secnum = -1;
- // if not manual do all sectors tagged the same as the line
- while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
- {
- sec = §ors[secnum];
- manual_crusher:
- // Do not start another function if ceiling already moving
- if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
- {
- if (!manual)
- continue;
- else
- return rtn;
- }
- // new ceiling thinker
- rtn = 1;
- ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
- memset(ceiling, 0, sizeof(*ceiling));
- P_AddThinker (&ceiling->thinker);
- sec->ceilingdata = ceiling; //jff 2/22/98
- ceiling->thinker.function = T_MoveCeiling;
- ceiling->crush = true;
- ceiling->direction = -1;
- ceiling->sector = sec;
- ceiling->texture = sec->ceilingpic;
- ceiling->newspecial = sec->special;
- ceiling->tag = sec->tag;
- ceiling->type = Slnt? genSilentCrusher : genCrusher;
- ceiling->topheight = sec->ceilingheight;
- ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
- // setup ceiling motion speed
- switch (Sped)
- {
- case SpeedSlow:
- ceiling->speed = CEILSPEED;
- break;
- case SpeedNormal:
- ceiling->speed = CEILSPEED*2;
- break;
- case SpeedFast:
- ceiling->speed = CEILSPEED*4;
- break;
- case SpeedTurbo:
- ceiling->speed = CEILSPEED*8;
- break;
- default:
- break;
- }
- ceiling->oldspeed=ceiling->speed;
- P_AddActiveCeiling(ceiling); // add to list of active ceilings
- if (manual) return rtn;
- }
- return rtn;
- }
- //
- // EV_DoGenLockedDoor()
- //
- // Handle generalized locked door types
- //
- // Passed the linedef activating the generalized locked door
- // Returns true if a thinker created
- //
- int EV_DoGenLockedDoor
- ( line_t* line )
- {
- int secnum,rtn;
- sector_t* sec;
- vldoor_t* door;
- boolean manual;
- unsigned value = (unsigned)line->special - GenLockedBase;
- // parse the bit fields in the line's special type
- int Kind = (value & LockedKind) >> LockedKindShift;
- int Sped = (value & LockedSpeed) >> LockedSpeedShift;
- int Trig = (value & TriggerType) >> TriggerTypeShift;
- rtn = 0;
- // check if a manual trigger, if so do just the sector on the backside
- manual = false;
- if (Trig==PushOnce || Trig==PushMany)
- {
- if (!(sec = line->backsector))
- return rtn;
- secnum = sec-sectors;
- manual = true;
- goto manual_locked;
- }
- secnum = -1;
- rtn = 0;
- // if not manual do all sectors tagged the same as the line
- while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
- {
- sec = §ors[secnum];
- manual_locked:
- // Do not start another function if ceiling already moving
- if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
- {
- if (!manual)
- continue;
- else
- return rtn;
- }
- // new door thinker
- rtn = 1;
- door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
- memset(door, 0, sizeof(*door));
- P_AddThinker (&door->thinker);
- sec->ceilingdata = door; //jff 2/22/98
- door->thinker.function = T_VerticalDoor;
- door->sector = sec;
- door->topwait = VDOORWAIT;
- door->line = line;
- door->topheight = P_FindLowestCeilingSurrounding(sec);
- door->topheight -= 4*FRACUNIT;
- door->direction = 1;
- /* killough 10/98: implement gradual lighting */
- door->lighttag = !comp[comp_doorlight] &&
- (line->special&6) == 6 &&
- line->special > GenLockedBase ? line->tag : 0;
- // setup speed of door motion
- switch(Sped)
- {
- default:
- case SpeedSlow:
- door->type = Kind? genOpen : genRaise;
- door->speed = VDOORSPEED;
- break;
- case SpeedNormal:
- door->type = Kind? genOpen : genRaise;
- door->speed = VDOORSPEED*2;
- break;
- case SpeedFast:
- door->type = Kind? genBlazeOpen : genBlazeRaise;
- door->speed = VDOORSPEED*4;
- break;
- case SpeedTurbo:
- door->type = Kind? genBlazeOpen : genBlazeRaise;
- door->speed = VDOORSPEED*8;
- break;
- }
- // killough 4/15/98: fix generalized door opening sounds
- // (previously they always had the blazing door close sound)
- S_StartSound((mobj_t *)&door->sector->soundorg, // killough 4/15/98
- door->speed >= VDOORSPEED*4 ? sfx_bdopn : sfx_doropn);
- if (manual)
- return rtn;
- }
- return rtn;
- }
- //
- // EV_DoGenDoor()
- //
- // Handle generalized door types
- //
- // Passed the linedef activating the generalized door
- // Returns true if a thinker created
- //
- int EV_DoGenDoor
- ( line_t* line )
- {
- int secnum,rtn;
- sector_t* sec;
- boolean manual;
- vldoor_t* door;
- unsigned value = (unsigned)line->special - GenDoorBase;
- // parse the bit fields in the line's special type
- int Dely = (value & DoorDelay) >> DoorDelayShift;
- int Kind = (value & DoorKind) >> DoorKindShift;
- int Sped = (value & DoorSpeed) >> DoorSpeedShift;
- int Trig = (value & TriggerType) >> TriggerTypeShift;
- rtn = 0;
- // check if a manual trigger, if so do just the sector on the backside
- manual = false;
- if (Trig==PushOnce || Trig==PushMany)
- {
- if (!(sec = line->backsector))
- return rtn;
- secnum = sec-sectors;
- manual = true;
- goto manual_door;
- }
- secnum = -1;
- rtn = 0;
- // if not manual do all sectors tagged the same as the line
- while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
- {
- sec = §ors[secnum];
- manual_door:
- // Do not start another function if ceiling already moving
- if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
- {
- if (!manual)
- continue;
- else
- return rtn;
- }
- // new door thinker
- rtn = 1;
- door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
- memset(door, 0, sizeof(*door));
- P_AddThinker (&door->thinker);
- sec->ceilingdata = door; //jff 2/22/98
- door->thinker.function = T_VerticalDoor;
- door->sector = sec;
- // setup delay for door remaining open/closed
- switch(Dely)
- {
- default:
- case 0:
- door->topwait = 35;
- break;
- case 1:
- door->topwait = VDOORWAIT;
- break;
- case 2:
- door->topwait = 2*VDOORWAIT;
- break;
- case 3:
- door->topwait = 7*VDOORWAIT;
- break;
- }
- // setup speed of door motion
- switch(Sped)
- {
- default:
- case SpeedSlow:
- door->speed = VDOORSPEED;
- break;
- case SpeedNormal:
- door->speed = VDOORSPEED*2;
- break;
- case SpeedFast:
- door->speed = VDOORSPEED*4;
- break;
- case SpeedTurbo:
- door->speed = VDOORSPEED*8;
- break;
- }
- door->line = line; // jff 1/31/98 remember line that triggered us
- /* killough 10/98: implement gradual lighting */
- door->lighttag = !comp[comp_doorlight] &&
- (line->special&6) == 6 &&
- line->special > GenLockedBase ? line->tag : 0;
- // set kind of door, whether it opens then close, opens, closes etc.
- // assign target heights accordingly
- switch(Kind)
- {
- case OdCDoor:
- door->direction = 1;
- door->topheight = P_FindLowestCeilingSurrounding(sec);
- door->topheight -= 4*FRACUNIT;
- if (door->topheight != sec->ceilingheight)
- S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast || comp[comp_sound] ? sfx_bdopn : sfx_doropn);
- door->type = Sped>=SpeedFast? genBlazeRaise : genRaise;
- break;
- case ODoor:
- door->direction = 1;
- door->topheight = P_FindLowestCeilingSurrounding(sec);
- door->topheight -= 4*FRACUNIT;
- if (door->topheight != sec->ceilingheight)
- S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast || comp[comp_sound] ? sfx_bdopn : sfx_doropn);
- door->type = Sped>=SpeedFast? genBlazeOpen : genOpen;
- break;
- case CdODoor:
- door->topheight = sec->ceilingheight;
- door->direction = -1;
- S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast && !comp[comp_sound] ? sfx_bdcls : sfx_dorcls);
- door->type = Sped>=SpeedFast? genBlazeCdO : genCdO;
- break;
- case CDoor:
- door->topheight = P_FindLowestCeilingSurrounding(sec);
- door->topheight -= 4*FRACUNIT;
- door->direction = -1;
- S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast && !comp[comp_sound] ? sfx_bdcls : sfx_dorcls);
- door->type = Sped>=SpeedFast? genBlazeClose : genClose;
- break;
- default:
- break;
- }
- if (manual)
- return rtn;
- }
- return rtn;
- }
|