Leaderstats will not update in other script

You can write your topic however you want, but you need to answer these questions:

  1. **What do you want to achieve?
    I want to update leaderstats.Ammo when I touch a part in workspace

  2. What is the issue? Include screenshots / videos if possible!
    In a server script in workspace I touch a part and my leaderstats.Ammo is filled ut to 99. When I shoot my gun it triggers a shoot function in a modulescript. There it withdraws 1 from leaderstats.Ammo when I shoot. So when I am out of ammo I touch the part again in the server script, but there the leaderstats.Ammo is still full (99 ammo), but in the modulescript it is 0.

This is my leaderstats:

local Players = game:GetService("Players")

local function onPlayerAdded(player)
	local leaderstats = Instance.new('Folder')
	leaderstats.Name = 'leaderstats'
	leaderstats.Parent = player

	local ammo = Instance.new('IntValue')
	ammo.Name = 'Ammo'
	ammo.Value = 0
	ammo.Parent = leaderstats

	local grenades = Instance.new('IntValue')
	grenades.Name = 'Grenades'
	grenades.Value = 0
	grenades.Parent = leaderstats

	local seconds = Instance.new('IntValue')
	seconds.Name = 'Seconds'
	seconds.Value = 0
	seconds.Parent = leaderstats

	local minutes = Instance.new('IntValue')
	minutes.Name = 'Minutes'
	minutes.Value = 0
	minutes.Parent = leaderstats

	while player.Parent do
		task.wait(1)
		seconds.Value = seconds.Value + 1
		if seconds.Value >= 60 then
			seconds.Value = 0
			minutes.Value = minutes.Value + 1
		end
	end
end

Players.PlayerAdded:Connect(onPlayerAdded)

for _, Player in Players:GetPlayers() do
	task.spawn(onPlayerAdded, Player)
end

This is my serverscript for filling up my ammo:

local currPartContainer = script.Parent
local touched = false --Variable for a debounce

local function PlayerTouched(part)
	if not touched then --Checks if the debounce variable is set to false
		touched = true --Debounce variable set to true
		local Parent = part.Parent
		local currPlayer = game.Players:GetPlayerFromCharacter(Parent)
		if currPlayer then
			if (currPlayer.leaderstats.Ammo.Value == 99) then
				print("Ammo is already full")
			else
				currPlayer.leaderstats.Ammo.Value = 99
				wait()
			end
		end

		touched = false 
	end
end

currPartContainer.Touched:Connect(PlayerTouched)

This is my modulescript for shooting. This is by the way code from the Roblox FPS system template:

function BlasterController:shoot()
	local spread = self.blaster:GetAttribute(Constants.SPREAD_ATTRIBUTE)
	local raysPerShot = self.blaster:GetAttribute(Constants.RAYS_PER_SHOT_ATTRIBUTE)
	local range = self.blaster:GetAttribute(Constants.RANGE_ATTRIBUTE)
	local rayRadius = self.blaster:GetAttribute(Constants.RAY_RADIUS_ATTRIBUTE)

	self.viewModelController:playShootAnimation()
	self.characterAnimationController:playShootAnimation()
	self:recoil()

	if (self.ammo > 0) then
		self.ammo -= 1
	end
	
	if (player.leaderstats.Ammo.Value > 0) then
                --this is where my leaderstats is updated
		player.leaderstats.Ammo.Value -= 1
	end

	self.guiController:setAmmo(self.ammo)

	local now = Workspace:GetServerTimeNow()
	local origin = camera.CFrame

	local rayDirections = getRayDirections(origin, raysPerShot, math.rad(spread), now)
	for index, direction in rayDirections do
		rayDirections[index] = direction * range
	end

	local rayResults = castRays(player, origin.Position, rayDirections, rayRadius)

	-- Rather than passing the entire table of rayResults to the server, we'll pass the shot origin and a list of tagged humanoids.
	-- The server will then recalculate the ray directions from the origin and validate the tagged humanoids.
	-- Strings are used for the indices since non-contiguous arrays do not get passed over the network correctly.
	-- (This may be non-contiguous in the case of firing a shotgun, where not all of the rays hit a target)
	local tagged = {}
	local didTag = false
	for index, rayResult in rayResults do
		if rayResult.taggedHumanoid then
			tagged[tostring(index)] = rayResult.taggedHumanoid
			didTag = true
		end
	end

	if didTag then
		self.guiController:showHitmarker()
	end

	shootRemote:FireServer(now, self.blaster, origin, tagged)

	local muzzlePosition = self.viewModelController:getMuzzlePosition()
	drawRayResults(muzzlePosition, rayResults)
end

But it seems like when the leaderstats is updated in the modulescript, it is not “updated” in the serverscript. Because when I hit the part in the serverscript the leaderstats is still full.

Anyone see why this is so?

The leaderstats is in ServerScriptService.
The modulescript is in ReplicatedStorage.
The touch serverscript is in workspace.

You are probably removing ammo fromclient.

The server can edit values in the leaderstats and it will be automatically replicated to the client, but the client does not automatically tell the server what is has done (removing ammo).

You need to create a function in the server that fires when player shoots, and here remove ammo.

Well, I have to remove the ammo from the module script.

The funny thing is that the first time I touch the part in workspace it fills up the leaderstats.Ammo to 99. And when I shoot the module script removes ammo from the leaderstats.Ammo. This I can see when I open up the player in the game and check the leaderstats folder.

So the leaderstats folder is empty (ammo=0), but the localplayer still have ammo=99.

I find this very strange.

The RunContext of a ModuleScript depends on the script that runs i, i.e a LocalScript causes the ModuleScript to run in a client-sided context.

Ok? So I should do a FireEvent to the server from the module script, and update the leaderstats from there?

Yes. That should do the trick if you are indeed calling the ModuleScript via the client.

Why you have to remove from the module ?

Your leaderstat is stored on the player right ? So you can easily access leaderstat from the server(using remote function/event).

Yes, that led me to the right path. I thought module script was server side. So I made a remoteEvent and updated the leaderstats from there. Worked like a charm. Thanks!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.