// // CL_ResetSectors // void CL_ResetSectors (void) { for(size_t i = 0; i < real_plats.size(); i++) { plat_pred_t *pred = &real_plats[i]; sector_t *sec = §ors[pred->secnum]; if(!sec->floordata) { if(real_plats.erase(real_plats.begin() + i) == real_plats.end()) break; continue; } if(sec->floordata->IsKindOf(RUNTIME_CLASS(DPlat))) { DPlat *plat = (DPlat *)sec->floordata; sec->floorheight = pred->floorheight; plat->SetState(pred->state, pred->count); } else if(sec->floordata && sec->floordata->IsKindOf(RUNTIME_CLASS(DMovingFloor))) { sec->floorheight = pred->floorheight; } } }
void EV_StopPlat (int tag) { DPlat *scan; TThinkerIterator<DPlat> iterator; while ( (scan = iterator.Next ()) ) { if (scan->m_Status != DPlat::in_stasis && scan->m_Tag == tag) scan->Stop (); } }
void P_ActivateInStasis (int tag) { DPlat *scan; TThinkerIterator<DPlat> iterator; while ( (scan = iterator.Next ()) ) { if (scan->m_Tag == tag && scan->m_Status == DPlat::in_stasis) scan->Reactivate (); } }
void FLevelLocals::ActivateInStasisPlat (int tag) { DPlat *scan; auto iterator = GetThinkerIterator<DPlat>(); while ( (scan = iterator.Next ()) ) { if (scan->m_Tag == tag && scan->m_Status == DPlat::in_stasis) scan->Reactivate (); } }
void FLevelLocals::EV_StopPlat (int tag, bool remove) { DPlat *scan; auto iterator = GetThinkerIterator<DPlat>(); scan = iterator.Next(); while (scan != nullptr) { DPlat *next = iterator.Next(); if (scan->m_Status != DPlat::in_stasis && scan->m_Tag == tag) { if (!remove) scan->Stop(); else scan->Destroy(); } scan = next; } }
// // Do Platforms // [RH] Changed amount to height and added delay, // lip, change, tag, and speed parameters. // BOOL EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, int height, int speed, int delay, int lip, int change) { DPlat *plat; int secnum; sector_t *sec; int rtn = false; BOOL manual = false; // [RH] If tag is zero, use the sector on the back side // of the activating line (if any). if (!tag) { if (!line || !(sec = line->backsector)) return false; secnum = sec - sectors; manual = true; goto manual_plat; } // Activate all <type> plats that are in_stasis switch (type) { case DPlat::platToggle: rtn = true; case DPlat::platPerpetualRaise: P_ActivateInStasis (tag); break; default: break; } secnum = -1; while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0) { sec = §ors[secnum]; manual_plat: if (sec->floordata) continue; // Find lowest & highest floors around sector rtn = true; plat = new DPlat (sec); plat->m_Type = type; plat->m_Crush = false; plat->m_Tag = tag; plat->m_Speed = speed; plat->m_Wait = delay; //jff 1/26/98 Avoid raise plat bouncing a head off a ceiling and then //going down forever -- default lower to plat height when triggered plat->m_Low = sec->floorheight; if (change) { if (line) sec->floorpic = sides[line->sidenum[0]].sector->floorpic; if (change == 1) sec->special = 0; // Stop damage and other stuff, if any } switch (type) { case DPlat::platRaiseAndStay: plat->m_High = P_FindNextHighestFloor (sec, sec->floorheight); plat->m_Status = DPlat::midup; plat->PlayPlatSound(); break; case DPlat::platUpByValue: case DPlat::platUpByValueStay: plat->m_High = sec->floorheight + height; plat->m_Status = DPlat::midup; plat->PlayPlatSound(); break; case DPlat::platDownByValue: plat->m_Low = sec->floorheight - height; plat->m_Status = DPlat::middown; plat->PlayPlatSound(); break; case DPlat::platDownWaitUpStay: plat->m_Low = P_FindLowestFloorSurrounding (sec) + lip*FRACUNIT; if (plat->m_Low > sec->floorheight) plat->m_Low = sec->floorheight; plat->m_High = sec->floorheight; plat->m_Status = DPlat::down; plat->PlayPlatSound(); break; case DPlat::platUpWaitDownStay: plat->m_High = P_FindHighestFloorSurrounding (sec); if (plat->m_High < sec->floorheight) plat->m_High = sec->floorheight; plat->m_Status = DPlat::up; plat->PlayPlatSound(); break; case DPlat::platPerpetualRaise: plat->m_Low = P_FindLowestFloorSurrounding (sec) + lip*FRACUNIT; if (plat->m_Low > sec->floorheight) plat->m_Low = sec->floorheight; plat->m_High = P_FindHighestFloorSurrounding (sec); if (plat->m_High < sec->floorheight) plat->m_High = sec->floorheight; plat->m_Status = P_Random () & 1 ? DPlat::down : DPlat::up; plat->PlayPlatSound(); break; case DPlat::platToggle: //jff 3/14/98 add new type to support instant toggle plat->m_Crush = false; //jff 3/14/98 crush anything in the way // set up toggling between ceiling, floor inclusive plat->m_Low = sec->ceilingheight; plat->m_High = sec->floorheight; plat->m_Status = DPlat::down; // SN_StartSequence (sec, "Silence"); break; case DPlat::platDownToNearestFloor: plat->m_Low = P_FindNextLowestFloor (sec, sec->floorheight) + lip*FRACUNIT; plat->m_Status = DPlat::down; plat->m_High = sec->floorheight; plat->PlayPlatSound(); break; case DPlat::platDownToLowestCeiling: plat->m_Low = P_FindLowestCeilingSurrounding (sec); plat->m_High = sec->floorheight; if (plat->m_Low > sec->floorheight) plat->m_Low = sec->floorheight; plat->m_Status = DPlat::down; plat->PlayPlatSound(); break; default: break; } if (manual) return rtn; } return rtn; }
bool FLevelLocals::EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, double height, double speed, int delay, int lip, int change) { DPlat *plat; int secnum; sector_t *sec; bool rtn = false; bool manual = false; double newheight = 0; vertex_t *spot; if (tag != 0) { // Activate all <type> plats that are in_stasis switch (type) { case DPlat::platToggle: rtn = true; case DPlat::platPerpetualRaise: ActivateInStasisPlat (tag); break; default: break; } } // [RH] If tag is zero, use the sector on the back side // of the activating line (if any). auto itr = GetSectorTagIterator(tag, line); while ((secnum = itr.Next()) >= 0) { sec = §ors[secnum]; if (sec->PlaneMoving(sector_t::floor)) { continue; } // Find lowest & highest floors around sector rtn = true; plat = CreateThinker<DPlat> (sec); plat->m_Type = type; plat->m_Crush = -1; plat->m_Tag = tag; plat->m_Speed = speed; plat->m_Wait = delay; //jff 1/26/98 Avoid raise plat bouncing a head off a ceiling and then //going down forever -- default lower to plat height when triggered plat->m_Low = sec->floorplane.fD(); if (change) { if (line) sec->SetTexture(sector_t::floor, line->sidedef[0]->sector->GetTexture(sector_t::floor)); if (change == 1) sec->ClearSpecial(); } switch (type) { case DPlat::platRaiseAndStay: case DPlat::platRaiseAndStayLockout: newheight = FindNextHighestFloor (sec, &spot); plat->m_High = sec->floorplane.PointToDist (spot, newheight); plat->m_Low = sec->floorplane.fD(); plat->m_Status = DPlat::up; plat->PlayPlatSound ("Floor"); sec->ClearSpecial(); break; case DPlat::platUpByValue: case DPlat::platUpByValueStay: newheight = sec->floorplane.ZatPoint (sec->centerspot) + height; plat->m_High = sec->floorplane.PointToDist (sec->centerspot, newheight); plat->m_Low = sec->floorplane.fD(); plat->m_Status = DPlat::up; plat->PlayPlatSound ("Floor"); break; case DPlat::platDownByValue: newheight = sec->floorplane.ZatPoint (sec->centerspot) - height; plat->m_Low = sec->floorplane.PointToDist (sec->centerspot, newheight); plat->m_High = sec->floorplane.fD(); plat->m_Status = DPlat::down; plat->PlayPlatSound ("Floor"); break; case DPlat::platDownWaitUpStay: case DPlat::platDownWaitUpStayStone: newheight = FindLowestFloorSurrounding (sec, &spot) + lip; plat->m_Low = sec->floorplane.PointToDist (spot, newheight); if (plat->m_Low < sec->floorplane.fD()) plat->m_Low = sec->floorplane.fD(); plat->m_High = sec->floorplane.fD(); plat->m_Status = DPlat::down; plat->PlayPlatSound (type == DPlat::platDownWaitUpStay ? "Platform" : "Floor"); break; case DPlat::platUpNearestWaitDownStay: newheight = FindNextHighestFloor (sec, &spot); // Intentional fall-through case DPlat::platUpWaitDownStay: if (type == DPlat::platUpWaitDownStay) { newheight = FindHighestFloorSurrounding (sec, &spot); } plat->m_High = sec->floorplane.PointToDist (spot, newheight); plat->m_Low = sec->floorplane.fD(); if (plat->m_High > sec->floorplane.fD()) plat->m_High = sec->floorplane.fD(); plat->m_Status = DPlat::up; plat->PlayPlatSound ("Platform"); break; case DPlat::platPerpetualRaise: newheight = FindLowestFloorSurrounding (sec, &spot) + lip; plat->m_Low = sec->floorplane.PointToDist (spot, newheight); if (plat->m_Low < sec->floorplane.fD()) plat->m_Low = sec->floorplane.fD(); newheight = FindHighestFloorSurrounding (sec, &spot); plat->m_High = sec->floorplane.PointToDist (spot, newheight); if (plat->m_High > sec->floorplane.fD()) plat->m_High = sec->floorplane.fD(); plat->m_Status = pr_doplat() & 1 ? DPlat::up : DPlat::down; plat->PlayPlatSound ("Platform"); break; case DPlat::platToggle: //jff 3/14/98 add new type to support instant toggle plat->m_Crush = 10; //jff 3/14/98 crush anything in the way // set up toggling between ceiling, floor inclusive newheight = FindLowestCeilingPoint(sec, &spot); plat->m_Low = sec->floorplane.PointToDist (spot, newheight); plat->m_High = sec->floorplane.fD(); plat->m_Status = DPlat::down; SN_StartSequence (sec, CHAN_FLOOR, "Silence", 0); break; case DPlat::platDownToNearestFloor: newheight = FindNextLowestFloor (sec, &spot) + lip; plat->m_Low = sec->floorplane.PointToDist (spot, newheight); plat->m_Status = DPlat::down; plat->m_High = sec->floorplane.fD(); plat->PlayPlatSound ("Platform"); break; case DPlat::platDownToLowestCeiling: newheight = FindLowestCeilingSurrounding (sec, &spot); plat->m_Low = sec->floorplane.PointToDist (spot, newheight); plat->m_High = sec->floorplane.fD(); if (plat->m_Low < sec->floorplane.fD()) plat->m_Low = sec->floorplane.fD(); plat->m_Status = DPlat::down; plat->PlayPlatSound ("Platform"); break; default: break; } } return rtn; }
BOOL EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing, int tag, int speed, int delay, card_t lock) { BOOL rtn = false; int secnum; sector_t* sec; DDoor *door; if (lock && thing && !P_CheckKeys (thing->player, lock, tag)) return false; if (tag == 0) { // [RH] manual door if (!line) return false; // if the wrong side of door is pushed, give oof sound if (line->sidenum[1]==-1) // killough { UV_SoundAvoidPlayer (thing, CHAN_VOICE, "player/male/grunt1", ATTN_NORM); return false; } // get the sector on the second side of activating linedef sec = sides[line->sidenum[1]].sector; secnum = sec-sectors; // if door already has a thinker, use it if (sec->ceilingdata && sec->ceilingdata->IsKindOf (RUNTIME_CLASS(DDoor))) { door = static_cast<DDoor *>(sec->ceilingdata); door->m_Line = line; // ONLY FOR "RAISE" DOORS, NOT "OPEN"s if (door->m_Type == DDoor::doorRaise && type == DDoor::doorRaise) { if (door->m_Direction == -1) { door->m_Direction = 1; // go back up } else if (GET_SPAC(line->flags) != SPAC_PUSH) // [RH] activate push doors don't go back down when you // run into them (otherwise opening them would be // a real pain). { if (thing && !thing->player) return false; // JDC: bad guys never close doors // From Chocolate Doom: // When is a door not a door? // In Vanilla, door->direction is set, even though // "specialdata" might not actually point at a door. else if (sec->floordata && sec->floordata->IsKindOf (RUNTIME_CLASS(DPlat))) { // Erm, this is a plat, not a door. // This notably causes a problem in ep1-0500.lmp where // a plat and a door are cross-referenced; the door // doesn't open on 64-bit. // The direction field in vldoor_t corresponds to the wait // field in plat_t. Let's set that to -1 instead. DPlat *plat = static_cast<DPlat *>(sec->floordata); byte state; int count; plat->GetState(state, count); if (count >= 16) // ep1-0500 always returns a count of 16. return false; // We may be able to always return false? } else { door->m_Direction = -1; // try going back down anyway? } } return true; } } else { door = new DDoor(sec, line, type, speed, delay); } if (door) { rtn = true; } } else { // [RH] Remote door secnum = -1; while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0) { sec = §ors[secnum]; // if the ceiling already moving, don't start the door action if (sec->ceilingdata) continue; if (new DDoor (sec, line, type, speed, delay)) rtn = true; } } return rtn; }