-- 任务系统开发 local stats = require "model.stats" local schema = require "model.schema" local util = require "util" local logger = require "logger" local min = math.min local max = math.max local _M = schema.new("quest_manager") local MODULE = {} local quest = {} -- 创建一个任务对象 function quest:new(character, rawdata, conf, func) local o = { rawdata = rawdata, -- 存放数据 eg: d.daily/d.achievementd等 required = conf.required, -- 要求1 required2 = conf.required2, model = assert(conf.model), -- 模块 eg:每日任务/成就/历练 send = func.send, save = assert(func.save), -- 保存数据的函数 } if rawdata.state == QUEST_PROGRESS then -- 进行中的任务 if rawdata.progress >= o.required then rawdata.state = QUEST_REACHED rawdata.progress = o.required end elseif rawdata.state == QUEST_REACHED then -- 已达成任务 if rawdata.progress < o.required then rawdata.state = QUEST_PROGRESS end elseif rawdata.state == QUEST_END then -- 已结束任务 if rawdata.progress ~= o.required then rawdata.progress = o.required end else assert(false, rawdata.state) end self.__index = self return setmetatable(o, self) end -- 任务进度处理 function quest:progress(character, value, added) assert(value > 0) local rawdata = self.rawdata if rawdata.state == QUEST_PROGRESS then if added then rawdata.progress = min(self.required, rawdata.progress + value) else rawdata.progress = min(self.required, max(rawdata.progress, value)) end if rawdata.progress == self.required then rawdata.state = QUEST_REACHED end if MAIN_QUEST == self.model or rawdata.state == QUEST_REACHED then if self.send then self.send(character, rawdata) end end self.save(character) -- 保存数据 return true end end -- 多条件 function quest:progress2(character, value, value2, added) assert(value > 0) local rawdata = self.rawdata if self.required2 ~= value2 then return true end if rawdata.state == QUEST_PROGRESS then if added then rawdata.progress = min(self.required, rawdata.progress + value) else rawdata.progress = min(self.required, max(rawdata.progress, value)) end if rawdata.progress == self.required then rawdata.state = QUEST_REACHED end if rawdata.state == QUEST_REACHED then if self.send then self.send(character, rawdata) end end self.save(character) -- 保存数据 return true end end local prototype = {} local function assert_check(rawdata) assert(rawdata.id > 0, rawdata.id) assert(rawdata.progress, rawdata.id) assert(rawdata.state, rawdata.id) end local function create_quest(character, rawdata, conf, quest_func, addnew, func) if addnew then rawdata.state = QUEST_PROGRESS if conf.reset then rawdata.progress = 0 else rawdata.progress = assert(func()) end end assert_check(rawdata) return quest:new(character, rawdata, conf, quest_func) end local function simple_creator(character, rawdata, conf, quest_func, addnew, ...) local args = {...} return create_quest(character, rawdata, conf, quest_func, addnew, function() return assert(stats.fetch(character, table.unpack(args))) end) end prototype[1] = function(character, rawdata, conf, quest_func, addnew) assert(quest_func.save) local list = {} function list:progress() if list.time and list.time == util.today() then list.time = nil return end if rawdata.state == QUEST_PROGRESS then rawdata.progress = min(conf.required, rawdata.progress + 1) if rawdata.progress == conf.required then rawdata.state = QUEST_REACHED end if rawdata.state == QUEST_REACHED then if self.send then self.send(character, rawdata) end end quest_func.save(character) -- 保存数据 return true end end if addnew then rawdata.state = QUEST_PROGRESS rawdata.progress = 1 list.time = util.today() end if rawdata.state == QUEST_PROGRESS then -- 进行中的任务 if rawdata.progress >= conf.required then rawdata.state = QUEST_REACHED rawdata.progress = conf.required end elseif rawdata.state == QUEST_REACHED then -- 已达成任务 if rawdata.progress < conf.required then rawdata.state = QUEST_PROGRESS end elseif rawdata.state == QUEST_END then -- 已结束任务 if rawdata.progress ~= conf.required then rawdata.progress = conf.required end else assert(false, rawdata.state) end return list end prototype[2] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "enter_simple_battle") end prototype[3] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "daily_battle") end prototype[4] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "buy_shop_item") end prototype[5] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "hero_upgrade") end prototype[6] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "draw_times") end prototype[7] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "recharge_times") end prototype[8] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "equip_upgrade") end prototype[9] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "telent_activate") end prototype[10] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "skill_card_upgrade") end prototype[11] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "add_stm_times") end prototype[12] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "buy_stm_times") end prototype[13] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "watch_ad_times") end -- prototype[14] = function(character, rawdata, conf, quest_func, addnew) -- return simple_creator(character, rawdata, conf, quest_func, addnew, "tower_battle") -- end prototype[14] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "relic_battle_num") end prototype[15] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "elite_battle") end prototype[16] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "hero_upstart") end prototype[17] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "equip_upstart") end prototype[18] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "skill_card_upstart") end prototype[19] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "building_upgrade") end prototype[20] = function(character, rawdata, conf, quest_func, addnew) return create_quest(character, rawdata, conf, quest_func, addnew, function() return character.level end) end prototype[21] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "hero_max_level") end prototype[22] = function(character, rawdata, conf, quest_func, addnew) return create_quest(character, rawdata, conf, quest_func, addnew, function() return assert(stats.hero_lv(character, conf.require2)) end) end prototype[23] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "simple_battle_pass") end prototype[24] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "elite_battle_pass") end prototype[25] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "relic_battle_num") end prototype[26] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "add_coin") end prototype[27] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "consume_diamond") end prototype[28] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "hero_add_num") end prototype[29] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "equip_add_num") end prototype[30] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "skill_card_add_num") end prototype[31] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "building_explore_times") end prototype[32] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "city_skill_upgrade") end prototype[33] = function(character, rawdata, conf, quest_func, addnew) return simple_creator(character, rawdata, conf, quest_func, addnew, "draw_equip_times") end local function update_progress(character, type, value, added) local ctx = _M.assert_runtime(character) for _, list in pairs(ctx.trigger) do local trigger = list[type] if trigger then for k, child in ipairs(trigger) do child:progress(character, value, added) end end end end local function update_progress2(character, type, value, value2, added) local ctx = _M.assert_runtime(character) for _, list in pairs(ctx.trigger) do local trigger = list[type] if trigger then for k, child in ipairs(trigger) do child:progress2(character, value, value2, added) end end end end local function register_event_interests(character) local monitor = character.monitor monitor("stats.login", function(_, value) update_progress(character, 1, value, true) end) monitor("stats.enter_simple_battle", function(_, value) update_progress(character, 2, value, true) end) monitor("stats.daily_battle", function(_, value) update_progress(character, 3, value, true) end) monitor("stats.buy_shop_item", function(_, value) update_progress(character, 4, value, true) end) monitor("stats.hero_upgrade", function(_, value) update_progress(character, 5, value, true) end) monitor("stats.draw_times", function(_, value) update_progress(character, 6, value, true) end) monitor("stats.recharge_times", function(_, value) update_progress(character, 7, value, true) end) monitor("stats.equip_upgrade", function(_, value) update_progress(character, 8, value, true) end) monitor("stats.telent_activate", function(_, value) update_progress(character, 9, value, true) end) monitor("stats.skill_card_upgrade", function(_, value) update_progress(character, 10, value, true) end) monitor("stats.add_stm_times", function(_, value) update_progress(character, 11, value, true) end) monitor("stats.buy_stm_times", function(_, value) update_progress(character, 12, value, true) end) monitor("stats.watch_ad_times", function(_, value) update_progress(character, 13, value, true) end) -- monitor("stats.tower_battle", function(_, value) -- update_progress(character, 14, value, true) -- end) monitor("stats.relic_battle_num", function(_, value) update_progress(character, 14, value, true) end) monitor("stats.elite_battle", function(_, value) update_progress(character, 15, value, true) end) monitor("stats.hero_upstart", function(_, value) update_progress(character, 16, value, true) end) monitor("stats.equip_upstart", function(_, value) update_progress(character, 17, value, true) end) monitor("stats.skill_card_upstart", function(_, value) update_progress(character, 18, value, true) end) monitor("stats.building_upgrade", function(_, value) update_progress(character, 19, value, true) end) monitor("role_level", function(_, pre, cur) update_progress(character, 20, cur, false) end) monitor("stats.hero_max_level", function(_, value) update_progress(character, 21, value, false) end) monitor("stats.hero_lv", function(_, value, value2) update_progress2(character, 22, value, value2, false) end) monitor("stats.simple_battle_pass", function(_, value) update_progress(character, 23, value, false) end) monitor("stats.elite_battle_pass", function(_, value) update_progress(character, 24, value, false) end) monitor("stats.relic_battle_num", function(_, value) update_progress(character, 25, value, true) end) monitor("stats.add_coin", function(_, value) update_progress(character, 26, value, true) end) monitor("stats.consume_diamond", function(_, value) update_progress(character, 27, value, true) end) monitor("stats.hero_add_num", function(_, value) update_progress(character, 28, value, true) end) monitor("stats.equip_add_num", function(_, value) update_progress(character, 29, value, true) end) monitor("stats.skill_card_add_num", function(_, value) update_progress(character, 30, value, true) end) monitor("stats.building_explore_times", function(_, value) update_progress(character, 31, value, true) end) monitor("stats.city_skill_upgrade", function(_, value) update_progress(character, 32, value, true) end) monitor("stats.draw_equip_times", function(_, value) update_progress(character, 33, value, true) end) end function MODULE.monitor(character) end function MODULE.parse(character) _M.load(character) local ctx = _M.assert_runtime(character) ctx.trigger = {} register_event_interests(character) end -- 加载一个任务 function MODULE.load(character, rawdata, conf, quest_func) local ctx = _M.assert_runtime(character) local type = conf.type or 0 local name = conf.model assert(type > 0) local gen = assert(prototype[type], type) ctx.trigger[name] = ctx.trigger[name] or {} ctx.trigger[name][type] = ctx.trigger[name][type] or {} table.insert(ctx.trigger[name][type], gen(character, rawdata, conf, quest_func, false)) end -- 接受一个新任务 function MODULE.accept(character, rawdata, conf, quest_func) local ctx = _M.assert_runtime(character) local type = conf.type or 0 local name = conf.model assert(type > 0) local gen = assert(prototype[type], type) ctx.trigger[name] = ctx.trigger[name] or {} ctx.trigger[name][type] = ctx.trigger[name][type] or {} table.insert(ctx.trigger[name][type], gen(character, rawdata, conf, quest_func, true)) end -- 清空内存数据 function MODULE.clear(character, name) assert(name) local ctx = _M.assert_runtime(character) ctx.trigger[name] = {} -- logger.trace("清空任务的 %s模块的内存", name) end -- 清空内存数据 function MODULE.del(character, conf) local name = conf.model local type = conf.type or 0 assert(type > 0) local ctx = _M.assert_runtime(character) local trigger = ctx.trigger[name] or {} for k, v in ipairs(trigger[type] or {}) do if v.rawdata.id == conf.id then table.remove(trigger[type], k) return true end end return false -- logger.trace("清空任务的 %s模块的内存", name) end return MODULE