Resource and ID based Item swap functionality returning incorrect values

Godot Version

Godot 4.5 is the version I am on.

Question

Greetings,

I have been working on my item logic as of late, currently I have hit a roadblock at item swap
functionality, the issue is, I have created a grid container with several customized button scenes,
The script is quite simply explained, each button has 4 IDs, in the globals script, called Snes,
it contains 4 variables that are note-able for this operation:

item_index ,

item_index2,

hero_index , and
hero_index2

Inside of the button script, inv_item.gd, there are 3 variables worth noting:
hero_index,
swap_index, and
swap_index2

A basic explanation is,

Each button has an on and off state,

this changes whether or not it can be selected as a command target or otherwise;

If it is on, the proper result of this would be that,
when the Transfer command is selected,
it should swap the menu_level to value 6,
which in turn should allow another selection;

if a button is clicked in menu level 6,
it will take the originally set id from the first select action made,

take it’s own ID, and runs those as well as the current hero item list and the previous hero item list (can be the same)
… into the swap_item function, this simply takes the given ids, and swaps all the data from the given resources, or at least it should:

Currently, for reasons I am not sure of (even after my diagnostics),
clicking certain selectors (it seems to be) after swapping an item between characters will give
the wrong ids and either swap items that werent even touched, do nothing at all, or flicker
strangely before going back to the initial layout.

I have currently run several diagnostics consisting of print messages, tests of various kinds, and

completely re-doing aspects, so far I have found no solution, the only clue I have found is that certain times it seems to sometimes be setting the ID twice, which seamlessly leads to malformed operations.
I have taken button sensativity into account, this is not an issue

Even more strangely so, there are no errors in the console other than a completely unrelated and unknown error: ERROR: platform/windows/display_server_windows.cpp:4011 - Parameter "hicon" is null. , which i have no intention to solve currently.

The console output after attempting to swap (if it fails) is the following:

0
1
first index is : 0 whereas the index for the second button is : 4

The entire file for the inventory item is here:

extends Button
var data : Item = null
var off = false
var hero_index : int = 0
var swap_index = 0
var swap_index2 = 0
var item_swap_text = preload("res://Dialog/ItemSwap.dialogue")
@export var index : int = 0
@onready var parent = get_parent().get_parent()
@onready var action_select = $"../../../ActionSelect"
@onready var inv_holder = %InvHolder
@onready var inv_holder_label = $"../../../ActionSelect/NAMELABEL"
@onready var balloon = %Balloon
func _process(_delta: float) -> void:
	if hero_index != inv_holder.hero_index:
		hero_index = inv_holder.hero_index
	if self.text != Snes.data.MainParty[hero_index].Items[index].Name:
		refresh_self()
	else: 
		pass
	if self.visible != false && Snes.menu_level == 4:
		refresh_self()
func _input(_event: InputEvent) -> void:
	refresh_self()
	if balloon.visible == false:
		if self.button_pressed:
			if off != true:
				if Snes.menu_level == 3:
					print("it should have changed ID now.")
					swap_index = inv_holder.hero_index
					if inv_holder.selected_item != index:
						inv_holder.selected_item = index
						swap_index = inv_holder.hero_index
					
					action_select.item = data
					inv_holder_label.text = Snes.data.MainParty[hero_index].Items[index].Name
					Snes.item_index = index
					Snes.item = Snes.data.MainParty[hero_index].Items[index]
					Snes.menu_level = 4
					
			if Snes.menu_level == 6:
				swap_index2 = inv_holder.hero_index
				inv_holder.selected_item2 = index
				Snes.item_index2 = index
				Snes.hero_index2 = hero_index
				
				_swap_item(swap_index, swap_index2, inv_holder.selected_item, inv_holder.selected_item2)
				refresh_self()
				Snes.menu_level = 3
				print("first index is : " + str(inv_holder.selected_item) + "whereas the index for the second button is : " + str(inv_holder.selected_item2))
				balloon.start(item_swap_text)
func _swap_item(index1: int = 0, index2: int = 0, item_index1: int = 0, item_index2: int = 0):
	var _first_selected : Item = Snes.data.MainParty[index1].Items[item_index1]
	var _second_selected : Item = Snes.data.MainParty[index2].Items[item_index2]
	print(index1)
	print(index2)
	Snes.data.MainParty[index1].Items[item_index1] = _second_selected
	Snes.data.MainParty[index2].Items[item_index2] = _first_selected


func refresh_self() -> void:
	data = Snes.data.MainParty[hero_index].Items[index]
	self.text = data.Name
	if self.text == "":
		off = true
		self.text = "   "
	else:
		off = false
	if Snes.menu_level == 4 or Snes.menu_level == 5:
		self.visible = false
	else:
		self.visible = true

If more info is required, I will share as needed, any help is highly appreciated.
(EDIT: moved code file towards bottom, apologies, earlier was unorganized)
Apologies if anything was long-winded or unneccesary.

If you want to execute code once every time the button gets pressed, connect the button’s pressed signal to a dedicated function, don’t use _input().

Thank you, however I am 99% sure that is not the issue, the double execution glitch happens on ID 1 of character array when i swap character item arrays,

this seems to be inversely but not entirely related to the actual buttons…

I feel like there is either another issue in a different area…
it isnt that functions are being executed more than once, it is that incorrect values are being outputted, completely incorrect values…

If I understand your code correctly, swap_index is only set on the first item selected, but _swap_item() is called from a different one. So the second item selected will always use the initial value of swap_index = 0 as first argument for _swap_item().

Yes, that is supposed to be the case, for some reason, however, it seems to use the combination 0, 1 when completely different indexes are selected if the character items array is anything other than index 0. . .

Combination for what? Character indices? Item indices?

What is the exact behavior you are getting and what are you expecting?

Combination of item indexes, and the last index is referring to the actual Database’s character data and party member’s item lists.

I think it is because the character ID for the buttons is becoming incorrectly set to the original and mismatches happen, but this is a hypothesis, i will test this right now…

*I stopped using a separate variable for the items array to display, and the effects were unchanged mostly… for some reason if only works if the character IDs are either both 0, 1 and 0, or 0 and 1, but not both 1…

Finally fixed it. here is my finished code, i suppose i was reusing other variables from previous actions; my code is more basic and the naming is a bit shorter for the IDs, but the functionality is fixed:

extends Button
var data : Item = null
var off = false


var item_swap_text = preload("res://Dialog/ItemSwap.dialogue")
@export var index : int = 0
@onready var parent = get_parent().get_parent()
@onready var action_select = $"../../../ActionSelect"
@onready var inv_holder = %InvHolder
@onready var inv_holder_label = $"../../../ActionSelect/NAMELABEL"
@onready var balloon = %Balloon

func _input(_event: InputEvent) -> void:
	
	refresh_self()
	
	if balloon.visible == false:
		
		if self.button_pressed:
			
			if off != true:
				
				if Snes.menu_level == 3:

					Snes.HIID1 = inv_holder.hero_index
					Snes.IID1 = index
					action_select.item = data

					inv_holder_label.text = Snes.data.MainParty[inv_holder.hero_index].Items[index].Name
					Snes.item = Snes.data.MainParty[inv_holder.hero_index].Items[index]
					Snes.menu_level = 4
					await get_tree().create_timer(0.03).timeout
					off = true


			if Snes.menu_level == 6:

				Snes.HIID2 = inv_holder.hero_index
				Snes.IID2 = index

				off = true

				_swap_item(Snes.IID1,Snes.IID2, Snes.HIID1, Snes.HIID2)

				balloon.start(item_swap_text)

				await get_tree().create_timer(0.03).timeout
				off = true
				Snes.menu_level = 3



func _swap_item(i1: int = 0, i2: int = 0, hi1: int = 0, hi2: int = 0):
	var _first_selected : Item = Snes.data.MainParty[hi1].Items[i1]
	var _second_selected : Item = Snes.data.MainParty[hi2].Items[i2]
	Snes.data.MainParty[hi1].Items[i1] = _second_selected
	Snes.data.MainParty[hi2].Items[i2] = _first_selected
	print("The first selected item is: ")
	print(i1)
	print("The second selected item is: ")
	print(i2)

func refresh_self() -> void:
	data = Snes.data.MainParty[inv_holder.hero_index].Items[index]
	self.text = data.Name
	if self.text == "":
		off = true
		self.text = "   "
	else:
		off = false
	if Snes.menu_level == 4 or Snes.menu_level == 5:
		self.visible = false
	else:
		self.visible = true

func _process(_delta: float) -> void:
	if self.text != Snes.data.MainParty[inv_holder.hero_index].Items[index].Name:
		refresh_self()
	else: 
		pass
	if self.visible != false && Snes.menu_level == 4:
		refresh_self()
		

thank you for your efforts, @hyvernox