[lua]local Player = FindMetaTable(“Player”)
local initialStats = {
Strength = 10,
Dexterity = 10,
Charisma = 0,
Intelligence = 20
}
if SERVER then
– table with weak keys so stat tables are garbage collected
local stats = setmetatable({}, {__mode=‘k’})
function Player:SetStat(sName, iValue)
stats[self][sName] = iValue
umsg.Start(“StatUpdate”, self)
umsg.String(sName)
– depends on your maximum value for a stat
– Char gives -128 to 127
umsg.Char(iValue)
umsg.End()
end
function Player:GetStat(sName)
return stats[self][sName]
end
hook.Add("InitialSpawn", function(pl)
stats[pl] = table.Copy(initialStats)
end)
else – client
local stats = table.Copy(initialStats)
usermessage.Hook(“StatUpdate”, function(um)
stats[um:ReadString()] = um:ReadChar()
end)
function Player:GetStat(sName)
if self ~= LocalPlayer() then
error("Can only GetStat of LocalPlayer
", 2)
end
return stats[sName]
end
function Player:SetStat()
error("Stats cannot be set Clientside
", 2)
end
end[/lua]
Strictly speaking GetStat on the client doesn’t have to go in the Player metatable, however it seems neater to me.
This implementation also protects the stat tables from meddling.
There’s also other stuff you could do, like having Stat objects with stuff like a Stat ID, so you don’t have to send strings to the Client. This will then need a lookup function so you can get the Stat object back from the ID.
Instead of a Stat being a string with an associated value, the Stat will be an object with many attributes, such as a maximum value, a minimum value, a name string and a description string.
You could then verify whether the stat changes are valid, first a Stat like that has to exist and second its value has to be within its valid range.