local skynet = require "skynet" local schema = require "model.schema" local manager = require "model.quest.manager" local logger = require "logger" local asset = require "model.asset" local stringify = require "stringify" local reward = require "model.reward" local common_fun = require "model.common_fun" local currency local daily_qlst local weekly_qlst local achi_qlst local newx_achi local main_quest_conf local next_main local module_id = MODULE_ID_QUEST local module_name = "quest" local _M = schema.new(module_name, { resettime = 0, -- 每日任务的重置时间 dlv = 0, -- 日常刷新时等级 wlv = 0, -- 周常刷新时等级 daward = 0, -- 已领取的奖励 waward = 0, -- 已领取的周常奖励 daily = { --[[ [id] = { id = id, progress = 0, state = QUEST_PROGRESS, } ]] }, -- 日常任务 weekly = {}, -- 周常任务 achievement = {}, -- 成就任务 }) local CMD = {} local REQUEST = {} local MODULE = {} local THIS= {} local function func_ret(fname, character, args) local f = THIS[fname] if not f then logger.error("func_ret not fname:%s !!!", fname) return {errno = STD_ERR.COMMON_SYS_ERR} end local errno, ret = f(character, args) if errno ~= 0 then return {errno = errno} end ret = ret or {} ret.errno = 0 return ret end local function quest_complate(character, data) character.send("quest_cmplate_notify", {data = data}) end -- 找出新增的任务并自动添加到玩家身上 local function accept_new_quest(character, list, qlst) local quest_func = { save = _M.persist, send = quest_complate, } local num = 0 -- manager.clear(character, DAILY_QUEST) for id, conf in pairs(qlst) do if list[id] then manager.load(character, list[id], conf, quest_func) else num = num + 1 list[id] = {id = id} manager.accept(character, list[id], conf, quest_func) -- trace("Quest: 开启日常任务 %s", sid) end end return num > 0 end -- 找出新增的任务并自动添加到玩家身上 local function accept_new_achi_quest(character, list, qlst) local quest_func = { save = _M.persist, send = quest_complate, } local num = 0 -- manager.clear(character, DAILY_QUEST) for id, conf in pairs(qlst) do local id = id local conf = conf if list[id] and list[id].progress == QUEST_END then local next_conf = newx_achi(id) if next_conf then conf = next_conf id = next_conf.id end end if list[id] then manager.load(character, list[id], conf, quest_func) else num = num + 1 list[id] = {id = id} manager.accept(character, list[id], conf, quest_func) -- trace("Quest: 开启日常任务 %s", sid) end end return num > 0 end -- 移除不存在的任务 local function flush_invalid_quest(character, list, qlst) local invalid = {} for sid, _ in pairs(list) do if qlst[sid] == nil then table.insert(invalid, sid) -- trace("Quest: 不存在的日常任务 %d, 将被移除", sid) end end for _, sid in ipairs(invalid) do list[sid] = nil end local num = #invalid return num > 0 end local function accept_new_main_quest(character, conf) manager.clear(character, MAIN_QUEST) if not conf then return end local d = _M.assert_get(character) or {} local quest_func = { save = _M.persist, send = quest_complate, } if not d.main_quest or d.main_quest.id ~= conf.id then d.main_quest = {id = conf.id} manager.accept(character, d.main_quest, conf, quest_func) return true else manager.load(character, d.main_quest, conf, quest_func) end end -- 更新任务表 local function init_quest_list(character) local d = _M.assert_get(character) or {} d.dlv = d.dlv or character.level local qlst = daily_qlst(d.dlv) local dirty = flush_invalid_quest(character, d.daily, qlst) dirty = accept_new_quest(character, d.daily, qlst) or dirty d.wlv = d.wlv or character.level qlst = weekly_qlst(d.wlv) dirty = flush_invalid_quest(character, d.weekly, qlst) dirty = accept_new_quest(character, d.weekly, qlst) or dirty local achi_list = {} for id in pairs(d.achievement) do table.insert(achi_list, id) end qlst = achi_qlst(achi_list) dirty = flush_invalid_quest(character, d.achievement, qlst) dirty = accept_new_achi_quest(character, d.achievement, qlst) or dirty if dirty then _M.persist(character) end local main_quest_id = d.main_quest and d.main_quest.id local main_conf = main_quest_conf(main_quest_id) if main_conf then accept_new_main_quest(character, main_conf) end end function MODULE.list_request_interests() return REQUEST end function MODULE.list_command_interests() return CMD end function MODULE.parse(character) local d = _M.load(character) local addr = skynet.localname(".quest") daily_qlst = function(lv) return skynet.call(addr, "lua", "daily_qlst", lv) end weekly_qlst = function(lv) return skynet.call(addr, "lua", "weekly_qlst", lv) end achi_qlst = function(list) return skynet.call(addr, "lua", "achi_qlst", list) end newx_achi = function(id) return skynet.call(addr, "lua", "newx_achi", id)end main_quest_conf = function(id) return skynet.call(addr, "lua", "get_main", id) end next_main = function(id) return skynet.call(addr, "lua", "next_main", id) end end local function reset_daily(character) local d = _M.assert_get(character) d.daily = {} manager.clear(character, DAILY_QUEST) d.dlv = character.level d.daward = 0 local qlst = daily_qlst(d.dlv) accept_new_quest(character, d.daily, qlst) _M.persist(character) end local function reset_weekly(character) local d = _M.assert_get(character) d.weekly = {} manager.clear(character, WEEKLY_QUEST) d.wlv = character.level d.waward = 0 local qlst = weekly_qlst(d.dlv) accept_new_quest(character, d.weekly, qlst) _M.persist(character) end function MODULE.monitor(character) character.monitor("daily_refresh", function() reset_daily(character) end) character.monitor("weekly_refresh", function() reset_weekly(character) end) end function MODULE.launch(character) currency = currency or require "model.currency" init_quest_list(character) end function MODULE.ready(character) local d = _M.assert_get(character) or {} logger.test("%s:ready, %s", module_name, stringify(d or {})) end function MODULE.saybye(character) end function THIS.quest_get_data(character, args) local d = _M.assert_get(character) or {} return 0, { dlv = d.dlv, wlv = d.wlv, daward = d.daward, waward = d.waward, daily = common_fun.tqueue(d.daily), weekly = common_fun.tqueue(d.weekly), achievement = common_fun.tqueue(d.achievement), main_quest = d.main_quest, } end function THIS.quest_get_award(character, args) local id = args.id if not id then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local quest_conf_list = asset.TaskConfig_proto local quest_conf = quest_conf_list[id] if not quest_conf then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local d = _M.assert_get(character) local quest_type = quest_conf.type local quest = nil if quest_type == DAILY_QUEST then quest = d.daily[id] elseif quest_type == WEEKLY_QUEST then quest = d.weekly[id] elseif quest_type == ACHI_QUEST then quest = d.achievement[id] elseif quest_type == MAIN_QUEST then quest = d.main_quest end if not quest then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end if quest.state ~= QUEST_REACHED then return STD_ERR.QUEST_NOT_COMPLATE -- 任务未完成 end local award_list = {} for i = 1, #quest_conf.reward, 2 do local item_id = quest_conf.reward[i] local item_num = quest_conf.reward[i+1] if item_id and item_num and item_id > 0 and item_num > 0 then table.insert(award_list, {id = item_id, num = item_num}) end end local desc = { module="quest", brief="任务奖励", context= "领取任务奖励:"..id, mailgen={subject=2, body=""}, notify={ flags="quest_get_award" }, detail=award_list } quest.state = QUEST_END if quest_type == ACHI_QUEST then local next_quest_conf = newx_achi(quest.id) if next_quest_conf then manager.del(character, next_quest_conf) d.achievement[id] = nil d.achievement[next_quest_conf.id] = {id = next_quest_conf.id} manager.accept(character, d.achievement[next_quest_conf.id], next_quest_conf, {save = _M.persist}) quest = d.achievement[next_quest_conf.id] end elseif quest_type == MAIN_QUEST then local conf = next_main(quest.id) accept_new_main_quest(character, conf) quest = d.main_quest end reward(character, desc) _M.persist(character) return 0, {id = args.id, data = quest} end function THIS.quest_active_award(character, args) local d = _M.assert_get(character) if not args.type then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local lv, award, active if args.type == DAILY_QUEST then lv = d.dlv award = d.daward active = currency.get_money(character, CURRENCY_ID_DACTIVITY) elseif args.type == WEEKLY_QUEST then lv = d.wlv award = d.waward active = currency.get_money(character, CURRENCY_ID_WACTIVITY) else return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local max_award = 0 local award_list = {} for _, conf in pairs(asset.ActiverewardConfig_proto) do 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 max_award = math.max(max_award, conf.active) for i = 1, #conf.reward, 2 do local item_id = conf.reward[i] local item_num = conf.reward[i+1] if item_id and item_num and item_id > 0 and item_num > 0 then table.insert(award_list, {id = item_id, num = item_num}) end end end end if not next(award_list) then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local desc = { module="quest", brief="活跃奖励", context= "领取活跃奖励:"..args.type, mailgen={subject=2, body=""}, notify={ flags="quest_active_award" }, detail=award_list } reward(character, desc) if args.type == DAILY_QUEST then d.daward = max_award elseif args.type == WEEKLY_QUEST then d.waward = max_award end _M.persist(character) return 0, {type = args.type, award = max_award} end function REQUEST.quest_get_data(character, args) return func_ret("quest_get_data", character, args) end function REQUEST.quest_get_award(character, args) return func_ret("quest_get_award", character, args) end function REQUEST.quest_active_award(character, args) return func_ret("quest_active_award", character, args) end local function set_quest_complate(character, id) local d = _M.assert_get(character) or {} local quest_conf_list = asset.TaskConfig_proto local quest_conf = quest_conf_list[id] if not quest_conf then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local quest_type = quest_conf.type local quest = nil if quest_type == DAILY_QUEST then quest = d.daily[id] elseif quest_type == WEEKLY_QUEST then quest = d.weekly[id] elseif quest_type == ACHI_QUEST then quest = d.achievement[id] end if not quest_conf then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local quest_type = quest_conf.type local quest = nil if quest_type == DAILY_QUEST then quest = d.daily[id] elseif quest_type == WEEKLY_QUEST then quest = d.weekly[id] elseif quest_type == ACHI_QUEST then quest = d.achievement[id] end if not quest then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end quest.progress = quest_conf.parameter quest.state = QUEST_REACHED quest_complate(character, quest) _M.persist(character) return 0 end function CMD.gm_quest_complate(character, args) local errno = set_quest_complate(character, args[1]) if errno ~= 0 then return "失败" end return "成功" end function MODULE.get_red_point(character) local d = _M.assert_get(character) or {} local data = d.daily or {} for _, v in pairs(data) do if v.state == QUEST_REACHED then return true, module_id end end data = d.achievement for _, v in pairs(data) do if v.state == QUEST_REACHED then return true, module_id end end data = d.weekly for _, v in pairs(data) do if v.state == QUEST_REACHED then return true, module_id end end local dactive = currency.get_money(character, CURRENCY_ID_DACTIVITY) local wactive = currency.get_money(character, CURRENCY_ID_WACTIVITY) for _, conf in pairs(asset.ActiverewardConfig_proto) do 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 return true, module_id end 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 return true, module_id end end end return MODULE