From 11cee37fbb7f88498d0a4649b3d21a9cc2ddfcc6 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 31 十二月 2024 15:07:51 +0800
Subject: [PATCH] 10350 【后端】【越南】【英文】【BT】【砍树】跨服竞技场优化(跨服排位)

---
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py                                          |  444 +++++++++++--------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/MirrorAttack.py                                  |   79 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                                          |    4 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFB.py                                                           |    2 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py                                                        |    5 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                                      |   56 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetCrossPK.py                               |   14 
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py                                                           |   56 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py                            |   14 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PlayerMirror.py                             |    4 
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py                                              |    3 
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py                                           |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossChampionship.py |  621 +++------------------------
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py                                             |    2 
 ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py                                                               |    4 
 15 files changed, 513 insertions(+), 797 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index 4158f76..327fa7b 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -17238,48 +17238,74 @@
 # C0 15 跨服排位分区分组信息 #tagGCCrossChampionshipPKZoneGroupInfo
 
 class  tagGCCrossChampionshipPKBattle(Structure):
-    _pack_ = 1
-    _fields_ = [
-                  ("BattleNum", c_ubyte),    # 对战组编号 1~n
-                  ("WinPlayerID", c_int),    # 获胜玩家ID
-                  ("PlayerIDA", c_int),    # 玩家IDA
-                  ("PlayerIDB", c_int),    # 玩家IDB
-                  ]
+    BattleNum = 0    #(BYTE BattleNum)// 对战组编号 1~n
+    WinPlayerID = 0    #(DWORD WinPlayerID)// 获胜玩家ID
+    PlayerIDA = 0    #(DWORD PlayerIDA)// 玩家IDA
+    PlayerIDB = 0    #(DWORD PlayerIDB)// 玩家IDB
+    BattleRetLen = 0    #(BYTE BattleRetLen)
+    BattleRet = ""    #(String BattleRet)// 战斗结果明细 {"playerID":[[第1局胜负,第1局总积分,胜负基础分,hp分,时间分], ...], ...}
+    data = None
 
     def __init__(self):
         self.Clear()
         return
 
-    def ReadData(self, stringData, _pos=0, _len=0):
+    def ReadData(self, _lpData, _pos=0, _Len=0):
         self.Clear()
-        memmove(addressof(self), stringData[_pos:], self.GetLength())
-        return _pos + self.GetLength()
+        self.BattleNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.WinPlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.PlayerIDA,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.PlayerIDB,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.BattleRetLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.BattleRet,_pos = CommFunc.ReadString(_lpData, _pos,self.BattleRetLen)
+        return _pos
 
     def Clear(self):
         self.BattleNum = 0
         self.WinPlayerID = 0
         self.PlayerIDA = 0
         self.PlayerIDB = 0
+        self.BattleRetLen = 0
+        self.BattleRet = ""
         return
 
     def GetLength(self):
-        return sizeof(tagGCCrossChampionshipPKBattle)
+        length = 0
+        length += 1
+        length += 4
+        length += 4
+        length += 4
+        length += 1
+        length += len(self.BattleRet)
+
+        return length
 
     def GetBuffer(self):
-        return string_at(addressof(self), self.GetLength())
+        data = ''
+        data = CommFunc.WriteBYTE(data, self.BattleNum)
+        data = CommFunc.WriteDWORD(data, self.WinPlayerID)
+        data = CommFunc.WriteDWORD(data, self.PlayerIDA)
+        data = CommFunc.WriteDWORD(data, self.PlayerIDB)
+        data = CommFunc.WriteBYTE(data, self.BattleRetLen)
+        data = CommFunc.WriteString(data, self.BattleRetLen, self.BattleRet)
+        return data
 
     def OutputString(self):
-        DumpString = '''// C0 15 跨服排位分区分组信息 //tagGCCrossChampionshipPKZoneGroupInfo:
+        DumpString = '''
                                 BattleNum:%d,
                                 WinPlayerID:%d,
                                 PlayerIDA:%d,
-                                PlayerIDB:%d
+                                PlayerIDB:%d,
+                                BattleRetLen:%d,
+                                BattleRet:%s
                                 '''\
                                 %(
                                 self.BattleNum,
                                 self.WinPlayerID,
                                 self.PlayerIDA,
-                                self.PlayerIDB
+                                self.PlayerIDB,
+                                self.BattleRetLen,
+                                self.BattleRet
                                 )
         return DumpString
 
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py
index 8d2a68e..93bbf87 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py
@@ -352,7 +352,7 @@
 def CopyBillboardOnDay():
     billboardMgr = PyDataManager.GetCrossBillboardManager()
     for billboardType in ShareDefine.CrossBillboardTypeList:
-        if billboardType in [ShareDefine.Def_CBT_BossTrialSubmitBak, ShareDefine.Def_CBT_BossTrialSubmitFamilyBak]:
+        if billboardType in [ShareDefine.Def_CBT_BossTrialSubmitBak, ShareDefine.Def_CBT_BossTrialSubmitFamilyBak, ShareDefine.Def_CBT_CrossRealmPK]:
             continue
         groupList = billboardMgr.GetBillboardGroupList(billboardType)
         for billboardType, groupValue1, groupValue2 in groupList:
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py
index 1dc3178..294786f 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py
@@ -38,6 +38,7 @@
 import datetime
 import random
 import time
+import json
 
 Def_CrossChampionshipPlayerMax = 64 # 最大玩家数
 Def_CrossChampionshipPlayerWFCount = 8 # 胜负排位所需玩家数
@@ -52,6 +53,7 @@
 value3:playerIDA        玩家IDA
 value4:playerIDB        玩家IDB
 value5:winPlayerID      获胜玩家ID
+strValue3:battleDict    镜像PK场次结果 {"玩家ID":[[第1场胜负,加积分,...], ...], ...}
 '''
 
 Def_RecType_CrossChampionshipGuess = ShareDefine.Def_UniversalGameRecType_CrossChampionshipGuess
@@ -238,6 +240,7 @@
         self.playerIDA = 0
         self.playerIDB = 0
         self.winPlayerID = 0
+        self.playerBatDict = {} # 镜像PK场次结果 {"玩家ID":[[第1场胜负,加积分,...], ...], ...}
         
         # 不存档
         self.roomID = 0
@@ -247,7 +250,7 @@
     
     def GetString(self):
         return {"overTime":self.overTime, "zoneID":self.zoneID, "groupMark":self.groupMark, "battleNum":self.battleNum,
-                "playerIDA":self.playerIDA, "playerIDB":self.playerIDB, "winPlayerID":self.winPlayerID}
+                "playerIDA":self.playerIDA, "playerIDB":self.playerIDB, "winPlayerID":self.winPlayerID, "playerBatDict":self.playerBatDict}
         
     def SetAttr(self, attrDict):
         for k, v in attrDict.items():
@@ -287,7 +290,24 @@
             GameWorld.Log("无该跨服排位争霸赛对战场次信息: groupMark=%s,battleNum=%s" % (groupMark, battleNum))
             
         # 不可能执行的代码,方便 . 出提示代码
-        if False:
+        if not battle and False:
+            battle = ChampionshipBattle()
+        return battle
+    
+    def GetBattleByPlayerID(self, groupMark, playerID):
+        battle = None
+        if groupMark in self.battleInfo:
+            battleDict = self.battleInfo[groupMark]
+            for bat in battleDict.values():
+                if playerID == bat.playerIDA or playerID == bat.playerIDB:
+                    battle = bat
+                    break
+                
+        if not battle:
+            GameWorld.Log("无该跨服排位争霸赛对战场次信息: groupMark=%s,playerID=%s" % (groupMark, playerID))
+            
+        # 不可能执行的代码,方便 . 出提示代码
+        if not battle and False:
             battle = ChampionshipBattle()
         return battle
     
@@ -331,6 +351,19 @@
     
     # 机器人
     if not obj or not hasattr(obj, "playerName"):
+        return
+    
+    packDataObj = PyDataManager.GetDBPlayerPackDataManager().GetPlayerPackObj(playerID)
+    # 如果有打包数据,以打包数据为准
+    if packDataObj:
+        obj.accID = packDataObj.accID
+        obj.playerName = packDataObj.playerName
+        obj.job = packDataObj.job
+        obj.lv = packDataObj.lv
+        obj.fightPower = packDataObj.fightPower
+        obj.realmLV = packDataObj.realmLV
+        obj.face = packDataObj.face
+        obj.facePic = packDataObj.facePic
         return
     
     if playerID < 10000:
@@ -448,7 +481,11 @@
         playerIDA = recData.GetValue3()
         playerIDB = recData.GetValue4()
         winPlayerID = recData.GetValue5()
-        
+        strValue3 = recData.GetStrValue3()
+        try:
+            playerBatDict = eval(strValue3) if strValue3 else {}
+        except:
+            playerBatDict = {}
         #if not playerIDA and not playerIDB:
         #    continue
         
@@ -466,6 +503,7 @@
             battle.playerIDA = playerIDA
             battle.playerIDB = playerIDB
             battle.winPlayerID = winPlayerID
+            battle.playerBatDict = playerBatDict
             pkZoneMgr.AddBattle(groupMark, battleNum, battle)
             GameWorld.Log("分组玩家: zoneID=%s,groupMark=%s,battleNum=%s,playerIDA=%s,playerIDB=%s,winPlayerID=%s" 
                           % (zoneID, groupMark, battleNum, playerIDA, playerIDB, winPlayerID))
@@ -608,6 +646,9 @@
                 recData.SetValue3(batObj.playerIDA)
                 recData.SetValue4(batObj.playerIDB)
                 recData.SetValue5(batObj.winPlayerID)
+                strValue3 = "%s" % batObj.playerBatDict
+                strValue3 = strValue3.replace(" ", "")
+                recData.SetStrValue3(strValue3)
                 
     GameWorld.Log("保存跨服排位玩家竞猜记录!")
     universalRecMgr.Delete(Def_RecType_CrossChampionshipGuess)
@@ -852,14 +893,14 @@
     PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipErrorDo, 1)
     return "OK"
 
-def OnMinuteProcess(curMinute):
+def OnMinuteProcess(curMinute=None):
     if not GameWorld.IsCrossServer():
         return
     
     Dispose_CrossChampionshipState()
     
     # 每半小时存档一次
-    if curMinute % 30 == 0:
+    if curMinute != None and curMinute % 30 == 0:
         SaveChampionshipData()
     return
 
@@ -1085,31 +1126,32 @@
     
     # 生成参赛玩家名单: 取跨服PK所有分区 championshipSeason 赛季的数据
     if championshipSeason:
-        crossPKBillboardMgr = PyDataManager.GetCrossPKBillboardManager()
+        crossBillboardMgr = PyDataManager.GetCrossBillboardManager()
         for zoneID in hisZoneIDList:
-            billboardList = crossPKBillboardMgr.GetCrossPKBillboardInfo(zoneID, championshipSeason)[0]
-            GameWorld.Log("zoneID=%s,billboardListLen=%s" % (zoneID, len(billboardList)))
-            if not billboardList:
+            groupValue1, groupValue2 = zoneID, championshipSeason
+            billboardObj = crossBillboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_CrossRealmPK, groupValue1, groupValue2)
+            billboardDataLen = billboardObj.GetCount()
+            GameWorld.Log("zoneID=%s,championshipSeason=%s,billboardDataLen=%s" % (zoneID, championshipSeason, billboardDataLen))
+            if not billboardDataLen:
                 # 没有玩家上榜的不处理
                 continue
             pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID, True)
-            battlePlayerList = billboardList[:Def_CrossChampionshipPlayerMax]
-            for num, billboardData in enumerate(battlePlayerList, 1):
-                playerID = billboardData.PlayerID
+            for index in range(Def_CrossChampionshipPlayerMax):
+                if index >= billboardDataLen:
+                    break
+                billboardData = billboardObj.At(index)
+                playerID = billboardData.ID
+                
                 batPlayer = ChampionshipBatPlayer()
                 batPlayer.zoneID = zoneID
                 batPlayer.playerID = playerID
