// // P_RemoveActiveCeiling() // // Removes a ceiling from the list of active ceilings // // Passed the ceiling motion structure // Returns nothing // void P_RemoveActiveCeiling(CeilingThinker* ceiling) { // ioanch 20160306 if(demo_compatibility || P_LevelIsVanillaHexen()) { for(int i = 0; i < vanilla_MAXCEILINGS; ++i) { if(vanilla_activeceilings[i] == ceiling) { ceiling->sector->ceilingdata = nullptr; S_StopSectorSequence(ceiling->sector, SEQ_ORIGIN_SECTOR_C); ceiling->removeThinker(); vanilla_activeceilings[i] = nullptr; break; } } return; } // ioanch: normal setup ceilinglist_t *list = ceiling->list; ceiling->sector->ceilingdata = NULL; //jff 2/22/98 S_StopSectorSequence(ceiling->sector, SEQ_ORIGIN_SECTOR_C); // haleyjd 09/28/06 ceiling->removeThinker(); if((*list->prev = list->next)) list->next->prev = list->prev; efree(list); }
// // T_MoveCeiling // // Action routine that moves ceilings. Called once per tick. // // Passed a CeilingThinker structure that contains all the info about the move. // see P_SPEC.H for fields. No return value. // // jff 02/08/98 all cases with labels beginning with gen added to support // generalized line type behaviors. // void CeilingThinker::Think() { result_e res; if(inStasis) return; switch(direction) { case plat_stop: // If ceiling in stasis, do nothing break; case plat_up: // Ceiling is moving up res = T_MoveCeilingUp(sector, speed, topheight, -1); // if not a silent crusher, make moving sound // haleyjd: now handled through sound sequences // handle reaching destination height if(res == pastdest) { switch(type) { // plain movers are just removed case raiseToHighest: case genCeiling: case paramHexenCrushRaiseStay: // ioanch 20160306 case paramHexenLowerCrush: P_RemoveActiveCeiling(this); break; // movers with texture change, change the texture then get removed case genCeilingChgT: case genCeilingChg0: //jff 3/14/98 transfer old special field as well P_TransferSectorSpecial(sector, &special); case genCeilingChg: P_SetSectorCeilingPic(sector, texture); P_RemoveActiveCeiling(this); break; // crushers reverse direction at the top case silentCrushAndRaise: // haleyjd: if not playing a looping sequence, start one if(!S_CheckSectorSequenceLoop(sector, SEQ_ORIGIN_SECTOR_C)) P_CeilingSequence(sector, CNOISE_SEMISILENT); case genSilentCrusher: case genCrusher: // ioanch 20160314: Generic_Crusher support if(type != silentCrushAndRaise) speed = oldspeed; case fastCrushAndRaise: case crushAndRaise: direction = plat_down; break; // ioanch 20160305 case paramHexenCrush: // preserve the weird Hexen behaviour where the crusher becomes mute // after any pastdest. if(P_LevelIsVanillaHexen()) S_StopSectorSequence(sector, SEQ_ORIGIN_SECTOR_C); else if(crushflags & crushSilent && !S_CheckSectorSequenceLoop(sector, SEQ_ORIGIN_SECTOR_C)) { P_CeilingSequence(sector, CNOISE_SEMISILENT); } direction = plat_down; speed = oldspeed; // restore the speed to the designated DOWN one break; default: break; } } break; case plat_down: // Ceiling moving down // ioanch 20160305: allow resting res = T_MoveCeilingDown(sector, speed, bottomheight, crush, !!(crushflags & crushRest)); // if not silent crusher type make moving sound // haleyjd: now handled through sound sequences // handle reaching destination height if(res == pastdest) { switch(this->type) { // 02/09/98 jff change slow crushers' speed back to normal // start back up case genSilentCrusher: case genCrusher: if(oldspeed < CEILSPEED*3) speed = this->upspeed; // ioanch 20160314: use up speed direction = plat_up; //jff 2/22/98 make it go back up! break; // make platform stop at bottom of all crusher strokes // except generalized ones, reset speed, start back up case silentCrushAndRaise: // haleyjd: if not playing a looping sequence, start one if(!S_CheckSectorSequenceLoop(sector, SEQ_ORIGIN_SECTOR_C)) P_CeilingSequence(sector, CNOISE_SEMISILENT); case crushAndRaise: speed = CEILSPEED; case fastCrushAndRaise: direction = plat_up; break; // in the case of ceiling mover/changer, change the texture // then remove the active ceiling case genCeilingChgT: case genCeilingChg0: //jff add to fix bug in special transfers from changes P_TransferSectorSpecial(sector, &special); case genCeilingChg: P_SetSectorCeilingPic(sector, texture); P_RemoveActiveCeiling(this); break; // all other case, just remove the active ceiling case lowerAndCrush: case lowerToFloor: case lowerToLowest: case lowerToMaxFloor: case genCeiling: case paramHexenLowerCrush: P_RemoveActiveCeiling(this); break; // ioanch 20160305 case paramHexenCrush: case paramHexenCrushRaiseStay: // preserve the weird Hexen behaviour where the crusher becomes mute // after any pastdest (only in maps for vanilla Hexen). if(P_LevelIsVanillaHexen()) S_StopSectorSequence(sector, SEQ_ORIGIN_SECTOR_C); else if(crushflags & crushSilent && !S_CheckSectorSequenceLoop(sector, SEQ_ORIGIN_SECTOR_C)) { P_CeilingSequence(sector, CNOISE_SEMISILENT); } direction = plat_up; // keep old speed in case it was decreased by crushing like Doom. speed = upspeed; // set to the different up speed break; default: break; } } else // ( res != pastdest ) { // handle the crusher encountering an obstacle if(res == crushed) { switch(type) { //jff 02/08/98 slow down slow crushers on obstacle case genCrusher: case genSilentCrusher: if(oldspeed < CEILSPEED*3) speed = CEILSPEED / 8; break; case silentCrushAndRaise: case crushAndRaise: case lowerAndCrush: speed = CEILSPEED / 8; break; case paramHexenCrush: case paramHexenCrushRaiseStay: case paramHexenLowerCrush: // if crusher doesn't rest on victims: // this is like ZDoom: if a ceiling speed is set exactly to 8, // then apply the Doom crusher slowdown. Otherwise, keep speed // constant. This may not apply to all crushing specials in // ZDoom, but for simplicity it has been applied generally here. if(!(crushflags & crushRest) && (crushflags & crushParamSlow)) speed = CEILSPEED / 8; break; default: break; } } } // end else break; } // end switch }
// // EV_CeilingCrushStop() // // Stops all active ceilings with the right tag // // Passed the linedef stopping the ceilings // Returns true if a ceiling put in stasis // int EV_CeilingCrushStop(const line_t* line, int tag) { int rtn = 0; // ioanch 20160314: avoid duplicating code auto pauseceiling = [&rtn](CeilingThinker *ceiling) { ceiling->olddirection = ceiling->direction; ceiling->direction = plat_stop; ceiling->inStasis = true; // ioanch 20160314: like in vanilla, do not make click sound when stopping // these types if(ceiling->type == silentCrushAndRaise || ceiling->crushflags & CeilingThinker::crushSilent) { S_SquashSectorSequence(ceiling->sector, SEQ_ORIGIN_SECTOR_C); } else S_StopSectorSequence(ceiling->sector, SEQ_ORIGIN_SECTOR_C); // haleyjd 09/28/06 rtn = 1; }; // ioanch 20160306 bool vanillaHexen = P_LevelIsVanillaHexen(); if(demo_compatibility || vanillaHexen) { for(int i = 0; i < vanilla_MAXCEILINGS; ++i) { CeilingThinker *ceiling = vanilla_activeceilings[i]; if(vanillaHexen) { if(ceiling && ceiling->tag == tag) { // in Hexen, just kill the crusher thinker rtn = 1; P_RemoveActiveCeiling(ceiling); break; // get out after killing a single crusher } } else if(ceiling && ceiling->tag == tag && ceiling->direction != plat_stop) { pauseceiling(ceiling); } } return rtn; } // ioanch: normal setup ceilinglist_t *cl; for(cl = activeceilings; cl; cl = cl->next) { CeilingThinker *ceiling = cl->ceiling; if(ceiling->direction != plat_stop && ceiling->tag == tag) { pauseceiling(ceiling); } } // hack to emulate the Hexen return rtn; }
// // T_VerticalDoor // // Passed a door structure containing all info about the door. // See P_SPEC.H for fields. // Returns nothing. // // jff 02/08/98 all cases with labels beginning with gen added to support // generalized line type behaviors. // void VerticalDoorThinker::Think() { result_e res; // Is the door waiting, going up, or going down? switch(direction) { case plat_stop: // Door is waiting if(!--topcountdown) // downcount and check { switch(type) { case doorNormal: case paramCloseIn: // haleyjd 03/01/05 case blazeRaise: direction = plat_down; // time to go back down P_DoorSequence(false, turbo, false, sector); // haleyjd break; case closeThenOpen: direction = plat_up; // time to go back up P_DoorSequence(true, turbo, false, sector); // haleyjd break; default: break; } } break; case plat_special: // haleyjd: changed from 2 // Special case for sector type door that opens in 5 mins if(!--topcountdown) // 5 minutes up? { switch(type) { case doorRaiseIn: direction = plat_up; // time to raise then if(turbo) type = blazeRaise; // act like a blaze raise door else type = doorNormal; // door acts just like normal 1 DR door now P_DoorSequence(true, turbo, false, sector); // haleyjd break; default: break; } } break; case plat_down: // Door is moving down res = T_MoveCeilingDown(sector, speed, sector->floorheight, -1); // killough 10/98: implement gradual lighting effects if(lighttag && topheight - sector->floorheight) EV_LightTurnOnPartway(lighttag, FixedDiv(sector->ceilingheight - sector->floorheight, topheight - sector->floorheight)); // handle door reaching bottom if(res == pastdest) { S_StopSectorSequence(sector, SEQ_ORIGIN_SECTOR_C); switch(type) { // regular raise and close doors are all done, remove them case doorNormal: case doorClose: case blazeRaise: case blazeClose: case paramCloseIn: // haleyjd 03/01/05 sector->ceilingdata = NULL; //jff 2/22/98 this->remove(); // unlink and free // killough 4/15/98: remove double-closing sound of blazing doors // haleyjd 10/06/06: behavior is determined via sound sequence now break; // close then open doors start waiting case closeThenOpen: direction = plat_stop; topcountdown = topwait; // jff 5/8/98 insert delay break; default: break; } } //jff 1/31/98 turn lighting off in tagged sectors of manual doors // killough 10/98: replaced with gradual lighting code else if(res == crushed) { // handle door meeting obstruction on way down switch(type) { case paramCloseIn: // haleyjd 03/01/05 case blazeClose: case doorClose: // Close types do not bounce, merely wait break; default: // other types bounce off the obstruction direction = plat_up; P_DoorSequence(true, false, true, sector); // haleyjd break; } } break; case plat_up: // Door is moving up res = T_MoveCeilingUp(sector, speed, topheight, -1); // killough 10/98: implement gradual lighting effects if(lighttag && topheight - sector->floorheight) EV_LightTurnOnPartway(lighttag, FixedDiv(sector->ceilingheight - sector->floorheight, topheight - sector->floorheight)); // handle door reaching the top if(res == pastdest) { switch(type) { case blazeRaise: // regular open/close doors start waiting case doorNormal: direction = plat_stop; // wait at top with delay topcountdown = topwait; break; case closeThenOpen: // close and close/open doors are done case blazeOpen: case doorOpen: S_StopSectorSequence(sector, SEQ_ORIGIN_SECTOR_C); sector->ceilingdata = NULL; //jff 2/22/98 this->remove(); // unlink and free break; default: break; } } // SoM: With attached sectors, doors can now encounter crushed events while opening else if(demo_version >= 333 && res == crushed) { // handle door meeting obstruction on attached surface moving down switch(type) { case doorOpen: // Open types do not bounce, merely wait case blazeOpen: break; default: // other types bounce off the obstruction direction = plat_down; P_DoorSequence(false, false, true, sector); // haleyjd break; } } //jff 1/31/98 turn lighting on in tagged sectors of manual doors // killough 10/98: replaced with gradual lighting code break; } }