big commit

This commit is contained in:
2024-02-08 18:59:42 -05:00
commit 699fe50fea
38 changed files with 2327 additions and 0 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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()

View 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

View 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

View 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)

View 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

View File

@@ -0,0 +1,8 @@
local GuiModule = {}
GuiModule.__index = GuiModule
local GuiService = game:GetService("GuiService")
return GuiModule

View 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

View 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

View 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

View 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()