//************************************************************************** //** //** ## ## ## ## ## #### #### ### ### //** ## ## ## ## ## ## ## ## ## ## #### #### //** ## ## ## ## ## ## ## ## ## ## ## ## ## ## //** ## ## ######## ## ## ## ## ## ## ## ### ## //** ### ## ## ### ## ## ## ## ## ## //** # ## ## # #### #### ## ## //** //** $Id$ //** //** Copyright (C) 1999-2006 Jānis Legzdiņš //** //** 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. //** //************************************************************************** class CeilingMover : SectorMover; enum { CEILEV_LowerToFloor, CEILEV_LowerToHighestFloor, CEILEV_LowerToLowest, CEILEV_RaiseToHighest, CEILEV_RaiseToNearest, CEILEV_LowerByValue, CEILEV_RaiseByValue, CEILEV_LowerByValueTimes8, CEILEV_RaiseByValueTimes8, CEILEV_LowerTimes8Instant, CEILEV_RaiseTimes8Instant, CEILEV_MoveToValueTimes8, CEILEV_LowerAndCrush, CEILEV_CrushAndRaise, CEILEV_CrushRaiseAndStay, CEILEV_CrushAndRaiseA, CEILEV_CrushAndRaiseSilA, CEILEV_CrushRaiseAndStayA, CEILEV_CrushRaiseAndStaySilA, CEILEV_Generic, CEILEV_GenericChange0, CEILEV_GenericChangeT, CEILEV_GenericChange, CEILEV_GenericCrush }; int Type; float BottomDist; float TopDist; float Speed; int Crush; int Direction; // 1 = up, 0 = waiting, -1 = down int Tag; int OldDirection; float DnSpeed; float UpSpeed; int Texture; int NewSpecial; bool bStopOnCrush; name SeqName; //========================================================================== // // Init // //========================================================================== void Init(sector_t* InSector, int Arg1, int Arg2, int Arg3, int Arg4, int Arg5, int InType, line_t* Line) { float DestHeight; TVec Spot; sector_t* ModelSec; Sector = InSector; Sector->CeilingData = self; Type = InType; Tag = Sector->tag; Crush = false; Speed = itof(Arg2) * 35.0 / 8.0; Spot = *Sector->lines[0]->v1; SeqName = 'CeilingNormal'; switch (Type) { case CEILEV_LowerToFloor: DestHeight = Level.FindHighestFloorPoint(Sector, &Spot); Spot.z = DestHeight; BottomDist = DotProduct(Sector->ceiling.normal, Spot); Direction = -1; break; case CEILEV_LowerToHighestFloor: DestHeight = Level.FindHighestFloorSurrounding(Sector, &Spot); Spot.z = DestHeight; BottomDist = DotProduct(Sector->ceiling.normal, Spot); Direction = -1; break; case CEILEV_LowerToLowest: DestHeight = Level.FindLowestCeilingSurrounding(Sector, &Spot); Spot.z = DestHeight; BottomDist = DotProduct(Sector->ceiling.normal, Spot); Direction = -1; break; case CEILEV_RaiseToHighest: DestHeight = Level.FindHighestCeilingSurrounding(Sector, &Spot); Spot.z = DestHeight; TopDist = DotProduct(Sector->ceiling.normal, Spot); Direction = 1; break; case CEILEV_RaiseToNearest: DestHeight = Level.FindNextHighestCeiling(Sector, &Spot); Spot.z = DestHeight; TopDist = DotProduct(Sector->ceiling.normal, Spot); Direction = 1; break; case CEILEV_LowerByValue: DestHeight = GetPlanePointZ(&Sector->ceiling, Spot) - itof(Arg3); Spot.z = DestHeight; BottomDist = DotProduct(Sector->ceiling.normal, Spot); Direction = -1; break; case CEILEV_RaiseByValue: DestHeight = GetPlanePointZ(&Sector->ceiling, Spot) + itof(Arg3); Spot.z = DestHeight; TopDist = DotProduct(Sector->ceiling.normal, Spot); Direction = 1; break; case CEILEV_LowerByValueTimes8: DestHeight = GetPlanePointZ(&Sector->ceiling, Spot) - itof(Arg3) * 8.0; Spot.z = DestHeight; BottomDist = DotProduct(Sector->ceiling.normal, Spot); Direction = -1; break; case CEILEV_RaiseByValueTimes8: DestHeight = GetPlanePointZ(&Sector->ceiling, Spot) + itof(Arg3) * 8.0; Spot.z = DestHeight; TopDist = DotProduct(Sector->ceiling.normal, Spot); Direction = 1; break; case CEILEV_LowerTimes8Instant: DestHeight = GetPlanePointZ(&Sector->ceiling, Spot) - itof(Arg3) * 8.0; Spot.z = DestHeight; BottomDist = DotProduct(Sector->ceiling.normal, Spot); Direction = -1; Speed = 35.0 * 2000.0; break; case CEILEV_RaiseTimes8Instant: DestHeight = GetPlanePointZ(&Sector->ceiling, Spot) + itof(Arg3) * 8.0; Spot.z = DestHeight; TopDist = DotProduct(Sector->ceiling.normal, Spot); Direction = 1; Speed = 35.0 * 2000.0; break; case CEILEV_MoveToValueTimes8: DestHeight = itof(Arg3) * 8.0; if (Arg4) { DestHeight = -DestHeight; } Spot.z = DestHeight; if (GetPlanePointZ(&Sector->ceiling, Spot) <= DestHeight) { Direction = 1; TopDist = DotProduct(Sector->ceiling.normal, Spot); } else { Direction = -1; BottomDist = DotProduct(Sector->ceiling.normal, Spot); } break; case CEILEV_LowerAndCrush: Crush = Arg3; // args[2] = crushing value DestHeight = Level.FindHighestFloorPoint(Sector, &Spot); Spot.z = DestHeight + 8.0; BottomDist = DotProduct(Sector->ceiling.normal, Spot); Direction = -1; bStopOnCrush = true; break; case CEILEV_CrushAndRaise: case CEILEV_CrushRaiseAndStay: Crush = Arg3; // args[2] = crushing value TopDist = Sector->ceiling.dist; DestHeight = Level.FindHighestFloorPoint(Sector, &Spot); Spot.z = DestHeight + 8.0; BottomDist = DotProduct(Sector->ceiling.normal, Spot); Direction = -1; bStopOnCrush = true; break; case CEILEV_CrushAndRaiseSilA: case CEILEV_CrushRaiseAndStaySilA: SeqName = 'CeilingSemiSilent'; case CEILEV_CrushAndRaiseA: case CEILEV_CrushRaiseAndStayA: Crush = Arg4; // args[3] = crushing value TopDist = Sector->ceiling.dist; DestHeight = Level.FindHighestFloorPoint(Sector, &Spot); Spot.z = DestHeight + 8.0; BottomDist = DotProduct(Sector->ceiling.normal, Spot); Direction = -1; DnSpeed = itof(Arg2) * 35.0 / 8.0; UpSpeed = itof(Arg3) * 35.0 / 8.0; break; case CEILEV_Generic: Crush = (Arg5 & 16) ? 20 : 0; Direction = (Arg5 & 8) ? 1 : -1; // Target heights. switch (Arg4) { case 1: DestHeight = Level.FindHighestCeilingSurrounding(Sector, &Spot); break; case 2: DestHeight = Level.FindLowestCeilingSurrounding(Sector, &Spot); break; case 3: if (Arg5 & 8) DestHeight = Level.FindNextHighestCeiling(Sector, &Spot); else DestHeight = Level.FindNextLowestCeiling(Sector, &Spot); break; case 4: DestHeight = Level.FindHighestFloorSurrounding(Sector, &Spot); break; case 5: DestHeight = Level.FindHighestFloorPoint(Sector, &Spot); break; case 6: DestHeight = GetPlanePointZ(&Sector->ceiling, Spot) + itof(Direction) * Level.FindShortestUpperAround(Sector); break; default: DestHeight = GetPlanePointZ(&Sector->ceiling, Spot) + itof(Direction * Arg3); break; } Spot.z = DestHeight; if (Direction == 1) TopDist = DotProduct(Sector->ceiling.normal, Spot); else BottomDist = DotProduct(Sector->ceiling.normal, Spot); // set texture/type change properties if (Arg5 & 3) // if a texture change is indicated { if (Arg5 & 4) // if a numeric model change { //jff 5/23/98 find model with floor at target height if target //is a floor type ModelSec = (Arg4 == 4 || Arg4 == 5) ? Level.FindModelFloorSector(Sector, DestHeight) : Level.FindModelCeilingSector(Sector, DestHeight); if (ModelSec) { Texture = ModelSec->ceiling.pic; switch (Arg5 & 3) { case 1: // type is zeroed NewSpecial = 0; Type = CEILEV_GenericChange0; break; case 2: // type is copied NewSpecial = Sector->special; Type = CEILEV_GenericChangeT; break; case 3: // type is left alone Type = CEILEV_GenericChange; break; } } } else if (Line) // else if a trigger model change { Texture = Line->frontsector->ceiling.pic; switch (Arg5 & 3) { case 1: // type is zeroed NewSpecial = 0; Type = CEILEV_GenericChange0; break; case 2: // type is copied NewSpecial = Line->frontsector->special; Type = CEILEV_GenericChangeT; break; case 3: // type is left alone Type = CEILEV_GenericChange; break; } } } break; case CEILEV_GenericCrush: Type = Arg4 ? CEILEV_CrushAndRaiseSilA : CEILEV_CrushAndRaiseA; Crush = Arg5; // args[4] = crushing value TopDist = Sector->ceiling.dist; DestHeight = Level.FindHighestFloorPoint(Sector, &Spot); Spot.z = DestHeight + 8.0; BottomDist = DotProduct(Sector->ceiling.normal, Spot); Direction = -1; DnSpeed = itof(Arg2) * 35.0 / 8.0; UpSpeed = itof(Arg3) * 35.0 / 8.0; if (Arg4) SeqName = 'CeilingSemiSilent'; break; } StartCeilingSound(); } //========================================================================== // // CrushStop // // Stop a ceiling from crushing! // //========================================================================== bool CrushStop(int InTag) { if (Tag == InTag && Direction != 0) { // Only types that will be resumed go into stasis. if (Type == CEILEV_CrushAndRaiseA || Type == CEILEV_CrushAndRaiseSilA) { OldDirection = Direction; Direction = 0; // in-stasis } else { SectorStopSequence(Sector); Finished(); } return true; } return false; } //========================================================================== // // ActivateInStasis // // Restart a ceiling that's in-stasis // //========================================================================== void ActivateInStasis(int InTag) { if (Tag == InTag && Direction == 0) { Direction = OldDirection; } } //========================================================================== // // Tick // //========================================================================== void Tick(float deltaTime) { int res; switch (Direction) { case 0: // IN STASIS break; case 1: // UP res = MovePlane(Sector, Speed * deltaTime, TopDist, false, 1, Direction, bStopOnCrush); if (res == RES_PASTDEST) { SectorStopSequence(Sector); switch (Type) { case CEILEV_CrushAndRaise: Direction = -1; Speed = Speed * 2.0; StartCeilingSound(); break; case CEILEV_CrushAndRaiseSilA: case CEILEV_CrushAndRaiseA: Direction = -1; Speed = DnSpeed; StartCeilingSound(); break; // movers with texture change, change the texture then get removed case CEILEV_GenericChangeT: case CEILEV_GenericChange0: Sector->special = NewSpecial; case CEILEV_GenericChange: Sector->ceiling.pic = Texture; default: Finished(); break; } } break; case -1: // DOWN res = MovePlane(Sector, Speed * deltaTime, BottomDist, Crush, 1, Direction, bStopOnCrush); if (res == RES_PASTDEST) { SectorStopSequence(Sector); switch (Type) { case CEILEV_CrushAndRaise: case CEILEV_CrushRaiseAndStay: Speed = Speed / 2.0; Direction = 1; StartCeilingSound(); break; case CEILEV_CrushAndRaiseSilA: case CEILEV_CrushRaiseAndStaySilA: case CEILEV_CrushAndRaiseA: case CEILEV_CrushRaiseAndStayA: Speed = UpSpeed; Direction = 1; StartCeilingSound(); break; // in the case of ceiling mover/changer, change the texture // then remove the active ceiling case CEILEV_GenericChangeT: case CEILEV_GenericChange0: Sector->special = NewSpecial; case CEILEV_GenericChange: Sector->ceiling.pic = Texture; default: Finished(); break; } } else if (res == RES_CRUSHED) { switch (Type) { case CEILEV_LowerAndCrush: case CEILEV_CrushAndRaiseA: case CEILEV_CrushAndRaiseSilA: case CEILEV_CrushRaiseAndStayA: case CEILEV_CrushRaiseAndStaySilA: if (DnSpeed == 35.0 && UpSpeed == 35.0) Speed = 35.0 / 8.0; break; } } break; } } //========================================================================== // // StartCeilingSound // //========================================================================== void StartCeilingSound() { if (Sector->seqType >= 0) { SectorStartSequence(Sector, GetSeqTrans(Sector->seqType, SEQ_Platform), 0); } else { SectorStartSequence(Sector, SeqName, 0); } } defaultproperties { }