class_name Tower extends StaticBody2D signal selected signal deselected static var selected_towers: Array[Tower] var is_selected = false : set(value): if value: if not Tower.selected_towers.has(self): Tower.selected_towers.append(self) selected.emit() else: Tower.selected_towers.erase(self) deselected.emit() Client.stage.hud.tower.text = "" is_selected = value queue_redraw() var is_hovered = false : set(value): is_hovered = value queue_redraw() var mobs_in_range: Array = [] var selection_area: Area2D # rpc owner id var owner_id = 1 # unique shared id on the network on all clients var network_id @export var attack_range: int = 32 @export var attack_power: int = 1 @export var attack_speed: int = 1 func _ready(): $Range/CollisionShape2D.shape.radius = attack_range $ShootCooldown.wait_time = attack_speed func _draw(): if is_selected: draw_circle( Client.stage.map.tile_set.tile_size, 8 + attack_range, Color(1, 1, 1, 0.75), false, 1.0 ) modulate = Color(1.5, 1.5, 1.5) elif is_hovered: if Client.state is StateDefault: draw_circle( Client.stage.map.tile_set.tile_size, 8 + attack_range, Color(1, 1, 1, 0.5), false, 1.0 ) modulate = Color(1.25, 1.25, 1.25) else: modulate = Color(1, 1, 1) func _process(_delta: float) -> void: if $ShootCooldown.is_stopped() and not mobs_in_range.is_empty(): shoot() $ShootCooldown.start() if selection_area and is_instance_valid(selection_area): var bodies = selection_area.get_overlapping_bodies() if bodies.size() > 0: selection_area.queue_free() for body in bodies: Client.select_tower(body) func _on_input_event(_viewport: Node, event: InputEvent, _shape_idx: int): # disable remote select for now if owner_id != multiplayer.get_unique_id(): return if Client.state is StateDefault: if event.is_action_pressed("builder_tower_select"): Client.select_tower(self) if event is InputEventMouseButton: if event.is_double_click(): selection_area = Area2D.new() selection_area.position = ( Client.stage.get_node("Camera").get_rect().position + Client.stage.get_node("Camera").get_rect().size / 2 ) selection_area.set_collision_mask_value(3, true) var collision_shape = CollisionShape2D.new() var shape = RectangleShape2D.new() shape.size = Client.stage.get_node("Camera").get_rect().size collision_shape.shape = shape selection_area.add_child(collision_shape) get_tree().current_scene.add_child(selection_area) if event.is_action_pressed("builder_cancel"): Client.remove_tower(self) func _on_range_body_entered(body: Node2D) -> void: mobs_in_range.append(body) func _on_range_body_exited(body: Node2D) -> void: mobs_in_range.remove_at(mobs_in_range.find(body)) func _on_mouse_entered() -> void: is_hovered = true func _on_mouse_exited() -> void: is_hovered = false func is_melee_range(): return attack_range <= (Client.stage.map.tile_set.tile_size.x * 2) func shoot(): var target = mobs_in_range.pick_random() as Unit if is_melee_range(): target.set_hp(target.hp - 1) else: # TODO target.set_hp(target.hp - 1) func show_ui(): # todo: show ui pass func get_region(): var collision_shape := $CollisionShape2D var shape = $CollisionShape2D.shape as RectangleShape2D return Rect2( collision_shape.position, shape.size ) func _on_tree_exiting() -> void: is_selected = false func get_rpc_properties() -> Dictionary: return { "global_position": null, "owner_id": null, "network_id": null, }