TowerGameProto/scripts/Machine.gd

113 lines
2.9 KiB
GDScript

extends Building
class_name Machine
#signal item_available(node: ItemNode)
@export var accepted_items: Array[Item]
@export var produced_item: Item
const item_node_scene: PackedScene = preload("res://objects/resource.tscn")
var remove_accepted_item_nodes: bool = true
@export var sources: Array[Machine]
@export var source_limit: int = 0
@export var sinks: Array[Machine]
@export var sink_limit: int = 0
@export var stored_items: Array[Item]
@export var storage_limit: int = 10
func _ready() -> void:
connect("input_event", on_input_event)
func place() -> void:
super()
func on_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
if event is InputEventMouseButton:
if event.button_mask & MOUSE_BUTTON_MASK_LEFT:
selected.emit(self)
func add_source(source: Machine) -> bool:
if sources.size() < source_limit:
sources.append(source)
if !source.sinks.has(self):
source.sinks.append(self)
return true
return false
func add_sink(sink: Machine) -> bool:
if sinks.size() < sink_limit:
sinks.append(sink)
if !sink.sources.has(self):
sink.sources.append(self)
return true
return false
func offer_item(node: ItemNode) -> bool:
return store_item(node)
func can_accept_item(item: Item) -> bool:
return (accepted_items.has(item) or accepted_items.is_empty()) \
and (stored_items.size() < storage_limit) \
and is_functional()
func produce() -> bool:
if stored_items.size() < storage_limit:
# create a new item if there's room
stored_items.append(produced_item)
if stored_items.has(produced_item):
# send items if we have them
if can_send_item(produced_item):
var item_node: ItemNode = unstore_item(produced_item)
if !send_item(item_node):
# TODO: just blow up the item for now
item_node.queue_free()
return true
return false
func unstore_item(item: Item) -> ItemNode:
if fetch_item_from_storage(item, 1):
var item_node: ItemNode = item_node_scene.instantiate(PackedScene.GEN_EDIT_STATE_DISABLED)
item_node.item_type = item
add_child(item_node)
item_node.global_position = global_position
return item_node
return null
func send_item(item_node: ItemNode) -> bool:
var machines: Array[Machine] = sinks.duplicate()
machines.shuffle()
for sink in machines:
if sink.offer_item(item_node):
return true
return false
func can_send_item(item: Item) -> bool:
return is_functional() and sinks.any(func(machine:Machine): return machine.can_accept_item(item))
func store_item(item_node: ItemNode) -> bool:
if stored_items.size() < storage_limit:
stored_items.append(item_node.item_type)
if remove_accepted_item_nodes:
item_node.queue_free()
return true
return false
func fetch_item_from_storage(item: Item, count: int) -> bool:
var idxs: Array[int] = []
for idx in range(stored_items.size()):
if stored_items[idx] == item:
idxs.append(idx)
count -= 1
if count <= 0:
break
if count <= 0:
for idx in idxs:
stored_items.remove_at(idx)
return true
else:
return false