Encounter / Assets / Scripts / GUIHandlers / GeneralUI.cs
GeneralUI.cs
Raw
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class GeneralUI : MonoBehaviour
{
    public static GeneralUI Instance;

    [Header("UI Components")]
    [SerializeField] private TextMeshProUGUI playeName;           // Reference to the name text in the player UI
    [SerializeField] private TextMeshProUGUI playerLevel;          // Reference to the level indicator in the player UI
    [SerializeField] private Image playerSprite;                   // Reference to the sprite image for the player
    [SerializeField] private TextMeshProUGUI healthTextPlaceOne;    // Text reference to the first health value place
    [SerializeField] private TextMeshProUGUI healthTextPlaceTwo;    // Text reference to the second health value place
    [SerializeField] private Slider healthSlider;                  // Reference to the health slider object that will slide the health bar down as the player is damaged
    [SerializeField] private TextMeshProUGUI manaTextPlaceOne;      // Text reference to the first mana value place
    [SerializeField] private TextMeshProUGUI manaTextPlaceTwo;      // Text reference to the second mana value place
    [SerializeField] private Slider manaSlider;                    // Reference to the mana slider object that will slide the mana bar down as the player uses mana
    [SerializeField] private Transform modifierField;              // Transform field for the modifiers
    [SerializeField] private GameObject modifierPrefab;            // Reference to the modifier prefab object
    [SerializeField] private GameObject inventoryButton;           // Reference to the inventory button object within the general UI
    [SerializeField] private Canvas inventoryCanvas;               // The canvas that will serve as the inventory management for the player
    [SerializeField] private GameObject diceRoller;                 // Reference to the dice roller object that will 

    [Header("Party Handling UI")]
    [SerializeField] private Transform partyTransform;          // Reference to the transform that will contain the party UI icons on the left
    [SerializeField] private GameObject partyGuiPrefab;            // Reference to the prefab that will hold the party information

    private GameObject playerObject;
    private Player playerComponent;
    private List<GameObject> allyIcons;
    private List<GameObject> minionIcons;
    private readonly Color DisabledColor = new Color(.65f, .65f, .65f, 1f);

    private bool allDiceRolled;
    private bool? canRollForDamage;
    private bool isFinalAttack;

    private void Awake()
    {
        Instance = this;

        allyIcons = new List<GameObject>();
        allDiceRolled = true;
    }
    /// <summary>
    /// Sets the information for each of the components within the UI scene
    /// </summary>
    public void SetInformation(bool setup = true)
    {
        playerObject ??= GameManager.Instance.GetPlayerObject();
        playerComponent ??= playerObject.GetComponent<Player>();

        playeName.text = playerComponent.GetName();
        playerLevel.text = playerComponent.GetLevel().ToString();

        SetHPAndMPStats();

        if (setup)
        {
            manaSlider.maxValue = playerComponent.RetrieveMaxMana();
            manaSlider.value = playerComponent.RetrieveMaxMana();
            healthSlider.maxValue = playerComponent.RetrieveMaxHealth();
            healthSlider.value = playerComponent.RetrieveMaxHealth();
        }
        else
        {
            manaSlider.maxValue = playerComponent.RetrieveMaxMana();
            manaSlider.value = playerComponent.RetrieveMana();
            healthSlider.maxValue = playerComponent.RetrieveMaxHealth();
            healthSlider.value = playerComponent.RetrieveHealth();
        }
    }
    /// <summary>
    /// Method that takes into account a player setting before indicating the hp and mp stats
    /// </summary>
    private void SetHPAndMPStats()
    {
        if (!Globals.CurMaxPositionSwitch) // Enabled should be CUR / MAX
        {
            healthTextPlaceOne.text = playerComponent.RetrieveHealth().ToString();
            healthTextPlaceTwo.text = playerComponent.RetrieveMaxHealth().ToString();
            manaTextPlaceOne.text = playerComponent.RetrieveMana().ToString();
            manaTextPlaceTwo.text = playerComponent.RetrieveMaxMana().ToString();
        }
        else                                // Disabled should be MAX / CUR
        {
            healthTextPlaceOne.text = playerComponent.RetrieveMaxHealth().ToString();
            healthTextPlaceTwo.text = playerComponent.RetrieveHealth().ToString();
            manaTextPlaceOne.text = playerComponent.RetrieveMaxMana().ToString();
            manaTextPlaceTwo.text = playerComponent.RetrieveMana().ToString();
        }
    }
    /// <summary>
    /// Updates the health, mana, and armor within the general UI screen based on the current player condition
    /// </summary>
    /// <param name="playerCondition">Reference to the current state of the player</param>
    public void UpdateHealthAndMana(Player playerCondition)
    {
        int maxHP                   = playerCondition.RetrieveMaxHealth();
        int maxMP                   = playerCondition.RetrieveMaxMana();
        int curHP                   = playerCondition.RetrieveHealth();
        int curMP                   = playerCondition.RetrieveMana();

        playerLevel.text            = playerCondition.GetLevel().ToString();

        healthSlider.maxValue      = maxHP;
        manaSlider.maxValue        = maxMP;

        healthSlider.value         = curHP;
        manaSlider.value           = curMP;

        SetHPAndMPStats();
    }
    public void EnableEventLayout()
    {
        //ResetUI();

        // TODO ---> Needs further work and implementation
        List<GameObject> buttons = new List<GameObject>();
        int number = 2;
        for (int i = 1; i <= number; i++)
        {
            //buttons.Add(Instantiate(normalButton, choice_Panel));
            TextMeshProUGUI retainer = buttons[i - 1].GetComponentInChildren<TextMeshProUGUI>();
            switch (i)
            {
                case 1:
                {
                    retainer.text = "Choice 1";
                    break;
                }
                case 2:
                {
                    retainer.text = "Choice 2";
                    break;
                }
            }
        }
    }
    /// <summary>
    /// Indicates modifiers within the horizontal row layout
    /// First deletes any that are already present and re-applies their images and descriptions to prevent duplicates
    /// </summary>
    /// <param name="player"></param>
    public void UpdateModifiers(Player player)
    {
        foreach (Transform item in modifierField)
            Destroy(item.gameObject);

        foreach (KeyValuePair<Modifier, int> modifier in player.GatherModList())
        {
            GameObject modImage = Instantiate(modifierPrefab, modifierField);
            modImage.GetComponent<Image>().sprite = modifier.Key.ModSprite;
            modImage.GetComponent<ModifierHelper>().InjectModifier(modifier.Key, modifier.Value);
        }
    }
    /// <summary>
    /// Opens the inventory screen and deactivates the inventory button since the screen is open, waking it up
    /// </summary>
    public void OpenInventoryScreen()
    {
        inventoryCanvas.enabled = true;
        DeactivateInventoryButton();
        GetComponent<InventoryManipulator>().WakeUp();
    }
    /// <summary>
    /// Closes the inventory screen and reactivates the inventory button since the screen is closed
    /// </summary>
    public void CloseInventoryScreen()
    {
        inventoryCanvas.enabled = false;
        ReactivateInventoryButton();
        GetComponent<InventoryManipulator>().Sleep();
    }
    /// <summary>
    /// Deactivates the inventory button to not be able to be clicked during scenes, parts in battle, etc.
    /// </summary>
    public void DeactivateInventoryButton()
    {
        inventoryButton.GetComponent<Button>().interactable = false;
        inventoryButton.GetComponent<Image>().color = DisabledColor;
    }
    /// <summary>
    /// Reactivates the inventory button to be able to be clicked for inventory management, such as in the end of encounters
    /// </summary>
    public void ReactivateInventoryButton()
    {
        inventoryButton.GetComponent<Button>().interactable = true;
        inventoryButton.GetComponent<Image>().color = Color.white;
    }
    public List<GameObject> GetAllyIconGUIs()
        => allyIcons;
    public void GenerateGUIs(GameObject[] allyObjects)
    {
        foreach (GameObject ally in allyObjects)
        {
            GameObject allyIcon = Instantiate(partyGuiPrefab, partyTransform);
            allyIcons.Add(allyIcon);
            allyIcon.GetComponent<PartyMemberGUI>().CallCreateGUI(ally.GetComponent<Ally>());
            ally.GetComponent<Ally>().InjectGUI(allyIcon.GetComponent<PartyMemberGUI>());
        }
    }
    public void UpdateGUIs(GameObject[] allyObjects)
    {
        foreach (GameObject allyObject in allyObjects)
        {
            try
            {
                allyObject.GetComponent<Ally>().GetGUI().UpdateStats(allyObject.GetComponent<Ally>());
            }
            catch { continue; }
        }
    }
    /// <summary>
    /// Creates a temporary GUI for the minion summoned by an ally or player
    /// </summary>
    /// <param name="minionComp">The minion Ally component</param>
    public void CreateTempGUI(Ally minionComp)
    {
        // Creates new GUI and initializes the minion list if not already initialized
        GameObject minionIcon = Instantiate(partyGuiPrefab, partyTransform);
        minionIcons ??= new List<GameObject>();
        minionIcons.Add(minionIcon);

        // Sets up the connections within the Party Member GUI and the Ally component
        minionIcon.GetComponent<PartyMemberGUI>().CallCreateGUI(minionComp);
        minionComp.InjectGUI(minionIcon.GetComponent<PartyMemberGUI>());
    }
    /// <summary>
    /// Eliminates all the temporary GUIs since the minions will have been destroyed at the end of battle
    /// </summary>
    public void EliminateTempGUIs()
    {
        // If the minions list wasn't intiialized, simply return since that indicates no minions were made
        if (minionIcons is null)
            return;

        int length = minionIcons.Count;
        // Destroy all Minion GUIs
        for (int i = 0; i < length; ++i)
        {
            // Destroy the GUI and then break out
            GameObject minionGUI = minionIcons[0];
            minionIcons.Remove(minionGUI);
            Destroy(minionGUI);
        }
    }
    /// <summary>
    /// Eliminates a specific GUI based on the ally component injected
    /// This is for when a minion has been fully defeated
    /// </summary>
    /// <param name="minionComp">The ally component to be searched for in the list</param>
    public void EliminateMinionGUI(Ally minionComp)
    {
        for (int i = 0; i < minionIcons.Count; ++i)
        {
            // Check for instance ID equality for the entities
            if (minionIcons[i].GetComponent<PartyMemberGUI>().GetAllyInfo().GetUniqueID() == minionComp.GetUniqueID())
            {
                // Destroy the GUI and then break out
                GameObject minionGUI = minionIcons[i];
                minionIcons.Remove(minionGUI);
                Destroy(minionGUI);
                break;
            }
        }
    }
    public async void RollToHit(bool rollingForDamage, bool hasCrit, SortedDictionary<int, (int, Dice)> diceToRoll, Entity attacker, Entity target, int toHitValue, 
                            int armorValue, SortedDictionary<int, (int, Dice)> damageRolls, Dictionary<string, (List<string>, List<object>)> triggers, bool isFinalAttack)
    {
        allDiceRolled = false;
        canRollForDamage = rollingForDamage;
        EnemyUI.Instance.SwitchMemberTurnText(false);
        diceRoller.SetActive(true);
        DiceRollerGUI rollerInstance = diceRoller.GetComponentInChildren<DiceRollerGUI>();
        this.isFinalAttack = isFinalAttack;
        rollerInstance.InjectNecessaryInfo(hasCrit, attacker, target, toHitValue, armorValue, damageRolls, triggers);
        rollerInstance.InjectToHitModifiers();
        rollerInstance.StartDiceRoller(diceToRoll, true);

        while (allDiceRolled is false)
            await Task.Yield();

        await Task.CompletedTask;
    }
    public async Task RollForDamage(SortedDictionary<int, (int, Dice)> diceToRoll, int baseDamage, int totalDamage, Dictionary<int, (List<SpellSO.Element>, List<WeaponSO.Type>)> typeCollection)
    {
        allDiceRolled = false;
        canRollForDamage = null;
        EnemyUI.Instance.SwitchMemberTurnText(false);
        diceRoller.SetActive(true);
        DiceRollerGUI rollerInstance = diceRoller.GetComponentInChildren<DiceRollerGUI>();
        rollerInstance.InjectDamageModifiers(baseDamage, totalDamage, typeCollection);
        rollerInstance.StartDiceRoller(diceToRoll, false);

        while (allDiceRolled is false)
            await Task.Yield();

        await Task.CompletedTask;
    }
    public void DiceAllRolled(Entity attacker, Entity target, int toHitValue, int armorValue, SortedDictionary<int, (int, Dice)> damageRolls, Dictionary<string, (List<string>, List<object>)> triggers)
    {
        allDiceRolled = true;
        diceRoller.SetActive(false);

        BattleHandler.Instance.CalculateDamage(diceRoller.GetComponent<DiceRollerGUI>().wasCrit, canRollForDamage, attacker, target, toHitValue, armorValue, damageRolls, triggers, isFinalAttack);
    }

    public void SwitchCurMaxPositions()
    {
        SetHPAndMPStats();
        GetComponent<InventoryManipulator>().SwitchCurMaxText();

        if (partyTransform.childCount > 0)
        {
            foreach (Transform child in partyTransform)
                child.gameObject.GetComponent<PartyMemberGUI>().SwitchHPandMPStats();
        }
    }
}