Help with gun recoil system

I was following this tutorial Roblox FPS Tutorial Part 2 Shooting, Replication, Recoil - YouTube (11:00) and I’m on the recoil part but my recoil (unlike his) goes WAYYY too far back and the kick is like 10x larger than its supposed to be… Can someone help?

my code:

local plr = game.Players.LocalPlayer
local char = plr.CharacterAdded:Wait()
local humanoid = char:WaitForChild("Humanoid")
local HRP = char:FindFirstChild("HumanoidRootPart")
local camera = game.Workspace.CurrentCamera
local Aiming = false
local UIS = game:GetService("UserInputService")
local RS = game:GetService("RunService")
local GUIservice = game:GetService("GuiService")
local TS = game:GetService("TweenService")
local ReplicatedStorage =game:GetService("ReplicatedStorage")
--UIS.MouseIconEnabled = false DISABLE MOUSE CURSOR
local springModule = require(game.ReplicatedStorage.Spring)

local viewmodel = ReplicatedStorage.Viewmodel:Clone()
viewmodel.Parent = camera

local gunModel = viewmodel.AwesomeGun:Clone()
gunModel.Parent = viewmodel
local Joint = Instance.new("Motor6D")
Joint.Part0 = viewmodel.Primary
Joint.Part1 = gunModel.Handle
Joint.Parent = gunModel.Handle
Joint.C1 = CFrame.new(0,.2,.2)
local Anims = {
	["Idle"] = viewmodel.AnimationController.Animator:LoadAnimation(ReplicatedStorage.Idle)
}
Anims.Idle:Play()
local AimingCF = CFrame.new()
local MouseSway = springModule.new(Vector3.new())
MouseSway.Speed = 20
MouseSway.Damper = .5

local MovementSway = springModule.new(Vector3.new())
MovementSway.Speed = 30
MovementSway.Damper = .4

local GunSpring = springModule.new(Vector3.new())
MouseSway.Speed = 20
MouseSway.Damper = .4

local RecoilSpring = springModule.new(Vector3.new())
MovementSway.Speed = 25
MovementSway.Damper = 1

local AUTO = true
local CD = 60/600
local CanShoot = true
local Shooting = false
local Range = 500
local KICK = Vector3.new(1,-1,1)
local RECOIL = Vector3.new(5,-0,10)
local RESETRECOIL = 0.2
local OOC = 2
local REC = 1
local RECOILS = {
	{-1,1},
	{-2,2},
	{-3,3},
	{-4,4},
	{-10,10},
	{-20,20}
}
local RECOILDAMPENER = 1

local Params = RaycastParams.new()
Params.FilterType = Enum.RaycastFilterType.Blacklist
Params.FilterDescendantsInstances = {viewmodel,char,workspace.FX}

local function getBobbing(Addition, Speed, Modifier)
	return math.sin(time()*Addition*Speed)*Modifier
end

UIS.InputBegan:Connect(function(input,gpe)
	if input.UserInputType == Enum.UserInputType.MouseButton2 then
		Aiming = true
	elseif input.UserInputType == Enum.UserInputType.MouseButton1 then
		Shooting = true
		CanShoot = false
		local StartShoot = time()
		local Shots = 0
		repeat
			if Shots <#RECOILS then
				Shots +=1
			end
			--GunSpring.Velocity += KICK
			local Recoil = RECOIL
			if time() - StartShoot > OOC then
				RECOIL += Vector3.new(0,(math.sin(10*(time()-StartShoot))*25),0)
			elseif time() - StartShoot > REC then
				RECOIL += Vector3.new(0,(math.cos(5*(time()-StartShoot))*12),0)
			end
			local x = math.random(RECOILS[Shots][1]*10,RECOILS[Shots][2]*10)/10 - RECOILS[Shots][1]
			local y = math.random(RECOILS[Shots][1]*10,RECOILS[Shots][2]*10)/10
			local z = 0
			Recoil += Vector3.new(x,y,z)
			RECOIL/=RECOILDAMPENER
			RecoilSpring.Velocity+=Recoil
			print(RECOIL)
			print(Recoil)
			task.delay(RESETRECOIL, function()
				RecoilSpring.Velocity-=Recoil
			end)
			
			task.wait(CD)
		until Shooting == false or AUTO == false
	end
end)

