using System;
using System.Collections.Generic;
using UnityEngine;
///
/// 이 인터페이스를 구현한 오브젝트가 데미지를 받는것에 대해서 나타내기 위함
///
public interface IDamageable
{
void TakeDamage(float damage);
}
///
/// 무기나 투사체에 붙여 동작에 대한 트리거를 ON/OFF 하는 컴포넌트.
///
///
///
///
///
public abstract class Damage : MonoBehaviour
{
[SerializeField] public LayerMask _targetlayer; // 공격 가능한 레이어 마스크
Collider _weaponCollider; // 공격 가능 시간만 활성화 되는 히트 센서로 활용하기 위해서 사용
protected readonly HashSet hitTargets = new HashSet();
// ToDo: 무기에 대한 여러 설정에 대한건 후에 Data_* 로 따로 관리
// 데미지, 다단히트, 히트 쿨타임, 넉백 등등
[SerializeField] private float _damage = 0f;
protected bool isActive = false; // 활성화 상태
public event Action OnHit;
protected virtual void Awake()
{
if (_weaponCollider == null) _weaponCollider = GetComponent();
if (_weaponCollider != null)
{
_weaponCollider.isTrigger = true;
_weaponCollider.enabled = false;
}
}
protected virtual bool LayerPassed(Collider target)
{
int layer = target.gameObject.layer;
return (_targetlayer.value & (1 << layer)) != 0;
}
protected void ApplyDamage(Collider target)
{
if(!isActive) return;
if(!LayerPassed(target)) return;
GameObject go = target.gameObject;
if(hitTargets.Contains(go)) return;
if (target.TryGetComponent(out IDamageable damagebable))
{
hitTargets.Add(go);
damagebable.TakeDamage(_damage);
OnHit?.Invoke(damagebable, target);
OnDamageApplied(target);
}
}
public void SetTriggerActive(bool active)
{
isActive = active;
if (_weaponCollider != null) _weaponCollider.enabled = active;
if (active) ResetHitCache();
}
protected void ResetHitCache() => hitTargets.Clear();
private void OnTriggerEnter(Collider other)
{
HandleCollision(other);
}
// 데미지 적용 후의 특화 동작 오버라이드 하기
protected virtual void OnDamageApplied(Collider target)
{
// 예: 피격 효과, 사운드 재생 등
// 투사체면 충돌시 파괴, 근접 무기면 히트 이펙트 재생이나 연속 공격 위해 아무것도 안하기
}
protected abstract void HandleCollision(Collider other);
}