diff --git a/src/client/Character/Client/init.client.lua b/src/client/Character/Client/init.client.lua index cedf364..35f12e2 100644 --- a/src/client/Character/Client/init.client.lua +++ b/src/client/Character/Client/init.client.lua @@ -105,7 +105,7 @@ HumanoidSettings:SetWalkSpeed() HumanoidSettings:SetJumpHeight() HRPSettings:DisableRobloxSounds() CameraConsturctor:EnableBobbing() -SpineMovement:Enable() +--SpineMovement:Enable() ClientCharacterBinds() Crosshair3DVelocity_Effect() diff --git a/src/server/main/Elevators/Buttons.lua b/src/server/main/Elevators/Buttons.lua index b852048..8310589 100644 --- a/src/server/main/Elevators/Buttons.lua +++ b/src/server/main/Elevators/Buttons.lua @@ -7,31 +7,23 @@ local Elevators = script.Parent local RS: ReplicatedStorage = game:GetService("ReplicatedStorage") local TagsModule = require(RS:WaitForChild("Tags")) -local Enums = require(Elevators:WaitForChild("Enums")) +local Enums = require(Elevators:WaitForChild("Enums")) -type Tags = TagsModule.ExportedTags +type Tags = TagsModule.ExportedTags +type HumanoidRootPart = BasePart +type PromptCallback = (Player: Player) -> () type GetButtons = {[string]: Instance} -type ButtonProperties = { - Inst: Instance?, - Prompt: ProximityPrompt? -} -type ButtonsTree = { - Landing: ButtonProperties, - Car: ButtonProperties, - Special: ButtonProperties, - Relays: ButtonProperties, - Unknown: ButtonProperties -} type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor)) type Impl_Constructor = { __index: Impl_Constructor, constructor: Constructor_Fun, --Class functions - Get: (self: ClassConstructor) -> GetButtons, - CreatePromptButtons: (self: ClassConstructor) -> ButtonsTree, - HookPromptButtonsGroup: (self: ClassConstructor) -> () + DecodeCarTag: (self: ClassConstructor, FloorTag: string) -> number?, + Get: (self: ClassConstructor) -> GetButtons, + CreatePromptButtons: (self: ClassConstructor) -> ButtonsTree, + HookPromptButtonsGroup: (self: ClassConstructor, Prompt: ProximityPrompt, Inst: BasePart, PromptCallback: PromptCallback) -> () } & Impl_Static_Props type Impl_Static_Props = { @@ -45,6 +37,19 @@ type Constructor_Return_Props = { Buttons: ButtonsTree } +export type ButtonsTree = { + Landing: ButtonProperties, + Car: ButtonProperties, + Special: ButtonProperties, + Relays: ButtonProperties +} +export type ButtonProperties = { + Inst: Instance?, + Prompt: ProximityPrompt?, + Attachment: Attachment? +} +export type ButtonsConstructor = ClassConstructor + local ButtonsModule = {} :: Impl_Constructor ButtonsModule.__index = ButtonsModule @@ -56,14 +61,18 @@ function ButtonsModule.constructor(Tags, Model) Landing = {}, Car = {}, Special = {}, - Relays = {}, - Unknown = {} + Relays = {} } }, ButtonsModule) end --Button parsing +function ButtonsModule:DecodeCarTag(FloorTag) + local Match = FloorTag:match('%d+$') + return Match and tonumber(Match) +end + function ButtonsModule:Get() local Buttons: GetButtons = {} @@ -94,59 +103,74 @@ function ButtonsModule:CreatePromptButtons() Attachment.Parent = Inst local Prompt = Instance.new("ProximityPrompt") :: ProximityPrompt Prompt.MaxActivationDistance = 3 + Prompt.HoldDuration = .30 Prompt.Parent = Attachment local Split = TagName:split('_') local ButtonType = if tonumber(Split[3]) then - Enums.Buttons.Car + Enums.Button.Car elseif Split[3] == "Floor" and Split[4]:match('%d') then - Enums.Buttons.Landing + Enums.Button.Landing elseif Split[2] == "ElevatorButton" then - Enums.Buttons.Special + Enums.Button.Special elseif Split[2] == "RelayButton" then - Enums.Buttons.Relay + Enums.Button.Relay else nil - if ButtonType == Enums.Buttons.Car then + if ButtonType == Enums.Button.Car then --ElevatorButton_1 + Prompt.ActionText = tostring(Split[3]) + Prompt.ObjectText = "Floor" + self.Buttons.Car[`{Split[2]}_{Split[3]}`] = { Inst = Inst, - Prompt = Prompt + Prompt = Prompt, + Attachment = Attachment } - Prompt.ActionText = tostring(Split[3]) - Prompt.ObjectText = "Floor" - elseif ButtonType == Enums.Buttons.Landing then + elseif ButtonType == Enums.Button.Landing then --ElevatorButton_Floor_1_Up + Prompt.ActionText = tostring(Split[5]) + Prompt.ObjectText = `Floor {tostring(Split[4])}` + self.Buttons.Landing[`{Split[2]}_{Split[3]}_{Split[4]}_{Split[5]}`] = { Inst = Inst, - Prompt = Prompt + Prompt = Prompt, + Attachment = Attachment } - Prompt.ActionText = tostring(Split[5]) - Prompt.ObjectText = `Floor {tostring(Split[4])}` - elseif ButtonType == Enums.Buttons.Special then + elseif ButtonType == Enums.Button.Special then --ElevatorButton_Open + Prompt.ActionText = tostring(Split[3]) + Prompt.ObjectText = "Floor" + self.Buttons.Special[`{Split[2]}_{Split[3]}`] = { Inst = Inst, - Prompt = Prompt + Prompt = Prompt, + Attachment = Attachment } - Prompt.ActionText = tostring(Split[3]) - Prompt.ObjectText = "Floor" - elseif ButtonType == Enums.Buttons.Relay then + elseif ButtonType == Enums.Button.Relay then --RelayButton_F1 - Attachment.Position-=Vector3.new(.1,.3,0) + if self.Model == Enums.Elevator.Otis1960 then --This is bad... + Attachment.Position-=Vector3.new(.1,.3,0) + end + + Prompt.MaxActivationDistance = 4 + Prompt.Exclusivity = Enum.ProximityPromptExclusivity.OneGlobally --why does this not work... + Prompt.ActionText = `Relay {tostring(Split[3])}` + Prompt.ObjectText = "Activate" self.Buttons.Relays[`{Split[2]}_{Split[3]}`] = { Inst = Inst, - Prompt = Prompt + Prompt = Prompt, + Attachment = Attachment } - Prompt.ActionText = `Relay {tostring(Split[3])}` - Prompt.ObjectText = "Activate" else + Attachment:Destroy() + Prompt:Destroy() warn(`{self.Model}: Door tag was present but couldnt specify its type for use "{TagName}"`) end @@ -156,8 +180,19 @@ function ButtonsModule:CreatePromptButtons() return self.Buttons end -function ButtonsModule:HookPromptButtonsGroup() +function ButtonsModule:HookPromptButtonsGroup(Prompt, Inst, PromptCallback) + Prompt.Triggered:Connect(function(Player) + local PlayerCharacter = Player.Character + local Root = PlayerCharacter and PlayerCharacter:FindFirstChild("HumanoidRootPart") :: HumanoidRootPart? + if Root then + if (Root.Position-Inst.Position).Magnitude<=Prompt.MaxActivationDistance+1 then + PromptCallback(Player) + else + warn(`{Player.Name}, {Player.UserId} activated a prompt without being in range of MaxActivationDistance.`) + end + end + end) end return ButtonsModule \ No newline at end of file diff --git a/src/server/main/Elevators/Enums.lua b/src/server/main/Elevators/Enums.lua index cf80a5e..7f2c264 100644 --- a/src/server/main/Elevators/Enums.lua +++ b/src/server/main/Elevators/Enums.lua @@ -2,17 +2,30 @@ --!native --!strict + local Enums = {} -Enums.Buttons = { - Car = "CarButton", - Landing = "LandingButton", - Special = "SpecialButton", - Relay = "RelayButton" +export type EnumValue = typeof(Enums.Button) + | typeof(Enums.ButtonTree) + | typeof(Enums.Elevator) + +Enums.Button = { + Car = "CarButton" :: "CarButton", + Landing = "LandingButton" :: "LandingButton", + Special = "SpecialButton" :: "SpecialButton", + Relay = "RelayButton" :: "RelayButton" } -Enums.Elevators = { - Otis1960 = "Otis1960" +Enums.ButtonTree = { + Car = "Car" :: "Car", + Landing = "Landing" :: "Landing", + Special = "Special" :: "Special", + Relays = "Relays" :: "Relays", + Unknown = "Unknown" :: "Unknown" +} + +Enums.Elevator = { + Otis1960 = "Otis1960" :: "Otis1960" } return Enums \ No newline at end of file diff --git a/src/server/main/Elevators/Otis1960/Leveling.lua b/src/server/main/Elevators/Otis1960/Leveling.lua index 7baac8d..c7ba571 100644 --- a/src/server/main/Elevators/Otis1960/Leveling.lua +++ b/src/server/main/Elevators/Otis1960/Leveling.lua @@ -2,9 +2,9 @@ --!native --!strict -local Leveling: {[number]: number} = { - [1] = 13.031, - [2] = 0, +local Leveling: {number} = { + [1] = 13.041, + [2] = 37.973, [3] = 0, [4] = 0, [5] = 0, diff --git a/src/server/main/Elevators/Otis1960/init.lua b/src/server/main/Elevators/Otis1960/init.lua index 94010ad..4228102 100644 --- a/src/server/main/Elevators/Otis1960/init.lua +++ b/src/server/main/Elevators/Otis1960/init.lua @@ -4,8 +4,10 @@ local Elevators = script.Parent -local RS: ReplicatedStorage = game:GetService("ReplicatedStorage") -local TagsModule = require(RS:WaitForChild("Tags")) +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")) @@ -21,29 +23,95 @@ type Impl_Constructor = { __index: Impl_Constructor, constructor: Constructor_Fun, --Class functions - MoveFloors: (self: ClassConstructor, Level: number) -> (), - GoToLevel: (self: ClassConstructor, RequestedLevel: number) -> () + __MoveFloors: (self: ClassConstructor, Level: number) -> (), + GoToLevel: (self: ClassConstructor, RequestedLevel: number) -> () +} & Impl_Static_Props + +type Impl_Static_Props = { + Moving: boolean } type Constructor_Fun = (Tags: Tags) -> ClassConstructor type Constructor_Return_Props = { - ElevatorBox_1960: BasePart, - ElevatorBox: BasePart, - ElevatorDoor1: BasePart, - ElevatorDoor2: BasePart, - ElevatorDoorSensor: Folder, - ProximityButtons: {Instance}, - BoxAttachment: Attachment, - BoxAlignPosition: AlignPosition, + Tags: Tags, + ElevatorBox_1960: BasePart, + ElevatorBox: BasePart, + ElevatorDoor1: BasePart, + ElevatorDoor2: BasePart, + ElevatorDoorSensor: Folder, + ProximityButtons: {Instance}, + BoxAttachment: Attachment, + BoxAlignPosition: AlignPosition, BoxAlignOrientation: AlignOrientation, - ElevatorDoors: Doors.DoorConstructor, + ElevatorDoors: Doors.DoorConstructor, } local Otis1960 = {} :: Impl_Constructor Otis1960.__index = Otis1960 +Otis1960.Moving = false + +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 :: BasePart self.ElevatorBox = Tags.ElevatorMover_1960 :: BasePart self.ElevatorDoor1 = Tags.ElevatorDoor_1960_1 :: BasePart @@ -55,23 +123,40 @@ function Otis1960.constructor(Tags) self.ElevatorDoors = Doors.constructor(self.ElevatorBox, self.ElevatorDoor1, self.ElevatorDoor2, self.ElevatorDoorSensor) --Buttons - local Buttons = ButtonTags.constructor(Tags, Enums.Elevators.Otis1960) - local Otis1960_Buttons = Buttons:CreatePromptButtons() + 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 setmetatable(self, Otis1960) + return ClassConstructor end -function Otis1960:MoveFloors(Level) +local BiggestRopeLength = Leveling[#Leveling]-2 + +function Otis1960:__MoveFloors(Level) local ElevatorBoxCurrentPos = self.ElevatorBox.Position + + local RopeConnection = RS.Heartbeat:Connect(function(_dt) + local Ropes = self.Tags["1960_ElevatorPulleyRope"] :: {Instance} + + for i: number = 1, #Ropes do + (Ropes[i] :: RopeConstraint).Length = (BiggestRopeLength-self.ElevatorBox.Position.Y)*10 + print((Ropes[i] :: RopeConstraint).Length) + end + end) + self.BoxAlignPosition.Position = Vector3.new(ElevatorBoxCurrentPos.X, Level, ElevatorBoxCurrentPos.Z) end function Otis1960:GoToLevel(RequestedLevel) local level: number = Leveling[RequestedLevel] - if level then - self:MoveFloors(level) + if level and level ~= 0 then + self:__MoveFloors(level) + else + warn(`[{Enums.Elevator.Otis1960}]: landing out of range! requested landing: {tostring(RequestedLevel)}`) end end