using System; using Platformer.Gameplay; using UnityEngine; using static Platformer.Core.Simulation; namespace Platformer.Mechanics { /// /// Represebts the current vital statistics of some game entity. /// public class Health : MonoBehaviour { /// /// The maximum hit points for the entity. /// public int maxHP = 1; /// /// 무적 시간 (i-frame) 지속 초 단위. 기획 04 §3-2 후보 0.4~0.8s. /// 라이프 1 전제에서 연속 히트 인정 금지를 위한 핵심 장치 (BT5-Dev 2단계 신설). /// public float invulnerableDuration = 0.6f; /// /// 현재 무적 상태 여부 (디버그·UX 피드백용 — 깜박임 제어 등에 사용 가능). /// public bool IsInvulnerable => Time.time < invulnerableUntil; /// /// Indicates if the entity should be considered 'alive'. /// public bool IsAlive => currentHP > 0; int currentHP; float invulnerableUntil = -1f; /// /// Increment the HP of the entity. /// public void Increment() { currentHP = Mathf.Clamp(currentHP + 1, 0, maxHP); } /// /// Decrement the HP of the entity. Will trigger a HealthIsZero event when /// current HP reaches 0. 무적 시간 (i-frame) 내에는 호출되어도 스킵된다. /// public void Decrement() { // BT5-Dev 2단계: i-frame 보호 — 무적 시간 내 중복 피격 차단 if (Time.time < invulnerableUntil) { return; } currentHP = Mathf.Clamp(currentHP - 1, 0, maxHP); // 피격 성공 시 무적 시간 활성화 (다음 피격 대비) if (invulnerableDuration > 0f) { invulnerableUntil = Time.time + invulnerableDuration; } if (currentHP == 0) { var ev = Schedule(); ev.health = this; } } /// /// Decrement the HP of the entitiy until HP reaches 0. /// i-frame 우회하여 즉사 처리 (낙사·승리 이탈 등 시스템 강제 사망). /// public void Die() { invulnerableUntil = -1f; // i-frame 무효화 while (currentHP > 0) { currentHP = Mathf.Clamp(currentHP - 1, 0, maxHP); if (currentHP == 0) { var ev = Schedule(); ev.health = this; break; } } } void Awake() { currentHP = maxHP; } } }