Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

How to Properly Use DataStoreService for my Leveling System?

Hello. I asked this question before but it went unanswered. I have attempted to try and solve the issue myself but still cannot seem to find a way to make it work. I have a gui that display's the players xp and level, but when testing my game the xp and level do not show up, the only thing that shows up is the two blank text labels. Also, the leaderstats do not show up either, it's just a leaderboard that states my username. Whenever I play test I get this message in my output: leaderstats is not a valid member of Player "Players.AROBLOXUSER12344" (AROBLOXUSER12344 is my username)

Here is my leaderstats and leveling script (in workspace):

local DataStoreService = game:GetService("DataStoreService")
local levelDataStore = DataStoreService:GetDataStore("levelDataStore")
local xpDataStore = DataStoreService:GetDataStore("xpDataStore")

function onXPChanged(player, XP, level)
	if XP.Value>=level.Value * 10 then 
		XP.Value = 0 
		level.Value = level.Value + 1 
	end
end

function onLevelUp(player, XP, level)
	local m = Instance.new("Hint")
	m.Parent = game.Workspace
	m.Text = player.Name .. " has leveled up!"
	wait(3)
	m.Parent = nil
   player.Humanoid.Health = 0
end


function onPlayerRespawned(player)
	wait(5)

	player.Character.Humanoid.Health = player.Character.Humanoid.Health + player.leaderstats.Level * 10

	player.Character.Humanoid.MaxHealth = player.Character.Humanoid.MaxHealth + player.leaderstats.Level * 10

end

function onPlayerEntered(player)
	
	local stats = Instance.new("IntValue")
	stats.Name = "leaderstats"
	local stats2 = Instance.new("IntValue")
	stats2.Name = "Tycoon"

   local kills = Instance.new("IntValue")
	kills.Name = "Kills"
	kills.Value = 0

	local deaths = Instance.new("IntValue")
	deaths.Name = "Deaths"
	deaths.Value = 0

   local level = Instance.new("IntValue")
   level.Name = "Level" -- The Name of LV
	level.Value = levelDataStore:GetAsync("Player_"..player.UserId) or 1
	local data
	local success, errormessage = pcall(function()
		data = levelDataStore:GetAsync(player.UserId.."-xp")
		data = xpDataStore:GetAsync(player.UserId.."-level")
	end)
	if success then
		level.Value = data
	else
		print("There was an error getting your data.")
		warn(errormessage)
	end

   local xp = Instance.new("IntValue")
   xp.Name = "XP" -- The Name of XP
	xp.Value = xpDataStore:GetAsync("Player_"..player.UserId) or 0
	local data
	local success, errormessage = pcall(function()
		data = levelDataStore:GetAsync(player.UserId.."-xp")
		data = xpDataStore:GetAsync(player.UserId.."-level")
	end)
	if success then
		xp.Value = data
	else
		print("There was a problem loading your data.")
		warn(errormessage)
	end
	
	game.Players.PlayerRemoving:Connect(function(player)
		local s, e = pcall(function()
			levelDataStore:SetAsync(player.UserId.."-level", player.leaderstats.Level.Value)
			xpDataStore:SetAsync(player.UserId.."-xp", player.leaderstats.Xp.Value)
		end)
		if s then
			print("Successfully saved data!")
		else
			print("There was an error when saving data.")
			warn(e)
		end
	end)
   
	stats2.Parent = player
	stats.Parent = player
	kills.Parent = stats
	deaths.Parent = stats
   level.Parent = stats
   xp.Parent = stats

	xp.Changed:connect(function() onXPChanged(player, xp, level) end)
	level.Changed:connect(function() onLevelUp(player, xp, level) end)

	while true do
		if player.Character ~= nil then break end
		wait(5)
	end

	local humanoid = player.Character.Humanoid

	humanoid.Died:connect(function() onHumanoidDied(humanoid, player) end )


	player.Changed:connect(function(property) onPlayerRespawn(property, player) end )


	stats.Parent = player

end

function Send_DB_Event_Died(victim, killer)

	local killername = "unknown"
	if killer ~= nil then killername = killer.Name end
	print(victim.Name, " was killed by ", killername)

	if shared["deaths"] ~= nil then 
		shared["deaths"](victim, killer)
		print("Death event sent.")
	end
end

function Send_DB_Event_Kill(killer, victim)
	print(killer.Name, " killed ", victim.Name)
	if shared["kills"] ~= nil then 
		shared["kills"](killer, victim)
		print("Kill event sent.")
	end
end



function onHumanoidDied(humanoid, player)
	local stats = player:findFirstChild("leaderstats")
	if stats ~= nil then
		local deaths = stats:findFirstChild("Deaths")
		deaths.Value = deaths.Value + 1


		local killer = getKillerOfHumanoidIfStillInGame(humanoid)


		Send_DB_Event_Died(player, killer)
		handleKillCount(humanoid, player)
	end
end

function onPlayerRespawn(property, player)

	
	if property == "Character" and player.Character ~= nil then
		local humanoid = player.Character.Humanoid
			local p = player
			local h = humanoid
			humanoid.Died:connect(function() onHumanoidDied(h, p) end )
	end
end

function getKillerOfHumanoidIfStillInGame(humanoid)

	local tag = humanoid:findFirstChild("creator")


	if tag ~= nil then
		
		local killer = tag.Value
		if killer.Parent ~= nil then 
			return killer
		end
	end

	return nil
end

function handleKillCount(humanoid, player)
	local killer = getKillerOfHumanoidIfStillInGame(humanoid)
	if killer ~= nil then
		local stats = killer:findFirstChild("leaderstats")
		if stats ~= nil then
			local kills = stats:findFirstChild("Kills")
         local xp = stats:findFirstChild("XP")
			if killer ~= player then
				kills.Value = kills.Value + 1
            xp.Value = xp.Value + 3
				
			else
				kills.Value = kills.Value - 0
				
			end
			Send_DB_Event_Kill(killer, player)
		end
	end
end

game.Players.ChildAdded:connect(onPlayerEntered)

Here is my gui text label script that is supposed to show the players current rank:

repeat 
wait()
until script.Parent.Parent.Parent.Parent.Parent.leaderstats:findFirstChild("Level")

while true do

if script.Parent.Parent.Parent.Parent.Parent.leaderstats.Level.Value == 1 then
wait(0.1)
script.Parent.Text = "Private I (Lvl 1)"
elseif script.Parent.Parent.Parent.Parent.Parent.leaderstats.Level.Value == 2 then
wait(0.1)
script.Parent.Text = "Private II (Lvl 2)"
elseif script.Parent.Parent.Parent.Parent.Parent.leaderstats.Level.Value == 3 then
wait(0.1)
script.Parent.Text = "Private lll (Lvl 3)"
end 
end 

And finally here is my other text label script that is supposed to show the xp the player has:

while true do
script.Parent.Text = "XP: " ..script.Parent.Parent.Parent.Parent.Parent.leaderstats.XP.Value
wait(0)
end

My concern is only the leveling and xp script not the other two text label scripts but I thought It was necessary if I included them both just in case. My screenshot below shows my error in my output: https://snipboard.io/wl6Rqj.jpg I've been stuck on this for so long and would love some help. Thank you!

1 answer

I haven't read this entire script yet, but I would use :WaitForChild() instead of just getting it immediately. I would also use a variable instead of just repeating script.Parent.Parent.Parent, etc.

This discussion is preserved as it was. New answers, comments, and votes are closed.