Setting 2 mouse.TargetFilter's

Problem
com-video-to-gif

if mouse.Target.Name == 'Hitbox' then
    mouse.TargetFilter = mouse.Target
end
					
if mouse.Target.Name == 'Spawn' then
    mouse.TargetFilter = mouse.Target
end

Problem being that if one is set, the other becomes unset, and causes further problems. So I need basically both of these items to have their TargetFilterer

4 Likes

MouseFilter isn’t powerful enough. You need to use raycasts.

7 Likes

How would I go about having to change what I got then, becausae the system I have currently works like a charm, and I don’t really wanna have to change it all now

if mouse.Target.Name == 'Hitbox' then
				        mouse.TargetFilter = mouse.Target
					end
					
					if mouse.Target.Name == 'Spawn' then
				        mouse.TargetFilter = mouse.Target
					end
										
					if mouse.Target.Name == 'Base' or mouse.Target.Name == 'PlaceArea' then
						playersPlot.PrimaryPart = mouse.Target
					end
					
					local cframe = placement(
						playersPlot.PrimaryPart,
						itemClone, 
						mouse.Hit.p, 
						var.Rotation
					)
					itemClone:SetPrimaryPartCFrame(cframe)

For starters, the mouse has a UnitRay property, which returns a Ray that’s oriented at where the mouse is on the screen.

Since this ray is only one stud long, you’ll need to make a new ray with the length that you want, and then do your raycasts using that ray.

local ray = Mouse.UnitRay
ray = Ray.new(ray.Origin, ray.Direction)

-- Do your raycasts here with Spawn and Hitbox in the ignore list, 
-- or cast the ray again until you hit either nothing or something that isn't named Hitbox/Spawn 
1 Like

So using this, I wouldn’t have to change how my placement etc. works?

You’ll need to stop using the mouse’s Hit property and use whatever position that the raycast returns instead.

There’s also probably an if mouse.Target == nil check above that code that you didn’t include. You’ll need to perform your raycast before that and check that the raycast didn’t hit nothing instead.

Ok sweet. Not entirely sure how to get the ignore and all that. Looking at the wiki with this

local ray = Ray.new(
    Weapon.Handle.CFrame.p,                           -- origin
    (mouse.Hit.p - Weapon.Handle.CFrame.p).unit * 500 -- direction
) 
local ignore = game.Players.LocalPlayer.Character
local hit, position, normal = Workspace:FindPartOnRay(ray, ignore)

It only has 1 ignore variable. How could I go about it with the 2 then?

And then removing mouse.Hit and mouse.Target, would they just be changed to ray?

if ray then
    -- etc..
    local cframe = placement(
        playersPlot.PrimaryPart,
        itemClone, 
        ray, 
        var.Rotation
    )
    itemClone:SetPrimaryPartCFrame(cframe)  
end

And also, since I’m ignoring items with names of ‘Hitbox’ and ‘Spawn’ is there anyway to ignore names? As theres millions of hitboxes in the game, I can’t reference all of them

1 Like

There’s also FindPartOnRayWithIgnoreList, which takes a list of things to ignore. Shove your player’s character + all your spawns and anything you want to ignore in here.

Alternatively, there’s FindPartOnRayWithWhitelist, which takes a list of things that you want to hit ONLY, and everything that isn’t in that list is ignored.

No, you’ll need to cast a ray. In the code snippet you saw from the wiki hit will be your mouse.Target and position will be Mouse.Hit.p.

1 Like

Ok so this is what I got

local ray = mouse.UnitRay
ray = Ray.new(ray.Origin, ray.Direction)
		
local hit, position, normal = workspace:FindPartOnRayWithIgnoreList(ray, ignoreList)

if hit then
    local cframe = placement(
        playersPlot.PrimaryPart,
        itemClone, 
        position, 
        var.Rotation
    )
    itemClone:SetPrimaryPartCFrame(cframe)
end

Problem arises with how to ignore said items. The game can include any number of hitboxes at once. That’s why I was doing mouse.Target.Name, so it was ignoring any parts named Hitbox and not so much the actual object itself.

I can’t actually ignore all the parts with hitbox in them, as if a player adds more items into their place, then there’s more hitboxes to that list

I also have mouse.Target, etc. used elsewhere in my code

