Finding a players tool

Ok so im trying to find a value in a players tool that they are holding but it in indexing to nil with the tool and i tried waitforchild so idl?

rp.AddWood.OnServerEvent:Connect(function()
	local axe = player.Axe
	print(axe.damage.Value)
	if plr.axes.twxWood.Value == true then
		wood.Value += axe.damage.Value *2
	else
		wood.Value += axe.damage.Value
	end
end)

If they are currently holding it, you need to look into the character.

player is the character it is out of the script but it is character

When RemoteEvent.OnServerEvent is connected to a function, the first thing it passes through to the function is the player who called RemoteEvent:FireServer().

In order to reference that player, you need to include a parameter in the parentheses of the function. And since we know it’ll always be the first thing passed through from the event, we just need to add one parameter:

Example Revision #1

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local addWoodRemoteEvent = ReplicatedStorage.AddWood

addWoodRemoteEvent.OnServerEvent:Connect(function(player)
    -- Continue
end)

However, in order to look for a Tool that the player has, the script might need to check two different places:

  • The Backpack, which is where Tool objects are when the player does not have it equipped
  • The Character model, which is where a singular Tool object will be when a player has it equipped.

Here’s how the function could be revised to check for that specific Tool (and to check for everything else):

Final Example Revision

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local addWoodRemoteEvent = ReplicatedStorage.AddWood

addWoodRemoteEvent.OnServerEvent:Connect(function(player)
    local Backpack = player:WaitForChild("Backpack")
    local Character = player.Character or player.CharacterAdded:Wait()

    local axe

    local function lookForAxe(container)
        for _, item in container:GetChildren() do
            if axe ~= nil then break end

            if item:IsA("Tool") and item.Name == "Axe" then
                axe = item
                break
            end

        end

    end

    lookForAxe(Backpack)
    lookForAxe(Character)

    if axe ~= nil then
        local damage = axe:WaitForChild("damage", 5)
        if not damage then return end

        -- Edit: Corrected capitalization typo
        local Axes = player:WaitForChild("axes", 5)
        if not Axes then return end

        local twxWood = Axes:WaitForChild("twxWood", 5)
        if not twxWood then return end


        if twxWood.Value == true then
            wood.Value += damage.Value * 2
        else
            wood.Value += damage.Value
        end

    end
end)
2 Likes

Can I see the hierarchy in game?

thankyou for the indepth review, but it is saying to index with nil waitofrchild

local twxWood = axes:WaitForChild("twxWood", 5)

Ah wait, I realized I just made a typo with the capitalization of “Axes” toward the end of the script. Updating the capitalization to “axes” should resolve it.

-- Before
local Axes = player:WaitForChild("Axes", 5)

-- After
local Axes = player:WaitForChild("axes", 5)

Original post

That’s probably happening because the “axes” object isn’t actually being stored in the Player object. By chance, since you included two separate references to the player in the original codeblock, what is plr referring to?

If plr is a completely separate Instance from the Player object in the Players service, then you could update the local Axes variable toward the end of the example revision I provided to reference the plr variable, instead:

-- Before
local Axes = player:WaitForChild("axes", 5)

-- After
local Axes = plr:WaitForChild("axes", 5)

hey, thankyou for anothe indepth answer, but sadly it is not adding anything to wood.v;aue?

 if axe ~= nil then
        local damage = axe:WaitForChild("damage", 5)
        local axes = plr:WaitForChild("Axes", 5)
		local twxWood = axes:WaitForChild("twxWood", 5)

        if not damage then return end
		if not axes then return end
		if not twxWood then return end
	
		print(damage.Value)

        if twxWood.Value == true then
            wood.Value += damage.Value * 2
        else
            wood.Value += damage.Value
        end
    end

It’s not the capitalization of the variable itself (local Axes) that needed to be updated; it’s the capitalization of the name of the object that is being looked for within the :WaitForChild() call that needed to be made lowercase, at least based on how it was referenced in the original post.

(Here’s what I included in my edit from the previous post, for reference)

-- Before
local Axes = player:WaitForChild("Axes", 5)

-- After
local Axes = player:WaitForChild("axes", 5)

Thanks for the undersight on that, but whenever I change axes it does not change the axes damage, is there a way to update when they change axes or just update when ever they call the function?

I don’t fully understand the question; could you explain it a bit more?


To clarify, whenever the function is called, it runs through the following checks:

  1. Looks for an object in the player’s Backpack, then Character model, for a Tool with the name of “Axe”
  2. Checks if the axe has an object called “damage” within it
  3. Checks if there’s an object named “axes” in the player object
  4. Checks if there’s an object named “twxWood” in “axes”
  5. Updates wood.Value depending on what twxWood.Value currently is

twxwood is a gamepass that doubles the amount of wood and the damage I want to be mainly added to the total wood count but it does not change when a anew tool comes

If it’s a gamepass, then what is twxWood.Value referring to in the script? Typically, you would need to use MarketplaceService:UserOwnsGamePassAsync() to check if a player owns a specific gamepass.

Are you updating a BoolValue to true from a different script if a player owns a particular gamepass?

And to make sure we’re on the same page, is the plr variable from the original codeblock you posted meant to be referencing the Player object, or is it something completely separate?


Ah, so if you’re wanting the function to specifically be run based on the current Tool that the player has equipped, then you can remove the lookForAxe(Backpack) function call from the example code revision, since that looks through the Backpack first for a Tool named “Axe” before looking through the Character model.

  • Since the Character model is where the player’s currently equipped Tool will be, that’s where the function should exclusively be looking through, for the use case you described.

With that change, as long as the same RemoteEvent is fired when a player is using the new tool, it should correctly reference their currently equipped axe and go through the rest of the checks in the function to see if each of the requirements were met before increasing wood.Value

it still does not work… it is increasing the same amount every time?

For reference, what does the updated script look like now?

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local addWoodRemoteEvent = ReplicatedStorage.AddWood

addWoodRemoteEvent.OnServerEvent:Connect(function(player)
    local Character = player.Character or player.CharacterAdded:Wait()

    local axe

    local function lookForAxe(container)
        for _, item in container:GetChildren() do
            if axe ~= nil then break end

            if item:IsA("Tool") and item.Name == "Axe" then
                axe = item
            end

        end

    end

	lookForAxe(Character)

	if axe ~= nil then
		local damage = axe:WaitForChild("damage", 5)
        local axes = plr:WaitForChild("axes", 5)
		local twxWood = axes:WaitForChild("twxWood", 5)

        if not damage then return end
		if not axes then return end
		if not twxWood then return end
	
		print(damage.Value)

        if twxWood.Value == true then
            wood.Value += damage.Value * 2
        else
            wood.Value += damage.Value
        end
    end
end)
1 Like

Based on the print statements that appeared in the Output, damage.Value is printing “20” both times. For reference, is the new Axe being given to the player via a server script?


Before starting another playtest:

In the explorer, look for the original “Diamond Axe” and verify that damage.Value was set to the intended value (which seems like it’s meant to be 50, based on the stats shown on the UI during the video).

yeah i already did that and it is ment to be 50 but it is printing 20 for some reason and the axe is being given in a local script

That’s probably what is causing the discrepancy, as the new Tool would only be visible from the perspective of the client. This means that the server still sees the original Axe equipped, so when it refers to damage.Value, it’ll be referencing the value from the original Axe and not the new one.

If you grant the Tool to the player via a server script (e.g. when a player presses the button to equip it, fire a RemoteEvent and handle the request on the server), it should resolve that issue.

1 Like

i will try that tomorrow it is late for me, if i have any issues ill ask you abt them

1 Like