Help with a 'Find The ...' game datastore

so basically, my datastore script basically saves when you find one of the characters. no issues with that. I just need help scripting the script so that it keeps track of which ones you find (so i can make an error message saying “you already have this one!”

heres my datastore script:

local dss = game:GetService("DataStoreService")
local amountCollected = dss:GetDataStore("collected")

game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder",player)
	leaderstats.Name = "leaderstats"
	
	local collected = Instance.new("IntValue",leaderstats)
	collected.Name = "Collected"
	collected.Value = 0
	
	local playerUserId = "player_"..player.UserId
	
	local amountCollectedData
	local success, errormessage = pcall(function()
		amountCollectedData = amountCollected:GetAsync(playerUserId)
	end)
	
	if success then
		collected.Value = amountCollectedData
	end
	
	game.Players.PlayerRemoving:Connect(function(player)
		local playerUserId = "player_"..player.UserId
		local collectedValue = player.leaderstats.Collected.Value
		
		local success, errormessage = pcall(function()
			amountCollected:SetAsync(playerUserId, collectedValue)
		end)
	end)
end)

and heres my collection script:

local WhatFound = "Sand Goober"

script.Parent.MouseClick:Connect(function(plr) 
	print("clicked!")
	plr.Character:MoveTo(game.Workspace.SandGoober.Torso.Position + Vector3.new(0, 2, 0))
	local Anim = plr.Character:WaitForChild("Humanoid"):LoadAnimation(script.Animation)
	Anim:Play()
	plr.Character:WaitForChild("Humanoid").WalkSpeed = 0
	plr.Character:WaitForChild("Humanoid").JumpPower = 0
	wait(1)
	local leaderstats = plr.leaderstats
	leaderstats.Collected.Value += 1
	game.ReplicatedStorage.Find:FireClient(plr, WhatFound)
	plr.Character:WaitForChild("Humanoid").WalkSpeed = 16
	plr.Character:WaitForChild("Humanoid").JumpPower = 50.145
	print("hi")
	game.ReplicatedStorage.Fail:FireClient(plr)
end)

Hey,
just create a table inside the PlayerAdded event which you insert the characters name in whenever one was found and checking if the characters name is inside the table to be able to tell whether a player has it already.
The functions you will need are:
table.insert() and table.find()

just a question, do tables carry through scripts? I just havent done enough scripting with them to know.

A table saved in a variable like:

local table = {["PlayerName"] = {"FoundCharacter";"FoundCharacter2"};}

and put on the beginning of a script, not inside any events will be able to be accessed troughout the entire script.

do i keep {“FoundCharacter”;“FoundCharacter2”}; as is or do i replace them with something? im pretty sure you replace them with something, just i dont know what.
also, not sure if you replace [“PlayerName”] with something too.

local characterTable = {}
local characterfoundevent = game:GetService("ReplicatedStorage"):WaitForChild("Event") -- Event which fires once a character has been found

characterfoundevent:Connect(function(plr, foundcharacterName)
if characterTable[plr.UserId] == nil then
 characterTable[plr.UserId] = {}
end
table.insert(characterTable[plr.UserId], foundcharacterName) 
end)

PlayerName is replaced to the name of the player and charactername to the name of the character that they found.

You can make a folder in the player with string values containing the names of every collected character

local dss = game:GetService("DataStoreService")
local collectedData = dss:GetDataStore("collected")

game.Players.PlayerAdded:Connect(function(player)
   local leaderstats = Instance.new("Folder")
   leaderstats.Name = "leaderstats"
   leaderstats.Parent = player

   local collectedFolder = Instance.new("Folder")
   collectedFolder.Name = "Collected"
   collectedFolder.Parent = player
	
   local collected = Instance.new("IntValue")
   collected.Name = "Collected"
   collected.Value = 0
   collected.Parent = leaderstats
	
   local playerUserId = "Player_"..player.UserId
	
   local data
   local success, errormessage = pcall(function()
	   data = collectedData:GetAsync(playerUserId)
   end)
	
   if success then
   	  collected.Value = data.amount
      for _, v in data.collectedCharacters do
         local str = Instance.new("StringValue")
         str.Name = v.Value
         str.Value = v.Value
         str.Parent = collectedFolder
      end
   end
end)
	
