Big client character refactor

This commit is contained in:
2024-04-21 15:04:12 -04:00
parent 36625162a1
commit 65e4b7eef2
9 changed files with 152 additions and 110 deletions

View File

@@ -41,6 +41,8 @@ type Constructor_Return_Props = {
ActionsTCP: TCP
}
export type ActionsConstructor = ClassConstructor
local Actions = {} :: Impl_Constructor
Actions.__index = Actions
@@ -116,7 +118,7 @@ function Actions:DisableCrouch()
}, Easing)
end
function Actions:EnableFlashlight(FlashlightKey: Enum.KeyCode)
function Actions:EnableFlashlight(FlashlightKey)
Actions.FlashlightEnabled = true
task.spawn(function()
@@ -133,12 +135,12 @@ function Actions:EnableFlashlight(FlashlightKey: Enum.KeyCode)
self.ActionsTCP:FireServer(FlashlightKey)
end
function Actions:DisableFlashlight(FlashlightKey: Enum.KeyCode)
function Actions:DisableFlashlight(FlashlightKey)
self.ActionsTCP:FireServer(FlashlightKey)
Actions.FlashlightEnabled = false
end
function Actions:ToggleFlashlight(FlashlightKey: Enum.KeyCode)
function Actions:ToggleFlashlight(FlashlightKey)
if Actions.FlashlightEnabled then
self:DisableFlashlight(FlashlightKey)
else

View File

@@ -40,11 +40,16 @@ type Constructor_Return_Props = {
Humanoid: Humanoid
}
export type BobbingConstructor = Impl_Constructor
export type BobbingConstructor = ClassConstructor
local Bobbing = {} :: Impl_Constructor
Bobbing.__index = Bobbing
local UIS = game:GetService("UserInputService")
local RS = game:GetService("ReplicatedStorage")
local Algebra = require(RS:WaitForChild("Algebra"))
Bobbing.TurnAlpha = 0.050
Bobbing.LeanMultiplier = 1.7
Bobbing.SwayMultiplier = 1.5
@@ -56,8 +61,6 @@ Bobbing.ForceStop = false
local Animations = {} :: AnimationsMap
local UIS = game:GetService("UserInputService")
local CN = CFrame.new
local ANG = CFrame.Angles
local CameraLean = CN()
@@ -66,8 +69,8 @@ local Animation = CN()
function Bobbing.constructor(HumanoidRootPart: HumanoidRootPart, CurrentCamera: CurrentCamera, Humanoid: Humanoid)
return setmetatable({
HumanoidRootPart = HumanoidRootPart,
CurrentCamera = CurrentCamera,
Humanoid = Humanoid
CurrentCamera = CurrentCamera,
Humanoid = Humanoid
}, Bobbing)
end
@@ -100,10 +103,6 @@ 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))
@@ -113,20 +112,20 @@ local function CameraAnimation(self: ClassConstructor, dt: deltatime)
--crying
Bobbing.Tick += 1
local Root: BasePart = self.HumanoidRootPart
local Velocity: Vector3 = Root:GetVelocityAtPosition(Root.Position)
local RootMagnitude: number = Velocity.Magnitude
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 AnimationType: string = Bobbing.ForceStop and "Stop" or RootMagnitude>1 and "Walk" or (not MaxMinY and "Idle" or "Stop")
local CurrentAnimation: CFrame = Animations[AnimationType](Bobbing.Tick, dt)
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 AnimationType: string = Bobbing.ForceStop and "Stop" 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)
function Bobbing:Frame(dt)
local Camera = self.CurrentCamera
local Humanoid = self.Humanoid
@@ -139,7 +138,7 @@ function Bobbing:Frame(dt: number)
--Jump?!
--local LeanDegree_Pitch = -CameraCF.UpVector:Dot(Humanoid.MoveDirection)*Bobbing.LeanMultiplier
local LeanMult_Roll = maxmin(-Bobbing.SwayMultiplier, LeanDegree_Roll-MouseDelta.X, Bobbing.SwayMultiplier)
local LeanMult_Roll = Algebra.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

View File

@@ -4,10 +4,8 @@
local Bobbing = require(script:WaitForChild("Bobbing"))
type FakeCamera = BasePart
type CurrentCamera = Camera
type HumanoidRootPart = BasePart
type Module = any
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
@@ -26,13 +24,15 @@ type Constructor_Return_Props = {
BobbingCamera: Bobbing.BobbingConstructor
}
export type CameraConstructor = ClassConstructor
local Camera = {} :: Impl_Constructor
Camera.__index = Camera
local RS = game:GetService("RunService")
function Camera.constructor(CurrentCamera: CurrentCamera, HumanoidRootPart: HumanoidRootPart, Humanoid: Humanoid)
local self = {}
local self = {} :: Constructor_Return_Props
self.CameraFPS = false
self.CurrentCamera = CurrentCamera
self.HumanoidRootPart = HumanoidRootPart

