From 59557612e1f6c0237742f681748920b17f5e0e91 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 11 四月 2025 16:31:10 +0800
Subject: [PATCH] 10367 【越南】【英语】【BT】【砍树】仙盟攻城战-服务端(增加圣泉抽奖;积分总榜增加轮次积分明细记录;优化活动相关榜单排序规则,支持战斗阶段每分钟统计最新积分情况;优化轮次结算汇总信息;轮次支持升降级;)

---
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossFamilyGCZ.py |  336 +++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 235 insertions(+), 101 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossFamilyGCZ.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossFamilyGCZ.py
index 0b61fe1..3a82fa8 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossFamilyGCZ.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossFamilyGCZ.py
@@ -37,14 +37,14 @@
 import time
 
 
-## 1-公示期;99-领奖期;轮次状态=轮次*10+轮次阶段;轮次阶段:1-分组战备;2-战斗;3-休战结算
+## 1-公示期;99-领奖期;轮次状态=轮次*10+轮次阶段;轮次阶段:1-分组战备;2-战斗;3-休战
 FamilyGCZState_Publicity = 1 # 公示期
 FamilyGCZState_Award = 99 # 结束领奖期
 
 # 轮次状态信息
 FamilyGCZRoundState_Group = 1 # 分组+战备
 FamilyGCZRoundState_Fight = 2 # 战斗
-FamilyGCZRoundState_Over = 3 # 休战结算
+FamilyGCZRoundState_Over = 3 # 休战,该阶段可有可无,由策划配置决定,程序结算逻辑不依赖与此状态
 
 # 战场类型
 BatTypeList = (
@@ -52,6 +52,20 @@
 BatType_Middle, # 中级 2
 BatType_High, # 高级 3
 ) = range(1, 1 + 3)
