I'm now trying to make the attribute system in my game save. but I don't know how should I do it

hey there peoples again, the previous topic is solved well, but I need help with one more thing right now, let me explain.

I am making an roblox RPG game with some kits and it have attribute system, pet system, and quest system. and such. but I have problem with attribute system, so when player uses attribute points for small boosts, it does work well until player rejoins, and when it happened it just resets player’s attribute points. so I need your help with making the whole thing saveable since DevZoid didn’t do that. thank you so much for helps again.

so, here is the script DevZoid have made for his video, video he showcase it is linked here. check out his video

local spdPerPoint = 0.20
local starterSpeed = 16

local hpPerPoint = 10

game.Players.PlayerAdded:Connect(function(player)
	
	local SC = Instance.new("IntValue")
	SC.Name = "SocialCredit"
	SC.Parent = player

	local attack = Instance.new("IntValue")
	attack.Name = "Attack"
	attack.Parent = player

	local speed = Instance.new("IntValue")
	speed.Name = "Speed"
	speed.Parent = player
end)

local repStorage = game:GetService("ReplicatedStorage")

local SCRemote = repStorage.Attributes.AddSC
local spdRemote = repStorage.Attributes.AddSpeed
local atkRemote = repStorage.Attributes.AddAttack
local reset = repStorage.Attributes.Reset

local function PointsAvailable(player)
	local pointsUsed = player.SocialCredit.Value + player.Attack.Value + player.Speed.Value
	local pointsAvailable = player.leaderstats.Level.Value - pointsUsed

	return pointsAvailable > 0
end

SCRemote.OnServerEvent:Connect(function(player)

	if not PointsAvailable(player) then return end

	player.SocialCredit.Value += 1
end)

spdRemote.OnServerEvent:Connect(function(player)

	if not PointsAvailable(player) then return end

	player.Speed.Value += 1

	player.Character.Humanoid.WalkSpeed = starterSpeed + player.Speed.Value * spdPerPoint
end)


atkRemote.OnServerEvent:Connect(function(player)

	if not PointsAvailable(player) then return end

	player.Attack.Value += 1
end)

reset.OnServerEvent:Connect(function(player)
	player.Attack.Value = 0
	player.SocialCredit.Value = 0
	player.Speed.Value = 0

	player.Character.Humanoid.WalkSpeed = starterSpeed + player.Speed.Value * spdPerPoint
end)

I’m wishing that peoples will come to this topic for help me once again, and always, thank you so much.
-mari

5 Likes

So you might need to save your player data with DataStore

Or a enchanced version of DataStore (DataStore2) of it which Is safer.

Here’s a tutorial from AlvinBlox for saving data & player data:

–Bloom

3 Likes

To make the attribute points saveable so that they persist even when the player rejoins the game, you can use data stores to store and retrieve the attribute values.
Try This Code:

local spdPerPoint = 0.20
local starterSpeed = 16

local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("PlayerData")

game.Players.PlayerAdded:Connect(function(player)
	
	local SC = Instance.new("IntValue")
	SC.Name = "SocialCredit"
	SC.Parent = player

	local attack = Instance.new("IntValue")
	attack.Name = "Attack"
	attack.Parent = player

	local speed = Instance.new("IntValue")
	speed.Name = "Speed"
	speed.Parent = player
	
	-- Load player's saved data
	local success, savedData = pcall(function()
		return playerDataStore:GetAsync(tostring(player.UserId))
	end)
	
	if success and savedData then
		SC.Value = savedData.SocialCredit or 0
		attack.Value = savedData.Attack or 0
		speed.Value = savedData.Speed or 0
	end
end)

local repStorage = game:GetService("ReplicatedStorage")

local SCRemote = repStorage.Attributes.AddSC
local spdRemote = repStorage.Attributes.AddSpeed
local atkRemote = repStorage.Attributes.AddAttack
local reset = repStorage.Attributes.Reset

