166 lines
4.9 KiB
C#
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);
|
|
}
|
|
}
|