local function t(t,P,W)repeat local Y,b=CastRay(t,P,W)if Y and(Y.Transparency>.95 or Y.CanCollide==false)then table.insert(W,Y)else return Y,b end until false end local function P(t,P,W)local Y,b=Camera.FieldOfView,Camera.CoordinateFrame local i=P.y/(2*math.tan(math.rad(Y)/2))local D=Vector3.new(t.x-P.x/2,P.y/2-t.y,-i)local e=(b:vectorToWorldSpace(D)).Unit local h=math.acos(math.min(1,e:Dot(b.lookVector)))local E=W/math.sin(math.pi/2-h)return b.p+e*E end local function W(t)if t=="\067\097\109\101\114\097\083\117\098\106\101\099\116"then VehicleParts={}local t=Camera.CameraSubject if t then PopperEnabled=false for P,W in pairs(VALID_SUBJECTS)do if t:IsA(W)then PopperEnabled=true break end end if t:IsA("\086\101\104\105\099\108\101\083\101\097\116")then VehicleParts=t:GetConnectedParts(true)end end end end local function Y(t,P)PlayerCharacters[t]=P end local function b(t)if t:IsA("\080\108\097\121\101\114")then t.CharacterAdded:connect(function(P)Y(t,P)end)if t.Character then Y(t,t.Character)end end end local function i(t)if t:IsA("\080\108\097\121\101\114")then PlayerCharacters[t]=nil end end local function D(t)if t=="\067\117\114\114\101\110\116\067\097\109\101\114\097"then local t=workspace.CurrentCamera if t then Camera=t if CameraChangeConn then CameraChangeConn:disconnect()end CameraChangeConn=Camera.Changed:connect(W)W("\067\097\109\101\114\097\083\117\098\106\101\099\116")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
		VehicleParts = {}
		
		local newSubject = Camera.CameraSubject
		if newSubject then
			-- Determine if we should be popping at all
			PopperEnabled = false
			for _, subjectType in pairs(VALID_SUBJECTS) do
				if newSubject:IsA(subjectType) then
					PopperEnabled = true
					break
				end
			end
			
			-- Get all parts of the vehicle the player is controlling
			if newSubject:IsA('VehicleSeat') then
				VehicleParts = newSubject:GetConnectedParts(true)
			end
		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)
			OnCameraChanged('CameraSubject')
		end
	end
end