+
+BatType_Min = BatType_Junior
+BatType_Max = BatType_High
+
+# 晋降级类型
+(
+UpdownState_None, # 未处理 0
+UpdownState_Down, # 降级 1
+UpdownState_Keep, # 保级 2
+UpdownState_Up, # 晋级 3
+) = range(4)
+
+# 每组固定仙盟数
+Def_PerGroupFamilyCnt = 12
 
 # 攻击类型
 (
@@ -276,7 +290,8 @@
         self.groupNum = 0
         self.campLV = 1 # 大本营等级
         self.campExp = 0
-        self.score = 0 # 活动总积分
+        self.roundInfoDict = {} # 仙盟轮次信息汇总 {轮次:{k:v, ...}, ...} k-batType,groupNum,rank,score,updownState
+        self.sortWeight = 0 # 榜单比较权值,用于平分或伤害相同时的比较权值
         
         self.familyName = ""
         self.lv = 0
@@ -314,6 +329,13 @@
         if isNotify:
             Sync_FamilyGCZCampInfo(self.zoneID, self.familyID)
         return isOK
+    
+    def GetTotalScore(self):
+        ## 获取仙盟当前总积分,所有轮次积分的总和
+        totalScore = 0
+        for info in self.roundInfoDict.values():
+            totalScore += info.get("score", 0)
+        return totalScore
     
     def AddCampExp(self, playerID, addCampExp, isNotify=True):
         ## 大本营加经验
@@ -491,6 +513,8 @@
         self.joinFamilyDict = {} # 参与仙盟对象信息 {familyID:FamilyGCZFamily, ...}
         self.joinMemberDict = {} # 参与玩家对象信息 {playerID:FamilyGCZMember, ...}
         self.roundGroupDict = {} # 当前轮次分组信息 {batType:{groupNum:FamilyGCZBatGroup, ...}, ...}
+        self.roundNum = 0 # roundGroupDict 数据对应的轮次
+        self.roundOver = 0 # roundNum轮次是否已结算了
         self.familyGuessDict = {} # 仙盟竞猜热度信息 {familyID:value, ...}
         self.playerGuessDict = {} # 玩家竞猜记录 {playerID:[familyID, ...], ...}
         
@@ -500,8 +524,10 @@
         self.inBatCityPlayerIDDict = {} # 在战斗城池中的玩家ID  {(batType, groupNum, cityID):[playerID, ...], ...}
         return
     
-    def OnRoundReset(self):
+    def OnRoundReset(self, roundNum):
         ## 分区轮次重置
+        self.roundNum = roundNum
+        self.roundOver = 0
         self.roundGroupDict = {}
         self.inBatScenePlayerIDDict = {}
         self.inBatCityPlayerIDDict = {}
@@ -722,6 +748,8 @@
         zone.lockFamilyIDList = zoneDataDict.get("lockFamilyIDList", [])
         zone.familyGuessDict = zoneDataDict.get("familyGuessDict", {})
         zone.playerGuessDict = zoneDataDict.get("playerGuessDict", {})
+        zone.roundNum = zoneDataDict.get("roundNum", 0)
+        zone.roundOver = zoneDataDict.get("roundOver", 0)
         GameWorld.Log("加载分区记录! zoneID=%s,joinFamilyCnt=%s,lockCnt=%s,%s" % (zoneID, zone.joinFamilyCnt, len(zone.lockFamilyIDList), zone.lockFamilyIDList))
         
         familyRecList = gameRecMgr.GetGameRecDataList(ShareDefine.Def_GameRecType_FamilyGCZJoinFamily, zoneID)
@@ -731,7 +759,6 @@
             groupNum = familyRecData.GetValue3()
             campLV = familyRecData.GetValue4()
             campExp = familyRecData.GetValue5()
-            score = familyRecData.GetValue6()
             familyDataDict = familyRecData.GetUserDataDict()
             
             joinFamily = zone.AddZoneJoinFamily(familyID)
@@ -739,7 +766,6 @@
             joinFamily.groupNum = groupNum
             joinFamily.campLV = campLV
             joinFamily.campExp = campExp
-            joinFamily.score = score
             joinFamily.familyName = familyDataDict.get("familyName", "")
             joinFamily.leaderID = familyDataDict.get("leaderID", 0)
             joinFamily.leaderName = familyDataDict.get("leaderName", "")
@@ -749,9 +775,11 @@
             joinFamily.fightPowerTotal = familyDataDict.get("fightPowerTotal", 0)
             joinFamily.joinMemberIDList = familyDataDict.get("joinMemberIDList", [])
             joinFamily.memAddCampExpInfo = familyDataDict.get("memAddCampExpInfo", {})
+            joinFamily.roundInfoDict = familyDataDict.get("roundInfoDict", {})
+            joinFamily.sortWeight = familyDataDict.get("sortWeight", 0)
             
-            GameWorld.Log("    加载分区仙盟 zoneID=%s,%s,familyID=%s,campLV=%s-%s,score=%s,,memAddCampExpInfo=%s" 
-                          % (zoneID, fNum, familyID, joinFamily.campLV, joinFamily.campExp, joinFamily.score, joinFamily.memAddCampExpInfo))
+            GameWorld.Log("    加载分区仙盟 zoneID=%s,%s,familyID=%s,campLV=%s-%s,roundInfoDict=%s" 
+                          % (zoneID, fNum, familyID, joinFamily.campLV, joinFamily.campExp, joinFamily.roundInfoDict))
             
         memberRecList = gameRecMgr.GetGameRecDataList(ShareDefine.Def_GameRecType_FamilyGCZJoinMember, zoneID)
         for pNum, memberRecData in enumerate(memberRecList, 1):
@@ -842,7 +870,8 @@
         zoneRecData = gameRecMgr.AddGameRecData(ShareDefine.Def_GameRecType_FamilyGCZMgr, zoneID)
         zoneRecData.SetValue1(zone.joinFamilyCnt)
         lockFamilyIDList = zone.GetZoneLockFamilyIDList()
-        zoneData = {"lockFamilyIDList":lockFamilyIDList, "familyGuessDict":zone.familyGuessDict, "playerGuessDict":zone.playerGuessDict}
+        zoneData = {"lockFamilyIDList":lockFamilyIDList, "familyGuessDict":zone.familyGuessDict, "playerGuessDict":zone.playerGuessDict, 
+                    "roundNum":zone.roundNum, "roundOver":zone.roundOver}
         zoneRecData.SetUserData(zoneData)
         
         GameWorld.Log("----- zoneID=%s,joinFamilyCnt=%s,lockFamilyIDList=%s,%s" % (zoneID, zone.joinFamilyCnt, len(lockFamilyIDList), lockFamilyIDList))
@@ -881,14 +910,14 @@
             familyRecData.SetValue3(joinFamily.groupNum)
             familyRecData.SetValue4(joinFamily.campLV)
             familyRecData.SetValue5(joinFamily.campExp)
-            familyRecData.SetValue6(joinFamily.score)
             
             familyData = {"familyName":joinFamily.familyName, "leaderID":joinFamily.leaderID, "leaderName":joinFamily.leaderName,
                           "lv":joinFamily.lv, "emblemID":joinFamily.emblemID, "serverID":joinFamily.serverID, "fightPowerTotal":joinFamily.fightPowerTotal,
-                          "joinMemberIDList":joinFamily.joinMemberIDList, "memAddCampExpInfo":joinFamily.memAddCampExpInfo
+                          "joinMemberIDList":joinFamily.joinMemberIDList, "memAddCampExpInfo":joinFamily.memAddCampExpInfo, 
+                          "roundInfoDict":joinFamily.roundInfoDict, "sortWeight":joinFamily.sortWeight
                           }
             familyRecData.SetUserData(familyData)
-            GameWorld.Log("    保存分区仙盟 zoneID=%s,%s,familyID=%s,campLV=%s-%s,score=%s," % (zoneID, fNum, familyID, joinFamily.campLV, joinFamily.campExp, joinFamily.score))
+            GameWorld.Log("    保存分区仙盟 zoneID=%s,%s,familyID=%s,campLV=%s-%s,roundInfoDict=%s" % (zoneID, fNum, familyID, joinFamily.campLV, joinFamily.campExp, joinFamily.roundInfoDict))
             
             for pNum, playerID in enumerate(joinFamily.joinMemberIDList, 1):
                 joinMember = zone.GetZoneJoinMember(playerID)
@@ -983,9 +1012,9 @@
             zone = gczMgr.GetActZone(zoneID)
             zone.OnRoundFightStart()
             
-        # 结算
+        # 结算,注:程序的结算流程不依赖与此状态,如果策划有配置,则直接在该阶段结算,如果没有配置则在分组时、活动领奖时之前校验上一轮结算
         elif roundState == FamilyGCZRoundState_Over:
-            DoRoundOver(curRound, zoneID)
+            DoRoundOver(zoneID)
             
     else:
         pass
@@ -1137,7 +1166,8 @@
     ## 执行轮次分组
     
     GameWorld.Log("========== 仙盟攻城战轮次分组: zoneID=%s,curRound=%s,joinFamilyCnt=%s" % (zoneID, curRound, joinFamilyCnt))
-    # 参与仙盟数对应分组及晋级规则 {参与仙盟数:{轮次:{战场类型:[组数, 前x名晋级, x名开始降级], ...}, ...}, ...}
+    DoRoundOver(zoneID)
+    # 参与仙盟数对应分组及晋级规则 {参与仙盟数:{轮次:{战场类型:[组数, 前x名晋级, 后x名降级], ...}, ...}, ...}
     FamilyGCZGroupSet = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZGroupSet", 1, {})
     if joinFamilyCnt not in FamilyGCZGroupSet:
         return
@@ -1147,55 +1177,38 @@
     batTypeDict = roundSetDict[curRound]
     
     groupValue1 = zoneID
-    billboardMgr = PyDataManager.GetCrossBillboardManager()
     gczMgr = GetFamilyGCZMgr()
     zone = gczMgr.GetActZone(zoneID)
-    
-    # 先处理上一轮晋级、保级、降级,需在重置前处理
-    nextBatTypeFamilyInfo = {} # 下一轮战场仙盟ID分配信息 {batType:[familyID, ...], ....}
-    preRound = curRound - 1
-    preBatTypeDict = roundSetDict.get(preRound, {})
-    for batType in BatTypeList: # 按战场类型顺序遍历处理
-        if batType not in zone.roundGroupDict:
-            continue
-        groupDict = zone.roundGroupDict[batType]
-        groupNumList = groupDict.keys()
-        groupNumList.sort()
-        preRoundSet = preBatTypeDict.get(batType, [0, 0])
-        upRank = preRoundSet[1] # 前x晋级
-        downRank = preRoundSet[2] if len(preRoundSet) > 2 else 0 # 大于等于x名降级,为0时不降级
-        GameWorld.Log("上轮战场类型分组: preRound=%s,batType=%s,upRank=%s,downRank=%s,%s" % (preRound, batType, upRank, downRank, groupNumList))
-        for groupNum in groupNumList:
-            groupValue2 = GetRoundHurtGroupID(batType, groupNum)
-            billboardObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZRoundHurt, groupValue1, groupValue2)
-            billboardObj.SortData()
-            upFamilyIDList, keepFamilyIDList, downFamilyIDList = [], [], []
-            for bIndex in range(billboardObj.GetCount()):
-                billData = billboardObj.At(bIndex)
-                familyID = billData.ID
-                rank = bIndex + 1
-                if rank <= upRank:
-                    nextBatType = min(BatType_High, batType + 1)
-                    upFamilyIDList.append(familyID)
-                elif downRank and rank >= downRank:
-                    nextBatType = max(BatType_Junior, batType - 1)
-                    downFamilyIDList.append(familyID)
-                # 除了升降级的就是保级
-                else:
-                    nextBatType = batType
-                    keepFamilyIDList.append(familyID)
-                    
-                if nextBatType not in nextBatTypeFamilyInfo:
-                    nextBatTypeFamilyInfo[nextBatType] = []
-                familyIDList = nextBatTypeFamilyInfo[nextBatType]
-                if familyID not in familyIDList:
-                    familyIDList.append(familyID)
-            GameWorld.Log("    升保降级zoneID=%s,batType=%s,groupNum=%s,up:%s,keep:%s,down:%s,%s" 
-                          % (zoneID, batType, groupNum, upFamilyIDList, keepFamilyIDList, downFamilyIDList, nextBatTypeFamilyInfo))
-            
+        
+    #汇总上一轮升降级明细
+    nextBatTypeFamilyInfo = {} # 根据上一轮结算的升降级状态汇总出的本轮仙盟ID战场归组
+    if curRound > 1:
+        preRound = curRound - 1
+        lockFamilyIDList = zone.GetZoneLockFamilyIDList()
+        for familyID in lockFamilyIDList:
+            joinFamily = zone.GetZoneJoinFamily(familyID)
+            if not joinFamily:
+                continue
+            roundInfo = joinFamily.roundInfoDict.get(preRound, {})
+            batType = roundInfo.get("batType", BatType_Min) # 默认最低级
+            updownState = roundInfo.get("updownState", UpdownState_Keep) # 默认保级
+            if updownState == UpdownState_Up:
+                nextBatType = min(batType + 1, BatType_Max)
+            elif updownState == UpdownState_Down:
+                nextBatType = max(batType - 1, BatType_Min)
+            else:
+                nextBatType = batType
+            if nextBatType not in nextBatTypeFamilyInfo:
+                nextBatTypeFamilyInfo[nextBatType] = []
+            batFamilyIDList = nextBatTypeFamilyInfo[nextBatType]
+            if familyID not in batFamilyIDList:
+                batFamilyIDList.append(familyID)
+        GameWorld.Log("上一轮升降级结算汇总: %s" % nextBatTypeFamilyInfo)
+        
     #每轮重新分组时,重置该分区下的轮次伤害相关榜单
