92 lines
2.8 KiB
C#
92 lines
2.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine;
|
|
|
|
|
|
[SerializeField]
|
|
public class Damageable : IDamageable {
|
|
public event Action<int, Vector2> OnTakeDamage;
|
|
public event Action OnDeath;
|
|
public event Action<int> OnHeal;
|
|
|
|
[SerializeField] public int BaseHealth { get; protected set; }
|
|
public int CurrentHealth { get; protected set; }
|
|
public bool IsDead => CurrentHealth <= 0;
|
|
|
|
public bool IsInvincible => Time.time < InvincibleUntil;
|
|
public float InvincibleUntil { get; protected set; } = 0f;
|
|
public float InvincibilityLeft => Math.Max(0, InvincibleUntil - Time.time);
|
|
[SerializeField] public float InvincibilityDuration { get; protected set; } = 0;
|
|
|
|
public bool IsFrameFrozen => Time.time < FrameFrozenUntil;
|
|
public float FrameFrozenUntil { get; protected set; }
|
|
public float FrameFreezeLeft => Math.Max(0, FrameFrozenUntil - Time.time);
|
|
[SerializeField] public float FrameFreezeDuration { get; protected set; } = 0;
|
|
|
|
public int DamageTaken { get; protected set; }
|
|
public Vector2 DirectionOfDamage { get; protected set; }
|
|
[SerializeField] public bool IsKnockable { get; protected set; }
|
|
public int Knockback { get; protected set; }
|
|
|
|
public void Damage(int amount, Vector2 hitDirection, int knockback = 1) {
|
|
if (IsDead || IsInvincible) return;
|
|
|
|
CurrentHealth -= amount;
|
|
CurrentHealth = Mathf.Max(CurrentHealth, 0);
|
|
InvincibleUntil = Time.time + InvincibilityDuration;
|
|
FrameFrozenUntil = Time.time + FrameFreezeDuration;
|
|
DamageTaken = amount;
|
|
if (IsKnockable) Knockback = knockback;
|
|
|
|
hitDirection = hitDirection.normalized;
|
|
if (hitDirection == Vector2.zero) hitDirection = Vector2.up;
|
|
DirectionOfDamage = hitDirection;
|
|
OnTakeDamage?.Invoke(amount, hitDirection);
|
|
if (CurrentHealth == 0) OnDeath?.Invoke();
|
|
}
|
|
|
|
public void Heal(int amount) {
|
|
if (IsDead) return;
|
|
|
|
CurrentHealth += amount;
|
|
CurrentHealth = Mathf.Min(CurrentHealth, BaseHealth);
|
|
OnHeal?.Invoke(amount);
|
|
}
|
|
|
|
public void Reset() {
|
|
CurrentHealth = BaseHealth;
|
|
InvincibleUntil = Time.time;
|
|
FrameFrozenUntil = Time.time;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public interface IDamageable {
|
|
int BaseHealth { get; }
|
|
int CurrentHealth { get; }
|
|
bool IsDead { get; }
|
|
|
|
bool IsInvincible { get; }
|
|
float InvincibleUntil { get; }
|
|
float InvincibilityLeft { get; }
|
|
float InvincibilityDuration { get; }
|
|
|
|
bool IsFrameFrozen { get; }
|
|
float FrameFrozenUntil { get; }
|
|
float FrameFreezeLeft { get; }
|
|
float FrameFreezeDuration { get; }
|
|
|
|
int DamageTaken { get; }
|
|
Vector2 DirectionOfDamage { get; }
|
|
bool IsKnockable { get; }
|
|
int Knockback { get; }
|
|
|
|
public void Damage(int amount, Vector2 hitDirection, int knockback = 1);
|
|
public void Heal(int amount);
|
|
public void Reset();
|
|
}
|