class_name EnemyArtilleryComponent extends Node # Stationary siege piece: drifts slowly toward the fleet (deliberately no # pursuit component - closing distance is incidental, not its purpose) and # fires a slow, clearly visible AOE shell on a long cooldown via a # standalone ArtilleryShell, so an already-launched shot survives this # enemy dying mid-flight, same as EnemyProjectile/Projectile already do. var capability_id: String = "artillery" @export var fire_cooldown: float = 6.0 @export var fire_range: float = 900.0 @export var shell_speed: float = 180.0 @export var aoe_radius: float = 220.0 @export var damage: int = 3 @export var drift_speed: float = 20.0 @export var color: Color = Color(1.0, 0.5, 0.2) var cooldown_left: float = 0.0 var shell_scene: PackedScene = preload("res://enemies/ArtilleryShell.tscn") func tick(delta: float) -> void: var enemy: Node2D = get_parent() _drift(enemy, delta) cooldown_left -= delta if cooldown_left > 0.0: return var fleet: Node2D = get_tree().get_first_node_in_group("player_fleet") if fleet == null or fleet.ships.is_empty(): return var centroid: Vector2 = fleet.get_centroid() if enemy.global_position.distance_to(centroid) > fire_range: return var shell: Node2D = shell_scene.instantiate() shell.shell_speed = shell_speed shell.aoe_radius = aoe_radius shell.damage = damage shell.color = color enemy.get_tree().root.add_child(shell) shell.launch(enemy.global_position, centroid) cooldown_left = fire_cooldown func _drift(enemy: Node2D, delta: float) -> void: # Local position throughout, same convention as EnemyPursuitComponent/ # EnemyStandoffComponent: valid as long as the enemy's container and # Fleet share a common origin, which every scene in this project does. var fleet: Node2D = get_tree().get_first_node_in_group("player_fleet") if fleet == null or fleet.ships.is_empty(): return var to_fleet: Vector2 = fleet.get_centroid() - enemy.position # #69: gated by the same fire_range it already shells within, rather # than a second tunable that could drift out of sync - outside its own # firing envelope it has nothing to be drifting toward yet. if to_fleet.length() > fire_range: return if to_fleet.length() < 1.0: return enemy.position += to_fleet.normalized() * drift_speed * delta