using System; using System.Threading.Tasks; using DG.Tweening; using UnityEngine; using UnityEngine.Assertions; using UnityEngine.UI; using TMPro; using System.Collections.Generic; using asap.core; using Game; public class EventBreakTunnelView : MonoBehaviour { [SerializeField] private EventBreakBlock[] blocks; [SerializeField] private Button btnDrill; [SerializeField] private Transform endPivot, drillStartPivot; [SerializeField] private EventBreakDrillDisplay drillDisplay; [SerializeField] private GameObject fxButtonGlitter; [SerializeField] private TMP_Text textCost; [SerializeField] private Animator aniBtnDrill; private float _spawnInterval = 0.1f, _dropDuration = 0.5f, _drillDuration = 0.8f, _dropHeight = 1680, _drillReadyDuration = 0.5f, _resetTunnelDelay = 10f, _btnPressedDuration = 0.3f, _drillDetectionRange = 50f, _blockDropSfxDelay = 0.1f; private AnimationCurve _easeCurve; private int _tunnelIdx; private List _blockEndPoints; private void Start() { btnDrill.onClick.AddListener(async () => await StartDrilling()); // foreach (var block in blocks) // Debug.Log($"[EventBreak] block height: {block.name} at {block.transform.position.y}"); } public void Init(EventBreakTunnelViewInitInfo info) { _blockEndPoints = new List(); foreach (var block in blocks) { block.gameObject.SetActive(false); _blockEndPoints.Add(block.transform.position); } drillDisplay.Init(info.Idx); _spawnInterval = info.SpawnInterval; _dropDuration = info.DropDuration; _drillDuration = info.DrillDuration; _tunnelIdx = info.Idx; _dropHeight = info.DropHeight; textCost.text = info.Job.Cost.ToString(); _easeCurve = info.EaseCurve; _drillReadyDuration = info.DrillReadyDuration; _resetTunnelDelay = info.ResetTunnelDelay; _btnPressedDuration = info.ButtonPressedDuration; _drillDetectionRange = info.DrillDetectionRange; _blockDropSfxDelay = info.BlockDropSfxDelay; SetTunnel(info.Job); } public async void SetTunnel(DrillJobModel job) { try { EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.Block)); aniBtnDrill.Play("Normal"); int jobCount = job.Blocks.Length, blockCount = blocks.Length; Assert.IsTrue(jobCount == blockCount, $"[EventBreak]Block count mismatch. Got {jobCount} jobs and {blockCount} blocks"); drillDisplay.PlayEnter(drillStartPivot.position); PlayBlockFallSfx(_blockDropSfxDelay); for (int i = blocks.Length - 1; i >= 0; i--) { blocks[i].Appear(job.Blocks[i], dropHeight: _dropHeight, endPoint: _blockEndPoints[i], dropTime: _dropDuration, easeCurve: _easeCurve); await Task.Delay(TimeSpan.FromSeconds(_spawnInterval)); } await Task.Delay(TimeSpan.FromSeconds(_dropDuration + 0.1f)); EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.Unblock)); } catch (Exception e) { Debug.Log($"[EventBreak] TunnelInitiationError: {e.Message}\n{e.StackTrace}"); } } private async void PlayBlockFallSfx(float delay = 0) { try { await Task.Delay(TimeSpan.FromSeconds(delay)); GContext.Publish(new EventUISound("audio_ui_drill_brick_falling", 0)); } catch (Exception e) { Debug.Log($"[EventBreak] SFX error: {e.Message}\n{e.StackTrace}"); } } public async Task StartDrilling() { // Debug.Log($"[EventBreak] Click No.{_tunnelIdx}!", this); if (EventBreakAct.DrillSystem.DoDrillJob(_tunnelIdx)) { EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.Block)); PlayBtnPressed(); drillDisplay.PlayDrill(); await Task.Delay(TimeSpan.FromSeconds(_drillReadyDuration)); drillDisplay.GetDrillTween(endPivot.transform.position, _drillDuration) .OnUpdate(DrillBlocks) .OnComplete(OnDrillComplete); } else { EventBreakAct.EventAggregator.Publish(new EventBreakInsufficientTicket()); } } public void StartDrillingTest() { // Debug.Log($"[EventBreak] Click No.{_tunnelIdx}!", this); drillDisplay.PlayDrill(); drillDisplay.GetDrillTween(endPivot.transform.position, _drillDuration) .OnUpdate(DrillBlocks); // .OnComplete(OnDrillComplete); } private async void OnDrillComplete() { try { await Task.Delay(TimeSpan.FromSeconds(_resetTunnelDelay)); var dm = GContext.container.Resolve(); SetTunnel(dm.DrillJobList[_tunnelIdx]); EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.Unblock)); } catch (Exception e) { Debug.Log($"[EventBreak] ResetTunnelError: {e.Message}\n{e.StackTrace}"); } } private void DrillBlocks() { foreach (var b in blocks) { if (b.gameObject.activeSelf == false) continue; var delta = b.transform.position.y - drillDisplay.Y; if (delta > _drillDetectionRange) continue; b.Break(); } } public void SetAvailabilityDisplay(bool doesShow) { fxButtonGlitter.SetActive(doesShow); textCost.color = doesShow ? Color.white : Color.red; } private async void PlayBtnPressed() { var isFxOn = fxButtonGlitter.activeInHierarchy; try { aniBtnDrill.Play("Pressed"); fxButtonGlitter.SetActive(false); await Task.Delay(TimeSpan.FromSeconds(_btnPressedDuration)); aniBtnDrill.Play("Normal"); fxButtonGlitter.SetActive(isFxOn); } catch (Exception e) { Debug.Log($"[EventBreak] Button Error: {e.Message}\n{e.StackTrace}"); } } } public class EventBreakTunnelViewInitInfo { public DrillJobModel Job { get; set; } public float SpawnInterval { get; set; } public float DropDuration { get; set; } public float DrillDuration { get; set; } public float DropHeight { get; set; } public float DrillReadyDuration { get; set; } public float ResetTunnelDelay { get; set; } public float ButtonPressedDuration { get; set; } public float DrillDetectionRange { get; set; } public float BlockDropSfxDelay { get; set; } public int Idx { get; set; } public AnimationCurve EaseCurve { get; set; } }