local function U(U,I)return math.atan2(I.X*U.Z-I.Z*U.X,I.X*U.X+I.Z*U.Z)end local function I()local I=RootCameraCreator()local s=math.rad(220)local Q=math.rad(0)local C=math.rad(250)local n=2 local d=nil local y=.7 local l=0 local o=.1 local Y=1 local N=ZERO_VECTOR2 local Z=.8 local t=nil local B=tick()I.LastUserPanCamera=tick()function I.Update(d)local y=tick()local l=y-B local o=d.UserPanningTheCamera==true local Y=workspace.CurrentCamera local N=PlayersService.LocalPlayer local Z=d:GetHumanoid()local t=Y and Y.CameraSubject local X=t and t:IsA("\086\101\104\105\099\108\101\083\101\097\116")local E=t and t:IsA("\083\107\097\116\101\098\111\097\114\100\080\108\097\116\102\111\114\109")if B==nil or y-B>1 then I:ResetCameraLook()d.LastCameraTransform=nil end if B then local U=d:UpdateGamepad()if d:ShouldUseVRRotation()then d.RotateInput=d.RotateInput+d:GetVRRotationInput()else local I=math.min(.1,y-B)if U~=ZERO_VECTOR2 then o=true d.RotateInput=d.RotateInput+U*I end local s=0 if not(X or E)then s=s+(d.TurningLeft and-120 or 0)s=s+(d.TurningRight and 120 or 0)end if s~=0 then d.RotateInput=d.RotateInput+Vector2.new(math.rad(s*I),0)o=true end end end if o then Q=0 I.LastUserPanCamera=tick()end local R=y-I.LastUserPanCamera<n local D=d:GetSubjectPosition()if D and(N and Y)then local I=d:GetCameraZoom()if I<.5 then I=.5 end if d:GetShiftLock()and not d:IsInFirstPerson()then local U=d:RotateCamera(d:GetCameraLook(),d.RotateInput)local I=((U*XZ_VECTOR):Cross(UP_VECTOR)).unit*1.75 if IsFiniteVector3(I)then D=D+I end else if d.LastCameraTransform and not o then local I=d:IsInFirstPerson()if(X or E)and(B and(Z and Z.Torso))then if I then if d.LastSubjectCFrame and((X or E)and t:IsA("\066\097\115\101\080\097\114\116"))then local I=-U(d.LastSubjectCFrame.lookVector,t.CFrame.lookVector)if IsFinite(I)then d.RotateInput=d.RotateInput+Vector2.new(I,0)end Q=0 end elseif not R then local I=Z.Torso.CFrame.lookVector if E then I=t.CFrame.lookVector end Q=clamp(0,C,Q+s*l)local n=clamp(0,1,Q*l)if d:IsInFirstPerson()then n=1 end local y=U(I,d:GetCameraLook())if IsFinite(y)and math.abs(y)>.0001 then d.RotateInput=d.RotateInput+Vector2.new(y*n,0)end end end end end local n=d:RotateCamera(d:GetCameraLook(),d.RotateInput)d.RotateInput=ZERO_VECTOR2 Y.Focus=UserInputService.VREnabled and d:GetVRFocus(D,l)or CFrame.new(D)Y.CoordinateFrame=CFrame.new(Y.Focus.p-I*n,Y.Focus.p)+Vector3.new(0,d:GetCameraHeight(),0)d.LastCameraTransform=Y.CoordinateFrame d.LastCameraFocus=Y.Focus if X or E and t:IsA("\066\097\115\101\080\097\114\116")then d.LastSubjectCFrame=t.CFrame else d.LastSubjectCFrame=nil end end B=y end return I end return I

local function findAngleBetweenXZVectors(vec2, vec1)
	return math.atan2(vec1.X*vec2.Z-vec1.Z*vec2.X, vec1.X*vec2.X + vec1.Z*vec2.Z)
end