-                batPlayer.playerName = billboardData.PlayerName
-                batPlayer.job = billboardData.Job
-                batPlayer.fightPower = billboardData.FightPower
-                batPlayer.realmLV = billboardData.RealmLV
                 pkZoneMgr.playerDict[playerID] = batPlayer
                 
                 getPlayer = pkZoneMgr.GetBatPlayer(playerID)
                 dataDict = {"zoneID":zoneID, "playerID":playerID, "accID":getPlayer.accID, "fightPower":getPlayer.fightPower}
                 DR_CrossChampionshipPK("StartPlayer", dataDict)
                 
-                GameWorld.Log("    AddBattlePlayer num=%s,playerID=%s,accID=%s,fightPower=%s" % (num, playerID, getPlayer.accID, getPlayer.fightPower))
+                GameWorld.Log("    AddBattlePlayer index=%s,playerID=%s,accID=%s,fightPower=%s" % (index, playerID, getPlayer.accID, getPlayer.fightPower))
                 
     GameWorld.Log("=============================================================")
     Send_CrossServerMsg_ChampionshipState(newAct=True)
@@ -1369,52 +1411,7 @@
 
 def DoCrossChampionshipStartEnter(state):
     ## 开启进场处理逻辑
-    if state not in ShareDefine.CrossChampionshipEnterStateInfo:
-        return
-    groupMark = ShareDefine.CrossChampionshipEnterStateInfo[state]
-    mapIndex = 0
-    mapIDList = IpyGameDataPY.GetFuncEvalCfg("CrossChamFB", 3)
-    GameWorld.Log("跨服排位争霸赛开启进场副本: groupMark=%s,mapIDList=%s" % (groupMark, mapIDList))
-    champMgr = GetChampionshipMgr()
-    pkZoneIDList = champMgr.GetChampPKZoneIDList()
-    for zoneID in pkZoneIDList:
-        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
-        if not pkZoneMgr:
-            continue
-        if groupMark not in pkZoneMgr.battleInfo:
-            GameWorld.Log("该跨服排位争霸赛分区没有对战组! zoneID=%s,groupMark=%s" % (zoneID, groupMark), zoneID)
-            continue
-        if mapIndex >= len(mapIDList):
-            GameWorld.ErrLog("该跨服排位争霸赛分区没有分配对战地图! zoneID=%s,mapIndex=%s" % (zoneID, mapIndex), zoneID)
-            continue
-        mapID = mapIDList[mapIndex]
-        mapIndex += 1
-        copyMapID = 0
-        copyPropertyList = []
-        battleDict = pkZoneMgr.battleInfo[groupMark]
-        for battleNum in battleDict.keys():
-            batObj = pkZoneMgr.GetBattle(groupMark, battleNum)
-            if not batObj:
-                continue
-            roomID = GetChampionshipPKRoomID(zoneID, groupMark, battleNum)
-            copyPropertyList.append([copyMapID, roomID])
-            batObj.mapID = mapID
-            batObj.roomID = roomID
-            batObj.copyMapID = copyMapID
-            
-            # 添加开启分线数据
-            realMapID = mapID
-            copyMapObj = PlayerFB.CrossCopyMapInfo(zoneID, ChConfig.Def_FBMapID_CrossChampionship, 0)
-            copyMapObj.realMapID = realMapID
-            copyMapObj.copyMapID = copyMapID
-            key = (realMapID, copyMapID)
-            PyGameData.g_crossDynamicLineCopyMapInfo[key] = copyMapObj
-            GameWorld.Log("    对战房间! zoneID=%s,groupMark=%s,battleNum=%s,playerIDA=%s,playerIDB=%s,roomID=%s,mapID=%s,copyMapID=%s" 
-                          % (zoneID, groupMark, battleNum, batObj.playerIDA, batObj.playerIDB, roomID, mapID, copyMapID))
-            copyMapID += 1
-            
-        PlayerFB.SendMapOpenFBEx(mapID, copyPropertyList)
-        
+    # 改为镜像战斗,废弃开地图房间
     return
 
 def Sync_CrossChampionshipDataToClientServer(serverGroupID=0):
@@ -1549,6 +1546,21 @@
         GameWorld.Log("子服重置跨服排位争霸赛对战数据! dbID=%s,ID=%s,PKZoneIDList=%s,prePKZoneIDList=%s" % (dbID, ID, PKZoneIDList, prePKZoneIDList))
         for zoneID in PKZoneIDList:
             champMgr.GetChampPKZoneMgr(zoneID)
+            
+    OnMapServerInitOK()
+    return
+
+def OnMapServerInitOK():
+    # 通知地图服务器状态
+    
+    if GameWorld.IsCrossServer():
+        return
+    
+    State = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipState)
+    StateError = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipStateError)
+    
+    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossChampionshipState, State)
+    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossChampionshipStateError, StateError)
     return
 
 def CrossServerMsg_ChampionshipPlayer(msgData):
@@ -1575,7 +1587,8 @@
                     pkZoneMgr.playerDict[playerID] = batPlayer
                 batPlayer.SetAttr(attrDict)
                 
-        if isSync:
+    if isSync:
+        for zoneID in zoneBatPlayerInfo.keys():
             Sync_ChampionshipPKZoneGroupInfo(zoneID)
             
     return
@@ -1702,95 +1715,84 @@
     
     return
 
-def OnRequestChampionshipVSRoom(playerID, serverGroupID):
-    ## 请求进入排位对战房间
-    
-    stateError = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipStateError)
-    if stateError:
-        GameWorld.ErrLog("跨服排位状态已经异常无法进入! stateError=%s" % stateError, playerID)
-        return
-    
-    state = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipState)
-    if state not in ShareDefine.CrossChampionshipEnterStateInfo:
-        GameWorld.ErrLog("当前状态非跨服排位战斗状态无法进入: state=%s" % state, playerID)
-        return
-    groupMark = ShareDefine.CrossChampionshipEnterStateInfo[state]
-    
-    mapPosList = IpyGameDataPY.GetFuncEvalCfg("CrossChamFB", 2)
-    if not mapPosList:
-        GameWorld.ErrLog("没有配置跨服排位对战地图进入坐标! CrossChamFB 数值2")
-        return
-    
-    roomID = 0
-    vsRoomDict = {}
-    
-    champMgr = GetChampionshipMgr()
-    for zoneID in champMgr.GetChampPKZoneIDList():
-        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
-        if not pkZoneMgr:
-            continue
-        if groupMark not in pkZoneMgr.battleInfo:
-            continue
-        battleDict = pkZoneMgr.battleInfo[groupMark]
-        for battleNum in battleDict.keys():
-            batObj = pkZoneMgr.GetBattle(groupMark, battleNum)
-            if not batObj:
-                continue
-            
-            if playerID == batObj.playerIDA:# or batObj.playerIDA == 496607:
-                factionIndex = 0
-            elif playerID == batObj.playerIDB:# or batObj.playerIDB == 489566:
-                factionIndex = 1
-            else:
-                continue
-            
-            if not batObj.mapID:
-                GameWorld.ErrLog("该跨服排位对战没有分配对战地图,无法进入! groupMark=%s,battleNum=%s" % (groupMark, battleNum), playerID)
-                return
-            roomID = batObj.roomID
-            realMapID = batObj.mapID
-            copyMapID = batObj.copyMapID
-            key = (realMapID, copyMapID)
-            if key not in PyGameData.g_crossDynamicLineCopyMapInfo:
-                GameWorld.ErrLog("该跨服排位对战没有分配对战地图线路,无法进入! groupMark=%s,battleNum=%s,realMapID=%s,copyMapID=%s" 
-                                 % (groupMark, battleNum, realMapID, copyMapID), playerID)
-                return
-            copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo[key]
-            if copyMapObj.openState != IPY_PlayerDefine.fbosOpen:
-                GameWorld.Log("该跨服排位对战分配的地图线路非开启状态,无法进入! groupMark=%s,battleNum=%s,realMapID=%s,copyMapID=%s,openState=%s" 
-                              % (groupMark, battleNum, realMapID, copyMapID, copyMapObj.openState), playerID)
-                return
-            
-            posX, posY = mapPosList[factionIndex] if len(mapPosList) > factionIndex else mapPosList[0]
-            
-            registerMap = ChConfig.Def_FBMapID_CrossChampionship
-            dataMapID = realMapID
-            
-            vsRoomDict = {roomID:{playerID:{"regMapInfo":[registerMap, realMapID, dataMapID, copyMapID, posX, posY]}}}
-            GameWorld.Log("玩家请求跨服排位对战组: zoneID=%s,groupMark=%s,battleNum=%s,roomID=%s" 
-                          % (zoneID, groupMark, battleNum, roomID), playerID)
-            break
-        
-    if not roomID or not vsRoomDict:
-        GameWorld.ErrLog("找不到玩家跨服排位对战组: state=%s,groupMark=%s" % (state, groupMark), playerID)
-        return
-    PlayerFB.Send_CrossServerMsg_EnterVSRoomRet(vsRoomDict, [serverGroupID])
-    return
+#def OnRequestChampionshipVSRoom(playerID, serverGroupID):
+#    ## 请求进入排位对战房间
+#    
+#    stateError = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipStateError)
+#    if stateError:
+#        GameWorld.ErrLog("跨服排位状态已经异常无法进入! stateError=%s" % stateError, playerID)
+#        return
+#    
+#    state = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipState)
+#    if state not in ShareDefine.CrossChampionshipEnterStateInfo:
+#        GameWorld.ErrLog("当前状态非跨服排位战斗状态无法进入: state=%s" % state, playerID)
+#        return
+#    groupMark = ShareDefine.CrossChampionshipEnterStateInfo[state]
+#    
+#    mapPosList = IpyGameDataPY.GetFuncEvalCfg("CrossChamFB", 2)
+#    if not mapPosList:
+#        GameWorld.ErrLog("没有配置跨服排位对战地图进入坐标! CrossChamFB 数值2")
+#        return
+#    
+#    roomID = 0
+#    vsRoomDict = {}
+#    
+#    champMgr = GetChampionshipMgr()
+#    for zoneID in champMgr.GetChampPKZoneIDList():
+#        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+#        if not pkZoneMgr:
+#            continue
+#        if groupMark not in pkZoneMgr.battleInfo:
+#            continue
+#        battleDict = pkZoneMgr.battleInfo[groupMark]
+#        for battleNum in battleDict.keys():
+#            batObj = pkZoneMgr.GetBattle(groupMark, battleNum)
+#            if not batObj:
+#                continue
+#            
+#            if playerID == batObj.playerIDA:# or batObj.playerIDA == 496607:
+#                factionIndex = 0
+#            elif playerID == batObj.playerIDB:# or batObj.playerIDB == 489566:
+#                factionIndex = 1
+#            else:
+#                continue
+#            
+#            if not batObj.mapID:
+#                GameWorld.ErrLog("该跨服排位对战没有分配对战地图,无法进入! groupMark=%s,battleNum=%s" % (groupMark, battleNum), playerID)
+#                return
+#            roomID = batObj.roomID
+#            realMapID = batObj.mapID
+#            copyMapID = batObj.copyMapID
+#            key = (realMapID, copyMapID)
+#            if key not in PyGameData.g_crossDynamicLineCopyMapInfo:
+#                GameWorld.ErrLog("该跨服排位对战没有分配对战地图线路,无法进入! groupMark=%s,battleNum=%s,realMapID=%s,copyMapID=%s" 
+#                                 % (groupMark, battleNum, realMapID, copyMapID), playerID)
+#                return
+#            copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo[key]
+#            if copyMapObj.openState != IPY_PlayerDefine.fbosOpen:
+#                GameWorld.Log("该跨服排位对战分配的地图线路非开启状态,无法进入! groupMark=%s,battleNum=%s,realMapID=%s,copyMapID=%s,openState=%s" 
+#                              % (groupMark, battleNum, realMapID, copyMapID, copyMapObj.openState), playerID)
+#                return
+#            
+#            posX, posY = mapPosList[factionIndex] if len(mapPosList) > factionIndex else mapPosList[0]
+#            
+#            registerMap = ChConfig.Def_FBMapID_CrossChampionship
+#            dataMapID = realMapID
+#            
+#            vsRoomDict = {roomID:{playerID:{"regMapInfo":[registerMap, realMapID, dataMapID, copyMapID, posX, posY]}}}
+#            GameWorld.Log("玩家请求跨服排位对战组: zoneID=%s,groupMark=%s,battleNum=%s,roomID=%s" 
+#                          % (zoneID, groupMark, battleNum, roomID), playerID)
+#            break
+#        
+#    if not roomID or not vsRoomDict:
+#        GameWorld.ErrLog("找不到玩家跨服排位对战组: state=%s,groupMark=%s" % (state, groupMark), playerID)
+#        return
+#    PlayerFB.Send_CrossServerMsg_EnterVSRoomRet(vsRoomDict, [serverGroupID])
+#    return
 
 def GetChampionshipPKRoomID(zoneID, groupMark, battleNum): return int("%d%03d%02d" % (zoneID, groupMark, battleNum))
