using vnxbqy.UI; using System.Collections.Generic; using System.Linq; using System; using UnityEngine; // startShowTime 和 endShowTime 同时为0 代表未推送 // startShowTime 不为0 endShowTime为0 代表正在推送 // endShowTime 不为0 推送结束 public class LimitedTimeLuxuryGiftInfo { public int startShowTime; //开始展示时间 public int endShowTime; //结束展示时间, 当一档内所有ctgid都购买完后或者到期,展示时间结束 public int index; //CTGID组里的当前第几档,一档内有多个ctgid public int isReset; //0 当前档展示完继续往下一档走 1 当前档展示完后从第一档开始 } public class LimitedTimeLuxuryGiftModel : ILModel { public int maxGroupsCount; //最大组数 //当前显示的ctgID private int m_showCtgId; public int showCtgId { get { return m_showCtgId; } set { if (m_showCtgId == value) return; m_showCtgId = value; UpdateAllUIEvent?.Invoke(); } } public int purchaseLimitPeriodS; //展示时长(秒) float randSeed; //控制推送概率 //豪礼id :[开始展示时间 开始冷却时间 第几档] public Dictionary luxuryGiftInfoDict = new Dictionary(); //展示豪礼id队列 private List luxuryGiftIdQueueList = new List(); public List LuxuryGiftIdQueueList { get { return luxuryGiftIdQueueList; } } VipModel vipModel { get { return ModelCenter.Instance.GetModelEx(); } } public Action UpdateAllUIEvent; int funcID = 221; //限时豪礼功能id string saveMark = "xshl1_"; protected override void Init() { GameEvent.afterPlayerDataInitializeEvent += OnAfterPlayerDataInitializeEvent; GlobalTimeEvent.Instance.secondEvent += OnRefreshSecond; vipModel.rechargeCountEvent += OnRechargeCountEvent; TimeMgr.Instance.OnWeekAfterPlayerDataInitializeEvent += OnWeek; TimeMgr.Instance.OnMonthAfterPlayerDataInitializeEvent += OnMonth; var config = FuncConfigConfig.Get("LimitedTimeLuxuryGift"); maxGroupsCount = int.Parse(config.Numerical1); purchaseLimitPeriodS = int.Parse(config.Numerical2); randSeed = float.Parse(config.Numerical3); } private void OnAfterPlayerDataInitializeEvent() { luxuryGiftInfoDict.Clear(); luxuryGiftIdQueueList.Clear(); //构建基础数据 var keyList = ILLimitedTimeLuxuryGiftConfig.GetKeys().ToList(); for (int i = 0; i < keyList.Count; i++) { luxuryGiftInfoDict[int.Parse(keyList[i])] = new LimitedTimeLuxuryGiftInfo { startShowTime = 0, endShowTime = 0, index = 0, isReset = 0, }; } // 在收到充值封包前构建 LoadLocalInfo(); } protected override void UnInit() { GlobalTimeEvent.Instance.secondEvent -= OnRefreshSecond; GameEvent.afterPlayerDataInitializeEvent -= OnAfterPlayerDataInitializeEvent; vipModel.rechargeCountEvent -= OnRechargeCountEvent; TimeMgr.Instance.OnWeekAfterPlayerDataInitializeEvent -= OnWeek; TimeMgr.Instance.OnMonthAfterPlayerDataInitializeEvent -= OnMonth; } public void OnMonth() { DebugEx.Log("收到过月通知"); ClearLocalInfo(); } public void OnWeek() { DebugEx.Log("收到过周通知"); ClearLocalInfo(); } void ClearLocalInfo() { var keyList = luxuryGiftInfoDict.Keys.ToList(); for (int i = 0; i < keyList.Count; i++) { int luxuryGiftId = keyList[i]; if (TimeUtility.GetTime((uint)(luxuryGiftInfoDict[luxuryGiftId].startShowTime + purchaseLimitPeriodS)) >= GetServerNow()) { luxuryGiftInfoDict[luxuryGiftId].isReset = 1; } else { luxuryGiftInfoDict[luxuryGiftId].startShowTime = 0; luxuryGiftInfoDict[luxuryGiftId].endShowTime = 0; luxuryGiftInfoDict[luxuryGiftId].index = 0; luxuryGiftInfoDict[luxuryGiftId].isReset = 0; } SaveLocalInfo(); } } private void OnRechargeCountEvent(int obj) { int luxuryGiftId = ILLimitedTimeLuxuryGiftConfig.GetLuxuryGiftIDByCtgID(obj); if (luxuryGiftId == -1) return; //购买的不是当前展示的豪礼 不处理 var index = ILLimitedTimeLuxuryGiftConfig.GetGiftGearIndexByCtgID(obj); if (luxuryGiftInfoDict[luxuryGiftId].index != index) return; //当前档位全买了就直接出队 if (IsGearAllBuy(luxuryGiftId)) { if (luxuryGiftIdQueueList.Contains(luxuryGiftId)) { PopQueueByLuxuryGiftId(luxuryGiftId); } //防止重登后重置了时间 if (luxuryGiftInfoDict[luxuryGiftId].endShowTime == 0 && luxuryGiftInfoDict[luxuryGiftId].startShowTime != 0) EditGiftState(3, luxuryGiftId, index); } } //每秒触发 public void OnRefreshSecond() { if (PlayerDatas.Instance.PlayerId == 0) return; var keyList = luxuryGiftInfoDict.Keys.ToList(); if (keyList.IsNullOrEmpty()) return; for (int i = 0; i < keyList.Count; i++) { int startShowTime = luxuryGiftInfoDict[keyList[i]].startShowTime; int endShowTime = luxuryGiftInfoDict[keyList[i]].endShowTime; int showCloseSeconds = GetShowCloseTime(keyList[i]); int index = luxuryGiftInfoDict[keyList[i]].index; if (endShowTime == 0 && startShowTime != 0 && showCloseSeconds <= 0) { PopQueueByLuxuryGiftId(keyList[i]); EditGiftState(2, keyList[i], index); } } } DateTime GetServerNow() { //return DateTime.Now; return TimeUtility.ServerNow; } int GetAllSeconds() { //return (int)(DateTime.Now - TimeUtility.OriginalTime).TotalSeconds; return TimeUtility.AllSeconds; } //读取本地数据 //读取数据时只校验安全性是否越界,数据重置可以通过热更指定豪华ID来实现 //!!!比如配置此功能热更的版本号对比,如果版本号不一致,清空指定豪华id的数据,也可以约定为0时清空所有数据,此方式可以同步热更暂且不实现 void LoadLocalInfo() { var keyList = luxuryGiftInfoDict.Keys.ToList(); for (int i = 0; i < keyList.Count; i++) { var luxuryID = keyList[i]; var data = LocalSave.GetIntArray(saveMark + ((ulong)PlayerDatas.Instance.PlayerId * 1000 + (ulong)luxuryID)); if (data.IsNullOrEmpty()) continue; //此处只校验是否越界,数据更新参考注释 var config = ILLimitedTimeLuxuryGiftConfig.Get(luxuryID); bool needSave = false; if (data.Length != 4 || (data.Length == 4 && data[2] >= config.CTGID.Length)) { //数据越界,清空本条 needSave = true; data = new int[4] { 0, 0, 0, 0 }; } luxuryGiftInfoDict[luxuryID] = new LimitedTimeLuxuryGiftInfo { startShowTime = data[0], endShowTime = data[1], index = data[2], isReset = data[3], }; if (needSave) { SaveLocalInfo(luxuryID); } //构建队列 if (data[0] != 0 && data[1] == 0) luxuryGiftIdQueueList.Add(luxuryID); } //按开始展示时间排序 luxuryGiftIdQueueList.Sort((a, b) => { return luxuryGiftInfoDict[a].startShowTime.CompareTo(luxuryGiftInfoDict[b].startShowTime); }); } //存储本地数据 0表示全部存储,其他表示存储指定限时豪华id public void SaveLocalInfo(int id = 0) { int[] data = new int[4]; if (id == 0) { //全部存储 var keyList = luxuryGiftInfoDict.Keys.ToList(); for (int i = 0; i < keyList.Count; i++) { var luxuryID = keyList[i]; data[0] = luxuryGiftInfoDict[luxuryID].startShowTime; data[1] = luxuryGiftInfoDict[luxuryID].endShowTime; data[2] = luxuryGiftInfoDict[luxuryID].index; data[3] = luxuryGiftInfoDict[luxuryID].isReset; LocalSave.SetIntArray(saveMark + ((ulong)PlayerDatas.Instance.PlayerId * 1000 + (ulong)luxuryID), data); } } else { if (!luxuryGiftInfoDict.ContainsKey(id)) return; //存储指定限时豪华id data[0] = luxuryGiftInfoDict[id].startShowTime; data[1] = luxuryGiftInfoDict[id].endShowTime; data[2] = luxuryGiftInfoDict[id].index; data[3] = luxuryGiftInfoDict[id].isReset; LocalSave.SetIntArray(saveMark + ((ulong)PlayerDatas.Instance.PlayerId * 1000 + (ulong)id), data); } } //切换豪礼状态 //1 开始展示 2 倒计时展示结束 3 当前档购买结束 4 记录已经是最后一档或者检索时对已购买的进行补充记录 5 重置本地数据 public void EditGiftState(int num, int luxuryGiftId, int index) { Debug.LogFormat("EditGiftState num {0} luxuryGiftId {1} index {2}", num, luxuryGiftId, index); if (!luxuryGiftInfoDict.ContainsKey(luxuryGiftId)) return; if (num == 1) { luxuryGiftInfoDict[luxuryGiftId].startShowTime = GetAllSeconds(); luxuryGiftInfoDict[luxuryGiftId].endShowTime = 0; luxuryGiftInfoDict[luxuryGiftId].index = index; } if (num == 2) { luxuryGiftInfoDict[luxuryGiftId].endShowTime = luxuryGiftInfoDict[luxuryGiftId].startShowTime + purchaseLimitPeriodS; } else if (num == 3) { luxuryGiftInfoDict[luxuryGiftId].endShowTime = GetAllSeconds(); } else if (num == 4) { luxuryGiftInfoDict[luxuryGiftId].startShowTime = 1; luxuryGiftInfoDict[luxuryGiftId].endShowTime = 1; luxuryGiftInfoDict[luxuryGiftId].index = index; } else if (num == 5) { luxuryGiftInfoDict[luxuryGiftId].isReset = 0; } SaveLocalInfo(luxuryGiftId); } // 获得当前按钮显示的状态 0 未购买 1 已购买 2 已结束 public int GetGiftState(int ctgId) { VipModel.RechargeCount rechargeCount; vipModel.TryGetRechargeCount(ctgId, out rechargeCount); var configCtg = CTGConfig.Get(ctgId); if (GetCheckNowTotalCnt(rechargeCount, configCtg) < GetCheckTableTotalCnt(configCtg)) { int luxuryGiftID = ILLimitedTimeLuxuryGiftConfig.GetLuxuryGiftIDByCtgID(ctgId); int seconds = GetShowCloseTime(luxuryGiftID); return seconds > 0 ? 0 : 2; } else { return 1; } } //得到指定豪礼的展示剩余时间 public int GetShowCloseTime(int luxuryGiftId) { if (!luxuryGiftInfoDict.ContainsKey(luxuryGiftId) || luxuryGiftInfoDict[luxuryGiftId].startShowTime == 0) return 0; var overTime = TimeUtility.GetTime((uint)(luxuryGiftInfoDict[luxuryGiftId].startShowTime + purchaseLimitPeriodS)); if (GetServerNow() > overTime) return 0; return (int)(overTime - GetServerNow()).TotalSeconds; } //得到指定豪礼的冷却结束时间 public int GetCoolDownTime(int luxuryGiftId) { if (!luxuryGiftInfoDict.ContainsKey(luxuryGiftId) || luxuryGiftInfoDict[luxuryGiftId].endShowTime == 0) return 0; int ShowIntervalS = GetShowIntervalS(luxuryGiftId); var overTime = TimeUtility.GetTime((uint)(luxuryGiftInfoDict[luxuryGiftId].endShowTime + ShowIntervalS)); if (GetServerNow() > overTime) return 0; return (int)(overTime - GetServerNow()).TotalSeconds; } //获取当前豪礼的冷却时间秒数 public int GetShowIntervalS(int luxuryGiftId) { int nowCtgidIndex = luxuryGiftInfoDict[luxuryGiftId].index; var config = ILLimitedTimeLuxuryGiftConfig.Get(luxuryGiftId); if (nowCtgidIndex >= config.CTGID.Length - 1) return 0; //如果当前档位大于配置的展示时间长度,取最后一个 return config.ShowInterval[Math.Min(nowCtgidIndex, config.ShowInterval.Length - 1)]; } //获取当前档最近的下一个未购买的档位 // -1 没有下一档了 public int GetNextGiftIndex(int luxuryGiftId) { int gearIndex = luxuryGiftInfoDict[luxuryGiftId].index; if (luxuryGiftInfoDict[luxuryGiftId].isReset == 1) return AllCanBuyGear(luxuryGiftId); var config = ILLimitedTimeLuxuryGiftConfig.Get(luxuryGiftId); if (gearIndex >= config.CTGID.Length - 1) return -1; //没有记录的情况下,先判断第一档是否购买过 if (!(gearIndex == 0 && luxuryGiftInfoDict[luxuryGiftId].startShowTime == 0)) gearIndex++; if (IsGearAllBuy(luxuryGiftId, gearIndex)) { //补充已购买的记录 EditGiftState(4, luxuryGiftId, gearIndex); return GetNextGiftIndex(luxuryGiftId); } return gearIndex; } //当前档或者指定档是否全买 public bool IsGearAllBuy(int luxuryGiftId, int index = -1) { if (luxuryGiftId == -1) return true; int gearIndex; if (index == -1) gearIndex = luxuryGiftInfoDict[luxuryGiftId].index; else gearIndex = index; var config = ILLimitedTimeLuxuryGiftConfig.Get(luxuryGiftId); for (int i = 0; i < config.CTGID[gearIndex].Length; i++) { VipModel.RechargeCount rechargeCount; int ctgID = config.CTGID[gearIndex][i]; vipModel.TryGetRechargeCount(ctgID, out rechargeCount); var configCtg = CTGConfig.Get(ctgID); if (GetCheckNowTotalCnt(rechargeCount, configCtg) < GetCheckTableTotalCnt(configCtg)) { return false; } } return true; } int GetCheckTableTotalCnt(CTGConfig ctg) { if (ctg.WeekBuyCount != 0) return ctg.WeekBuyCount; if (ctg.MonthBuyCount != 0) return ctg.MonthBuyCount; return ctg.TotalBuyCount; } int GetCheckNowTotalCnt(VipModel.RechargeCount rechargeCnt, CTGConfig ctg) { if (ctg.WeekBuyCount != 0) return rechargeCnt.weekPayCount; if (ctg.MonthBuyCount != 0) return rechargeCnt.monthPayCount; return rechargeCnt.totalCount; } //获取展示时间最快结束的豪礼id public int GetMaxFastCloseGiftID() { if (luxuryGiftIdQueueList.IsNullOrEmpty()) return -1; return luxuryGiftIdQueueList[0]; } //队列中有几个可以展示的豪礼 public int ShowLuxuryGiftIdCount() { return luxuryGiftIdQueueList.Count; } public void PushQueueByLuxuryGiftId(int luxuryGiftId) { luxuryGiftIdQueueList.Add(luxuryGiftId); } public void PopQueueByLuxuryGiftId(int luxuryGiftId) { luxuryGiftIdQueueList.Remove(luxuryGiftId); } //获取所有展示豪礼的未购买ctgid public List GetShowCtgIDList() { List ctgIDList = new List(); for (int i = 0; i < luxuryGiftIdQueueList.Count; i++) { int luxuryGiftId = luxuryGiftIdQueueList[i]; int gearIndex = luxuryGiftInfoDict[luxuryGiftId].index; var config = ILLimitedTimeLuxuryGiftConfig.Get(luxuryGiftId); for (int j = 0; j < config.CTGID[gearIndex].Length; j++) { VipModel.RechargeCount rechargeCount; int ctgID = config.CTGID[gearIndex][j]; vipModel.TryGetRechargeCount(ctgID, out rechargeCount); var configCtg = CTGConfig.Get(ctgID); if (GetCheckNowTotalCnt(rechargeCount, configCtg) < GetCheckTableTotalCnt(configCtg)) { ctgIDList.Add(ctgID); } } } return ctgIDList; } //限时豪礼入口开启条件 public bool IsShow() { if (!FuncOpen.Instance.IsFuncOpen(funcID)) return false; if (ShowLuxuryGiftIdCount() == 0) return false; return true; } //传入的豪礼id是否符合推送要求 // type 1代表物品id, 2 代表货币类型,由id传输 public bool IsItemIdShow(int luxuryGiftId, int id, int singleCnt, int type, int isJumpOrOpen = 0) { if (!IsRequirementOpen(luxuryGiftId)) return false; float curCnt = 0; if (type == 1) { PackModel packModel = ModelCenter.Instance.GetModel(); curCnt = (ulong)packModel.GetItemCountByID(PackType.Item, id); //身上物品数量 } else if (type == 2) { curCnt = HeroControler.Instance.GetMoneyCntIL(id); } else { curCnt = 1; singleCnt = 1; } double result = Math.Max((1 - (curCnt - singleCnt) / singleCnt / randSeed), 0) * 10000; var rand = UnityEngine.Random.Range(1, 10000); DebugEx.LogFormat("公式算出的结果: luxuryGiftId {4} result {0} - rand {1} curCnt {2} singleCnt {3} ", result, rand, curCnt, singleCnt, luxuryGiftId); if (rand > result) return false; int pushIndex = GetNextGiftIndex(luxuryGiftId); if (pushIndex == -1) { var config = ILLimitedTimeLuxuryGiftConfig.Get(luxuryGiftId); EditGiftState(4, luxuryGiftId, config.CTGID.Length - 1); return false; } PushQueueByLuxuryGiftId(luxuryGiftId); EditGiftState(1, luxuryGiftId, pushIndex); showCtgId = GetNextCtgId(luxuryGiftId); if (luxuryGiftInfoDict[luxuryGiftId].isReset == 1) EditGiftState(5, luxuryGiftId, 0); if (isJumpOrOpen == 0) { WindowCenter.Instance.Open("LimitedTimeLuxuryGiftWin"); } else { WindowJumpMgr.Instance.WindowJumpToEx("LimitedTimeLuxuryGiftWin"); } return true; } //找出推送档中未购买的ctgid public int GetNextCtgId(int luxuryGiftId) { int gearIndex = luxuryGiftInfoDict[luxuryGiftId].index; var config = ILLimitedTimeLuxuryGiftConfig.Get(luxuryGiftId); for (int i = 0; i < config.CTGID[gearIndex].Length; i++) { VipModel.RechargeCount rechargeCount; int ctgID = config.CTGID[gearIndex][i]; vipModel.TryGetRechargeCount(ctgID, out rechargeCount); var configCtg = CTGConfig.Get(ctgID); if (GetCheckNowTotalCnt(rechargeCount, configCtg) < GetCheckTableTotalCnt(configCtg)) { return ctgID; } } return 0; } //这档豪礼所有ctgid都无法购买 public bool IsNoAllBuy(int luxuryGiftId) { var config = ILLimitedTimeLuxuryGiftConfig.Get(luxuryGiftId); for (int i = 0; i < config.CTGID.Length; i++) { for (int j = 0; j < config.CTGID[i].Length; j++) { int ctgID = config.CTGID[i][j]; VipModel.RechargeCount rechargeCount; vipModel.TryGetRechargeCount(ctgID, out rechargeCount); var configCtg = CTGConfig.Get(ctgID); if (GetCheckNowTotalCnt(rechargeCount, configCtg) < GetCheckTableTotalCnt(configCtg)) { return false; } } } return true; } //这档豪礼所有 CTGID中第一个可购买的CTGID 所在的档位 public int AllCanBuyGear(int luxuryGiftId) { var config = ILLimitedTimeLuxuryGiftConfig.Get(luxuryGiftId); for (int i = 0; i < config.CTGID.Length; i++) { for (int j = 0; j < config.CTGID[i].Length; j++) { int ctgID = config.CTGID[i][j]; VipModel.RechargeCount rechargeCount; vipModel.TryGetRechargeCount(ctgID, out rechargeCount); var configCtg = CTGConfig.Get(ctgID); if (GetCheckNowTotalCnt(rechargeCount, configCtg) < GetCheckTableTotalCnt(configCtg)) { return ILLimitedTimeLuxuryGiftConfig.GetGiftGearIndexByCtgID(ctgID); } } } return 0; } //是否满足推送条件 bool IsRequirementOpen(int luxuryGiftId) { if (!FuncOpen.Instance.IsFuncOpen(funcID)) return false; //传入的豪礼id表中没有,不推送 if (!luxuryGiftInfoDict.ContainsKey(luxuryGiftId)) return false; //超出推送上限 if (luxuryGiftIdQueueList.Count >= maxGroupsCount) return false; //展示指定条件如等级或者指定功能开启 var config = ILLimitedTimeLuxuryGiftConfig.Get(luxuryGiftId); if (config.ShowRequirement[0] == 0) { if (PlayerDatas.Instance.baseData.LV < config.ShowRequirement[1]) return false; } else { if (!FuncOpen.Instance.IsFuncOpen(config.ShowRequirement[1])) return false; } DebugEx.Log("isReset " + luxuryGiftInfoDict[luxuryGiftId].isReset); if (luxuryGiftInfoDict[luxuryGiftId].isReset == 1) { DebugEx.Log("isReset 走 没有可购买CTG的不推送"); //没有可购买CTG的不推送 if (IsNoAllBuy(luxuryGiftId)) return false; } else { DebugEx.Log("isReset 走 已全部推送完毕的不推送"); //已全部推送完毕的不推送 int gearIndex = luxuryGiftInfoDict[luxuryGiftId].index; if (gearIndex >= config.CTGID.Length - 1) return false; } //正在展示中的不推送 if (luxuryGiftIdQueueList.Contains(luxuryGiftId)) return false; //冷却中的不推送 if (GetCoolDownTime(luxuryGiftId) > 0) return false; return true; } }