How to make a category/tab system

So for context I’m making a game that has cosmetics. All the cosmetics have info like name, imageid, cosmetic type, etc. Anyways these are all stored in a massive module script in replicated storage which has a dictionary storing the table of info for each item. I’ll show an example below

[“Fire Sword”] = {
Name = “Fire Sword”;
CategoryType = “Sword”;
ImageId = 12345678;
Price = 1234;
};
more tables would be listed below

So basically for my shop System I was going to insert a script into each tab. That script would use a in pairs loop to loop through the script and search for anything with the “Sword” category type then read the table info for each cosmetic with the sword type and then put that info into each slot in the shop. I was going to do something similar for the inventory when players load in. It’ll loop through their inventory and load everything into a specific tab based off category name.

I have 2 problems. 1 being ALL of my cosmetics are stored in a single module script. This specific shop I’m talking about doesn’t need to load all of these since some are gamepass only or cosmetics for the weekly item shop. How can I make it so it only loads specific cosmetics for this shop? Second problem being how would I make this category system? I need a bit of help with execution.

I would add an extra variable to each cosmetic, something like purchaseType, and check that in the for loop.

Here is a straightforward functional programming example. You can just drop it into your script and it will work because the functions are pure.
This is merely a crude illustration. As you mentioned, you desire a search function, a sorting function, and a way to just display particular objects.

This is the list that will be sorted:

local list = {
	["Sword"] = {
		["category"] = "melee",
		["damage"] = 10,
		["inclusionId"] = 1 -- extra property
	},
	["Premium blade"] = {
		["category"] = "melee",
		["damage"] = 10,
		["inclusionId"] = 2
	},
	["Bow"] = {
		["category"] = "range",
		["damage"] = 1,
		["inclusionId"] = 1
	},
	["Knife"] = {
		["category"] = "melee",
		["damage"] = 4,
		["inclusionId"] = 1
	}
}

We will print our sorted list first.

-- Heres a list we want to sort and filter
local list = {
	["Sword"] = {
		["category"] = "melee",
		["damage"] = 10,
		["inclusionId"] = 1 -- extra property
	},
	["Premium blade"] = {
		["category"] = "melee",
		["damage"] = 10,
		["inclusionId"] = 2
	},
	["Bow"] = {
		["category"] = "range",
		["damage"] = 1,
		["inclusionId"] = 1
	},
	["Knife"] = {
		["category"] = "melee",
		["damage"] = 4,
		["inclusionId"] = 1
	}
}

-- We want to filter the list, lets add a extra property called "inclusionId"
-- This filter is going to check if this inclusionId id matches
-- If you want to add a new list of items then create a new unique id
function Include<T>(items: {T}, permission: (value: T) -> boolean): {}
	local includedList = {}

	for i, item in pairs(items) do
		if permission(item) then
			includedList[i] = item
		end

		continue
	end

	return includedList
end

-- We want to sort our list
function Sort<T>(items: {T}, selecting: (value: T) -> string): {}
	local sortedList = {}
	
	for i, item in items do
		local result = selecting(item)
		
		if not sortedList[result] then
			sortedList[result] = {}
		end
		
		sortedList[result][i] = item
		
		continue
	end
	
	return sortedList
end

function Filter<T>(items: {T}, filter: (value: T) -> string)
	local filteredList = {}
	
	for i, item in items do
		if filter(i) then
			filteredList[i] = item
		end
	end
	
	return filteredList
end

-- Now we want to use our pure functions

-- We test if the id's match
local included = Include(list, function(item)
	return item.inclusionId == 1
end)

-- Now we filter the list with a search query
-- If none is given then it will return the full list
-- Remember its not case sensetive

local foo = "" -- This is your data from an input

local filtered = Filter(included, function(item)
	return item:lower():match(foo:lower())
end)

-- Now sort the list and done!
local sorted = Sort(filtered, function(item)
	return item.category
end)

-- Do something
print(sorted)

Here’s the outcome.

image

We’ll introduce a premium user interface next. It’s… stunning. Just kidding, I believe I rushed it.
Anyway, here is the local script’s content and structure.

image

local list = {
	["Sword"] = {
		["category"] = "melee",
		["damage"] = 10,
		["price"] = 100,
		["inclusionId"] = 1
	},
	["Premium blade"] = {
		["category"] = "melee",
		["damage"] = 10,
		["price"] = 1000,
		["inclusionId"] = 2
	},
	["Bow"] = {
		["category"] = "range",
		["damage"] = 1,
		["price"] = 100,
		["inclusionId"] = 1
	},
	["Knife"] = {
		["category"] = "melee",
		["damage"] = 4,
		["price"] = 10,
		["inclusionId"] = 1
	}
}

function Include<T>(items: {T}, permission: (value: T) -> boolean): {}
	local includedList = {}

	for i, item in pairs(items) do
		if permission(item) then
			includedList[i] = item
		end

		continue
	end

	return includedList
end

function Sort<T>(items: {T}, selecting: (value: T) -> string): {}
	local sortedList = {}

	for i, item in items do
		local result = selecting(item)

		if not sortedList[result] then
			sortedList[result] = {}
		end

		sortedList[result][i] = item

		continue
	end

	return sortedList
end

function Filter<T>(items: {T}, filter: (value: T) -> string)
	local filteredList = {}

	for i, item in items do
		if filter(i) then
			filteredList[i] = item
		end
	end

	return filteredList
end

-- Heres the new stuff

local QueryBox = script.Parent.TextBox
local Content = script.Parent.Frame

local Preset = game:GetService("ReplicatedStorage").Preset

function Update()
	local included = Include(list, function(item)
		return item.inclusionId == 1
	end)

	local filtered = Filter(included, function(item)
		return item:lower():match(QueryBox.Text:lower())
	end)

	local sorted = Sort(filtered, function(item)
		return item.category
	end)
	
	for i, v in pairs(Content:GetChildren()) do
		
		if v:IsA("Frame") then
			
			v:Destroy()
			
		end
		
	end
	
	for i, category in sorted do

		for j, item in category do
			
			local Copy = Preset:Clone()
			
			Copy.Title.Text = j
			Copy.Type.Text = i
			Copy.Price.Text = item.price
			Copy.Parent = Content

		end

	end
end

Update() -- We need one update before we start

QueryBox:GetPropertyChangedSignal("Text"):Connect(Update)

There you have it. You can handle things from here, I’m sure. You can ask me questions if you have any.

3 Likes

This looks awesome! Definitely gonna implement this

1 Like

You seem to be getting started. Strongly advised are Suphi and Sleitnick. Suphi offers helpful tutorials, while Sleitnick has a vast library of material to master. Here are more details on functional programming.

Functional programming:

Suphi:

Sleitnick:

Wishing you success on your development journey!

1 Like

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