2026-01-29 06:58:38 +00:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using System;
|
2026-02-02 15:02:12 +00:00
|
|
|
|
using System.Collections;
|
2026-01-29 06:58:38 +00:00
|
|
|
|
|
|
|
|
|
|
public class PlayerHealth : MonoBehaviour, IDamageable
|
|
|
|
|
|
{
|
2026-02-02 15:02:12 +00:00
|
|
|
|
[Header("=== 참조 ===")]
|
2026-01-29 06:58:38 +00:00
|
|
|
|
[SerializeField] private Stats stats;
|
2026-01-29 16:11:10 +00:00
|
|
|
|
[SerializeField] private Animator animator;
|
2026-02-10 08:04:33 +00:00
|
|
|
|
[SerializeField] private PlayerAttack attackScript;
|
|
|
|
|
|
|
|
|
|
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
// 🔗 보스 패턴 스크립트 연결 (Inspector에서 할당)
|
|
|
|
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
[Header("🔗 보스 패턴 연결")]
|
|
|
|
|
|
public BossPatternPhases bossPattern;
|
2026-01-29 06:58:38 +00:00
|
|
|
|
|
|
|
|
|
|
public bool IsDead { get; private set; }
|
2026-01-29 16:11:10 +00:00
|
|
|
|
public bool isHit { get; private set; }
|
2026-02-01 15:49:12 +00:00
|
|
|
|
public bool isInvincible; // 대시 중 무적 플래그
|
2026-01-29 06:58:38 +00:00
|
|
|
|
|
2026-02-02 15:02:12 +00:00
|
|
|
|
public event Action OnHitEvent, OnDead;
|
2026-01-29 06:58:38 +00:00
|
|
|
|
public event Action<float, float> OnHealthChanged;
|
|
|
|
|
|
|
|
|
|
|
|
private float _currentHealth;
|
|
|
|
|
|
|
2026-02-01 15:49:12 +00:00
|
|
|
|
private IEnumerator Start()
|
2026-01-29 06:58:38 +00:00
|
|
|
|
{
|
2026-02-01 15:49:12 +00:00
|
|
|
|
yield return null;
|
|
|
|
|
|
|
2026-01-29 06:58:38 +00:00
|
|
|
|
if (stats != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_currentHealth = stats.MaxHealth;
|
|
|
|
|
|
OnHealthChanged?.Invoke(_currentHealth, stats.MaxHealth);
|
2026-02-01 15:49:12 +00:00
|
|
|
|
Debug.Log($"<color=cyan>[UI Sync]</color> 초기 체력 설정 완료: {_currentHealth}/{stats.MaxHealth}");
|
2026-01-29 06:58:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (animator == null) animator = GetComponent<Animator>();
|
2026-02-02 15:02:12 +00:00
|
|
|
|
if (attackScript == null) attackScript = GetComponent<PlayerAttack>();
|
2026-01-29 06:58:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-29 16:11:10 +00:00
|
|
|
|
public void RefreshHealthUI()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (stats != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_currentHealth = Mathf.Min(_currentHealth, stats.MaxHealth);
|
2026-02-01 15:49:12 +00:00
|
|
|
|
OnHealthChanged?.Invoke(_currentHealth, stats.MaxHealth);
|
2026-01-29 16:11:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-10 08:04:33 +00:00
|
|
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
// ⭐ 데미지를 받는 함수
|
|
|
|
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
2026-01-29 06:58:38 +00:00
|
|
|
|
public void TakeDamage(float amount)
|
|
|
|
|
|
{
|
2026-02-10 08:04:33 +00:00
|
|
|
|
// 무적이거나 이미 죽었으면 데미지 무시
|
2026-02-01 15:49:12 +00:00
|
|
|
|
if (isInvincible || IsDead) return;
|
2026-02-02 15:02:12 +00:00
|
|
|
|
|
2026-01-29 06:58:38 +00:00
|
|
|
|
_currentHealth = Mathf.Max(0, _currentHealth - amount);
|
|
|
|
|
|
OnHealthChanged?.Invoke(_currentHealth, stats.MaxHealth);
|
2026-02-02 15:02:12 +00:00
|
|
|
|
|
2026-02-10 08:04:33 +00:00
|
|
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
// 🔗 NEW: 보스 패턴 시스템에 "피격당함"을 알림
|
|
|
|
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
if (bossPattern != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
// BossPatternPhases 스크립트의 OnPlayerHit() 함수 호출
|
|
|
|
|
|
// 이 함수 안에서 "패턴 진행 중인지" 체크하고 XP 감점 처리
|
|
|
|
|
|
bossPattern.OnPlayerHit();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-02 15:02:12 +00:00
|
|
|
|
// ⭐ 피격 시 트리거 및 상태 리셋 함수 호출
|
|
|
|
|
|
OnHit();
|
|
|
|
|
|
|
|
|
|
|
|
OnHitEvent?.Invoke(); // 이벤트 발생
|
|
|
|
|
|
|
2026-01-29 06:58:38 +00:00
|
|
|
|
if (!IsDead) StartHit();
|
|
|
|
|
|
if (_currentHealth <= 0) Die();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-02 15:02:12 +00:00
|
|
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
2026-02-10 08:04:33 +00:00
|
|
|
|
// ⭐ 피격 시 공격 상태 리셋
|
2026-02-02 15:02:12 +00:00
|
|
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
public void OnHit()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (animator != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. 남아있는 공격 트리거를 강제로 꺼버림 (유령 공격 방지)
|
|
|
|
|
|
animator.ResetTrigger("Attack");
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 다른 공격(예: 투척) 트리거가 있다면 그것도 리셋
|
|
|
|
|
|
animator.ResetTrigger("Throw");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 3. PlayerAttack 스크립트의 공격 중인 상태 플래그도 강제로 꺼줌
|
|
|
|
|
|
if (attackScript != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
attackScript.IsAttacking = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Debug.Log("<color=yellow>[Combat]</color> 피격으로 인해 공격 예약 및 상태가 초기화되었습니다.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-29 06:58:38 +00:00
|
|
|
|
private void StartHit()
|
|
|
|
|
|
{
|
|
|
|
|
|
isHit = true;
|
2026-02-02 15:02:12 +00:00
|
|
|
|
// 인스펙터에 적힌 피격 애니메이션 이름(HitAnime) 재생
|
2026-01-29 16:11:10 +00:00
|
|
|
|
if (animator != null) animator.Play("HitAnime", 0, 0f);
|
2026-02-02 15:02:12 +00:00
|
|
|
|
|
2026-01-29 06:58:38 +00:00
|
|
|
|
CancelInvoke(nameof(OnHitEnd));
|
2026-02-01 15:49:12 +00:00
|
|
|
|
Invoke(nameof(OnHitEnd), 0.25f);
|
2026-01-29 06:58:38 +00:00
|
|
|
|
}
|
2026-02-02 15:02:12 +00:00
|
|
|
|
|
2026-01-29 16:11:10 +00:00
|
|
|
|
public void OnHitEnd() { isHit = false; }
|
|
|
|
|
|
|
2026-02-10 08:04:33 +00:00
|
|
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
// ⭐ 사망 처리
|
|
|
|
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
2026-02-02 15:02:12 +00:00
|
|
|
|
private void Die()
|
|
|
|
|
|
{
|
|
|
|
|
|
IsDead = true;
|
|
|
|
|
|
Cursor.visible = true;
|
|
|
|
|
|
Cursor.lockState = CursorLockMode.None;
|
|
|
|
|
|
OnDead?.Invoke();
|
2026-02-10 08:04:33 +00:00
|
|
|
|
|
|
|
|
|
|
// ★ ★ ★ NEW: 사망 시 임시 XP를 영구 XP로 전환 ★ ★ ★
|
|
|
|
|
|
if (ObsessionSystem.instance != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
ObsessionSystem.instance.OnDeathConvertXP();
|
|
|
|
|
|
}
|
2026-02-02 15:02:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Heal(float amount)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (IsDead) return;
|
|
|
|
|
|
_currentHealth = Mathf.Min(_currentHealth + amount, stats.MaxHealth);
|
|
|
|
|
|
OnHealthChanged?.Invoke(_currentHealth, stats.MaxHealth);
|
|
|
|
|
|
}
|
2026-01-29 06:58:38 +00:00
|
|
|
|
}
|