Kaynağa Gözat

收纳箱功能

gitxsm 3 hafta önce
ebeveyn
işleme
b03514693f

+ 1 - 0
script/common/Lang.lua

@@ -213,6 +213,7 @@ ITEM_GET_SUCCESS = [[领取成功]]
 ITEM_BUY_ERROR = [[购买错误]]
 ITEM_BUY_ERR_MAX = [[道具购买已达上限]]
 ITEM_BUY_DEFAULT = [[购买失败]]
+ITEM_CANNOT_RECYCLE = [[道具无法被回收]]
 
 ACT_NOT_START = [[活动未开始]]
 ACT_WAS_OVER = [[活动已结束]]

+ 4 - 2
script/common/LogDefine.lua

@@ -320,8 +320,10 @@ DEFINE = {
 	HeroTianYuan 			= 780,  		-- 英雄天元系统
 	BreakThroughTheme 		= 781,  		-- 闯关主题
 	VoucherInvest 			= 782,  		-- 代金券投资
-	Artifacts				= 783,			-- 英雄神威灵装
-	BattleGift				= 784,			-- 闯关礼金
+	LevelGift 				= 783,  		-- 送万元充值
+	Artifacts				= 784,			-- 英雄神威灵装
+	BattleGift				= 785,			-- 闯关礼金
+	RecycleItem				= 786,			-- 收纳箱
 
 	errHandle				= 99999,		-- 异常处理
 }

+ 4 - 0
script/common/ProtoID.lua

@@ -1815,6 +1815,10 @@ _ENV[1851]="CG_BATTLEGIFT_GET"
 
 _ENV[1854]="GC_POWERRANK_TOPONE_LOGIN"
 
+_ENV[1855]="CG_RECYCLE_QUERY"
+_ENV[1856]="GC_RECYCLE_QUERY"
+_ENV[1857]="CG_RECYCLE_RECYCLEITEM"
+
 _ENV[1896]="CG_ZHUANPAN_SUBSCRIBE_REWARD_QUERY"
 _ENV[1897]="GC_ZHUANPAN_SUBSCRIBE_REWARD_QUERY"
 _ENV[1898]="CG_ZHUANPAN_SUBSCRIBE_REWARD_GET"

+ 56 - 0
script/common/Util.lua

@@ -474,6 +474,62 @@ function split(str, split_char,isNumber)
     return t
 end
 
+
+TONUMBER_KEY   = "key"
+TONUMBER_VALUE = "value"
+TONUMBER_ALL   = "all"
+--- 灵活解析键值字符串
+-- @param str           源字符串,如 "1001-10|1002-11"
+-- @param segSep        段分隔符,如 "|"(默认 "|")
+-- @param kvSep         键值分隔符,如 "-"(默认 "-")
+-- @param tonumberMode  可选:"key"只转键,"value"只转值,"all"都转,nil不转
+-- @return table        解析后的字典表
+function parseKVString(str, segSep, kvSep, tonumberMode)
+    -- 防护:nil 或空字符串直接返回空表
+    if not str or str == "" then
+        return {}
+    end
+
+    -- 去掉首尾空白(可选,视需求而定)
+    str = string.match(str, "^%s*(.-)%s*$") or ""
+    if str == "" then
+        return {}
+    end
+
+    segSep = segSep or "|"
+    kvSep = kvSep or "-"
+
+    -- 转义模式中的特殊字符
+    local function escapePattern(s)
+        return (string.gsub(s, "([%-%.%+%*%?%[%]%^%$%(%)%%])", "%%%1"))
+    end
+
+    local segPattern = escapePattern(segSep)
+
+    local result = {}
+
+    for segment in string.gmatch(str, "([^" .. segPattern .. "]+)") do
+        local pos = string.find(segment, kvSep, 1, true)
+        if pos then
+            local key = string.sub(segment, 1, pos - 1)
+            local value = string.sub(segment, pos + string.len(kvSep))
+
+            if tonumberMode == "key" or tonumberMode == "all" then
+                key = tonumber(key) or key
+            end
+            if tonumberMode == "value" or tonumberMode == "all" then
+                value = tonumber(value) or value
+            end
+
+            result[key] = value
+        end
+    end
+
+    return result
+end
+
+
+
 -- 根据KEY从小到大排序
 function pairsByKeys(t)
 	local a = {}

+ 4 - 0
script/module/bag/BagLogic.lua

@@ -885,4 +885,8 @@ function calculateBonusItemCount(human, id, cnt,logType)
     end
     -- 默认返回原数量
     return cnt
+end
+
+function GetBagData(human)
+	return human.db.bag
 end

+ 10 - 0
script/module/bag/Handler.lua

@@ -4,6 +4,7 @@ local ItemLogic = require("bag.ItemLogic")
 local BoxLogic = require("bag.BoxLogic")
 local DropSpecial = require("bag.DropSpecial")
 local HeroSkinLogic = require("present.HeroSkinLogic")
+local RecycleItem = require("bag.RecycleItem")
 
 -- 请求碎片英雄信息
 function CG_SUIPIAN_HERO_QUERY(human, msg)
@@ -91,4 +92,13 @@ end
 
 function CG_DUIHUANG_DO(human, msg)
 	SuipianLogic.SuiPianLogic_DuiHuangDo(human, msg.nID, msg.nNum)
