local ipairs = ipairs local table = table local math = math local next = next local string = string local redisproxy = redisproxy local MsgPack = MsgPack local getRandomName = getRandomName local mcast_util = mcast_util local string_format = string.format local tonumber = tonumber local require = require local table_insert = table.insert local tconcat = table.concat local table_unpack = table.unpack local _M = {} local function getChangeAttrJson(oldAttr, newAttr) local change = {} for k, v in pairs(newAttr) do change[k] = v - oldAttr[k] change[k] = math.ceil(change[k]) if change[k] == 0 then change[k] = nil end end return change end function _M.levelUpRpc( agent, data ) local role = agent.role local msg = MsgPack.unpack(data) local hero = role.heros[msg.id] if not hero then return 1 end if hero:getProperty("level") >= hero:getMaxLevel() then return 2 end local curData = csvdb["unit_expCsv"][hero:getProperty("level")] local cost = {[ItemId.Exp] = curData.exp, [ItemId.Gold] = curData.gold} if not role:checkItemEnough(cost) then return 3 end role:costItems(cost, {log = {desc = "heroLevelUp", int1 = msg.id, int2 = hero:getProperty("type")}}) local oldAttr = hero:getTotalAttrs() local oldBattleV = hero:getProperty("battleV") hero:updateProperty({field = "level", delta = 1}) role:log("hero_upgrade", { hero_id = hero:getProperty("type"), --英雄ID hero_upgrade_cost = cost, -- 英雄升级消耗,json格式记录,{道具ID1:消耗数量1,道具ID2:消耗数量2,………...} hero_upgrade_result = getChangeAttrJson(oldAttr, hero:getTotalAttrs()), -- 英雄升级效果,可记录效果ID,或json格式记录提升效果,{攻击:20,闪避:20,……..} hero_upgrade_type = 0, -- 英雄升级方式,连续升级:1,单击升级:0 hero_upgrade_score = hero:getProperty("battleV"), -- 英雄升级后评分 hero_upgrade_scoreget = hero:getProperty("battleV") - oldBattleV, -- 通过英雄升级提升的评分 }) hero:mylog({desc = "levelUp", int1 = hero:getProperty("level")}) role:checkTaskEnter("HeroLevelUp", {level = hero:getProperty("level")}) role:checkTaskEnter("HeroLvlCollect", {}) SendPacket(actionCodes.Hero_levelUpRpc, '') return true end function _M.breakRpc( agent, data ) local role = agent.role local msg = MsgPack.unpack(data) local hero = role.heros[msg.id] if not hero then return 1 end if hero:getProperty("level") < hero:getMaxLevel() then return 2 end if hero:getProperty("breakL") >= #csvdb["unit_breakCsv"] then return 3 end local curData = csvdb["unit_breakCsv"][hero:getProperty("breakL")] local cost = {[ItemId.BreakCost] = curData.cost, [ItemId.Gold] = curData.gold} if not role:checkItemEnough(cost) then return 4 end role:costItems(cost, {log = {desc = "heroBreak", int1 = msg.id, int2 = hero:getProperty("type")}}) local oldAttr = hero:getTotalAttrs() hero:updateProperty({field = "breakL", delta = 1}) role:log("hero_break", { hero_id = hero:getProperty("type"), --英雄ID hero_break_cost = cost, -- 英雄突破消耗,json格式记录,{道具ID1:消耗数量1,道具ID2:消耗数量2,………...} hero_break_result = getChangeAttrJson(oldAttr, hero:getTotalAttrs()), -- 英雄突破效果,可记录效果ID,或json格式记录提升效果,{攻击:20,闪避:20,……..} hero_break_level = hero:getMaxLevel(), -- 英雄突破后等级上限 }) hero:mylog({desc = "break", int1 = hero:getProperty("breakL")}) SendPacket(actionCodes.Hero_breakRpc, '') return true end function _M.wakeRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local hero = role.heros[msg.id] if not hero then return 1 end if hero:getProperty("wakeL") >= #csvdb["unit_wakeCsv"] then return 2 end local typ = hero:getProperty("type") local wakeData = csvdb["unit_wakeCsv"][hero:getProperty("wakeL")] if not wakeData then return 3 end local costMaterial = wakeData.costMaterial:toArray(true,"=") local cost = {[typ] = wakeData.costFigment,[globalCsv.unit_wake_cost[hero:getCamp()][costMaterial[1]]] = costMaterial[2]} if not role:checkItemEnough(cost) then return 4 end role:costItems(cost, {log = {desc = "heroWake", int1 = msg.id, int2 = hero:getProperty("type")}}) local oldAttr = hero:getTotalAttrs() local oldBattleV = hero:getProperty("battleV") hero:updateProperty({field = "wakeL", delta = 1}) local curLevel = hero:getProperty("wakeL") role:checkTaskEnter("Wake", {heroType = typ, wakeL = curLevel}) if curLevel == 3 then -- 解锁cg role:checkTaskEnter("WakeCG", {heroType = typ}) end hero:mylog({desc = "wake", int1 = hero:getProperty("wakeL")}) role:log("hero_rise", { hero_id = typ, --英雄ID hero_rise_cost = cost, --英雄觉醒消耗,json格式记录,{道具ID1:消耗数量1,道具ID2:消耗数量2,………...} hero_rise_score = hero:getProperty("battleV"), --英雄觉醒后评分提升 hero_rise_scoreget = hero:getProperty("battleV") - oldBattleV, --英雄觉醒后评分提升 hero_rise_result = getChangeAttrJson(oldAttr, hero:getTotalAttrs()), --英雄觉醒效果,可记录效果ID,或json格式记录提升效果,{攻击:20,闪避:20,……..} }) if hero:getProperty("type") == 204 then role:finishGuide(7) end SendPacket(actionCodes.Hero_wakeRpc, '') role:checkTaskEnter("HeroStarCollect", {}) return true end function _M.talentRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local hero = role.heros[msg.id] if not hero then return 1 end local talent = hero:getProperty("talent") local heroCfgId = hero:getProperty("type") local curStage = talent:getv(0, 1) local oldStage = curStage local curLevel = talent:getv(1, 1) local oldLevel = curLevel local curData = csvdb["unit_talent_"..heroCfgId.."Csv"][curStage] if not curData then return 1 end local oldSkillLv = hero:getSkillLevel(1) local cost = {} if curLevel == #curData then talent = talent:setv(0, curStage + 1) talent = talent:setv(1, 1) else if curLevel > #curData then return 2 end local talentData = curData[curLevel] if not talentData then return 3 end if talentData.lvRequire > hero:getProperty("level") then return 4 end cost = talentData.money:toNumMap() if not role:checkItemEnough(cost) then return 5 end role:costItems(cost, {log = {desc = "heroTalent", int1 = msg.id, int2 = hero:getProperty("type")}}) talent = talent:setv(1, curLevel + 1) end curStage = talent:getv(0, 1) role:checkTaskEnter("HeroTalent", {heroType = hero:getProperty("type"), alv = curStage}) hero:updateProperty({field = "talent", value = talent}) role:log("hero_talent", { hero_id = hero:getProperty("type"), --英雄ID hero_talent_stagebef = oldStage, --英雄精进升级前停留阶段 hero_talent_stage = curStage, --英雄精进升级后停留阶段 hero_talent_cost = cost, --英雄精进升级消耗,json格式记录,{道具ID1:消耗数量1,道具ID2:消耗数量2,….} hero_talent_subid = curData[oldLevel].effect, --升级属性ID,生命、攻击、防御、命中、闪避分别对应(0,1,2,3,4) hero_talent_sublevel = curData[oldLevel].level, --升级属性等级,如生命升级从1到2,则记录2 }) hero:mylog({desc = "talent", int1 = talent:getv(0, 1), int2 = talent:getv(1, 1)}) SendPacket(actionCodes.Hero_talentRpc, '') return true end -- 暂时没有这个功能 function _M.likeHeroRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local heroType = msg.type local result = {status = 0} local isLike = false local hadLike = role:getProperty("likeHero"):toArray(true, "=") for _, v in pairs(hadLike) do if v == heroType then isLike = true break end end if isLike then result.status = 1 else redisproxy:hincrby("hero:like", "hero:"..heroType, 1) table.insert(hadLike, heroType) role:setProperty("likeHero", table.concat(hadLike, "=")) end SendPacket(actionCodes.Hero_likeHeroRpc, MsgPack.pack(result)) return true end local RankLikeNum = 5 --热度显示几个 local TimeLikeNum = 95 -- 时间显示几个 local function getCommentKey(heroType) return { commentListKey = string.format("list:%d:herocomments", heroType), commentRankKey = string.format("rank:%d:herocomments", heroType), commentKey = string.format("hero:%d:comments", heroType), } end local function trimComment(heroType, commentId) -- 剪裁 CommentList local commentKey = getCommentKey(heroType) local redret = redisproxy:pipelining(function (red) red:lpush(commentKey.commentListKey, commentId) red:lrange(commentKey.commentListKey, TimeLikeNum,-1) red:ltrim(commentKey.commentListKey, 0, TimeLikeNum - 1) red:zrevrange(commentKey.commentRankKey, 0, RankLikeNum - 1) end) local hots = {} for _, hot in pairs(redret[4]) do hots[hot] = 1 end redisproxy:pipelining(function (red) local needDel = {} for _, tempId in pairs(redret[2]) do if not hots[tempId] then table.insert(needDel, tempId) end end if #needDel > 0 then red:zrem(commentKey.commentRankKey, table_unpack(needDel)) red:hdel(commentKey.commentKey, table_unpack(needDel)) end end) end function _M.commentHeroRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local heroType = msg.type local content = msg.content local result = {status = 0} -- status 0 成功 1 已经评论过了 local curStutus = role.dailyData:getProperty("commentHero") if curStutus:getv(heroType, 0) ~= 0 then result.status = 1 else local commentKey = getCommentKey(heroType) local SERV = string.format(".chated%d", math.random(1, 5)) local legal, mod = skynet.call(SERV, "lua", "check", content) if not legal then content = mod or "" end local commentId = tostring(redisproxy:hincrby("hero:comment:autoincr", "hero:" .. heroType, 1)) local comment = { commentId = commentId, content = content, roleId = role:getProperty("id"), name = role:getProperty("name"), -- time = skynet.timex() } redisproxy:hset(commentKey.commentKey, commentId, json.encode(comment)) trimComment(heroType, commentId) comment.like = 0 result.comment = comment role.dailyData:setProperty("commentHero", curStutus:setv(heroType, 1)) role:log("hero_note", { hero_id = heroType, -- 英雄ID hero_note_action = 0, -- 英雄评价界面操作,发布评论:0,点赞:1,反对:2 hero_note_id = commentId, -- 操作的评价ID hero_note_text = content, -- 操作的评价内容 }) end SendPacket(actionCodes.Hero_commentHeroRpc, MsgPack.pack(result)) return true end function _M.getCommentsRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local heroType = msg.type local list = {} -- 评论列表 local commentKey = getCommentKey(heroType) local commentRoleKey = string.format("comment:%d:like", role:getProperty("id")) local redret = redisproxy:pipelining(function (red) red:lrange(commentKey.commentListKey, 0,TimeLikeNum - 1) red:zrevrange(commentKey.commentRankKey, 0, -1, "WITHSCORES") --热门 red:hget("hero:like", "hero:"..heroType) red:lrange(commentRoleKey, 0, 999) end) local likeMap = {} local idList = {} local liked = {} for i = 1, #redret[2], 2 do likeMap[redret[2][i]] = redret[2][i + 1] if i < RankLikeNum * 2 then table.insert(idList, redret[2][i]) end end for i = 1, #redret[1] do table.insert(idList, redret[1][i]) end for i = 1, #redret[4] do liked[redret[4][i]] = 1 end local commentData = redisproxy:pipelining(function (red) for _, commentId in ipairs(idList) do red:hget(commentKey.commentKey, commentId) end end) for _, commentS in ipairs(commentData or {}) do local comment = json.decode(commentS) comment.like = likeMap[tostring(comment.commentId)] or 0 comment.liked = liked[heroType .. ":" .. comment.commentId] or 0 table.insert(list, comment) end SendPacket(actionCodes.Hero_getCommentsRpc, MsgPack.pack({list = list, like = tonumber(redret[3] or 0)})) return true end function _M.likeCommentRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local actType = msg.actType -- 1 顶 2 踩 local heroType = msg.type local commentId = msg.commentId --评论id local commentKey = getCommentKey(heroType) local add = 0 if actType == 1 then add = 1 elseif actType == 2 then add = -1 else return end local result = {status = 0} local commentIndex = heroType .. ":" .. commentId local commentRoleKey = string.format("comment:%d:like", role:getProperty("id")) local redret = redisproxy:pipelining(function (red) red:hget(commentKey.commentKey, commentId) red:lrem(commentRoleKey, 1, commentIndex) red:lpush(commentRoleKey, commentIndex) red:ltrim(commentRoleKey, 0, 999) end) if (tonumber(redret[2]) or 0) > 0 then result.status = 1 else if redret[1] then-- 查不到也返回ture local comment = json.decode(redret[1]) local redret2 = redisproxy:pipelining(function (red) red:zrevrange(commentKey.commentRankKey, 0, RankLikeNum - 1) --热门 red:zincrby(commentKey.commentRankKey, add, commentId) red:zrevrange(commentKey.commentRankKey, 0, RankLikeNum - 1) --热门 end) local out = {} for _, v in pairs(redret2[1]) do out[v] = 1 end local new = {} for _, v in pairs(redret2[3]) do if out[v] then out[v] = nil else new[v] = 1 end end for tempId, _ in pairs(out) do trimComment(heroType, tempId) end redisproxy:pipelining(function (red) for tempId, _ in pairs(new) do red:lrem(commentKey.commentListKey, 0, tempId) end end) role:log("hero_note", { hero_id = heroType, -- 英雄ID hero_note_action = add > 0 and 1 or 2, -- 英雄评价界面操作,发布评论:0,点赞:1,反对:2 hero_note_id = commentId, -- 操作的评价ID hero_note_text = comment.content, -- 操作的评价内容 }) end end SendPacket(actionCodes.Hero_likeCommentRpc, MsgPack.pack(result)) return true end function _M.createHeroRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local heroType = msg.heroType local unitData = csvdb["unitCsv"][heroType] if not unitData then return end local cost = globalCsv.unit_fragment_cost[unitData["rare"]] if not cost then return end if role:getItemCount(heroType) < cost then return end for _, hero in pairs(role.heros) do if hero:getProperty("type") == heroType then return end end role:costItems({[heroType] = cost}, {log = {desc = "createHero"}}) role:award({[heroType + ItemStartId.Hero] = 1}, {log = {desc = "createHero"}}) SendPacket(actionCodes.Hero_createHeroRpc, "") return true end -- typ 位置,level等级对应唯一装备,level为0时为移除,不为0时无则装备,有则替换 function _M.referEquipsRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local hero = role.heros[msg.id] if not hero then return 10 end local equips = msg.equips local isAuto = msg.isAuto if not equips or not next(equips) then return 11 end for typ = 1, 4 do -- 4件装备 if equips[typ] and equips[typ] ~= 0 then if role:getEquipCount(typ, equips[typ]) <= 0 then return end end end local oldBattleV = hero:getProperty("battleV") local wear = {} local curEquip = hero:getProperty("equip") for typ = 1, 4 do -- 4件装备 if equips[typ] then local cur = curEquip:getv(typ, 0) if cur ~= equips[typ] then if equips[typ] == 0 then curEquip = curEquip:delk(typ) else role:addEquip(typ, equips[typ], -1, {log = {desc = "refer"}}) -- 穿上 curEquip = curEquip:setv(typ, equips[typ]) wear[typ] = {id = equips[typ], act = 0} end if cur ~= 0 then role:addEquip(typ, cur, 1, {log = {desc = "refer"}}) -- 脱掉 wear[typ] = {id = cur, act = 1} end end end end -- 更新角色 hero:updateProperty({field = "equip", value = curEquip}) for typ, data in pairs(wear) do role:log("equip_wear", { hero_id = hero:getProperty("type"), --英雄ID equip_id = data.id, --装备ID equip_wear_action = data.act, --装备操作类型:装备:0,卸载:1 equip_wear_part = typ, --装备部位,记录部位ID equip_wear_scorebef = oldBattleV, --装备前英雄评分 equip_wear_score = hero:getProperty("battleV"), --装备后英雄评分 equip_wear_mode = isAuto and 0 or 1, --用以区分自动装备还是手动装备,自动记录为0,手动记录为1 }) end SendPacket(actionCodes.Hero_referEquipsRpc, "") return true end -- typ 位置,uid对应唯一符文,uid为0时为移除,不为0时无则装备,有则替换 function _M.referRunesRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local hero = role.heros[msg.id] if not hero then return 10 end local runes = msg.runes if not runes or not next(runes) then return 11 end local used = {} for typ = 1, 6 do if runes[typ] and runes[typ] ~= 0 then local ownRune = role.runeBag[runes[typ]] if not ownRune then return end if ownRune:getProperty("refer") ~= 0 then used[ownRune:getProperty("refer")] = used[ownRune:getProperty("refer")] or {} used[ownRune:getProperty("refer")][runes[typ]] = 1 end end end for cheroId, cIds in pairs(used) do local chero = role.heros[cheroId] local hrunes = chero:getProperty("rune") for slot, rId in pairs(hrunes:toNumMap()) do if cIds[rId] then hrunes = hrunes:delk(slot) end end chero:updateProperty({field = "rune", value = hrunes}) end local oldAttr = hero:getTotalAttrs() local oldBattleV = hero:getProperty("battleV") local wear = {} local curRune = hero:getProperty("rune") for typ = 1, 6 do if runes[typ] then local cur = curRune:getv(typ, 0) if cur ~= runes[typ] then if runes[typ] == 0 then curRune = curRune:delk(typ) else local newRune = role.runeBag[runes[typ]] newRune:updateProperty({field = "refer",value = hero:getProperty("id")}) curRune = curRune:setv(typ, runes[typ]) wear[runes[typ]] = typ end if cur ~= 0 then local oldR = role.runeBag[cur] if oldR then oldR:updateProperty({field = "refer",value = 0}) end end end end end hero:updateProperty({field = "rune", value = curRune}) local attrChange = getChangeAttrJson(oldAttr, hero:getTotalAttrs()) for runeId, typ in pairs(wear) do local ownRune = role.runeBag[runeId] if ownRune then role:log("hero_jewel", { hero_id = hero:getProperty("type"), -- 英雄ID hero_jewel_id = ownRune:getProperty("id"), -- 铭文ID hero_jewel_part = typ, -- 铭文装备部位 hero_jewel_score = hero:getProperty("battleV"), -- 铭文装备后的英雄分值 hero_jewel_scorebefore = oldBattleV, -- 铭文装备前的英雄分值 hero_jewel_result = attrChange, -- 铭文装备后效果,可记录效果ID,或json格式记录提升效果,{攻击:20,闪避:20,……..} }) end end role:checkTaskEnter("RuneQualityCollect", {}) SendPacket(actionCodes.Hero_referRunesRpc, "") return true end function _M.createHeroRandomRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local itemId = msg.itemId local itemData = csvdb["itemCsv"][itemId] if not itemData or itemData.type ~= ItemType.HeroFCommon then return end local cost = globalCsv.unit_fragment_cost[itemData.quality] if not cost or role:getItemCount(itemId) < cost then return 1 end local randomData = csvdb["item_randomCsv"][tonumber(itemData.use_effect)] if not randomData then return 2 end local temp = randomData.gift1:randWeight(true) if not temp or not next(temp) then return 3 end role:costItems({[itemId] = cost}, {log = {desc = "createHeroRandom"}}) local reward, change = role:award({[temp[1]] = 1}, {log = {desc = "createHeroRandom"}}) SendPacket(actionCodes.Hero_createHeroRandomRpc, MsgPack.pack(role:packReward(reward, change))) return true end function _M.getResetRewardRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local hero = role.heros[msg.id] if not hero then return end local level = hero:getProperty("level") local breakL = hero:getProperty("breakL") local talent = hero:getProperty("talent") local heroCfgId = hero:getProperty("type") local tmpLevel = level if level <= 1 and talent == "" then return end local pay = true if level <= 60 then pay = false end if pay then local costArr = globalCsv.unit_heroBack_cost:toArray(true, "=") local itemCount = role:getItemCount(costArr[1]) local totalCost = {} if itemCount >= costArr[2] then totalCost[costArr[1]] = costArr[2] else local diamond = (costArr[2] - itemCount) * costArr[3] if role:getItemCount(ItemId.Diamond) < diamond then return 1 end totalCost[costArr[1]] = itemCount totalCost[ItemId.Diamond] = diamond end --if pay and not role:costDiamond({count = globalCsv.unit_heroBack_cost or 200, log = {desc = "resetHero", int1 = msg.id}}) then -- return 1 --end role:costItems(totalCost, {log = {desc = "resetHero", int1 = msg.id}}) end local reward = {} while level > 1 do local curData = csvdb["unit_expCsv"][level - 1] reward[ItemId.Exp] = (reward[ItemId.Exp] or 0) + curData.exp reward[ItemId.Gold] = (reward[ItemId.Gold] or 0) + curData.gold level = level - 1 end while breakL > 0 do local curData = csvdb["unit_breakCsv"][breakL - 1] reward[ItemId.BreakCost] = (reward[ItemId.BreakCost] or 0) + curData.cost reward[ItemId.Gold] = (reward[ItemId.Gold] or 0) + curData.gold breakL = breakL - 1 end local stage = talent:getv(0, 1) local curTalentLvl = talent:getv(1, 1) --local tlevel = {talent:getv(1, 0), talent:getv(2, 0), talent:getv(3, 0), talent:getv(4, 0)} while stage > 0 do local curData = csvdb["unit_talent_"..heroCfgId.."Csv"][stage] local offset = stage == talent:getv(0,1) and curTalentLvl - 1 or #curData for lvl = 1, offset do local talentData = curData[lvl] for itemId, count in pairs(talentData.money:toNumMap()) do reward[itemId] = (reward[itemId] or 0) + count end end stage = stage - 1 end local equip = hero:getProperty("equip") for k, v in pairs(equip:toNumMap()) do role:addEquip(k, v, 1, {log = {desc = "resetHero", int1 = msg.id, int2 = hero:getProperty("type")}}) end local rune = hero:getProperty("rune") for _, id in pairs(rune:toNumMap()) do local curRune = role.runeBag[id] if curRune then curRune:updateProperty({field = "refer", value = 0}) end end hero:updateProperties({ level = level, breakL = breakL, talent = "", equip = "", rune = "", }) hero:mylog({desc = "resetHero"}) --local coef = globalCsv.unit_back_discount --coef = (pay or tmpLevel <= 60) and 1 or coef for itemId, count in pairs(reward) do reward[itemId] = count end local change reward, change = role:award(reward, {log = {desc = "resetHero", int1 = msg.id, int2 = hero:getProperty("type")}}) role:log("hero_recycle", { hero_recycle_list = {[hero:getProperty("type")] = 1}, -- 回收的英雄id列表,建议使用json格式记录。示例:{ "XX": "1", "XXX": "3"} hero_recycle_reward = reward, -- 回收后获得的奖励,建议使用json格式记录。示例:{ "XX": "1", "XXX": "3"} hero_recycle_cnt = 1, -- 总回收英雄量 }) SendPacket(actionCodes.Hero_getResetRewardRpc, MsgPack.pack(role:packReward(reward, change))) return true end function _M.drawHeroRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local actid = msg.actid if not role:isFuncUnlock(FuncUnlock.GetHero) then return 1 end local btype = msg.pool -- 1 2 3 4 5 卡池类型 4新手卡池 5心愿卡池 local subType = msg.subType or 1-- 定向卡池需要传 子类型 local drawType = msg.type -- 1 单抽 2 十连 if btype ~= 1 then subType = 1 if btype == 4 and role:getProperty("newerDraw") >= 10 then subType = 2 if(role:getProperty("newerDraw") >= 30) then return 30 end end end -- 另开活动卡池 if actid then if not role.activity:isOpenById(actid, "ActHeroPool") then return end local cfg = csvdb["activity_ctrlCsv"][actid] if not cfg then return end btype = cfg.condition end if btype == 1 then -- 判断定向卡池活动开启 if not role.activity:isOpen("RaceDraw") then return end elseif btype == 2 then if role:getProperty("newerGuide") ~= "8=1" then -- 判断普通卡池 if role.activity:isOpen("WishHeroPool") then return end end elseif btype == 5 then -- 判断心愿单卡池 if not role.activity:isOpen("WishHeroPool") then return end end local buildTypeData = csvdb["build_typeCsv"][btype] if not buildTypeData then return 2 end local drawCount = {1, 10} -- 抽取次数 if not drawCount[drawType] then return 3 end local draw_floor_back_counts = globalCsv.draw_floor_back_counts[btype] local floorHeroCount = role:getProperty("floorHero")[btype] or 0 -- 计算抽卡消耗品 local cost = {} if buildTypeData["draw_coin_1"] == "" then return 11 end local diamondCost = buildTypeData["draw_coin_1"]:toArray(true, "=") local isEnough = true for _, costType in ipairs({"draw_card_"}) do costType = costType..drawCount[drawType] if buildTypeData[costType] ~= "" then local curCost = buildTypeData[costType]:toArray(true, "=") local hadCount = role:getItemCount(curCost[1]) if hadCount >= curCost[2] then cost[curCost[1]] = curCost[2] break else cost[curCost[1]] = hadCount diamondCost[2] = (curCost[2] - hadCount) * diamondCost[2] if not role:checkItemEnough({[diamondCost[1]]=diamondCost[2]}) then isEnough = false break end cost[diamondCost[1]] = diamondCost[2] end end end if isEnough == false then -- 钱不够 return 4 end -- 抽取的池子 local poolMap = buildTypeData["pool"]:toNumMap() local poolId = poolMap[subType] if not poolId then return 5 end --判断定向卡池是否开启 if btype == 1 then if not role:isTimeResetOpen(TimeReset["DrawType" .. subType]) then local unlockPool = role.dailyData:getProperty("unlockPool") if not unlockPool[subType] then return 6 end end end --TODO 活动覆盖 local actPoolId = role.activity:getActivityPool(btype, subType) if actPoolId ~= 0 then poolId = actPoolId end local unitPool = csvdb["build_unitCsv"][poolId] if not unitPool then return 7 end -- 开始抽 local resultPool = {} local function fillDrawPool(isFloorBack) local condition = {"rare"} local values = {} for idx, field in ipairs(condition) do if not values[idx] then local lpool = {} local curIdx = 1 while unitPool[field .. "_" .. curIdx] do lpool[curIdx] = {unitPool[field .. "_" .. curIdx]} curIdx = curIdx + 1 end if next(lpool) then values[idx] = math.randWeight(lpool, 1) end end end local weight = 0 local up_pool = nil local rand_v = math.randomInt(1, 100) if values[1] == HeroQuality.SR then weight = unitPool["up_sr_weight"] up_pool = unitPool["up_sr_id"] elseif values[1] == HeroQuality.SSR then weight = unitPool["up_ssr_weight"] up_pool = unitPool["up_ssr_id"] if btype == 5 then local wishPool = role:getProperty("wishPool") or {} weight = weight * #wishPool end end --print(poolId, rand_v, weight, up_pool, values[1]) if rand_v < weight and up_pool then up_pool = up_pool:toArray(true, "=") if btype == 5 then -- 爱心卡池,使用玩家设置的备选池子 up_pool = role:getProperty("wishPool") end for k, v in ipairs(up_pool) do resultPool[v] = {1} end else for itemId, oneData in pairs(isFloorBack and csvdb["build_floorCsv"] or csvdb["build_poolCsv"]) do local pool_str = "pool_" .. poolId if oneData[pool_str] and oneData[pool_str] ~= "" then local itemData = csvdb["itemCsv"][itemId] while itemData do if itemData.type ~= ItemType.Hero then break end local heroData = csvdb["unitCsv"][itemData.id - ItemStartId.Hero] if not heroData then break end local ok = true -- 保底是全随机,不用比较类型 if not isFloorBack then for idx, field in ipairs(condition) do if heroData[field] ~= values[idx] then ok = false break end end end -- 随机剔除up池中的角色 if up_pool then for k, v in ipairs(up_pool) do if v == itemData.id then ok = false break end end end if not ok then break end if oneData[pool_str] > 0 then resultPool[itemId] = {oneData[pool_str]} -- itemId, count, 概率 end break end end end end end role:costItems(cost, {log = {desc = "drawHero", int1 = btype, int2 = poolId}}) local guideHero = nil if role:getProperty("newerGuide") == "8=1" then guideHero = globalCsv.newdraw_hero_item_id or 503 end local ssrCount = 0 local reward = {} local logReward = {} for i = 1, drawCount[drawType] do floorHeroCount = floorHeroCount + 1 local isFloorBack = draw_floor_back_counts and floorHeroCount >= draw_floor_back_counts resultPool = {} fillDrawPool(isFloorBack) if not next(resultPool) then skynet.error("random pool error, poolId:" .. poolId) return 8 end local itemId = math.randWeight(resultPool, 1) if guideHero then itemId = guideHero guideHero = nil end local itemData = csvdb["itemCsv"][itemId] if itemData.quality == HeroQuality.SSR then ssrCount = ssrCount + 1 if not guideHero then -- 广播获得ssr英雄 local ntf = {heroId = itemData.id - ItemStartId.Hero, nick = role:getProperty("name")} mcast_util.pub_world(actionCodes.Role_broadGetSSR, MsgPack.pack(ntf)) end end if btype == 4 and role:getProperty("newerDraw") == 0 then -- 新手卡池 if itemData.quality == HeroQuality.SSR then floorHeroCount = 0 end else if itemData.quality >= HeroQuality.SR then floorHeroCount = 0 end end if role:isHaveHero(itemData.id - ItemStartId.Hero) then local fragId = itemData.id - ItemStartId.Hero local heroData = csvdb["unitCsv"][fragId] local count = globalCsv.draw_unit_tofragment[heroData.rare] role:award({[fragId] = count}, {log = {desc = "drawHero", int1 = btype, int2 = poolId}}) logReward[fragId] = (logReward[fragId] or 0) + count table.insert(reward, {id = fragId, count = count, from = itemId, fcount = 1}) else role:award({[itemId] = 1}, {log = {desc = "drawHero", int1 = btype, int2 = poolId}}) logReward[itemId] = (logReward[itemId] or 0) + 1 table.insert(reward, {id = itemId, count = 1}) end end if draw_floor_back_counts then local floorHero = role:getProperty("floorHero") floorHero[btype] = floorHeroCount role:setProperty("floorHero", floorHero) end if btype == 4 then local newCount = role:getProperty("newerDraw") role:updateProperty({field="newerDraw", value = newCount + drawCount[drawType]}) end role:checkTaskEnter("DrawHero", {pool = btype, count = drawCount[drawType]}) if ssrCount > 0 then role:checkTaskEnter("DrawSSR", {count = ssrCount}) end role:finishGuide(8) role:log("gacha", { gacha_id = poolId, -- 卡池ID gacha_type = btype, -- 卡池类型 gacha_up = 0, -- 卡池UP角色 gacha_times = drawCount[drawType], -- 抽卡次数 gacha_reward = logReward, -- 抽卡结果,建议使用json格式记录。示例:{ "XX": "1", "XXX": "3"} gacha_cost = cost, -- 购买道具消耗的货币 gacha_cnt = floorHeroCount, }) SendPacket(actionCodes.Hero_drawHeroRpc, MsgPack.pack({reward = reward})) -- 这个 reward 是数组 local feedbackId = buildTypeData["can_feedback"] or 0 if feedbackId ~= 0 then -- 达到一定次数,给响应奖励 local oldVal = role:getProperty("repayHero") or 0 if actid then local actData = role.activity:getActData("ActHeroPool") oldVal = actData[btype] or 0 end local newVal = oldVal + drawCount[drawType] local drawCardReward, val = role:getDrawCardExtraReward(feedbackId, oldVal, newVal) -- 空字符穿代表直接给英雄 走以前repayHeroRpc if drawCardReward == "" then local repayHeroMaxCount = role:getProperty("repayMaxC") or 0 repayHeroMaxCount = repayHeroMaxCount + 1 role:updateProperty({field = "repayMaxC", value = repayHeroMaxCount}) local even = repayHeroMaxCount % 2 local id = 0 if even == 1 then id = math.randWeight(csvdb["build_giftCsv"], "pool_"..feedbackId) else local giftHeroSet = {} for gid, cfg in pairs(csvdb["build_giftCsv"]) do if cfg["pool_"..feedbackId] ~= 0 and not role:isHaveHero(gid - ItemStartId.Hero) then giftHeroSet[gid] = {1} end end if next(giftHeroSet) then id = math.randWeight(giftHeroSet, 1) end end if id == 0 then id = math.randWeight(csvdb["build_giftCsv"], "pool_"..feedbackId) end local r,change = {} local itemData = csvdb["itemCsv"][id] --if itemData.type == ItemType.Hero and role:isHaveHero(itemData.id - ItemStartId.Hero) then -- local fragId = itemData.id - ItemStartId.Hero -- local heroData = csvdb["unitCsv"][fragId] -- local count = globalCsv.draw_unit_tofragment[heroData.rare] -- r, change = role:award({[fragId] = count}, {log = {desc = "drawHeroExtraReward"}}) -- --r = {id = fragId, count = count, from = id, fcount = 1} --else r, change = role:award({[id] = 1}, {log = {desc = "drawHeroExtraReward"}}) --end SendPacket(actionCodes.Hero_drawHeroExtraRewardNtf, MsgPack.pack(role:packReward(r, change))) elseif drawCardReward and drawCardReward ~= "" then local r,change = {} r, change = role:award(drawCardReward, {log = {desc = "drawHeroExtraReward", int1 = oldVal, int2 = newVal}}) SendPacket(actionCodes.Hero_drawHeroExtraRewardNtf, MsgPack.pack(role:packReward(r, change))) end if not actid then role:updateProperty({field = "repayHero", value = val}) else local actData = role.activity:getActData("ActHeroPool") actData[btype] = val role.activity:updateActData("ActHeroPool", actData) end end return true end function _M.repayHeroRpc(agent, data) local role = agent.role local repayHero = role:getProperty("repayHero") local cnt = globalCsv.draw_times_to_get_ssr or 100 if repayHero < cnt then return end local result = repayHero - cnt role:updateProperty({field = "repayHero", value = result}) local id = math.randWeight(csvdb["build_giftCsv"], "pool_1") local reward = {} local itemData = csvdb["itemCsv"][id] if itemData.type == ItemType.Hero and role:isHaveHero(itemData.id - ItemStartId.Hero) then local fragId = itemData.id - ItemStartId.Hero local heroData = csvdb["unitCsv"][fragId] local count = globalCsv.draw_unit_tofragment[heroData.rare] role:award({[fragId] = count}, {log = {desc = "heroRepay"}}) reward = {id = fragId, count = count, from = id, fcount = 1} else role:award({[id] = 1}, {log = {desc = "heroRepay"}}) reward = {id = id, count = 1} end role:mylog("hero_action", {desc = "heroRepay", int1=result}) SendPacket(actionCodes.Hero_repayHeroRpc, MsgPack.pack({reward = reward})) return true end function _M.unlockPoolRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) if not role:isFuncUnlock(FuncUnlock.GetHero) then return end local type = msg.type -- 指定定向卡池需要类型 1, 2, 3 local needCost = true --当前开启的类型不用解锁 if role:isTimeResetOpen(TimeReset["DrawType" .. type]) then needCost = false end --已经解锁的不需要重复解锁 local unlockPool = role.dailyData:getProperty("unlockPool") if unlockPool[type] then needCost = false end if needCost then if not role:costDiamond({count = globalCsv.draw_unlock_pool_diamond or 300, log = {desc = "unlockPool", int1 = type}}) then return end end unlockPool[type] = 1 role.dailyData:updateProperty({field="unlockPool", value = unlockPool}) role.dailyData:updateProperty({field="curPool", value = type}) role:mylog("hero_action", {desc = "unlockPool", int1=type}) SendPacket(actionCodes.Hero_unlockPoolRpc, MsgPack.pack({})) return true end function _M.changeCrown(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local heroType = msg.heroType if not role:isHaveHero(heroType) then return true end role:setProperty("crown", heroType) role:log("hero_show", { hero_id = heroType, }) return true end function _M.itemComposeRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local itemId = msg.id local count = msg.count if not csvdb["itemCsv"][itemId] then return 1 end local config = csvdb["item_processCsv"][itemId] if not config then return 2 end local cost = config.cost:toNumMap() for k, v in pairs(cost) do cost[k] = v * count end if not role:checkItemEnough(cost) then return 2 end role:costItems(cost, {log = {desc = "itemCompose", int1 = itemId, int2 = count}}) role:award({[itemId] = count}, {log = {desc = "itemCompose"}}) SendPacket(actionCodes.Hero_itemComposeRpc, "") return true end function _M.setWishPoolRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local heros = msg.heros if #heros > 3 then return 1 end for _, heroId in pairs(heros) do local cfg = csvdb["build_poolCsv"][heroId] if not cfg then return 2 end local buildTypeData = csvdb["build_typeCsv"][5] if not buildTypeData then return 3 end local poolMap = buildTypeData["pool"]:toNumMap() local poolId = poolMap[1] if not poolId then return 4 end if cfg["pool_"..poolId] == 0 then return 5 end end role:updateProperty({field="wishPool", value = heros}) SendPacket(actionCodes.Hero_setWishPoolRpc, "") return true end return _M