Best Way To Award/Update Leaderstat Points from a Tool attached to a Part inside the Player

Hello,

Apologies for how long this post is and how complicated the problem is. I wanted to include as much relevant information as I could to provide the clearest picture with the problem I’m having.

I have added Tools that are welded to Pets that can be summoned in my game, and have also set up IntValues inside the Datastore to represent stats for the Pets - PetLevel and PetEXP. I want to ensure that I have scripted the best methods for updating these IntValues.

Issue: My Datastore does not appear to want to update the PetLevel IntValue properly when the appropriate PetEXP value has been reached.

Process:
When a Player summons a Pet, it becomes attached to the Player’s UpperTorso as a Part, and that Part then has a Tool and Handle inside:

Inside the Tool (labeled ‘Pet’ also) here is the LocalScript - ‘HurtLocalScript’, which I have setup to award the PetEXP IntValue upon Touch of an opposing player:

local Player = game.Players.LocalPlayer 
local damage = 100
		local x = script.Parent.Weapon
		x.Touched:Connect(function(x)
			if x.Parent:FindFirstChild("Humanoid") and x.Parent.Name ~= Player.Name then
				Player.leaderstats.PetEXP.Value = Player.leaderstats.PetEXP.Value + 1 
				wait()
			end
		end)

Inside the Handle of the Tool, labeled as as ‘Weapon’, is the Script - ‘HurtScript’, which I have setup to deal damage to the opposing player:

local Player =  script.Parent.Parent.Parent.Parent.Parent
    local damage = 100
    		local x = script.Parent.Parent.Weapon
    			if x.Parent:FindFirstChild("Humanoid") and x.Parent.Name ~= Player.Name then
    				x.Parent.Humanoid:TakeDamage(damage)
    			end
    		end)

As you can see in the script above, I may not be identifying the Player in the best way from the Script inside the Tool’s Handle. Ideally, I’d like to have this be one script, but it currently is applying damage to the opposing player, and it does update the PetEXP IntValue inside the player’s leaderstats. However, and I think this is due to the way I have set up the previous two scripts, my Datastore script does not do the math equation properly to convert the PetEXP into PetLevel values. This is the relevant section inside my Datastore Script:

local requiredPet = (PetLevel.Value*77) 
PetEXP.Changed:Connect(function()
	if PetEXP.Value >= requiredPet then
			PetLevel.Value = PetLevel.Value + 1
			PetEXP.Value = PetEXP.Value - requiredPet
	end
end)

PetLevel

I know the math formula should work, as its the same formula used for the Player’s Level to increase after obtaining the required EXP, which works properly. From what I can tell, this is due to the way the weapon scripts inside the Tool attached to the Pet, which is welded to the Player’s UpperTorso is processing the request.

When I manually change the PetEXP value while inside Play mode, the PetLevel adjusts accordingly, but when I manually change the PetEXP during a Client test, the PetLevel does not adjust. Currently, the PetEXP.Value continues to grow larger and larger without converting as it should with the math equation in the Datastore.

I’ve attempted to modify a regular “sword” script from weapons that the player equips and place the Script “HurtScript” inside the Handle, but without luck:

local Player =  script.Parent.Parent.Parent.Parent.Parent    
local damage = 100
local tool = script.Parent.Parent
local debris = game:GetService("Debris")
local handle = tool:WaitForChild("Weapon")
local hithumanoids = {}
equipped = true

handle.Touched:connect(function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if humanoid then
local TargetPlayer = game.Players:GetPlayerFromCharacter(humanoid.Parent)
	if equipped and Player and humanoid and humanoid.Health > 0 and hit and not hit:isDescendantOf(Player) then
		if  humanoid and  humanoid.Health > 0 and not hithumanoids[humanoid] 
			then
			hithumanoids[ humanoid] = true
			
			for _, v in pairs( humanoid:GetChildren()) do
				if v and v.Name == "creator" then
					v:remove()
				end
			end
			local tag = Instance.new("ObjectValue")
			tag.Name = "creator"
			tag.Value = Player
			debris:AddItem(tag, 3)
			tag.Parent =  humanoid
			 humanoid:TakeDamage(damage)

			else
		
		end	
	end	
end
end)

