Setting up a camera shake

I’ve worked out the solution a while ago by this point, but I felt like I should resolve the post. It could be done more efficiently but it works for what I need.

-- This script is mostly just the relevant parts of the camera script

local CAS = game:GetService("ContextActionService")
local UIS = game:GetService("UserInputService")
local RS = game:GetService("RunService")
local RepStore = game:GetService("ReplicatedStorage")
local TS = game:GetService("TweenService")

local plr = game.Players.LocalPlayer
local cam = game.Workspace.CurrentCamera

-- Rather than having two different global values, I can instead just use a remote event to change one local value
local shakeOffset = Vector3.new(0, 0, 0)

local follow = Instance.new("Part")
follow.CanCollide = false
follow.CanQuery = false
follow.Transparency = 1
follow.Anchored = true
follow.Parent = game.Workspace

local rootLerp = 0.6

local camAngX = 0
local camAngY = 0
local loop

local head

plr.CharacterAdded:Connect(function(chr)
	local hum = chr:WaitForChild("Humanoid")
	local root = chr:WaitForChild("HumanoidRootPart")
	head = chr:WaitForChild("Head")

	local function plrInput(_, inpState, inpObject)
		if inpState == Enum.UserInputState.Change then
			if _G.toggle == false then
				camAngX = camAngX - inpObject.Delta.X
				camAngY = math.clamp(camAngY - inpObject.Delta.Y * 0.4, -55, 35)
			end	
		end
	end

	CAS:BindAction("plrInput", plrInput, false, Enum.UserInputType.MouseMovement)
	
	local function moveCam()
		if hum.Health > 0 then
			if cam.CameraType ~= Enum.CameraType.Scriptable then
				cam.CameraType = Enum.CameraType.Scriptable
			end

			follow.CFrame = follow.CFrame:Lerp(head.CFrame, 0.3)

			local newCamOffset = currentCamOffset.Value
			local startCF = CFrame.new(root.CFrame.Position) * CFrame.Angles(0, math.rad(camAngX), 0) * CFrame.Angles(math.rad(camAngY), 0, 0)
			local camCFrame = startCF:ToWorldSpace(CFrame.new(newCamOffset.X, newCamOffset.Y, newCamOffset.Z))
			local camFocus = startCF:ToWorldSpace(CFrame.new(newCamOffset.X, newCamOffset.Y, -10000))

			local org = follow.Position + shakeOffset
			local dir = CFrame.lookAt(follow.Position, camCFrame.Position).LookVector * 15

			local exclude = {chr, workspace["enemies"], workspace["npcs"], workspace["raycastParts"], workspace["vfx"], workspace["projectiles"]}

			local params = RaycastParams.new()
			params.FilterType = Enum.RaycastFilterType.Exclude

			for _,c in pairs(game.Workspace:GetChildren()) do
				if c:IsA("Model") and game.Players:FindFirstChild(c.Name) then
					table.insert(exclude, c)
				end
			end

			params.FilterDescendantsInstances = exclude

			local hitPos
			if result then
				hitPos = result.Position
			else
				hitPos = org + dir
			end
			local finalCF = CFrame.lookAt(hitPos, camFocus.Position)
			cam.CFrame = CFrame.lookAt(hitPos, camFocus.Position)

			lastCF = cam.CFrame
		else
			cam.CFrame = lastCF
		end
	end

	RS:BindToRenderStep("moveCam", Enum.RenderPriority.Camera.Value + 1, moveCam)
end)

local function randomFromTable(arr)
	local amnt = #arr
	local random = math.random(1, amnt)
	return arr[random]
end

local function cameraShake(intensity, decay)
	local intensityCopy = intensity
	local loop
	loop = RS.Stepped:Connect(function()
		local xOffset = randomFromTable({-1, 1})
		local yOffset = randomFromTable({-1, 1})
		local zOffset = randomFromTable({-1, 1})
-- Constantly change the camera's shake offset to a random Vector3 which decreases in magnitude over time
		shakeOffset = shakeOffset:Lerp(Vector3.new(xOffset, yOffset, zOffset) * intensityCopy, 0.2)
		intensityCopy *= decay
		if intensityCopy < 0.1 then
-- When the intensity has lowered enough, stop the loop and remove the offset
			loop:Disconnect()
			shakeOffset = Vector3.new(0, 0, 0)
		end
	end)
end

RepStore["Events"]["shake"].OnClientEvent:Connect(cameraShake)
RepStore["Events"]["shake"]["bindable"].Event:Connect(cameraShake)