local httpc = require("http.httpc") local md5 = require "md5" local cjson = require "shared.json" local serverId = tonumber(skynet.getenv("servId")) local RolePlugin = {} function RolePlugin.bind(Role) function Role:loadAll() self:loadDaily() self:loadEquips() self:loadRunes() self:loadHeros() self:loadDiner() self:loadActivity() self:loadStoreInfo() --self:loadRoleIncre() self:loadFriends() self:loadSparks() end function Role:reloadWhenLogin() end function Role:SendPacket(...) SendPacket(...) end function Role:onOfflineEvent() -- 设置最新的登录时间 self:setProperty("ltime", skynet.timex()) end local function checkItemCount(self, itemId, count) local itemData = csvdb["itemCsv"][itemId] -- 种类 类型数量限制 local page = globalCsv.store_type[itemData.type] local limit = self:getProperty("bagLimit")[page] if limit and self:getItemCount(itemId) == 0 then local curCount = 0 local items = self:getProperty("items"):toNumMap() for id ,_ in pairs(items) do local tempData = csvdb["itemCsv"][id] if tempData then if globalCsv.store_type[tempData.type] == page then curCount = curCount + 1 if curCount >= limit then count = 0 break end end end end end return count end local function _award(self, itemId, count, params) local count = math.floor(count) local pms = clone(params) local itemData = csvdb["itemCsv"][itemId] if not itemData then -- 加一层保护 return 0, {} end local curType = itemData.type local change = {} -- 奖励被转化为了其他奖励 id = count local itemIdAward = { [ItemId.PlayerExp] = function() self:addPlayExp(count, pms) end, [ItemId.AdvPower] = function() self:changeAdvCount(-count) end, } local itemTypeAward = { [ItemType.Hero] = function() pms.type = itemId - ItemStartId.Hero local status = self:addHero(pms) local gcount = 1 if not status then gcount = 0 end if count - gcount > 0 then local heroData = csvdb["unitCsv"][pms.type] change[pms.type] = (change[pms.type] or 0) + (count - gcount) * globalCsv.draw_unit_tofragment[heroData.rare] end count = gcount end, [ItemType.EquipBase] = function() local typ = math.floor((itemId-7000)/100) local lv = (itemId-7000)%100 self:addEquip(typ, lv, count ,pms) local equipCsv = (csvdb["equipCsv"][typ] or {})[lv] self:checkTaskEnter("AddEquip", {equipId = itemId, rarity = equipCsv.rarity}, pms.notNotify) end, [ItemType.Rune] = function() local typ = math.floor((itemId-10000)/1000) for _= 1, count do self:addRune({type = typ,id = itemId, notNotify = pms.notNotify, log = pms.log}) end end, [ItemType.Spark] = function() for _= 1, count do self:addSpark({id = itemId, notNotify = pms.notNotify, log = pms.log}) end end, [ItemType.AdvItem] = function() --冒险道具不会进入 玩家仓库 count = 0 end, [ItemType.FuncOpen] = function() self:funcOpen(itemId, count, pms) end, [ItemType.HeroFCommon] = function() if itemData.use_type == 2 then local randomData = csvdb["item_randomCsv"][tonumber(itemData.use_effect)] for _i = 1, count do for i = 1, 10 do local num = randomData["num" .. i] local gift = randomData["gift" .. i] if num and gift and num > 0 and gift ~= "" then local pool = {} for _, temp in ipairs(gift:toArray()) do table.insert(pool, temp:toArray(true, "=")) end local needCount = math.min(#pool, num) for j = 1, needCount do local idx = math.randWeight(pool, 3) change[pool[idx][1]] = (change[pool[idx][1]] or 0) + pool[idx][2] table.remove(pool, idx) end end end end change[0] = nil count = 0 else pms.itemId = itemId pms.count = count self:addItem(pms) end end, [ItemType.Potion] = function () self:addPotion({id = itemId, count = count, notNotify = pms.notNotify, log = pms.log}) end, [ItemType.BossTicket] = function () if not self.activity:isOpen("ChallengeLevel") then return end local actData = self.activity:getActData("ChallengeLevel") actData["ticket"] = (actData["ticket"] or 0) + count self.activity:updateActData("ChallengeLevel", actData) end, } if count > 0 then local itemCfg = csvdb["itemCsv"][itemId] local itemType = 0 if itemCfg then itemType = itemCfg.type end self:checkTaskEnter("AddItem", {id = itemId, count = count, type = itemType}) end -- 对数量筛查 count = checkItemCount(self, itemId, count) if count ~= 0 then if itemIdAward[itemId] then itemIdAward[itemId]() elseif itemTypeAward[curType] then itemTypeAward[curType]() else pms.itemId = itemId pms.count = count self:addItem(pms) end end return count, change -- count 实际发放的奖励个数 change 物品实际奖励与当前id 不符 就发生转换 而不实际发奖 end -- 发奖功能入口 award string id=count or {[id] = count} function Role:award(gift, params) params = params or {} local tgift = {} if type(gift) == "string" then for _, one in pairs(gift:toTableArray(true)) do tgift[one[1]] = (tgift[one[1]] or 0) + one[2] end else tgift = gift end local reward, allChange = {}, {} for itemId, rcount in pairs(tgift) do local count, change = _award(self, itemId, rcount, params) if count > 0 then reward[itemId] = (reward[itemId] or 0) + count end if next(change) then local cr, _ = self:award(change, params) -- 内部转换忽略 防止死循环 if next(cr) then for _id, _ct in pairs(cr) do reward[_id] = (reward[_id] or 0) + _ct end table.insert(allChange, {form = {[itemId] = rcount - count}, to = cr}) end end end if not next(allChange) then allChange = nil end return reward, allChange --实际获得的奖励 和 最高级奖励转化过程 end function Role:packReward(reward, change) if not reward then return nil end return {reward = reward, change = change} end function Role:awardExpireItem(expireTime, gift, params) if expireTime <= skynet.timex() then return end local reward = self:award(gift, params) local expireItem = self:getProperty("expireItem") for itemId, _ in pairs(reward) do expireItem[itemId] = expireTime end self:setProperty("expireItem", expireItem) end function Role:checkExpireItem(notNotify) local expireItem = self:getProperty("expireItem") local now = skynet.timex() for itemId, expireTime in pairs(expireItem) do if expireTime <= now then expireItem[itemId] = nil local itemCount = self:getItemCount(itemId) if itemCount > 0 then -- 过期物品删掉 self:addItem({itemId = itemId, count = -itemCount, log = {desc = "expire"}, notNotify = notNotify}) --过期 local itemData = csvdb["itemCsv"][itemId] if itemData then if itemData.type == ItemType.Head then -- 检查头像是不是在穿戴 if self:getProperty("headId") == itemId then self:changeHead(globalCsv.defaultHead, notNotify) local headData = csvdb["player_iconCsv"][itemId] -- pvp 跨服竞技场奖励 if headData and headData.path == 2 then mysqlproxy:insertEmail({roleId = self:getProperty("id"), emailId = 19}) end end end end end end end self:setProperty("expireItem", expireItem) end function Role:changeHead(id, notNotify) self:updateProperty({field = "headId" ,value = id, notNotify = notNotify}) self:changeCrossServerPvpSelfInfo("headId") self:mylog("role_action", {desc = "changeHead", int1 = id}) end function Role:addPlayExp(addExp, params) local level = self:getProperty("level") local oldLevel = level if not csvdb["player_expCsv"][level + 1] then return end local exp = self:getProperty("exp") local newExp = exp + addExp while newExp >= csvdb["player_expCsv"][level].exp do if csvdb["player_expCsv"][level + 1] then -- 有下一级 newExp = newExp - csvdb["player_expCsv"][level].exp level = level + 1 self:checkTaskEnter("RoleLevelUp", {level = level}) else newExp = csvdb["player_expCsv"][level].exp - 1 -- 没有下一级了 经验溢出太多 扣除 end end if level > oldLevel then if params.log then local log = params.log self:log("setLevel", { level_before = oldLevel, level_changemain = log.desc, level_changedetail = log.int1 or 0, level_reward = {}, }) else print("addPlayExp no log ", debug.traceback()) end end if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] then print("addPlayExp error log have cint1 or cint2 or cint3", debug.traceback()) end log["cint1"] = addExp log["cint2"] = newExp log["cint3"] = level self:mylog("player_exp", log) else print("addPlayExp no log ", debug.traceback()) end self:updateProperties({level = level, exp = newExp}, params.notNotify) self:changeCrossServerPvpSelfInfo("level") end function Role:addPotion(params) local pId = globalCsv.adv_item_potion[params.id] local potionBag = self:getProperty("potionBag") local origin = potionBag[pId] or 0 local nums = origin + params.count potionBag[pId] = nums self:logItems(params.id, origin, nums, params.log) if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] then print("addItem error log have cint1 or cint2 ", debug.traceback()) end log["cint1"] = params.id log["cint2"] = math.abs(params.count) if params.count <= 0 then self:mylog("out_item", log) else self:mylog("in_item", log) end else print("addItem no log ", debug.traceback()) end self:updateProperty({field = "potionBag", value = potionBag}) if not params.notNotify then SendPacket(actionCodes.Role_updateItems, MsgPack.pack({[params.id] = params.count})) end end function Role:addItem(params) params = params or {} params.count = math.floor(params.count or 0) if params.itemId == ItemId.Diamond then self:gainDiamond(params) return end local items = self:getProperty("items") local origin = items:getv(params.itemId, 0) local nums = origin+params.count if nums <= 0 then items = items:delk(params.itemId) nums = 0 else items = items:incrv(params.itemId, params.count) end self:logItems(params.itemId, origin, nums, params.log) if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] then print("addItem error log have cint1 or cint2 ", debug.traceback()) end log["cint1"] = params.itemId log["cint2"] = math.abs(params.count) if params.count <= 0 then self:mylog("out_item", log) else self:mylog("in_item", log) end else print("addItem no log ", debug.traceback()) end self:setProperty("items", items) if not params.notNotify then SendPacket(actionCodes.Role_updateItems, MsgPack.pack({[params.itemId] = nums})) end end function Role:checkItemEnough(itemCountT) local less = {} if not next(itemCountT) then return true, less end for itemId, count in pairs(itemCountT) do if count <= 0 then -- 判断物品数量值不应该小于等于0 less[itemId] = 0 else local last = self:getItemCount(itemId) - count if last < 0 then less[itemId] = -last end end end return (not next(less)), less -- 是否足够,,缺什么缺多少 end function Role:costItems(itemCountT, params) local pms = clone(params or {}) if itemCountT[ItemId.Diamond] then --优先扣除钻石 pms.count = itemCountT[ItemId.Diamond] if not self:costDiamond(pms) then return end end for itemId, count in pairs(itemCountT) do if itemId ~= ItemId.Diamond then pms.itemId = itemId pms.count = - count self:addItem(pms) self:itemDeltaEvent(pms) end end return true end function Role:itemDeltaEvent(pms) self:eventBoxL(pms) end -- 拆解室的生产线启动 function Role:eventBoxL(pms) local limit = globalCsv.box_key_max[pms.itemId] if not limit then return end local update = false local boxL = self:getProperty("boxL") or {} for slot, data in pairs(boxL) do if data.time == 0 and data.id == pms.itemId and self:getItemCount(pms.itemId) < limit then update = true data.time = skynet.timex() end end if update then self:updateProperty({field = "boxL", value = boxL, notNotify = pms.notNotify}) end end function Role:getItemCount(itemId) if itemId == ItemId.Diamond then return self:getAllDiamond() end return self:getProperty("items"):getv(itemId, 0) end function Role:getAllDiamond() local diamond = self:getProperty("sid") == IOS_SID and self:getProperty("reDiamondIos") or self:getProperty("reDiamond") --return self:getProperty("diamond") + diamond return diamond end function Role:gainDiamond(params) if not params or type(params) ~= "table" then return false end local count = tonum(params.count) if isnan(count) then return false end local origind = 0 -- self:getProperty("diamond") local originr = self:getProperty("sid") == IOS_SID and self:getProperty("reDiamondIos") or self:getProperty("reDiamond") local origin = origind + originr --if params.isRecharge then if params.sid == IOS_SID then self:incrProperty("reDiamondIos", count) else self:incrProperty("reDiamond", count) end --else --self:incrProperty("diamond", count) --end self:logItems(ItemId.Diamond, origin, count, params.log) if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] or log["cint3"] then print("costDiamond error log have cint1 or cint2 or cint3 ", debug.traceback()) end log["cint1"] = origin log["cint2"] = count self:mylog("in_diamond", log) else print("gainDiamond no log ", debug.traceback()) end self:notifyUpdateProperty("diamond", self:getAllDiamond()) return true end function Role:costDiamond(params) if not params or type(params) ~= "table" then return false end local count = tonum(params.count) if isnan(count) then return false end if count <= 0 then return false end local isIos = self:getProperty("sid") == IOS_SID local origind = 0 -- self:getProperty("diamond") local originr = isIos and self:getProperty("reDiamondIos") or self:getProperty("reDiamond") local origin = origind + originr if origin < 0 then return false end if origin < count then return false end local diamondKey = isIos and "reDiamondIos" or "reDiamond" self:incrProperty(diamondKey, -count) --local last = count --local costFirst = isIos and {"diamond", "reDiamondIos"} or {"diamond", "reDiamond"} --if params.isRecharge then -- costFirst = isIos and {"reDiamondIos", "diamond"} or {"reDiamond", "diamond"} --end --last = math.max(last - self:getProperty(costFirst[1]), 0) --if last < count then -- self:incrProperty(costFirst[1], last - count) --end --if last > 0 then -- self:incrProperty(costFirst[2], -last) --end self:logItems(ItemId.Diamond, origin, count, params.log) if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] or log["cint3"] then print("costDiamond error log have cint1 or cint2 or cint3 ", debug.traceback()) end log["cint1"] = origin log["cint2"] = count self:mylog("out_diamond", log) else print("costDiamond no log ", debug.traceback()) end self:notifyUpdateProperty("diamond", self:getAllDiamond()) self:checkTaskEnter("CostDiamond", {count = count}) return true end function Role:increBy(field, val) local roleIncre = self:getProperty("roleIncre") local curId = roleIncre[field] or 0 roleIncre[field] = curId + val self:setProperty("roleIncre", roleIncre) return curId + val end function Role:addHero(params) local roleId = self:getProperty("id") local heroType = params.type if self:isHaveHero(heroType) then return end local unitData = csvdb["unitCsv"][heroType] if not unitData then return false end local heroId = self:increBy("heroId" , 1) local heroInfo = { key = string.format("%d",roleId * MAX_HERO_NUM + heroId), id = roleId * MAX_HERO_NUM + heroId, roleid = roleId, type= heroType, wakeL = globalCsv.unit_wake_initLevel[unitData.rare], } if heroInfo.wakeL == 3 then self:checkTaskEnter("WakeCG", {heroType = heroType}) end local newHero = require("models.Hero").new(heroInfo) newHero:create() newHero.owner = self newHero:saveBattleValue() self.heros[heroId] = newHero local ssrCount = 0 if unitData.rare == HeroQuality.SSR then ssrCount = self:getSSRHeroCount() end self:checkTaskEnter("AddHero", {heroType = heroType, wakeL = newHero:getProperty("wakeL"), camp = unitData.camp, job = unitData.job, ssrCount = ssrCount}, params.notNotify) self:checkTaskEnter("HeroQualityCollect", {}) if not params.notNotify then local heroResponse = {} table.insert(heroResponse, newHero:data()) local bin = MsgPack.pack(heroResponse) SendPacket(actionCodes.Hero_loadInfos, bin) end self:logItems(heroType + ItemStartId.Hero, 0, 1, params.log) if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] or log["cint3"] then print("addHero error log have cint1 or cint2 or cint3 ", debug.traceback()) end log["cint1"] = heroId log["cint2"] = heroType self:mylog("in_hero", log) else print("addHero no log ", debug.traceback()) end return true, newHero end function Role:isHaveHero(heroType) if not csvdb["unitCsv"][heroType] then return false end for _, hero in pairs(self.heros) do if hero:getProperty("type") == heroType then return hero end end end function Role:getSSRHeroCount() local count = 0 for _, hero in pairs(self.heros) do if hero:getRare() == HeroQuality.SSR then count = count + 1 end end return count end function Role:loadHeros() local roleId = self:getProperty("id") local res = mysqlproxy:query(string.format("SELECT * FROM `Hero` WHERE `roleid` = %s", roleId)) for _, data in ipairs(res) do local hero = require("models.Hero").new({key = string.format("%d",data.id), id=data.id}) if hero:load(data) then hero.owner = self self.heros[hero:getSimpleHeroId()] = hero end end end function Role:loadFriends() local roleId = self:getProperty("id") local res = mysqlproxy:query(string.format("SELECT * FROM `Friend` WHERE `roleid` = %s", roleId)) for _, data in ipairs(res) do local friend = require("models.Friend").new({key = string.format("%d",data.id), id = data.id}) if friend:load(data) then self.friends[friend:getProperty("fid")] = friend end end end function Role:loadDaily() local roleId = self:getProperty("id") local dataKey = string.format("%d", roleId) self.dailyData = require("models.Daily").new({key = dataKey, id = roleId}) self.dailyData.owner = self if not self.dailyData:checkKeyExists(dataKey) then self.dailyData:create() else self.dailyData:load() end end function Role:loadActivity() local roleId = self:getProperty("id") local dataKey = string.format("%d", roleId) self.activity = require("models.Activity").new({key = dataKey, id = roleId}) self.activity.owner = self if not self.activity:checkKeyExists(dataKey) then self.activity:create() else self.activity:load() end end function Role:loadDiner() local roleId = self:getProperty("id") local dataKey = string.format("%d", roleId) self.dinerData = require("models.Diner").new({key = dataKey, id = roleId}) self.dinerData.owner = self if not self.dinerData:checkKeyExists(dataKey) then self.dinerData:create() else self.dinerData:load() end end function Role:loadEquips() -- 放role 里面了 end function Role:loadStoreInfo() local roleId = self:getProperty("id") local dataKey = string.format("%d", roleId) self.storeData = require("models.Store").new({key = dataKey, id = roleId}) self.storeData.owner = self if not self.storeData:checkKeyExists(dataKey) then self.storeData:create() else self.storeData:load() end end --function Role:loadRoleIncre() -- local roleId = self:getProperty("id") -- local dataKey = string.format("%d", roleId) -- self.roleIncre = require("models.RoleIncre").new({key = dataKey, id = roleId}) -- self.roleIncre.owner = self -- if not self.roleIncre:checkKeyExists(dataKey) then -- self.roleIncre:create() -- else -- self.roleIncre:load() -- end --end function Role:addEquip(equipType, equipLv, count, pms) pms = pms or {} if count ~= count then return end local equipCsv = (csvdb["equipCsv"][equipType] or {})[equipLv] if not equipCsv then return end local equips = self:getProperty("equips") local curTypeEquips = equips[equipType] or {} local oldCount = curTypeEquips[equipLv] or 0 local curCount = oldCount + count -- 是否足够上层判断 if curCount < 0 then curCount = 0 curTypeEquips[equipLv] = nil else curTypeEquips[equipLv] = curCount end if next(curTypeEquips) then equips[equipType] = curTypeEquips else equips[equipType] = nil end self:setProperty("equips", equips) self:logItems(equipCsv.id, oldCount, curCount, pms.log) if pms.log then local log = clone(pms.log) if log["cint1"] or log["cint2"] or log["cint3"] then print("addEquip error log have cint1 or cint2 or cint3 ", debug.traceback()) end log["cint1"] = equipType log["cint2"] = equipLv log["cint3"] = math.abs(count) if count < 0 then self:mylog("out_equip", log) else self:mylog("in_equip", log) end else print("addEquip no log ", debug.traceback()) end if not pms.notNotify then self:changeUpdates({{type = "equips", field = {equipType, equipLv}, value = curCount, isOnlyToC = true}}) -- 通知客户端 end end function Role:getEquipCount(typ,lv) return (self:getProperty("equips")[typ] or {})[lv] or 0 end function Role:loadRunes() local roleId = self:getProperty("id") local res = mysqlproxy:query(string.format("SELECT * FROM `Rune` WHERE `roleid` = %s", roleId)) for _, data in ipairs(res) do local rune = require("models.Rune").new({key = string.format("%d",data.uid), uid=data.uid}) if rune:load(data) then rune.owner = self self.runeBag[data.uid] = rune end end end function Role:loadSparks() local roleId = self:getProperty("id") local res = mysqlproxy:query(string.format("SELECT * FROM `Spark` WHERE `roleid` = %s", roleId)) for _, data in ipairs(res) do local spark = require("models.Spark").new({key = string.format("%d",data.id), id=data.id}) if spark:load(data) then spark.owner = self self.sparkBag[data.id] = spark end end end -- 0 为操作成功 function Role:addRune(params) if params.type and params.id then local set = csvdb["runeCsv"][params.type] if not set then return 2 end local data = set[params.id] if not data then return 3 end local roleId = self:getProperty("id") local runeUid = self:increBy("runeId" , 1) local runeInfo = { key = string.format("%d",roleId * MAX_RUNE_NUM + runeUid), uid = roleId * MAX_RUNE_NUM + runeUid, roleid = roleId, type = params.type, id = params.id, } local newRune = require("models.Rune").new(runeInfo) newRune:create() newRune:generateAttrs() newRune.owner = self self.runeBag[runeUid] = newRune if not params.notNotify then local response = {} table.insert(response, newRune:data()) SendPacket(actionCodes.Role_loadRunes, MsgPack.pack(response)) end self:checkTaskEnter("AddRune", {id = params.id, type = params.type, rarity = data.rarity}, params.notNotify) self:logItems(params.id, 0, 1, params.log) if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] or log["cint3"] then print("addRune error log have cint1 or cint2 or cint3 ", debug.traceback()) end log["cint1"] = runeUid log["cint2"] = params.type log["cint3"] = params.id self:mylog("in_rune", log) else print("addRune no log ", debug.traceback()) end return 0, newRune else return 1 end end -- 0 为操作成功 function Role:addSpark(params) if params.id then local set = csvdb["sparkCsv"][params.id] if not set then return 2 end local data = set[0] if not data then return 3 end local roleId = self:getProperty("id") local sparkUid = self:increBy("sparkId" , 1) local sparkInfo = { key = string.format("%d",roleId * MAX_SPARK_NUM + sparkUid), id = roleId * MAX_SPARK_NUM + sparkUid, roleid = roleId, cfg_id = params.id, } local newSpark = require("models.Spark").new(sparkInfo) newSpark:create() newSpark:addAttr(data.attr:toNumMap()) newSpark.owner = self self.sparkBag[sparkUid] = newSpark if not params.notNotify then local response = {} table.insert(response, newSpark:data()) SendPacket(actionCodes.Role_loadSparks, MsgPack.pack(response)) end --self:checkTaskEnter("AddSpark", {id = params.id, type = params.type, rarity = data.rarity}, params.notNotify) self:logItems(params.id, 0, 1, params.log) if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] or log["cint3"] then print("addSpark error log have cint1 or cint2 or cint3 ", debug.traceback()) end log["cint1"] = sparkUid log["cint2"] = params.cfg_id self:mylog("in_spark", log) else print("addSpark no log ", debug.traceback()) end return 0, newSpark else return 1 end end function Role:delSparks(sparkIds, params) -- 批量删除 {id, } params = params or {} local roleId = self:getProperty('id') local bDel = {} for _, sparkId in pairs(sparkIds) do local spark = self.sparkBag[sparkId] if spark then self:logItems(spark:getProperty("id"), 1, 0, params.log) if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] then print("delSpark error log have cint1 or cint2 ", debug.traceback()) end log["cint1"] = sparkId log["cint2"] = spark:getProperty("cfg_id") self:mylog("out_spark", log) else print("delSparks no log ", debug.traceback()) end self.sparkBag[sparkId] = nil table.insert(bDel, sparkId) end end -- delete spark mysqlproxy:query(string.format("DELETE FROM `Spark` WHERE `id` in (%s)", table.concat(bDel, ","))) local response = {} for _, sparkId in pairs(bDel) do table.insert(response, {id = sparkId, bDel = true}) end SendPacket(actionCodes.Role_loadSparks, MsgPack.pack(response)) end function Role:delRunes(runeIds, params) -- 批量删除 {id, } params = params or {} local roleId = self:getProperty('id') local bDel = {} for _, runeId in pairs(runeIds) do local rune = self.runeBag[runeId] if rune and rune:getProperty("refer") == 0 then self:logItems(rune:getProperty("id"), 1, 0, params.log) if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] or log["cint3"] then print("delRunes error log have cint1 or cint2 or cint3 ", debug.traceback()) end log["cint1"] = runeId log["cint2"] = rune:getProperty("type") log["cint3"] = rune:getProperty("id") self:mylog("out_rune", log) else print("delRunes no log ", debug.traceback()) end self.runeBag[runeId] = nil table.insert(bDel, runeId) end end -- delete rune mysqlproxy:query(string.format("DELETE FROM `Rune` WHERE `uid` in (%s)", table.concat(bDel, ","))) local response = {} for _, runeId in pairs(bDel) do table.insert(response, {uid = runeId, bDel = true}) end SendPacket(actionCodes.Role_loadRunes, MsgPack.pack(response)) end function Role:getRuneByType(typ) local runeSet = {} for _,v in pairs(self.runeBag) do if v.type == typ then table.insert(runeSet,v) end end return runeSet end function Role:getAdvData(notNotify) if not self.advData then self.advData = require("adv.Adv").new(self) local status, err = pcall(function() self.advData:initByInfo() end) if not status then self.advData:forceOver(notNotify, true) skynet.error("getAdvData error adv initByInfo " .. err) end end return self.advData end function Role:getHeroMaxField(field, hType) local max = 0 for _, hero in pairs(self.heros) do if not hType or hero:getProperty("type") == hType then if hero:getProperty(field) > max then max = hero:getProperty(field) end end end return max end function Role:warningHeartTooQuick() -- 加速器检测 local heartWarning = self:getProperty("heartWarning") heartWarning = heartWarning + 1 self:setProperty("heartWarning", heartWarning) if heartWarning == 50 then self:setBan(30, 1) --封禁 30天 return end if heartWarning < 50 and heartWarning % 5 == 0 then self:sendGmMsg("server_accountBanned_warning") self:mylog("role_action",{desc = "heartWarning", int1 = heartWarning}) end end function Role:setBan(time, banType) time = time or 0 banType = banType or 0 local now = skynet.timex() if time <= 0 then self:setProperty("banTime", 0) self:setProperty("banType", 0) self:setProperty("heartWarning", 0) self:mylog("role_action", {desc = "ban_rm"}) else self:sendGmMsg(globalCsv.ban_tips[banType] or globalCsv.ban_tips[0]) self:setProperty("banTime", math.ceil(now + 86400 * time)) self:setProperty("banType", banType) self:resetRank() self:mylog("role_action", {desc = "ban", int1 = math.ceil(time), int2 = banType}) end end -- 清掉所有排行榜 function Role:resetRank() local roleId = self:getProperty("id") redisproxy:pipelining(function (red) red:zrem(RANK_TOWER, roleId) for _, rk in pairs(RANK_ADV) do red:zrem(rk, roleId) end for _, rk in pairs(RANK_DINER) do red:zrem(rk, roleId) end for _, rk in pairs(RANK_PVP_COMMON_KEY) do red:zrem(rk, roleId) end for _, rk in pairs(RANK_PVP_HIGHT_KEY) do red:zrem(rk, roleId) end for _, ct in pairs(RANK_TYPE) do red:zrem(RANK_COMMON .. ct, roleId) end end) end function Role:sendGmMsg(text, isNotKey) SendPacket(actionCodes.Sys_maintainNotice, MsgPack.pack({ body = text, iskey = not isNotKey})) local agent = datacenter.get("agent", self:getProperty("id")) if agent then skynet.timeout(50, function () skynet.call(agent.gate_serv, "lua", "forcekick", agent.fd) end) end end -- function Role:getHeroActiveRelationData(heros) -- local relations = {} -- for _, id in pairs(heros or {}) do -- local hero = self.heros[id] -- if hero then -- local camp = csvdb["unitCsv"][hero:getProperty("type")].camp -- relations[camp] = (relations[camp] or 0) + 1 -- end -- end -- local curData = csvdb["unit_relationCsv"][0] -- if not next(relations) then return curData end -- for _, data in ipairs(csvdb["unit_relationCsv"]) do -- local had = {} -- local isDone = true -- for _, count in pairs(data.relation:toArray(true, "=")) do -- local find = false -- for camp, _count in pairs(relations) do -- if count == _count and not had[camp] then -- had[camp] = true -- find = true -- break -- end -- end -- if not find then -- isDone = false -- break -- end -- end -- if isDone then -- curData = data -- end -- end -- return curData -- end -- function Role:getHeroActiveRelation(heros) -- local data = self:getHeroActiveRelationData(heros) -- local result = {} -- for attr, value in pairs(data.effect:toNumMap()) do -- result[AttsEnumEx[attr]] = (result[AttsEnumEx[attr]] or 0) + value -- end -- return result -- end function Role:getHerosCamp(heros) local had = {} for _, id in pairs(heros or {}) do local hero = self.heros[id] if hero then local camp = csvdb["unitCsv"][hero:getProperty("type")].camp had[camp] = (had[camp] or 0) + 1 end end local curCamp = 0 for camp , count in pairs(had) do if count >= 3 then curCamp = camp break end end return curCamp end -- function Role:getRealBattleValue(heros, activeRelation) -- 获取队伍战斗力 羁绊加成 function Role:getRealBattleValue(heros) -- 获取队伍战斗力 羁绊加成 heros = heros or {} -- local activeRelation = activeRelation or self:getHeroActiveRelation(heros) local battleValue = 0 for _, id in pairs(heros) do local hero = self.heros[id] if hero then -- battleValue = battleValue + hero:getBattleValue(activeRelation) battleValue = battleValue + hero:getBattleValue() end end return battleValue end function Role:getAdvHangLimit() return globalCsv.adv_daily_cross_count + self:getFuncLv(FuncOpenType.AdvCount) end function Role:checkAdvCount(need) local oldCount = self:getProperty("advC") local oldTime = self:getProperty("advCT") local newCount = oldCount if oldCount > 0 then local add = math.max(math.floor((skynet.timex() - oldTime) / (globalCsv.adv_daily_regain_min * 60)), 0) newCount = math.max(oldCount - add, 0) end return newCount + need <= self:getAdvHangLimit() end --忽略上限 function Role:changeAdvCount(change) if change == 0 then return end local count = self:getProperty("advC") local ctime = self:getProperty("advCT") if ctime == 0 then ctime = skynet.timex() end local add = math.max(math.floor((skynet.timex() - ctime) / (globalCsv.adv_daily_regain_min * 60)), 0) local nextTime = ctime + add * (globalCsv.adv_daily_regain_min * 60) if count > 0 then count = math.max(count - add, 0) end self:updateProperties({ advC = count + change, advCT = nextTime, }) end function Role:getAdvElLimit() return globalCsv.adv_endless_daily_cross_count + self:getFuncLv(FuncOpenType.AdvCountEL) end -- 走 guide_unlock 表的 被动解锁 function Role:isFuncUnlock(func) if not func then return true end -- 没有就是解锁了 local data = csvdb["guide_unlockCsv"][func] if not data then return true end -- 没有就是解锁了 if self:checkHangPass(data.carbonId) then return true else return false end end -- 走 unlock 表的主动解锁 function Role:isFuncOpen(func) return self:getProperty("funcOpen")[func] == 1 end function Role:getFuncLv(func) return self:getProperty("funcLv")[func] or 1 end -- 参数有level 则是检查是否可以升级 function Role:isArtifactOpen(id, isEndless, level) local isCheckLevel = not not level level = level or 1 local curData = (csvdb["adv_artifactCsv"][id] or {})[level] if not curData then return false end if curData.unlock == 1 then -- 获得解锁 return self:getProperty("advAFOpen")[id] and true or false elseif curData.unlock == 2 then -- 特殊神器 不可解锁 return isCheckLevel elseif curData.unlock == 3 then return isEndless end return true end function Role:funcOpen(func, count, params) params = params or {} count = count or 1 self:logItems(func, 0, count, params.log) if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] or log["cint3"] then print("funcOpen error log have cint1 or cint2 or cint3 ", debug.traceback()) end log["cint1"] = func log["cint2"] = count self:mylog("func_open", log) else print("funcOpen no log ", debug.traceback()) end if csvdb["itemCsv"][func] and csvdb["itemCsv"][func].type == ItemType.FuncOpen then local unlockData = csvdb["unlockCsv"][func] self:log("function_open", {function_id = func}) if unlockData.type == 4 then -- 解锁神器 if self:getProperty("advAFOpen")[unlockData.value1] ~= 1 then self:changeUpdates({{type = "advAFOpen", field = unlockData.value1, value = 1}}) end elseif TypeIsFunc[unlockData.type] then if unlockData.value1 == 0 or unlockData.value1 == 1 then if self:getProperty("funcOpen")[unlockData.type] ~= 1 then self:changeUpdates({{type = "funcOpen", field = unlockData.type, value = 1}}) end else local oldV = self:getFuncLv(unlockData.type) local newLv = math.min(oldV + count, unlockData.value2) if oldV ~= newLv then self:changeUpdates({{type = "funcLv", field = unlockData.type, value = newLv}}) end end else if self:getProperty("funcOpen")[func] ~= 1 then self:changeUpdates({{type = "funcOpen", field = func, value = 1}}) end end end end function Role:advChapterIsOpen(chapterId) local chapterData = csvdb["adv_chapterCsv"][chapterId] if chapterData.prepose ~= 0 and not self:checkHangPass(chapterData.prepose) then return false end return true end function Role:advEventOpenStatus() local openStatus = {} for func , data in pairs(csvdb["unlockCsv"]) do if data.type == 5 then openStatus[data.value1] = openStatus[data.value1] or {} openStatus[data.value1][data.value2] = self:isFuncOpen(func) end end return openStatus end -- 赛季检查 function Role:advEndlessSeasonCheck(notNotify) -- 重置一下冒险 local nowSeason = tonum(redisproxy:hget("adv_season", "idx")) if self:getProperty("advElS") ~= nowSeason then -- 胡博文让注释掉 衰减 从0开始 -- local ml = self:getProperty("advElM") -- local nl = math.max(0, ml - (math.floor(ml / 50) + 2) * 10) -- self:setProperty("advElM", math.floor(nl / 10) * 10) -- 正在无尽冒险清掉 local adv = self:getAdvData() if adv:isRunning() and adv:isEndless() then adv:forceOver() end -- 路过的中继层重置掉 local advRelay = self:getProperty("advRelay") advRelay[-1] = nil -- 清掉冒险手册 self:updateProperties({ advEAchiev = {}, advElM = 0, advElS = nowSeason, advRelay = advRelay, }, notNotify) -- 重新设定冒险章节和冒险结束时间 self.advElChapter = tonum(redisproxy:hget("adv_season", "chapter"), globalCsv.adv_endless_default_chapter) self.advOverTime = tonum(redisproxy:hget("adv_season", "overTime")) if not notNotify then SendPacket(actionCodes.Role_updateProperties, MsgPack.pack({ advElChapter = self.advElChapter, advOverTime = self.advOverTime, })) end end end -- 结算上期海港贸易季 function Role:checkSeaportTrade() local openTime0 = tonum(redisproxy:hget("autoincrement_set", "seaportTime0") or 0) local openTime1 = tonum(redisproxy:hget("autoincrement_set", "seaportTime1") or 0) local openTime2 = tonum(redisproxy:hget("autoincrement_set", "seaportTime2") or 0) local seaport = self:getProperty("seaport") or {} local oldTime = seaport.time or 0 local update = false local function getReward(reset) -- 全服捐赠奖励 local donate = seaport.donate or {} if not reset and (not donate[1] or not donate[2]) then local result = self:getSeaportServerProgress() for idx, set in ipairs(csvdb["seaport_purchaseCsv"]) do local done = true for id, data in ipairs(set) do if donate[id] or not result[idx] or not result[idx][id] or result[idx][id] < data.need_num then done = false break end end if done then update = true redisproxy:insertEmail({ roleId = self:getProperty("id"), emailId = idx == 1 and 361 or 362, attachments = set[1].phase_award, }) -- self:award(set[1].phase_award, {log = {desc = "seaportReward", int1 = set[1].phase, int2 = set[1].id}}) donate[idx] = 1 end end seaport.donate = donate end -- 委托任务的奖励 local collect = seaport.collect or {} if next(collect) then local function getHeroCoef(hero, condition) -- 基础概率 local rareMap = {[HeroQuality.N] = 10, [HeroQuality.R] = 10, [HeroQuality.SR] = 15, [HeroQuality.SSR] = 20} local rare = hero:getRare() local result = 0 for _, it in ipairs(condition:toTableArray(true)) do local type = it[1] local value = it[2] local add = it[3] if type == 1 then -- 种族加成 if hero:getCamp() == value then result = result + add end elseif type == 2 then -- 定位加成 if hero:getPosition() == value then result = result + add end end end return result + (rareMap[rare] or 0) end local carbonCsv = csvdb["idle_battleCsv"] local expData = self:getProperty("hangInfo").expData or {} local taskCsv = csvdb["seaport_taskCsv"] local endTime = openTime0 + 86400 * 2 local reward = {} for slot, set in pairs(taskCsv) do if collect[slot] then update = true local level = collect[slot].level local data = set[level] local teams = collect[slot].team local time = collect[slot].time if time + data.time <= endTime then --if not carbonCsv[expCarbonId] then break end local totalCoef = 0 for _, heroId in ipairs(teams:toArray(true,"=")) do local hero = self.heros[heroId] if hero then totalCoef = totalCoef + getHeroCoef(hero, data.success) hero:addHeroFaith(data.trust) end end local bigSuccess = false local result = math.randomInt(0, 100) if result < totalCoef then bigSuccess = true end local money = math.ceil((expData.money or 0) / 5 * data.time * data.money_clear) local exp = math.ceil((expData.exp or 0) / 5 * data.time * data.exp_clear) local itemReward = data.item_clear_special:toNumMap() itemReward[ItemId.Gold] = (itemReward[ItemId.Gold] or 0) + money itemReward[ItemId.Exp] = (itemReward[ItemId.Exp] or 0) + exp if bigSuccess then for key, value in pairs(itemReward) do itemReward[key] = math.ceil(1.5 * value) end end for itemId, value in pairs(itemReward) do reward[itemId] = (reward[itemId] or 0) + value end -- self:award(itemReward, {log = {desc = "seaportTask", int1 = slot, int2 = level}}) end end end if next(reward) then local rewardStr = "" for itemId, value in pairs(reward) do if rewardStr ~= "" then rewardStr = rewardStr .. " " end rewardStr = rewardStr .. string.format("%s=%s",itemId,value) end redisproxy:insertEmail({ roleId = self:getProperty("id"), emailId = 363, attachments = rewardStr, }) end end seaport.collect = {} if update or reset then if reset then seaport = { time = openTime0, shop = {}, collect = {}, donate = {} } end self:updateProperty({field = "seaport", value = seaport}) end end if oldTime == openTime0 then if openTime1 == 1 or openTime2 == 1 then return end getReward() else getReward(true) end end -- 检查回归者 function Role:checkReturner() local returner = self:getProperty("returner") or {} if next(returner) then return end local now = specTime({hour = 4}) returner.time = now self:updateProperty({field = "returner", value = returner}) end function Role:getSeaportServerProgress() local result = {} local dataCsv = csvdb["seaport_purchaseCsv"] local rediskey = {SEAPORT_TRADE_TASK_1,SEAPORT_TRADE_TASK_2} for idx, set in ipairs(dataCsv) do local temp = {} temp = redisproxy:pipelining(function (red) for id, data in ipairs(set) do red:hget(rediskey[idx], id) end end) result[idx] = {} for i,v in pairs(temp) do if v then result[idx][i] = tonumber(v) end end end return result end -- 获得激活的冒险效果 function Role:getAdvActiveSupportEffect() local effect = {} local advEAchiev = self:getProperty("advEAchiev") for id, status in pairs(advEAchiev[self.advElChapter] or {}) do if status == -1 then local achvData = csvdb["adv_achievementCsv"][id] if achvData and achvData.support ~= 0 then effect[achvData.support] = 1 end end end return effect end --获取冒险支援效果免费刷新次数 function Role:getAdvSupportFreeCount() local count = 1 --默认每天有1次 local openEffects = self:getAdvActiveSupportEffect() for aId, _ in pairs(openEffects) do local curData = csvdb["adv_supportCsv"][aId] if curData.type == 2 then for _, effect in ipairs(curData.effect:toArray()) do local cur = effect:toArray(true, "=") if cur[1] == 8 then count = count + cur[2] end end end end return count end -- 冒险随机新的支援效果 function Role:advRandomSupportEffect(notNotify) local pool = {} local openEffects = self:getAdvActiveSupportEffect() for id, data in pairs(csvdb["adv_supportCsv"]) do if data.type == 0 then if openEffects[id] then table.insert(pool, data) end elseif data.type == 1 then table.insert(pool, data) end end local advSup = {} for i = 1, math.min(3, #pool) do local idx = math.randWeight(pool, "showup") table.insert(advSup, pool[idx].id) table.remove(pool, idx) end self:updateProperty({field = "advSup", value = advSup, notNotify = notNotify}) end function Role:getCurDinerRankKey() local round = self:getTimeResetRound(TimeReset.DinerRank) local idx = 1 if round % 2 == 1 then idx = 2 end return RANK_DINER[idx] end local StdTowerRankTime = toUnixtime("2019010100") local TowerRankInfo = { [1] = {rank = RANK_TOWER, rankInfo = RANK_TOWER_INFO}, [2] = {rank = RANK_TOWER1, rankInfo = RANK_TOWER1_INFO}, [3] = {rank = RANK_TOWER2, rankInfo = RANK_TOWER2_INFO}, [4] = {rank = RANK_TOWER3, rankInfo = RANK_TOWER3_INFO}, } function Role:setTowerRank(level,tType) tType = tType or 1 local now = skynet.timex() local ct = math.ceil((now - StdTowerRankTime) / 86400) --按天计算 365 * 27 < 10000 可以维持 27 年 local ct = 10000 - ct -- 越早的排名越靠前 local info = TowerRankInfo[tType] local towerTeam = self:getTowerTeamFormat(tostring(tType)) local battleV = self:getTeamBattleValue(towerTeam.heros) local score = (level * 10000 + ct) * 10000000 + battleV local curInfo = { name = self:getProperty("name"), headId = self:getProperty("headId"), lv = self:getProperty("level"), batteV = battleV, level = level, format = self:getTeamHerosInfo(towerTeam).heros, } local roleId = self:getProperty("id") redisproxy:pipelining(function (red) red:zadd(info.rank, score, roleId) --更新分数 red:hset(info.rankInfo, roleId, MsgPack.pack(curInfo)) end) end function Role:getTowerRank(tType) tType = tType or 1 local info = TowerRankInfo[tType] local list = {} local ids = redisproxy:zrevrange(info.rank, 0 , 99) local redret = {} if ids and next(ids) then redret = redisproxy:pipelining(function (red) for i = 1, #ids do local roleId = ids[i] table.insert(list, {roleId = tonumber(roleId)}) red:hget(info.rankInfo, roleId) end end) end for i = 1, #redret do local player = MsgPack.unpack(redret[i]) player.format = nil list[i].player = player end local rank = redisproxy:ZREVRANK(info.rank, self:getProperty("id")) if not rank then rank = -1 else rank = rank + 1 end return {list = list, rank = rank} end function Role:getTowerRankOneInfo(roleId,tType) tType = tType or 1 local info = TowerRankInfo[tType] local data = redisproxy:hget(info.rankInfo, roleId) if data then local player = MsgPack.unpack(data) return player.format end end function Role:addAdvLvExp(exp) local advL = self:getProperty("advL") local level = advL[1] local oldLevel = level local newExp = (advL[2] or 0) + exp if not csvdb["adv_level_fundCsv"][level + 1] then return end while newExp >= csvdb["adv_level_fundCsv"][level].exp do --if csvdb["adv_level_fundCsv"][level + 1] and self:advChapterIsOpen(100 + csvdb["adv_level_fundCsv"][level + 1].chapter) then -- 有下一级 if csvdb["adv_level_fundCsv"][level + 1] then -- 有下一级 newExp = newExp - csvdb["adv_level_fundCsv"][level].exp level = level + 1 else newExp = csvdb["adv_level_fundCsv"][level].exp - 1 -- 没有下一级了 经验溢出太多 扣除 end end if level > advL[1] then self:checkTaskEnter("AdvLevel", {level = level}) end advL[1] = level advL[2] = newExp self:updateProperty({field = "advL", value = advL}) return oldLevel, level end function Role:getAdvWheelSurfLv(ptype) local level = 1 for i = 0, self:getProperty("advL")[1] do local effects = csvdb["adv_level_fundCsv"][i].effect:toArray() for _, one in ipairs(effects) do local effect = one:toArray(true, "=") if effect[1] == 2 and ptype == effect[2] then level = effect[3] end end end return level end function Role:fixAdvScoreChange(score) local change = 0 for i = 0, self:getProperty("advL")[1] do local effects = csvdb["adv_level_fundCsv"][i].effect:toArray() for _, one in ipairs(effects) do local effect = one:toArray(true, "=") if effect[1] == 3 then change = change + effect[2] end end end return math.floor(score * (1 + change / 100)) end function Role:getAdvLvAddAttrs() -- 1=冒险队属性;1=点数/百分比=属性枚举=参数;属性枚举(1=生命上限/2=魔法上限/3=攻击/4=防御);点数/百分比(0=点数/1=百分比) local attrs = {} for i = 0, self:getProperty("advL")[1] do local effects = csvdb["adv_level_fundCsv"][i].effect:toArray() for _, one in ipairs(effects) do local effect = one:toArray(true, "=") if effect[1] == 1 then attrs[effect[2]] = (attrs[effect[2]] or 0) + effect[3] end end end return attrs end function Role:getTeamBattleInfo(team) local teamInfo = {heros = {}, supports = {}} -- local activeRelation = self:getHeroActiveRelation(team.heros) for slot, id in pairs(team.heros or {}) do local info = {} local hero = self.heros[id] if not hero then print("error heroid " .. id) end -- local attrs = hero:getTotalAttrs({activeRelation = activeRelation}) local attrs = hero:getTotalAttrs() for k, v in pairs(AttsEnumEx) do info[v] = (attrs[v] or 0) end info.type = hero:getProperty("type") info.level = hero:getProperty("level") info.wakeL = hero:getProperty("wakeL") info.blockLevel = hero:getSkillLevel(4) info.specialLevel = hero:getSkillLevel(1) info.passiveLevel = hero:getSkillLevel(3) info.runeSkill = hero:getRuneSkill(102) info.talentSkills = hero:getTalentSkill() teamInfo.heros[slot] = info end for slot, id in pairs(team.supports or {}) do teamInfo.supports[slot] = {id, self.dinerData:getProperty("dishTree"):getv(id, 0)} end teamInfo.tactics = globalCsv.tactics_skill_passive_cell[team.tactics] and team.tactics or nil return teamInfo end function Role:getTeamHerosInfo(team) local format = {} local heros = {} for slot, heroId in pairs(team.heros or {}) do local hero = self.heros[heroId] heros[slot] = { type = hero:getProperty("type"), level = hero:getProperty("level"), wakeL = hero:getProperty("wakeL"), } end format.heros = heros format.supports = team.supports or {} format.tactics = team.tactics or nil return format end function Role:getTeamBattleValue(heros) -- local battleV = 0 -- for _, heroId in pairs(heros or {}) do -- local hero = self.heros[heroId] -- battleV = battleV + hero:getProperty("battleV") -- end -- return battleV return self:getRealBattleValue(heros) end function Role:updateHangTeamInfo() local team = self:getTeamFormatByType(TeamSystemType.Hang) if not team then return end self:setProperties({ hangTS = self:getTeamHerosInfo(team), hangTB = self:getTeamBattleInfo(team), hangTBV = self:getTeamBattleValue(team.heros), }) end -- 设置pve阵容 function Role:getTeamFormat(index) local teams = self:getProperty("hangTeams") or {} local team = teams[index] or {} return team end function Role:getTeamFormatByType(type) local teamIndex = self:getProperty("teamIndex") or {} local index = teamIndex[type] if not index then return {} end return self:getTeamFormat(index) end function Role:setTeamFormat(index, team) local teams = self:getProperty("hangTeams") or {} teams[index] = team self:updateProperty({field = "hangTeams", value = teams, notNotify = false}) end -- 设置拾荒编队阵容 function Role:getAdvTeamFormat(index) local teams = self:getProperty("advTeams") or {} local team = teams[index] or {} return team end function Role:setAdvTeamFormat(index, team) local teams = self:getProperty("advTeams") or {} teams[index] = team self:updateProperty({field = "advTeams", value = teams, notNotify = false}) end function Role:savePvpCTeam(team) if not team then team = self:getProperty("pvpTC") else self:updateProperty({field = "pvpTC", value = team}) end self:setProperties({ pvpTSC = self:getTeamHerosInfo(team), pvpTBC = self:getTeamBattleInfo(team), pvpTBVC = self:getTeamBattleValue(team.heros), }) end function Role:savePvpHTeam(team) if not team then team = self:getProperty("pvpTH") else self:updateProperty({field = "pvpTH", value = team}) end local pvpTSH, pvpTBH, pvpTBVH = {}, {}, {} for i = 1, 3 do if team[i] then pvpTSH[i] = self:getTeamHerosInfo(team[i]) pvpTBH[i] = self:getTeamBattleInfo(team[i]) pvpTBVH[i] = self:getTeamBattleValue(team[i].heros) end end self:setProperties({ pvpTSH = pvpTSH, pvpTBH = pvpTBH, pvpTBVH = pvpTBVH, }) end -- 设置电波塔阵容 function Role:getTowerTeamFormat(teamIdx) local teams = self:getProperty("towerTeams") or {} local team = teams[tostring(teamIdx)] or {} return team end function Role:setTowerTeamFormat(teamIdx, team) local teams = self:getProperty("towerTeams") or {} teams[tostring(teamIdx)] = team self:updateProperty({field = "towerTeams", value = teams, notNotify = false}) end -- update function Role:onRecoverTimer(now) self:updateTimeReset(now, true) self:checkNewEvent(now) self:saveRoleData() end function Role:saveRoleData() self:update() local objs = {self.activity, self.dailyData, self.dinerData, self.storeData, self.roleIncre} for _, info in ipairs(objs) do info:update() end local tbObjs = {self.friends, self.heros, self.runeBag, self.sparkBag} for _, tbObj in ipairs(tbObjs) do for _, info in pairs(tbObj) do info:update() end end end local function breath(sec, name) local last_breath = 0 return function (now, role) if name == "email" and role.sendMailFlag then last_breath = now + sec role.sendMailFlag = false return true end if now >= last_breath then last_breath = now + sec return true end return false end end local breathes = { ["email"] = breath(120, "email"), -- email ["pvphg"] = breath(300, "pvphg"), -- 高级竞技场 奖励满的红点 } function Role:checkNewEvent(now) if now - self:getProperty("ltime") < 5 then return end local checks = {} -- 检查全局邮件 -- 增加邮件红点 checks["email"] = function() local mid = self:getProperty("sid") local result = redisproxy:hmget("autoincrement_set", "email", "emailTimestamp") local globalEmail = tonum(result[1]) local timestamp = tonum(result[2]) local emailSync = self:getProperty("emailSync") if globalEmail > emailSync and timestamp > self:getProperty("ctime") then local emailSync = math.max(emailSync + 1, globalEmail - EMAIL_LIMIT + 1) local redret = redisproxy:pipelining(function (red) for id = emailSync, globalEmail do red:hgetall(string.format("globalEmail:%s", id)) end end) for _, data in ipairs(redret) do local email = tarr2tab(data) -- 0 需要判斷創角時間小於郵件創建時間 1 只需要在時間段內登陸即可領取 local delayType = tonum(email.delayType) local flag = false if delayType == 1 then flag = skynet.timex() > tonum(email.createtime) else flag = tonum(email.createtime) > self:getProperty("ctime") end if flag and ( not email.mid or tonum(email.mid) == mid ) and ( not email.endtime or tonum(email.endtime) > now )then return true end end end local roleId = self:getProperty("id") local res = mysqlproxy:query(string.format("SELECT `id` FROM `Email` WHERE `roleId` = %d AND `status` = 0;", roleId)) self.SendMailFlag = false return next(res) end checks["pvphg"] = function() if not self:isTimeResetOpen(TimeReset.PvpHight) then return end local pvpHGTime = self:getProperty("pvpHGTime") if pvpHGTime == 0 then return end local division = self:getPvpHDivision() local divisionData = csvdb["pvp_group_divisionCsv"][division] local newTime, newReward = self:calculatePvpHGift(division) if table.pack(next(newReward))[2] >= divisionData.limit then return true end end local events = {} for name, breath in pairs(breathes) do if breath(now, self) and checks[name] then local status = checks[name]() if status then if status == true then events[name] = 1 else events[name] = status end end end end if next(events) then SendPacket(actionCodes.Role_notifyNewEvent, MsgPack.pack({events = events})) end end function Role:checkHangPass(carbonId) local hangPass = self:getProperty("hangPass") local diff = math.floor(carbonId / 10000) return (hangPass[diff] or 0) >= carbonId end function Role:hangFinish(carbonId) local hangPass = self:getProperty("hangPass") local diff = math.floor(carbonId / 10000) if (hangPass[diff] or 0) < carbonId then hangPass[diff] = carbonId self:updateProperty({field = "hangPass", value = hangPass}) end end function Role:getAdvRankKey() local round = self:getProperty("advElS") local idx = 1 if round % 2 == 1 then idx = 2 end return RANK_ADV[idx] end -- 消除指定tag 红点 function Role:clearRedPTag(tag) local redp = self:getProperty("redp") redp[tag] = nil self:updateProperty({field = "redp", value = redp}) end -- 网页支付获取订单号 function Role:getPurchaseOrderByPlatform(params) local checkPlatform = { ["mycard"] = "mycard_product_id", } local pidField = checkPlatform[params.payMode or ""] if not pidField or not params.product_id or params.product_id == "" then return "no product" end for k , v in pairs(csvdb["shop_rechargeCsv"]) do if not v[pidField] then return "no product" end if v[pidField] == params.product_id then if v.twd * 100 ~= tonumber(params.money) then return "error money" end -- 发现需要的id local partnerOrderId = self:getPurchaseOrder(k, params.transactionId, params.choose) if partnerOrderId == "" then return "no product" end return json.encode({order = partnerOrderId}) end end end -- 获取充值订单号 function Role:getPurchaseOrder(rechargeId, transactionId, choose) local roleId = self:getProperty("id") local rechargeData = csvdb["shop_rechargeCsv"][rechargeId] if not rechargeData then skynet.error("recharge id not exist", rechargeId) return "" end local limit = rechargeData.limit local rechargeRecord = self.storeData:getProperty("payR") or {} if limit ~= 0 and limit <= (rechargeRecord[rechargeId] or 0) then return "" end -- 检查礼包自选奖励合法 if choose and choose ~= "" then if rechargeData.itemgift == "" then return "" end local slot = rechargeData.itemdirect or 0 local set = choose:toTableArray(true) if slot ~= #set then return "" end local pass = {} local groups = rechargeData.itemgift:toTableArray(true) for idx, item in ipairs(set) do for _, group in ipairs(groups) do if group[2] == item[1] and group[3] == item[2] and idx == group[1] then pass[group[1]] = 1 break end end end if #pass ~= slot then return "" end end --判断是否是活动商品 if rechargeData.activity_id ~= 0 then local actCfg = csvdb["activity_ctrlCsv"][rechargeData.activity_id] if not actCfg then return "" end if not self.activity:isOpenById(rechargeData.activity_id, "ActShopGoods") then return "" end end local orderId = redisproxy:hget(string.format(R_ORDERS, roleId), rechargeId) if orderId then local uid = orderId * MAX_SVR_ID + serverId local orderObject = require("models.Order").new({ key = string.format("%d", uid), id = uid }) if orderObject:load() and orderObject:getProperty("rechargeId") == rechargeId and math.abs(skynet.timex() - orderObject:getProperty("createTime")) < 5 * 60 then return string.format("%d", uid) end end orderId = redisproxy:hincrby("autoincrement_set", "order", 1) local uid = orderId * MAX_SVR_ID + serverId local partnerOrderId = string.format("%d", orderId * MAX_SVR_ID + serverId) local orderKey = string.format(R_ORDER, roleId, orderId) redisproxy:del(orderKey) -- 删掉可能有了 local order = require("models.Order").new({ key = partnerOrderId, id = tonum(partnerOrderId), rechargeId = rechargeId, createTime = skynet.timex(), transactionId = transactionId, roleid = roleId, sid = self:getProperty("sid"), choose = choose or "", }) order:create() -- 正在进行中的订单 缓存 redisproxy:hset(string.format(R_ORDERS, roleId), rechargeId, orderId) return partnerOrderId end -- 更新订单信息 --[[ status success fail finsh unknow --]] function Role:updatePurchaseOrder(partnerOrderStr, platformOrder, status) if not partnerOrderStr then return false end local roleId = self:getProperty("id") local orderObject = require("models.Order").new({ key = string.format("%d", partnerOrderStr), id = tonum(partnerOrderStr)}) if not orderObject:load() then return false end local rechargeId = orderObject:getProperty("rechargeId") local dataSet = csvdb["shop_rechargeCsv"][rechargeId] local sid = orderObject:getProperty("sid") if roleId ~= orderObject:getProperty("roleid") then skynet.error(string.format("[recharge] with a different role id, current roleId:%d, order role Id:%d, order cpOrder: %s, platformOrder : %s, hadPlatformOrder: %s, id: %s, overTime : %s", roleId, orderObject:getProperty("roleid"), partnerOrderStr, platformOrder, orderObject:getProperty("transactionId"), rechargeId, orderObject:getProperty("finishTime") )) return false, "unknow" end if orderObject:getProperty("finishTime") > 0 then skynet.error(string.format("[recharge] is a finish order cpOrder: %s, platformOrder : %s, hadPlatformOrder: %s, id: %s, overTime : %s", partnerOrderStr, platformOrder, orderObject:getProperty("transactionId"), rechargeId, orderObject:getProperty("finishTime") )) return false, "finsh" end if platformOrder then orderObject:setProperty("transactionId", platformOrder) end orderObject:setProperty("status", status) -- 开始下单 if status == "success" then elseif status == "fail" then -- redisproxy:hdel(string.format(R_ORDERS, roleId), rechargeId) elseif status == "finsh" then orderObject:setProperty("finishTime", skynet.time()) redisproxy:hdel(string.format(R_ORDERS, roleId), rechargeId) end orderObject:update() if status ~= "unknow" then self:log("setOrder", { order_status = ({success = 100, finsh = 200, fail = 300})[status] or 1000, -- "订单状态:100 - 开始下单(玩家还未开始付费行为记录)200 - 支付完成并发货(SDK通知可以发货时记录),300 - 订单被取消,1000 - 其他" item_id = rechargeId, -- 道具id item_type = dataSet.type, -- 购买的道具类型,具体见"onItems"方法中道具类型枚举表 item_name = dataSet.title, -- 购买的道具名 item_number = 1, -- 购买的道具数量 item_level = 1, -- 购买的道具等级 order_cost = dataSet.rmb * 100, -- 此次消费的现金金额(单位:分),如 51800即未518元,对应客户端SDK传入的'total_fee' order_currency = "CNY", -- 货币类型,默认为"CNY"(人民币),遵循ISO 4217规范 order_type = self:getProperty("rmbC") > 0 and 0 or 1, -- 订单类型,首充记录为1,否则为0 order_id = platformOrder, -- 本条记录的订单号,对应客户端SDK返回的'bs_trade_no' }) end return true, rechargeId, sid, orderObject:getProperty("choose") end -- 充值 -- --[[ request.order = data.out_trade_no request.amount = data.money request.game_money = data.game_money request.product_id = data.product_id request.pay_time = data.pay_time request.transactionId = data.order_no request.extension_info = data.extension_info request.is_mycard = 1 ]] function Role:handlePurchase(params) local roleId = self:getProperty("id") local partnerOrderStr = params.order local status, back, sid, choose = self:updatePurchaseOrder(partnerOrderStr, params.transactionId, "finsh") if not status then if back == "finsh" then -- 订单已经处理 SendPacket(actionCodes.Store_ayncPurchaseRpc, MsgPack.pack({ result = "handled" })) end return end local rechargeId = back local rechargeData = csvdb["shop_rechargeCsv"][rechargeId] if (params.is_mycard and rechargeData.twd * 100 ~= tonumber(params.amount)) or (not params.is_mycard and rechargeData.rmb * 100 ~= tonumber(params.amount)) then skynet.error(string.format("[recharge] fake order: %s, roleId: %d, order: %s, rmb %s, get %s", params.transactionId, roleId, partnerOrderStr, rechargeData.rmb, params.amount )) return end local status, reward = self:recharge({ id = rechargeId, transactionId = params.transactionId, pay_time = params.pay_time, order = partnerOrderStr, sid = sid, choose = choose, }) if not status then if params.extension_info == "mycard_web" then self:sendMail(MailId.MyCardBuy, nil, nil, {rechargeId}) end SendPacket(actionCodes.Store_ayncPurchaseRpc, MsgPack.pack({ order = partnerOrderStr, result = "success", reward = reward})) end return rechargeId end function Role:recharge(params) local id = tonumber(params.id) local rechargeData = csvdb["shop_rechargeCsv"][id] if not rechargeData then skynet.error("[recharge] recharge id not exist", id) return 1 end if not self.storeData:checkRechargeRecord(rechargeData.limit, id) then return 2 end local diamondCount = 0 local reward = {} if rechargeData.shop == 1 then -- 钻石 local rechargeF = self:getProperty("rechargeF") diamondCount = rechargeData.diamond + rechargeData.diamondExtra if not rechargeF[id] then diamondCount = diamondCount + rechargeData.diamondFirst rechargeF[id] = 1 self:updateProperty({field = "rechargeF", value = rechargeF}) end self:gainDiamond({count = diamondCount, isRecharge = true, sid = params.sid, log = {desc = "recharge", int1 = id}}) elseif rechargeData.shop == 2 then --通行证商店 reward, _ = self:award(rechargeData.itemFirst, {isRecharge = true, log = {desc = "recharge", int1 = id}}) self.storeData:onBuyCard(rechargeData.type, rechargeData.time, rechargeData.id, rechargeData.activity_id) elseif rechargeData.shop == 3 then -- 礼包商店 reward, _ = self:award(rechargeData.itemFirst, {isRecharge = true, log = {desc = "recharge", int1 = id}}) else skynet.error("[recharge] invalid recharge shop type " .. id) return 3 end -- 自选奖励部分 if params.choose and params.choose ~= "" then local tReward, tChange = self:award(params.choose, {log = {desc = "recharge", int1 = id}}) for itemId, value in pairs(tReward) do reward[itemId] = (reward[itemId] or 0) + value end for itemId, value in pairs(tChange or {}) do reward[itemId] = (reward[itemId] or 0) + value end end if diamondCount > 0 then reward[ItemId.Diamond] = (reward[ItemId.Diamond] or 0) + diamondCount end self:checkTaskEnter("Pay", {rmb = rechargeData.rmb, twd = rechargeData.twd}) -- 累充 local rmb = rechargeData.rmb self:updateProperty({field = "rmbC", delta = rmb}) self:updateProperty({field = "twdC", delta = rechargeData.twd}) self:mylog("role_action", {desc = "recharge", int1 = id, int2 = rmb, key1 = params.transactionId, key2 = params.order, long1 = tonum(params.pay_time, 0)}) return nil, reward end --直接给玩家发送邮件,立即推送小红点 function Role:sendMail(mailId, createTime, reward, contentPms) local tgift = {} if type(reward) == "string" then for _, one in pairs(reward:toTableArray(true)) do tgift[one[1]] = (tgift[one[1]] or 0) + one[2] end else tgift = reward or {} end local gift = "" for k, v in pairs(tgift) do gift = gift .. k.."="..v.." " end mysqlproxy:insertEmail({roleId = self:getProperty("id"), emailId = mailId, createtime = createTime, attachments = gift, contentPms = contentPms}) self.sendMailFlag = true end -- 是否需要进行引导 function Role:checkOverGuide(guideId,slave) local funcGuide = self:getProperty("funcGuide") if funcGuide:getv(guideId * 1000 + (slave or 0), 0) > 0 then return true end return false end -- 保存引导步骤 function Role:saveGuide(master,slave,force) local newerGuide = self:getProperty("newerGuide") local guide = newerGuide:toArray(true,"=") local sMaster, sSlave = guide[1], guide[2] if not force and master < sMaster then return end if not force and master <= sMaster and slave < sSlave then return end local funcGuide = self:getProperty("funcGuide") funcGuide = funcGuide:setv(master * 1000 + slave, 1) if funcGuide:getv(master * 1000,0) == 0 then funcGuide = funcGuide:setv(master * 1000, 1) end self:updateProperty({field = "funcGuide", value = funcGuide}) self:log("onGuidePoint", {guild_type = 0, guild_id = master, guild_point = slave, guild_pass = 0}) self:mylog("guide", {desc = "guide_new",int1 = master*1000+slave}) newerGuide = string.format("%d=%d",master,slave) self:updateProperty({field = "newerGuide", value = newerGuide}) end -- 引导大步骤结束 function Role:finishGuide(master) local newerGuide = self:getProperty("newerGuide") local guide = newerGuide:toArray(true,"=") if guide[1] > master then return end local guideCsv = csvdb["guide_mainCsv"] local lastStep = guideCsv[master][#guideCsv[master]] if guideCsv[master + 1] then self:updateProperty({field = "newerGuide", value = string.format("%d=%d",master + 1,1)}) else self:updateProperty({field = "newerGuide", value = "9999=1"}) end end -- 抽卡阶段奖励 function Role:getDrawCardExtraReward(feedbackId, oldVal, newVal) local reward = nil local maxCount = 0 for k, v in pairs(csvdb["build_extraRewardCsv"][feedbackId]) do if oldVal < k and newVal >= k then reward = v["reward"] or "" end maxCount = k > maxCount and k or maxCount end return reward, (newVal >= maxCount and newVal - maxCount or newVal) end -- 获取下一个挂机关卡id function Role:getNextCarbonId(curId) local diff = math.floor(curId / 10000) local chapterId = math.floor((curId / 100) % 100) local subId = curId % 100 local nextId = curId + 1 local function makeCarbonId(diff, chapterId, subId) return diff * 10000 + chapterId * 100 + subId end if not csvdb["idle_battleCsv"][nextId] then nextId = makeCarbonId(diff, chapterId + 1, 1) if not csvdb["idle_battleCsv"][nextId] then nextId = makeCarbonId(diff + 1, 1, 1) if not csvdb["idle_battleCsv"][nextId] then nextId = 0 end end end return nextId end -- 根据累计充值金额计算奖励档位 function Role:getPaybackReward(oldVal, newVal) local maxVal, diff, extraReward = 0, 0, "" local gift = "" local checkPoint = {} for k, v in pairs(csvdb["rebateCsv"]) do if k > maxVal then maxVal = k end if v.isLoop > diff then diff = v.isLoop extraReward = v.reward end if oldVal < k and newVal > k then gift = gift .. v.reward .. " " table.insert(checkPoint, k) end end if newVal > maxVal then local cnt = 0 local oldCheckPoint = 0 if oldVal < maxVal then cnt = math.floor((newVal - maxVal) / diff) oldCheckPoint = maxVal else cnt = math.floor((newVal - maxVal) / diff) - math.floor((oldVal - maxVal) / diff) oldCheckPoint = maxVal + math.floor((oldVal - maxVal) / diff) * diff end for i = 1, cnt do gift = gift .. extraReward .. " " table.insert(checkPoint, oldCheckPoint + i * diff) end end table.sort(checkPoint, function(a, b) return a < b end) return gift, checkPoint end --[[ "hang" : "挂机资源满", "box" : "箱子拆解完毕", "food" : "食物出售完毕", "adv" : "代理拾荒完毕", --]] function Role:pushMsg(params) if not self._pushToken or self._pushToken == "" then return end if params.time <= 0 then self:pushCancel(params) return end local content = string.format("push:%d:%s:%s:%s", self:getProperty("id"), params.type, params.slot or 1, self._pushToken) notifyClient({content = content, time = math.floor(params.time)}) end function Role:pushCancel(params) if not self._pushToken or self._pushToken == "" then return end local content = string.format("push:%d:%s:%s:%s", self:getProperty("id"), params.type, params.slot or 1, self._pushToken) deleteNotify({content = content}) end function Role:pushCancelAll(ptype) if not self._pushToken or self._pushToken == "" then return end local pattern = string.format("push:%d:*", self:getProperty("id")) if ptype then pattern = string.format("push:%d:%s:*", self:getProperty("id"), ptype) end deleteNotify({pattern = pattern}) end local CommonRankTime = toUnixtime("2019010100") local CommonCoef1 = 10000 local CommonCoef2 = 10000 function Role:updateRankCommon(rankType, rankVal, reserve) if not rankType then return end reserve = reserve or 0 local now = skynet.timex() local ct = math.ceil((now - CommonRankTime) / 86400) --按天计算 365 * 27 < 10000 可以维持 27 年 ct = 10000 - ct -- 越早的排名越靠前 local score = (rankVal * CommonCoef1 + ct) * CommonCoef2 + reserve local roleId = self:getProperty("id") redisproxy:pipelining(function (red) red:zadd(RANK_COMMON..rankType, score, roleId) --更新分数 end) end function Role:getRankInfoCommon(rankType) if not rankType then return end local list = {} local rankKey = RANK_COMMON .. rankType local ids = redisproxy:zrevrange(rankKey, 0 , 99, "WITHSCORES") for i = 1, #ids, 2 do local roleId = tonumber(ids[i]) local rankVal = tonumber(ids[i + 1]) rankVal = math.floor(math.floor(rankVal / CommonCoef2) / CommonCoef1) table.insert(list, {roleId = roleId, player = rankVal}) end for _, v in ipairs(list) do local _, curInfo = rpcRole(v.roleId, "friendSInfo") curInfo.ltime = nil curInfo.rankVal = v.player v.player = curInfo end local rank = redisproxy:ZREVRANK(rankKey, self:getProperty("id")) if not rank then rank = -1 else rank = rank + 1 end return {list = list, rank = rank} end function Role:addHeroFaith(heroId, exp) local hero = self.heros[heroId] if not hero then return end hero:addHeroFaith(exp) return hero:getProperty("faith") end local function table_keys( t ) local keys = {} for k, _ in pairs( t ) do keys[#keys + 1] = k end return keys end local function makeStr(params, key, urlsign) local keys = table_keys(params) table.sort(keys) local sign2Str, requestStr = "", "" for _, key in ipairs(keys) do sign2Str = sign2Str .. (urlsign and urlencode(params[key]) or params[key]) requestStr = requestStr .. string.format("%s=%s&",key,urlencode(params[key])) end local sign = md5.sumhexa(sign2Str .. key):lower() requestStr = requestStr .. string.format("sign=%s",sign) return requestStr end function Role:biliChatSDK(content) if content == "" then return end local base64Content = base64.encode(content) local uids = self:getProperty("uid"):split2("_") local uid = uids[2] or self:getProperty("uid") local urls = { "http://pnew.biligame.net", "http://pserver.bilibiligame.net" } local secret = "8920e9dcf0cb4ebca87393ce48021ead" local headers = { ["User-Agent"] = 'Mozilla/5.0 GameServer', ["Content-Type"] = "application/x-www-form-urlencoded", } local send = { game_id = 4818, uid = uid, merchant_id = 1, server_id = 3957, version = "1", timestamp = math.floor(skynet.timex() * 1000), content = base64Content, } local params = makeStr(send, secret) httpc.timeout = 100 local status, body = httpc.request("POST", urls[1], "/api/server/censor", {}, headers, params) if tonumber(status) ~= 200 then status, body = httpc.request("POST", urls[2], "/api/server/censor", {}, headers, params) end if tonumber(status) ~= 200 then return end local result = json.decode(body) if not result or result.code ~= 0 then return end return result.data.content end function Role:uoChatSDK(content) if content == "" then return end local base64Content = base64.encode(content) local uids = self:getProperty("uid"):split2("_") local uid = uids[2] or self:getProperty("uid") local urls = { "http://uosdk.biligame.com", } local secret = "4243b5fb44b64175a20a53dcfb1346eb" local headers = { ["User-Agent"] = 'Mozilla/5.0 CP-Game-Server', ["Content-Type"] = "application/x-www-form-urlencoded", } local send = { app_id = 4821, user_id = uid, timestamp = math.floor(skynet.timex() * 1000), content = base64Content, } local params = makeStr(send, secret, true) httpc.timeout = 100 local status, body = httpc.request("POST", urls[1], "/api/server/censor", {}, headers, params) if tonumber(status) ~= 200 then return end local result = json.decode(body) if not result or result.code ~= 0 then return end return result.data.content end function Role:getTowerBnousActive(update) if not update and self.towerBnousActive then return self.towerBnousActive end local towerInfo = self:getProperty("towerInfo") local towerLevel = {towerInfo.l or 1, towerInfo.l1 or 10001, towerInfo.l2 or 20001, towerInfo.l3 or 30001} local towerBnous = self:getProperty("towerBnous") local bnousCsv = csvdb["tower_battle_additionCsv"] self.towerBnousActive = {} for towerIdx, Set in pairs(towerBnous) do for id, _ in pairs(Set) do local data = bnousCsv[towerIdx][id] if data then local effects = data.effect:toTableArraySec() for _, effect in pairs(effects) do local pm1, pm2, pm3, pm4 = tonumber(effect[1]), tonumber(effect[2]), tonumber(effect[3]), tonumber(effect[4]) if not self.towerBnousActive[pm1] then self.towerBnousActive[pm1] = {} end if pm1 == SystemBnousType.TowerBuff then if not self.towerBnousActive[pm1][pm2] then self.towerBnousActive[pm1][pm2] = {} end table.insert(self.towerBnousActive[pm1][pm2],pm3) elseif pm1 == SystemBnousType.Adv then if not self.towerBnousActive[pm1][pm4] then self.towerBnousActive[pm1][pm4] = {} end self.towerBnousActive[pm1][pm4][pm2] = (self.towerBnousActive[pm1][pm4][pm2] or 0) + pm3 elseif pm1 == SystemBnousType.HangTime then if type(self.towerBnousActive[pm1]) == "table" then self.towerBnousActive[pm1] = 0 end self.towerBnousActive[pm1] = self.towerBnousActive[pm1] + pm2 else self.towerBnousActive[pm1][pm2] = (self.towerBnousActive[pm1][pm2] or 0) + pm3 end end end end end return self.towerBnousActive end function Role:getDeltaValue(result, value) if not result then return 0 end local delta = 0 if result[1] and value then delta = math.floor(value * result[1] / 100) end if result[0] then delta = delta + result[0] end return delta end function Role:getBnousBattleBuff() local towerBnous = self:getTowerBnousActive() return towerBnous[SystemBnousType.TowerBuff] end function Role:getBnousCrusade(value) local towerBnous = self:getTowerBnousActive() return self:getDeltaValue(towerBnous[SystemBnousType.CrusadeTask], value) end function Role:getBnousDiner(type, value) local towerBnous = self:getTowerBnousActive() type = type or 1 local result if type == 1 then result = towerBnous[SystemBnousType.DinerGet] elseif type == 2 then result = towerBnous[SystemBnousType.DinerLimit] elseif type == 3 then result = towerBnous[SystemBnousType.DinerSell] elseif type == 4 then result = towerBnous[SystemBnousType.DinerPrice] end return self:getDeltaValue(result, value) end function Role:getBnousAdv() local towerBnous = self:getTowerBnousActive() return towerBnous[SystemBnousType.Adv] or {} end function Role:getBnousHangTime() local towerBnous = self:getTowerBnousActive() return towerBnous[SystemBnousType.HangTime] or 0 end function Role:getBnousPvpTicket() local towerBnous = self:getTowerBnousActive() return towerBnous[SystemBnousType.PvpTicket] or {} end function Role:getBnousSweep() local towerBnous = self:getTowerBnousActive() return towerBnous[SystemBnousType.SweepReward] or {} end end return RolePlugin