game.Players.PlayerRemoving:Connect(function(player)
   local playerUserId = "Player_"..player.UserId
   local collectedValue = player.leaderstats.Collected.Value
   local collectedValues = player.Collected:GetChildren()

	  local success, errormessage = pcall(function()
		 collectedData:SetAsync(playerUserId, {amount = collectedValue, collectedCharacters = collectedValues}
  	  end)
   end)
end)

when collecting a new character, just make a new string value with name and value set to the character name

so i tried that, and added an extra part to make the character add to the collected list. All i need is it to save (the save part doesnt work for the collected characters). heres the script now.

local dss = game:GetService("DataStoreService")
local collectedData = dss:GetDataStore("collected")

game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local collectedFolder = Instance.new("Folder")
	collectedFolder.Name = "Collected"
	collectedFolder.Parent = player

	local collected = Instance.new("IntValue")
	collected.Name = "Collected"
	collected.Value = 0
	collected.Parent = leaderstats

	local playerUserId = "Player_"..player.UserId

	local data
	local success, errormessage = pcall(function()
		data = collectedData:GetAsync(playerUserId)
	end)

	if success then
		collected.Value = data.amount
		for _, v in data.collectedCharacters do
			local str = Instance.new("StringValue")
			str.Name = v.Value
			str.Value = v.Value
			str.Parent = collectedFolder
		end
	end
	
	game.ReplicatedStorage.SaveGoober.OnServerEvent:Connect(function(plr, WhatFoundSave)
		local str = Instance.new("StringValue")
		str.Name = "Goober"
		str.Value = WhatFoundSave
		str.Parent = collectedFolder
	end)
end)

game.Players.PlayerRemoving:Connect(function(player)
	local playerUserId = "Player_"..player.UserId
	local collectedValue = player.leaderstats.Collected.Value
	local collectedValues = player.Collected:GetChildren()

	local success, errormessage = pcall(function()
		collectedData:SetAsync(playerUserId, {amount = collectedValue, collectedCharacters = collectedValues})
	end)
end)

my bad, forgot you cant save tables/arrays

local dss = game:GetService("DataStoreService")
local httpservice = game:GetService("HttpService")
local collectedData = dss:GetDataStore("collected")

game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local collectedFolder = Instance.new("Folder")
	collectedFolder.Name = "Collected"
	collectedFolder.Parent = player

	local collected = Instance.new("IntValue")
	collected.Name = "Collected"
	collected.Value = 0
	collected.Parent = leaderstats

	local playerUserId = "Player_"..player.UserId

	local data
	local success, errormessage = pcall(function()
		data = collectedData:GetAsync(playerUserId)
	end)

	if success then
		collected.Value = data.amount
        local savedCharacters = httpservice:JSONDecode(data.collectedCharacters)
		for _, v in savedCharacters do
			local str = Instance.new("StringValue")
			str.Name = v.Value
			str.Value = v.Value
			str.Parent = collectedFolder
		end
	end
	
	game.ReplicatedStorage.SaveGoober.OnServerEvent:Connect(function(plr, WhatFoundSave)
		local str = Instance.new("StringValue")
		str.Name = "Goober"
		str.Value = WhatFoundSave
		str.Parent = collectedFolder
	end)
end)

game.Players.PlayerRemoving:Connect(function(player)
	local playerUserId = "Player_"..player.UserId
	local collectedValue = player.leaderstats.Collected.Value
	local collectedValues = httpservice:JSONEncode(player.Collected:GetChildren())

	local success, errormessage = pcall(function()
		collectedData:SetAsync(playerUserId, {amount = collectedValue, collectedCharacters = collectedValues})
	end)
end)

also, for adding new characters to the folder:
add a remote event in repstorage named “AddCharacter”

local dss = game:GetService("DataStoreService")
local httpservice = game:GetService("HttpService")
local collectedData = dss:GetDataStore("collected")

