How can I make the leaderstats save?

I’m not much of a coder, so I deeply apologize. However, I’m trying to figure out how to save the currency (Studs), but The same script is also used for the game itself, so any help will be appreciated!

local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("DATA STORES")


function saveData(plr)

	if not plr:FindFirstChild("FAILED TO LOAD DATA") then
		local cash = plr.leaderstats.Cash.Value

		local success, err = nil, nil
		while not success do
			success, err = pcall(function()
				return ds:SetAsync(plr.UserId, cash)
			end)
			warn(err)
			task.wait(0.1)
		end
	end
end

game.Players.PlayerRemoving:Connect(saveData)
game:BindToClose(function()
	for i, plr in pairs(game.Players:GetPlayers()) do
		saveData(plr)
	end
end)


game.Players.PlayerAdded:Connect(function(plr)

	local ls = Instance.new("Folder")
	ls.Name = "leaderstats"
	ls.Parent = plr

	local studvalue = Instance.new("IntValue")
	studvalue.Name = "Studs"
	studvalue.Parent = ls


	local success, data = pcall(function()
		return ds:GetAsync(plr.UserId)
	end)

	if success then
		studvalue.Value = data or 0

	else
		local failedValue = Instance.new("StringValue")
		failedValue.Name = "FAILED TO LOAD DATA"
		task.wait(1)
		failedValue.Parent = plr
	end
end)



local rs = game.ReplicatedStorage:WaitForChild("BombTagReplicatedStorage")
local config = require(rs:WaitForChild("CONFIGURATION"))
local maps = rs:WaitForChild("Maps")


local status = Instance.new("StringValue")
status.Name = "STATUS"
status.Parent = rs

local currentTagged = Instance.new("ObjectValue")
currentTagged.Name = "CURRENT TAGGED PLAYER"
currentTagged.Parent = rs

local explodeTimer = Instance.new("IntValue")
explodeTimer.Name = "EXPLODE TIMER"
explodeTimer.Parent = rs


function getPlayers(playerList)
	
	local playerList = playerList or game.Players:GetPlayers()
	local playersInGame = {}

	for i, plr in pairs(playerList) do
		local char = if plr.Parent == game.Players then plr.Character else plr
		if char and char:FindFirstChild("Humanoid") and char.Humanoid.Health > 0 then
			table.insert(playersInGame, char)
		end
	end
	return playersInGame
end


local function getReadyPlayers()
	local list = {}
	for _, player in game:GetService("Players"):GetPlayers() do
		if not player:GetAttribute("AFK") and player.Character then
			table.insert(list, player.Character)
		end
	end
	return list
end


