Hello Roblox community, I’m kinda new to the dev forums. I am currently making a badge hunting game on Roblox and I made an amount system where if you collected many ‘badges’, It will tell the amount on how many ‘badges’ you have. It also set the bool attribute to true on each of them. Although when I tested, the script didn’t work. However, there are no errors in the script. How do I fix this?
ServerScript
game.Players.PlayerAdded:Connect(function(player)
local ReplicatedStorage = game:GetService('ReplicatedStorage')
ReplicatedStorage.OwnedEvent:FireClient(player)
end)
LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local player = game.Players.LocalPlayer
local data = player:FindFirstChild("Data")
local bool = data:IsA("BoolValue")
local owned = script.Parent.ScrollingFrame.Script.Owned
local total = script.Parent.ScrollingFrame.Script.Total
local amount = script.Parent.Amount
owned:GetPropertyChangedSignal("Value"):Connect(function()
amount.Text = tostring(owned.Value).."/"..tostring(total.Value)
end)
ReplicatedStorage.OwnedEvent.OnClientEvent:Connect(function()
if bool.Value == true then
owned.Value = owned.Value +1
end
amount.Text = tostring(owned.Value).."/"..tostring(total.Value)
end)
well in line 3 and 4
you set data to be an instance in the player object
and set bool to data:IsA(“BoolValue”)
IsA returns true or false not an instance
so if data is already a boolvalue just do data.Value
if it isnt find the boolvalue in its children
if you made it an attribute then run :GetAttritube(nameOfAttritube)
Depending on where the local script is the connection ReplicatedStorage.OwnedEvent.OnClientEvent won’t be made before the server fires it. If the local script is in anything other than StarterPlayerScripts (and it might even fail there) the order of events is as follows.
Player connects → The server fires and event hoping the player catches it → the player is still setting up and has not run any scripts, thus the event is ignored → nothing happens.
Generally there is no reason to fire an event to the player that is joining, you can just place your script in StarterPlayerScripts and it will run as they join.
After fixing this event issue you will run into a couple of type issues.
local bool = data:IsA("BoolValue") -- bool == false
-- is probably supposed to be
local bool = data:FindFirstChildOfClass("BoolValue") -- bool == BoolValue object
I would need to understand what the other systems you have are but here is an easy way to transform a list of booleans into a total. It seems like you already have a owned and total variable but I do not see a list of collected things.
-- example data
local collected_items = {
collectable_red = true,
collectable_green = false,
collectable_blue = false,
collectable_beachball = true,
}
local function get_collected(): number
local total = 0
for _, value in pairs(collected_items) do
if value then
total += 1
end
end
return total
end
Basically how the collected things work is that each and every ObjectValue in Workspace will clone to the LocalPlayer data folder and will save it to the data service. Then It will count the amount of how many of the bool values that is ‘true’. I’m bad at explaining but I hope this summarize it.
Here’s a script for the data
local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("CollectedData")
local function onPlayerJoin(player) -- Runs when players join
local foundfolder = Instance.new("Folder") --Sets up leaderstats folder
foundfolder.Name = "Data"
foundfolder.Parent = player
for i,v in pairs(workspace.BloxikinSaves:GetChildren()) do
if v:IsA("ObjectValue") then
local Found = game.ReplicatedStorage.Found:Clone()
Found.Name = v.Name
Found.Parent = foundfolder
end
end
local playerUserId = "Player_" .. player.UserId --Gets player ID
local data = playerData:GetAsync(playerUserId) --Checks if player has stored data
if data then
for _,collected in pairs(player.Data:GetChildren()) do
if collected:IsA("BoolValue") then
local name = collected.Name
collected.Value = data[name]
end
end
end
end
local function create_table(player)
local player_stats = {}
for _, stat in pairs(player.Data:GetChildren()) do
player_stats[stat.Name] = stat.Value
end
return player_stats
end
local function onPlayerExit(player) --Runs when players exit
local player_stats = create_table(player)
local success, err = pcall(function()
local playerUserId = "Player_" .. player.UserId
playerData:SetAsync(playerUserId, player_stats) --Saves player data
end)
if not success then
warn('Could not save data!')
end
end
game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)
Maybe you could use this then. I adapted by example to use BoolValues and your player.Data structure.
local function get_player_total(player: Player): number
local total: number = 0
for _, stat in ipairs(player.Data:GetChildren()) do
if stat.Value then -- BoolValue
total += 1
end
end
return total
end
owned.Value = get_player_total(game.Players.LocalPlayer)