+    billboardMgr = PyDataManager.GetCrossBillboardManager()
     billboardMgr.ClearBillboard(ShareDefine.Def_CBT_FamilyGCZRoundHurt, groupValue1)
-    zone.OnRoundReset()
+    zone.OnRoundReset(curRound)
     
     for batType in BatTypeList: # 按战场类型顺序遍历处理
         if batType not in batTypeDict:
@@ -1232,16 +1245,16 @@
             if not joinFamily:
                 continue
             groupFamilySortList.append(joinFamily)
-            groupFamilyDict[familyID] = [joinFamily.fightPowerTotal, joinFamily.score]
+            groupFamilyDict[familyID] = [joinFamily.fightPowerTotal, joinFamily.GetTotalScore()]
             
         # 先按总战力倒序,可扩展积分等
-        groupFamilySortList.sort(key=lambda f: (f.fightPowerTotal, f.score), reverse=True)
+        groupFamilySortList.sort(key=lambda f: (f.fightPowerTotal, f.GetTotalScore()), reverse=True)
         groupFamilyIDSortList = [f.familyID for f in groupFamilySortList]
-        
-        GameWorld.Log("开始分组按排序后的顺序循环插入每组! 仙盟数:%s, %s, %s" % (len(groupFamilyIDSortList), groupFamilyIDSortList, groupFamilyDict))
+        groupFamilyIDCnt = len(groupFamilyIDSortList)
+        GameWorld.Log("开始分组按排序后的顺序循环插入每组! 仙盟数:%s, %s, %s" % (groupFamilyIDCnt, groupFamilyIDSortList, groupFamilyDict))
         
         groupNum = 0