Again, not sure this is the best way to identify the Player from the Script, but since its a Tool attached to a part inside the Player’s UpperTorso, I’m unsure of a better method. I was thinking that having a script similar to the Player’s weapons, would cooperate better with the “Death Script” I have that normally updates the Player’s leaderstats. Below is the edited, relevant, portion of my Death Script that updates the leaderstats inside the Datastore:

game.Players.PlayerAdded:connect(function(player)
	player.CharacterAdded:connect(function(char)
		local hum = char:WaitForChild('Humanoid')
		hum.Died:connect(function()											
			local tag = hum:FindFirstChild('creator')											
			if tag ~= nil then
				if tag.Value ~= nil then
					local leaderstats = tag.Value:FindFirstChild('leaderstats')
					if leaderstats ~= nil then
						leaderstats.Coins.Value = leaderstats.Coins.Value + player.leaderstats.Level.Value * 2 
						leaderstats.Experience.Value = leaderstats.Experience.Value + player.leaderstats.Level.Value * 20 
					end
				end	
			end
		end)
	end)
end)

Any advice or assistance would be much appreciated. :slight_smile: Thank you.

UPDATE: Question was solved thanks to DarkContinuum and iRexBot. Thank you both! :slight_smile:

Put simply, this won’t replicate. The value has only be changed locally so anything server-side won’t know that the value has changed.

Tbh, the mixture of a load of scripts and local scripts isn’t the best way to do this. It’d be a lot easier to either use a remote or do everything on the server if you’re not using animations etc.

2 Likes

Thanks for the response!

Okay, I edited the Script like so:

local Player =  script.Parent.Parent.Parent.Parent.Parent
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PR = ReplicatedStorage:WaitForChild("PetRemotes")
local PetEvent = PR:WaitForChild("PetEvent")

local damage = 100
		local x = script.Parent.Parent.Weapon
		x.Touched:Connect(function(x)
			if x.Parent:FindFirstChild("Humanoid") and x.Parent.Name ~= Player.Name then
				x.Parent.Humanoid:TakeDamage(damage)
				PetEvent:FireClient(Player)
			end
		end)

and then I added this event to my Event Handler script under ServerScriptStorage:

PetEvent.OnServerEvent:Connect(function(Player)
		Player.leaderstats.PetEXP.Value = Player.leaderstats.PetEXP.Value + 10 
		Player.leaderstats.Experience.Value = Player.leaderstats.Experience.Value + 10 

end)

I receive this error:

FireClient: player argument must be a Player object

Is there a better way for me to define the Player when using a Script and not a Local Script?

script.Parent.Parent.Parent…?
This is a problem. The tool won’t return the player if not held because it’s parent is changed to the player’s backpack. Take a look at this

1 Like

Thank you for the response and link. I checked it out and changed up the Script inside the Pet’s Tool’s Handle to be:

local character = game.Workspace.Player
local player = game.Players:GetPlayerFromCharacter(character)

if player then
	local damage = 100
		local x = script.Parent.Parent.Weapon
		x.Touched:Connect(function(x)
			if x.Parent:FindFirstChild("Humanoid") and x.Parent.Name ~= player.Name then
				x.Parent.Humanoid:TakeDamage(damage)
				player.leaderstats.PetEXP.Value = player.leaderstats.PetEXP.Value + 10 
			end
		end)		
end

I’m getting the following error for the very first line:

Player is not a valid member of Workspace

Thoughts? >_<

“character” has to be a tool part. Any part within the tool should do fine. The problem here is that when the tool loads in the player will be nil. You’ll need a method of updating the player.

1 Like

Ah, you’re absolutely right. When I change it to:

local character = script.Parent.Parent.Weapon
local player = game.Players:GetPlayerFromCharacter(character)
print(player)

it does indeed print out “nil” as the player. How would I go about updating the player here? I’m not seeing anything here for how to update a player.

That’s not the character, you need the character model itself. I believe in your case(I don’t know where your script is located though) you can just remove “.Weapon”. Also, your remote event is very insecure allowing exploiters to give them self exp countless times. Never trust the client; validate everything it tells you.

3 Likes

Thank you! :slight_smile: Between you and iRexBot, I was able to figure it out. I’ll definitely make the RemoteEvent more secure too.