How do I check if player is holding a specific tool?

I am trying to change ProximityPrompt’s HoldDuration and ActionText when the player is holding a tool called “lockpick”. But I don’t know how I can do it. I have tried the if statement to check if the player’s humanoid has the lockpick, but it just gave me an error. I have also tried ChildAdded, but I don’t know how to check if the child that is added is “lockpick”.

local tween = game:GetService("TweenService")
local player = game.Players.LocalPlayer
local charater = player.Character

for _,door in pairs(game.Workspace:GetDescendants()) do
	if door:IsA'Model' then
		if door.Name == "Door" then
			local prompt = door.Base.ProximityPrompt
			local locked = door.Locked
			local hinge = prompt.Parent.Parent.Doorframe.Hinge
			local openandclose = script["Open/Close"]
			local locksound = script.Locked
			local player = game.Players.LocalPlayer
			local text = player.PlayerGui:WaitForChild("Text").StatusText
			local trans = text.TextTransparency
			
			if locked.Value == true then
				prompt.HoldDuration = 0
			end
			
			charater.ChildAdded:Connect(function()
				
			end)
1 Like

for _, tool in pairs(character:GetChildren()) do
if tool:IsA(‘Tool’) then
if tool.Name == ‘TOOL NAME HERE’ then
–// Player is holding the tool
end
end
end

Or to be honest the better way to do this:

if character:FindFirstChild('TOOLNAMEHERE') then
    --// The tool is being held
end

It didn’t work, there is no error, but for some reason it just didn’t work.

local tween = game:GetService("TweenService")
local player = game.Players.LocalPlayer

for _,door in pairs(game.Workspace:GetDescendants()) do
	if door:IsA'Model' then
		if door.Name == "Door" then
			local prompt = door.Base.ProximityPrompt
			local locked = door.Locked
			local hinge = prompt.Parent.Parent.Doorframe.Hinge
			local openandclose = script["Open/Close"]
			local locksound = script.Locked
			local player = game.Players.LocalPlayer
			local text = player.PlayerGui:WaitForChild("Text").StatusText
			local trans = text.TextTransparency
			
			if locked.Value == true then
				local character = player.Character
				if character:FindFirstChild('Lockpick') then
					prompt.HoldDuration = 5
					prompt.ActionText = "Unlock"
				else
					prompt.HoldDuration = 0
				end
			end

I still can’t figure it out, I don’t know what’s wrong with it :frowning:

Just check if the tool is in the players character using FindFirstChild

I did, and it didn’t work, it didn’t give me any error.

it is case sensitive, maybe FindFirstChild('lockpick') is what you need, check what is a child of the character in the explorer while testing. add break points or print statements to find out where it is and isn’t failing

I did exactly what you and the other 2 people said, it just wouldn’t work. And I am 100% sure that the thing that isn’t working is the FindFirstChild, because everything else in the script is working completely fine.

maybe your lockpick tool has a space at the start or end like " lockpick" or "lockpick ", if find first child isn’t finding it then the string provided just isn’t it’s .Name. try printing the tool’s name on equip to find out more

Nope, I have checked, there is no space before, between, and after the name, I also spelled it exactly the same as the tool’s name.

			if locked.Value == true then
				local character = player.Character
				if character:FindFirstChild('Lockpick') then
					prompt.HoldDuration = 5
					prompt.ActionText = "Unlock"
				else
					prompt.HoldDuration = 0
				end
			end

The proximity prompt changes probably are not be replicated to the server, thus it seems like nothing is happening. You might have to only set prompt.Visible and switch visibility on a “pick lock” vs “open” prompt; but Visible might have the same issue I’m not sure.

this probably happening because the code run first then the tool appear in the player’s character, to fix this use Repeat

repeat 

task.Wait()

until  character:FindFirstChild('Lockpick')

– the code here will only run when the tool is in the character.

1 Like

Omg, that works, thank you! Why did the if statement not work and this work, I am confused.

True but repeating this big descendant search will be very bad for performance. Checking all doors on lockpick equip would be much more efficient

tool.Equipped:Connect(function()
for _,door in pairs(game.Workspace:GetDescendants()) do
	if door:IsA'Model' and door.Name == "Door" then
		-- ...
		if locked.Value == true then
			prompt.HoldDuration = 5
			prompt.ActionText = "Unlock"
		end
	end
end)

tool.Unequipped:Connect(function()
for _,door in pairs(game.Workspace:GetDescendants()) do
	if door:IsA'Model' and door.Name == "Door" then
		-- ...
		if locked.Value == true then
			prompt.HoldDuration = 0
			prompt.ActionText = "Locked!"
		end
	end
end)
2 Likes

because as I told you the code run first then the tool appears so that’s why the if statement didn’t work because the script didn’t found any tools in the player’s character yet…

1 Like

You script would run from top to bottom at the start of the game.
it goes through every object looking for doors, when it finds a door it checks if the player is holding a lockpick; but the player is never holding a lockpick at the start, so this is false. The script ends when it hits the bottom since there is nothing telling it to check again.

@THEWOLF5555555 's example does the same script from top to bottom, but the repeat tells it to wait for the next frame then check again. This works but is bad because it is doing a lot of extra checking.

In my example the Equipped:Connect(...) tells the game to run your script only when the player equips a lockpick, so it is more accurately checking when needed.

1 Like

But how do I get the variables? This?

local player = game.Players.LocalPlayer
local backpack = player:WaitForChild('Backpack')
local tool = backpack:WaitForChild('Lockpick')

or this?

local player = game.Players.LocalPlayer
local character = player.Charater
local tool = character:WaitForChild('Lockpick')

Because in your example, when the tool moves from the player to the humanoid, it changes parent. So how do I set the variables for the tool?

image

-- inside tool's local script
local player = game.Players.LocalPlayer
local tool = script.Parent

Like this! player is still accessible since it is a local script, the tool is always the script’s parent.

If you need the character then you can get it with tool.Parent or player.Character but do not save this as a global variable as the tool’s owner can and will change on death, equip, and unequip.

1 Like

Thanks, I still have problems on this but the tool is working!