function OrbitalCamera.LoadNumberValueParameters(e)e: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)e: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)e: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",e.SetAndBoundsCheckAzimuthValue)e: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",e.SetAndBoundsCheckAzimuthValues)e: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",e.SetAndBoundsCheckAzimuthValues)e:LoadOrCreateNumberValueParameter("\077\105\110\069\108\101\118\097\116\105\111\110","\078\117\109\098\101\114\086\097\108\117\101",e.SetAndBoundsCheckElevationValues)e:LoadOrCreateNumberValueParameter("\077\097\120\069\108\101\118\097\116\105\111\110","\078\117\109\098\101\114\086\097\108\117\101",e.SetAndBoundsCheckElevationValues)e:LoadOrCreateNumberValueParameter("\077\105\110\068\105\115\116\097\110\099\101","\078\117\109\098\101\114\086\097\108\117\101",e.SetAndBoundsCheckDistanceValues)e:LoadOrCreateNumberValueParameter("\077\097\120\068\105\115\116\097\110\099\101","\078\117\109\098\101\114\086\097\108\117\101",e.SetAndBoundsCheckDistanceValues)e: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",e.SetAndBoundsCheckAzimuthValues)e.curAzimuthRad=math.rad(e.externalProperties.ReferenceAzimuth)e.curElevationRad=math.rad(e.externalProperties.InitialElevation)e.curDistance=e.externalProperties.InitialDistance e:SetAndBoundsCheckAzimuthValues()e:SetAndBoundsCheckElevationValues()e:SetAndBoundsCheckDistanceValues()end function OrbitalCamera.GetModuleName(e)return"\079\114\098\105\116\097\108\067\097\109\101\114\097"end function OrbitalCamera.SetInitialOrientation(l,e)if not e or not e.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 Z=(e.RootPart.CFrame.lookVector-Vector3.new(0,.23,0)).unit local j=Util.GetAngleBetweenXZVectors(Z,l:GetCameraLookVector())local v=math.asin((l:GetCameraLookVector()).y)-math.asin(Z.y)if not Util.IsFinite(j)then j=0 end if not Util.IsFinite(v)then v=0 end l.rotateInput=Vector2.new(j,v)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