-def MapServer_CrossChampionshipPKOver(infoList, tick):
-    ## 收到MapServer副本跨服排位PK结果同步
-    
-    roomID, winnerID, loserID, roundWinnerIDList, overType = infoList
-    zoneID = roomID / 100000
-    groupMark = roomID % 100000 / 100
-    battleNum = roomID % 100
-    GameWorld.Log("=== 收到MapServer_跨服排位PK战斗结果: zoneID=%s,groupMark=%s,battleNum=%s,roomID=%s,winnerID=%s,loserID=%s,roundWinnerIDList=%s,overType=%s" 
-                  % (zoneID, groupMark, battleNum, roomID, winnerID, loserID, roundWinnerIDList, overType), roomID)
-    DoBattleOverLogic(zoneID, groupMark, battleNum, winnerID, loserID, roundWinnerIDList, overType)
-    return
 
-def DoBattleOverLogic(zoneID, groupMark, battleNum, winnerID=0, loserID=0, roundWinnerIDList=None, overType=0):
+def DoBattleOverLogic(zoneID, groupMark, battleNum):
     ## 执行对战结算逻辑
     
     if not zoneID:
@@ -1809,10 +1811,7 @@
     if not battleObj:
         return
     
-    if roundWinnerIDList == None:
-        roundWinnerIDList = []
-        
-    roomID = battleObj.roomID
+    roomID = GetChampionshipPKRoomID(zoneID, groupMark, battleNum) # 改版后roomID没用了,仅作为日志输出用
     if battleObj.overTime:
         GameWorld.ErrLog("跨服排位PK对战已经结算过了,不重复结算! zoneID=%s,groupMark=%s,battleNum=%s,winPlayerID=%s,overTime=%s" 
                          % (zoneID, groupMark, battleNum, battleObj.winPlayerID, GameWorld.ChangeTimeNumToStr(battleObj.overTime)), roomID)
@@ -1821,11 +1820,30 @@
     playerIDA = battleObj.playerIDA
     playerIDB = battleObj.playerIDB
     roomPlayerIDList = [playerIDA, playerIDB]
