class_name EnemyRangedWeaponComponent extends Node # Same shape as VesselWeaponComponent, mirrored for an enemy: fires an # EnemyProjectile at the nearest player ship's CURRENT position, not led, # so a moving ship can dodge it. var capability_id: String = "ranged_weapon" @export var fire_range: float = 700.0 @export var fire_cooldown: float = 2.2 @export var projectile_speed: float = 260.0 @export var damage: int = 1 var fire_timer: float = 0.0 var projectile_scene: PackedScene = preload("res://enemies/EnemyProjectile.tscn") func tick(delta: float) -> void: fire_timer -= delta if fire_timer > 0.0: return var enemy: Node2D = get_parent() var target: Node2D = _nearest_ship_in_range(enemy) if target == null: fire_timer = 0.25 return var projectile: Area2D = projectile_scene.instantiate() # global_position: the projectile is reparented to root, a different # node than the enemy's own (possibly nested) parent, so local # position would be wrong the moment an enemy isn't a direct root # child - exactly the case #44 introduced (planet-surface hosting). projectile.position = enemy.global_position projectile.damage = damage projectile.speed = projectile_speed enemy.get_tree().root.add_child(projectile) projectile.launch(target.global_position - enemy.global_position) fire_timer = fire_cooldown # #101: shoots at whatever EnemyTargets says it is coming for, so a sniper # shells a depot rather than sitting in range of one doing nothing. func _nearest_ship_in_range(enemy: Node2D) -> Node2D: var target: Node2D = EnemyTargets.nearest_target(self, enemy.global_position) if target == null: return null if enemy.global_position.distance_to(target.global_position) > fire_range: return null return target