I’ve been trying to sort players in a table in order from most gems to least. When there are 2 or more players print(jewels) prints 0 even when the player has more than 0 jewels. It works fine when there is only one player.
local plrs = {}
local playerRankingsDictionary = {}
local names = {}
local function SortByGemsDescending(plrs)
for i, player in pairs(plrs) do
local jewels = game.Players:FindFirstChild(player).jewels.Value
print(jewels)
playerRankingsDictionary[player] = jewels
end
end
local function game_ended()
SortByGemsDescending(plrs)
wait(1)
for k,_ in pairs(playerRankingsDictionary) do
table.insert(names, k)
end
table.sort(names)
for k, v in pairs(playerRankingsDictionary) do
print(k.."="..v)
end
end
game_ended()
You can’t really sort a dictionary, you’d need to keep it as an array, like so:
local plrs = {}
local playerRankingsDictionary = {}
local names = {}
local function SortByGemsDescending(plrs)
for i, player in pairs(plrs) do
local jewels = game.Players:FindFirstChild(player).jewels.Value
print(jewels)
playerRankingsDictionary[player] = jewels
end
end
-- Convert the dict into an array instead, so you can use the table.sort method
local function SortByGemsDescending(plrs)
local playerRankingsDictionary = { }
for i, player in next, plrs do
player = player:IsA 'Player' and player or (type(player) == 'string' and game.Players:FindFirstChild(player) or nil)
if player and player:FindFirstChild 'jewels' then
playerRankingsDictionary[#playerRankingsDictionary + 1] = {player = player; jewels = player.jewels.Value}
end
end
table.sort(playerRankingDictionary, function (a, b)
-- a.jewels > b.jewels is descending order
-- if you wanted ascending, you would do: a.jewels < b.jewels
return a.jewels > b.jewels
end)
return playerRankingsDictionary
end
-- For you to test:
local function printGemList(plrs)
--[[
Should print e.g.:
Player1 is 1st with 10 jewels
Player2 is 2nd with 5 jewels
n-player is n-th with n jewels
]]
local function ordinalNumber(n)
local ordinal, digit = {"st", "nd", "rd"}, string.sub(n, -1)
if tonumber(digit) > 0 and tonumber(digit) <= 3 and string.sub(n,-2) ~= 11 and string.sub(n,-2) ~= 12 and string.sub(n,-2) ~= 13 then
return n .. ordinal[tonumber(digit)]
else
return n .. "th"
end
end
local orderedList = SortByGemsDescending(plrs)
for i, packet in next, orderedList do
if packet.player and packet.player.Parent then
print(
('%s is %d%s with %d jewels!'):format(packet.player.Name, i, ordinalNumber(i), packet.jewels)
)
end
end
end
Also, if it’s the ‘print(jewels)’ that’s printing 0 in your original ‘SortByGemsDescending()’ function, are you sure you’re updating these values from a server script and not a local script? If this game_ended() function is running on a server and you’ve been updating the jewels value on the client without informing the server, then it’s because it’s not replicated and you will need to make use of RemoteEvents (or pass the decision making for incrementing jewels to the server entirely)
That’s not sorting a dictionary though, you’re sorting the array ‘plrs’? The dictionary in his example is the table ‘playerRankingsDictionary’ with the index as a Player (GameObject) and the value as the jewel (number/int)
Could this still be the problem if there’s only one person in the array and it works fine, but if there’s more than one person it always says 0 jewels?
It would work fine with the code I posted above, but I have no idea how you’re determining who’s name is put inside of the ‘plrs’ array. Could you post that code and I can tell you if that’s wrong?
local plrs = {}
local plr_limit = 6
local function check_plr(plr)
local found_plr = false
for _,v in pairs(plrs) do
if v == plr then
found_plr = true
break
end
end
return found_plr
end
script.Parent.Touched:Connect(function(p)
if #plrs < plr_limit and p.Parent:FindFirstChildOfClass("Humanoid") and not check_plr(p.Parent.Name) then
table.insert(plrs, p.Parent.Name)
game.Workspace:WaitForChild(p.Parent.Name).Head.BillboardGui.Enabled = true
elseif #plrs >= plr_limit and not func_started then
func_started = true
start_script()
end
end)
This is the whole script just in case you want to see it
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local plrs = {}
local plr_limit = 2
local func_started = false
local function SortByGemsDescending(plrs)
local playerRankingsDictionary = {}
for i, player in next, plrs do
player = player and (type(player) == 'string' and game.Players:FindFirstChild(player) or (typeof(player) == 'Instance' and player or nil)) or nil
if player and player:FindFirstChild 'jewels' then
playerRankingsDictionary[#playerRankingsDictionary + 1] = {player = player; jewels = player.jewels.Value}
end
end
table.sort(playerRankingsDictionary, function (a, b)
return a.jewels > b.jewels
end)
return playerRankingsDictionary
end
local function printGemList(plrs)
local function ordinalNumber(n)
local ordinal, digit = {"st", "nd", "rd", "th", "th"}, string.sub(n, -1)
if tonumber(digit) > 0 and tonumber(digit) <= 3 and string.sub(n, -2) ~= 1 and string.sub(n, -2) ~= 2 and string.sub(n, -2) ~= 3 then
return n .. ordinal[tonumber(digit)]
else
return n .. "th"
end
end
local orderedList = SortByGemsDescending(plrs)
for i, packet in next, orderedList do
if packet.player and packet.player.Parent then
print(
('%s is %d%s with %d jewels!'):format(packet.player.Name, i, ordinalNumber(i), packet.jewels)
)
end
end
end
local function game_ended()
SortByGemsDescending(plrs)
printGemList(plrs)
end
local function start_script()
local timeLeft = 20
for i = 1, timeLeft do
for i, player in pairs(plrs) do
local plr = game.Players:FindFirstChild(player)
timeLeft -= 1
plr.gameTime.Value -= 1
if timeLeft == 1 then
print("fire game ended")
game_ended()
end
end
wait(1)
end
end
local function check_plr(plr)
local found_plr = false
for _,v in pairs(plrs) do
if v == plr then
found_plr = true
break
end
end
return found_plr
end
script.Parent.Touched:Connect(function(p)
if #plrs < plr_limit and p.Parent:FindFirstChildOfClass("Humanoid") and not check_plr(p.Parent.Name) then
table.insert(plrs, p.Parent.Name)
game.Workspace:WaitForChild(p.Parent.Name).Head.BillboardGui.Enabled = true
elseif #plrs >= plr_limit and not func_started then
func_started = true
start_script()
end
end)
There’s no reason why this would stop it from counting the jewels. How have you implemented the updating of the gem value? Is it a local script or a server script?
Similarly, is the script you posted above in a local or a server script?
Some changes for some extra checks:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DEBUG = true --> Turn it off to stop printing the gem data
local plrs = { }
local plr_limit = 2
local func_started = false
local function SortByGemsDescending(plrs)
local playerRankingsDictionary = { }
for i, player in next, plrs do
player = game.Players:FindFirstChild(player)
if player and player:IsA 'Player' and player:FindFirstChild 'jewels' then
playerRankingsDictionary[#playerRankingsDictionary + 1] = {player = player; jewels = player.jewels.Value}
end
end
table.sort(playerRankingsDictionary, function (a, b)
return a.jewels > b.jewels
end)
return playerRankingsDictionary
end
local function printGemList(plrs)
local function ordinalNumber(n)
local ordinal, digit = {"st", "nd", "rd", "th", "th"}, string.sub(n, -1)
if tonumber(digit) > 0 and tonumber(digit) <= 3 and string.sub(n, -2) ~= 1 and string.sub(n, -2) ~= 2 and string.sub(n, -2) ~= 3 then
return n .. ordinal[tonumber(digit)]
else
return n .. "th"
end
end
local orderedList = SortByGemsDescending(plrs)
for i, packet in next, orderedList do
if packet.player and packet.player.Parent then
print(
('%s is %d%s with %d jewels!'):format(packet.player.Name, i, ordinalNumber(i), packet.jewels)
)
end
end
end
local function game_ended()
--> Do stuff with the ranked list here
local rankedByJewelList = SortByGemsDescending(plrs)
--> Print the gem list for debug purposes
if DEBUG then
printGemList(plrs)
end
--> Reset our func state
func_started = false
end
local function start_script()
--> If we've already started, don't start it again
if func_started then
return
end
local timeLeft = 20
for i = 1, timeLeft do
for i, player in pairs(plrs) do
local plr = game.Players:FindFirstChild(player)
timeLeft = timeLeft - 1
plr.gameTime.Value = plr.gameTime.Value - 1
if timeLeft == 1 then
print("fire game ended")
game_ended()
break
end
end
wait(1)
end
end
local function check_plr(plr)
local found_plr = false
for _,v in pairs(plrs) do
if v == plr then
found_plr = true
break
end
end
return found_plr
end
script.Parent.Touched:Connect(function (p)
if #plrs < plr_limit and p and p.Parent and p.Parent:FindFirstChildOfClass("Humanoid") and not check_plr(p.Parent.Name) then
--> Let's make sure all the pieces are in the right place, if so, we can add them to our list
if p.Parent:FindFirstChild 'Head' then
if p.Parent.Head:FindFirstChild 'BillboardGui' then
table.insert(plrs, p.Parent.Name)
p.Parent.Head.BillboardGui.Enabled = true
end
end
--> Start it now if we have enough players
if #plrs >= plr_limit and not func_started then
func_started = true
start_script()
end
elseif #plrs >= plr_limit and not func_started then
func_started = true
start_script()
end
end)
Thank you so much! It’s working fine now, but is there a way to make it so when you sort the player into the playerRankingsDictionary you add their name instead of a letters and numbers like this: 0xb1065764b8a63133?
So the hash you sent above is actually what’s called a table reference, it’s the reference in memory to that table.
In the function:
local function game_ended()
--> Do stuff with the ranked list here
local rankedByJewelList = SortByGemsDescending(plrs)
--> Print the gem list for debug purposes
if DEBUG then
printGemList(plrs)
end
--> Reset our func state
func_started = false
end
When you define the variable ‘rankedByJewelList’ as the return value from SortByGemsDescending() function, it returns a table such that:
-- Let's pretend both you and I are in a game, and you have 5 jewels and I have 2
local rankedByJewelList = SortByGemsAscending(plrs)
-- The table actually looks like this:
--[[
local rankedByJewelList = {
[1] = {player = game.Players.Play_MazeOfHeck; jewels = 5}; -- You're the 1st index as you have the most jewels
[2] = {player = game.Players.Isocortex;, jewels = 2};
}
]]
Therefore, if you want the person with the most jewels, you would just index the table with its 1st index i.e.
local MostJewelsPacket = rankedByJewelList[1]
local MostJewelsCount = MostJewelsPacket.jewels
local MostJewelsPlayer = MostJewelsPacket.player
Or, if you wanted to iterate through the result to get each index:
for WhatTheyPlaced, Packet in next, rankedByJewelList do
local player = Packet.player -- the player we're looking at
local jewels = Packet.jewels -- the jewels they managed to get
print(player.Name, 'came', WhatTheyPlaced, 'with', jewels, 'jewels!')
-- In the case above (with you and I in a game), this would print something like:
--[[
Play_MazeOfHeck came 1 with 5 jewels!
Isocortex came 2 with 2 jewels!
]]
end
``