2026-04-20 13:49:36 +08:00
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using DG.Tweening;
|
|
|
|
|
using BingoBrain.Core;
|
|
|
|
|
using BingoBrain.HotFix;
|
|
|
|
|
using Spine.Unity;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
namespace BingoBrain
|
|
|
|
|
{
|
|
|
|
|
public class CardBoardEntity
|
|
|
|
|
{
|
|
|
|
|
public GameCell GoCell = new();
|
|
|
|
|
|
|
|
|
|
public CardBoardData data = new();
|
|
|
|
|
public List<CardEntity> cardList = new();
|
|
|
|
|
public bool isFinish;
|
|
|
|
|
public bool isBingoing;
|
|
|
|
|
|
|
|
|
|
public SkeletonAnimation bingGoSke;
|
|
|
|
|
private ParticleSystem[] idleSys = new ParticleSystem[3];
|
|
|
|
|
private ParticleSystem[] enterSys = new ParticleSystem[3];
|
|
|
|
|
private ParticleSystem exitSys;
|
|
|
|
|
|
|
|
|
|
private Vector3 originPos = new(-3.38f, 2.96f);
|
|
|
|
|
private float offset = 1.685f;
|
|
|
|
|
private Transform finishMask;
|
|
|
|
|
|
|
|
|
|
private List<int> needShowBingoList = new();
|
|
|
|
|
private Gsss showBingoSequence = new();
|
|
|
|
|
|
|
|
|
|
private bool isDelayCheckBingo;
|
|
|
|
|
|
|
|
|
|
public List<int> bingoedList = new();
|
|
|
|
|
|
|
|
|
|
public void SetData()
|
|
|
|
|
{
|
|
|
|
|
InitGameObj();
|
|
|
|
|
InitCardList();
|
|
|
|
|
InitReward();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InitReward()
|
|
|
|
|
{
|
|
|
|
|
var coinCount = Random.Range(BingoCell.MinCoinCount, BingoCell.MaxCoinCount + 1);
|
|
|
|
|
var cashCount = Random.Range(BingoCell.MinCashCount, BingoCell.MaxCashCount + 1);
|
|
|
|
|
|
|
|
|
|
var list = GlobalHarmony.GetRandomList(
|
|
|
|
|
cardList.FindAll(tmp => !tmp.data.isSelect && !tmp.data.isCoin && tmp.data.type == CardPropType.none),
|
|
|
|
|
coinCount);
|
|
|
|
|
if (list != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var card in list)
|
|
|
|
|
{
|
|
|
|
|
card.data.type = CardPropType.coin;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list = GlobalHarmony.GetRandomList(
|
|
|
|
|
cardList.FindAll(tmp => !tmp.data.isSelect && !tmp.data.isCoin && tmp.data.type == CardPropType.none),
|
|
|
|
|
cashCount);
|
|
|
|
|
if (list != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var card in list)
|
|
|
|
|
{
|
|
|
|
|
card.data.type = CardPropType.cash;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var card in cardList)
|
|
|
|
|
{
|
|
|
|
|
card.SetReward();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitGameObj()
|
|
|
|
|
{
|
|
|
|
|
if (GoCell.gameObject == null)
|
|
|
|
|
{
|
|
|
|
|
GoCell.InitByPath("Prefab.Game.Card", "CardBoard", () =>
|
|
|
|
|
{
|
|
|
|
|
GoCell.transform.SetParent(BingoCell.root, false);
|
|
|
|
|
GoCell.gameObject.SetActive(false);
|
|
|
|
|
finishMask = GoCell.transform.Find("Finish");
|
|
|
|
|
DoSomething();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DoSomething();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void DoSomething()
|
|
|
|
|
{
|
|
|
|
|
if (!bingGoSke)
|
|
|
|
|
{
|
|
|
|
|
FX.Instance.GetFx<SkeletonAnimation>(Fx_Type.spine_bingo, sk =>
|
|
|
|
|
{
|
|
|
|
|
bingGoSke = sk;
|
|
|
|
|
bingGoSke.transform.SetParent(GoCell.transform);
|
|
|
|
|
bingGoSke.transform.localPosition = Vector3.zero;
|
|
|
|
|
idleSys[0] = bingGoSke.transform.Find("fx_lizi_idle01").GetComponent<ParticleSystem>();
|
|
|
|
|
idleSys[1] = bingGoSke.transform.Find("fx_lizi_idle02").GetComponent<ParticleSystem>();
|
|
|
|
|
idleSys[2] = bingGoSke.transform.Find("fx_lizi_idle03").GetComponent<ParticleSystem>();
|
|
|
|
|
enterSys[0] = bingGoSke.transform.Find("fx_lizi_enter01").GetComponent<ParticleSystem>();
|
|
|
|
|
enterSys[1] = bingGoSke.transform.Find("fx_lizi_enter02").GetComponent<ParticleSystem>();
|
|
|
|
|
enterSys[2] = bingGoSke.transform.Find("fx_lizi_enter03").GetComponent<ParticleSystem>();
|
|
|
|
|
for (var i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
idleSys[i].gameObject.SetActive(false);
|
|
|
|
|
enterSys[i].gameObject.SetActive(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exitSys = bingGoSke.transform.Find("fx_lizi_exit").GetComponent<ParticleSystem>();
|
|
|
|
|
bingGoSke.gameObject.SetActive(false);
|
|
|
|
|
GoCell.gameObject.SetActive(true);
|
|
|
|
|
finishMask.gameObject.SetActive(false);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
bingGoSke.gameObject.SetActive(false);
|
|
|
|
|
GoCell.gameObject.SetActive(true);
|
|
|
|
|
finishMask.gameObject.SetActive(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitCardList()
|
|
|
|
|
{
|
|
|
|
|
var index = 0;
|
|
|
|
|
var isFirst = cardList.Count == 0;
|
|
|
|
|
foreach (var cardData in data.cardNumList)
|
|
|
|
|
{
|
|
|
|
|
CardEntity cardEntity;
|
|
|
|
|
if (isFirst)
|
|
|
|
|
{
|
|
|
|
|
cardEntity = new CardEntity();
|
|
|
|
|
cardEntity.InitGameObj(() =>
|
|
|
|
|
{
|
|
|
|
|
cardEntity.data.index = index;
|
|
|
|
|
cardEntity.data.cardBoard = this;
|
|
|
|
|
cardList.Add(cardEntity);
|
|
|
|
|
SetByIndex(cardEntity.Game.transform, index);
|
|
|
|
|
cardEntity.Game.transform.SetParent(GoCell.transform, false);
|
|
|
|
|
index++;
|
|
|
|
|
|
|
|
|
|
cardEntity.data.isSelect = false;
|
|
|
|
|
cardEntity.data.isCoin = false;
|
|
|
|
|
cardEntity.data.isDelaySelect = false;
|
|
|
|
|
cardEntity.data.type = CardPropType.none;
|
|
|
|
|
cardEntity.data.num = cardData;
|
|
|
|
|
cardEntity.SetByData();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cardEntity = cardList[index];
|
|
|
|
|
cardEntity.InitGameObj(() =>
|
|
|
|
|
{
|
|
|
|
|
cardEntity.data.isSelect = false;
|
|
|
|
|
cardEntity.data.isCoin = false;
|
|
|
|
|
cardEntity.data.isDelaySelect = false;
|
|
|
|
|
cardEntity.data.type = CardPropType.none;
|
|
|
|
|
cardEntity.data.num = cardData;
|
|
|
|
|
cardEntity.SetByData();
|
|
|
|
|
});
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (index == data.cardNumList.Count)
|
|
|
|
|
{
|
|
|
|
|
finishMask.SetAsLastSibling();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetByIndex(Transform gameObjTransform, int index)
|
|
|
|
|
{
|
|
|
|
|
if (gameObjTransform != null)
|
|
|
|
|
{
|
|
|
|
|
gameObjTransform.localPosition = originPos + new Vector3(index / BingoCell.bingoCount * offset,
|
2026-05-08 11:03:00 +08:00
|
|
|
index % BingoCell.bingoCount * -(offset + 0.02f));
|
2026-04-20 13:49:36 +08:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.Log("[ BingoBrain ] gameObjTransform is null");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void OnReset()
|
|
|
|
|
{
|
|
|
|
|
needShowBingoList.Clear();
|
|
|
|
|
bingoedList.Clear();
|
|
|
|
|
data.selectList.Clear();
|
|
|
|
|
data.cardNumList.Clear();
|
|
|
|
|
isBingoing = false;
|
|
|
|
|
isFinish = false;
|
|
|
|
|
foreach (var card in cardList)
|
|
|
|
|
{
|
|
|
|
|
card.OnReset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
idleSys[i].gameObject.SetActive(false);
|
|
|
|
|
enterSys[i].gameObject.SetActive(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exitSys.gameObject.SetActive(false);
|
|
|
|
|
|
|
|
|
|
showBingoSequence?.Cancel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void DelayCheckBingo()
|
|
|
|
|
{
|
|
|
|
|
if (BingoCell.isProcedure)
|
|
|
|
|
{
|
|
|
|
|
isDelayCheckBingo = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CheckBingo();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CheckBingo()
|
|
|
|
|
{
|
|
|
|
|
if (BingoCell.isProcedure)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (BingoCell.bingoCardboardIndex != -1 && BingoCell.bingoCardboardIndex != data.index)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var bingoType = IsBingo(data.selectList);
|
|
|
|
|
while (bingoType != -1)
|
|
|
|
|
{
|
|
|
|
|
BingoCell.bingoCardboardIndex = data.index;
|
|
|
|
|
isBingoing = true;
|
|
|
|
|
bingoedList.Add(bingoType);
|
|
|
|
|
PreferencesMgr.Instance.BingoSum += 1;
|
|
|
|
|
|
|
|
|
|
needShowBingoList.Add(bingoType);
|
|
|
|
|
bingoType = IsBingo(data.selectList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
showBingoSequence = new Gsss();
|
|
|
|
|
if (needShowBingoList.Count != 0)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
showBingoSequence.Add(obj =>
|
|
|
|
|
{
|
|
|
|
|
var delay = 0.2f;
|
|
|
|
|
foreach (var tmpType in needShowBingoList)
|
|
|
|
|
{
|
|
|
|
|
var count = BingoCell.bingoDic[tmpType].Count;
|
|
|
|
|
|
|
|
|
|
for (var j = 0; j < count; j++)
|
|
|
|
|
{
|
|
|
|
|
var index = BingoCell.bingoDic[tmpType][j];
|
|
|
|
|
if (cardList[index].data.isCoin)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cardList[index].SetCoin(delay);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DOVirtual.DelayedCall(delay, obj.InvokeComplete).SetAutoKill();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
showBingoSequence.Add((obj) =>
|
|
|
|
|
{
|
|
|
|
|
Audio.Instance.PlayDynamicEffect("Bingo");
|
|
|
|
|
|
|
|
|
|
int bingoingNumber = Mathf.Clamp(bingoedList.Count, 0, 3);
|
|
|
|
|
NAAVsa.SetSkin(bingGoSke, "default");
|
|
|
|
|
this.bingGoSke.gameObject.SetActive(true);
|
|
|
|
|
switch (bingoingNumber)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
this.bingGoSke.state.SetAnimation(0, "single", false);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
this.bingGoSke.state.SetAnimation(0, "double", false);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
this.bingGoSke.state.SetAnimation(0, "multiple", false);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enterSys[bingoingNumber - 1].gameObject.SetActive(true);
|
|
|
|
|
idleSys[bingoingNumber - 1].gameObject.SetActive(true);
|
|
|
|
|
finishMask.gameObject.SetActive(true);
|
|
|
|
|
if (bingoedList.Count >= 3 && !isDelayCheckBingo)
|
|
|
|
|
{
|
|
|
|
|
DOVirtual.DelayedCall(1.8f, () =>
|
|
|
|
|
{
|
|
|
|
|
NAAVsa.SetSkin(bingGoSke, "default");
|
|
|
|
|
idleSys[bingoingNumber - 1].gameObject.SetActive(true);
|
|
|
|
|
enterSys[bingoingNumber - 1].gameObject.SetActive(false);
|
|
|
|
|
obj.InvokeComplete();
|
|
|
|
|
}).SetAutoKill();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DOVirtual.DelayedCall(1.5f, () =>
|
|
|
|
|
{
|
|
|
|
|
exitSys.gameObject.SetActive(true);
|
|
|
|
|
idleSys[bingoingNumber - 1].gameObject.SetActive(false);
|
|
|
|
|
enterSys[bingoingNumber - 1].gameObject.SetActive(false);
|
|
|
|
|
|
|
|
|
|
DOVirtual.DelayedCall(0.8f, (TweenCallback)(() =>
|
|
|
|
|
{
|
|
|
|
|
finishMask.gameObject.SetActive(false);
|
|
|
|
|
this.bingGoSke.gameObject.SetActive(false);
|
|
|
|
|
exitSys.gameObject.SetActive(false);
|
|
|
|
|
|
|
|
|
|
obj.InvokeComplete();
|
|
|
|
|
}));
|
|
|
|
|
}).SetAutoKill();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (needShowBingoList.Count > 1)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
showBingoSequence.Add(true, obj =>
|
|
|
|
|
{
|
|
|
|
|
UICtrlDispatcher.Instance.Dispatch(SkinInfo.ChestUI_Open);
|
|
|
|
|
UICtrlDispatcher.Instance.AddOnceListener(SkinInfo.ChestUI_Close,
|
|
|
|
|
_ => { obj.InvokeComplete(); });
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (showBingoSequence.Count != 0)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
showBingoSequence.Add(obj =>
|
|
|
|
|
{
|
|
|
|
|
if (BingoCell.KeyCardSum >= 3)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
UICtrlDispatcher.Instance.AddOnceListener(SkinInfo.BingoCardUI_Close, o =>
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
obj.InvokeComplete();
|
|
|
|
|
});
|
|
|
|
|
BingoCell.OpenActivityUI();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
obj.InvokeComplete();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (BingoCell.KeyCardSum >= 3)
|
|
|
|
|
{
|
|
|
|
|
showBingoSequence.Add(obj =>
|
|
|
|
|
{
|
|
|
|
|
if (BingoCell.KeyCardSum >= 3)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
UICtrlDispatcher.Instance.AddOnceListener(SkinInfo.BingoCardUI_Close, o =>
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
obj.InvokeComplete();
|
|
|
|
|
});
|
|
|
|
|
BingoCell.OpenActivityUI();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
obj.InvokeComplete();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (showBingoSequence.Count != 0)
|
|
|
|
|
{
|
|
|
|
|
BingoCell.isProcedure = true;
|
|
|
|
|
GameDispatcher.Instance.Dispatch(BingoInfo.AddPause, 1);
|
|
|
|
|
showBingoSequence.onFinish = OnFinish;
|
|
|
|
|
showBingoSequence.Run();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
isBingoing = false;
|
|
|
|
|
BingoCell.isProcedure = false;
|
|
|
|
|
showBingoSequence.onFinish = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CheckFinish();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnFinish()
|
|
|
|
|
{
|
|
|
|
|
GameDispatcher.Instance.Dispatch(BingoInfo.AddPause, -1);
|
|
|
|
|
needShowBingoList.Clear();
|
|
|
|
|
BingoCell.bingoCardboardIndex = -1;
|
|
|
|
|
|
|
|
|
|
BingoCell.isProcedure = false;
|
|
|
|
|
if (isDelayCheckBingo)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
isDelayCheckBingo = false;
|
|
|
|
|
CheckBingo();
|
|
|
|
|
GameDispatcher.Instance.Dispatch(BingoInfo.CheckBingo, data.index);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (isBingoing)
|
|
|
|
|
{
|
|
|
|
|
isBingoing = false;
|
|
|
|
|
CheckFinish();
|
|
|
|
|
GameDispatcher.Instance.Dispatch(BingoInfo.CheckBingo, data.index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CheckFinish()
|
|
|
|
|
{
|
|
|
|
|
if (bingoedList.Count >= 3)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
isFinish = true;
|
|
|
|
|
|
|
|
|
|
if (!bingGoSke.gameObject.activeInHierarchy)
|
|
|
|
|
{
|
|
|
|
|
bingGoSke.gameObject.SetActive(true);
|
|
|
|
|
NAAVsa.SetSkin(bingGoSke, "default");
|
|
|
|
|
|
|
|
|
|
idleSys[2].gameObject.SetActive(true);
|
|
|
|
|
finishMask.gameObject.SetActive(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!BingoCell.IsInGame)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GameDispatcher.Instance.Dispatch(BingoInfo.FinishOneCardBoard, this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int IsBingo(List<int> selectList)
|
|
|
|
|
{
|
|
|
|
|
foreach (var kv in from kv in BingoCell.bingoDic
|
2026-05-08 11:03:00 +08:00
|
|
|
where !bingoedList.Contains(kv.Key)
|
|
|
|
|
let isAllMatch = kv.Value.All(selectList.Contains)
|
|
|
|
|
where isAllMatch
|
|
|
|
|
select kv)
|
2026-04-20 13:49:36 +08:00
|
|
|
{
|
|
|
|
|
return kv.Key;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|