-        for familyID in groupFamilyIDSortList:
+        for index, familyID in enumerate(groupFamilyIDSortList):
             groupNum += 1
             if groupNum > groupCnt:
                 groupNum = 1
@@ -1253,10 +1266,12 @@
             if not joinFamily:
                 GameWorld.ErrLog("仙盟分配到战斗分组失败! zoneID=%s,batType=%s,groupNum=%s,familyID=%s" % (zoneID, batType, groupNum, familyID))
                 continue
+            joinFamily.sortWeight = batType * 10000 + (100 - groupNum) * 100 + (groupFamilyIDCnt - index)
             UndFamilyRoundHurtBillboard(joinFamily)
             GameWorld.Log("    仙盟ID分组: zoneID=%s,curRound=%s,batType=%s,groupNum=%s,familyID=%s,%s" % (zoneID, curRound, batType, groupNum, familyID, groupFamilyDict[familyID]))
             
     Sync_FamilyGCZBatGroupInfo(zoneID)
+    RefreshFamilyGCZBillboard(zoneID, True) # 分组完毕后,有新轮次数据了,强制刷新一次榜单,更新新一轮的积分
     return
 
 def UndFamilyRoundHurtBillboard(joinFamily):
@@ -1275,24 +1290,138 @@
     roundTotalHurt = sum(joinFamily.cityWall.fighterHurtDict.values())
     cmpValue = roundTotalHurt / ChConfig.Def_PerPointValue
     cmpValue2 = roundTotalHurt % ChConfig.Def_PerPointValue
