extends Node2D const BEAM_DURATION := 3.0 const PRIMARY_TICK_DMG := 15 const SPLASH_TICK_DMG := 3 const TICK_INTERVAL := 0.5 @export var segment_size := 16.0 var beam_seg := preload("res://scenes/beam.tscn") var target: Node2D = null var all_segs: Array = [] var mid_segs: Array = [] var tick_timer := 0.0 var elapsed := 0.0 var done := false func _ready() -> void: target = get_highest_hp_enemy() if target == null: queue_free() return spawn_beam() func _process(delta: float) -> void: if done: return elapsed += delta tick_timer += delta if tick_timer >= TICK_INTERVAL: tick_timer -= TICK_INTERVAL do_damage_tick() if elapsed >= BEAM_DURATION: done = true cleanup() func spawn_beam() -> void: var origin := global_position var dest := target.global_position var dir := origin.direction_to(dest) var dist := origin.distance_to(dest) var angle := dir.angle() place_seg("start", origin, angle) var n_mid := int(max(0.0, dist - segment_size * 2.0) / segment_size) for i in range(n_mid): var pos := origin + dir * (segment_size * (float(i) + 1.0)) mid_segs.append(place_seg("middle", pos, angle)) place_seg("end", dest, angle) func place_seg(type: String, pos: Vector2, angle: float) -> Node: var seg = beam_seg.instantiate() seg.beam_type = type seg.global_position = pos seg.rotation = angle get_parent().add_child(seg) all_segs.append(seg) return seg func do_damage_tick() -> void: if is_instance_valid(target) and not target.is_dying: target.take_damage(PRIMARY_TICK_DMG) var hit: Array = [] for seg in mid_segs: if not is_instance_valid(seg): continue for body in seg.get_overlapping_bodies(): if body.is_in_group("enemies") and not body.is_dying \ and body != target and not hit.has(body): body.take_damage(SPLASH_TICK_DMG) hit.append(body) func cleanup() -> void: for seg in all_segs: if is_instance_valid(seg): seg.queue_free() queue_free() func get_highest_hp_enemy() -> Node: var best: Node = null var best_hp: int = -1 for enemy in get_tree().get_nodes_in_group("enemies"): if not is_instance_valid(enemy) or enemy.is_dying: continue if enemy.hp > best_hp: best_hp = enemy.hp best = enemy return best