Dead npc's weird behavior

Godot Version

4.6.1

I was implementing a feature in my game where after npc was being killed in the game, he would spawn his dead body on the floor. Among of the functions of the body, the player could pick up it by pressing the button and drag it somewhere. I use reparent function to make a corpse a child of one of the player’s node’s, but it’s very unstable. The corpse can be very close to the player or too far, depending on where the player was in the body’s area when pressing the button.

class_name Dead_npc extends CharacterBody2D

var money:=preload("uid://cubsltkbeane8").instantiate()
@onready var pick_up_button: Button = %PickUpButton
var player:Player

func _ready() -> void:
	pick_up_button.hide()
	var x_cords:=randf_range(-50.0,50.0)
	var y_cords:=randf_range(-50.0,50.0)
	money.global_position=global_position+Vector2(x_cords,y_cords)
	get_tree().root.add_child(money)

func _on_pick_up_button_pressed() -> void:
	if player:
		call_deferred("reparent",player.get_node("Secundary_hand"))
		pick_up_button.hide()
		rotation-=142.0
		if get_parent().get_parent() is Player:
			position=Vector2.ZERO
			player.speed-=100.0
			player.rotation_speed-=0.7
			pick_up_button.hide()

func _on_hitbox_body_entered(body: Node2D) -> void:
	if body is Player:
		player=body
		pick_up_button.show()

func _on_hitbox_body_exited(body: Node2D) -> void:
	if body is Player:
		player=null
		pick_up_button.hide()

Is the issue just with the position? It’s a bit hard to tell what your question is.

If the issue is position, I think there’s a problem caused by the order things are happening. If I remember correctly, reparenting maintains the global position, not the local position by default.

So the local position is being set to (0,0) before reparenting to the player because the reparent call is deferred.

I think you can give it a new transform with this line as there is an optional parameter for that.

call_deferred("reparent", player.get_node("Secundary_hand"), false)

Otherwise you can defer your call to change the position as well so it happens after reparenting

call_deferred("set_position", Vector2.ZERO)

I always seem to forget the syntax with call_deferred so hopefully that is right.