+    cmpValue3 = joinFamily.sortWeight
     CrossBillboard.UpdCrossBillboard(ShareDefine.Def_CBT_FamilyGCZRoundHurt, groupValue1, dataID, name1, name2, type2, value1, value2,
-                                     cmpValue, cmpValue2, groupValue2=groupValue2, id2=id2, autoSort=True, value3=value3, value5=value5)
+                                     cmpValue, cmpValue2, cmpValue3, groupValue2=groupValue2, id2=id2, autoSort=True, value3=value3, value5=value5)
     return
 
-def DoRoundOver(curRound, zoneID):
-    ## 执行轮次结算
+def OnMinuteProcess(curMinute):
+    ## 每分钟处理
+    if not GameWorld.IsCrossServer():
+        return
+    
+    gczMgr = GetFamilyGCZMgr()
+    zoneIDList = gczMgr.zoneDict.keys()
+    if not zoneIDList:
+        return
+    
+    for zoneID in zoneIDList:
+        if not zoneID:
+            continue
+        RefreshFamilyGCZBillboard(zoneID)
+        
+    return
+
+def RefreshFamilyGCZBillboard(zoneID, force=False):
+    ## 刷新并排序当前活动相关榜单
+    
+    # 非强制刷新的,仅战斗阶段定时刷新
+    if not force:
+        actInfo = CrossActionControl.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+        if not actInfo:
+            return
+        state = actInfo.get(ShareDefine.ActKey_State)
+        if not state:
+            return
+        curRound, roundState = GetRoundState(state)
+        # 仅轮次战斗阶段需要定时刷新
+        if not curRound or roundState != FamilyGCZRoundState_Fight:
+            return
+        
     gczMgr = GetFamilyGCZMgr()
     zone = gczMgr.GetActZone(zoneID)
