feat(items): add RoomChest with spawn and receive logic
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,8 @@ const HAND_SLOT_RADIUS: float = 60.0
|
||||
|
||||
@export var item_id: String = ""
|
||||
|
||||
var home_chest: Node2D = null
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var drag: DragDropComponent = get_node_or_null("DragDropComponent") as DragDropComponent
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
## RoomChest — tappable storage node. Spawns HoldableItem/OutfitItem instances on demand.
|
||||
## Items fly out with a tween. Receives items back via receive_item().
|
||||
class_name RoomChest extends Node2D
|
||||
|
||||
signal items_spawned(chest: RoomChest)
|
||||
signal item_received(chest: RoomChest, item_id: String)
|
||||
|
||||
const SPAWN_TWEEN_DURATION: float = 0.3
|
||||
|
||||
@export var chest_id: String = ""
|
||||
|
||||
var _spawned_items: Array = []
|
||||
var _item_configs: Array[ChestItemData] = []
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("room_chests")
|
||||
_item_configs = RoomChestConfig.get_items(chest_id)
|
||||
if not chest_id.is_empty() and GameState.has_method("get_chest_state"):
|
||||
if not GameState.get_chest_state(chest_id).is_empty():
|
||||
spawn_items()
|
||||
|
||||
|
||||
func spawn_items() -> void:
|
||||
if not _spawned_items.is_empty():
|
||||
return
|
||||
var parent: Node = get_parent()
|
||||
for config: ChestItemData in _item_configs:
|
||||
var item: HoldableItem = _create_item(config)
|
||||
item.home_chest = self
|
||||
if parent != null:
|
||||
parent.add_child(item)
|
||||
else:
|
||||
add_child(item)
|
||||
item.global_position = global_position
|
||||
_spawned_items.append(item)
|
||||
_tween_item_out(item, config.spawn_offset)
|
||||
if GameState.has_method("set_chest_state"):
|
||||
GameState.set_chest_state(chest_id, _get_spawned_ids())
|
||||
items_spawned.emit(self)
|
||||
|
||||
|
||||
func receive_item(item: HoldableItem) -> void:
|
||||
_spawned_items.erase(item)
|
||||
if GameState.has_method("set_chest_state"):
|
||||
if _spawned_items.is_empty():
|
||||
GameState.clear_chest_state(chest_id)
|
||||
else:
|
||||
GameState.set_chest_state(chest_id, _get_spawned_ids())
|
||||
item_received.emit(self, item.item_id)
|
||||
_tween_item_in(item)
|
||||
|
||||
|
||||
func are_items_spawned() -> bool:
|
||||
return not _spawned_items.is_empty()
|
||||
|
||||
|
||||
func get_spawned_count() -> int:
|
||||
return _spawned_items.size()
|
||||
|
||||
|
||||
func get_item_config_count() -> int:
|
||||
return _item_configs.size()
|
||||
|
||||
|
||||
func _create_item(config: ChestItemData) -> HoldableItem:
|
||||
var item: HoldableItem
|
||||
if config.item_type == ChestItemData.ItemType.OUTFIT:
|
||||
var outfit: OutfitItem = OutfitItem.new()
|
||||
outfit.outfit_layer = config.outfit_layer
|
||||
item = outfit
|
||||
else:
|
||||
item = HoldableItem.new()
|
||||
item.item_id = config.item_id
|
||||
return item
|
||||
|
||||
|
||||
func _get_spawned_ids() -> Array:
|
||||
var ids: Array = []
|
||||
for item: HoldableItem in _spawned_items:
|
||||
ids.append(item.item_id)
|
||||
return ids
|
||||
|
||||
|
||||
func _tween_item_out(item: HoldableItem, offset: Vector2) -> void:
|
||||
var tween: Tween = create_tween()
|
||||
tween.tween_property(item, "global_position", global_position + offset, SPAWN_TWEEN_DURATION)
|
||||
|
||||
|
||||
func _tween_item_in(item: HoldableItem) -> void:
|
||||
var tween: Tween = create_tween()
|
||||
tween.tween_property(item, "global_position", global_position, SPAWN_TWEEN_DURATION)
|
||||
tween.tween_callback(item.queue_free)
|
||||
Reference in New Issue
Block a user