Need help converting some scripts to globals

Godot Version

4.6.1

Question

Hi. I am attempting to convert my inventory to global scenes. I added them and since then my game is bricked and will not run from errors.

Error 1

insert: Invalid access to property or key ‘inventorySlot’ on a base object of type ‘Nil’.

Error 2
slot_gui.gd:16 @ insert(): Required object “rp_child” is null.

code

extends Button
#from makertech vid #2

@onready var SlotBackground: Sprite2D = $"slot background"
@onready var container: CenterContainer = $CenterContainer

var inventorySlot: InventorySlot
@onready var inventory := preload("res://resource items/chest_inventory_1.tres")

var itemStackGui: = StackGui
var index: int

#adds itemStackGui to the container
func insert(isg: ItemStackGui) -> void:
	itemStackGui = isg
	container.add_child(itemStackGui)
	
	#need to fix bug here when moving item to a spot not in the array 
	#because the spots are not yet unlocked
	if !itemStackGui.inventorySlot || inventory.slots[index] == itemStackGui.inventorySlot:
		return
		
	inventory.insert_slot(index, itemStackGui.inventorySlot)

#vid 2 click and move from inventory maker tech
#removes itemStackGui from the scene
func take_item():
	var item := itemStackGui
	
	inventory.remove_slot(itemStackGui.inventorySlot)
	
	container.remove_child(itemStackGui)
	itemStackGui = null
	
	return item
	
func is_empty():
	return !itemStackGui

other global script called by slots script
extends Panel

class_name  ItemStackGui

@onready var InventoryItemSprite: Sprite2D = $"inventory item"
@onready var AmountLabel: Label = $Label

var inventorySlot: InventorySlot

#adds item texture to inventory and amount label
func update() -> void:
	if !inventorySlot || !inventorySlot.item: return
	InventoryItemSprite.visible = true
	InventoryItemSprite.texture = inventorySlot.item.item_texture
	if inventorySlot.amount > 1:
		AmountLabel.visible = true
		AmountLabel.text = str(inventorySlot.amount)
	else:
		AmountLabel.visible = false

extends Control
#maker tech #1
class_name InventoryGUI

signal opened
signal closed

var isOpen: bool = false

#preloads player inventory array resource
@onready var inventory: Inventory = preload("res://resource items/player_inventory.tres")
@onready var slots: Array = $"Inventory Image/MarginContainer/GridContainer".get_children()
var ItemStackGuiClass := StackGui
#preload("res://scenes/inventory/item_stack_gui.tscn")

var itemInHand: ItemStackGui
#from makertech vid #2  calls the updated signal in inventory script
func _ready() -> void:
	connect_slots()
	inventory.updated.connect(update)
	update()

#connects the slot to the signal maybe
func connect_slots() -> void:
	for i in range(slots.size()):
		var slot = slots[i]
		slot.index = i
		
		var callable := Callable(on_slot_clicked)
		callable = callable.bind(slot)
		slot.pressed.connect(callable)

#update the slots size checks the number in the array
func update() -> void:
	for i in range(min(inventory.slots.size(), slots.size())):
		var inventorySlot: InventorySlot = inventory.slots[i]
		
		if !inventorySlot.item: continue
		
		var itemStackGui: ItemStackGui = slots[i].StackGui
		if !itemStackGui:
			itemStackGui = ItemStackGuiClass.instantiate()
			slots[i].insert(itemStackGui)
			
		itemStackGui.inventorySlot = inventorySlot
		itemStackGui.update()

func open() -> void:
	visible = true
	isOpen = true
	opened.emit()
	
func close() -> void:
	visible = false
	isOpen = false
	closed.emit()
	
#functionality for moving items in inventory
#inserts the item into the new slot if empty also calls the stack items if its the same item name
func on_slot_clicked(slot) -> void:
	if slot.is_empty():
		if !itemInHand: return
		
		insert_item_in_slot(slot)
		return
		
	if !itemInHand:
		take_item_from_slot(slot)
		return
		
	if slot.itemStackGui.inventorySlot.item.item_name == itemInHand.inventorySlot.item.item_name:
		stack_items(slot)
		return
		
	swap_items(slot)
		
