using System; using System.Collections; using BlueWater.Npcs.Customers; using DG.Tweening; using TMPro; using UnityEngine; using UnityEngine.UI; using Random = UnityEngine.Random; namespace BlueWater { public class Bill : MonoBehaviour { [SerializeField] private RectTransform _rect; [SerializeField] private AnimationController _animationController; [SerializeField] private Slider _slider; [SerializeField] private Image _filledImage; [SerializeField] private Image _orderImage; [SerializeField] private GameObject _makingCocktailPivotObject; [SerializeField] private GameObject _checkImageObject; [SerializeField] private GameObject _stampImageObject; [SerializeField] private GameObject _tableNumberImageObject; [SerializeField] private TMP_Text _tableNumberText; [SerializeField] private Color _startColor = Color.green; [SerializeField] private Color _middleColor = Color.yellow; [SerializeField] private Color _endColor = Color.red; public BillInfo CurrentBillInfo { get; private set; } private Tween _sliderTween; private Sequence _moveSequence; private Sequence _arrivedSequence; private Vector3 _spawnPosition; private Color _previousColor; private float _maxDistance; private Action _removeEvent; private void OnDestroy() { _slider.onValueChanged.RemoveListener(OnSliderValueChanged); _sliderTween?.Kill(); _moveSequence?.Kill(); _arrivedSequence?.Kill(); } public void Initialize(Customer customer, Vector3 spawnPosition, Vector3 billInfoPosition0, Action removeEvent) { _removeEvent = removeEvent; _slider.onValueChanged.AddListener(OnSliderValueChanged); _spawnPosition = spawnPosition; _rect.anchoredPosition = _spawnPosition; _maxDistance = Vector3.Distance(_rect.anchoredPosition, billInfoPosition0); _slider.value = 1f; _slider.gameObject.SetActive(true); _orderImage.sprite = customer.OrderedCocktailData.Sprite; _orderImage.gameObject.SetActive(true); _makingCocktailPivotObject.SetActive(false); _checkImageObject.SetActive(false); _stampImageObject.SetActive(false); _tableNumberText.text = customer.CurrentTableSeat.TableNumber.ToString(); _tableNumberImageObject.SetActive(true); SetTween(customer.CurrentLevelData.WaitTime, customer.HurryTime); } public void SetTween(int waitTime, int hurryTime) { _sliderTween = _slider.DOValue(0f, hurryTime) .From(1f) .SetEase(Ease.Linear) .SetDelay(waitTime) .SetAutoKill(true); } private void OnSliderValueChanged(float value) { if (value > 0.6f) { if (_previousColor != _startColor) { _filledImage.color = _startColor; _previousColor = _startColor; } } else if (value > 0.3f) { if (_previousColor != _middleColor) { _filledImage.color = _middleColor; _previousColor = _middleColor; } } else { if (_previousColor != _endColor) { _filledImage.color = _endColor; _previousColor = _endColor; } } } public void Move(BillInfo billInfo) { if (!this || _rect == null || !gameObject.activeInHierarchy) return; if (CurrentBillInfo != null) { CurrentBillInfo.IsEmpty = true; } CurrentBillInfo = billInfo; CurrentBillInfo.IsEmpty = false; CurrentBillInfo.IsMoving = true; var distance = Vector3.Distance(_rect.anchoredPosition, CurrentBillInfo.Position); var moveTime = Mathf.Lerp(0.2f, 1f, distance / _maxDistance); var rotationAngle = Mathf.Lerp(8f, 40f, distance / _maxDistance); var punchStrength = Mathf.Lerp(1f, 5f, distance / _maxDistance); _moveSequence = DOTween.Sequence() .Append(_rect?.DOLocalMoveX(CurrentBillInfo.Position.x, moveTime)) .Join(_rect?.DOLocalRotate(new Vector3(0, 0, rotationAngle), moveTime / 5f)) .Join(_rect?.DOPunchRotation(new Vector3(0f, 0f, punchStrength), moveTime * 4f / 5f, 3, 0.2f) .SetDelay(0.2f) .SetEase(Ease.InOutBounce)) .AppendCallback(() => { if (!this || _rect == null) return; OnArrivedTarget(); }) .SetAutoKill(true); } private void OnArrivedTarget() { if (CurrentBillInfo == null) return; CurrentBillInfo.IsMoving = false; var randomZ = Random.Range(-15f, 15f); _arrivedSequence = DOTween.Sequence() .Append(_rect?.DOLocalRotate(Vector3.zero, 0.2f).SetEase(Ease.InQuad)) .Append(_rect?.DOPunchRotation(new Vector3(0f, 0f, -20f), 1f, 5, 0.5f).SetEase(Ease.InOutBounce)) .Append(_rect?.DOLocalRotate(new Vector3(0f, 0f, randomZ), 0.2f).SetEase(Ease.InQuad)) .SetAutoKill(true); } public void OrderResult(bool isSucceed) { StartCoroutine(WaitForAnimation(isSucceed)); } private IEnumerator WaitForAnimation(bool isSucceed) { _animationController.SetAnimationParameter("isOrderedSucceed", isSucceed); _animationController.SetAnimationParameter("isAnimationTrigger", true); var animationName = isSucceed ? "OrderedSucceed" : "OrderedFail"; var animationStarted = false; yield return StartCoroutine(_animationController.WaitForAnimationToRun(animationName, success => animationStarted = success)); if (!animationStarted) { Debug.LogError("애니메이션 오류"); } _stampImageObject.SetActive(true); _sliderTween?.Kill(); var isTrigger = false; while (_animationController.IsComparingCurrentAnimation(animationName) && _animationController.GetCurrentAnimationNormalizedTime() < 1f) { if (!isTrigger && _animationController.GetCurrentAnimationNormalizedTime() >= 0.5f) { _slider.gameObject.SetActive(false); _makingCocktailPivotObject.SetActive(false); _checkImageObject.gameObject.SetActive(false); _orderImage.gameObject.SetActive(false); _stampImageObject.SetActive(false); _tableNumberImageObject.SetActive(false); isTrigger = true; } yield return null; } Destroy(); } public void BartenderMakingCocktail() { _makingCocktailPivotObject.gameObject.SetActive(true); } public void BartenderCompleteMakingCocktail() { _makingCocktailPivotObject.gameObject.SetActive(false); _checkImageObject.gameObject.SetActive(true); _animationController.SetAnimationParameter("isBartenderChecked", true); } public void ResetGauge() { if (_sliderTween == null) { Debug.LogError("Bill 게이지 리셋 오류"); return; } _sliderTween.Restart(); } public void Destroy() { _sliderTween?.Kill(); _moveSequence?.Kill(); _arrivedSequence?.Kill(); CurrentBillInfo.ResetData(); _removeEvent?.Invoke(); Destroy(gameObject); } } }