the new structure

This commit is contained in:
2024-09-13 17:35:45 -04:00
parent 991da97c9f
commit fe2dfca727
5 changed files with 1 additions and 1 deletions

View File

@@ -0,0 +1,105 @@
--!optimize 2
--!strict
local ParentDir = script.Parent
local ElevatorDir = ParentDir.Parent
local ElevatorsDir = ElevatorDir.Parent.Parent
local MainDir = ElevatorsDir.Parent
local StorageService = game:GetService("ReplicatedStorage")
local Enums = require(StorageService:WaitForChild("Enums"))
local InitElevator = require(ElevatorsDir:WaitForChild("System"))
local Buttons = require(ElevatorDir:WaitForChild("Buttons"))
local Doors = require(ElevatorDir:WaitForChild("Doors"))
local TagsModule = require(MainDir:WaitForChild("Map"):WaitForChild("Load"):WaitForChild("Tags"))
local ElevatorTypes = require(MainDir:WaitForChild("Types"):WaitForChild("Elevator"))
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
__index: Impl_Constructor,
constructor: Constructor_Fun,
--Class functions
Events: (self: ClassConstructor) -> ()
}
type Constructor_Fun = (
ElevatorConfig: ElevatorTypes.ElevatorConfigurationTable,
ElevatorConstructor: InitElevator.constructor,
DoorsConstructor: Doors.constructor,
ButtonsConstructor: Buttons.constructor
) -> ClassConstructor
type Constructor_Return_Props = {
ElevatorConfig: ElevatorTypes.ElevatorConfigurationTable,
ElevatorConstructor: InitElevator.constructor,
DoorsConstructor: Doors.constructor,
ButtonsConstructor: Buttons.constructor
}
local ButtonEvents = {} :: Impl_Constructor
ButtonEvents.__index = ButtonEvents
function ButtonEvents.constructor(ElevatorConfig, ElevatorConstructor, DoorsConstructor, ButtonsConstructor)
return setmetatable({
ElevatorConfig = ElevatorConfig,
ElevatorConstructor = ElevatorConstructor,
DoorsConstructor = DoorsConstructor,
ButtonsConstructor = ButtonsConstructor
}, ButtonEvents)
end
local function ElevatorGoingUpDirection(CurrentFloor: number, RequestedFloor: number): boolean
return CurrentFloor<RequestedFloor
end
local function DeactivateButton(self: ClassConstructor, Properties: TagsModule.ButtonProperties)
(Properties.Inst :: BasePart).Color = self.ElevatorConfig.Colors.ButtonDeactivated.Color;
(Properties.Inst :: BasePart).Material = self.ElevatorConfig.Colors.ButtonDeactivated.Material
Properties.Prompt.Enabled = true
end
local function ActivateButton(self: ClassConstructor, Properties: TagsModule.ButtonProperties)
Properties.Prompt.Enabled = false
(Properties.Inst :: BasePart).Color = self.ElevatorConfig.Colors.ButtonActivated.Color;
(Properties.Inst :: BasePart).Material = self.ElevatorConfig.Colors.ButtonActivated.Material
end
local function ButtonAttributes(self: ClassConstructor)
local Attributes = self.ElevatorConstructor.Attributes
Attributes.CurrentFloor:GetPropertyChangedSignal("Value"):Connect(function()
if Attributes.CurrentFloor.Value == Attributes.Goal.Value then
local FloorButton = self.ButtonsConstructor:Get(Enums.ButtonTree.Car, Attributes.CurrentFloor.Value)
if FloorButton then
DeactivateButton(self, FloorButton)
end
end
end)
end
function ButtonEvents:Events()
self.ElevatorConstructor.RelayAlgorithm.Events.Added:Connect(function(_Direction: Enums.ElevatorCallDirectionValues, AddedFloor: number)
local FloorButton = self.ButtonsConstructor:Get(Enums.ButtonTree.Car, AddedFloor)
if FloorButton then
ActivateButton(self, FloorButton)
end
end)
self.ButtonsConstructor.Events.FloorButtonActivated:Connect(function(Success: boolean, Floor: number, Properties: TagsModule.ButtonProperties)
if Success then
if self.DoorsConstructor:CloseAtFloor(self.ElevatorConstructor.Attributes.CurrentFloor.Value) then
self.DoorsConstructor:CloseCabAsync()
end
local Direction = ElevatorGoingUpDirection(self.ElevatorConstructor.Attributes.CurrentFloor.Value, Floor) and Enums.ElevatorCallDirection.Up or Enums.ElevatorCallDirection.Down
self.ElevatorConstructor:RequestLevelAsync(Floor, Direction :: Enums.ElevatorCallDirectionValues)
else
ActivateButton(self, Properties)
task.wait(.45)
DeactivateButton(self, Properties)
end
end)
ButtonAttributes(self)
end
return ButtonEvents