View File

@@ -22,20 +22,22 @@ type Constructor_Return_Props = {
Humanoid: Humanoid
}
export type HumanoidConstructor = ClassConstructor
local HumanoidModule = {} :: Impl_Constructor
HumanoidModule.__index = HumanoidModule
function HumanoidModule.constructor(Humanoid: Humanoid)
function HumanoidModule.constructor(Humanoid)
return setmetatable({
Humanoid = Humanoid
}, HumanoidModule)
end
function HumanoidModule:SetWalkSpeed(Speed: WalkSpeed)
function HumanoidModule:SetWalkSpeed(Speed)
self.Humanoid.WalkSpeed = Speed or 10
end
function HumanoidModule:SetJumpHeight(Height: JumpHeight)
function HumanoidModule:SetJumpHeight(Height)
self.Humanoid.JumpHeight = Height or 7.2
end

View File

@@ -18,6 +18,8 @@ type Constructor_Return_Props = {
HumanoidRootPart: HumanoidRootPart
}
export type HumanoidRPSettingsConstructor = ClassConstructor
local HumanoidRPSettings = {} :: Impl_Constructor
HumanoidRPSettings.__index = HumanoidRPSettings

View File

@@ -4,6 +4,7 @@
type UDP = UnreliableRemoteEvent
type CurrentCamera = Camera
type CharacterShared = Folder
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
@@ -14,7 +15,7 @@ type Impl_Constructor = {
Disable: (self: ClassConstructor) -> ()
} & Impl_Static_Props
type Constructor_Fun = (CurrentCamera: CurrentCamera) -> ClassConstructor
type Constructor_Fun = (CharacterShared: CharacterShared, CurrentCamera: CurrentCamera) -> ClassConstructor
type Impl_Static_Props = {
Running: boolean
}
@@ -23,6 +24,8 @@ type Constructor_Return_Props = {
CurrentCamera: CurrentCamera
}
export type SpineConstructor = ClassConstructor
local Spine = {} :: Impl_Constructor
Spine.__index = Spine
@@ -30,16 +33,14 @@ Spine.Running = false
local Storage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local Delta = require(Storage:WaitForChild("Delta"))
local Player = Players.LocalPlayer
local CharacterShared = _G.include(script, "CharacterShared")
function Spine.constructor(CurrentCamera: CurrentCamera)
function Spine.constructor(CharacterShared, CurrentCamera)
return setmetatable({
Remote = CharacterShared:WaitForChild("SpineStream"),
CurrentCamera = CurrentCamera
Remote = CharacterShared:WaitForChild("SpineStream") :: UDP,
CurrentCamera = CurrentCamera :: CurrentCamera
}, Spine)
end

View File

