using System; using System.Collections.Generic; using System.Linq; using UnityEngine; public class TimeRushManager : GameSystemManager, IOpenServerActivity { public Action PlayAnimationSync; private bool isPlayAnimation = false; public bool IsPlayAnimation { get { return isPlayAnimation; } set { isPlayAnimation = value; if (isPlayAnimation) { PlayAnimationSync?.Invoke(); } isPlayAnimation = false; } } public const int activityType = (int)OpenServerActivityCenter.ActivityType.AT_Activity2; public const int activityID = (int)NewDayActivityID.TimeRushAct; public int actNum = 10; public static OperationType operaType = OperationType.default47; public Redpoint redPoint = new Redpoint(MainRedDot.TimeRushRepoint); public bool IsOpen => OperationTimeHepler.Instance.SatisfyOpenCondition(operaType); public bool IsAdvance => OperationTimeHepler.Instance.SatisfyAdvanceCondition(operaType); public bool priorityOpen => redPoint.state == RedPointState.Simple; public event Action onStateUpdate; //类型对应功能ID public Dictionary funcIdDict = new Dictionary(); public bool TryGetFuncIdByRoundType(int roundType, out int funcId) { return funcIdDict.TryGetValue(roundType, out funcId); } //类型对应窗口ID public Dictionary windowIDDict = new Dictionary(); public bool TryGetWindowIDByRoundType(int roundType, out int windowID) { return windowIDDict.TryGetValue(roundType, out windowID); } public Dictionary moneyTypeDict = new Dictionary(); public bool TryGetMoneyTypeByRoundType(int roundType, out int windowID) { return moneyTypeDict.TryGetValue(roundType, out windowID); } public override void Init() { OperationTimeHepler.Instance.operationTimeUpdateEvent += OperationTimeUpdateEvent; OperationTimeHepler.Instance.operationStartEvent += OperationStartEvent; OperationTimeHepler.Instance.operationEndEvent += OperationEndEvent; OperationTimeHepler.Instance.operationAdvanceEvent += OperationAdvanceEvent; StoreModel.Instance.RefreshBuyShopLimitEvent += RefreshBuyShopLimitEvent; //storeModel.RefreshBuyShopLimitEvent += RefreshBuyShopLimitEvent; OpenServerActivityCenter.Instance.Register(activityID, this, activityType); var config = FuncConfigConfig.Get("TimeRush"); windowIDDict = ConfigParse.ParseIntDict(config.Numerical1); funcIdDict = ConfigParse.ParseIntDict(config.Numerical2); moneyTypeDict = ConfigParse.ParseIntDict(config.Numerical3); } public override void Release() { OperationTimeHepler.Instance.operationTimeUpdateEvent -= OperationTimeUpdateEvent; OperationTimeHepler.Instance.operationStartEvent -= OperationStartEvent; OperationTimeHepler.Instance.operationEndEvent -= OperationEndEvent; OperationTimeHepler.Instance.operationAdvanceEvent -= OperationAdvanceEvent; StoreModel.Instance.RefreshBuyShopLimitEvent -= RefreshBuyShopLimitEvent; } private void OperationTimeUpdateEvent(OperationType type) { if (type == operaType) { UpdateRedpoint(); } } private void RefreshBuyShopLimitEvent() { UpdateRedpoint(); } private void OperationStartEvent(OperationType type, int state) { if (type == operaType && state == 0) { if (onStateUpdate != null) { onStateUpdate(activityID); } UpdateRedpoint(); } } private void OperationEndEvent(OperationType type, int state) { if (type == operaType) { if (onStateUpdate != null) { onStateUpdate(activityID); } if (UIManager.Instance.IsOpened()) { UIManager.Instance.CloseWindow(); } UpdateRedpoint(); } } private void OperationAdvanceEvent(OperationType type) { if (type == operaType) { if (onStateUpdate != null) { onStateUpdate(activityID); } UpdateRedpoint(); } } public bool TryGetOperationInfo(out OperationCycleHall act) { act = null; return OperationTimeHepler.Instance.TryGetOperation(operaType, out act) && act != null; } public bool TryGetInListIndexById(int id, out int index) { index = -1; var list = GetTabIDList(); if (list.IsNullOrEmpty() || !list.Contains(id)) return false; index = list.IndexOf(id); return index >= 0; } public bool IsFuncOpen() { if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.TimeRush)) return false; if (!IsOpen) return false; if (!TryGetOperationInfo(out OperationCycleHall act)) return false; List list = GetTabIDList(); if (list.IsNullOrEmpty()) return false; return true; } private int m_NowTabId; public event Action OnNowTabIdChangeEvent; public int nowTabId { get { return m_NowTabId; } set { if (m_NowTabId != value) m_NowTabId = value; OnNowTabIdChangeEvent?.Invoke(); } } public List GetTabIDList() { if (!TryGetOperationInfo(out OperationCycleHall act)) return null; var list = ActLunhuidianTypeConfig.GetTabList(); if (list.IsNullOrEmpty()) return null; List resList = new List(); for (int i = 0; i < list.Count; i++) { int id = list[i]; if (!ActLunhuidianTypeConfig.TryGetConfig(id, out var config)) continue; if (!act.TryGetRound(config.RoundType, out var info)) continue; //没配功能ID直接加入 if (!funcIdDict.TryGetValue(config.RoundType, out var funcId)) { if (!resList.Contains(id)) resList.Add(id); continue; } //配了功能ID,判断功能是否开启 if (FuncOpen.Instance.IsFuncOpen(funcId)) { if (!resList.Contains(id)) resList.Add(id); } } return resList; } public Dictionary playerInfoDict = new Dictionary(); public bool TryGetPlayerInfo(int roundType, out HAA89_tagMCActLunhuidianPlayerInfo playerInfo) { return playerInfoDict.TryGetValue(roundType, out playerInfo) && playerInfo != null; } public event Action OnUpdatePlayerInfoEvent; public void UpdatePlayerInfo(HAA89_tagMCActLunhuidianPlayerInfo netPack) { if (actNum != netPack.ActNum) return; if (!playerInfoDict.ContainsKey(netPack.RoundType)) playerInfoDict[netPack.RoundType] = new HAA89_tagMCActLunhuidianPlayerInfo(); playerInfoDict[netPack.RoundType].RoundType = netPack.RoundType; playerInfoDict[netPack.RoundType].CurRound = netPack.CurRound; playerInfoDict[netPack.RoundType].CurValue = netPack.CurValue; playerInfoDict[netPack.RoundType].AwardRecord = netPack.AwardRecord; CheckNewAwardHave(netPack.RoundType, (int)netPack.CurRound, (int)netPack.CurValue); OnUpdatePlayerInfoEvent?.Invoke(); UpdateRedpoint(); } public int newRoundType; public int newAwardType; public int newAwardTypeValue; public int newAwardIndex; // <轮回类型, 上一次的CurRound> public Dictionary lastCurRoundDict = new Dictionary(); // <轮回类型, 上一次的CurValue> public Dictionary lastCurValueDict = new Dictionary(); public event Action OnNewAwardHaveEvent; public void CheckNewAwardHave(int roundType, int curRound, int curValue) { if (lastCurRoundDict.ContainsKey(roundType) && lastCurValueDict.ContainsKey(roundType)) { int lastCurRound = lastCurRoundDict[roundType]; int lastCurValue = lastCurValueDict[roundType]; if (lastCurRound < curRound) { lastCurValueDict[roundType] = 0; } lastCurValue = lastCurValueDict[roundType]; if (lastCurValue < curValue) { if (!TryGetOperationInfo(out var act)) return; if (act.TryGetRound(roundType, out var round) && round.AwardList != null) { for (int i = 0; i < round.AwardList.Length; i++) { var Award = round.AwardList[i]; int state = GetAwardState(roundType, Award.AwardIndex); if (Award.NeedValue > lastCurValue && Award.NeedValue <= curValue && state == 1) { newRoundType = roundType; newAwardType = round.AwardType; newAwardTypeValue = (int)round.AwardTypeValue; newAwardIndex = Award.AwardIndex; if (!UIManager.Instance.IsOpened()) { UIManager.Instance.OpenWindow(); } OnNewAwardHaveEvent?.Invoke(); } } } } } lastCurRoundDict[roundType] = curRound; lastCurValueDict[roundType] = curValue; } public int GetAwardState(int roundType, int awardIndex) { if (!TryGetPlayerInfo(roundType, out var playerInfo)) return 0; if (!TryGetOperationInfo(out var act)) return 0; if (!act.TryGetRoundInfoByIndex(roundType, awardIndex, out var awardInfo, out int listIndex)) return 0; if (playerInfo.CurValue >= awardInfo.NeedValue) { return (playerInfo.AwardRecord & (1 << awardIndex)) != 0 ? 2 : 1; } else { return 0; } } public void HaveAllMissionAward(int roundType) { if (!TryGetOperationInfo(out var act)) return; if (!act.TryGetRound(roundType, out var round) || round.AwardList == null) return; for (int i = 0; i < round.AwardList.Length; i++) { var award = round.AwardList[i]; int state = GetAwardState(roundType, award.AwardIndex); if (state == 1) { SendGetAward(roundType, (int)award.NeedValue); } } } public bool IsCanBuyCTG(int ctgID) { if (!RechargeManager.Instance.TryGetRechargeCount(ctgID, out var rechargeCount)) return false; if (!CTGConfig.HasKey(ctgID)) return false; CTGConfig config = CTGConfig.Get(ctgID); return rechargeCount.totalCount < config.TotalBuyCount; } public bool IsFree(int shopID) { if (!StoreConfig.HasKey(shopID)) return false; StoreConfig config = StoreConfig.Get(shopID); return config.MoneyNum == 0; } public bool IsCanBuyShop(int shopID) { if (!StoreConfig.HasKey(shopID)) return false; StoreConfig config = StoreConfig.Get(shopID); int remainNum; StoreModel.Instance.TryGetIsSellOut(config, out remainNum); return remainNum > 0; } public List GetGiftItemList(int roundType, bool isSort = false) { List res = new List(); if (TryGetOperationInfo(out var act) && act.TryGetRound(roundType, out var round) && round.CTGIDList != null) { var list = StoreModel.Instance.storeTypeDict[round.ShopType]; if (!list.IsNullOrEmpty()) { for (int i = 0; i < list.Count; i++) { var item = list[i]; if (item.storeConfig == null) continue; res.Add(new TimeRushGiftItem { type = 0, id = item.storeConfig.ID, }); } } for (int i = 0; i < round.CTGIDList.Length; i++) { var item = round.CTGIDList[i]; res.Add(new TimeRushGiftItem { type = 1, id = item, }); } if (isSort) { res = res.OrderBy(item => { bool isCanBuy = item.type == 0 ? IsCanBuyShop(item.id) : IsCanBuyCTG(item.id); return !isCanBuy; }) .ThenBy(item => item.type) .ThenBy(item => item.id) .ToList(); } } return res; } public List GetTaskList(int roundType, bool isSort = false) { if (!TryGetOperationInfo(out var act) || !act.TryGetRound(roundType, out var round) || round.AwardList == null) return null; List res = round.AwardList.ToList(); if (isSort) { // 先获取状态并缓存,避免排序时重复调用 GetAwardState res = res.Select(award => new { Data = award, State = GetAwardState(roundType, award.AwardIndex) }).OrderBy(x => { // 定义优先级映射:数字越小,排得越靠前 if (x.State == 1) return 0; // 最前:可领取 if (x.State == 0) return 1; // 中间:未达成 return 2; // 最后:已领取 (state == 2) }) .ThenBy(x => x.Data.AwardIndex) // 状态相同时,AwardIndex 小的在前 .Select(x => x.Data) // 提取回原始数据结构 .ToList(); } return res; } public bool IsTabShowRed(int id) { if (!ActLunhuidianTypeConfig.TryGetConfig(id, out var config)) return false; int roundType = config.RoundType; int tabType = config.TabType; if (tabType == 1) { var taskList = GetTaskList(roundType); if (taskList.IsNullOrEmpty()) return false; for (int i = 0; i < taskList.Count; i++) { var task = taskList[i]; int state = GetAwardState(roundType, task.AwardIndex); if (state == 1) return true; } return false; } var list = GetGiftItemList(roundType); if (list.IsNullOrEmpty()) return false; for (int i = 0; i < list.Count; i++) { var item = list[i]; if (item.type == 0) { bool isFree = IsFree(item.id); bool isCanBuy = IsCanBuyShop(item.id); if (isFree && isCanBuy) return true; } } return false; } public void SendGetAward(int roundType, int needValue) { CA504_tagCMPlayerGetReward getReward = new CA504_tagCMPlayerGetReward(); getReward.RewardType = 78; getReward.DataEx = (uint)actNum; getReward.DataExStr = StringUtility.Concat(roundType.ToString(), "|", needValue.ToString()); getReward.DataExStrLen = (byte)getReward.DataExStr.Length; GameNetSystem.Instance.SendInfo(getReward); } public void UpdateRedpoint() { redPoint.state = RedPointState.None; if (!IsFuncOpen()) return; if (!TryGetOperationInfo(out var act) || act.roundInfoDict == null) return; foreach (var roundType in act.roundInfoDict.Keys) { ActLunhuidianTypeConfig config; if (ActLunhuidianTypeConfig.TryGetConfig(roundType, 1, out config)) { bool isShow = IsTabShowRed(config.ID); if (isShow) { redPoint.state = RedPointState.Simple; return; } } if (ActLunhuidianTypeConfig.TryGetConfig(roundType, 2, out config)) { bool isShow = IsTabShowRed(config.ID); if (isShow) { redPoint.state = RedPointState.Simple; return; } } } } }