-    billboardMgr = PyDataManager.GetCrossBillboardManager()
-    batTypeScoreInfo = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZGroupSet", 2, {})
-    GameWorld.Log("========== 仙盟攻城战轮次结算: zoneID=%s,curRound=%s" % (zoneID, curRound))
+    if zone.roundOver:
+        # 轮次数据已经结算过了,不需要再处理
+        return
+    roundNum = zone.roundNum
+    if not roundNum:
+        return
+    GameWorld.DebugLog("仙盟攻城战榜单排序! zoneID=%s,roundNum=%s,force=%s" % (zoneID, roundNum, force))
+    
+    billboardMgr = PyDataManager.GetCrossBillboardManager()    
+    playerHurtBillObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZPlayerHurt, zoneID)
+    playerHurtBillObj.SortData()
+    
+    batTypeScoreInfo = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZGroupSet", 2, {}) # 不同战场类型仙盟排名对应积分 {"战场类型":{"名次":积分, ...}, ...}
     for batType, groupDict in zone.roundGroupDict.items():
         rankScoreInfo = batTypeScoreInfo.get(str(batType), {})
         if not rankScoreInfo:
             GameWorld.ErrLog("仙盟攻城战战场类型没有配置名次积分! batType=%s" % batType)
         rankScoreDict = {int(k):v for k, v in rankScoreInfo.items()}
         groupNumList = groupDict.keys()
-        GameWorld.Log("zoneID=%s,batType=%s,groupCnt=%s,rankScoreDict=%s" % (zoneID, batType, len(groupNumList), rankScoreDict))
+        for groupNum in groupNumList:
+            batGroup = zone.GetBatGroup(batType, groupNum)
+            if not batGroup:
+                continue
+            groupValue2 = GetRoundHurtGroupID(batType, groupNum)
+            roundBillboardObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZRoundHurt, zoneID, groupValue2)
+            roundBillboardObj.SortData()
+            for bIndex in range(roundBillboardObj.GetCount()):
+                billData = roundBillboardObj.At(bIndex)
+                familyID = billData.ID
+                rank = bIndex + 1
+                score = GameWorld.GetOrderValueByDict(rankScoreDict, rank, False, 0)
+                joinFamily = zone.GetZoneJoinFamily(familyID)
+                if not joinFamily:
+                    continue
+                roundInfo = joinFamily.roundInfoDict.get(roundNum, {})
+                roundInfo.update({"batType":batType, "groupNum":groupNum, "rank":rank, "score":score})
+                joinFamily.roundInfoDict[roundNum] = roundInfo
+                
+    lockFamilyIDList = zone.GetZoneLockFamilyIDList()
+    for familyID in lockFamilyIDList:
+        joinFamily = zone.GetZoneJoinFamily(familyID)
+        if not joinFamily:
+            continue
+        dataID = joinFamily.familyID
+        name1 = joinFamily.familyName
+        id2 = joinFamily.leaderID
+        name2 = joinFamily.leaderName
+        type2, value1, value2 = 0, 0, 0
+        value3 = joinFamily.emblemID
+        value5 = joinFamily.serverID
+        cmpValue = joinFamily.GetTotalScore()
+        cmpValue2 = joinFamily.sortWeight
+        CrossBillboard.UpdCrossBillboard(ShareDefine.Def_CBT_FamilyGCZScore, zoneID, dataID, name1, name2, type2, value1, value2,
+                                         cmpValue, cmpValue2=cmpValue2, id2=id2, autoSort=False, value3=value3, value5=value5, userData=joinFamily.roundInfoDict)
+        
+    familyScoreBillObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZScore, zoneID)
+    familyScoreBillObj.SortData()
+    return
+
+def DoRoundOver(zoneID):
+    ## 执行轮次结算,这里可以不用管是第几轮,对于结算来说只对当前的轮次数据做结算
+    gczMgr = GetFamilyGCZMgr()
+    zone = gczMgr.GetActZone(zoneID)
+    if zone.roundOver:
+        # 已经结算过了,不重复结算
+        return
+    roundNum = zone.roundNum
+    if not roundNum:
+        # 还没有轮次不处理
+        return
+    RefreshFamilyGCZBillboard(zoneID, True) # 强制刷新一次榜单
+    
+    joinFamilyCnt = zone.joinFamilyCnt
+    # 参与仙盟数对应分组及晋级规则 {参与仙盟数:{轮次:{战场类型:[组数, 前x名晋级, 后x名降级], ...}, ...}, ...}
+    FamilyGCZGroupSet = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZGroupSet", 1, {})
+    if joinFamilyCnt not in FamilyGCZGroupSet:
+        return
+    roundSetDict = FamilyGCZGroupSet[joinFamilyCnt]
+    if roundNum not in roundSetDict:
+        return
+    batTypeDict = roundSetDict[roundNum]
+    
+    billboardMgr = PyDataManager.GetCrossBillboardManager()
+    GameWorld.Log("========== 仙盟攻城战轮次结算: zoneID=%s,roundNum=%s" % (zoneID, roundNum))
+    for batType, groupDict in zone.roundGroupDict.items():
+        if batType not in batTypeDict:
+            continue
+        batTypeSet = batTypeDict[batType]
+        upRank = batTypeSet[1] # 前x晋级
+        downRank = batTypeSet[2] if len(batTypeSet) > 2 else 0 # 后x名降级,为0时不降级
+        groupNumList = groupDict.keys()
+        GameWorld.Log("zoneID=%s,batType=%s,upRank=%s,downRank=%s,groupNumList=%s" % (zoneID, batType, upRank, downRank, groupNumList))
         for groupNum in groupNumList:
             batGroup = zone.GetBatGroup(batType, groupNum)
             if not batGroup:
@@ -1300,41 +1429,32 @@
             
             groupValue2 = GetRoundHurtGroupID(batType, groupNum)
             billboardObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZRoundHurt, zoneID, groupValue2)
-            billboardObj.SortData()
-            GameWorld.Log("zoneID=%s,batType=%s,groupNum=%s,roundHurtFamilyCnt=%s" % (zoneID, batType, groupNum, billboardObj.GetCount()))
+            GameWorld.Log("zoneID=%s,batType=%s,groupNum=%s,groupFamilyCnt=%s" % (zoneID, batType, groupNum, billboardObj.GetCount()))
             for bIndex in range(billboardObj.GetCount()):
                 billData = billboardObj.At(bIndex)
                 familyID = billData.ID
-                hurtValue = billData.CmpValue
-                hurtValueEx = billData.CmpValue2
-                hurtValueTotal = hurtValue * ChConfig.Def_PerPointValue + hurtValueEx
+                cmpValue = billData.CmpValue
+                cmpValue2 = billData.CmpValue2
+                hurtValueTotal = cmpValue * ChConfig.Def_PerPointValue + cmpValue2
                 rank = bIndex + 1
-                addScore = GameWorld.GetOrderValueByDict(rankScoreDict, rank, False, 0)
-                
+                updownState = UpdownState_Keep # 本轮结算晋级降级状态:0-未处理,1-降级;2-保级;3-晋级,即本轮的晋降级状态决定下一轮的战场类型
+                if rank <= upRank and batType < BatType_Max:
+                    updownState = UpdownState_Up
+                elif downRank and rank > (Def_PerGroupFamilyCnt - downRank) and batType > BatType_Min:
+                    updownState = UpdownState_Down
+                    
                 joinFamily = zone.GetZoneJoinFamily(familyID)
                 if not joinFamily:
                     continue
-                joinFamily.score += addScore
-                GameWorld.Log("    zoneID=%s,batType=%s,groupNum=%s,rank=%s,familyID=%s,addScore=%s,updScore=%s,hurtValueTotal=%s" 
-                              % (zoneID, batType, groupNum, rank, familyID, addScore, joinFamily.score, hurtValueTotal))
+                roundInfo = joinFamily.roundInfoDict.get(roundNum, {})
+                roundInfo.update({"updownState":updownState})
+                joinFamily.roundInfoDict[roundNum] = roundInfo
                 