View File

@@ -0,0 +1,107 @@
--!optimize 2
--!strict
local ParentDir = script.Parent
local MapDir = ParentDir.Parent
local ElevatorDir = MapDir.Parent
local MainDir = ElevatorDir.Parent
local TagsModule = MainDir:WaitForChild("Map"):WaitForChild("Load"):WaitForChild("Tags")
local StorageService = game:GetService("ReplicatedStorage")
local Enums = require(StorageService:WaitForChild("Enums"))
local ButtonTags = require(TagsModule:WaitForChild("Buttons"))
local Tags = require(TagsModule)
local ButtonManager = require(ElevatorDir:WaitForChild("ButtonManager"))
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
__index: Impl_Constructor,
constructor: Constructor_Fun,
--Class functions
InitForElevator: (self: ClassConstructor, MaxActivationDistance: number?, AddedOffset: Vector3?) -> (),
Get: (self: ClassConstructor, ButtonType: Enums.ButtonTreeValues, ButtonID: number) -> Tags.ButtonProperties?
}
type Constructor_Fun = (
ElevatorModel: Enums.ElevatorValues,
ButtonTags: Tags.ElevatorButtons,
CurrentFloor: IntValue
) -> ClassConstructor
type Constructor_Return_Props = {
ElevatorModel: Enums.ElevatorValues,
ButtonTags: Tags.ElevatorButtons,
CurrentFloor: IntValue,
Events: Events,
__PromptButtons__: Tags.ButtonsTree?
}
export type Events = {
FloorButtonActivated: RBXScriptSignal<boolean, number, Tags.ButtonProperties>,
__eventInstances__: {
FloorButtonActivated: BindableEvent
}
}
export type constructor = ClassConstructor
local Buttons = {} :: Impl_Constructor
Buttons.__index = Buttons
function Buttons.constructor(ElevatorModel, ButtonTags, CurrentFloor)
local ButtonActivated = Instance.new("BindableEvent") :: BindableEvent
return setmetatable({
ElevatorModel = ElevatorModel,
ButtonTags = ButtonTags,
CurrentFloor = CurrentFloor,
Events = {
FloorButtonActivated = ButtonActivated.Event,
__eventInstances__ = {
FloorButtonActivated = ButtonActivated
}
}
}, Buttons)
end
function Buttons:InitForElevator(MaxActivationDistance, AddedOffset)
MaxActivationDistance = MaxActivationDistance or ButtonTags.DefaultMaxActivationDistance
AddedOffset = AddedOffset or Vector3.zero
local ButtonManagerConstructor = ButtonManager.constructor(self.CurrentFloor)
local ButtonTagsConstructor = ButtonTags.constructor(self.ButtonTags, self.ElevatorModel)
self.__PromptButtons__ = ButtonTagsConstructor:CreatePromptButtons()
local CarButtonPrompts = (self.__PromptButtons__ :: Tags.ButtonsTree)[self.ElevatorModel].Car
for PromptType, PromptProperties in CarButtonPrompts do
PromptProperties.Prompt.MaxActivationDistance = MaxActivationDistance :: number
PromptProperties.Attachment.Position+=AddedOffset :: Vector3
ButtonManagerConstructor:CarButton(PromptType, PromptProperties, function(ButtonFloor: number)
self.Events.__eventInstances__.FloorButtonActivated:Fire(true, ButtonFloor, PromptProperties)
end, function(ButtonFloor: number)
self.Events.__eventInstances__.FloorButtonActivated:Fire(false, ButtonFloor, PromptProperties)
end)
end
end
function Buttons:Get(ButtonType, ButtonName)
assert(self.__PromptButtons__, `Initialize the elevator buttons first before using :Get, self.__PromptButtons__={self.__PromptButtons__}`)
local Button = self.__PromptButtons__[self.ElevatorModel][ButtonType] :: Tags.ButtonDictionary?
if Button then
--mega cringe
for ButtonFullName: string, ButtonProps: Tags.ButtonProperties in Button do
if ButtonProps.ID == ButtonName then
return ButtonProps
end
end
end
return nil
end
return Buttons

