using UnityEngine; using System.Collections; using System.Collections.Generic; /// /// Central manager for game state, death, and respawn logic /// public class GameManager : MonoBehaviour { public static GameManager Instance { get; private set; } [Header("References")] public TeamCohesionManager cohesionManager; public CheckpointSystem checkpointSystem; public DeathScreenUI deathScreenUI; public GridMovement playerMovement; [Header("Death Settings")] public float deathDelay = 2f; // Time before showing death screen public float respawnFadeTime = 1f; public bool resetMonstersOnRespawn = false; [Header("Respawn Penalties (Optional)")] public bool applyGoldPenalty = false; public float goldPenaltyPercent = 0f; // 0 = no penalty private bool isPlayerDead = false; private CanvasGroup fadeCanvasGroup; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; // Create fade overlay if it doesn't exist CreateFadeOverlay(); } private void Start() { if (cohesionManager == null) cohesionManager = FindFirstObjectByType(); if (checkpointSystem == null) checkpointSystem = FindFirstObjectByType(); if (deathScreenUI == null) deathScreenUI = FindFirstObjectByType(); if (playerMovement == null) playerMovement = FindFirstObjectByType(); // Verify setup ValidateSetup(); } private void ValidateSetup() { Debug.Log("=== GameManager Setup Validation ==="); Debug.Log($"Cohesion Manager: {(cohesionManager != null ? "✓ Assigned" : "✗ MISSING")}"); Debug.Log($"Checkpoint System: {(checkpointSystem != null ? "✓ Assigned" : "✗ MISSING")}"); Debug.Log($"Death Screen UI: {(deathScreenUI != null ? "✓ Assigned" : "✗ MISSING")}"); Debug.Log($"Player Movement: {(playerMovement != null ? "✓ Assigned" : "✗ MISSING")}"); if (cohesionManager == null || checkpointSystem == null || deathScreenUI == null || playerMovement == null) { Debug.LogError("[GameManager] Some references are missing! Respawn system may not work correctly."); } else { Debug.Log("[GameManager] All references validated successfully!"); } } /// /// Called when all party members have died /// public void OnPartyWiped() { if (isPlayerDead) return; // Prevent multiple triggers isPlayerDead = true; Debug.Log("[GameManager] Party wiped! Initiating death sequence..."); StartCoroutine(HandleDeathSequence()); } private IEnumerator HandleDeathSequence() { // Disable player input if (playerMovement != null) playerMovement.enabled = false; // Stop all monster attacks StopAllMonsterAttacks(); // Wait a moment for dramatic effect yield return new WaitForSeconds(deathDelay); // Fade to black yield return StartCoroutine(FadeToBlack(respawnFadeTime)); // Show death screen if (deathScreenUI != null) { deathScreenUI.Show(); } else { Debug.LogWarning("[GameManager] Death Screen UI not found, auto-respawning..."); RespawnParty(); } } /// /// Respawn the party at the last checkpoint /// public void RespawnParty() { Debug.Log("[GameManager] Respawning party..."); StartCoroutine(RespawnSequence()); } private IEnumerator RespawnSequence() { Debug.Log("[GameManager] RespawnSequence started"); // Hide death screen if visible if (deathScreenUI != null) { deathScreenUI.Hide(); Debug.Log("[GameManager] Death screen hidden"); } // Small delay for UI to hide yield return new WaitForSeconds(0.2f); // Load checkpoint data if (checkpointSystem != null) { Debug.Log("[GameManager] Loading checkpoint..."); checkpointSystem.LoadCheckpoint(); } else { Debug.LogWarning("[GameManager] No CheckpointSystem found, performing basic respawn"); BasicRespawn(); } // Apply penalties if enabled if (applyGoldPenalty && goldPenaltyPercent > 0) { ApplyGoldPenalty(); } // Reset monsters if enabled if (resetMonstersOnRespawn) { ResetMonsters(); } // Small delay before fade in yield return new WaitForSeconds(0.3f); Debug.Log("[GameManager] Starting fade from black..."); // Fade back from black yield return StartCoroutine(FadeFromBlack(respawnFadeTime)); Debug.Log("[GameManager] Fade complete, re-enabling player controls"); // Re-enable player input if (playerMovement != null) playerMovement.enabled = true; isPlayerDead = false; Debug.Log("[GameManager] Respawn complete!"); } /// /// Basic respawn without checkpoint system - restores party to full health /// private void BasicRespawn() { if (cohesionManager == null || cohesionManager.groupMembers == null) { Debug.LogError("[GameManager] Cannot respawn: CohesionManager or group members not found"); return; } foreach (var character in cohesionManager.groupMembers) { character.currentHP = character.maxHP; character.currentFatigue = character.maxFatigue; character.currentMana = character.maxMana; // Update UI UIUpdater.Instance?.UpdateCharacterHP(character); UIUpdater.Instance?.UpdateCharacterFatigue(character); } } private void ApplyGoldPenalty() { // TODO: Implement gold system penalty if you have a gold/currency system Debug.Log($"[GameManager] Gold penalty applied: {goldPenaltyPercent}%"); } private void StopAllMonsterAttacks() { // Find all monster formation groups and stop their attacks MonsterFormationGroup[] monsterGroups = FindObjectsByType(FindObjectsSortMode.None); foreach (var group in monsterGroups) { // Stop their current behavior immediately group.StopAllCoroutines(); group.isChasing = false; group.hasDetectedPlayer = false; // Stop individual monster animations foreach (var monster in group.frontRow) { if (monster != null) monster.StopMove(); } foreach (var monster in group.backRow) { if (monster != null) monster.StopMove(); } Debug.Log($"[GameManager] Stopped attacks from monster group: {group.gameObject.name}"); } } private void ResetMonsters() { // Find all monster formation groups and reset them MonsterFormationGroup[] monsterGroups = FindObjectsByType(FindObjectsSortMode.None); foreach (var group in monsterGroups) { // Stop their current behavior group.StopAllCoroutines(); group.isChasing = false; group.hasDetectedPlayer = false; Debug.Log($"[GameManager] Reset monster group: {group.gameObject.name}"); } } #region Fade Effects private void CreateFadeOverlay() { // Create a full-screen black overlay for fade effects GameObject fadeObj = new GameObject("FadeOverlay"); fadeObj.transform.SetParent(transform); Canvas canvas = fadeObj.AddComponent(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; canvas.sortingOrder = 100; // Below death screen UI (which should be 200+) fadeCanvasGroup = fadeObj.AddComponent(); fadeCanvasGroup.alpha = 0f; fadeCanvasGroup.interactable = false; fadeCanvasGroup.blocksRaycasts = false; // Add black panel GameObject panel = new GameObject("BlackPanel"); panel.transform.SetParent(fadeObj.transform, false); UnityEngine.UI.Image image = panel.AddComponent(); image.color = Color.black; RectTransform rect = panel.GetComponent(); rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.sizeDelta = Vector2.zero; } private IEnumerator FadeToBlack(float duration) { float elapsed = 0f; while (elapsed < duration) { elapsed += Time.deltaTime; fadeCanvasGroup.alpha = Mathf.Lerp(0f, 1f, elapsed / duration); yield return null; } fadeCanvasGroup.alpha = 1f; } private IEnumerator FadeFromBlack(float duration) { float elapsed = 0f; while (elapsed < duration) { elapsed += Time.deltaTime; fadeCanvasGroup.alpha = Mathf.Lerp(1f, 0f, elapsed / duration); yield return null; } fadeCanvasGroup.alpha = 0f; } #endregion public bool IsPlayerDead() => isPlayerDead; }