UIS.InputEnded:Connect(function(input,gpe)
	if input.UserInputType == Enum.UserInputType.MouseButton2 then
		Aiming = false
	elseif input.UserInputType == Enum.UserInputType.MouseButton1 and Shooting then
		
	Shooting = false
	end
end)

RS:BindToRenderStep("Viewmodel",301, function(DT)
	local mouseDelta = UIS:GetMouseDelta()
	MouseSway.Velocity += (Vector3.new(mouseDelta.X /450,mouseDelta.Y/450))
	local MovementSwayAmount = Vector3.new(getBobbing(10,1,.2),getBobbing(5,1,.2),getBobbing(5,1,.2))
	
	
	
	if Aiming then
		AimingCF = AimingCF:Lerp(gunModel.AimPart.CFrame:ToObjectSpace(viewmodel.PrimaryPart.CFrame),.3)
		MovementSwayAmount/=6
		humanoid.WalkSpeed = 7
	else
		AimingCF = AimingCF:Lerp(CFrame.new(), .3)
		humanoid.WalkSpeed = 16
	end
	MovementSway.Velocity += ((MovementSwayAmount/25)* DT * 60 * HRP.AssemblyLinearVelocity.Magnitude)
	camera.CFrame *= CFrame.Angles(math.rad(RecoilSpring.Position.X),math.rad(RecoilSpring.Position.Y),math.rad(RecoilSpring.Position.Z))
	
	print(GunSpring.Position.Y)
	viewmodel:PivotTo(
			camera.CFrame * CFrame.new(MovementSway.Position.X/2,MovementSway.Position.Y/2,0)
			*AimingCF
			* CFrame.Angles(0,-MouseSway.Position.X,MouseSway.Position.Y)
			* CFrame.Angles(0,MovementSway.Position.Y,MovementSway.Position.X)
			* CFrame.Angles(GunSpring.Position.X,GunSpring.Position.Y,0)
			* CFrame.new(0,0,GunSpring.Position.X * 5)
	
	)
	
	
end)

plr.CharacterAdded:Connect(function(char)
	char = plr.Character
	humanoid = char:WaitForChild("Humanoid")
	Params.FilterDescendantsInstances = {viewmodel,char,workspace.FX}
end)

Spring module:

--[[
class Spring
Description:
    A physical model of a spring, useful in many applications. Properties only evaluate
    upon index making this model good for lazy applications
API:
    Spring = Spring.new(number position)
        Creates a new spring in 1D
    Spring = Spring.new(Vector3 position)
        Creates a new spring in 3D
    Spring.Position
        Returns the current position
    Spring.Velocity
        Returns the current velocity
    Spring.Target
        Returns the target
    Spring.Damper
        Returns the damper
    Spring.Speed
        Returns the speed
    Spring.Target = number/Vector3
        Sets the target
    Spring.Position = number/Vector3
        Sets the position
    Spring.Velocity = number/Vector3
        Sets the velocity
    Spring.Damper = number [0, 1]
        Sets the spring damper, defaults to 1
    Spring.Speed = number [0, infinity)
        Sets the spring speed, defaults to 1
    Spring:TimeSkip(number DeltaTime)
        Instantly skips the spring forwards by that amount of now
    Spring:Impulse(number/Vector3 velocity)
        Impulses the spring, increasing velocity by the amount given
Visualization (by Defaultio):
    https://www.desmos.com/calculator/hn2i9shxbz
]]


local Spring = {}

--- Creates a new spring
-- @param initial A number or Vector3 (anything with * number and addition/subtraction defined)
-- @param[opt=os.clock] clock function to use to update spring
function Spring.new(initial, clock)
	local target = initial or 0
	clock = clock or os.clock
	return setmetatable({
		_clock = clock;
		_time0 = clock();
		_position0 = target;
		_velocity0 = 0*target;
		_target = target;
		_damper = 1;
		_speed = 1;
	}, Spring)
end

--- Impulse the spring with a change in velocity
-- @param velocity The velocity to impulse with
function Spring:Impulse(velocity)
	self.Velocity = self.Velocity + velocity
end