+end
+
+
+function CG_RECYCLE_QUERY(human, msg)
+	RecycleItem.RecycleItem_Query(human)
+end
+
+function CG_RECYCLE_RECYCLEITEM(human, msg)
+	RecycleItem.RecycleItem_Recycle_Do(human, msg.recycleItemStr)
 end

+ 26 - 0
script/module/bag/Proto.lua

@@ -364,4 +364,30 @@ GC_DUIHUANG_QUERY = {
 CG_DUIHUANG_DO = {
 	{"nID",		1,		"int"},		-- 物品ID
 	{"nNum",	1,		"int"},		-- 兑换数量
+}
+
+
+-------------------------收纳箱---------------------------------
+
+RECYCLE_ITEM = {
+	{"id",			1,		"int"},		-- 物品ID
+	{"recycleVal",	1,		"short"},	-- 回收值
+}
+--查询
+CG_RECYCLE_QUERY = {}
+
+GC_RECYCLE_QUERY = {
+	{"currentLevel",	1,		"short"},		-- 当前等级
+	{"maxLevel",		1,		"short"},		-- 最高等级
+	{"currentExp",		1,		"int"},			-- 当前经验值
+	{"nextLvExp",		1,		"int"},			-- 升到下一级所需经验
+	{"currentLvAttrs",	4,		Attr},			-- 当前等级加成属性
+	{"nextLvAttrs",		4,		Attr},			-- 下一级加成属性
+	{"recycleList",		30,		RECYCLE_ITEM},	-- 可回收道具列表
+}
+
+
+--回收道具
+CG_RECYCLE_RECYCLEITEM = {
+	{"recycleItemStr",		1,		"string"},	-- 回收道具信息, 格式:"道具Id-数量|道具Id-数量"
 }

+ 265 - 0
script/module/bag/RecycleItem.lua

@@ -0,0 +1,265 @@
+-- 收纳箱(回收道具)
+
+--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.recycle").RecycleLvList
+local ItemConfig = require("excel.item").item
+-- local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
+-- local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
+
+local LOG_TAG = "RecycleItem" -- 本系统的日志标识
+local OPEN_COND_LV = 150 -- 开启功能需要的等级
+
+local function initRecycleData(human)
+    human.db.recycleData = { level = 0, exp = 0 }
+end
+
+local function getRecycleData(human)
+    return human.db.recycleData
+end
+
+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.atttrs then
+            for _,v in ipairs(cfg.atttrs) 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.atttrs then
+        net[0] = #cfg.atttrs
+        for k,v in ipairs(cfg.atttrs) 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)
+    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 - currentExp
+    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
+
+-- 回收道具
+function RecycleItem_Recycle_Do(human, recycleItemStr)
+    if not isOpen(human) then
+        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
+    end
+
+    local itemList = Util.parseKVString(recycleItemStr, "|", "-", Util.TONUMBER_ALL)
+    if not next(itemList) then
+        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
+    end
+
+    local recycleData = getRecycleData(human)
+    local currentLevel = recycleData and recycleData.level or 0
+    local maxLevel = #RecycleConfig
+    if currentLevel >= maxLevel then
+        return Broadcast.sendErr(human, Lang.COMMON_MAXLEVEL)
+    end
+
+    local totalExp = 0
+    for itemId, itemCnt in pairs(itemList) do
+        local itemCfg = ItemConfig[itemId]
+        if not itemCfg or not itemCfg.val or itemCfg.val <= 0 then
+            return Broadcast.sendErr(human, Lang.ITEM_CANNOT_RECYCLE)
+        end
+
+        if BagLogic.getItemCnt(human, itemId) < itemCnt then
+            return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH)
+        end
+
+        totalExp = totalExp + itemCfg.val
+    end
+
+    for itemId, itemCnt in pairs(itemList) do
+        if BagLogic.getItemCnt(human, itemId) < itemCnt then
+            return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH)
+        end
+        BagLogic.delItem(human, itemId, itemCnt, LOG_TAG)
+    end
+
+    -- 更新等级, 经验
+    local newLv, newExp = calcLv(human, totalExp)
+    updateRecycleData(human, newLv, newExp)
+
+    -- 更新战力
+    updatePower(human)
+
+    -- 更新UI界面数据
+    RecycleItem_Query(human)
+end

+ 3 - 1
script/module/role/RoleAttr.lua

@@ -47,6 +47,7 @@ local HeroSeed = require("hero.HeroSeed")
 local ElfLogic = require("elf.ElfLogic")
 local HeroTianYuan = require("hero.HeroTianYuan")
 local HeroArtifacts = require("hero.HeroArtifacts")
+local RecycleItem = require("bag.RecycleItem")
 
 
 local function printAttr(attr, szText)
@@ -186,7 +187,8 @@ function calcHeroGrid(heroGrid, index, human)
 	ElfLogic.doCalcHero(human, HERO_OTHER_ATTRS) --精灵系统
 	HeroTianYuan.doCalcHero(human, heroGrid, HERO_OTHER_ATTRS) -- 英雄天元
 	HeroArtifacts.doCalcHero(human, heroGrid, HERO_OTHER_ATTRS) -- 英雄神威灵装
-
+	RecycleItem.doCalcHero(human, HERO_OTHER_ATTRS) -- 收纳箱
+	
 	--不同模块在英雄属性计算 end	
 	
 	-- 计算评分