My Point System

Hello, I’m having trouble using DataStores to create a system where it uses a command of “!Point [Input]” to give a point to someone and then save them point(s) and when leaving adds that to a DataStore so it loads back up when joined again, I’ve tried a bit but haven’t really got far. I’d be great if someone could help explain how to do or something. This would be amazing, thank you!

1 Like

If possible, please show any code that you already have. It’s easier for me to correct things for you than it is for me to try and explain everything in text.

You will need these things to have that system work:

  1. Use the Player.Chatted event to detect when someone chats.
  2. Change the point values inside leaderstats
  3. Use the Players.PlayerRemoving event to save to DataStores using the GlobalDataStore:SetAsync()

This is what I currently have, most likely has a lot of errors and all so excuse me for all of them ahah. Pretty sure there’s an easier way to do it but I’m too dumb for that.

local DataStoreService = game:GetService("DataStoreService")
local players = game.Players

game.Players.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
	
function GetPlayerData(player)
local playerData = DataStoreService:GetDataStore("PlayerData")
local success, data = pcall(function()
    playerData:GetAsync(player.UserId)
end)
if not success then
    wait(0.5)
    GetPlayerData(player)
else
    if data then
        workspace.PointValues[player.Name .. "Points"].Value = data
    else
        workspace.PointValues[player.Name .. "Points"].Value = 0
    end
    print(player.Name .. " has " .. workspace.PointValues[player.Name .. "Points"].Value)
end
end

players.PlayerAdded:Connect(function(player)
local Points = Instance.new("IntValue")
Points.Name = player.Name .. "Points"
Points.Parent = workspace.PointValues
GetPlayerData(player)
end)

function SavePlayerData(player)
local playerData = DataStoreService:GetDataStore("PlayerData")
local success = pcall(function()
    playerData:SetAsync(player.UserId, workspace.PointValues[player.Name] .. "Points")
end)
if success then
    workspace.PointValues[player.Name .. "Points"]:Destroy()
    print("Successfully saved " .. player.Name .. "'s data.")
else
    wait(0.5)
    SavePlayerData(player)
end
end

Player.Chatted:connect(function(chat)
	if string.sub(chat,0,string.len("!points")) == "!points" then
		local point = string.sub(chat,8)
		if tostring(point) then
			print(player.Name .. " has gained point(s), saving data")
			workspace.PointValues[player.Name .. "Points"].Value = (point)
			SavePlayerData(player)
			end

players.PlayerRemoving:Connect(function(player)
print(player.Name .. " has left the server, saving data")
workspace.PointValues[player.Name .. "Points"].Value = (point)
SavePlayerData(player)
end) end

Please indent properly and use whitespace in your code. I indented it myself, and it was clear that there are a lot of problems.

For one, the amount of ends.

Secondly, the point variable contains the sub string from the start of chat to its eighth character. If chat was equal to “!points 28”, then point would be equal to "!points ". So, you’d be setting the player’s PointValue to a string. Since those are of the class IntValue, this is not possible. You’re also performing tostring on something you know is a string. This is redundant. You were probably looking for tonumber to make sure that the point value inputted was a valid number. Also, I would not reccomend using this for a game as this is a very insecure system as anyone can change their data.

Thirdly, the SavePlayerData function. When it sets async, it tries to index workspace.PointValues with the player’s name and then concatenate that (which will be an object) with a string. What you were probably trying to do is to try to index workspace.PointValues with the string resulting from concatenating the player’s name from a string. Although, even if you got this object correctly, you can’t save objects to DataStores. So, you’d have to grab the value from that object. The correct code would be:

playerData:SetAsync(player.UserId, workspace.PointValues[player.Name.. "Points"].Value)

Fourthly, in the callback for the PlayerRemoving event, you’re attempting to set the value of one of those PointValues to point. The variable point will be out of scope in this chunk. The line is redundant in any case.

Fifthly (if that’s the proper word), in the GetPlayerData function you’re trying to get data from the pcall function. The second return value of the pcall will be an error if there is one occuring in the code encased within the pcall, not the data returned from GetAsync. To do this, you’d have to declare a variable outside of the pcall and assign to it in the pcall the data returned from GetAsync.

Reccomendations
Inside the callback of the CharacterAdded event of each player passed by PlayerAdded you’re adding connections for events from the service Players when you could add those connections outside of that chunk. You do not even have to use the CharacterAdded event in this code. I would also declare the functions (“GetPlayerData”,“SavePlayerData”) outside of the PlayerAdded chunk.

Wrong one. That one only fires if ChatService’s Chat method is called. The proper function to use would be Player.Chatted or an LCS command module.

2 Likes