local schema = require "model.schema" local logger = require "logger" local common_fun = require "model.common_fun" local module_fun = require "model.module_fun" local asset = require "model.asset" local payment = require "model.payment" local reward = require "model.reward" local stringify = require "stringify" local keygen = require "model.keygen" local embattle local logger_trace = logger.trace local table_insert = table.insert local math_min = math.min local MAX_NUM = 2000 -- 装备背包最大数量 local MAX_UPGRADE = 1000 -- 最大升级数量 local module_name = "equip" local _M = schema.new(module_name, { first = nil, key = 100, num = 0, list = { --[[ [sid] = { sid = 唯一id, id = 模板id, lv = 1, hero = 穿戴的英雄id } ]] }, }) local REQUEST = {} local CMD = {} local MODULE = {} local THIS = {} local tm_list = {} tm_list.equip_onekey_upgrade_star = 0 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 if tm_list[fname] then local now = os.time() if now - tm_list[fname] == 0 then return {errno = STD_ERR.COMMON_CLICK_TOO_FAST} -- 点击太快了 else tm_list[fname] = now end 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.num = d.num or 0 d.list = d.list or {} end -- TODO: 侦听事件 function MODULE.monitor(character) end -- TODO: 类似泰利的 prepare 接口 function MODULE.launch(character) local d = _M.assert_get(character) local u = _M.assert_runtime(character) embattle = embattle or require "model.embattle" end -- TODO: 与客户端同步数据 function MODULE.ready(character) local d = _M.assert_get(character) -- logger.test("%s:ready, %s", module_name, stringify(d or {})) end -- TODO: 玩家下线时的处理 function MODULE.saybye(character) end function MODULE.equip_surplus(character) local d = _M.assert_get(character) return math.max((MAX_NUM - d.num), 0) end local function new_equip(character, id) return { sid = THIS.key(character), id = id, lv = 1 } end function MODULE.add_equip(character, id, num, collect, dispose, addition) local d = _M.assert_get(character) or {} local equip_conf_list = assert(asset.ArmorConfig_proto, "ArmorConfig_proto") local conf = equip_conf_list[id] if not conf and dispose then dispose(nil, id, num) return end local surplus = MODULE.equip_surplus(character) if num >= 1 and num <= MAX_NUM then local add_num = math.min(surplus, num) if add_num > 0 then for i = 1, add_num do local equip = new_equip(character, id) d.list[equip.sid] = equip collect(GOODS_EQUIP, equip) end d.num = d.num + add_num _M.persist(character) character.dispatch("equip_add_num", id, num) end addition(GOODS_EQUIP, id, add_num) if add_num < num then dispose(GOODS_EQUIP, id, num - add_num) end return true, add_num else if dispose then dispose(nil, id, num) end end end function MODULE.equip_check(character, sid) local d = _M.assert_get(character) return d.list[sid] and true or false end function MODULE.equip_get(character, sid) local d = _M.assert_get(character) return d.list[sid] end function MODULE.equip_wear(character, hero, old_list, new_list) local d = _M.assert_get(character) local equip_conf_list = assert(asset.ArmorConfig_proto, "ArmorConfig_proto") local old_wear = 0 local new_wear = 0 local surplus = MODULE.equip_surplus(character) local sid = hero.sid local heroid = hero.id local hero_conf = asset.RoleConfig_proto[heroid] if not hero_conf then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end local hero_profession = hero_conf.profession for pos, esid in ipairs(new_list or {}) do if esid and esid ~= "" then local data = d.list[esid] if not data then return STD_ERR.COMMON_PARM_ERR -- 未找到装备 end local id = data.id local conf = equip_conf_list[id] if not conf then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end if conf.type ~= pos then return STD_ERR.EQUIP_POS_ERR -- 装备位置异常 end local can_wear = false for _, profession in ipairs(conf.profession) do if hero_profession == profession then can_wear = true break end end if not can_wear then return STD_ERR.EQUIP_PROFESSION_ERR -- 装备位置异常 end if data.hero and data.hero ~= sid then return STD_ERR.EQUIP_BE_USED -- 装备被穿戴 end new_wear = new_wear + 1 end end for _, esid in ipairs(old_list or {}) do if esid and esid ~= "" and d.list[esid] and d.list[esid].hero then old_wear = old_wear + 1 end end if surplus < old_wear - new_wear then return STD_ERR.EQUIP_FULL -- 背包已满 end for _, esid in ipairs(old_list or {}) do if esid and esid ~= "" and d.list[esid] and d.list[esid].hero then d.list[esid].hero = nil end end for _, esid in ipairs(new_list or {}) do if esid and esid ~= "" and d.list[esid] then d.list[esid].hero = sid end end d.num = d.num + new_wear - old_wear _M.persist(character) return 0 end function MODULE.equip_remove_check(character, list) local num = MODULE.equip_surplus(character) return num > #list end function MODULE.equip_remove(character, list) local d = _M.assert_get(character) local add_num = 0 for _, esid in ipairs(list or {}) do if esid and esid ~= "" and d.list[esid] and d.list[esid].hero then d.list[esid].hero = nil add_num = add_num + 1 end end d.num = d.num + add_num _M.persist(character) return 0 end function MODULE.equip_save(character) _M.persist(character) end function THIS.equip_get_data(character, args) local d = _M.assert_get(character) return 0, {list = common_fun.tqueue(d.list)} end local function get_max_upgrade(character, equip_pos, cur_lv, max_lv) local num = 0 local max_lv = max_lv or cur_lv + MAX_UPGRADE local level_conf_list = assert(asset.EquipmentLevelConfig_proto, "EquipmentLevelConfig_proto") local scrol_id = asset.DataConfig_proto[6].data6[equip_pos] local errno = common_fun.goods_check(scrol_id) if errno ~= 0 then return num end local goods_list = {} for lv = cur_lv+1, max_lv do local level_conf = level_conf_list[lv] if not level_conf then break end if level_conf.scrollNum > 0 then local item_id = scrol_id local item_num = level_conf.scrollNum if not goods_list[item_id] then goods_list[item_id] = module_fun.get_goods_num(character, item_id) end if goods_list[item_id] < item_num then break end goods_list[item_id] = goods_list[item_id] - item_num end if level_conf.goodNum > 0 then local item_id = CURRENCY_ID_COINS local item_num = level_conf.goodNum if not goods_list[item_id] then goods_list[item_id] = module_fun.get_goods_num(character, item_id) end if goods_list[item_id] < item_num then break end goods_list[item_id] = goods_list[item_id] - item_num end num = lv - cur_lv end return num end local function upgrade_award(equip_pos, cur, tar, list) local item_id = asset.DataConfig_proto[6].data6[equip_pos] local errno = common_fun.goods_check(item_id) if errno ~= 0 then return errno end local level_conf_list = assert(asset.EquipmentLevelConfig_proto, "EquipmentLevelConfig_proto") for lv = cur+1, tar do local level_conf = level_conf_list[lv] if not level_conf then return STD_ERR.COMMON_SYS_ERR -- 系统异常 end if level_conf.scrollNum > 0 then table_insert(list, {id = item_id, num = level_conf.scrollNum}) end if level_conf.goodNum > 0 then table_insert(list, {id = CURRENCY_ID_COINS, num = level_conf.goodNum}) end end return 0 end local function reset_level(equip_pos, lv, list) return upgrade_award(equip_pos, 1, lv, list) end function THIS.key(character) local d = _M.assert_get(character) d.key = d.key + 1 return tostring(d.key) end function THIS.equip_upgrade(character, args) local d = _M.assert_get(character) local sid = args.sid local num = args.num or 0 if not sid then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end if num < 0 or num > MAX_UPGRADE then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local data = d.list[sid] local level = data.lv if not data then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local equip_conf_list = assert(asset.ArmorConfig_proto, "ArmorConfig_proto") local equip_conf = equip_conf_list[data.id] if not equip_conf then logger_trace("ArmorConfig_proto:%d", data.id) return STD_ERR.COMMON_CONF_ERR -- 配置异常 end local quality_conf_list = assert(asset.EquipmentQualityConfig_proto, "EquipmentQualityConfig_proto") local cur_quality = common_fun.get_equip_quality(data.id) local quality_conf = quality_conf_list[cur_quality] if not quality_conf then logger_trace("EquipmentQualityConfig_proto:%d", cur_quality) return STD_ERR.COMMON_CONF_ERR -- 配置异常 end if num == 0 then num = get_max_upgrade(character, equip_conf.type, level, math_min(quality_conf.maxLv, character.level)) end if level+num > quality_conf.maxLv or level+num > character.level then return STD_ERR.EQUIP_MAX_LEVEL -- 超过最大等级 end local pay_list = {} local errno = upgrade_award(equip_conf.type, level, level+num, pay_list) if errno ~= 0 then return errno end local receipt = { module="equip", brief="装备升级", context=string.format("装备id%d, 从%d升级到%d", data.id, level, level+num), notify={ flags="equip_upgrade" }, detail=pay_list } local errno = payment(character, receipt) if errno ~=0 then return errno end local pre_lv = data.lv local cur_lv = data.lv + num data.lv = data.lv+num _M.persist(character) character.dispatch("equip_upgrade", data.id, pre_lv, cur_lv) return 0, {data = data} end function THIS.equip_upgrade_star(character, args) local d = _M.assert_get(character) local sid = args.sid local same_list = args.same or {} local other_list = args.other or {} local item_list = args.currency or {} local buse_item = next(item_list) and item_list.num and item_list.num > 0 and true or false if buse_item then if not item_list.id then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end end if not sid then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local data = d.list[sid] if not data then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end -- 先检查是否重复 local temp_list = {[sid] = 1} for _, v in ipairs(same_list) do if temp_list[v] then return STD_ERR.EQUIP_SAME_SID -- 重复的装备id end if not d.list[v] or d.list[v].hero then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end temp_list[v] = 1 end for _, v in ipairs(other_list) do if temp_list[v] then return STD_ERR.EQUIP_SAME_SID -- 重复的装备id end if not d.list[v] or d.list[v].hero then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end temp_list[v] = 1 end local equip_conf_list = assert(asset.ArmorConfig_proto, "ArmorConfig_proto") local equip_conf = equip_conf_list[data.id] local equip_type = equip_conf.type if not equip_type then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end if not equip_conf then logger_trace("ArmorConfig_proto:%d", data.id) return STD_ERR.COMMON_CONF_ERR -- 配置异常 end local cur_quality = common_fun.get_equip_quality(data.id) local max_quality = asset.DataConfig_proto[5].data3 if cur_quality >= max_quality then return STD_ERR.EQUIP_START_MAX -- 达到最大突破等级 end local min_id = math.floor(data.id/100)*100+1 local max_id = min_id + 98 local conf_id = data.id + 1 if not equip_conf_list[conf_id] then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end local quality_conf_list = assert(asset.EquipmentQualityConfig_proto, "EquipmentQualityConfig_proto") local quality_conf = quality_conf_list[cur_quality+1] if not quality_conf then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end -- 检查消耗数量 if quality_conf.sameQualityNum ~= #same_list or quality_conf.anyQualityNum ~= #other_list + (buse_item and item_list.num or 0) then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end --检查同名装备消耗 for i = 1, #same_list do local id = d.list[same_list[i]].id if id < min_id or id > max_id then return STD_ERR.EQUIP_SAME_PAY_ERR -- 不符合消耗条件 end -- local conf = equip_conf_list[id] local quality = common_fun.get_equip_quality(id) if quality ~= quality_conf.sameQuality then return STD_ERR.EQUIP_SAME_PAY_ERR -- 不符合消耗条件 end end --检查任意装备消耗 for i = 1, #other_list do local id = d.list[other_list[i]].id local conf = equip_conf_list[id] local quality = common_fun.get_equip_quality(id) if quality ~= quality_conf.anyQuality or conf.type ~= equip_type then return STD_ERR.EQUIP_OTHER_PAY_ERR -- 不符合消耗条件 end end local del_list = {} local award_list = {} -- 把突破的装备排除和已装备的装备排除 temp_list[sid] = nil for k in pairs(temp_list) do if d.list[k].lv > 1 or d.list[k].hero then local errno = reset_level(equip_type, d.list[k].lv, award_list) if errno ~= 0 then return errno end end table_insert(del_list, k) end -- 检查替代品消耗 if buse_item then if quality_conf.resetGoods[equip_type] ~= item_list.id then return STD_ERR.EQUIP_OTHER_PAY_ERR -- 不符合消耗条件 end local receipt = { module="equip", brief="装备升星", context=string.format("装备id%d, 升星为%d", data.id, conf_id), notify={ flags="equip_upgrade_star" }, detail={item_list} } local errno = payment(character, receipt) if errno ~= 0 then return errno end end if next(award_list) then local desc = { module="equip", brief="装备突破", context= "装备突破返还", mailgen={subject=2, body=""}, notify={ flags="equip_upgrade_star" }, detail=award_list } reward(character, desc) end for _, v in ipairs(del_list)do if d.list[v] then d.list[v] = nil end end d.list[sid].id = conf_id d.num = d.num - #temp_list _M.persist(character) character.dispatch("equip_del", del_list) character.dispatch("equip_upstart", conf_id, cur_quality, cur_quality+1) return 0, {data = d.list[sid], same = args.same, other = args.other, currency = args.currency} end function THIS.equip_onekey_upgrade_star(character, args) local d = _M.assert_get(character) local temp_list = {} for sid, data in pairs(d.list) do -- 紫色 未上阵 未升级的装备一键突破 local quality = common_fun.get_equip_quality(data.id) if data.lv == 1 and quality < STAR_COLOR_PURPLE and not data.hero or data.hero == "" then temp_list[quality] = temp_list[quality] or {} temp_list[quality][data.id] = temp_list[quality][data.id] or {} table_insert(temp_list[quality][data.id], sid) end end local del_list = {} local change_list = {} local max_quality = 1 for quality = 1, STAR_COLOR_PURPLE do local quality_conf_list = assert(asset.EquipmentQualityConfig_proto, "EquipmentQualityConfig_proto") if not quality_conf_list[quality] or quality_conf_list[quality].anyQualityNum > 0 then break end local temp = temp_list[quality] if temp then for id, list in pairs(temp) do local quality_conf = quality_conf_list[quality+1] local equip_conf = assert(asset.ArmorConfig_proto, "ArmorConfig_proto")[id+1] local num = #list local step = quality_conf.sameQualityNum+1 assert(step > 0) if equip_conf and step <= num and quality_conf.sameQuality == quality then for i = 1, num, step do if list[i+step-1] then d.list[list[i]].id = id+1 table.insert(change_list, d.list[list[i]]) for j = i+1, i+step-1 do d.list[list[j]] = nil table.insert(del_list, list[j]) end max_quality = quality if #change_list >= 100 then goto equip_onekey_upgrade_star_break end end end end end end end ::equip_onekey_upgrade_star_break:: if not next(change_list) then return STD_ERR.EQUIP_NOBODY_CAN_UP_STAR -- 没有 end d.num = d.num - #del_list _M.persist(character) character.dispatch("equip_del", del_list) character.dispatch("equip_upstart_times", #change_list, max_quality+1) return 0, {del_list = del_list, change_list = change_list} end -- 重置装备 function THIS.equip_reset(character, args) local sid = args.sid if not sid then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local d = _M.assert_get(character) local data = d.list[sid] if not data then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local temp_data = common_fun.scopy(data) local award_list = {} local desc = { module="equip", brief="重置装备", mailgen={subject=2, body=""}, notify={ flags="equip_reset" }, } local equip_conf_list = assert(asset.ArmorConfig_proto, "ArmorConfig_proto") local equip_conf = equip_conf_list[data.id] if not equip_conf then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end if args.level then if data.lv <= 1 then return STD_ERR.COMMON_PARM_ERR -- 参数异常 end desc.context= string.format("重置装备等级, sid:%s, lv:%d", sid, data.lv) else local quality = common_fun.get_equip_quality(data.id) local min_quality = -1 if quality > STAR_COLOR_RED then min_quality = STAR_COLOR_RED elseif quality > STAR_COLOR_ORANGE then min_quality = STAR_COLOR_ORANGE elseif quality > STAR_COLOR_PURPLE then min_quality = STAR_COLOR_PURPLE else return STD_ERR.COMMON_PARM_ERR -- 参数异常 end local quality_conf_list = assert(asset.EquipmentQualityConfig_proto, "EquipmentQualityConfig_proto") for i = min_quality+1, quality do local quality_conf = quality_conf_list[i] if not quality_conf or quality_conf.sameQualityNum > 0 then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end local item_id = quality_conf.resetGoods[equip_conf.type] if not item_id or item_id <= 0 then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end table_insert(award_list, {id = item_id, num = quality_conf.anyQualityNum}) end local new_id = math.floor(data.id/100)*100+min_quality equip_conf = equip_conf_list[new_id] if not equip_conf then return STD_ERR.COMMON_CONF_ERR -- 配置异常 end desc.context = string.format("重置装备突破等级, sid:%s, id:%d==>%d", sid, data.id, new_id) temp_data.id = new_id end if data.lv > 1 then local errno = reset_level(equip_conf.type, data.lv, award_list) if errno ~= 0 then return end temp_data.lv = 1 end desc.detail = award_list reward(character, desc) d.list[sid] = temp_data _M.persist(character) return 0, {data = temp_data} end -- 装备背包数据 function REQUEST.equip_get_data(character, args) return func_ret("equip_get_data", character, args) end -- 装备升级 function REQUEST.equip_upgrade(character, args) return func_ret("equip_upgrade", character, args) end -- 装备升星 function REQUEST.equip_upgrade_star(character, args) return func_ret("equip_upgrade_star", character, args) end -- 一键升星 function REQUEST.equip_onekey_upgrade_star(character, args) return func_ret("equip_onekey_upgrade_star", character, args) end -- 重置 function REQUEST.equip_reset(character, args) return func_ret("equip_reset", character, args) end function MODULE.get_equip_data(character, sid) local d = _M.assert_get(character) return d.list[sid] end return MODULE