--!optimize 2 --!native --!strict local Elevators = script.Parent local Storage: ReplicatedStorage = game:GetService("ReplicatedStorage") local RS: RunService = game:GetService("RunService") local TagsModule = require(Storage:WaitForChild("Tags")) local Leveling = require(script:WaitForChild("Leveling")) local Doors = require(script:WaitForChild("Doors")) local Enums = require(Elevators:WaitForChild("Enums")) local ElevatorMover = require(Elevators:WaitForChild("Mover")) local ButtonTags = require(Elevators:WaitForChild("Buttons")) local TractionRopes = require(Elevators:WaitForChild("TractionRopes")) type Tags = TagsModule.ExportedTags type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor)) type Impl_Constructor = { __index: Impl_Constructor, constructor: Constructor_Fun, --Class functions __MoveFloors: (self: ClassConstructor, Level: number) -> (), GoToLevel: (self: ClassConstructor, RequestedLevel: number) -> () } & Impl_Static_Props type Impl_Static_Props = { Moving: boolean, Responsiveness: number, MaxVelocity: number } type Constructor_Fun = (Tags: Tags) -> ClassConstructor type Constructor_Return_Props = { Tags: Tags, ElevatorBox_1960: UnionOperation, ElevatorDoor1: BasePart, ElevatorDoor2: BasePart, ElevatorDoorSensor: Folder, ProximityButtons: {Instance}, BoxAttachment: Attachment, BoxAlignPosition: AlignPosition, BoxAlignOrientation: AlignOrientation, ElevatorDoors: Doors.DoorConstructor, Ropes: {Instance}, TractionRopes: TractionRopes.TractionRopesConstructor, PiePlateSelector: UnionOperation, __RopeConnection: RBXScriptConnection? } local Otis1960 = {} :: Impl_Constructor Otis1960.__index = Otis1960 Otis1960.Moving = false Otis1960.Responsiveness = 50 Otis1960.MaxVelocity = 10 local function ButtonPress(Button: BasePart, Activated: boolean) task.spawn(function() local Glass = Button:FindFirstChild("Glass") :: BasePart if Glass then Glass.Position+=Glass.CFrame.LookVector/50 if not Activated then Glass.Material = Enum.Material.Neon Glass.Color = Color3.fromRGB(180,0,0) Glass.Transparency = 0 end end Button.Position+=Glass.CFrame.LookVector/50 task.wait(.30) if Glass then Glass.Position-=Glass.CFrame.LookVector/50 end Button.Position-=Glass.CFrame.LookVector/50 end) end local function HookButtons(self: ClassConstructor, ButtonsConstructor: ButtonTags.ButtonsConstructor, ButtonType: Enums.EnumValue) for ButtonNameType, ButtonList in ButtonsConstructor.Buttons do for ButtonName, ButtonTree in ButtonList do if ButtonTree.Prompt then if ButtonTree.Inst then if ButtonNameType == Enums.ButtonTree.Car then local DecodedFloor = ButtonsConstructor:DecodeCarTag(ButtonName) ButtonsConstructor:HookPromptButtonsGroup(ButtonTree.Prompt, ButtonTree.Inst, function(_Player: Player) if DecodedFloor then --ButtonTree.Prompt.Enabled = false ButtonPress(ButtonTree.Inst, false) self:GoToLevel(DecodedFloor) end end) elseif ButtonNameType == Enums.ButtonTree.Special then elseif ButtonNameType == Enums.ButtonTree.Landing then ButtonsConstructor:HookPromptButtonsGroup(ButtonTree.Prompt, ButtonTree.Inst, function(_Player: Player) ButtonTree.Prompt.Enabled = false ButtonPress(ButtonTree.Inst, false) end) end else warn(`{ButtonTree} is missing the field "Inst"`) end else warn(`{ButtonTree} is missing the field "Prompt"`) end end end end function Otis1960.constructor(Tags) local self = {} :: Constructor_Return_Props self.Tags = Tags self.ElevatorBox_1960 = Tags.ElevatorMover_1960 :: UnionOperation self.ElevatorDoor1 = Tags.ElevatorDoor_1960_1 :: BasePart self.ElevatorDoor2 = Tags.ElevatorDoor_1960_2 :: BasePart self.ElevatorDoorSensor = Tags.ElevatorDoor_Sensor_1960 :: Folder self.ProximityButtons = Tags.ProximityElevatorButton :: {Instance} self.Ropes = Tags["1960_ElevatorPulleyRope"] :: {Instance} self.PiePlateSelector = Tags.Otis1960_PiePlateSelector :: UnionOperation self.BoxAttachment, self.BoxAlignPosition, self.BoxAlignOrientation = ElevatorMover(self.ElevatorBox_1960, self.ElevatorBox_1960.Position, Otis1960.Responsiveness, Otis1960.MaxVelocity) self.ElevatorDoors = Doors.constructor(self.ElevatorBox_1960, self.ElevatorDoor1, self.ElevatorDoor2, self.ElevatorDoorSensor) self.TractionRopes = TractionRopes.constructor(self.Ropes, self.ElevatorBox_1960, Leveling) --Buttons local ButtonsConstructor = ButtonTags.constructor(Tags, Enums.Elevator.Otis1960) local Otis1960_Buttons = ButtonsConstructor:CreatePromptButtons() local ClassConstructor = setmetatable(self, Otis1960) HookButtons(ClassConstructor, ButtonsConstructor, Enums.ButtonTree.Car) print("[DEBUG] Otis1960 Buttons=", Otis1960_Buttons) print("🔝 Otis1960 initialized and ready") return ClassConstructor end function Otis1960:__MoveFloors(Level) local ElevatorBoxCurrentPos = self.ElevatorBox_1960.Position self.TractionRopes:Moving(Level, 26) self.BoxAlignPosition.Position = Vector3.new(ElevatorBoxCurrentPos.X, Level, ElevatorBoxCurrentPos.Z) end function Otis1960:GoToLevel(RequestedLevel) local level: number = Leveling[RequestedLevel] if level and level ~= 0 then self:__MoveFloors(level) else warn(`[{Enums.Elevator.Otis1960}]: landing out of range! requested landing: {tostring(RequestedLevel)}`) end end return Otis1960