local function G(G,t,q)repeat local U,O=CastRay(G,t,q)if U and(U.Transparency>.95 or U.CanCollide==false)then table.insert(q,U)else return U,O end until false end local function t(G,t,q)local U,O=Camera.FieldOfView,Camera.CoordinateFrame local j=t.y/(2*math.tan(math.rad(U)/2))local c=Vector3.new(G.x-t.x/2,t.y/2-G.y,-j)local L=(O:vectorToWorldSpace(c)).Unit local Y=math.acos(math.min(1,L:Dot(O.lookVector)))local m=q/math.sin(math.pi/2-Y)return O.p+L*m end local function q(G)if G=="\067\097\109\101\114\097\083\117\098\106\101\099\116"then local G=Camera.CameraSubject if G and G:IsA("\086\101\104\105\099\108\101\083\101\097\116")then VehicleParts=G:GetConnectedParts(true)else VehicleParts={}end end end local function U(G,t)PlayerCharacters[G]=t end local function O(G)if G:IsA("\080\108\097\121\101\114")then G.CharacterAdded:connect(function(t)U(G,t)end)if G.Character then U(G,G.Character)end end end local function j(G)if G:IsA("\080\108\097\121\101\114")then PlayerCharacters[G]=nil end end local function c(G)if G=="\067\117\114\114\101\110\116\067\097\109\101\114\097"then local G=workspace.CurrentCamera if G then Camera=G if CameraChangeConn then CameraChangeConn:disconnect()end CameraChangeConn=Camera.Changed:connect(q)end end end
-- Casts and recasts until it hits either: nothing, or something not transparent or collidable
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
