class_name HUD extends CanvasLayer var selection_groups := {} var selected_group := "": set(value): redraw_multiselect(selected_group, value) selected_group = value redraw_select(selection_groups[selected_group][0].get_hud()) signal attack_value_changed(value: int) @onready var time: Label = %Time @onready var money: Label = %Money @onready var income: Label = %Income @onready var spawn_box: Control = %SpawnBox @onready var team_top: PanelContainer = %TeamTop @onready var team_bottom: PanelContainer = %TeamBottom @onready var lives_top: Label = %LivesTop @onready var lives_bottom: Label = %LivesBottom func _ready(): Client.player.money_changed.connect(func(): money.text = "Money: " + str(Client.player.money) ) Client.player.income_changed.connect(func(): income.text = "Income: " + str(Client.player.income) ) Client.current_stage.lives_changed.connect(func(): lives_top.text = "Lives: %02d" % Client.current_stage.teams.top.lives lives_bottom.text = "Lives: %02d" % Client.current_stage.teams.bottom.lives ) Client.stage_state_changed.connect(func(state: State): if state is StateBuild: %TowerConfigurationsContainer.visible = true else: %TowerConfigurationsContainer.visible = false ) # TODO: fix multi select %SelectionContainer.visible = false %SelectionData.get_child(0).queue_free() %MultiSelectionContainer.visible = false Client.placed_tower.connect(func(tower: Tower): tower.selected.connect(func(): var hud_data = tower.get_hud() var multi_select_hud_data = TextureRect.new() multi_select_hud_data.name = tower.name multi_select_hud_data.modulate = Color(0.5, 0.5, 0.5) var texture = AtlasTexture.new() texture.atlas = preload("res://core_outdoor.png") texture.region = Rect2(400, 432, 32, 48) multi_select_hud_data.texture = texture if not tower.selection_group_id in selection_groups: selection_groups[tower.selection_group_id] = [] selection_groups[tower.selection_group_id].append(tower) multi_select_hud_data.add_to_group(tower.selection_group_id) # TODO: build groups from current component configurations matches. md5 of property values? # TODO: do in tower.gd at select? # TODO: probably do here at the selected signal and add to groups var at top if Tower.selected_towers.size() == 1: %SelectionContainer.visible = true %MultiSelectionContainer.visible = false redraw_select(hud_data) %MultiSelectionList.add_child(multi_select_hud_data) elif Tower.selected_towers.size() > 1: %MultiSelectionContainer.visible = true %MultiSelectionList.add_child(multi_select_hud_data) redraw_multiselect("", selected_group) ) tower.deselected.connect(func(): if Tower.selected_towers.size() == 0: %SelectionContainer.visible = false %MultiSelectionContainer.visible = false for child in %SelectionData.get_children(): child.queue_free() for child in %MultiSelectionList.get_children(): child.queue_free() elif Tower.selected_towers.size() == 1: %MultiSelectionContainer.visible = false %SelectionContainer.visible = true %MultiSelectionList.get_node(NodePath(tower.name)).queue_free() elif Tower.selected_towers.size() > 1: # only remove deselected tower from list var node = %MultiSelectionList.get_node_or_null(NodePath(tower.name)) if node: # when double click selecting in quick succession not found error node.queue_free() if tower.selection_group_id in selection_groups: selection_groups[tower.selection_group_id].erase(tower) if selection_groups[tower.selection_group_id].is_empty(): selection_groups.erase(tower.selection_group_id) ) tower.selection_group_id_changed.connect(func(previous_id: String): if not tower.selection_group_id in selection_groups: selection_groups[tower.selection_group_id] = [] selection_groups[tower.selection_group_id].append(tower) %MultiSelectionList.get_node(NodePath(tower.name)).add_to_group(tower.selection_group_id) selection_groups[previous_id].erase(tower) if selection_groups[previous_id].is_empty(): selection_groups.erase(previous_id) if previous_id == selected_group: selected_group = tower.selection_group_id %MultiSelectionList.get_node(NodePath(tower.name)).remove_from_group(previous_id) if tower.name == selection_groups[tower.selection_group_id][0].name: redraw_select(tower.get_hud()) ) tower.attack_value_changed.connect(func(value: int): attack_value_changed.emit(value) ) ) Client.multi_select_finished.connect(func(): selected_group = get_ordered_group_keys()[0] ) func _input(event: InputEvent): if event.is_action_pressed("spawn_box_toggle"): spawn_box.visible = not spawn_box.visible if event.is_action_pressed("players_list_toggle"): team_top.visible = not team_top.visible team_bottom.visible = not team_bottom.visible if %MultiSelectionContainer.visible and event.is_action_pressed("selection_cycle"): var keys = get_ordered_group_keys() var current_idx = keys.find(selected_group) selected_group = keys[(current_idx + 1) % keys.size()] func redraw_select(hud_data: Control): for node in %SelectionData.get_children(): node.queue_free() %SelectionData.add_child(hud_data) func redraw_multiselect(previous_group: String, new_group: String): var idx = 0 for group_key in get_ordered_group_keys(): var group = selection_groups[group_key] for node in group: var selection_node = %MultiSelectionList.get_node_or_null(NodePath(node.name)) if selection_node: # when double click selecting in quick succession not found error %MultiSelectionList.move_child(selection_node, idx) idx += 1 for node in get_tree().get_nodes_in_group(previous_group): node.modulate = Color(0.5, 0.5, 0.5) for node in get_tree().get_nodes_in_group(new_group): node.modulate = Color(1.0, 1.0, 1.0) func get_ordered_group_keys() -> Array: var keys = selection_groups.keys() keys.sort_custom(func(a, b): var group_a = selection_groups[a] var group_b = selection_groups[b] return group_a.size() > group_b.size() ) keys.sort_custom(func(a, b): var group_a = selection_groups[a] var group_b = selection_groups[b] var node_a = group_a[0] var node_b = group_b[0] return ( (node_a.attack_range / 8) + node_a.attack_power + node_a.attack_speed > (node_b.attack_range / 8) + node_b.attack_power + node_b.attack_speed ) ) keys.sort_custom(func(a, b): var group_a = selection_groups[a] var group_b = selection_groups[b] return group_a[0].components.size() > group_b[0].components.size() ) return keys func _on_build_mode_button_gui_input(event: InputEvent) -> void: if event.is_action_pressed("select"): if Client.state is StateDefault: get_tree().current_scene.get_node("StateManager").set_state("StateBuild") elif Client.state is StateBuild: get_tree().current_scene.get_node("StateManager").set_state("StateDefault") func _on_spawner_box_button_gui_input(event: InputEvent) -> void: if event.is_action_pressed("select"): spawn_box.visible = not spawn_box.visible func _on_player_list_button_gui_input(event: InputEvent) -> void: if event.is_action_pressed("select"): team_top.visible = not team_top.visible team_bottom.visible = not team_bottom.visible