spaceship/boss/BossMinion.gd
2026-09-03 11:49:51 +02:00

105 lines
2.7 KiB
GDScript

class_name BossMinion
extends Area2D
signal destroyed
const COMBAT_TARGET = preload("res://core/CombatTarget.gd")
@export var marked: bool = false
@export var max_hp: int = 5
@export var speed: float = 245.0
@export var acceleration: float = 520.0
var boss: Node2D
const REDRAW_INTERVAL: float = 1.0 / 12.0
var hp: int = 5
var velocity: Vector2 = Vector2.ZERO
var phase: float = 0.0
var dead: bool = false
var redraw_left: float = 0.0
var fleet: Node2D = null
func _ready() -> void:
hp = max_hp
add_to_group("enemies")
add_to_group("boss_minions")
COMBAT_TARGET.register(self, COMBAT_TARGET.DANGER_PRIORITY)
phase = randf() * TAU
fleet = get_tree().get_first_node_in_group("player_fleet")
queue_redraw()
func _physics_process(delta: float) -> void:
phase += delta
if not is_instance_valid(fleet):
fleet = get_tree().get_first_node_in_group("player_fleet")
if fleet != null and not fleet.ships.is_empty():
var to_fleet: Vector2 = fleet.get_centroid() - global_position
if to_fleet.length() > 1.0:
velocity = velocity.move_toward(to_fleet.normalized() * speed,
acceleration * delta)
global_position += velocity * delta
if velocity.length() > 4.0:
rotation = lerp_angle(rotation, velocity.angle() + PI / 2.0,
7.0 * delta)
redraw_left -= delta
if redraw_left <= 0.0:
redraw_left = REDRAW_INTERVAL
queue_redraw()
func take_damage(amount: int) -> bool:
if dead:
return false
hp -= maxi(amount, 1)
if hp > 0:
return false
_die(true)
return true
func collide_with_player_vessel() -> void:
_die(false)
func retire() -> void:
if dead:
return
dead = true
hp = 0
destroyed.emit()
queue_free()
func _die(killed_by_player: bool) -> void:
if dead:
return
dead = true
hp = 0
if killed_by_player and marked and is_instance_valid(boss):
boss.accept_marked_kill(global_position)
EnemyExplosionVFX.spawn(get_tree().root, global_position)
Sfx.play(get_tree(), Sfx.ENEMY_DEATH)
destroyed.emit()
queue_free()
func _draw() -> void:
var glow := Color(1.0, 0.78, 0.18) if marked else Color(0.9, 0.16, 0.58)
var core := Color(0.13, 0.01, 0.09)
# A small bulb with four streaming arms: recognisably related to the boss,
# but compact enough to read among an entire wave.
draw_set_transform(Vector2.ZERO, 0.0, Vector2(1.0, 0.76))
NeonDraw.draw_glowing_circle(self, Vector2(0, -7), 13.0, glow, 1.0, core)
draw_set_transform(Vector2.ZERO, 0.0, Vector2.ONE)
for i in range(4):
var x: float = -12.0 + float(i) * 8.0
var curl: float = sin(phase * 5.0 + float(i)) * 5.0
NeonDraw.draw_glowing_path(self, PackedVector2Array([
Vector2(x, 1), Vector2(x + curl * 0.35, 10), Vector2(x + curl, 21),
]), glow, 0.85, 0.35, core)
if marked:
NeonDraw.draw_glowing_circle(self, Vector2(0, -8), 4.0,
Color.WHITE, 1.0, core)