UnionTask.lua 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. UnionTask = {}
  2. local this = {}
  3. ---@class UnionTask
  4. ---@field taskrecord table<number, UnionTaskRecord>
  5. ---@field memberrecord number[]
  6. ---@field createtime number
  7. ---@class UnionTaskRecord
  8. ---@field taskid number
  9. ---@field tasktype number
  10. ---@field taskcount number
  11. ---@field createtime string
  12. this.UNION_TASK_KEY = PlayerDefKey.UNION.UNION_TASK_KEY
  13. this.UNION_TASK_RESET_KEY = PlayerDefKey.UNION.UNION_TASK_RESET_KEY
  14. this.UNION_TASK_MAIL_ID = 207004
  15. this.UNION_TASK_SUBMIT_STRING_TIP_ID = "241"
  16. this.TASK_TARGET = {
  17. KILL_SPECIFIED_TYPE_MONSTER = 1, -- 击杀指定类型怪物
  18. KILL_SPECIFIED_MONSTER = 2, -- 击杀指定怪物
  19. FINISH_SPECIFIED_DUPLICATE = 3, -- 完成指定副本
  20. KILL_OTHER_UNION_PLAYER = 4, -- 击杀其他战盟玩家
  21. }
  22. function UnionTask.serverMiddleNight()
  23. this.middleNightResetTask()
  24. end
  25. function UnionTask.onUnionCreate(actor)
  26. this.initUnionTaskByActor(actor)
  27. end
  28. function UnionTask.onUnionClose(actor)
  29. this.clearUnionTaskData(actor)
  30. end
  31. function UnionTask.killMonsterEvent(actor, monsterCfgId)
  32. this.killMonsterEvent(actor, monsterCfgId)
  33. end
  34. function UnionTask.killPlayerEvent(actor, die_actor)
  35. this.killPlayerEvent(actor, die_actor)
  36. end
  37. function UnionTask.enterDuplicate(actor, rep_id)
  38. this.enterDuplicate(actor, rep_id)
  39. end
  40. -- -------------------------------------------------------------------------- --
  41. function this.initUnionTaskByActor(actor)
  42. local union_id = getbaseinfo(actor, "unionid")
  43. return this.initUnionTask(union_id)
  44. end
  45. function this.initUnionTask(union_id)
  46. if tonumber(union_id) < 1 then
  47. this.jprint("初始化战盟任务失败")
  48. return {}
  49. end
  50. local config_arr = ConfigDataManager.getList("cfg_gard_task")
  51. local now = getbaseinfo("now")
  52. local union_task_record = {}
  53. for _, config in pairs(config_arr) do
  54. local task_record = this.createUnionTask(config, now)
  55. union_task_record[tonumber(config.id)] = task_record
  56. end
  57. this.setUnionTask(union_id, union_task_record)
  58. this.setUnionTaskCreateData(union_id, now)
  59. return union_task_record
  60. end
  61. function this.clearUnionTaskData(actor)
  62. this.setUnionTask(actor:toString(), nil)
  63. this.setUnionTaskCreateData(actor:toString(), nil)
  64. end
  65. ---@return table<number, UnionTaskRecord>
  66. function this.getUnionTask(union_id)
  67. local union_actor = getguild(union_id)
  68. return getguilddef(union_actor, this.UNION_TASK_KEY)
  69. end
  70. function this.setUnionTask(union_id, union_task)
  71. local union_actor = getguild(union_id)
  72. setguilddef(union_actor, this.UNION_TASK_KEY, union_task)
  73. end
  74. function this.getUnionTaskCreateData(union_id)
  75. local union_actor = getguild(union_id)
  76. return getguilddef(union_actor, this.UNION_TASK_RESET_KEY)
  77. end
  78. function this.setUnionTaskCreateData(union_id, now)
  79. local union_actor = getguild(union_id)
  80. setguilddef(union_actor, this.UNION_TASK_RESET_KEY, now)
  81. end
  82. function this.createUnionTask(config, now)
  83. ---@type UnionTaskRecord
  84. local task_record = {}
  85. task_record.taskid = tonumber(config.id)
  86. task_record.tasktype = tonumber(config.tasktype)
  87. task_record.taskcount = 0
  88. task_record.createtime = tostring(now)
  89. return task_record
  90. end
  91. function this.killMonsterEvent(actor, monster_cfg_id)
  92. this.updateUnionTask(actor, this.TASK_TARGET.KILL_SPECIFIED_MONSTER, monster_cfg_id)
  93. local mon_type = ConfigDataManager.getTableValue("cfg_monster", "type", "id", monster_cfg_id)
  94. this.updateUnionTask(actor, this.TASK_TARGET.KILL_SPECIFIED_TYPE_MONSTER, mon_type)
  95. end
  96. function this.killPlayerEvent(actor, die_actor)
  97. local union_id = getbaseinfo(actor, "unionid")
  98. local target_union_id = getbaseinfo(die_actor, "unionid")
  99. if union_id == target_union_id then
  100. return
  101. end
  102. this.updateUnionTask(actor, this.TASK_TARGET.KILL_OTHER_UNION_PLAYER)
  103. end
  104. function this.enterDuplicate(actor, rep_id)
  105. local activity_id = ConfigDataManager.getTableValue("cfg_rep", "type", "id", rep_id)
  106. this.updateUnionTask(actor, this.TASK_TARGET.FINISH_SPECIFIED_DUPLICATE, tonumber(activity_id))
  107. end
  108. function this.updateUnionTask(actor, task_type, target)
  109. local union_id = getbaseinfo(actor, "unionid")
  110. if tonumber(union_id) < 1 then
  111. return
  112. end
  113. local change_ids = {}
  114. ---@type table<number, UnionTaskRecord>
  115. local union_task = this.getUnionTask(union_id)
  116. if table.isEmpty(union_task) then
  117. return
  118. end
  119. for task_id, task_record in pairs(union_task) do
  120. if tonumber(task_record.tasktype) ~= task_type then
  121. goto continue
  122. end
  123. local target_id, target_count = this.getUnionTaskTargetConfig(task_id)
  124. if target_id ~= 0 and tonumber(target) ~= target_id then
  125. goto continue
  126. end
  127. local task_count = task_record.taskcount
  128. if task_count >= target_count then
  129. goto continue
  130. end
  131. task_record.taskcount = task_count + 1
  132. change_ids[task_id] = task_record
  133. -- 发放特殊奖励
  134. if task_record.taskcount == target_count then
  135. local special_reward_str = ConfigDataManager.getTableValue("cfg_gard_task", "rewardspecial", "id", task_id)
  136. local success, result = xpcall(this.addItemToBag, debug.traceback, actor, special_reward_str)
  137. gameDebug.assertPrint(success, "特殊奖励发放失败!", result, "参数", actor:toString(), task_id)
  138. end
  139. :: continue ::
  140. end
  141. if table.isEmpty(change_ids) then
  142. return
  143. end
  144. this.setUnionTask(union_id, union_task)
  145. sendluamsg(actor, LuaMessageIdToClient.RES_UNION_TASK_CHANGE, change_ids)
  146. end
  147. function this.getUnionTaskTargetConfig(task_id)
  148. local task_target_str = ConfigDataManager.getTableValue("cfg_gard_task", "taskcontent", "id", task_id)
  149. local target_arr = string.split(task_target_str, "#")
  150. if #target_arr < 2 then
  151. return 0, tonumber(target_arr[1])
  152. end
  153. return tonumber(target_arr[1]), tonumber(target_arr[2])
  154. end
  155. function this.middleNightResetTask()
  156. local data = getallunionsummary()
  157. if table.isEmpty(data) then
  158. return
  159. end
  160. local now = tonumber(getbaseinfo("now"))
  161. for _, summary in pairs(data) do
  162. local union_id = summary.unionid
  163. local time_data = this.getUnionTaskCreateData(union_id)
  164. local create_mills = string.tonumber(time_data)
  165. local ret = this.checkTaskResetTime(create_mills, now)
  166. if not ret then
  167. goto continue
  168. end
  169. local union_data = getunioninfo(union_id)
  170. if table.isEmpty(union_data) then
  171. goto continue
  172. end
  173. local finish_task_ids = {}
  174. local task_record_map = this.getUnionTask(union_id)
  175. if not table.isEmpty(task_record_map) then
  176. for task_id, task_record in pairs(task_record_map) do
  177. local _, target_count = this.getUnionTaskTargetConfig(task_id)
  178. if task_record.taskcount >= target_count then
  179. table.insert(finish_task_ids, task_id)
  180. end
  181. end
  182. end
  183. for member_id, member_info in pairs(union_data.memberinfos) do
  184. local member_actor = getactor(member_id)
  185. if #finish_task_ids > 0 then
  186. local un_received_task_ids = {}
  187. local member_task = this.getMemberTaskData(member_actor)
  188. if table.isEmpty(member_task) then
  189. un_received_task_ids = finish_task_ids
  190. else
  191. un_received_task_ids = this.tableDifference(finish_task_ids, member_task.finishtask)
  192. end
  193. local item_map = {}
  194. -- 校验在线时间 领取可以领取的奖励
  195. for _, task_id in pairs(un_received_task_ids) do
  196. local can_receive = this.checkJoinTime(member_info, task_id)
  197. if can_receive then
  198. -- 遍历计算奖励
  199. local reward_str = ConfigDataManager.getTableValue("cfg_gard_task", "rewarditem", "id", task_id)
  200. string.putIntIntMap(item_map,reward_str, "#", "|")
  201. end
  202. end
  203. -- 发送邮件
  204. if not table.isNullOrEmpty(item_map) then
  205. sendconfigmailbyrid(member_id, this.UNION_TASK_MAIL_ID, item_map)
  206. end
  207. end
  208. -- 重置成员任务
  209. this.setMemberTaskData(member_actor, nil)
  210. end
  211. -- 重置战盟任务
  212. this.initUnionTask(union_id)
  213. :: continue ::
  214. end
  215. end
  216. function this.tableDifference(table1, table2)
  217. local result = {}
  218. local table2Set = {}
  219. if table.isEmpty(table2) then
  220. return table1
  221. end
  222. for _, value in ipairs(table2) do
  223. table2Set[value] = true
  224. end
  225. for _, value in ipairs(table1) do
  226. if not table2Set[value] then
  227. table.insert(result, value)
  228. end
  229. end
  230. return result
  231. end
  232. function this.checkTaskResetTime(create_time, now_time)
  233. create_time = floor(create_time / 1000)
  234. now_time = floor(now_time / 1000)
  235. -- 默认读第一条配置 没有配置时默认为1天
  236. local days = tonumber(ConfigDataManager.getTableValue("cfg_gard_task", "taskrefreshes", "id", 1)) or 1
  237. local thirdDayMidnight = create_time + (24 * 60 * 60 * days)
  238. local thirdDayMidnightDate = os.date("*t", thirdDayMidnight)
  239. thirdDayMidnightDate.hour = 0
  240. thirdDayMidnightDate.min = 0
  241. thirdDayMidnightDate.sec = 0
  242. local expectedMidnightTimestamp = os.time(thirdDayMidnightDate)
  243. return now_time >= expectedMidnightTimestamp
  244. end
  245. -- -------------------------------------------------------------------------- --
  246. UnionMemberTask = {}
  247. ---@class UnionMemberTask
  248. ---@field finishtask number[]
  249. ---@field createtime string
  250. this.UnionMemberTaskDataKey = PlayerDefKey.UNION.UnionMemberTaskDataKey
  251. function UnionMemberTask.sendUnionTaskData(actor)
  252. this.sendUnionTaskData(actor)
  253. end
  254. function UnionMemberTask.submitUnionTask(actor, task_id)
  255. this.submitUnionTask(actor, task_id)
  256. end
  257. ---@return UnionMemberTask
  258. function this.getMemberTaskData(actor)
  259. return getplaydef(actor, this.UnionMemberTaskDataKey)
  260. end
  261. function this.setMemberTaskData(actor, data)
  262. setplaydef(actor, this.UnionMemberTaskDataKey, data)
  263. end
  264. function this.initMemberTask(actor)
  265. ---@type UnionMemberTask
  266. local member_task = {}
  267. member_task.finishtask = {}
  268. member_task.createtime = tostring(getbaseinfo("now"))
  269. this.setMemberTaskData(actor, member_task)
  270. return member_task
  271. end
  272. function this.sendUnionTaskData(actor)
  273. ---@type UnionTask
  274. local union_task = {}
  275. local union_id = tostring(getbaseinfo(actor, "unionid"))
  276. if tonumber(union_id) < 1 then
  277. return
  278. end
  279. local task_record = this.getUnionTask(union_id)
  280. if table.isEmpty(task_record) then
  281. task_record = this.initUnionTaskByActor(actor)
  282. end
  283. local member_task = this.getMemberTaskData(actor)
  284. if not table.isEmpty(member_task) then
  285. union_task.memberrecord = member_task.finishtask
  286. end
  287. union_task.taskrecord = task_record
  288. local mills = this.getUnionTaskCreateData(union_id)
  289. if mills then
  290. union_task.createtime = mills
  291. end
  292. sendluamsg(actor, LuaMessageIdToClient.RES_UNION_TASK_DATA, union_task)
  293. end
  294. function this.submitUnionTask(actor, task_id)
  295. local union_id = tostring(getbaseinfo(actor, "unionid"))
  296. if tonumber(union_id) < 1 then
  297. return
  298. end
  299. local union_task_record = this.getUnionTask(union_id)
  300. if table.isEmpty(union_task_record) then
  301. return
  302. end
  303. local task_record = union_task_record[task_id]
  304. local _, target_count = this.getUnionTaskTargetConfig(task_id)
  305. local task_count = task_record.taskcount
  306. if target_count > task_count then
  307. this.debug("-- 任务未完成, 无法提交 --", task_id, target_count, task_count)
  308. return
  309. end
  310. local finish_task_tbl
  311. local member_task = this.getMemberTaskData(actor)
  312. if table.isEmpty(member_task) then
  313. finish_task_tbl = {}
  314. member_task = this.initMemberTask(actor)
  315. else
  316. finish_task_tbl = member_task.finishtask
  317. if table.contains(finish_task_tbl, task_id) then
  318. this.jprint("战盟任务奖励已经领取")
  319. return
  320. end
  321. end
  322. local rid = getbaseinfo(actor, "id")
  323. local union_data = getunioninfo(actor)
  324. local can_receive, hour = this.checkJoinTime(union_data.memberinfos[rid], task_id)
  325. if not can_receive then
  326. -- sendluamsg(actor, LuaMessageIdToClient.TIPS, "加入战盟时间需要" .. hour .. "小时以上")
  327. noticeTip.noticeinfo(actor, this.UNION_TASK_SUBMIT_STRING_TIP_ID, hour)
  328. this.debug("-- 领取任务奖励失败 --", can_receive, hour)
  329. return
  330. end
  331. local reward_str = ConfigDataManager.getTableValue("cfg_gard_task", "rewarditem", "id", task_id)
  332. this.addItemToBag(actor, reward_str)
  333. member_task.finishtask[#finish_task_tbl + 1] = task_id
  334. this.setMemberTaskData(actor, member_task)
  335. sendluamsg(actor, LuaMessageIdToClient.RES_SUBMIT_UNION_TASK, task_id)
  336. end
  337. function this.addItemToBag(actor, item_str)
  338. local item_tbl = string.toIntIntMap(item_str, "#", "|")
  339. additemmaptobag(actor, item_tbl, 0, 9999, '战盟任务')
  340. end
  341. function this.checkJoinTime(member_info, task_id)
  342. local now = getbaseinfo("now")
  343. local join_hour = (tonumber(now) - tonumber(member_info.jointime)) / 60 / 60 / 1000
  344. local hour = ConfigDataManager.getTableValue("cfg_gard_task", "hour", "id", task_id)
  345. return join_hour >= tonumber(hour), hour
  346. end
  347. function this.mergeAndSumTables(table1, table2)
  348. for key, value in pairs(table2) do
  349. key = tonumber(key)
  350. value = tonumber(value)
  351. if table1[key] then
  352. table1[key] = table1[key] + value
  353. else
  354. table1[key] = value
  355. end
  356. end
  357. end
  358. -- -------------------------------------------------------------------------- --
  359. -- 日志打印
  360. this.log_open = false
  361. function this.debug(...)
  362. if not this.log_open then
  363. return
  364. end
  365. gameDebug.print(...)
  366. end
  367. function this.jprint(param)
  368. if not this.log_open then
  369. return
  370. end
  371. if param == nil then
  372. param = "error! 输出内容为空. nil"
  373. end
  374. jprint(param)
  375. end
  376. -- --------------------- GM 调试函数 --------------------
  377. local gm_open = true
  378. function l_uniontask_resetuniontaskdata()
  379. if not gm_open then
  380. return
  381. end
  382. local data = getallunionsummary()
  383. if table.isEmpty(data) then
  384. return
  385. end
  386. for _, summary in pairs(data) do
  387. this.jprint("------ GM重置战盟任务 ------")
  388. -- 重置成员任务
  389. local union_id = summary.unionid
  390. local union_data = getunioninfo(union_id)
  391. if table.isEmpty(union_data) then
  392. goto continue
  393. end
  394. for member_id, _ in pairs(union_data.memberinfos) do
  395. local member_actor = getactor(member_id)
  396. this.setMemberTaskData(member_actor, nil)
  397. end
  398. -- 重置战盟任务
  399. this.initUnionTask(union_id)
  400. :: continue ::
  401. end
  402. end
  403. function l_uniontask_finishuniontask(actor, type, target)
  404. if not gm_open then
  405. return
  406. end
  407. this.updateUnionTask(actor, tonumber(type), tonumber(target))
  408. end
  409. function l_uniontask_submituniontask(actor, task_id)
  410. if not gm_open then
  411. return
  412. end
  413. this.submitUnionTask(actor, tonumber(task_id))
  414. end
  415. function l_uniontask_middlenightresettask()
  416. if not gm_open then
  417. return
  418. end
  419. this.middleNightResetTask()
  420. end