Need help with inventory system

Hey y’all, so I’ve been working on an inventory system for the past few days and have ran into an issue that I don’t know how to fix. For some context, my inventory system has different categories named “Pockets” to better sort and organize the player’s items. The intended behavior is that items from one category, let’s say Medicine for example, are only visible in the Medicine pocket and not the Discs pocket. But as my script currently works, the items continue persist and appear in other pockets instead of disappearing. So now potions end up appearing in the discs pocket, and vice versa. Any help figuring out a solution to this problem will be greatly appreciated!

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local player = game.Players.LocalPlayer
local PlayerGui = player.PlayerGui

local globalVariables = require(ReplicatedStorage.Modules.globalVariables)
local movesData = require(ReplicatedStorage.Modules.Data.BattleData.movesData)
local experienceData = require(ReplicatedStorage.Modules.Data.BattleData.experienceData)
local personalitiesData = require(ReplicatedStorage.Modules.Data.BattleData.personalitiesData)
local itemsData = require(ReplicatedStorage.Modules.Data.itemsData)
local mathModule = require(ReplicatedStorage.Modules.Services.MathService.mathModule)
local gatchipediaModule = require(ReplicatedStorage.Modules.Services.GatchipediaService.gatchipediaModule)
local battleModule = require(ReplicatedStorage.Modules.Services.BattleService.battleModule)

local buttonActions = require(game.StarterPlayer.StarterCharacterScripts.Character.buttonActions)

local getInventoryFunction = ReplicatedStorage.remoteFunctions.getInventory
local playerItems = getInventoryFunction:InvokeServer()

local GUI = PlayerGui.Main.GUI
local Bag = GUI.Bag
local InventoryScroll = GUI.Bag.InventoryScroll
local ItemSlot = PlayerGui.Templates.ItemSlot

--scroll text function here

function hash(num)
	return (num + 4) * 8
end

function dehash(num)
	return (num - 32) / 8
end

function HPCalculation(level, up, tp, gatchi)
	return(up + 2 * globalVariables.Gatchimon[gatchi].Stats.HP + tp / 4) * 100 + 10 + level
end

function otherStatCalculation(basestat, level, up, tp, personality, gatchi)
	return((up + 2 * globalVariables.Gatchimon[gatchi].Stats[basestat] + tp / 4) * level / 100 + 5) * personality
end

local stats = { "HP", "STA", "ATK", "DEF", "MA", "SPD" }
function determinePersonality(stat, personality)
	if personalitiesData[stat .. "Up"][personality] then
		return 1.1
	elseif personalitiesData[stat .. "Down"][personality] then
		return 0.9
	else
		return 1
	end
end

--Initalize the inventory
local currentPocket = "Medicine"

local function loadItems()
	for itemName, itemData in pairs (itemsData) do
		local newItem = ItemSlot:Clone()
		if itemData.Class == "Medicine" and currentPocket == "Medicine" then
			newItem.Visible = false
			newItem.Parent = InventoryScroll
			newItem.NameButton.Text = itemData.DisplayName
			newItem.ItemIcon.Image = itemData.Image
			newItem:AddTag(itemData.Class)
			newItem.ItemIcon:AddTag(itemData.Class)
			buttonActions.invItem(newItem.NameButton)
		elseif itemData.Class == "Item" and currentPocket == "Items" then
			newItem.Visible = false
			newItem.Parent = InventoryScroll
			newItem.NameButton.Text = itemData.DisplayName
			newItem.ItemIcon.Image = itemData.Image
			newItem:AddTag(itemData.Class)
			newItem.ItemIcon:AddTag(itemData.Class)
			buttonActions.invItem(newItem.NameButton)
		elseif itemData.Class == "CaptureDisc" and currentPocket == "Discs" then
			newItem.Visible = false
			newItem.Parent = InventoryScroll
			newItem.NameButton.Text = itemData.DisplayName
			newItem.ItemIcon.Image = itemData.Image
			newItem:AddTag(itemData.Class)
			newItem.ItemIcon:AddTag(itemData.Class)
			buttonActions.invItem(newItem.NameButton)
		elseif itemData.Class == "MoveManual" and currentPocket == "Move Manuals" then
			newItem.Visible = false
			newItem.Parent = InventoryScroll
			newItem.NameButton.Text = itemData.DisplayName
			newItem.ItemIcon.Image = itemData.Image
			newItem:AddTag(itemData.Class)
			newItem.ItemIcon:AddTag(itemData.Class)
			buttonActions.invItem(newItem.NameButton)
		elseif itemData.Class == "Fruit" and currentPocket == "Fruits" then
			newItem.Visible = false
			newItem.Parent = InventoryScroll
			newItem.NameButton.Text = itemData.DisplayName
			newItem.ItemIcon.Image = itemData.Image
			newItem:AddTag(itemData.Class)
			newItem.ItemIcon:AddTag(itemData.Class)
			buttonActions.invItem(newItem.NameButton)
		elseif itemData.Class == "Key" and currentPocket == "Key Items" then
			newItem.Visible = false
			newItem.Parent = InventoryScroll
			newItem.NameButton.Text = itemData.DisplayName
			newItem.ItemIcon.Image = itemData.Image
			newItem:AddTag(itemData.Class)
			newItem.ItemIcon:AddTag(itemData.Class)
			buttonActions.invItem(newItem.NameButton)
		end
		newItem.Name = itemName
	end