game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local collectedFolder = Instance.new("Folder")
	collectedFolder.Name = "Collected"
	collectedFolder.Parent = player

	local collected = Instance.new("IntValue")
	collected.Name = "Collected"
	collected.Value = 0
	collected.Parent = leaderstats

	local playerUserId = "Player_"..player.UserId

	local data
	local success, errormessage = pcall(function()
		data = collectedData:GetAsync(playerUserId)
	end)

	if success then
		collected.Value = data.amount
        local savedCharacters = httpservice:JSONDecode(data.collectedCharacters)
		for _, v in savedCharacters do
			local str = Instance.new("StringValue")
			str.Name = v.Value
			str.Value = v.Value
			str.Parent = collectedFolder
		end
	end
end)


game.Players.PlayerRemoving:Connect(function(player)
	local playerUserId = "Player_"..player.UserId
	local collectedValue = player.leaderstats.Collected.Value
	local collectedValues = httpservice:JSONEncode(player.Collected:GetChildren())

	local success, errormessage = pcall(function()
		collectedData:SetAsync(playerUserId, {amount = collectedValue, collectedCharacters = collectedValues})
	end)
end)

game:BindToClose(function()
    task.wait(5)
end)

game:GetService("ReplicatedStorage"):WaitForChild("AddCharacter").OnServerEvent:Connect(function(player, character)
    local str = Instance.new("StringValue")
    str.Name = character
    str.Value = character
    str.Parent = player.Collected
end)

if you wanted to add a character from server do this (example for touching, adjust if not a touching script):

script.Parent.ClickDetector.MouseClick:Connect(function(player)
    if player.Collected:FindFirstChild(script.Parent.Name) then return end
    local str = Instance.new("StringValue")
    str.Name = script.Parent.Name
    str.Value = script.Parent.Name
    str.Parent = player.Collected
end)

adding a character from client:

game:GetService("TextChatService").OnIncomingMessage = function(message)
   if message.Text:lower() == "/e free character" and not message.TextSource.Collected:FindFirstChild("Free Goober") then
      game:GetService("ReplicatedStorage"):FindFirstChild("AddCharacter", true):FireServer("Free Goober")
   end
   return
end

still doesnt seem to save… other than that it still works. Not sure if it just doesnt save because im in studio but it saves the leaderstats.

after reading jsonencode docs i realised the problem

local dss = game:GetService("DataStoreService")
local httpservice = game:GetService("HttpService")
local collectedData = dss:GetDataStore("collected")

game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local collectedFolder = Instance.new("Folder")
	collectedFolder.Name = "Collected"
	collectedFolder.Parent = player

	local collected = Instance.new("IntValue")
	collected.Name = "Collected"
	collected.Value = 0
	collected.Parent = leaderstats

	local playerUserId = "Player_"..player.UserId

	local data
	local success, errormessage = pcall(function()
		data = collectedData:GetAsync(playerUserId)
	end)

	if success then
		collected.Value = data.amount
        local savedCharacters = httpservice:JSONDecode(data.collectedCharacters)
		for _, v in savedCharacters do
			local str = Instance.new("StringValue")
			str.Name = v
			str.Value = v
			str.Parent = collectedFolder
		end
	end
end)


game.Players.PlayerRemoving:Connect(function(player)
	local playerUserId = "Player_"..player.UserId
	local collectedValue = player.leaderstats.Collected.Value
    local newtable = {}
    for _, v in player.Collected:GetChildren()
       table.insert(newtable, v.Value)
    end
	local collectedValues = httpservice:JSONEncode(newtable)

	local success, errormessage = pcall(function()
		collectedData:SetAsync(playerUserId, {amount = collectedValue, collectedCharacters = collectedValues})
	end)
end)

game:BindToClose(function()
    task.wait(5)
end)

game:GetService("ReplicatedStorage"):WaitForChild("AddCharacter").OnServerEvent:Connect(function(player, character)
    local str = Instance.new("StringValue")
    str.Name = character
    str.Value = character
    str.Parent = player.Collected
end)

Thanks! it works now!

characterlimit

1 Like

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