local c=Vector3.new local K=math.max local w=math.pi local Z=w*2 local m=tick local function D(c,K)local m=(K-c)%Z return m>w and m-Z or m end local function C(K,w)return c(D(K.X,w.X),D(K.Y,w.Y),D(K.Z,w.Z))end local P={}P.__index=P function P.new()return setmetatable({MaxSpeed=math.huge;_update=m();_velocity=c()},P)end function P.Update(D,c,w,Z)local C=D._velocity local P=m()local n=P-D._update Z=K(.0001,Z)local N=2/Z local J=N*n local t=1/(((1+J)+(.48*J)*J)+((.235*J)*J)*J)local H=c-w local T=w local I=D.MaxSpeed*Z H=H.Magnitude>I and H.Unit*I or H w=c-H local q=(C+N*H)*n C=(C-N*q)*t local u=w+(H+q)*t if(T-c):Dot(u-T)>0 then u=T C=(u-T)/n end D._velocity=C D._update=P return u end function P.UpdateAngle(Z,c,K,w)return Z:Update(c,c+C(c,K),w)end return P
-- Smooth Damp
-- Crazyman32
-- January 30, 2017

--[[
	
	local SmoothDamp = require(this)
	
	smooth = SmoothDamp.new()
	smooth.MaxSpeed
	smooth:Update(currentVector, targetVector, smoothTime)
	smooth:UpdateAngle(currentVector, targetVector, smoothTime)
	
	
	Use UpdateAngle if smoothing out angles. The only difference is that
	it makes sure angles wrap properly (in radians). For instance, if
	damping a rotating wheel, UpdateAngle should be used.
	
	
	-- Example:
	
	local smooth = SmoothDamp.new()
	function Update()
		local current = camera.CFrame.p
		local target = (part.CFrame * CFrame.new(0, 5, -10)).p
		local camPos = smooth:Update(current, target, 0.2)
		camera.CFrame = CFrame.new(camPos, part.Position)
	end
	
--]]


----------------------------------------------------------------------------------------------------------------

local Vector3_new = Vector3.new
local math_max = math.max
local PI = math.pi
local TAU = PI * 2
local tick = tick

local function DeltaAngle(current, target)
	local n = ((target - current) % TAU)
	return (n > PI and (n - TAU) or n)
end

local function DeltaAngleV3(p1, p2)
	return Vector3_new(DeltaAngle(p1.X, p2.X), DeltaAngle(p1.Y, p2.Y), DeltaAngle(p1.Z, p2.Z))
end

----------------------------------------------------------------------------------------------------------------

local SmoothDamp = {}
SmoothDamp.__index = SmoothDamp

function SmoothDamp.new()
	return setmetatable({
		MaxSpeed = math.huge;
		_update = tick();
		_velocity = Vector3_new();
	}, SmoothDamp)
end

function SmoothDamp:Update(current, target, smoothTime)
	local currentVelocity = self._velocity
	local now = tick()
	local deltaTime = (now - self._update)
	smoothTime = math_max(0.0001, smoothTime)
	local num = (2 / smoothTime)
	local num2 = (num * deltaTime)
	local d = (1 / (1 + num2 + 0.48 * num2 * num2 + 0.235 * num2 * num2 * num2))
	local vector = (current - target)
	local vector2 = target
	local maxLength = (self.MaxSpeed * smoothTime)
	vector = vector.Magnitude > maxLength and (vector.Unit * maxLength) or vector -- Clamp magnitude.
	target = (current - vector)
	local vector3 = ((currentVelocity + num * vector) * deltaTime)
	currentVelocity = ((currentVelocity - num * vector3) * d)
	local vector4 = (target + (vector + vector3) * d)
	if ((vector2 - current):Dot(vector4 - vector2) > 0) then
		vector4 = vector2
		currentVelocity = ((vector4 - vector2) / deltaTime)
	end
	self._velocity = currentVelocity
	self._update = now
	return vector4
end

function SmoothDamp:UpdateAngle(current, target, smoothTime)
	return self:Update(current, (current + DeltaAngleV3(current, target)), smoothTime)
end

return SmoothDamp
