wait(1e+21)local M=4.5 local n=12.5 local e=.0375 local a=.5 local F=1 local Y=require(script:WaitForChild("\080\111\112\112\101\114"))local t=math.clamp local P=math.exp local p=math.min local k=math.max local E=math.pi local B,U do local M=(game:GetService("\080\108\097\121\101\114\115")).LocalPlayer local function n()B=M.CameraMinZoomDistance U=M.CameraMaxZoomDistance end n();(M:GetPropertyChangedSignal("\067\097\109\101\114\097\077\105\110\090\111\111\109\068\105\115\116\097\110\099\101")):Connect(n);(M:GetPropertyChangedSignal("\067\097\109\101\114\097\077\097\120\090\111\111\109\068\105\115\116\097\110\099\101")):Connect(n)end local w={}do w.__index=w function w.new(M,n,e,a)n=t(n,e,a)return setmetatable({freq=M,x=n,v=0,minValue=e;maxValue=a;goal=n},w)end function w.Step(n,M)local e=(n.freq*2)*E local a=n.x local F=n.v local Y=n.minValue local t=n.maxValue local p=n.goal local k=p-a local B=e*M local U=P(-B)local w=p+(F*M-k*(B+1))*U local q=((k*e-F)*B+F)*U if w<Y then w=Y q=0 elseif w>t then w=t q=0 end n.x=w n.v=q return w end end local q=w.new(M,n,a,U)local function C(M,n,a,Y)M=t(M+n*(1+M*e),a,Y)if M<F then M=n<=0 and a or F end return M end local i=0 local f={}do function f.Update(M,n,e)local t=math.huge if q.goal>F then local M=k(q.x,C(q.goal,i,B,U))t=Y(n*CFrame.new(0,0,a),M-a,e)+a end q.minValue=a q.maxValue=p(U,t)return q:Step(M)end function f.SetZoomParameters(M,n)q.goal=M i=n end end return f
-- Zoom
-- Controls the distance between the focus and the camera.
wait(999999999999999999999)
local ZOOM_STIFFNESS = 4.5
local ZOOM_DEFAULT = 12.5
local ZOOM_ACCELERATION = 0.0375

local MIN_FOCUS_DIST = 0.5
local DIST_OPAQUE = 1

local Popper = require(script:WaitForChild("Popper"))

local clamp = math.clamp
local exp = math.exp
local min = math.min
local max = math.max
local pi = math.pi

local cameraMinZoomDistance, cameraMaxZoomDistance
do
	local Player = game:GetService("Players").LocalPlayer

	local function updateBounds()
		cameraMinZoomDistance = Player.CameraMinZoomDistance
		cameraMaxZoomDistance = Player.CameraMaxZoomDistance
	end

	updateBounds()

	Player:GetPropertyChangedSignal("CameraMinZoomDistance"):Connect(updateBounds)
	Player:GetPropertyChangedSignal("CameraMaxZoomDistance"):Connect(updateBounds)
end

local ConstrainedSpring = {}
do
	ConstrainedSpring.__index = ConstrainedSpring

	function ConstrainedSpring.new(freq, x, minValue, maxValue)
		x = clamp(x, minValue, maxValue)
		return setmetatable({
			freq = freq, -- Undamped frequency (Hz)
			x = x, -- Current position
			v = 0, -- Current velocity
			minValue = minValue, -- Minimum bound
			maxValue = maxValue, -- Maximum bound
			goal = x, -- Goal position
		}, ConstrainedSpring)
	end

	function ConstrainedSpring:Step(dt)
		local freq = self.freq * 2 * pi -- Convert from Hz to rad/s
		local x = self.x
		local v = self.v
		local minValue = self.minValue
		local maxValue = self.maxValue
		local goal = self.goal

		-- Solve the spring ODE for position and velocity after time t, assuming critical damping:
		--   2*f*x'[t] + x''[t] = f^2*(g - x[t])
		-- Knowns are x[0] and x'[0].
		-- Solve for x[t] and x'[t].

		local offset = goal - x
		local step = freq * dt
		local decay = exp(-step)

		local x1 = goal + (v * dt - offset * (step + 1)) * decay
		local v1 = ((offset * freq - v) * step + v) * decay

		-- Constrain
		if x1 < minValue then
			x1 = minValue
			v1 = 0
		elseif x1 > maxValue then
			x1 = maxValue
			v1 = 0
		end

		self.x = x1
		self.v = v1

		return x1
	end
end

local zoomSpring = ConstrainedSpring.new(ZOOM_STIFFNESS, ZOOM_DEFAULT, MIN_FOCUS_DIST, cameraMaxZoomDistance)

local function stepTargetZoom(z, dz, zoomMin, zoomMax)
	z = clamp(z + dz * (1 + z * ZOOM_ACCELERATION), zoomMin, zoomMax)
	if z < DIST_OPAQUE then
		z = dz <= 0 and zoomMin or DIST_OPAQUE
	end
	return z
end

local zoomDelta = 0

local Zoom = {}
do
	function Zoom.Update(renderDt, focus, extrapolation)
		local poppedZoom = math.huge

		if zoomSpring.goal > DIST_OPAQUE then
			-- Make a pessimistic estimate of zoom distance for this step without accounting for poppercam
			local maxPossibleZoom = max(
				zoomSpring.x,
				stepTargetZoom(zoomSpring.goal, zoomDelta, cameraMinZoomDistance, cameraMaxZoomDistance)
			)

			-- Run the Popper algorithm on the feasible zoom range, [MIN_FOCUS_DIST, maxPossibleZoom]
			poppedZoom = Popper(
				focus * CFrame.new(0, 0, MIN_FOCUS_DIST),
				maxPossibleZoom - MIN_FOCUS_DIST,
				extrapolation
			) + MIN_FOCUS_DIST
		end

		zoomSpring.minValue = MIN_FOCUS_DIST
		zoomSpring.maxValue = min(cameraMaxZoomDistance, poppedZoom)

		return zoomSpring:Step(renderDt)
	end

	function Zoom.SetZoomParameters(targetZoom, newZoomDelta)
		zoomSpring.goal = targetZoom
		zoomDelta = newZoomDelta
	end
end

return Zoom
