// ======================================== // StaticElevator // // An elevator that teleports the player instead of relying on movers // Its behaviour depends on which type of button is used to trigger it // ======================================== class StaticElevator extends Keypoint; var() int FloorNum; // The floor number for this elevator var() name ShaftName; // The common shaft name, must be identical with other relevant elevators var() name OuterDoorTag; // The mover tag for the outer doors in this shaft var() name InnerDoorTag; // The mover tag for the inner doors in this elevator var() float TransitionTime; // The time it takes to travel between each floor // BEGIN UE1 var StaticElevator aTargetElevator; var float CurrentTransitionTime; var bool bBusy; // -------------------------------------------------- // Sets the busy flag for all elevators in this shaft // -------------------------------------------------- function SetBusy(bool bNewBusy) { local StaticElevator aElevator; foreach AllActors(class'StaticElevator', aElevator) { if(aElevator.ShaftName != ShaftName) continue; aElevator.bBusy = bNewBusy; } } // ------------------------------------------ // Trigger derives behaviour from button type // ------------------------------------------ function Trigger(Actor aOther, Pawn aInstigator) { local Button1 aButton; aButton = Button1(aOther); // We only work with buttons, and while we're not busy if(aButton == None || bBusy) return; switch(aButton.ButtonType) { case BT_Up: GoToFloor(FloorNum + 1); break; case BT_Down: GoToFloor(FloorNum - 1); break; case BT_Blank: ToggleDoors(); break; case BT_1: GoToFloor(1); break; case BT_2: GoToFloor(2); break; case BT_3: GoToFloor(3); break; case BT_4: GoToFloor(4); break; case BT_5: GoToFloor(5); break; case BT_6: GoToFloor(6); break; case BT_7: GoToFloor(7); break; case BT_8: GoToFloor(8); break; case BT_9: GoToFloor(9); break; } } // ------------------------------------ // Sends the player to a specific floor // ------------------------------------ function GoToFloor(int Num) { local StaticElevator aElevator; local int MinFloor, MaxFloor; MinFloor = 1000; // First establish the numerical bounds of the floors in the shaft foreach AllActors(class'StaticElevator', aElevator) { if(aElevator.ShaftName != ShaftName) continue; MinFloor = Min(aElevator.FloorNum, MinFloor); MaxFloor = Max(aElevator.FloorNum, MaxFloor); } // Then make sure we're within range Num = Clamp(Num, MinFloor, MaxFloor); // Then make sure we're not already there if(Num == FloorNum) return; // Then calculate the time it will take to get there CurrentTransitionTime = Abs(Num - FloorNum) * TransitionTime; // Then find the target elevator in the same shaft foreach AllActors(class'StaticElevator', aElevator) { if(aElevator.ShaftName == ShaftName && aElevator.FloorNum == Num) { aTargetElevator = aElevator; break; } } if(aTargetElevator == None) return; // Then start the transition GoToState('ElevatorMoving'); } // --------------------------------- // Opens the doors (only this floor) // --------------------------------- function OpenDoors() { local Mover aDoor; if(InnerDoorTag != '') { foreach AllActors(class'Mover', aDoor, InnerDoorTag) { if(!aDoor.bOpening || aDoor.KeyNum == 0) { aDoor.DoOpen(); } } } if(OuterDoorTag != '') { foreach AllActors(class'Mover', aDoor, OuterDoorTag) { if(!aDoor.bOpening || aDoor.KeyNum == 0) { aDoor.DoOpen(); } } } } // ----------------------------- // Closes the doors (all floors) // ----------------------------- function CloseDoors() { local Mover aDoor; local StaticElevator aElevator; foreach AllActors(class'StaticElevator', aElevator) { if(aElevator.ShaftName != ShaftName) continue; if(aElevator.InnerDoorTag != '') { foreach AllActors(class'Mover', aDoor, aElevator.InnerDoorTag) { if(aDoor.bOpening || aDoor.KeyNum > 0) { aDoor.DoClose(); } } } if(aElevator.OuterDoorTag != '') { foreach AllActors(class'Mover', aDoor, aElevator.OuterDoorTag) { if(aDoor.bOpening || aDoor.KeyNum > 0) { aDoor.DoClose(); } } } } } // ------------------- // Gets the door delay // ------------------- function float GetDoorDelay() { local Mover aDoor; local float Delay; if(InnerDoorTag != '') { foreach AllActors(class'Mover', aDoor, InnerDoorTag) { Delay = FMax(Delay, aDoor.MoveTime); } } if(OuterDoorTag != '') { foreach AllActors(class'Mover', aDoor, OuterDoorTag) { Delay = FMax(Delay, aDoor.MoveTime); } } return Delay; } // ------------------------------- // Gets whether the doors are open // ------------------------------- function bool AreDoorsOpen() { local Mover aDoor; if(InnerDoorTag != '') { foreach AllActors(class'Mover', aDoor, InnerDoorTag) { return aDoor.bOpening || aDoor.KeyNum > 0; } } if(OuterDoorTag != '') { foreach AllActors(class'Mover', aDoor, OuterDoorTag) { return aDoor.bOpening || aDoor.KeyNum > 0; } } return False; } // ----------------------------- // Toggles the doors open/closed // ----------------------------- function ToggleDoors() { if(AreDoorsOpen()) CloseDoors(); else OpenDoors(); } // -------------------------------------------------------------------- // Teleports the actors inside the elevator to their target destination // -------------------------------------------------------------------- function TeleportActors() { local Actor aActor; if(aTargetElevator == None) return; // NOTE: I wanted to use TouchingActors here, but it didn't work foreach AllActors(class'Actor', aActor) { if(!aActor.bMovable || aActor.bStatic || aActor.bHidden || !IsOverlapping(aActor) || aActor.IsA('StaticElevator')) continue; aActor.SetLocation(aTargetElevator.Location + (aActor.Location - Location)); } } auto state ElevatorWaiting { } state ElevatorMoving { Begin: SetBusy(True); if(AreDoorsOpen()) { CloseDoors(); Sleep(GetDoorDelay()); } TeleportActors(); aTargetElevator.PlaySound(Sound'Elevator2Start'); Sleep(1.8); aTargetElevator.AmbientSound = Sound'Elevator2Move'; Sleep(CurrentTransitionTime); aTargetElevator.AmbientSound = None; aTargetElevator.PlaySound(Sound'Elevator2Stop'); Sleep(1.0); aTargetElevator.OpenDoors(); Sleep(GetDoorDelay()); Sleep(4.0); if(aTargetElevator.AreDoorsOpen()) aTargetElevator.CloseDoors(); SetBusy(False); GoToState('ElevatorWaiting'); } // END UE1 defaultproperties { bStatic=False TransitionTime=2.0 SoundVolume=128 }