local schema = require "model.schema" local logger = require "logger" local reward = require "model.reward" local payment = require "model.payment" local asset = require "model.asset" local common_fun = require "model.common_fun" local module_fun = require "model.module_fun" local skynet = require "skynet" local stringify = require "stringify" local rankinglist local supreme_card local talent local hero local module_name = "adventure" local LAYER_SYS_NUM = 100 -- 波次系数(关卡*100+1为本关第一波) local NIL_RET = -1 -- 为nil时返回值 local NULL_ADV = -1 local SIMPLE_ADV = 0 local ELITE_ADV = 1 local MIN_ELITE_ID = 101 local math_floor = math.floor local table_insert = table.insert local math_min = math.min local _M = schema.new(module_name, { pass = { -- [1] = { -- id = 关卡; -- tm = 时间 -- award = {123,456} -- award_list = {} -- } }, cost = nil, type = nil, layer = nil, trialid = 0, -- 试玩英雄配置id trialnum = 0, -- 试玩英雄次数 btrial = false, -- 是否开始试玩 }) local REQUEST = {} local CMD = {} 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 function MODULE.list_request_interests() return REQUEST end function MODULE.list_command_interests() return CMD end -- TODO: 解析/升级模块数据 function MODULE.parse(character) local d = _M.load(character) d.pass = d.pass or {} if not d.pass[SIMPLE_ADV] then d.pass[SIMPLE_ADV] = {id = 0, tm = 0, award = {}} end if not d.pass[ELITE_ADV] then d.pass[ELITE_ADV] = {id = 0, tm = 0, award = {}} end d.trialid = d.trialid or 0 d.trialnum = d.trialnum or 0 end local function sysnc_adventure(character) -- if character.ban_rank ~= 0 then -- return -- end -- local d = _M.assert_get(character) -- if d.pass[SIMPLE_ADV].id <=0 then -- return -- end -- local data = { -- num = d.pass[SIMPLE_ADV].id, -- num2 = d.pass[SIMPLE_ADV].tm, -- role = module_fun.simple_role(character), -- } -- skynet.call(rankinglist, "lua", "update", RANKING_ADV, data) end -- TODO: 侦听事件 function MODULE.monitor(character) local d = _M.assert_get(character) character.monitor("simple_battle_pass", function(_, id) sysnc_adventure(character) end) end -- TODO: 类似泰利的 prepare 接口 function MODULE.launch(character) local d = _M.assert_get(character) local u = _M.assert_runtime(character) rankinglist = skynet.localname(".rankinglist") end -- TODO: 与客户端同步数据 function MODULE.ready(character) local d = _M.assert_get(character) sysnc_adventure(character) logger.test("%s: ready, d:%s", module_name, stringify(d)) end -- TODO: 玩家下线时的处理 function MODULE.saybye(character) sysnc_adventure(character) end function MODULE.gm_set_simple_adventure(character, id) local d = _M.assert_get(character) or {} if d.pass[SIMPLE_ADV].id < id then character.dispatch("simple_battle_pass", id) end d.pass[SIMPLE_ADV].id = id d.pass[SIMPLE_ADV].tm = os.time() _M.persist(character) end function MODULE.gm_set_elite_adventure(character, id) local d = _M.assert_get(character) or {} if asset.EliteInfoConfig_proto[id] then if d.pass[ELITE_ADV].id < id then character.dispatch("elite_battle_pass", id) end d.pass[ELITE_ADV].id = id d.pass[ELITE_ADV].tm = os.time() _M.persist(character) return true end return false end function MODULE.get_simple_pass(character) local d = _M.assert_get(character) or {} return d.pass[SIMPLE_ADV].id or 0 end function MODULE.get_simple_pass_data(character) local d = _M.assert_get(character) or {} return d.pass[SIMPLE_ADV] end function MODULE.get_elite_pass(character) local d = _M.assert_get(character) or {} return d.pass[ELITE_ADV].id or 0 end function MODULE.get_elite_pass_data(character) local d = _M.assert_get(character) or {} return d.pass[ELITE_ADV] end local function touch_trail(character, ttype, id) -- local d = _M.assert_get(character) -- if d.trialid and d.trialid > 0 then -- local conf = asset.TrialConfig_proto[d.trialid] -- if conf and id >= conf.parameter or id < conf.endcondition then -- return -- end -- end -- for _, conf in pairs(asset.TrialConfig_proto) do -- if id >= conf.parameter and id < conf.endcondition then -- if conf.integral == ttype then -- d.trialid = conf.ID -- d.trialnum = 0 -- -- d.btrial = ttype == 1 and true or false -- _M.persist(character) -- return -- else -- return -- end -- end -- end end function THIS.get_conf_list(adv_type) if adv_type == SIMPLE_ADV then return assert(asset.StageInfoConfig_proto, "StageInfoConfig_proto") elseif adv_type == ELITE_ADV then return assert(asset.EliteInfoConfig_proto, "EliteInfoConfig_proto") end end function THIS.get_layer_conf_list(adv_type) if adv_type == SIMPLE_ADV then return assert(asset.StageConfig_proto, "StageConfig_proto") elseif adv_type == ELITE_ADV then return assert(asset.EliteStageConfig_proto, "EliteStageConfig_proto") end end function THIS.adventure_layer(character, args) local d = _M.assert_get(character) if not d.layer or not d.type then return STD_ERR.ADVENTURE_NOT_BATTLE end local id = math_floor(d.layer/LAYER_SYS_NUM) if id ~= math_floor(args.layer/LAYER_SYS_NUM) then return STD_ERR.COMMON_PARM_ERR end local conf_list = THIS.get_layer_conf_list(d.type) if not conf_list or not conf_list[args.layer] then return STD_ERR.COMMON_SYS_ERR end local conf = conf_list[args.layer] local max_list = {} local all_num = 0 if conf then all_num = all_num + #conf.roles for _, monster_id in ipairs(conf.roles) do local monster_conf = asset.MonsterConfig_proto[monster_id] if monster_conf then max_list[monster_conf.type] = (max_list[monster_conf.type] or 0) + 1 end end end local kill_boss = math.min(max_list[MONESTER_TYPE_BOSS] or 0, args.monster_num or 0) local all_num = math.min(all_num, (args.monster_num or 0) + (args.elite_num or 0) + (args.boss_num or 0)) if args.layer > d.layer then d.layer = args.layer _M.persist(character) if all_num > 0 then character.dispatch("kill_monster", all_num) end if kill_boss > 0 then character.dispatch("kill_boss", kill_boss) end end if d.type == SIMPLE_ADV then local data = d.pass[SIMPLE_ADV] if id > data.id then data.progress = math.max(d.layer%LAYER_SYS_NUM, data.progress or 0) _M.persist(character) end end return 0 end function THIS.adventure_start(character, args) local d = _M.assert_get(character) local id = args.id local key = args.type or 0 -- 在冒险中 -- if d.layer and d.type then -- return STD_ERR.ADVENTURE_IN_BATTLE -- 有冒险在进行 -- end if not id or not key then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local conf_list = THIS.get_conf_list(key) if not conf_list or not conf_list[id] then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end if not d.pass and not d.pass[key] then return STD_ERR.COMMON_SYS_ERR -- 系统异常 end local data = d.pass[key] if conf_list[id].front > data.id then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end if key == ELITE_ADV then if conf_list[id].condition > d.pass[SIMPLE_ADV].id then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end end local conf_list = assert(asset.DataConfig_proto, "DataConfig_proto") local conf = conf_list[1] if not conf then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end local costnum = conf.data5[1] if not costnum or costnum < 0 then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end if key == SIMPLE_ADV then local detail = {{ id = CURRENCY_ID_STM, num = costnum }} local receipt = { module="adventure", brief="闯关开始", context="闯关开始:"..id, notify={ flags="adventure_start" }, detail=detail } local errno = payment(character, receipt) if errno ~=0 then return errno end end d.layer = id * LAYER_SYS_NUM + 1; d.type = key d.cost = 0; _M.persist(character) if key == SIMPLE_ADV then touch_trail(character, 1, id) character.dispatch("simple_battle", id) elseif key == ELITE_ADV then character.dispatch("elite_battle", id) end -- if key == SIMPLE_ADV and d.trialid > 0 then -- local conf = asset.TrialConfig_proto[d.trialid] -- if conf and id >= conf.parameter and id <= conf.endcondition and d.trialnum < conf.rank then -- return 0, { -- trial_id = d.trialid, -- trial_num = d.trialnum, -- btrial = d.btrial -- } -- end -- end return 0 end function THIS.adventure_end(character, args) local d = _M.assert_get(character) or {} if not d.layer or not d.type or d.layer <= 0 then return STD_ERR.ADVENTURE_NOT_BATTLE -- 没有进行中的冒险 end local bwin = args.win local id = math_floor(d.layer/LAYER_SYS_NUM) if id <= 0 then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local key = d.type or 0 if key ~= ELITE_ADV and key ~= SIMPLE_ADV then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local award_list local start_id = id*LAYER_SYS_NUM + 1 -- 保护下每关最多99波 local end_id = math_min(d.layer-1, (id+1)*LAYER_SYS_NUM-1) if not d.layer then return STD_ERR.ADVENTURE_NOT_BATTLE -- 没有进行中的冒险 end local conf_list = THIS.get_layer_conf_list(d.type) if not conf_list then return STD_ERR.COMMON_SYS_ERR end local data = d.pass[key] if bwin then end_id = (id+1)*LAYER_SYS_NUM-1 else if key == SIMPLE_ADV then touch_trail(character, 2, id) end end -- 简单关卡才有奖励 if key == SIMPLE_ADV then local errno errno, award_list = THIS.simple_award(character, start_id, end_id) if errno ~= 0 then return errno end if award_list and next(award_list) then local desc = { module="adventure", brief="闯关奖励", context= string.format("闯关奖励%d", id), mailgen={subject=2, body=""}, notify={ flags="adventure_end" }, detail=award_list } reward(character, desc) end end local max_list = {} local all_num = 0 for confid = start_id, end_id do local conf = conf_list[confid] if conf then all_num = all_num + #conf.roles for _, monster_id in ipairs(conf.roles) do local monster_conf = asset.MonsterConfig_proto[monster_id] if monster_conf then max_list[monster_conf.type] = (max_list[monster_conf.type] or 0) + 1 end end end end if id > data.id then if bwin then d.pass[key].id = id d.pass[key].tm = os.time() d.pass[key].progress = 0 if key == SIMPLE_ADV then character.dispatch("simple_battle_pass", id) local ctx = _M.assert_runtime(character) ctx.ad_award = award_list ctx.id = id if d.btrial then d.trialnum = d.trialnum + 1 end elseif key == ELITE_ADV then character.dispatch("elite_battle_pass", id) end else d.pass[key].progress = math.max(d.layer%LAYER_SYS_NUM, d.pass[key].progress or 0) end end local kill_boss = math.min(max_list[MONESTER_TYPE_BOSS] or 0, args.boss_num or 0) local all_num = math.min(all_num, (args.monster_num or 0) + (args.elite_num or 0) + (args.boss_num or 0)) if all_num > 0 then character.dispatch("kill_monster", all_num) end if kill_boss > 0 then character.dispatch("kill_boss", kill_boss) end d.layer = nil; d.type = nil d.cost = nil _M.persist(character) return 0 end local function adv_coins_add_addition(character, equip_list) -- supreme_card = supreme_card or require "model.activity.supreme_card" -- local unlock_supreme_card = supreme_card.card_unlock(character) local add_num = 0 -- if unlock_supreme_card then -- add_num = add_num + asset.DataConfig_proto[48].data3*100 -- end talent = talent or require "model.talent" local talent_list = talent.get_special_attr(character) if talent_list then add_num = add_num + (talent_list[ATTR_ADV_COIN] or 0) end if equip_list then add_num = add_num + (equip_list[ATTR_ADV_COIN] or 0) end return add_num end local function adv_exp_add_addition(character) -- supreme_card = supreme_card or require "model.activity.supreme_card" -- local unlock_supreme_card = supreme_card.card_unlock(character) local add_num = 0 -- if unlock_supreme_card then -- add_num = add_num + asset.DataConfig_proto[48].data2*100 -- end return add_num end local function adv_exp_stone_add_addition(character, equip_list) local add_num = 0 talent = talent or require "model.talent" local talent_list = talent.get_special_attr(character) if talent_list then add_num = add_num + (talent_list[ATTR_ADV_EXP_STONE] or 0) end if equip_list then add_num = add_num + (equip_list[ATTR_ADV_EXP_STONE] or 0) end return add_num end function THIS.simple_award(character, min, max) local list = {} local conf_list = assert(asset.StageConfig_proto, "StageConfig_proto") for i = min, max do local conf = conf_list[i] if not conf then break end for _, id in ipairs(conf.rewardId or {}) do if id <= 0 then break end local errno, temp = common_fun.get_award(id) if errno ~= 0 then return errno end if temp and next(temp) then if not next(list) then list = temp else list = common_fun.merge2list(list, temp) end end end end hero = hero or require "model.hero" local equip_list = hero.get_special_attr(character) local coin_addition = adv_coins_add_addition(character, equip_list) local exp_addition = adv_exp_add_addition(character) local exp_stone = adv_exp_stone_add_addition(character, equip_list) if coin_addition > 0 or exp_addition > 0 or exp_stone > 0 then list = list or common_fun.merge_award(list) for _, v in ipairs(list) do if v.id == CURRENCY_ID_COINS and coin_addition > 0 then v.num = v.num + math.floor(v.num * coin_addition/10000) end if v.id == CURRENCY_ID_ROLE_EXP and exp_addition > 0 then v.num = v.num + math.floor(v.num * exp_addition/10000) end if v.id == CURRENCY_ID_EXP_STONE and exp_stone > 0 then v.num = v.num + math.floor(v.num * exp_stone/10000) end end end return 0, list end function THIS.adventure_sweep(character, args) local d = _M.assert_get(character) or {} local id = args.id if not id then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local info_conf_list = assert(asset.StageInfoConfig_proto, "StageInfoConfig_proto") if not info_conf_list[id] then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end if d.pass[SIMPLE_ADV].id < id then return STD_ERR.ADVENTURE_NOT_PASS -- 未通关 end local conf_list = assert(asset.DataConfig_proto, "DataConfig_proto") local conf = conf_list[1] if not conf then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end local costnum = conf.data5[1] if not costnum then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end local pay_list = {{ id = CURRENCY_ID_STM, num = costnum }} local receipt = { module="adventure", brief="扫荡", context="扫荡:"..id, notify={ flags="adventure_sweep" }, detail=pay_list } -- 检查消耗 local errno = module_fun.paymeny_check(character, pay_list) if errno ~= 0 then return errno end local min_id = id*LAYER_SYS_NUM+1 local max_id = (id+1)*LAYER_SYS_NUM-1 local award_list errno, award_list = THIS.simple_award(character, min_id, max_id) if errno ~= 0 then return errno end if not award_list or not next(award_list) then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end -- 发奖励 local desc = { module="adventure", brief="扫荡", context= "扫荡:"..id, mailgen={subject=2, body=""}, notify={ flags="adventure_sweep" }, detail=award_list } payment(character, receipt, true) reward(character, desc) character.dispatch("sweep_simple_battle", id) return 0 end function THIS.adventure_pass_award(character, args) local id = args.id local key = args.type or 0 if not id then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end if key ~= SIMPLE_ADV and key ~= ELITE_ADV then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local d = _M.assert_get(character) local data = d.pass[key] if not d.pass[key] then return STD_ERR.COMMON_SYS_ERR -- 系统异常 end if data.id < id then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local temp_id = id - 1 local index = math_floor(temp_id/32)+1 local pos = math_floor(temp_id%32) data.award = data.award or {} if key == ELITE_ADV then index = math_floor((temp_id - 100)/10)+1 pos = math_floor(temp_id%10) end if index < 1 or pos < 0 then return STD_ERR.COMMON_SYS_ERR -- 参数异常 end for i = 1, index do data.award[i] = data.award[i] or 0 end if data.award[index] & (1< 0 then return STD_ERR.COMMON_AWARD_RECEIVED -- 已领取过奖励 end local conf_list if key == SIMPLE_ADV then conf_list = assert(asset.StageInfoConfig_proto, "StageInfoConfig_proto") elseif key == ELITE_ADV then conf_list = assert(asset.EliteInfoConfig_proto, "EliteInfoConfig_proto") else return STD_ERR.COMMON_CONF_ERR -- 配置异常 end local conf = conf_list[id] if not conf then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end local award_list = {} for i = 1, #conf.reward, 2 do local item = conf.reward[i] local num = conf.reward[i+1] if item and num and item > 0 and num > 0 then table_insert(award_list, {id = item, num = num}) else break end end -- 发奖励 local desc = { module="adventure", brief="通关奖励", context= "通关奖励:"..id, mailgen={subject=2, body=""}, notify={ flags="adventure_pass_award" }, detail=award_list } reward(character, desc) data.award[index] = data.award[index] | (1< 0 and not d.btrial then d.btrial = d.btrial or true _M.persist(character) end return 0 end function THIS.adventure_box_award(character, args) local id = args.id local pos = args.pos if not id or not pos or pos < 1 or pos > 10 then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local d = _M.assert_get(character) or {} local data = d.pass[SIMPLE_ADV] if not data then return STD_ERR.COMMON_SYS_ERR end if id > data.id + 1 then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local conf_list = THIS.get_conf_list(SIMPLE_ADV) if not conf_list then return STD_ERR.COMMON_SYS_ERR end local conf = conf_list[id] if not conf.boxcondition[pos] or not conf.box[pos] then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end if id == data.id + 1 then if not data.progress or data.progress <= conf.boxcondition[pos] then return STD_ERR.COMMON_AWARD_NOT_UNLOCK end end data.award_list = data.award_list or {} data.award_list[id] = data.award_list[id] or 0 local flag = 1 << pos-1 if data.award_list[id] & flag > 0 then return STD_ERR.COMMON_AWARD_RECEIVED end local errno, award_list = common_fun.get_award(conf.box[pos]) if errno ~= 0 then return errno end local desc = { module="adventure", brief="关卡宝箱奖励", context= string.format("关卡宝箱奖励%d", id), mailgen={subject=2, body=""}, notify={ flags="adventure_box_award" }, detail=award_list } reward(character, desc) data.award_list[id] = data.award_list[id] + flag _M.persist(character) return 0, {id = args.id, pos = args.pos, data = data.award_list[id]} end function REQUEST.adventure_start(character, args) return func_ret("adventure_start", character, args) end function REQUEST.adventure_end(character, args) return func_ret("adventure_end", character, args) end function REQUEST.adventure_data(character, args) local d = _M.assert_get(character) or {} -- local elite_id = d.pass[ELITE_ADV].id+1 -- if elite_id <= 100 then -- elite_id = MIN_ELITE_ID -- end -- if not asset.EliteInfoConfig_proto[elite_id] then -- for id = elite_id, elite_id + 20 do -- if asset.EliteInfoConfig_proto[id] then -- elite_id = id -- break -- end -- end -- end local list = {} d.pass[SIMPLE_ADV].award_list = d.pass[SIMPLE_ADV].award_list or {} for i = 1, d.pass[SIMPLE_ADV].id +1 do if d.pass[SIMPLE_ADV].award_list[i] then table.insert(list, d.pass[SIMPLE_ADV].award_list[i]) else table.insert(list, 0) end end return { errno = 0, id1 = d.pass[SIMPLE_ADV].id +1, award1 = d.pass[SIMPLE_ADV].award, -- id2 = elite_id, box_award = list, award2 = d.pass[ELITE_ADV].award, layer = d.pass[SIMPLE_ADV].progress and d.pass[SIMPLE_ADV].progress or 0, type = d.type and d.type or NIL_RET, cost = d.cost and d.cost or NIL_RET } end function REQUEST.adventure_layer(character, args) return func_ret("adventure_layer", character, args) end function REQUEST.adventure_sweep(character, args) return func_ret("adventure_sweep", character, args) end function REQUEST.adventure_pass_award(character, args) return func_ret("adventure_pass_award", character, args) end function REQUEST.adventure_ad_award(character, args) return func_ret("adventure_ad_award", character, args) end function REQUEST.adventure_trial(character, args) return func_ret("adventure_trial", character, args) end function REQUEST.adventure_box_award(character, args) return func_ret("adventure_box_award", character, args) end return MODULE