Attempt to index nil with 'Visible'

I’m trying to code a basic inventory system, where the player has different pockets with arrays of their owned items categorized by class, into their respective pockets. But I keep getting this error "attempt to index nil with ‘Visible’ " whenever I try to activate the only working button. This button is what is supposed to turn the item slot visible, as the player owns it. By chance, would anyone be able to help me figure this out? My script will be pasted below, apologies if its a total mess ToT

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 InventoryScroll = GUI.Bag.InventoryScroll
local ItemSlot = PlayerGui.Templates.ItemSlot

local pockets = {
	["Medicine"] = {},
	["Items"] = {},
	["Discs"] = {},
	["Move Manuals"] = {},
	["Fruits"] = {},
	["Key Items"] = {},
}

repeat
	repeat
		wait()
	until globalVariables.itemsReady
until player

scrollText = function(gui, text, thing)
	for i = 1, #text do
		gui.Text = string.sub(text, 1, i)
		wait(0.05)
	end
	if thing == nil then
		wait(0.55)
	end
end

changeVisible = function(thing, isa, bool)
	for i,v in ipairs(thing:GetChildren()) do
		if v:IsA(isa) then
			v.Visible = bool
		end
	end
end

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

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

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

otherStatCalculation = function(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" }
determinePersonality = function(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 _, 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
		--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)
					item.Visible = true
					item.UsesLabel.Text =  "x" .. itemData.uses
				end
			end
		end
	end
end

--Change pockets
local function changePocket(Pocket: "Medicine" | "Items" | "Discs" | "Move Manuals" | "Fruits" | "Key Items")
	if "Medicine" then
		currentPocket = "Medicine"
		loadItems()
	elseif "Items" then
		currentPocket = "Items"
		loadItems()
	elseif "Discs" then
		currentPocket = "Discs"
		loadItems()
	elseif "Move Manuals" then
		currentPocket = "Move Manuals"
		loadItems()
	elseif "Fruits" then
		currentPocket = "Fruits"
		loadItems()
	elseif "Key Items" then
		currentPocket = "Key Items"
		loadItems()
	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)

the hell is this

repeat
	repeat
		wait()
	until globalVariables.itemsReady
until player

theres never a case where LocalPlayer is nil in Playersservice
debug itemName

I wasn’t aware that LocalPlayer never returns nil, thanks for pointing that out!
And when you say to debug itemName, how do you reccomend going about it? I’m still overall new to scripting, apologies

It’s just your Player Instance, if you are connected to the game, the Instance will never be nil

just print it, see what do u get, then in explorer, check if that item or whatever with that name does exist in inventory scroll

I added a print to see if itemName would return as a potion, and it did! But when I went into the explorer, I didn’t see any item under the InventoryScroll, which leads me to believe now that it isn’t cloning as intended. . .

may I see itemsData?, also tip: set Parent properly last, so it renders the instance after every other property has been set

Here’s itemsData right here.

