Leaderboard stats not being changed

I am trying to create a script that adds +1 to a stat on the leaderboard called “Cured” once the hit.Parent is destroyed. The function works just it doesn’t change the value on the leaderboard. I get this error in the output:

[19:14:17.830 - Workspace.Lab1…Patient.Script:11: attempt to index nil with ‘FindFirstChild’]

Does anyone know what I am doing wrong and is there a way I can locate the local players leaderstats by using the hit.Parent hierarchy?

local Cure = game.workspace[".Gamedata"][".RDisease"][".RCure"]

function Cured(hit)
print(hit)
		if hit.Parent.Name == Cure.Value then
		hit.Parent:Destroy()
		local Players = game:FindFirstChild("Players")
		local player = game.Players.LocalPlayer
		game.Players.LocalPlayer:FindFirstChild("leaderstats")
		player.leaderstats.Cured.Value = player.leaderstats.Cured.Value +1
	end
end

script.Parent.UpperTorso.Touched:connect(Cured)
1 Like

This is a script, not a localscript. Local Player can only be defined by the client, please try getting the player from the hit event instead;

2 Likes

Does this still work if I am trying to change the stat for the player that the item was in? So when the tool was destroyed the player who originally had the tool gained the stat.

1 Like

You also use :connect which is deprecated, use :Connect instead.

Try using a Server Script to get the leaderstats through a Touched Event with an anonymous function, like this :

local cure = workspace:WaitForChild(".Gamedata")[".RDisease"][".RCure"]

cure.Touched:Connect(function(touch)
           local player = game:GetService("Players"):GetPlayerFromCharacter(touch.Parent)
           if player then
           local leaderstats = player:FindFirstChild("leaderstats")
     local Cured = leaderstats.Cured.Value
     leaderstats.Cured.Value = Cured + 1
   end
end)
1 Like

I would want to check for a humanoid before doing this just to check.

I understand the Connect part but honestly I have no idea what the rest of what you said means. Can you explain what a touched event and an anonymous function is?

Is the cure something that is spawned in at random intervals of time across the playing area?

No the players create a cure and use it to cure a patients symptoms. The way we are curing the patient is by using the hit affect between the cure tool and the patient. The patient is just a dummy

I would advise using the Activated() event that is part of a Tool instance.

How would I use that in the situation? Does Activated() just mean when the player takes the tool out?

Activated() fires when the player presses their mouse button while holding the tool.

Of course, adding extra checks are usually necessary for cases like these,
@TooMuchRice my post was a rough basis for what you would have done.

You can use the API for that too.

A .Touched Event fires for a base part when it comes in contact with another physical instance. We pass a parameter to a function connected to the Event to detect what actually came in contact with that part.

For instance you have a part called “PartA” and you want to see whether it came in contact with “PartB” , for that you would do :

  local partA = workspace:WaitForChild("PartA")

  partA.Touched:Connect(function(hit)
  -- we can name the parameter anything we want, I named it hit
  if hit.Parent.Name == PartB then
  print("Part B touched Part A")
  end
end)
 

Now when we use this for players, we can use this to detect whether a player touched a part. (or rather a player’s characters descendant)


   local part = workspace:WaitForChild("MyPart")
   part.Touched:Connect(function(hit)
  
   if not hit.Parent:FindFirstChild("Humanoid") or hit.Parent == nil then
      return 
   end
 
   -- below this, code will not run 
 -- if the above criteria returned true, like if hit.Parent was nil
 -- then this part will not run, this prevents errors

   local char = hit.Parent 
   local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
    
   -- do stuff

Basically there is a built in function to return a player instance from a character.

I used game:GetService(“Players”) rather than game.Players because GetService method calls return the service after they have instantiated, otherwise you would have the chances of indexing nil with players, because ‘Players’ wouldn’t have existed, that’s the reason GetService is always the best way to get a Service.

Also an anonymous function is a function that has no variable assigned to it, for example a function would be :

local function OnTouched(hit) -- the hit parameter passed
       return print(hit.Name)
end

but if you would want to connect that to an Event, or simply put , run that code when a specific Event fires , you would do

Part.Touched:Connect(OnTouched)

Now if you didn’t have your function pre-defined, you could connect it just like

part.Touched:Connect(function(hit) 
-- note how this function doesn't have a name assigned, 
-- thre previous one was called OnTouched

My explanation can be wordy, use the API for better on-point information.

Touched Event :

https://developer.roblox.com/en-us/api-reference/event/BasePart/Touched

Anonymous Function :
image
and How do I make an anonymous function?

1 Like

Don’t do this:

local Players = game:FindFirstChild("Players")

Do this instead:

local Players = game:GetService("Players")

@TooMuchRice

we use checks such as :

if not hit.Parent == nil 

so as to prevent errors.

We use this check :

if hit.Parent.Humanoid then

to ensure hit.Parent is the Character because of a player’s character’s descendants, whatever physical object that exists and comes in contact with anything else, is parented directly to the Character.

So if a character touches a part, then hit.Parent will be the Character.

The Humanoid is a direct child of the Character, so we can do

local humanoid = hit.Parent:FindFirstChild("Humanoid")
1 Like

Jeez you really went out of your way to explain this lmao. I appreciate the help I think I know how to solve my issue now.

1 Like