Get Higher Ancestor

I am attempting to create a system where when you hold a weapon and click it does a raycast and returns the first part it intersects with. I would like to go to the highest ancestor (right below game.workspace, so the model) and check a BoolValue inside said model. The reason I need to do this is because there are parts inside parts inside parts (for example, I have a mask with plenty of pieces, so I put them all inside a part with qPerfectionWeld which is then welded to a player’s head, which the main mask part is a child of.) If this is too confusing, let me know and I’ll try to break it down.

Tool’s raycast code:

local Tool = script.Parent --make sure this is a Tool object
 
Tool.Equipped:Connect(function(Mouse)
	Mouse.Button1Down:Connect(function()
		getMouseTarget()
	end)
end)

function getMouseTarget()
	local cursorPosition = game:GetService("UserInputService"):GetMouseLocation()
	local oray = game.workspace.CurrentCamera:ViewportPointToRay(cursorPosition.x, cursorPosition.y, 0)
	local ray = Ray.new(game.Workspace.CurrentCamera.CFrame.p,(oray.Direction * 1000))
	print(tostring(workspace:FindPartOnRay(ray)))
end
1 Like

Would this help?

function getHighestAncestorWithBoolValue(part)
	local parent = part.Parent
	while (parent ~= workspace and parent ~= nil) do
		if parent:FindFirstChild("NameOfTheBoolValueYoureLookingFor") ~= nil then
			return parent
		else
			parent = parent.Parent
		end
	end
end

This function should return null if called on a part that has no boolvalue or is parented to nil.

2 Likes

I’m sure there’s a way to do this using :FindFirstAncestor, however I’m not too familiar with it.

I’d personally do it using Indexing.

local Tool = script.Parent --make sure this is a Tool object
 
Tool.Equipped:Connect(function(Mouse)
	Mouse.Button1Down:Connect(function()
		getMouseTarget()
	end)
end)

function getMouseTarget()
	local cursorPosition = game:GetService("UserInputService"):GetMouseLocation()
	local oray = game.workspace.CurrentCamera:ViewportPointToRay(cursorPosition.x, cursorPosition.y, 0)
	local ray = Ray.new(game.Workspace.CurrentCamera.CFrame.p,(oray.Direction * 1000))
	
	Checker(ray)
end

function Checker(ray)
	local a = workspace:FindPartOnRay(ray)
	local b
	for i = 1, 250 do wait()
		if a then -- Makes sure there's a Ray to begin with,
			if a:FindFirstChild("BoolValue") ~= nil then -- Checks to see if the Ray has the required value in it,
				b = a["BoolValue"] -- Sets the value,
				print("BoolValue found.")
				break
			else
				a = a.Parent -- If the Ray or current 'a' doesn't have the desired Value in it, it'll work it's way up through the parents.
			end
		end
	end
end

While I’m sure Blokav’s will work, yours seems to be more reliable so I will go with that.