fgm24/Assets/Scripts/HeathSystem/HealthComponent.cs

166 lines
4.9 KiB
C#

using UnityEngine;
using UnityEngine.Events;
using TMPro;
using System;
using UnityUtils;
using System.Collections;
public class HealthComponent : MonoBehaviour, ISquezeDamageReceiver
{
public bool bloodRegen = false;
public float regen = 1000;
[SerializeField] private bool onlyCallZeroHealthOnce = true;
[SerializeField] float maxHealth = 100;
//[SerializeField] float damageTickDelay = 0.25f; //Unused
//private float currentDamageTick = 0f; //Unused
private float accumulatedDamageInTick = 0f;
public float currentHealth { get; private set; }
public static event Action<Vector3, float> OnHealthChangeAtPos;
public UnityEvent OnHealthZero;
public UnityEvent<float, float> OnHealthChange;
[Header("Squeze Damage")]
[SerializeField]
float minThreshold = 1f;
[SerializeField]
float squezeDamageScalor = 1f;
bool alreadyReachedZero = false;
public void resetKillFlag() {
alreadyReachedZero = false;
}
void Awake()
{
currentHealth = maxHealth;
OnHealthChange.AddListener((prev, nex) => showRedTint = nex<prev);
StartCoroutine(RedTintLoop());
}
bool showRedTint = false;
private IEnumerator RedTintLoop()
{
SpriteRenderer sr = GetComponentInChildren<SpriteRenderer>();
while (true)
{
if (!showRedTint)
{
yield return new WaitForSecondsRealtime(0.1f);
continue;
}
sr.color = Color.red;
yield return new WaitForSecondsRealtime(0.1f);
sr.color = Color.white;
yield return new WaitForSecondsRealtime(0.1f);
sr.color = Color.red;
yield return new WaitForSecondsRealtime(0.1f);
sr.color = Color.white;
yield return new WaitForSecondsRealtime(0.1f);
sr.color = Color.red;
yield return new WaitForSecondsRealtime(0.1f);
sr.color = Color.white;
yield return new WaitForSecondsRealtime(0.1f);
sr.color = Color.red;
yield return new WaitForSecondsRealtime(0.1f);
sr.color = Color.white;
yield return new WaitForSecondsRealtime(0.1f);
sr.color = Color.red;
yield return new WaitForSecondsRealtime(0.1f);
sr.color = Color.white;
yield return new WaitForSecondsRealtime(0.1f);
sr.color = Color.red;
yield return new WaitForSecondsRealtime(0.1f);
sr.color = Color.white;
yield return new WaitForSecondsRealtime(0.1f);
showRedTint = false;
}
}
void Update()
{
//// blod regen
//if (bloodRegen)
//{
// PlayerInput playerInput = GetComponent<PlayerInput>();
// float bloodAccumalted = playerInput.PlayerNum == 0 ? BloodComputeShader.Instance.mop1Clean : BloodComputeShader.Instance.mop2Clean;
// TakeDamage(-bloodAccumalted / regen);
//}
//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;
alreadyReachedZero = false;
}
}
public void TakeDamage(float damage)
{
if (damage == 0f) return;
currentHealth -= damage;
currentHealth = Mathf.Clamp(currentHealth, 0f, getMaxHealth());
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);
float power = 10.0f + (maxHealth / 25.0f);
BloodComputeShader.Instance.createBlood(transform.position, blood / 2, power);
BloodComputeShader.Instance.createBlood(transform.position, blood / 2, power);
}
}
}
public void TakeSquezeDamage(float squezeDamage)
{
if (squezeDamage < minThreshold) return;
TakeDamage((int) Mathf.Round(squezeDamage * squezeDamageScalor));
}
public void EnemyKill()
{
Destroy(gameObject);
}
}