end

--Change pockets
local function changePocket(Pocket: "Medicine" | "Items" | "Discs" | "Move Manuals" | "Fruits" | "Key Items")
	currentPocket = Pocket
	loadItems()
	
	--Load the player's items
	if playerItems ~= nil then
		for itemName, itemData in pairs (playerItems) do
			if itemData.uses > 0 then
				local item = InventoryScroll:FindFirstChild(itemName)
				if not item then continue end
				item.Visible = true
				item.UsesLabel.Text =  "x" .. itemData.uses
			end
		end
	end
end

--Item functions
function Heal(item, gatchimon, Recover)
	if gatchimon.currentHP.Value == gatchimon.Stats.HPStat.Value or gatchimon.Status.Value == "Faint" then
		loadItems()
	else
		mathModule.Change(gatchimon.currentHP, math.min(gatchimon.currentHP.Value + item.Use.Heal, gatchimon.Stats.HPStat.Value))
		mathModule.Check(Recover[item], false)
	end
	loadItems()
end

function FullRestore(item, gatchimon, Recover)
	
end

function CureStatus(item, gatchimon)
	
end

function CuresAll(item, gatchimon)
	
end

function RaiseStat(item, gatchimon)
	
end

function Exp(item, gatchimon)
	
end

function Catch(item, gatchimon)
	local bonusStatus = 1
	if gatchimon.Status.Value == "Paralysis" or gatchimon.Status.Value == "Drowsy" then
		bonusStatus = 2
	else
		if gatchimon.Status.Value == "Burn" or gatchimon.Status.Value == "Frostbite" or gatchimon.Status.Value == "Poison" then
			bonusStatus = 1.5
		end
	end
	mathModule.Check(player.Bag.CaptureDisc[item])
	local HPMax = gatchimon.Stats.HPStat.Value
	local HPCurrent = gatchimon.currentHP.Value
	local rate = 1
	--put other capture discs here
	--end
	local catchRate = math.min(100, math.max(0, math.floor(HPMax * rate * bonusStatus / 3 / HPCurrent)))
	local shakeChecking = 65536 / 255 / catchRate ^ 0.25
	local shakeCheck = nil
	local shakes = 0
	for i = 1, 3 do
		local shakeWeight = math.random(0, 65535)
		if catchRate > 255 or item == "Ultimate Disc" then
			shakes = 3
			shakeCheck = "Success"
			break
		elseif shakeChecking < shakeWeight then
			shakeCheck = "Fail"
			break
		elseif shakes == 3 then
			shakeCheck = "Success"
		else
			shakes = shakes + 1
		end
	end
end

function Evolve(item, gatchimon)
	
end

function RaiseLevel(item, gatchimon)
	--soundEffect here
	if gatchimon.Level.Value < 100 and gatchimon.currentHP.Value > 0 then
		--soundEffect:Play()
		mathModule.Change(gatchimon.Experience, hash(experienceData[gatchimon[gatchimon.Name].GrowthRate .. "EXP"](gatchimon.level.Value)))
		local HPBefore = gatchimon.Stats.HPStat.Value
		for i, v in ipairs(stats) do
			if v == "HP" then
				--mathModule.Change(gatchimon.Stat[???], ???(gatchimon.Level.Value, gatchimon.UP[???].Value, ???, ???))
			else
				--mathModule.Change(gatchimon.Stat[???], ???(gatchimon.Level.Value, gatchimon.UP[???].Value, ???, ???))
			end
		end
		mathModule.Change(gatchimon.currentHP, gatchimon.currentHP.Value + (gatchimon.Stats.HPStat.Value - HPBefore))
		if gatchimon.currentHP.Value == 0 then
			gatchimon.Status.Value = "Faint"
		end
		--check if the gatchimon can evolve
	end
end

