using System; using BlueWater.Items; using BlueWater.Players; using BlueWater.Utility; using Sirenix.OdinInspector; using UnityEngine; namespace BlueWater.Tycoons { public static class BarrelSpineAnimation { public const string Idle = "IdleNormal"; public const string Mold = "IdleDirty"; public const string ChangeIdle = "ChangeClean"; public const string ChangeMold = "ChangeDirty"; } public class Barrel : InteractionFurniture { [SerializeField] private SpineController _spineController; [SerializeField, Required] private SpriteRenderer _liquidImage; [SerializeField, Required] private SpriteRenderer _fill; [SerializeField, Range(1f, 5f), Tooltip("목표 색상 * 밝기")] private float _colorIntensity = 2f; [SerializeField] private string _idx; [SerializeField] private LiquidData _liquidData; [field: SerializeField] public int CurrentAmount { get; private set; } [field: SerializeField] public bool IsStatue { get; private set; } [field: SerializeField] public bool IsActivated { get; private set; } [field: SerializeField] public bool IsAutoSupply { get; private set; } [field: SerializeField] public bool IsMoldy { get; private set; } [SerializeField] private float _playerHoldingTime = 3f; private Material _instanceMaterial; private float _supplyElapsedTime; private bool _isPlayerInteracting; public static event Action OnBarrelInteracted; public static event Action OnBarrelCancelInteracted; // Hashes private static readonly int LiquidAmountHash = Shader.PropertyToID("_LiquidAmount"); private static readonly int LiquidColorHash = Shader.PropertyToID("_LiquidColor"); protected override void Awake() { base.Awake(); _spineController = GetComponent(); _instanceMaterial = Instantiate(_fill.material); _fill.material = _instanceMaterial; _liquidData = ItemManager.Instance.LiquidDataSo.GetDataByIdx(_idx); SetCurrentAmount(0); } protected override void Start() { base.Start(); EventManager.OnAddBarrels += AddCurrentAmount; EventManager.OnAutoSupplyBarrels += AutoSupply; _liquidImage.sprite = IsActivated ? _liquidData.Sprite : DataManager.Instance.SpriteDataSo.BarrelLock; _instanceMaterial.SetColor(LiquidColorHash, _liquidData.Color * _colorIntensity); if (_spineController) { _spineController.PlayAnimation(BarrelSpineAnimation.Idle, false); } } private void Update() { if (IsShowing) { var holdingGauge = Mathf.Clamp(HoldingElapsedTime / _playerHoldingTime, 0f, 1f); EventManager.InvokeHoldInteracting(holdingGauge); } if (IsMoldy) { if (HoldingElapsedTime >= _playerHoldingTime) { Recovery(); } if (_isPlayerInteracting) { HoldingElapsedTime += Time.deltaTime; } else { if (HoldingElapsedTime > 0f) { HoldingElapsedTime -= Time.deltaTime; } } } else { if (!IsAutoSupply) return; if (_supplyElapsedTime >= 1f) { AddCurrentAmount(TycoonManager.Instance.TycoonStatus.BarrelAutoIncrease); _supplyElapsedTime -= 1f; } _supplyElapsedTime += Time.deltaTime; } } private void OnDestroy() { EventManager.OnAddBarrels -= AddCurrentAmount; EventManager.OnAutoSupplyBarrels -= AutoSupply; } public override void Interaction() { if (!IsMoldy) { OnBarrelInteracted?.Invoke(this); GameManager.Instance.CurrentTycoonPlayer.IsMakingCocktail = true; } else { _isPlayerInteracting = true; } } public override void CancelInteraction() { if (!IsMoldy) { OnBarrelCancelInteracted?.Invoke(); GameManager.Instance.CurrentTycoonPlayer.IsMakingCocktail = false; } else { _isPlayerInteracting = false; HoldingElapsedTime = 0f; } } /// /// 1. 플레이어가 빈 잔을 들고 있거나 완성되지 않은 잔을 들고 있을 때 /// public override bool CanInteraction() { return IsActivated && !CurrentTycoonPlayer.TycoonPickupHandler.IsPickedUpItem && ((!IsMoldy && CanConsume(1)) || IsMoldy); } public override void ShowInteractionUi() { if (IsMoldy) { UpdateLocalizedString("InteractionMold"); } else { InteractionMessage = $"{Utils.GetLocalizedString(_liquidData.Idx)} {Utils.GetLocalizedString("Pour")}"; } if (IsStatue) { base.ShowInteractionUi(); } else { _spineController.EnableCustomMaterial(); EventManager.InvokeShowInteractionUi(InteractionMessage); IsShowing = true; } } public override void HideInteractionUi() { if (IsStatue) { base.HideInteractionUi(); } else { _spineController.DisableCustomMaterial(); EventManager.InvokeHideInteractionUi(); IsShowing = false; } } public bool CanConsume(int amount) { return CurrentAmount - amount > 0; } public void Consume(int amount) { if (CurrentAmount == int.MaxValue) { return; } var consumeAmount = CurrentAmount - amount; SetCurrentAmount(consumeAmount); } public bool TryConsume(int amount) { if (!CanConsume(amount)) return false; Consume(amount); return true; } public LiquidData GetLiquidData() => _liquidData; public void SetCurrentAmount(int amount) { if (CurrentAmount == int.MaxValue) { return; } CurrentAmount = amount; var liquidAmount = CurrentAmount / 4000f; _instanceMaterial.SetFloat(LiquidAmountHash, liquidAmount); } public void Activate() { IsActivated = true; _liquidImage.sprite = IsActivated ? _liquidData.Sprite : DataManager.Instance.SpriteDataSo.BarrelLock; SetCurrentAmount(_liquidData.GetMaxAmount()); } public void AutoSupply() { IsAutoSupply = true; } public void AddCurrentAmount(int addedValue) { if (!IsActivated) return; SetCurrentAmount(CurrentAmount + addedValue); } public bool CanMold() { return _liquidData.Idx != "LiquidA" && IsActivated && !IsMoldy; } public void Mold() { IsMoldy = true; _spineController.PlayAnimation(BarrelSpineAnimation.ChangeMold, false); _spineController.AddAnimation(BarrelSpineAnimation.Mold, true); } public void Recovery() { CancelInteraction(); IsMoldy = false; _spineController.PlayAnimation(BarrelSpineAnimation.ChangeIdle, false); _spineController.AddAnimation(BarrelSpineAnimation.Idle, false); } } }