gae_wild_jam/scripts/laser.gd

92 lines
2.2 KiB
GDScript

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