using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; public class CastBarHandler : MonoBehaviour { #region Singleton private static CastBarHandler _instance; // Public reference to the singleton instance public static CastBarHandler Instance { get { // If the instance doesn't exist, try to find it in the scene if (_instance == null) { _instance = FindObjectOfType(); // If it's still null, create a new GameObject and add the component if (_instance == null) { GameObject singletonObject = new GameObject(typeof(CastBarHandler).Name); _instance = singletonObject.AddComponent(); } } return _instance; } } #endregion public GameObject castBar; public Image imageToFill; public float timer; public float currentCastTime; public float currentChannelTime; public BaseAbility currentAbility; float startFill; float endFill; public UnityEvent OnCastingStateChanged = new UnityEvent(); Action currentlyWaitingAbilityExecution; Action currentlyChannelingAbilityExecution; private void Awake() { if (_instance != null && _instance != this) { Destroy(gameObject); return; } // If this is the first instance, set it as the singleton _instance = this; DontDestroyOnLoad(gameObject); } private void Start() { ToggleCastBarVisibility(false); } public void ShowCastBar(BaseAbility ability, Action abilityExecution) { currentlyWaitingAbilityExecution = abilityExecution; currentAbility = ability; currentCastTime = ability.castTime; StartCoroutine(FillImageOverTime(ability.castTime + 0.01f)); } public void ShowChannelingBar(BaseAbility ability, Action abilityChannelExecution) { currentlyChannelingAbilityExecution = abilityChannelExecution; currentAbility = ability; currentChannelTime = ability.castTime; StartCoroutine(DecayImageOverTime(((ChanneledAbility)ability).duration + 0.01f)); } IEnumerator FillImageOverTime(float castTime) { ToggleCastBarVisibility(true); timer = 0f; startFill = 0f; endFill = 1f; imageToFill.fillAmount = startFill; while (timer < castTime) { float fillAmount = Mathf.Lerp(startFill, endFill, timer / castTime); imageToFill.fillAmount = fillAmount; timer += Time.deltaTime; yield return null; } // Ensure fillAmount is exactly 1 at the end imageToFill.fillAmount = endFill; ToggleCastBarVisibility(false); } IEnumerator DecayImageOverTime(float channelTime) { ToggleCastBarVisibility(true); timer = 0f; startFill = 1f; endFill = 0f; imageToFill.fillAmount = startFill; while (timer < channelTime) { float fillAmount = Mathf.Lerp(startFill, endFill, timer / channelTime); imageToFill.fillAmount = fillAmount; timer += Time.deltaTime; yield return null; } // Ensure fillAmount is exactly 1 at the end imageToFill.fillAmount = endFill; ToggleCastBarVisibility(false); } private void ToggleCastBarVisibility(bool isVisible) { castBar.SetActive(isVisible); OnCastingStateChanged.Invoke(isVisible); } public void CancelChannelingOnButtonReleased() { StopAllCoroutines(); ToggleCastBarVisibility(false); } public void ExecuteQueuedCastOnAnimationEvent() { //Debug.Log("$$Executing queued melee before null check"); if (currentlyWaitingAbilityExecution == null) return; //Debug.Log("$$Executing queued melee after check"); currentlyWaitingAbilityExecution.Invoke(); } }