XGachaManagerCreator = function() local GET_GACHA_DATA_INTERVAL = 15 local XGachaManager = {} local ParseToTimestamp = XTime.ParseToTimestamp -- 以下数据都要通过gachaId查找,因为可能同时开多个卡池 local LastGetGachaRewardInfoTimes = {} local GachaProbShows = {} local GachaLogList = {} local GachaRewardInfos = {} local IsInfinite = {} local CurCountOfAll = {} local MaxCountOfAll = {} local CurExchangeItemCount = {} -- 当前购买过的gacha币数量 local TotalGachaTimes = {} local MissTimes = {} -- 保底次数 -- -- 卡池组状态 -- Key:number OrganizeId -- Value:Table { gachaId = XGachaConfigs.OrganizeGachaStatus } local GachaOrganizeStatus = {} local METHOD_NAME = { GetGachaInfo = "GetGachaInfoRequest", Gacha = "GachaRequest", GetGachaOrganizeInfo = "GetGachaOrganizeInfoRequest", GachaItemExchangeRequest = "GachaItemExchangeRequest", } function XGachaManager.Init() XGachaManager.SetGachaProbShowInfo() local gachaCfg = XGachaConfigs.GetGachas() for k, v in pairs(gachaCfg) do XGachaManager.SetGachaRewardInfo(k) IsInfinite[k] = false CurCountOfAll[k] = 0 MaxCountOfAll[k] = 0 CurExchangeItemCount[k] = 0 TotalGachaTimes[k] = 0 MissTimes[k] = 0 end end function XGachaManager.GetMissTimes(gachaId) return MissTimes[gachaId] or 0 end function XGachaManager.GetCurExchangeItemCount(gachaId) return CurExchangeItemCount[gachaId] or 0 end function XGachaManager.GetTotalGachaTimes(gachaId) return TotalGachaTimes[gachaId] or 0 end function XGachaManager.GetGachaRewardInfoById(gaChaId) local gachaCfg = XGachaConfigs.GetGachas() MaxCountOfAll[gaChaId] = 0 CurCountOfAll[gaChaId] = 0 IsInfinite[gaChaId] = false local groupIdList = {} for _, groupId in pairs(gachaCfg[gaChaId].GroupId) do table.insert(groupIdList, groupId) end local list = {} for _, v in pairs(GachaRewardInfos[gaChaId]) do for _, groupId in pairs(groupIdList) do if v.GroupId == groupId then table.insert(list, v) break end end end for _, v in pairs(list) do if v.RewardType == XGachaConfigs.RewardType.NotCount then IsInfinite[gaChaId] = true end MaxCountOfAll[gaChaId] = MaxCountOfAll[gaChaId] + v.UsableTimes CurCountOfAll[gaChaId] = CurCountOfAll[gaChaId] + (v.UsableTimes - v.CurCount) end table.sort(list, function(a, b) if a.Priority == b.Priority then return a.Id < b.Id else return a.Priority > b.Priority end end) return list end function XGachaManager.IsClearMinimumGuarantee(gaChaId) local gachaCfg = XGachaConfigs.GetGachaCfgById(gaChaId) local data = XGachaManager.GetGachaRewardInfoById(gaChaId) local isAllClear = true for k, v in pairs(data) do if v.CurCount > 0 and v.GroupId == gachaCfg.PropAddGroupId then isAllClear = false end end return isAllClear end -- 1核心层,2第一层、、、 function XGachaManager.GetGachaRewardSplitByRareLevel(gaChaId) local list = XGachaManager.GetGachaRewardInfoById(gaChaId) local res = {} for k, v in pairs(list) do if XTool.IsNumberValid(v.Rarelevel) then if not res[v.Rarelevel] then res[v.Rarelevel] = {} end table.insert(res[v.Rarelevel], v) end end return res end function XGachaManager.GetGachaProbShowById(gaChaId) local gachaProbShowInfo = GachaProbShows[gaChaId] if gachaProbShowInfo then table.sort(gachaProbShowInfo, function(a, b) if a.IsRare == b.IsRare then return a.Id < b.Id else return a.IsRare == XGachaConfigs.RareType.Rare end end) else XLog.Error("ProbShows's Data Is Null By GachaId :"..gaChaId) end return gachaProbShowInfo end function XGachaManager.GetCurCountOfAll(gachaId) return CurCountOfAll[gachaId] or 0 end function XGachaManager.GetMaxCountOfAll(gachaId) return MaxCountOfAll[gachaId] or 0 end function XGachaManager.GetIsInfinite(gachaId) if IsInfinite[gachaId] then return true end return false end function XGachaManager.GetGachaLogById(gachaId) return GachaLogList[gachaId] or {} end --- ---@param notCheckDraw boolean 是否检测活动研发功能开启,true:不检测,false:检测 function XGachaManager.CheckGachaIsOpenById(id, IsShowText, notCheckDraw) if IsShowText then if not notCheckDraw and not XFunctionManager.DetectionFunction(XFunctionManager.FunctionName.ActivityDrawCard) then return false end else if not notCheckDraw and not XFunctionManager.JudgeCanOpen(XFunctionManager.FunctionName.ActivityDrawCard) then return false end end local gachaCfg = XGachaConfigs.GetGachas() if not gachaCfg[id] then XLog.Error("GachaId Is Not Exist :"..id) return false end local timeId = gachaCfg[id].TimeId local IsInTime = XFunctionManager.CheckInTimeByTimeId(timeId) if IsShowText and not IsInTime then local str = CS.XTextManager.GetText("GachaIsClose") XUiManager.TipMsg(str) end -- if IsShowText and IsClose then -- XUiManager.TipText("GachaIsClose") -- end return IsInTime end --- --- 检测扭蛋组是否开启 function XGachaManager.CheckGachaOrganizeIsOpen(organizeId, isShowText) local startTimeStr, endTimeStr = XGachaConfigs.GetOrganizeTime(organizeId) if not startTimeStr or not endTimeStr then return false end local nowTime = XTime.GetServerNowTimestamp() local startTime = ParseToTimestamp(startTimeStr) local endTime = ParseToTimestamp(endTimeStr) local IsNotOpen = startTime > nowTime if isShowText and IsNotOpen then local str = CS.XTextManager.GetText("GachaIsNotOpen", startTimeStr, endTimeStr) XUiManager.TipMsg(str) end local IsClose = nowTime > endTime if isShowText and IsClose then XUiManager.TipText("GachaIsClose") end return (not IsClose) and (not IsNotOpen) end function XGachaManager.UpdateGachaRewardInfo(gridInfoList, gachaId) for _, v in pairs(gridInfoList or {}) do if GachaRewardInfos[gachaId][v.Id] then GachaRewardInfos[gachaId][v.Id].CurCount = GachaRewardInfos[gachaId][v.Id].UsableTimes - v.Times end end end function XGachaManager.UpdateGachaLog(gachaId, logList) GachaLogList = GachaLogList or {} GachaLogList[gachaId] = logList end function XGachaManager.SetGachaRewardInfo(gachaId) local gachaRewardCfg = XGachaConfigs.GetGachaReward() local tempGachaInfo = GachaRewardInfos[gachaId] if not tempGachaInfo then GachaRewardInfos[gachaId] = {} tempGachaInfo = GachaRewardInfos[gachaId] end for id, reward in pairs(gachaRewardCfg) do tempGachaInfo[id] = {} for k, v in pairs(reward) do tempGachaInfo[id][k] = v end tempGachaInfo[id].CurCount = tempGachaInfo[id].UsableTimes end end function XGachaManager.SetGachaProbShowInfo() local gachaProbShowCfg = XGachaConfigs.GetGachaProbShows() for _, probShow in pairs(gachaProbShowCfg) do GachaProbShows[probShow.GachaId] = GachaProbShows[probShow.GachaId] or {} table.insert(GachaProbShows[probShow.GachaId],probShow) end end function XGachaManager.GetGachaRewardInfoRequest(gaChaId, cb) local now = XTime.GetServerNowTimestamp() if LastGetGachaRewardInfoTimes[gaChaId] and now - LastGetGachaRewardInfoTimes[gaChaId] <= GET_GACHA_DATA_INTERVAL then cb() return end XNetwork.Call(METHOD_NAME.GetGachaInfo, { Id = gaChaId }, function(res) if res.Code ~= XCode.Success then XUiManager.TipCode(res.Code) return end XGachaManager.UpdateGachaRewardInfo(res.GridInfoList, gaChaId) XGachaManager.UpdateGachaLog(gaChaId, res.GachaRecordList) LastGetGachaRewardInfoTimes[gaChaId] = XTime.GetServerNowTimestamp() CurExchangeItemCount[gaChaId] = res.CurExchangeItemCount TotalGachaTimes[gaChaId] = res.TotalTimes MissTimes[gaChaId] = res.MissTimes cb(res) end) end function XGachaManager.DoGacha(gaChaId, count, cb, errorCb, organizeId) XNetwork.Call(METHOD_NAME.Gacha, { Id = gaChaId, Times = count }, function(res) if res.Code ~= XCode.Success then XUiManager.TipCode(res.Code) if errorCb then errorCb() end return end XGachaManager.UpdateGachaRewardInfo(res.GridInfoList, gaChaId) XGachaManager.UpdateGachaLog(gaChaId, res.GachaRecordList) TotalGachaTimes[gaChaId] = res.GachaCourseResult.TotalTimes MissTimes[gaChaId] = res.MissTimes local newUnlockGachaId if organizeId then newUnlockGachaId = XGachaManager.DrawUpdateOrganizeStatus(organizeId, gaChaId) end if cb then cb(res.RewardList, newUnlockGachaId) end end) end --- --- 在进入界面的时候请求'organizeId'卡池组里的已售罄池子,以及最新解锁的池子的奖励信息 function XGachaManager.GetGachaOrganizeInfoRequest(organizeId, cb) XNetwork.Call(METHOD_NAME.GetGachaOrganizeInfo, { OrganizeId = organizeId }, function(res) if res.Code ~= XCode.Success then XUiManager.TipCode(res.Code) return end XGachaManager.UpdateGachaRewardInfo(res.GridInfoList, organizeId) XGachaManager.UpdateGachaLog(res.CurrentId, res.GachaRecordList) XGachaManager.OpenUpdateOrganizeStatus(organizeId, res.CurrentId, res.OutOfStockIdList) if cb then cb(res.CurrentId) end end) end --------------------------------------------Organize卡池状态相关------------------------------------------------------ --- --- 进入界面时更新卡池组的卡池状态 --- --- 'newestGachaId'为最新解锁的卡池Id,它前面的卡池状态为正常或售罄,后面的卡池状态为锁定 --- 'outSoldList'为已售罄卡池Id数组,这样就不用发送所有卡池的奖励信息,就能知道所有卡池的状态 function XGachaManager.OpenUpdateOrganizeStatus(organizeId, newestGachaId, outSoldList) if not GachaOrganizeStatus[organizeId] then GachaOrganizeStatus[organizeId] = {} end -- 设置已售罄卡池 for _, gachaId in ipairs(outSoldList) do if not GachaOrganizeStatus[organizeId][gachaId] then GachaOrganizeStatus[organizeId][gachaId] = XGachaConfigs.OrganizeGachaStatus.SoldOut end -- 进入界面时,客户端缓存的售馨卡池与服务器下发的售罄卡池不同步 if GachaOrganizeStatus[organizeId][gachaId] ~= XGachaConfigs.OrganizeGachaStatus.SoldOut then XLog.Error(string.format("XGachaManager.UpdateOrganizeGachaStatus函数错误,服务器下发的最新卡池Id为%s,卡池组%s的卡池%s状态与服务器不同步,客户端的为未售罄状态", tostring(newestGachaId), tostring(organizeId), tostring(gachaId))) GachaOrganizeStatus[organizeId][gachaId] = XGachaConfigs.OrganizeGachaStatus.SoldOut end end local organizeGachaIdList = XGachaConfigs.GetOrganizeGahcaIdList(organizeId) -- organizeId组的所有gachaId数组,已根据Sort排序 local newestGachaIndex = XGachaConfigs.GetOrganizeIndex(organizeId, newestGachaId) -- 最新解锁卡池在organizeGachaIdList数组里的序号 if not newestGachaIndex then return end -- 最新解锁卡池前面的卡池为已解锁或售罄,后面的为锁定 for index, gachaId in ipairs(organizeGachaIdList) do if index <= newestGachaIndex then if not GachaOrganizeStatus[organizeId][gachaId] then GachaOrganizeStatus[organizeId][gachaId] = XGachaConfigs.OrganizeGachaStatus.Normal end -- 进入界面时,客户端缓存的 newestGachaId卡池前面的卡池的状态 为锁定,说明状态与服务器不同步 if GachaOrganizeStatus[organizeId][gachaId] == XGachaConfigs.OrganizeGachaStatus.Lock then XLog.Error(string.format("XGachaManager.UpdateOrganizeGachaStatus函数错误,服务器下发的最新卡池Id为%s,卡池组%s的卡池%s状态与服务器不同步,客户端的为上锁状态", tostring(newestGachaId), tostring(organizeId), tostring(gachaId))) GachaOrganizeStatus[organizeId][gachaId] = XGachaConfigs.OrganizeGachaStatus.Normal end else if not GachaOrganizeStatus[organizeId][gachaId] then GachaOrganizeStatus[organizeId][gachaId] = XGachaConfigs.OrganizeGachaStatus.Lock end -- 进入界面时,客户端缓存的 newestGachaId卡池后面的卡池的状态为正常,说明状态与服务器不同步 if GachaOrganizeStatus[organizeId][gachaId] == XGachaConfigs.OrganizeGachaStatus.Normal then XLog.Error(string.format("XGachaManager.UpdateOrganizeGachaStatus函数错误,服务器下发的最新卡池Id为%s,卡池组%s的卡池%s状态与服务器不同步,客户端的为正常状态", tostring(newestGachaId), tostring(organizeId), tostring(gachaId))) GachaOrganizeStatus[organizeId][gachaId] = XGachaConfigs.OrganizeGachaStatus.Lock end end end end --- 抽卡后更新卡池组的卡池状态 --- 如果解锁了新卡池则返回该卡池Id ---@return number function XGachaManager.DrawUpdateOrganizeStatus(organizeId, DrawingGachaId) if not GachaOrganizeStatus[organizeId] then XLog.Error(string.format("XGachaManager.DrawUpdateOrganizeStatus函数错误,卡池组%s的状态数据为空", tostring(organizeId))) GachaOrganizeStatus[organizeId] = {} end local isSoldOutRare = true -- 特殊奖励是否售罄 local isSoldOut = true -- 全部奖励是否售罄 local groupIdList = {} -- 是否无限次数 if IsInfinite[DrawingGachaId] then isSoldOut = false else -- 找出DrawingGachaId的奖励 local gachaCfg = XGachaConfigs.GetGachas() for _, groupId in pairs(gachaCfg[DrawingGachaId].GroupId) do table.insert(groupIdList, groupId) end for _, v in pairs(GachaRewardInfos[DrawingGachaId]) do -- 是否属于DrawingGachaId的奖励组 for _, groupId in pairs(groupIdList) do if v.GroupId == groupId and v.CurCount ~= 0 then isSoldOut = false if v.Rare then isSoldOutRare = false end break end end end end if isSoldOut then GachaOrganizeStatus[organizeId][DrawingGachaId] = XGachaConfigs.OrganizeGachaStatus.SoldOut end local isUnlockNext if isSoldOutRare then -- 是否解锁了新的卡池62504 local nextGachaStatus, nextGachaId = XGachaManager.GetOrganizeNextGachaStatus(organizeId, DrawingGachaId) if nextGachaStatus and nextGachaId then if nextGachaStatus == XGachaConfigs.OrganizeGachaStatus.Lock then GachaOrganizeStatus[organizeId][nextGachaId] = XGachaConfigs.OrganizeGachaStatus.Normal isUnlockNext = nextGachaId end end end return isUnlockNext end --- --- 获取''organizeId'卡池组内'gachaId'卡池的状态 function XGachaManager.GetOrganizeGachaStatus(organizeId, gachaId) if not gachaId or gachaId == 0 then return end if GachaOrganizeStatus[organizeId] then if GachaOrganizeStatus[organizeId][gachaId] then return GachaOrganizeStatus[organizeId][gachaId] else XLog.Error(string.format("XGachaManager.GetOrganizeGachaStatus函数错误,卡池%s的状态数据为空", gachaId)) end else XLog.Error(string.format("XGachaManager.GetOrganizeGachaStatus函数错误,卡池组%s的状态数据为空", organizeId)) end return XGachaConfigs.OrganizeGachaStatus.Lock end --- --- 获取''organizeId'卡池组内'gachaId'前一个卡池的状态与Id --- --- 如果'gachaId'是第一个卡池,则返回nil function XGachaManager.GetOrganizePreGachaStatus(organizeId, gachaId) local preGachaId = XGachaConfigs.GetOrganizePreGachaId(organizeId, gachaId) local status = XGachaManager.GetOrganizeGachaStatus(organizeId, preGachaId) if status then return status, preGachaId end end --- --- 获取''organizeId'卡池组内'gachaId'后一个卡池的状态与Id --- --- 如果'gachaId'是最后一个卡池,则返回nil function XGachaManager.GetOrganizeNextGachaStatus(organizeId, gachaId) local nextGachaId = XGachaConfigs.GetOrganizeNextGachaId(organizeId, gachaId) local status = XGachaManager.GetOrganizeGachaStatus(organizeId, nextGachaId) if status then return status, nextGachaId end end function XGachaManager.BuyTicket(gachaId, buyCount, ticketKey, cb) XNetwork.Call(METHOD_NAME.GachaItemExchangeRequest, { Id = gachaId, ExchangeNum = buyCount, SelectIndex = ticketKey }, function(res) if res.Code ~= XCode.Success then XUiManager.TipCode(res.Code) return end CurExchangeItemCount[gachaId] = res.CurExchangeItemCount local reward = XRewardManager.CreateRewardGoodsByTemplate({ TemplateId = res.GainItemId, Count = res.GainItemCount }) if cb then cb({ reward }) end end) end -------------------------------------------------------------------------------------------------------------------- XGachaManager.Init() return XGachaManager end