Help about weapon changing sistem

lastest

Hello i’m doing a game for a school proyect, so far i have the player character that works well and a faulty weapon sistem. When the player passes trough a weapon on the floor it picks it up and if it had a weapon in hand it dropes it into the scene the first part works, the last part (where it trows the last weapon iot had on hand into the ground ) doesn’t. Sorry if the scripts imma upload are in spanish it’s my native language
jugador.gd:

#jugador.gd
extends CharacterBody2D

@export var speed = 50
var moveDirection = Vector2.ZERO
var balas= 99
var arma_actual = null
var puede_recoger_arma = true
var tiempo_repickup = 0.5
var tiempo_restante_repickup = 0.0
@onready var animationTree = $AnimationTree

@export var maxHealth = 30

func _ready():
	animationTree.active = true
func activar_cooldown_pickup():
	puede_recoger_arma = false
	tiempo_restante_repickup = tiempo_repickup

func validateInput():
	moveDirection = Vector2.ZERO
	
	if Input.is_action_pressed("ui_left") or Input.is_key_pressed(KEY_A):
		moveDirection.x -= 1
	if Input.is_action_pressed("ui_right") or Input.is_key_pressed(KEY_D):
		moveDirection.x += 1
	if Input.is_action_pressed("ui_up") or Input.is_key_pressed(KEY_W):
		moveDirection.y -= 1
	if Input.is_action_pressed("ui_down") or Input.is_key_pressed(KEY_S):
		moveDirection.y += 1
	
	moveDirection = moveDirection.normalized()
	velocity = moveDirection * speed

func animatePlayer():
	animationTree["parameters/caminar/blend_position"] = moveDirection

func _physics_process(_delta):
	validateInput()
	animatePlayer()
	move_and_slide()
	# Cooldown para recoger arma
	if not puede_recoger_arma:
		tiempo_restante_repickup -= _delta
		if tiempo_restante_repickup <= 0:
			puede_recoger_arma = true

arma_base.gd:

#arma_base.gd
extends CharacterBody2D

class_name ArmaBase

@export var tiempo_entre_disparos := 0.5
@export var bala_scene: PackedScene
@export var version_suelo: PackedScene

var tiempo_restante := 0.0
var jugador: CharacterBody2D

func _physics_process(delta):
	look_at(get_global_mouse_position())

	if tiempo_restante > 0:
		tiempo_restante -= delta

	if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
		if tiempo_restante <= 0:
			shoot()
			tiempo_restante = tiempo_entre_disparos

func shoot():
	if jugador and jugador.balas > 0:
		var nueva_bala = bala_scene.instantiate()
		nueva_bala.direccion = rotation
		nueva_bala.global_position = $spawnpoint.global_position
		get_tree().current_scene.add_child(nueva_bala)

		jugador.balas -= 1
		print("Balas restantes:", jugador.balas)
	else:
		print("❌ Sin balas")

func _process(_delta):
	if jugador:
		global_position = jugador.global_position

arma_suelo.gd:

#arma_suelo.gd
extends Area2D
class_name ArmaSuelo

var nuevo_objeto : PackedScene
var version_suelo : PackedScene

func _ready():
	body_entered.connect(_on_body_entered)

func _on_body_entered(body):
	if body.name != "jugador":
		return

	if not body.puede_recoger_arma:
		return

	body.activar_cooldown_pickup()

	if body.name == "jugador":
		# Bloque para soltar el arma actual (Solo si ya tiene una)
		if body.arma_actual:
			# 1. Guarda la referencia y la posición ANTES de eliminar el nodo
			var version_a_dropeada = body.arma_actual.version_suelo
			var posicion_a_dropear = body.global_position

			# 2. Ahora, elimina el arma vieja
			body.arma_actual.queue_free()
			body.arma_actual = null # Reinicia la referencia del jugador

			# 3. Instancia y añade el arma soltada
			if version_a_dropeada:
				var arma_suelo_instancia = version_a_dropeada.instantiate()
				if arma_suelo_instancia:
					arma_suelo_instancia.global_position = posicion_a_dropear
					get_tree().current_scene.add_child(arma_suelo_instancia)


		# 4. Recoger la nueva arma (se ejecuta siempre que el body sea el jugador)
		var instancia = nuevo_objeto.instantiate()
		instancia.jugador = body
		body.call_deferred("add_child", instancia)
		body.arma_actual = instancia
		call_deferred("queue_free") # Elimina el arma en el suelo (la que se acaba de recoger)

ak47.gd (pistola.gd is similar):

extends ArmaBase

func _ready():
	bala_scene = preload("res://escenas/bala.tscn")
	version_suelo = preload("res://escenas/ak47_suelo_temp.tscn")
	tiempo_entre_disparos = 0.2

ak47_suelo.gd (also pistola_suelo.gd is similar):

# ak47_suelo.gd
extends "res://scripts/arma_suelo.gd"

func _ready():
	nuevo_objeto = preload("res://escenas/ak47.tscn")
	# ELIMINAR -> version_suelo = preload("res://escenas/ak47_suelo.tscn")
	super._ready()

The issue seems to be with the order of operations when you drop the current weapon.
Right now, your code removes (queue_free()) the weapon in the player’s hand before creating the “ground version” of it. When that happens, the reference to “version_suelo” can become invalid, or Godot may have already deleted the node before the new one is spawned , so nothing actually appears on the ground.

To fix this, instantiate the ground version first, then remove the old weapon afterward. This way, you’re still working with a valid reference when you spawn the dropped weapon.

Also, watch out for the pickup area on the dropped weapon: if the player stays inside it, the weapon might be picked up again immediately. You can prevent that with a short pickup cooldown or by temporarily disabling the collider.