Skip to content

Instantly share code, notes, and snippets.

@angeld23
Last active January 17, 2022 23:06
Show Gist options
  • Save angeld23/7f7a3acd515951710b3cf7cb2a2faaa3 to your computer and use it in GitHub Desktop.
Save angeld23/7f7a3acd515951710b3cf7cb2a2faaa3 to your computer and use it in GitHub Desktop.
-- Name: Leaderstats Module
-- Author: angeld23
-- Date: 2022-17-01
-- Description: Wrapper that automatically handles the creation and modification of leaderstats inside Roblox Player instances.
--[[ Usage Example
```lua
local Leaderstats = require(Path.To.Leaderstats.Module.Here)
local Player1 = game.Players.Player1
local tableForPlayer1 = Leaderstats[Player1]
tableForPlayer1.TestValue = 999 --// A new entry labeled "TestValue" will appear on the leaderboard next to Player1 with the value "999"
print(tableForPlayer1.TestValue) --> 999
--// You can also overwrite the whole table like this:
Leaderstats[Player1] = {
Value1 = 999;
Value2 = 9001;
Value3 = 1337;
}
--// To remove a value from the leaderboard, just set it to nil:
tableForPlayer1.Value3 = nil
--// You can set the value to a different type and the Value object will be updated automatically:
tableForPlayer1.Value3 = 1337 -- NumberValue is created
tableForPlayer1.Value3 = "Hello World" -- NumberValue is deleted, and StringValue is created with the same name
--// To iterate over either the whole leaderboard or a specific player's stats, use the following:
for plr, statsTable in Leaderstats.__pairs() do
-- (this code runs for every player)
end
for statKey, statValue in Leaderstats[Player1].__pairs() do
-- (this code runs for every stat in Player1's leaderboard)
end
-- (if only roblox supported the __pairs metamethod)
-- :(
--// Not all types are supported because Roblox Value objects have limits.
--// Supported types:
-- string, number, boolean, Vector3, Color3, Instance, CFrame, Ray
--// The module will throw an error otherwise.
--// But there's honestly no reason to be using anything except strings and numbers.
--// It's just a leaderboard, dude.
```
]]
local types = {
string = "StringValue";
number = "NumberValue";
boolean = "BoolValue";
Vector3 = "Vector3Value";
Color3 = "Color3Value";
Instance = "ObjectValue";
CFrame = "CFrameValue";
Ray = "RayValue";
["nil"] = ""; -- so the type validation somewhere below this doesn't freak out
}
function getLeaderstatFolder (plr)
local leaderstats = plr:FindFirstChild("leaderstats") or Instance.new("Folder", plr)
leaderstats.Name = "leaderstats"
return leaderstats
end
function setLeaderstat (plr, key, value)
local folder = getLeaderstatFolder(plr)
if value == nil then
local stat = folder:FindFirstChild(key)
if stat then
stat:Destroy()
end
else
local stat = folder:FindFirstChild(key)
if not stat then
stat = Instance.new(types[typeof(value)], folder)
stat.Name = key
elseif stat.ClassName ~= types[typeof(value)] then
stat:Destroy()
stat = Instance.new(types[typeof(value)], folder)
stat.Name = key
end
stat.Value = value
end
end
function getLeaderstat (plr, key, value)
local folder = getLeaderstatFolder(plr)
local stat = folder:FindFirstChild(key)
if stat then
return stat.Value
end
end
local toReturn = {}
toReturn.__pairs = (function ()
local tablefied = {}
for _, plr in pairs(game:GetService("Players"):GetPlayers()) do
tablefied[plr] = toReturn[plr]
end
return pairs(tablefied)
end)
setmetatable(toReturn, {
__index = (function (t, plr)
if typeof(plr) == "Instance" and plr:IsA("Player") then
local p = {}
p.__pairs = function ()
local tablefied = {}
for _, valueObj in pairs(getLeaderstatFolder(plr):GetChildren()) do
tablefied[valueObj.Name] = valueObj.Value
end
return pairs(tablefied)
end
return setmetatable(p, {
__index = (function(t, key)
return getLeaderstat(plr, key)
end);
__newindex = (function(t, key, value)
if not types[typeof(value)] then
error("Invalid leaderstat type: " .. typeof(value), 2)
end
setLeaderstat(plr, key, value)
end);
})
end
end);
__newindex = function (t, plr, value)
if typeof(value) == "table" and typeof(plr) == "Instance" and plr:IsA("Player") then
getLeaderstatFolder(plr):ClearAllChildren()
for key, val in pairs(value) do
if not types[typeof(val)] then
continue
end
setLeaderstat(plr, key, val)
end
end
end;
__metatable = "Locked";
})
return toReturn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment