Godot 4.2.1 card game problem

Godot 4.2.1

Can someone please help. I am working on my small card game and there is one problem that I’ve been trying to fix for the past hour or so.

When the user selects a card and a drags it to one of the slots the card does not create a new instance of it self and place it in the slot and then removes it self. Well it does but its weird, the way it works I don’t know why but the card needs to be offsetted from the slot position for the card to be placed.

Video link (sorry i couldn’t attach the video because i am a new user so i had to upload it to youtube):

I see you have a couple of print statements when mouse enters and mouse exits, what is the output?
In this case it might be an idea to print to a label on mouse entered to see if that signal is working the way you expect it to.
I am not sure using the underlying slots mouse entered signal is ideal. The mouse registers at one point (usually/probably the top left of your card). You want to be able to drop that card when any part of the card is over the slot.

The print statement you see is the Game.mouse_on_slot, this variable is in the GAME script which is auto loaded. There is two signals in the slot that sets to true or false, that is mouse_entered() and mouse_exited(). The slot is detecting correctly whether the mouse has entered or exited it just the card itself, I just can’t find it.

I was talking about the Slot functions _on_mouse_entered() and _on_mouse_exited().
They have print statements. What is the output from them?

And man, you must post actual code. It is beyond frustrating trying to queue up a video to find code and then have to type that code in because…its a video.
I usually don’t even try to help when code isn’t posted and I probably am not alone in that.

On the text box you type into is a toolbar with something that looks like this </>
Use that tool to surround the code so that it retains its formatting.

I suspect that the Game.mouse_on_slot (or whatever it is called) is being reset on you.
Another way to test that is to add a setter to that variable that shows its state in a label.

var mouse_on_slot:bool = false:  
    set(value): 
        mouse_on_slot = value
        my_debug_label.text = str(value)

The print statements on the Slot are print(“entered”) for the mouse_entered() and print(“exited”) on the mouse_exited() and like I said the detection on the Slot is correct.

#Slot

extends Control

func _on_mouse_entered():
	print("entered")
	Game.mouse_on_slot = true
	Game.slot_name = name


func _on_mouse_exited():
	print("exit")
	Game.mouse_on_slot = false
	Game.slot_name = null


#Card

extends Control

var is_selected : bool = false
var following_mouse : bool = false
var is_placed : bool = false

var tween_hover : Tween


var initial_pos : Vector2 = Vector2.ZERO

func _ready():
	pass




func _process(_delta):
	print(Game.mouse_on_slot)
	if following_mouse:
		global_position = get_global_mouse_position()
		




func _gui_input(event):
	
	if event is InputEventMouseButton and event.button_index == 1:
		if event.button_mask == 1:
			if is_selected:
				initial_pos = position
				following_mouse = true
				Game.card_scene = load("res://Cards/base_card.tscn")
				Game.card_name = name
		if event.button_mask == 0:
			
			if Game.mouse_on_slot:
				var temp_card = Game.card_scene.instantiate()
				get_tree().get_root().get_child(1).get_child(0).find_child(Game.slot_name).add_child(temp_card)
				get_tree().get_root().get_child(1).get_child(1).get_child(0).find_child(Game.card_name).queue_free()
				is_selected = false
				following_mouse = false
			else:
				following_mouse = false
				is_selected = false
				position = initial_pos
			Game.card_scene = null
			Game.card_name = null
	
	



func _on_mouse_entered():
	is_selected = true
	
	if tween_hover and tween_hover.is_running():
		tween_hover.kill()
	tween_hover = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_ELASTIC)
	tween_hover.tween_property(self, "scale", Vector2(1.05, 1.05), 0.5)


func _on_mouse_exited():
	if not following_mouse:
		is_selected = false
	
		if tween_hover and tween_hover.is_running():
			tween_hover.kill()
		tween_hover = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_ELASTIC)
		tween_hover.tween_property(self, "scale", Vector2.ONE, 0.55)


game (this script is auto loaded)

extends Node

var card_scene
var card_name
var mouse_on_slot = false
var slot_name

This section seems a little strange to me.

if event.button_mask == 0:
		if Game.mouse_on_slot:
			var temp_card = Game.card_scene.instantiate()
			get_tree().get_root().get_child(1).get_child(0).find_child(Game.slot_name).add_child(temp_card)
			get_tree().get_root().get_child(1).get_child(1).get_child(0).find_child(Game.card_name).queue_free()
    		is_selected = false
			following_mouse = false
		else:
			following_mouse = false
			is_selected = false

Are you certain this line is getting the node you want?:
get_tree().get_root().get_child(1).get_child(0).find_child(Game.slot_name).add_child(temp_card)
I would dump that into a variable and check that you are getting the slot you ask for.
If you are searching for a child node by name then you don’t need the extended get_child as find_child() has a parameter called recursive that defaults to true and will search the childs child (if I read the docs right…you can test that out).

var slot_node = get_tree().get_root().find_child(Game.slot_name)
slot_node.add_child(temp_card)

Similarly for the next line; check to make sure you are getting the node you want.
It seems strange to me that you are queue freeing the node Game.card_name but with get_childs() I have no way of seeing what exactly is being freed.
Maybe if you could describe the logic starting from
if event.button_mask == 0
(Alternatively, you can post the project on github so we can have a look)

I still strongly suspect that mouse_exit() is being fired unexpectedly and causing your issues. I remember working with these mouse events and being surprised by the events firing when I thought they could not be.

I can’t see anything immediately obvious in the code that would reject the card drop.
To debug this, you are going to have to somehow trap the code flow at the point that you drop the card and it doesn’t take.

As an aside you have these statements identical on opposing sides of an if statement. One of them will run and since they are the same they need not be inside the if statement.

				is_selected = false
				following_mouse = false
			else:
				following_mouse = false
				is_selected = false

It also doesn’t make sense to me to load this scene inside the input event.
Game.card_scene = load("res://Cards/base_card.tscn")
Load it once in the _ready() function and then instantiate it at will.
iirc GODOT handles repeated loading of the same resource elegantly so it won’t cause an issue but it seems disorganized to me.
(These last to things are not related to your issue)

You were right the first time, it was the Game.mouse_on_slot not being detected correctly. Thank you for your help!