using StarterAssets; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; public class GameManager : MonoBehaviour { public static GameManager Instance; [Header("Game Settings")] public int totalOrbsToWin = 20; public float timeRemaining = 300f; [Header("UI References")] public TextMeshProUGUI orbText; public TextMeshProUGUI timerText; [Header("Game Over UI")] public GameObject gameOverPanel; public TextMeshProUGUI gameOverTitleText; private int currentOrbs = 0; private bool isGameOver = false; public int GetOrbsInternal() { return currentOrbs; } public void SetDataInternal(int orbs, float time) { currentOrbs = orbs; timeRemaining = time; UpdateOrbUI(); UpdateTimerUI(); } void Awake() { if (Instance == null) Instance = this; else Destroy(gameObject); } void Start() { // 1. ALWAYS reset time and cursor state first Time.timeScale = 1f; isGameOver = false; StarterAssetsInputs inputs = FindFirstObjectByType(); if (inputs != null) { inputs.cursorInputForLook = true; inputs.cursorLocked = true; } Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; // 2. Logic for Loading vs. Random Spawning if (MainMenu.shouldLoadSave) { Invoke("DelayedLoad", 0.1f); } else { Debug.Log("GameManager: Fresh Start/Restart. Randomizing spawn..."); TeleportPlayerToRandomGround(); // Reset stats for a fresh start currentOrbs = 0; timeRemaining = 300f; UpdateOrbUI(); UpdateTimerUI(); } } void DelayedLoad() { SaveSystem saveSys = FindFirstObjectByType(); if (saveSys != null) saveSys.LoadGame(); MainMenu.shouldLoadSave = false; } void Update() { if (isGameOver) return; if (timeRemaining > 0) { timeRemaining -= Time.deltaTime; UpdateTimerUI(); } else { GameOver(false); } } public void TeleportPlayerToRandomGround() { GameObject player = GameObject.FindGameObjectWithTag("Player"); if (player == null) return; // Use a loop to ensure we find a valid hit (just in case it hits a hole or edge) bool foundSpot = false; int attempts = 0; while (!foundSpot && attempts < 10) { attempts++; // Adjust these ranges to match your Mesh Generator size (e.g., 250x250) float randomX = Random.Range(-200f, 200f); float randomZ = Random.Range(-200f, 200f); Vector3 rayStart = new Vector3(randomX, 150f, randomZ); if (Physics.Raycast(rayStart, Vector3.down, out RaycastHit hit, 200f)) { // IMPORTANT: CharacterController MUST be disabled to move the Transform manually CharacterController cc = player.GetComponent(); if (cc != null) cc.enabled = false; player.transform.position = hit.point + Vector3.up * 2f; if (cc != null) cc.enabled = true; foundSpot = true; Debug.Log($"Player spawned on attempt {attempts} at {hit.point}"); } } } public void AddOrb() { currentOrbs++; UpdateOrbUI(); if (currentOrbs >= totalOrbsToWin) { GameOver(true); } } // Cleaned up to use the SaveSystem instead of PlayerPrefs public void SaveProgress() { SaveSystem saveSys = FindFirstObjectByType(); if (saveSys != null) { saveSys.SaveGame(); Debug.Log("GameManager: Progress saved via JSON."); } } public void LoadProgress() { SaveSystem saveSys = FindFirstObjectByType(); if (saveSys != null) { saveSys.LoadGame(); Debug.Log("GameManager: Progress loaded via JSON."); } } public void ClearSave() { string path = Application.persistentDataPath + "/savegame.json"; if (System.IO.File.Exists(path)) System.IO.File.Delete(path); SceneManager.LoadScene(SceneManager.GetActiveScene().name); } void UpdateOrbUI() { if (orbText != null) orbText.text = "Orbs: " + currentOrbs + " / " + totalOrbsToWin; } void UpdateTimerUI() { if (timerText != null) { float minutes = Mathf.FloorToInt(timeRemaining / 60); float seconds = Mathf.FloorToInt(timeRemaining % 60); timerText.text = string.Format("Time: {0:00}:{1:00}", minutes, seconds); } } public void GameOver(bool won) { isGameOver = true; Time.timeScale = 0f; gameOverPanel.SetActive(true); // --- ADD THIS TO STOP CAMERA --- StarterAssetsInputs inputs = FindFirstObjectByType(); if (inputs != null) { inputs.cursorInputForLook = false; // Disables mouse look inputs.cursorLocked = false; // Unlocks the mouse } if (won) { gameOverTitleText.text = "VICTORY!"; gameOverTitleText.color = Color.green; } else { gameOverTitleText.text = "NIGHT HAS FALLEN..."; gameOverTitleText.color = Color.red; } Cursor.lockState = CursorLockMode.None; Cursor.visible = true; } public void RestartGame() { Time.timeScale = 1f; // Ensure time flows again before loading SceneManager.LoadScene(SceneManager.GetActiveScene().name); } public void LoadMainMenu() { Time.timeScale = 1f; SceneManager.LoadScene("MainMenu"); } }