local N=require((game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")):WaitForChild("\078\101\118\101\114\109\111\114\101"))local C=N("\067\097\109\101\114\097\083\116\097\116\101")local F=N("\083\117\109\109\101\100\067\097\109\101\114\097")local h=N("\083\112\114\105\110\103")local d={}d.ClassName="\083\109\111\111\116\104\090\111\111\109\101\100\067\097\109\101\114\097"d._maxZoom=100 d._minZoom=.5 d.BounceAtEnd=true function d.new()local N=setmetatable({},d)N.Spring=h.new(0)N.Speed=15 return N end function d.__add(C,N)return F.new(C,N)end function d.ZoomIn(h,N,C,F)if C or F then h.Zoom=h.Zoom-math.clamp(N,C or-math.huge,F or math.huge)else h.Zoom=h.Zoom-N end end function d.Impulse(C,N)C.Spring:Impulse(N)end function d.__newindex(F,N,C)if N=="\084\097\114\103\101\116\090\111\111\109"or N=="\084\097\114\103\101\116"then local N=math.clamp(C,F.MinZoom,F.MaxZoom)F.Spring.Target=N if F.BounceAtEnd then if N<C then F:Impulse(F.MaxZoom)elseif N>C then F:Impulse(-F.MinZoom)end end elseif N=="\084\097\114\103\101\116\080\101\114\099\101\110\116\090\111\111\109"then F.Target=F.MinZoom+F.Range*C elseif N=="\080\101\114\099\101\110\116\090\111\111\109"then F.Zoom=F.MinZoom+F.Range*C elseif N=="\068\097\109\112\101\114"then F.Spring.Damper=C elseif N=="\086\097\108\117\101"or N=="\090\111\111\109"then F.Spring.Value=math.clamp(C,F.MinZoom,F.MaxZoom)elseif N=="\083\112\101\101\100"then F.Spring.Speed=C elseif N=="\077\097\120\090\111\111\109"then F._maxZoom=C elseif N=="\077\105\110\090\111\111\109"then F._minZoom=C else rawset(F,N,C)end end function d.__index(F,N)if N=="\083\116\097\116\101"or N=="\067\097\109\101\114\097\083\116\097\116\101"or N=="\067\097\109\101\114\097"then local N=C.new()N.Position=Vector3.new(0,0,F.Zoom)return N elseif N=="\090\111\111\109"or N=="\118\097\108\117\101"then return F.Spring.Value elseif N=="\084\097\114\103\101\116\080\101\114\099\101\110\116\090\111\111\109"then return(F.Target-F.MinZoom)/F.Range elseif N=="\080\101\114\099\101\110\116\090\111\111\109"then return(F.Zoom-F.MinZoom)/F.Range elseif N=="\077\097\120\090\111\111\109"then return F._maxZoom elseif N=="\077\105\110\090\111\111\109"then return F._minZoom elseif N=="\082\097\110\103\101"then return F.MaxZoom-F.MinZoom elseif N=="\068\097\109\112\101\114"then return F.Spring.Damper elseif N=="\083\112\101\101\100"then return F.Spring.Speed elseif N=="\084\097\114\103\101\116"or N=="\084\097\114\103\101\116\090\111\111\109"then return F.Spring.Target elseif N=="\086\101\108\111\099\105\116\121"then return F.Spring.Velocity elseif N=="\072\097\115\082\101\097\099\104\101\100\084\097\114\103\101\116"then return math.abs(F.Value-F.Target)<.0001 and math.abs(F.Velocity)<.0001 else return d[N]end end return d
--- Allow freedom of movement around a current place, much like the classic script works now.
-- Not intended to be use with the current character script
-- Intended to be used with a SummedCamera, relative.
-- @classmod SmoothZoomedCamera

local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore"))

local CameraState = require("CameraState")
local SummedCamera = require("SummedCamera")
local Spring = require("Spring")

local SmoothZoomedCamera = {}
SmoothZoomedCamera.ClassName = "SmoothZoomedCamera"
SmoothZoomedCamera._maxZoom = 100
SmoothZoomedCamera._minZoom = 0.5
SmoothZoomedCamera.BounceAtEnd = true

function SmoothZoomedCamera.new()
	local self = setmetatable({}, SmoothZoomedCamera)

	self.Spring = Spring.new(0)
	self.Speed = 15

	return self
end

function SmoothZoomedCamera:__add(other)
	return SummedCamera.new(self, other)
end

function SmoothZoomedCamera:ZoomIn(value, min, max)
	if min or max then
		self.Zoom = self.Zoom - math.clamp(value, min or -math.huge, max or math.huge)
	else
		self.Zoom = self.Zoom - value
	end
end

function SmoothZoomedCamera:Impulse(value)
	self.Spring:Impulse(value)
end


function SmoothZoomedCamera:__newindex(index, value)
	if index == "TargetZoom" or index == "Target" then
		local target = math.clamp(value, self.MinZoom, self.MaxZoom)
		self.Spring.Target = target

		if self.BounceAtEnd then
			if target < value then
				self:Impulse(self.MaxZoom)
			elseif target > value then
				self:Impulse(-self.MinZoom)
			end
		end
	elseif index == "TargetPercentZoom" then
		self.Target = self.MinZoom + self.Range*value
	elseif index == "PercentZoom" then
		self.Zoom = self.MinZoom + self.Range*value
	elseif index == "Damper" then
		self.Spring.Damper = value
	elseif index == "Value" or index == "Zoom" then
		self.Spring.Value = math.clamp(value, self.MinZoom, self.MaxZoom)
	elseif index == "Speed" then
		self.Spring.Speed = value
	elseif index == "MaxZoom" then
		--assert(value > self.MinZoom, "MaxZoom can't be less than MinZoom")

		self._maxZoom = value
	elseif index == "MinZoom" then
		--assert(value < self.MaxZoom, "MinZoom can't be greater than MinZoom")

		self._minZoom = value
	else
		rawset(self, index, value)
	end
end

function SmoothZoomedCamera:__index(index)
	if index == "State" or index == "CameraState" or index == "Camera" then
		local state = CameraState.new()
		state.Position = Vector3.new(0, 0, self.Zoom)
		return state
	elseif index == "Zoom" or index == "value" then
		return self.Spring.Value
	elseif index == "TargetPercentZoom" then
		return (self.Target - self.MinZoom) / self.Range
	elseif index == "PercentZoom" then
		return (self.Zoom - self.MinZoom) / self.Range
	elseif index == "MaxZoom" then
		return self._maxZoom
	elseif index == "MinZoom" then
		return self._minZoom
	elseif index == "Range" then
		return self.MaxZoom - self.MinZoom
	elseif index == "Damper" then
		return self.Spring.Damper
	elseif index == "Speed" then
		return self.Spring.Speed
	elseif index == "Target" or index == "TargetZoom" then
		return self.Spring.Target
	elseif index == "Velocity" then
		return self.Spring.Velocity
	elseif index == "HasReachedTarget" then
		return math.abs(self.Value - self.Target) < 1e-4 and math.abs(self.Velocity) < 1e-4
	else
		return SmoothZoomedCamera[index]
	end
end

return SmoothZoomedCamera