RiftMayhem/Assets/Scripts/Player/PlayerDeathManager.cs
2025-02-21 18:35:51 +00:00

279 lines
7.9 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class PlayerDeathManager : MonoBehaviour
{
[SerializeField] private GameEvent onLocalPlayerCheatedDeath;
[SerializeField] private GameEvent onLocalPlayerFainted;
[SerializeField] private GameEvent onLocalPlayerPermaDeath;
[SerializeField] private GameEvent onLocalPlayerRevived;
[Space]
[SerializeField] private GameObject reviveProgressGO;
[SerializeField] private GameObject bleedOutProgressGO;
[SerializeField] private Image reviveProgressFill;
[SerializeField] private Image bleedOutProgressFill;
private bool hasUsedCheatDeath = false;
public bool HasUsedCheatDeath => hasUsedCheatDeath;
private bool isFainted = false;
public bool IsFainted => isFainted;
private float bleedOutTimer = 0f;
public float BleedOutTimer => bleedOutTimer;
private float reviveProgress = 0f;
public float ReviveProgress => reviveProgress;
RiftPlayer ownerPlayer;
Health health;
SphereCollider reviveTrigger;
CharacterAnimatorController anim;
RiftPlayer possibleReviver;
public List<RiftPlayer> playersInsideReviveTrigger = new List<RiftPlayer>();
PlayerDeathManager potentialReferenceAddition;
NetworkManager networkManager;
private void Awake()
{
ownerPlayer = GetComponentInParent<RiftPlayer>();
health = GetComponentInParent<Health>();
anim = ownerPlayer.GetComponentInChildren<CharacterAnimatorController>();
reviveTrigger = GetComponentInChildren<SphereCollider>();
reviveTrigger.transform.localScale = Vector3.one * GameConstants.CharacterBalancing.ReviveTriggerRadius * 2;
reviveTrigger.isTrigger = true;
reviveTrigger.gameObject.SetActive(false);
reviveProgressGO.SetActive(false);
bleedOutProgressGO.SetActive(false);
networkManager = FindObjectOfType<NetworkManager>();
}
private void Start()
{
health.onDeath.AddListener(OnDeath);
}
private void OnDeath()
{
//if (PhotonNetwork.CurrentRoom.PlayerCount <= 1)
//{
HandleSoloDeath();
//}
//else
//{
// HandleGroupDeath();
//}
}
private void HandleSoloDeath()
{
if (!hasUsedCheatDeath)
{
CheatDeath();
}
else
{
Die();
}
}
private void HandleGroupDeath()
{
EnterFaintedState();
}
private void CheatDeath()
{
hasUsedCheatDeath = true;
health.SetCurrentValue(health.GetMaxValue() * GameConstants.CharacterBalancing.SoloCheatDeathHealthPercent);
StartCoroutine(SoloInvulnerability());
onLocalPlayerCheatedDeath.Raise();
}
private IEnumerator SoloInvulnerability()
{
// Implement invulnerability logic
health.SetInvulnerabilityState(true);
yield return new WaitForSeconds(GameConstants.CharacterBalancing.SoloCheatDeathInvulnerabilityDuration);
// Remove invulnerability
health.SetInvulnerabilityState(false);
}
private void EnterFaintedState()
{
isFainted = true;
reviveTrigger.gameObject.SetActive(true);
// Disable player movement and abilities
// Change player visuals to "fainted" state
health.SetIsDeadState(true);
StartCoroutine(BleedOutTimerCoroutine());
// if (AreAllPlayersFaintedOrDead())
// {
// StartCoroutine(Return());
// }
reviveProgressGO.SetActive(true);
bleedOutProgressGO.SetActive(true);
anim.OnDeath();
onLocalPlayerFainted.Raise();
}
private IEnumerator BleedOutTimerCoroutine()
{
bleedOutTimer = GameConstants.CharacterBalancing.GroupBleedOutDuration;
bleedOutProgressFill.fillAmount = bleedOutTimer / GameConstants.CharacterBalancing.GroupBleedOutDuration;
while (bleedOutTimer > 0 && isFainted)
{
bleedOutTimer -= Time.deltaTime;
bleedOutProgressFill.fillAmount = bleedOutTimer / GameConstants.CharacterBalancing.GroupBleedOutDuration;
yield return null;
}
if (isFainted)
{
Die();
}
}
private void OnTriggerEnter(Collider other)
{
if (!isFainted) return;
possibleReviver = other.GetComponentInParent<RiftPlayer>();
if (possibleReviver == null) return;
if (possibleReviver == ownerPlayer) return;
if (playersInsideReviveTrigger.Contains(possibleReviver)) return;
Debug.Log($"R: added {possibleReviver.name} as a reviver");
playersInsideReviveTrigger.Add(possibleReviver);
}
private void Update()
{
if (!isFainted) return;
if (playersInsideReviveTrigger.Count > 0)
{
for (int i = playersInsideReviveTrigger.Count - 1; i >= 0; i--)
{
if (playersInsideReviveTrigger[i].health.GetCurrentValue() <= 0)
playersInsideReviveTrigger.RemoveAt(i);
}
reviveProgress += GameConstants.CharacterBalancing.ReviveSpeed * playersInsideReviveTrigger.Count * Time.deltaTime;
reviveProgressFill.fillAmount = reviveProgress / GameConstants.CharacterBalancing.ReviveTime;
if (reviveProgress >= GameConstants.CharacterBalancing.ReviveTime)
{
Revive();
}
}
}
private void OnTriggerExit(Collider other)
{
if (!isFainted) return;
possibleReviver = other.GetComponentInParent<RiftPlayer>();
if (possibleReviver == null) return;
if (possibleReviver == ownerPlayer) return;
if (!playersInsideReviveTrigger.Contains(possibleReviver)) return;
Debug.Log($"R: removed {possibleReviver.name} from revivers pool");
playersInsideReviveTrigger.Remove(possibleReviver);
}
private void Revive()
{
isFainted = false;
reviveTrigger.gameObject.SetActive(false);
reviveProgress = 0;
health.SetIsDeadState(false);
health.SetCurrentValue(health.GetMaxValue() * GameConstants.CharacterBalancing.ReviveHealthPercent);
// Re-enable player movement and abilities
// Restore normal player visuals
playersInsideReviveTrigger.Clear();
reviveProgressGO.SetActive(false);
bleedOutProgressGO.SetActive(false);
anim.OnRevived();
onLocalPlayerRevived.Raise();
}
private void Die()
{
health.SetIsDeadState(true);
// Implement full death logic (respawn, etc.)
// if (PhotonNetwork.CurrentRoom.PlayerCount <= 1)
// {
//Player perma death on the job, wait X to show info, then PhotonNetwork.LoadLevel(RiftHuntersInn)
StartCoroutine(Return());
// }
// else
// {
//if players alive > 0
//wait motherfucker
//else
//all dead, host load level
// if (AreAllPlayersFaintedOrDead())
// {
// if (PhotonNetwork.IsMasterClient)
// {
// StartCoroutine(Return());
// }
//}
// }
if (!isFainted)
anim.OnDeath();
reviveProgressGO.SetActive(false);
bleedOutProgressGO.SetActive(false);
onLocalPlayerPermaDeath.Raise();
}
/* private bool AreAllPlayersFaintedOrDead()
{
for (int i = 0; i < networkManager.party.Count; i++)
{
potentialReferenceAddition = ((RiftPlayer)networkManager.party[i].TagObject).GetComponentInChildren<PlayerDeathManager>();
if (potentialReferenceAddition.IsFainted) continue;
else return false;
}
return true;
}*/
IEnumerator Return()
{
yield return new WaitForSeconds(GameConstants.GameBalancing.PermaDeathInfoTime);
SceneManager.LoadScene("4-RiftHuntersInn");
}
}