local function Q(Q,i)return math.atan2(i.X*Q.Z-i.Z*Q.X,i.X*Q.X+i.Z*Q.Z)end local function i(Q,i)local N=(i:Cross(Q)).unit local B=(Q:Cross(N)).unit Q=Q.unit return CFrame.new(0,0,0,N.x,B.x,Q.x,N.y,B.y,Q.y,N.z,B.z,Q.z)end local function N()local i=RootCameraCreator()local N=tick()function i.Update(B)local V=tick()local h=workspace.CurrentCamera local O=PlayersService.LocalPlayer if N==nil or V-N>1 then i:ResetCameraLook()B.LastCameraTransform=nil end local H=B:GetSubjectPosition()if H and(O and h)then local i=B:GetCameraZoom()if i<=0 then i=.1 end if B.LastCameraTransform then local i=B:GetHumanoid()if N and(i and i.Torso)then local N=i.Torso.CFrame.lookVector local V=Q(N,B:GetCameraLook())if IsFinite(V)and math.abs(V)>.0001 then B.RotateInput=B.RotateInput+Vector2.new(V,0)end end end local V=B:RotateCamera(B:GetCameraLook(),B.RotateInput)B.RotateInput=Vector2.new()h.Focus=CFrame.new(H)h.CoordinateFrame=CFrame.new(h.Focus.p-i*V,h.Focus.p)B.LastCameraTransform=h.CoordinateFrame end N=V end return i end return N
-- May return NaN or inf or -inf
-- This is a way of finding the angle between the two vectors:
local function findAngleBetweenXZVectors(vec2, vec1)
	return math.atan2(vec1.X * vec2.Z - vec1.Z * vec2.X, vec1.X * vec2.X + vec1.Z * vec2.Z)
end

local function GetOrientationZY(backVector, upVector)
	local rightVector = upVector:Cross(backVector).unit
	local upVector = backVector:Cross(rightVector).unit
	backVector = backVector.unit
	return CFrame.new(
		0,
		0,
		0,
		rightVector.x,
		upVector.x,
		backVector.x,
		rightVector.y,
		upVector.y,
		backVector.y,
		rightVector.z,
		upVector.z,
		backVector.z
	)
end

local function CreateAttachCamera()
	local module = RootCameraCreator()

	local lastUpdate = tick()
	function module:Update()
		local now = tick()

		local camera = workspace.CurrentCamera
		local player = PlayersService.LocalPlayer

		if lastUpdate == nil or now - lastUpdate > 1 then
			module:ResetCameraLook()
			self.LastCameraTransform = nil
		end

		local subjectPosition = self:GetSubjectPosition()
		if subjectPosition and player and camera then
			local zoom = self:GetCameraZoom()
			if zoom <= 0 then
				zoom = 0.1
			end

			if self.LastCameraTransform then
				local humanoid = self:GetHumanoid()
				if lastUpdate and humanoid and humanoid.Torso then
					local forwardVector = humanoid.Torso.CFrame.lookVector

					local y = findAngleBetweenXZVectors(forwardVector, self:GetCameraLook())
					if IsFinite(y) and math.abs(y) > 0.0001 then
						self.RotateInput = self.RotateInput + Vector2.new(y, 0)
					end
				end
			end
			local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput)
			self.RotateInput = Vector2.new()

			camera.Focus = CFrame.new(subjectPosition)
			camera.CoordinateFrame = CFrame.new(camera.Focus.p - (zoom * newLookVector), camera.Focus.p)
			self.LastCameraTransform = camera.CoordinateFrame
		end
		lastUpdate = now
	end

	return module
end

return CreateAttachCamera
