--新商业化活动——秘境翻牌 --db --[=[ human.db.absAct[id] = { freeCnt = nil, 当日免费抽取次数,为0时表示没有,为其他表示可以免费抽取一次 normalAwardIdxTbl --普通奖励,value为配置表的Index normalAwardRecord = { --普通奖励获得记录,key为 normalAwardIdxTbl 中的索引,有值则表示获得了 [1] = '1', [3] = '1', }, lineAwardIdxTbl= = nil, --当前横排(上方)大奖Index列表, value为配置表的Index lineAwardRecord = { --横排大奖(上方)获得记录,key为 lineAwardRecord 中的索引,有值则表示获得了 [1] = '1', [3] = '1', }, rowAwardIdxTbl = nil, --当前竖排(右边)大奖Index列表, value为配置表的Index rowAwardRecord = { --竖排大奖(右边)获得记录,key为 rowAwardIdxTbl 中的索引,有值则表示获得了 [1] = '1', [3] = '1', } } ]=]-- local Msg = require("core.Msg") local Grid = require("bag.Grid") local BagLogic = require("bag.BagLogic") local AbsActLogic = require("absAct.AbsActLogic") local Broadcast = require("broadcast.Broadcast") local Lang = require("common.Lang") local AbsActExcel = require("excel.absAct") local YunYingLogic = require("yunying.YunYingLogic") local ItemDefine = require("bag.ItemDefine") local TriggerDefine = require("trigger.TriggerDefine") local TriggerLogic = require("trigger.TriggerLogic") local CycleActivityLogic = require("yunying.CycleActivity") local LOGTAG = "AbsLotteryCardLogic" --日志标识 local LOTTERYCOSTTYPE = ItemDefine.ITEM_ZUANSHI_ID --抽奖消耗道具ID local LOTTERY1COSTCNT = 400 --单抽消耗的数量 local LOTTERY10COSTCNT = 4000 --十连消耗的数量 local RESETCOSTCNT = 1000 --重置需要消耗的数量 local FOUR = 4 --是否是GM模式, 为true时, 每次抽取只会获得没有抽到的奖励, 抽够一定次数, 则一定会获得所有奖励 local isGmMode = false --生成奖励 local function generateAwardByWeight(awardConfig, awardNum) local totalWeight = 0 for _, v in pairs(awardConfig) do totalWeight = totalWeight + v[3] end local weight, randWeight = 0, 0 local awardIdxTbl = {} for i=1, awardNum do weight = 0 randWeight = math.random(0, totalWeight) for idx, cfg in ipairs(awardConfig) do weight = weight + cfg[3] if randWeight <= weight then awardIdxTbl[i] = idx break end end end return awardIdxTbl end --封装奖励协议数据结构 local function populateAwardMsg(net, awardCfg, awardRecordData, indexTbl) net[0] = #indexTbl for k, awardIdx in ipairs(indexTbl) do net[k].idx = k net[k].getState = 0 if awardRecordData and awardRecordData[k] then net[k].getState = 1 end local itemInfo = awardCfg[awardIdx] Grid.makeItem(net[k].item, itemInfo[1], itemInfo[2]) end end --封装协议数据结构 local function populateMsg(msgRet, actData) msgRet.freeCnt = 0 local freeCnt = actData.freeCnt if not freeCnt or freeCnt ~= 0 then msgRet.freeCnt = 1 end local config = AbsActExcel.AbsLotteryCardLogic --普通奖励 populateAwardMsg(msgRet.normalAwardInfo, config[1].award, actData.normalAwardRecord, actData.normalAwardIdxTbl) --横排大奖 populateAwardMsg(msgRet.lineAwardInfo, config[2].award, actData.lineAwardRecord, actData.lineAwardIdxTbl) --竖排大奖 populateAwardMsg(msgRet.rowAwardInfo, config[3].award, actData.rowAwardRecord, actData.rowAwardIdxTbl) end --计算一个值在4 x 4 矩阵中 横排和竖排的位置 local function calcLineRowPos(num) local linePos, rowPos = 0, 0 rowPos = num % FOUR if rowPos == 0 then rowPos = FOUR end linePos = math.ceil(num / FOUR) return linePos, rowPos end --判断是否获得横排(上方)大奖 local function isGetLineAward(pos, awardRecordData) -- if pos % FOUR == 0 then -- pos = FOUR -- end local isGet = true for i=1, FOUR do if not awardRecordData[pos] then isGet = false break end pos = pos + FOUR end return isGet end --判断是否获得竖排(右边)大奖 local function isGetRowAward(pos, awardRecordData) local isGet = true local startPos = (pos- 1) * FOUR + 1 for i=1, FOUR do if not awardRecordData[startPos] then isGet = false break end startPos = startPos + 1 end return isGet end --是否需要重置奖励 local function isReset(lineTbl, rowTbl) local lineNum, rowNum = 0,0 for _,_ in pairs(lineTbl or {}) do lineNum = lineNum + 1 end if lineNum < FOUR then return false end for _,_ in pairs(rowTbl or {}) do rowNum = rowNum + 1 end if rowNum < FOUR then return false end return true end --随机普通奖励,返回的是normalAwardIdxTbl的key local function randAwardIdx(normalAwardIdxTbl, normalAwardRecord, normalAwardCfg) local weight, randIdx, randWeight, totalWeight = 0,0,0,0 local len = 0 local subAwardIdxVec = {} for i, cfgIndex in ipairs(normalAwardIdxTbl) do if isGmMode and normalAwardRecord then --GM模式随机,剔除掉已经获得的奖励, 在剩下奖励中随机 if not normalAwardRecord[i] then len = len + 1 totalWeight = totalWeight + normalAwardCfg[cfgIndex][3] subAwardIdxVec[len] = {normalAwardCfg[cfgIndex][3], i} end else len = len + 1 totalWeight = totalWeight + normalAwardCfg[cfgIndex][3] subAwardIdxVec[len] = {normalAwardCfg[cfgIndex][3], i} end end randWeight = math.random(0, totalWeight) for _, data in ipairs(subAwardIdxVec) do weight = weight + data[1] if randWeight <= weight then randIdx = data[2] break end end return randIdx end --重置奖励 local function reset(actData) actData.normalAwardRecord = nil actData.lineAwardRecord = nil actData.rowAwardRecord = nil local config = AbsActExcel.AbsLotteryCardLogic actData.lineAwardIdxTbl = generateAwardByWeight(config[2].award, FOUR) actData.rowAwardIdxTbl = generateAwardByWeight(config[3].award, FOUR) end --抽奖 local function lottery(human, actData, lotteryCnt, awardVec) local config = AbsActExcel.AbsLotteryCardLogic local normalAwardCfg = config[1].award local normalAwardRecord = actData.normalAwardRecord local normalAwardIdxTbl = actData.normalAwardIdxTbl local subCnt = -1 local randPosList = {} --local isRepeat = false local repeatPosList = {} local getNormalAwardCnt = 0 if normalAwardRecord then for _,_ in pairs(normalAwardRecord) do getNormalAwardCnt = getNormalAwardCnt + 1 end end for i=1, lotteryCnt do local randPos = randAwardIdx(normalAwardIdxTbl, normalAwardRecord, normalAwardCfg) randPosList[#randPosList+1] = randPos local cfgIndex = normalAwardIdxTbl[randPos] local itemInfo = normalAwardCfg[cfgIndex] awardVec[#awardVec+1] = {itemInfo[1], itemInfo[2]} getNormalAwardCnt = getNormalAwardCnt + 1 --当前抽得普通奖励大于4个且之前未抽到过该位置的奖励 if getNormalAwardCnt >= FOUR and not normalAwardRecord[randPos] then local linePos, rowPos = calcLineRowPos(randPos) local lineAwardRecord = actData.lineAwardRecord local rowAwardRecord = actData.rowAwardRecord --更新普通奖励获得记录 normalAwardRecord[randPos] = '1' local isGetLine, isGetRow = false, false --是否获得横排(上方的)大奖 if not lineAwardRecord or not lineAwardRecord[rowPos] then isGetLine = isGetLineAward(rowPos, normalAwardRecord) if isGetLine then local cfgIdx = actData.lineAwardIdxTbl[rowPos] local lineAwardItem = config[2].award[cfgIdx] awardVec[#awardVec+1] = {lineAwardItem[1], lineAwardItem[2]} actData.lineAwardRecord = actData.lineAwardRecord or {} actData.lineAwardRecord[rowPos] = '1' end end --是否获得竖排(右方的)大奖 if not rowAwardRecord or not rowAwardRecord[linePos] then isGetRow = isGetRowAward(linePos, normalAwardRecord) if isGetRow then local cfgIdx = actData.rowAwardIdxTbl[linePos] local rowAwardItem = config[3].award[cfgIdx] awardVec[#awardVec+1] = {rowAwardItem[1], rowAwardItem[2]} actData.rowAwardRecord = actData.rowAwardRecord or {} actData.rowAwardRecord[linePos] = '1' end end --是否所有奖励都领完, 需要重置奖励 if isGetLine or isGetRow then if isReset(actData.lineAwardRecord, actData.rowAwardRecord) then reset(actData) subCnt = lotteryCnt - i break end end else if normalAwardRecord and normalAwardRecord[randPos] then --isRepeat = true repeatPosList[#repeatPosList+1] = randPos else normalAwardRecord = normalAwardRecord or {} normalAwardRecord[randPos] = '1' actData.normalAwardRecord = normalAwardRecord end end end return randPosList, repeatPosList, subCnt end --GM接口,设置本活动是否使用GM模式, val > 0 表示使用GM模式 function SetMode(val) if val > 0 then isGmMode = true else isGmMode = false end end function isOpen(human, YYInfo, funcConfig) -- local state, endTime, startTime = AbsActLogic.isStarted(human, funcConfig.funcID) local state, endTime, startTime = CycleActivityLogic.isStarted(human, funcConfig.funcID) return state, endTime, startTime end function isActive(human, YYInfo, funcConfig) local state = isOpen(human, YYInfo, funcConfig) return not state end --红点判断 function isRed(human, YYInfo, funcConfig) local actData = human.db.absAct[funcConfig.funcID] if not actData then return false end local freeCnt = actData.freeCnt if freeCnt and freeCnt == 0 then return false end return true end --跨天函数 function updateDaily(human, id) -- local state = AbsActLogic.isStarted(human, id) local state = CycleActivityLogic.isStarted(human, id) if not state then return end local actData = human.db.absAct[id] if not actData then return end actData.freeCnt = 1 --红点刷新 YunYingLogic.sendBanner(human) local config = AbsActExcel.absActivity[id] YunYingLogic.sendGroupUpdate(YYInfo[id], human, config.panelID) end --查询 function Query(human, id) -- local state = AbsActLogic.isStarted(human, id) local state = CycleActivityLogic.isStarted(human, id) if not state then return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME) end local actData = human.db.absAct[id] if not actData then return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME) end local msgRet = Msg.gc.GC_LOTTERYCARD_QUERY local config = AbsActExcel.AbsLotteryCardLogic if not actData.lineAwardIdxTbl then actData.lineAwardIdxTbl = generateAwardByWeight(config[2].award, FOUR) actData.rowAwardIdxTbl = generateAwardByWeight(config[3].award, FOUR) actData.normalAwardIdxTbl = generateAwardByWeight(config[1].award, 16) end populateMsg(msgRet, actData) Grid.makeItem(msgRet.lottery1Spend, LOTTERYCOSTTYPE, LOTTERY1COSTCNT) Grid.makeItem(msgRet.lottery10Spend, LOTTERYCOSTTYPE, LOTTERY10COSTCNT) Grid.makeItem(msgRet.resetSpend, LOTTERYCOSTTYPE, RESETCOSTCNT) Msg.send(msgRet, human.fd) end --抽奖, 可抽到重复奖励, 某行/列的普通奖励都获得时,自动获得对应行列的大奖,所有普通和大奖都获得时,重置奖励 function Lottery(human, id, lotteryCnt) -- local state = AbsActLogic.isStarted(human, id) local state = CycleActivityLogic.isStarted(human, id) if not state then return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME) end local actData = human.db.absAct[id] if not actData then return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME) end if lotteryCnt ~= 1 and lotteryCnt ~= 10 then return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR) end local itemSpendCnt = LOTTERY1COSTCNT if lotteryCnt == 1 then if not actData.freeCnt or actData.freeCnt ~= 0 then itemSpendCnt = 0 actData.freeCnt = 0 end else itemSpendCnt = LOTTERY10COSTCNT end if itemSpendCnt > 0 then if BagLogic.getItemCnt(human, LOTTERYCOSTTYPE) < itemSpendCnt then return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH) end --扣消耗 BagLogic.delItem(human, LOTTERYCOSTTYPE, itemSpendCnt, LOGTAG) end --抽奖 local awardVec = {} local randPosList, repeatPosList, subCnt = lottery(human, actData, lotteryCnt, awardVec) --全部奖励已获得,还有抽奖次数,需要先重置奖励 if subCnt > 0 then local msgRet = Msg.gc.GC_LOTTERYCARD_RESET msgRet.isActive = 1 populateMsg(msgRet, actData) Msg.send(msgRet, human.fd) randPosList, repeatPosList = lottery(human, actData, subCnt, awardVec) end --发放抽到的道具 BagLogic.addItemList(human, awardVec, LOGTAG) local config = AbsActExcel.AbsLotteryCardLogic local awardCfg = config[1].award local msgRet = Msg.gc.GC_LOTTERYCARD_LOTTERY local normalAwardInfo = msgRet.normalAwardInfo normalAwardInfo[0] = #randPosList --小奖卡牌重复被翻到后,更换该牌的奖励 local normalAwardIdxTbl = actData.normalAwardIdxTbl local newAwardPosList = generateAwardByWeight(config[1].award, #randPosList) for i, dbIdx in ipairs(repeatPosList) do --print(string.format("重复随机到奖励位置: %d, 新奖励在配置中位置: %d\n", dbIdx, newAwardPosList[i])) local cfgIdx = newAwardPosList[i] normalAwardIdxTbl[dbIdx] = cfgIdx end for i, dbIdx in ipairs(randPosList) do normalAwardInfo[i].idx = dbIdx normalAwardInfo[i].getState = 1 local cfgIdx = normalAwardIdxTbl[dbIdx] local itemInfo = awardCfg[cfgIdx] Grid.makeItem(normalAwardInfo[i].item, itemInfo[1], itemInfo[2]) end --下发数据 msgRet.isRepeat = #repeatPosList > 0 and 1 or 0 msgRet.freeCnt = 0 local freeCnt = actData.freeCnt if not freeCnt or freeCnt ~= 0 then msgRet.freeCnt = 1 end --普通奖励 --populateAwardMsg(msgRet.normalAwardInfo, config[1].award, actData.normalAwardRecord, actData.normalAwardIdxTbl) --横排大奖 populateAwardMsg(msgRet.lineAwardInfo, config[2].award, actData.lineAwardRecord, actData.lineAwardIdxTbl) --竖排大奖 populateAwardMsg(msgRet.rowAwardInfo, config[3].award, actData.rowAwardRecord, actData.rowAwardIdxTbl) Msg.send(msgRet, human.fd) -- for i, idx in ipairs(randIds) do -- local cfgIdx = newAwardPosList[i] -- normalAwardIdxTbl[idx] = cfgIdx -- end --全部奖励已获得,没有抽奖次数,最后重置奖励 if subCnt == 0 then local msgRet = Msg.gc.GC_LOTTERYCARD_RESET msgRet.isActive = 1 populateMsg(msgRet, actData) Msg.send(msgRet, human.fd) -- 代表秘境翻盘完成一次? TriggerLogic.PublishEvent(TriggerDefine.SECRET_REALM, human.db._id, 1) end --更新红点 if itemSpendCnt <= 0 then YunYingLogic.sendBanner(human) local config = AbsActExcel.absActivity[id] YunYingLogic.sendGroupUpdate(YYInfo[id], human, config.panelID) end end --重置 function ResetAward(human, id) -- local state = AbsActLogic.isStarted(human, id) local state = CycleActivityLogic.isStarted(human, id) if not state then return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME) end local actData = human.db.absAct[id] if not actData then return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME) end if BagLogic.getItemCnt(human, LOTTERYCOSTTYPE) < RESETCOSTCNT then return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH) end --扣消耗 BagLogic.delItem(human, LOTTERYCOSTTYPE, RESETCOSTCNT, LOGTAG) --重置 reset(actData) --下发数据 local msgRet = Msg.gc.GC_LOTTERYCARD_RESET msgRet.isActive = 0 populateMsg(msgRet, actData) Msg.send(msgRet, human.fd) end