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 playersInsideReviveTrigger = new List(); PlayerDeathManager potentialReferenceAddition; NetworkManager networkManager; private void Awake() { ownerPlayer = GetComponentInParent(); health = GetComponentInParent(); anim = ownerPlayer.GetComponentInChildren(); reviveTrigger = GetComponentInChildren(); reviveTrigger.transform.localScale = Vector3.one * GameConstants.CharacterBalancing.ReviveTriggerRadius * 2; reviveTrigger.isTrigger = true; reviveTrigger.gameObject.SetActive(false); reviveProgressGO.SetActive(false); bleedOutProgressGO.SetActive(false); networkManager = FindObjectOfType(); } 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(); 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(); 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(); if (potentialReferenceAddition.IsFainted) continue; else return false; } return true; }*/ IEnumerator Return() { yield return new WaitForSeconds(GameConstants.GameBalancing.PermaDeathInfoTime); SceneManager.LoadScene("4-RiftHuntersInn"); } }