@tool class_name Unit extends Composer signal promoted @export var sprite: Texture2D: set(val): sprite = val _check_compose() @export var player: Node: set(val): if val is Player: player = val else: player = null _check_compose() @export var hitpoints := 1 var chief_ref := WeakRef.new() var target_position := Vector2.ZERO var target_linear_velocity := Vector2.ZERO var target_angular_velocity := 0.0 var target_reached := false var is_chief := false var subordinates := 0 func _ready(): target_position = global_position super._ready() func _compose(): $sprite.texture = sprite if player: # TODO something more subtle $sprite.self_modulate = player.color if player.code and not Engine.is_editor_hint(): add_to_group("player:" + player.code) func _process(delta): if Engine.is_editor_hint(): return if target_reached: target_linear_velocity = Vector2.ZERO else: var current_position = self.global_position var diff = target_position - current_position if diff.length() > 5.0: target_linear_velocity = diff.normalized() * clamp(diff.length() * 0.1, 1.0, 10.0) * 10.0 else: target_reached = true self.linear_velocity = Tools.accel(self.linear_velocity, target_linear_velocity, 0.4, delta) func move_to(pos: Vector2): if pos != target_position: target_position = pos target_reached = false func damage(lost_hitpoints: float): hitpoints = max(0.0, hitpoints - lost_hitpoints) if hitpoints <= 0: die() func get_chief(): return chief_ref.get_ref() func die(): var chief = get_chief() if chief: chief.subordinates -= 1 queue_free() func promote_chief(): if not is_chief: is_chief = true if player: add_to_group("chief:" + player.code) promoted.emit() func set_chief(chief): if chief is Unit and chief.is_chief and chief != self: chief_ref = weakref(chief) chief.subordinates += 1 func list_chiefs(): return get_tree().get_nodes_in_group("chief:" + player.code)