extends TileMapLayer @export var building_spots: Array[Vector2i] @export var tree_spots: Array[Vector2i] @export var rock_spots: Array[Vector2i] @export var th_spots: Array[Vector2i] @export var level: int var ruins_spots: Array[Vector2i] var error_pings: Dictionary var building_data = {} var last_tile var last_text var last_food_text var last_water_text var rand = 0 const NAME_ICON = preload("res://NameIcon.tscn") const RESOURCE_GAIN = preload("res://ResourceGain.tscn") const ERROR_PING = preload("res://ErrorPing.tscn") var building_to_tile_map = { "tents": { "source": 8, "atlas": 0 }, "quarter": { "source": 8, "atlas": 1 }, "house": { "source": 8, "atlas": 2 }, "essencecompressor": { "source": 9, "atlas": 2 }, "woodcutter": { "source": 9, "atlas": 1 }, "stoneminer": { "source": 9, "atlas": 0 }, "foodgathering": { "source": 7, "atlas": 2 }, "foodprocessing": { "source": 7, "atlas": 3 }, "waterprocessor": { "source": 7, "atlas": 1 }, "waterpump": { "source": 7, "atlas": 0 } } func _process(delta: float) -> void: var tile = local_to_map(get_global_mouse_position()) var building_mode = Persister.get_value("building_mode") for spot in building_spots: if not building_data.has(spot) and not tree_spots.has(spot) and not rock_spots.has(spot) and not th_spots.has(spot) and not ruins_spots.has(spot): erase_cell(spot) if last_tile != tile: if last_text and is_instance_valid(last_text) and last_text.selected: last_text._deselect() if last_food_text and is_instance_valid(last_food_text) and last_food_text.selected: last_food_text._deselect() if last_water_text and is_instance_valid(last_water_text) and last_water_text.selected: last_water_text._deselect() rand = randi_range(0, 1) if not Persister.get_value("building_mode") and Persister.get_value("flood_level", PersisterEnums.Scope.UNKNOWN, 0) < level: if rock_spots.has(tile): last_text = NAME_ICON.instantiate() last_text.text = "[center]Rock" last_text.position = map_to_local(tile) + Vector2(-25, -10) add_sibling(last_text) elif tree_spots.has(tile): last_text = NAME_ICON.instantiate() last_text.text = "[center]Tree" last_text.position = map_to_local(tile) + Vector2(-25, -10) add_sibling(last_text) elif th_spots.has(tile): last_text = NAME_ICON.instantiate() last_text.text = "[center]Town Hall" last_text.position = map_to_local(tile) + Vector2(-25, -30) add_sibling(last_text) last_food_text = NAME_ICON.instantiate() last_food_text.text = "[center]%d Food" % [Persister.get_value("food")] last_food_text.position = map_to_local(tile) + Vector2(-25, -20) add_sibling(last_food_text) last_water_text = NAME_ICON.instantiate() last_water_text.text = "[center]%d Water" % [Persister.get_value("water")] last_water_text.position = map_to_local(tile) + Vector2(-25, -10) add_sibling(last_water_text) elif ruins_spots.has(tile): last_text = NAME_ICON.instantiate() last_text.text = "[center]Ruins" last_text.position = map_to_local(tile) + Vector2(-25, -10) add_sibling(last_text) elif building_data.has(tile): last_text = NAME_ICON.instantiate() last_text.text = "[center]%s" % [Data.data.buildings[building_data[tile].key].name] last_text.position = map_to_local(tile) + Vector2(-25, -10) add_sibling(last_text) for coords in building_data: var building = building_data[coords] if building.has("workers") and building.workers > 0 and (not Data.data.buildings[building.key].has("needs") or (Persister.get_value(Data.data.buildings[building.key].needs, PersisterEnums.Scope.UNKNOWN, 0) > 0)): building.progress += delta * building.efficiency / 100.0 if building.progress >= Data.data.buildings[building.key].time: if Data.data.buildings[building.key].has("needs"): Persister.change_value(Data.data.buildings[building.key].needs, -1) Persister.change_value(Data.data.buildings[building.key].resource, Data.data.buildings[building.key].amount) var gain = RESOURCE_GAIN.instantiate() gain.text = "[center]+1 %s" % [Data.data.buildings[building.key].resourcename] gain.position = map_to_local(coords) + Vector2(-60, -5) add_sibling(gain) building.progress -= Data.data.buildings[building.key].time if building.has("workers"): var close_bonus = 1.0 if building.workers == 0 and not error_pings.has(coords): var new_ping = ERROR_PING.instantiate() new_ping.type = "workers" new_ping.position = map_to_local(coords) + Vector2(2, -10) add_sibling(new_ping) error_pings[coords] = new_ping elif building.workers != 0 and error_pings.has(coords) and error_pings[coords].type == "workers": error_pings[coords].queue_free() error_pings.erase(coords) if building.key == "woodcutter": if tree_spots.size() == 0: close_bonus = 0 else: var min_distance = INF for tree in tree_spots: var distance = tree.distance_to(coords) if distance < min_distance: min_distance = distance if min_distance > 5: close_bonus = 0 else: close_bonus = 1 - (min_distance / 5) elif building.key == "stoneminer": if rock_spots.size() == 0: close_bonus = 0 else: var min_distance = INF for tree in rock_spots: var distance = tree.distance_to(coords) if distance < min_distance: min_distance = distance if min_distance > 5: close_bonus = 0 else: close_bonus = 1 - (min_distance / 5) elif building.key == "waterpump": var water_level = Persister.get_value("flood_level", PersisterEnums.Scope.UNKNOWN, 0) var amount = level - water_level if amount > 3: close_bonus = 0 else: close_bonus = (3 - amount) building.efficiency = (100 + Persister.get_value("conduit_bonus", PersisterEnums.Scope.UNKNOWN, 0)) * building.workers * 0.5 * close_bonus if building.efficiency == 0 and not building.workers == 0 and not error_pings.has(coords): var new_ping = ERROR_PING.instantiate() new_ping.type = "resources" new_ping.position = map_to_local(coords) + Vector2(2, -10) add_sibling(new_ping) error_pings[coords] = new_ping elif (building.efficiency != 0 or building.workers == 0) and error_pings.has(coords) and error_pings[coords].type == "resources": error_pings[coords].queue_free() error_pings.erase(coords) last_tile = tile if not building_mode: return if building_spots.has(tile) and not rock_spots.has(tile) and not tree_spots.has(tile) and not th_spots.has(tile) and not building_data.has(tile) and not ruins_spots.has(tile): var build_data = building_to_tile_map[Persister.get_value("building_key")] set_cell(tile, build_data["source"], Vector2i(build_data["atlas"],rand), 0) func _ready() -> void: Triggerer.listen("flood_level", _on_flood_level) func _on_flood_level(data): var value = int(data.value) if value >= level: for coords in building_data: var building = building_data[coords] var build_data = Data.data.buildings[building.key] var bttm = building_to_tile_map[building.key] var atlas = bttm.atlas var source match build_data.type: "utility": source = 11 "housing": source = 12 "production": source = 10 if building.has("workers"): Persister.change_value("avail_population", building.workers) elif build_data.type == "housing": Persister.change_value("max_population", -build_data.amount) ruins_spots.push_back(coords) set_cell(coords, source, Vector2i(atlas,building.rand), 0) building_data.clear() for error_ping in error_pings: error_pings[error_ping].queue_free() error_pings.clear() func kill_citizen(): for coords in building_data: var building = building_data[coords] if building.has("workers") and building.workers > 0: building.workers -= 1 return true return false func pick_block(): if Persister.get_value("win") or Persister.get_value("lose"): return var tile = local_to_map(get_global_mouse_position()) if building_data.has(tile): var data = Data.data.buildings[building_data[tile].key] if (not data.cost.has("wood") or int(data.cost.wood) <= Persister.get_value("wood")) and (not data.cost.has("stone") or int(data.cost.stone) <= Persister.get_value("stone")): Persister.persist_data("building_mode", true) Persister.persist_data("building_key", building_data[tile].key) func destroy(tile: Vector2i): if building_data.has(tile): var building = building_data[tile] var build_data = Data.data.buildings[building.key] if building.has("workers"): Persister.change_value("avail_population", building.workers) elif build_data.type == "housing": Persister.change_value("max_population", -build_data.amount) building_data.erase(tile) ruins_spots = ruins_spots.filter(func(coords): return coords != tile) if error_pings.has(tile): error_pings[tile].queue_free() error_pings.erase(tile) func place_building(): if Persister.get_value("win") or Persister.get_value("lose"): return var tile = local_to_map(get_global_mouse_position()) if building_spots.has(tile) and not building_data.has(tile) and not tree_spots.has(tile) and not rock_spots.has(tile) and not th_spots.has(tile): Persister.persist_data("building_mode", false) building_data[tile] = { "key": Persister.get_value("building_key"), "rand": rand, "level": level, "coords": tile } var build_data = Data.data.buildings[Persister.get_value("building_key")] var cost = build_data.cost if cost.has("wood"): Persister.change_value("wood", -int(cost.wood)) if cost.has("stone"): Persister.change_value("stone", -int(cost.stone)) if build_data.type == "housing": Persister.change_value("max_population", int(build_data.amount)) building_data[tile].max_population = int(build_data.amount) elif build_data.name != "Conduit": building_data[tile].workers = 0 building_data[tile].max_workers = 6 building_data[tile].efficiency = 100 + Persister.get_value("conduit_bonus", PersisterEnums.Scope.UNKNOWN, 0) building_data[tile].progress = 0 else: Persister.change_value("conduit_bonus", 20) Persister.persist_data("drag_mode", false) func show_info_building(): var tile = local_to_map(get_global_mouse_position()) if building_data.has(tile): Triggerer.trigger("show_info", building_data[tile]) elif ruins_spots.has(tile): Triggerer.trigger("show_info", { "key": "ruins", "coords": tile, "level": level })