Pedro Gomes 2773ef7d6e Player Death Update
- Players can now die (finally)
- Solo players have a single cheat death per scene (reviving automatically after the first death)
- group players have revive mechanic, where a player faints when his health gets to 0, creating a revive circle around him, other players can stand on it to revive him. if after x seconds they don't get revived they bleed out and stay perma death until scene changes or all players die
- Multiple VFX added using post processing for cheat death, fainting, reviving, and perma death events.
- stopped players from moving and pressing keys when dead
- enemies now change target if they try to attack a dead/fainted target.
2024-07-20 19:49:14 +01:00

178 lines
4.6 KiB
C#

using Kryz.CharacterStats.Examples;
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class Health : Resource
{
protected CharacterStats character;
protected AbsorbEffectInstance absorbEffectInstance;
protected DamageIncomeModifierEffectInstance damageIncomeModifierEffectInstance;
public UnityEvent<float> onMaxHealthChanged = new UnityEvent<float>();
public UnityEvent onDeath = new UnityEvent();
[HideInInspector]
public PhotonView photonView;
protected bool invulnerable = false;
public bool Invulnerable => invulnerable;
float incomingValue;
private bool isDead;
public UnityEvent<bool> OnInvulnerabilityStateChanged = new UnityEvent<bool>();
public void SetIsDeadState(bool isDead)
{
this.isDead = isDead;
canRegen = !isDead;
}
protected virtual void Awake()
{
character = GetComponent<CharacterStats>();
photonView = GetComponent<PhotonView>();
absorbEffectInstance = GetComponent<AbsorbEffectInstance>();
damageIncomeModifierEffectInstance = GetComponent<DamageIncomeModifierEffectInstance>();
baseMaxValue = maxValue;
baseFlatRegen = flatRegen;
character.onUpdateStatValues.AddListener(CalculateMaxValueBasedOnStat);
}
protected override void Start()
{
if (!photonView.IsMine) return;
base.Start();
}
public void SetInvulnerabilityState(bool isInvulnerable)
{
if (!photonView.IsMine) return;
photonView.RPC(nameof(RPC_SetInvulnerabilityState), RpcTarget.All, isInvulnerable);
}
[PunRPC]
public void RPC_SetInvulnerabilityState(bool isInvulnerable)
{
invulnerable = isInvulnerable;
OnInvulnerabilityStateChanged.Invoke(invulnerable);
}
protected void HandleDamageIncomeModifierEffects()
{
if (incomingValue < 0)
{
if (damageIncomeModifierEffectInstance.IsActive)
{
Debug.Log("Incoming damage b4 mitigation: " + incomingValue);
incomingValue = damageIncomeModifierEffectInstance.ModifyDamageIncome(incomingValue);
if (incomingValue > 0) //avoid damage ultra mitigated turning into healing
incomingValue = 0;
}
Debug.Log("Incoming damage after mitigation: " + incomingValue);
}
}
protected void HandleAbsorbEffects()
{
if (incomingValue < 0)
{
if (absorbEffectInstance.IsActive)
{
Debug.Log("Incoming damage b4 absorbs: " + incomingValue);
incomingValue = absorbEffectInstance.AbsorbDamage(incomingValue);
if (incomingValue > 0) //avoid complete absorbs turning into healing
incomingValue = 0;
}
Debug.Log("Incoming damage after absorbs: " + incomingValue);
}
}
public override void ChangeValue(float value)
{
if (!photonView.IsMine) return;
//Debug.Log("Value to change: " + value);
if (isDead) return;
incomingValue = value;
if (invulnerable && incomingValue < 0) return;
HandleDamageIncomeModifierEffects();
HandleAbsorbEffects();
currentValue += incomingValue;
currentValue = Mathf.Clamp(currentValue, 0, maxValue);
if (currentValue == 0)
{
//dead;
onDeath.Invoke();
}
//Debug.Log("CurrentHealth: " + currentValue);
onResourceChanged.Invoke(currentValue);
}
public bool EnoughHealth(float cost)
{
if (invulnerable) return true;
return cost <= currentValue;
}
[PunRPC]
public void RPC_ChangeValueHealth(float value)
{
if (!photonView.IsMine) return;
Debug.Log("Received ChangeValue from RPC from someone");
ChangeValue(value);
}
public override float GetMaxValue()
{
return base.GetMaxValue();
}
public virtual void CalculateMaxValueBasedOnStat()
{
maxValue = baseMaxValue + character.Vitality.Value * 10f;
CalculateRegenValueBasedOnStat();
onMaxHealthChanged.Invoke(maxValue);
}
public void CalculateRegenValueBasedOnStat()
{
flatRegen = baseFlatRegen + (character.Strength.Value - character.Strength.BaseValue) * 0.5f;
percentRegen = (character.Vitality.Value - character.Vitality.BaseValue) * 0.01f;
}
public override void SetMaxValue(float value)
{
base.SetMaxValue(value);
onMaxHealthChanged.Invoke(maxValue);
}
}