local function SavePlayerData(player)
	local data = {
		SocialCredit = player.SocialCredit.Value,
		Attack = player.Attack.Value,
		Speed = player.Speed.Value,
	}

	local success, error = pcall(function()
		playerDataStore:SetAsync(tostring(player.UserId), data)
	end)

	if not success then
		warn("Failed to save data for player " .. player.Name .. ": " .. error)
	end
end

local function PointsAvailable(player)
	local pointsUsed = player.SocialCredit.Value + player.Attack.Value + player.Speed.Value
	local pointsAvailable = player.leaderstats.Level.Value - pointsUsed

	return pointsAvailable > 0
end

SCRemote.OnServerEvent:Connect(function(player)

	if not PointsAvailable(player) then return end

	player.SocialCredit.Value += 1
	SavePlayerData(player)
end)

spdRemote.OnServerEvent:Connect(function(player)

	if not PointsAvailable(player) then return end

	player.Speed.Value += 1

	player.Character.Humanoid.WalkSpeed = starterSpeed + player.Speed.Value * spdPerPoint

	SavePlayerData(player)
end)


atkRemote.OnServerEvent:Connect(function(player)

	if not PointsAvailable(player) then return end

	player.Attack.Value += 1

	SavePlayerData(player)
end)

reset.OnServerEvent:Connect(function(player)
	player.Attack.Value = 0
	player.SocialCredit.Value = 0
	player.Speed.Value = 0

	player.Character.Humanoid.WalkSpeed = starterSpeed + player.Speed.Value * spdPerPoint

	SavePlayerData(player)
end)
4 Likes

He’s probably watching the tutorial or something, but your code is the exact answer. Nice

1 Like

hey there fozy, thank you for your splendid help, but however there is one problem remaining, in the DevZoid’s Attribute system, it uses gui to modify the attribute point uses, but when player rejoins, the attribute GUI resets, and it goes like this. also thankfully the attribute points did save after rejoin, but since attribute GUI is reseted, so when player clicks the add button to modify the attributes, the whole attribute points player had goes reset. so here is the screenshot.

so what I want you to do is that, I’m aksing you for modify the script code I showed you below to sync and detect current attribute points player has.
so example if speed attribute script detects player already had some speed attribute points, it will change it’s *script.Parent.Parent.Value.Text into current speed attribute point player currently has, so therefore the GUI will not reset the player’s attribute points upon it’s add button is clicked. so here is the script.

local remote = game:GetService("ReplicatedStorage").Attributes.AddSpeed

script.Parent.Activated:Connect(function()
	
	if tonumber(script.Parent.Parent.Parent.Total.Value.Text) > 0 then
		script.Parent.Parent.Value.Text += 1
		script.Parent.Parent.Parent.Total.Value.Text -=1
		
		remote:FireServer()
	end
end)

as always again. thank you so much for you guy’s help. I wish that I could make great game out of these.

I’ve added two functions: updateAttributePoints and handleClick

local remote = game:GetService("ReplicatedStorage").Attributes.AddSpeed

-- Function to update the GUI text with the current attribute points
local function updateAttributePoints(points)
	script.Parent.Parent.Value.Text = tostring(points)
end

-- Function to handle the button click
local function handleClick()
	local totalPoints = tonumber(script.Parent.Parent.Parent.Total.Value.Text)
	local currentPoints = tonumber(script.Parent.Parent.Value.Text)

	if totalPoints > 0 then
		script.Parent.Parent.Value.Text = tostring(currentPoints + 1)
		script.Parent.Parent.Parent.Total.Value.Text = tostring(totalPoints - 1)
		
		remote:FireServer()
	end
end

-- Check if the player already has attribute points when the GUI is initialized
local currentPoints = tonumber(script.Parent.Parent.Value.Text)
if currentPoints > 0 then
	updateAttributePoints(currentPoints)
end

script.Parent.Activated:Connect(handleClick)

By using these modifications, the GUI will display the player’s current attribute points correctly and avoid resetting them when the add button is clicked.

