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

How is my global leaderboard scrpit not working?

I dont actually know where I have gone wrong. I am getting an error saying that my argument is wrong expected a table (got Instance) and it carries on in the script in which I saw fine. (I made a datastore saying if the user is not in datastore then make a store for the char.) But when I joined back in, it still showed as if I have not joined the game again.

Here is my script -

local DS = game:GetService("DataStoreService")
local winsODS = DS:GetOrderedDataStore('WINDATA') 

game.Players.PlayerAdded:Connect(function(plr)
	local winDataODS = winsODS:GetAsync(plr.Name) -- Where error is taking place.
	if plr.Name == winsODS then
		print(plr.Name, 'ALREADY RECOGNISED.')
	elseif plr.Name ~= winDataODS then
		print(plr.Name, 'NOT RECOGNISED.')
		wait(0.5)
		print('ADDING CHAR FILE...')
		wait(1)
		local success, err = pcall(function()
			winsODS:SetAsync(plr.Name, 0)
		end)
			
		if success then
			print(plr.Name, 'SUCCESSFULLY ADDED.')
		else
			warn(plr.Name, 'WAS NOT ADDED SUCCESSFULLY')
		end
	end
end)

local pos1 = false
local pos2 = false
local pos3 = false
local pos4 = false
local pos5 = false
local pos6 = false
local pos7 = false
local pos8 = false
local pos9 = false
local pos10 = false

local function topTenPlayers()
	local pages = winsODS:GetSortedAsync(false, 10)
	local topTen = pages:GetCurrentPage()
	
	for rank, data in ipairs(topTen) do
		local name = data.key
		local wins = data.value
		
		if pos1 == false then
			pos1 = true
			script.Parent.Position1.name1.Text = name
			script.Parent.Position1.num1.Text = wins
		elseif pos2 == false then
			pos2 = true
			script.Parent.Position2.name2.Text = name
			script.Parent.Position2.num2.Text = wins
		elseif pos3 == false then
			pos3 = true
			script.Parent.Position3.name3.Text = name
			script.Parent.Position3.num3.Text = wins
		elseif pos4 == false then
			pos4 = true
			script.Parent.Position4.name4.Text = name
			script.Parent.Position4.num4.Text = wins
		elseif pos5 == false then
			pos5 = true
			script.Parent.Position5.name5.Text = name
			script.Parent.Position5.num5.Text = wins
		elseif pos6 == false then
			pos6 = true
			script.Parent.Position6.name6.Text = name
			script.Parent.Position6.num6.Text = wins
		elseif pos7 == false then
			pos7 = true
			script.Parent.Position7.name7.Text = name
			script.Parent.Position7.num7.Text = wins
		elseif pos8 == false then
			pos8 = true
			script.Parent.Position8.name8.Text = name
			script.Parent.Position8.num8.Text = wins
		elseif pos9 == false then
			pos9 = true
			script.Parent.Position9.name9.Text = name
			script.Parent.Position9.num9.Text = wins
		elseif pos7 == false then
			pos10 = true
			script.Parent.Position10.name10.Text = name
			script.Parent.Position10.num10.Text = wins
		end		
	end	
end

while true do
	print('UPDATING GLOBAL LEADERBOARD')
	topTenPlayers()
	wait(30)
end

ps - idk data stores that well :P

1 answer

✓ Accepted answer

Lets start with some DRY cleanup. This code:

local pos1 = false
local pos2 = false
local pos3 = false
local pos4 = false
local pos5 = false
local pos6 = false
local pos7 = false
local pos8 = false
local pos9 = false
local pos10 = false

local function topTenPlayers()
    local pages = winsODS:GetSortedAsync(false, 10)
    local topTen = pages:GetCurrentPage()

    for rank, data in ipairs(topTen) do
        local name = data.key
        local wins = data.value

        if pos1 == false then
            pos1 = true
            script.Parent.Position1.name1.Text = name
            script.Parent.Position1.num1.Text = wins
        elseif pos2 == false then
            pos2 = true
            script.Parent.Position2.name2.Text = name
            script.Parent.Position2.num2.Text = wins
        elseif pos3 == false then
            pos3 = true
            script.Parent.Position3.name3.Text = name
            script.Parent.Position3.num3.Text = wins
        elseif pos4 == false then
            pos4 = true
            script.Parent.Position4.name4.Text = name
            script.Parent.Position4.num4.Text = wins
        elseif pos5 == false then
            pos5 = true
            script.Parent.Position5.name5.Text = name
            script.Parent.Position5.num5.Text = wins
        elseif pos6 == false then
            pos6 = true
            script.Parent.Position6.name6.Text = name
            script.Parent.Position6.num6.Text = wins
        elseif pos7 == false then
            pos7 = true
            script.Parent.Position7.name7.Text = name
            script.Parent.Position7.num7.Text = wins
        elseif pos8 == false then
            pos8 = true
            script.Parent.Position8.name8.Text = name
            script.Parent.Position8.num8.Text = wins
        elseif pos9 == false then
            pos9 = true
            script.Parent.Position9.name9.Text = name
            script.Parent.Position9.num9.Text = wins
        elseif pos7 == false then
            pos10 = true
            script.Parent.Position10.name10.Text = name
            script.Parent.Position10.num10.Text = wins
        end     
    end 
end

Should not be used. BTW, notice the error in line 56? That kind of copy/paste errors are hard to find and that is exactly why you should replace your code with this:

local function topTenPlayers()
    local pages = winsODS:GetSortedAsync(false, 10)
    local topTen = pages:GetCurrentPage()

    local pos = 0
    for rank, data in ipairs(topTen) do
	pos = pos + 1
	local Position = script.Parent:FindFirstChild("Position" .. pos)
	local name = Position:FindFirstChild("name" .. pos)
	local num = Position:FindFirstChild("num" .. pos)
	name.Text = data.key 
	num.Text = data.value
    end
end

Now the important bit. Your GetAsync function should be wrapped in pcall. It may, and in my experience with Roblox, will fail rather often. Once it fails your program will assume that no data exist and will overwrite any records with 0. You will get some very angry players.

My advise will be however to get rid of GetAsync altogether, as you do not really need that information anyway in PlayerAdded. Instead replace SetAsync with UpdateAsync, that will check automatically for an old data.

Why you get error that you mentioned however is a mystery to me, but just to let you know you had errors in line 6 and 8. Neither WinsODS neither WinDataODS should be compared with player.Name. It just doesn't make sense, as none of them will never be equal to player.Name

So your function should look something like this:

local DS = game:GetService("DataStoreService")
local winsODS = DS:GetOrderedDataStore('WINDATA') 

game.Players.PlayerAdded:Connect(function(plr)

        local success, err = pcall(function()
            winsODS:UpdateAsync(plr.Name, function(oldValue)
			if typeof(oldValue) ~= "number" then 
				return 0
			else
				return oldValue
			end
		end)
        end)

        if success then
            print(plr.Name, 'SUCCESSFULLY ADDED.')
        else
            warn(plr.Name, 'WAS NOT ADDED SUCCESSFULLY')
        end
end)

UpdateAsync will only write 0 when old data is not present or is not a number (corrupted). Believe me it happens more that you can imagine, if you have been using SetAsync before. As a side note, try to avoid SetAsync whenever you can. IncrementAsync is preferred in OrderedDataStores.

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