--Buttons
local MedicineButton = GUI.Bag.MedicineButton
local ItemsButton = GUI.Bag.ItemsButton
local DiscsButton = GUI.Bag.DiscsButton
local MMsButton = GUI.Bag.MMsButton
local FruitsButton = GUI.Bag.FruitsButton
local KeyButton = GUI.Bag.KeyButton
local CloseButton = GUI.Bag.CloseButton

MedicineButton.Activated:Connect(function()
	changePocket("Medicine")
	print("Changed pocket to Medicine!")
end)

ItemsButton.Activated:Connect(function()
	changePocket("Items")
	print("Changed pocket to Items!")
end)

DiscsButton.Activated:Connect(function()
	changePocket("Discs")
	print("Changed pocket to Discs!")
end)

MMsButton.Activated:Connect(function()
	changePocket("Move Manuals")
	print("Changed pocket to Move Manuals!")
end)

FruitsButton.Activated:Connect(function()
	changePocket("Fruits")
	print("Changed pocket to Fruits!")
end)

KeyButton.Activated:Connect(function()
	changePocket("Key Items")
	print("Changed pocket to Key Items!")
end)```
3 Likes

quick question, are all these classes of items added and removed through 1 scrolling frame? or is it multiple scrolling frames for each respective catagory

1 Like

All of the items are added and removed through one scrolling frame

1 Like

ok so, even though this sounds very nooby of a method, something i suggest is making each catagory have its own scrolling frame, and add the items into their respective scrolling frames for that catagory. Whilst this isnt a fix for the original issue, i feel like this method is easiest to implement

1 Like

Why not use :string in changePocket of argument Pocket instead of this string.

This might be issue ?

(Topic-off)

Also you could like use for getting (index, not important unless your just coding it for something) and getting instances button and connecting a connect to it activated and then changing pocket depending on button (this might require array, basically mention of this instance’s value, could use Gui.Name althought you choice)

1 Like

I wasn’t aware that there could be a difference in using string: over Pocket: in changePocket, I had only coded what made the most sense to me at that time

1 Like

I meant like this Pocket:string

1 Like

Oh my bad for the misunderstanding, I had originally thought having the strings listed out was better for consistency but now I’m seeing how less efficient that is

1 Like

I’d prefer having one scrolling frame then several different ones, to make designing the updating the ui faster on my end. Plus there’s already an issue with the scrolling frame cutting off content after a certain point, and the proposal I’ve received to fix this would make it even more complicated lol

1 Like

Also, the alternative to the buttons you proposed sounds like a better solution then what I implemented, but i’m not entirely sure how to code it despite your explanation. Do you mind elaborating a bit more on it?

1 Like
-- this changes depending on name but you could use dictionaries for pointing a what kind value is supposed to mention
-- i is index (which first thing is always mention)
-- v is any (which depends on types, however different types have different using)

for i,v in Gui:GetChildren() do
if v.Activated then changePocket(v.Name) end
end
1 Like

Ohhh okay, I understand now. Thanks for writing it for me haha

1 Like

I’ve used single scrolling frame and you can just remove frames by settings visibility to false, also it’s good if you have some sort of itemID that you can track items from, and have module with info about what item is in which category, then when you just update gui, you check if item you want to update is currently displayed, and it should work fine

1 Like

Do you have any examples of an effective check for the item categories? I already have a module script with the item info, and in my current code I thought that the checks in loadItems() were accurate, but now I’m having second thoughts. . .

1 Like

In my projects i usually use info sort of module with item ids, e.g:

local ItemsInfo = {
    [1] = {
        Name = "Sword",
        Category = 1
    },
   [2] = {
        Name = "Bow",
        Category = 2
    },
}

And then when you want to check if item is displayed on update you do:

local function onUpdate(ItemID)
    local Info = ItemsInfo[ItemID]
    if not Info then
        return
    end

    if CurrentCategory ~= Info.Category then
        --/ Hide
    else
        --/ Show
    end

end

I tried something similar to the example you gave, but my items weren’t appearing. Does this code look functional or did I misinterpret your given example?

local function loadItems(itemID)
	local newItem = ItemSlot:Clone()
	local itemInfo = itemsData[itemID]
	if not itemInfo then
		return
	end
	for itemName, itemData in pairs(itemsData) do
		if currentPocket ~= itemInfo.Class then
			newItem.Visible = false
			newItem.Parent = InventoryScroll
			newItem.NameButton.Text = itemData.DisplayName
			newItem.ItemIcon.Image = itemData.Image
			newItem:AddTag(itemData.Class)
			newItem.ItemIcon:AddTag(itemData.Class)
			buttonActions.invItem(newItem.NameButton)
		end
		newItem.Name = itemName
	end
end
1 Like

It might be the problem with tonumber, try tonumbering currentPocket, and remember it should be the same as the name you try to check in class