local itemsData = {
	Potion = {
		DisplayName = "Potion",
		Class = "Medicine",
		Description = "A medicinal balm intended for injured Gatchimon. Restores 25 HP to a single Gatchimon.",
		Use = { Heal = 25 },
		Image = "",
		Price = "",
	},
	MegaPotion = {
		DisplayName = "Mega Potion",
		Class = "Medicine",
		Description = "A medicinal balm intended for injured Gatchimon. Restores 50 HP to a single Gatchimon.",
		Use = { Heal = 50 },
		Image = "",
		Price = "",
	},
	GigaPotion = {
		DisplayName = "Giga Potion",
		Class = "Medicine",
		Description = "A medicinal balm intended for injured Gatchimon. Restores 200 HP to a single Gatchimon.",
		Use = { Heal = 200 },
		Image = "",
		Price = "",
	},
	TeraPotion = {
		DisplayName = "Tera Potion",
		Class = "Medicine",
		Description = "A medicinal balm intended for injured Gatchimon. Fully restores the max HP of a single Gatchimon, and cures it of any status condition.",
		Use = { FullRestore },
		Image = "",
		Price = "",
	},
	Antidote = {
		DisplayName = "Antidote",
		Class = "Medicine",
		Description = "A topical medicine which can cure a single Gatchimon of the poison status.",
		Use = { CureStatus = { "Poison" } },
		Image = "",
		Price = "",
	},
	Awakening = {
		DisplayName = "Awakening",
		Class = "Medicine",
		Description = "A topical medicine which can cure a single Gatchimon of the drowsy status.",
		Use = { CureStatus = { "Drowsy" } },
		Image = "",
		Price = "",
	},
	ParalysisHeal = {
		DisplayName = "Paralysis Heal",
		Class = "Medicine",
		Description = "A topical medicine which can cure a single Gatchimon of the paralysis status.",
		Use = { CureStatus = { "Paralysis" } },
		Image = "",
		Price = "",
	},
	BurnHeal = {
		DisplayName = "Burn Heal",
		Class = "Medicine",
		Description = "A topical medicine which can cure a single Gatchimon of the burn status.",
		Use = { CureStatus = { "Burn" } },
		Image = "",
		Price = "",
	},
	FrostbiteHeal = {
		DisplayName = "Frostbite Heal",
		Class = "Medicine",
		Description = "A topical medicine which can cure a single Gatchimon of the frostbite status.",
		Use = { CureStatus = { "Frostbite" } },
		Image = "",
		Price = "",
	},
	Cureall = {
		DisplayName = "Cure-all",
		Class = "Medicine",
		Description = "A topical medicine which can cure a single Gatchimon of any status condition.",
		Use = { Curesall },
		Image = "",
		Price = "",
	},
	HealthCandy = {
		DisplayName = "Health Candy",
		Class = "Medicine",
		Description = "A hard candy which can slightly raise a single Gatchimon's HP stat.",
		Use = { RaiseStat = { "HP" } },
		Image = "",
		Price = "",
	},
	StaminaCandy = {
		DisplayName = "Stamina Candy",
		Class = "Medicine",
		Description = "A hard candy which can slightly raise a single Gatchimon's STA stat.",
		Use = { RaiseStat = { "STA" } },
		Image = "",
		Price = "",
	},
	AttackCandy = {
		DisplayName = "Attack Candy",
		Class = "Medicine",
		Description = "A hard candy which can slightly raise a single Gatchimon's ATK stat.",
		Use = { RaiseStat = { "ATK" } },
		Image = "",
		Price = "",
	},
	DefenseCandy = {
		DisplayName = "Defense Candy",
		Class = "Medicine",
		Description = "A hard candy which can slightly raise a single Gatchimon's DEF stat.",
		Use = { RaiseStat = { "DEF" } },
		Image = "",
		Price = "",
	},
	MagicCandy = {
		DisplayName = "Magic Candy",
		Class = "Medicine",
		Description = "A hard candy which can slightly raise a single Gatchimon's MA stat.",
		Use = { RaiseStat = { "MA" } },
		Image = "",
		Price = "",
	},
	SpeedCandy = {
		DisplayName = "Speed Candy",
		Class = "Medicine",
		Description = "A hard candy which can slightly raise a single Gatchimon's SPD stat.",
		Use = { RaiseStat = { "SPD" } },
		Image = "",
		Price = "",
	},
	EXPCandyS = {
		DisplayName = "EXP Candy S.",
		Class = "Medicine",
		Description = "A small jelly candy which can grant a single Gatchimon some EXP points.",
		Use = { Exp = 800 },
		Image = "",
		Price = "",
	},
	EXPCandyM = {
		DisplayName = "EXP Candy M.",
		Class = "Medicine",
		Description = "A medium jelly candy which can grant a single Gatchimon EXP points.",
		Use = { Exp = 3, 000 },
		Image = "",
		Price = "",
	},
	EXPCandyL = {
		DisplayName = "EXP Candy L.",
		Class = "Medicine",
		Description = "A large jelly candy which can grant as single Gatchimon a lot of EXP points.",
		Use = { Exp = 10, 000 },
		Image = "",
		Price = "",
	},
	Levelup = {
		DisplayName = "Level-Up",
		Class = "Medicine",
		Description = "A candy bar which can grant a single Gatchimon a level up.",
		Use = { RaiseLevel },
		Image = "",
		Price = "",
	},
	CaptureDisc = {
		DisplayName = "Capture Disc",
		Class = "CaptureDisc",
		Description = "An egg shaped device capable of capturing wild Gatchimon.",
		Use = { Catch = 1 },
		Image = "",
		Price = "",
	},
	GreaterDisc = {
		DisplayName = "Greater Disc",
		Class = "CaptureDisc",
		Description = "A slightly improved model of the Capture Disc, with slightly better odds.",
		Use = { Catch = 1.5 },
		Image = "",
		Price = "",
	},
	AdvancedDisc = {
		DisplayName = "Advanced Disc",
		Class = "CaptureDisc",
		Description = "The superior model of the Capture Disc, holding some of the best odds for catching Gatchimon.",
		Use = { Catch = 2 },
		Image = "",
		Price = "",
	},
	UltimateDisc = {
		DisplayName = "Ultimate Disc",
		Class = "CaptureDisc",
		Description = "The perfect Capture Disc model, capable of catching wild Gatchimon without fail.",
		Use = { Catch = 255 },
		Image = "",
		Price = "",
	},
}
return itemsData```

I see the issue, you forgot to set Name property of the newItem
and a practice tip: return if the child doesn’t exist

I just tried setting the name property, but I’m still receiving the same error

local function loadItems()
	for _, itemData in pairs (itemsData) do
		local newItem = ItemSlot:Clone()
		if itemData.Class == "Medicine" and currentPocket == "Medicine" then
			newItem.Visible = false
			newItem.Name = itemData.DisplayName
			newItem.NameButton.Text = itemData.DisplayName
			newItem.ItemIcon.Image = itemData.Image
			newItem:AddTag(itemData.Class)
			newItem.ItemIcon:AddTag(itemData.Class)
			newItem.Parent = InventoryScroll
			buttonActions.invItem(newItem.NameButton)```

