using System; using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.SceneManagement; public class GameManager : MonoBehaviour { //Variables [Header("PlayerStats")] [SerializeField] private int playerGold = 500; [SerializeField] private int playerLevel = 1; [SerializeField] private int baseXP = 100; [SerializeField] private int maxLevel = 20; [SerializeField] private float xpMultiplier = 2.5f; [SerializeField] private int playerCurrentXP = 0; [SerializeField] private int targetLevelXP; [SerializeField] private int abilityPoints; [Header("Item Stack Prefabs")] [SerializeField] private Item item; public GameObject itemStack; [Header("Player Inventory")] public int inventorySize; public Inventory inventory; private bool isProcessingXP = false; private Queue<int> xpQueue = new Queue<int>(); [Header("Cursor")] [SerializeField] private Texture2D cursorTexture; private static GameManager instance; //Events public event Action<int> OnLevelUp; public event Action<int> OnXpGained; public event Action<int> OnGoldAdded; //public GameStateManager currentGameState { get; set; } public static GameManager Instance => instance; public int PlayerGold { get => playerGold; set { playerGold = value; OnGoldAdded?.Invoke(value); } } public int PlayerLevel { private set { if (playerLevel <= maxLevel) { playerLevel = value; OnLevelUp.Invoke(value); } } get => playerLevel; } public int TargetLevelXP => targetLevelXP; public int PlayerCurrentXP { get => playerCurrentXP; private set => playerCurrentXP = value; } private void Awake() { //currentGameState = GameStateManager.Active; if (instance != null && instance != this) { Destroy(gameObject); // Ensures there's only one instance } else { instance = this; DontDestroyOnLoad(gameObject); // Ensure the GameManager persists between scene loads } } // Start is called before the first frame update void Start() { Cursor.SetCursor(cursorTexture, Vector2.zero, CursorMode.ForceSoftware); targetLevelXP = GetXPForNextLevel(playerLevel); inventory = new Inventory(inventorySize, PlayerController.Instance.gameObject); } // Level up the player and distribute excess XP if any private void LevelUp(int excessXP) { PlayerLevel++; // Increase player level abilityPoints++; // Grant ability points targetLevelXP = GetXPForNextLevel(playerLevel); // Calculate XP for next level FIRST playerCurrentXP = excessXP; // Set the leftover XP after updating target XP OnLevelUp?.Invoke(playerLevel); // Notify HUD after updating level and XP } // This handles checking and leveling up the player if needed private void ProcessExperience() { while (playerCurrentXP >= targetLevelXP && playerLevel < maxLevel) { int excessXP = playerCurrentXP - targetLevelXP; LevelUp(excessXP); // Level up and process excess XP } } // Main method to gain experience and handle potential level-ups public void GainExperience(int xpAmount) { xpQueue.Enqueue(xpAmount); // Add XP to the queue if (!isProcessingXP) { StartCoroutine(ProcessXPQueue()); } } private IEnumerator ProcessXPQueue() { isProcessingXP = true; while (xpQueue.Count > 0) { int xpAmount = xpQueue.Dequeue(); // Get the next XP amount to process playerCurrentXP += xpAmount; ProcessExperience(); // Check for level-up OnXpGained?.Invoke(playerCurrentXP); // Update XP in the HUD yield return new WaitForSeconds(0.1f); // Add a small delay to prevent spamming } isProcessingXP = false; } public void Update() { //Testing purposes if (Input.GetKeyDown(KeyCode.F)) { //GainExperience(5); inventory.AddItem(item); } Debug.Log("IS IT FULL" + inventory.IsFull()); } //Geometric Progression to LevelExperience private int GetXPForNextLevel(int level) => Mathf.FloorToInt(baseXP * Mathf.Pow(xpMultiplier, level - 1)); }