extends Building @export var speed: float = 1.0 @export var item_offset: Vector3 = Vector3(0,2.0,0) @export var extra_distance_start: float = 1.0 @export var extra_distance_end: float = 1.0 @export var spacing: float = 1.0 var transported_items: Dictionary[Item, PackedFloat64Array] = {} var belt_moving: bool = true var closest_item: float = 0.0 @onready var path: Path3D = $Path3D @onready var multimesh: MultiMeshInstance3D = $MultiMeshInstance3D var test_timer: float = 0 @onready var test_item: Item = load("res://items/metal.tres") var input_building: Building = null: set(value): if value.producer != null: input_building = value input_building.producer.consumers.append(consumer) var output_building: Building = null: set(value): if value.consumer != null: output_building = value producer.consumers.append(output_building.consumer) var waypoints: Array[Vector3] = [] var editing_waypoint: int = 0 func _exit_tree() -> void: if input_building != null: input_building.producer.consumers.erase(consumer) if output_building != null: producer.consumers.erase(output_building.consumer) func _placement_select_building(building: Building, confirmed: bool) -> int: var ret: int = 0 if input_building == null: if building.producer != null: ret |= PLACEMENT_POSITION_OK if confirmed: input_building = building ret |= PLACEMENT_PART_ADDED set_path_waypoint(building.global_position + Vector3(0,1,0), confirmed) elif output_building == null and building != input_building: if building.consumer != null: ret |= PLACEMENT_POSITION_OK if confirmed: output_building = building ret |= PLACEMENT_COMPLETED set_path_waypoint(building.global_position + Vector3(0,1,0), confirmed) return ret #return super(building, confirmed) func _placement_select_position(pos: Vector3, confirmed: bool) -> int: var ret: int = PLACEMENT_POSITION_OK set_path_waypoint(pos.round() + Vector3(0,1,0), confirmed) if confirmed: ret |= PLACEMENT_PART_ADDED return confirmed func set_path_waypoint(global_pos: Vector3, add: bool) -> void: var local_pos: Vector3 if editing_waypoint == 0: global_position = global_pos local_pos = Vector3() else: local_pos = to_local(global_pos) while waypoints.size() <= editing_waypoint: waypoints.append(Vector3()) waypoints[editing_waypoint] = local_pos if add: editing_waypoint += 1 update_path_from_waypoints() func update_path_from_waypoints() -> void: path.curve.clear_points() for waypoint in waypoints: path.curve.add_point(waypoint) # find paths between the defined points #for i in range(1, waypoints.size()): #var a: Vector3 = to_global(waypoints[i-1]) #var b: Vector3 = to_global(waypoints[i]) #var route: PackedVector3Array = NavigationServer3D.map_get_path(NavigationServer3D.get_maps()[0], a, b, false, 1) # #for point in route: #path.curve.add_point(to_local(point + Vector3(0,1,0))) # set the path3d's points to the path points # adjust the control points to some uniform amount pass func _ready() -> void: multimesh.multimesh = multimesh.multimesh.duplicate() path.curve = path.curve.duplicate() func _process(delta: float) -> void: belt_moving = is_functional() and check_items_at_end() consumer.enabled = belt_moving and (closest_item >= spacing) var movement: float = (delta * speed) closest_item += movement if belt_moving: for transported_item_type: Item in transported_items.keys(): var offsets: PackedFloat64Array = transported_items[transported_item_type] multimesh.multimesh.instance_count = offsets.size() for i in range(offsets.size()): offsets[i] += movement position_item(i, transported_item_type, offsets[i]) func consumer_has_item(item: Item) -> void: if consumer.take_item_from_storage(item): add_item(item) func add_item(item: Item) -> void: if item.model != multimesh.multimesh.mesh: multimesh.multimesh.mesh = item.model var offsets: PackedFloat64Array if transported_items.has(item): offsets = transported_items[item] else: offsets = [] offsets.append(get_start_offset()) transported_items[item] = offsets closest_item = 0.0 func check_items_at_end() -> bool: var length: float = get_end_offset() var ret: bool = true for transported_item_type: Item in transported_items.keys(): var offsets: PackedFloat64Array = transported_items[transported_item_type] var to_delete: Array[int] = [] for i in range(offsets.size()): if offsets[i] >= length: var sent: bool = producer.send_item(transported_item_type) if !sent: ret = false else: to_delete.append(i) for d in to_delete: offsets.remove_at(d) return ret func get_start_offset() -> float: return -extra_distance_start func get_end_offset() -> float: return path.curve.get_baked_length() + extra_distance_end func position_item(instance: int, _item: Item, offset: float) -> void: var trans: Transform3D trans = sample_curve_with_extrapolation(offset).translated_local(item_offset) multimesh.multimesh.set_instance_transform(instance, trans) func sample_curve_with_extrapolation(offset: float) -> Transform3D: var end_offset: float = path.curve.get_baked_length() if offset <= 0: var zero: Transform3D = path.curve.sample_baked_with_rotation(0) var almost_zero: Transform3D = path.curve.sample_baked_with_rotation(0.1) return almost_zero.interpolate_with(zero, (0.1-offset) * 10) elif offset > end_offset: var end: Transform3D = path.curve.sample_baked_with_rotation(end_offset) var almost_end: Transform3D = path.curve.sample_baked_with_rotation(end_offset-0.1) return almost_end.interpolate_with(end, (offset - (end_offset - 0.1)) * 10) else: return path.curve.sample_baked_with_rotation(offset)