use the key of the itemData, not the value maybe? i don’t know how ur player inventory item data is stuctured rn
image


you also forgot to do the conditions correctly, strings are truthy, you meant to do if Pocket == "Medicine"… etc

Thanks for pointing the conditions out! Also I just tried the key of itemData using brackets, but that didn’t work either. . .

local function loadItems()
	for _, itemData in pairs (itemsData) do
		local newItem = ItemSlot:Clone()
		if itemData.Class == "Medicine" and currentPocket == "Medicine" then
			newItem.Visible = false
			newItem.Name = itemData[DisplayName]
			newItem.NameButton.Text = itemData.DisplayName
			newItem.ItemIcon.Image = itemData.Image
			newItem:AddTag(itemData.Class)
			newItem.ItemIcon:AddTag(itemData.Class)
			newItem.Parent = InventoryScroll
			buttonActions.invItem(newItem.NameButton)```

i meant for ItemName, itemData in itemsDat and use ItemName its the key of ur itemData

Like this?

		--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)
					print(itemName)
					item[itemName].Visible = true
					item[itemName].UsesLabel.Text =  "x" .. itemData.uses
				end
			end
		end
	end
end```

noooo… where you are loading the items and cloning, the name needs to be the key of the itemdata

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 InventoryScroll = GUI.Bag.InventoryScroll
local ItemSlot = PlayerGui.Templates.ItemSlot

local pockets = {
	["Medicine"] = {},
	["Items"] = {},
	["Discs"] = {},
	["Move Manuals"] = {},
	["Fruits"] = {},
	["Key Items"] = {},
}

repeat
	repeat
		wait()
	until globalVariables.itemsReady
until player

scrollText = function(gui, text, thing)
	for i = 1, #text do
		gui.Text = string.sub(text, 1, i)
		wait(0.05)
	end
	if thing == nil then
		wait(0.55)
	end
end

changeVisible = function(thing, isa, bool)
	for i,v in ipairs(thing:GetChildren()) do
		if v:IsA(isa) then
			v.Visible = bool
		end
	end
end

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

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

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

otherStatCalculation = function(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" }
determinePersonality = function(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
		--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
end

--Change pockets
local function changePocket(Pocket: "Medicine" | "Items" | "Discs" | "Move Manuals" | "Fruits" | "Key Items")
	currentPocket = Pocket
    loadItems()
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)

try this

Just tried it, and this works! Thanks for helping me through this ^ - ^

1 Like

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