AbsLotteryCardLogic.lua 17 KB

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