## HoldableItem — Node2D that can be held in a Character's HandLeft or HandRight slot. ## Attach DragDropComponent as a child. On drag_released scans "characters" group for ## the nearest free hand slot within HAND_SLOT_RADIUS. class_name HoldableItem extends Node2D signal item_picked_up(item: HoldableItem) signal item_placed(item: HoldableItem) const HAND_SLOT_RADIUS: float = 60.0 const CHEST_RETURN_RADIUS: float = 80.0 @export var item_id: String = "" var home_chest: Node2D = null func _ready() -> void: var drag: DragDropComponent = get_node_or_null("DragDropComponent") as DragDropComponent if drag != null: drag.drag_picked_up.connect(_on_drag_picked_up) drag.drag_released.connect(_on_drag_released) func _on_drag_picked_up(_pos: Vector2) -> void: if is_in_hand_slot(): _detach_from_hand_slot() AudioManager.play_sfx("item_drag_start") item_picked_up.emit(self) func _on_drag_released(_pos: Vector2) -> void: if _try_return_to_chest(): return var result: Array = _find_nearest_free_hand_slot() if not result.is_empty(): var character: Character = result[0] as Character var hand: String = result[1] as String character.attach_item(hand, self) AudioManager.play_sfx("item_drop_hand") else: AudioManager.play_sfx("item_drop_floor") item_placed.emit(self) func _try_return_to_chest() -> bool: if home_chest == null: return false if global_position.distance_to(home_chest.global_position) >= CHEST_RETURN_RADIUS: return false var chest: RoomChest = home_chest as RoomChest if chest == null: return false AudioManager.play_sfx("item_return_chest") chest.receive_item(self) return true func is_in_hand_slot() -> bool: var p: Node = get_parent() if p == null: return false return p.name == "HandLeft" or p.name == "HandRight" func _detach_from_hand_slot() -> void: var hand_slot: Node = get_parent() var character: Character = hand_slot.get_parent() as Character if character == null: return var hand: String = "left" if hand_slot.name == "HandLeft" else "right" character.detach_item(hand) func _find_nearest_free_hand_slot() -> Array: var best_dist: float = HAND_SLOT_RADIUS var best_character: Character = null var best_hand: String = "" for node: Node in get_tree().get_nodes_in_group("characters"): var character: Character = node as Character if character == null: continue for hand: String in ["left", "right"]: if not character.is_hand_free(hand): continue var slot: Node2D = character.get_node_or_null("Hand" + hand.capitalize()) as Node2D if slot == null: continue var dist: float = global_position.distance_to(slot.global_position) if dist < best_dist: best_dist = dist best_character = character best_hand = hand if best_character == null: return [] return [best_character, best_hand]