@@ -2,62 +2,86 @@
--!native
--!strict
type CharacterSharedFolder = Folder
type Character = Model
type TCP = RemoteEvent
type include<T> = (this: LuaSourceContainer, FunName: string, ...T) -> T
local CharacterModule = {}
CharacterModule.__index = CharacterModule
local RS = game:GetService("RunService")
local Storage = game:GetService("ReplicatedStorage")
local ClientStorage = Storage:WaitForChild("Client") :: Folder
local ClientStorage = Storage:WaitForChild("Client")
local BindModule = require(ClientStorage:WaitForChild("KeyBinds"))
local function client_preprocessor<T>(Character: Character): (include<T>, CharacterSharedFolder)
local preprocessor = {}
local CharacterShared = Character:WaitForChild("shared") :: CharacterSharedFolder
local HumanoidRPSettings = require(script:WaitForChild("HumanoidRootPart"))
local CameraModule = require(script:WaitForChild("Camera"))
local HumanoidModule = require(script:WaitForChild("Humanoid"))
local SpineModule = require(script:WaitForChild("SpineKinematics"))
local ActionsModule = require(script:WaitForChild("Actions"))
function preprocessor.CharacterShared(): CharacterSharedFolder
return CharacterShared
end
type Character = Model
type HumanoidRootPart = BasePart
type TCP = RemoteEvent
type CurrentCamera = Camera
_G.include = function<T>(this: LuaSourceContainer, FunName: string, ...: T)
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())
return nil
end
end
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
__index: Impl_Constructor,
constructor: Constructor_Fun,
--Class functions
CharacterKeyBinds: (self: ClassConstructor) -> (),
Crosshair: (self: ClassConstructor) -> RBXScriptConnection,
SetWalkSpeed: (self: ClassConstructor) -> (),
SetJumpHeight: (self: ClassConstructor) -> (),
DisableRobloxSounds: (self: ClassConstructor) -> (),
EnableCameraBobbing: (self: ClassConstructor) -> (),
EnableSpineMovement: (self: ClassConstructor) -> ()
} & Impl_Static_Props
return _G.include, CharacterShared
end
type Impl_Static_Props = {
KeyBinds: {
Crouch: {Enum.KeyCode},
Walk: {Enum.KeyCode},
Flashlight: {Enum.KeyCode}
}
}
type Constructor_Fun = (Character: Character) -> ClassConstructor
type Constructor_Return_Props = {
ActionsTCP: TCP,
CurrentCamera: CurrentCamera,
HRPSettings: HumanoidRPSettings.HumanoidRPSettingsConstructor,
CameraConsturctor: CameraModule.CameraConstructor,
HumanoidSettings: HumanoidModule.HumanoidConstructor,
SpineMovement: SpineModule.SpineConstructor
}
local CharacterModule = {} :: Impl_Constructor
CharacterModule.__index = CharacterModule
CharacterModule.KeyBinds = {
Crouch = {
Enum.KeyCode.RightControl,
Enum.KeyCode.LeftControl
},
Walk = {
Enum.KeyCode.LeftAlt,
Enum.KeyCode.RightAlt,
Enum.KeyCode.LeftShift,
Enum.KeyCode.RightShift
},
Flashlight = {
Enum.KeyCode.F
}
}
function CharacterModule.constructor(Character)
local _, CharacterShared = client_preprocessor(Character)
local HumanoidRPSettings = require(script:WaitForChild("HumanoidRootPart"))
local CameraModule = require(script:WaitForChild("Camera"))
local HumanoidModule = require(script:WaitForChild("Humanoid"))
local SpineModule = require(script:WaitForChild("SpineKinematics"))
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local Humanoid = Character:WaitForChild("Humanoid")
local self = {}
self.ActionsTCP = CharacterShared:WaitForChild("Actions")
self.ActionsModule = require(script:WaitForChild("Actions"))
self.BindModule = require(ClientStorage:WaitForChild("KeyBinds"))
local CharacterShared = Character:WaitForChild("shared") :: Folder
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart") :: HumanoidRootPart
local Humanoid = Character:WaitForChild("Humanoid") :: Humanoid
local self = {} :: Constructor_Return_Props
self.CurrentCamera = workspace.CurrentCamera
self.ActionsTCP = CharacterShared:WaitForChild("Actions") :: TCP
self.HRPSettings = HumanoidRPSettings.constructor(HumanoidRootPart)
self.CameraConsturctor = CameraModule.constructor(self.CurrentCamera, HumanoidRootPart, Humanoid)
self.HumanoidSettings = HumanoidModule.constructor(Humanoid)
self.SpineMovement = SpineModule.constructor(self.CurrentCamera)
self.SpineMovement = SpineModule.constructor(CharacterShared, self.CurrentCamera)
pcall(table.clear, _G)
pcall(table.freeze, _G)
@@ -68,37 +92,27 @@ function CharacterModule.constructor(Character)
end
function CharacterModule:CharacterKeyBinds()
local ClientBindMap = self.BindModule.constructor(false)
local Actions = self.ActionsModule.constructor(self.HumanoidSettings, self.CurrentCamera, self.ActionsTCP)
local ClientBindMap = BindModule.constructor(false)
local Actions = ActionsModule.constructor(self.HumanoidSettings, self.CurrentCamera, self.ActionsTCP)
--Crouch
ClientBindMap:AddInputBegan({Enum.KeyCode.RightControl, Enum.KeyCode.LeftControl}, function(_KeyPressed)
ClientBindMap:AddInputBegan(CharacterModule.KeyBinds.Crouch, function(_KeyPressed)
Actions:EnableCrouch()
end)
ClientBindMap:AddInputEnded({Enum.KeyCode.RightControl, Enum.KeyCode.LeftControl}, function(_KeyPressed)
ClientBindMap:AddInputEnded(CharacterModule.KeyBinds.Crouch, function(_KeyPressed)
Actions:DisableCrouch()
end)
--Walk
ClientBindMap:AddInputBegan({
Enum.KeyCode.LeftAlt,
Enum.KeyCode.RightAlt,
Enum.KeyCode.LeftShift,
Enum.KeyCode.RightShift
}, function(_KeyPressed)
ClientBindMap:AddInputBegan(CharacterModule.KeyBinds.Walk, function(_KeyPressed)
Actions:EnableSneak()
end)
ClientBindMap:AddInputEnded({
Enum.KeyCode.LeftAlt,
Enum.KeyCode.RightAlt,
Enum.KeyCode.LeftShift,
Enum.KeyCode.RightShift
}, function(_KeyPressed)
ClientBindMap:AddInputEnded(CharacterModule.KeyBinds.Walk, function(_KeyPressed)
Actions:DisableSneak()
end)
--Flashlight
ClientBindMap:AddInputBegan({Enum.KeyCode.F}, function(KeyPressed: Enum.KeyCode)
ClientBindMap:AddInputBegan(CharacterModule.KeyBinds.Flashlight, function(KeyPressed: Enum.KeyCode)
Actions:ToggleFlashlight(KeyPressed)
end)
end

View File

@@ -28,11 +28,16 @@ export type Math = {
OutBounce: EaseFunction,
InQuad: EaseFunction,
RotationMatrix: (X: number, Y: number, Z: number) -> RotationMatrix,
Scalar: (X1: number, Y1: number, X2: number, Y2: number) -> Scalar
Scalar: (X1: number, Y1: number, X2: number, Y2: number) -> Scalar,
maxmin: (min: number, n: number, max: number) -> number
}
local Math = {} :: Math
function Math.maxmin(min, n, max)
return math.max(min, math.min(n, max))
end
function Math.RotationMatrix(X: number, Y: number, Z: number): RotationMatrix
return {
Ixx = math.cos(Z)*math.cos(X)-math.sin(Z)*math.sin(X)*math.sin(Y);

View File

@@ -2,34 +2,51 @@
--!native
--!strict
--I couldn't get ContextActionService to work how i wanted it to
--Couldn't get ContextActionService to work how i wanted
local BindLink = {}
BindLink.__index = BindLink
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
__index: Impl_Constructor,
constructor: Constructor_Fun,
--Class functions
CharacterKeyBinds: (self: ClassConstructor) -> (),
AddInputBegan: (self: ClassConstructor, Keys: {Enum.KeyCode}, Callback: CallbackFunction) -> (),
AddInputEnded: (self: ClassConstructor, Keys: {Enum.KeyCode}, Callback: CallbackFunction) -> (),
KeyHold: (self: ClassConstructor, Key: Enum.KeyCode) -> boolean
}
type Constructor_Fun = (gameProcessing: boolean) -> ClassConstructor
type Constructor_Return_Props = {
BindMap: KeyBindMap,
InputBegan: InputBegan,
InputEnded: InputEnded
}
type CallbackFunction = (KeyPressed: Enum.KeyCode) -> ()
export type KeyBindMap = {
[string]: {
[Enum.KeyCode]: (KeyPressed: Enum.KeyCode) -> ()
}
}
type BindConstructor = {
BindMap: KeyBindMap,
InputBegan: InputBegan,
InputEnded: InputEnded
}
export type InputBegan = RBXScriptConnection
export type InputEnded = RBXScriptConnection
type CallbackFunction = (KeyPressed: Enum.KeyCode) -> ()
export type KeyBindsConstructor = ClassConstructor
local BindLink = {} :: Impl_Constructor
BindLink.__index = BindLink
local UIS = game:GetService("UserInputService")
function BindLink.constructor(gameProcessing: boolean) --Allow multiple bindings of the same keys, no overwrites
local self = {} :: BindConstructor
local self = {} :: Constructor_Return_Props
self.BindMap = {
Began = {},
Ended = {}
}
--Return these for convenience
self.InputBegan = UIS.InputBegan:Connect(function(input, gameProcessedEvent)
if gameProcessing and gameProcessedEvent or not gameProcessedEvent then
@@ -55,9 +72,9 @@ function BindLink.constructor(gameProcessing: boolean) --Allow multiple bindings
return setmetatable(self, BindLink)
end
function BindLink:AddInputBegan(Keys: {Enum.KeyCode}, Callback: CallbackFunction)
for i = 1, #Keys do
local Key = Keys[i]
function BindLink:AddInputBegan(Keys, Callback)
for n: number = 1, #Keys do
local Key = Keys[n]
if self.BindMap.Began[Key] then
warn(`Key >began< "{Key.Name}" is already binded on this KeyBind map`, debug.traceback())
end
@@ -65,9 +82,9 @@ function BindLink:AddInputBegan(Keys: {Enum.KeyCode}, Callback: CallbackFunction
end
end
function BindLink:AddInputEnded(Keys: {Enum.KeyCode}, Callback: CallbackFunction)
for i = 1, #Keys do
local Key = Keys[i]
function BindLink:AddInputEnded(Keys, Callback)
for n: number = 1, #Keys do
local Key = Keys[n]
if self.BindMap.Ended[Key] then
warn(`Key >ended< "{Key.Name}" is already binded on this KeyBind map`, debug.traceback())
end
@@ -75,7 +92,7 @@ function BindLink:AddInputEnded(Keys: {Enum.KeyCode}, Callback: CallbackFunction
end
end
function BindLink:KeyHold(Key: Enum.KeyCode): boolean
function BindLink:KeyHold(Key)
return UIS:IsKeyDown(Key)
end