class_name ShootComponent extends Node @onready var weapon_component: Node = %WeaponComponent @onready var player = $".." @onready var ship: Sprite2D = get_node("../Ship") @onready var fire_helper: WeaponFireHelper = %WeaponFireHelper func shoot(): var weapon_data = weapon_component.weapon_data var current_time = Time.get_ticks_msec() / 1000.0 if player.travel > weapon_data.projectile_vertical_spacing: _shoot_standard(weapon_data, current_time) _shoot_grouped(weapon_data, current_time) # Reset travel after firing to prevent multiple bursts per tap player.travel = 0.0 # Standard projectile logic (delegates to WeaponFireHelper) func _shoot_standard(weapon_data: WeaponShot, current_time: float): var total_projectiles: int = weapon_data.projectiles if total_projectiles > 0: for b in range(total_projectiles): var bullet := weapon_data.bullet_scene.instantiate() as Area2D get_tree().root.add_child(bullet) # Delegate math to the helper, with spawn position offset by weapon origin var spawn_position = ship.global_position + weapon_data.origin var props = fire_helper.compute_standard_props(weapon_data, b, spawn_position, current_time) bullet.position = props.position bullet.angle = props.angle bullet.time_offset = props.time_offset bullet.fire_time = props.fire_time # Set the bullet data bullet.set_weapon_data(weapon_data.bullet_scene, weapon_data) # Offset animation playback per projectile if enabled if weapon_data.stagger_animation: bullet.set_animation_offset(props.animation_offset) # Grouped projectile logic (delegates to WeaponFireHelper) func _shoot_grouped(weapon_data: WeaponShot, current_time: float): for group: WeaponProjectileGroup in weapon_data.groups.filter(func(g): return g != null): for b in range(group.bullet_count): var bullet := weapon_data.bullet_scene.instantiate() as Area2D get_tree().root.add_child(bullet) # Apply computed properties for the original bullet var spawn_position = ship.global_position + weapon_data.origin var props = fire_helper.compute_grouped_props(group, weapon_data, b, spawn_position, current_time, false) bullet.position = props.position bullet.angle = props.angle bullet.time_offset = props.time_offset bullet.fire_time = props.fire_time bullet.set_weapon_data(weapon_data.bullet_scene, weapon_data) if weapon_data.stagger_animation: bullet.set_animation_offset(props.animation_offset) # If mirroring is enabled, fire a mirrored copy if group.mirror: var mirror_bullet := weapon_data.bullet_scene.instantiate() as Area2D get_tree().root.add_child(mirror_bullet) # Apply computed properties for the mirrored bullet var mirror_spawn = ship.global_position + weapon_data.origin var mirror_props = fire_helper.compute_grouped_props(group, weapon_data, b, mirror_spawn, current_time, true) mirror_bullet.position = mirror_props.position mirror_bullet.angle = mirror_props.angle mirror_bullet.time_offset = mirror_props.time_offset mirror_bullet.fire_time = mirror_props.fire_time mirror_bullet.set_weapon_data(weapon_data.bullet_scene, weapon_data) if weapon_data.stagger_animation: mirror_bullet.set_animation_offset(mirror_props.animation_offset)