-    GameWorld.Log("结算跨服排位PK战斗结果: zoneID=%s,groupMark=%s,battleNum=%s,playerIDA=%s,playerIDB=%s,roomPlayerIDList=%s" 
+    GameWorld.Log("结算跨服排位PK胜负结果: zoneID=%s,groupMark=%s,battleNum=%s,playerIDA=%s,playerIDB=%s,roomPlayerIDList=%s" 
                   % (zoneID, groupMark, battleNum, playerIDA, playerIDB, roomPlayerIDList), roomID)
     
+    winnerID, loserID = 0, 0
     if playerIDA and playerIDB:
-        if not winnerID and not loserID:
+        totalScoreDict = {}
+        for batPlayerID, batRetList in battleObj.playerBatDict.items():
+            for retInfo in batRetList:
+                if not retInfo or len(retInfo) < 2:
+                    continue
+                addScore = retInfo[1]
+                totalScoreDict[batPlayerID] = totalScoreDict.get(batPlayerID, 0) + addScore
+        playerScoreA = totalScoreDict.get(playerIDA, 0)
+        playerScoreB = totalScoreDict.get(playerIDB, 0)
+        GameWorld.Log("    总积分: %s, %s" % (totalScoreDict, battleObj.playerBatDict), roomID)
+        if playerScoreA > playerScoreB:
+            winnerID = playerIDA
+            loserID = playerIDB
+            GameWorld.Log("    跨服排位赛玩家累计总分高者获胜! winner is playerIDA=%s,loserID=%s" % (playerIDA, loserID), roomID)
+        elif playerScoreB > playerScoreA:
+            winnerID = playerIDB
+            loserID = playerIDA
+            GameWorld.Log("    跨服排位赛玩家累计总分高者获胜! winner is playerIDB=%s,loserID=%s" % (playerIDB, loserID), roomID)
+        else: # 平分
             playerA = pkZoneMgr.GetBatPlayer(playerIDA)
             playerB = pkZoneMgr.GetBatPlayer(playerIDB)
             fightPowerA = playerA.fightPower if playerA else 0
@@ -1843,18 +1861,7 @@
                 winnerID, loserID = roomPlayerIDList
                 GameWorld.Log("    跨服排位赛对战地图没有玩家参与或没有胜负玩家,战力相同随机玩家获胜! fightPowerA=%s(%s) = fightPowerB=%s(%s),winnerID=%s,loserID=%s" 
                               % (fightPowerA, playerIDA, fightPowerB, playerIDB, winnerID, loserID), roomID)
-        elif not loserID:
-            for roomPlayerID in roomPlayerIDList:
-                if roomPlayerID != winnerID:
-                    loserID = roomPlayerID
-                    GameWorld.Log("    跨服排位赛对战地图没有失败玩家,默认对方为失败玩家! loserID=%s" % loserID, roomID)
-                    break
                 
-        if not winnerID or winnerID not in roomPlayerIDList or loserID not in roomPlayerIDList:
-            GameWorld.ErrLog("跨服排位赛PK房间胜负玩家异常,不结算! roomID=%s,winnerID=%s,loserID=%s,roomPlayerIDList=%s" 
-                             % (roomID, winnerID, loserID, roomPlayerIDList), roomID)
-            return
-        
     elif playerIDA:
         winnerID = playerIDA
         loserID = playerIDB
@@ -1874,9 +1881,6 @@
     winner = pkZoneMgr.GetBatPlayer(winnerID)
     loser = pkZoneMgr.GetBatPlayer(loserID)
     
-    winnerName = winner.playerName if winner else str(winnerID)
-    loserName = loser.playerName if loser else str(loserID)
-    
     # 决赛可获取最终名次
     playerRankInfo = {}
     if groupMark == 2:
@@ -1894,8 +1898,7 @@
     wAwardItemList, fAwardItemList = [], []
     if wfAwardItemList and len(wfAwardItemList) == 2:
         wAwardItemList, fAwardItemList = wfAwardItemList
-                
-    timeStr = GameWorld.GetCurrentDataTimeStr()
+        
     # 结算
     for playerID in [winnerID, loserID]:
         if not playerID:
@@ -1904,15 +1907,15 @@
         if playerID == winnerID:
             addItemList = wAwardItemList
             mailTypeKey = "CrossChampionshipPKWin%s" % groupMark
-            tagPlayerID, tagPlayerName = loserID, loserName
+            tagPlayerID = loserID
         else:
             addItemList = fAwardItemList
             mailTypeKey = "CrossChampionshipPKLose%s" % groupMark
-            tagPlayerID, tagPlayerName = winnerID, winnerName
+            tagPlayerID = winnerID
             
         rank = playerRankInfo.get(playerID, 0)
-        GameWorld.Log("    结算跨服排位赛玩家奖励: zoneID=%s,roomID=%s,groupMark=%s,battleNum=%s,rank=%s,tagPlayerID=%s" 
-                           % (zoneID, roomID, groupMark, battleNum, rank, tagPlayerID), playerID)
+        GameWorld.Log("    结算跨服排位赛玩家奖励: zoneID=%s,groupMark=%s,battleNum=%s,rank=%s,tagPlayerID=%s,addItemList=%s" 
+                           % (zoneID, groupMark, battleNum, rank, tagPlayerID, addItemList), playerID)
         if rank:
             paramList = [rank]
         else:
@@ -1920,30 +1923,84 @@
         playerIDList = [playerID]
         PlayerCompensation.SendMailByKey(mailTypeKey, playerIDList, addItemList, paramList, crossMail=True)
         
-        player = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
-        if player:
-            overPack = ChPyNetSendPack.tagGCCrossChampionshipPKOver()
-            overPack.GroupMark = groupMark
-            overPack.TimeStr = timeStr
-            overPack.OverType = overType
-            overPack.WinnerID = winnerID
-            overPack.LoserID = loserID
-            overPack.RoundWinnerID = roundWinnerIDList
-            overPack.RoundCount = len(overPack.RoundWinnerID)
-            overPack.TagName = tagPlayerName
-            overPack.TagNameLen = len(overPack.TagName)
-            overPack.Rank = rank
-            NetPackCommon.SendFakePack(player, overPack)
-            
     # 同步子服
     Send_CrossServerMsg_ChampionshipGroup(battleObj=battleObj)
     
     # 记录流向
     winnerInfo = winner.GetString() if winner else {}
     loserInfo = loser.GetString() if loser else {}
-    dataDict = {"roundWinnerIDList":roundWinnerIDList, "overType":overType, "winner":winnerInfo, "loser":loserInfo, 
+    dataDict = {"winner":winnerInfo, "loser":loserInfo, 
                 "battle":battleObj.GetString(), "playerRankInfo":playerRankInfo}
     DR_CrossChampionshipPK("PKRoomOver", dataDict)    
+    return True
+
+def ClientServerMsg_ChampionshipPKOver(serverGroupID, msgData):
+    ## 收到子服同步的镜像PK结果
+    playerID = msgData["playerID"]
+    tagPlayerID = msgData["tagPlayerID"]
+    funcLineID = msgData["funcLineID"]
+    isWin = msgData["isWin"]
+    addScore = msgData["addScore"]
+    baseScore = msgData["baseScore"]
+    hpScore = msgData["hpScore"]
+    timeScore = msgData["timeScore"]
+    pkCountMax = msgData["pkCountMax"]
+    
+    zoneID = funcLineID / 100
+    groupMark = funcLineID % 100
+    
+    groupMarkList = ShareDefine.CrossChampionshipEnterStateInfo.values()
+    if groupMark not in groupMarkList:
+        GameWorld.ErrLog("跨服排位镜像PK结果分组异常! groupMark=%s" % groupMark, playerID)
+        return
+    
+    champMgr = GetChampionshipMgr()
+    pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+    if not pkZoneMgr:
+        return
+    battleObj = pkZoneMgr.GetBattleByPlayerID(groupMark, playerID)
+    if not battleObj:
+        GameWorld.ErrLog("跨服排位镜像PK结果玩家不在该排位分组中! zoneID=%s,groupMark=%s" % (zoneID, groupMark), playerID)
+        return
+    battleNum = battleObj.battleNum
+    playerIDA = battleObj.playerIDA
+    playerIDB = battleObj.playerIDB
+    roomPlayerIDList = [playerIDA, playerIDB]
+    # 有轮空的默认不用打
+    if playerID not in roomPlayerIDList or tagPlayerID not in roomPlayerIDList or not tagPlayerID or not playerIDA or not playerIDB:
+        GameWorld.ErrLog("跨服排位镜像PK结果玩家ID错误! zoneID=%s,groupMark=%s,playerID=%s,tagPlayerID=%s,roomPlayerIDList=%s" 
+                         % (zoneID, groupMark, playerID, tagPlayerID, roomPlayerIDList), playerID)
+        return
+    if playerID not in battleObj.playerBatDict:
+        battleObj.playerBatDict[playerID] = []
+    batRetList = battleObj.playerBatDict[playerID]
+    if len(batRetList) >= pkCountMax or not pkCountMax:
+        GameWorld.ErrLog("跨服排位镜像PK结果已达PK次数上限! zoneID=%s,groupMark=%s,playerID=%s,tagPlayerID=%s,batRetList=%s" 
+                         % (zoneID, groupMark, playerID, tagPlayerID, batRetList), playerID)
+        return
+    if battleObj.overTime:
+        GameWorld.ErrLog("跨服排位镜像PK胜负已经结算过了,不再更新PK结果! zoneID=%s,groupMark=%s,battleNum=%s,winPlayerID=%s,overTime=%s" 
+                         % (zoneID, groupMark, battleNum, battleObj.winPlayerID, GameWorld.ChangeTimeNumToStr(battleObj.overTime)), playerID)
+        return
+    
+    isWin = 1 if isWin else 0
+    batRetList.append([isWin, addScore, baseScore, hpScore, timeScore])
+    GameWorld.Log("跨服排位镜像PK结果: zoneID=%s,groupMark=%s,battleNum=%s,playerIDA=%s,playerIDB=%s,batCount=%s,isWin=%s,addScore=%s,baseScore=%s,hpScore=%s,timeScore=%s" 
+                  % (zoneID, groupMark, battleNum, playerIDA, playerIDB, len(batRetList), isWin, addScore, baseScore, hpScore, timeScore), playerID)
+    
+    # 是否都打完所有次数,是的话直接结算胜负
+    isAllOver = True
+    for roomPlayerID in roomPlayerIDList:
+        batList = battleObj.playerBatDict.get(roomPlayerID, [])
+        if len(batList) < pkCountMax:
+            isAllOver = False
+            break
+    if isAllOver:
+        if DoBattleOverLogic(zoneID, groupMark, battleNum):
+            return
+        
+    # 同步子服
+    Send_CrossServerMsg_ChampionshipGroup(battleObj=battleObj)
     return
 
 def DoCrossChampionshipFinalOver():
@@ -2947,11 +3004,14 @@
             battleObj = pkZoneMgr.GetBattle(groupMark, battleNum)
             if not battleObj:
                 continue
+            battleRetDict = {str(k):v for k, v in battleObj.playerBatDict.items()}
             battlePack = ChPyNetSendPack.tagGCCrossChampionshipPKBattle()
             battlePack.BattleNum = battleNum
             battlePack.WinPlayerID = battleObj.winPlayerID
             battlePack.PlayerIDA = battleObj.playerIDA
             battlePack.PlayerIDB = battleObj.playerIDB
+            battlePack.BattleRet = json.dumps(battleRetDict, ensure_ascii=False).replace(" ", "")
+            battlePack.BattleRetLen = len(battlePack.BattleRet)
             groupPack.BattleList.append(battlePack)
         groupPack.BattleCount = len(groupPack.BattleList)
         clientPack.GroupList.append(groupPack)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
index 6ab4977..d68ca6c 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
@@ -156,6 +156,9 @@
         elif msgType == ShareDefine.ClientServerMsg_BattlefieldCallChange:
             CrossBattlefield.ClientServerMsg_BattlefieldCallChange(serverGroupID, msgData)
             
+        elif msgType == ShareDefine.ClientServerMsg_ChampionshipPKOver:
+            CrossChampionship.ClientServerMsg_ChampionshipPKOver(serverGroupID, msgData)
+            
         elif msgType == ShareDefine.ClientServerMsg_ChampionshipOfficialApply:
             CrossChampionship.ClientServerMsg_ChampionshipOfficialApply(serverGroupID, msgData)
             
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
index a566574..c97d62f 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
@@ -1532,6 +1532,8 @@
     
     # 跨服PK
     CrossRealmPK.OnMapServerInitOK()
+    # 跨服排位赛
+    CrossChampionship.OnMapServerInitOK()
     #跨服战场
     CrossBattlefield.OnMapServerInitOK()
     # 本服竞技场
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFB.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFB.py
index 3298d23..e6afa38 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFB.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFB.py
@@ -171,7 +171,7 @@
     playerLV = msgData["LV"]
     
     if mapID == ChConfig.Def_FBMapID_CrossChampionship:
-        CrossChampionship.OnRequestChampionshipVSRoom(playerID, serverGroupID)
+        #CrossChampionship.OnRequestChampionshipVSRoom(playerID, serverGroupID)
         return
     
     zoneIpyData = CrossRealmPlayer.GetCrossZoneIpyDataByServerGroupID(mapID, serverGroupID)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
index fd732aa..ae649a6 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -644,11 +644,6 @@
     if callName == "ReuestPlayerPackData":
         PlayerPackData.OnMGReuestPlayerPackData(eval(resultName))
         return
-        
-    #跨服排位PK战斗结算
-    if callName == "CrossChampionshipPKOver":
-        CrossChampionship.MapServer_CrossChampionshipPKOver(eval(resultName), tick)
-        return
     
     #跨服PK请求玩家当前排名
     if callName == "CrossPKSeasonOrder":
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
index c3f1e64..b0412c7 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -182,6 +182,9 @@
 Def_Notify_WorldKey_CrossPKSeasonID = "CrossPKSeasonID"  # 本服跨服PK当前赛季
 Def_Notify_WorldKey_CrossPKSeasonState = "CrossPKSeasonState"  # 本服跨服PK赛季状态 0-关闭,1-开启中
 
+Def_Notify_WorldKey_CrossChampionshipState = "CrossChampionshipState"  # 跨服排位赛状态
+Def_Notify_WorldKey_CrossChampionshipStateError = "CrossChampionshipStateError"  # 跨服排位赛状态是否已经异常
+
 Def_Notify_WorldKey_LuckyCloudBuyInfo = "LuckyCloudBuyInfo"  # 本服幸运云购最新一期信息
 
 Def_Notify_WorldKey_CrossBattlefieldCallTeamInfo = "CrossBattlefieldCallTeamInfo" # 跨服战场召集队伍信息
@@ -1715,6 +1718,7 @@
 ClientServerMsg_BattlefieldCallKick = "BattlefieldCallKick"   # 跨服战场召集 - 踢出
 ClientServerMsg_ActDropSpecItem = "ActDropSpecItem"     # 活动特殊掉落
 ClientServerMsg_CrossAssist = "CrossAssist"             # 跨服协助
+ClientServerMsg_ChampionshipPKOver = "ChampionshipPKOver" # 跨服排位PK结束
 ClientServerMsg_ChampionshipOfficialApply = "ChampionshipOfficialApply" # 跨服排位申请官职
 ClientServerMsg_ChampionshipOfficialApplyReply = "ChampionshipOfficialApplyReply" # 跨服排位官职申请回应
 ClientServerMsg_ChampionshipOfficialKick = "ChampionshipOfficialKick" # 跨服排位辞退下级仙官
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/MirrorAttack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/MirrorAttack.py
index 73f663d..0d9b1e3 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/MirrorAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/MirrorAttack.py
@@ -58,16 +58,29 @@
         self.mapID = 0 # 功能mapID,代表某一个功能
         self.funcLineID = 0
         self.batState = 0 # 状态:0-无;1-准备中;2-战斗中;3-快速结束中,4-结束
+        self.startTick = 0 # 开始战斗tick
+        self.fightTickMax = 0 # 战斗最大时长,tick
+        self.fightTickRemain = 0 # 剩余战斗时长,tick
         self.mirrorIDDict = {} # 该场所有玩家镜像实例ID对应真实ID {playerID:realPlayerID, ...}
         self.realIDDict = {} # 该场所有真实玩家对应初始信息 {playerID:{k:v, ...}, ...}
         self.playerFactionDict = {} # 该场所有玩家阵营信息,真实玩家+镜像玩家 {playerID:faction, ...}
         self.playerAutoSkillInfo = {} # 玩家自动释放技能列表 {playerID:[skillTypeID, ...], ...}
         self.deadPlayerIDList = [] # 已被击杀的玩家ID列表
+        self.tagPlayerIDList = [] # 对手真实玩家ID列表
         
         self.isLogout = False # 是否下线的
         self.isQuick = False # 是否快速战斗结束的
+        self.isWin = False # 是否获胜
         self.winFaction = 0 # 获胜阵营
         return
+    
+    def GetTagPlayerID(self): return self.tagPlayerIDList[0] if self.tagPlayerIDList else 0
+    
+    def CaclFightTick(self, tick):
+        ## 计算战斗时长,返回剩余时长tick
+        fightTickCost = tick - self.startTick # 已过战斗时长
+        self.fightTickRemain = max(0, self.fightTickMax - fightTickCost) # 剩余战斗时长
+        return self.fightTickRemain
     
     def AddBattlePlayer(self, curPlayer, faction, posX=0, posY=0):
         playerID = curPlayer.GetPlayerID()
@@ -220,7 +233,9 @@
     dataFightPower = PlayerControl.GetFightPower(mirrorPlayer)
     GameWorld.DebugLog("CreateMirrorPlayer mirrorID=%s,realPlayerID=%s,mapID=%s,funcLineID=%s,posX=%s,posY=%s,faction=%s,dataFightPower=%s,,accID=%s" 
                        % (mirrorID, realPlayerID, mapID, funcLineID, posX, posY, faction, dataFightPower, mirrorPlayer.GetAccID()), playerID)
-    
+    if faction != 1:
+        battle.tagPlayerIDList.append(realPlayerID)
+        
     ChPlayer.InitPlayerPack(mirrorPlayer)
     PlayerHorse.PlayerRideHorseUp(mirrorPlayer, False, False)
     
@@ -399,7 +414,7 @@
     if cmdType == 2:
         battle = GetMirrorBattle(curPlayer)
         if battle:
-            DoMirrorBattleQuick(battle.battleID)
+            DoMirrorBattleQuick(battle.battleID, isClick=True)
         return
     
     # 不战斗直接跳过,即玩家没有参与,创建系统战斗场,之后扩展
@@ -426,7 +441,7 @@
     
     # 如果还在战斗中,直接快速执行战斗结果
     if battle.batState == ChConfig.Def_MirrorBatState_Fight:
-        DoMirrorBattleQuick(battle.battleID, True)
+        DoMirrorBattleQuick(battle.battleID, isLogout=True)
         
     # 统一退出
     if PlayerControl.GetCustomMapID(curPlayer):
@@ -534,6 +549,8 @@
         CreateMirrorPlayer(battleID, batPlayerID, packData, posX, posY, faction, curPlayer)
         
     battle.batState = ChConfig.Def_MirrorBatState_Prepare
+    fightTimeLimitDict = IpyGameDataPY.GetFuncEvalCfg("MirrorAttack", 1, {})
+    battle.fightTickMax = fightTimeLimitDict.get(str(mapID), 60) * 1000 # 最大战斗时长,默认60秒
     
     if not isSysbg:
         return
@@ -551,6 +568,7 @@
     if battle.batState >= ChConfig.Def_MirrorBatState_Fight:
         return
     battle.batState = ChConfig.Def_MirrorBatState_Fight
+    battle.startTick = GameWorld.GetGameWorld().GetTick()
     return
 
 def ProcessPlayerMirrorAI(curPlayer, tick):
@@ -567,6 +585,9 @@
         realPlayerID = curPlayer.GetRealPlayerID()
         if not realPlayerID:
             # 常规战斗下,真实玩家不处理,由玩家自行控制
+            # 真实玩家附加判断是否PK超时
+            if battle.startTick and battle.CaclFightTick(tick) <= 0:
+                OnMirrorAttackOver(battle.battleID)
             return
         
     if GameObj.GetHP(curPlayer) <= 0:
@@ -709,22 +730,39 @@
     curPlayer.NotifyAll(sendPack.GetBuffer(), sendPack.GetLength())
     return
 
-def DoMirrorBattleQuick(battleID, isLogout=False):
+def DoMirrorBattleQuick(battleID, isLogout=False, isClick=False):
     ## 执行快速战斗
     battle = GetMirrorBattleByID(battleID)
     if not battle:
         return
     if battle.batState > ChConfig.Def_MirrorBatState_Fight:
         return
+    if battle.isQuick:
+        #不重复触发处理
+        return
+    mapID = battle.mapID
+    if not battle.isSysbg:
+        if isClick:
+            quickLimitMapIDList = IpyGameDataPY.GetFuncEvalCfg("MirrorAttack", 2)
+            if mapID in quickLimitMapIDList:
+                GameWorld.DebugLog("战斗中不允许点击快速战斗! mapID=%s" % mapID, battle.playerID)
+                return
+        if isLogout:
+            logoutQuickLimitMapIDList = IpyGameDataPY.GetFuncEvalCfg("MirrorAttack", 3)
+            if mapID in logoutQuickLimitMapIDList:
+                GameWorld.DebugLog("掉线不允许快速战斗! mapID=%s" % mapID, battle.playerID)
+                return
     tick = GameWorld.GetGameWorld().GetTick()
     battle.batState = ChConfig.Def_MirrorBatState_Fight
     battle.isQuick = True
     battle.isLogout = isLogout
+    battle.CaclFightTick(tick)
     
     playerMgr = GameWorld.GetMapCopyPlayerManager()
     perLoopTick = 100 # 每次循环视为已过毫秒
-    maxLoopCount = 60 * 1000 / perLoopTick # 循环次数上限,暂定最长PK时长60秒
-    GameWorld.DebugLog("DoMirrorBattleQuick isLogout=%s,maxLoopCount=%s,tick=%s" % (isLogout, maxLoopCount, tick), battleID)
+    maxLoopCount = battle.fightTickRemain / perLoopTick # 循环次数上限
+    GameWorld.DebugLog("DoMirrorBattleQuick isLogout=%s,maxLoopCount=%s,tick=%s,fightTickRemain=%s" 
+                       % (isLogout, maxLoopCount, tick, battle.fightTickRemain), battleID)
     
     # 屏蔽发包
     for batPlayerID in battle.realIDDict.keys():
@@ -737,8 +775,9 @@
         if battle.batState != ChConfig.Def_MirrorBatState_Fight:
             # 可能还没循环完毕就结束了
             break
-        tick += loopCount * perLoopTick # 修改每次循环的tick
-        GameWorld.DebugLog("    loopCount=%s,tick=%s" % (loopCount, tick), battleID)
+        tick += perLoopTick # 修改每次循环的tick
+        battle.CaclFightTick(tick)
+        GameWorld.DebugLog("    loopCount=%s,tick=%s,fightTickRemain=%s" % (loopCount, tick, battle.fightTickRemain), battleID)
         for batPlayerID in battle.playerFactionDict.keys():
             if batPlayerID in battle.deadPlayerIDList:
                 continue
@@ -765,14 +804,11 @@
                 
             ProcessPlayerMirrorAI(curPlayer, tick)
             
-    if battle.winFaction:
-        # 已经有获胜方了,代表已经触发过结算胜负
-        return
-    # 暂定没击杀算输,发起方为1
-    GameWorld.DebugLog("没有击败对方阵营!", battleID)
-    battle.winFaction = 2
-    OnMirrorAttackOver(battleID)
-    return
+    # 没有获胜方
+    if not battle.winFaction:
+        GameWorld.DebugLog("没有击败对方阵营!", battleID)
+        OnMirrorAttackOver(battleID)
+    return True
 
 def OnPlayerDead(curPlayer):
     battleID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MirrorBattleID)
@@ -811,13 +847,20 @@
         # 已经结算过
         return
     battle.batState = ChConfig.Def_MirrorBatState_Over
+    tick = GameWorld.GetGameWorld().GetTick()
+    if not battle.fightTickRemain:
+        battle.CaclFightTick(tick)
+    # 暂定没击杀算输,发起方为1
+    if not battle.winFaction:
+        battle.winFaction = 2
+    battle.isWin = 1 if battle.winFaction == 1 else 0
     mapID = battle.mapID
     funcLineID = battle.funcLineID
     winFaction = battle.winFaction
     isQuick = battle.isQuick
     isLogout = battle.isLogout
-    GameWorld.DebugLog("镜像战斗结束: mapID=%s,funcLineID=%s,winFaction=%s,isQuick=%s,isLogout=%s" 
-                       % (mapID, funcLineID, winFaction, isQuick, isLogout), battleID)
+    GameWorld.DebugLog("镜像战斗结束: mapID=%s,funcLineID=%s,winFaction=%s,isWin=%s,isQuick=%s,isLogout=%s" 
+                       % (mapID, funcLineID, winFaction, battle.isWin, isQuick, isLogout), battleID)
     
     playerMgr = GameWorld.GetMapCopyPlayerManager()
     
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 4158f76..327fa7b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -17238,48 +17238,74 @@
 # C0 15 跨服排位分区分组信息 #tagGCCrossChampionshipPKZoneGroupInfo
 
 class  tagGCCrossChampionshipPKBattle(Structure):
-    _pack_ = 1
-    _fields_ = [
-                  ("BattleNum", c_ubyte),    # 对战组编号 1~n
-                  ("WinPlayerID", c_int),    # 获胜玩家ID
-                  ("PlayerIDA", c_int),    # 玩家IDA
-                  ("PlayerIDB", c_int),    # 玩家IDB
-                  ]
+    BattleNum = 0    #(BYTE BattleNum)// 对战组编号 1~n
+    WinPlayerID = 0    #(DWORD WinPlayerID)// 获胜玩家ID
+    PlayerIDA = 0    #(DWORD PlayerIDA)// 玩家IDA
+    PlayerIDB = 0    #(DWORD PlayerIDB)// 玩家IDB
+    BattleRetLen = 0    #(BYTE BattleRetLen)
+    BattleRet = ""    #(String BattleRet)// 战斗结果明细 {"playerID":[[第1局胜负,第1局总积分,胜负基础分,hp分,时间分], ...], ...}
+    data = None
 
     def __init__(self):
         self.Clear()
         return
 
-    def ReadData(self, stringData, _pos=0, _len=0):
+    def ReadData(self, _lpData, _pos=0, _Len=0):
         self.Clear()
-        memmove(addressof(self), stringData[_pos:], self.GetLength())
-        return _pos + self.GetLength()
+        self.BattleNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.WinPlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.PlayerIDA,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.PlayerIDB,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.BattleRetLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.BattleRet,_pos = CommFunc.ReadString(_lpData, _pos,self.BattleRetLen)
+        return _pos
 
     def Clear(self):
         self.BattleNum = 0
         self.WinPlayerID = 0
         self.PlayerIDA = 0
         self.PlayerIDB = 0
+        self.BattleRetLen = 0
+        self.BattleRet = ""
         return
 
     def GetLength(self):
-        return sizeof(tagGCCrossChampionshipPKBattle)
+        length = 0
+        length += 1
+        length += 4
+        length += 4
+        length += 4
+        length += 1
+        length += len(self.BattleRet)
+
+        return length
 
     def GetBuffer(self):
-        return string_at(addressof(self), self.GetLength())
+        data = ''
+        data = CommFunc.WriteBYTE(data, self.BattleNum)
+        data = CommFunc.WriteDWORD(data, self.WinPlayerID)
+        data = CommFunc.WriteDWORD(data, self.PlayerIDA)
+        data = CommFunc.WriteDWORD(data, self.PlayerIDB)
+        data = CommFunc.WriteBYTE(data, self.BattleRetLen)
+        data = CommFunc.WriteString(data, self.BattleRetLen, self.BattleRet)
+        return data
 
     def OutputString(self):
-        DumpString = '''// C0 15 跨服排位分区分组信息 //tagGCCrossChampionshipPKZoneGroupInfo:
+        DumpString = '''
                                 BattleNum:%d,
                                 WinPlayerID:%d,
                                 PlayerIDA:%d,
-                                PlayerIDB:%d
+                                PlayerIDB:%d,
+                                BattleRetLen:%d,
+                                BattleRet:%s
                                 '''\
                                 %(
                                 self.BattleNum,
                                 self.WinPlayerID,
                                 self.PlayerIDA,
-                                self.PlayerIDB
+                                self.PlayerIDB,
+                                self.BattleRetLen,
+                                self.BattleRet
                                 )
         return DumpString
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PlayerMirror.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PlayerMirror.py
index 7bb7fb0..5aba18f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PlayerMirror.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PlayerMirror.py
@@ -89,7 +89,9 @@
     elif value1 == "q":
         battle = MirrorAttack.GetMirrorBattle(curPlayer)
         if battle:
-            MirrorAttack.DoMirrorBattleQuick(battle.battleID)
+            if not MirrorAttack.DoMirrorBattleQuick(battle.battleID, isClick=True):
+                GameWorld.DebugAnswer(curPlayer, "无法执行快速战斗,详见地图日志!")
+                return
             
     elif value1 == "e":
         PlayerFB.DoExitCustomScene(curPlayer)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetCrossPK.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetCrossPK.py
index 48cb47d..feab5e2 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetCrossPK.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetCrossPK.py
@@ -36,20 +36,22 @@
         return
     
     if msgList[0] == "b":        
-        danLV = msgList[1] if len(msgList) > 1 else 0
-        pkScore = msgList[2] if len(msgList) > 2 else 0
-        cWinCount = msgList[3] if len(msgList) > 3 else None
+        zoneID = msgList[1] if len(msgList) > 1 else 0
+        seasonID = msgList[2] if len(msgList) > 2 else 0
+        danLV = msgList[3] if len(msgList) > 3 else 0
+        pkScore = msgList[4] if len(msgList) > 4 else 0
+        cWinCount = msgList[5] if len(msgList) > 5 else None
         danIpyData = IpyGameDataPY.GetIpyGameData("CrossRealmPKDan", danLV)
         if not danIpyData:
             GameWorld.DebugAnswer(curPlayer, "不存在该段位:%s" % danLV)
             return
         if pkScore <= 0:
             pkScore = danIpyData.GetLVUpScore()
-        errorMsg = PlayerCrossRealmPK.GMSetPlayerCrossPKData(curPlayer, danLV, pkScore, cWinCount)
+        errorMsg = PlayerCrossRealmPK.GMSetPlayerCrossPKData(curPlayer, danLV, pkScore, cWinCount, zoneID=zoneID, seasonID=seasonID)
         if errorMsg:
             GameWorld.DebugAnswer(curPlayer, "分区赛季异常!")
         else:
-            GameWorld.DebugAnswer(curPlayer, "设置上榜段位:%s,积分:%s" % (danLV, pkScore))
+            GameWorld.DebugAnswer(curPlayer, "设置上榜分区:%s,赛季:%s,段位:%s,积分:%s" % (zoneID, seasonID, danLV, pkScore))
         return
     
     if len(msgList) == 1:
@@ -140,7 +142,7 @@
     GameWorld.DebugAnswer(curPlayer, "设置历史记录: SetCrossPK 赛季ID 类型 数值")
     GameWorld.DebugAnswer(curPlayer, "类型:0-段位,1-名次,2-积分,3-奖励等级")
     GameWorld.DebugAnswer(curPlayer, "当前连败次数: %s" % curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_CLoseCount))
-    GameWorld.DebugAnswer(curPlayer, "设置上榜: SetCrossPK b 段位 [积分 连胜]")
+    GameWorld.DebugAnswer(curPlayer, "设置上榜: SetCrossPK b 分区 赛季 段位 [积分 连胜]")
     return
 
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossChampionship.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossChampionship.py
index 2871188..e9b8e42 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossChampionship.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossChampionship.py
@@ -15,567 +15,116 @@
 #"""Version = 2022-09-21 21:30"""
 #-------------------------------------------------------------------------------
 
-import ChPlayer
 import GameWorld
+import MirrorAttack
 import IPY_GameWorld
 import PlayerControl
-import GameWorldProcess
+import CrossRealmPlayer
 import IpyGameDataPY
-import SkillCommon
+import ShareDefine
 import FBCommon
-import ChConfig
 import GameObj
 
-(
-Def_Time_MaxWait, # 最长等待时间, 秒
-Def_Time_MapPrepare, # 准备时间, 秒
-Def_Time_Fight, # 战斗时间, 秒
-Def_Time_Protect, # 保护时间,秒,玩家战斗中掉线保护时长
-Def_Time_Leave, # 结束退出时间, 秒
-) = range(5)
 
-# 当前副本地图的状态
-(
-FB_State_Open,
-FB_State_Waiting, # 等待对手阶段
-FB_State_MapPrepare, # 地图准备
-FB_State_Fight, # 战斗阶段
-FB_State_Reborn, # 复活阶段
-FB_State_Leave, # 离开阶段
-FB_State_Close, # 关闭阶段
-) = range(7)
-
-# 对战结束类型定义
-(
-Def_OverType_LackPlayer, # 缺少对手
-Def_OverType_PlayerExit, # 对手退出(视为认输)
-Def_OverType_Kill, # 击杀对手
-Def_OverType_TimeOut, # PK时间超时
-) = range(4)
-
-# 副本相关字典key
-GameFBDict_FBPlayerID = "FBD_FBPlayerID_%s" # 玩家ID, 参数, 进入顺序
-GameFBDict_PlayerWinCnt = "FBD_PlayerWinCnt_%s" # 玩家已获胜次数, 参数[playerID]
-GameFBDict_PlayerLeaveTick = "FBD_PlayerLeaveTick_%s" # 玩家已获胜次数, 参数[playerID]
-
-FBPDict_PVPDamage = "FBPD_PVPDamage" # 玩家伤害输出
-FBPDict_PVPDamUpdTick = "FBPD_PVPDamUpdTick" # 更新伤害tick
-FBPDict_ResetPosX = "FBPD_ResetPosX" # 玩家重置坐标X
-FBPDict_ResetPosY = "FBPD_ResetPosY" # 玩家重置坐标Y
-FBPDict_RoundNum = "FBPD_RoundNum" # 玩家当前所属回合数
-
-FB_RoundNum = "FB_RoundNum" # 副本当前回合数
-FB_RoundWinPlayerID = "FB_RoundWinPlayerID_%s" # 回合获胜玩家ID, 参数[回合数]
-
-def OnOpenFB(tick):
-    # 开启副本直接进入等待阶段
-    FBCommon.SetFBStep(FB_State_Waiting, tick)
-    return
-
-## 是否能够通过活动查询进入
-def OnEnterFBEvent(curPlayer, mapID, lineID, tick):
+###处理副本中杀死玩家逻辑
+def DoFBOnKill_Player(atkobj, defender, tick):
+    GameWorld.DebugLog("镜像切磋击杀玩家: defID=%s" % (defender.GetID()), atkobj.GetID())
     return True
 
-#def OnGetFBEnterPos(curPlayer, mapID, lineId, ipyEnterPosInfo, tick):
-#    posDict = {117401:(40,37), 117403:(10, 7)}
-#    return posDict.get(curPlayer.GetPlayerID())
-
-## 玩家进入副本
-def DoEnterFB(curPlayer, tick):
-    playerID = curPlayer.GetPlayerID()
-    playerVSRoomID = curPlayer.GetVsRoomId()
-    roomID = GameWorld.GetGameWorld().GetPropertyID()        
-    gameFB = GameWorld.GetGameFB()
-    fbStep = gameFB.GetFBStep()
-    GameWorld.Log("DoEnterFB fbRoomID=%s,playerVSRoomID=%s,fbStep=%s" % (roomID, playerVSRoomID, fbStep), playerID)
-    
-    if gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerID):
-        GameWorld.Log("    玩家离线保护时间内上线!", playerID)
-        gameFB.SetGameFBDict(GameFBDict_PlayerLeaveTick % playerID, 0)
-        playerManager = GameWorld.GetMapCopyPlayerManager()
-        for index in xrange(playerManager.GetPlayerCount()):
-            player = playerManager.GetPlayerByIndex(index)
-            if player and player.GetPlayerID() != curPlayer.GetPlayerID():
-                player.Sync_TimeTick(ChConfig.tttPlayerLeave, 0, 0, True)
-                
-    fbRoundNum = gameFB.GetGameFBDictByKey(FB_RoundNum)
-    playerRoundNum = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_RoundNum)
-    if playerRoundNum and fbRoundNum and playerRoundNum != fbRoundNum:
-        # 一般是掉线时上个回合已经结束了
-        GameWorld.DebugLog("玩家进入副本时与当前副本回合数不一致时,重置状态!fbRoundNum=%s,playerRoundNum=%s" 
-                           % (fbRoundNum, playerRoundNum), playerID)
-        gameFB.SetPlayerGameFBDict(playerID, FBPDict_RoundNum, fbRoundNum)
-        __ResetPlayerState(gameFB, curPlayer, playerID)
-        
-    if fbStep >= FB_State_Leave or not roomID or not playerVSRoomID or roomID != playerVSRoomID:
-        PlayerControl.PlayerLeaveFB(curPlayer)
-        return
-    PlayerControl.SetSight(curPlayer, ChConfig.Def_PlayerSight_Default * 3)
-    
-    # 非战斗阶段,通知动态障碍点
-    if fbStep < FB_State_Fight:
-        FBCommon.SyncDynamicBarrierState(IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 2), 1, curPlayer) # 准备期间有动态障碍点
-        
-    fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)
-    
-    if fbStep == FB_State_Open:
-        pass
-    
-    elif fbStep == FB_State_Waiting:
-        playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)
-        playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)
-        if not playerIDA and not playerIDB:
-            gameFB.SetGameFBDict(GameFBDict_FBPlayerID % 1, playerID)
-            gameFB.SetPlayerGameFBDict(playerID, FBPDict_ResetPosX, curPlayer.GetPosX())
-            gameFB.SetPlayerGameFBDict(playerID, FBPDict_ResetPosY, curPlayer.GetPosY())
-            gameFB.SetPlayerGameFBDict(playerID, FBPDict_RoundNum, 1)
-            GameWorld.Log("    第一个进入,阵营1,roomID=%s" % (roomID), playerID)
-            __ResetPlayerState(gameFB, curPlayer, playerID)
-            
-        elif not playerIDB and playerIDA != playerID:
-            gameFB.SetGameFBDict(GameFBDict_FBPlayerID % 2, playerID)
-            gameFB.SetPlayerGameFBDict(playerID, FBPDict_ResetPosX, curPlayer.GetPosX())
-            gameFB.SetPlayerGameFBDict(playerID, FBPDict_ResetPosY, curPlayer.GetPosY())
-            gameFB.SetPlayerGameFBDict(playerID, FBPDict_RoundNum, 1)
-            GameWorld.Log("    第二个进入,阵营2,roomID=%s" % (roomID), playerID)
-            __ResetPlayerState(gameFB, curPlayer, playerID)
-            
-        playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)
-        playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)
-        if GameWorld.GetMapCopyPlayerManager().GetPlayerCount() == 2 and playerIDA and playerIDB:
-            GameWorld.Log("    两个人都在,设置副本进入战斗倒计时阶段!roomID=%s" % (roomID), playerID)
-            FBCommon.SetFBStep(FB_State_MapPrepare, tick)
-            FBCommon.Sync_Player_TimeTick(ChConfig.tttWaitStart, fbTimeList[Def_Time_MapPrepare] * 1000)
-            gameFB.SetGameFBDict(FB_RoundNum, 1)
-        else:
-            notify_tick = fbTimeList[Def_Time_MaxWait] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
-            curPlayer.Sync_TimeTick(ChConfig.tttWaitPlayer, 0, max(notify_tick, 0), True)
-            GameWorld.Log("    对手不在,继续等待!roomID=%s" % (roomID), playerID)
-            
-    elif fbStep == FB_State_MapPrepare:
-        notify_tick = fbTimeList[Def_Time_MapPrepare] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
-        curPlayer.Sync_TimeTick(ChConfig.tttWaitStart, 0, max(notify_tick, 0), True)
-        
-    elif fbStep == FB_State_Fight:
-        notify_tick = fbTimeList[Def_Time_Fight] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
-        curPlayer.Sync_TimeTick(ChConfig.tttTowerTake, 0, max(notify_tick, 0), True)
-        
-    FBCommon.Notify_FBHelp(curPlayer, __GetFBHelpInfo())
-    PlayerControl.DelLimitSuperBuff(curPlayer, tick)
-    PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState()
-    return
-
-def __GetFBHelpInfo():
-    gameFB = GameWorld.GetGameFB()
-    roundWinerIDList = []
-    roundNum = gameFB.GetGameFBDictByKey(FB_RoundNum)
-    for roundNum in xrange(1, roundNum + 1):
-        winnerID = gameFB.GetGameFBDictByKey(FB_RoundWinPlayerID % roundNum)
-        if not winnerID:
-            break
-        roundWinerIDList.append(winnerID)
-        
-    return {"roundNum":roundNum, "roundWinerIDList":roundWinerIDList}
-
-
-## 玩家退出副本
-def DoExitFB(curPlayer, tick):
-    # 结算时间
-    gameFB = GameWorld.GetGameFB()
-    fbStep = gameFB.GetFBStep()
-    
-    if fbStep >= FB_State_Leave:
-        return
+def OnMirrorBattleRequest(curPlayer, mapID, funcLineID):
+    ## 镜像战斗请求
     
     playerID = curPlayer.GetPlayerID()
-    gameFB.SetGameFBDict(GameFBDict_PlayerLeaveTick % playerID, tick)
-    GameWorld.Log("玩家战斗阶段下线!playerID=%s,waitPlayerID=%s" % (playerID, playerID))
-    
-    ## 通知对方,对手掉线
-    playerManager = GameWorld.GetMapCopyPlayerManager()
-    for index in xrange(playerManager.GetPlayerCount()):
-        player = playerManager.GetPlayerByIndex(index)
-        if player and player.GetPlayerID() != curPlayer.GetPlayerID():
-            fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)
-            player.Sync_TimeTick(ChConfig.tttPlayerLeave, 0, max(fbTimeList[Def_Time_Protect] * 1000, 0), True)
-            
-    return
-
-##玩家主动离开副本.
-def DoPlayerLeaveFB(curPlayer, tick):
-    gameFB = GameWorld.GetGameFB()
-    fbStep = gameFB.GetFBStep()
-    
-    if fbStep <= FB_State_Waiting or fbStep >= FB_State_Leave:
+    if GameWorld.IsCrossServer():
         return
     
-    leavePlayerID = curPlayer.GetPlayerID()
-    roomID = GameWorld.GetGameWorld().GetPropertyID()
-    playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)
-    playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)
-    
-    loser, loserID = curPlayer, leavePlayerID
-    winnerID = playerIDA if playerIDB == loserID else playerIDB
-    winner = GameWorld.GetMapCopyPlayerManager().FindPlayerByID(winnerID)
-    GameWorld.Log("玩家主动退出,直接算输! roomID=%s,leavePlayerID=%s,loserID=%s,winnerID=%s" % (roomID, leavePlayerID, loserID, winnerID))
-    __DoFBPKAllOver(winner, winnerID, loser, loserID, Def_OverType_PlayerExit, tick)
-    return
-
-## 获得副本帮助信息
-def DoFBHelp(curPlayer, tick):
-    return
-
-## 副本总逻辑计时器
-def OnProcess(tick):
-    gameFB = GameWorld.GetGameFB()
-    fbStep = gameFB.GetFBStep()
-    
-    if fbStep == FB_State_Waiting:
-        __DoLogic_Waiting(tick)
-    elif fbStep == FB_State_MapPrepare:
-        if not __CheckLeaveProtectTimeout(tick):
-            __DoLogic_MapPrepare(tick)
-    elif fbStep == FB_State_Fight:
-        if not __CheckLeaveProtectTimeout(tick):
-            __DoLogic_MapFight(tick)
-    elif fbStep == FB_State_Reborn:
-        __DoLogic_Reborn(tick)
-    elif fbStep == FB_State_Leave:
-        __DoLogic_LeaveTime(tick)
-        
-    return
-
-##等待玩家进入阶段处理
-def __DoLogic_Waiting(tick):
-    fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)
-    if tick - GameWorld.GetGameFB().GetFBStepTick() < fbTimeList[Def_Time_MaxWait] * 1000:
+    if not CrossRealmPlayer.IsCrossServerOpen():
+        PlayerControl.NotifyCode(curPlayer, "CrossMatching18")
         return
     
-    winner, winnerID, loser, loserID = __GetTimeoutWinerInfo(tick)
-    # 对手没来,直接获胜
-    roomID = GameWorld.GetGameWorld().GetPropertyID()
-    GameWorld.Log("战前等待对手阶段超时,直接结束!roomID=%s,winnerID=%s,loserID=%s" % (roomID, winnerID, loserID))
-    __DoFBPKAllOver(winner, winnerID, loser, loserID, Def_OverType_LackPlayer, tick)
-    return
-
-def __CheckLeaveProtectTimeout(tick):
-    gameFB = GameWorld.GetGameFB()
-    playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)
-    playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)
-    playerLeaveTickA = gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerIDA)
-    playerLeaveTickB = gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerIDB)
-    if not playerLeaveTickA and not playerLeaveTickB:
+    if curPlayer.GetPlayerAction() == IPY_GameWorld.paDie or GameObj.GetHP(curPlayer) == 0:
+        GameWorld.DebugLog("已死亡,无法进行跨服排位赛!", playerID)
         return
     
-    fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)
-    if playerLeaveTickA > playerLeaveTickB:
-        if tick - playerLeaveTickA < fbTimeList[Def_Time_Protect] * 1000:
-            return
-    else:
-        if tick - playerLeaveTickB < fbTimeList[Def_Time_Protect] * 1000:
-            return
-        
-    winner, winnerID, loser, loserID = __GetTimeoutWinerInfo(tick)
-    # 对手没来,直接获胜
-    roomID = GameWorld.GetGameWorld().GetPropertyID()
-    GameWorld.Log("战斗中对手离线超时,直接结束!roomID=%s,winnerID=%s,loserID=%s" % (roomID, winnerID, loserID))
-    __DoFBPKAllOver(winner, winnerID, loser, loserID, Def_OverType_PlayerExit, tick)
+    stateError = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossChampionshipStateError)
+    if stateError:
+        GameWorld.ErrLog("跨服排位状态已经异常无法进入! stateError=%s" % stateError, playerID)
+        return
+    
+    state = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossChampionshipState)
+    if state not in ShareDefine.CrossChampionshipEnterStateInfo:
+        GameWorld.ErrLog("当前状态非跨服排位战斗状态无法进入: state=%s" % state, playerID)
+        return
+    groupMark = ShareDefine.CrossChampionshipEnterStateInfo[state]
+    reqGroupMark = funcLineID % 100
+    if reqGroupMark != groupMark:
+        GameWorld.ErrLog("当前状态与跨服排位战斗分组不一致无法进入: funcLineID=%s,reqGroupMark=%s != %s" % (funcLineID, reqGroupMark, groupMark), playerID)
+        return
+    
     return True
 
-def __GetTimeoutWinerInfo(tick):
-    ''' 时间超时,获取获胜的玩家
-                    战斗阶段有两个玩家时优先比较输出
-                    其他情况则在线玩家获胜,如果没有玩家在线,则最迟离线的获胜
-    '''
-    winner, winnerID, loser, loserID = None, 0, None, 0
-    roomID = GameWorld.GetGameWorld().GetPropertyID()
-    gameFB = GameWorld.GetGameFB()
-    fbStep = gameFB.GetFBStep()
-    copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()
-    playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)
-    playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)
+def OnMirrorBattleOver(battleID):
+    ## 镜像战斗结束
     
-    # 战斗阶段有两个玩家时优先比较输出
-    if fbStep == FB_State_Fight and copyMapPlayerManager.GetPlayerCount() == 2:
-        # 时间到还没分出胜负, 根据以下规则决定胜负,这里用玩家ID处理,防止结算时都掉线了导致没有结果
-        # 伤害输出 > 优先到达时间 > 剩余HP > 最大HP > playerID
-        
-        GameWorld.Log("两个人都在线,根据超时规则判断胜负玩家! roomID=%s" % (roomID))
-        playerInfoList = []
-        for playerID in [playerIDA, playerIDB]:
-            player = copyMapPlayerManager.FindPlayerByID(playerID)
-            # 还是离线时间的,走掉线逻辑,越晚掉线的赢;需要加这个逻辑主要是因为当玩家没有触发完整登录流程导致玩家在线但是没有触发DoEnter
-            playerLeaveTick = gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerID)
-            if playerLeaveTick:
-                pvpDamage, sortTick, curHP, curMaxHP = 0, 0, 0, 0
-                playerInfoList.append([pvpDamage, sortTick, curHP, curMaxHP, playerLeaveTick, playerID, player])
-                GameWorld.Log("PK超时: playerLeaveTick=%s" % (playerLeaveTick), playerID)
-                continue
-            pvpDamage = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_PVPDamage)
-            pvpDamTick = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_PVPDamUpdTick)
-            sortTick = tick - pvpDamTick
-            curHP = 0 if not player else GameObj.GetHP(player)
-            curMaxHP = 0 if not player else GameObj.GetMaxHP(player)
-            playerInfoList.append([pvpDamage, sortTick, curHP, curMaxHP, playerLeaveTick, playerID, player])
-            GameWorld.Log("PK超时: pvpDamge=%s,pvpDamTick=%s,tick=%s,sortTick=%s,HP=%s/%s,playerLeaveTick=%s" 
-                          % (pvpDamage, pvpDamTick, tick, sortTick, curHP, curMaxHP, playerLeaveTick), playerID)
+    battle = MirrorAttack.GetMirrorBattleByID(battleID)
+    if not battle:
+        return
+    mapID = battle.mapID
+    funcLineID = battle.funcLineID
+    isWin = battle.isWin
+    curPlayerID = battle.requestID # 副本所属玩家ID,该玩家不一定参与实际战斗
+    tagPlayerID = battle.GetTagPlayerID()
+    fightTickRemain = battle.fightTickRemain
+    curHPPer = 0 # 自己剩余血量百分比 0~100,支持小数点
+    tagHPPer = 0 # 对方剩余血量百分比 0~100,支持小数点
+    
+    curPlayer = None
+    playerMgr = GameWorld.GetMapCopyPlayerManager()
+    for playerID, faction in battle.playerFactionDict.items():
+        player = playerMgr.FindPlayerByID(playerID)
+        if not player:
+            continue
+        realPlayerID = player.GetRealPlayerID()
+        hp = GameObj.GetHP(player)
+        hpMax = GameObj.GetMaxHP(player)
+        hpPer = hp / float(hpMax) * 100
+        GameWorld.DebugLog("    剩余血量: %s/%s,hpPer=%s%%,playerID=%s,realPlayerID=%s,faction=%s" 
+                           % (hp, hpMax, hpPer, playerID, realPlayerID, faction), battleID)
+        if not realPlayerID and curPlayerID == playerID:
+            curPlayer = player
+            curHPPer = hpPer
+        if tagPlayerID == realPlayerID:
+            tagHPPer = hpPer
             
-        playerInfoList.sort(reverse=True)
-        GameWorld.Log("PK超时, 进入结算!playerInfoList=%s" % str(playerInfoList))
-        winner = playerInfoList[0][-1] if len(playerInfoList) > 0 else None
-        loser = playerInfoList[1][-1] if len(playerInfoList) > 1 else None
-        winnerID = 0 if not winner else winner.GetPlayerID()
-        loserID = 0 if not loser else loser.GetPlayerID()
-        return winner, winnerID, loser, loserID
-    
-    # 其他情况则在线玩家获胜,如果没有玩家在线,则最迟离线的获胜
-    for i in xrange(copyMapPlayerManager.GetPlayerCount()):
-        player = copyMapPlayerManager.GetPlayerByIndex(i)
-        if player == None or player.IsEmpty():
-            continue
-        playerID = player.GetPlayerID()
-        if playerID not in [playerIDA, playerIDB]:
-            GameWorld.ErrLog("副本中玩家不在进入的玩家ID里,不处理! roomID=%s,playerID=%s" % (roomID, playerID))
-            continue
-        winner = player
-        winnerID = player.GetPlayerID()
-        GameWorld.Log("超时结算,玩家在线,直接获胜: roomID=%s,winnerID=%s" % (roomID, winnerID))
-        break
-    
-    if not winner:
-        playerLeaveTickA = gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerIDA)
-        playerLeaveTickB = gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerIDB)
-        GameWorld.Log("超时结算,没有玩家在线,后离线的获胜: playerLeaveTickA=%s,playerLeaveTickB=%s" % (playerLeaveTickA, playerLeaveTickB))
-        # 离线tick较大的就是比较晚离线的
-        if playerLeaveTickA > playerLeaveTickB:
-            winnerID = playerIDA
-            loserID = playerIDB
-        else:
-            winnerID = playerIDB
-            loserID = playerIDA
-    else:
-        loserID = playerIDB if playerIDA == winnerID else playerIDA
-    return winner, winnerID, loser, loserID
-
-##副本准备时间
-def __DoLogic_MapPrepare(tick):
-    fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)
-    if tick - GameWorld.GetGameFB().GetFBStepTick() < fbTimeList[Def_Time_MapPrepare] * 1000:
+    if not curPlayer:
         return
     
-    FBCommon.SetFBStep(FB_State_Fight, tick)
-    FBCommon.Sync_Player_TimeTick(ChConfig.tttTowerTake, fbTimeList[Def_Time_Fight] * 1000)
-    FBCommon.SyncDynamicBarrierState(IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 2), 0)
+    baseScoreList = IpyGameDataPY.GetFuncEvalCfg("CrossChamMirrorPK", 2)
+    baseScore = 0
+    if baseScoreList and len(baseScoreList) == 2:
+        baseScore = baseScoreList[0] if battle.isWin else baseScoreList[1]
+    hpScore = int(eval(IpyGameDataPY.GetFuncCompileCfg("CrossChamMirrorPK", 3)))
+    GameWorld.DebugLog("    hpScore=%s,curHPPer=%s,tagHPPer=%s" % (hpScore, curHPPer, tagHPPer), battleID)
+    remainTimePer = fightTickRemain / float(battle.fightTickMax) * 100 # 剩余战斗时间百分比
+    timeScore = int(eval(IpyGameDataPY.GetFuncCompileCfg("CrossChamMirrorPK", 4)))
+    addScore = baseScore + hpScore + timeScore
+    GameWorld.DebugLog("    timeScore=%s,remainTimePer=%s%%,fightTickRemain=%s,fightTickMax=%s" % (timeScore, remainTimePer, fightTickRemain, battle.fightTickMax), battleID)
     
-    # 通知回合开始
-    helpDict = __GetFBHelpInfo()
-    helpDict["isStart"] = 1
-    copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()
-    for i in xrange(copyMapPlayerManager.GetPlayerCount()):
-        player = copyMapPlayerManager.GetPlayerByIndex(i)
-        if player == None or player.IsEmpty():
-            continue
-        FBCommon.Notify_FBHelp(player, helpDict)
-        
-    return
-
-##战斗阶段
-def __DoLogic_MapFight(tick):
-    fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)
-    if tick - GameWorld.GetGameFB().GetFBStepTick() < fbTimeList[Def_Time_Fight] * 1000:
-        return
-    
-    winner, winnerID, loser, loserID = __GetTimeoutWinerInfo(tick)
-    roomID = GameWorld.GetGameWorld().GetPropertyID()
-    GameWorld.Log("PK超时, 进入结算! roomID=%s,winnerID=%s,loserID=%s" % (roomID, winnerID, loserID))
-    __DoLogicAddPlayerWinCnt(winner, winnerID, loser, loserID, Def_OverType_TimeOut, tick)
-    return
-
-##复活阶段阶段
-def __DoLogic_Reborn(tick):
-    gameFB = GameWorld.GetGameFB()
-    
-    helpDict = __GetFBHelpInfo()
-    
-    fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)
-    prepareTime = fbTimeList[Def_Time_MapPrepare] * 1000
-    helpDict["prepareTime"] = prepareTime
-    
-    roundNum = gameFB.GetGameFBDictByKey(FB_RoundNum)
-    winnerID = gameFB.GetGameFBDictByKey(FB_RoundWinPlayerID % roundNum)
-    
-    nextRoundNum = gameFB.GetGameFBDictByKey(FB_RoundNum) + 1
-    gameFB.SetGameFBDict(FB_RoundNum, nextRoundNum)
-    
-    copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()
-    for i in xrange(copyMapPlayerManager.GetPlayerCount()):
-        player = copyMapPlayerManager.GetPlayerByIndex(i)
-        if player == None or player.IsEmpty():
-            continue
-        
-        playerID = player.GetPlayerID()
-        gameFB.SetPlayerGameFBDict(playerID, FBPDict_RoundNum, nextRoundNum)
-        
-        if player.GetPlayerAction() == IPY_GameWorld.paDie or GameObj.GetHP(player) <= 0:
-            GameWorld.DebugLog("复活玩家...", player.GetPlayerID())
-            ChPlayer.PlayerRebornByType(player, ChConfig.rebornType_System, tick, isAddSuperBuff=False)
-            __ResetPlayerState(gameFB, player, playerID)
-        elif winnerID and playerID != winnerID:
-            GameWorld.DebugLog("平局,输的玩家回满血!", playerID)
-            __ResetPlayerState(gameFB, player, playerID)         
-        else:
-            __ResetPlayerState(gameFB, player, playerID, False)
-                
-        FBCommon.Notify_FBHelp(player, helpDict)
-        
-    GameWorld.Log("开始下一回合: nextRoundNum=%s" % (nextRoundNum))
-    
-    # 重置伤害输出
-    playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)
-    playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)
-    gameFB.SetPlayerGameFBDict(playerIDA, FBPDict_PVPDamage, 0)
-    gameFB.SetPlayerGameFBDict(playerIDA, FBPDict_PVPDamUpdTick, tick)
-    gameFB.SetPlayerGameFBDict(playerIDB, FBPDict_PVPDamage, 0)
-    gameFB.SetPlayerGameFBDict(playerIDB, FBPDict_PVPDamUpdTick, tick)
-    
-    # 进入准备倒计时,开始下一局准备
-    FBCommon.SetFBStep(FB_State_MapPrepare, tick)
-    #FBCommon.Sync_Player_TimeTick(ChConfig.tttWaitStart, prepareTime)
-    return
-
-##比赛结束的空闲时间
-def __DoLogic_LeaveTime(tick):
-    fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)
-    if tick - GameWorld.GetGameFB().GetFBStepTick() < fbTimeList[Def_Time_Leave] * 1000:
-        return
-    FBCommon.SetFBStep(FB_State_Close, tick)
-    GameWorldProcess.CloseFB(tick)
-    return
-
-## PVP伤害相关
-def OnPVPDamage(curPlayer, damageValue, tagPlayer, tick):
+    pkCountMax = IpyGameDataPY.GetFuncCfg("CrossChamMirrorPK", 1)
     playerID = curPlayer.GetPlayerID()
-    tagPlayerID = tagPlayer.GetPlayerID()
-    
-    gameFB = GameWorld.GetGameFB()
-    curPlayerDamage = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_PVPDamage)
-    updDamage = min(ChConfig.Def_UpperLimit_DWord, curPlayerDamage + damageValue)
-    gameFB.SetPlayerGameFBDict(playerID, FBPDict_PVPDamage, updDamage)
-    gameFB.SetPlayerGameFBDict(playerID, FBPDict_PVPDamUpdTick, tick)
-    GameWorld.DebugLog("OnPVPDamage playerID=%s,tagPlayerID=%s,damageValue=%s,updDamage=%s,tick=%s" 
-                       % (playerID, tagPlayerID, damageValue, updDamage, tick))
-    
-    #helpDict = {"PVPDamage":[playerID, updDamage, tick]}
-    #FBCommon.Notify_FBHelp(curPlayer, helpDict)
-    #FBCommon.Notify_FBHelp(tagPlayer, helpDict)
+    dataMsg = {
+               "playerID":playerID,
+               "tagPlayerID":tagPlayerID,
+               "funcLineID":funcLineID,
+               "isWin":isWin,
+               "addScore":addScore,
+               "baseScore":baseScore,
+               "hpScore":hpScore,
+               "timeScore":timeScore,
+               "pkCountMax":pkCountMax,
+               }
+    GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_ChampionshipPKOver, dataMsg)
+    overDict = {"isWin":isWin, "tagPlayerID":tagPlayerID, "addScore":addScore, "baseScore":baseScore, "hpScore":hpScore, "timeScore":timeScore}
+    FBCommon.NotifyFBOver(curPlayer, mapID, funcLineID, isWin, overDict)
     return
-
-##处理副本中杀死玩家逻辑
-def DoFBOnKill_Player(curPlayer, defender, tick):
-    winnerID = curPlayer.GetPlayerID()
-    loserID = defender.GetPlayerID()
-    roomID = GameWorld.GetGameWorld().GetPropertyID()
-    
-    GameWorld.Log("DoFBOnKill_Player roomID=%s,winnerID=%s,loserID=%s" % (roomID, winnerID, loserID), winnerID)
-    if GameWorld.GetGameFB().GetFBStep() != FB_State_Fight:
-        return
-    
-    __DoLogicAddPlayerWinCnt(curPlayer, winnerID, defender, loserID, Def_OverType_Kill, tick)
-    return True
-
-def __DoLogicAddPlayerWinCnt(winner, winnerID, loser, loserID, overType, tick):
-        
-    gameFB = GameWorld.GetGameFB()
-    roomID = GameWorld.GetGameWorld().GetPropertyID()
-    
-    winnerWinCnt = gameFB.GetGameFBDictByKey(GameFBDict_PlayerWinCnt % winnerID)
-    updWinCnt = winnerWinCnt + 1
-    gameFB.SetGameFBDict(GameFBDict_PlayerWinCnt % winnerID, updWinCnt)
-    
-    roundNum = gameFB.GetGameFBDictByKey(FB_RoundNum)
-    gameFB.SetGameFBDict(FB_RoundWinPlayerID % roundNum, winnerID)
-    
-    GameWorld.Log("回合结束: roomID=%s,roundNum=%s,winnerID=%s,loserID=%s,updWinCnt=%s" % (roomID, roundNum, winnerID, loserID, updWinCnt))
-    isOver = (updWinCnt >= IpyGameDataPY.GetFuncCfg("CrossChamPKFB", 3))
-    if not isOver:
-        if winner:
-            clearDeBuff = False
-            # 胜利者马上清除负面buff,防止死亡导致回合表现异常,如中毒
-            for buffType in [IPY_GameWorld.bfDeBuff, IPY_GameWorld.bfProcessDeBuff, IPY_GameWorld.bfActionBuff]:
-                buffTuple = SkillCommon.GetBuffManagerByBuffType(winner, buffType)
-                if buffTuple:
-                    buffState = buffTuple[0]
-                    buffCount = buffState.GetBuffCount()
-                    if buffCount:
-                        clearDeBuff = True
-                        buffState.Clear()
-                        GameWorld.DebugLog("胜者马上清除 buffType=%s,buffCount=%s" % (buffType, buffCount), winner.GetPlayerID())
-                        
-            if clearDeBuff:
-                PlayerControl.PlayerControl(winner).RefreshAllState()
-                
-        FBCommon.SetFBStep(FB_State_Reborn, tick)
-        return
-    
-    GameWorld.Log("    已达到最大胜场,获得最终胜利!winnerID=%s" % winnerID)
-    __DoFBPKAllOver(winner, winnerID, loser, loserID, overType, tick)
-    return
-
-def __ResetPlayerState(gameFB, player, playerID, resetAttr=True):
-    posX = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_ResetPosX)
-    posY = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_ResetPosY)
-    player.ResetPos(posX, posY)
-    
-    if not resetAttr:
-        return
-    
-    if GameObj.GetHP(player) != GameObj.GetMaxHP(player):
-        GameObj.SetHP(player, GameObj.GetMaxHP(player))
-        
-    if PlayerControl.GetProDef(player) != PlayerControl.GetMaxProDef(player):
-        PlayerControl.SetProDef(player, PlayerControl.GetMaxProDef(player))
-        
-    SkillCommon.ResetAllSkillCD(player)
-    return
-
-## 跨服PK结束处理,注意 winner、loser 参数可能为None
-def __DoFBPKAllOver(winner, winnerID, loser, loserID, overType, tick):
-    gameFB = GameWorld.GetGameFB()
-    
-    roundWinerIDList = []
-    roundNum = gameFB.GetGameFBDictByKey(FB_RoundNum)
-    for roundNum in xrange(1, roundNum + 1):
-        roundWinerIDList.append(gameFB.GetGameFBDictByKey(FB_RoundWinPlayerID % roundNum))
-        
-    #副本状态进入关闭倒计时
-    fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)
-    FBCommon.Sync_Player_TimeTick(ChConfig.tttLeaveMap, fbTimeList[Def_Time_Leave] * 1000)
-    FBCommon.SetFBStep(FB_State_Leave, tick)
-    
-    #发送一条消息到GameServer通知PK对战结束,因为地图可能对手没来导致没有失败玩家ID,所以结算统一在GameServer处理
-    overType = 1 if overType in [Def_OverType_LackPlayer, Def_OverType_PlayerExit] else 0
-    roomID = GameWorld.GetGameWorld().GetPropertyID()
-    sendMsg = str([roomID, winnerID, loserID, roundWinerIDList, overType])
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "CrossChampionshipPKOver", sendMsg, len(sendMsg))
-    GameWorld.Log("PK结算SendToGameServer: roomID=%s,winnerID=%s,loserID=%s,roundWinerIDList=%s,overType=%s" 
-                  % (roomID, winnerID, loserID, roundWinerIDList, overType))
-    return
-
-#关系有3层,无-友好-敌人
-def CheckPlayersRelation_IsFriend(curPlayer, curTagPlayer):
-    return not CanAttackPlayer(curPlayer, curTagPlayer)
-
-##副本中,攻击队友逻辑
-def DoCanAttackTeamer(curPlayer, curTagPlayer):
-    return CanAttackPlayer(curPlayer, curTagPlayer)
-
-##副本中,是否可攻击
-def CanAttackPlayer(curPlayer, curTagPlayer):
-    fbStep = GameWorld.GetGameFB().GetFBStep()
-    
-    if fbStep != FB_State_Fight:
-        GameWorld.DebugLog("非战斗阶段,不可攻击!")
-        return False
-    
-    return True
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py
index c94c0bb..ffca60a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py
@@ -419,15 +419,15 @@
     GameWorld.DebugLog("同步跨服服务器PK结算: %s" % str(dataMsg), playerID)
     return
 
-def GMSetPlayerCrossPKData(curPlayer, danLV, pkScore, cWinCount=None, resultDict=None):
+def GMSetPlayerCrossPKData(curPlayer, danLV, pkScore, cWinCount=None, resultDict=None, zoneID=0, seasonID=0):
     ## GM设置玩家跨服PK数据,一般用于测试或修复外网数据
-    zoneID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID)
-    seasonID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
-    seasonState = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonState)
-    
+    if not zoneID or not seasonID:
+        zoneID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID)
+        seasonID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
+        
     errorMsg = "" 
     playerInfoDict = {}
-    if not zoneID or not seasonID or seasonState == 2:
+    if not zoneID or not seasonID:
         errorMsg = "zone season or state error."
     else:
         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DanLV, danLV)
@@ -454,7 +454,7 @@
         SyncCrossRealmPKPlayerInfo(curPlayer)
         
     if resultDict:
-        resultDict.update({"zoneID":zoneID, "seasonID":seasonID, "seasonState":seasonState, "errorMsg":errorMsg, "PlayerInfo":playerInfoDict})
+        resultDict.update({"zoneID":zoneID, "seasonID":seasonID, "errorMsg":errorMsg, "PlayerInfo":playerInfoDict})
     return errorMsg
 
 #// C1 02 跨服PK购买次数 #tagCMCrossRealmPKBuy
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index c3f1e64..b0412c7 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -182,6 +182,9 @@
 Def_Notify_WorldKey_CrossPKSeasonID = "CrossPKSeasonID"  # 本服跨服PK当前赛季
 Def_Notify_WorldKey_CrossPKSeasonState = "CrossPKSeasonState"  # 本服跨服PK赛季状态 0-关闭,1-开启中
 
+Def_Notify_WorldKey_CrossChampionshipState = "CrossChampionshipState"  # 跨服排位赛状态
+Def_Notify_WorldKey_CrossChampionshipStateError = "CrossChampionshipStateError"  # 跨服排位赛状态是否已经异常
+
 Def_Notify_WorldKey_LuckyCloudBuyInfo = "LuckyCloudBuyInfo"  # 本服幸运云购最新一期信息
 
 Def_Notify_WorldKey_CrossBattlefieldCallTeamInfo = "CrossBattlefieldCallTeamInfo" # 跨服战场召集队伍信息
@@ -1715,6 +1718,7 @@
 ClientServerMsg_BattlefieldCallKick = "BattlefieldCallKick"   # 跨服战场召集 - 踢出
 ClientServerMsg_ActDropSpecItem = "ActDropSpecItem"     # 活动特殊掉落
 ClientServerMsg_CrossAssist = "CrossAssist"             # 跨服协助
+ClientServerMsg_ChampionshipPKOver = "ChampionshipPKOver" # 跨服排位PK结束
 ClientServerMsg_ChampionshipOfficialApply = "ChampionshipOfficialApply" # 跨服排位申请官职
 ClientServerMsg_ChampionshipOfficialApplyReply = "ChampionshipOfficialApplyReply" # 跨服排位官职申请回应
 ClientServerMsg_ChampionshipOfficialKick = "ChampionshipOfficialKick" # 跨服排位辞退下级仙官

--
Gitblit v1.8.0