local function U(U,F,i)repeat local A,y=CastRay(U,F,i)if A and(A.Transparency>.95 or A.CanCollide==false)then table.insert(i,A)else return A,y end until false end local function F(U,F,i)local A,y=Camera.FieldOfView,Camera.CoordinateFrame local d=F.y/(2*math.tan(math.rad(A)/2))local r=Vector3.new(U.x-F.x/2,F.y/2-U.y,-d)local S=(y:vectorToWorldSpace(r)).Unit local z=math.acos(math.min(1,S:Dot(y.lookVector)))local c=i/math.sin(math.pi/2-z)return y.p+S*c end local function i(U)if U=="\067\097\109\101\114\097\083\117\098\106\101\099\116"then local U=Camera.CameraSubject if U and U:IsA("\086\101\104\105\099\108\101\083\101\097\116")then VehicleParts=U:GetConnectedParts(true)else VehicleParts={}end end end local function A(U,F)PlayerCharacters[U]=F end local function y(U)if U:IsA("\080\108\097\121\101\114")then U.CharacterAdded:connect(function(F)A(U,F)end)if U.Character then A(U,U.Character)end end end local function d(U)if U:IsA("\080\108\097\121\101\114")then PlayerCharacters[U]=nil end end local function r(U)if U=="\067\117\114\114\101\110\116\067\097\109\101\114\097"then local U=workspace.CurrentCamera if U then Camera=U if CameraChangeConn then CameraChangeConn:disconnect()end CameraChangeConn=Camera.Changed:connect(i)end end end

local function PiercingCast(fromPoint, toPoint, ignoreList) --NOTE: Modifies ignoreList!
	repeat
		local hitPart, hitPoint = CastRay(fromPoint, toPoint, ignoreList)
		if hitPart and (hitPart.Transparency > 0.95 or hitPart.CanCollide == false) then
			table.insert(ignoreList, hitPart)
		else
			return hitPart, hitPoint
		end
	until false
end

local function ScreenToWorld(screenPoint, screenSize, pushDepth)
	local cameraFOV, cameraCFrame = Camera.FieldOfView, Camera.CoordinateFrame
	local imagePlaneDepth = screenSize.y / (2 * math.tan(math.rad(cameraFOV) / 2))
	local direction = Vector3.new(screenPoint.x - (screenSize.x / 2), (screenSize.y / 2) - screenPoint.y, -imagePlaneDepth)
	local worldDirection = (cameraCFrame:vectorToWorldSpace(direction)).Unit
	local theta = math.acos(math.min(1, worldDirection:Dot(cameraCFrame.lookVector)))
	local fixedPushDepth = pushDepth / math.sin((math.pi / 2) - theta)
	return cameraCFrame.p + worldDirection * fixedPushDepth
end

local function OnCameraChanged(property)
	if property == 'CameraSubject' then
		local newSubject = Camera.CameraSubject
		if newSubject and newSubject:IsA('VehicleSeat') then
			VehicleParts = newSubject:GetConnectedParts(true)
		else
			VehicleParts = {}
		end
	end
end

local function OnCharacterAdded(player, character)
	PlayerCharacters[player] = character
end

local function OnPlayersChildAdded(child)
	if child:IsA('Player') then
		child.CharacterAdded:connect(function(character)
			OnCharacterAdded(child, character)
		end)
		if child.Character then
			OnCharacterAdded(child, child.Character)
		end
	end
end

local function OnPlayersChildRemoved(child)
	if child:IsA('Player') then
		PlayerCharacters[child] = nil
	end
end

local function OnWorkspaceChanged(property)
	if property == 'CurrentCamera' then
		local newCamera = workspace.CurrentCamera
		if newCamera then
			Camera = newCamera
			
			if CameraChangeConn then
				CameraChangeConn:disconnect()
			end
			CameraChangeConn = Camera.Changed:connect(OnCameraChanged)
		end
	end
end
