Projext/Assets/Scripts/Core/Utils/StatusEffectProcessor.cs

156 lines
9.4 KiB
C#
Raw Permalink Normal View History

2026-02-13 09:11:54 +00:00
using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
using UnityEngine.AI; // 내비게이션 기능을 불러올거에요 -> UnityEngine.AI를
using System.Collections; // 코루틴을 사용할거에요 -> System.Collections를
/// <summary>
2026-02-21 06:14:24 +00:00
/// 화상, 독, 슬로우, 감전 등의 상태이상을 전담 처리하는 클래스
/// [UPGRADED] 틱 간격(tickInterval) 지원 오버로드 + ApplyPoison 추가
2026-02-13 09:11:54 +00:00
/// </summary>
public class StatusEffectProcessor // 클래스를 선언할거에요 -> 상태이상 로직을 담당하는 클래스를
{
private readonly MonoBehaviour _owner; // 변수를 선언할거에요 -> 코루틴 실행 주체를
private readonly IDamageable _damageable; // 변수를 선언할거에요 -> 데미지 인터페이스를
private readonly NavMeshAgent _agent; // 변수를 선언할거에요 -> 이동 에이전트를
private readonly Animator _animator; // 변수를 선언할거에요 -> 애니메이터를
public StatusEffectProcessor(MonoBehaviour owner, IDamageable damageable, NavMeshAgent agent, Animator animator) // 생성자를 만들거에요 -> 의존성 주입을 위한
{
_owner = owner; // 값을 저장할거에요 -> 주인을
_damageable = damageable; // 값을 저장할거에요 -> 데미지 대상을
_agent = agent; // 값을 저장할거에요 -> 에이전트를
_animator = animator; // 값을 저장할거에요 -> 애니메이터를
}
2026-02-21 06:14:24 +00:00
// ─────────────────────────────────────────────────────────
// 화상 (Burn)
// ─────────────────────────────────────────────────────────
2026-02-13 09:11:54 +00:00
2026-02-21 06:14:24 +00:00
/// <summary>
/// [기존] 화상 — 2-파라미터 (하위 호환, 기본 틱 간격 0.5초)
/// </summary>
public void ApplyBurn(float damage, float duration) // 함수를 선언할거에요 -> 화상 적용을 (2-파라미터 버전)
2026-02-13 09:11:54 +00:00
{
2026-02-21 06:14:24 +00:00
_owner.StartCoroutine(DotRoutine("화상", damage, duration, 0.5f)); // 실행할거에요 -> 기본 틱 간격 0.5초로 도트 코루틴을
}
/// <summary>
/// [NEW] 화상 — 3-파라미터 (틱 간격 지정 가능)
/// </summary>
public void ApplyBurn(float damagePerTick, float duration, float tickInterval) // 함수를 선언할거에요 -> 화상 적용을 (3-파라미터 버전)
{
_owner.StartCoroutine(DotRoutine("화상", damagePerTick, duration, tickInterval)); // 실행할거에요 -> 지정 틱 간격으로 도트 코루틴을
}
// ─────────────────────────────────────────────────────────
// 독 (Poison)
// ─────────────────────────────────────────────────────────
/// <summary>
/// [NEW] 독 — 2-파라미터 (기본 틱 간격 1초)
/// </summary>
public void ApplyPoison(float damage, float duration) // 함수를 선언할거에요 -> 독 적용을 (2-파라미터 버전)
{
_owner.StartCoroutine(DotRoutine("독", damage, duration, 1f)); // 실행할거에요 -> 기본 틱 간격 1초로 도트 코루틴을
}
/// <summary>
/// [NEW] 독 — 3-파라미터 (틱 간격 지정 가능)
/// </summary>
public void ApplyPoison(float damagePerTick, float duration, float tickInterval) // 함수를 선언할거에요 -> 독 적용을 (3-파라미터 버전)
{
_owner.StartCoroutine(DotRoutine("독", damagePerTick, duration, tickInterval)); // 실행할거에요 -> 지정 틱 간격으로 도트 코루틴을
}
// ─────────────────────────────────────────────────────────
// 슬로우 (Slow)
// ─────────────────────────────────────────────────────────
/// <summary>
/// [기존] 슬로우 — 2-파라미터
/// amount: 감속 비율 (0~1 사이 값 또는 0~100 사이 값 모두 지원)
/// </summary>
public void ApplySlow(float amount, float duration) // 함수를 선언할거에요 -> 슬로우 적용을
{
_owner.StartCoroutine(SlowRoutine(amount, duration)); // 실행할거에요 -> 슬로우 코루틴을
}
// ─────────────────────────────────────────────────────────
// 감전/스턴 (Shock)
// ─────────────────────────────────────────────────────────
/// <summary>
/// [기존] 감전 — 즉발 데미지 + 스턴
/// </summary>
public void ApplyShock(float damage, float duration) // 함수를 선언할거에요 -> 감전 적용을
{
_damageable.TakeDamage(damage); // 실행할거에요 -> 즉발 데미지를
_owner.StartCoroutine(StunRoutine(duration)); // 실행할거에요 -> 스턴 코루틴을
}
// ─────────────────────────────────────────────────────────
// 코루틴들
// ─────────────────────────────────────────────────────────
/// <summary>
/// [NEW] 통합 도트 데미지 코루틴 — 화상/독 모두 이것을 사용
/// damagePerTick: 1틱당 데미지
/// duration: 총 지속 시간 (초)
/// tickInterval: 틱 간격 (초)
/// </summary>
private IEnumerator DotRoutine(string effectName, float damagePerTick, float duration, float tickInterval) // 코루틴을 정의할거에요 -> 통합 도트 데미지 로직을
{
if (tickInterval <= 0f) tickInterval = 0.5f; // 안전장치를 넣을거에요 -> 틱 간격이 0 이하면 0.5초로
float elapsed = 0f; // 변수를 초기화할거에요 -> 경과 시간을 0으로
Debug.Log($"[StatusEffect] {effectName} 시작! 틱당:{damagePerTick} 간격:{tickInterval}초 지속:{duration}초"); // 로그를 출력할거에요 -> 효과 시작 안내를
while (elapsed < duration) // 반복할거에요 -> 지속 시간이 끝날 때까지
2026-02-13 09:11:54 +00:00
{
2026-02-21 06:14:24 +00:00
_damageable.TakeDamage(damagePerTick); // 실행할거에요 -> 1틱 데미지를
yield return new WaitForSeconds(tickInterval); // 기다릴거에요 -> 틱 간격만큼
elapsed += tickInterval; // 값을 더할거에요 -> 경과 시간에 틱 간격을
2026-02-13 09:11:54 +00:00
}
2026-02-21 06:14:24 +00:00
Debug.Log($"[StatusEffect] {effectName} 종료!"); // 로그를 출력할거에요 -> 효과 종료 안내를
2026-02-13 09:11:54 +00:00
}
2026-02-21 06:14:24 +00:00
/// <summary>
/// [기존] 슬로우 코루틴
/// amount가 1 이하면 비율로(0.5 = 50% 감속), 1 초과면 퍼센트로(50 = 50% 감속)
/// </summary>
private IEnumerator SlowRoutine(float amount, float duration) // 코루틴을 정의할거에요 -> 슬로우 로직을
2026-02-13 09:11:54 +00:00
{
if (_agent == null) yield break; // 조건이 맞으면 종료할거에요 -> 에이전트가 없으면
2026-02-21 06:14:24 +00:00
2026-02-13 09:11:54 +00:00
float orgSpeed = _agent.speed; // 값을 저장할거에요 -> 원래 속도를
2026-02-21 06:14:24 +00:00
// amount 해석: 1 이하면 비율(0.5 = 50% 감속), 1 초과면 퍼센트(50 = 50% 감속)
float slowRate = amount > 1f ? Mathf.Clamp01(amount / 100f) : Mathf.Clamp01(amount); // 값을 계산할거에요 -> 감속 비율을
_agent.speed *= (1f - slowRate); // 값을 바꿀거에요 -> 속도를 줄여서
Debug.Log($"[StatusEffect] 슬로우! 원래:{orgSpeed} → 감속:{_agent.speed} ({slowRate * 100}% 감속) {duration}초간"); // 로그를 출력할거에요 -> 슬로우 내역을
2026-02-13 09:11:54 +00:00
yield return new WaitForSeconds(duration); // 기다릴거에요 -> 지속 시간만큼
_agent.speed = orgSpeed; // 값을 복구할거에요 -> 원래 속도로
2026-02-21 06:14:24 +00:00
Debug.Log($"[StatusEffect] 슬로우 해제! 속도 복구: {orgSpeed}"); // 로그를 출력할거에요 -> 해제 안내를
2026-02-13 09:11:54 +00:00
}
2026-02-21 06:14:24 +00:00
/// <summary>
/// [기존] 스턴 코루틴 — 이동 정지 + 애니 멈춤
/// </summary>
private IEnumerator StunRoutine(float duration) // 코루틴을 정의할거에요 -> 스턴 로직을
2026-02-13 09:11:54 +00:00
{
if (_agent != null) _agent.isStopped = true; // 명령을 내릴거에요 -> 이동 정지를
if (_animator != null) _animator.speed = 0; // 값을 바꿀거에요 -> 애니 속도를 0으로
2026-02-21 06:14:24 +00:00
Debug.Log($"[StatusEffect] 스턴! {duration}초간 행동 불능"); // 로그를 출력할거에요 -> 스턴 안내를
2026-02-13 09:11:54 +00:00
yield return new WaitForSeconds(duration); // 기다릴거에요 -> 스턴 시간만큼
2026-02-21 06:14:24 +00:00
2026-02-13 09:11:54 +00:00
if (_agent != null && _agent.isOnNavMesh) _agent.isStopped = false; // 명령을 내릴거에요 -> 이동 재개를
if (_animator != null) _animator.speed = 1; // 값을 바꿀거에요 -> 애니 속도 복구를
2026-02-21 06:14:24 +00:00
Debug.Log($"[StatusEffect] 스턴 해제!"); // 로그를 출력할거에요 -> 해제 안내를
2026-02-13 09:11:54 +00:00
}
}