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