local function CreateClassicCamera()
	local module = RootCameraCreator()
	
	local tweenAcceleration = math.rad(220)
	local tweenSpeed = math.rad(0)
	local tweenMaxSpeed = math.rad(250)
	local timeBeforeAutoRotate = 2
	
	local lastThumbstickRotate = nil
	local numOfSeconds = 0.7
	local currentSpeed = 0
	local maxSpeed = 0.1
	local thumbstickSensitivity = 1
	local lastThumbstickPos = ZERO_VECTOR2
	local ySensitivity = 0.8
	local lastVelocity = nil
	
	local lastUpdate = tick()
	module.LastUserPanCamera = tick()
	function module:Update()
		local now = tick()
		local timeDelta = (now - lastUpdate)
		
		local userPanningTheCamera = (self.UserPanningTheCamera == true)
		local camera = 	workspace.CurrentCamera
		local player = PlayersService.LocalPlayer
		local humanoid = self:GetHumanoid()
		local cameraSubject = camera and camera.CameraSubject
		local isInVehicle = cameraSubject and cameraSubject:IsA('VehicleSeat')
		local isOnASkateboard = cameraSubject and cameraSubject:IsA('SkateboardPlatform')
		
		if lastUpdate == nil or now - lastUpdate > 1 then
			module:ResetCameraLook()
			self.LastCameraTransform = nil
		end	
		
		if lastUpdate then
			local gamepadRotation = self:UpdateGamepad()
			
			if self:ShouldUseVRRotation() then				
				self.RotateInput = self.RotateInput + self:GetVRRotationInput()
			else
				-- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from
				local delta = math.min(0.1, now - lastUpdate)
				
				if gamepadRotation ~= ZERO_VECTOR2 then
					userPanningTheCamera = true
					self.RotateInput = self.RotateInput + (gamepadRotation * delta)
				end

				local angle = 0
				if not (isInVehicle or isOnASkateboard) then
					angle = angle + (self.TurningLeft and -120 or 0)
					angle = angle + (self.TurningRight and 120 or 0)
				end
				
				if angle ~= 0 then
					self.RotateInput = self.RotateInput +  Vector2.new(math.rad(angle * delta), 0)
					userPanningTheCamera = true
				end
			end
		end

		-- Reset tween speed if user is panning
		if userPanningTheCamera then
			tweenSpeed = 0
			module.LastUserPanCamera = tick()
		end
		
		local userRecentlyPannedCamera = now - module.LastUserPanCamera < timeBeforeAutoRotate
		local subjectPosition = self:GetSubjectPosition()
		
		if subjectPosition and player and camera then
			local zoom = self:GetCameraZoom()
			if zoom < 0.5 then
				zoom = 0.5
			end
			
			if self:GetShiftLock() and not self:IsInFirstPerson() then
				-- We need to use the right vector of the camera after rotation, not before
				local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput)
				local offset = ((newLookVector * XZ_VECTOR):Cross(UP_VECTOR).unit * 1.75)

				if IsFiniteVector3(offset) then
					subjectPosition = subjectPosition + offset
				end
			else
				if self.LastCameraTransform and not userPanningTheCamera then
					local isInFirstPerson = self:IsInFirstPerson()
					if (isInVehicle or isOnASkateboard) and lastUpdate and humanoid and humanoid.Torso then
						if isInFirstPerson then
							if self.LastSubjectCFrame and (isInVehicle or isOnASkateboard) and cameraSubject:IsA('BasePart') then
								local y = -findAngleBetweenXZVectors(self.LastSubjectCFrame.lookVector, cameraSubject.CFrame.lookVector)
								if IsFinite(y) then
									self.RotateInput = self.RotateInput + Vector2.new(y, 0)
								end
								tweenSpeed = 0
							end
						elseif not userRecentlyPannedCamera then
							local forwardVector = humanoid.Torso.CFrame.lookVector
							if isOnASkateboard then
								forwardVector = cameraSubject.CFrame.lookVector
							end
							
							tweenSpeed = clamp(0, tweenMaxSpeed, tweenSpeed + tweenAcceleration * timeDelta)
	
							local percent = clamp(0, 1, tweenSpeed * timeDelta)
							if self:IsInFirstPerson() then
								percent = 1
							end
							
							local y = findAngleBetweenXZVectors(forwardVector, self:GetCameraLook())
							if IsFinite(y) and math.abs(y) > 0.0001 then
								self.RotateInput = self.RotateInput + Vector2.new(y * percent, 0)
							end
						end
					end
				end
			end
			
			local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput)
			self.RotateInput = ZERO_VECTOR2



			camera.Focus = UserInputService.VREnabled and self:GetVRFocus(subjectPosition, timeDelta) or CFrame.new(subjectPosition)
			camera.CoordinateFrame = CFrame.new(camera.Focus.p - (zoom * newLookVector), camera.Focus.p) + Vector3.new(0, self:GetCameraHeight(), 0)

			self.LastCameraTransform = camera.CoordinateFrame
			self.LastCameraFocus = camera.Focus
			if isInVehicle or isOnASkateboard and cameraSubject:IsA('BasePart') then
				self.LastSubjectCFrame = cameraSubject.CFrame
			else
				self.LastSubjectCFrame = nil
			end
		end
		
		lastUpdate = now
	end
	
	return module
end

return CreateClassicCamera
