mirror of
https://github.com/unixtensor/Roblox-Elevator-Game.git
synced 2026-02-03 21:36:49 +00:00
big commit
This commit is contained in:
114
src/client/Character/Client/Camera/Bobbing.lua
Normal file
114
src/client/Character/Client/Camera/Bobbing.lua
Normal file
@@ -0,0 +1,114 @@
|
||||
local Bobbing = {}
|
||||
Bobbing.__index = Bobbing
|
||||
|
||||
Bobbing.TurnAlpha = 0.050
|
||||
Bobbing.LeanMultiplier = 1.7
|
||||
Bobbing.SwayMultiplier = 1.5
|
||||
Bobbing.AnimationAlpha = 0.5
|
||||
Bobbing.MaxGimbalLockY = 65
|
||||
Bobbing.AnimationSpeed = 200
|
||||
Bobbing.Tick = 0
|
||||
Bobbing.ForceStop = false
|
||||
|
||||
type AnimationsMap = {[string]: (tick: number, dt: number) -> Euler}
|
||||
|
||||
local Animations: AnimationsMap = {}
|
||||
|
||||
type Euler = CFrame
|
||||
type HumanoidRootPart = BasePart
|
||||
|
||||
local UIS = game:GetService("UserInputService")
|
||||
|
||||
local CN = CFrame.new
|
||||
local ANG = CFrame.Angles
|
||||
local CameraLean = CN()
|
||||
local Animation = CN()
|
||||
|
||||
function Bobbing.constructor(HumanoidRootPart: HumanoidRootPart, CurrentCamera: Camera, Humanoid: Humanoid)
|
||||
return setmetatable({
|
||||
HumanoidRootPart = HumanoidRootPart,
|
||||
CurrentCamera = CurrentCamera,
|
||||
Humanoid = Humanoid
|
||||
}, Bobbing)
|
||||
end
|
||||
|
||||
type deltatime = number
|
||||
type tick = number
|
||||
type EulerValue = number
|
||||
|
||||
function Animations.Idle(t: tick, dt: deltatime)
|
||||
return ANG(
|
||||
math.rad(math.cos(t/80)/(Bobbing.AnimationSpeed+50)),
|
||||
math.rad(math.sin(t/50)/Bobbing.AnimationSpeed),
|
||||
math.rad(math.sin(t/70)/(Bobbing.AnimationSpeed-50))
|
||||
)
|
||||
end
|
||||
|
||||
function Animations.Walk(t: tick, dt: deltatime)
|
||||
-- return ANG(
|
||||
-- math.rad(-10*math.cos(t)/2),
|
||||
-- 0,
|
||||
-- math.rad(5*math.cos(t)/2)
|
||||
-- )
|
||||
return ANG(
|
||||
0,
|
||||
0,
|
||||
0
|
||||
)
|
||||
end
|
||||
|
||||
function Animations.Stop()
|
||||
return ANG(0,0,0)
|
||||
end
|
||||
|
||||
function Animations.Falling()
|
||||
return ANG(0,0,0)
|
||||
end
|
||||
|
||||
local function maxmin(min: number, mid: number, max: number): number
|
||||
return math.max(min, math.min(mid, max))
|
||||
end
|
||||
|
||||
local function Camera_YArc(Camera: Camera): EulerValue --stop Euler gimbal lock when you're looking directly up or down
|
||||
local EulerY,_,_ = Camera.CFrame.Rotation:ToEulerAnglesYXZ()
|
||||
return math.abs(math.deg(EulerY))
|
||||
end
|
||||
|
||||
local function CameraAnimation(self, dt: deltatime)
|
||||
--crying
|
||||
Bobbing.Tick += 1
|
||||
|
||||
local Root: BasePart = self.HumanoidRootPart
|
||||
local Velocity: Vector3 = Root:GetVelocityAtPosition(Root.Position)
|
||||
local RootMagnitude: number = Velocity.Magnitude
|
||||
|
||||
--go go boolean algebra
|
||||
local MaxMinY: boolean = Camera_YArc(self.CurrentCamera)>Bobbing.MaxGimbalLockY --TODO: instead, make this an equation so it will just subtract from the existing animation radians
|
||||
local ForceStop: boolean = Bobbing.ForceStop and "Stop"
|
||||
local AnimationType: string = ForceStop or RootMagnitude>1 and "Walk" or (not MaxMinY and "Idle" or "Stop")
|
||||
local CurrentAnimation: CFrame = Animations[AnimationType](Bobbing.Tick, dt)
|
||||
|
||||
--"Lerp" so the transitions between walking and idling are smoothed instead of instant
|
||||
return Animation:Lerp(CurrentAnimation, Bobbing.AnimationAlpha)
|
||||
end
|
||||
|
||||
function Bobbing:Frame(dt: number)
|
||||
local Camera = self.CurrentCamera
|
||||
local Humanoid = self.Humanoid
|
||||
|
||||
local CameraCF = Camera.CFrame
|
||||
Animation = CameraAnimation(self, dt)
|
||||
|
||||
--Lean the camera based on looking and moving direction(s)
|
||||
local MouseDelta = UIS:GetMouseDelta()
|
||||
local LeanDegree_Roll = -CameraCF.RightVector:Dot(Humanoid.MoveDirection)*Bobbing.LeanMultiplier
|
||||
--Jump?!
|
||||
--local LeanDegree_Pitch = -CameraCF.UpVector:Dot(Humanoid.MoveDirection)*Bobbing.LeanMultiplier
|
||||
|
||||
local LeanMult_Roll = maxmin(-Bobbing.SwayMultiplier, LeanDegree_Roll-MouseDelta.X, Bobbing.SwayMultiplier)
|
||||
CameraLean = CameraLean:Lerp(ANG(0, 0, math.rad(LeanMult_Roll)), Bobbing.TurnAlpha)
|
||||
|
||||
Camera.CFrame *= Animation*CameraLean
|
||||
end
|
||||
|
||||
return Bobbing
|
||||
41
src/client/Character/Client/Camera/init.lua
Normal file
41
src/client/Character/Client/Camera/init.lua
Normal file
@@ -0,0 +1,41 @@
|
||||
local Camera = {}
|
||||
local FakeCamera = {}
|
||||
Camera.__index = Camera
|
||||
FakeCamera.__index = FakeCamera
|
||||
|
||||
local RS = game:GetService("RunService")
|
||||
local Bobbing = require(script:WaitForChild("Bobbing"))
|
||||
|
||||
type FakeCamera = BasePart
|
||||
|
||||
function Camera.constructor(CurrentCamera: Camera, HumanoidRootPart: BasePart, Humanoid: Humanoid)
|
||||
local self = {}
|
||||
self.CameraFPS = false
|
||||
self.CurrentCamera = CurrentCamera
|
||||
self.HumanoidRootPart = HumanoidRootPart
|
||||
self.BobbingCamera = Bobbing.constructor(HumanoidRootPart, CurrentCamera, Humanoid)
|
||||
return setmetatable(self, Camera)
|
||||
end
|
||||
|
||||
function Camera:EnableBobbing()
|
||||
if not self.CameraFPS then
|
||||
RS:BindToRenderStep("CameraAnimations", Enum.RenderPriority.Camera.Value+1, function(dt)
|
||||
self.BobbingCamera:Frame(dt)
|
||||
end)
|
||||
self.CameraFPS = true
|
||||
else
|
||||
print("Character Camera: Cannot call EnableBobbing while its active", debug.traceback())
|
||||
end
|
||||
end
|
||||
|
||||
function Camera:DisableBobbing()
|
||||
if self.CameraFPS then
|
||||
RS:UnbindFromRenderStep("CameraAnimations")
|
||||
self.CameraFPS = false
|
||||
else
|
||||
print("Character Camera: DisableBobbing was called before EnableBobbing", debug.traceback())
|
||||
end
|
||||
self.CurrentCamera.CFrame *= CFrame.Angles(0,0,0)
|
||||
end
|
||||
|
||||
return Camera
|
||||
37
src/client/Character/Client/Crouch.lua
Normal file
37
src/client/Character/Client/Crouch.lua
Normal file
@@ -0,0 +1,37 @@
|
||||
local CrouchModule = {
|
||||
StandHeight = 2.1,
|
||||
CrouchHeight = .6,
|
||||
WalkSpeedMultiplier = 6,
|
||||
CrouchSpeed = .2
|
||||
}
|
||||
CrouchModule.__index = CrouchModule
|
||||
|
||||
local Tween = require(game:GetService("ReplicatedStorage"):WaitForChild("Tween"))
|
||||
|
||||
function CrouchModule.constructor(Humanoid: Humanoid)
|
||||
return setmetatable({
|
||||
Humanoid = Humanoid
|
||||
}, CrouchModule)
|
||||
end
|
||||
|
||||
local CrouchTween = Tween.constructor()
|
||||
|
||||
function CrouchModule:Crouch(StandingWalkSpeed: number)
|
||||
local Easing = TweenInfo.new(CrouchModule.CrouchSpeed, Enum.EasingStyle.Linear)
|
||||
|
||||
CrouchTween:Start(self.Humanoid, {
|
||||
HipHeight = CrouchModule.CrouchHeight,
|
||||
WalkSpeed = math.max(1, StandingWalkSpeed-CrouchModule.WalkSpeedMultiplier)
|
||||
}, Easing)
|
||||
end
|
||||
|
||||
function CrouchModule:Stand(CrouchingWalkSpeed: number)
|
||||
local Easing = TweenInfo.new(CrouchModule.CrouchSpeed, Enum.EasingStyle.Linear)
|
||||
|
||||
CrouchTween:Start(self.Humanoid, {
|
||||
HipHeight = CrouchModule.StandHeight,
|
||||
WalkSpeed = math.max(1, CrouchingWalkSpeed+CrouchModule.WalkSpeedMultiplier)
|
||||
}, Easing)
|
||||
end
|
||||
|
||||
return CrouchModule
|
||||
21
src/client/Character/Client/Humanoid.lua
Normal file
21
src/client/Character/Client/Humanoid.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
local HumanoidModule = {}
|
||||
HumanoidModule.__index = HumanoidModule
|
||||
|
||||
type WalkSpeed = number?
|
||||
type JumpHeight = number?
|
||||
|
||||
function HumanoidModule.constructor(Humanoid: Humanoid)
|
||||
return setmetatable({
|
||||
Humanoid = Humanoid
|
||||
}, HumanoidModule)
|
||||
end
|
||||
|
||||
function HumanoidModule:SetWalkSpeed(Speed: WalkSpeed)
|
||||
self.Humanoid.WalkSpeed = Speed or 10
|
||||
end
|
||||
|
||||
function HumanoidModule:SetJumpHeight(Height: JumpHeight)
|
||||
self.Humanoid.JumpHeight = Height or 7.2
|
||||
end
|
||||
|
||||
return HumanoidModule
|
||||
21
src/client/Character/Client/HumanoidRootPart.lua
Normal file
21
src/client/Character/Client/HumanoidRootPart.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
local HumanoidRPSettings = {}
|
||||
HumanoidRPSettings.__index = HumanoidRPSettings
|
||||
|
||||
function HumanoidRPSettings.constructor(HumanoidRootPart: BasePart)
|
||||
return setmetatable({
|
||||
HumanoidRootPart = HumanoidRootPart
|
||||
}, HumanoidRPSettings)
|
||||
end
|
||||
|
||||
function HumanoidRPSettings:DisableRobloxSounds()
|
||||
local HRP_objects = self.HumanoidRootPart:GetChildren()
|
||||
for i = 1, #HRP_objects do
|
||||
local Object = HRP_objects[i]
|
||||
|
||||
if Object:IsA("Sound") then
|
||||
Object.Volume = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return HumanoidRPSettings
|
||||
46
src/client/Character/Client/SpineKinematics.lua
Normal file
46
src/client/Character/Client/SpineKinematics.lua
Normal file
@@ -0,0 +1,46 @@
|
||||
local Spine = {
|
||||
Running = false
|
||||
}
|
||||
Spine.__index = Spine
|
||||
|
||||
local Storage = game:GetService("ReplicatedStorage")
|
||||
local Players = game:GetService("Players")
|
||||
|
||||
local Delta = require(Storage:WaitForChild("Delta"))
|
||||
|
||||
local Player = Players.LocalPlayer
|
||||
local CharacterShared = _G.include(script, "CharacterShared")
|
||||
|
||||
type CurrentCamera = Camera
|
||||
|
||||
type struct_Spine = {
|
||||
Remote: UnreliableRemoteEvent,
|
||||
CurrentCamera: CurrentCamera
|
||||
}
|
||||
|
||||
type CharacterSharedFolder = Folder
|
||||
|
||||
function Spine.constructor(CurrentCamera: CurrentCamera)
|
||||
local self: struct_Spine = {}
|
||||
self.Remote = CharacterShared:WaitForChild("SpineStream")
|
||||
self.CurrentCamera = CurrentCamera
|
||||
return setmetatable(self, Spine)
|
||||
end
|
||||
|
||||
function Spine:Enable()
|
||||
Spine.Running = true
|
||||
|
||||
while Spine.Running do
|
||||
local IsFirstPerson = Player.CameraMode == Enum.CameraMode.LockFirstPerson
|
||||
self.Remote:FireServer(self.CurrentCamera.CFrame, IsFirstPerson)
|
||||
|
||||
Delta:time()
|
||||
end
|
||||
end
|
||||
|
||||
function Spine:Disable()
|
||||
Spine.Running = false
|
||||
Delta:time()
|
||||
end
|
||||
|
||||
return Spine
|
||||
63
src/client/Character/Client/init.client.lua
Normal file
63
src/client/Character/Client/init.client.lua
Normal file
@@ -0,0 +1,63 @@
|
||||
local Character = script.Parent
|
||||
local preprocessor = {}
|
||||
|
||||
type CharacterSharedFolder = Folder
|
||||
|
||||
function preprocessor.CharacterShared(): CharacterSharedFolder
|
||||
return script.Parent:WaitForChild("shared")
|
||||
end
|
||||
|
||||
_G.include = function(this: LuaSourceContainer, FunName: string, ...)
|
||||
if this:IsDescendantOf(script) then --getfenv is being removed
|
||||
local switch = preprocessor[FunName]
|
||||
return type(switch) == "function" and switch(...) or switch
|
||||
else
|
||||
warn(`Preprocessor append failed "{FunName}"`, debug.traceback())
|
||||
end
|
||||
end
|
||||
|
||||
local Storage = game:GetService("ReplicatedStorage")
|
||||
local ClientStorage = Storage:WaitForChild("Client")
|
||||
local LoadCompleted = ClientStorage:WaitForChild("LoadingComplete")
|
||||
|
||||
--We need to wait for the game to load before spamming functionality
|
||||
repeat
|
||||
local GameIsLoaded = LoadCompleted:Invoke()
|
||||
task.wait()
|
||||
until GameIsLoaded
|
||||
|
||||
local HumanoidRPSettings = require(script:WaitForChild("HumanoidRootPart"))
|
||||
local CameraModule = require(script:WaitForChild("Camera"))
|
||||
local CrouchModule = require(script:WaitForChild("Crouch"))
|
||||
local HumanoidModule = require(script:WaitForChild("Humanoid"))
|
||||
local SpineModule = require(script:WaitForChild("SpineKinematics"))
|
||||
local BindModule = require(ClientStorage:WaitForChild("KeyBinds"))
|
||||
|
||||
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
|
||||
local Humanoid = Character:WaitForChild("Humanoid")
|
||||
local CurrentCamera = workspace.CurrentCamera
|
||||
|
||||
local HRPSettings = HumanoidRPSettings.constructor(HumanoidRootPart)
|
||||
local CameraConsturctor = CameraModule.constructor(CurrentCamera, HumanoidRootPart, Humanoid)
|
||||
local HumanoidSettings = HumanoidModule.constructor(Humanoid)
|
||||
local SpineMovement = SpineModule.constructor(CurrentCamera)
|
||||
|
||||
local function CrouchFeature()
|
||||
local CrouchConstructor = CrouchModule.constructor(Humanoid)
|
||||
local CourchBindMap = BindModule.constructor()
|
||||
|
||||
CourchBindMap:AddInputBegan({Enum.KeyCode.RightControl, Enum.KeyCode.LeftControl}, function()
|
||||
CrouchConstructor:Crouch(10)
|
||||
end)
|
||||
CourchBindMap:AddInputEnded({Enum.KeyCode.RightControl, Enum.KeyCode.LeftControl}, function()
|
||||
CrouchConstructor:Stand(5)
|
||||
end)
|
||||
end
|
||||
|
||||
HumanoidSettings:SetWalkSpeed()
|
||||
HumanoidSettings:SetJumpHeight()
|
||||
HRPSettings:DisableRobloxSounds()
|
||||
CameraConsturctor:EnableBobbing()
|
||||
SpineMovement:Enable()
|
||||
|
||||
CrouchFeature()
|
||||
35
src/client/Character/Server/Shadows.lua
Normal file
35
src/client/Character/Server/Shadows.lua
Normal file
@@ -0,0 +1,35 @@
|
||||
--This really should be only client
|
||||
|
||||
local Shadows = {}
|
||||
Shadows.__index = Shadows
|
||||
|
||||
type Character = Model
|
||||
|
||||
function Shadows.constructor(Character: Character)
|
||||
return setmetatable({
|
||||
Character = Character
|
||||
}, Shadows)
|
||||
end
|
||||
|
||||
function Shadows:PartToggle(Instance: BasePart, CastingShadow: boolean)
|
||||
if Instance:IsA("BasePart") then --not 100%, but im sure types are only in effect on the editor side
|
||||
Instance.CastShadow = CastingShadow
|
||||
end
|
||||
end
|
||||
|
||||
local function CharacterShadows(self, enabled: boolean)
|
||||
local CharacterDescendants = self.Character:GetDescendants()
|
||||
for i = 1, #CharacterDescendants do
|
||||
self:PartToggle(CharacterDescendants[i], enabled)
|
||||
end
|
||||
end
|
||||
|
||||
function Shadows:on()
|
||||
CharacterShadows(self, true)
|
||||
end
|
||||
|
||||
function Shadows:off()
|
||||
CharacterShadows(self, false)
|
||||
end
|
||||
|
||||
return Shadows
|
||||
84
src/client/Character/Server/SpineKinematics.lua
Normal file
84
src/client/Character/Server/SpineKinematics.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
local Spine = {
|
||||
Enabled = true,
|
||||
Multiplier = .5
|
||||
}
|
||||
Spine.__index = Spine
|
||||
|
||||
type Head = BasePart
|
||||
type UpperTorso = BasePart
|
||||
type Neck = Motor6D
|
||||
|
||||
type NeckC0 = CFrame
|
||||
type WaistC0 = CFrame
|
||||
|
||||
type struct_Spine = {
|
||||
Remote: UnreliableRemoteEvent,
|
||||
Head: Head,
|
||||
UpperTorso: UpperTorso,
|
||||
Neck: Neck,
|
||||
NeckC0: NeckC0,
|
||||
WaistC0: WaistC0
|
||||
}
|
||||
|
||||
local Remote = Instance.new("UnreliableRemoteEvent")
|
||||
Remote.Name = "SpineStream"
|
||||
Remote.Parent = _G.include(script, "CharacterShared")
|
||||
|
||||
function Spine.constructor(Head: Head, UpperTorso: UpperTorso)
|
||||
local self: struct_Spine = {}
|
||||
self.Head = Head
|
||||
self.UpperTorso = UpperTorso
|
||||
self.Neck = Head:WaitForChild("Neck")
|
||||
self.Waist = UpperTorso:WaitForChild("Waist")
|
||||
self.Remote = Remote
|
||||
|
||||
self.NeckC0 = self.Neck.C0
|
||||
self.WaistC0 = self.Waist.C0
|
||||
return setmetatable(self, Spine)
|
||||
end
|
||||
|
||||
type struct_SpineMovement = {
|
||||
Neck: CFrame,
|
||||
Waist: CFrame
|
||||
}
|
||||
|
||||
local function SpineMovement(self, CameraCFrame: CFrame, IsFirstPerson: boolean): struct_SpineMovement
|
||||
local HeadCFrame: CFrame = self.Head.CFrame
|
||||
local TorsoPosition: Vector3 = self.UpperTorso.Position
|
||||
local TorsoLookVector: Vector3 = self.UpperTorso.CFrame.LookVector
|
||||
local HeadPosition: Vector3 = HeadCFrame.Position
|
||||
local CameraPosition: Vector3 = CameraCFrame.Position
|
||||
|
||||
local HeadDelta: Vector3 = HeadPosition-CameraPosition
|
||||
local TorsoDeltaNormal: Vector3 = (TorsoPosition-CameraPosition).Unit
|
||||
local HeadDeltaNormal: Vector3 = HeadDelta.Unit
|
||||
local HeadDeltaMagnitude: number = HeadDelta.Magnitude
|
||||
|
||||
local arc = Spine.Multiplier*math.asin(HeadDelta.Y/HeadDeltaMagnitude)
|
||||
local Neck = CFrame.Angles(arc, 0, 0)
|
||||
local Waist = CFrame.Angles(arc, 0, 0)
|
||||
|
||||
if not IsFirstPerson then
|
||||
--Make this less cringe at some point, combine the dot product into the equation
|
||||
local LookingAtSelf = CameraCFrame.LookVector:Dot(HeadCFrame.LookVector)<0 --Make our head face the camera if we are looking at ourself
|
||||
local HeadCrossDelta = Spine.Multiplier*HeadDeltaNormal:Cross(TorsoLookVector).Y
|
||||
local TorsoCrossDelta = Spine.Multiplier*TorsoDeltaNormal:Cross(TorsoLookVector).Y
|
||||
|
||||
Neck*=CFrame.Angles(0, HeadCrossDelta, 0)
|
||||
Waist*=CFrame.Angles(0, LookingAtSelf and TorsoCrossDelta or -TorsoCrossDelta, 0)
|
||||
end
|
||||
|
||||
return {
|
||||
Neck = Neck,
|
||||
Waist = Waist
|
||||
}
|
||||
end
|
||||
|
||||
function Spine:Move(CameraCFrame: CFrame, IsFirstPerson: boolean)
|
||||
local SpineIK = SpineMovement(self, CameraCFrame, IsFirstPerson)
|
||||
|
||||
self.Neck.C0 = self.Neck.C0:Lerp(self.NeckC0*SpineIK.Neck, .9)
|
||||
self.Waist.C0 = self.Waist.C0:Lerp(self.WaistC0*SpineIK.Waist, .9)
|
||||
end
|
||||
|
||||
return Spine
|
||||
52
src/client/Character/Server/init.server.lua
Normal file
52
src/client/Character/Server/init.server.lua
Normal file
@@ -0,0 +1,52 @@
|
||||
local Character = script.Parent
|
||||
local preprocessor = {}
|
||||
|
||||
--Create the character shared directory here
|
||||
local CharacterShared = Instance.new("Folder")
|
||||
CharacterShared.Name = "shared"
|
||||
CharacterShared.Parent = Character
|
||||
|
||||
type CharacterSharedFolder = Folder
|
||||
function preprocessor.CharacterShared(): CharacterSharedFolder
|
||||
return CharacterShared
|
||||
end
|
||||
|
||||
_G.include = function(this: LuaSourceContainer, FunName: string, ...)
|
||||
--its not extremely necessary to have security for the server-side
|
||||
if this:IsDescendantOf(script) then --getfenv is being removed
|
||||
local switch = preprocessor[FunName]
|
||||
return type(switch) == "function" and switch(...) or switch
|
||||
else
|
||||
warn(`Preprocessor append failed "{FunName}"`, debug.traceback())
|
||||
end
|
||||
end
|
||||
|
||||
local Players = game:GetService("Players")
|
||||
|
||||
local Shadows = require(script:WaitForChild("Shadows"))
|
||||
local SpineModule = require(script:WaitForChild("SpineKinematics"))
|
||||
|
||||
local Head = Character:WaitForChild("Head")
|
||||
local UpperTorso = Character:WaitForChild("UpperTorso")
|
||||
|
||||
local LocalPlayer = Players:GetPlayerFromCharacter(Character)
|
||||
|
||||
local CharacterShadows = Shadows.constructor(Character)
|
||||
local Spine = SpineModule.constructor(Head, UpperTorso)
|
||||
|
||||
CharacterShadows:off() --I plan having 2 player support and characters block a ton of light
|
||||
|
||||
Character.DescendantAdded:Connect(function(Instance)
|
||||
task.wait() --Wait for the instance to properly replicate?
|
||||
CharacterShadows:PartToggle(Instance, false)
|
||||
end)
|
||||
|
||||
Spine.Remote.OnServerEvent:Connect(function(Messenger: Player, CameraPosition: Vector3, IsFirstPerson: boolean)
|
||||
if Messenger.UserId == LocalPlayer.UserId then
|
||||
if Spine.Enabled then
|
||||
Spine:Move(CameraPosition, IsFirstPerson)
|
||||
end
|
||||
else
|
||||
warn("hacker")
|
||||
end
|
||||
end)
|
||||
80
src/client/Player/CoreGuis.lua
Normal file
80
src/client/Player/CoreGuis.lua
Normal file
@@ -0,0 +1,80 @@
|
||||
local CoreGuis = {
|
||||
AllowReset = false,
|
||||
AllowEmotes = true,
|
||||
AllowBackpack = false,
|
||||
AllowPlayerList = false
|
||||
}
|
||||
CoreGuis.__index = CoreGuis
|
||||
|
||||
local SG = game:GetService("StarterGui")
|
||||
local Players = game:GetService("Players")
|
||||
|
||||
type CustomCoreGuiEnums = {Enum.CoreGuiType}
|
||||
|
||||
local function CustomCoreGuiEnums(): CustomCoreGuiEnums
|
||||
local CoreElements = Enum.CoreGuiType:GetEnumItems()
|
||||
table.remove(CoreElements, table.find(CoreElements, Enum.CoreGuiType.All))
|
||||
|
||||
if CoreGuis.AllowBackpack then
|
||||
table.remove(CoreElements, table.find(CoreElements, Enum.CoreGuiType.Backpack))
|
||||
end
|
||||
if CoreGuis.AllowEmotes then
|
||||
table.remove(CoreElements, table.find(CoreElements, Enum.CoreGuiType.EmotesMenu))
|
||||
end
|
||||
if CoreGuis.AllowPlayerList then
|
||||
table.remove(CoreElements, table.find(CoreElements, Enum.CoreGuiType.PlayerList))
|
||||
end
|
||||
return CoreElements
|
||||
end
|
||||
|
||||
local function ResetEnabled(enabled: boolean)
|
||||
--Roblox actually doesn't register this fast enough so we gotta resort to cringe tactics
|
||||
repeat
|
||||
local PossibleMemoryLeak = pcall(SG.SetCore, SG, "ResetButtonCallback", enabled)
|
||||
task.wait()
|
||||
until PossibleMemoryLeak
|
||||
end
|
||||
|
||||
function CoreGuis:On()
|
||||
local Elements = CustomCoreGuiEnums()
|
||||
for i = 1, #Elements do
|
||||
SG:SetCoreGuiEnabled(Elements[i], true)
|
||||
end
|
||||
|
||||
ResetEnabled(CoreGuis.AllowReset)
|
||||
end
|
||||
|
||||
function CoreGuis:Off()
|
||||
if #Players:GetPlayers()>1 then
|
||||
--Enable multiplayer features
|
||||
self:On()
|
||||
|
||||
local PlayerAdded --So weird...
|
||||
PlayerAdded = Players.PlayerAdded:Connect(function(_)
|
||||
if #Players:GetPlayers()>1 then
|
||||
self:On()
|
||||
--We dont need to listen for players anymore
|
||||
PlayerAdded:Disconnect()
|
||||
end
|
||||
end)
|
||||
else
|
||||
local Elements = CustomCoreGuiEnums()
|
||||
for i = 1, #Elements do
|
||||
SG:SetCoreGuiEnabled(Elements[i], false)
|
||||
end
|
||||
end
|
||||
|
||||
ResetEnabled(CoreGuis.AllowReset)
|
||||
end
|
||||
|
||||
function CoreGuis:ForceOff()
|
||||
SG:SetCoreGuiEnabled(Enum.CoreGuiType.All, false)
|
||||
ResetEnabled(false)
|
||||
end
|
||||
|
||||
function CoreGuis:ForceOn()
|
||||
SG:SetCoreGuiEnabled(Enum.CoreGuiType.All, true)
|
||||
ResetEnabled(true)
|
||||
end
|
||||
|
||||
return CoreGuis
|
||||
8
src/client/Player/GuiService.lua
Normal file
8
src/client/Player/GuiService.lua
Normal file
@@ -0,0 +1,8 @@
|
||||
local GuiModule = {}
|
||||
GuiModule.__index = GuiModule
|
||||
|
||||
local GuiService = game:GetService("GuiService")
|
||||
|
||||
|
||||
|
||||
return GuiModule
|
||||
13
src/client/Player/Mouse.lua
Normal file
13
src/client/Player/Mouse.lua
Normal file
@@ -0,0 +1,13 @@
|
||||
local Mouse = {}
|
||||
|
||||
local UIS = game:GetService("UserInputService")
|
||||
|
||||
function Mouse:DisablePointer()
|
||||
UIS.MouseIconEnabled = false
|
||||
end
|
||||
|
||||
function Mouse:EnablePointer()
|
||||
UIS.MouseIconEnabled = true
|
||||
end
|
||||
|
||||
return Mouse
|
||||
31
src/client/Player/UI/Crosshair.lua
Normal file
31
src/client/Player/UI/Crosshair.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
local CrosshairModule = {
|
||||
Icon = "rbxassetid://12643750723"
|
||||
}
|
||||
CrosshairModule.__index = CrosshairModule
|
||||
|
||||
--Use a custom crosshair so we can do effects to it
|
||||
type rbxassetid = string
|
||||
|
||||
function CrosshairModule.constructor(PlayerGui: PlayerGui)
|
||||
local Screen = PlayerGui:WaitForChild("Crosshair")
|
||||
local Icon = Screen:WaitForChild("ImageLabel")
|
||||
|
||||
return setmetatable({
|
||||
Screen = Screen,
|
||||
Icon = Icon
|
||||
}, CrosshairModule)
|
||||
end
|
||||
|
||||
function CrosshairModule:Enable()
|
||||
self.Screen.Enabled = true
|
||||
end
|
||||
|
||||
function CrosshairModule:Disable()
|
||||
self.Screen.Enabled = false
|
||||
end
|
||||
|
||||
function CrosshairModule:Change(ID: rbxassetid)
|
||||
self.Icon.Image = ID or CrosshairModule.Icon
|
||||
end
|
||||
|
||||
return CrosshairModule
|
||||
27
src/client/Player/UI/Vignette.lua
Normal file
27
src/client/Player/UI/Vignette.lua
Normal file
@@ -0,0 +1,27 @@
|
||||
local VignetteModule = {
|
||||
Enabled = false,
|
||||
Icon = "rbxassetid://4576475446"
|
||||
}
|
||||
VignetteModule.__index = VignetteModule
|
||||
|
||||
function VignetteModule.constructor(PlayerGui: PlayerGui)
|
||||
local Screen = PlayerGui:WaitForChild("Vignette")
|
||||
local Icon = Screen:WaitForChild("ImageLabel")
|
||||
|
||||
return setmetatable({
|
||||
Screen = Screen,
|
||||
Icon = Icon
|
||||
}, VignetteModule)
|
||||
end
|
||||
|
||||
function VignetteModule:Enable()
|
||||
VignetteModule.Enabled = true
|
||||
self.Screen.Enabled = true
|
||||
end
|
||||
|
||||
function VignetteModule:Disable()
|
||||
VignetteModule.Enabled = false
|
||||
self.Screen.Enabled = false
|
||||
end
|
||||
|
||||
return VignetteModule
|
||||
51
src/client/Player/init.client.lua
Normal file
51
src/client/Player/init.client.lua
Normal file
@@ -0,0 +1,51 @@
|
||||
local UI = script:WaitForChild("UI")
|
||||
local CrosshairSettings = require(UI:WaitForChild("Crosshair"))
|
||||
local VignetteSettings = require(UI:WaitForChild("Vignette"))
|
||||
local CoreGuis = require(script:WaitForChild("CoreGuis"))
|
||||
local Mouse = require(script:WaitForChild("Mouse"))
|
||||
|
||||
local Players = game:GetService("Players")
|
||||
local Storage = game:GetService("ReplicatedStorage")
|
||||
|
||||
local ClientStorage = Storage:WaitForChild("Client")
|
||||
local LoadCompleted = ClientStorage:WaitForChild("LoadingComplete")
|
||||
local KeyBindsModule = require(ClientStorage:WaitForChild("KeyBinds"))
|
||||
local CameraSettings = require(ClientStorage:WaitForChild("Camera"))
|
||||
|
||||
local Player = Players.LocalPlayer
|
||||
local PlayerGui = Player:WaitForChild("PlayerGui")
|
||||
|
||||
--We need to wait for the game to load before spamming functionality
|
||||
repeat
|
||||
local GameIsLoaded = LoadCompleted:Invoke()
|
||||
task.wait()
|
||||
until GameIsLoaded
|
||||
|
||||
local CurrentCamera = nil
|
||||
repeat
|
||||
task.wait()
|
||||
CurrentCamera = workspace.CurrentCamera
|
||||
until CurrentCamera
|
||||
|
||||
local Vignette = VignetteSettings.constructor(PlayerGui)
|
||||
local Camera = CameraSettings.constructor(CurrentCamera, Player)
|
||||
local Crosshair = CrosshairSettings.constructor(PlayerGui)
|
||||
|
||||
--Keybinds
|
||||
local function CameraBinds()
|
||||
local CameraBindMap = KeyBindsModule.constructor()
|
||||
|
||||
CameraBindMap:AddInputBegan({Enum.KeyCode.C, Enum.KeyCode.Z}, function()
|
||||
Camera:ZoomIn(Vignette, Crosshair)
|
||||
end)
|
||||
CameraBindMap:AddInputEnded({Enum.KeyCode.C, Enum.KeyCode.Z}, function()
|
||||
Camera:ZoomOut(Vignette, Crosshair)
|
||||
end)
|
||||
end
|
||||
|
||||
CoreGuis:Off()
|
||||
Camera:FirstPerson()
|
||||
Mouse:DisablePointer()
|
||||
Crosshair:Enable()
|
||||
|
||||
CameraBinds()
|
||||
Reference in New Issue
Block a user