AbsLotteryCardLogic.lua 17 KB

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