-- 资源 local code = require "code" local gameConst = require("const.gameConst") local util_user = require("utils.util_user") local timeUtil = require "utils.timeUtil" local baseAdapt = require "base.baseAdapt" local resAdapt = require("adapt.resAdapt") local moduleData = require("data.module") local heroData = require("data.hero") local hookData = require("data.hook") local MODULE_NAME = "tb_res" -- 升序排. local function sortAsc(list, key) table.sort( list or {}, function(a, b) return a[key] < b[key] end ) end local root = {} -- 玩家资源初始化(新手物品初始化) function root:init(uid) local lastInitTime = self:_get_last_init_time(uid) -- 仅初始化1次 if lastInitTime > 0 then return end local initConfig = resAdapt:get_init_conf() local initItems = {} for _, v in ipairs(initConfig) do table.arry_merge(initItems, v.items) end if #initItems > 0 then local reason = gameConst.RES_REASON_PRE.INIT self:update_items(uid, initItems, reason) end local curTime = timeUtil.now(uid) self:_set_last_init_time(uid, curTime) end -- 请求获取背包信息 function root:get_info(uid) log.info("get_info uid:%s", uid) local itemInfo = moduleData:hget_json(uid, MODULE_NAME, "itemInfo") or {} local isUpdate = false local curTime = timeUtil.now(uid) for i = #(itemInfo or {}), 1, -1 do local item = itemInfo[i] if item.expTime and curTime > item.expTime then -- 已经过期 isUpdate = true item.count = 0 end if item.count == 0 then isUpdate = true table.remove(itemInfo, i) end end if isUpdate then -- 存储 moduleData:hset(uid, MODULE_NAME, "itemInfo", itemInfo) end return itemInfo end --[[ 请求增减资源列表 返回的是 DataResUpdateItem 列表 ]] function root:update_items(uid, items, reason) -- log.info("update_items uid:%s items:%s reason:%s", uid, tostring(items), tostring(reason)) local itemInfo = moduleData:hget_json(uid, MODULE_NAME, "itemInfo") or {} local list = {} for _, v in ipairs(items) do local updateItems = self:_update_item(uid, itemInfo, v.id, v.count, v.bid) if updateItems then table.arry_merge(list, updateItems) end end -- 存储 moduleData:hset(uid, MODULE_NAME, "itemInfo", itemInfo) -- 推送 self:_on_res_update(uid, list, reason) -- 事件 self:_dispatch_event(uid, list) -- 日志-资源变化 self:_log_resource(uid, list, reason) -- 英雄卡的自动激活、自动溢出转化 self:_check_hero_item(uid, list, reason) return list end -- 判断 兑换随机英雄 资源是否足够 function root:check_hero_random_exchange(uid, sourceId, times) local conf = resAdapt:get_hero_exchange_conf(sourceId) if not conf then return false, code.RES.ID_ERROR end local sourceCount = conf.sourceCount local needCount = sourceCount * times local count = self:get_item_count(uid, sourceId) if count < needCount then return false, code.RES.NOT_ENOUGH end return true end -- 请求兑换英雄。物品类型200的使用这个接口 function root:hero_random_exchange(uid, sourceId, times) -- log.info("hero_random_exchange uid:%s sourceId:%s times:%s", uid, sourceId, times) local conf = resAdapt:get_hero_exchange_conf(sourceId) if not conf then log.error("兑换英雄的配置异常") return end local sourceCount = conf.sourceCount local targetQa = conf.targetQa local targetColor = conf.targetColor local targetCamp = conf.targetCamp local targetCount = conf.targetCount local heroItemIds = nil -- 限定英雄 if not is_empty(conf.baseRandomHeros) then -- 玩家已获得同品质英雄 heroItemIds = table.copy(conf.baseRandomHeros) local ownQaHeroList = heroData:get_qa_hero_id_list(uid, targetQa) if not is_empty(ownQaHeroList) then for _, v in ipairs(ownQaHeroList) do local heroId = v + 10000 table.unique_insert(heroItemIds, heroId) end end else heroItemIds = resAdapt:get_hero_item_ids(targetQa, targetColor, targetCamp) end log.info( "hero_random_exchange uid[%s] sourceId[%s] heroItemIds[%s]", tostring(uid), tostring(sourceId), tostring(heroItemIds) ) if not heroItemIds then log.error("兑换英雄的配置异常 找不到可以随机的英雄卡id") return end local targetItems = {} local totalCount = targetCount * times for i = 1, totalCount do local heroItemId = heroItemIds[math.random(#heroItemIds)] table.insert(targetItems, {id = heroItemId, count = 1}) end local reason = gameConst.RES_REASON_PRE.HERO_RANDOM_EXCHANGE local needCount = sourceCount * times local sourceItems = { {id = sourceId, count = needCount} } self:consume_items(uid, sourceItems, reason) self:add_items(uid, targetItems, reason) return targetItems end -- 请求兑换英雄。物品类型220的使用这个接口 function root:hero_compound(uid, resId, times) -- log.info("hero_random_exchange uid:%s sourceId:%s times:%s", uid, resId, times) local conf = resAdapt:get_hero_exchange_conf(resId) if not conf then log.error("兑换英雄的配置异常") return end local sourceCount = conf.sourceCount or 1 local targetCount = conf.targetCount or 1 local targetItems = {} local reason = gameConst.RES_REASON_PRE.HERO_COMPOUND do local needCount = sourceCount * times local sourceItems = { {id = resId, count = needCount} } self:consume_items(uid, sourceItems, reason) end do local totalCount = targetCount * times table.insert(targetItems, {id = conf.appointHero, count = totalCount}) self:add_items(uid, targetItems, reason) end return targetItems end -- 判断 兑换自选英雄 资源是否足够 function root:check_hero_optional_exchange(uid, sourceId, items) local conf = resAdapt:get_hero_exchange_conf(sourceId) if not conf then return false, code.RES.ID_ERROR end local sourceCount = conf.sourceCount local targetQa = conf.targetQa local targetColor = conf.targetColor local targetCamp = conf.targetCamp local targetCount = conf.targetCount local heroItemIds = resAdapt:get_hero_item_ids(targetQa, targetColor, targetCamp) if not heroItemIds then log.error("兑换英雄的配置异常 找不到可以自选的英雄卡id") return false, code.RES.CONFIG_ERROR end -- 兑换卡的数量 local totalCount = 0 for _, v in ipairs(items) do totalCount = totalCount + v.count end local times = math.floor(totalCount / targetCount) -- 兑换数量检查 local needCount = sourceCount * times local count = self:get_item_count(uid, sourceId) if count < needCount then return false, code.RES.NOT_ENOUGH end -- 兑换卡属性检查 local ok = true for _, v in ipairs(items) do if not table.indexof(heroItemIds, v.id) then ok = false break end end if not ok then return false, code.RES.LOGIC_ERROR end return true end -- 请求兑换自选英雄。物品类型210的使用这个接口 function root:hero_optional_exchange(uid, sourceId, items) log.info("hero_optional_exchange uid:%s sourceId:%s items:%s", uid, sourceId, tostring(items)) local conf = resAdapt:get_hero_exchange_conf(sourceId) if not conf then log.error("兑换英雄的配置异常") return end local sourceCount = conf.sourceCount local targetCount = conf.targetCount local targetItems = {} local totalCount = 0 -- 兑换卡的次数 for _, v in ipairs(items) do table.insert(targetItems, {id = v.id, count = v.count}) totalCount = totalCount + v.count end local times = math.floor(totalCount / targetCount) local reason = gameConst.RES_REASON_PRE.HERO_OPTIONAL_EXCHANGE local needCount = sourceCount * times local sourceItems = { {id = sourceId, count = needCount} } self:consume_items(uid, sourceItems, reason) self:add_items(uid, targetItems, reason) return targetItems end -- 判断 兑换资源包 资源是否足够 function root:check_item_count(uid, sourceId, times) local needCount = times local count = self:get_item_count(uid, sourceId) if count < needCount then return false, code.RES.NOT_ENOUGH end return true end -- 请求兑换资源包。物品类型30的使用这个接口 function root:onhook_exchange(uid, sourceId, times) log.info("onhook_exchange uid:%s sourceId:%s times:%s", uid, sourceId, times) local conf = resAdapt:get_onhook_exchange_conf(sourceId) if not conf then log.error("兑换资源包的配置异常") return end local targetType = conf.targetType local duration = conf.duration -- 获取挂机效率 local rateItems = hookData:get_hook_minute_rate_items(uid) -- 灵晶 local speedItem1 = table.key_find(rateItems, "id", gameConst.ITEM_ID.SPAR) or {} local speed1 = speedItem1.count or 0 -- 突破石 local speedItem2 = table.key_find(rateItems, "id", gameConst.ITEM_ID.BREAK) or {} local speed2 = speedItem2.count or 0 -- 帝国币 local speedItem3 = table.key_find(rateItems, "id", gameConst.ITEM_ID.GOLD) or {} local speed3 = speedItem3.count or 0 -- 装备强化石 local speedItem4 = table.key_find(rateItems, "id", gameConst.ITEM_ID.EQ_LEVEL) or {} local speed4 = speedItem4.count or 0 -- 装备精练石 local speedItem5 = table.key_find(rateItems, "id", gameConst.ITEM_ID.EQ_BREAK) or {} local speed5 = speedItem5.count or 0 local targetItems if targetType == gameConst.ONHOOK_TYPE.ALL then targetItems = { {id = gameConst.ITEM_ID.SPAR, count = duration * speed1 * times}, {id = gameConst.ITEM_ID.BREAK, count = duration * speed2 * times}, {id = gameConst.ITEM_ID.GOLD, count = duration * speed3 * times} } elseif targetType == gameConst.ONHOOK_TYPE.SPAR then targetItems = { {id = gameConst.ITEM_ID.SPAR, count = duration * speed1 * times} } elseif targetType == gameConst.ONHOOK_TYPE.BREAK then targetItems = { {id = gameConst.ITEM_ID.BREAK, count = duration * speed2 * times} } elseif targetType == gameConst.ONHOOK_TYPE.GOLD then targetItems = { {id = gameConst.ITEM_ID.GOLD, count = duration * speed3 * times} } elseif targetType == gameConst.ONHOOK_TYPE.QIANGHUA then targetItems = { {id = gameConst.ITEM_ID.EQ_LEVEL, count = duration * speed4 * times} } elseif targetType == gameConst.ONHOOK_TYPE.JINGJIAN then targetItems = { {id = gameConst.ITEM_ID.EQ_BREAK, count = duration * speed5 * times} } else log.error("不支持的挂机资源类型") end if targetItems then local reason = gameConst.RES_REASON_PRE.ONHOOK_EXCHANGE local needCount = times local sourceItems = { {id = sourceId, count = needCount} } self:consume_items(uid, sourceItems, reason) self:add_items(uid, targetItems, reason) end return targetItems end -- 请求兑换英雄。物品类型200的使用这个接口 function root:use_equip_box(uid, resId, times) -- log.debug("use_equip_box uid:%s resId:%s times:%s \n", uid, resId, tostring(times)) local configs = resAdapt:getResEquipBoxConfig(resId) if not configs then log.error(string.format("获取到相应的装备宝箱的配置异常,resId:[%s]", tostring(resId))) return end local function keyRandWeight(array, totalWeight) local weight = {} local t = 0 if not totalWeight then for _, v in ipairs(array) do if v.totalWeight then totalWeight = v.totalWeight break end end end if not totalWeight then return end for _, v in ipairs(array) do local ranNum = math.random(0, totalWeight) if v.weight and ranNum <= v.weight then return v.equipBag end end end local targetItems = {} do -- 可能一次性开N个宝箱 -- 先排序 sortAsc(configs, "seq") for i = 1, (times or 0), 1 do local equipBag = keyRandWeight(configs) local reqbConfigs = resAdapt:getResEquipBagConfig(equipBag or 0) if reqbConfigs then -- 随机配置 local index = random_list_by_weight(reqbConfigs) local conf = reqbConfigs[index] log.debug( "use_equip_box uid[%s] resId[%s] equipBag[%s] index[%s], conf[%s]", tostring(self.uid), tostring(resId), tostring(equipBag), tostring(index), tostring(conf) ) if conf and conf.resId then table.insert(targetItems, {id = conf.resId, count = conf.count or 1}) end else log.error(string.format("获取到相应的装备包的配置异常,resId:[%s]", tostring(resId))) end end end local reason = "equip_box_random" local sourceItems = { {id = resId, count = times} } if #targetItems > 0 then self:consume_items(uid, sourceItems, reason) self:add_items(uid, targetItems, reason) end return targetItems end function root:useEquipBoxDebris(uid, resId, times) local resConfig = baseAdapt:getOneConfig("ResEquipExchangeConfig", resId, "id") if not resConfig or not resConfig.sourceCount or not resConfig.targetId then return code.CONFIG_ERROR end local getCount = math.floor(times / resConfig.sourceCount) local totalCount = (resConfig.sourceCount * getCount) if totalCount > times or getCount <= 0 then return code.RES.NOT_ENOUGH end local haveCount = self:get_item_count(uid, resId) if haveCount < times then return code.RES.NOT_ENOUGH end local reason = "equip_box_random_debris" local sourceItems = { {id = resId, count = totalCount} } local targetItems = { {id = resConfig.targetId, count = getCount} } self:consume_items(uid, sourceItems, reason) self:add_items(uid, targetItems, reason) targetItems = self:use_equip_box(uid, resConfig.targetId, getCount) return code.OK, targetItems end function root:use_equip_optional_box(uid, resId, items, times) -- log.debug("use_equip_optional_box uid:%s resId:%s items:%s", uid, resId, tostring(items)) local configs = resAdapt:getResEquipChoiceConfig(resId) if not configs then log.error("装备包配置的配置异常") return end -- log.debug("use_equip_optional_box uid:%s items:%sm v.id:%s", uid, tostring(resId), tostring(configs)) local targetItems = {} for _, v in ipairs(items or {}) do local config = table.key_find(configs, "equipId", v.id) -- log.debug("use_equip_optional_box uid:%s items:%sm v.id:%s", uid, tostring(v), tostring(config)) if config then for i = 1, (times or 1), 1 do table.insert(targetItems, {id = v.id, count = (config.count or 1)}) end end end local reason = "use_equip_optional_box" local sourceItems = { {id = resId, count = times or 1} } if #targetItems > 0 then self:consume_items(uid, sourceItems, reason) self:add_items(uid, targetItems, reason) end return targetItems end ---------------------------------------------------------------- -- 判断资源是否足够 function root:is_enough(uid, items) -- 求和 local tempMap = {} for _, v in ipairs(items) do if not tempMap[v.id] then tempMap[v.id] = v.count else tempMap[v.id] = tempMap[v.id] + v.count end end local itemInfo = moduleData:hget_json(uid, MODULE_NAME, "itemInfo") or {} local ret = true for k, v in pairs(tempMap) do local item = table.key_find(itemInfo, "id", k) if not item or not item.count or item.count < v then ret = false break end end return ret end function root:is_enough_by_bid(uid, items) -- 求和 local tempMap = {} for _, v in ipairs(items) do if not tempMap[v.bid] then tempMap[v.bid] = v.count else tempMap[v.bid] = tempMap[v.bid] + v.count end end local itemInfo = moduleData:hget_json(uid, MODULE_NAME, "itemInfo") or {} local ret = true for k, v in pairs(tempMap) do local item = table.key_find(itemInfo, "bid", k) if not item or not item.count or item.count < v then ret = false break end end return ret end --[[ 增加资源 返回的是 DataResUpdateItem 列表 ]] function root:add_items(uid, items, reason) return self:update_items(uid, items, reason) end --[[ 消耗资源。资源不足也会消耗,消耗到0为止 返回的是 DataResUpdateItem 列表 ]] function root:consume_items(uid, items, reason) local tempList = {} for _, v in ipairs(items) do table.insert(tempList, {id = v.id, count = -v.count, bid = v.bid}) end return self:update_items(uid, tempList, reason) end -- 获取资源数量 function root:get_item_count(uid, itemId) -- log.info("get_item_count uid:%s itemId:%s", uid, itemId) local itemInfo = moduleData:hget_json(uid, MODULE_NAME, "itemInfo") or {} local item = table.key_find(itemInfo, "id", itemId) or {} return item.count or 0 end -- 获取资源数量 function root:get_item_by_bid(uid, bid) -- log.info("get_item_by_bid uid:%s bid:%s", uid, bid) local itemInfo = moduleData:hget_json(uid, MODULE_NAME, "itemInfo") or {} local item = table.key_find(itemInfo, "bid", bid) or {} return item end -- 获取帝国币 function root:get_gold(uid) return self:get_item_count(uid, gameConst.ITEM_ID.GOLD) end -- 获取宝石 function root:get_diamond(uid) return self:get_item_count(uid, gameConst.ITEM_ID.DIAMOND) end -- 获取友情点 function root:get_friend_coin(uid) return self:get_item_count(uid, gameConst.ITEM_ID.FRIEND_COIN) end -- 获取祈愿币 function root:get_hero_coin(uid) return self:get_item_count(uid, gameConst.ITEM_ID.HERO_COIN) end -- 获取公会声望 function root:get_club_coin(uid) return self:get_item_count(uid, gameConst.ITEM_ID.CLUB_COIN) end -- 获取灵晶 function root:get_spar(uid) return self:get_item_count(uid, gameConst.ITEM_ID.SPAR) end -- 获取突破石 function root:get_break(uid) return self:get_item_count(uid, gameConst.ITEM_ID.BREAK) end -- 获取觉醒石 function root:get_awake(uid) return self:get_item_count(uid, gameConst.ITEM_ID.AWAKE) end -- 获取装备强化石 function root:get_eqlevel(uid) return self:get_item_count(uid, gameConst.ITEM_ID.EQ_LEVEL) end -- 获取装备精练石 function root:get_eqbreak(uid) return self:get_item_count(uid, gameConst.ITEM_ID.EQ_BREAK) end -- 获取试炼券 function root:get_trial_ticket(uid) return self:get_item_count(uid, gameConst.ITEM_ID.TRIAL_TICKET) end -- 判断是否开启了指定的头像 function root:is_open_album(uid, albumId) local conf = resAdapt:get_album_conf(albumId) if not conf then return false end local type = conf.type if type == 1 then -- 默认解锁的 return true elseif type == 2 then -- 拥有英雄解锁的 local heroId = conf.heroId return heroData:user_is_own_hero(uid, heroId) else -- 拥有物品解锁的 local count = self:get_item_count(uid, albumId) return count > 0 end end -- 判断是否开启了指定的头像框 function root:is_open_frame(uid, frameId) local conf = resAdapt:get_frame_conf(frameId) if not conf then return false end local type = conf.type if type == 1 then -- 默认解锁的 return true elseif type == 2 then -- 拥有英雄解锁的 local heroId = conf.heroId return heroData:user_is_own_hero(uid, heroId) else -- 拥有物品解锁的 local count = self:get_item_count(uid, frameId) return count > 0 end end -- 判断是否开启了指定的称号 function root:is_open_title(uid, titleId) local conf = resAdapt:get_title_conf(titleId) if not conf then return false end local type = conf.type if type == 1 then -- 默认解锁的 return true elseif type == 2 then -- 拥有英雄解锁的 local heroId = conf.heroId return heroData:user_is_own_hero(uid, heroId) else -- 拥有物品解锁的 local count = self:get_item_count(uid, titleId) return count > 0 end end -- 判断是否开启了指定的表情 function root:is_open_face(uid, faceId) local conf = resAdapt:get_face_conf(faceId) if not conf then return false end local type = conf.type if type == 1 then -- 默认解锁的 return true elseif type == 2 then -- 拥有英雄解锁的 local heroId = conf.heroId return heroData:user_is_own_hero(uid, heroId) else -- 拥有物品解锁的 local count = self:get_item_count(uid, faceId) return count > 0 end end -- 判断是否开启了指定的看板娘 function root:is_open_signboard(uid, signboardId) -- 拥有英雄解锁的 local heroId = signboardId return heroData:user_is_own_hero(uid, heroId) end -- 已获得类型物品ID列表 function root:get_own_type_item_id_list(uid, resType) if uid == nil or resType == nil then return end local resIdList = {} local itemInfo = moduleData:hget_json(uid, MODULE_NAME, "itemInfo") or {} for k, v in ipairs(itemInfo) do if resAdapt:is_type(v.id, resType) then table.insert(resIdList, v.id) end end return resIdList end -- 获取英雄拥有数量(包括觉醒) function root:get_hero_count(uid, heroId) if uid == nil or heroId == nil then return end -- 背包剩余数量 local count = self:get_item_count(uid, heroId) -- 觉醒消耗数量 local awakeCount = heroData:get_hero_awake_cost_count(uid, heroId) count = count + (awakeCount or 0) return count end ---------------------------------------- -- 以下是私有方法 ---------------------------------------- -- 获取新的bid function root:_new_bid(uid) local lastBid = moduleData:hget_int(uid, MODULE_NAME, "lastBid") or 0 lastBid = lastBid + 1 moduleData:hset(uid, MODULE_NAME, "lastBid", lastBid) return lastBid end -- 最后初始化资源的时间戳 function root:_get_last_init_time(uid) return moduleData:hget_int(uid, MODULE_NAME, "lastInitTime") or 0 end function root:_set_last_init_time(uid, timestamp) moduleData:hset(uid, MODULE_NAME, "lastInitTime", timestamp) end function root:_AddExpirationTime(resConfing, uid) -- 计算失效时间/过期时间,expiration time ==> expTime; local expTime if resConfing then local curTime = timeUtil.now(uid) if resConfing.activeDays then expTime = curTime + (expTime or 0) + 86400 * tonumber(resConfing.activeDays) end if resConfing.termOfValidity then expTime = curTime + (expTime or 0) + tonumber(resConfing.termOfValidity) end end return expTime end function root:_AddItemByBid(uid, itemInfo, itemId, count, bid, resConfing, composite) local item if count > 0 and composite then local newBid = self:_new_bid(uid) item = { id = itemId, count = 0, bid = newBid } table.insert(itemInfo, item) else -- 不可叠加的物品只能通过bid来获取,但只有装备是通过bid来获取. item = table.key_find(itemInfo, "bid", bid) if not item and not bid then item = table.key_find(itemInfo, "id", itemId) end end -- 都没有获取到,就新建一个. if not item then local newBid = self:_new_bid(uid) item = { id = itemId, count = 0, bid = newBid } table.insert(itemInfo, item) end local oldCount = item.count or 0 local newCount = oldCount + count newCount = math.max(newCount, 0) item.count = newCount item.expTime = self:_AddExpirationTime(resConfing, uid) return {{id = itemId, deltaCount = count, count = newCount, bid = item.bid}} end -- 更新单个资源 function root:_update_item(uid, itemInfo, itemId, count, bid) local conf = resAdapt:get_item_conf(itemId) if not conf then log.error("更新资源异常,未找到[%s]资源配置", tostring(itemId)) return end -- 处理特殊id的资源 local otherModule = conf.otherModule local isSpecial = self:_update_special_item(uid, itemId, count, otherModule) if isSpecial then -- 特殊资源,不返回新数量 return end local updateItems -- 必须执行 if 1 == 1 then -- 资源可叠加 if conf.enableComposite then updateItems = self:_AddItemByBid(uid, itemInfo, itemId, count, bid, conf) else updateItems = self:_AddItemByBid(uid, itemInfo, itemId, count, bid, conf, true) end else local itemType = conf.type if itemType == gameConst.RES_TYPE.COIN then updateItems = self:_update_coin_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.EXP then updateItems = self:_update_exp_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.CONSUME then updateItems = self:_update_consume_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.LOTTERY then updateItems = self:_update_lottery_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.TICKET then updateItems = self:_update_ticket_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.PAY then updateItems = self:_update_pay_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.ONHOOK then updateItems = self:_update_onhook_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.HERO_CARD then updateItems = self:_update_hero_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.RANDOM_HERO_CARD then updateItems = self:_update_random_hero_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.OPTIONAL_HERO_CARD then updateItems = self:_update_optional_hero_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.ALBUM then updateItems = self:_update_album_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.FACE then updateItems = self:_update_face_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.FRAME then updateItems = self:_update_frame_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.TITLE then updateItems = self:_update_title_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.EQUIP then updateItems = self:_update_unable_composit_type_item(uid, itemInfo, itemId, count, bid) elseif itemType == gameConst.RES_TYPE.EQUIP_BOX then updateItems = self:_update_enable_composit_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.EQUIP_CHOICE_BOX then updateItems = self:_update_enable_composit_type_item(uid, itemInfo, itemId, count) elseif itemType == gameConst.RES_TYPE.EQUIP_BOX_DEBRIS then updateItems = self:_update_enable_composit_type_item(uid, itemInfo, itemId, count) else log.error("更新资源异常,未知资源类型 itemId:%s", itemId) end end return updateItems end -- 特殊资源更新 function root:_update_special_item(uid, itemId, count, otherModule) log.debug("-- DEBUG INFO : uid, itemId, count, otherModule :[%s]", tostring({uid, itemId, count, otherModule})) if otherModule == "pass" then self:_update_special_item_pay_pass(uid, itemId, count) return true elseif otherModule == "adventure" then self:_update_special_item_adventure_active(uid, itemId, count) return true elseif itemId == gameConst.ITEM_ID.USER_EXP then self:_update_special_item_user_exp(uid, itemId, count) return true elseif itemId == gameConst.ITEM_ID.VIP_EXP then self:_update_special_item_vip_exp(uid, itemId, count) return true elseif itemId == gameConst.ITEM_ID.ARENA_CUP then self:_update_special_item_arena_cup(uid, itemId, count) return true elseif itemId == gameConst.ITEM_ID.PASS_EXP then self:_update_special_item_pass_exp(uid, itemId, count) return true elseif itemId == gameConst.ITEM_ID.ADVENTURE_POINTS then self:_update_special_item_adventure_points(uid, itemId, count) return true elseif itemId == gameConst.ITEM_ID.ARENA then local arenaData = require("data.arena") arenaData:active_vip_status(uid, itemId) return true elseif itemId == gameConst.ITEM_ID.PETBORN_AWARD then self:_update_special_item_pve_vip_status(uid, itemId, count) return true else return false end end function root:_update_special_item_user_exp(uid, itemId, count) local playerData = require("data.player") playerData:add_level_exp(uid, count) end function root:_update_special_item_vip_exp(uid, itemId, count) local playerData = require("data.player") playerData:add_vip_level_exp(uid, count) end function root:_update_special_item_arena_cup(uid, itemId, count) local arenaData = require("data.arena") arenaData:user_add_cups(uid, count, "gm") end -- 悬赏经验 function root:_update_special_item_pass_exp(uid, itemId, count) local exploitData = require("data.exploit") exploitData:add_progress(uid, count) end function root:_update_special_item_pay_pass(uid, itemId, count) local exploitData = require("data.exploit") exploitData:active_vip_award(uid) end -- 冒险积分 function root:_update_special_item_adventure_points(uid, itemId, count) local pveStarsData = require("data.pveStars") pveStarsData:add_adventure_points(uid, count) end -- 冒险经费付费奖励激活 function root:_update_special_item_adventure_active(uid, itemId, count) local adventureData = require("data.adventure") adventureData:active_vip_award(uid, itemId) end function root:_update_special_item_pve_vip_status(uid, itemId, count) local THIS_MODULE_NAME = "tb_pve" local contractData = moduleData:hget_json(uid, THIS_MODULE_NAME, "contractData") contractData = contractData or {} contractData.statusVip = 1 moduleData:hset(uid, THIS_MODULE_NAME, "contractData", contractData) local currSeasonId = moduleData:hget_int(uid, THIS_MODULE_NAME, "pveId") or 1 -- 通知玩家 local msg = { statusVip = 1, seasonId = currSeasonId } util_user:user_proto_notify(uid, "on_pve_vip_status", msg) local keyEvent = string.format("pve-active-vip-item") local cnt = string.format("%s", tostring(itemId)) util_user:log_event(uid, keyEvent, cnt) end -- 通用资源更新。仅数量累计 function root:_update_common_type_item(uid, itemInfo, itemId, deltaCount) local item = table.key_find(itemInfo, "id", itemId) if not item then local newBid = self:_new_bid(uid) item = {id = itemId, count = 0, bid = newBid} table.insert(itemInfo, item) end local bid = item.bid local oldCount = item.count or 0 local newCount = oldCount + deltaCount newCount = math.max(newCount, 0) item.count = newCount return {id = itemId, deltaCount = deltaCount, count = newCount, bid = bid} end -- 通用资源更新。不可叠加的物品,仅数量累计 function root:_update_ones_type_item(uid, itemInfo, itemId, deltaCount, bId) local item = table.key_find(itemInfo or {}, "bid", bId or 0) if not item then local newBid = self:_new_bid(uid) item = {id = itemId, count = 0, bid = newBid} table.insert(itemInfo, item) end local bid = item.bid local oldCount = item.count or 0 local newCount = oldCount + deltaCount newCount = math.max(newCount, 0) item.count = newCount return {id = itemId, deltaCount = deltaCount, count = newCount, bid = bid} end -- 更新代币类资源 function root:_update_coin_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新经验类资源 function root:_update_exp_type_item(uid, itemInfo, itemId, count) log.error("更新资源异常:经验类资源都是特殊资源,不应该进入本逻辑") local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新消耗类类资源 function root:_update_consume_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新祈愿券类资源 function root:_update_lottery_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新门票类资源 function root:_update_ticket_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新付费订阅道具类资源 function root:_update_pay_type_item(uid, itemInfo, itemId, count) log.error("更新资源异常:付费订阅道具类资源都是特殊资源,不应该进入本逻辑") local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新挂机资源包类资源 function root:_update_onhook_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新英雄卡类资源。 function root:_update_hero_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新随机英雄卡类资源 function root:_update_random_hero_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新自选英雄卡类资源 function root:_update_optional_hero_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新头像类资源 function root:_update_album_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新表情类资源 function root:_update_face_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新头像框类资源 function root:_update_frame_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 更新称号类资源 function root:_update_title_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 可叠加的物品 function root:_update_enable_composit_type_item(uid, itemInfo, itemId, count) local updateItem = self:_update_common_type_item(uid, itemInfo, itemId, count) return {updateItem} end -- 不可叠加的物品 function root:_update_unable_composit_type_item(uid, itemInfo, itemId, count, bid) local updateItem = self:_update_ones_type_item(uid, itemInfo, itemId, count, bid) return {updateItem} end -- 检查英雄列表。检查自动激活、自动溢出兑换 function root:_check_hero_item(uid, updateItems, reason) local itemIdMap = {} for _, v in ipairs(updateItems) do if v.deltaCount and v.deltaCount > 0 then if resAdapt:is_type(v.id, gameConst.RES_TYPE.HERO_CARD) then itemIdMap[v.id] = true end end end for k, _ in pairs(itemIdMap) do self:_check_hero_active(uid, k, reason) self:_check_hero_overflow(uid, k, reason) end end -- 检查英雄自动激活 function root:_check_hero_active(uid, itemId, srcReason) local conf = resAdapt:get_hero_conf(itemId) if not conf then log.error("检查英雄激活异常:没找到对应英雄配置") return end local count = self:get_item_count(uid, itemId) if count <= 0 then return end local heroId = conf.heroId -- 是否拥有该英雄 local hasHero = heroData:user_is_own_hero(uid, heroId) if not hasHero then local ok = heroData:user_active_hero(uid, heroId) if ok then local reason = gameConst.RES_REASON_PRE.AUTO_HERO_ACTIVE local cardItem = {id = itemId, count = 1} self:consume_items(uid, {cardItem}, reason) self:_on_res_auto_hero_active(uid, cardItem, heroId, srcReason) end end end -- 检查英雄自动激活 function root:_check_hero_overflow(uid, itemId, srcReason) local conf = resAdapt:get_hero_conf(itemId) if not conf then log.error("检查英雄溢出异常:没找到对应英雄配置") return end local count = self:get_item_count(uid, itemId) if count <= 0 then return end local heroId = conf.heroId local overflowItems = conf.overflowItems -- 英雄觉醒满还需要的卡牌数量 local needCardCount = heroData:get_hero_full_awake_card_count(uid, heroId) local overflowCount = count - needCardCount if overflowCount <= 0 then return end local reason = gameConst.RES_REASON_PRE.AUTO_EXCHANGE local fromItems = {{id = itemId, count = overflowCount}} local toItems = {} for _, v in ipairs(overflowItems) do local count = v.count * overflowCount table.insert(toItems, {id = v.id, count = count}) end self:consume_items(uid, fromItems, reason) self:add_items(uid, toItems, reason) self:_on_res_auto_exchange(uid, fromItems, toItems, srcReason) end -- 推送资源变化 function root:_on_res_update(uid, updateItems, reason) local msg = { reason = reason, items = updateItems } util_user:user_proto_notify(uid, "on_res_update", msg) end -- 推送资源自动激活英雄 function root:_on_res_auto_hero_active(uid, cardItem, heroId, reason) local msg = { reason = reason, cardItem = cardItem, heroId = heroId } util_user:user_proto_notify(uid, "on_res_auto_hero_active", msg) end -- 推送资源自动兑换 function root:_on_res_auto_exchange(uid, fromItems, toItems, reason) local msg = { reason = reason, fromItems = fromItems, toItems = toItems } util_user:user_proto_notify(uid, "on_res_auto_exchange", msg) end -- 资源变化事件 function root:_dispatch_event(uid, updateItems) for _, v in ipairs(updateItems) do local conf = resAdapt:get_item_conf(v.id) or {} local evtParams = { times = 1, id = v.id, count = math.abs(v.deltaCount), add = v.deltaCount, type = conf.type, bId = v.bid, totalCount = v.count } util_user:user_dispatch_event(uid, gameConst.EVENT_ID.RES, evtParams) end end -- 资源变化事件 function root:_log_resource(uid, updateItems, reason) for _, v in ipairs(updateItems) do util_user:log_resource(uid, reason, v.id, v.deltaCount, v.count) end end return root