146 lines
5.4 KiB
GDScript
146 lines
5.4 KiB
GDScript
extends StaticBody2D
|
|
|
|
export(Constants.MACHINE_TYPE) var machine_type = Constants.MACHINE_TYPE.SMELTER
|
|
export var max_idle_time := 8.0
|
|
export var max_input_buffer := 3
|
|
var num_inputs = 0
|
|
var working := false setget set_working
|
|
var idle_time := 0.0
|
|
var work_time := 0.0
|
|
var anim_speed = 1.0
|
|
onready var rect = $sprite.get_rect()
|
|
onready var width = rect.size.x
|
|
onready var height = rect.size.y
|
|
onready var w_cells = width/8
|
|
onready var h_cells = height/8
|
|
onready var beltmap = $"../../BeltTiles"
|
|
var surrounding_tilename_indices
|
|
var surrounding_tilename_indices_internal
|
|
var surrounding_tilename_indices_dir
|
|
var was_started = false
|
|
|
|
var dir_vectors = [Vector2(1,0), Vector2(0,-1), Vector2(-1,0), Vector2(0,1)]
|
|
var dir_angles = [0, 90, 0, 90] # Angles to rotate output by
|
|
func get_belt_direction(tx, ty):
|
|
var xflip = beltmap.is_cell_x_flipped(tx, ty)
|
|
var tp = beltmap.is_cell_transposed(tx, ty)
|
|
return int(tp) + int(xflip)*2
|
|
|
|
func get_global_rect():
|
|
return Rect2(to_global(rect.position), rect.size)
|
|
|
|
onready var recipe = Constants.RECIPES[machine_type]
|
|
func _ready():
|
|
var top_left_corner_tile = position - Vector2(width/2-4, height/2-4)
|
|
var tlct = beltmap.world_to_map(top_left_corner_tile)
|
|
surrounding_tilename_indices = []
|
|
surrounding_tilename_indices_internal = []
|
|
surrounding_tilename_indices_dir = []
|
|
# Add all orthogonal cells in clockwise order
|
|
for i in w_cells:
|
|
surrounding_tilename_indices.append(tlct+Vector2(i,-1))
|
|
surrounding_tilename_indices_internal.append(tlct+Vector2(i,0))
|
|
surrounding_tilename_indices_dir.append(1)
|
|
for i in h_cells:
|
|
surrounding_tilename_indices.append(tlct+Vector2(w_cells,i))
|
|
surrounding_tilename_indices_internal.append(tlct+Vector2(w_cells-1,i))
|
|
surrounding_tilename_indices_dir.append(0)
|
|
for i in w_cells:
|
|
surrounding_tilename_indices.append(tlct+Vector2(w_cells-1-i,h_cells))
|
|
surrounding_tilename_indices_internal.append(tlct+Vector2(w_cells-1-i,h_cells-1))
|
|
surrounding_tilename_indices_dir.append(3)
|
|
for i in h_cells:
|
|
surrounding_tilename_indices.append(tlct+Vector2(-1,h_cells-1-i))
|
|
surrounding_tilename_indices_internal.append(tlct+Vector2(0,h_cells-1-i))
|
|
surrounding_tilename_indices_dir.append(2)
|
|
|
|
func _process(delta):
|
|
if num_inputs < max_input_buffer and recipe.input != Constants.MATERIAL_TYPE.iMOLTEN:
|
|
suck_materials()
|
|
|
|
if working:
|
|
if work_time >= recipe.time:
|
|
output()
|
|
else:
|
|
work_time += delta
|
|
return
|
|
|
|
if num_inputs <= 0:
|
|
self.working = false
|
|
if not was_started:
|
|
return
|
|
idle_time += delta
|
|
if idle_time >= max_idle_time:
|
|
$"/root/Main".game_over()
|
|
var overspeed = clamp(floor(idle_time/2)*2, 1, 8)
|
|
$sprite.material.set_shader_param('rps', overspeed*anim_speed)
|
|
else:
|
|
self.working = true
|
|
was_started = true
|
|
num_inputs -= 1
|
|
work_time = 0
|
|
idle_time = 0
|
|
|
|
func output():
|
|
if recipe.output == Constants.MATERIAL_TYPE.iMOLTEN:
|
|
for i in len(surrounding_tilename_indices):
|
|
var ind = surrounding_tilename_indices[i]
|
|
if beltmap.get_cell(ind.x, ind.y) == 4: # Channel
|
|
var dir = get_belt_direction(ind.x, ind.y)
|
|
if dir != surrounding_tilename_indices_dir[i]:
|
|
continue
|
|
else:
|
|
var xy = ind
|
|
while(true):
|
|
xy += dir_vectors[dir]
|
|
if beltmap.get_cell(xy.x, xy.y) == 4:
|
|
if get_belt_direction(xy.x, xy.y) == dir:
|
|
continue
|
|
else:
|
|
for child in get_parent().get_children(): # Check if a suitable machine is on this tile
|
|
if child.rect.has_point(child.to_local(beltmap.map_to_world(xy) + Vector2(4,4))):
|
|
child.feed(null)
|
|
return
|
|
break
|
|
else:
|
|
for i in len(surrounding_tilename_indices):
|
|
var ind = surrounding_tilename_indices[i]
|
|
var celltype = beltmap.get_cell(ind.x, ind.y)
|
|
if celltype >= 0 and celltype != 4: # Belt
|
|
# For correct logic on 2wide outputs, we'd have to check for 2 adjacent belts
|
|
# Since we have no time, we'll just throw it out as if there was a second belt
|
|
# If people think they're exploiting the game, they're only playing themselves
|
|
var dir = get_belt_direction(ind.x, ind.y)
|
|
if dir != surrounding_tilename_indices_dir[i]:
|
|
continue
|
|
var product = Constants.MATERIAL_SCENES[recipe.output].instance()
|
|
var outpos = beltmap.map_to_world(surrounding_tilename_indices_internal[i]) + Vector2(4, 4)
|
|
if recipe.output > 2: # Make a proper check later
|
|
outpos += dir_vectors[surrounding_tilename_indices_dir[i]-1]*4 # the list progresses CCW, we want CW
|
|
product.position = outpos
|
|
product.rotation_degrees = dir_angles[surrounding_tilename_indices_dir[i]]
|
|
outpos -= dir_vectors[surrounding_tilename_indices_dir[i]] # Hack to make feed exit work
|
|
product.leave_machine(self, outpos)
|
|
$"../../Objects".add_child(product)
|
|
return
|
|
|
|
func set_working(state):
|
|
working = state
|
|
$sprite.material.set_shader_param('rps', int(state)*anim_speed)
|
|
|
|
func suck_materials():
|
|
for candidate in $SuckArea.get_overlapping_bodies():
|
|
if candidate.has_method('enter_machine'):
|
|
if candidate.material_type == recipe.input and not candidate.entering_machine:
|
|
var displacement = candidate.position - position
|
|
var nearest_col = clamp(round((displacement.x + width/2 - 4)/8), 0, w_cells-1)
|
|
var nearest_row = clamp(round((displacement.y + height/2 - 4)/8), 0, h_cells-1)
|
|
var port = position + Vector2(nearest_col*8-width/2+4, nearest_row*8-height/2+4)
|
|
candidate.enter_machine(self, port)
|
|
|
|
func feed(object):
|
|
if object:
|
|
object.get_parent().remove_child(object)
|
|
object.queue_free()
|
|
num_inputs += 1
|