1 Like

hey there again fozy, the updated code for Attribute gui didn’t worked, I have one question of how does it work, does this code need data from player? or does it gathers datastore data from player so it loads player’s attribute points?

and also, there is one script that remain not updated, that is an script named “resetattribute” which is inside reset textbutton. I’ll give you an code of it again, and I will be pleased if you could get an fix with the code. so here we go.

local remote = game:GetService("ReplicatedStorage").Attributes.Reset

local points = game.Players.LocalPlayer.leaderstats.Level

script.Parent.Parent.Total.Value.Text = points.Value

script.Parent.Activated:Connect(function()
	script.Parent.Parent.Attack.Value.Text = 0
	script.Parent.Parent.Health.Value.Text = 0
	script.Parent.Parent.Speed.Value.Text = 0
	
	script.Parent.Parent.Total.Value.Text = points.Value
	
	remote:FireServer()
end)

points.Changed:Connect(function()
script.Parent.Parent.Total.Value.Text += 1
end)

thank you so much for helping for this topic :hugs: -mari

hello? are you here right now?

Why am I mentioned in this?

Very sorry, I accidently replied with a link to your reply. I am not very experienced to really use this forum, sorry I will change it.

1 Like

the datastore thing works correctly on my game, the attribute points save after rejoin, but the problem is that in attribute gui, player will spend their attribute points they gained from level ip, but the numbers in gui doesn’t sync with current attribute point players has, so when any button is clicked in that gui, it resets the whole thing ;-; -mari

hello? is anyone can help me with finishing the attribute system in my game? and after the attribute system is completed. I can now publish the rpg game I was working on anytime soon.
-mari

That’s not what I was asking about. I literally never clicked on this before and I got mentioned.

Wont talk in this anymore

hey there again fozy, I have modified the script by bit, but it doesn’t seems to work at all, do you have any idea to fix it? thank you so much.

local remote = game:GetService("ReplicatedStorage").Attributes.AddAttack
local playerAP = game.Players.LocalPlayer

-- Function to update the GUI text with the current attribute points
local function updateAttributePoints(points)
	script.Parent.Parent.Value.Text = tostring(points)
end

-- Function to handle the button click
local function handleClick()
	local totalPoints = tonumber(script.Parent.Parent.Parent.Total.Value.Text)
	local currentPoints = tonumber(playerAP.Attack.Value)

	if totalPoints > 0 then
		script.Parent.Parent.Value.Text = tostring(currentPoints + 1)
		script.Parent.Parent.Parent.Total.Value.Text = tostring(totalPoints - 1)

		remote:FireServer()
	end
end

-- Check if the player already has attribute points when the GUI is initialized
local currentPoints = tonumber(script.Parent.Parent.Value.Text)
if currentPoints > 0 then
	updateAttributePoints(currentPoints)
end

script.Parent.Activated:Connect(handleClick)

-mari

now I modified the code like this yet it’s still not working…

local remote = game:GetService("ReplicatedStorage").Attributes.AddSC

-- Function to update the GUI text with the current attribute points
local function updateAttributePoints(points)
	script.Parent.Parent.Value.Text = tostring(points)
end

-- Function to handle the button click
local function handleClick()
	local totalPoints = tonumber(script.Parent.Parent.Parent.Total.Value.Text)
	local currentPoints = game.Players.LocalPlayer.Attack.Value

	if totalPoints > 0 then
		script.Parent.Parent.Value.Text = tostring(currentPoints + 1)
		script.Parent.Parent.Parent.Total.Value.Text = tostring(totalPoints - 1)

		remote:FireServer()
	end
end

-- Check if the player already has attribute points when the GUI is initialized
local currentPoints = tonumber(script.Parent.Parent.Value.Text)
if currentPoints > 0 then
	updateAttributePoints(currentPoints)
end

script.Parent.Activated:Connect(handleClick)

it would be awesome if you could help me out with it. thank you again
-mari again