Files
ft/Client/Assets/Scripts/MatchGame/UI/EventMatchGamePanel.cs
2026-06-29 21:18:33 +08:00

632 lines
21 KiB
C#

using asap.core;
using cfg;
using game;
using Game;
using GameCore;
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.UI;
public class EventMatchGamePanel : BasePanel
{
int ShowRewardCount = 5;
Button btn_close;
CanvasGroup rootCanvas;
Animation ani;
Button btn_questionmark;
SandDigLevel[] levels;
RewardItemNew reward_final;
TMP_Text time_text;
[SerializeField] EventMatchNpcPresenter matchNpc;
List<RewardItemNew> rewards = new List<RewardItemNew>();
Image ticket;
Button btn_ticket;
TMP_Text text_num;
List<GameObject> hatShelf;
List<MatchHat> matchHats;
List<MatchHat> showTips;
Transform guidance;
EventMatchGameManager matchGameManager;
FishingEvent fishingEvent;
EventMatchInit eventMatchInit;
List<int> board;
Tables tables;
DateTime endDateTime;
CompositeDisposable _disposable = new CompositeDisposable();
GameCore.Timer _timer;
IDisposable rewardPanelClose;
public float SuccessMoreCount = 3;
public float upDuration = 0.3f;
public float upToDownDuration = 0.3f;
public float downDuration = 0.3f;
public float disappearDuration = 0.3f;
public float disappearDurationUp = 0.5f;
public float showSpDuration = 1f;
public float disappearSpDuration = 1f;
private void Awake()
{
rootCanvas = transform.Find("root").GetComponent<CanvasGroup>();
ani = transform.Find("root").GetComponent<Animation>();
btn_questionmark = transform.Find("root/title/Btn_questionmark").GetComponent<Button>();
levels = transform.Find("root/title/level").GetComponentsInChildren<SandDigLevel>();
reward_final = transform.Find("root/title/level/reward").GetComponent<RewardItemNew>();
time_text = transform.Find("root/title/level/Txt_time").GetComponent<TMP_Text>();
for (int i = 1; i <= 2; i++)
{
rewards.Add(transform.Find($"root/RewardObject/reward/reward{i}").GetComponent<RewardItemNew>());
}
ticket = transform.Find("root/icon_ticket/Img_ticket").GetComponent<Image>();
text_num = transform.Find("root/icon_ticket/txt_num").GetComponent<TMP_Text>();
btn_ticket = transform.Find("root/icon_ticket").GetComponent<Button>();
hatShelf = new List<GameObject>();
for (int i = 0; i < 4; i++)
{
hatShelf.Add(transform.Find($"root/ItemList/Shelf_{i}").gameObject);
}
guidance = transform.Find("root/Guidance");
btn_close = rootCanvas.transform.Find("btn_close").GetComponent<Button>();
}
protected override void Start()
{
tables = GContext.container.Resolve<Tables>();
matchGameManager = new EventMatchGameManager();
// 初始化取消令牌(若未初始化)
MatchGameData data = matchGameManager.GetEventData();
fishingEvent = tables.TbFishingEvent.GetOrDefault(data.eventID);
eventMatchInit = matchGameManager.GetMatchInitRedirectID(fishingEvent.RedirectID);
if (eventMatchInit == null)
{
OnCloseBtn();
return;
}
endDateTime = DateTime.Parse((fishingEvent.TimeDefinition as LimitedTime).EndTime);
btn_close.onClick.AddListener(OnCloseBtn);
btn_questionmark.onClick.AddListener(OnQuestionMarkBtn);
btn_ticket.onClick.AddListener(OnClickBtnPack);
base.Start();
AddEvent();
ShowRewardCount = levels.Length;
CheckNextStage();
Show();
UpdateView();
ShowTime();
GContext.container.Resolve<GuideDataCenter>().TriggerGuide(GroupName.Match01.ToString(), "EventMatchEasterPanel", false, gameObject.name);
}
void AddMatchHat(GameObject shelf, int subCount)
{
shelf.SetActive(true);
for (int i = 0; i < 4; i++)
{
MatchHat hat = shelf.transform.Find($"list/item_{i}").GetComponent<MatchHat>();
if (i < subCount)
{
matchHats.Add(hat);
}
hat.gameObject.SetActive(false);
}
}
IEnumerator InitBoard(List<int> isOpenedList)
{
int openIndex = -1;
if (isOpenedList.Count % 2 == 1)
{
openIndex = isOpenedList[^1];
}
EventMatchItem eventMatchItem;
int state;
MatchHat hat;
IUIService uiService = GContext.container.Resolve<IUIService>();
ani.Play();
yield return new WaitForSeconds(1);
for (int i = 0; i < board.Count; i++)
{
hat = matchHats[i];
hat.gameObject.SetActive(true);
eventMatchItem = tables.TbEventMatchItem.GetOrDefault(board[i]);
hat.OnClickItem = OnClickItem;
state = 0;
if (isOpenedList.Contains(i))
{
state = openIndex == i ? 1 : 2;
}
hat.Init(i, state, eventMatchItem.Fx);
if (state != 2)
{
uiService.SetImageSprite(hat.image_prop, eventMatchItem.Icon, PanelName);
}
}
}
void Show()
{
MatchGameData data = matchGameManager.GetEventData();
board = matchGameManager.GetBoardData(data);
if (data.swapFrom != data.swapTo
&& data.swapFrom >= 0 && data.swapTo >= 0
&& data.swapFrom < board.Count
&& data.swapTo < board.Count)
{
(board[data.swapFrom], board[data.swapTo]) = (board[data.swapTo], board[data.swapFrom]);
}
if (data.swapFrom2 != data.swapTo2
&& data.swapFrom2 >= 0 && data.swapTo2 >= 0
&& data.swapFrom2 < board.Count
&& data.swapTo2 < board.Count)
{
(board[data.swapFrom2], board[data.swapTo2]) = (board[data.swapTo2], board[data.swapFrom2]);
}
SetHats(data);
UpdateReward(data);
StartCoroutine(InitBoard(data.isOpenedList));
}
void SetHats(MatchGameData data)
{
EventMatchShelf eventMatchShelf = tables.TbEventMatchShelf.GetOrDefault(board.Count);
//架子层数
int level = 4;
if (eventMatchShelf != null)
{
level = eventMatchShelf.Level;
}
int subCount = board.Count / level;
int subCount2 = board.Count % level;
if (subCount2 > 0)
{
subCount++;
level--;
subCount2 = board.Count - subCount * level;
}
matchHats = new List<MatchHat>();
for (int i = 0; i < hatShelf.Count; i++)
{
if (i < level)
{
AddMatchHat(hatShelf[i], subCount);
}
else if (i == level && subCount2 > 0)
{
AddMatchHat(hatShelf[i], subCount2);
}
else
{
hatShelf[i].SetActive(false);
}
}
}
public void AddEvent()
{
GContext.OnEvent<ResAddEvent>().Where(_ => _.Type == matchGameManager.ItemType && _.SubType == matchGameManager.ItemSubType).Subscribe(_ => UpdateCount()).AddTo(_disposable);
}
void OnCloseAwardPanel(RewardPanelClose data)
{
rewardPanelClose?.Dispose();
rewardPanelClose = null;
Show();
}
public void ClearEvent()
{
_disposable.Dispose();
}
private void OnCloseBtn()
{
ClearEvent();
GContext.Publish(new UnloadActToNextAct());
}
void OnQuestionMarkBtn()
{
UIManager.Instance.ShowUI(new UIType(eventMatchInit.InfoPanel));
}
private void UpdateView()
{
UpdateCount();
cfg.Item item = tables.TbItem.GetOrDefault(eventMatchInit.ItemID);
if (item != null)
{
GContext.container.Resolve<IUIService>().SetImageSprite(ticket, item.Icon, PanelName);
}
}
private void UpdateCount()
{
int count = matchGameManager.GetTokenCount(fishingEvent.ID);
if (count <= 0)
{
text_num.text = $"<color=red>0</color>";
}
else
{
text_num.text = ConvertTools.GetNumberString(count);
}
}
private void UpdateShow(int curIndex, int levelCount)
{
int startIndex;
int offseIndex = levelCount - ShowRewardCount;
if (curIndex <= 1)
{
startIndex = 0;
}
else if (curIndex > offseIndex)
{
startIndex = offseIndex;
}
else
{
startIndex = curIndex - 1;
}
for (int i = 0; i < ShowRewardCount - 1; i++)
{
int index = startIndex + i;
if (index >= levelCount)
{ break; }
int state = 0;
if (index < curIndex)
{
state = 2;
}
else if (index == curIndex)
{
state = 1;
}
levels[i].SetState(state);
levels[i].SetTextNum($"{index + 1}");
}
levels[ShowRewardCount - 1].SetTextNum($"{levelCount}");
}
private void UpdateReward(MatchGameData data)
{
int stageID;
int finalDropID;
int count = eventMatchInit.StageListRound1.Count;
if (data.index < count)
{
UpdateShow(data.index, count);
stageID = eventMatchInit.StageListRound1[data.index];
finalDropID = tables.TbEventMatchStage.GetOrDefault(eventMatchInit.StageListRound1[^1]).DropId;
}
else
{
int index = data.index - count;
count = eventMatchInit.StageListRound2.Count;
index %= count;
UpdateShow(index, count);
stageID = eventMatchInit.StageListRound2[index];
finalDropID = tables.TbEventMatchStage.GetOrDefault(eventMatchInit.StageListRound2[^1]).DropId;
}
EventMatchStage stage = tables.TbEventMatchStage.GetOrDefault(stageID);
if (stage != null)
{
bool isLastStage;
if (data.index < eventMatchInit.StageListRound1.Count)
{
isLastStage = data.index == eventMatchInit.StageListRound1.Count - 1;
}
else
{
int r2Index = (data.index - eventMatchInit.StageListRound1.Count) % eventMatchInit.StageListRound2.Count;
isLastStage = r2Index == eventMatchInit.StageListRound2.Count - 1;
}
if (isLastStage)
{
rewards[0].InflationRate = data.inflation;
rewards[0].SetDropIcon(reward_final.icon.sprite, finalDropID);
for (int i = 1; i < rewards.Count; i++)
{
rewards[i].gameObject.SetActive(false);
}
}
else
{
List<ItemData> itemData = GContext.container.Resolve<PlayerItemData>().GetItemDataByDropIdLureInflation(data.inflation, stage.DropId);
int itemCount = itemData.Count;
for (int i = 0; i < rewards.Count; i++)
{
if (i < itemCount)
{
rewards[i].SetData(itemData[i]);
}
else
{
rewards[i].gameObject.SetActive(false);
}
}
}
}
reward_final.InflationRate = data.inflation;
reward_final.SetDropIcon("", finalDropID);
}
private void ShowTime()
{
//显示倒计时
if (_timer == null)
{
TimeSpan now = endDateTime - ZZTimeHelper.UtcNow();
double seconds = now.TotalSeconds;
_timer = this.AttachTimer((float)seconds,
OnTimeEnd,
(elapsed) =>
{
now = endDateTime - ZZTimeHelper.UtcNow();
time_text.text = LocalizationMgr.GetFormatTextValue("UI_COMMON_end",
ConvertTools.ConvertTime2(now.Days, now.Hours, now.Minutes, now.Seconds));
}, useRealTime: true);
}
}
void OnTimeEnd()
{
ClearEvent();
GContext.Publish(new UnloadActToNextAct());
}
void PlayNPC(bool ismore)
{
GContext.Publish(new EventUISound(ismore ? "audio_ui_match_npc_more" : "audio_ui_match_npc_normal"));
if (matchNpc != null)
matchNpc.PlayMatchReaction(ismore);
}
void OnClickItem(int index)
{
MatchGameData data = matchGameManager.GetEventData();
int tokens = matchGameManager.GetTokenCount(fishingEvent.ID);
if (tokens <= 0)
{
//代币不足
OnClickBtnPack();
return;
}
if (data.index == 2
&& data.swapFrom == -1
&& data.swapTo == -1
&& data.index < eventMatchInit.StageListRound1.Count
&& data.isOpenedList.Count == 0
&& !eventMatchInit.EventSpecialItemList.Contains(board[index]))
{
for (int i = 0; i < board.Count; i++)
{
if (eventMatchInit.EventSpecialItemList.Contains(board[i]))
{
(board[index], board[i]) = (board[i], board[index]);
data.swapFrom = index;
data.swapTo = i;
matchGameManager.SaveData(data);
IUIService uiService = GContext.container.Resolve<IUIService>();
cfg.EventMatchItem itemA = tables.TbEventMatchItem.GetOrDefault(board[index]);
cfg.EventMatchItem itemB = tables.TbEventMatchItem.GetOrDefault(board[i]);
matchHats[index].Init(index, 0, itemA.Fx);
uiService.SetImageSprite(matchHats[index].image_prop, itemA.Icon, PanelName);
matchHats[i].Init(i, 0, itemB.Fx);
uiService.SetImageSprite(matchHats[i].image_prop, itemB.Icon, PanelName);
break;
}
}
guidance.position = matchHats[index].transform.position;
GContext.container.Resolve<GuideDataCenter>().TriggerGuide(GroupName.Match02.ToString(), "EventMatchEasterPanel", true, gameObject.name);
}
if (data.index == 2
&& data.swapFrom2 == -1
&& data.swapTo2 == -1
&& data.index < eventMatchInit.StageListRound1.Count
&& data.isOpenedList.Count == 1
&& !eventMatchInit.EventSpecialItemList.Contains(board[index]))
{
int firstOpened = data.isOpenedList[0];
for (int i = 0; i < board.Count; i++)
{
if (i != firstOpened && i != index && eventMatchInit.EventSpecialItemList.Contains(board[i]))
{
(board[index], board[i]) = (board[i], board[index]);
data.swapFrom2 = index;
data.swapTo2 = i;
matchGameManager.SaveData(data);
IUIService uiService = GContext.container.Resolve<IUIService>();
cfg.EventMatchItem itemA = tables.TbEventMatchItem.GetOrDefault(board[index]);
cfg.EventMatchItem itemB = tables.TbEventMatchItem.GetOrDefault(board[i]);
matchHats[index].Init(index, 0, itemA.Fx);
uiService.SetImageSprite(matchHats[index].image_prop, itemA.Icon, PanelName);
matchHats[i].Init(i, 0, itemB.Fx);
uiService.SetImageSprite(matchHats[i].image_prop, itemB.Icon, PanelName);
break;
}
}
GContext.container.Resolve<GuideDataCenter>().TriggerGuide(GroupName.Match03.ToString(), "EventMatchEasterPanel", true, gameObject.name);
}
FlipResult result = matchGameManager.AddProgress(fishingEvent.ID, data, eventMatchInit.EventSpecialItemList, index, board, out List<int> openPos);
//刷新代币
UpdateCount();
switch (result)
{
// case FlipResult.InsufficientTokens:
// //代币不足
// OnClickBtnPack();
// return;
case FlipResult.FirstHatFlipped:
FirstHatFlipped(openPos);
break;
case FlipResult.Match:
int count = data.isOpenedList.Count / 2;
StartCoroutine(Match(openPos, count));
break;
case FlipResult.NoMatch:
StartCoroutine(NoMatch(openPos));
break;
}
}
//第一顶帽子翻开
void FirstHatFlipped(List<int> openPos)
{
//第一顶帽子翻开
if (showTips != null)
{
for (int i = 0; i < showTips.Count; i++)
{
showTips[i].PlayInitial();
}
showTips = null;
}
matchHats[openPos[0]].PlayUp();
GContext.Publish(new VibrationData(HapticTypes.SoftImpact));
}
IEnumerator Match(List<int> openPos, int count)
{
//第二顶帽子翻开
rootCanvas.blocksRaycasts = false;
matchHats[openPos[1]].PlayUp();
//- 两顶帽子消失
yield return new WaitForSeconds(upDuration);
PlayNPC(count % 3 == 0);
//-如果是套索,显示套索效果
if (openPos.Count > 2)
{
GContext.Publish(new VibrationData(HapticTypes.Success));
//-物品放大,微微晃动,物品缩小 + 透明
matchHats[openPos[0]].PlayDisappearUp();
matchHats[openPos[1]].PlayDisappearUp();
yield return new WaitForSeconds(disappearDurationUp);
for (int i = 2; i < openPos.Count; i++)
{
matchHats[openPos[i]].PlaySpShow();
yield return new WaitForSeconds(0.03f);
}
yield return new WaitForSeconds(showSpDuration);
for (int i = 2; i < openPos.Count; i++)
{
matchHats[openPos[i]].PlaySpDisappear();
}
yield return new WaitForSeconds(disappearSpDuration);
}
else
{
GContext.Publish(new VibrationData(HapticTypes.MediumImpact));
//-物品放大,微微晃动,物品缩小 + 透明
matchHats[openPos[0]].PlayDisappear();
matchHats[openPos[1]].PlayDisappear();
yield return new WaitForSeconds(disappearDuration);
}
//检查是否进入下一关
CheckNextStage();
rootCanvas.blocksRaycasts = true;
}
IEnumerator NoMatch(List<int> openPos)
{
GContext.Publish(new VibrationData(HapticTypes.SoftImpact));
//第二顶帽子翻开
rootCanvas.blocksRaycasts = false;
matchHats[openPos[1]].PlayUp();
yield return new WaitForSeconds(upDuration + upToDownDuration);
//-两顶帽子原地盖回
matchHats[openPos[0]].PlayDown();
matchHats[openPos[1]].PlayDown();
yield return new WaitForSeconds(downDuration);
rootCanvas.blocksRaycasts = true;
if (openPos.Count >= 2)
{
openPos.RemoveRange(0, 2);
TipsItem(openPos);
}
}
void TipsItem(List<int> openPos)
{
showTips = new List<MatchHat>();
for (int i = 0; i < openPos.Count; i++)
{
matchHats[openPos[i]].ShowTips();
showTips.Add(matchHats[openPos[i]]);
}
}
async void CheckNextStage()
{
int isNext = matchGameManager.NextStage();
if (isNext == 1)
{
GContext.Publish(new ShowData());
rewardPanelClose = GContext.OnEvent<RewardPanelClose>().Subscribe(OnCloseAwardPanel);
}
else if (isNext == 2)
{
UIType uIType = new UIType(eventMatchInit.MatchOpenPrefab);
await UIManager.Instance.ShowUI(uIType);
await Awaiters.Seconds(3);
UIManager.Instance.DestroyUI(uIType);
GContext.Publish(new ShowData());
rewardPanelClose = GContext.OnEvent<RewardPanelClose>().Subscribe(OnCloseAwardPanel);
}
}
#region NeoNormalPack
public void OnClickBtnPack()
{
matchGameManager.ShowFestPack(fishingEvent.ID);
}
#endregion
#if UNITY_EDITOR
string lv = "1";
private void OnGUI()
{
int fontSize = 40;
GUI.skin.textField.fontSize = fontSize;
GUI.skin.button.fontSize = fontSize;
GUI.skin.label.fontSize = fontSize;
// 区域尺寸与边距(可按需调整)
int areaWidth = 220;
int areaHeight = 180;
// 将 GUILayout 区域放到屏幕右下角
Rect area = new Rect(30, 100, areaWidth, areaHeight);
GUILayout.BeginArea(area, GUI.skin.box);
{
GUILayout.BeginVertical();
GUILayout.Label("LV:");
lv = GUILayout.TextField(lv, GUILayout.Height(50));
if (GUILayout.Button("Jump", GUILayout.Height(55)))
{
if (int.TryParse(lv, out int parsed) && parsed > 0)
{
GM(parsed);
}
}
GUILayout.EndVertical();
}
GUILayout.EndArea();
}
void GM(int lv)
{
MatchGameData data = matchGameManager.GetEventData();
data.index = lv - 1;
data.seed = new System.Random().Next();
data.isOpenedList.Clear();
data.swapFrom = -1;
data.swapTo = -1;
data.swapFrom2 = -1;
data.swapTo2 = -1;
matchGameManager.SaveData(data);
Show();
}
#endif
}