EerieVillage/Assets/Scripts/Skills/Effectors/StatusApplier.cs

87 lines
3.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using Platformer.Mechanics;
namespace EerieVillage.Skills.Effectors
{
/// <summary>
/// 상태 효과 일괄 적용기.
/// Projectile.OnTriggerEnter2D 등 타격 판정 후 ActiveSkillData 필드를 읽어
/// DoT·Stun·Slow·Knockback·DebuffStack 을 EnemyController 에 적용한다.
/// BT12-Dev Phase 2-B §4-5.
/// </summary>
public static class StatusApplier
{
public static void Apply(ActiveSkillData data, EnemyController enemy)
{
if (data == null || enemy == null) return;
// DoT (화염·독 등) — DotInterval > 0 영역만 발화 (DotDuration 영역 OnDotFxPrefab.ParticleSystem.main.duration 영역 자동 영역)
// BT12-Dev 2026-05-13 — damage = BaseDamage × DotDamageMultiplier (PD 영역: 25%) + OnDotFxPrefab 자식 spawn
if ((data.DotDuration > 0f || data.OnDotFxPrefab != null) && data.DotInterval > 0f)
{
int dotDamage = Mathf.Max(1, Mathf.RoundToInt(data.BaseDamage * data.DotDamageMultiplier));
ApplyDoT(enemy, dotDamage, data.DotDuration, data.DotInterval, data.OnDotFxPrefab, data.DotFxScale);
}
// 기절 (스턴)
if (data.StunDuration > 0f)
{
ApplyStun(enemy, data.StunDuration);
}
// 감속 (슬로우)
if (data.SlowDuration > 0f && data.SlowMultiplier < 1.0f)
{
ApplySlow(enemy, data.SlowDuration, data.SlowMultiplier);
}
// 넉백
if (data.KnockbackForce > 0f)
{
ApplyKnockback(enemy, data.KnockbackForce);
}
// 저주 스택 (A08 저주의 화살)
if (data.DebuffStackLimit > 0)
{
DebuffStack.AddStack(enemy, data.DebuffStackLimit, data.BaseDamage);
}
}
// -------------------------------------------------------------------
// 내부 헬퍼
// -------------------------------------------------------------------
private static void ApplyDoT(EnemyController enemy, int damagePerTick, float duration, float interval, GameObject fxPrefab = null, float fxScale = 1f)
{
var existing = enemy.GetComponent<EnemyDoTState>();
if (existing == null) existing = enemy.gameObject.AddComponent<EnemyDoTState>();
existing.AddDoT(damagePerTick, duration, interval, fxPrefab, fxScale);
}
private static void ApplyStun(EnemyController enemy, float duration)
{
var existing = enemy.GetComponent<EnemyStunState>();
if (existing == null) existing = enemy.gameObject.AddComponent<EnemyStunState>();
existing.ApplyStun(duration);
}
private static void ApplySlow(EnemyController enemy, float duration, float multiplier)
{
var existing = enemy.GetComponent<EnemySlowState>();
if (existing == null) existing = enemy.gameObject.AddComponent<EnemySlowState>();
existing.ApplySlow(duration, multiplier);
}
private static void ApplyKnockback(EnemyController enemy, float force)
{
var rb = enemy.GetComponent<Rigidbody2D>();
if (rb != null)
{
// facing 반대 방향 넉백 — 단순 +x 방향 (Phase 2 범위, Phase 2-C에서 방향 정합 예정)
rb.AddForce(Vector2.right * force, ForceMode2D.Impulse);
}
}
}
}