quest.lua 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. -- 任务
  2. local skynet = require "skynet"
  3. require "skynet.manager"
  4. local socket = require "skynet.socket"
  5. local logger = require "logger"
  6. local asset = require "model.asset"
  7. local util = require "util"
  8. local stringify = require "stringify"
  9. local skynet_retpack = skynet.retpack
  10. -- 日常任务
  11. local daily = {
  12. --[[
  13. [等级] = {{
  14. id = id,
  15. type = type,
  16. required = required
  17. required2 = required2
  18. }}
  19. ]]
  20. }
  21. -- 周常任务
  22. local weekly = {
  23. --[[
  24. [等级] = {{
  25. id = id,
  26. type = type,
  27. required = required
  28. required2 = required2
  29. }}
  30. ]]
  31. }
  32. -- 成就任务
  33. local achi = {
  34. --[[
  35. [类型] = {{
  36. id = id,
  37. type = type,
  38. required = required
  39. required2 = required2
  40. }}
  41. ]]
  42. }
  43. -- 主线任务
  44. local main_quest = {
  45. first = nil,
  46. list = {
  47. --[[
  48. [id] = {
  49. next = next_index
  50. }
  51. ]]
  52. }
  53. }
  54. local function new_quest(desc, reset)
  55. local ret = {
  56. id = desc.ID,
  57. type = desc.touch, -- 触发器
  58. model = desc.type,
  59. required = desc.parameter, -- 数值要求
  60. required2 = desc.data, -- 品质要求
  61. reset = reset or desc.timely == 1,
  62. }
  63. -- 特殊原因需要将21触发器多条件任务的主条件和副条件对调.
  64. if ret.type == 22 then
  65. ret.required, ret.required2 = ret.required2, ret.required
  66. end
  67. return ret
  68. end
  69. local function register_level_quest(t, conf)
  70. local quest = new_quest(conf, true)
  71. if conf.interval[2] then
  72. for i = conf.interval[1], conf.interval[2] do
  73. t[i] = t[i] or {}
  74. t[i][conf.ID] = quest
  75. end
  76. end
  77. end
  78. local function register_type_quest(t, conf)
  79. local quest = new_quest(conf)
  80. t[conf.touch] = t[conf.touch] or {}
  81. table.insert(t[conf.touch], quest)
  82. end
  83. local function register_main_quest(t, conf)
  84. local quest = new_quest(conf)
  85. t.list = t.list or {}
  86. t.index = t.index or {}
  87. assert(not t.list[quest.id], quest.id)
  88. t.list[quest.id] = quest
  89. table.insert(t.index, quest.id)
  90. end
  91. local function register_quest(list, config)
  92. for _, desc in pairs(config) do
  93. if desc.type == DAILY_QUEST then
  94. register_level_quest(list.daily, desc)
  95. elseif desc.type == WEEKLY_QUEST then
  96. register_level_quest(list.weekly, desc)
  97. elseif desc.type == ACHI_QUEST then
  98. register_type_quest(list.achi, desc)
  99. elseif desc.type == MAIN_QUEST then
  100. register_main_quest(list.main, desc)
  101. end
  102. end
  103. end
  104. local function optimize()
  105. -- 首先,构建关卡的任务列表
  106. local list = {
  107. daily = {},
  108. weekly = {},
  109. achi = {},
  110. main = {},
  111. }
  112. register_quest(list, asset.TaskConfig_proto)
  113. for _, v in pairs(list.achi or {}) do
  114. table.sort(v, function(a, b)
  115. if a.required < b.required then
  116. return true
  117. end
  118. if a.required > b.required then
  119. return false
  120. end
  121. if a.required2 and b.required2 then
  122. if a.required2 < b.required2 then
  123. return true
  124. end
  125. end
  126. return false
  127. end)
  128. end
  129. if list.main.index then
  130. table.sort(list.main.index)
  131. list.main.first = list.main.index[1]
  132. for i = 1, #list.main.index do
  133. local cur_index = list.main.index[i]
  134. local nex_index = list.main.index[i+1]
  135. if nex_index then
  136. list.main.list[cur_index].next = nex_index
  137. end
  138. end
  139. end
  140. daily = list.daily
  141. weekly = list.weekly
  142. achi = list.achi
  143. if list.main then
  144. main_quest.first = list.main.first
  145. main_quest.list = list.main.list
  146. end
  147. logger.trace("main_quest:"..stringify(main_quest or {}))
  148. end
  149. local CMD = {}
  150. function CMD.start()
  151. optimize()
  152. end
  153. function CMD.daily_qlst(lv)
  154. return daily[lv] or {}
  155. end
  156. function CMD.weekly_qlst(lv)
  157. return weekly[lv] or {}
  158. end
  159. function CMD.achi_qlst(list)
  160. local ret = {}
  161. local temp ={}
  162. for _, id in ipairs(list or {}) do
  163. local conf = asset.TaskConfig_proto[id]
  164. if conf and conf.touch and conf.type == ACHI_QUEST then
  165. temp[conf.touch] = id
  166. end
  167. end
  168. for type, v in pairs(achi) do
  169. local find = false
  170. if temp[type] then
  171. for _, quest in ipairs(v) do
  172. if quest.id == temp[type] then
  173. ret[quest.id] = quest
  174. find = true
  175. break
  176. end
  177. end
  178. end
  179. if not find then
  180. local quest = v[1]
  181. if quest then
  182. ret[quest.id] = quest
  183. end
  184. end
  185. end
  186. return ret
  187. end
  188. function CMD.newx_achi(id)
  189. local conf = asset.TaskConfig_proto[id]
  190. local list = achi[conf.touch]
  191. if not list then
  192. return
  193. end
  194. for k, quest in ipairs(list) do
  195. if quest.id == id then
  196. return list[k+1]
  197. end
  198. end
  199. end
  200. function CMD.quest(id)
  201. local conf = asset.TaskConfig_proto[id]
  202. if conf then
  203. return new_quest(conf)
  204. end
  205. return nil
  206. end
  207. function CMD.get_main(id)
  208. if not id or not main_quest.list[id] then
  209. return CMD.next_main(id)
  210. else
  211. return main_quest.list[id]
  212. end
  213. end
  214. function CMD.next_main(id)
  215. if not main_quest.first then
  216. return
  217. end
  218. if not id then
  219. return main_quest.list[main_quest.first]
  220. else
  221. if main_quest.list[id] then
  222. if main_quest.list[id].next then
  223. return main_quest.list[main_quest.list[id].next]
  224. end
  225. return
  226. else
  227. local index = main_quest.first
  228. while(main_quest.list[index]) do
  229. if index > id then
  230. return main_quest.list[index]
  231. else
  232. local next_index = main_quest.list[index].next
  233. if next_index and next_index ~= index then
  234. index = next_index
  235. else
  236. return
  237. end
  238. end
  239. end
  240. end
  241. end
  242. end
  243. function CMD.hotfix(list)
  244. if list.TaskConfig_proto then
  245. logger.info("=============== quest hotfix ===================")
  246. local ok, msg = pcall(optimize)
  247. if not ok then
  248. logger.warn("=============== quest hotfix ERR===================\n, msg:"..msg)
  249. end
  250. end
  251. end
  252. skynet.init(function()
  253. skynet.register(".quest")
  254. end)
  255. skynet.start(function()
  256. logger.label("<Quest>,")
  257. skynet.dispatch("lua", function(session,_, cmd, ...)
  258. local f = assert(CMD[cmd])
  259. if session == 0 then
  260. f(...)
  261. else
  262. skynet_retpack(f(...))
  263. end
  264. end)
  265. end)