// // Copyright(C) 1993-1996 Id Software, Inc. // Copyright(C) 1993-2008 Raven Software // Copyright(C) 2005-2014 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. // #include "h2def.h" #include "p_local.h" //================================================================== //================================================================== // // CEILINGS // //================================================================== //================================================================== ceiling_t *activeceilings[MAXCEILINGS]; //================================================================== // // T_MoveCeiling // //================================================================== void T_MoveCeiling(ceiling_t * ceiling) { result_e res; switch (ceiling->direction) { // case 0: // IN STASIS // break; case 1: // UP res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight, false, 1, ceiling->direction); if (res == RES_PASTDEST) { SN_StopSequence((mobj_t *) & ceiling->sector->soundorg); switch (ceiling->type) { case CLEV_CRUSHANDRAISE: ceiling->direction = -1; ceiling->speed = ceiling->speed * 2; break; default: P_RemoveActiveCeiling(ceiling); break; } } break; case -1: // DOWN res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, 1, ceiling->direction); if (res == RES_PASTDEST) { SN_StopSequence((mobj_t *) & ceiling->sector->soundorg); switch (ceiling->type) { case CLEV_CRUSHANDRAISE: case CLEV_CRUSHRAISEANDSTAY: ceiling->direction = 1; ceiling->speed = ceiling->speed / 2; break; default: P_RemoveActiveCeiling(ceiling); break; } } else if (res == RES_CRUSHED) { switch (ceiling->type) { case CLEV_CRUSHANDRAISE: case CLEV_LOWERANDCRUSH: case CLEV_CRUSHRAISEANDSTAY: //ceiling->speed = ceiling->speed/4; break; default: break; } } break; } } //================================================================== // // EV_DoCeiling // Move a ceiling up/down and all around! // //================================================================== int EV_DoCeiling(line_t * line, byte * arg, ceiling_e type) { int secnum, rtn; sector_t *sec; ceiling_t *ceiling; secnum = -1; rtn = 0; /* Old Ceiling stasis code // // Reactivate in-stasis ceilings...for certain types. // switch(type) { case CLEV_CRUSHANDRAISE: P_ActivateInStasisCeiling(line); default: break; } */ while ((secnum = P_FindSectorFromTag(arg[0], secnum)) >= 0) { sec = §ors[secnum]; if (sec->specialdata) continue; // // new door thinker // rtn = 1; ceiling = Z_Malloc(sizeof(*ceiling), PU_LEVSPEC, 0); P_AddThinker(&ceiling->thinker); sec->specialdata = ceiling; ceiling->thinker.function = T_MoveCeiling; ceiling->sector = sec; ceiling->crush = 0; ceiling->speed = arg[1] * (FRACUNIT / 8); switch (type) { case CLEV_CRUSHRAISEANDSTAY: ceiling->crush = arg[2]; // arg[2] = crushing value ceiling->topheight = sec->ceilingheight; ceiling->bottomheight = sec->floorheight + (8 * FRACUNIT); ceiling->direction = -1; break; case CLEV_CRUSHANDRAISE: ceiling->topheight = sec->ceilingheight; case CLEV_LOWERANDCRUSH: ceiling->crush = arg[2]; // arg[2] = crushing value case CLEV_LOWERTOFLOOR: ceiling->bottomheight = sec->floorheight; if (type != CLEV_LOWERTOFLOOR) { ceiling->bottomheight += 8 * FRACUNIT; } ceiling->direction = -1; break; case CLEV_RAISETOHIGHEST: ceiling->topheight = P_FindHighestCeilingSurrounding(sec); ceiling->direction = 1; break; case CLEV_LOWERBYVALUE: ceiling->bottomheight = sec->ceilingheight - arg[2] * FRACUNIT; ceiling->direction = -1; break; case CLEV_RAISEBYVALUE: ceiling->topheight = sec->ceilingheight + arg[2] * FRACUNIT; ceiling->direction = 1; break; case CLEV_MOVETOVALUETIMES8: { int destHeight = arg[2] * FRACUNIT * 8; if (arg[3]) { destHeight = -destHeight; } if (sec->ceilingheight <= destHeight) { ceiling->direction = 1; ceiling->topheight = destHeight; if (sec->ceilingheight == destHeight) { rtn = 0; } } else if (sec->ceilingheight > destHeight) { ceiling->direction = -1; ceiling->bottomheight = destHeight; } break; } default: rtn = 0; break; } ceiling->tag = sec->tag; ceiling->type = type; P_AddActiveCeiling(ceiling); if (rtn) { SN_StartSequence((mobj_t *) & ceiling->sector->soundorg, SEQ_PLATFORM + ceiling->sector->seqType); } } return rtn; } //================================================================== // // Add an active ceiling // //================================================================== void P_AddActiveCeiling(ceiling_t * c) { int i; for (i = 0; i < MAXCEILINGS; i++) if (activeceilings[i] == NULL) { activeceilings[i] = c; return; } } //================================================================== // // Remove a ceiling's thinker // //================================================================== void P_RemoveActiveCeiling(ceiling_t * c) { int i; for (i = 0; i < MAXCEILINGS; i++) if (activeceilings[i] == c) { activeceilings[i]->sector->specialdata = NULL; P_RemoveThinker(&activeceilings[i]->thinker); P_TagFinished(activeceilings[i]->sector->tag); activeceilings[i] = NULL; break; } } #if 0 //================================================================== // // Restart a ceiling that's in-stasis // //================================================================== void P_ActivateInStasisCeiling(line_t * line) { int i; for (i = 0; i < MAXCEILINGS; i++) if (activeceilings[i] && (activeceilings[i]->tag == line->arg1) && (activeceilings[i]->direction == 0)) { activeceilings[i]->direction = activeceilings[i]->olddirection; activeceilings[i]->thinker.function = T_MoveCeiling; SN_StartSequence((mobj_t *) & activeceilings[i]->sector->soundorg, SEQ_PLATFORM + activeceilings[i]->sector->seqType); } } #endif //================================================================== // // EV_CeilingCrushStop // Stop a ceiling from crushing! // //================================================================== int EV_CeilingCrushStop(line_t * line, byte * args) { int i; int rtn; rtn = 0; for (i = 0; i < MAXCEILINGS; i++) { if (activeceilings[i] && activeceilings[i]->tag == args[0]) { rtn = 1; SN_StopSequence((mobj_t *) & activeceilings[i]->sector->soundorg); activeceilings[i]->sector->specialdata = NULL; P_RemoveThinker(&activeceilings[i]->thinker); P_TagFinished(activeceilings[i]->sector->tag); activeceilings[i] = NULL; break; } } return rtn; }