--!optimize 2 --!native --!strict local Elevators = script.Parent local MainDir = Elevators.Parent local LoadDir = MainDir:WaitForChild("Load") local RunService = game:GetService("RunService") local ElevatorTypes = require(MainDir:WaitForChild("Types"):WaitForChild("Elevator")) local Tags = require(LoadDir:WaitForChild("Tags")) local RelayAlgorithm = require(script:WaitForChild("RelayAlgorithm")) type Tags = Tags.ExportedTags type TagsConstructor = Tags.TagsConstructor type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor)) type Impl_Constructor = { __index: Impl_Constructor, constructor: Constructor_Fun, --Class functions RequestLevel: (self: ClassConstructor, RequestedLevel: number) -> boolean, __TravelToFloor: (self: ClassConstructor, LevelInt: number, LevelVec3: number, ElevatorGoingUp: boolean) -> (), } type FloorLevelingPositions = {number} type Constructor_Fun = (ElevatorBoxModel: UnionOperation, ElevatorConfigurationTable: ElevatorTypes.ElevatorConfigurationTable, FloorLevelingPositions: FloorLevelingPositions) -> ClassConstructor type Constructor_Return_Props = { RelayAlgorithm: RelayAlgorithm.RelayAlgorithmConstructor, FloorLevelingPositions: FloorLevelingPositions, Elevator: { BoxModel: UnionOperation, AlignPosition: AlignPosition, Configuration: ElevatorTypes.ElevatorConfigurationTable }, Attributes: { PreviousFloor: IntValue, CurrentFloor: IntValue, NextFloor: IntValue, Goal: IntValue, GoingUp: BoolValue, Stopped: BoolValue }, Events: { CabProgression: RBXScriptSignal, CabTraveling: RBXScriptSignal, Parked: RBXScriptSignal, Leveling: RBXScriptSignal, Leveling3Phase: RBXScriptSignal, __eventInstances__: { CabProgression: BindableEvent, CabTraveling: BindableEvent, Parked: BindableEvent, Leveling: BindableEvent, Leveling3Phase: BindableEvent, } }, __Connections: { Moving: RBXScriptConnection?, } } local Elevator = {} :: Impl_Constructor Elevator.__index = Elevator local function ElevatorGoingUpDirection(CurrentFloor: number, RequestedFloor: number): boolean -- -(CurrentFloor-RequestedFloor)>0 -- -CurrentFloor+RequestedFloor>0 return CurrentFloor1, `[{ElevatorConfigurationTable.Name}] requires more floors to operate. Floors={FloorLevelingPositions}, #Floors={#FloorLevelingPositions}.`) local _BoxAttachment, BoxAlignPosition, _BoxAlignOrientation = Mover(ElevatorBoxModel, ElevatorConfigurationTable.Responsiveness, ElevatorConfigurationTable.MaxVelocity) local RelayAlgorithmConstructor = RelayAlgorithm.constructor(BoxAlignPosition) local CabProgression = Instance.new("BindableEvent") :: BindableEvent local CabTraveling = Instance.new("BindableEvent") :: BindableEvent local Parked = Instance.new("BindableEvent") :: BindableEvent local Leveling = Instance.new("BindableEvent") :: BindableEvent local Leveling3Phase = Instance.new("BindableEvent") :: BindableEvent local Attributes = { PreviousFloor = Instance.new("IntValue") :: IntValue, CurrentFloor = Instance.new("IntValue") :: IntValue, NextFloor = Instance.new("IntValue") :: IntValue, Goal = Instance.new("IntValue") :: IntValue, GoingUp = Instance.new("BoolValue") :: BoolValue, Stopped = Instance.new("BoolValue") :: BoolValue } Attributes.CurrentFloor.Value = 1 Attributes.PreviousFloor.Value = Attributes.CurrentFloor.Value Attributes.NextFloor.Value = Attributes.CurrentFloor.Value+1 Attributes.GoingUp.Value = false Attributes.Goal.Value = 1 print(`🛗 [{ElevatorConfigurationTable.Name}]: Initialized and ready`) return setmetatable({ RelayAlgorithm = RelayAlgorithmConstructor, FloorLevelingPositions = FloorLevelingPositions, Elevator = { BoxModel = ElevatorBoxModel, AlignPosition = BoxAlignPosition, Configuration = ElevatorConfigurationTable, }, Events = { CabProgression = CabProgression.Event, CabTraveling = CabTraveling.Event, Parked = Parked.Event, Leveling = Leveling.Event, Leveling3Phase = Leveling3Phase.Event, __eventInstances__ = { CabProgression = CabProgression, CabTraveling = CabTraveling, Parked = Parked, Leveling = Leveling, Leveling3Phase = Leveling3Phase, } }, Attributes = Attributes, __Connections = {} }, Elevator) end local function CheckFloorQueue(self: ClassConstructor) if self.RelayAlgorithm.__FloorQueue[1] ~= self.Attributes.CurrentFloor.Value then warn("The floor queue first index did not match the elevator's current floor, CurrentFloor=", self.Attributes.CurrentFloor.Value, "FloorQueue[1]=", self.RelayAlgorithm.__FloorQueue[1]) end table.remove(self.RelayAlgorithm.__FloorQueue, 1) local NextFloorInQueue = self.RelayAlgorithm.__FloorQueue[1] print(NextFloorInQueue) if NextFloorInQueue then local ElevatorGoingUp = ElevatorGoingUpDirection(self.Attributes.CurrentFloor.Value, NextFloorInQueue) local LevelVec3 = self.FloorLevelingPositions[NextFloorInQueue] self:__TravelToFloor(NextFloorInQueue, LevelVec3, ElevatorGoingUp) end end local function CabTraveling(self: ClassConstructor, deltaTime: number, LevelVec3: number, ElevatorGoingUp: boolean) local ElevatorPosition = self.Elevator.BoxModel.Position local AtFloorY = self.FloorLevelingPositions[ElevatorGoingUp and self.Attributes.CurrentFloor.Value+1 or self.Attributes.CurrentFloor.Value-1] if ElevatorGoingUp then --Detecting between the floors if ElevatorPosition.Y>=AtFloorY-self.Elevator.Configuration.FloorLevelingDistance then self.Attributes.PreviousFloor.Value = self.Attributes.CurrentFloor.Value self.Attributes.CurrentFloor.Value+=1 self.Attributes.NextFloor.Value = math.clamp(1, self.Attributes.CurrentFloor.Value+1, #self.FloorLevelingPositions) self.Events.__eventInstances__.CabProgression:Fire(self.Attributes.PreviousFloor.Value, self.Attributes.CurrentFloor.Value, self.Attributes.NextFloor.Value) end --Elevator is riding upwards towards the destination if ElevatorPosition.Y>=LevelVec3-self.Elevator.Configuration.FloorLevelingDistance then self.Events.__eventInstances__.Leveling:Fire() self.Elevator.AlignPosition.MaxVelocity = self.Elevator.Configuration.LevelingVelocity if ElevatorPosition.Y>=LevelVec3-self.Elevator.Configuration.FloorLeveling3PhaseDistance then self.Events.__eventInstances__.Leveling3Phase:Fire() self.Elevator.AlignPosition.MaxVelocity = self.Elevator.Configuration.Phase3LevelingVelocity if ElevatorPosition.Y>=LevelVec3-self.Elevator.Configuration.ParkedDistance then self.Events.__eventInstances__.Parked:Fire() CheckFloorQueue(self); (self.__Connections.Moving :: RBXScriptConnection):Disconnect() end end end else if ElevatorPosition.Y<=AtFloorY+self.Elevator.Configuration.FloorLevelingDistance then self.Attributes.PreviousFloor.Value = self.Attributes.CurrentFloor.Value self.Attributes.CurrentFloor.Value-=1 self.Attributes.NextFloor.Value = math.clamp(1, self.Attributes.CurrentFloor.Value-1, #self.FloorLevelingPositions) self.Events.__eventInstances__.CabProgression:Fire(self.Attributes.PreviousFloor.Value, self.Attributes.CurrentFloor.Value, self.Attributes.NextFloor.Value) end --Elevator is riding upwards towards the destination if ElevatorPosition.Y<=LevelVec3+self.Elevator.Configuration.FloorLevelingDistance then self.Events.__eventInstances__.Leveling:Fire() self.Elevator.AlignPosition.MaxVelocity = self.Elevator.Configuration.LevelingVelocity if ElevatorPosition.Y<=LevelVec3+self.Elevator.Configuration.FloorLeveling3PhaseDistance then self.Events.__eventInstances__.Leveling3Phase:Fire() self.Elevator.AlignPosition.MaxVelocity = self.Elevator.Configuration.Phase3LevelingVelocity if ElevatorPosition.Y<=LevelVec3+self.Elevator.Configuration.ParkedDistance then self.Events.__eventInstances__.Parked:Fire() CheckFloorQueue(self); (self.__Connections.Moving :: RBXScriptConnection):Disconnect() end end end end self.Events.__eventInstances__.CabTraveling:Fire(deltaTime, ElevatorPosition) end function Elevator:__TravelToFloor(LevelInt, LevelVec3, ElevatorGoingUp) if self.__Connections.Moving and self.__Connections.Moving.Connected then self.__Connections.Moving:Disconnect() end self.Attributes.Goal.Value = LevelInt self.Attributes.GoingUp.Value = ElevatorGoingUp self.__Connections.Moving = RunService.Heartbeat:Connect(function(deltaTime) CabTraveling(self, deltaTime, LevelVec3, ElevatorGoingUp) end) --Set the elevator's AlignPosition to the floor Y vector self.Elevator.AlignPosition.Position = Vector3.new(self.Elevator.AlignPosition.Position.X, LevelVec3, self.Elevator.AlignPosition.Position.Z) --Set the elevator's max velocity to its fastest speed when moving starts self.Elevator.AlignPosition.MaxVelocity = self.Elevator.Configuration.MaxVelocity end function Elevator:RequestLevel(RequestedLevel) local LevelVec3 = self.FloorLevelingPositions[RequestedLevel] if LevelVec3 then if RequestedLevel ~= self.Attributes.CurrentFloor.Value then local ElevatorGoingUp = ElevatorGoingUpDirection(self.Attributes.CurrentFloor.Value, RequestedLevel) self.RelayAlgorithm:AddFloor(ElevatorGoingUp, self.Attributes.GoingUp, RequestedLevel) if #self.RelayAlgorithm.__FloorQueue == 1 then self:__TravelToFloor(RequestedLevel, LevelVec3, ElevatorGoingUp) end else warn(`[{self.Elevator.Configuration.Name}]: The elevator is already at the requested floor. RequestLevel={RequestedLevel}, CurrentLevel={self.Attributes.CurrentFloor.Value}`) return false end return true end warn(`[{self.Elevator.Configuration.Name}]: Requested floor: "{RequestedLevel}" does not exist for this elevator`) return false end return Elevator