Ignore accessories while raycasting

Hello,
I look at many posts but couldn’t find my case. I want the ray to ignore player’s accessories and I saw on other posts how to do it with the ignore list but the code for raycasting that I use looks different and I’m unsure how to implement it into my code

code:

-- setup raycast parameters --
	local raycastParams = RaycastParams.new()
	raycastParams.FilterDescendantsInstances = {player.Character, } -- blacklist player (thats shooting) character from being hit
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	
	-- send the raycast from gun to mouse position --
	local raycastResult = workspace:Raycast(script.Parent.Handle.Position, (mousePos - script.Parent.Handle.Position) * range, raycastParams)		
	
	if raycastResult then -- if hit something
		
		local hitPart = raycastResult.Instance
		local model = hitPart:FindFirstAncestorOfClass("Model")
		
		if model then -- if it's a model
			
			if model:FindFirstChild("Humanoid") then -- if it contains humanoid
				
				if hitPart.Name == "Head" then
					
					model.Humanoid:TakeDamage(headDamage)
					
				else if hitPart.Name == "UpperTorso" then
						
						model.Humanoid:TakeDamage(torsoDamage)
						
					 end
				end
				
					model.Humanoid:TakeDamage(otherDamage)
				
				else
				
				
			end
			
		else
			
			local hitMark = Instance.new("Part")
			hitMark.Parent = game.Workspace
			hitMark.Anchored = true
			hitMark.CanCollide = false
			hitMark.Position = raycastResult.Position
			hitMark.Size = Vector3.new(.15, .15, .15)
			hitMark.BrickColor = BrickColor.Black()
			
		end

The main and likely cleanest solution to this would be to simply loop through each player in the game, and then loop through the children of each of their character’s (if the character exists) and create an array that includes the shooting player’s character, as well as the accessories of each player. Then, set FilterDescendantsInstances to this array that we have created.

If you wanted to as well, you could also just reduce the hat hitboxes to a tiny size, avoiding having to loop through the characters each time you fire (or performing multiple raycasts.)

2 Likes

Thanks for the response, I will try this right now.

Note: If you have NPCs, it’s better to loop through humanoids in the game. Or only use HumanoidRootParts

1 Like

Thank you, but I don’t have any npcs in my game.

1 Like

Hey, I have a question. How would I check if the character is loaded, I tried using “player.CharacterAdded:Wait()” but it seems to be stuck on that. And here is the code I did.

local ignoreList = {}
	local igIndex = 1
	
	for i, v in ipairs(game.Players:GetChildren()) do

		v.CharacterAdded:Wait()
		
		for i,v in ipairs(v:GetChildren()) do
			
			if v:IsA("Accessory") then
				
				table.insert(ignoreList, igIndex, v)
				print(v)
				igIndex += 1
				
			end
			
		end
		
	end
	table.insert(ignoreList, igIndex, player.Character)
	
	igIndex = 1

It’s doing it whenever a player shoots their gun.

.CharacterAdded results in waiting for the player’s character being loaded in each player that you are looping through. In this case, we can merely check if Player.Character exists, and if it does not, we can just continue as if the player does not have a character, they obviously won’t have any accessories we need to worry about.

As a side note, you do not need to include the index, as if you do not include an index it simply inserts into the end of the table, which is all we need for this to work. We can also just pre-include the player’s character in this table. Here are these two things implemented below:

local ignoreList = {player.Character}

for i, v in ipairs(game.Players:GetChildren()) do
	if v.Character then -- Check if their character exists
		for i,v in ipairs(v.Character:GetChildren()) do -- Do not loop through the player, but loop through their character.
			if v:IsA("Accessory") then
				table.insert(ignoreList, v)
				print(v)
			end
		end
	end
end

Keep in mind that you’ll need to run this every time the player fires (which isn’t too computationally expensive, and shouldn’t matter too much,) or go with a more complex solution. Stick to just running this every time the player fires for now.

2 Likes

Thank you so much man! It works perfectly and I learned useful things from what you said.

Can I just quickly ask you, do you know why when I shoot someone in the head it does headshot damage but also body damage?

Just noticed that section of the code, of which I will state a few things about:

  1. To answer your question, it is because you check if the HitPart has been the Head or the Torso, and then deal damage, and then deal damage separately as otherDamage. This is what your code is doing right now:

What you want to do is make this a part of that statement, instead of having it outside of it. However, you have a second issue: else if is not the same as elseif.

Elseif (no space) makes the code a part of the same “block”, while else if makes a new “block” of conditionals. Your code is currently structured like this:

I will leave my comment about the Model issue up to you to deal with (unless if this is intended,) however, here’s how that inside part should be handled:

if model:FindFirstChild("Humanoid") then -- if it contains humanoid
	if hitPart.Name == "Head" then
		model.Humanoid:TakeDamage(headDamage)
	elseif hitPart.Name == "UpperTorso" then -- Note the change of "else if" to "elseif"!
		model.Humanoid:TakeDamage(torsoDamage)
		-- The second end that was here before should have been an indication that something was amiss.
	else
		model.Humanoid:TakeDamage(otherDamage)
	end
	-- Forgot to mention, this else in here due to the issue above was linked to the Humanoid block, and not to the hitPart conditionals.
	-- This is likely where you intended for your particle code to go, so I have left it in with proper identation.
else
	
end
  1. You will encounter an issue on your code where if you attempt to shoot another player, the player will not actually take damage on their screen, and will only take damage on your screen. This is because of client server replication in ROBLOX, and to fix this, you will need to use RemoteEvents. The dev wiki provides a good intro this this concept here: Roblox Client-Server Model

Once you read that last article, read this for an idea on RemoteEvents and RemoteFunctions:

As a note, you should only need one server script to handle damage and effects in your game. Your remote event should be stored in a place accessible to both the Tool’s client script (preferably ReplicatedStorage) and the singular script should be in ServerScriptService.

I have dumped a lot of information in this post, and I’ll check back in if you need any other sort of help :slight_smile:

Honestly thank you man for all of this. I structured the code like this and it works great now.
code:

if model then
			
			if model:FindFirstChild("Humanoid") then -- if it contains humanoid

				if hitPart.Name == "Head" then

					model.Humanoid:TakeDamage(headDamage)

				elseif hitPart.Name == "UpperTorso" then

					model.Humanoid:TakeDamage(torsoDamage)

				else

					model.Humanoid:TakeDamage(otherDamage)

				end

			end
			
		else
			
			local hitMark = Instance.new("Part")
			hitMark.Parent = game.Workspace
			hitMark.Anchored = true
			hitMark.CanCollide = false
			hitMark.Position = raycastResult.Position
			hitMark.Size = Vector3.new(.15, .15, .15)
			hitMark.BrickColor = BrickColor.Black()
			
		end

And I should probably show it earlier but I am using a local script for detecting the mouse input and reloading then it sends a remote event to the server script which I posted a bit of. Also for all the damage, reload time, range info I am using a module script located in replicated storage because I believe it is safe from exploiters.

this is inside of the gun (starter pack)
image

1 Like