-                dataID = joinFamily.familyID
-                name1 = joinFamily.familyName
-                id2 = joinFamily.leaderID
-                name2 = joinFamily.leaderName
-                type2, value1, value2 = 0, 0, 0
-                value3 = joinFamily.emblemID
-                value5 = joinFamily.serverID
-                cmpValue = joinFamily.score
-                CrossBillboard.UpdCrossBillboard(ShareDefine.Def_CBT_FamilyGCZScore, zoneID, dataID, name1, name2, type2, value1, value2,
-                                                 cmpValue, id2=id2, autoSort=False, value3=value3, value5=value5)
+                GameWorld.Log("    升保降级zoneID=%s,batType=%s,groupNum=%s,rank=%s,familyID=%s,updownState=%s,hurtValueTotal=%s" 
+                              % (zoneID, batType, groupNum, rank, familyID, updownState, hurtValueTotal))
+                Sync_FamilyGCZCampInfo(zoneID, familyID)
                 
-    # 都加完积分后统一排序
-    familyScoreBillObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZScore, zoneID)
-    familyScoreBillObj.SortData()
-    
-    playerHurtBillObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZPlayerHurt, zoneID)
-    playerHurtBillObj.SortData()
+    zone.roundOver = 1 # 标记已结算
     return
 
 def DoGenerateGuess(zoneID, state):
@@ -1360,6 +1480,8 @@
 
 def DoStartAward(zoneID):
     ## 开始领奖
+    
+    DoRoundOver(zoneID)
     
     # 下发竞猜统计结果
     Sync_FamilyGCZGuessInfo(zoneID)
@@ -2595,9 +2717,11 @@
     guessCountMax = IpyGameDataPY.GetFuncCfg("FamilyGCZGuess", 3)
     billboardMgr = PyDataManager.GetCrossBillboardManager()
     scoreBillObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZScore, zoneID)
-    for index in range(guessCountMax):
+    for index in range(scoreBillObj.GetCount()):
         billData = scoreBillObj.At(index)
         finalFamilyIDList.append(billData.ID)
+        if len(finalFamilyIDList) >= guessCountMax:
+            break
         
     # 统计竞猜结果
     rightRankAwardIDDict = GameWorld.GetActGuessRightRankAwardIDDict(guessTemplateID)
@@ -2712,7 +2836,7 @@
         return
     
     clientPack = ChPyNetSendPack.tagGCFamilyGCZBatGroupInfo()
-    clientPack.RoundNum = curRound
+    clientPack.RoundNum = zone.roundNum
     clientPack.BatList = []
     for batType, groupNumDict in zone.roundGroupDict.items():
         batInfo = ChPyNetSendPack.tagGCFamilyGCZBat()
@@ -2753,7 +2877,6 @@
     clientPack = ChPyNetSendPack.tagGCFamilyGCZCampInfo()
     clientPack.Clear()
     clientPack.FamilyID = familyID
-    clientPack.Score = joinFamily.score
     clientPack.CampLV = joinFamily.campLV
     clientPack.CampExp = joinFamily.campExp
     clientPack.CityLV = joinFamily.cityWall.cityLV
@@ -2763,6 +2886,17 @@
     clientPack.HPMaxEx = joinFamily.cityWall.hpMax / ChConfig.Def_PerPointValue
     clientPack.HP = joinFamily.cityWall.hp % ChConfig.Def_PerPointValue
     clientPack.HPEx = joinFamily.cityWall.hp / ChConfig.Def_PerPointValue
+    clientPack.RoundInfoList = []
+    for roundNum, info in joinFamily.roundInfoDict.items():
+        roundObj = ChPyNetSendPack.tagGCFamilyGCZCampRound()
+        roundObj.RoundNum = roundNum
+        roundObj.BatType = info.get("batType", 0)
+        roundObj.GroupNum = info.get("groupNum", 0)
+        roundObj.Rank = info.get("rank", 0)
+        roundObj.Score = info.get("score", 0)
+        roundObj.UpdownState = info.get("updownState", 0)
+        clientPack.RoundInfoList.append(roundObj)
+    clientPack.RoundCnt = len(clientPack.RoundInfoList)
     clientPack.DefMemList = []
     for playerID in joinFamily.joinMemberIDList:                
         if defMemIDList != None and playerID not in defMemIDList:

--
Gitblit v1.8.0