📄 p_genlin.c
字号:
// Emacs style mode select -*- C++ -*- //-----------------------------------------------------------------------------//// Copyright (C) 1993-1996 by id Software, Inc.// Portions Copyright (C) 1998-2000 by DooM Legacy Team.//// 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.//////// DESCRIPTION:// Generalized linedef type handlers// Floors, Ceilings, Doors, Locked Doors, Lifts, Stairs, Crushers////-----------------------------------------------------------------------------#include "doomdef.h"#include "g_game.h"#include "p_local.h"#include "r_data.h"#include "m_random.h"#include "s_sound.h"#include "z_zone.h"/* SoM: 3/9/2000: Copied this entire file from Boom sources to Legacy sources. This file contains all routiens for Generalized linedef types.*///// EV_DoGenFloor()//// Handle generalized floor types//// Passed the line activating the generalized floor function// Returns true if a thinker is created//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(floormove_t), PU_LEVSPEC, 0); P_AddThinker (&floor->thinker); sec->floordata = floor; floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; floor->crush = Crsh; floor->direction = Dirn? 1 : -1; floor->sector = sec; floor->texture = sec->floorpic; floor->newspecial = sec->special; 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) floor->floordestheight=32000; 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; 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; floor->oldspecial = 0; floor->type = genFloorChg0; break; case FChgTyp: // copy type floor->newspecial = sec->special; 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; floor->oldspecial = 0; floor->type = genFloorChg0; break; case FChgTyp: // copy type floor->newspecial = line->frontsector->special; 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//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)) { if (!manual) continue; else return rtn; } // new ceiling thinker rtn = 1; ceiling = Z_Malloc (sizeof(ceiling_t), PU_LEVSPEC, 0); P_AddThinker (&ceiling->thinker); sec->ceilingdata = ceiling; ceiling->thinker.function.acp1 = (actionf_p1) T_MoveCeiling; ceiling->crush = Crsh; ceiling->direction = Dirn? 1 : -1; ceiling->sector = sec; ceiling->texture = sec->ceilingpic; ceiling->newspecial = sec->special; 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) targheight=32000; 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; } //that doesn't compile under windows //Dirn? ceiling->topheight : ceiling->bottomheight = targheight; 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; 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; ceiling->oldspecial = 0; ceiling->type = genCeilingChg0; break; case CChgTyp: // type is copied ceiling->newspecial = sec->special; 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; ceiling->oldspecial = 0; ceiling->type = genCeilingChg0; break; case CChgTyp: // type is copied ceiling->newspecial = line->frontsector->special; 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); P_AddThinker(&plat->thinker); plat->sector = sec; plat->sector->floordata = plat; plat->thinker.function.acp1 = (actionf_p1) 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()&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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -