using System.Collections.Generic;
using UnityEngine;
using Platformer.Mechanics;
using Platformer.Gameplay;
using static Platformer.Core.Simulation;
namespace EerieVillage.Skills.Effectors
{
///
/// A04 번개 충격 Effector — IEffector 구현.
/// PD 지시 (2026-05-13):
/// - 2.5초 주기 (BaseCooldown 2.5)
/// - 화면 내 보이는 임의의 몬스터 1기 타격
/// - BaseDamage 15
/// - 타격 지점 영역 좁은 범위 (HitboxSize) 내 다른 적도 함께 피해
/// - 이펙트: data.OnHitFxPrefab (FX_Thunder)
///
/// 화면 내 검출 — Camera.main 영역 OrthographicSize·aspect 기반 좌·우·상·하 영역 측정.
///
public class LightningStrikeSpawner : IEffector
{
public void Trigger(ActiveSkillRuntime runtime, PlayerSkillInventory inventory)
{
var data = runtime.ActiveData;
// 1. 화면 내 Enemy 후보 수집
var cam = Camera.main;
if (cam == null) return;
float halfH = cam.orthographicSize;
float halfW = halfH * cam.aspect;
Vector2 camPos = cam.transform.position;
float xMin = camPos.x - halfW, xMax = camPos.x + halfW;
float yMin = camPos.y - halfH, yMax = camPos.y + halfH;
var enemies = Object.FindObjectsByType(FindObjectsSortMode.None);
var candidates = new List();
foreach (var e in enemies)
{
if (e == null) continue;
var h = e.GetComponent();
if (h == null || !h.IsAlive) continue;
var p = e.transform.position;
if (p.x < xMin || p.x > xMax || p.y < yMin || p.y > yMax) continue;
candidates.Add(e);
}
if (candidates.Count == 0) return;
// 2. 임의 1기 선택 (Primary target)
var primary = candidates[Random.Range(0, candidates.Count)];
Vector2 strikePos = primary.transform.position;
// 3. 이펙트 spawn (data.OnHitFxPrefab — FX_Thunder) + 총 lifetime 측정
float fxTotalLifetime = 1f;
if (data.OnHitFxPrefab != null)
{
var fx = Object.Instantiate(data.OnHitFxPrefab, strikePos, Quaternion.identity);
// PD 지시 2026-05-13 — 번개 이펙트 크기 20% 축소
fx.transform.localScale *= 0.2f;
fxTotalLifetime = GetFxLifetime(fx);
AutoDestroyFx(fx, fxTotalLifetime);
}
// 4. PD 지시 2026-05-13 — 이펙트 총 lifetime 의 4/5 시점에 데미지 판정 (이펙트 강타 정합)
int damage = Mathf.Max(runtime.CalculateEffectiveDamage(), data.BaseDamage);
float radius = Mathf.Max(data.HitboxSize.x, data.HitboxSize.y);
float damageDelay = fxTotalLifetime * 0.8f;
inventory.StartCoroutine(DelayedDamage(strikePos, radius, damage, primary, candidates, damageDelay));
}
// PD 지시 2026-05-13 — FX_Thunder 영역 root PS 영역 wrapper (10s) 이므로 자식 PS 영역 영역 영역 영역
// 자식 PS 평균 lifetime 영역 시각 정합 (강타 자식 영역 약 1초 내외).
static float GetFxLifetime(GameObject fxGo)
{
if (fxGo == null) return 1f;
var psList = fxGo.GetComponentsInChildren(true);
float sum = 0f;
int n = 0;
foreach (var ps in psList)
{
// root PS 제외 (wrapper)
if (ps.transform == fxGo.transform) continue;
var main = ps.main;
float t = main.duration + main.startLifetime.constantMax;
sum += t;
n++;
}
if (n == 0) return 1f;
return sum / n;
}
static System.Collections.IEnumerator DelayedDamage(Vector2 strikePos, float radius, int damage, EnemyController primary, List candidates, float delay)
{
yield return new WaitForSeconds(delay);
foreach (var e in candidates)
{
if (e == null) continue;
if (Vector2.Distance(e.transform.position, strikePos) > radius && e != primary) continue;
var h = e.GetComponent();
if (h == null || !h.IsAlive) continue;
h.Decrement(damage);
if (!h.IsAlive)
{
Schedule().enemy = e;
}
}
}
static void AutoDestroyFx(GameObject fxGo, float lifetime)
{
if (fxGo == null) return;
Object.Destroy(fxGo, lifetime + 0.2f);
}
}
}