using UniRx; using UnityEngine; using UnityEngine.UI; using System.Collections; using System.Collections.Generic; using TMPro; using System.Linq; using UnityEngine.Assertions; using System.Threading.Tasks; using System; using game; using asap.core.common; using GameCore; using Game; using asap.core; public class EventLuckMagicMainPanel : MonoBehaviour { [SerializeField] private EventLuckMagicBlockView[] outerRing, middleRing, innerRing; [SerializeField] private Button btnClose, btnTicket, btnInfo; [SerializeField] private GameObject singleBtnGroup, doubleBtnGroup, goClickMask, fxReset; [SerializeField] private TMP_Text textTicketCount, textHigherRingCountDown, textTimer; [SerializeField] private EventLuckMagicTaskView[] taskViews; [SerializeField] private RewardFly rewardFlyPrefab; // [SerializeField] private RewardStashButton _rewardStashButton; [SerializeField] private EventLuckMagicDrawButtonView btnDrawCurrentSingle, btnDrawCurrentDouble, btnDrawHigher; [SerializeField] private EventLuckMagicSkipAnimationBtn skipSingle, skipDouble; [SerializeField] private EventLuckMagicLightView lightView; [SerializeField] private EventLuckMagicSelectionView selectionView; [SerializeField] private LuckyTaskBtn luckyTaskBtn; // private EventLuckMagicModel _model; private EventLuckMagicSystem _system; private EventLuckMagicTableContext _tableContext; private EventLuckMagicParamsCtrl _paramsCtrl; private IEventAggregator _eventAggregator; private IObjectPoolService _objectPoolService; private Dictionary _taskViewDict; private EventLuckMagicSpinParams _outerSpinParams, _innerSpinParams, _middleSpinParams; private const float RewardFlyDuration = 1.2f, resetFxDuration = 0.8f; private int _evIsEnd, _evItemCost, _evRing, _evSquareId, _evRewardId, _evRewardCount, _evAchieve_target_reward1, _evAchieve_target_reward2, _evTurnItem1, _evTurnItem2, _evRound; private const string SfxSelectionStrong = "audio_ui_luckmagic_select_1", SfxSelectionWeak = "audio_ui_luckmagic_select_2"; private void Start() { btnClose.onClick.AddListener(OnClickClose); var _model = GContext.container.Resolve(); btnDrawCurrentSingle.ButtonDraw.onClick.AddListener(() => DrawCurrentRing()); btnDrawCurrentDouble.ButtonDraw.onClick.AddListener(() => DrawCurrentRing()); btnDrawHigher.ButtonDraw.onClick.AddListener(() => DrawHigherRing()); btnTicket.onClick.AddListener(OnClickPack); EventLuckMagicAct.EventAggregator.GetEvent() .Subscribe(_ => UpdateTicketCount()).AddTo(this); btnInfo.onClick.AddListener(OnClickInfo); lightView.PlayStandBy(); fxReset.SetActive(false); luckyTaskBtn.Init(_model, _model.LuckyTaskRedPointKey); } public void Init(Vector2? selectionPosition = null) { _tableContext = EventLuckMagicAct.TableContext; var _model = GContext.container.Resolve(); _system = EventLuckMagicAct.System; GetParams(_model.ParamsCtrl); for (int i = 0; i < outerRing.Length; i++) outerRing[i].Init(_model.OuterRing.Blocks[i]); for (int i = 0; i < middleRing.Length; i++) middleRing[i].Init(_model.MiddleRing.Blocks[i]); for (int i = 0; i < innerRing.Length; i++) innerRing[i].Init(_model.InnerRing.Blocks[i]); SetDrawButtons(!_model.HigherRingData.DoesExist); _taskViewDict = new Dictionary(); var taskInfo = _tableContext.GetTaskInfo(_model.RoundCount); for (int i = 0; i < taskInfo.Count; i++) _taskViewDict.Add(taskInfo.Keys.ToList()[i], taskViews[i]); UpdateTicketCount(); foreach (var kv in taskInfo) _taskViewDict[kv.Key].Init(_model.TaskProgress[kv.Key], kv.Value, kv.Key); _eventAggregator = EventLuckMagicAct.EventAggregator; selectionView.ShowStandByOrHide(selectionPosition); CreateRewardFlyObjectPool(); // _rewardStashButton.Init(_eventAggregator); _eventAggregator.GetEvent() .Subscribe(_ => DrawHigherRing(true)).AddTo(this); skipSingle.Init(); skipDouble.Init(); UpdateTimer(); Observable.Interval(TimeSpan.FromSeconds(1f)).Subscribe(UpdateTimer).AddTo(this); var chainPackData = _model.ToChainPackData(); RedPointManager.Instance.SetRedPointState(chainPackData.RedPointKey, chainPackData.DoNeedPackRedPoint); } private async void ResetPanel() { var _model = GContext.container.Resolve(); try { // Debug.Log($"[EventLuckMagic] ResetPanel."); SetDrawButtons(!_model.HigherRingData.DoesExist); UpdateTicketCount(); selectionView.ShowStandByOrHide(); _taskViewDict.Values.Select((v, i) => (v, i)).ToList() .ForEach(vi => { vi.v.ResetTask(EventLuckMagicAct.TableContext.GetTaskReward(_model.RoundCount, vi.i == 0)); vi.v.PlayAnimation(); }); skipSingle.Init(); skipDouble.Init(); fxReset.SetActive(false); fxReset.SetActive(true); await Task.Delay(TimeSpan.FromSeconds(resetFxDuration)); for (int i = 0; i < outerRing.Length; i++) outerRing[i].Init(_model.OuterRing.Blocks[i]); for (int i = 0; i < middleRing.Length; i++) middleRing[i].Init(_model.MiddleRing.Blocks[i]); for (int i = 0; i < innerRing.Length; i++) innerRing[i].Init(_model.InnerRing.Blocks[i]); BlockInput(false); } catch (Exception e) { Debug.Log($"[EventLuckMagic] ResetPanel error."); Debug.Log(e); } } private void OnClickClose() { var _model = GContext.container.Resolve(); // Debug.Log($"[EventLuckMagic] OnClickClose."); _model.ToPfData().Save(); _model.ToPpData().Save(); ReleaseRewardFlyObjectPool(); GContext.Publish(new UnloadActToNextAct()); } private void SetDrawButtons(bool doesShowSingle) { var _model = GContext.container.Resolve(); singleBtnGroup.SetActive(doesShowSingle); doubleBtnGroup.SetActive(!doesShowSingle); skipSingle.Init(); skipDouble.Init(); if (!doesShowSingle) { StartCoroutine(ScrapRoadSignCountDown()); } if (_model.CurrentRing == null) return; btnDrawCurrentSingle.Init(_model.CurrentRing.Cost, _model.CurrentRing.RingType); btnDrawCurrentDouble.Init(_model.CurrentRing.Cost, _model.CurrentRing.RingType); if (_model.HigherRingData.DoesExist) btnDrawHigher.Init(_model.HigherRingData.Ring.Cost, _model.HigherRingData.Ring.RingType); } private IEnumerator ScrapRoadSignCountDown() { var _model = GContext.container.Resolve(); while (_model.HigherRingData.DoesExist) { textHigherRingCountDown.text = LocalizationMgr.GetFormatTextValue("UI_COMMON_end", ConvertTools.ConvertTime2(_model.HigherRingData.RemainingTime)); yield return new WaitForSeconds(1); } SetDrawButtons(true); } private void UpdateTicketCount() { var _model = GContext.container.Resolve(); textTicketCount.text = $"{_model.TicketCount}"; } # if UNITY_EDITOR private void Update() { if (Input.GetKeyDown(KeyCode.T)) { _debugFlag = !_debugFlag; } } private bool _debugFlag = false; # endif private void DrawCurrentRing(bool hideButton = false) { DrawInRing(GContext.container.Resolve().CurrentRing, hideButton); } private void DrawHigherRing(bool hideButton = true) { DrawInRing(GContext.container.Resolve().HigherRingData.Ring, hideButton); } private void DrawInRing(EventLuckMagicRing ring, bool doesHideButton = false) { var _model = GContext.container.Resolve(); if (ring == null) { Debug.LogError($"[EventLuckMagic] Ring is null."); return; } if (_model.TicketCount < ring.Cost) { // Debug.Log($"[EventLuckMagic] Insufficient tickets."); OnClickPack(); return; } if (!_system.Draw(ring, out var spinCtx, out _evSquareId)) { ResetPanel(); return; } # if UNITY_EDITOR if (_debugFlag) { if (ring.RingType == EEventLuckMagicRingType.OuterRing) { spinCtx.Index = 14; spinCtx.Reward = new ItemData(8030102, 1); } else if (ring.RingType == EEventLuckMagicRingType.MiddleRing) { spinCtx.Index = 4; spinCtx.Reward = new ItemData(8030103, 1); } } # endif BlockInput(true); spinCtx.doesHideButton = doesHideButton; if (doesHideButton) { _model.HigherRingData.SetEmpty(); } _model.AddTicket(-ring.Cost); _system.GrantReward(spinCtx); _model.ToPfData().Save(); _evIsEnd = _model.IsGameDepleted ? 1 : 0; _evItemCost = ring.Cost; _evRing = ring.RingType switch { EEventLuckMagicRingType.OuterRing => 1, EEventLuckMagicRingType.MiddleRing => 2, EEventLuckMagicRingType.InnerRing => 3, _ => 0 }; _evRewardId = spinCtx.Reward.id; _evRewardCount = (int)spinCtx.Reward.count; var keys = _model.TaskProgress.Keys.ToList(); _evAchieve_target_reward1 = spinCtx.Reward.id == keys[0] && _model.TaskProgress[keys[0]] >= 3 ? 1 : 0; _evAchieve_target_reward2 = spinCtx.Reward.id == keys[1] && _model.TaskProgress[keys[1]] >= 3 ? 1 : 0; _evTurnItem1 = _tableContext.IsRewardRoadSign(EEventLuckMagicRingType.OuterRing, spinCtx.Reward.id) ? 1 : 0; _evTurnItem2 = _tableContext.IsRewardRoadSign(EEventLuckMagicRingType.MiddleRing, spinCtx.Reward.id) ? 1 : 0; _evRound = _model.RoundCount; // Debug.Log($"[EventLuckMagic] -------------------Event Tracking---------------------"); // Debug.Log($"[EventLuckMagic] is_end: {_evIsEnd}"); // Debug.Log($"[EventLuckMagic] item_cost: {_evItemCost}"); // Debug.Log($"[EventLuckMagic] ring: {_evRing}"); // Debug.Log($"[EventLuckMagic] square_id: {_evSquareId}"); // Debug.Log($"[EventLuckMagic] reward_id: {_evRewardId}"); // Debug.Log($"[EventLuckMagic] reward_count: {_evRewardCount}"); // Debug.Log($"[EventLuckMagic] achieve_target_reward1: {_evAchieve_target_reward1}"); // Debug.Log($"[EventLuckMagic] achieve_target_reward2: {_evAchieve_target_reward2}"); // Debug.Log($"[EventLuckMagic] turn_item1: {_evTurnItem1}"); // Debug.Log($"[EventLuckMagic] turn_item2: {_evTurnItem2}"); // Debug.Log($"[EventLuckMagic] -------------------End of Event Tracking---------------------"); # if AGG using (var e = GEvent.GameEvent("event_luckmagic")) { e.AddContent("round", _evRound) .AddContent("is_end", _evIsEnd) .AddContent("item_cost", _evItemCost) .AddContent("ring", _evRing) .AddContent("square_id", _evSquareId) .AddContent("reward_id", _evRewardId) .AddContent("reward_count", _evRewardCount) .AddContent("achieve_target_reward1", _evAchieve_target_reward1) .AddContent("achieve_target_reward2", _evAchieve_target_reward2) .AddContent("turn_item1", _evTurnItem1) .AddContent("turn_item2", _evTurnItem2); } # endif switch (ring.RingType) { case EEventLuckMagicRingType.OuterRing: SpinWheel(spinCtx, outerRing, _outerSpinParams); break; case EEventLuckMagicRingType.MiddleRing: SpinWheel(spinCtx, middleRing, _middleSpinParams); break; case EEventLuckMagicRingType.InnerRing: SpinWheel(spinCtx, innerRing, _innerSpinParams); break; } } private async void SpinWheel(EventLuckMagicSpinCtx spinCtx, EventLuckMagicBlockView[] blockViews, EventLuckMagicSpinParams p) { var _model = GContext.container.Resolve(); try { var ringData = spinCtx.Ring; var end = spinCtx.Index; Assert.IsTrue(ringData.Blocks.Count == blockViews.Length, $"RingData.Blocks.Count {ringData.Blocks.Count} != blockViews.Length {blockViews.Length}"); ringData.GetLoopAnimationInfo(end, p.ExtraLoopCount, out int startIdx, out int stepCount); selectionView.ShowBlinkOrStandBy(blockViews[startIdx].transform.position); int i = 0; float interval = 0, ratio; EventLuckMagicBlockView targetBlock = null; if (!_model.DoesSkipAnimation) { while (i < stepCount) { ratio = p.IntervalLerpCurve.Evaluate((float)i / stepCount); interval = Mathf.Lerp(p.MinInterval, p.MaxInterval, ratio); await Task.Delay(TimeSpan.FromSeconds(interval)); i++; targetBlock = blockViews[(startIdx + i) % blockViews.Length]; selectionView.ShowBlinkOrStandBy(targetBlock.transform.position); GContext.Publish(new EventUISound(i % 2 == 0 ? SfxSelectionStrong : SfxSelectionWeak)); } await Task.Delay(TimeSpan.FromSeconds(interval)); if (targetBlock == null) { BlockInput(false); return; } } else { targetBlock = blockViews[(startIdx + stepCount) % blockViews.Length]; selectionView.ShowBlinkOrStandBy(targetBlock.transform.position); } selectionView.ShowBlinkOrStandBy(); _model.ToPpData().Save(); if (_tableContext.IsRewardRoadSign(spinCtx.Reward.id, out _, out var dropId, out _)) { // SetDrawButtons(false); lightView.PlayNormal(); var alternativeReward = GContext.container.Resolve().GetItemDataByDropId(dropId)[0]; GContext.Publish(new EventRewardFlyStashRequest(alternativeReward, targetBlock.GetComponent())); await Task.Delay(TimeSpan.FromSeconds(RewardFlyDuration)); var higherRingData = _model.HigherRingData; var tcs = new TaskCompletionSource(); (await UIManager.Instance.ShowUINotLoading(UITypes.EventLuckMagicRoadSignPanel)) .GetComponent() .Init(higherRingData.ExpireTime, ringData.RoadSignId, higherRingData.Ring.RingType, higherRingData.Ring.Cost, tcs); BlockInput(false); await tcs.Task; SetDrawButtons(!_model.HigherRingData.DoesExist); } else { lightView.PlayGrand(); if (_model.HigherRingData.DoesExist && _model.CurrentRing == _model.HigherRingData.Ring) _model.HigherRingData.SetEmpty(); if (_tableContext.IsRewardProgressItem(spinCtx.Reward.id, 0, out _)) { targetBlock.SetReceived(true); SetDrawButtons(!_model.HigherRingData.DoesExist); var e = new EventRewardFlyStashRequest(spinCtx.Reward, targetBlock.GetComponent()); await taskViews[0].OnRewardFlyRequest(e); await taskViews[1].OnRewardFlyRequest(e); if (_model.TaskProgress[spinCtx.Reward.id] < EventLuckMagicModel.TaskProgressCount) { BlockInput(false); return; } var rewardPanel = (await UIManager.Instance.ShowUINotLoading(UITypes.EventLuckMagicTaskRewardPopupPanel)) .GetComponent(); Debug.Log($"[EventLuckMagic] RoundCount: {_model.RoundCount}"); var taskInfo = _tableContext.GetTaskInfo(_model.RoundCount); var tcs = new TaskCompletionSource(); rewardPanel.Init(new EventLuckMagicRewardPanelInfo { Reward = taskInfo[spinCtx.Reward.id], TaskItemId = spinCtx.Reward.id, TaskCompletionSource = tcs }); BlockInput(false); await tcs.Task; } else { lightView.PlayNormal(); targetBlock.SetReceived(true); SetDrawButtons(!_model.HigherRingData.DoesExist); // Broadcast to reward stash button GContext.Publish(new EventRewardFlyStashRequest(spinCtx.Reward, targetBlock.GetComponent())); await Task.Delay(TimeSpan.FromSeconds(RewardFlyDuration)); BlockInput(false); } } if (_model.IsGameDepleted) { Debug.Log($"[EventLuckMagic] Game Depleted @ Current Ring. Old RoundCOunt: {_model.RoundCount}"); //TODO: Reset performance _model.AddRoundCount(); _model.Reset(); ResetPanel(); return; } } catch (Exception ex) { Debug.LogError("[EventLuckMagic] SpinWheel error."); Debug.LogError(ex); BlockInput(false); } } private void CreateRewardFlyObjectPool() { _objectPoolService = GContext.container.Resolve(); _objectPoolService.CreatePool(rewardFlyPrefab, 0, 10); } private void ReleaseRewardFlyObjectPool() { _objectPoolService?.DestroyPool(typeof(RewardFly)); } private void GetParams(EventLuckMagicParamsCtrl p) { _paramsCtrl = p; _outerSpinParams = new EventLuckMagicSpinParams() { MaxInterval = _paramsCtrl.OuterIntervalMax, MinInterval = _paramsCtrl.OuterIntervalMin, ExtraLoopCount = _paramsCtrl.OuterExtraLoopCount, IntervalLerpCurve = _paramsCtrl.OuterIntervalLerpCurve, }; _middleSpinParams = new EventLuckMagicSpinParams() { MaxInterval = _paramsCtrl.InnerIntervalMax, MinInterval = _paramsCtrl.InnerIntervalMin, ExtraLoopCount = _paramsCtrl.MiddleExtraLoopCount, IntervalLerpCurve = _paramsCtrl.InnerIntervalLerpCurve, }; _innerSpinParams = new EventLuckMagicSpinParams() { MaxInterval = _paramsCtrl.InnerIntervalMax, MinInterval = _paramsCtrl.InnerIntervalMin, ExtraLoopCount = _paramsCtrl.InnerExtraLoopCount, IntervalLerpCurve = _paramsCtrl.InnerIntervalLerpCurve, }; } private async void OnClickPack() { // var chainData = GContext.container.Resolve().ToChainPackData(); // if (chainData.IsChainPackDepleted) // { // var normalPanel = (await UIManager.Instance.ShowUINotLoading(UITypes.LackOfCommonItemPopupPanel)) // .GetComponent(); // normalPanel.Init(EventLuckMagicAct.TableContext.GetLackOfTicketPanelInfo()); // } // else // { // var chainPanel = (await UIManager.Instance.ShowUINotLoading(UITypes.EventLuckMagicChainPackPanel)) // .GetComponent(); // chainPanel.Init(chainData); // } var triplePackPanel = (await UIManager.Instance.ShowUINotLoading(UITypes.EventLuckMagicTriplePackPanel)) .GetComponent(); triplePackPanel.Init(EventLuckyTriplePackData.Create(EventLuckMagicAct.TableContext.EventId, EventLuckMagicAct.TableContext.PackId)); } private void UpdateTimer(long _ = 0L) { var _model = GContext.container.Resolve(); textTimer.text = LocalizationMgr.GetFormatTextValue("UI_COMMON_end", ConvertTools.ConvertTime2(_model.RemainingTime)); if (_model.RemainingTime.TotalSeconds <= 0) OnTimeUp(); } private void OnTimeUp() { // Debug.Log("[EventLuckMagic] Time's up in panel!"); OnClickClose(); var _model = GContext.container.Resolve(); _model?.DisposeLuckyTaskSubscription(); GContext.container.Unregister(); } private async void OnClickInfo() { var panel = (await UIManager.Instance.ShowUINotLoading(UITypes.EventLuckMagicInfoPanel)).GetComponent(); panel.Init(EventLuckMagicAct.TableContext.GetInfoPanelInfo()); } private void BlockInput(bool doesBlock) { goClickMask.SetActive(doesBlock); } } public class EventLuckMagicTicketChange { } /* public class EventLuckMagicBlockInput { public bool DoesBlock; } */