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("\103\101\116\082\111\116\097\116\105\111\110\073\110\088\090\080\108\097\110\101")local h=N("\083\117\109\109\101\100\067\097\109\101\114\097")local d={}d.ClassName="\082\111\116\097\116\101\100\067\097\109\101\114\097"d._MaxY=math.rad(80)d._MinY=math.rad(-80)d._AngleXZ=0 d._AngleY=0 function d.new()local N=setmetatable({},d)return N end function d.__add(C,N)return h.new(C,N)end function d.RotateXY(C,N)C.AngleX=C.AngleX+N.x C.AngleY=C.AngleY+N.y end function d.__newindex(h,N,C)if N=="\067\070\114\097\109\101"then local N=F(C)h.AngleXZ=math.atan2(N.lookVector.x,N.lookVector.z)+math.pi local d=(N:toObjectSpace(C)).lookVector.y h.AngleY=math.asin(d)elseif N=="\065\110\103\108\101\089"then h._AngleY=math.clamp(C,h.MinY,h.MaxY)elseif N=="\065\110\103\108\101\088"or N=="\065\110\103\108\101\088\090"then h._AngleXZ=C elseif N=="\077\097\120\089"then assert(C>=h.MinY,"\077\097\120\089 \109\117\115\116 \098\101 \103\114\101\097\116\101\114 \116\104\097\110 \077\105\110\089")h._MaxY=C h.AngleY=h.AngleY elseif N=="\077\105\110\089"then assert(C<=h.MaxY,"\077\105\110\089 \109\117\115\116 \098\101 \108\101\115\115 \116\104\097\110 \077\097\120\089")h._MinY=C h.AngleY=h.AngleY elseif d[N]~=nil then rawset(h,N,C)else error(N.." \105\115 \110\111\116 \097 \118\097\108\105\100 \109\101\109\098\101\114 \111\114 \082\111\116\097\116\101\100\067\097\109\101\114\097")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.CFrame=F.CFrame return N elseif N=="\076\111\111\107\086\101\099\116\111\114"then return F.Rotation.lookVector elseif N=="\067\070\114\097\109\101"then return CFrame.Angles(0,F.AngleXZ,0)*CFrame.Angles(F.AngleY,0,0)elseif N=="\065\110\103\108\101\089"then return F._AngleY elseif N=="\065\110\103\108\101\088"or N=="\065\110\103\108\101\088\090"then return F._AngleXZ elseif N=="\077\097\120\089"then return F._MaxY elseif N=="\077\105\110\089"then return F._MinY 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. This is the rotation component.
-- Intended to be used with a SummedCamera, relative.
-- @classmod RotatedCamera

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

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

local RotatedCamera = {}
RotatedCamera.ClassName = "RotatedCamera"

-- Max/Min aim up and down
RotatedCamera._MaxY = math.rad(80)
RotatedCamera._MinY = math.rad(-80)
RotatedCamera._AngleXZ = 0
RotatedCamera._AngleY = 0

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

	return self
end

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

---
-- @param xzrotvector Vector2, the delta rotation to apply
function RotatedCamera:RotateXY(xzrotvector)
	self.AngleX = self.AngleX + xzrotvector.x
	self.AngleY = self.AngleY + xzrotvector.y
end

function RotatedCamera:__newindex(index, value)
	if index == "CFrame" then
		local zxrot = getRotationInXZPlane(value)
		self.AngleXZ = math.atan2(zxrot.lookVector.x, zxrot.lookVector.z) + math.pi

		local yrot = zxrot:toObjectSpace(value).lookVector.y
		self.AngleY = math.asin(yrot)
	elseif index == "AngleY" then
		self._AngleY = math.clamp(value, self.MinY, self.MaxY)
	elseif index == "AngleX" or index == "AngleXZ" then
		self._AngleXZ = value
	elseif index == "MaxY" then
		assert(value >= self.MinY, "MaxY must be greater than MinY")
		self._MaxY = value
		self.AngleY = self.AngleY -- Reclamp value
	elseif index == "MinY" then
		assert(value <= self.MaxY, "MinY must be less than MaxY")
		self._MinY = value
		self.AngleY = self.AngleY -- Reclamp value
	elseif RotatedCamera[index] ~= nil then
		rawset(self, index, value)
	else
		error(index .. " is not a valid member or RotatedCamera")
	end
end

function RotatedCamera:__index(index)
	if index == "State" or index == "CameraState" or index == "Camera" then
		local State = CameraState.new()
		State.CFrame = self.CFrame
		return State
	elseif index == "LookVector" then
		return self.Rotation.lookVector
	elseif index == "CFrame" then
		return CFrame.Angles(0, self.AngleXZ, 0) * CFrame.Angles(self.AngleY, 0, 0)
	elseif index == "AngleY" then
		return self._AngleY
	elseif index == "AngleX" or index == "AngleXZ" then
		return self._AngleXZ
	elseif index == "MaxY" then
		return self._MaxY
	elseif index == "MinY" then
		return self._MinY
	else
		return RotatedCamera[index]
	end
end

return RotatedCamera