//************************************************************************** //** //** ## ## ## ## ## #### #### ### ### //** ## ## ## ## ## ## ## ## ## ## #### #### //** ## ## ## ## ## ## ## ## ## ## ## ## ## ## //** ## ## ######## ## ## ## ## ## ## ## ### ## //** ### ## ## ### ## ## ## ## ## ## //** # ## ## # #### #### ## ## //** //** $Id: Platform.vc 1744 2006-10-01 12:40:46Z dj_jl $ //** //** 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 Platform : SectorMover; enum { PLAT_Up, PLAT_Down, PLAT_Waiting, PLAT_InStasis }; enum { PLATEV_PerpetualRaise, PLATEV_PerpetualRaiseLip, PLATEV_DownWaitUpStay, PLATEV_DownWaitUpStayLip, PLATEV_DownNearestWaitUpStay, PLATEV_DownLowestCeilingWaitUpStay, PLATEV_DownByValueWaitUpStay, PLATEV_UpWaitDownStay, PLATEV_UpNearestWaitDownStay, PLATEV_UpByValueWaitDownStay, PLATEV_Toggle, PLATEV_Generic }; int Type; int Tag; float Speed; float Low; float High; float Time; float Wait; int Status; int OldStatus; int Crush; name StartSound; //========================================================================== // // Init // //========================================================================== void Init(sector_t* InSector, int Arg1, int Arg2, int Arg3, int Arg4, int Arg5, int InType) { float DestHeight; TVec Spot; Sector = InSector; Sector->FloorData = self; Type = InType; // Handle generic lifts here. if (Type == PLATEV_Generic) { switch (Arg4) { case 1: Type = PLATEV_DownWaitUpStayLip; Arg4 = 0; break; case 2: Type = PLATEV_DownNearestWaitUpStay; Arg4 = 0; break; case 3: Type = PLATEV_DownLowestCeilingWaitUpStay; Arg4 = 0; break; case 4: Type = PLATEV_PerpetualRaiseLip; Arg4 = 0; break; default: Type = PLATEV_UpByValueWaitDownStay; Arg4 = Arg5; break; } } Tag = Arg1; Speed = itof(Arg2) * 35.0 / 8.0; Crush = 0; StartSound = LineSpecialLevelInfo(Level).DefaultPlatformSound; switch (Type) { case PLATEV_PerpetualRaise: DestHeight = Level.FindLowestFloorSurrounding(Sector, &Spot); Spot.z = DestHeight + 8.0; Low = DotProduct(Sector->floor.normal, Spot); if (Low > Sector->floor.dist) Low = Sector->floor.dist; DestHeight = Level.FindHighestFloorSurrounding(Sector, &Spot); Spot.z = DestHeight; High = DotProduct(Sector->floor.normal, Spot); if (High < Sector->floor.dist) High = Sector->floor.dist; Wait = itof(Arg3) / 35.0; Status = P_Random() & 1; break; case PLATEV_PerpetualRaiseLip: DestHeight = Level.FindLowestFloorSurrounding(Sector, &Spot); Spot.z = DestHeight + itof(Arg4); Low = DotProduct(Sector->floor.normal, Spot); if (Low > Sector->floor.dist) Low = Sector->floor.dist; DestHeight = Level.FindHighestFloorSurrounding(Sector, &Spot); Spot.z = DestHeight; High = DotProduct(Sector->floor.normal, Spot); if (High < Sector->floor.dist) High = Sector->floor.dist; Wait = itof(Arg3) / 35.0; Status = P_Random() & 1; break; case PLATEV_DownWaitUpStay: DestHeight = Level.FindLowestFloorSurrounding(Sector, &Spot); Spot.z = DestHeight + 8.0; Low = DotProduct(Sector->floor.normal, Spot); if (Low > Sector->floor.dist) Low = Sector->floor.dist; High = Sector->floor.dist; Wait = itof(Arg3) / 35.0; Status = PLAT_Down; break; case PLATEV_DownWaitUpStayLip: DestHeight = Level.FindLowestFloorSurrounding(Sector, &Spot); Spot.z = DestHeight + itof(Arg4); Low = DotProduct(Sector->floor.normal, Spot); if (Low > Sector->floor.dist) Low = Sector->floor.dist; High = Sector->floor.dist; Wait = itof(Arg3) / 35.0; Status = PLAT_Down; if (Arg5) StartSound = LineSpecialLevelInfo(Level).DefaultFloorSound; break; case PLATEV_DownNearestWaitUpStay: DestHeight = Level.FindNextLowestFloor(Sector, &Spot); Spot.z = DestHeight + itof(Arg4); Low = DotProduct(Sector->floor.normal, Spot); High = Sector->floor.dist; Wait = itof(Arg3) / 35.0; Status = PLAT_Down; break; case PLATEV_DownLowestCeilingWaitUpStay: DestHeight = Level.FindLowestCeilingSurrounding(Sector, &Spot); Spot.z = DestHeight; Low = DotProduct(Sector->floor.normal, Spot); if (Low > Sector->floor.dist) Low = Sector->floor.dist; High = Sector->floor.dist; Wait = itof(Arg3) / 35.0; Status = PLAT_Down; break; case PLATEV_DownByValueWaitUpStay: Spot = *Sector->lines[0]->v1; Spot.z = GetPlanePointZ(&Sector->floor, Spot) - itof(Arg4) * 8.0; Low = DotProduct(Sector->floor.normal, Spot); if (Low > Sector->floor.dist) Low = Sector->floor.dist; High = Sector->floor.dist; Wait = itof(Arg3) / 35.0; Status = PLAT_Down; break; case PLATEV_UpWaitDownStay: DestHeight = Level.FindHighestFloorSurrounding(Sector, &Spot); Spot.z = DestHeight; High = DotProduct(Sector->floor.normal, Spot); if (High < Sector->floor.dist) High = Sector->floor.dist; Low = Sector->floor.dist; Wait = itof(Arg3) / 35.0; Status = PLAT_Up; break; case PLATEV_UpNearestWaitDownStay: DestHeight = Level.FindNextHighestFloor(Sector, &Spot); Spot.z = DestHeight; High = DotProduct(Sector->floor.normal, Spot); if (High < Sector->floor.dist) High = Sector->floor.dist; Low = Sector->floor.dist; Wait = itof(Arg3) / 35.0; Status = PLAT_Up; break; case PLATEV_UpByValueWaitDownStay: Spot = *Sector->lines[0]->v1; Spot.z = GetPlanePointZ(&Sector->floor, Spot) + itof(Arg4) * 8.0; High = DotProduct(Sector->floor.normal, Spot); if (High < Sector->floor.dist) High = Sector->floor.dist; Low = Sector->floor.dist; Wait = itof(Arg3) / 35.0; Status = PLAT_Up; break; case PLATEV_Toggle: //jff 3/14/98 add new type to support instant toggle Crush = 10; //jff 3/14/98 crush anything in the way // set up toggling between ceiling, floor inclusive DestHeight = Level.FindLowestCeilingPoint(Sector, &Spot); Spot.z = DestHeight; Low = DotProduct(Sector->floor.normal, Spot); High = Sector->floor.dist; Status = PLAT_Down; break; } if (Type != PLATEV_Toggle) StartPlatSound(); } //========================================================================== // // StopPlat // //========================================================================== bool StopPlat(int InTag) { if (Status != PLAT_InStasis && Tag == InTag) { OldStatus = Status; Status = PLAT_InStasis; SectorStopSequence(Sector); return true; } return false; } //========================================================================== // // ActivateInStasis // //========================================================================== void ActivateInStasis(int InTag) { if (Tag == InTag && Status == PLAT_InStasis) { if (Type == PLATEV_Toggle) //jff 3/14/98 reactivate toggle type Status = OldStatus == PLAT_Up ? PLAT_Down : PLAT_Up; else { Status = OldStatus; StartPlatSound(); } } } //========================================================================== // // Tick // // Move a plat up and down // //========================================================================== void Tick(float deltaTime) { int res; switch (Status) { case PLAT_Up: res = MovePlane(Sector, Speed * deltaTime, High, false, Crush, 1, false); if (res == RES_CRUSHED && Crush == 0) { Time = Wait; Status = PLAT_Down; StartPlatSound(); } else if (res == RES_PASTDEST) { if (Type == PLATEV_Toggle) { OldStatus = Status; //jff 3/14/98 after action wait Status = PLAT_InStasis; //for reactivation of toggle } else { Time = Wait; Status = PLAT_Waiting; SectorStopSequence(Sector); switch (Type) { case PLATEV_DownWaitUpStay: case PLATEV_DownWaitUpStayLip: case PLATEV_DownByValueWaitUpStay: case PLATEV_DownNearestWaitUpStay: case PLATEV_DownLowestCeilingWaitUpStay: Finished(); break; default: break; } } } break; case PLAT_Down: res = MovePlane(Sector, Speed * deltaTime, Low, false, Crush, -1, false); if (res == RES_PASTDEST) { if (Type == PLATEV_Toggle) { // instant toggles go into stasis awaiting next activation OldStatus = Status; //jff 3/14/98 after action wait Status = PLAT_InStasis; //for reactivation of toggle } else { Time = Wait; Status = PLAT_Waiting; SectorStopSequence(Sector); switch (Type) { case PLATEV_UpWaitDownStay: case PLATEV_UpNearestWaitDownStay: case PLATEV_UpByValueWaitDownStay: Finished(); break; default: break; } } } break; case PLAT_Waiting: Time -= deltaTime; if (Time <= 0.0) { Time = 0.0; if (Sector->floor.dist == Low) Status = PLAT_Up; else Status = PLAT_Down; StartPlatSound(); } break; case PLAT_InStasis: break; } } //========================================================================== // // StartPlatSound // //========================================================================== void StartPlatSound() { if (!StartSound || Sector->seqType >= 0) { SectorStartSequence(Sector, GetSeqTrans(Sector->seqType, SEQ_Platform), 0); } else { SectorStartSequence(Sector, StartSound, 0); } } defaultproperties { }