AbsLotteryCardLogic.lua 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. --新商业化活动——秘境翻牌
  2. --db
  3. --[=[
  4. human.db.absAct[id] = {
  5. freeCnt = nil, 当日免费抽取次数,为0时表示没有,为其他表示可以免费抽取一次
  6. normalAwardIdxTbl --普通奖励,value为配置表的Index
  7. normalAwardRecord = { --普通奖励获得记录,key为 normalAwardIdxTbl 中的索引,有值则表示获得了
  8. [1] = '1',
  9. [3] = '1',
  10. },
  11. lineAwardIdxTbl= = nil, --当前横排(上方)大奖Index列表, value为配置表的Index
  12. lineAwardRecord = { --横排大奖(上方)获得记录,key为 lineAwardRecord 中的索引,有值则表示获得了
  13. [1] = '1',
  14. [3] = '1',
  15. },
  16. rowAwardIdxTbl = nil, --当前竖排(右边)大奖Index列表, value为配置表的Index
  17. rowAwardRecord = { --竖排大奖(右边)获得记录,key为 rowAwardIdxTbl 中的索引,有值则表示获得了
  18. [1] = '1',
  19. [3] = '1',
  20. }
  21. }
  22. ]=]--
  23. local Msg = require("core.Msg")
  24. local Grid = require("bag.Grid")
  25. local BagLogic = require("bag.BagLogic")
  26. local AbsActLogic = require("absAct.AbsActLogic")
  27. local Broadcast = require("broadcast.Broadcast")
  28. local Lang = require("common.Lang")
  29. local AbsActExcel = require("excel.absAct")
  30. local YunYingLogic = require("yunying.YunYingLogic")
  31. local ItemDefine = require("bag.ItemDefine")
  32. local LOGTAG = "AbsLotteryCardLogic" --日志标识
  33. local LOTTERYCOSTTYPE = ItemDefine.ITEM_ZUANSHI_ID --抽奖消耗道具ID
  34. local LOTTERY1COSTCNT = 400 --单抽消耗的数量
  35. local LOTTERY10COSTCNT = 4000 --十连消耗的数量
  36. local RESETCOSTCNT = 1000 --重置需要消耗的数量
  37. local FOUR = 4
  38. --是否是GM模式, 为true时, 每次抽取只会获得没有抽到的奖励, 抽够一定次数, 则一定会获得所有奖励
  39. local isGmMode = false
  40. --生成奖励
  41. local function generateAwardByWeight(awardConfig, awardNum)
  42. local totalWeight = 0
  43. for _, v in pairs(awardConfig) do
  44. totalWeight = totalWeight + v[3]
  45. end
  46. local weight, randWeight = 0, 0
  47. local awardIdxTbl = {}
  48. for i=1, awardNum do
  49. weight = 0
  50. randWeight = math.random(0, totalWeight)
  51. for idx, cfg in ipairs(awardConfig) do
  52. weight = weight + cfg[3]
  53. if randWeight <= weight then
  54. awardIdxTbl[i] = idx
  55. break
  56. end
  57. end
  58. end
  59. return awardIdxTbl
  60. end
  61. --封装奖励协议数据结构
  62. local function populateAwardMsg(net, awardCfg, awardRecordData, indexTbl)
  63. net[0] = #indexTbl
  64. for k, awardIdx in ipairs(indexTbl) do
  65. net[k].idx = k
  66. net[k].getState = 0
  67. if awardRecordData and awardRecordData[k] then
  68. net[k].getState = 1
  69. end
  70. local itemInfo = awardCfg[awardIdx]
  71. Grid.makeItem(net[k].item, itemInfo[1], itemInfo[2])
  72. end
  73. end
  74. --封装协议数据结构
  75. local function populateMsg(msgRet, actData)
  76. msgRet.freeCnt = 0
  77. local freeCnt = actData.freeCnt
  78. if not freeCnt or freeCnt ~= 0 then
  79. msgRet.freeCnt = 1
  80. end
  81. local config = AbsActExcel.AbsLotteryCardLogic
  82. --普通奖励
  83. populateAwardMsg(msgRet.normalAwardInfo, config[1].award, actData.normalAwardRecord, actData.normalAwardIdxTbl)
  84. --横排大奖
  85. populateAwardMsg(msgRet.lineAwardInfo, config[2].award, actData.lineAwardRecord, actData.lineAwardIdxTbl)
  86. --竖排大奖
  87. populateAwardMsg(msgRet.rowAwardInfo, config[3].award, actData.rowAwardRecord, actData.rowAwardIdxTbl)
  88. end
  89. --计算一个值在4 x 4 矩阵中 横排和竖排的位置
  90. local function calcLineRowPos(num)
  91. local linePos, rowPos = 0, 0
  92. rowPos = num % FOUR
  93. if rowPos == 0 then
  94. rowPos = FOUR
  95. end
  96. linePos = math.ceil(num / FOUR)
  97. return linePos, rowPos
  98. end
  99. --判断是否获得横排(上方)大奖
  100. local function isGetLineAward(pos, awardRecordData)
  101. -- if pos % FOUR == 0 then
  102. -- pos = FOUR
  103. -- end
  104. local isGet = true
  105. for i=1, FOUR do
  106. if not awardRecordData[pos] then
  107. isGet = false
  108. break
  109. end
  110. pos = pos + FOUR
  111. end
  112. return isGet
  113. end
  114. --判断是否获得竖排(右边)大奖
  115. local function isGetRowAward(pos, awardRecordData)
  116. local isGet = true
  117. local startPos = (pos- 1) * FOUR + 1
  118. for i=1, FOUR do
  119. if not awardRecordData[startPos] then
  120. isGet = false
  121. break
  122. end
  123. startPos = startPos + 1
  124. end
  125. return isGet
  126. end
  127. --是否需要重置奖励
  128. local function isReset(lineTbl, rowTbl)
  129. local lineNum, rowNum = 0,0
  130. for _,_ in pairs(lineTbl or {}) do
  131. lineNum = lineNum + 1
  132. end
  133. if lineNum < FOUR then
  134. return false
  135. end
  136. for _,_ in pairs(rowTbl or {}) do
  137. rowNum = rowNum + 1
  138. end
  139. if rowNum < FOUR then
  140. return false
  141. end
  142. return true
  143. end
  144. --随机普通奖励,返回的是normalAwardIdxTbl的key
  145. local function randAwardIdx(normalAwardIdxTbl, normalAwardRecord, normalAwardCfg)
  146. local weight, randIdx, randWeight, totalWeight = 0,0,0,0
  147. local len = 0
  148. local subAwardIdxVec = {}
  149. for i, cfgIndex in ipairs(normalAwardIdxTbl) do
  150. if isGmMode and normalAwardRecord then --GM模式随机,剔除掉已经获得的奖励, 在剩下奖励中随机
  151. if not normalAwardRecord[i] then
  152. len = len + 1
  153. totalWeight = totalWeight + normalAwardCfg[cfgIndex][3]
  154. subAwardIdxVec[len] = {normalAwardCfg[cfgIndex][3], i}
  155. end
  156. else
  157. len = len + 1
  158. totalWeight = totalWeight + normalAwardCfg[cfgIndex][3]
  159. subAwardIdxVec[len] = {normalAwardCfg[cfgIndex][3], i}
  160. end
  161. end
  162. randWeight = math.random(0, totalWeight)
  163. for _, data in ipairs(subAwardIdxVec) do
  164. weight = weight + data[1]
  165. if randWeight <= weight then
  166. randIdx = data[2]
  167. break
  168. end
  169. end
  170. return randIdx
  171. end
  172. --重置奖励
  173. local function reset(actData)
  174. actData.normalAwardRecord = nil
  175. actData.lineAwardRecord = nil
  176. actData.rowAwardRecord = nil
  177. local config = AbsActExcel.AbsLotteryCardLogic
  178. actData.lineAwardIdxTbl = generateAwardByWeight(config[2].award, FOUR)
  179. actData.rowAwardIdxTbl = generateAwardByWeight(config[3].award, FOUR)
  180. end
  181. --抽奖
  182. local function lottery(human, actData, lotteryCnt, awardVec)
  183. local config = AbsActExcel.AbsLotteryCardLogic
  184. local normalAwardCfg = config[1].award
  185. local normalAwardRecord = actData.normalAwardRecord
  186. local normalAwardIdxTbl = actData.normalAwardIdxTbl
  187. local subCnt = -1
  188. local randPosList = {}
  189. --local isRepeat = false
  190. local repeatPosList = {}
  191. local getNormalAwardCnt = 0
  192. if normalAwardRecord then
  193. for _,_ in pairs(normalAwardRecord) do
  194. getNormalAwardCnt = getNormalAwardCnt + 1
  195. end
  196. end
  197. for i=1, lotteryCnt do
  198. local randPos = randAwardIdx(normalAwardIdxTbl, normalAwardRecord, normalAwardCfg)
  199. randPosList[#randPosList+1] = randPos
  200. local cfgIndex = normalAwardIdxTbl[randPos]
  201. local itemInfo = normalAwardCfg[cfgIndex]
  202. awardVec[#awardVec+1] = {itemInfo[1], itemInfo[2]}
  203. getNormalAwardCnt = getNormalAwardCnt + 1
  204. --当前抽得普通奖励大于4个且之前未抽到过该位置的奖励
  205. if getNormalAwardCnt >= FOUR and not normalAwardRecord[randPos] then
  206. local linePos, rowPos = calcLineRowPos(randPos)
  207. local lineAwardRecord = actData.lineAwardRecord
  208. local rowAwardRecord = actData.rowAwardRecord
  209. --更新普通奖励获得记录
  210. normalAwardRecord[randPos] = '1'
  211. local isGetLine, isGetRow = false, false
  212. --是否获得横排(上方的)大奖
  213. if not lineAwardRecord or not lineAwardRecord[rowPos] then
  214. isGetLine = isGetLineAward(rowPos, normalAwardRecord)
  215. if isGetLine then
  216. local cfgIdx = actData.lineAwardIdxTbl[rowPos]
  217. local lineAwardItem = config[2].award[cfgIdx]
  218. awardVec[#awardVec+1] = {lineAwardItem[1], lineAwardItem[2]}
  219. actData.lineAwardRecord = actData.lineAwardRecord or {}
  220. actData.lineAwardRecord[rowPos] = '1'
  221. end
  222. end
  223. --是否获得竖排(右方的)大奖
  224. if not rowAwardRecord or not rowAwardRecord[linePos] then
  225. isGetRow = isGetRowAward(linePos, normalAwardRecord)
  226. if isGetRow then
  227. local cfgIdx = actData.rowAwardIdxTbl[linePos]
  228. local rowAwardItem = config[3].award[cfgIdx]
  229. awardVec[#awardVec+1] = {rowAwardItem[1], rowAwardItem[2]}
  230. actData.rowAwardRecord = actData.rowAwardRecord or {}
  231. actData.rowAwardRecord[linePos] = '1'
  232. end
  233. end
  234. --是否所有奖励都领完, 需要重置奖励
  235. if isGetLine or isGetRow then
  236. if isReset(actData.lineAwardRecord, actData.rowAwardRecord) then
  237. reset(actData)
  238. subCnt = lotteryCnt - i
  239. break
  240. end
  241. end
  242. else
  243. if normalAwardRecord and normalAwardRecord[randPos] then
  244. --isRepeat = true
  245. repeatPosList[#repeatPosList+1] = randPos
  246. else
  247. normalAwardRecord = normalAwardRecord or {}
  248. normalAwardRecord[randPos] = '1'
  249. actData.normalAwardRecord = normalAwardRecord
  250. end
  251. end
  252. end
  253. return randPosList, repeatPosList, subCnt
  254. end
  255. --GM接口,设置本活动是否使用GM模式, val > 0 表示使用GM模式
  256. function SetMode(val)
  257. if val > 0 then
  258. isGmMode = true
  259. else
  260. isGmMode = false
  261. end
  262. end
  263. function isOpen(human, YYInfo, funcConfig)
  264. local state, endTime, startTime = AbsActLogic.isStarted(human, funcConfig.funcID)
  265. return state, endTime, startTime
  266. end
  267. function isActive(human, YYInfo, funcConfig)
  268. local state = isOpen(human, YYInfo, funcConfig)
  269. return not state
  270. end
  271. --红点判断
  272. function isRed(human, YYInfo, funcConfig)
  273. local actData = human.db.absAct[funcConfig.funcID]
  274. if not actData then
  275. return false
  276. end
  277. local freeCnt = actData.freeCnt
  278. if freeCnt and freeCnt == 0 then
  279. return false
  280. end
  281. return true
  282. end
  283. --跨天函数
  284. function updateDaily(human, id)
  285. local state = AbsActLogic.isStarted(human, id)
  286. if not state then
  287. return
  288. end
  289. local actData = human.db.absAct[id]
  290. if not actData then
  291. return
  292. end
  293. actData.freeCnt = 1
  294. --红点刷新
  295. YunYingLogic.sendBanner(human)
  296. local config = AbsActExcel.absActivity[id]
  297. YunYingLogic.sendGroupUpdate(YYInfo[id], human, config.panelID)
  298. end
  299. --查询
  300. function Query(human, id)
  301. local state = AbsActLogic.isStarted(human, id)
  302. if not state then
  303. return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
  304. end
  305. local actData = human.db.absAct[id]
  306. if not actData then
  307. return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
  308. end
  309. local msgRet = Msg.gc.GC_LOTTERYCARD_QUERY
  310. local config = AbsActExcel.AbsLotteryCardLogic
  311. if not actData.lineAwardIdxTbl then
  312. actData.lineAwardIdxTbl = generateAwardByWeight(config[2].award, FOUR)
  313. actData.rowAwardIdxTbl = generateAwardByWeight(config[3].award, FOUR)
  314. actData.normalAwardIdxTbl = generateAwardByWeight(config[1].award, 16)
  315. end
  316. populateMsg(msgRet, actData)
  317. Grid.makeItem(msgRet.lottery1Spend, LOTTERYCOSTTYPE, LOTTERY1COSTCNT)
  318. Grid.makeItem(msgRet.lottery10Spend, LOTTERYCOSTTYPE, LOTTERY10COSTCNT)
  319. Grid.makeItem(msgRet.resetSpend, LOTTERYCOSTTYPE, RESETCOSTCNT)
  320. Msg.send(msgRet, human.fd)
  321. end
  322. --抽奖, 可抽到重复奖励, 某行/列的普通奖励都获得时,自动获得对应行列的大奖,所有普通和大奖都获得时,重置奖励
  323. function Lottery(human, id, lotteryCnt)
  324. local state = AbsActLogic.isStarted(human, id)
  325. if not state then
  326. return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
  327. end
  328. local actData = human.db.absAct[id]
  329. if not actData then
  330. return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
  331. end
  332. if lotteryCnt ~= 1 and lotteryCnt ~= 10 then
  333. return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
  334. end
  335. local itemSpendCnt = LOTTERY1COSTCNT
  336. if lotteryCnt == 1 then
  337. if not actData.freeCnt or actData.freeCnt ~= 0 then
  338. itemSpendCnt = 0
  339. actData.freeCnt = 0
  340. end
  341. else
  342. itemSpendCnt = LOTTERY10COSTCNT
  343. end
  344. if itemSpendCnt > 0 then
  345. if BagLogic.getItemCnt(human, LOTTERYCOSTTYPE) < itemSpendCnt then
  346. return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH)
  347. end
  348. --扣消耗
  349. BagLogic.delItem(human, LOTTERYCOSTTYPE, itemSpendCnt, LOGTAG)
  350. end
  351. --抽奖
  352. local awardVec = {}
  353. local randPosList, repeatPosList, subCnt = lottery(human, actData, lotteryCnt, awardVec)
  354. --全部奖励已获得,还有抽奖次数,需要先重置奖励
  355. if subCnt > 0 then
  356. local msgRet = Msg.gc.GC_LOTTERYCARD_RESET
  357. msgRet.isActive = 1
  358. populateMsg(msgRet, actData)
  359. Msg.send(msgRet, human.fd)
  360. randPosList, repeatPosList = lottery(human, actData, subCnt, awardVec)
  361. end
  362. --发放抽到的道具
  363. BagLogic.addItemList(human, awardVec, LOGTAG)
  364. local config = AbsActExcel.AbsLotteryCardLogic
  365. local awardCfg = config[1].award
  366. local msgRet = Msg.gc.GC_LOTTERYCARD_LOTTERY
  367. local normalAwardInfo = msgRet.normalAwardInfo
  368. normalAwardInfo[0] = #randPosList
  369. --小奖卡牌重复被翻到后,更换该牌的奖励
  370. local normalAwardIdxTbl = actData.normalAwardIdxTbl
  371. local newAwardPosList = generateAwardByWeight(config[1].award, #randPosList)
  372. for i, dbIdx in ipairs(repeatPosList) do
  373. --print(string.format("重复随机到奖励位置: %d, 新奖励在配置中位置: %d\n", dbIdx, newAwardPosList[i]))
  374. local cfgIdx = newAwardPosList[i]
  375. normalAwardIdxTbl[dbIdx] = cfgIdx
  376. end
  377. for i, dbIdx in ipairs(randPosList) do
  378. normalAwardInfo[i].idx = dbIdx
  379. normalAwardInfo[i].getState = 1
  380. local cfgIdx = normalAwardIdxTbl[dbIdx]
  381. local itemInfo = awardCfg[cfgIdx]
  382. Grid.makeItem(normalAwardInfo[i].item, itemInfo[1], itemInfo[2])
  383. end
  384. --下发数据
  385. msgRet.isRepeat = #repeatPosList > 0 and 1 or 0
  386. msgRet.freeCnt = 0
  387. local freeCnt = actData.freeCnt
  388. if not freeCnt or freeCnt ~= 0 then
  389. msgRet.freeCnt = 1
  390. end
  391. --普通奖励
  392. --populateAwardMsg(msgRet.normalAwardInfo, config[1].award, actData.normalAwardRecord, actData.normalAwardIdxTbl)
  393. --横排大奖
  394. populateAwardMsg(msgRet.lineAwardInfo, config[2].award, actData.lineAwardRecord, actData.lineAwardIdxTbl)
  395. --竖排大奖
  396. populateAwardMsg(msgRet.rowAwardInfo, config[3].award, actData.rowAwardRecord, actData.rowAwardIdxTbl)
  397. Msg.send(msgRet, human.fd)
  398. -- for i, idx in ipairs(randIds) do
  399. -- local cfgIdx = newAwardPosList[i]
  400. -- normalAwardIdxTbl[idx] = cfgIdx
  401. -- end
  402. --全部奖励已获得,没有抽奖次数,最后重置奖励
  403. if subCnt == 0 then
  404. local msgRet = Msg.gc.GC_LOTTERYCARD_RESET
  405. msgRet.isActive = 1
  406. populateMsg(msgRet, actData)
  407. Msg.send(msgRet, human.fd)
  408. end
  409. --更新红点
  410. if itemSpendCnt <= 0 then
  411. YunYingLogic.sendBanner(human)
  412. local config = AbsActExcel.absActivity[id]
  413. YunYingLogic.sendGroupUpdate(YYInfo[id], human, config.panelID)
  414. end
  415. end
  416. --重置
  417. function ResetAward(human, id)
  418. local state = AbsActLogic.isStarted(human, id)
  419. if not state then
  420. return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
  421. end
  422. local actData = human.db.absAct[id]
  423. if not actData then
  424. return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
  425. end
  426. if BagLogic.getItemCnt(human, LOTTERYCOSTTYPE) < RESETCOSTCNT then
  427. return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH)
  428. end
  429. --扣消耗
  430. BagLogic.delItem(human, LOTTERYCOSTTYPE, RESETCOSTCNT, LOGTAG)
  431. --重置
  432. reset(actData)
  433. --下发数据
  434. local msgRet = Msg.gc.GC_LOTTERYCARD_RESET
  435. msgRet.isActive = 0
  436. populateMsg(msgRet, actData)
  437. Msg.send(msgRet, human.fd)
  438. end