using UnityEngine; using UnityEngine.Events; using TMPro; using System; using UnityUtils; public class HealthComponent : MonoBehaviour, ISquezeDamageReceiver { [SerializeField] private bool onlyCallZeroHealthOnce = true; [SerializeField] float maxHealth = 100; [SerializeField] float damageTickDelay = 0.25f; private float currentDamageTick = 0f; private float accumulatedDamageInTick = 0f; public float currentHealth { get; private set; } public static event Action OnHealthChangeAtPos; public UnityEvent OnHealthZero; public UnityEvent OnHealthChange; [Header("Squeze Damage")] [SerializeField] float minThreshold = 1f; [SerializeField] float squezeDamageScalor = 1f; bool alreadyReachedZero = false; void Awake() { currentHealth = maxHealth; } void Update() { if (currentDamageTick < Time.time) { if (accumulatedDamageInTick < 1f) return; OnHealthChangeAtPos?.Invoke(transform.position.Add(y: 2f), accumulatedDamageInTick); currentDamageTick = Time.time + damageTickDelay; accumulatedDamageInTick = 0f; } } public float getMaxHealth() { return maxHealth; } public void setMaxHealth(float amount, bool heal = false) { maxHealth = amount; if (heal) currentHealth = amount; } public void TakeDamage(float damage) { currentHealth -= damage; OnHealthChange?.Invoke(currentHealth + damage, currentHealth); accumulatedDamageInTick += damage; if (currentHealth <= 0) { if (alreadyReachedZero && onlyCallZeroHealthOnce) return; alreadyReachedZero = true; // Make sure to flush accumulated when dying if (accumulatedDamageInTick > 1f) OnHealthChangeAtPos?.Invoke(transform.position.Add(y: 2f), accumulatedDamageInTick); OnHealthZero?.Invoke(); if (BloodComputeShader.Instance != null) { int blood = (int)(maxHealth * 100.0f * BloodComputeShader.Instance.scoreMult); BloodComputeShader.Instance.createBlood(transform.position, blood / 2, maxHealth / 8.0f); BloodComputeShader.Instance.createBlood(transform.position, blood / 2, maxHealth / 8.0f); } } } public void TakeSquezeDamage(float squezeDamage) { if (squezeDamage < minThreshold) return; TakeDamage((int) Mathf.Round(squezeDamage * squezeDamageScalor)); } public void EnemyKill() { Destroy(gameObject); } }