View File

@@ -0,0 +1,308 @@
--!optimize 2
--!strict
local ParentDir = script.Parent
local ElevatorsDir = ParentDir.Parent.Parent
local MainDir = ElevatorsDir.Parent
local Storage = game:GetService("ReplicatedStorage")
local RS = game:GetService("RunService")
local Types = MainDir:WaitForChild("Types")
local GCSignal = require(Storage:WaitForChild("GCSignal"))
local DoorEnums = require(Types:WaitForChild("Enums"):WaitForChild("Doors"))
local ElevatorEnums = require(Types:WaitForChild("Elevator"))
local Tags = require(MainDir:WaitForChild("Map"):WaitForChild("Load"):WaitForChild("Tags"))
local Algebra = require(Storage:WaitForChild("Algebra"))
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
__index: Impl_Constructor,
constructor: Constructor_Fun,
--Class functions
OpenCabAsync: (self: ClassConstructor) -> boolean,
CloseCabAsync: (self: ClassConstructor) -> boolean,
OpenAtFloor: (self: ClassConstructor, Floor: number) -> boolean,
CloseAtFloor: (self: ClassConstructor, Floor: number) -> boolean,
}
type Constructor_Fun = (
LevelingFloors: {number},
ElevatorBox: BasePart,
DoorConfig: ElevatorEnums.DoorsConfig,
DoorsTree: Tags.LandingTags
) -> ClassConstructor
type Attributes = {
Hall: {
[number]: {
Open: BoolValue
}
},
Cab: {
Open: BoolValue,
}
}
type Constructor_Return_Props = {
DoorConfig: ElevatorEnums.DoorsConfig,
ElevatorBox: BasePart,
DoorsTree: Tags.LandingTags,
Attributes: Attributes,
__Connections: {
Cab: RBXScriptConnection?,
Landing: RBXScriptConnection?
}
}
type Signal = GCSignal.constructor
export type constructor = ClassConstructor
local Doors = {} :: Impl_Constructor
Doors.__index = Doors
function Doors.constructor(LevelingFloors, ElevatorBox, DoorConfig, DoorsTree)
local CabOpenAttribute = Instance.new("BoolValue") :: BoolValue
local DoorAttributes = {
Hall = {},
Cab = {
Open = CabOpenAttribute
}
}
for n: number = 1, #LevelingFloors do
DoorAttributes.Hall[n] = {
Open = Instance.new("BoolValue") :: BoolValue
}
end
return setmetatable({
DoorConfig = DoorConfig,
ElevatorBox = ElevatorBox,
DoorsTree = DoorsTree,
Attributes = DoorAttributes,
__Connections = {}
}, Doors)
end
type DoorAnimationCallback<T...> = (self: ClassConstructor, Time: number, T...) -> ()
local function DoorAnimationRuntime(self: ClassConstructor, Time: number, Type: DoorEnums.DoorLocationValues, Callback: DoorAnimationCallback<()>): Signal
if self.__Connections[Type] and self.__Connections[Type].Connected then
self.__Connections[Type]:Disconnect()
end
local Finished = GCSignal.constructor()
local StartTime = os.clock()
self.__Connections[Type] = RS.Stepped:Connect(function(_delta: number, _dt: number)
local AnimationTime = Algebra.LinearElapse(StartTime, Time)
Callback(self, AnimationTime)
if AnimationTime>=1 then
Finished:Fire();
(self.__Connections[Type] :: RBXScriptConnection):Disconnect()
end
end)
return Finished
end
--a<T> = ...T
type DoorAnimationsMap = {
Cab: {
SingleSpeed: DoorAnimationCallback<Vector3, Vector3, Vector3>,
DoubleSpeed: DoorAnimationCallback<Vector3, Vector3, Vector3, Vector3>,
TripleSpeed: DoorAnimationCallback<Vector3, Vector3, Vector3, Vector3, Vector3, Vector3>,
},
Landing: {
SingleSpeed: DoorAnimationCallback<number, Vector3, Vector3>,
DoubleSpeed: DoorAnimationCallback<number, Vector3, Vector3, Vector3>,
TripleSpeed: DoorAnimationCallback<number, Vector3, Vector3, Vector3, Vector3>,
}
}
local DoorAnimations = {
Cab = {},
Landing = {}
} :: DoorAnimationsMap
--Cab doors--
@native
function DoorAnimations.Cab.SingleSpeed(self, AnimationTime, Door1Position, OpenToVec1)
local CabDoor1 = self.DoorsTree.Cab[1] :: BasePart
local ElevatorY = Vector3.new(0, self.ElevatorBox.Position.Y, 0)
local Door1XZ = Vector3.new(Door1Position.X, 0, Door1Position.Z)
local Door1Y = Vector3.new(0, CabDoor1.Position.Y-self.ElevatorBox.Position.Y, 0)
local OpenToVec1XZ = Vector3.new(OpenToVec1.X, 0, OpenToVec1.Z)
CabDoor1.Position = ElevatorY+Door1Y+Door1XZ:Lerp(Door1XZ+OpenToVec1XZ, Algebra.Easing.OutQuad(AnimationTime))
end
@native
function DoorAnimations.Cab.DoubleSpeed(self, AnimationTime, Door1Position, Door2Position, OpenToVec1, OpenToVec2)
local CabDoor1 = self.DoorsTree.Cab[1] :: BasePart
local CabDoor2 = self.DoorsTree.Cab[2] :: BasePart
local AlgebraEasing = Algebra.Easing.OutQuad(AnimationTime)
local ElevatorY = Vector3.new(0, self.ElevatorBox.Position.Y, 0)
local Door1XZ = Vector3.new(Door1Position.X, 0, Door1Position.Z)
local Door2XZ = Vector3.new(Door2Position.X, 0, Door2Position.Z)
local Door1Y = Vector3.new(0, CabDoor1.Position.Y-self.ElevatorBox.Position.Y, 0)
local Door2Y = Vector3.new(0, CabDoor2.Position.Y-self.ElevatorBox.Position.Y, 0)
local OpenToVec1XZ = Vector3.new(OpenToVec1.X, 0, OpenToVec1.Z)
local OpenToVec2XZ = Vector3.new(OpenToVec2.X, 0, OpenToVec2.Z)
CabDoor1.Position = ElevatorY+Door1Y+Door1XZ:Lerp(Door1XZ+OpenToVec1XZ, AlgebraEasing)
CabDoor2.Position = ElevatorY+Door2Y+Door2XZ:Lerp(Door2XZ+OpenToVec2XZ, AlgebraEasing)
end
@native
function DoorAnimations.Cab.TripleSpeed(self, AnimationTime, Door1Position, Door2Position, Door3Position, OpenToVec1, OpenToVec2, OpenToVec3)
local CabDoor1 = self.DoorsTree.Cab[1] :: BasePart
local CabDoor2 = self.DoorsTree.Cab[2] :: BasePart
local CabDoor3 = self.DoorsTree.Cab[3] :: BasePart
local AlgebraEasing = Algebra.Easing.OutQuad(AnimationTime)
local ElevatorY = Vector3.new(0, self.ElevatorBox.Position.Y, 0)
local Door1XZ = Vector3.new(Door1Position.X, 0, Door1Position.Z)
local Door2XZ = Vector3.new(Door2Position.X, 0, Door2Position.Z)
local Door3XZ = Vector3.new(Door3Position.X, 0, Door3Position.Z)
local Door1Y = Vector3.new(0, CabDoor1.Position.Y-self.ElevatorBox.Position.Y, 0)
local Door2Y = Vector3.new(0, CabDoor1.Position.Y-self.ElevatorBox.Position.Y, 0)
local Door3Y = Vector3.new(0, CabDoor1.Position.Y-self.ElevatorBox.Position.Y, 0)
local OpenToVec1XZ = Vector3.new(OpenToVec1.X, 0, OpenToVec1.Z)
local OpenToVec2XZ = Vector3.new(OpenToVec2.X, 0, OpenToVec2.Z)
local OpenToVec3XZ = Vector3.new(OpenToVec3.X, 0, OpenToVec3.Z)
CabDoor1.Position = ElevatorY+Door1Y+Door1XZ:Lerp(Door1XZ+OpenToVec1XZ, AlgebraEasing)
CabDoor2.Position = ElevatorY+Door2Y+Door2XZ:Lerp(Door2XZ+OpenToVec2XZ, AlgebraEasing)
CabDoor3.Position = ElevatorY+Door3Y+Door3XZ:Lerp(Door3XZ+OpenToVec3XZ, AlgebraEasing)
end
----
--Floor doors--
@native
function DoorAnimations.Landing.SingleSpeed(self, Floor, AnimationTime, Door1Position, OpenToVec1)
(self.DoorsTree.Hall[Floor][1] :: BasePart).Position = Door1Position:Lerp(Door1Position+OpenToVec1, Algebra.Easing.OutQuad(AnimationTime))
end
---
--this is ridiculous optimization tech
local function OpenVecTuple(self: ClassConstructor, Opening: boolean, Type: DoorEnums.DoorLocationValues, HallFloor: number?): ...Vector3?
if Type == DoorEnums.DoorLocation.Landing and not HallFloor then
warn("Hall/landing doors were called but no HallFloor number was received")
return nil
end
local DoorsType: {Instance?}? = Type == DoorEnums.DoorLocation.Cab and self.DoorsTree.Cab or self.DoorsTree.Hall[HallFloor :: number]
local ConfType = Type == DoorEnums.DoorLocation.Cab and self.DoorConfig.Cab or self.DoorConfig.Landing
if ConfType.Type == DoorEnums.Door.SingleSpeed then
if DoorsType and DoorsType[1] then
local P = (DoorsType[1] :: BasePart).Position
local Direction = Opening and -ConfType.Goal or ConfType.Goal
return table.unpack({
P,
Direction
})
end
elseif ConfType.Type == DoorEnums.Door.DoubleSpeed then
if DoorsType and DoorsType[1] and DoorsType[2] then
local P = (DoorsType[1] :: BasePart).Position
local P2 = (DoorsType[2] :: BasePart).Position
local Direction = Opening and -ConfType.Goal or ConfType.Goal
return table.unpack({
P,
P2,
Direction,
Direction/2
})
end
elseif ConfType.Type == DoorEnums.Door.TripleSpeed then
--idk man
if DoorsType and DoorsType[1] and DoorsType[2] and DoorsType[3] then
local P = (DoorsType[1] :: BasePart).Position
local P2 = (DoorsType[2] :: BasePart).Position
local P3 = (DoorsType[3] :: BasePart).Position
local Direction = Opening and -ConfType.Goal or ConfType.Goal
return table.unpack({
P,
P2,
P3,
Direction,
Direction/1.5,
Direction/2,
})
end
end
return nil
end
--this module is built off my insanity
local function ToggleDoors(self: ClassConstructor, Type: DoorEnums.DoorLocationValues, Opening: boolean, Floor: number?): boolean
local Config: ElevatorEnums.DoorsConfigProperties? = Type == DoorEnums.DoorLocation.Cab and self.DoorConfig.Cab or self.DoorConfig.Landing
if Config then
local P1, P2, P3, P4, P5, P6 = OpenVecTuple(self, Opening, Type, Floor)
if P1 then
if Type == DoorEnums.DoorLocation.Cab then
local FinishedSignal = DoorAnimationRuntime(self, Config.Time, Type, function(self, AnimationTime)
DoorAnimations.Cab[Config.Type](self, AnimationTime, P1, P2, P3, P4, P5, P6)
end)
FinishedSignal:Once(function(...)
self.Attributes.Cab.Open.Value = Opening
end)
return true
elseif Type == DoorEnums.DoorLocation.Landing then
local FinishedSignal = DoorAnimationRuntime(self, Config.Time, Type, function(self, AnimationTime)
DoorAnimations.Landing[Config.Type](self, Floor, AnimationTime, P1, P2, P3, P4, P5, P6)
end)
FinishedSignal:Once(function(...)
self.Attributes.Hall[Floor :: number].Open.Value = Opening
end)
return true
end
return false
end
else
return false
end
return false
end
function Doors:OpenCabAsync()
if self.Attributes.Cab.Open.Value then
warn("Elevator doors already open")
return false
end
return ToggleDoors(self, DoorEnums.DoorLocation.Cab, true)
end
function Doors:CloseCabAsync()
if not self.Attributes.Cab.Open.Value then
warn("Elevator doors already closed")
return false
end
return ToggleDoors(self, DoorEnums.DoorLocation.Cab, false)
end
function Doors:OpenAtFloor(Floor)
if self.Attributes.Hall[Floor].Open.Value then
warn(`Elevator doors at floor "{Floor}" already open`)
return false
end
return ToggleDoors(self, DoorEnums.DoorLocation.Landing, true, Floor)
end
function Doors:CloseAtFloor(Floor)
if not self.Attributes.Hall[Floor].Open.Value then
warn(`Elevator doors at floor "{Floor}" already closed`)
return false
end
return ToggleDoors(self, DoorEnums.DoorLocation.Landing, false, Floor)
end
return Doors

