TowerDefenseGame/Assets/Scripts/Runtime/Core/Combat/Damageable.cs
Nico 62b981f440 Add knockbock gaurd against being pushed out of bounds
Further develop on attacking and taking damage states
2025-07-25 17:52:08 -07:00

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();
}