-- 跨服商业活动-巅峰战场(跨服) local Msg = require("core.Msg") local Timer = require("core.Timer") local DB = require("common.DB") local CommonDB = require("common.CommonDB") local CommonDefine = require("common.CommonDefine") local Log = require("common.Log") local LuaMongo = _G.lua_mongo local Util = require("common.Util") local Grid = require("bag.Grid") local MiddleConnect = require("middle.MiddleConnect") local InnerMsg = require("core.InnerMsg") local MiddleManager = require("middle.MiddleManager") local NpcConfig = require("excel.jjc").skyladdernpc local CreateRole = require("role.CreateRole") local ServerCommerceActDefine = require("serverCommerce.ServerCommerceActDefine") local CombatDefine = require("combat.CombatDefine") local dbUpdate = {_id=nil} local dbUpdateField = {} local RANK_SHOW_NUM = 50 -- 排行榜显示的数量 local repeateServerIdList = {} local battleGroundData = { -- allAreaRankList = { -- 各个战区排行榜, 榜上的都是真实玩家 -- [WarZoneServerIdx] = { -- [rank] = { -- rank = rank, -- serverId = serverId, -- playerUuid = playerUuid, -- name = name, -- bodyId = bodyId, -- headId = headId, -- headFrameId = headFrameId, -- heroArr = {heroId1, heroId2}, -- }, -- }, -- }, -- generaRankList = { -- 通用排行榜(榜上都是机器人),各个战区排行榜上没有真实玩家或对应排名没有真实玩家时, 使用该排行榜 -- [rank] = { -- rank = rank, -- serverId = serverId, -- playerUuid = playerUuid, -- name = name, -- bodyId = bodyId, -- headId = headId, -- headFrameId = headFrameId, -- monsterOutID = monsterOutID, -- 机器人才有 -- heroArr = {heroId1, heroId2}, -- }, -- }, -- }, -- joinList = { -- 参加过该活动的玩家列表 -- -- {serverId, playerUuid}, -- -- {serverId2, playerUuid2}, -- }, } -- 生成一个排行榜列表 local function genRankList(rankList) local function genPlayerData(player, tNpcConfig, rank) local r = math.random(1, #tNpcConfig.monsterOutID) player.rank = rank player.name = CreateRole.getRandomName() player.headId = CreateRole.getRandomHead() player.headFrameId = CreateRole.getRandomHeadFrame() player.bodyId = CreateRole.getRandomBody() player.playerUuid = tNpcConfig.monsterOutID[r] player.monsterOutID = tNpcConfig.monsterOutID[r] end local rank = 1 for _, cfg in ipairs(NpcConfig) do for i = 1, cfg.cnt do rankList[rank] = {} genPlayerData(rankList[rank], cfg, rank) rank = rank + 1 if rank > ServerCommerceActDefine.COMMERCEACT_NPC_CNT then break end end end end -- 插入数据 local function insertData(data) LuaMongo.insert(DB.db_battleground, data) end -- 修改db单个字段 local function updateValue(key, value) if not key then return end if value then dbUpdateField["$set"] = {[key]=value} dbUpdateField["$unset"] = nil else dbUpdateField["$set"] = nil dbUpdateField["$unset"] = {[key]=1} end dbUpdate._id = battleGroundData._id LuaMongo.update(DB.db_battleground, dbUpdate, dbUpdateField) end -- 保存所有数据 local function saveAllData() dbUpdate._id = battleGroundData._id LuaMongo.update(DB.db_battleground, dbUpdate, battleGroundData) end local function loadData() LuaMongo.find(DB.db_battleground) local data = {} if LuaMongo.next(data) then battleGroundData = data end if battleGroundData.allAreaRankList and next(battleGroundData.allAreaRankList) then for areaIdx, rankList in pairs(battleGroundData.allAreaRankList) do battleGroundData.allAreaRankList[areaIdx] = {} for _, player in pairs(rankList) do battleGroundData.allAreaRankList[areaIdx][player.rank] = player end end end if not battleGroundData.generaRankList then battleGroundData.generaRankList = {} genRankList(battleGroundData.generaRankList) insertData(battleGroundData) end table.sort(battleGroundData.generaRankList, function (a, b) return a.rank < b.rank end) end function BattleGround_InitAfterStart() if _G.is_middle ~= true then return end loadData() end function onZero() if next(repeateServerIdList) then repeateServerIdList = {} end end -- 通过本服Id获取所在战区Id local function getWarZoneServerIdx(sourceServerId) local nServerKey = MiddleConnect.MiddleConnect_TrueServerID2ConfServerID(sourceServerId) nServerKey = MiddleConnect.MiddleConnect_GetWarZoneServer(nServerKey) return nServerKey end -- 通服务器Id获取所在战区Id的最小服务器Id,最大服务器Id local function getWarZoneServerArea(sourceServerId) local nServerKey = MiddleConnect.MiddleConnect_TrueServerID2ConfServerID(sourceServerId) return MiddleConnect.MiddleConnect_GetWarZoneServer(nServerKey) end -- 生成一个战区排行榜 local function genWarZoneRankList(warZoneServerIdx) local isInsert = false if not next(battleGroundData) then isInsert = true end battleGroundData.allAreaRankList = battleGroundData.allAreaRankList or {} battleGroundData.allAreaRankList[warZoneServerIdx] = {} genRankList(battleGroundData.allAreaRankList[warZoneServerIdx]) if isInsert then return insertData(battleGroundData) end updateValue("allAreaRankList".."."..warZoneServerIdx, battleGroundData.allAreaRankList[warZoneServerIdx]) end -- 获取本服所在战区的排行榜 local function getMyWarZoneRankList(sourceServerId) local warZoneServerIdx = getWarZoneServerIdx(sourceServerId) if not battleGroundData.allAreaRankList or not battleGroundData.allAreaRankList[warZoneServerIdx] then -- genWarZoneRankList(warZoneServerIdx) return end return battleGroundData.allAreaRankList[warZoneServerIdx] end -- 初始化本战区的排行榜 local function initMyWarZoneRankList(sourceServerId) local warZoneServerIdx = getWarZoneServerIdx(sourceServerId) if not battleGroundData.allAreaRankList or not battleGroundData.allAreaRankList[warZoneServerIdx] then battleGroundData.allAreaRankList = battleGroundData.allAreaRankList or {} battleGroundData.allAreaRankList[warZoneServerIdx] = {} end end -- 获取通用排行榜 local function getGeneraRankList() return battleGroundData.generaRankList end -- 通过玩家uuid获取排名 local function getPlayerRankByUuid(rankList, targetPlayerUuid) local targetRank = ServerCommerceActDefine.COMMERCEACT_NPC_CNT + 1 if not rankList then return targetRank end for rank, rankInfo in pairs(rankList) do if rankInfo.playerUuid == targetPlayerUuid then targetRank = rank break end end return targetRank end -- 遍历 local function findVal(list, val) for k, info in pairs(list or {}) do if info[2] == val then return k end end end local function writeLog(logStr) Log.write(Log.LOGID_OSS_COMMON_ACT, logStr) end -- 发奖 local function issueReward(fd, rankArr) local msgData = InnerMsg.wl.WL_BATTLEGROUND_NOTIFY_PRIZEAWARD msgData.playerArr = rankArr InnerMsg.sendMsg(fd, msgData) end -- 普通服请求玩家排名 function BG_N2C_PlayerRank_Req(msg) local msgData = InnerMsg.wl.WL_BATTLEGROUND_PLAYER_RANK_QUERY msgData.playerRank = 0 msgData.playerUuid = msg.playerUuid local myWarZoneRankList = getMyWarZoneRankList(msg.sourceServerId) msgData.playerRank = getPlayerRankByUuid(myWarZoneRankList, msg.playerUuid) local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId) InnerMsg.sendMsg(fd, msgData) end -- 普通服请求对手数据 function BG_N2C_MatchList_Req(msg) local msgData = InnerMsg.wl.WL_BATTLEGROUND_MATCHLIST_QUERY msgData.playerUuid = msg.playerUuid msgData.playerInfoList = {} local myWarZoneRankList = getMyWarZoneRankList(msg.sourceServerId) local generaRankList = getGeneraRankList() for _, rank in ipairs(msg.matchList) do local rankInfo = myWarZoneRankList and myWarZoneRankList[rank] or generaRankList[rank] if rankInfo then msgData.playerInfoList[#msgData.playerInfoList+1] = { rank = rank, serverId = rankInfo.serverId, name = rankInfo.name, showBodyId = rankInfo.bodyId } end end local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId) InnerMsg.sendMsg(fd, msgData) end -- 普通服请求玩家数据 function BG_N2C_PlayerData_Req(msg) local msgData = InnerMsg.wl.WL_BATTLEGROUND_PLAYER_DATA_QUERY msgData.playerUuid = msg.playerUuid msgData.playerInfo = {} local myWarZoneRankList = getMyWarZoneRankList(msg.sourceServerId) local generaRankList = getGeneraRankList() local rankInfo = myWarZoneRankList and myWarZoneRankList[msg.playerRank] or generaRankList[msg.playerRank] if rankInfo then msgData.playerInfo.serverId = rankInfo.serverId msgData.playerInfo.name = rankInfo.name msgData.playerInfo.heroHeadId = rankInfo.headId msgData.playerInfo.heroHeadFrameId = rankInfo.headFrameId msgData.playerInfo.monsteroutId = 0 if rankInfo.serverId then -- 真实玩家 msgData.playerInfo.heroArr = {} for _, heroId in ipairs(rankInfo.heroArr or {}) do msgData.playerInfo.heroArr[#msgData.playerInfo.heroArr+1] = heroId end else -- 机器人 msgData.playerInfo.monsteroutId = rankInfo.monsterOutID end end local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId) InnerMsg.sendMsg(fd, msgData) end -- 普通服请求排行榜数据 function BG_N2C_RankList_Req(msg) local msgData = InnerMsg.wl.WL_BATTLEGROUND_RANKLIST_QUERY msgData.playerUuid = msg.playerUuid msgData.rankList = {} local myWarZoneRankList = getMyWarZoneRankList(msg.sourceServerId) local generaRankList = getGeneraRankList() for rank=1, RANK_SHOW_NUM do local rankInfo = myWarZoneRankList and myWarZoneRankList[rank] or generaRankList[rank] msgData.rankList[rank] = { rank = rank, serverId = rankInfo.serverId, name = rankInfo.name, heroHeadId = rankInfo.headId, heroHeadFrameId = rankInfo.headFrameId, playerUuid = rankInfo.playerUuid, } end local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId) InnerMsg.sendMsg(fd, msgData) end -- 玩家请求挑战某个排名 function BG_N2C_Challenge_Req(msg) local msgData = InnerMsg.wl.WL_BATTLEGROUND_CHALLENGE_QUERY msgData.playerUuid = msg.playerUuid msgData.playerInfo = {} msgData.errCode = 0 local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId) local targetRank = msg.rank local myWarZoneRankList = getMyWarZoneRankList(msg.sourceServerId) local generaRankList = getGeneraRankList() local targetRanker = myWarZoneRankList and myWarZoneRankList[targetRank] or generaRankList[targetRank] if not targetRanker then msgData.errCode = -1 return InnerMsg.sendMsg(fd, msgData) end msgData.playerInfo = { rank = targetRank, playerUuid = targetRanker.playerUuid, defServerId = targetRanker.serverId or 0 } InnerMsg.sendMsg(fd, msgData) end -- 挑战结束 function BG_N2C_Challenge_End(msg) local atkPlayerUuid = msg.playerUuid local atkRank = msg.atkRank local defRank = msg.defRank local challengeRes = msg.challengeRes -- 加入参与列表 battleGroundData.joinList = battleGroundData.joinList or {} if not findVal(battleGroundData.joinList, atkPlayerUuid) then battleGroundData.joinList[#battleGroundData.joinList+1] = {msg.sourceServerId, atkPlayerUuid} updateValue("joinList", battleGroundData.joinList) end -- 挑战没有胜利 if challengeRes ~= CombatDefine.RESULT_WIN then return end local myWarZoneRankList = getMyWarZoneRankList(msg.sourceServerId) if not myWarZoneRankList then initMyWarZoneRankList(msg.sourceServerId) myWarZoneRankList = getMyWarZoneRankList(msg.sourceServerId) end -- 如果挑战方在榜上, 则检查当前排名与挑战时排名是否一致, 如果不一致则获取最新排名 local atkRanker = myWarZoneRankList[atkRank] if atkRanker and atkRanker.playerUuid ~= atkPlayerUuid then atkRank = getPlayerRankByUuid(myWarZoneRankList, msg.playerUuid) end local msgData = InnerMsg.wl.WL_BATTLEGROUND_NOTIFY_PLAYER local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId) msgData.playerUuid = msg.playerUuid msgData.newRank = atkRank msgData.atkeServerId = msg.sourceServerId msgData.atkName = atkRanker and atkRanker.name or msg.playerShowData.name or "" msgData.updateType = 0 -- 如果挑战者排名高于被挑战者排名, 则只通知挑战者刷新匹配列表 if atkRank < defRank then return InnerMsg.sendMsg(fd, msgData) end local defTemp = myWarZoneRankList[defRank] -- 如果挑战方在榜上, 则先把挑战方从排行榜上移除 if atkRank <= ServerCommerceActDefine.COMMERCEACT_NPC_CNT then myWarZoneRankList[atkRank] = nil end -- 第一次挑战, 则使用生成的玩家数据 if not atkRanker then atkRanker = msg.playerShowData end -- 把挑战方加入到排行榜上, 排名为防守方原排名 atkRanker.rank = defRank myWarZoneRankList[defRank] = atkRanker -- 如果双方都在榜上, 则被挑战方排名下降为挑战方原排名 if defTemp and atkRank <= ServerCommerceActDefine.COMMERCEACT_NPC_CNT then defTemp.rank = atkRank myWarZoneRankList[atkRank] = defTemp end -- 保存排行榜数据 local warZoneServerIdx = getWarZoneServerIdx(msg.sourceServerId) updateValue("allAreaRankList".."."..warZoneServerIdx, battleGroundData.allAreaRankList[warZoneServerIdx]) -- 通知挑战者排名提高 fd = MiddleManager.getFDBySvrIndex(atkRanker.serverId) msgData.playerUuid = atkRanker.playerUuid msgData.newRank = atkRanker.rank msgData.atkeServerId = msg.sourceServerId msgData.atkName = atkRanker.name msgData.updateType = 1 InnerMsg.sendMsg(fd, msgData) -- 如果被挑战方是真实玩家, 则通知 if defTemp and defTemp.serverId and defTemp.serverId ~= 0 then msgData.playerUuid = defTemp.playerUuid msgData.newRank = defTemp.rank msgData.updateType = 2 fd = MiddleManager.getFDBySvrIndex(defTemp.serverId) InnerMsg.sendMsg(fd, msgData) end end -- 更换战斗阵容 function BG_N2C_Lineup_Update(msg) local myWarZoneRankList = getMyWarZoneRankList(msg.sourceServerId) local myRank = getPlayerRankByUuid(myWarZoneRankList, msg.playerUuid) if myRank > ServerCommerceActDefine.COMMERCEACT_NPC_CNT then return end myWarZoneRankList[myRank].heroArr = msg.heroArr local warZoneServerIdx = getWarZoneServerIdx(msg.sourceServerId) updateValue("allAreaRankList".."."..warZoneServerIdx, battleGroundData.allAreaRankList[warZoneServerIdx]) end -- 活动结束 function BG_N2C_Act_End(msg) local warZoneServerIdMin, warZoneServerIdMax = getWarZoneServerArea(msg.sourceServerId) if not warZoneServerIdMin or warZoneServerIdMin == 0 then return end if repeateServerIdList[warZoneServerIdMin] then return end -- 更新标识 repeateServerIdList[warZoneServerIdMin] = true local fd_2_PlayerList = {} local joinList = battleGroundData.joinList local serverIdxMin = MiddleConnect.MiddleConnect_ConfServerID2TrueServerID(warZoneServerIdMin) local serverIdxMax = MiddleConnect.MiddleConnect_ConfServerID2TrueServerID(warZoneServerIdMax) -- 参与玩家(包括在榜玩家) for k = #joinList, 1, -1 do local playerInfo = joinList[k] local serverId = playerInfo[1] if serverId >= serverIdxMin and serverId <= serverIdxMax then local fd = MiddleManager.getFDBySvrIndex(serverId) if fd then fd_2_PlayerList[fd] = fd_2_PlayerList[fd] or {} fd_2_PlayerList[fd][#fd_2_PlayerList[fd]+1] = {ServerCommerceActDefine.COMMERCEACT_NPC_CNT, playerInfo[2]} end table.remove(joinList, k) end end -- 在榜玩家 local myWarZoneRankList = getMyWarZoneRankList(msg.sourceServerId) for _, player in pairs(myWarZoneRankList or {}) do local fd = MiddleManager.getFDBySvrIndex(player.serverId) if fd then fd_2_PlayerList[fd] = fd_2_PlayerList[fd] or {} local idx = findVal(fd_2_PlayerList[fd], player.playerUuid) if idx then fd_2_PlayerList[fd][idx][1] = player.rank end end end if battleGroundData.allAreaRankList and battleGroundData.allAreaRankList[warZoneServerIdMin] then battleGroundData.allAreaRankList[warZoneServerIdMin] = nil end if next(fd_2_PlayerList) then -- 写日志 local logTab2 = Util.serialize(fd_2_PlayerList) local logStr2 = table.concat(logTab2) Timer.addLater(45, writeLog, logStr2) local delay_sec = 0 for fd, rankArr in pairs(fd_2_PlayerList) do delay_sec = delay_sec + 3 Timer.addLater(delay_sec, issueReward, fd, rankArr) end -- 更新数据 if not next(battleGroundData.joinList) then battleGroundData.joinList = nil end updateValue("joinList", battleGroundData.joinList) if not next(battleGroundData.allAreaRankList) then battleGroundData.allAreaRankList = nil end updateValue("allAreaRankList", battleGroundData.allAreaRankList) end end