using asap.core; using cfg; using GameCore; using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using TMPro; using UniRx; using UnityEngine; using UnityEngine.UI; namespace game { public class EventScratchTicketPanel : BasePanel { [Header("奖励设置")] [SerializeField] private float m_ProgressBarSpeed = 0.5f; [SerializeField] private float m_PauseTimeAfterProgressBarIsFull = 0.1f; [SerializeField] private List m_StampRewardList; [SerializeField] private GameObject m_RewardFlyPrefab; [Header("brush设置")] [SerializeField] private float m_Auto_Brush_Waiting_Time = 0.1f; [Header("动画效果")] [SerializeField] private string m_AnimScratchStart = "scratch_start"; [SerializeField] private float m_AnimScratchStartDurationTime = 0.3f; [SerializeField] private string m_AnimScrachEnd = "scrach_end"; [SerializeField] private float m_AnimScrachEndDurationTime = 0.2f; [SerializeField] private Animation m_AnimEmptyRewardAnim; [SerializeField] private string m_AnimEmptyReward = "emoji_show"; [SerializeField] private float m_AnimEmptyRewardDurationTime = 0.5f; [SerializeField] private string m_AnimMaskShow = "mask_show"; [SerializeField] private string m_AnimMaskDisappear = "mask_disappear"; [SerializeField] private float m_AnimMaskWaitingTime = 0.3f; [Header("位置")] [SerializeField] private List m_RewardFlyTransformList1 = new List(); [SerializeField] private List m_RewardFlyTransformList2 = new List(); [SerializeField] private List m_RewardFlyTransformList3 = new List(); [SerializeField] private List m_RewardFlyTransformList4 = new List(); [SerializeField] private List m_RewardFlyTransformList5 = new List(); #region 新手引导 public async void InitGuidance() { //var scratchMain = m_DataManager.GetCurrentEventScratchMain(); //GContext.container.Resolve().InspectTriggerGuide(scratchMain.UIPanel, curPanelName: gameObject.name); if (m_DataManager.HasSaveKey(EventScratchTicketConfig.key_first_in)) return; m_DataManager.SaveData(EventScratchTicketConfig.key_first_in, "ok"); await UIManager.Instance.ShowUI(m_DataManager.GetInfoPanel()); } #endregion #region 刮刮卡相关 private void StartScratch1() { brush_coin2.gameObject.SetActive(true); FishingScratchTicketAct.Publish(new EventScratchTicketChangeScratchTypeData() { ScratchType = EventScratchTicketScratchType.TypeScratch1 }); } private int m_Scratch5MaxNum = 5; private int m_Scratch5CumulativeNum = 0; private void StartScratch5() { brush_coin2.gameObject.SetActive(true); if (m_Scratch5CumulativeNum >= m_Scratch5MaxNum) { // 5连刮奖励 FishingScratchTicketAct.Publish(new EventScratchTicketStampRewardFlyData() { ScratchType = EventScratchTicketScratchType.TypeScratch5 }); } else { // 更换卡片 m_DataManager.UpdateLuckyValueAndWeight(); FishingScratchTicketAct.Publish(new EventScratchTicketUpdateEventScratchCardData()); FishingScratchTicketAct.Publish(new EventScratchTicketChangeScratchTypeData() { ScratchType = EventScratchTicketScratchType.TypeScratch5 }); StartCoroutine(StartAutoBrush()); ++m_Scratch5CumulativeNum; } } private IEnumerator StartAutoBrush() { yield return new WaitForSeconds(m_Auto_Brush_Waiting_Time); int count = brush_coin2_anim_list.Count; int index = UnityEngine.Random.Range(0, count); string anim = brush_coin2_anim_list[index]; brush_coin2.Play(brush_coin2_anim_list[index]); Debug.LogWarning("--- 当前五连刮使用动画:" + anim); } #endregion #region 链式礼包 & 普通礼包 & 奖励等 private async void GotoChainPack() { EventScratchTicketChainPackData chainPackData = m_DataManager.GetChainPackData(); if (chainPackData == null) return; if (chainPackData.IsChainPackDepleted) { // 普通礼包 GameObject go = await UIManager.Instance.ShowUI(m_DataManager.GetPackPanel()); var normalPackPanel = go.GetComponent(); normalPackPanel.Init(m_DataManager.GetNormalPackData()); } else { // 链式礼包 GameObject go = await UIManager.Instance.ShowUI(m_DataManager.GetChainPackPanel()); var chainPackPanel = go.GetComponent(); chainPackPanel.Init(chainPackData); } } private void CheckForStampReward(EventScratchTicketScratchType scratchType) { if (m_DataManager.GetStampRewardNum() > 0) { HandleStampRewardList(scratchType); } else { FishingScratchTicketAct.Publish(new EventScratchTicketPanelPlayEndAnimData() { ScratchType = scratchType }); } } private async void HandleStampRewardList(EventScratchTicketScratchType scratchType) { if (m_DataManager.GetStampRewardNum() > 0) { PlayerItemData playerItemData = GContext.container.Resolve(); EventScratchCard card = m_DataManager.GetFirstStampReward(); if (card != null) { ItemData rewardItem = playerItemData.GetItemDataOne(card.DropReward); m_DataManager.RemoveFirstStampReward(); GameObject go = await UIManager.Instance.ShowUI(m_DataManager.GetRewardPanel()); var rewardPopupPanel = go.GetComponent(); rewardPopupPanel.Init(rewardItem, card, () => { HandleStampRewardList(scratchType); }); } } else { await HandleReward(scratchType); } } #endregion #region 动画相关 private IEnumerator ScratchStartAnim(Action action) { m_animation.Play(m_AnimScratchStart); yield return new WaitForSeconds(m_AnimScratchStartDurationTime); if (action != null) { action.Invoke(); } } private IEnumerator ScratchEndAnim(EventScratchTicketScratchType scratchType, Action action) { m_animation.Play(m_AnimScrachEnd); yield return new WaitForSeconds(m_AnimScrachEndDurationTime); FishingScratchTicketAct.Publish(new EventScratchTicketChangeScratchTypeData() { ScratchType = EventScratchTicketScratchType.TypeInvalid }); if (action != null) { action.Invoke(scratchType); } } private void StopScratch() { brush_coin2.gameObject.SetActive(false); FishingScratchTicketAct.Publish(new EventScratchTicketChangeScratchTypeData() { ScratchType = EventScratchTicketScratchType.TypeTemporary }); } private List GetRewardFlyTransformList(int count) { switch (count) { case 5: return m_RewardFlyTransformList5; case 4: return m_RewardFlyTransformList4; case 3: return m_RewardFlyTransformList3; case 2: return m_RewardFlyTransformList2; case 1: return m_RewardFlyTransformList1; default: return m_RewardFlyTransformList5; } } private async Task PlayRewardFlyAnim(EventScratchTicketStampRewardFlyData data) { if (data.ScratchType == EventScratchTicketScratchType.TypeScratch1) { await PlayStampRewardFlyAnimInTypeScratch1(data); await HandleReward(data.ScratchType); } else if (data.ScratchType == EventScratchTicketScratchType.TypeScratch5) { FishingScratchTicketAct.Publish(new EventScratchTicketStartStampRewardCountUpdateData()); //mask.gameObject.SetActive(true); FishingScratchTicketAct.Publish(new EventScratchTicketStartMaskData()); var taskList = new List(); int count = m_DataManager.ScratchStampList.Count; List transformList = GetRewardFlyTransformList(count); for (int i = 0; i < count; i++) { int cardID = m_DataManager.ScratchStampList[i]; EventScratchCard card = m_DataManager.GetEventScratchCard(cardID); if (card.DropReward > 0) { taskList.Add(PlayStampRewardFlyAnimInTypeScratch5(data, card, transformList, i)); } } if (taskList.Count > 0) { await Task.WhenAll(taskList.ToArray()); } m_DataManager.ClearScratchStampList(); //mask.gameObject.SetActive(false); StopMask(); FishingScratchTicketAct.Publish(new EventScratchTicketStopStampRewardCountUpdateData()); await HandleReward(data.ScratchType); } } private async Task HandleReward(EventScratchTicketScratchType scratchType) { int count = m_StampRewardList.Count; var taskArr = new Task[count]; for (var i = 0; i < count; i++) { taskArr[i] = m_StampRewardList[i].CheckReward(); } await Task.WhenAll(taskArr); bool flag = false; foreach (var task in taskArr) { if (task.Result) { flag = true; break; } } m_DataManager.SyncData(); if (flag) { CheckForStampReward(scratchType); } else { FishingScratchTicketAct.Publish(new EventScratchTicketPanelPlayEndAnimData() { ScratchType = scratchType }); } } private async Task PlayStampRewardFlyAnimInTypeScratch1(EventScratchTicketStampRewardFlyData data) { FishingScratchTicketAct.Publish(new EventScratchTicketStartStampRewardCountUpdateData()); //mask.gameObject.SetActive(true); FishingScratchTicketAct.Publish(new EventScratchTicketStartMaskData()); EventScratchCard scratchCard = m_DataManager.GetFirstScratchStamp(); EventScratchTicketStampRewardView stampRewardView = null; foreach (var item in m_StampRewardList) { if (item.EventScratchQuality == scratchCard.Quality) { stampRewardView = item; break; } } if (stampRewardView == null) { Debug.LogError("--- PlayRewardFlyAnimStep 数据错误,找不到对应的 EventScratchTicketStampRewardView"); return; } Sprite icon = m_DataManager.SpriteAtlas.GetSprite(scratchCard.Icon); Vector3 srcPosition = data.SrcPosition; var targetImg = stampRewardView.GetFirstEmptyImage(); Vector3 destPosition = targetImg.rectTransform.position; Vector3 localScale = data.LocalScale; float iconSize = targetImg.rectTransform.rect.width; int rewardNum = stampRewardView.RewardNum; var recordData = m_DataManager.AddRecordData(); recordData.TicketID = scratchCard.ID; recordData.SetScratchType(data.ScratchType); recordData.TicketFinishID = ((rewardNum % scratchCard.Count) == 0) ? scratchCard.DropReward : 0; CollectionItemFly collectionItemFly = new CollectionItemFly() { icon = m_DataManager.SpriteAtlas.GetSprite(scratchCard.Icon), numStr = "", sourcePos = data.SrcPosition, destPos = destPosition, scale = data.LocalScale, isPlayOpen = true, isPlayClose = true, isDestinationRewardStash = false, // isDestinationRewardStash = false, targetIconSize = iconSize }; //var rewardFly = m_RewardFlyList[0]; var rewardFly = Instantiate(m_RewardFlyPrefab, m_RewardFlyPrefab.transform.parent).GetComponent(); rewardFly.gameObject.SetActive(true); await rewardFly.ShowAsync(collectionItemFly); Destroy(rewardFly.gameObject); //mask.gameObject.SetActive(false); StopMask(); targetImg.gameObject.SetActive(true); m_DataManager.ClearScratchStampList(); FishingScratchTicketAct.Publish(new EventScratchTicketStopStampRewardCountUpdateData()); } private async Task PlayStampRewardFlyAnimInTypeScratch5(EventScratchTicketStampRewardFlyData data, EventScratchCard scratchCard, List transformList, int index) { EventScratchTicketStampRewardView stampRewardView = null; foreach (var item in m_StampRewardList) { if (item.EventScratchQuality == scratchCard.Quality) { stampRewardView = item; break; } } if (stampRewardView == null) { Debug.LogError("--- PlayRewardFlyAnimStep 数据错误,找不到对应的 EventScratchTicketStampRewardView"); return; } Sprite icon = m_DataManager.SpriteAtlas.GetSprite(scratchCard.Icon); Vector3 srcPosition = data.SrcPosition; var targetImg = stampRewardView.GetFirstEmptyImage(); Vector3 destPosition = targetImg.rectTransform.position; Vector3 localScale = data.LocalScale; float iconSize = targetImg.rectTransform.rect.width; var rewardFlyTransform = transformList[index]; int rewardNum = stampRewardView.RewardNum; var recordData = m_DataManager.AddRecordData(); recordData.TicketID = scratchCard.ID; recordData.SetScratchType(data.ScratchType); recordData.TicketFinishID = ((rewardNum % scratchCard.Count) == 0) ? scratchCard.DropReward : 0; CollectionItemFly collectionItemFly = new CollectionItemFly() { icon = m_DataManager.SpriteAtlas.GetSprite(scratchCard.Icon), numStr = "", sourcePos = rewardFlyTransform.position, destPos = destPosition, scale = rewardFlyTransform.localScale, isPlayOpen = true, isPlayClose = true, isDestinationRewardStash = false, // isDestinationRewardStash = false, targetIconSize = iconSize }; var rewardFly = Instantiate(m_RewardFlyPrefab, m_RewardFlyPrefab.transform.parent).GetComponent(); rewardFly.gameObject.SetActive(true); await rewardFly.ShowAsync(collectionItemFly); Destroy(rewardFly.gameObject); targetImg.gameObject.SetActive(true); } private IEnumerator PlayRewardEmptyAnim(EventScratchTicketRewardEmptyData data) { // 播放空奖动画 m_AnimEmptyRewardAnim.gameObject.SetActive(true); m_AnimEmptyRewardAnim.Play(m_AnimEmptyReward); yield return new WaitForSeconds(m_AnimEmptyRewardDurationTime); m_AnimEmptyRewardAnim.gameObject.SetActive(false); EventScratchCard scratchCard = m_DataManager.GetCurrentEventScratchCard(); var recordData = m_DataManager.AddRecordData(); recordData.TicketID = scratchCard.ID; recordData.SetScratchType(data.ScratchType); recordData.TicketFinishID = 0; FishingScratchTicketAct.Publish(new EventScratchTicketOutData() { ScratchType = data.ScratchType }); //if (data.ScratchType == EventScratchTicketScratchType.TypeScratch1) //{ // FishingScratchTicketAct.Publish(new EventScratchTicketPanelPlayEndAnimData() // { // ScratchType = data.ScratchType // }); //} //else if (data.ScratchType == EventScratchTicketScratchType.TypeScratch5) //{ // FishingScratchTicketAct.Publish(new EventScratchTicketPlayScratchType5()); //} } private IEnumerator StartMask() { mask.gameObject.SetActive(true); mask.Play(m_AnimMaskShow); yield return new WaitForSeconds(m_AnimMaskWaitingTime); mask.Play(m_AnimMaskDisappear); } private void StopMask() { // 停止播放动画 mask.gameObject.SetActive(false); } #endregion #region 事件相关 private void InitEvent() { FishingScratchTicketAct.Subscribe(UpdateToken); FishingScratchTicketAct.Subscribe(OnStampRewardFlyEvent); FishingScratchTicketAct.Subscribe(PlayScratchEndAnim); FishingScratchTicketAct.Subscribe(UpdateRewardTask); FishingScratchTicketAct.Subscribe(PlayScratchType5); FishingScratchTicketAct.Subscribe(OnRewardEmptyEvent); FishingScratchTicketAct.Subscribe(OnScratchCardRevealedAll); FishingScratchTicketAct.Subscribe(OnStartMaskEvent); // 监听关闭奖励面板 GContext.OnEvent().Subscribe(OnRewardPanelClose).AddTo(FishingScratchTicketAct.Disposables); } private void OnStartMaskEvent(EventScratchTicketStartMaskData data) { StartCoroutine(StartMask()); } private void OnScratchCardRevealedAll(EventScratchTicketRevealedAllData data) { if (brush_coin2 == null) return; brush_coin2.Stop(); brush_coin2.gameObject.SetActive(false); } private void OnRewardEmptyEvent(EventScratchTicketRewardEmptyData data) { this.StartCoroutine(PlayRewardEmptyAnim(data)); } private void OnRewardPanelClose(RewardPanelClose data) { //FishingScratchTicketAct.Publish(new EventScratchTicketPanelPlayEndAnimData()); } private void PlayScratchType5(EventScratchTicketPlayScratchType5 data) { StartScratch5(); } private void PlayScratchEndAnim(EventScratchTicketPanelPlayEndAnimData data) { if (m_DataManager.ScratchTicketData.ConsumedToken > 0) { StartCoroutine(ScratchEndAnim(data.ScratchType, CheckTokenReward)); } else { StartCoroutine(ScratchEndAnim(data.ScratchType, null)); } StopScratch(); } private void CheckTokenReward(EventScratchTicketScratchType scratchType) { // token 消费积分奖励 FishingScratchTicketAct.Publish(new EventScratchTicketRewardTaskUpdateData() { ScratchType = scratchType, Token = m_DataManager.ScratchTicketData.ConsumedToken }); } private async void OnStampRewardFlyEvent(EventScratchTicketStampRewardFlyData data) { if (data == null) return; await PlayRewardFlyAnim(data); } private void UpdateToken(EventScratchTicketTokenUpdateData data) { if (m_DataManager == null || token_text_num == null) return; int token = m_DataManager.GetToken(); token_text_num.text = "" + token; } private async void UpdateRewardTask(EventScratchTicketRewardTaskUpdateData data) { if (m_DataManager == null) return; PlayerItemData playerItemData = GContext.container.Resolve(); EventScratchReward finalReward = m_DataManager.GetEventScratchFinalReward(); var finalDataItem = playerItemData.GetItemDataOne(finalReward.DropReward); top_reward.SetData(finalDataItem, abbr: true); if (data == null && m_DataManager.ScratchTicketData.ConsumedToken > 0) { data = new EventScratchTicketRewardTaskUpdateData() { ScratchType = EventScratchTicketScratchType.TypeInvalid, Token = m_DataManager.ScratchTicketData.ConsumedToken }; } if (data == null) { EventScratchReward curReward = m_DataManager.GetEventScratchReward(m_DataManager.ScratchTicketData.EventScratchRewardTaskID); var curDataItem = playerItemData.GetItemDataOne(curReward.DropReward); reward.SetData(curDataItem, abbr: true); img_bar.fillAmount = (float)m_DataManager.ScratchTicketData.RewardTaskConsumedToken / curReward.TokenRequired; text_progress.text = m_DataManager.ScratchTicketData.RewardTaskConsumedToken + "/" + curReward.TokenRequired; } else { await StartUpdateProgressBar(data); } } private Queue GetRewardDisplayUpdateDataQueue(EventScratchTicketRewardTaskUpdateData data) { Queue updateQueue = new Queue(); int fromToken = m_DataManager.ScratchTicketData.RewardTaskConsumedToken; int targetToken = fromToken + data.Token; int taskID = m_DataManager.ScratchTicketData.EventScratchRewardTaskID; EventScratchReward curScratchReward = m_DataManager.GetEventScratchReward(taskID); while (targetToken >= curScratchReward.TokenRequired) { EventScratchTicketRewardDisplayUpdateData rewardDisplayUpdateData = new EventScratchTicketRewardDisplayUpdateData(); rewardDisplayUpdateData.TaskID = taskID; rewardDisplayUpdateData.Reward = m_DataManager.GetEventScratchReward(rewardDisplayUpdateData.TaskID); rewardDisplayUpdateData.FromToken = fromToken; rewardDisplayUpdateData.TargetToken = curScratchReward.TokenRequired; rewardDisplayUpdateData.LevelToken = curScratchReward.TokenRequired; rewardDisplayUpdateData.FromRatio = (float)rewardDisplayUpdateData.FromToken / rewardDisplayUpdateData.LevelToken; rewardDisplayUpdateData.TargetRatio = (float)rewardDisplayUpdateData.TargetToken / rewardDisplayUpdateData.LevelToken; updateQueue.Enqueue(rewardDisplayUpdateData); fromToken = 0; targetToken -= curScratchReward.TokenRequired; taskID = curScratchReward.NextTask; curScratchReward = m_DataManager.GetEventScratchReward(taskID); } { EventScratchTicketRewardDisplayUpdateData rewardDisplayUpdateData = new EventScratchTicketRewardDisplayUpdateData(); rewardDisplayUpdateData.TaskID = taskID; rewardDisplayUpdateData.Reward = m_DataManager.GetEventScratchReward(rewardDisplayUpdateData.TaskID); rewardDisplayUpdateData.FromToken = fromToken; rewardDisplayUpdateData.TargetToken = targetToken; rewardDisplayUpdateData.LevelToken = curScratchReward.TokenRequired; rewardDisplayUpdateData.FromRatio = (float)rewardDisplayUpdateData.FromToken / rewardDisplayUpdateData.LevelToken; rewardDisplayUpdateData.TargetRatio = (float)rewardDisplayUpdateData.TargetToken / rewardDisplayUpdateData.LevelToken; updateQueue.Enqueue(rewardDisplayUpdateData); } return updateQueue; } public async Task StartUpdateProgressBar(EventScratchTicketRewardTaskUpdateData data) { Queue updateQueue = GetRewardDisplayUpdateDataQueue(data); bool syncData = updateQueue.Count > 0; PlayerItemData playerItemData = GContext.container.Resolve(); EventScratchReward curReward = null; int finalToken = 0; while (updateQueue.Count > 0) { var item = updateQueue.Dequeue(); int fromToken = item.FromToken; int targetToken = item.TargetToken; int levelToken = item.LevelToken; float fromRatio = item.FromRatio; float targetRatio = item.TargetRatio; finalToken = targetToken; curReward = item.Reward; var curDataItem = playerItemData.GetItemDataOne(curReward.DropReward); reward.SetData(curDataItem, abbr: true); text_progress.text = fromToken + "/" + levelToken; img_bar.fillAmount = fromRatio; await Awaiters.NextFrame; while (fromRatio < targetRatio) { fromRatio += m_ProgressBarSpeed * Time.deltaTime; fromToken = (int)(levelToken * fromRatio); text_progress.text = fromToken + "/" + levelToken; img_bar.fillAmount = fromRatio; await Awaiters.NextFrame; } text_progress.text = targetToken + "/" + levelToken; img_bar.fillAmount = targetRatio; if (targetToken >= levelToken && curReward.DropReward > 0) { await HandleTokenReward(curReward.DropReward); } if (fromToken >= 0f) { await Awaiters.Seconds(m_PauseTimeAfterProgressBarIsFull); } else { await Awaiters.NextFrame; } } m_DataManager.RecordStatisticalData(); m_DataManager.ScratchTicketData.EventScratchRewardTaskID = curReward.TaskID; m_DataManager.ScratchTicketData.ConsumedToken = 0; m_DataManager.ScratchTicketData.RewardTaskConsumedToken = finalToken; m_DataManager.SyncData(); m_DataManager.ClearRecordList(); } private async Task HandleTokenReward(int rewardId) { //mask.gameObject.SetActive(true); ItemData itemData = GContext.container.Resolve().GetItemDataOne(rewardId); Vector3 srcPosition = reward.transform.position; //var targetImg = stampRewardView.GetFirstEmptyImage(); Vector3 destPosition = m_BtnPack.transform.position; float iconSize = m_BtnPack.Icon.rect.width; CollectionItemFly collectionItemFly = new CollectionItemFly() { itemID = itemData.id, numStr = "", sourcePos = srcPosition, destPos = destPosition, scale = reward.icon.rectTransform.localScale, isPlayOpen = true, isPlayClose = true, isDestinationRewardStash = false, // isDestinationRewardStash = false, targetIconSize = iconSize }; var rewardFly = Instantiate(m_RewardFlyPrefab, m_RewardFlyPrefab.transform.parent).GetComponent(); rewardFly.gameObject.SetActive(true); await rewardFly.ShowAsync(collectionItemFly); Destroy(rewardFly.gameObject); //mask.gameObject.SetActive(false); List rewardList = new List(); rewardList.Add(itemData); // GContext.container.Resolve().AddItem(rewardList); GContext.Publish(new DeferredRewardStashService.EventStashItems { Items = rewardList }); } #endregion #region UI // animation private Animation m_animation; // questionmark private Button btn_questionmark; private TMP_Text text_time; // 关闭按钮 private Button btn_close; // icon_ticket private TMP_Text token_text_num; private Button icon_ticket; // mask private Image click_mask; private Animation mask; // reward_fly //private List m_RewardFlyList = new List(); // scratch 1 & scratch 5 private Button btn_scratch_1; private Button btn_scratch_5; // brush private Image brush_coin1; private Animation brush_coin2; private List brush_coin2_anim_list = new List(); // bar private Animation anim_bar; private RewardItemNew top_reward; private Image img_bar; private RewardItemNew reward; private TMP_Text text_progress; // pack private DeferredRewardStashButton m_BtnPack; private void InitUI() { // animation m_animation = transform.GetComponent(); // btn_questionmark btn_questionmark = transform.Find("root/title/btn_questionmark").GetComponent