Files
Roblox-Elevator-Game/src/server/main/Elevators/Otis1960/init.lua
2024-05-02 22:59:55 -04:00

266 lines
10 KiB
Lua

--!optimize 2
--!native
--!strict
local Elevators = script.Parent
local MainDir = Elevators.Parent
local LoadDir = MainDir:WaitForChild("Load")
local Storage: ReplicatedStorage = game:GetService("ReplicatedStorage")
local RS: RunService = game:GetService("RunService")
local Enums = require(Storage:WaitForChild("Enums"))
local Leveling = require(script:WaitForChild("Leveling"))
local Doors = require(script:WaitForChild("Doors"))
local MovingObjects = require(script:WaitForChild("MovingObjects"))
local ElevatorMover = require(Elevators:WaitForChild("Mover"))
local ButtonTags = require(Elevators:WaitForChild("Buttons"))
local TractionRopes = require(Elevators:WaitForChild("TractionRopes"))
local Lanterns = require(Elevators:WaitForChild("Lanterns"))
local PromptModule = require(MainDir:WaitForChild("Map"):WaitForChild("Prompts"))
local Tags = require(LoadDir:WaitForChild("Tags"))
type rbxassetid = string
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
__MoveFloors: (self: ClassConstructor, Level: number, RequestedLevel: number, GoingUp: boolean) -> (),
GoToLevel: (self: ClassConstructor, RequestedLevel: number) -> ()
} & Impl_Static_Props
type Impl_Static_Props = {
Responsiveness: number,
MaxVelocity: number,
ButtonActivatedColor: Color3,
LanternDisplayColorOn: Color3,
LanternDisplayColorOff: Color3,
LanternChimeDirection: rbxassetid,
LanternChimeLanding: rbxassetid,
FloorLevelingDistance: number,
LeveledDistance: number,
__Moving: boolean,
__CurrentFloor: number
}
type Constructor_Fun = (TagsConstructor: TagsConstructor, ButtonsTags: Tags.ElevatorButtons, LanternsTags: Tags.Lanterns) -> ClassConstructor
type Constructor_Return_Props = {
Tags: Tags,
MOConstructor: MovingObjects.MovingObjectsConstructor,
LanternsConstructor: Lanterns.LanternsConstructor,
ElevatorBox_1960: UnionOperation,
ElevatorDoor1: BasePart,
ElevatorDoor2: BasePart,
ElevatorDoorSensor: Folder,
BoxAttachment: Attachment,
BoxAlignPosition: AlignPosition,
BoxAlignOrientation: AlignOrientation,
ElevatorDoors: Doors.DoorConstructor,
Ropes: {Instance},
TractionRopes: TractionRopes.TractionRopesConstructor,
Pulley: UnionOperation,
Pulley2: UnionOperation,
Governor: UnionOperation,
GovernorFlyballs: Part,
PieplatePulley: UnionOperation,
MachineRoom: MovingObjects.MachineRoom,
__MovingConnection: RBXScriptConnection?,
}
type ButtonFunction = (self: ClassConstructor, ButtonName: string, ButtonsConstructor: ButtonTags.ButtonsConstructor, ButtonTree: Tags.ButtonProperties) -> ()
type ButtonFunctions = {
[Enums.ButtonTreeValues]: ButtonFunction
}
local Otis1960 = {} :: Impl_Constructor
Otis1960.__index = Otis1960
Otis1960.FloorLevelingDistance = 2.5
Otis1960.LeveledDistance = 0.5
Otis1960.Responsiveness = 50
Otis1960.MaxVelocity = 10
Otis1960.ButtonActivatedColor = Color3.fromRGB(180,0,0)
Otis1960.LanternDisplayColorOn = Color3.fromRGB(255,114,71)
Otis1960.LanternDisplayColorOff = Color3.fromRGB(55,55,55)
Otis1960.LanternChimeDirection = "rbxassetid://16990287228"
Otis1960.LanternChimeLanding = "rbxassetid://16990290265"
--*read-only*
Otis1960.__Moving = false
Otis1960.__CurrentFloor = 1
local ButtonFunctions: ButtonFunctions = {
[Enums.ButtonTree.Landing] = function(self, ButtonName, ButtonsConstructor, ButtonTree)
end,
[Enums.ButtonTree.Car] = function(self, ButtonName, ButtonsConstructor, ButtonTree)
local DecodedFloor = Tags.Decoders.CarTag(ButtonName)
if not DecodedFloor then
end
local Prompt = PromptModule.constructor(ButtonTree.Prompt, ButtonTree.Inst)
Prompt:AddHookTriggered(function(Player: Player)
if DecodedFloor then
local _ButtonThread = ButtonsConstructor:AestheticActivateButton(ButtonTree.Inst :: BasePart, false, Otis1960.ButtonActivatedColor)
self:GoToLevel(DecodedFloor)
end
end)
end,
[Enums.ButtonTree.Special] = function(self, ButtonName, ButtonsConstructor, ButtonTree)
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
local Button = ButtonFunctions[ButtonNameType :: Enums.ButtonTreeValues]
if Button then
Button(self, ButtonName, ButtonsConstructor, ButtonTree)
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(TagsConstructor, ButtonsTags, LanternsTags)
local self = {} :: Constructor_Return_Props
self.ElevatorBox_1960 = TagsConstructor:Request("ElevatorMover_1960") :: UnionOperation
self.ElevatorDoor1 = TagsConstructor:Request("ElevatorDoor_1960_1") :: BasePart
self.ElevatorDoor2 = TagsConstructor:Request("ElevatorDoor_1960_2") :: BasePart
self.ElevatorDoorSensor = TagsConstructor:Request("ElevatorDoor_Sensor_1960") :: Folder
self.Ropes = TagsConstructor:Request("1960_ElevatorPulleyRope") :: {Instance}
--Rotation objects
self.MachineRoom = {_CFrame = {}} :: MovingObjects.MachineRoom
self.MachineRoom.Pulley = TagsConstructor:Request("Otis1960_Pulley") :: UnionOperation
self.MachineRoom.Pulley2 = TagsConstructor:Request("Otis1960_Pulley2") :: UnionOperation
self.MachineRoom.Governor = TagsConstructor:Request("Otis1960_Governor") :: UnionOperation
self.MachineRoom.GovernorFlyballs = TagsConstructor:Request("Otis1960_GovernorFlyballs") :: Part
self.MachineRoom.PiePlatePulley = TagsConstructor:Request("Otis1960_PieplatePulley") :: UnionOperation
self.MachineRoom.PiePlatePlates = TagsConstructor:Request("Otis1960_PiePlatePlates") :: UnionOperation
self.MachineRoom.PiePlateSelector = TagsConstructor:Request("Otis1960_PiePlateSelector") :: UnionOperation
self.MOConstructor = MovingObjects.constructor({MachineRoom = self.MachineRoom} :: MovingObjects.InstanceTree)
--Audio
local LanternDisplay = TagsConstructor:Request("Otis1960_LanternDisplayMain") :: UnionOperation
self.LanternsConstructor = Lanterns.constructor(LanternDisplay, Otis1960.LanternChimeDirection, Otis1960.LanternChimeLanding, LanternsTags, {
Active = Otis1960.LanternDisplayColorOn,
Off = Otis1960.LanternDisplayColorOff
} :: Lanterns.Colors)
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(TagsConstructor, ButtonsTags)
local Otis1960_Buttons = ButtonsConstructor:CreatePromptButtons()
local ClassConstructor = setmetatable(self, Otis1960)
HookButtons(ClassConstructor, ButtonsConstructor, Enums.ButtonTree.Car)
print("🔝 Otis1960 initialized and ready")
return ClassConstructor
end
local function FloorLeveling(self: ClassConstructor, RequestedLevel: number)
self.BoxAlignPosition.MaxVelocity = 1
self.LanternsConstructor:Toggle(true, RequestedLevel)
end
local function FloorLeveled(self: ClassConstructor, RequestedLevel: number)
(self.__MovingConnection :: RBXScriptConnection):Disconnect()
Otis1960.__Moving = false
Otis1960.__CurrentFloor = RequestedLevel
self.BoxAlignPosition.MaxVelocity = Otis1960.MaxVelocity
self.LanternsConstructor:Reset()
end
function Otis1960:__MoveFloors(GoalLevelVEC, RequestedLevel, GoingUp)
local RotationDelta = 0
local ElevatorBoxCurrentPos = self.ElevatorBox_1960.Position
if self.__MovingConnection and self.__MovingConnection.Connected then
self.__MovingConnection:Disconnect()
end
self.MOConstructor:UpdateCFrame()
if GoingUp then
self.LanternsConstructor:DirectionUp(true)
else
self.LanternsConstructor:DirectionDown(true)
end
--Otis1960_ShaftGovernor
self.__MovingConnection = RS.Heartbeat:Connect(function(_dt) --Not safe for parallel
RotationDelta+=1
Otis1960.__Moving = true
local ElevatorPosition: Vector3 = self.ElevatorBox_1960.Position
local ElevatorVelocityY: number = self.ElevatorBox_1960:GetVelocityAtPosition(ElevatorPosition).Y
self.MOConstructor:Frame_Pullies(RotationDelta, ElevatorVelocityY)
self.TractionRopes:Move(26.3, ElevatorPosition)
--Kill the connection
if GoingUp then
if ElevatorPosition.Y>=self.BoxAlignPosition.Position.Y-Otis1960.FloorLevelingDistance then
FloorLeveling(self, RequestedLevel)
end
if ElevatorPosition.Y>=self.BoxAlignPosition.Position.Y-Otis1960.LeveledDistance then
FloorLeveled(self, RequestedLevel)
end
else
if ElevatorPosition.Y<=self.BoxAlignPosition.Position.Y+Otis1960.FloorLevelingDistance then
FloorLeveling(self, RequestedLevel)
end
if ElevatorPosition.Y<=self.BoxAlignPosition.Position.Y+Otis1960.LeveledDistance then
FloorLeveled(self, RequestedLevel)
end
end
end)
self.BoxAlignPosition.Position = Vector3.new(ElevatorBoxCurrentPos.X, GoalLevelVEC, ElevatorBoxCurrentPos.Z)
end
function Otis1960:GoToLevel(RequestedLevel)
local GoalLevelVEC: number = Leveling[RequestedLevel]
if GoalLevelVEC and GoalLevelVEC ~= 0 and GoalLevelVEC ~= Otis1960.__CurrentFloor then
local GoingUp: boolean = -(Otis1960.__CurrentFloor-RequestedLevel)>0 --My clever math function for determining if the elevator goal is to move upwards or not
self:__MoveFloors(GoalLevelVEC, RequestedLevel, GoingUp)
else
warn(`[{Enums.Elevator.Otis1960}]: landing out of range or equals the same range as goal! requested landing: {tostring(RequestedLevel)}`)
end
end
return Otis1960