while true do
	
	local playersInGame = {} :: { Player }
	
	while #playersInGame < config.MinimumPlayersNeeded do
		playersInGame = getReadyPlayers()
		
		if #playersInGame < config.MinimumPlayersNeeded then
			local neededPlayers = config.MinimumPlayersNeeded - #playersInGame
			
			status.Value = "Waiting for " .. neededPlayers .. " more player" .. (neededPlayers ~= 1 and "s" or "")

			task.wait(1)
		end
	end
	
	for i = config.IntermissionTime, 0, -1 do
		status.Value = "Choosing next location in " .. i .. " seconds"
		task.wait(1)
	end
	
	local chosenMap = maps:GetChildren()[Random.new():NextInteger(1, #maps:GetChildren())]:Clone()
	chosenMap.Parent = workspace
	
	status.Value = "Now going to " .. chosenMap.Name
	
	task.wait(config.MapWaitTime)
	
	
	playersInGame = getReadyPlayers()
	
	if #playersInGame < config.MinimumPlayersNeeded then
		continue
	else
		
		local tagDebounce = false
		for i, char in pairs(playersInGame) do
			
			char.Humanoid.WalkSpeed = config.SurvivorSpeed
			char.HumanoidRootPart.CFrame = chosenMap.SPAWN.CFrame
			
			char.Humanoid.Touched:Connect(function(hit)
				if not tagDebounce and currentTagged.Value then
					
					local hitChar = hit.Parent
					if game.Players:GetPlayerFromCharacter(hitChar) then
						
						if char == currentTagged.Value then
							tagDebounce = true
							
							char.Humanoid.WalkSpeed = config.SurvivorSpeed
							hitChar.Humanoid.WalkSpeed = config.TaggedSpeed
							
							currentTagged.Value = hitChar
							
							task.wait(config.TagCooldown)
							tagDebounce = false
							
						elseif hitChar == currentTagged.Value then
							tagDebounce = true
							
							hitChar.Humanoid.WalkSpeed = config.SurvivorSpeed
							char.Humanoid.WalkSpeed = config.TaggedSpeed

							currentTagged.Value = char

							task.wait(config.TagCooldown)
							tagDebounce = false
						end
					end
				end
			end)
		end
		
		local iterations = 0
		while true do
			iterations += 1
			
			playersInGame = getPlayers(playersInGame)
			
			if #playersInGame > 1 then
				local randomChar = playersInGame[Random.new():NextInteger(1, #playersInGame)]
				randomChar.Humanoid.WalkSpeed = config.TaggedSpeed
				
				if iterations == 1 then
					randomChar.HumanoidRootPart.Anchored = true
					
					for i = config.PreparationTime, 0, -1 do
						status.Value = randomChar.Name .. " has the cheese touch. You have " .. i .. "s to get ready."
						task.wait(1)
					end
					currentTagged.Value = randomChar
					status.Value = randomChar.Name .. " has the cheese touch!"
					randomChar.HumanoidRootPart.Anchored = false
					
				else
					currentTagged.Value = randomChar
					status.Value = randomChar.Name .. " has the cheese touch!"
				end
				
				local explodesIn = config.BombExplodeTimes[#playersInGame]
				explodeTimer.Value = explodesIn
				
				local bombTimerStarted = tick()
				while tick() - bombTimerStarted < explodesIn do
					
					game:GetService("RunService").Heartbeat:Wait()
					explodeTimer.Value = explodesIn - math.round(tick() - bombTimerStarted)
					
					if not currentTagged.Value or #getPlayers(playersInGame) < 2 then
						break
					end
				end
				
				if currentTagged.Value and #getPlayers(playersInGame) >= 2 then
					local explosion = Instance.new("Explosion")
					explosion.DestroyJointRadiusPercent = 0
					explosion.Position = currentTagged.Value.HumanoidRootPart.Position
					explosion.Parent = workspace
					
					currentTagged.Value.Humanoid.Health = 0
					currentTagged.Value = nil
				end
			else
				break
			end
		end
		
		local winner = game.Players:GetPlayerFromCharacter(playersInGame[1])
		if winner then
			winner.leaderstats.Cash.Value += config.SurviveReward
			status.Value = winner.Name .. " survived the cheese touch!"
		end
		
		chosenMap:Destroy()
		for i, plr in pairs(game.Players:GetPlayers()) do
			plr:LoadCharacter()
		end
		
		task.wait(config.RoundEndTime)
	end
end
2 Likes

Use profile service once you set it up it’s way easier to scale and in general it’s less difficult

5 Likes

I can also suggest this library that I made myself (which is made with non-coders in mind). It is quite easy to set up any sort of save structure you might need with DMOP - Creator Store

Here are the steps:

  1. Put DMOP script in ServerScriptService

  2. Make a folder called DataModel in ServerStorage

  3. Make a folder called leaderstats in DataModel

  4. Put BaseValue objects in leaderstats, such as Kills as a NumberValue

That’s it! The leaderstats will persist with DMOP.

Do take note that the version of DMOP I just provided does not re-attempt to load/save player data if that fails. You do have the freedom to call DataMemory.Save() and DataMemory.Load() yourself though.

DMOP makes the directories automatically when the player joins, so you also do not need to make the leaderstats folder yourself anymore.

2 Likes

IDk how this solved the issue of saving the data tbh…
@Gear_Dev did it actually solve your problem? From your code, I can tell you’re a beginner, so I’m not sure if learning how to use a new data saving module actually helped you

“Give a man a script and you feed him for a day. Teach a man to use one of the best modules created and you feed him for a lifetime.”

if you don’t realize what the original quote is then the joke makes no sense so I hope you do

I’m not a beginner, I been doing studio for 7 years, just never got into the flow of coding. However, I understand it quite a bit just have trouble with where to put it and etc.

I would recommend structuring your code like this:

  1. Services
  2. Variables
  3. Functions
  4. Logic

The fourth section would be like connecting functions to events, and many more. This would make your code easier to read, and it would also look cleaner

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.