View File

@@ -0,0 +1,56 @@
--!optimize 2
--!strict
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
__index: Impl_Constructor,
constructor: Constructor_Fun,
--Class functions
Update: (self: ClassConstructor) -> ()
}
type Constructor_Fun = (CabRopesObject: BasePart, PulleyRopesObject: BasePart) -> ClassConstructor
type Constructor_Return_Props = {
CabRopesObject: BasePart,
PulleyRopesObject: BasePart,
PulleyCables: {RopeConstraint}
}
export type constructor = ClassConstructor
local TractionRopes = {} :: Impl_Constructor
TractionRopes.__index = TractionRopes
function TractionRopes.constructor(CabRopesObject, PulleyRopesObject)
local PulleyCables = {}
local PulleyCablesChildren = PulleyRopesObject:GetChildren()
for n: number = 1, #PulleyCablesChildren do
local Object = PulleyCablesChildren[n] :: Instance
if Object:IsA("BasePart") then
local Rope = Object:FindFirstChildOfClass("RopeConstraint")
if Rope then
table.insert(PulleyCables, Rope)
end
end
end
assert(#PulleyCables>0, "0 RopeConstraint's were found for an elevator with traction ropes!")
return setmetatable({
CabRopesObject = CabRopesObject,
PulleyRopesObject = PulleyRopesObject,
PulleyCables = PulleyCables
}, TractionRopes)
end
@native
function TractionRopes:Update()
local StudLength = (self.PulleyRopesObject.Position-self.CabRopesObject.Position).Magnitude+1
for n: number = 1, #self.PulleyCables do
self.PulleyCables[n].Length = StudLength
end
end
return TractionRopes