--------------------[ TWEEN FUNCTIONS ]-----------------------------------------------

function TweenJoint(Joint, NewC0, NewC1, Alpha, Duration)
	coroutine.resume(coroutine.create(function()
		local TweenIndicator = nil --At the current moment, this is how the script determines whether the function is already tweening a joint
		local NewCode = math.random(-1e9, 1e9) --This creates a random code between -1000000000 and 1000000000
		if (not Joint:FindFirstChild("TweenCode")) then --If the joint isn't being tweened, then
			TweenIndicator = Instance.new("IntValue")
			TweenIndicator.Name = "TweenCode"
			TweenIndicator.Value = NewCode
			TweenIndicator.Parent = Joint
		else
			TweenIndicator = Joint.TweenCode
			TweenIndicator.Value = NewCode --If the joint is already being tweened, this will change the code, and the tween loop will stop
		end
		local MatrixCFrame = function(CFPos, CFTop, CFBack)
			local CFRight = CFTop:Cross(CFBack)
			return CF(
				CFPos.x, CFPos.y, CFPos.z,
				CFRight.x, CFTop.x, CFBack.x,
				CFRight.y, CFTop.y, CFBack.y,
				CFRight.z, CFTop.z, CFBack.z
			)
		end
		local LerpCF = function(StartCF, EndCF, Alpha)
			local StartTop = (StartCF * CFANG(RAD(90), 0, 0)).lookVector
			local StartBack = -StartCF.lookVector
			local EndTop = (EndCF * CFANG(RAD(90), 0, 0)).lookVector
			local EndBack = -EndCF.lookVector
			local StartPos = StartCF.p
			local EndPos = EndCF.p
			local NewCF = MatrixCFrame(
				StartPos:lerp(EndPos, Alpha),
				StartTop:lerp(EndTop, Alpha),
				StartBack:lerp(EndBack, Alpha)
			)
			return NewCF
		end
		local StartC0 = Joint.C0
		local StartC1 = Joint.C1
		local X = 0
		while true do
			local NewX = X + math.min(1.5 / math.max(Duration, 0), 90)
			X = (NewX > 90 and 90 or NewX)
			if TweenIndicator.Value ~= NewCode then break end --This makes sure that another tween wasn't called on the same joint
			if (not Selected) then break end --This stops the tween if the tool is deselected
			if NewC0 then Joint.C0 = LerpCF(StartC0, NewC0, Alpha(X)) end
			if NewC1 then Joint.C1 = LerpCF(StartC1, NewC1, Alpha(X)) end
			if X == 90 then break end
			RS:wait() --This makes the for loop step every 1/60th of a second
		end
		if TweenIndicator.Value == NewCode then --If this tween functions was the last one called on a joint then it will remove the code
			TweenIndicator:Destroy()
		end
	end))
end

function RotCamera(RotX, RotY, SmoothRot, Duration)
	spawn(function()
		if SmoothRot then
			local TweenIndicator = nil
			local NewCode = math.random(-1e9, 1e9)
			if (not Camera:FindFirstChild("TweenCode")) then
				TweenIndicator = Instance.new("IntValue")
				TweenIndicator.Name = "TweenCode"
				TweenIndicator.Value = NewCode
				TweenIndicator.Parent = Camera
			else
				TweenIndicator = Camera.TweenCode
				TweenIndicator.Value = NewCode
			end
			
			local Step = math.min(1.5 / math.max(Duration, 0), 90)
			local X = 0
			while true do
				local NewX = X + Step
				X = (NewX > 90 and 90 or NewX)
				if TweenIndicator.Value ~= NewCode then break end
				if (not Selected) then break end
				
				local CamRot = Camera.CoordinateFrame - Camera.CoordinateFrame.p
				local CamDist = (Camera.CoordinateFrame.p - Camera.Focus.p).magnitude
				local NewCamCF = CF(Camera.Focus.p) * CamRot * CFANG(RotX / (90 / Step), RotY / (90 / Step), 0)
				Camera.CoordinateFrame = CF(NewCamCF.p, NewCamCF.p + NewCamCF.lookVector) * CF(0, 0, CamDist)
				
				if X == 90 then break end
				RS:wait()
			end
			
			if TweenIndicator.Value == NewCode then
				TweenIndicator:Destroy()
			end
		else
			local CamRot = Camera.CoordinateFrame - Camera.CoordinateFrame.p
			local CamDist = (Camera.CoordinateFrame.p - Camera.Focus.p).magnitude
			local NewCamCF = CF(Camera.Focus.p) * CamRot * CFANG(RotX, RotY, 0)
			Camera.CoordinateFrame = CF(NewCamCF.p, NewCamCF.p + NewCamCF.lookVector) * CF(0, 0, CamDist)
		end
	end)
end