#picks up item into itemInHand
func take_item_from_slot(slot) -> void:
	itemInHand = slot.take_item()
	add_child(itemInHand)
	update_item_in_hand()
	
#removes item from itemInHand
func insert_item_in_slot(slot) -> void:
	var item = itemInHand
	
	remove_child(itemInHand)
	itemInHand = null
	
	slot.insert(item)

#swaps the items in the slot to the in hand
func swap_items(slot) -> void:
	var tempItem = slot.take_item()
	
	insert_item_in_slot(slot)
	
	itemInHand = tempItem
	add_child(itemInHand)
	update_item_in_hand()
	
#stacks items when moved taking into account the max allowed per stack
func stack_items(slot) -> void:
	var slotItem: ItemStackGui = slot.itemStackGui
	var maxAmount = slotItem.inventorySlot.item.max_amount_stack
	var totalAmount = slotItem.inventorySlot.amount + itemInHand.inventorySlot.amount
	
	if slotItem.inventorySlot.amount == maxAmount:
		swap_items(slot)
		return
		
	#when the total amount is less than max changes the total amount and takes it out of the hand
	if totalAmount <= maxAmount:
		slotItem.inventorySlot.amount = totalAmount
		remove_child(itemInHand)
		itemInHand = null
	else:
		#takes the leftover after max amount reached and adds it to hand
		slotItem.inventorySlot.amount = maxAmount
		itemInHand.inventorySlot.amount = totalAmount - maxAmount
		
	slotItem.update()
	if itemInHand: itemInHand.update()
	
#when item is in hand it moves with the mouse
func update_item_in_hand() -> void:
	if !itemInHand: return
	itemInHand.global_position = get_global_mouse_position() - itemInHand.size / 2
	
func _input(event: InputEvent) -> void:
	update_item_in_hand()
			

Who and when calls insert() and with what argument?

Put a debugger breakpoint in there and inspect the value of isg. If it’s null, look at the call stack and backtrack where the call came from and why it passed an uninitialized reference as the argument.

func update() → void:
for i in range(min(inventory.slots.size(), slots.size())):
var inventorySlot: InventorySlot = inventory.slots[i]

	if !inventorySlot.item: continue
	
	var itemStackGui: ItemStackGui = slots[i].itemStackGui
	if !itemStackGui:
		#itemStackGui = ItemStackGuiClass.instantiate()
		slots[i].insert(itemStackGui)
		
	itemStackGui.inventorySlot = inventorySlot
	itemStackGui.update()

this is from the main inventory gui which is also now a global

it is null

W

Determine why it is null. Perhaps because the caller is only calling update if itemStackGui is null. So no-brainer it will be null

I am calling it here at the top of the script.

var itemStackGui: = StackGui

StackGui is a global

It is a global no reason for it to be null

You’re literally doing:

if !itemStackGui:
		slots[i].insert(itemStackGui)

Which says if itemStackGui is null - pass that null to insert()

ugh its because it wont let me call instantiate now. I # it out

Invalid access to property or key ‘StackGui’ on a base object of type ‘Button (slot_gui.gd)’.

It wont let me call the other global script.

func update() → void:
for i in range(min(inventory.slots.size(), slots.size())):
var inventorySlot: InventorySlot = inventory.slots[i]

	if !inventorySlot.item: continue
	
	var itemStackGui: ItemStackGui = slots[i].StackGui
	if !itemStackGui:
		itemStackGui = ItemStackGuiClass.instantiate()
		slots[i].insert(itemStackGui)
		
	itemStackGui.inventorySlot = inventorySlot
	itemStackGui.update()

the var is unuseable

Print statements and breakpoints are your best friends when debugging. Use them to determine where your program is going, what it’s doing and what are the values of important variables.

Is ItemStackGuiClass a packed scene? If not then you can’t call instantiate() on it.

its a global

I want to know how to add it without the instantiate then

is this script not able to be a global? if so i wasted more than 4 weeks doing this and need to scrap the entire project

I updated the post to include all the relevant script.

all i need to know is how to convert the script to a global. I cant find any rules on what can be in a global and how to convert a script

var itemStackGui: ItemStackGui = slots[i].ItemStackGui