local renderStepped	
	renderStepped = runService.RenderStepped:Connect(function()
		local ray = mouse.UnitRay
		ray = Ray.new(ray.Origin, ray.Direction)
		
		local hit, position, normal = workspace:FindPartOnRayWithIgnoreList(ray, ignoreList)
		
		if hit then
			if mouse.Target:IsDescendantOf(playersPlot) then
				if furnitureData[itemClone.Name].Base == 'Floor' or furnitureData[itemClone.Name].Base == 'Table' then					
					if mouse.Target.Name == 'Base' or mouse.Target.Name == 'PlaceArea' then
						playersPlot.PrimaryPart = mouse.Target
					end
					
					local cframe = placement(
						playersPlot.PrimaryPart,
						itemClone, 
						position, 
						var.Rotation
					)
					itemClone:SetPrimaryPartCFrame(cframe)
				else
					if mouse.Target.Parent:IsDescendantOf(playersPlot.House) then
						itemClone:SetPrimaryPartCFrame((getCFrame(mouse, itemClone.PrimaryPart.Size.Z))*CFrame.Angles(0, 0, var.Rotation))
					end
				end
				
				for _, v in pairs(getTouchingParts(itemClone.Hitbox)) do
					if not v:IsDescendantOf(itemClone) and v.Name ~= 'Spawn' and not v:IsDescendantOf(players:FindFirstChild(playersPlot.Name).Character) then
						itemClone.Hitbox.Transparency = 0.5	
						break			
					end
					itemClone.Hitbox.Transparency = 1
				end
			end
		end
	end)
local ray = mouse.UnitRay
ray = Ray.new(ray.Origin, ray.Direction)
		
local hit, position, normal = workspace:FindPartOnRayWithIgnoreList(ray, {playersPlot.Spawn})
print(1)
if hit then
    print(2)
end

Just been playing around with it, however, it isn’t recognizing the hit, so it’s only printing 1 and not 2.

And printing hit returns nil

You could add what you want to ignore into a model and then set the target filter to that model.

I can’t do that, as each hitbox has their own model, and the Hitboxes can’t be put in the same model as the spawn

Which is the “Spawn” model? From the video it looks like you’re trying to ignore your character as well as the model you’re placing.

Reading some of the earlier replies, I think I have a better understanding of what your problem is.

Since new hit boxes can appear whenever a new model is placed, you can try to get all the models named hitbox in the area you’re allowed to plot at, and add them to a table along with their current parent. Then set all their parents to the same model and change the target filter to that model until the model you’re placing gets placed. Then just parent all the items in that table back where they were originally.

I don’t see why you wouldn’t be able to set the spawn and hitbox models to the same parent.

I have been doing stuff like this for awhile. I put a folder in the workspace called “Ignore” and set the targetfilter to that folder. (The folder can be inside other models.) Now, when you want something to be ignored just stick it into the folder.

Idk what your system is but I would suggest going to this because it could make things easier in the future if you ever want to have even more target filters.

Now when somebody clicks something to place, stick the placement model in the folder with the hitbox. To check collision use Region3 and do FindPartsInRegion3 so that if anything is inside the hitbox then don’t let the player place. Then when the player actually places it stick the real model into their base or whatever it is.

I feel like this should be a feature to be able to make a table of Instances instead of using a folder, it would be very convenient to have something like Mouse.TargetFilterList

Referring to Post #10:

local ray = mouse.UnitRay
ray = Ray.new(ray.Origin, ray.Direction)
   	
local hit, position, normal = workspace:FindPartOnRayWithIgnoreList(ray, {playersPlot.Spawn})
print(1)
if hit then
   print(2)
end

Because mouse.UnitRay is, well, a unit ray, you have to multiply its direction by how far you want the ray to reach, otherwise, it will only look for parts in your desired direction for one stud. I would multiply by 500 or so just to be safe:

local ray = mouse.UnitRay
ray = Ray.new(ray.Origin, ray.Direction*500)

I would also use a pre-assigned ignore list and a repeat until loop to repeat raycasting until either the hit does not exist or you hit an object whose name is either “Spawn” or “Base”:

local hit, position, normal
local IgnoreList = {playersPlot.Spawn}
repeat
    hit, position, normal = workspace:FindPartOnRayWithIgnoreList(ray, IgnoreList)
    table.insert(IgnoreList, hit)
until not hit or hit.Name == "Spawn" or hit.Name == "Base"

print(1)
if hit then
    print(2)
end
until conditional erroring

The until conitional at the end might error if OR gates continue evaluating after their ultimate condition is true, unlike AND gates. If this is the case, use this:

until not (hit and hit.Name ~= "Spawn" and hit.Name ~= "Base")

I hope this helps…

1 Like

tysm ive been looking for something like this for a bit
edit: for anyone looking at this, u can also do workspace:FindPartOnRayWithWhitelist(ray,whiteList)
the whitelist can be workspace:GetChildren() or descendants