mirror of
https://github.com/unixtensor/Roblox-Elevator-Game.git
synced 2025-12-14 06:41:55 +00:00
Working lanterns as floors pass by, need to work on going down, start working on hall displays
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -20,7 +20,7 @@ type Impl_Constructor = {
|
|||||||
constructor: Constructor_Fun,
|
constructor: Constructor_Fun,
|
||||||
Get: (Tags: Tags.TagsConstructor, Model: Enums.ElevatorValues) -> Tags.Lanterns,
|
Get: (Tags: Tags.TagsConstructor, Model: Enums.ElevatorValues) -> Tags.Lanterns,
|
||||||
--Class functions
|
--Class functions
|
||||||
Activate: (self: ClassConstructor, EnabledState: boolean, IsDirectionLantern: boolean, Lantern: Tags.Lantern) -> (),
|
Activate: (self: ClassConstructor, EnabledState: boolean, IsDirectionLantern: boolean, Lantern: Tags.Lantern, Chime: boolean) -> (),
|
||||||
DirectionUp: (self: ClassConstructor, Enabled: boolean) -> (),
|
DirectionUp: (self: ClassConstructor, Enabled: boolean) -> (),
|
||||||
DirectionDown: (self: ClassConstructor, Enabled: boolean) -> (),
|
DirectionDown: (self: ClassConstructor, Enabled: boolean) -> (),
|
||||||
Toggle: (self: ClassConstructor, Enabled: boolean, Floor: number) -> (),
|
Toggle: (self: ClassConstructor, Enabled: boolean, Floor: number) -> (),
|
||||||
@@ -74,18 +74,20 @@ end
|
|||||||
|
|
||||||
local LanternLight = Tween.constructor(TweenInfo.new(Lanterns.LightTweenTime))
|
local LanternLight = Tween.constructor(TweenInfo.new(Lanterns.LightTweenTime))
|
||||||
|
|
||||||
function Lanterns:Activate(EnabledState, IsDirectionLantern, Lantern)
|
function Lanterns:Activate(EnabledState, IsDirectionLantern, Lantern, Chime)
|
||||||
local Tween = LanternLight:Start(Lantern.Light, {
|
local Tween = LanternLight:Start(Lantern.Light, {
|
||||||
Color = EnabledState and self.Colors.Active or self.Colors.Off
|
Color = EnabledState and self.Colors.Active or self.Colors.Off
|
||||||
})
|
})
|
||||||
|
|
||||||
if EnabledState then
|
if EnabledState then
|
||||||
if IsDirectionLantern then
|
if Chime then
|
||||||
self.AudioChimeDirection:Play()
|
if IsDirectionLantern then
|
||||||
else
|
self.AudioChimeDirection:Play()
|
||||||
Tween.Completed:Once(function()
|
else
|
||||||
self.AudioChimeLanding:Play()
|
Tween.Completed:Once(function()
|
||||||
end)
|
self.AudioChimeLanding:Play()
|
||||||
|
end)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if Lantern.PointLight then
|
if Lantern.PointLight then
|
||||||
@@ -110,17 +112,17 @@ end
|
|||||||
function Lanterns:Reset(ExcludeFloor)
|
function Lanterns:Reset(ExcludeFloor)
|
||||||
if self.LanternsMap.Up then
|
if self.LanternsMap.Up then
|
||||||
self.LanternsMap.Up.Played = false
|
self.LanternsMap.Up.Played = false
|
||||||
self:Activate(false, true, self.LanternsMap.Up)
|
self:Activate(false, true, self.LanternsMap.Up, true)
|
||||||
end
|
end
|
||||||
if self.LanternsMap.Down then
|
if self.LanternsMap.Down then
|
||||||
self.LanternsMap.Down.Played = false
|
self.LanternsMap.Down.Played = false
|
||||||
self:Activate(false, true, self.LanternsMap.Down)
|
self:Activate(false, true, self.LanternsMap.Down, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
for n: number = 1, #self.LanternsMap do
|
for n: number = 1, #self.LanternsMap do
|
||||||
local Lantern = self.LanternsMap[n]
|
local Lantern = self.LanternsMap[n]
|
||||||
|
|
||||||
self:Activate(ExcludeFloor and n == ExcludeFloor or false, false, Lantern)
|
self:Activate(ExcludeFloor and n == ExcludeFloor or false, false, Lantern, false)
|
||||||
Lantern.Played = false
|
Lantern.Played = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -128,22 +130,26 @@ end
|
|||||||
function Lanterns:DirectionUp(Enabled)
|
function Lanterns:DirectionUp(Enabled)
|
||||||
if self.LanternsMap.Up and not self.LanternsMap.Up.Played then
|
if self.LanternsMap.Up and not self.LanternsMap.Up.Played then
|
||||||
self.LanternsMap.Up.Played = true
|
self.LanternsMap.Up.Played = true
|
||||||
self:Activate(Enabled, true, self.LanternsMap.Up)
|
self:Activate(Enabled, true, self.LanternsMap.Up, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Lanterns:DirectionDown(Enabled)
|
function Lanterns:DirectionDown(Enabled)
|
||||||
if self.LanternsMap.Down and not self.LanternsMap.Down.Played then
|
if self.LanternsMap.Down and not self.LanternsMap.Down.Played then
|
||||||
self.LanternsMap.Down.Played = true
|
self.LanternsMap.Down.Played = true
|
||||||
self:Activate(Enabled, true, self.LanternsMap.Down)
|
self:Activate(Enabled, true, self.LanternsMap.Down, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Lanterns:Toggle(Enabled, Floor)
|
function Lanterns:Toggle(Enabled, Floor)
|
||||||
local f = self.LanternsMap[Floor]
|
local f = self.LanternsMap[Floor]
|
||||||
|
|
||||||
|
if not Enabled then
|
||||||
|
f.Played = false
|
||||||
|
end
|
||||||
if not f.Played then
|
if not f.Played then
|
||||||
f.Played = true
|
f.Played = true
|
||||||
self:Activate(Enabled, false, f)
|
self:Activate(Enabled, false, f, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
12
src/server/main/Elevators/Otis1960/ButtonFunctions.lua
Normal file
12
src/server/main/Elevators/Otis1960/ButtonFunctions.lua
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
--!optimize 2
|
||||||
|
--!native
|
||||||
|
--!strict
|
||||||
|
|
||||||
|
local ButtonFunctions = {}
|
||||||
|
ButtonFunctions.__index = ButtonFunctions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return ButtonFunctions
|
||||||
38
src/server/main/Elevators/Otis1960/HallDisplays.lua
Normal file
38
src/server/main/Elevators/Otis1960/HallDisplays.lua
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
--!optimize 2
|
||||||
|
--!native
|
||||||
|
--!strict
|
||||||
|
|
||||||
|
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
|
||||||
|
type Impl_Constructor = {
|
||||||
|
__index: Impl_Constructor,
|
||||||
|
constructor: Constructor_Fun,
|
||||||
|
--Class functions
|
||||||
|
BindHallDisplays: (self: ClassConstructor) -> ()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Constructor_Fun = (CurrentFloorAttribute: IntValue) -> ClassConstructor
|
||||||
|
type Constructor_Return_Props = {
|
||||||
|
CurrentFloorAttribute: IntValue,
|
||||||
|
__CurrentFloorConnection: RBXScriptConnection?
|
||||||
|
}
|
||||||
|
|
||||||
|
local HallDisplays = {} :: Impl_Constructor
|
||||||
|
HallDisplays.__index = HallDisplays
|
||||||
|
|
||||||
|
function HallDisplays.constructor(CurrentFloorAttribute)
|
||||||
|
return setmetatable({
|
||||||
|
CurrentFloorAttribute = CurrentFloorAttribute
|
||||||
|
}, HallDisplays)
|
||||||
|
end
|
||||||
|
|
||||||
|
function HallDisplays:BindHallDisplays()
|
||||||
|
if self.__CurrentFloorConnection and self.__CurrentFloorConnection.Connected then
|
||||||
|
self.__CurrentFloorConnection:Disconnect()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.__CurrentFloorConnection = self.CurrentFloorAttribute:GetPropertyChangedSignal("Value"):Connect(function()
|
||||||
|
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return HallDisplays
|
||||||
@@ -49,8 +49,11 @@ type Impl_Static_Props = {
|
|||||||
FloorLevelingDistance: number,
|
FloorLevelingDistance: number,
|
||||||
DoorOpeningDistance: number,
|
DoorOpeningDistance: number,
|
||||||
LeveledDistance: number,
|
LeveledDistance: number,
|
||||||
__Moving: boolean,
|
Attributes: {
|
||||||
__CurrentFloor: number
|
PassingFloor: IntValue,
|
||||||
|
Moving: BoolValue,
|
||||||
|
CurrentFloor: IntValue
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
type Constructor_Fun = (TagsConstructor: TagsConstructor, ButtonsTags: Tags.ElevatorButtons, LanternsTags: Tags.Lanterns, LandingDoors: Tags.LandingTags) -> ClassConstructor
|
type Constructor_Fun = (TagsConstructor: TagsConstructor, ButtonsTags: Tags.ElevatorButtons, LanternsTags: Tags.Lanterns, LandingDoors: Tags.LandingTags) -> ClassConstructor
|
||||||
@@ -96,9 +99,18 @@ Otis1960.LanternDisplayColorOn = Color3.fromRGB(255,114,71)
|
|||||||
Otis1960.LanternDisplayColorOff = Color3.fromRGB(55,55,55)
|
Otis1960.LanternDisplayColorOff = Color3.fromRGB(55,55,55)
|
||||||
Otis1960.LanternChimeDirection = "rbxassetid://16990287228"
|
Otis1960.LanternChimeDirection = "rbxassetid://16990287228"
|
||||||
Otis1960.LanternChimeLanding = "rbxassetid://16990290265"
|
Otis1960.LanternChimeLanding = "rbxassetid://16990290265"
|
||||||
--*read-only*
|
|
||||||
Otis1960.__Moving = false
|
Otis1960.Attributes = {
|
||||||
Otis1960.__CurrentFloor = 1
|
PassingFloor = Instance.new("IntValue") :: IntValue,
|
||||||
|
Moving = Instance.new("BoolValue") :: BoolValue,
|
||||||
|
CurrentFloor = Instance.new("IntValue") :: IntValue
|
||||||
|
}
|
||||||
|
|
||||||
|
Otis1960.Attributes.PassingFloor.Value = 1
|
||||||
|
Otis1960.Attributes.Moving.Value = false
|
||||||
|
Otis1960.Attributes.CurrentFloor.Value = 1
|
||||||
|
|
||||||
|
local Attributes = Otis1960.Attributes
|
||||||
|
|
||||||
local ButtonFunctions: ButtonFunctions = {
|
local ButtonFunctions: ButtonFunctions = {
|
||||||
[Enums.ButtonTree.Landing] = function(self, ButtonName, ButtonsConstructor, ButtonTree)
|
[Enums.ButtonTree.Landing] = function(self, ButtonName, ButtonsConstructor, ButtonTree)
|
||||||
@@ -116,12 +128,12 @@ local ButtonFunctions: ButtonFunctions = {
|
|||||||
task.spawn(function()
|
task.spawn(function()
|
||||||
ButtonsConstructor:AestheticActivateButton(ButtonTree.Inst :: BasePart, Otis1960.ButtonActivatedColor)
|
ButtonsConstructor:AestheticActivateButton(ButtonTree.Inst :: BasePart, Otis1960.ButtonActivatedColor)
|
||||||
|
|
||||||
if DecodedFloor == Otis1960.__CurrentFloor then
|
if DecodedFloor == Attributes.CurrentFloor.Value then
|
||||||
ButtonsConstructor:DeactivateButton(ButtonTree.Inst :: BasePart, Otis1960.ButtonDeactivatedColor)
|
ButtonsConstructor:DeactivateButton(ButtonTree.Inst :: BasePart, Otis1960.ButtonDeactivatedColor)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
if DecodedFloor ~= Otis1960.__CurrentFloor then
|
if DecodedFloor ~= Attributes.CurrentFloor.Value then
|
||||||
self:GoToLevel(DecodedFloor)
|
self:GoToLevel(DecodedFloor)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -214,51 +226,74 @@ end
|
|||||||
local function FloorLeveled(self: ClassConstructor, RequestedLevel: number)
|
local function FloorLeveled(self: ClassConstructor, RequestedLevel: number)
|
||||||
(self.__MovingConnection :: RBXScriptConnection):Disconnect()
|
(self.__MovingConnection :: RBXScriptConnection):Disconnect()
|
||||||
|
|
||||||
Otis1960.__Moving = false
|
Attributes.Moving.Value = false
|
||||||
Otis1960.__CurrentFloor = RequestedLevel
|
Attributes.CurrentFloor.Value = RequestedLevel
|
||||||
self.BoxAlignPosition.MaxVelocity = Otis1960.MaxVelocity
|
self.BoxAlignPosition.MaxVelocity = Otis1960.MaxVelocity
|
||||||
|
|
||||||
self.LanternsConstructor:Reset(Otis1960.__CurrentFloor)
|
self.LanternsConstructor:Reset(Attributes.CurrentFloor.Value)
|
||||||
|
end
|
||||||
|
|
||||||
|
local FloorPassingLookAhead = Attributes.CurrentFloor.Value+1
|
||||||
|
|
||||||
|
local function FloorPassingUp(self: ClassConstructor, ElevatorPositionY: number, RequestedLevel: number)
|
||||||
|
if ElevatorPositionY>=Leveling[FloorPassingLookAhead] then
|
||||||
|
FloorPassingLookAhead+=1
|
||||||
|
Attributes.CurrentFloor.Value+=1
|
||||||
|
|
||||||
|
if Attributes.CurrentFloor.Value ~= RequestedLevel then
|
||||||
|
self.LanternsConstructor:Toggle(true, Attributes.CurrentFloor.Value)
|
||||||
|
self.LanternsConstructor:Toggle(false, Attributes.CurrentFloor.Value-1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function FloorPassingDown(self: ClassConstructor, ElevatorPositionY: number, RequestedLevel: number)
|
||||||
|
--Attributes.CurrentFloor.Value -= 1
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Otis1960:__MoveFloors(GoalLevelVEC, RequestedLevel, GoingUp)
|
function Otis1960:__MoveFloors(GoalLevelVEC, RequestedLevel, GoingUp)
|
||||||
self.ElevatorDoors:ToggleElevatorDoors(false, Otis1960.__CurrentFloor)
|
self.ElevatorDoors:ToggleElevatorDoors(false, Attributes.CurrentFloor.Value)
|
||||||
|
|
||||||
local Delta = 0
|
|
||||||
local DoorsOpeningEvent = false
|
|
||||||
local ElevatorBoxCurrentPos = self.ElevatorBox_1960.Position
|
|
||||||
|
|
||||||
if self.__MovingConnection and self.__MovingConnection.Connected then
|
if self.__MovingConnection and self.__MovingConnection.Connected then
|
||||||
self.__MovingConnection:Disconnect()
|
self.__MovingConnection:Disconnect()
|
||||||
end
|
end
|
||||||
|
|
||||||
self.MOConstructor:UpdateCFrame()
|
|
||||||
|
|
||||||
if GoingUp then
|
if GoingUp then
|
||||||
self.LanternsConstructor:DirectionUp(true)
|
self.LanternsConstructor:DirectionUp(true)
|
||||||
else
|
else
|
||||||
self.LanternsConstructor:DirectionDown(true)
|
self.LanternsConstructor:DirectionDown(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.MOConstructor:UpdateCFrame()
|
||||||
|
|
||||||
|
local Delta = 0
|
||||||
|
local DoorsOpeningEvent = false
|
||||||
|
local ElevatorBoxCurrentPos = self.ElevatorBox_1960.Position
|
||||||
|
|
||||||
|
FloorPassingLookAhead = Attributes.CurrentFloor.Value
|
||||||
|
|
||||||
--Otis1960_ShaftGovernor
|
--Otis1960_ShaftGovernor
|
||||||
self.__MovingConnection = RS.Heartbeat:Connect(function(_dt) --Not safe for parallel
|
self.__MovingConnection = RS.Heartbeat:Connect(function(_dt)
|
||||||
Delta+=1
|
Delta+=1
|
||||||
Otis1960.__Moving = true
|
Attributes.Moving.Value = true
|
||||||
|
|
||||||
local ElevatorPosition: Vector3 = self.ElevatorBox_1960.Position
|
local ElevatorPosition: Vector3 = self.ElevatorBox_1960.Position
|
||||||
local ElevatorPositionY: number = ElevatorPosition.Y
|
local ElevatorPositionY: number = ElevatorPosition.Y
|
||||||
local BoxAlignY: number = self.BoxAlignPosition.Position.Y
|
local BoxAlignY: number = self.BoxAlignPosition.Position.Y
|
||||||
local ElevatorVelocityY: number = self.ElevatorBox_1960:GetVelocityAtPosition(ElevatorPosition).Y
|
local ElevatorVelocityY: number = self.ElevatorBox_1960:GetVelocityAtPosition(ElevatorPosition).Y
|
||||||
|
|
||||||
|
self.TractionRopes:Move(27, self.ElevatorBox_1960.Position)
|
||||||
self.MOConstructor:Frame_Pullies(Delta, ElevatorVelocityY)
|
self.MOConstructor:Frame_Pullies(Delta, ElevatorVelocityY)
|
||||||
self.TractionRopes:Move(27, ElevatorPosition)
|
|
||||||
|
|
||||||
--Kill the connection
|
--Kill the connection
|
||||||
if GoingUp then
|
if GoingUp then
|
||||||
|
FloorPassingUp(self, ElevatorPositionY, RequestedLevel)
|
||||||
|
|
||||||
if ElevatorPositionY>=BoxAlignY-Otis1960.FloorLevelingDistance then
|
if ElevatorPositionY>=BoxAlignY-Otis1960.FloorLevelingDistance then
|
||||||
FloorLeveling(self, RequestedLevel)
|
FloorLeveling(self, RequestedLevel)
|
||||||
|
|
||||||
if ElevatorPositionY>=BoxAlignY-Otis1960.DoorOpeningDistance and not DoorsOpeningEvent then
|
if not DoorsOpeningEvent and ElevatorPositionY>=BoxAlignY-Otis1960.DoorOpeningDistance then
|
||||||
DoorsOpeningEvent = true
|
DoorsOpeningEvent = true
|
||||||
self.ElevatorDoors:ToggleElevatorDoors(true, RequestedLevel)
|
self.ElevatorDoors:ToggleElevatorDoors(true, RequestedLevel)
|
||||||
end
|
end
|
||||||
@@ -268,10 +303,12 @@ function Otis1960:__MoveFloors(GoalLevelVEC, RequestedLevel, GoingUp)
|
|||||||
FloorLeveled(self, RequestedLevel)
|
FloorLeveled(self, RequestedLevel)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
FloorPassingDown(self, ElevatorPositionY, RequestedLevel)
|
||||||
|
|
||||||
if ElevatorPositionY<=BoxAlignY+Otis1960.FloorLevelingDistance then
|
if ElevatorPositionY<=BoxAlignY+Otis1960.FloorLevelingDistance then
|
||||||
FloorLeveling(self, RequestedLevel)
|
FloorLeveling(self, RequestedLevel)
|
||||||
|
|
||||||
if ElevatorPositionY>=BoxAlignY-Otis1960.DoorOpeningDistance and not DoorsOpeningEvent then
|
if not DoorsOpeningEvent and ElevatorPositionY>=BoxAlignY-Otis1960.DoorOpeningDistance then
|
||||||
DoorsOpeningEvent = true
|
DoorsOpeningEvent = true
|
||||||
self.ElevatorDoors:ToggleElevatorDoors(true, RequestedLevel)
|
self.ElevatorDoors:ToggleElevatorDoors(true, RequestedLevel)
|
||||||
end
|
end
|
||||||
@@ -289,12 +326,12 @@ end
|
|||||||
function Otis1960:GoToLevel(RequestedLevel)
|
function Otis1960:GoToLevel(RequestedLevel)
|
||||||
local GoalLevelVEC: number = Leveling[RequestedLevel]
|
local GoalLevelVEC: number = Leveling[RequestedLevel]
|
||||||
|
|
||||||
if GoalLevelVEC and GoalLevelVEC ~= 0 and GoalLevelVEC ~= Otis1960.__CurrentFloor then
|
if GoalLevelVEC and GoalLevelVEC ~= Attributes.CurrentFloor.Value then
|
||||||
local GoingUp: boolean = -(Otis1960.__CurrentFloor-RequestedLevel)>0 --My clever math function for determining if the elevator goal is to move upwards or not
|
local GoingUp: boolean = -(Attributes.CurrentFloor.Value-RequestedLevel)>0 --My clever math function for determining if the elevator goal is to move upwards or not
|
||||||
|
|
||||||
self:__MoveFloors(GoalLevelVEC, RequestedLevel, GoingUp)
|
self:__MoveFloors(GoalLevelVEC, RequestedLevel, GoingUp)
|
||||||
else
|
else
|
||||||
warn(`[{Enums.Elevator.Otis1960}]: landing out of range or equals the same range as goal! requested landing: {tostring(RequestedLevel)}`)
|
warn(`[{Enums.Elevator.Otis1960}]: landing out of range or equals the same range as the goal, requested landing: {tostring(RequestedLevel)}`)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -151,9 +151,7 @@ function Tags:Request(Name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Tags:Nuke()
|
function Tags:Nuke()
|
||||||
local Exports = self.__export
|
for i: string, v: TagProduct in self.__export do
|
||||||
|
|
||||||
for i: string, v: TagProduct in Exports do
|
|
||||||
if type(v) == "table" then
|
if type(v) == "table" then
|
||||||
for n: number = 1, #v do
|
for n: number = 1, #v do
|
||||||
CS:RemoveTag(v[n], i)
|
CS:RemoveTag(v[n], i)
|
||||||
@@ -276,7 +274,6 @@ function Tags:__ElevatorDoors()
|
|||||||
if not Doors[ModelHint][FloorNumber] then
|
if not Doors[ModelHint][FloorNumber] then
|
||||||
Doors[ModelHint][FloorNumber] = {}
|
Doors[ModelHint][FloorNumber] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
if typeof(Inst) ~= "Instance" then
|
if typeof(Inst) ~= "Instance" then
|
||||||
Inst = Inst[1]
|
Inst = Inst[1]
|
||||||
warn(`[{ModelHint}] Door {Inst} was not a single instance, duplicate doors detected Tag={TagName}`)
|
warn(`[{ModelHint}] Door {Inst} was not a single instance, duplicate doors detected Tag={TagName}`)
|
||||||
|
|||||||
@@ -2,12 +2,10 @@
|
|||||||
--!native
|
--!native
|
||||||
--!strict
|
--!strict
|
||||||
|
|
||||||
--[[
|
local function MakeEvent<T,U>()
|
||||||
Module.Property = Property.constructor()
|
|
||||||
]]
|
|
||||||
|
|
||||||
local function Property<T>()
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return Property
|
return {
|
||||||
|
MakeEvent = MakeEvent
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user