fgm24/Assets/Scripts/Player/HealthComponent.cs

159 lines
4.8 KiB
C#
Raw Normal View History

2024-02-03 01:14:34 +01:00
using UnityEngine;
using UnityEngine.Events;
using TMPro;
2024-02-04 01:25:59 +01:00
using System;
using UnityUtils;
2024-02-04 10:24:38 +01:00
using System.Collections;
2024-02-03 01:14:34 +01:00
public class HealthComponent : MonoBehaviour, ISquezeDamageReceiver
{
2024-02-04 11:45:02 +01:00
public bool bloodRegen = false;
public float regen = 1000;
2024-02-04 02:26:11 +01:00
[SerializeField] private bool onlyCallZeroHealthOnce = true;
2024-02-04 01:25:59 +01:00
[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<Vector3, float> OnHealthChangeAtPos;
2024-02-03 01:14:34 +01:00
public UnityEvent OnHealthZero;
2024-02-04 01:25:59 +01:00
public UnityEvent<float, float> OnHealthChange;
2024-02-03 01:14:34 +01:00
[Header("Squeze Damage")]
[SerializeField]
float minThreshold = 1f;
[SerializeField]
float squezeDamageScalor = 1f;
2024-02-04 02:26:11 +01:00
bool alreadyReachedZero = false;
2024-02-03 01:14:34 +01:00
void Awake()
{
currentHealth = maxHealth;
2024-02-04 11:48:46 +01:00
OnHealthChange.AddListener((prev, nex) => showRedTint = nex<prev);
2024-02-04 10:24:38 +01:00
StartCoroutine(RedTintLoop());
}
2024-02-04 10:40:05 +01:00
bool showRedTint = false;
2024-02-04 10:24:38 +01:00
private IEnumerator RedTintLoop()
{
SpriteRenderer sr = GetComponentInChildren<SpriteRenderer>();
while (true)
{
2024-02-04 10:40:05 +01:00
if (!showRedTint)
2024-02-04 10:24:38 +01:00
{
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);
2024-02-04 10:40:05 +01:00
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;
2024-02-04 10:24:38 +01:00
}
2024-02-03 01:14:34 +01:00
}
2024-02-04 01:25:59 +01:00
void Update()
{
2024-02-04 11:45:02 +01:00
// blod regen
if (bloodRegen)
{
PlayerInput playerInput = GetComponent<PlayerInput>();
2024-02-04 11:48:24 +01:00
float bloodAccumalted = playerInput.PlayerNum == 0 ? BloodComputeShader.Instance.mop1Clean : BloodComputeShader.Instance.mop2Clean;
2024-02-04 11:45:02 +01:00
TakeDamage(-bloodAccumalted / regen);
}
2024-02-04 01:25:59 +01:00
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() {
2024-02-03 18:07:52 +01:00
return maxHealth;
}
2024-02-04 01:25:59 +01:00
public void setMaxHealth(float amount, bool heal = false) {
2024-02-03 18:07:52 +01:00
maxHealth = amount;
if (heal)
currentHealth = amount;
}
2024-02-04 01:25:59 +01:00
public void TakeDamage(float damage)
2024-02-03 01:14:34 +01:00
{
2024-02-04 11:45:02 +01:00
if (damage == 0f) return;
2024-02-03 01:14:34 +01:00
currentHealth -= damage;
2024-02-04 11:45:02 +01:00
currentHealth = Mathf.Clamp(currentHealth, 0f, getMaxHealth());
2024-02-03 01:14:34 +01:00
OnHealthChange?.Invoke(currentHealth + damage, currentHealth);
2024-02-04 01:25:59 +01:00
accumulatedDamageInTick += damage;
if (currentHealth <= 0) {
2024-02-04 02:26:11 +01:00
if (alreadyReachedZero && onlyCallZeroHealthOnce) return;
alreadyReachedZero = true;
2024-02-04 02:11:43 +01:00
// Make sure to flush accumulated when dying
if (accumulatedDamageInTick > 1f)
OnHealthChangeAtPos?.Invoke(transform.position.Add(y: 2f), accumulatedDamageInTick);
2024-02-03 01:14:34 +01:00
OnHealthZero?.Invoke();
2024-02-04 02:26:11 +01:00
2024-02-04 04:04:25 +01:00
if (BloodComputeShader.Instance != null)
{
int blood = (int)(maxHealth * 100.0f * BloodComputeShader.Instance.scoreMult);
2024-02-04 09:52:47 +01:00
float power = 10.0f + (maxHealth / 25.0f);
2024-02-04 02:26:11 +01:00
2024-02-04 09:52:47 +01:00
BloodComputeShader.Instance.createBlood(transform.position, blood / 2, power);
BloodComputeShader.Instance.createBlood(transform.position, blood / 2, power);
2024-02-04 04:04:25 +01:00
}
}
2024-02-03 01:14:34 +01:00
}
public void TakeSquezeDamage(float squezeDamage)
{
if (squezeDamage < minThreshold) return;
TakeDamage((int) Mathf.Round(squezeDamage * squezeDamageScalor));
}
2024-02-04 00:08:25 +01:00
public void EnemyKill()
2024-02-03 01:14:34 +01:00
{
2024-02-04 00:12:16 +01:00
2024-02-03 01:14:34 +01:00
Destroy(gameObject);
}
}