init.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. local skynet = require "skynet"
  2. local schema = require "model.schema"
  3. local manager = require "model.quest.manager"
  4. local logger = require "logger"
  5. local asset = require "model.asset"
  6. local stringify = require "stringify"
  7. local reward = require "model.reward"
  8. local common_fun = require "model.common_fun"
  9. local currency
  10. local daily_qlst
  11. local weekly_qlst
  12. local achi_qlst
  13. local newx_achi
  14. local main_quest_conf
  15. local next_main
  16. local module_id = MODULE_ID_QUEST
  17. local module_name = "quest"
  18. local _M = schema.new(module_name, {
  19. resettime = 0, -- 每日任务的重置时间
  20. dlv = 0, -- 日常刷新时等级
  21. wlv = 0, -- 周常刷新时等级
  22. daward = 0, -- 已领取的奖励
  23. waward = 0, -- 已领取的周常奖励
  24. daily = {
  25. --[[
  26. [id] = {
  27. id = id,
  28. progress = 0,
  29. state = QUEST_PROGRESS,
  30. }
  31. ]]
  32. }, -- 日常任务
  33. weekly = {}, -- 周常任务
  34. achievement = {}, -- 成就任务
  35. })
  36. local CMD = {}
  37. local REQUEST = {}
  38. local MODULE = {}
  39. local THIS= {}
  40. local function func_ret(fname, character, args)
  41. local f = THIS[fname]
  42. if not f then
  43. logger.error("func_ret not fname:%s !!!", fname)
  44. return {errno = STD_ERR.COMMON_SYS_ERR}
  45. end
  46. local errno, ret = f(character, args)
  47. if errno ~= 0 then
  48. return {errno = errno}
  49. end
  50. ret = ret or {}
  51. ret.errno = 0
  52. return ret
  53. end
  54. local function quest_complate(character, data)
  55. character.send("quest_cmplate_notify", {data = data})
  56. end
  57. -- 找出新增的任务并自动添加到玩家身上
  58. local function accept_new_quest(character, list, qlst)
  59. local quest_func = {
  60. save = _M.persist,
  61. send = quest_complate,
  62. }
  63. local num = 0
  64. -- manager.clear(character, DAILY_QUEST)
  65. for id, conf in pairs(qlst) do
  66. if list[id] then
  67. manager.load(character, list[id], conf, quest_func)
  68. else
  69. num = num + 1
  70. list[id] = {id = id}
  71. manager.accept(character, list[id], conf, quest_func)
  72. -- trace("Quest: 开启日常任务 %s", sid)
  73. end
  74. end
  75. return num > 0
  76. end
  77. -- 找出新增的任务并自动添加到玩家身上
  78. local function accept_new_achi_quest(character, list, qlst)
  79. local quest_func = {
  80. save = _M.persist,
  81. send = quest_complate,
  82. }
  83. local num = 0
  84. -- manager.clear(character, DAILY_QUEST)
  85. for id, conf in pairs(qlst) do
  86. local id = id
  87. local conf = conf
  88. if list[id] and list[id].progress == QUEST_END then
  89. local next_conf = newx_achi(id)
  90. if next_conf then
  91. conf = next_conf
  92. id = next_conf.id
  93. end
  94. end
  95. if list[id] then
  96. manager.load(character, list[id], conf, quest_func)
  97. else
  98. num = num + 1
  99. list[id] = {id = id}
  100. manager.accept(character, list[id], conf, quest_func)
  101. -- trace("Quest: 开启日常任务 %s", sid)
  102. end
  103. end
  104. return num > 0
  105. end
  106. -- 移除不存在的任务
  107. local function flush_invalid_quest(character, list, qlst)
  108. local invalid = {}
  109. for sid, _ in pairs(list) do
  110. if qlst[sid] == nil then
  111. table.insert(invalid, sid)
  112. -- trace("Quest: 不存在的日常任务 %d, 将被移除", sid)
  113. end
  114. end
  115. for _, sid in ipairs(invalid) do
  116. list[sid] = nil
  117. end
  118. local num = #invalid
  119. return num > 0
  120. end
  121. local function accept_new_main_quest(character, conf)
  122. manager.clear(character, MAIN_QUEST)
  123. if not conf then
  124. return
  125. end
  126. local d = _M.assert_get(character) or {}
  127. local quest_func = {
  128. save = _M.persist,
  129. send = quest_complate,
  130. }
  131. if not d.main_quest or d.main_quest.id ~= conf.id then
  132. d.main_quest = {id = conf.id}
  133. manager.accept(character, d.main_quest, conf, quest_func)
  134. return true
  135. else
  136. manager.load(character, d.main_quest, conf, quest_func)
  137. end
  138. end
  139. -- 更新任务表
  140. local function init_quest_list(character)
  141. local d = _M.assert_get(character) or {}
  142. d.dlv = d.dlv or character.level
  143. local qlst = daily_qlst(d.dlv)
  144. local dirty = flush_invalid_quest(character, d.daily, qlst)
  145. dirty = accept_new_quest(character, d.daily, qlst) or dirty
  146. d.wlv = d.wlv or character.level
  147. qlst = weekly_qlst(d.wlv)
  148. dirty = flush_invalid_quest(character, d.weekly, qlst)
  149. dirty = accept_new_quest(character, d.weekly, qlst) or dirty
  150. local achi_list = {}
  151. for id in pairs(d.achievement) do
  152. table.insert(achi_list, id)
  153. end
  154. qlst = achi_qlst(achi_list)
  155. dirty = flush_invalid_quest(character, d.achievement, qlst)
  156. dirty = accept_new_achi_quest(character, d.achievement, qlst) or dirty
  157. if dirty then
  158. _M.persist(character)
  159. end
  160. local main_quest_id = d.main_quest and d.main_quest.id
  161. local main_conf = main_quest_conf(main_quest_id)
  162. if main_conf then
  163. accept_new_main_quest(character, main_conf)
  164. end
  165. end
  166. function MODULE.list_request_interests() return REQUEST end
  167. function MODULE.list_command_interests() return CMD end
  168. function MODULE.parse(character)
  169. local d = _M.load(character)
  170. local addr = skynet.localname(".quest")
  171. daily_qlst = function(lv) return skynet.call(addr, "lua", "daily_qlst", lv) end
  172. weekly_qlst = function(lv) return skynet.call(addr, "lua", "weekly_qlst", lv) end
  173. achi_qlst = function(list) return skynet.call(addr, "lua", "achi_qlst", list) end
  174. newx_achi = function(id) return skynet.call(addr, "lua", "newx_achi", id)end
  175. main_quest_conf = function(id) return skynet.call(addr, "lua", "get_main", id) end
  176. next_main = function(id) return skynet.call(addr, "lua", "next_main", id) end
  177. end
  178. local function reset_daily(character)
  179. local d = _M.assert_get(character)
  180. d.daily = {}
  181. manager.clear(character, DAILY_QUEST)
  182. d.dlv = character.level
  183. d.daward = 0
  184. local qlst = daily_qlst(d.dlv)
  185. accept_new_quest(character, d.daily, qlst)
  186. _M.persist(character)
  187. end
  188. local function reset_weekly(character)
  189. local d = _M.assert_get(character)
  190. d.weekly = {}
  191. manager.clear(character, WEEKLY_QUEST)
  192. d.wlv = character.level
  193. d.waward = 0
  194. local qlst = weekly_qlst(d.dlv)
  195. accept_new_quest(character, d.weekly, qlst)
  196. _M.persist(character)
  197. end
  198. function MODULE.monitor(character)
  199. character.monitor("daily_refresh", function()
  200. reset_daily(character)
  201. end)
  202. character.monitor("weekly_refresh", function()
  203. reset_weekly(character)
  204. end)
  205. end
  206. function MODULE.launch(character)
  207. currency = currency or require "model.currency"
  208. init_quest_list(character)
  209. end
  210. function MODULE.ready(character)
  211. local d = _M.assert_get(character) or {}
  212. logger.test("%s:ready, %s", module_name, stringify(d or {}))
  213. end
  214. function MODULE.saybye(character)
  215. end
  216. function THIS.quest_get_data(character, args)
  217. local d = _M.assert_get(character) or {}
  218. return 0, {
  219. dlv = d.dlv,
  220. wlv = d.wlv,
  221. daward = d.daward,
  222. waward = d.waward,
  223. daily = common_fun.tqueue(d.daily),
  224. weekly = common_fun.tqueue(d.weekly),
  225. achievement = common_fun.tqueue(d.achievement),
  226. main_quest = d.main_quest,
  227. }
  228. end
  229. function THIS.quest_get_award(character, args)
  230. local id = args.id
  231. if not id then
  232. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  233. end
  234. local quest_conf_list = asset.TaskConfig_proto
  235. local quest_conf = quest_conf_list[id]
  236. if not quest_conf then
  237. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  238. end
  239. local d = _M.assert_get(character)
  240. local quest_type = quest_conf.type
  241. local quest = nil
  242. if quest_type == DAILY_QUEST then
  243. quest = d.daily[id]
  244. elseif quest_type == WEEKLY_QUEST then
  245. quest = d.weekly[id]
  246. elseif quest_type == ACHI_QUEST then
  247. quest = d.achievement[id]
  248. elseif quest_type == MAIN_QUEST then
  249. quest = d.main_quest
  250. end
  251. if not quest then
  252. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  253. end
  254. if quest.state ~= QUEST_REACHED then
  255. return STD_ERR.QUEST_NOT_COMPLATE -- 任务未完成
  256. end
  257. local award_list = {}
  258. for i = 1, #quest_conf.reward, 2 do
  259. local item_id = quest_conf.reward[i]
  260. local item_num = quest_conf.reward[i+1]
  261. if item_id and item_num and item_id > 0 and item_num > 0 then
  262. table.insert(award_list, {id = item_id, num = item_num})
  263. end
  264. end
  265. local desc = {
  266. module="quest",
  267. brief="任务奖励",
  268. context= "领取任务奖励:"..id,
  269. mailgen={subject=2, body=""},
  270. notify={
  271. flags="quest_get_award"
  272. },
  273. detail=award_list
  274. }
  275. quest.state = QUEST_END
  276. if quest_type == ACHI_QUEST then
  277. local next_quest_conf = newx_achi(quest.id)
  278. if next_quest_conf then
  279. manager.del(character, next_quest_conf)
  280. d.achievement[id] = nil
  281. d.achievement[next_quest_conf.id] = {id = next_quest_conf.id}
  282. manager.accept(character, d.achievement[next_quest_conf.id], next_quest_conf, {save = _M.persist})
  283. quest = d.achievement[next_quest_conf.id]
  284. end
  285. elseif quest_type == MAIN_QUEST then
  286. local conf = next_main(quest.id)
  287. accept_new_main_quest(character, conf)
  288. quest = d.main_quest
  289. end
  290. reward(character, desc)
  291. _M.persist(character)
  292. return 0, {id = args.id, data = quest}
  293. end
  294. function THIS.quest_active_award(character, args)
  295. local d = _M.assert_get(character)
  296. if not args.type then
  297. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  298. end
  299. local lv, award, active
  300. if args.type == DAILY_QUEST then
  301. lv = d.dlv
  302. award = d.daward
  303. active = currency.get_money(character, CURRENCY_ID_DACTIVITY)
  304. elseif args.type == WEEKLY_QUEST then
  305. lv = d.wlv
  306. award = d.waward
  307. active = currency.get_money(character, CURRENCY_ID_WACTIVITY)
  308. else
  309. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  310. end
  311. local max_award = 0
  312. local award_list = {}
  313. for _, conf in pairs(asset.ActiverewardConfig_proto) do
  314. if conf.type == args.type and lv >= (conf.interval[1] or 0) and lv <= (conf.interval[2] or 0) and award < conf.active and active >= conf.active then
  315. max_award = math.max(max_award, conf.active)
  316. for i = 1, #conf.reward, 2 do
  317. local item_id = conf.reward[i]
  318. local item_num = conf.reward[i+1]
  319. if item_id and item_num and item_id > 0 and item_num > 0 then
  320. table.insert(award_list, {id = item_id, num = item_num})
  321. end
  322. end
  323. end
  324. end
  325. if not next(award_list) then
  326. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  327. end
  328. local desc = {
  329. module="quest",
  330. brief="活跃奖励",
  331. context= "领取活跃奖励:"..args.type,
  332. mailgen={subject=2, body=""},
  333. notify={
  334. flags="quest_active_award"
  335. },
  336. detail=award_list
  337. }
  338. reward(character, desc)
  339. if args.type == DAILY_QUEST then
  340. d.daward = max_award
  341. elseif args.type == WEEKLY_QUEST then
  342. d.waward = max_award
  343. end
  344. _M.persist(character)
  345. return 0, {type = args.type, award = max_award}
  346. end
  347. function REQUEST.quest_get_data(character, args)
  348. return func_ret("quest_get_data", character, args)
  349. end
  350. function REQUEST.quest_get_award(character, args)
  351. return func_ret("quest_get_award", character, args)
  352. end
  353. function REQUEST.quest_active_award(character, args)
  354. return func_ret("quest_active_award", character, args)
  355. end
  356. local function set_quest_complate(character, id)
  357. local d = _M.assert_get(character) or {}
  358. local quest_conf_list = asset.TaskConfig_proto
  359. local quest_conf = quest_conf_list[id]
  360. if not quest_conf then
  361. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  362. end
  363. local quest_type = quest_conf.type
  364. local quest = nil
  365. if quest_type == DAILY_QUEST then
  366. quest = d.daily[id]
  367. elseif quest_type == WEEKLY_QUEST then
  368. quest = d.weekly[id]
  369. elseif quest_type == ACHI_QUEST then
  370. quest = d.achievement[id]
  371. end
  372. if not quest_conf then
  373. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  374. end
  375. local quest_type = quest_conf.type
  376. local quest = nil
  377. if quest_type == DAILY_QUEST then
  378. quest = d.daily[id]
  379. elseif quest_type == WEEKLY_QUEST then
  380. quest = d.weekly[id]
  381. elseif quest_type == ACHI_QUEST then
  382. quest = d.achievement[id]
  383. end
  384. if not quest then
  385. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  386. end
  387. quest.progress = quest_conf.parameter
  388. quest.state = QUEST_REACHED
  389. quest_complate(character, quest)
  390. _M.persist(character)
  391. return 0
  392. end
  393. function CMD.gm_quest_complate(character, args)
  394. local errno = set_quest_complate(character, args[1])
  395. if errno ~= 0 then
  396. return "失败"
  397. end
  398. return "成功"
  399. end
  400. function MODULE.get_red_point(character)
  401. local d = _M.assert_get(character) or {}
  402. local data = d.daily or {}
  403. for _, v in pairs(data) do
  404. if v.state == QUEST_REACHED then
  405. return true, module_id
  406. end
  407. end
  408. data = d.achievement
  409. for _, v in pairs(data) do
  410. if v.state == QUEST_REACHED then
  411. return true, module_id
  412. end
  413. end
  414. data = d.weekly
  415. for _, v in pairs(data) do
  416. if v.state == QUEST_REACHED then
  417. return true, module_id
  418. end
  419. end
  420. local dactive = currency.get_money(character, CURRENCY_ID_DACTIVITY)
  421. local wactive = currency.get_money(character, CURRENCY_ID_WACTIVITY)
  422. for _, conf in pairs(asset.ActiverewardConfig_proto) do
  423. if conf.type == DAILY_QUEST and d.dlv >= (conf.interval[1] or 0) and d.dlv <= (conf.interval[2] or 0) and d.daward < conf.active and dactive >= conf.active then
  424. return true, module_id
  425. end
  426. if conf.type == WEEKLY_QUEST and d.wlv >= (conf.interval[1] or 0) and d.wlv <= (conf.interval[2] or 0) and d.waward < conf.active and wactive >= conf.active then
  427. return true, module_id
  428. end
  429. end
  430. end
  431. return MODULE