function OrbitalCamera.LoadNumberValueParameters(g)g:LoadOrCreateNumberValueParameter("\073\110\105\116\105\097\108\069\108\101\118\097\116\105\111\110","\078\117\109\098\101\114\086\097\108\117\101",nil)g:LoadOrCreateNumberValueParameter("\073\110\105\116\105\097\108\068\105\115\116\097\110\099\101","\078\117\109\098\101\114\086\097\108\117\101",nil)g:LoadOrCreateNumberValueParameter("\082\101\102\101\114\101\110\099\101\065\122\105\109\117\116\104","\078\117\109\098\101\114\086\097\108\117\101",g.SetAndBoundsCheckAzimuthValue)g:LoadOrCreateNumberValueParameter("\067\087\065\122\105\109\117\116\104\084\114\097\118\101\108","\078\117\109\098\101\114\086\097\108\117\101",g.SetAndBoundsCheckAzimuthValues)g:LoadOrCreateNumberValueParameter("\067\067\087\065\122\105\109\117\116\104\084\114\097\118\101\108","\078\117\109\098\101\114\086\097\108\117\101",g.SetAndBoundsCheckAzimuthValues)g:LoadOrCreateNumberValueParameter("\077\105\110\069\108\101\118\097\116\105\111\110","\078\117\109\098\101\114\086\097\108\117\101",g.SetAndBoundsCheckElevationValues)g:LoadOrCreateNumberValueParameter("\077\097\120\069\108\101\118\097\116\105\111\110","\078\117\109\098\101\114\086\097\108\117\101",g.SetAndBoundsCheckElevationValues)g:LoadOrCreateNumberValueParameter("\077\105\110\068\105\115\116\097\110\099\101","\078\117\109\098\101\114\086\097\108\117\101",g.SetAndBoundsCheckDistanceValues)g:LoadOrCreateNumberValueParameter("\077\097\120\068\105\115\116\097\110\099\101","\078\117\109\098\101\114\086\097\108\117\101",g.SetAndBoundsCheckDistanceValues)g:LoadOrCreateNumberValueParameter("\085\115\101\065\122\105\109\117\116\104\076\105\109\105\116\115","\066\111\111\108\086\097\108\117\101",g.SetAndBoundsCheckAzimuthValues)g.curAzimuthRad=math.rad(g.externalProperties.ReferenceAzimuth)g.curElevationRad=math.rad(g.externalProperties.InitialElevation)g.curDistance=g.externalProperties.InitialDistance g:SetAndBoundsCheckAzimuthValues()g:SetAndBoundsCheckElevationValues()g:SetAndBoundsCheckDistanceValues()end function OrbitalCamera.GetModuleName(g)return"\079\114\098\105\116\097\108\067\097\109\101\114\097"end function OrbitalCamera.SetInitialOrientation(X,g)if not g or not g.RootPart then warn("\079\114\098\105\116\097\108\067\097\109\101\114\097 \099\111\117\108\100 \110\111\116 \115\101\116 \105\110\105\116\105\097\108 \111\114\105\101\110\116\097\116\105\111\110 \100\117\101 \116\111 \109\105\115\115\105\110\103 \104\117\109\097\110\111\105\100")return end local m=(g.RootPart.CFrame.lookVector-Vector3.new(0,.23,0)).unit local f=Util.GetAngleBetweenXZVectors(m,X:GetCameraLookVector())local E=math.asin((X:GetCameraLookVector()).y)-math.asin(m.y)if not Util.IsFinite(f)then f=0 end if not Util.IsFinite(E)then E=0 end X.rotateInput=Vector2.new(f,E)end

function OrbitalCamera:LoadNumberValueParameters()
	-- These initial values do not require change listeners since they are read only once
	self:LoadOrCreateNumberValueParameter("InitialElevation", "NumberValue", nil)
	self:LoadOrCreateNumberValueParameter("InitialDistance", "NumberValue", nil)

	-- Note: ReferenceAzimuth is also used as an initial value, but needs a change listener because it is used in the calculation of the limits
	self:LoadOrCreateNumberValueParameter("ReferenceAzimuth", "NumberValue", self.SetAndBoundsCheckAzimuthValue)
	self:LoadOrCreateNumberValueParameter("CWAzimuthTravel", "NumberValue", self.SetAndBoundsCheckAzimuthValues)
	self:LoadOrCreateNumberValueParameter("CCWAzimuthTravel", "NumberValue", self.SetAndBoundsCheckAzimuthValues)
	self:LoadOrCreateNumberValueParameter("MinElevation", "NumberValue", self.SetAndBoundsCheckElevationValues)
	self:LoadOrCreateNumberValueParameter("MaxElevation", "NumberValue", self.SetAndBoundsCheckElevationValues)
	self:LoadOrCreateNumberValueParameter("MinDistance", "NumberValue", self.SetAndBoundsCheckDistanceValues)
	self:LoadOrCreateNumberValueParameter("MaxDistance", "NumberValue", self.SetAndBoundsCheckDistanceValues)
	self:LoadOrCreateNumberValueParameter("UseAzimuthLimits", "BoolValue", self.SetAndBoundsCheckAzimuthValues)

	-- Internal values set (in radians, from degrees), plus sanitization
	self.curAzimuthRad = math.rad(self.externalProperties["ReferenceAzimuth"])
	self.curElevationRad = math.rad(self.externalProperties["InitialElevation"])
	self.curDistance = self.externalProperties["InitialDistance"]

	self:SetAndBoundsCheckAzimuthValues()
	self:SetAndBoundsCheckElevationValues()
	self:SetAndBoundsCheckDistanceValues()
end

function OrbitalCamera:GetModuleName()
	return "OrbitalCamera"
end

function OrbitalCamera:SetInitialOrientation(humanoid)
	if not humanoid or not humanoid.RootPart then
		warn("OrbitalCamera could not set initial orientation due to missing humanoid")
		return
	end
	local newDesiredLook = (humanoid.RootPart.CFrame.lookVector - Vector3.new(0,0.23,0)).unit
	local horizontalShift = Util.GetAngleBetweenXZVectors(newDesiredLook, self:GetCameraLookVector())
	local vertShift = math.asin(self:GetCameraLookVector().y) - math.asin(newDesiredLook.y)
	if not Util.IsFinite(horizontalShift) then
		horizontalShift = 0
	end
	if not Util.IsFinite(vertShift) then
		vertShift = 0
	end
	self.rotateInput = Vector2.new(horizontalShift, vertShift)
end
