浏览代码

Merge branch '360test' of https://gitee.com/wangwenfan/congkong into 360test

flowerpig 5 月之前
父节点
当前提交
27608f4b5f

+ 1 - 0
script/common/Lang.lua

@@ -844,5 +844,6 @@ AB_JOINED = [[已报名]]
 AB_OCCUPY_POINT_MAX = [[当前占据的据点已达上限]]
 AB_HERO_IN_OTHER_POINT= [[英雄在其他据点上阵了]]
 AB_UPDATE_LINEUP_SUCC= [[更换防守阵容成功]]
+AB_POINT_CHALLENGING= [[已有玩家在进攻该据点]]
 
 AB_MIYAO_NOT_ENOUG = [[秘钥不足]]

+ 18 - 6
script/module/anotherWorldBattle/AnotherWordTreasure.lua

@@ -74,12 +74,22 @@ local function populateMsg(net, itemArr)
 end
 
 -- 填充协议结构2
-local function populateMsg2(net, weightArr)
+local function populateMsg2(net, weightArr, isMaxLv)
     local len = 0
-    for _, weightTb in ipairs(weightArr) do
-        for _, weight in ipairs(weightTb) do
-            len = len + 1
-            net[len] = weight
+
+    if isMaxLv == 1 then
+        for _, weightTb in ipairs(weightArr) do
+            for i=1, 2 do
+                len = len + 1
+                net[len] = weightTb[2]
+            end
+        end
+    else
+        for _, weightTb in ipairs(weightArr) do
+            for _, weight in ipairs(weightTb) do
+                len = len + 1
+                net[len] = weight
+            end
         end
     end
 
@@ -115,6 +125,8 @@ function AB_Treasure_Query(human)
     if nextLv >= maxLv then
         nextLv = maxLv
     end
+
+    msgRet.isMaxLv = nowLv == maxLv and 1 or 0
     local nextLvCfg = AnotherWorldBattleConfig.treasureLv[nextLv]
     msgRet.nextLvCondTimes = nextLvCfg.condLotteryNum
 
@@ -132,7 +144,7 @@ function AB_Treasure_Query(human)
 
     populateMsg(msgRet.lottery2Cost, costCfg.lottery2Cost)
     populateMsg(msgRet.lottery20Cost, costCfg.lottery20Cost)
-    populateMsg2(msgRet.nextLvProArr, nextLvCfg.probabilityArr)
+    populateMsg2(msgRet.nextLvProArr, nextLvCfg.probabilityArr, msgRet.isMaxLv)
 
     Msg.send(msgRet, human.fd)
 end

+ 58 - 26
script/module/anotherWorldBattle/AnotherWorldBattleCS.lua

@@ -152,6 +152,8 @@ local function groupingAlgorithm(unionArray, len)
 
         for i=1, cnt do
             local correctTb = checkRandIdx(startIdx, endIdx)
