ZhuanpanLogic.lua 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980
  1. local Lang = require("common.Lang")
  2. local Msg = require("core.Msg")
  3. local ObjHuman = require("core.ObjHuman")
  4. local ZhuanpanExcel = require("excel.zhuanpan")
  5. local ItemDefine = require("bag.ItemDefine")
  6. local BagLogic = require("bag.BagLogic")
  7. local Grid = require("bag.Grid")
  8. local Broadcast = require("broadcast.Broadcast")
  9. local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
  10. local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
  11. local ItemExcel = require("excel.item").item
  12. local Util = require("common.Util")
  13. local HeroExcel = require("excel.hero").hero
  14. local ChatPaoMaLogic = require("chat.ChatPaoMaLogic")
  15. local VipLogic = require("vip.VipLogic")
  16. local EquipLogic = require("equip.EquipLogic")
  17. local YunYingLogic = require("yunying.YunYingLogic")
  18. local TriggerDefine = require("trigger.TriggerDefine")
  19. local TriggerLogic = require("trigger.TriggerLogic")
  20. local WeekTaskLogic = require("dailyTask.WeekTaskLogic")
  21. local ClutterDataLogic = require("clutter.ClutterDataLogic")
  22. local ClutterDataDefine = require("clutter.ClutterDataDefine")
  23. local ZhuanpanGift = require("zhuanpan.ZhuanpanGift")
  24. local Log = require("common.Log")
  25. local DB = require("common.DB")
  26. local LuaMongo = _G.lua_mongo
  27. local MailManager = require("mail.MailManager")
  28. -- 允许的渠道
  29. local ALLOW_CHANNELS = {
  30. [11] = true,
  31. [17] = true, -- 美团2楼
  32. }
  33. DEFAULT_ZHUANPAN_TYPE_NORMAL = 1 -- 基础转盘
  34. DEFAULT_ZHUANPAN_TYPE_GAOJI = 2 -- 高级转盘
  35. DEFAULT_BUY_ZHUANPAN_CNT = 50 -- 购买许愿珠所需钻石
  36. DEFAULT_FREE_REFRESH_TIME = 10800 -- 免费刷新的时间
  37. ZHUAN_PAN_ITEM_KIND_CNT = 8 -- 转盘种类数量
  38. DEFAULT_MAX_LUCK = 1000
  39. REWARD_RECORD = { index={}, order={} }
  40. REWARD_RECORD_CNT = 15
  41. function getLuckConfig(mainType)
  42. local config = nil
  43. if mainType == DEFAULT_ZHUANPAN_TYPE_NORMAL then
  44. config = ZhuanpanExcel.luck1
  45. elseif mainType == DEFAULT_ZHUANPAN_TYPE_GAOJI then
  46. config = ZhuanpanExcel.luck2
  47. end
  48. return config
  49. end
  50. function red(human, type)
  51. if not human.db.zhuanpan then return end
  52. local zhuanpan = human.db.zhuanpan[type]
  53. local config = getLuckConfig(type)
  54. if zhuanpan then
  55. local luck = zhuanpan.luck or 0
  56. local luckStatus = zhuanpan.luckStatus
  57. for k, v in pairs(config) do
  58. if luck >= k then
  59. if luckStatus[k] == 1 then
  60. return true
  61. end
  62. end
  63. end
  64. end
  65. if zhuanpan.free == 1 then
  66. return true
  67. end
  68. end
  69. -- 转盘查询
  70. function query(human, mainType)
  71. local zhuanpanConfig = ZhuanpanExcel[mainType]
  72. if not zhuanpanConfig then return end
  73. -- 高级转盘判断等级
  74. local roleConfig = nil
  75. local flag, roleConfig = RoleSystemLogic.isOpen(human,RoleSystemDefine.ROLE_SYS_ID_501)
  76. if mainType == DEFAULT_ZHUANPAN_TYPE_GAOJI then
  77. if flag ~= true then
  78. return Broadcast.sendErr(human, Lang.ZHUANPAN_GAIJI_NEED_LV)
  79. end
  80. end
  81. local oldCnt = getCntByType(human, mainType)
  82. local oldLuck
  83. local tOldStatus = nil
  84. if human.db.zhuanpan and human.db.zhuanpan[mainType] then
  85. oldLuck = human.db.zhuanpan[mainType].luck
  86. if human.db.zhuanpan[mainType].luckStatus then
  87. tOldStatus = Util.copyTable(human.db.zhuanpan[mainType].luckStatus)
  88. end
  89. end
  90. -- 更新
  91. update(human, mainType)
  92. -- 初始化
  93. initDB(human, mainType, oldCnt,oldLuck, tOldStatus)
  94. local zuanpan = human.db.zhuanpan[mainType]
  95. local config = ZhuanpanExcel.define[mainType]
  96. local msgRet = Msg.gc.GC_ZHUANPAN_QUERY
  97. msgRet.type = mainType
  98. msgRet.isFirst = zuanpan.free == 1 and 1 or 0
  99. local now = os.time()
  100. local ts1 = now - zuanpan.ts1
  101. msgRet.refreshTime = 24 * 60 * 60 - ts1
  102. msgRet.freeRefreshTime = DEFAULT_FREE_REFRESH_TIME - (now - zuanpan.ts2)
  103. if msgRet.freeRefreshTime < 0 then
  104. msgRet.freeRefreshTime = 0
  105. end
  106. Grid.makeItem(msgRet.itemID, config.useItemID , 1)
  107. msgRet.itemCnt[0] = 2
  108. msgRet.itemCnt[1] = config.useItemCnt1
  109. msgRet.itemCnt[2] = config.useItemCnt2
  110. msgRet.drawCnt = config.drawCnt2
  111. Grid.makeItem(msgRet.zuanshiNeed, config.refreshCost[1][1], config.refreshCost[1][2])
  112. msgRet.needLv = config and config.lv or 0
  113. if mainType == DEFAULT_ZHUANPAN_TYPE_NORMAL then
  114. msgRet.needLv = ZhuanpanExcel.define[DEFAULT_ZHUANPAN_TYPE_GAOJI].lv
  115. elseif mainType == DEFAULT_ZHUANPAN_TYPE_GAOJI then
  116. msgRet.needLv = ZhuanpanExcel.define[DEFAULT_ZHUANPAN_TYPE_NORMAL].lv
  117. end
  118. msgRet.needVipLv = VipLogic.getPowerNeedLv(VipLogic.VIP_POWER15)
  119. for i = 1, ZHUAN_PAN_ITEM_KIND_CNT do
  120. local data = zuanpan[i]
  121. local dataID = data.id
  122. local tempConfig = zhuanpanConfig[dataID]
  123. Grid.makeItem(msgRet.list[i].item, data.itemID, data.itemCnt)
  124. msgRet.list[i].id = dataID
  125. msgRet.list[i].chance = tempConfig.chance
  126. msgRet.list[i].maxCnt = tempConfig.getCnt
  127. msgRet.list[i].getCnt = 0
  128. if data.getCnt then
  129. msgRet.list[i].getCnt = data.getCnt
  130. end
  131. end
  132. local luckConfig = getLuckConfig(mainType)
  133. msgRet.luck = zuanpan.luck or 0
  134. local len = 0
  135. for k, v in pairs(luckConfig) do
  136. len = len + 1
  137. local net = msgRet.luckList[len]
  138. net.id = k
  139. net.status = zuanpan.luckStatus[k] or 0
  140. Grid.makeItem(net.item, v.reward[1] , v.reward[2])
  141. end
  142. msgRet.luckList[0] = len
  143. len = 0
  144. if REWARD_RECORD[mainType] then
  145. for k, v in ipairs(REWARD_RECORD[mainType]) do
  146. len = len + 1
  147. local net = msgRet.record[len]
  148. net.id = k
  149. net.tips = v.tips
  150. net.timer = v.timer
  151. net.order = v.order
  152. end
  153. end
  154. msgRet.record[0] = len
  155. msgRet.list[0] = ZHUAN_PAN_ITEM_KIND_CNT
  156. len = 0
  157. local totalWeight = 0
  158. local chanceList = {}
  159. for k, v in pairs(zhuanpanConfig) do
  160. totalWeight = totalWeight + v.chance
  161. chanceList[k] = chanceList[k] or {}
  162. local rewardWeight = 0
  163. for a, b in ipairs(v.rewardID) do
  164. rewardWeight = rewardWeight + b[3]
  165. end
  166. chanceList[k].totalWeight = rewardWeight
  167. end
  168. -- 大全重占比
  169. local temp = {}
  170. for k, v in pairs(zhuanpanConfig) do
  171. local chance = chanceList[k]
  172. local scale = v.chance / totalWeight
  173. for a, b in ipairs(v.rewardID) do
  174. local itemID = b[1]
  175. if not temp[itemID] then
  176. local weight = b[3] / chance.totalWeight
  177. len = len + 1
  178. local net = msgRet.chanceList[len]
  179. local itemConfig = ItemDefine.getConfig(itemID)
  180. if not itemConfig then
  181. print(itemID)
  182. end
  183. net.tips = itemConfig and itemConfig.name or ""
  184. net.chance = weight * scale * 100
  185. temp[itemID] = 1
  186. end
  187. end
  188. end
  189. msgRet.chanceList[0] = len
  190. local red1 = red(human, DEFAULT_ZHUANPAN_TYPE_NORMAL)
  191. msgRet.red1 = red1 == true and 1 or 0
  192. local red2 = red(human, DEFAULT_ZHUANPAN_TYPE_GAOJI)
  193. msgRet.red2 = red2 == true and 1 or 0
  194. Msg.send(msgRet, human.fd)
  195. end
  196. function refresh(human, mainType, needTime, bRefreshLuck)
  197. if not ZhuanpanExcel[mainType] then
  198. return
  199. end
  200. local oldCnt = getCntByType(human, mainType)
  201. local oldLuck
  202. local tOldStatus = nil
  203. if human.db.zhuanpan and human.db.zhuanpan[mainType] then
  204. oldLuck = human.db.zhuanpan[mainType].luck
  205. if human.db.zhuanpan[mainType].luckStatus and not bRefreshLuck then
  206. tOldStatus = Util.copyTable(human.db.zhuanpan[mainType].luckStatus)
  207. end
  208. end
  209. -- 更新
  210. update(human, mainType)
  211. -- 初始化
  212. initDB(human, mainType, oldCnt,oldLuck,tOldStatus)
  213. -- 判断是否免费
  214. if needTime then
  215. local config = ZhuanpanExcel.define[mainType]
  216. local needCost = 0
  217. local now = os.time()
  218. local ts2 = now - human.db.zhuanpan[mainType].ts2
  219. local leftTime = DEFAULT_FREE_REFRESH_TIME - ts2
  220. if leftTime > 0 then
  221. needCost = config.refreshCost[1][2]
  222. end
  223. -- 判断消耗
  224. local cnt = BagLogic.getItemCnt(human, config.refreshCost[1][1])
  225. if cnt < needCost then
  226. return
  227. end
  228. -- 扣消耗
  229. if needCost > 0 then
  230. BagLogic.delItem(human, config.refreshCost[1][1], needCost, "zhuanpan_refresh")
  231. end
  232. -- 改db
  233. local dayStartTime = Util.getDayStartTime(now)
  234. human.db.zhuanpan[mainType].ts2 = now
  235. human.db.zhuanpan[mainType].ts1 = dayStartTime
  236. end
  237. addRandomReward(human, mainType)
  238. -- 通知客户端
  239. if needTime then
  240. query(human, mainType)
  241. end
  242. end
  243. -- 刷新数据
  244. function updateDaily(human)
  245. refresh(human, DEFAULT_ZHUANPAN_TYPE_NORMAL)
  246. refresh(human, DEFAULT_ZHUANPAN_TYPE_GAOJI)
  247. human.db.zhuanpan[DEFAULT_ZHUANPAN_TYPE_NORMAL].free = 1
  248. human.db.zhuanpan[DEFAULT_ZHUANPAN_TYPE_NORMAL].freeCnt = 0
  249. ZhuanpanGift.updateDaily(human)
  250. end
  251. -- 抽奖
  252. function getReward(human, mainType, cnt)
  253. local config = ZhuanpanExcel.define[mainType]
  254. if not ZhuanpanExcel[mainType] then
  255. return
  256. end
  257. local needItemID = config.useItemID
  258. local needItemCnt = nil
  259. if cnt == 1 then
  260. needItemCnt = config.useItemCnt1
  261. elseif cnt == config.drawCnt2 then
  262. needItemCnt = config.useItemCnt2
  263. -- 多次抽奖需要达到指定vip等级
  264. --[[local needVipLv = VipLogic.getPowerNeedLv(VipLogic.VIP_POWER15)
  265. if VipLogic.getVipLv(human) < needVipLv then
  266. return Broadcast.sendErr(human, Util.format(Lang.ROLE_VIP_ERROR2, needVipLv))
  267. end]]
  268. end
  269. if needItemCnt == nil then
  270. return
  271. end
  272. local oldCnt = getCntByType(human, mainType)
  273. local oldLuck
  274. local tOldStatus = nil
  275. if human.db.zhuanpan and human.db.zhuanpan[mainType] then
  276. oldLuck = human.db.zhuanpan[mainType].luck
  277. if human.db.zhuanpan[mainType].luckStatus then
  278. tOldStatus = Util.copyTable(human.db.zhuanpan[mainType].luckStatus)
  279. end
  280. end
  281. -- 更新
  282. update(human, mainType)
  283. -- 初始化
  284. initDB(human, mainType, oldCnt,oldLuck, tOldStatus)
  285. local zhuanpan = human.db.zhuanpan[mainType]
  286. if not BagLogic.checkItemCnt(human, needItemID, needItemCnt) then
  287. return
  288. end
  289. -- 每日可抽取次数检测
  290. -- local dayTimes = ClutterDataLogic.GetZhuanPanTimes(human)
  291. -- if dayTimes < cnt then
  292. -- return Broadcast.sendErr(human, Lang.JINBI_EXCHANGE_ERR_CNT)
  293. -- end
  294. -- --更新每次抽取次数
  295. -- dayTimes = dayTimes - cnt
  296. -- 改为只更新次数
  297. ClutterDataLogic.UpdateZhuanPanTimes(human, cnt)
  298. -- 扣消耗
  299. BagLogic.delItem(human, needItemID, needItemCnt, "zhuanpan_get")
  300. local msgRet = Msg.gc.GC_ZHUANPAN_GET_REWARD
  301. msgRet.type = mainType
  302. msgRet.list[0] = cnt
  303. local len = 0
  304. for i = 1, cnt do
  305. local result = getLuckDrawSingle(human, mainType)
  306. if result == nil then
  307. assert(nil)
  308. end
  309. -- 改db
  310. local data = zhuanpan[result]
  311. local zhuanpanConfig = ZhuanpanExcel[mainType]
  312. local tempConfig = zhuanpanConfig[data.id]
  313. local nowGetCnt = data.getCnt or 0
  314. local maxGetCnt = tempConfig.getCnt
  315. if maxGetCnt ~= 0 then
  316. data.getCnt = nowGetCnt + 1
  317. end
  318. -- 加道具
  319. local itemID = data.itemID
  320. local itemCnt = data.itemCnt
  321. BagLogic.addItem(human, itemID, itemCnt, "zhuanpan_get")
  322. local itemConfig = ItemExcel[itemID]
  323. local heroConfig = HeroExcel[itemID]
  324. -- 存在部分 英雄配表里面的id 和装备配表重合了
  325. if itemConfig and itemConfig.subType == ItemDefine.ITEM_SUBTYPE_SUIPIAN and heroConfig and heroConfig.star == 5 then
  326. if mainType == DEFAULT_ZHUANPAN_TYPE_GAOJI then
  327. ChatPaoMaLogic.broadcast(human, ChatPaoMaLogic.PAOMA_TYPE_BROAD_TYPE11, tempConfig.grade, itemID)
  328. else
  329. ChatPaoMaLogic.broadcast(human, ChatPaoMaLogic.PAOMA_TYPE_BROAD_TYPE10, tempConfig.grade, itemID)
  330. end
  331. end
  332. if tempConfig.getCnt > 0 then
  333. if not REWARD_RECORD[mainType] then
  334. REWARD_RECORD[mainType] = {}
  335. end
  336. local record = REWARD_RECORD[mainType]
  337. local index = REWARD_RECORD.index[mainType] or 1
  338. local order = REWARD_RECORD.order[mainType] or 1
  339. record[index] = record[index] or {}
  340. record[index].tips = Util.format(Lang.ZHUANPAN_RECORD_TWO, human.db.name, ItemDefine.getValue(itemID,"name"), itemCnt)
  341. record[index].timer = os.time()
  342. record[index].order = order
  343. index = index + 1
  344. if index > REWARD_RECORD_CNT then
  345. index = 1
  346. end
  347. REWARD_RECORD.order[mainType] = order + 1
  348. REWARD_RECORD.index[mainType] = index
  349. end
  350. msgRet.list[i] = data.id
  351. len = len + 1
  352. if not ItemDefine.isEquip(itemID) then
  353. Grid.makeItem(msgRet.item[len], itemID, itemCnt)
  354. else
  355. EquipLogic.makeEquipItemOne(human, msgRet.item[len])
  356. end
  357. end
  358. msgRet.item[0] = len
  359. -- 增加积分
  360. local itemID = ItemDefine.ITEM_LUCK_ID
  361. local itemCnt = cnt * 10
  362. BagLogic.addItem(human, itemID, itemCnt, "zhuanpan_back")
  363. msgRet.luckItem[0] = 1
  364. Grid.makeItem(msgRet.luckItem[1], itemID, itemCnt)
  365. zhuanpan.cnt = zhuanpan.cnt or 0
  366. zhuanpan.cnt = zhuanpan.cnt + cnt
  367. zhuanpan.luck = zhuanpan.luck or 0
  368. zhuanpan.luck = zhuanpan.luck + cnt * 10
  369. zhuanpan.luckStatus = zhuanpan.luckStatus or {}
  370. local luckConfig = getLuckConfig(mainType)
  371. -- 集火幸运值 奖励
  372. local luckStatus = zhuanpan.luckStatus
  373. for k, v in pairs(luckConfig) do
  374. if zhuanpan.luck >= k then
  375. if luckStatus[k] == nil then
  376. luckStatus[k] = 1
  377. end
  378. end
  379. end
  380. Msg.send(msgRet, human.fd)
  381. query(human, mainType)
  382. YunYingLogic.onCallBack(human, "onFindStar", cnt)
  383. TriggerLogic.PublishEvent(TriggerDefine.EVENT_TYPE_FINDSTAR, human.db._id, cnt)
  384. --周任务,寻星
  385. WeekTaskLogic.recordWeekTaskFinishCnt(human, WeekTaskLogic.WEEK_TASK_ID_1, cnt)
  386. end
  387. -- 购买许愿珠
  388. function buyCnt(human, mainType, cnt)
  389. if cnt < 1 then return end
  390. if mainType ~= DEFAULT_ZHUANPAN_TYPE_NORMAL then
  391. return
  392. end
  393. local needZuanshi = 50 * cnt
  394. -- 判断消耗
  395. if not ObjHuman.checkRMB(human, needZuanshi) then
  396. return
  397. end
  398. -- 扣消耗
  399. ObjHuman.decZuanshi(human, -needZuanshi, "zhuanpan_buy_cnt", ItemDefine.ITEM_BASE_QIYUANZHU_ID, cnt)
  400. -- 增加物品
  401. BagLogic.addItem(human, ItemDefine.ITEM_BASE_QIYUANZHU_ID, cnt, "zhuanpan_buy_cnt")
  402. -- 通知客户端
  403. local msgRet = Msg.gc.GC_BUY_ZHUANPAN_CNT
  404. Msg.send(msgRet, human.fd)
  405. end
  406. ------------------------------功能函数--------------------------------------
  407. function addRandomReward(human, mainType)
  408. local zhuanpanConfig = ZhuanpanExcel[mainType]
  409. if not zhuanpanConfig then return end
  410. local nowLv = human.db.lv
  411. local itemID = nil
  412. local itemCnt = nil
  413. local cntIndex = 0
  414. for i = 1, #zhuanpanConfig do
  415. local tempConfig = zhuanpanConfig[i]
  416. if not tempConfig then return end
  417. if mainType == DEFAULT_ZHUANPAN_TYPE_NORMAL then
  418. if nowLv >= tempConfig.minLv and nowLv <= tempConfig.maxLv then
  419. itemID, itemCnt = getRandomItem(human, tempConfig)
  420. if itemID and itemCnt then
  421. cntIndex = cntIndex + 1
  422. human.db.zhuanpan[mainType][cntIndex] = {}
  423. human.db.zhuanpan[mainType][cntIndex].id = i
  424. human.db.zhuanpan[mainType][cntIndex].itemID = itemID
  425. human.db.zhuanpan[mainType][cntIndex].itemCnt = itemCnt
  426. end
  427. end
  428. elseif mainType == DEFAULT_ZHUANPAN_TYPE_GAOJI then
  429. itemID, itemCnt = getRandomItem(human, tempConfig)
  430. if itemID and itemCnt then
  431. cntIndex = cntIndex + 1
  432. human.db.zhuanpan[mainType][cntIndex] = {}
  433. human.db.zhuanpan[mainType][cntIndex].id = i
  434. human.db.zhuanpan[mainType][cntIndex].itemID = itemID
  435. human.db.zhuanpan[mainType][cntIndex].itemCnt = itemCnt
  436. end
  437. end
  438. end
  439. end
  440. function getLuckDrawSingle(human, mainType)
  441. local zhuanpanConfig = ZhuanpanExcel[mainType]
  442. if not zhuanpanConfig then return end
  443. local totalWeight = 0
  444. local recordData = nil
  445. for i = 1, ZHUAN_PAN_ITEM_KIND_CNT do
  446. local data = human.db.zhuanpan[mainType][i]
  447. local drawID = data.id
  448. local tempConfig = zhuanpanConfig[drawID]
  449. local nowGetCnt = data.getCnt or 0
  450. local maxGetCnt = tempConfig.getCnt
  451. if maxGetCnt == 0 or maxGetCnt > nowGetCnt then
  452. totalWeight = totalWeight + tempConfig.chance
  453. end
  454. end
  455. local randNum = math.random(1,totalWeight)
  456. for i = 1, ZHUAN_PAN_ITEM_KIND_CNT do
  457. local data = human.db.zhuanpan[mainType][i]
  458. local drawID = data.id
  459. local tempConfig = zhuanpanConfig[drawID]
  460. local nowGetCnt = data.getCnt or 0
  461. local maxGetCnt = tempConfig.getCnt
  462. if maxGetCnt == 0 or maxGetCnt > nowGetCnt then
  463. local tempWeight = tempConfig.chance
  464. if randNum <= tempWeight then
  465. return i
  466. end
  467. randNum = randNum - tempWeight
  468. end
  469. end
  470. end
  471. function initDB(human, mainType, cnt, oldluck, tOldStatus)
  472. if human.db.zhuanpan ~= nil and
  473. human.db.zhuanpan[mainType] ~= nil then
  474. return
  475. end
  476. local now = os.time()
  477. human.db.zhuanpan = human.db.zhuanpan or {}
  478. human.db.zhuanpan[mainType] = {}
  479. local dayStartTime = Util.getDayStartTime(now)
  480. human.db.zhuanpan[mainType].ts1 = dayStartTime
  481. human.db.zhuanpan[mainType].ts2 = now - DEFAULT_FREE_REFRESH_TIME
  482. human.db.zhuanpan[mainType].cnt = cnt
  483. human.db.zhuanpan[mainType].luck = oldluck
  484. human.db.zhuanpan[mainType].free = 1
  485. if tOldStatus then
  486. human.db.zhuanpan[mainType].luckStatus = tOldStatus
  487. else
  488. human.db.zhuanpan[mainType].luckStatus = {}
  489. end
  490. addRandomReward(human, mainType)
  491. end
  492. function update(human, mainType)
  493. if human.db.zhuanpan == nil or human.db.zhuanpan[mainType] == nil then
  494. return
  495. end
  496. if human.db.zhuanpan[mainType].ts1 then
  497. -- 防止前端 在结束倒计时结束 发送查询 , 这边还没有结束 返回一样的数据
  498. local now = os.time() + 1
  499. local ts1 = now - human.db.zhuanpan[mainType].ts1
  500. local leftTime = 24 * 60 * 60 - ts1
  501. if leftTime <= 0 then
  502. human.db.zhuanpan[mainType] = nil
  503. end
  504. end
  505. end
  506. function getRandomItem(human, tempConfig)
  507. local totalWeight = 0
  508. for k, v in ipairs(tempConfig.rewardID) do
  509. totalWeight = totalWeight + v[3]
  510. end
  511. local random = math.random(1, totalWeight)
  512. for k, v in ipairs(tempConfig.rewardID) do
  513. local weight = v[3]
  514. local itemID = v[1]
  515. local itemCnt = v[2]
  516. if random <= weight then
  517. return itemID, itemCnt
  518. end
  519. random = random - weight
  520. end
  521. end
  522. function zhuanpanByGm(human,mainType,val)
  523. if not mainType and not val then
  524. return
  525. end
  526. if mainType == 0 or mainType > 2 or val < 5 then
  527. return
  528. end
  529. if human.db.zhuanpan[mainType] then
  530. local now = os.time()
  531. human.db.zhuanpan[mainType].ts1 = now - 24 * 60 * 60 + val
  532. end
  533. end
  534. function getCntByType(human, mainType)
  535. local num = 0
  536. if human.db.zhuanpan and human.db.zhuanpan[mainType] then
  537. human.db.zhuanpan[mainType].cnt = human.db.zhuanpan[mainType].cnt or 0
  538. num = human.db.zhuanpan[mainType].cnt
  539. end
  540. return num
  541. end
  542. function getLuck(human, msg)
  543. local mainType = msg.type
  544. local config = getLuckConfig(mainType)
  545. if not config then
  546. return
  547. end
  548. local zhuanpan = human.db.zhuanpan[mainType]
  549. if zhuanpan == nil then
  550. return
  551. end
  552. if zhuanpan.luck <= 0 then
  553. return
  554. end
  555. local luckStatus = zhuanpan.luckStatus
  556. if luckStatus == nil then
  557. luckStatus = {}
  558. zhuanpan.luckStatus = luckStatus
  559. end
  560. -- 收集所有可领取的奖励(status == 1)
  561. local itemList = {}
  562. local itemListLen = 0
  563. -- 遍历所有配置的奖励,找到可领取的(status == 1)
  564. for k, v in pairs(config) do
  565. if luckStatus[k] == 1 then
  566. -- 标记为已领取
  567. luckStatus[k] = 2
  568. -- 添加奖励到背包
  569. BagLogic.addItem(human, v.reward[1], v.reward[2], "zhuanpan_back")
  570. -- 收集到奖励列表
  571. itemListLen = itemListLen + 1
  572. itemList[itemListLen] = {v.reward[1], v.reward[2]}
  573. end
  574. end
  575. -- 如果没有可领取的奖励,直接返回
  576. if itemListLen == 0 then
  577. return
  578. end
  579. -- 循环处理幸运值扣除和重新激活奖励(可能领取多轮)
  580. while true do
  581. -- 计算是否需要重新扣除幸运值 重新激活奖励
  582. local luck = zhuanpan.luck
  583. local calc = true
  584. for k, v in pairs(config) do
  585. if luckStatus[k] == nil or luckStatus[k] ~= 2 then
  586. calc = false
  587. end
  588. end
  589. -- 如果所有奖励都已领取,扣除幸运值并重新激活
  590. if calc == true then
  591. zhuanpan.luckStatus = {}
  592. luck = luck - DEFAULT_MAX_LUCK
  593. luck = luck < 0 and 0 or luck
  594. zhuanpan.luck = luck
  595. -- 重新激活幸运值奖励
  596. luckStatus = zhuanpan.luckStatus
  597. for k, v in pairs(config) do
  598. if zhuanpan.luck >= k then
  599. if luckStatus[k] == nil then
  600. luckStatus[k] = 1
  601. end
  602. end
  603. end
  604. -- 如果重新激活后还有可领取的奖励,继续循环领取
  605. local hasMore = false
  606. for k, v in pairs(config) do
  607. if luckStatus[k] == 1 then
  608. hasMore = true
  609. -- 领取这个奖励
  610. luckStatus[k] = 2
  611. BagLogic.addItem(human, v.reward[1], v.reward[2], "zhuanpan_back")
  612. itemListLen = itemListLen + 1
  613. itemList[itemListLen] = {v.reward[1], v.reward[2]}
  614. end
  615. end
  616. -- 如果没有更多可领取的奖励,退出循环
  617. if not hasMore then
  618. break
  619. end
  620. else
  621. -- 不是所有奖励都已领取,退出循环
  622. break
  623. end
  624. end
  625. -- 发送所有奖励列表
  626. if itemListLen > 0 then
  627. BagLogic.sendItemGetList(human, itemList, "zhuanpan_back")
  628. end
  629. query(human, msg.type)
  630. end
  631. function isDot(human)
  632. local red1 = red(human, DEFAULT_ZHUANPAN_TYPE_NORMAL)
  633. if red1 then return true end
  634. --local red2 = red(human, DEFAULT_ZHUANPAN_TYPE_GAOJI)
  635. --if red2 then return true end
  636. return false
  637. end
  638. function getFree(human)
  639. local oldLuck
  640. local tOldStatus = nil
  641. if human.db.zhuanpan and human.db.zhuanpan[DEFAULT_ZHUANPAN_TYPE_NORMAL] then
  642. oldLuck = human.db.zhuanpan[DEFAULT_ZHUANPAN_TYPE_NORMAL].luck
  643. if human.db.zhuanpan[DEFAULT_ZHUANPAN_TYPE_NORMAL].luckStatus then
  644. tOldStatus = Util.copyTable(human.db.zhuanpan[DEFAULT_ZHUANPAN_TYPE_NORMAL].luckStatus)
  645. end
  646. end
  647. initDB(human,DEFAULT_ZHUANPAN_TYPE_NORMAL,nil, oldLuck,tOldStatus)
  648. if human.db.zhuanpan[DEFAULT_ZHUANPAN_TYPE_NORMAL].free ~= 1 then
  649. return
  650. end
  651. human.db.zhuanpan[DEFAULT_ZHUANPAN_TYPE_NORMAL].free = 0
  652. local zhuanpanConfig = ZhuanpanExcel.define[DEFAULT_ZHUANPAN_TYPE_NORMAL]
  653. local len = #zhuanpanConfig.freeCnt
  654. local totalWeight = 0
  655. for i = 1,len do
  656. totalWeight = totalWeight + zhuanpanConfig.freeCnt[i][2]
  657. end
  658. local itemCnt = nil
  659. local randomWeight = math.random(1,totalWeight)
  660. for i = 1,len do
  661. if randomWeight < zhuanpanConfig.freeCnt[i][2] then
  662. itemCnt = zhuanpanConfig.freeCnt[i][1]
  663. break
  664. else
  665. randomWeight = randomWeight - zhuanpanConfig.freeCnt[i][2]
  666. end
  667. end
  668. if itemCnt then
  669. local item = {}
  670. item[1] = {zhuanpanConfig.useItemID,itemCnt}
  671. item[2] = zhuanpanConfig.freeitem[1]
  672. BagLogic.addItemList(human, item, "zhuanpan_get")
  673. else
  674. assert()
  675. end
  676. end
  677. -- 检查账号下是否有任何角色已领取每日固定奖励(账号级别判断)
  678. local function checkAccountDailyFixedReward(account)
  679. if not account then
  680. return false
  681. end
  682. local QueryByAccount = {account = account}
  683. local fields = {zhuanpan = 1}
  684. LuaMongo.find(DB.db_char, QueryByAccount, fields)
  685. while true do
  686. local data = {}
  687. if not LuaMongo.next(data) then
  688. break
  689. end
  690. if data.zhuanpan and data.zhuanpan.dailyFixedReward then
  691. local getTime = data.zhuanpan.dailyFixedReward.getTime
  692. if getTime and Util.isSameDay(getTime) then
  693. return true -- 账号下已有角色今日领取过
  694. end
  695. end
  696. end
  697. return false -- 账号下没有角色今日领取过
  698. end
  699. -- 获取账号下最早创建的角色注册日期(账号级别判断)
  700. local function getAccountEarliestCreateTime(account)
  701. if not account then
  702. return nil
  703. end
  704. local QueryByAccount = {account = account}
  705. local fields = {createTime = 1}
  706. LuaMongo.find(DB.db_char, QueryByAccount, fields)
  707. local earliestTime = nil
  708. while true do
  709. local data = {}
  710. if not LuaMongo.next(data) then
  711. break
  712. end
  713. if data.createTime then
  714. if not earliestTime or data.createTime < earliestTime then
  715. earliestTime = data.createTime
  716. end
  717. end
  718. end
  719. return earliestTime
  720. end
  721. -- 检查渠道17是否已超过注册后15天(基于当前角色注册时间)
  722. local function isChannel18Over15Days(human)
  723. if not human or not human.db or not human.db.createTime then
  724. return false
  725. end
  726. local createTime = human.db.createTime
  727. local registerDayStart = Util.getDayStartTime(createTime)
  728. local now = os.time()
  729. local todayDayStart = Util.getDayStartTime(now)
  730. -- 计算从注册日期到今天已经过了多少天(注册日期是第1天)
  731. local daysSinceRegister = math.floor((todayDayStart - registerDayStart) / 86400) + 1
  732. -- 如果超过15天,则不能领取
  733. return daysSinceRegister > 7
  734. end
  735. -- 检查账号下是否有任何角色已领取一次性奖励(账号级别判断)
  736. local function checkAccountOnceReward(account)
  737. if not account then
  738. return false
  739. end
  740. local QueryByAccount = {account = account}
  741. local fields = {zhuanpan = 1}
  742. LuaMongo.find(DB.db_char, QueryByAccount, fields)
  743. while true do
  744. local data = {}
  745. if not LuaMongo.next(data) then
  746. break
  747. end
  748. if data.zhuanpan and data.zhuanpan.onceReward then
  749. local getTime = data.zhuanpan.onceReward.getTime
  750. if getTime then
  751. return true -- 账号下已有角色领取过
  752. end
  753. end
  754. end
  755. return false -- 账号下没有角色领取过
  756. end
  757. -- 检查账号下是否有任何角色已领取订阅奖励(账号级别判断)
  758. local function checkAccountSubscribeReward(account)
  759. if not account then
  760. return false
  761. end
  762. local QueryByAccount = {account = account}
  763. local fields = {zhuanpan = 1}
  764. LuaMongo.find(DB.db_char, QueryByAccount, fields)
  765. while true do
  766. local data = {}
  767. if not LuaMongo.next(data) then
  768. break
  769. end
  770. if data.zhuanpan and data.zhuanpan.subscribeReward then
  771. local getTime = data.zhuanpan.subscribeReward.getTime
  772. if getTime then
  773. return true -- 账号下已有角色领取过
  774. end
  775. end
  776. end
  777. return false -- 账号下没有角色领取过
  778. end
  779. -- 从newUniqueTag解析渠道ID (格式: "channelID|serverTag|account")
  780. local function getChannelIdFromNewUniqueTag(newUniqueTag)
  781. if not newUniqueTag then
  782. return nil
  783. end
  784. local parts = {}
  785. for part in string.gmatch(newUniqueTag, "([^|]+)") do
  786. table.insert(parts, part)
  787. end
  788. if #parts >= 1 then
  789. return tonumber(parts[1])
  790. end
  791. return nil
  792. end
  793. -- 获取每日固定奖励配置(根据渠道ID)
  794. local function getDailyFixedRewardConfig(channelId)
  795. if channelId == 17 then
  796. -- 渠道17(美图2楼):[[101,20000],[111,5000]]
  797. return {
  798. {101, 20000},
  799. {111, 5000}
  800. }
  801. else
  802. -- 渠道11(默认):[[102, 50]]
  803. return {
  804. {102, 50}
  805. }
  806. end
  807. end
  808. -- 每日固定奖励查询
  809. function dailyFixedRewardQuery(human)
  810. local msgRet = Msg.gc.GC_ZHUANPAN_DAILY_FIXED_QUERY
  811. if not msgRet then
  812. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardQuery] 错误: msgRet为nil")
  813. return
  814. end
  815. -- 每日更新检查
  816. ObjHuman.updateDaily(human)
  817. local account = human.db.account
  818. local isReceived = false
  819. -- 先读取当日是否已领取(必须在 or {} 初始化之前读,否则可能被空表覆盖导致刚写入的 getTime 丢失)
  820. local getTime = nil
  821. if human.db.zhuanpan and human.db.zhuanpan.dailyFixedReward then
  822. getTime = human.db.zhuanpan.dailyFixedReward.getTime
  823. end
  824. if getTime and Util.isSameDay(getTime) then
  825. isReceived = true
  826. else
  827. isReceived = checkAccountDailyFixedReward(account)
  828. end
  829. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardQuery] getTime=" .. tostring(getTime) .. ", isReceived=" .. tostring(isReceived) .. ", account=" .. tostring(account))
  830. -- 初始化数据库(放在读取 getTime 之后,避免覆盖已有 dailyFixedReward 导致 isReceived 错误)
  831. human.db.zhuanpan = human.db.zhuanpan or {}
  832. human.db.zhuanpan.dailyFixedReward = human.db.zhuanpan.dailyFixedReward or {}
  833. -- 渠道17(美团2楼)需要满足:
  834. -- 1) 当日从2楼登录(mtFrom2floor == 1,且 mtFrom2floorDay 是今天)
  835. -- 2) 订阅奖励已领取且在7日有效期内
  836. local newUniqueTag = human.db.newUniqueTag or human.newUniqueTag
  837. local channelId = getChannelIdFromNewUniqueTag(newUniqueTag)
  838. if channelId == 17 then
  839. -- 2楼登录状态(mtFrom2floor 可能为字符串;Util.isSameDay 同天返回 now 时间戳,否则 nil,转为布尔)
  840. local from2floorOk = false
  841. if tonumber(human.db.mtFrom2floor) == 1 and human.db.mtFrom2floorDay then
  842. from2floorOk = (Util.isSameDay(human.db.mtFrom2floorDay) and true or false)
  843. end
  844. -- 订阅相关状态(mtSubscribe 可能为字符串 "1",用 tonumber 统一判断)
  845. local isSubscribed = (tonumber(human.db.mtSubscribe) == 1)
  846. local zhuanpan = human.db.zhuanpan
  847. local hasSubscribeReward = zhuanpan and zhuanpan.subscribeReward and zhuanpan.subscribeReward.getTime
  848. local inValidPeriod = hasSubscribeReward and isSubscribeRewardInValidPeriod(human)
  849. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardQuery] channelId=17 from2floorOk=" .. tostring(from2floorOk) .. ", mtFrom2floor=" .. tostring(human.db.mtFrom2floor) .. ", mtFrom2floorDay=" .. tostring(human.db.mtFrom2floorDay) .. ", isSubscribed=" .. tostring(isSubscribed) .. ", hasSubscribeReward=" .. tostring(hasSubscribeReward) .. ", inValidPeriod=" .. tostring(inValidPeriod))
  850. if not isSubscribed then
  851. -- 未订阅:不可领取
  852. msgRet.status = 3 -- 未激活(未订阅)
  853. elseif isReceived then
  854. -- 当日已领取:固定为 2,不因 mtFrom2floor 被置 0 而变成 0
  855. msgRet.status = 2 -- 已领取(今日已领取)
  856. elseif not from2floorOk then
  857. -- 当天未从2楼进入:不可领取
  858. msgRet.status = 0
  859. else
  860. if not hasSubscribeReward or not inValidPeriod then
  861. -- 已订阅,但订阅奖励尚未领取,或已超过7日有效期
  862. msgRet.status = 3 -- 未激活(订阅奖励未领或15天已满)
  863. else
  864. msgRet.status = 1 -- 可领取(已激活且在7日内,且今日未领)
  865. end
  866. end
  867. else
  868. -- 其他渠道保持原有逻辑
  869. if isReceived then
  870. msgRet.status = 2 -- 已领取(账号级别)
  871. else
  872. msgRet.status = 1 -- 可领取
  873. end
  874. end
  875. -- 根据渠道ID设置奖励物品
  876. local newUniqueTag = human.db.newUniqueTag or human.newUniqueTag
  877. local channelId = getChannelIdFromNewUniqueTag(newUniqueTag)
  878. local rewardConfig = getDailyFixedRewardConfig(channelId or 11) -- 默认渠道11
  879. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardQuery] 查询奖励信息: rewardConfig",rewardConfig)
  880. -- 循环处理所有奖励物品
  881. for i = 1, #rewardConfig do
  882. Grid.makeItem(msgRet.reward[i], rewardConfig[i][1], rewardConfig[i][2])
  883. end
  884. msgRet.reward[0] = #rewardConfig -- 设置数组长度
  885. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardQuery] channelId=" .. tostring(channelId) .. ", status=" .. tostring(msgRet.status))
  886. if human.fd then
  887. Msg.send(msgRet, human.fd)
  888. else
  889. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardQuery] 错误: human.fd为nil,无法发送协议")
  890. end
  891. end
  892. -- 每日固定奖励领取
  893. function dailyFixedRewardGet(human, channelId)
  894. if not ALLOW_CHANNELS[channelId] then
  895. Log.write(
  896. Log.LOGID_DEBUG,
  897. "[dailyFixedRewardGet] 渠道不匹配: channelId=" .. (channelId or "nil") .. ", 允许=11,16,18"
  898. )
  899. return Broadcast.sendErr(human, "渠道不匹配")
  900. end
  901. -- 每日更新检查
  902. ObjHuman.updateDaily(human)
  903. -- 初始化数据库
  904. human.db.zhuanpan = human.db.zhuanpan or {}
  905. human.db.zhuanpan.dailyFixedReward = human.db.zhuanpan.dailyFixedReward or {}
  906. -- 账号级别判断:先检查当前角色的内存数据,再检查数据库
  907. local account = human.db.account
  908. local isReceived = false
  909. -- 先检查当前角色的内存数据
  910. local getTime = human.db.zhuanpan.dailyFixedReward.getTime
  911. if getTime and Util.isSameDay(getTime) then
  912. isReceived = true
  913. else
  914. -- 再检查账号下其他角色(数据库)
  915. isReceived = checkAccountDailyFixedReward(account)
  916. end
  917. if isReceived then
  918. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardGet] 账号今日已领取: account="..(account or "nil"))
  919. return Broadcast.sendErr(human, "今日已领取")
  920. end
  921. -- 渠道17(美团2楼)额外条件:
  922. -- 1) 当日从2楼登录(mtFrom2floor == 1 且 mtFrom2floorDay 为今天)
  923. -- 2) 订阅奖励已领取且在7日有效期内
  924. if channelId == 17 then
  925. -- 2楼登录状态(mtFrom2floor 可能为字符串,Util.isSameDay 同天返回时间戳,转为布尔)
  926. local from2floorOk = false
  927. if tonumber(human.db.mtFrom2floor) == 1 and human.db.mtFrom2floorDay then
  928. from2floorOk = (Util.isSameDay(human.db.mtFrom2floorDay) and true or false)
  929. end
  930. if not from2floorOk then
  931. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardGet] 渠道17当日未从2楼进入,无法领取: account="..(account or "nil"))
  932. return Broadcast.sendErr(human, "条件不足,无法领取")
  933. end
  934. -- 订阅有效期检查(mtSubscribe 可能为字符串 "1")
  935. if tonumber(human.db.mtSubscribe) ~= 1 or not isSubscribeRewardInValidPeriod(human) then
  936. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardGet] 渠道17订阅未激活或已过期,无法领取: account="..(account or "nil"))
  937. return Broadcast.sendErr(human, "订阅未激活或已过期")
  938. end
  939. end
  940. BagLogic.cleanMomentItemList()
  941. -- 根据渠道ID发放不同的奖励(循环处理所有奖励)
  942. local rewardConfig = getDailyFixedRewardConfig(channelId)
  943. for i = 1, #rewardConfig do
  944. BagLogic.updateMomentItem(BagLogic.ADDITEM_TYPE_1, rewardConfig[i][1], rewardConfig[i][2])
  945. end
  946. -- 复用已有的日志类型,避免未定义的logType导致断言
  947. local success, err = pcall(function()
  948. BagLogic.addMomentItemList(human, "zhuanpan_once_reward")
  949. end)
  950. if not success then
  951. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardGet] 错误: 添加到背包失败: "..(err or "unknown"))
  952. return Broadcast.sendErr(human, "发放奖励失败")
  953. end
  954. -- 记录领取时间
  955. local nowTime = os.time()
  956. human.db.zhuanpan.dailyFixedReward.getTime = nowTime
  957. -- 渠道17:领取成功后,消耗当天的2楼登录资格,防止同日重复触发
  958. if channelId == 17 then
  959. human.db.mtFrom2floor = 0
  960. end
  961. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardGet] 领取成功 account=" .. tostring(human.db.account) .. " channelId=" .. tostring(channelId) .. " getTime=" .. tostring(nowTime) .. " mtFrom2floor=" .. tostring(human.db.mtFrom2floor))
  962. -- 领取成功后下发查询协议
  963. local querySuccess, queryErr = pcall(function()
  964. dailyFixedRewardQuery(human)
  965. end)
  966. if not querySuccess then
  967. Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardGet] 错误: 发送查询协议失败: "..(queryErr or "unknown"))
  968. -- 即使查询协议发送失败,奖励已经发放,所以不返回错误
  969. end
  970. -- Log.write(Log.LOGID_DEBUG, "[dailyFixedRewardGet] 领取完成")
  971. end
  972. -- 抖音渠道一次性奖励查询
  973. function onceRewardQuery(human)
  974. local msgRet = Msg.gc.GC_ZHUANPAN_ONCE_REWARD_QUERY
  975. if not msgRet then
  976. Log.write(Log.LOGID_DEBUG, "[onceRewardQuery] 错误: msgRet为nil")
  977. return
  978. end
  979. -- 初始化数据库
  980. human.db.zhuanpan = human.db.zhuanpan or {}
  981. human.db.zhuanpan.onceReward = human.db.zhuanpan.onceReward or {}
  982. -- 账号级别判断:先检查当前角色的内存数据,再检查数据库
  983. local account = human.db.account
  984. local isReceived = false
  985. -- 先检查当前角色的内存数据
  986. local getTime = human.db.zhuanpan.onceReward.getTime
  987. if getTime then
  988. isReceived = true
  989. else
  990. -- 再检查账号下其他角色(数据库)
  991. isReceived = checkAccountOnceReward(account)
  992. end
  993. if isReceived then
  994. msgRet.status = 2 -- 已领取(账号级别)
  995. else
  996. msgRet.status = 1 -- 可领取
  997. end
  998. -- 设置奖励物品列表:[[102,500],[118,10],[111,100000]]
  999. local success, err = pcall(function()
  1000. Grid.makeItem(msgRet.reward[1], 102, 500)
  1001. Grid.makeItem(msgRet.reward[2], 118, 10)
  1002. Grid.makeItem(msgRet.reward[3], 111, 100000)
  1003. msgRet.reward[0] = 3 -- 设置数组长度
  1004. end)
  1005. if not success then
  1006. Log.write(Log.LOGID_DEBUG, "[onceRewardQuery] 错误: 设置奖励物品失败: "..tostring(err))
  1007. return
  1008. end
  1009. if human.fd then
  1010. Msg.send(msgRet, human.fd)
  1011. end
  1012. end
  1013. -- 抖音渠道一次性奖励领取
  1014. function onceRewardGet(human, channelId)
  1015. if not ALLOW_CHANNELS[channelId] then
  1016. Log.write(
  1017. Log.LOGID_DEBUG,
  1018. "[onceRewardGet] 渠道不匹配: channelId=" .. (channelId or "nil") .. ", 允许=11,12"
  1019. )
  1020. return Broadcast.sendErr(human, "渠道不匹配")
  1021. end
  1022. -- 初始化数据库
  1023. human.db.zhuanpan = human.db.zhuanpan or {}
  1024. human.db.zhuanpan.onceReward = human.db.zhuanpan.onceReward or {}
  1025. -- 账号级别判断:先检查当前角色的内存数据,再检查数据库
  1026. local account = human.db.account
  1027. local isReceived = false
  1028. -- 先检查当前角色的内存数据
  1029. local getTime = human.db.zhuanpan.onceReward.getTime
  1030. if getTime then
  1031. isReceived = true
  1032. else
  1033. -- 再检查账号下其他角色(数据库)
  1034. isReceived = checkAccountOnceReward(account)
  1035. end
  1036. if isReceived then
  1037. Log.write(Log.LOGID_DEBUG, "[onceRewardGet] 账号已领取过,无法重复领取: account="..(account or "nil"))
  1038. return Broadcast.sendErr(human, "已领取过,无法重复领取")
  1039. end
  1040. BagLogic.cleanMomentItemList()
  1041. -- 发放奖励:[[102,500],[118,10],[111,100000]]
  1042. BagLogic.updateMomentItem(BagLogic.ADDITEM_TYPE_1, 102, 500)
  1043. BagLogic.updateMomentItem(BagLogic.ADDITEM_TYPE_1, 118, 10)
  1044. BagLogic.updateMomentItem(BagLogic.ADDITEM_TYPE_1, 111, 100000)
  1045. local success, err = pcall(function()
  1046. BagLogic.addMomentItemList(human, "zhuanpan_once_reward")
  1047. end)
  1048. if not success then
  1049. Log.write(Log.LOGID_DEBUG, "[onceRewardGet] 错误: 添加到背包失败: "..(err or "unknown"))
  1050. return Broadcast.sendErr(human, "发放奖励失败")
  1051. end
  1052. -- 记录领取时间(永久记录)
  1053. human.db.zhuanpan.onceReward.getTime = os.time()
  1054. local querySuccess, queryErr = pcall(function()
  1055. onceRewardQuery(human)
  1056. end)
  1057. if not querySuccess then
  1058. Log.write(Log.LOGID_DEBUG, "[onceRewardGet] 错误: 发送查询协议失败: "..(queryErr or "unknown"))
  1059. -- 即使查询协议发送失败,奖励已经发放,所以不返回错误
  1060. end
  1061. end
  1062. -- 检查当前角色订阅奖励是否在7日有效期内(从订阅奖励领取时间起算)
  1063. function isSubscribeRewardInValidPeriod(human)
  1064. if not human or not human.db then
  1065. return false
  1066. end
  1067. local zhuanpan = human.db.zhuanpan
  1068. if not zhuanpan or not zhuanpan.subscribeReward or not zhuanpan.subscribeReward.getTime then
  1069. return false
  1070. end
  1071. local activateTime = zhuanpan.subscribeReward.getTime
  1072. local activateDayStart = Util.getDayStartTime(activateTime)
  1073. local nowTs = os.time()
  1074. local todayDayStart = Util.getDayStartTime(nowTs)
  1075. -- 激活日为第1天,7日内有效
  1076. local daysSinceActivate = math.floor((todayDayStart - activateDayStart) / 86400) + 1
  1077. return daysSinceActivate <= 7
  1078. end
  1079. -- 检查美团2楼玩家每日固定奖励领取情况(晚上11点调用)
  1080. function checkMtFrom2floorDailyReward()
  1081. if _G.is_middle == true then
  1082. return
  1083. end
  1084. local QueryMtFrom2floor = {mtFrom2floor = 1}
  1085. local fields = {zhuanpan = 1, createTime = 1, mtSubscribe = 1, account = 1}
  1086. LuaMongo.find(DB.db_char, QueryMtFrom2floor, fields)
  1087. local now = os.time()
  1088. local todayDayStart = Util.getDayStartTime(now)
  1089. local dailyMailSentCount = 0
  1090. local subscribeMailSentCount = 0
  1091. while true do
  1092. local data = {}
  1093. if not LuaMongo.next(data) then
  1094. break
  1095. end
  1096. -- 检查是否在订阅有效期内(如果从未激活订阅奖励,视为未激活,不发每日固定奖励)
  1097. if data.mtSubscribe ~= 1 then
  1098. goto continue
  1099. end
  1100. local inValidPeriod = false
  1101. if data.zhuanpan and data.zhuanpan.subscribeReward and data.zhuanpan.subscribeReward.getTime then
  1102. local activateTime = data.zhuanpan.subscribeReward.getTime
  1103. local activateDayStart = Util.getDayStartTime(activateTime)
  1104. local daysSinceActivate = math.floor((todayDayStart - activateDayStart) / 86400) + 1
  1105. inValidPeriod = (daysSinceActivate <= 7)
  1106. end
  1107. -- 订阅奖励未激活或已过期,则不发每日固定奖励
  1108. if not inValidPeriod then
  1109. goto continue
  1110. end
  1111. -- 检查今天是否已领取每日固定奖励
  1112. local hasReceivedToday = false
  1113. if data.zhuanpan and data.zhuanpan.dailyFixedReward then
  1114. local getTime = data.zhuanpan.dailyFixedReward.getTime
  1115. if getTime and Util.isSameDay(getTime) then
  1116. hasReceivedToday = true
  1117. end
  1118. end
  1119. -- 如果今天没领取,发送邮件,并将 mtFrom2floor 置为0,防止当天再次通过登录触发
  1120. if not hasReceivedToday then
  1121. local title = "每日固定奖励提醒"
  1122. local content = "您今日尚未领取每日固定奖励,请及时领取!"
  1123. local rewardItems = {{101, 20000}, {111, 5000}} -- 渠道17的奖励
  1124. local success, err = pcall(function()
  1125. MailManager.add(MailManager.SYSTEM, data._id, title, content, rewardItems)
  1126. -- 更新数据库:标记今日已通过邮件发放,并清除当天的2楼标记
  1127. local updateFields = {
  1128. ["zhuanpan.dailyFixedReward.getTime"] = now,
  1129. ["mtFrom2floor"] = 0,
  1130. }
  1131. LuaMongo.update(DB.db_char, {_id = data._id}, updateFields, false, false)
  1132. end)
  1133. if success then
  1134. dailyMailSentCount = dailyMailSentCount + 1
  1135. Log.write(Log.LOGID_DEBUG, "[checkMtFrom2floorDailyReward] 发送每日固定奖励邮件并更新状态成功: uuid="..data._id)
  1136. else
  1137. Log.write(Log.LOGID_DEBUG, "[checkMtFrom2floorDailyReward] 发送每日固定奖励邮件或更新状态失败: uuid="..data._id..", err="..tostring(err))
  1138. end
  1139. end
  1140. -- 检查订阅奖励:如果已订阅(mtSubscribe == 1)且未领取,发送邮件
  1141. if data.mtSubscribe == 1 then
  1142. -- 检查账号下是否已领取订阅奖励
  1143. local hasReceivedSubscribe = checkAccountSubscribeReward(data.account)
  1144. if not hasReceivedSubscribe then
  1145. local title = "订阅奖励提醒"
  1146. local content = "您已订阅但尚未领取订阅奖励,请及时领取!"
  1147. local rewardItems = {{101, 50000}, {112, 100}} -- 订阅奖励
  1148. local success, err = pcall(function()
  1149. MailManager.add(MailManager.SYSTEM, data._id, title, content, rewardItems)
  1150. end)
  1151. if success then
  1152. subscribeMailSentCount = subscribeMailSentCount + 1
  1153. Log.write(Log.LOGID_DEBUG, "[checkMtFrom2floorDailyReward] 发送订阅奖励邮件成功: uuid="..data._id)
  1154. else
  1155. Log.write(Log.LOGID_DEBUG, "[checkMtFrom2floorDailyReward] 发送订阅奖励邮件失败: uuid="..data._id..", err="..tostring(err))
  1156. end
  1157. end
  1158. end
  1159. ::continue::
  1160. end
  1161. Log.write(Log.LOGID_DEBUG, "[checkMtFrom2floorDailyReward] 检查完成,每日固定奖励邮件数量: "..dailyMailSentCount..", 订阅奖励邮件数量: "..subscribeMailSentCount)
  1162. end
  1163. -- 美团订阅奖励查询(同时接收并存储订阅状态)
  1164. function subscribeRewardQuery(human, msg)
  1165. local msgRet = Msg.gc.GC_ZHUANPAN_SUBSCRIBE_REWARD_QUERY
  1166. if not msgRet then
  1167. Log.write(Log.LOGID_DEBUG, "[subscribeRewardQuery] 错误: msgRet为nil")
  1168. return
  1169. end
  1170. -- 如果前端上传了订阅状态,则进行存储
  1171. if msg and msg.mtSubscribe ~= nil then
  1172. local val = tonumber(msg.mtSubscribe) or 0
  1173. -- 只从 0 -> 1,避免重复覆盖或回退
  1174. if val == 1 and human.db then
  1175. human.db.mtSubscribe = human.db.mtSubscribe or 0
  1176. if human.db.mtSubscribe ~= 1 then
  1177. human.db.mtSubscribe = 1
  1178. Log.write(Log.LOGID_DEBUG, "[subscribeRewardQuery] 更新订阅状态为1, account="..tostring(human.db.account))
  1179. end
  1180. end
  1181. end
  1182. -- 初始化数据库
  1183. human.db.zhuanpan = human.db.zhuanpan or {}
  1184. human.db.zhuanpan.subscribeReward = human.db.zhuanpan.subscribeReward or {}
  1185. -- 检查是否订阅(mtSubscribe == 1)
  1186. local isSubscribed = (human.db.mtSubscribe == 1)
  1187. -- 账号级别判断:先检查当前角色的内存数据,再检查数据库
  1188. local account = human.db.account
  1189. local isReceived = false
  1190. if isSubscribed then
  1191. -- 先检查当前角色的内存数据
  1192. local getTime = human.db.zhuanpan.subscribeReward.getTime
  1193. if getTime then
  1194. isReceived = true
  1195. else
  1196. -- 再检查账号下其他角色(数据库)
  1197. isReceived = checkAccountSubscribeReward(account)
  1198. end
  1199. end
  1200. if not isSubscribed then
  1201. msgRet.status = 0 -- 不可领取(未订阅)
  1202. elseif isReceived then
  1203. msgRet.status = 2 -- 已领取
  1204. else
  1205. msgRet.status = 1 -- 可领取
  1206. end
  1207. -- 设置奖励物品列表:[[101,50000],[112,100]]
  1208. local success, err = pcall(function()
  1209. Grid.makeItem(msgRet.reward[1], 101, 50000)
  1210. Grid.makeItem(msgRet.reward[2], 112, 100)
  1211. msgRet.reward[0] = 2 -- 设置数组长度
  1212. end)
  1213. if not success then
  1214. Log.write(Log.LOGID_DEBUG, "[subscribeRewardQuery] 错误: 设置奖励物品失败: "..tostring(err))
  1215. return
  1216. end
  1217. if human.fd then
  1218. Msg.send(msgRet, human.fd)
  1219. end
  1220. end
  1221. -- 美团订阅奖励领取
  1222. function subscribeRewardGet(human, channelId)
  1223. -- 检查渠道,只有渠道ID=17(美团2楼)才能领取
  1224. if not channelId or channelId ~= 17 then
  1225. Log.write(Log.LOGID_DEBUG, "[subscribeRewardGet] 渠道不匹配: channelId="..(channelId or "nil")..", 需要=18")
  1226. return Broadcast.sendErr(human, "渠道不匹配")
  1227. end
  1228. -- 检查是否订阅(mtSubscribe == 1)
  1229. if human.db.mtSubscribe ~= 1 then
  1230. Log.write(Log.LOGID_DEBUG, "[subscribeRewardGet] 未订阅: mtSubscribe="..(human.db.mtSubscribe or "nil"))
  1231. return Broadcast.sendErr(human, "未订阅,无法领取")
  1232. end
  1233. -- 初始化数据库
  1234. human.db.zhuanpan = human.db.zhuanpan or {}
  1235. human.db.zhuanpan.subscribeReward = human.db.zhuanpan.subscribeReward or {}
  1236. -- 账号级别判断:先检查当前角色的内存数据,再检查数据库
  1237. local account = human.db.account
  1238. local isReceived = false
  1239. -- 先检查当前角色的内存数据
  1240. local getTime = human.db.zhuanpan.subscribeReward.getTime
  1241. if getTime then
  1242. isReceived = true
  1243. else
  1244. -- 再检查账号下其他角色(数据库)
  1245. isReceived = checkAccountSubscribeReward(account)
  1246. end
  1247. if isReceived then
  1248. Log.write(Log.LOGID_DEBUG, "[subscribeRewardGet] 账号已领取过,无法重复领取: account="..(account or "nil"))
  1249. return Broadcast.sendErr(human, "已领取过,无法重复领取")
  1250. end
  1251. BagLogic.cleanMomentItemList()
  1252. -- 发放奖励:[[101,50000],[112,100]]
  1253. BagLogic.updateMomentItem(BagLogic.ADDITEM_TYPE_1, 101, 50000)
  1254. BagLogic.updateMomentItem(BagLogic.ADDITEM_TYPE_1, 112, 100)
  1255. -- 使用已存在的日志类型,避免日志定义缺失导致的断言
  1256. local success, err = pcall(function()
  1257. BagLogic.addMomentItemList(human, "zhuanpan_once_reward")
  1258. end)
  1259. if not success then
  1260. Log.write(Log.LOGID_DEBUG, "[subscribeRewardGet] 错误: 添加到背包失败: "..(err or "unknown"))
  1261. return Broadcast.sendErr(human, "发放奖励失败")
  1262. end
  1263. -- 记录领取时间(永久记录)
  1264. human.db.zhuanpan.subscribeReward.getTime = os.time()
  1265. local querySuccess, queryErr = pcall(function()
  1266. subscribeRewardQuery(human)
  1267. end)
  1268. if not querySuccess then
  1269. Log.write(Log.LOGID_DEBUG, "[subscribeRewardGet] 错误: 发送订阅奖励查询协议失败: "..(queryErr or "unknown"))
  1270. -- 即使查询协议发送失败,奖励已经发放,所以不返回错误
  1271. end
  1272. -- 领取订阅奖励后,同时下发每日固定奖励查询协议
  1273. local dailyQuerySuccess, dailyQueryErr = pcall(function()
  1274. dailyFixedRewardQuery(human)
  1275. end)
  1276. if not dailyQuerySuccess then
  1277. Log.write(Log.LOGID_DEBUG, "[subscribeRewardGet] 错误: 发送每日固定奖励查询协议失败: "..(dailyQueryErr or "unknown"))
  1278. -- 即使查询协议发送失败,奖励已经发放,所以不返回错误
  1279. end
  1280. end
  1281. -----------------------淘宝小程序桌面活动-----------------------
  1282. -- 奖励配置(占位,按需修改)
  1283. local TB_ENTER_REWARD = {{112, 100}} -- 桌面进入奖励(每日1次)
  1284. local TB_SECOND_FLOOR_REWARD = {{127, 10}} -- 二楼进入奖励(每日1次)
  1285. local TB_DESKTOP_REWARD = {{118, 5}} -- 添加桌面奖励(仅1次)
  1286. -- 渠道校验:仅 pf == "tbMiniGame" 的玩家可参与
  1287. local function isTbMiniApp(human)
  1288. return human.pf_info and human.pf_info.pf == "tbMiniGame"
  1289. end
  1290. -- 淘宝小程序桌面活动查询
  1291. -- status: 1=桌面进入 2=二楼进入
  1292. function tbminiappQuery(human, status)
  1293. Log.write(Log.LOGID_DEBUG, "[tbminiappQuery] 收到请求 account=" .. tostring(human and human.db and human.db.account)
  1294. .. " pf=" .. tostring(human and human.pf)
  1295. .. " status=" .. tostring(status))
  1296. local msgRet = Msg.gc.GC_ZHUANPAN_TB_QUERY
  1297. if not msgRet then
  1298. Log.write(Log.LOGID_DEBUG, "[tbminiappQuery] 错误: msgRet为nil")
  1299. return
  1300. end
  1301. if not isTbMiniApp(human) then
  1302. Log.write(Log.LOGID_DEBUG, "[tbminiappQuery] 渠道不匹配 pf=" .. tostring(human and human.pf))
  1303. return Broadcast.sendErr(human, "渠道不匹配")
  1304. end
  1305. ObjHuman.updateDaily(human)
  1306. human.db.zhuanpan = human.db.zhuanpan or {}
  1307. human.db.zhuanpan.tbminiapp = human.db.zhuanpan.tbminiapp or {}
  1308. local tb = human.db.zhuanpan.tbminiapp
  1309. -- 是否已添加桌面
  1310. msgRet.isDesktopAdded = tb.desktopAdded and 1 or 0
  1311. -- 是否已领取添加桌面奖励(一次性)
  1312. msgRet.isDesktopRewardReceived = (tb.desktopReward and tb.desktopReward.getTime) and 1 or 0
  1313. -- 是否已领取桌面进入奖励(每日1次)
  1314. local enterTime = tb.enterReward and tb.enterReward.getTime
  1315. msgRet.isEnterRewardReceived = (enterTime and Util.isSameDay(enterTime)) and 1 or 0
  1316. -- 是否已领取二楼进入奖励(每日1次)
  1317. local floorTime = tb.floorReward and tb.floorReward.getTime
  1318. msgRet.isFloorRewardReceived = (floorTime and Util.isSameDay(floorTime)) and 1 or 0
  1319. -- 填充奖励道具信息
  1320. local ok, err = pcall(function()
  1321. Grid.makeItem(msgRet.enterReward, TB_ENTER_REWARD[1][1], TB_ENTER_REWARD[1][2])
  1322. Grid.makeItem(msgRet.floorReward, TB_SECOND_FLOOR_REWARD[1][1], TB_SECOND_FLOOR_REWARD[1][2])
  1323. Grid.makeItem(msgRet.desktopReward, TB_DESKTOP_REWARD[1][1], TB_DESKTOP_REWARD[1][2])
  1324. end)
  1325. if not ok then
  1326. Log.write(Log.LOGID_DEBUG, "[tbminiappQuery] 错误: Grid.makeItem失败: " .. tostring(err))
  1327. return
  1328. end
  1329. Log.write(Log.LOGID_DEBUG, "[tbminiappQuery] 准备发送"
  1330. .. " isDesktopAdded=" .. tostring(msgRet.isDesktopAdded)
  1331. .. " isDesktopRewardReceived=" .. tostring(msgRet.isDesktopRewardReceived)
  1332. .. " isEnterRewardReceived=" .. tostring(msgRet.isEnterRewardReceived)
  1333. .. " isFloorRewardReceived=" .. tostring(msgRet.isFloorRewardReceived)
  1334. .. " fd=" .. tostring(human.fd))
  1335. if human.fd then
  1336. Msg.send(msgRet, human.fd)
  1337. Log.write(Log.LOGID_DEBUG, "[tbminiappQuery] 发送成功 account=" .. tostring(human.db.account))
  1338. else
  1339. Log.write(Log.LOGID_DEBUG, "[tbminiappQuery] 错误: human.fd为nil,无法发送协议 account=" .. tostring(human.db.account))
  1340. end
  1341. end
  1342. -- 淘宝小程序添加桌面上报:记录添加状态
  1343. function tbminiappAddDesktop(human)
  1344. if not isTbMiniApp(human) then
  1345. return Broadcast.sendErr(human, "渠道不匹配")
  1346. end
  1347. human.db.zhuanpan = human.db.zhuanpan or {}
  1348. human.db.zhuanpan.tbminiapp = human.db.zhuanpan.tbminiapp or {}
  1349. human.db.zhuanpan.tbminiapp.desktopAdded = true
  1350. Log.write(Log.LOGID_DEBUG, "[tbminiappAddDesktop] 添加桌面成功 account=" .. tostring(human.db.account))
  1351. local querySuccess, queryErr = pcall(function()
  1352. tbminiappQuery(human, 0)
  1353. end)
  1354. if not querySuccess then
  1355. Log.write(Log.LOGID_DEBUG, "[tbminiappAddDesktop] 错误: 发送查询协议失败: "..(queryErr or "unknown"))
  1356. end
  1357. end
  1358. -- 淘宝小程序活动奖励领取
  1359. -- status: 1=桌面进入奖励(每日1次)2=二楼进入奖励(每日1次)3=添加桌面奖励(仅1次)
  1360. function tbminiappRewardGet(human, status)
  1361. if not isTbMiniApp(human) then
  1362. return Broadcast.sendErr(human, "渠道不匹配")
  1363. end
  1364. ObjHuman.updateDaily(human)
  1365. human.db.zhuanpan = human.db.zhuanpan or {}
  1366. human.db.zhuanpan.tbminiapp = human.db.zhuanpan.tbminiapp or {}
  1367. local tb = human.db.zhuanpan.tbminiapp
  1368. local rewardConfig = nil
  1369. if status == 1 then
  1370. -- 桌面进入奖励(每日1次)
  1371. local enterTime = tb.enterReward and tb.enterReward.getTime
  1372. if enterTime and Util.isSameDay(enterTime) then
  1373. Log.write(Log.LOGID_DEBUG, "[tbminiappRewardGet] 今日已领取桌面进入奖励 account=" .. tostring(human.db.account))
  1374. return Broadcast.sendErr(human, "今日已领取桌面进入奖励")
  1375. end
  1376. rewardConfig = TB_ENTER_REWARD
  1377. elseif status == 2 then
  1378. -- 二楼进入奖励(每日1次)
  1379. local floorTime = tb.floorReward and tb.floorReward.getTime
  1380. if floorTime and Util.isSameDay(floorTime) then
  1381. Log.write(Log.LOGID_DEBUG, "[tbminiappRewardGet] 今日已领取二楼进入奖励 account=" .. tostring(human.db.account))
  1382. return Broadcast.sendErr(human, "今日已领取二楼进入奖励")
  1383. end
  1384. rewardConfig = TB_SECOND_FLOOR_REWARD
  1385. elseif status == 3 then
  1386. -- 添加桌面奖励(仅1次)
  1387. if not tb.desktopAdded then
  1388. Log.write(Log.LOGID_DEBUG, "[tbminiappRewardGet] 尚未添加桌面 account=" .. tostring(human.db.account))
  1389. return Broadcast.sendErr(human, "尚未添加桌面")
  1390. end
  1391. if tb.desktopReward and tb.desktopReward.getTime then
  1392. Log.write(Log.LOGID_DEBUG, "[tbminiappRewardGet] 添加桌面奖励已领取 account=" .. tostring(human.db.account))
  1393. return Broadcast.sendErr(human, "添加桌面奖励已领取")
  1394. end
  1395. rewardConfig = TB_DESKTOP_REWARD
  1396. else
  1397. return Broadcast.sendErr(human, "无效的status参数")
  1398. end
  1399. -- 发放奖励
  1400. BagLogic.cleanMomentItemList()
  1401. for _, v in ipairs(rewardConfig) do
  1402. BagLogic.updateMomentItem(BagLogic.ADDITEM_TYPE_1, v[1], v[2])
  1403. end
  1404. local success, err = pcall(function()
  1405. BagLogic.addMomentItemList(human, "zhuanpan_once_reward")
  1406. end)
  1407. if not success then
  1408. Log.write(Log.LOGID_DEBUG, "[tbminiappRewardGet] 错误: 添加到背包失败: "..(err or "unknown"))
  1409. return Broadcast.sendErr(human, "发放奖励失败")
  1410. end
  1411. -- 记录领取时间
  1412. local nowTime = os.time()
  1413. if status == 1 then
  1414. tb.enterReward = tb.enterReward or {}
  1415. tb.enterReward.getTime = nowTime
  1416. elseif status == 2 then
  1417. tb.floorReward = tb.floorReward or {}
  1418. tb.floorReward.getTime = nowTime
  1419. elseif status == 3 then
  1420. tb.desktopReward = tb.desktopReward or {}
  1421. tb.desktopReward.getTime = nowTime
  1422. end
  1423. Log.write(Log.LOGID_DEBUG, "[tbminiappRewardGet] 领取成功 status=" .. tostring(status) .. " account=" .. tostring(human.db.account))
  1424. -- 下发查询协议
  1425. local querySuccess, queryErr = pcall(function()
  1426. tbminiappQuery(human, 0)
  1427. end)
  1428. if not querySuccess then
  1429. Log.write(Log.LOGID_DEBUG, "[tbminiappRewardGet] 错误: 发送查询协议失败: "..(queryErr or "unknown"))
  1430. end
  1431. end
  1432. -----------------------游戏圈任务-----------------------
  1433. -- 游戏圈任务配置
  1434. -- reward: {itemId, count} target: 完成目标数量 type: "once"永久/"daily"每日/"weekly"每周
  1435. local YOUXI_TASK_CONFIG = {
  1436. [1] = { reward = {118, 10}, target = 1, taskType = "once" }, -- 首次加入游戏圈: 10连抽
  1437. [2] = { reward = {117, 1}, target = 1, taskType = "daily" }, -- 今日点赞1次: 金币100
  1438. [3] = { reward = {117, 1}, target = 1, taskType = "daily" }, -- 今日发表评论1次: 金币100
  1439. [4] = { reward = {117, 5}, target = 10, taskType = "weekly" }, -- 每周点赞10次: 金币100
  1440. [5] = { reward = {117, 5}, target = 20, taskType = "weekly" }, -- 每周发表评论20次: 金币100
  1441. }
  1442. -- 获取本周一0点时间戳
  1443. local function getWeekStartTime()
  1444. local now = os.time()
  1445. local t = os.date("*t", now)
  1446. local daysFromMonday = (t.wday - 2) % 7 -- wday: 1=Sun, 2=Mon
  1447. local todayStart = Util.getDayStartTime(now)
  1448. return todayStart - daysFromMonday * 86400
  1449. end
  1450. -- 判断时间戳是否在本周(本周一0点)之后
  1451. local function isCurrentWeek(timestamp)
  1452. if not timestamp then return false end
  1453. return timestamp >= getWeekStartTime()
  1454. end
  1455. -- 更新每日 SDK 进度(当天自然日,同天取最大值;跨天把昨天 count 累加入本周合计)
  1456. -- weekTotal 始终不含当天,getWeekProgress 统一加上今日 count
  1457. local function updateDailyCount(field, newCount)
  1458. field = field or {}
  1459. local now = os.time()
  1460. if field.dayTime and Util.isSameDay(field.dayTime) then
  1461. -- 同一天:仅在 newCount > 0 时更新;weekTotal 不动(不含今天)
  1462. if newCount > 0 then
  1463. field.count = newCount
  1464. end
  1465. else
  1466. -- 新的一天:把昨天的 count 累加到本周合计,重置今天的记录
  1467. local weekTotal = field.weekTotal or 0
  1468. if field.weekTime and isCurrentWeek(field.weekTime) then
  1469. -- 同一周:把昨天(或更早今天之前)的 count 并入 weekTotal
  1470. field.weekTotal = weekTotal + (field.count or 0)
  1471. else
  1472. -- 新的一周:重置,weekTotal 不含今天
  1473. field.weekTotal = 0
  1474. end
  1475. field.count = newCount
  1476. field.dayTime = now
  1477. field.weekTime = now
  1478. end
  1479. return field
  1480. end
  1481. -- 获取本周累计进度:weekTotal(不含今天)+ 今日 count
  1482. local function getWeekProgress(field)
  1483. if not field then return 0 end
  1484. local weekTotal = 0
  1485. if field.weekTime and isCurrentWeek(field.weekTime) then
  1486. weekTotal = field.weekTotal or 0
  1487. end
  1488. -- 今天的 count 始终不在 weekTotal 里,直接加上
  1489. if field.dayTime and Util.isSameDay(field.dayTime) then
  1490. return weekTotal + (field.count or 0)
  1491. end
  1492. return weekTotal
  1493. end
  1494. -- 检查账号下是否有任何角色已领取指定游戏圈任务(账号级别判断)
  1495. local function checkAccountYouxiTaskClaimed(account, taskId)
  1496. if not account then return false end
  1497. local config = YOUXI_TASK_CONFIG[taskId]
  1498. if not config then return false end
  1499. LuaMongo.find(DB.db_char, {account = account}, {zhuanpan = 1})
  1500. while true do
  1501. local data = {}
  1502. if not LuaMongo.next(data) then break end
  1503. local yt = data.zhuanpan and data.zhuanpan.youxiTask
  1504. if yt then
  1505. if config.taskType == "once" then
  1506. if yt.joinGetTime then return true end
  1507. elseif config.taskType == "daily" then
  1508. local field = (taskId == 2) and yt.dailyLike or yt.dailyComment
  1509. if field and field.getTime and Util.isSameDay(field.getTime) then return true end
  1510. elseif config.taskType == "weekly" then
  1511. local field = (taskId == 4) and yt.dailyLike or yt.dailyComment
  1512. if field and field.weekGetTime and isCurrentWeek(field.weekGetTime) then return true end
  1513. end
  1514. end
  1515. end
  1516. return false
  1517. end
  1518. -- 游戏圈任务查询(前端上传 SDK 数据,后端存储并计算进度)
  1519. function youxiTaskQuery(human, msg)
  1520. local msgRet = Msg.gc.GC_ZHUANPAN_YOUXI_TASK_QUERY
  1521. if not msgRet then
  1522. Log.write(Log.LOGID_DEBUG, "[youxiTaskQuery] 错误: msgRet为nil")
  1523. return
  1524. end
  1525. human.db.zhuanpan = human.db.zhuanpan or {}
  1526. human.db.zhuanpan.youxiTask = human.db.zhuanpan.youxiTask or {}
  1527. local yt = human.db.zhuanpan.youxiTask
  1528. -- 存储 SDK 上报数据并更新进度
  1529. if msg then
  1530. -- 任务1:加入游戏圈(joinTime > 0 表示已加入)
  1531. if msg.joinTime and msg.joinTime > 0 and not yt.joined then
  1532. yt.joined = true
  1533. end
  1534. -- 任务2/4:点赞(count=0 时也需调用,以便跨天时将昨日 count 累入 weekTotal)
  1535. if msg.likeCount ~= nil then
  1536. yt.dailyLike = updateDailyCount(yt.dailyLike, msg.likeCount)
  1537. end
  1538. -- 任务3/5:评论(同上)
  1539. if msg.commentCount ~= nil then
  1540. yt.dailyComment = updateDailyCount(yt.dailyComment, msg.commentCount)
  1541. end
  1542. end
  1543. local ok, err = pcall(function()
  1544. for taskId = 1, 5 do
  1545. local config = YOUXI_TASK_CONFIG[taskId]
  1546. local taskData = msgRet.tasks[taskId]
  1547. taskData.taskId = taskId
  1548. taskData.target = config.target
  1549. Grid.makeItem(taskData.reward, config.reward[1], config.reward[2])
  1550. if config.taskType == "once" then
  1551. taskData.progress = yt.joined and 1 or 0
  1552. local claimed = yt.joinGetTime or checkAccountYouxiTaskClaimed(human.db.account, taskId)
  1553. if claimed then
  1554. taskData.status = 2
  1555. elseif yt.joined then
  1556. taskData.status = 1
  1557. else
  1558. taskData.status = 0
  1559. end
  1560. elseif config.taskType == "daily" then
  1561. local field = (taskId == 2) and yt.dailyLike or yt.dailyComment
  1562. local dayCount = (field and field.dayTime and Util.isSameDay(field.dayTime)) and (field.count or 0) or 0
  1563. taskData.progress = math.min(dayCount, config.target)
  1564. local getTime = field and field.getTime
  1565. local claimed = (getTime and Util.isSameDay(getTime)) or checkAccountYouxiTaskClaimed(human.db.account, taskId)
  1566. if claimed then
  1567. taskData.status = 2
  1568. elseif dayCount >= config.target then
  1569. taskData.status = 1
  1570. else
  1571. taskData.status = 0
  1572. end
  1573. elseif config.taskType == "weekly" then
  1574. local field = (taskId == 4) and yt.dailyLike or yt.dailyComment
  1575. local weekCount = getWeekProgress(field)
  1576. taskData.progress = math.min(weekCount, config.target)
  1577. local weekGetTime = field and field.weekGetTime
  1578. local claimed = (weekGetTime and isCurrentWeek(weekGetTime)) or checkAccountYouxiTaskClaimed(human.db.account, taskId)
  1579. if claimed then
  1580. taskData.status = 2
  1581. elseif weekCount >= config.target then
  1582. taskData.status = 1
  1583. else
  1584. taskData.status = 0
  1585. end
  1586. end
  1587. end
  1588. msgRet.tasks[0] = 5
  1589. end)
  1590. if not ok then
  1591. Log.write(Log.LOGID_DEBUG, "[youxiTaskQuery] 错误: " .. tostring(err))
  1592. return
  1593. end
  1594. if human.fd then
  1595. Msg.send(msgRet, human.fd)
  1596. end
  1597. end
  1598. -- 游戏圈任务领取(前端协议调用)
  1599. -- taskId: 1-5
  1600. function youxiTaskGetReward(human, taskId)
  1601. local config = YOUXI_TASK_CONFIG[taskId]
  1602. if not config then
  1603. Log.write(Log.LOGID_DEBUG, "[youxiTaskGetReward] 无效taskId=" .. tostring(taskId))
  1604. return Broadcast.sendErr(human, "无效的任务ID")
  1605. end
  1606. human.db.zhuanpan = human.db.zhuanpan or {}
  1607. human.db.zhuanpan.youxiTask = human.db.zhuanpan.youxiTask or {}
  1608. local yt = human.db.zhuanpan.youxiTask
  1609. local now = os.time()
  1610. -- 校验条件 & 重复领取(账号级别判断,同账号多角色共享)
  1611. -- 先查当前角色内存,没有再查 DB 其他角色(与美团订阅奖励模式一致)
  1612. local account = human.db.account
  1613. if config.taskType == "once" then
  1614. local claimed = yt.joinGetTime or checkAccountYouxiTaskClaimed(account, taskId)
  1615. if claimed then
  1616. return Broadcast.sendErr(human, "已领取过")
  1617. end
  1618. if not yt.joined then
  1619. return Broadcast.sendErr(human, "尚未加入游戏圈")
  1620. end
  1621. elseif config.taskType == "daily" then
  1622. local field = (taskId == 2) and yt.dailyLike or yt.dailyComment
  1623. local getTime = field and field.getTime
  1624. local claimed = (getTime and Util.isSameDay(getTime)) or checkAccountYouxiTaskClaimed(account, taskId)
  1625. if claimed then
  1626. return Broadcast.sendErr(human, "今日已领取")
  1627. end
  1628. local dayCount = (field and field.dayTime and Util.isSameDay(field.dayTime)) and (field.count or 0) or 0
  1629. if dayCount < config.target then
  1630. return Broadcast.sendErr(human, "任务未完成")
  1631. end
  1632. elseif config.taskType == "weekly" then
  1633. local field = (taskId == 4) and yt.dailyLike or yt.dailyComment
  1634. local weekGetTime = field and field.weekGetTime
  1635. local claimed = (weekGetTime and isCurrentWeek(weekGetTime)) or checkAccountYouxiTaskClaimed(account, taskId)
  1636. if claimed then
  1637. return Broadcast.sendErr(human, "本周已领取")
  1638. end
  1639. if getWeekProgress(field) < config.target then
  1640. return Broadcast.sendErr(human, "任务未完成")
  1641. end
  1642. end
  1643. -- 发放奖励
  1644. BagLogic.cleanMomentItemList()
  1645. BagLogic.updateMomentItem(BagLogic.ADDITEM_TYPE_1, config.reward[1], config.reward[2])
  1646. local success, err = pcall(function()
  1647. BagLogic.addMomentItemList(human, "zhuanpan_once_reward")
  1648. end)
  1649. if not success then
  1650. Log.write(Log.LOGID_DEBUG, "[youxiTaskGetReward] 发放奖励失败 task=" .. taskId .. " err=" .. tostring(err))
  1651. return Broadcast.sendErr(human, "发放奖励失败")
  1652. end
  1653. -- 记录领取时间
  1654. if config.taskType == "once" then
  1655. yt.joinGetTime = now
  1656. elseif config.taskType == "daily" then
  1657. local key = (taskId == 2) and "dailyLike" or "dailyComment"
  1658. yt[key] = yt[key] or {}
  1659. yt[key].getTime = now
  1660. elseif config.taskType == "weekly" then
  1661. local key = (taskId == 4) and "dailyLike" or "dailyComment"
  1662. yt[key] = yt[key] or {}
  1663. yt[key].weekGetTime = now
  1664. end
  1665. Log.write(Log.LOGID_DEBUG, "[youxiTaskGetReward] 领取成功 task=" .. taskId .. " account=" .. tostring(human.db.account))
  1666. -- 领取后下发最新查询(不传 msg,不更新 SDK 数据)
  1667. youxiTaskQuery(human, nil)
  1668. end
  1669. -- SDK 回调奖励发放(内部调用,与任务奖励独立)
  1670. -- items: {{itemId, count}, ...}
  1671. function youxiSdkReward(human, items)
  1672. if not items or #items == 0 then
  1673. Log.write(Log.LOGID_DEBUG, "[youxiSdkReward] items为空 account=" .. tostring(human.db.account))
  1674. return
  1675. end
  1676. BagLogic.cleanMomentItemList()
  1677. for _, v in ipairs(items) do
  1678. BagLogic.updateMomentItem(BagLogic.ADDITEM_TYPE_1, v[1], v[2])
  1679. end
  1680. local success, err = pcall(function()
  1681. BagLogic.addMomentItemList(human, "zhuanpan_once_reward")
  1682. end)
  1683. if not success then
  1684. Log.write(Log.LOGID_DEBUG, "[youxiSdkReward] 发放失败 err=" .. tostring(err) .. " account=" .. tostring(human.db.account))
  1685. else
  1686. Log.write(Log.LOGID_DEBUG, "[youxiSdkReward] 发放成功 cnt=" .. #items .. " account=" .. tostring(human.db.account))
  1687. end
  1688. end