--- Skip forwards in now
-- @param delta now to skip forwards
function Spring:TimeSkip(delta)
	local now = self._clock()
	local position, velocity = self:_positionVelocity(now+delta)
	self._position0 = position
	self._velocity0 = velocity
	self._time0 = now
end

function Spring:__index(index)
	if Spring[index] then
		return Spring[index]
	elseif index == "Value" or index == "Position" or index == "p" then
		local position, _ = self:_positionVelocity(self._clock())
		return position
	elseif index == "Velocity" or index == "v" then
		local _, velocity = self:_positionVelocity(self._clock())
		return velocity
	elseif index == "Target" or index == "t" then
		return self._target
	elseif index == "Damper" or index == "d" then
		return self._damper
	elseif index == "Speed" or index == "s" then
		return self._speed
	elseif index == "Clock" then
		return self._clock
	else
		error(("%q is not a valid member of Spring"):format(tostring(index)), 2)
	end
end

function Spring:__newindex(index, value)
	local now = self._clock()

	if index == "Value" or index == "Position" or index == "p" then
		local _, velocity = self:_positionVelocity(now)
		self._position0 = value
		self._velocity0 = velocity
		self._time0 = now
	elseif index == "Velocity" or index == "v" then
		local position, _ = self:_positionVelocity(now)
		self._position0 = position
		self._velocity0 = value
		self._time0 = now
	elseif index == "Target" or index == "t" then
		local position, velocity = self:_positionVelocity(now)
		self._position0 = position
		self._velocity0 = velocity
		self._target = value
		self._time0 = now
	elseif index == "Damper" or index == "d" then
		local position, velocity = self:_positionVelocity(now)
		self._position0 = position
		self._velocity0 = velocity
		self._damper = value
		self._time0 = now
	elseif index == "Speed" or index == "s" then
		local position, velocity = self:_positionVelocity(now)
		self._position0 = position
		self._velocity0 = velocity
		self._speed = value < 0 and 0 or value
		self._time0 = now
	elseif index == "Clock" then
		local position, velocity = self:_positionVelocity(now)
		self._position0 = position
		self._velocity0 = velocity
		self._clock = value
		self._time0 = value()
	else
		error(("%q is not a valid member of Spring"):format(tostring(index)), 2)
	end
end

function Spring:_positionVelocity(now)
	local p0 = self._position0
	local v0 = self._velocity0
	local p1 = self._target
	local d = self._damper
	local s = self._speed

	local t = s*(now - self._time0)
	local d2 = d*d

	local h, si, co
	if d2 < 1 then
		h = math.sqrt(1 - d2)
		local ep = math.exp(-d*t)/h
		co, si = ep*math.cos(h*t), ep*math.sin(h*t)
	elseif d2 == 1 then
		h = 1
		local ep = math.exp(-d*t)/h
		co, si = ep, ep*t
	else
		h = math.sqrt(d2 - 1)
		local u = math.exp((-d + h)*t)/(2*h)
		local v = math.exp((-d - h)*t)/(2*h)
		co, si = u + v, u - v
	end

	local a0 = h*co + d*si
	local a1 = 1 - (h*co + d*si)
	local a2 = si/s

	local b0 = -s*si
	local b1 = s*si
	local b2 = h*co - d*si

	return
		a0*p0 + a1*p1 + a2*v0,
	b0*p0 + b1*p1 + b2*v0
end

return Spring

local RECOIL = Vector3.new(2.5,-0,5)

replace that with the line in the main script

By the looks of things, this is the line that manages camera recoil and you have this line in the a function bound to framerate, may i ask if you’re using an fps unlocker?
If so, that’s why your recoil is a lot higher than it should be.

You’ll might want to add DeltaTime checks to this.

local Accumulated = 0
local Rate = 1/60 -- 60 times a second

RunService.RenderStepped:Connect(function(DeltaTime)
	Accumulated += DeltaTime
	if Accumulated >= Rate then
		Accumulated -= Rate
		camera.CFrame *= CFrame.Angles(math.rad(RecoilSpring.Position.X),math.rad(RecoilSpring.Position.Y),math.rad(RecoilSpring.Position.Z))
	end
end)

That will bind camera movement to be locked at 60fps or lower, and as far as I know there isn’t anything you can do to stop lower FPS giving lower recoil.