+            if #correctTb == 0 then break end
+
             local matchIdx = correctTb[math.random(1, #correctTb)]
             usedTb[currentIdx] = true
             usedTb[matchIdx] = true
@@ -177,7 +179,7 @@ local function grouping()
     if not joinUnionArr then
         -- 没有公会参加, 本轮活动结束
         local now = os.time()
-        AnotherWorldBattleDB.UpdateLastRoundStartTime(now)
+        -- AnotherWorldBattleDB.UpdateLastRoundStartTime(now)
         return AnotherWorldBattleDB.UpdateStage(AnotherWorldBattleDefine.AB_STATE_END)
     end
 
@@ -238,18 +240,21 @@ local function genUnionOccupyInfo(unionId, union, playerListData)
     }
 
     local now = os.time()
-    local tbl = occupyTb.occupyCityArr
-    tbl[#tbl+1] = union.baseCityId
+    local t1 = occupyTb.occupyCityArr
+    local t2 = occupyTb.point2CityIdArr
+
+    t1[#t1+1] = union.baseCityId
 
-    local tbl2 = occupyTb.point2CityIdArr
     for cityId, cityIno in pairs(union.occupCityList or {}) do
         if cityIno.isOccupy then
-            tbl[#tbl+1] = cityId
+            t1[#t1+1] = cityId
         end
 
         for _, pointInfo in pairs(cityIno.occupyPointList) do
             if pointInfo.playerUuid then
-                occupyTb.occuoyPointNum = occupyTb.occuoyPointNum + 1
+                if not cityIno.isOccupy then
+                    occupyTb.occuoyPointNum = occupyTb.occuoyPointNum + 1
+                end
 
                 -- 更新据点最新占领时间段的结束时间
                 local occupyTimeArr = pointInfo.occupyTimeArr
@@ -259,14 +264,14 @@ local function genUnionOccupyInfo(unionId, union, playerListData)
                 end
             end
 
-            tbl2[#tbl2+1] = {cityId, pointInfo.occupyTimeArr}
+            t2[#t2+1] = {cityId, pointInfo.occupyTimeArr}
         end
     end
 
     -- 出生点算5个据点
     local baseCiyuTimeArr = { {union.baseCityStartTime, union.baseCityEndTime or now } }
     for i=1, AnotherWorldBattleDefine.AB_POINT_MAX_NUM do
-        tbl2[#tbl2+1] = {union.baseCityId,  baseCiyuTimeArr}
+        t2[#t2+1] = {union.baseCityId,  baseCiyuTimeArr}
     end
 
 
@@ -304,7 +309,7 @@ function IssueRewardManager()
     end
 end
 
--- 检测活动各阶段及相关处理
+-- 检测活动各阶段状态及相关处理
 local function timedStageHandle()
     -- 处于报名阶段
     -- if table.find(AnotherWorldBattleDefine.AB_JOIN_WDAY_AREA, wDay) then
@@ -557,8 +562,7 @@ local function isCanChallengePoint(targetCityId, targetPointIdx, myUnionId, play
         return -2
     end
 
-    local cityList = AnotherWorldBattleDB.GetCityListByGroupId(groupId)
-    local tagetCityData = cityList[targetCityId]
+    local tagetCityData = AnotherWorldBattleDB.GetCityData(groupId, targetCityId)
     if not tagetCityData then
         return -3
     end
@@ -839,8 +843,8 @@ function N2C_CityDetailed_Query(msg)
         return errTips(msg.sourceServerId, playerUuid, AnotherWorldBattleDefine.ERR_CODE_3)
     end
 
-    local cityList = AnotherWorldBattleDB.GetCityListByGroupId(groupId)
-    if not cityList or not cityList[targetCityId] then
+    local cityData = AnotherWorldBattleDB.GetCityData(groupId, targetCityId)
+    if not cityData then
         return errTips(msg.sourceServerId, playerUuid, AnotherWorldBattleDefine.ERR_CODE_4)
     end
 
@@ -853,9 +857,8 @@ function N2C_CityDetailed_Query(msg)
     end
     msgData.myUnionOccupyArr = myUnionOccupyArr
 
-    local cityData = cityList[targetCityId]
-    local pointArrMsg = msgData.pointArr
 
+    local pointArrMsg = msgData.pointArr
     for pointIdx, occupyInfo in ipairs(cityData.pointArr) do
         pointArrMsg[pointIdx] = {}
         local state = isCanChallengePoint(targetCityId, pointIdx, myUnionId, playerUuid)
@@ -929,12 +932,11 @@ function N2C_PointDetailed_Query(msg)
         return errTips(msg.sourceServerId, msg.playerUuid, AnotherWorldBattleDefine.ERR_CODE_3)
     end
 
-    local cityList = AnotherWorldBattleDB.GetCityListByGroupId(groupId)
-    if not cityList or not cityList[targetCityId] then
+    local cityData = AnotherWorldBattleDB.GetCityData(groupId, targetCityId)
+    if not cityData then
         return errTips(msg.sourceServerId, msg.playerUuid, AnotherWorldBattleDefine.ERR_CODE_4)
     end
 
-    local cityData = cityList[targetCityId]
     local pointData = cityData.pointArr[targetPointIdx]
     if not pointData then
         return errTips(msg.sourceServerId, msg.playerUuid, AnotherWorldBattleDefine.ERR_CODE_4)
@@ -1226,8 +1228,8 @@ function N2C_Try_Challengde_Point(msg)
     end
 
     local groupId = getMyUnionGourpId(myUnionId)
-    local cityList = AnotherWorldBattleDB.GetCityListByGroupId(groupId)
-    local targetPointData = cityList[targetCityId].pointArr[targetPointIdx]
+    local cityData = AnotherWorldBattleDB.GetCityData(groupId, targetCityId)
+    local targetPointData = cityData.pointArr[targetPointIdx]
 
     local pointOccupyInfo = {targetCityId = targetCityId, targetPointIdx = targetPointIdx}
     if targetPointData.unionId then
@@ -1241,6 +1243,18 @@ function N2C_Try_Challengde_Point(msg)
         pointOccupyInfo.isGather = 1
     end
 
+    -- 检查据点是否有人挑战
+    local now = os.time()
+    local pointBattleTime = targetPointData.battleTime
+    if pointBattleTime and now - pointBattleTime < AnotherWorldBattleDefine.AB_POINT_BATTLE_TIME then
+        return errTips(msg.sourceServerId, playerUuid, AnotherWorldBattleDefine.ERR_CODE_11)
+    end
+
+    -- 更新据点被挑战时间
+    targetPointData.battleTime = now
+    AnotherWorldBattleDB.UpdateCityData(groupId, targetCityId, cityData)
+
+
     local msgData = InnerMsg.wl.WL_ANOTHERWORLDBATTLE_POINT_ISCAN_CHALLENGE
     msgData.playerUuid = playerUuid
     msgData.targetCityId = targetCityId
@@ -1273,14 +1287,19 @@ local function challenge_Win(msg)
         return errTips(msg.sourceServerId, msg.playerUuid, AnotherWorldBattleDefine.ERR_CODE_3)
     end
 
-    local cityList = AnotherWorldBattleDB.GetCityListByGroupId(groupId)
-    local cityData = cityList[targetCityId]
+    local cityData = AnotherWorldBattleDB.GetCityData(groupId, targetCityId)
     local pointData = cityData.pointArr[targetPointIdx]
 
     local now = os.time()
     local cityNum, pointNum = 0, 1
     local pointWeight = AnotherWorldBattleConfig.city[targetCityId].pointWeight
 
+
+    -- 如果城池之前被占领了, 则重置占领城池的公会Id
+    if cityData.occupyUnion then
+        cityData.occupyUnion = nil
+    end
+
     -- 防守方是真实玩家
     if pointData.unionId and pointData.playerUuid then
         -- 更新防守方公会数据
@@ -1315,7 +1334,7 @@ local function challenge_Win(msg)
         -- 更新防守方公会的排行榜数据
         AnotherWorldBattleDB.UpdateUnionRankList(groupId, pointData.unionId, cityNum, pointNum)
         -- 更新防守方玩家的排行榜数据
-        AnotherWorldBattleDB.UpdatePlayerRankList(groupId, playerUuid, -pointNum, -pointWeight)
+        AnotherWorldBattleDB.UpdatePlayerRankList(groupId, pointData.playerUuid, -pointNum, -pointWeight)
 
         -- 通知玩家
         pointLose(defUnionData.serverId, pointData.playerUuid, targetCityId, targetPointIdx)
@@ -1328,6 +1347,9 @@ local function challenge_Win(msg)
     pointData.unionId = myUnionId
     pointData.playerUuid = playerUuid
 
+    -- 据点挑战结束
+    pointData.battleTime = nil
+
     -- 更新进攻方公会数据—— 据点占有者, 最新的据点占有时间
     myUnionData.occupCityList = myUnionData.occupCityList or {}
     local occupCityList = myUnionData.occupCityList
@@ -1384,22 +1406,32 @@ local function challenge_Win(msg)
     -- 更新进攻方公会的排行榜数据
     AnotherWorldBattleDB.UpdateUnionRankList(groupId, myUnionId, cityNum, pointNum)
     -- 更新进攻方玩家的排行榜数据
-    AnotherWorldBattleDB.UpdatePlayerRankList(groupId, playerUuid, pointNum, pointWeight)
+    AnotherWorldBattleDB.UpdatePlayerRankList(groupId, playerUuid, pointNum, pointWeight, playerShowInfo.power)
 
 
     -- 更新城池数据
-    AnotherWorldBattleDB.UpdateCityList(groupId, cityList)
+    AnotherWorldBattleDB.UpdateCityData(groupId, targetCityId, cityData)
 end
 -- 玩家挑战据点失败
 local function challenge_Fail(msg)
     local playerUuid = msg.playerUuid
     local myUnionId = msg.myUnionId
+    local targetCityId = msg.targetCityId
+    local targetPointIdx = msg.targetPointIdx
 
     local groupId = getMyUnionGourpId(myUnionId)
     if not groupId then
         return
     end
 
+    -- 据点挑战结束
+    local cityData = AnotherWorldBattleDB.GetCityData(groupId, targetCityId)
+    if cityData and cityData.pointArr[targetPointIdx] then
+        local targetPointData = cityData.pointArr[targetPointIdx]
+        targetPointData.battleTime = nil
+        AnotherWorldBattleDB.UpdateCityData(groupId, targetCityId, cityData)
+    end
+
     local playerData = AnotherWorldBattleDB.GetPlayerData(playerUuid)
     playerData = playerData or {}
     playerData.name = playerData.name
@@ -1413,7 +1445,7 @@ local function challenge_Fail(msg)
     AnotherWorldBattleDB.UpdatePlayerData(playerUuid, playerData)
 
     -- 加入个人排行榜
-    AnotherWorldBattleDB.UpdatePlayerRankList(groupId, playerUuid, 0, 0)
+    AnotherWorldBattleDB.UpdatePlayerRankList(groupId, playerUuid, 0, 0, playerData.power)
 end
 
 --挑战据点结束的处理函数

+ 124 - 566
script/module/anotherWorldBattle/AnotherWorldBattleDB.lua

@@ -204,589 +204,136 @@ local function genCityList(net, unionIdArr)
 end
 
 -- 工会排行榜
+-- 目前最多8条
 local function createGuildRank()
-    local state = {
-        guilds = {},           -- {[guildId] = {id, name, power, occupyCityNum, occupyPointNum, ...}}
-        sortedGuilds = {},     -- 排序后的工会数组
-        isDirty = true,
-        maxSize = 8
-    }
-    
-    -- 创建接口表
-    local interface = {}
-    
-    -- 计算组合键
-    local function getGuildSortKey(occupyCityNum, occupyPointNum, power)
-        return occupyCityNum * 100000000000000000000 +  -- 10^20
-               occupyPointNum * 1000000000000 +         -- 10^12
-               power
-    end
-    
-    -- 使用组合键进行比较
-    local function compareGuilds(a, b)
-        local keyA = getGuildSortKey(a.occupyCityNum, a.occupyPointNum, a.power)
-        local keyB = getGuildSortKey(b.occupyCityNum, b.occupyPointNum, b.power)
-        
-        if keyA ~= keyB then
-            return keyA > keyB  -- 组合键大的排名高
-        end
-        
-        -- 组合键相同,按ID排序
-        return a.id < b.id
-    end
-    
-    local function quickSort(arr, left, right)
-        if left >= right then return end
-        
-        local pivot = arr[math.floor((left + right) / 2)]
-        local i, j = left, right
-        
-        while i <= j do
-            while compareGuilds(arr[i], pivot) do i = i + 1 end
-            while compareGuilds(pivot, arr[j]) do j = j - 1 end
-            
-            if i <= j then
-                arr[i], arr[j] = arr[j], arr[i]
-                i = i + 1
-                j = j - 1
-            end
-        end
-        
-        quickSort(arr, left, j)
-        quickSort(arr, i, right)
-    end
-    
-    local function refreshRank()
-        -- 收集所有工会到数组
-        local guildArray = {}
-        for _, guild in pairs(state.guilds) do
-            table.insert(guildArray, guild)
-        end
-        
-        -- 使用快速排序
-        if #guildArray > 0 then
-            quickSort(guildArray, 1, #guildArray)
+    local guilds = {}      -- id -> guildRec(永久表,不删)
+    local rank   = {}      -- 1..#guilds 复用数组
+
+    local function cmp(a, b)
+        if a.occupyCityNum ~= b.occupyCityNum then
+            return a.occupyCityNum > b.occupyCityNum
         end
-        
-        -- 只保留前8名
-        state.sortedGuilds = {}
-        for i = 1, math.min(state.maxSize, #guildArray) do
-            state.sortedGuilds[i] = {
-                guildId = guildArray[i].id,
-                rank = i,
-                power = guildArray[i].power,
-                name = guildArray[i].name,
-                occupyCityNum = guildArray[i].occupyCityNum,
-                occupyPointNum = guildArray[i].occupyPointNum
-            }
+        if a.occupyPointNum ~= b.occupyPointNum then
+            return a.occupyPointNum > b.occupyPointNum
         end
-        
-        state.isDirty = false
+        return a.power > b.power
     end
 
-    -- 定义接口函数
-    function interface.updateGuild(guildId, name, power, occupyCityNum, occupyPointNum)
-        if not state.guilds[guildId] then
-            state.guilds[guildId] = {
-                id = guildId, 
-                name = name, 
-                power = power,
+    local function updateGuild(id, name, occupyCityNum, occupyPointNum, power)
+        local g = guilds[id]
+        if not g then
+            g = { id = id, name = name or "",
                 occupyCityNum = occupyCityNum or 0,
-                occupyPointNum = occupyPointNum or 0
-            }
+                occupyPointNum = occupyPointNum or 0,
+                power = power or 0 }
+            guilds[id] = g
         else
-            state.guilds[guildId].power = power
-            state.guilds[guildId].occupyCityNum = occupyCityNum or state.guilds[guildId].occupyCityNum
-            state.guilds[guildId].occupyPointNum = occupyPointNum or state.guilds[guildId].occupyPointNum
-            if name then
-                state.guilds[guildId].name = name
-            end
-        end
-        state.isDirty = true
-    end
-
-    function interface.updateOccupyCityNum(guildId, occupyCityNum)
-        if state.guilds[guildId] then
-            state.guilds[guildId].occupyCityNum = occupyCityNum
-            state.isDirty = true
-        end
-    end
-
-    function interface.updateOccupyPointNum(guildId, occupyPointNum)
-        if state.guilds[guildId] then
-            state.guilds[guildId].occupyPointNum = occupyPointNum
-            state.isDirty = true
-        end
-    end
-
-    function interface.updatePower(guildId, power)
-        if state.guilds[guildId] then
-            state.guilds[guildId].power = power
-            state.isDirty = true
-        end
-    end
-
-    function interface.disbandGuild(guildId)
-        if state.guilds[guildId] then
-            state.guilds[guildId] = nil
-            state.isDirty = true
-            return true
-        end
-        return false
-    end
-
-    function interface.getRankList()
-        if state.isDirty then
-            refreshRank()
-        end
-        return state.sortedGuilds
-    end
-
-    function interface.getGuildRank(guildId)
-        if state.isDirty then
-            refreshRank()
-        end
-        
-        for i, guild in ipairs(state.sortedGuilds) do
-            if guild.guildId == guildId then
-                return i
-            end
-        end
-        return nil
-    end
-
-    function interface.getGuildDetail(guildId)
-        if state.isDirty then
-            refreshRank()
-        end
-        
-        for i, guild in ipairs(state.sortedGuilds) do
-            if guild.guildId == guildId then
-                return {
-                    rank = i,
-                    guildId = guild.guildId,
-                    name = guild.name,
-                    power = guild.power,
-                    occupyCityNum = guild.occupyCityNum,
-                    occupyPointNum = guild.occupyPointNum
-                }
-            end
-        end
-        return nil
-    end
-
-    function interface.hasGuild(guildId)
-        return state.guilds[guildId] ~= nil
-    end
-
-    function interface.getTotalGuilds()
-        return tableCount(state.guilds)
-    end
-
-    function interface._getState()
-        return {
-            totalGuilds = tableCount(state.guilds),
-            isDirty = state.isDirty
-        }
-    end
+            g.occupyCityNum = occupyCityNum or g.occupyCityNum
+            g.occupyPointNum = occupyPointNum or g.occupyPointNum
+            g.power = power or g.power
+            if name then g.name = name end
+        end
+
+        -- 全量重建(8 条以内,可忽略性能)
+        local n = 0
+        for _, v in pairs(guilds) do
+            n = n + 1
+            rank[n] = v
+        end
+        table.sort(rank, cmp)
+        for i = n + 1, #rank do rank[i] = nil end   -- 清理旧数据
+    end
+
+    local function getRankList()
+        local ret = {}
+        for i = 1, #rank do
+            local g = rank[i]
+            ret[i] =
+            {
+                rank = i, guildId = g.id, name = g.name,
+                occupyCityNum = g.occupyCityNum,
+                occupyPointNum = g.occupyPointNum,
+                power = g.power}
+        end
+        return ret
+    end
+
+    local function getGuildDetail(id) return guilds[id] end
+    -- 在返回表里加
+    return { 
+        updateGuild = updateGuild,
+        getRankList = getRankList, 
+        getGuildDetail = getGuildDetail
+    }
 
-    return interface
 end
 
 -- 玩家排行榜
+-- 当前每个公会最多25人,8个公会为一组,最多200人
 local function createPlayerRank()
-    local state = {
-        players = {},           -- {[playerId] = {id, name, power, pointNum, pointAllWeight, ...}}
-        rankArray = {},         -- 排行榜数组,按组合键排序
-        playerIndex = {},       -- {[playerId] = 在rankArray中的索引}
-        candidateMap = {},      -- 候选玩家 {[playerId] = true}
-        maxSize = AnotherWorldBattleDefine.AB_RANK_MAX_NUM,
-        size = 0
-    }
-    
-    -- 创建接口表
-    local interface = {}
-    
-    -- 计算组合键
-    local function getPlayerSortKey(pointNum, pointAllWeight, power)
-        return pointNum * 10000000000000000 +    -- 10^16
-               pointAllWeight * 10000000000 +    -- 10^10
-               power
-    end
-
-    -- 使用组合键进行比较
-    local function comparePlayers(a, b)
-        local keyA = getPlayerSortKey(a.pointNum, a.pointAllWeight, a.power)
-        local keyB = getPlayerSortKey(b.pointNum, b.pointAllWeight, b.power)
-
-        if keyA ~= keyB then
-            return keyA > keyB  -- 组合键大的排名高
-        end
-        
-        -- 组合键相同,按ID排序
-        return a.id < b.id
-    end
-
-    -- 二分查找插入位置(使用组合键)
-    local function findInsertPosition(playerData)
-        local left, right = 1, state.size
-        local key = getPlayerSortKey(playerData.pointNum, playerData.pointAllWeight, playerData.power)
-        
-        while left <= right do
-            local mid = math.floor((left + right) / 2)
-            local midPlayer = state.rankArray[mid]
-            local midKey = getPlayerSortKey(midPlayer.pointNum, midPlayer.pointAllWeight, midPlayer.power)
-            
-            if key > midKey then
-                right = mid - 1
-            else
-                left = mid + 1
-            end
-        end
-        
-        return left
-    end
-    
-    -- 插入玩家到排行榜
-    local function insertToRank(playerData)
-        if state.size == 0 then
-            state.rankArray[1] = playerData
-            state.playerIndex[playerData.id] = 1
-            state.size = 1
-            return
-        end
-        
-        local pos = findInsertPosition(playerData)
-        
-        -- 向后移动元素
-        for i = state.size, pos, -1 do
-            state.rankArray[i + 1] = state.rankArray[i]
-            state.playerIndex[state.rankArray[i].id] = i + 1
-        end
-        
-        -- 插入新元素
-        state.rankArray[pos] = playerData
-        state.playerIndex[playerData.id] = pos
-        state.size = state.size + 1
-        
-        -- 如果超过最大大小,移除最后一个
-        if state.size > state.maxSize then
-            local removedPlayer = state.rankArray[state.maxSize + 1]
-            if removedPlayer then
-                state.playerIndex[removedPlayer.id] = nil
-                state.candidateMap[removedPlayer.id] = true
-            end
-            state.size = state.maxSize
-        end
-    end
-    
-    -- 从排行榜移除玩家
-    local function removeFromRank(playerId)
-        local index = state.playerIndex[playerId]
-        if not index then return false end
-        
-        -- 向前移动元素
-        for i = index, state.size - 1 do
-            state.rankArray[i] = state.rankArray[i + 1]
-            state.playerIndex[state.rankArray[i].id] = i
-        end
-        
-        state.rankArray[state.size] = nil
-        state.playerIndex[playerId] = nil
-        state.size = state.size - 1
-        return true
-    end
-    
-    -- 调整玩家在排行榜中的位置
-    local function adjustPlayerPosition(playerId)
-        local currentIndex = state.playerIndex[playerId]
-        if not currentIndex then return end
-        
-        local playerData = state.players[playerId]
-        if not playerData then return end
-        
-        -- 先移除,再重新插入(确保位置正确)
-        removeFromRank(playerId)
-        insertToRank(playerData)
-    end
-
-    -- 检查候选玩家
-    local function checkCandidates()
-        if state.size < state.maxSize then
-            -- 排行榜未满,找到最佳候选加入
-            local bestCandidate = nil
-            local bestKey = -1
-            
-            for playerId, _ in pairs(state.candidateMap) do
-                local player = state.players[playerId]
-                if player then
-                    local key = getPlayerSortKey(player.pointNum, player.pointAllWeight, player.power)
-                    if key > bestKey then
-                        bestCandidate = playerId
-                        bestKey = key
-                    elseif key == bestKey and player.id < bestCandidate then
-                        bestCandidate = playerId
-                        bestKey = key
-                    end
-                end
-            end
-            
-            if bestCandidate then
-                state.candidateMap[bestCandidate] = nil
-                insertToRank(state.players[bestCandidate])
-            end
+    local players     = {}              -- id -> rec(永久存在,不删)
+    local rank        = {}              -- 1..RANK_MAX 复用
+    local tmp         = {}              -- 一次性长到 MAX_PEOPLE
+
+    local function cmp(a, b)
+        if a.pointNum ~= b.pointNum then return a.pointNum > b.pointNum end
+        if a.pointAllWeight ~= b.pointAllWeight then return a.pointAllWeight > b.pointAllWeight end
+        return a.power > b.power
+    end
+
+    -- 预分配 tmp 数组,避免运行时扩容
+    for i = 1, 500 do tmp[i] = nil end
+
+    local function updatePlayer(id, name, power, pNum, pWeight)
+        -- 1. 取出或新建记录
+        local rec = players[id]
+        if not rec then
+            rec = { id = id, name = name or "", power = power,
+                    pointNum = pNum or 0, pointAllWeight = pWeight or 0 }
+            players[id] = rec
         else
-            -- 检查候选是否应该替换最后一名
-            local lastPlayer = state.rankArray[state.size]
-            local lastKey = getPlayerSortKey(lastPlayer.pointNum, lastPlayer.pointAllWeight, lastPlayer.power)
-            local bestCandidate = nil
-            local bestKey = lastKey
-            
-            for playerId, _ in pairs(state.candidateMap) do
-                local player = state.players[playerId]
-                if player then
-                    local key = getPlayerSortKey(player.pointNum, player.pointAllWeight, player.power)
-                    if key > bestKey then
-                        bestCandidate = playerId
-                        bestKey = key
-                    elseif key == bestKey and player.id < bestCandidate then
-                        bestCandidate = playerId
-                        bestKey = key
-                    end
-                end
-            end
-            
-            if bestCandidate then
-                state.candidateMap[bestCandidate] = nil
-                state.candidateMap[lastPlayer.id] = true
-                removeFromRank(lastPlayer.id)
-                insertToRank(state.players[bestCandidate])
-            end
-        end
-    end
-
-    -- 完全移除玩家(包括从候选集)
-    local function removePlayerCompletely(playerId)
-        -- 从排行榜移除
-        removeFromRank(playerId)
-        
-        -- 从候选集移除
-        state.candidateMap[playerId] = nil
-        
-        -- 从玩家数据移除
-        state.players[playerId] = nil
-        
-        return true
-    end
-
-    -- 定义接口函数
-    function interface.updatePlayer(playerId, name, power, pointNum, pointAllWeight)
-        local playerData = state.players[playerId]
-        
-        if not playerData then
-            -- 新玩家
-            playerData = {
-                id = playerId, 
-                name = name, 
-                power = power,
-                pointNum = pointNum or 0,
-                pointAllWeight = pointAllWeight or 0
-            }
-            state.players[playerId] = playerData
-            
-            if state.size < state.maxSize then
-                insertToRank(playerData)
-            else
-                -- 检查是否能直接进入排行榜
-                local lastPlayer = state.rankArray[state.size]
-                local lastKey = getPlayerSortKey(lastPlayer.pointNum, lastPlayer.pointAllWeight, lastPlayer.power)
-                local newKey = getPlayerSortKey(pointNum or 0, pointAllWeight or 0, power)
-                
-                if newKey > lastKey or (newKey == lastKey and playerId < lastPlayer.id) then
-                    state.candidateMap[lastPlayer.id] = true
-                    removeFromRank(lastPlayer.id)
-                    insertToRank(playerData)
-                else
-                    state.candidateMap[playerId] = true
-                end
-            end
-        else
-            -- 已有玩家
-            playerData.power = power
-            playerData.pointNum = pointNum or playerData.pointNum
-            playerData.pointAllWeight = pointAllWeight or playerData.pointAllWeight
-            if name then
-                playerData.name = name
-            end
-            
-            local currentIndex = state.playerIndex[playerId]
-            
-            if currentIndex then
-                -- 玩家在排行榜中,需要调整位置
-                adjustPlayerPosition(playerId)
-            else
-                -- 玩家不在排行榜中,检查候选集
-                if state.candidateMap[playerId] then
-                    if state.size < state.maxSize then
-                        state.candidateMap[playerId] = nil
-                        insertToRank(playerData)
-                    else
-                        local lastPlayer = state.rankArray[state.size]
-                        local lastKey = getPlayerSortKey(lastPlayer.pointNum, lastPlayer.pointAllWeight, lastPlayer.power)
-                        local newKey = getPlayerSortKey(playerData.pointNum, playerData.pointAllWeight, playerData.power)
-                        
-                        if newKey > lastKey or (newKey == lastKey and playerId < lastPlayer.id) then
-                            state.candidateMap[lastPlayer.id] = true
-                            state.candidateMap[playerId] = nil
-                            removeFromRank(lastPlayer.id)
-                            insertToRank(playerData)
-                        end
-                    end
-                end
-            end
-        end
-    end
-
-    function interface.updatePointNum(playerId, pointNum)
-        if state.players[playerId] then
-            state.players[playerId].pointNum = pointNum
-            
-            local currentIndex = state.playerIndex[playerId]
-            if currentIndex then
-                adjustPlayerPosition(playerId)
-            else
-                -- 不在排行榜中,检查候选集
-                if state.candidateMap[playerId] then
-                    checkCandidates()
-                end
-            end
-        end
-    end
-
-    function interface.updatePointAllWeight(playerId, pointAllWeight)
-        if state.players[playerId] then
-            state.players[playerId].pointAllWeight = pointAllWeight
-            
-            local currentIndex = state.playerIndex[playerId]
-            if currentIndex then
-                adjustPlayerPosition(playerId)
-            else
-                -- 不在排行榜中,检查候选集
-                if state.candidateMap[playerId] then
-                    checkCandidates()
-                end
-            end
-        end
-    end
-
-    function interface.updatePower(playerId, power)
-        if state.players[playerId] then
-            state.players[playerId].power = power
-            
-            local currentIndex = state.playerIndex[playerId]
-            if currentIndex then
-                adjustPlayerPosition(playerId)
-            else
-                -- 不在排行榜中,检查候选集
-                if state.candidateMap[playerId] then
-                    checkCandidates()
-                end
-            end
+            -- 原地更新
+            rec.power = power
+            if pNum ~= nil then rec.pointNum = pNum end
+            if pWeight ~= nil then rec.pointAllWeight = pWeight end
+            if name then rec.name = name end
         end
-    end
-
-    function interface.removePlayer(playerId)
-        return removePlayerCompletely(playerId)
-    end
 
-    function interface.getRankList()
-        checkCandidates()  -- 每次获取时检查候选
-        
-        local result = {}
-        for i = 1, state.size do
-            local player = state.rankArray[i]
-            table.insert(result, {
-                playerId = player.id,
-                name = player.name,
-                rank = i,
-                power = player.power,
-                pointNum = player.pointNum,
-                pointAllWeight = player.pointAllWeight
-            })
+        -- 2. 全量收集(只复制引用,不创建新表)
+        local n = 0
+        for _, v in pairs(players) do
+            n = n + 1
+            tmp[n] = v
         end
-        return result
-    end
 
-    function interface.getPlayerRank(playerId)
-        local index = state.playerIndex[playerId]
-        return index
-    end
+        -- 3. 只排序有用部分
+        table.sort(tmp, cmp)
 
-    function interface.getPlayerDetail(playerId)
-        local index = state.playerIndex[playerId]
-        if index then
-            local player = state.rankArray[index]
-            return {
-                rank = index,
-                playerId = player.id,
-                name = player.name,
-                power = player.power,
-                pointNum = player.pointNum,
-                pointAllWeight = player.pointAllWeight
-            }
+        -- 4. 取前 RANK_MAX 到 rank,复用 rank 数组
+        for i = 1, AnotherWorldBattleDefine.AB_RANK_MAX_NUM do
+            rank[i] = tmp[i]
         end
-        return nil
-    end
-
-    function interface.hasPlayer(playerId)
-        return state.players[playerId] ~= nil
+        for i = AnotherWorldBattleDefine.AB_RANK_MAX_NUM + 1, #rank do rank[i] = nil end
     end
 
-    function interface.getTotalPlayers()
-        return tableCount(state.players)
-    end
-
-    function interface.batchUpdate(updates)
-        for _, update in ipairs(updates) do
-            if update.playerId then
-                interface.updatePlayer(
-                    update.playerId,
-                    update.name,
-                    update.power,
-                    update.pointNum, 
-                    update.pointAllWeight
-                )
-            end
+    local function getRankList()
+        local ret = {}
+        for i = 1, #rank do
+            local p = rank[i]
+            ret[i] = { rank = i, playerId = p.id, name = p.name, power = p.power,
+                        pointNum = p.pointNum, pointAllWeight = p.pointAllWeight }
         end
+        return ret
     end
 
-    function interface._getState()
-        return {
-            totalPlayers = tableCount(state.players),
-            rankSize = state.size,
-            candidateCount = tableCount(state.candidateMap)
-        }
-    end
-
-    return interface
-end
-
--- 辅助函数:计算表的元素数量
-function tableCount(t)
-    local count = 0
-    for _ in pairs(t) do count = count + 1 end
-    return count
-end
-
-
--- 辅助函数:计算表的元素数量
-function tableCount(t)
-    local count = 0
-    for _ in pairs(t) do count = count + 1 end
-    return count
+    local function getPlayerDetail(id) return players[id] end
+    return {
+        updatePlayer = updatePlayer,
+        getRankList  = getRankList,
+        getPlayerDetail = getPlayerDetail,
+    }
 end
 
-
 -- 生成公会排行榜
 local function genGroupUnionRankList(unionRank, unionIdArr)
     local function getUnionRankVal(union)
@@ -810,16 +357,14 @@ local function genGroupUnionRankList(unionRank, unionIdArr)
         local unionData = AnotherWorldBattleData.unionList[unionId]
         if unionData then
             local occupyCityNum, occupyPointNum, power = getUnionRankVal(unionData)
-            unionRank.updateGuild(unionId, unionData.name, power, occupyCityNum, occupyPointNum )
+            unionRank.updateGuild(unionId, unionData.name, occupyCityNum, occupyPointNum, power)
         end
     end
 end
 
 -- 生成个人排行榜
 local function genGroupPlayerRankList(playerRank, unionIdArr, playerListData)
-    local playerArr = {}
-
-    local function insertPlayerArr(unionId)
+    local function insertPlayerRank(unionId)
         if not playerListData then
             return
         end
@@ -835,16 +380,15 @@ local function genGroupPlayerRankList(playerRank, unionIdArr, playerListData)
                     end
                 end
 
-                playerArr[#playerArr+1] = {playerId = playerUuid, name = playerInfo.name, power = playerInfo.power, pointNum = pointNum, pointAllWeight = pointAllWeight}
+                playerRank.updatePlayer(playerUuid, playerInfo.name, playerInfo.power, pointNum, pointAllWeight)
             end
         end
     end
 
     for _, unionId in ipairs(unionIdArr) do
-        insertPlayerArr(unionId)
+        insertPlayerRank(unionId)
     end
 
-    playerRank.batchUpdate(playerArr)
 end
 
 -- 生成 "公会-公会所属分组Id" 映射表
@@ -1048,16 +592,30 @@ end
 
 
 -- 获取城池数据
+function GetCityData(groupId, cityId)
+    if Group_2_CityList[groupId] then
+        return Group_2_CityList[groupId][cityId]
+    end
+end
+-- 更新城池数据
+function UpdateCityData(groupId, cityId, newCityData)
+    if Group_2_CityList[groupId] then
+        Group_2_CityList[groupId][cityId] = newCityData
+    end
+end
+
+-- 获取所有城池数据
 function GetCityListByGroupId(groupId)
     return Group_2_CityList[groupId]
 end
--- 更新城池数据
+-- 更新所有城池数据
 function UpdateCityList(groupId, newCityList)
     Group_2_CityList[groupId] = newCityList
 end
 
 
 
+
 -- 获取公会排行数据
 function GetUnionRankList(groupId)
     local unionRank = Group_2_UnionRankList[groupId]
@@ -1075,7 +633,7 @@ function UpdateUnionRankList(groupId, unionId, cityVal, pointVal, newPower)
         if newPower then
             unionRankInfo.power = newPower
         end
-        unionRank.updateGuild(unionId, unionRankInfo.name, unionRankInfo.power, unionRankInfo.occupyCityNum, unionRankInfo.occupyPointNum)
+        unionRank.updateGuild(unionId, unionRankInfo.name, unionRankInfo.occupyCityNum, unionRankInfo.occupyPointNum, unionRankInfo.power)
     end
 end
 

+ 5 - 1
script/module/anotherWorldBattle/AnotherWorldBattleDefine.lua

@@ -36,8 +36,12 @@ AB_PLAYER_OCCUPY_POINT_MAX_NUM = 15  -- 每个玩家最多占领据点数量
 AB_RANK_MAX_NUM = 50        -- 公会/个人排行榜最大上榜数量
 
 AB_PLAYER_CHALLENGE_TIMES = 50  -- 玩家初始时挑战次数
+
 AB_PLAYER_CHALLENGETIMES_SEC = 3600  -- 每一个小时恢复一次挑战次数
 
+AB_POINT_BATTLE_TIME = 30        -- 挑战据点从发起战斗 ~ 结束时间  临时改为30, 等客户端战斗结束协议请求时机后再看怎么改
+
+
 
 AB_AWARD_MAIL_ID = 7030        -- 奖励发放邮件Id
 AB_LOSE_POINT_MAIL_ID = 7031   -- 玩家失去据点后通知邮件Id
@@ -57,7 +61,7 @@ ERR_CODE_7 = 7      -- 城池不相邻
 ERR_CODE_8 = 8      -- 公会已报名
 ERR_CODE_9 = 9      -- 没有在本城池发起集结
 ERR_CODE_10 = 10    -- 当前占据的据点已达上限
-
+ERR_CODE_11 = 11    -- 当前据点被挑战中, 请稍后再试
 
 
 

+ 17 - 11
script/module/anotherWorldBattle/AnotherWorldBattleNS.lua

@@ -347,7 +347,7 @@ local function genAwardObjArr(unionOccupyInfo)
     local function calcMinute(timeArr)
         local minuteVal = 0
         for _, timeTb in ipairs(timeArr or {}) do
-            local sec = timeTb[2] - timeTb[1]
+            local sec = (timeTb[2] or 0) - (timeTb[1] or 0)
             if sec > 0 then
                 minuteVal = minuteVal + sec
             end
@@ -356,25 +356,26 @@ local function genAwardObjArr(unionOccupyInfo)
         return math.floor(minuteVal / 60)
     end
 
+    -- 没有玩家参与
     if not unionOccupyInfo.playerUuidArr or #unionOccupyInfo.playerUuidArr <= 0 then
         return
     end
 
     local itemList = {}
     local occupyCityInfo = {0,0,0,0,0}
-
     local item_185_Id = 185
     local item_185_Num = 0
-    item_185_Num = item_185_Num + (unionOccupyInfo.occuoyPointNum or 0) -- 待优化
+
+    occupyCityInfo[1] = unionOccupyInfo.occuoyPointNum
 
     -- 额外奖励
+    item_185_Num = item_185_Num + (unionOccupyInfo.occuoyPointNum or 0)
+
     for _, cityId in ipairs(unionOccupyInfo.occupyCityArr) do
         local cityCfg = AnotherWorldBattleConfig.city[cityId]
-
         if cityCfg then
             if cityCfg.isBaseCity == 1 then
                 item_185_Num = item_185_Num + 20
-                occupyCityInfo[1] = occupyCityInfo[1] + 1
             else
                 if cityCfg.cityLv == 2 then
                     item_185_Num = item_185_Num + 2
@@ -397,12 +398,12 @@ local function genAwardObjArr(unionOccupyInfo)
     for _, pointInfo in ipairs(unionOccupyInfo.point2CityIdArr) do
         local cityId = pointInfo[1]
         local occupyTimeArr = pointInfo[2]
-        local cityCfg = AnotherWorldBattleConfig.city[cityId]
 
+        local cityCfg = AnotherWorldBattleConfig.city[cityId]
         local totalMinVal = calcMinute(occupyTimeArr)
         if totalMinVal > 0 then
             local itemId, itemNum = cityCfg.cityAward[1], cityCfg.cityAward[2]
-            itemList[itemId] = totalMinVal * itemNum
+            itemList[itemId] = (itemList[itemId] or 0) + totalMinVal * itemNum
         end
     end
 
@@ -726,9 +727,9 @@ local function challenge_End(human, args)
     -- 挑战没有胜利
     if args.challengeRes ~= CombatDefine.RESULT_WIN then
         -- 说明之前已经在跨服上保存玩家的基础数据了
-        if human.db.anotherWorlBattle then
-            return
-        end
+        -- if human.db.anotherWorlBattle then
+        --     return
+        -- end
 
         msgData.playerShowInfo = {
             name = human.db.name,
@@ -850,6 +851,8 @@ function C2N_ErrTips(msg)
         tips = Lang.AB_CITY_NO_GATHER
     elseif errCode == AnotherWorldBattleDefine.ERR_CODE_10 then
         tips = Lang.AB_OCCUPY_POINT_MAX
+    elseif errCode == AnotherWorldBattleDefine.ERR_CODE_11 then
+        tips = Lang.AB_POINT_CHALLENGING
     end
 
     Broadcast.sendErr(human, tips)
@@ -1266,9 +1269,12 @@ function C2N_Point_Lose(msg)
         ObjHuman.save(human) --后续可优化只更新 anotherWorlBattle 数据
     end
 
+
+    local cityCfg = AnotherWorldBattleConfig.city[loseCityId]
+
     -- 发邮件
     local mailCfg = MailExcel.mail[AnotherWorldBattleDefine.AB_LOSE_POINT_MAIL_ID]
-    local content = Util.format(mailCfg.content, losePointIdx)
+    local content = Util.format(mailCfg.content, cityCfg and cityCfg.cityName or "", loseCityId)
     MailManager.add(MailManager.SYSTEM, msg.playerUuid, mailCfg.title, content, nil, mailCfg.senderName or "GM")
 
     -- 把最新的防守阵容数据推给客户端

+ 2 - 1
script/module/anotherWorldBattle/Proto.lua

@@ -216,7 +216,8 @@ GC_AB_TREASURE_QUERY = {
     {"lottery2Cost",        2,      ItemData},  -- 双抽消耗
     {"lottery10Cost",       1,      ItemData},  -- 十连抽消耗
     {"lottery20Cost",       2,      ItemData},  -- 二十连抽消耗
-    {"nextLvProArr",        18,      "int"},    -- 下一级道具概率变化值列表
+    {"nextLvProArr",        18,     "int"},    -- 下一级道具概率变化值列表
+    {"isMaxLv",             1,      "byte"},   -- 是否已经满级, 0-没有, 1-满级
 }
 
 

+ 1 - 1
script/module/union/UnionLogic.lua

@@ -530,7 +530,7 @@ function applyJoinUnion(human, unionUuid)
     
         local res = isCanOperation(union)
         if not res then
-            return
+            return Broadcast.sendErr(human, Lang.AB_CANNOT_OPERATION)
         end
 
 		-- 自动同意