class_name StorageDestination extends Node2D ## Abstract base for all item-storage destinations (floor stockpile zones, ## containers, etc.). Hauling AI treats all subclasses as a unified candidate ## pool via this interface. ## ## StorageDestination extends Node2D (not Node) so subclasses can implement ## _draw() for priority-tinted overlays without a separate CanvasItem child. ## ## Subclasses MUST override: accepts(), find_drop_position(), covers_tile(). ## Subclasses SHOULD call World.register_stockpile(self) in _ready() and ## World.unregister_stockpile(self) in _exit_tree(). ## ## See docs/architecture.md "Storage destinations: a unified concept". ## Five priority levels matching Rimworld semantics (design.md Priorities). ## Lower enum int = higher priority (CRITICAL = 0 pulls before LOW = 4). ## Priority.OFF = no hauling in or out; invisible to HaulingProvider. enum Priority { CRITICAL = 0, HIGH = 1, NORMAL = 2, LOW = 3, OFF = 4, } ## Priority determines whether haulers will fill this destination and whether ## items here will be re-hauled upward to a higher-priority destination. @export var priority: Priority = Priority.NORMAL ## Item types this destination accepts. Empty array = wildcard (accepts all). ## Each entry is a StringName matching Item.TYPE_* constants (e.g. &"wood"). @export var accepted_types: Array[StringName] = [] ## Emitted when items are registered or unregistered with this destination, ## so interested parties (UI, re-scan logic) can react without polling. signal contents_changed # ── abstract interface — subclasses must override ──────────────────────────── ## Returns true if this destination currently accepts `item` (filter + priority ## check + any capacity logic owned by the subclass). func accepts(item) -> bool: push_error("StorageDestination.accepts: '%s' must override this method" % name) return false ## Returns a tile coordinate inside this destination where `item` can be ## placed (filter-pass AND the tile is not already occupied by another item). ## Returns Vector2i(-1, -1) when no slot is available. func find_drop_position(item) -> Vector2i: push_error("StorageDestination.find_drop_position: '%s' must override this method" % name) return Vector2i(-1, -1) ## Returns true if `tile` falls inside this destination's region. ## Used by HaulingProvider to find which destination currently holds an item. func covers_tile(tile: Vector2i) -> bool: push_error("StorageDestination.covers_tile: '%s' must override this method" % name) return false # ── shared helper ──────────────────────────────────────────────────────────── ## Priority-and-filter gate, shared by all subclasses. ## Returns false when OFF or when the item's type is not in accepted_types. ## accepted_types.is_empty() is the wildcard "accept any type" case. func _filter_accepts(item) -> bool: if priority == Priority.OFF: return false if accepted_types.is_empty(): return true return item.item_type in accepted_types