@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 @export var rotation_offset := 0.0 var chief_ref := WeakRef.new() var target_reached = true var target_position := Vector2.ZERO 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 _physics_process(delta): if not target_reached: # TODO use position instead of global_position, once parented to battlefield var previous = global_position global_position += (target_position - global_position).normalized() * 100.0 * delta var diff = global_position - previous if diff.length() > 0.01: $sprite.rotation = rotation_offset + diff.angle() if global_position.distance_to(target_position) < 5.0: target_reached = true 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)