Newer
Older
TheVengeance-Project-IADE-Unity2D / Assets / Scripts / GameManager.cs
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));

}