How do i check multiple bool attribute is true in a 'if statement'

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
1 Like

You said they are attributes so use SetAttribute to set them and GetAttribute to reference them

Use GetAttributeChangedSignal

Rawr char rawr

1 Like

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)

This works very well! Thank you very much.