## EnemyBulletManager — 敌方子弹管理器 Autoload（伤害玩家）
## 平行于 BulletManager（玩家子弹 vs 敌人）；本池每帧检测 vs 玩家。
## SoA 布局（ENEMY_BULLET_STRIDE=7）：[ x, y, vx, vy, lifetime, radius, damage ]
##   0  1   2   3      4        5       6
extends Node

const ENEMY_BULLET_STRIDE: int = 7      # 禁裸整数
const MAX_ENEMY_BULLETS:   int = 1024
const PLAYER_HIT_RADIUS:   float = 12.0 # 玩家碰撞半径估算（与玩家标记视觉一致）

var _data: PackedFloat32Array = PackedFloat32Array()
var _active_count: int = 0

func _ready() -> void:
	_data.resize(MAX_ENEMY_BULLETS * ENEMY_BULLET_STRIDE)
	_data.fill(0.0)

func _physics_process(delta: float) -> void:
	var player: Vector2 = PlayerManager.get_position()
	var i: int = 0
	while i < _active_count:
		var base: int = i * ENEMY_BULLET_STRIDE
		_data[base + 0] += _data[base + 2] * delta
		_data[base + 1] += _data[base + 3] * delta
		_data[base + 4] -= delta
		if _data[base + 4] <= 0.0:
			_swap_and_pop(i)
			continue
		var dx: float = _data[base + 0] - player.x
		var dy: float = _data[base + 1] - player.y
		var rr: float = _data[base + 5] + PLAYER_HIT_RADIUS
		if dx * dx + dy * dy <= rr * rr:
			PlayerStats.take_damage(_data[base + 6])
			VFXManager.play("hit_spark", Vector2(_data[base + 0], _data[base + 1]))
			_swap_and_pop(i)
			continue
		i += 1

func _swap_and_pop(idx: int) -> void:
	if _active_count <= 0:
		return  # 防重入：玩家死亡致命一击触发 reset() 已清空池，勿再 -1
	var last: int = _active_count - 1
	if idx != last:
		var b_i: int = idx * ENEMY_BULLET_STRIDE
		var b_l: int = last * ENEMY_BULLET_STRIDE
		for s in ENEMY_BULLET_STRIDE:
			_data[b_i + s] = _data[b_l + s]
	_active_count -= 1

## 生成敌方子弹，返回 id（满容返回 -1）
func spawn_bullet(pos: Vector2, vel: Vector2, lifetime: float, radius: float, damage: float) -> int:
	if _active_count >= MAX_ENEMY_BULLETS:
		return -1
	var id: int = _active_count
	var base: int = id * ENEMY_BULLET_STRIDE
	_data[base + 0] = pos.x
	_data[base + 1] = pos.y
	_data[base + 2] = vel.x
	_data[base + 3] = vel.y
	_data[base + 4] = lifetime
	_data[base + 5] = radius
	_data[base + 6] = damage
	_active_count += 1
	return id

func get_active_count() -> int:
	return _active_count

## 渲染：SoA 位置 → MultiMesh（与 BulletManager.sync_multimesh 同法）
func sync_multimesh(mm: MultiMesh) -> void:
	if mm == null:
		return
	var n: int = min(_active_count, mm.instance_count)
	mm.visible_instance_count = n
	for i in n:
		var base: int = i * ENEMY_BULLET_STRIDE
		var r: float = _data[base + 5]
		mm.set_instance_transform_2d(i, Transform2D(
			0.0, Vector2(r * 2.0, r * 2.0), 0.0,
			Vector2(_data[base + 0], _data[base + 1])))

func reset() -> void:
	_active_count = 0
	_data.fill(0.0)
