-- 收纳箱(回收道具) -- -- doCalcHero 统计收纳箱英雄属性加成 -- RecycleItem_Query 查询收纳箱等级/经验/属性 -- RecycleItem_RecycleItemListQuery 查询可回收道具列表 -- RecycleItem_Recycle_Do 执行回收 --db --[=[ human.db.recycleData = { level = nil, exp = nil, } ]=]-- local Msg = require("core.Msg") local Lang = require("common.Lang") local Broadcast = require("broadcast.Broadcast") local Util = require("common.Util") local BagLogic = require("bag.BagLogic") local RoleAttr = require("role.RoleAttr") local RoleDefine = require("role.RoleDefine") local ObjHuman = require("core.ObjHuman") local RecycleConfig = require("excel.recycleItem").RecycleLvList local ItemConfig = require("excel.item").item local FuwenConfig = require("excel.fuwen").fuwen local ItemDefine = require("bag.ItemDefine") local FuwenLogic = require("fuwen.FuwenLogic") -- local RoleSystemLogic = require("roleSystem.RoleSystemLogic") -- local RoleSystemDefine = require("roleSystem.RoleSystemDefine") local LOG_TAG = "RecycleItem" -- 本系统的日志标识 local OPEN_COND_LV = 150 -- 开启功能需要的等级 local RECYCLE_ITEM_TYPE_ITEM = 1 -- item表道具 local RECYCLE_ITEM_TYPE_FUWEN = 2 -- 符文 -- 初始化收纳箱数据 local function initRecycleData(human) human.db.recycleData = { level = 0, exp = 0 } end -- 获取收纳箱数据 local function getRecycleData(human) return human.db.recycleData end -- 获取道具/符文的回收值, 仅 val > 0 时可回收 local function getRecycleVal(itemId) if ItemDefine.isFuwen(itemId) then local fuwenCfg = FuwenConfig[itemId] if fuwenCfg and fuwenCfg.val and fuwenCfg.val > 0 then return fuwenCfg.val end return end local itemCfg = ItemConfig[itemId] if itemCfg and itemCfg.val and itemCfg.val > 0 then return itemCfg.val end end -- 收集背包中可回收的item表道具, 返回 {{id, recycleVal, extraInfo}, ...} local function collectItemRecycleList(human) local itemArr = {} local bagData = BagLogic.GetBagData(human) if not bagData then return itemArr end for itemId in pairs(bagData) do if not ItemDefine.isFuwen(itemId) then local itemCfg = ItemConfig[itemId] if itemCfg and itemCfg.val and itemCfg.val > 0 then itemArr[#itemArr + 1] = {itemId, itemCfg.val, 0} end end end return itemArr end -- 收集符文背包中可回收的符文, extraInfo 为符文背包idx local function collectFuwenRecycleList(human) local itemArr = {} local fuwenBag = FuwenLogic.getFuwenBagData(human) if not fuwenBag then return itemArr end for index, fuwenGrid in pairs(fuwenBag) do local fuwenId = fuwenGrid and fuwenGrid.id if fuwenId then local recycleVal = getRecycleVal(fuwenId) if recycleVal then itemArr[#itemArr + 1] = {fuwenId, recycleVal, index} end end end return itemArr end -- 解析回收请求字符串, 返回 {{id, value}, ...} local function parseRecycleEntries(recycleItemStr) local entries = Util.parseKVList(recycleItemStr, "|", "-", Util.TONUMBER_ALL) if #entries == 0 then return end return entries end -- 合并相同道具id的回收数量, 避免重复条目导致数量校验/扣除错误 local function mergeItemRecycleEntries(entries) local mergedMap = {} for _, entry in ipairs(entries) do local itemId, itemCnt = entry[1], entry[2] mergedMap[itemId] = (mergedMap[itemId] or 0) + (itemCnt or 0) end local mergedList = {} for itemId, itemCnt in pairs(mergedMap) do mergedList[#mergedList + 1] = {itemId, itemCnt} end return mergedList end -- 校验item表道具回收, 成功返回 totalExp, 失败返回 nil, errLang local function validateItemRecycle(human, entries) local totalExp = 0 for _, entry in ipairs(entries) do local itemId, itemCnt = entry[1], entry[2] if not itemId or not itemCnt or itemCnt <= 0 then return nil, Lang.COMMON_ARGUMENT_ERROR end if ItemDefine.isFuwen(itemId) then return nil, Lang.ITEM_CANNOT_RECYCLE end local recycleVal = getRecycleVal(itemId) if not recycleVal then return nil, Lang.ITEM_CANNOT_RECYCLE end if BagLogic.getItemCnt(human, itemId) < itemCnt then return nil, Lang.COMMON_ITEM_NOT_ENOUGH end totalExp = totalExp + recycleVal * itemCnt end return totalExp end -- 校验符文回收, 成功返回 totalExp, 失败返回 nil, errLang local function validateFuwenRecycle(human, entries) local totalExp = 0 local indexMap = {} for _, entry in ipairs(entries) do local fuwenId, index = entry[1], entry[2] if not fuwenId or not index or index <= 0 or indexMap[index] then return nil, Lang.COMMON_ARGUMENT_ERROR end indexMap[index] = true local recycleVal = getRecycleVal(fuwenId) if not recycleVal then return nil, Lang.ITEM_CANNOT_RECYCLE end local fuwenGrid = FuwenLogic.getFuwenGrid(human, index) if not fuwenGrid or fuwenGrid.id ~= fuwenId then return nil, Lang.COMMON_ITEM_NOT_ENOUGH end totalExp = totalExp + recycleVal end return totalExp end -- 删除待回收的item表道具 local function deleteItemRecycle(human, entries) for _, entry in ipairs(entries) do BagLogic.delItem(human, entry[1], entry[2], LOG_TAG) end end -- 删除待回收的符文 local function deleteFuwenRecycle(human, entries) for _, entry in ipairs(entries) do FuwenLogic.del(human, entry[2], LOG_TAG) end end -- 回收校验处理器, 按 itemType 分发 local RECYCLE_VALIDATE_HANDLER = { [RECYCLE_ITEM_TYPE_ITEM] = validateItemRecycle, [RECYCLE_ITEM_TYPE_FUWEN] = validateFuwenRecycle, } -- 回收删除处理器, 按 itemType 分发 local RECYCLE_DELETE_HANDLER = { [RECYCLE_ITEM_TYPE_ITEM] = deleteItemRecycle, [RECYCLE_ITEM_TYPE_FUWEN] = deleteFuwenRecycle, } -- 更新收纳箱等级和经验 local function updateRecycleData(human, newLv, newExp) local recycleData = getRecycleData(human) if not recycleData then initRecycleData(human) recycleData = getRecycleData(human) end recycleData.level = newLv recycleData.exp = newExp end -- 是否开启本系统 local function isOpen(human) -- return RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_2031) -- 待修改 return human.db.lv >= OPEN_COND_LV end -- 计算当前等级加成属性 local function calcCurrentLvAttrs(currentLevel) if not currentLevel or currentLevel <= 0 then return end local attrs = {} for i=1, currentLevel do local cfg = RecycleConfig[i] if cfg and cfg.attrs then for _,v in ipairs(cfg.attrs) do local attrId = v[1] local attrVal = v[2] attrs[attrId] = (attrs[attrId] or 0) + attrVal end end end return attrs end -- 重算战力 local function updatePower(human) RoleAttr.cleanHeroAttrCache(human) RoleAttr.doCalc(human) ObjHuman.sendAttr(human, RoleDefine.ZHANDOULI) end -- 计算出新的等级和经验 local function calcLv(human, addExp) local recycleData = getRecycleData(human) local currentLevel = recycleData and recycleData.level or 0 local currentExp = recycleData and recycleData.exp or 0 currentExp = currentExp + addExp local newLv = currentLevel for i=currentLevel+1, #RecycleConfig do local cfg = RecycleConfig[i] if currentExp < cfg.exp then break end currentExp = currentExp - cfg.exp newLv = i if currentExp <= 0 then break end end return newLv, currentExp end -- 填充当前等级属性到协议结构 local function populateCurrentLvAttrs(net, currentLevel) local isZero = false if currentLevel <= 0 then currentLevel = 1 isZero = true end local len = 0 net[0] = len local attrs = calcCurrentLvAttrs(currentLevel) for attrId, attrVal in pairs(attrs or {}) do len = len + 1 net[0] = len net[len].key = attrId net[len].value = isZero and 0 or attrVal end end -- 填充下一等级属性到协议结构 local function populateNextLvAttrs(net, nextLv) local isMax = false local maxLv = #RecycleConfig if maxLv <= nextLv then nextLv = maxLv isMax = true end net[0] = 0 local cfg = RecycleConfig[nextLv] if cfg and cfg.attrs then net[0] = #cfg.attrs for k,v in ipairs(cfg.attrs) do net[k].key = v[1] net[k].value = isMax and 0 or v[2] end end end -- local function populateRecycleItem(net, human) -- net[0] = 0 -- local bagData = BagLogic.GetBagData(human) -- if not bagData then -- return -- end -- local len = 0 -- for itemId in pairs(bagData) do -- local itemCfg = ItemConfig[itemId] -- if itemCfg and itemCfg.val and itemCfg.val > 0 then -- len = len + 1 -- net[0] = len -- net[len].id = itemId -- net[len].recycleVal = itemCfg.val -- end -- end -- end -- 外部调用, 统计收纳箱加成属性 function doCalcHero(human, addAttrs) if not human then return end local recycleData = getRecycleData(human) if not recycleData then return end local currentLevel = recycleData and recycleData.level or 0 if currentLevel <= 0 then return end local attrs = calcCurrentLvAttrs(currentLevel) for attrId, attrVal in pairs(attrs or {}) do RoleAttr.updateValue(attrId, attrVal, addAttrs) end end -- 查询收纳箱等级、经验及属性加成 function RecycleItem_Query(human) if not isOpen(human) then return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED) end local recycleData = getRecycleData(human) local currentLevel = recycleData and recycleData.level or 0 local currentExp = recycleData and recycleData.exp or 0 local maxLevel = #RecycleConfig local nextLvExp = 0 if currentLevel < maxLevel then local nextLvCfg = RecycleConfig[currentLevel + 1] nextLvExp = nextLvCfg.exp end local msgRet = Msg.gc.GC_RECYCLE_QUERY msgRet.currentLevel = currentLevel msgRet.maxLevel = maxLevel msgRet.currentExp = currentExp msgRet.nextLvExp = nextLvExp populateCurrentLvAttrs(msgRet.currentLvAttrs, currentLevel) populateNextLvAttrs(msgRet.nextLvAttrs, currentLevel+1) -- populateRecycleItem(msgRet.recycleList, human) Msg.send(msgRet, human.fd) end -- 查询可回收道具列表, itemType: 1-item表道具, 2-符文 function RecycleItem_RecycleItemListQuery(human, itemType) if not isOpen(human) then return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED) end if itemType ~= RECYCLE_ITEM_TYPE_ITEM and itemType ~= RECYCLE_ITEM_TYPE_FUWEN then return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR) end local msgRet = Msg.gc.GC_RECYCLE_GET_RECYCLE_LIST msgRet.recycleList[0] = 0 msgRet.isStart = 1 msgRet.isEnd = 0 local itemArr if itemType == RECYCLE_ITEM_TYPE_FUWEN then itemArr = collectFuwenRecycleList(human) else itemArr = collectItemRecycleList(human) end local itemNum = #itemArr if itemNum == 0 then msgRet.isEnd = 1 return Msg.send(msgRet, human.fd) end local len = 0 local onceMsgLen = 50 for _, itemInfo in ipairs(itemArr) do len = len + 1 msgRet.recycleList[0] = len msgRet.recycleList[len].id = itemInfo[1] msgRet.recycleList[len].recycleVal = itemInfo[2] msgRet.recycleList[len].extraInfo = itemInfo[3] or 0 if len >= onceMsgLen then itemNum = itemNum - len if itemNum <= 0 then msgRet.isEnd = 1 return Msg.send(msgRet, human.fd) end Msg.send(msgRet, human.fd) len = 0 msgRet.isStart = 0 end end if len > 0 then msgRet.isEnd = 1 Msg.send(msgRet, human.fd) end end -- 执行回收, itemType: 1-item表道具, 2-符文 function RecycleItem_Recycle_Do(human, itemType, recycleItemStr) if not isOpen(human) then return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED) end if itemType ~= RECYCLE_ITEM_TYPE_ITEM and itemType ~= RECYCLE_ITEM_TYPE_FUWEN then return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR) end local recycleData = getRecycleData(human) local currentLevel = recycleData and recycleData.level or 0 if currentLevel >= #RecycleConfig then return Broadcast.sendErr(human, Lang.COMMON_MAXLEVEL) end local entries = parseRecycleEntries(recycleItemStr) if not entries then return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR) end if itemType == RECYCLE_ITEM_TYPE_ITEM then entries = mergeItemRecycleEntries(entries) end local validateHandler = RECYCLE_VALIDATE_HANDLER[itemType] local deleteHandler = RECYCLE_DELETE_HANDLER[itemType] local totalExp, errLang = validateHandler(human, entries) if errLang then return Broadcast.sendErr(human, errLang) end deleteHandler(human, entries) local newLv, newExp = calcLv(human, totalExp) updateRecycleData(human, newLv, newExp) updatePower(human) RecycleItem_Query(human) RecycleItem_RecycleItemListQuery(human, itemType) end