From f2aeecf0a02b97418b762bd6ee518c33d3ae2685 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 12 九月 2025 10:22:35 +0800
Subject: [PATCH] 129 【战斗】战斗系统-服务端(新增演武场;支持机器人;支持PVP战斗;每场战斗结束后支持查看战斗回放;榜单优化存储玩家形象Value5;主线关卡榜支持;支持查看玩家;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py                        |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBGameRec.py                         |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py                                     |   98 -
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                                 | 1036 +++++----------------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py                                     |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py                          |   82 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py                                      |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/ProjSpecialProcess.py |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py                          |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py                               |  138 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Arena.py        |  207 ++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py    |   17 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                                   |   23 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Robot.py                               |   46 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py                                 |   47 
 PySysDB/PySysDBPY.h                                                                                                    |    7 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py                 |    7 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py                            |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Arena.py                               |   22 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                                     |   42 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py                          |  121 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerArena.py                              |  566 +++++------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py      |  229 ----
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py                           |   21 
 /dev/null                                                                                                              |   54 -
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py                             |    7 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini                                             |   12 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py                       |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py                                     |    7 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                                        |   14 
 30 files changed, 1,279 insertions(+), 1,546 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index d19eff1..a59137e 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -3292,3 +3292,10 @@
 	BYTE		NeedSeconds;	//耗时秒
 };
 
+
+//机器人
+struct	Robot
+{
+	DWORD		_ID;	//机器人ID,同玩家ID
+	char		ViewCache;	//机器人缓存
+};
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index 3f4abaf..f2128de 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -513,7 +513,7 @@
 Writer = hxp
 Releaser = hxp
 RegType = 0
-RegisterPackCount = 25
+RegisterPackCount = 26
 
 PacketCMD_1 = 0xA5
 PacketSubCMD_1 = 0x04
@@ -614,6 +614,10 @@
 PacketCMD_25=0xA1
 PacketSubCMD_25=0x20
 PacketCallFunc_25=OnMoneyExchange
+
+PacketCMD_26=0xA0
+PacketSubCMD_26=0x08
+PacketCallFunc_26=OnViewGameRec
 
 ;签到
 [PlayerSignDay]
@@ -1282,9 +1286,9 @@
 PacketSubCMD_1=0x09
 PacketCallFunc_1=OnArenaMatch
 
-PacketCMD_2=0xB2
-PacketSubCMD_2=0x10
-PacketCallFunc_2=OnArenaBattle
+PacketCMD_2=
+PacketSubCMD_2=
+PacketCallFunc_2=
 
 ;节日祝福
 [PlayerFeastWish]
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
index dde3b29..18ffeee 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -21,6 +21,7 @@
 
 import ChConfig
 import PlayerTask
+import PlayerViewCache
 import ChPyNetSendPack
 import NetPackCommon
 import PlayerControl
@@ -162,26 +163,43 @@
         self.startTime = 0 # 开始时间戳,支持毫秒小数
         self.costTime = 0 # 单场战斗总耗时,支持毫秒小数
         
-        # 多小队 - 一般只有PVE用到
+        # pve 多小队 - 一般只有PVE用到
         self.lineupIndex = 0 # 当前小队索引
         self.lineupIDList = [] # npc小队列表
         self.strongerLV = 0 # npc成长等级
         self.difficulty = 0 # npc难度
+        
+        # pvp 目标
+        self.tagPlayerID = 0
+        self.tagViewCache = None
         return
     
-    def setTurnFight(self, mapID, funcLineID, turnMax, isNeedReport=False, msgDict={}, lineupIDList=[], strongerLV=0, difficulty=0):
+    def setTurnFight(self, mapID, funcLineID, turnMax, isNeedReport=False, msgDict={}):
         ## 设置本场回合战斗设定
         self.mapID = mapID
         self.funcLineID = funcLineID
         self.turnMax = turnMax # 最大回合数
         self.isNeedReport = isNeedReport
+        self.setPVE()
+        self.setPVP()
+        self.msgDict = {}
+        self.nextTurnFight(msgDict)
+        return
+    
+    def setPVE(self, lineupIDList=[], strongerLV=0, difficulty=0):
         self.lineupIndex = 0
         self.lineupIDList = lineupIDList
         self.strongerLV = strongerLV
         self.difficulty = difficulty
-        self.msgDict = {}
-        self.nextTurnFight(msgDict)
         return
+    
+    def setPVP(self, tagPlayerID=0, tagViewCache=None):
+        self.tagPlayerID = tagPlayerID
+        self.tagViewCache = tagViewCache
+        return
+    
+    #def setPVPTeam(self):
+    #    return
     
     def nextTurnFight(self, msgDict={}, resetByNextTeam=False):
         ## 一般用于玩家发起的战斗,在需要保留玩家阵容属性及状态的情况下,重置回合进入下一场战斗
@@ -481,10 +499,30 @@
                           % (chapterID, levelNum, nowChapterID, fixNowValue), curPlayer.GetPlayerID())
     return
 
-def GetPlayerLineupInfoByCache(playerID, lineupID):
-    ## 获取玩家阵容信息 - 根据玩家查看缓存
-    lineupInfo = {}
+
+def GetCacheLineupFightPower(tagViewCache, lineupID):
+    lineupInfo = GetCacheLineupInfo(tagViewCache, lineupID)
+    return lineupInfo.get("FightPower", 0)
+def GetCacheLineupInfo(tagViewCache, lineupID):
+    ## 根据查看缓存获取阵容信息,一般是 GetPlayerLineupInfo 返回的结果
+    plusDict = tagViewCache.GetPlusDict()
+    lineupDict = plusDict.get("Lineup", {})
+    lineupInfo = lineupDict.get("%s" % lineupID, {})
+    if not lineupInfo:
+        lineupInfo = lineupDict.get("%s" % ShareDefine.Lineup_Main, {})
     return lineupInfo
+
+def GetPlayerLineupFightPower(curPlayer, lineupID):
+    ## 获取玩家阵容战力,一般用于直接获取阵容战力记录用
+    return GetPlayerLineup(curPlayer, lineupID).fightPower
+def GetPlayerLineup(curPlayer, lineupID):
+    ## 获取玩家阵容
+    olPlayer = PlayerOnline.GetOnlinePlayer(curPlayer)
+    lineup = olPlayer.GetLineup(lineupID)
+    if not lineup.lineupHeroDict:
+        # 为空时默认取主阵容
+        lineup = olPlayer.GetLineup(ShareDefine.Lineup_Main)
+    return lineup
 
 def GetPlayerLineupInfo(curPlayer, lineupID):
     ## 获取玩家阵容信息,可用于战斗或查看缓存,因为可能取玩家的缓存进行对战,所以统一使用json格式,前端通用
@@ -492,11 +530,10 @@
     # @return: 阵容全部信息json字典,前端通用格式
     
     playerID = curPlayer.GetPlayerID()
-    lineup = PlayerOnline.GetOnlinePlayer(curPlayer).GetLineup(lineupID)
+    lineup = GetPlayerLineup(curPlayer, lineupID)
     if not lineup.lineupHeroDict:
         return {}
     
-    lineupInfo = {"PlayerID":playerID, "FightPower":lineup.fightPower, "ShapeType":lineup.shapeType}
     heroDict = {}
     curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptHero)
     for posNum in lineup.lineupHeroDict.keys():
@@ -522,8 +559,11 @@
                                  "AttrDict":{str(k):v for k, v in hero.heroBatAttrDict.items() if v > 0},
                                  "SkillIDList":skillIDlist,
                                  }
-    lineupInfo.update({"Hero":heroDict})
+        
+    if not heroDict:
+        return {}
     
+    lineupInfo = {"PlayerID":playerID, "FightPower":lineup.fightPower, "ShapeType":lineup.shapeType, "Hero":heroDict}
     return lineupInfo
 
 def GetNPCLineupInfo(lineupID, strongerLV=0, difficulty=0):
@@ -633,7 +673,7 @@
             if skillID:
                 skillIDList.append(skillID)
                 
-    awakeIpyDataList = IpyGameDataPY.GetIpyGameDataList("HeroAwake", heroID)
+    awakeIpyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("HeroAwake", heroID)
     if awakeIpyDataList:
         for awakeIpyData in awakeIpyDataList:
             if awakeIpyData.GetAwakeLV() > awakeLV:
@@ -824,12 +864,11 @@
     atkLineupID, defLineupID = FBLogic.GetFBPlayerLineupID(curPlayer, mapID, funcLineID)
     if atkLineupID not in ShareDefine.LineupList or defLineupID not in ShareDefine.LineupList:
         return
-        
+    
     # 玩家
     if tagType == 1:
-        # OnTurnFightVSPlayer
-        pass
-    
+        OnTurnFightVSPlayer(curPlayer, mapID, funcLineID, atkLineupID, defLineupID, tagID)
+        
     # NPC
     else:
         ret = FBLogic.GetFBNPCLineupInfo(curPlayer, mapID, funcLineID)
@@ -852,9 +891,8 @@
         GameWorld.DebugLog("玩家没有该阵容数据! atkLineupID=%s" % atkLineupID, playerID)
         return
     
-    turnMax = 15
+    turnMax = GetTurnMax(mapID)
     if mapID == ChConfig.Def_FBMapID_MainBoss:
-        turnMax = IpyGameDataPY.GetFuncCfg("Mainline", 3)
         # 停止主线小怪战斗、清空
         mainFightMgr = GetMainFightMgr(curPlayer)
         mainTF = mainFightMgr.turnFight
@@ -865,7 +903,8 @@
     turnFight = tfMgr.addTurnFight(mapID, funcLineID, playerID)
     guid = turnFight.guid
     
-    turnFight.setTurnFight(mapID, funcLineID, turnMax, True, lineupIDList=npcLineupIDList, strongerLV=strongerLV, difficulty=difficulty)
+    turnFight.setTurnFight(mapID, funcLineID, turnMax, True)
+    turnFight.setPVE(npcLineupIDList, strongerLV, difficulty)
     turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo})
     
     for index, lineupID in enumerate(npcLineupIDList):
@@ -882,9 +921,54 @@
         if not turnFight.isWin:
             break
         
+    PlayerOnline.GetOnlinePlayer(curPlayer).SetLastBatBuffer(guid, turnFight.batBuffer)
     SyncTurnFightReport(curPlayer, guid, turnFight.batBuffer)
     tfMgr.delTurnFight(guid)
     return
+
+def OnTurnFightVSPlayer(curPlayer, mapID, funcLineID, atkLineupID, defLineupID, tagPlayerID):
+    playerID = curPlayer.GetPlayerID()
+    GameWorld.DebugLog("OnTurnFightVSPlayer: mapID=%s,funcLineID=%s,atkLineupID=%s,defLineupID=%s,tagPlayerID=%s" 
+                       % (mapID, funcLineID, atkLineupID, defLineupID, tagPlayerID), playerID)
+    atkLineupInfo = GetPlayerLineupInfo(curPlayer, atkLineupID)
+    if not atkLineupInfo:
+        GameWorld.DebugLog("玩家没有该阵容数据! atkLineupID=%s" % atkLineupID, playerID)
+        return
+    
+    tagViewCache = PlayerViewCache.FindViewCache(tagPlayerID)
+    if not tagViewCache:
+        GameWorld.DebugLog("目标玩家没有缓存数据! tagPlayerID=%s" % tagPlayerID, playerID)
+        return {}
+    defLineupInfo = GetCacheLineupInfo(tagViewCache, defLineupID)
+    if not defLineupInfo:
+        GameWorld.DebugLog("目标玩家没有该阵容数据! tagPlayerID=%s,defLineupID=%s" % (tagPlayerID, defLineupID), playerID)
+        return
+    
+    turnMax = GetTurnMax(mapID)
+    
+    tfMgr = GetTurnFightMgr()
+    turnFight = tfMgr.addTurnFight(mapID, funcLineID, playerID)
+    guid = turnFight.guid
+    
+    turnFight.setTurnFight(mapID, funcLineID, turnMax, True)
+    turnFight.setPVP(tagPlayerID, tagViewCache)
+    turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:atkLineupInfo})
+    turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:defLineupInfo})
+    turnFight.sortActionQueue()
+    turnFight.startFight()
+    
+    __processTurnFight(turnFight.guid)
+    
+    PlayerOnline.GetOnlinePlayer(curPlayer).SetLastBatBuffer(guid, turnFight.batBuffer)
+    SyncTurnFightReport(curPlayer, guid, turnFight.batBuffer)
+    tfMgr.delTurnFight(guid)
+    return
+
+def GetTurnMax(mapID):
+    if mapID == ChConfig.Def_FBMapID_Main:
+        return IpyGameDataPY.GetFuncCfg("TurnMax", 1)
+    mapTurnMaxDict= IpyGameDataPY.GetFuncEvalCfg("TurnMax", 3, {})
+    return mapTurnMaxDict.get(mapID, IpyGameDataPY.GetFuncCfg("TurnMax", 2))
 
 #// B4 13 主线战斗请求 #tagCSMainFightReq
 #
@@ -997,13 +1081,14 @@
     mainFightMgr.levelNum = levelNum
     mainFightMgr.waveMax = waveMax
     mainFightMgr.wave = wave
-    turnMax = IpyGameDataPY.GetFuncCfg("Mainline", 2)
     mapID, funcLineID = ChConfig.Def_FBMapID_Main, PlayerControl.ComMainLevelValue(chapterID, levelNum, wave)
+    turnMax = GetTurnMax(mapID)
     GameWorld.DebugLog("设置起始关卡波: 关卡%s-%s,波=%s/%s,lineupIDList=%s,mapID=%s,funcLineID=%s,lineupID=%s,strongerLV=%s,difficulty=%s" 
                        % (chapterID, levelNum, wave, waveMax, lineupIDList, mapID, funcLineID, lineupID, strongerLV, difficulty), playerID)
     
     turnFight = mainFightMgr.turnFight
-    turnFight.setTurnFight(mapID, funcLineID, turnMax, False, lineupIDList=lineupIDList, strongerLV=strongerLV, difficulty=difficulty)
+    turnFight.setTurnFight(mapID, funcLineID, turnMax, False)
+    turnFight.setPVE(lineupIDList, strongerLV, difficulty)
     turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo})
     turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID, strongerLV, difficulty)})
     turnFight.sortActionQueue()
@@ -1589,10 +1674,19 @@
 #    char        GUID[40];    //战报guid
 #};
 def OnTurnFightReportView(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    guid = clientData.GUID
     
-    # 通过查找已存在的战报
+    lastBatBufferInfo = PlayerOnline.GetOnlinePlayer(curPlayer).GetLastBatBuffer()
+    if lastBatBufferInfo and len(lastBatBufferInfo) == 2 and guid == lastBatBufferInfo[0]:
+        guid, reprot = lastBatBufferInfo
+        SyncTurnFightReport(curPlayer, guid, reprot)
+        return
     
-    #SyncTurnFightReport(curPlayer, guid, reprot)
+    # 其他战报,一般是入库存储的,待扩展
+    
+    # 战报已过期
+    PlayerControl.NotifyCode(curPlayer, "FightReportExpired")
     return
 
 def SyncTurnFightReport(curPlayer, guid, reprot):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 7174656..356ab3b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -1894,6 +1894,7 @@
 
 Def_FBMapID_Main = 1 # 主线小怪
 Def_FBMapID_MainBoss = 2 # 主线Boss
+Def_FBMapID_ArenaBattle = 3 # 演武场
 
 #创角新手村地图ID列表
 Def_CreatRoleMapIDList = [10000]
@@ -2001,18 +2002,16 @@
 Def_FBMapID_CrossBattlefield = 32060
 #跨服仙盟夺旗战/逐鹿万界
 Def_FBMapID_CrossFamilyFlagwar = 32090
-#竞技场战斗
-Def_FBMapID_ArenaBattle = 31290
 #情缘副本
 Def_FBMapID_Love = 31300
 #镜像切磋
 Def_FBMapID_MirrorBattle = 100
 
 #前端自定义场景地图
-ClientCustomSceneList = [Def_FBMapID_PersonalBoss, Def_FBMapID_ArenaBattle, Def_FBMapID_MirrorBattle]
+ClientCustomSceneList = []
 
 #镜像PK的地图ID列表
-MirrorBattleMapIDList = [Def_FBMapID_MirrorBattle, Def_FBMapID_ArenaBattle, Def_FBMapID_CrossRealmPK, Def_FBMapID_CrossChampionship]
+MirrorBattleMapIDList = []
 
 #注册上传跨服服务器数据后直接进入跨服服务器的地图
 RegisterEnter_CrossServerMapIDList = [Def_FBMapID_CrossPenglai, Def_FBMapID_CrossDemonLand, Def_FBMapID_CrossDemonKing, 
@@ -2108,6 +2107,7 @@
 Def_FB_MapID = {
                 'MainLevel':[Def_FBMapID_Main],  # 主线关卡
                 'MainLevelBoss':[Def_FBMapID_MainBoss],  # 主线关卡boss
+                'Arena':[Def_FBMapID_ArenaBattle],
                 }
 
 #特殊副本ID, 由系统分配, 进入时候不验证IsMapCopyFull
@@ -4085,13 +4085,7 @@
 Def_PDict_SkillElementLV = "SkillElementLV%s" #专精技能技能等级  参数技能ID
 
 #竞技场
-Def_PDict_ArenaOSSeasonState = "ArenaOSSeasonState" # 开服前定制X天赛季状态  0-未比赛过,1-进行中,>1结算时的开服天
 Def_PDict_ArenaScore = "ArenaScore" # 当前积分
-Def_PDict_ArenaHighestScore = "ArenaHighestScore" # 历史最高积分
-Def_PDict_ArenaBattleCountDay = "ArenaBattleCountDay" # 今日已战斗次数
-Def_PDict_ArenaMatchRefreshCount = "ArenaMatchRefreshCount" # 匹配刷新列表次数
-Def_PDict_ArenaItemAddCount = "ArenaItemAddCount" # 今日已使用物品增加次数
-Def_PDict_ArenaBattleTagID = "ArenaBattleTagID" # 当前对战的对手ID
 
 #功能系统特权
 Def_PDict_FuncSysPrivilegeActTime = "FuncSysPrivilegeActTime_%s" # 系统功能特权激活时间戳,参数(系统功能ID)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index e01a6e6..9a3f902 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -275,20 +275,21 @@
 
 
 #------------------------------------------------------
-#A0 01 查看玩家信息通用记录 #tagViewUniversalGameRec
+# A0 08 查看通用记录 #tagCSViewGameRec
 
-class  tagViewUniversalGameRec(Structure):
+class  tagCSViewGameRec(Structure):
     _pack_ = 1
     _fields_ = [
                   ("Cmd", c_ubyte),
                   ("SubCmd", c_ubyte),
-                  ("ViewType", c_ubyte),    #查看记录的类型
+                  ("RecType", c_ushort),    #记录类型
+                  ("RecID", c_int),    #自定义记录ID
                   ]
 
     def __init__(self):
         self.Clear()
         self.Cmd = 0xA0
-        self.SubCmd = 0x01
+        self.SubCmd = 0x08
         return
 
     def ReadData(self, stringData, _pos=0, _len=0):
@@ -298,32 +299,35 @@
 
     def Clear(self):
         self.Cmd = 0xA0
-        self.SubCmd = 0x01
-        self.ViewType = 0
+        self.SubCmd = 0x08
+        self.RecType = 0
+        self.RecID = 0
         return
 
     def GetLength(self):
-        return sizeof(tagViewUniversalGameRec)
+        return sizeof(tagCSViewGameRec)
 
     def GetBuffer(self):
         return string_at(addressof(self), self.GetLength())
 
     def OutputString(self):
-        DumpString = '''//A0 01 查看玩家信息通用记录 //tagViewUniversalGameRec:
+        DumpString = '''// A0 08 查看通用记录 //tagCSViewGameRec:
                                 Cmd:%s,
                                 SubCmd:%s,
-                                ViewType:%d
+                                RecType:%d,
+                                RecID:%d
                                 '''\
                                 %(
                                 self.Cmd,
                                 self.SubCmd,
-                                self.ViewType
+                                self.RecType,
+                                self.RecID
                                 )
         return DumpString
 
 
-m_NAtagViewUniversalGameRec=tagViewUniversalGameRec()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagViewUniversalGameRec.Cmd,m_NAtagViewUniversalGameRec.SubCmd))] = m_NAtagViewUniversalGameRec
+m_NAtagCSViewGameRec=tagCSViewGameRec()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSViewGameRec.Cmd,m_NAtagCSViewGameRec.SubCmd))] = m_NAtagCSViewGameRec
 
 
 #------------------------------------------------------
@@ -14015,70 +14019,14 @@
 
 
 #------------------------------------------------------
-# B2 10 竞技场挑战玩家 #tagCMArenaBattle
+# B2 09 演武场匹配玩家 #tagCSArenaMatch
 
-class  tagCMArenaBattle(Structure):
+class  tagCSArenaMatch(Structure):
     _pack_ = 1
     _fields_ = [
                   ("Cmd", c_ubyte),
                   ("SubCmd", c_ubyte),
-                  ("TagPlayerID", c_int),    # 目标玩家ID或机器人ID
-                  ("Result", c_ubyte),    # 0-进入自定义场景发送通知后端;1-胜利(后端处理,暂时不需要发送此状态);2-失败(前端被对手击杀需要发送此状态)
-                  ]
-
-    def __init__(self):
-        self.Clear()
-        self.Cmd = 0xB2
-        self.SubCmd = 0x10
-        return
-
-    def ReadData(self, stringData, _pos=0, _len=0):
-        self.Clear()
-        memmove(addressof(self), stringData[_pos:], self.GetLength())
-        return _pos + self.GetLength()
-
-    def Clear(self):
-        self.Cmd = 0xB2
-        self.SubCmd = 0x10
-        self.TagPlayerID = 0
-        self.Result = 0
-        return
-
-    def GetLength(self):
-        return sizeof(tagCMArenaBattle)
-
-    def GetBuffer(self):
-        return string_at(addressof(self), self.GetLength())
-
-    def OutputString(self):
-        DumpString = '''// B2 10 竞技场挑战玩家 //tagCMArenaBattle:
-                                Cmd:%s,
-                                SubCmd:%s,
-                                TagPlayerID:%d,
-                                Result:%d
-                                '''\
-                                %(
-                                self.Cmd,
-                                self.SubCmd,
-                                self.TagPlayerID,
-                                self.Result
-                                )
-        return DumpString
-
-
-m_NAtagCMArenaBattle=tagCMArenaBattle()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMArenaBattle.Cmd,m_NAtagCMArenaBattle.SubCmd))] = m_NAtagCMArenaBattle
-
-
-#------------------------------------------------------
-# B2 09 竞技场匹配玩家 #tagCMArenaMatch
-
-class  tagCMArenaMatch(Structure):
-    _pack_ = 1
-    _fields_ = [
-                  ("Cmd", c_ubyte),
-                  ("SubCmd", c_ubyte),
-                  ("IsRefresh", c_ubyte),    # 0-打开界面无匹配数据时时查询,1-强制刷新匹配列表
+                  ("IsRefresh", c_ubyte),    # 0-打开界面无匹配数据时查询,1-强制刷新匹配列表
                   ]
 
     def __init__(self):
@@ -14099,13 +14047,13 @@
         return
 
     def GetLength(self):
-        return sizeof(tagCMArenaMatch)
+        return sizeof(tagCSArenaMatch)
 
     def GetBuffer(self):
         return string_at(addressof(self), self.GetLength())
 
     def OutputString(self):
-        DumpString = '''// B2 09 竞技场匹配玩家 //tagCMArenaMatch:
+        DumpString = '''// B2 09 演武场匹配玩家 //tagCSArenaMatch:
                                 Cmd:%s,
                                 SubCmd:%s,
                                 IsRefresh:%d
@@ -14118,8 +14066,8 @@
         return DumpString
 
 
-m_NAtagCMArenaMatch=tagCMArenaMatch()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMArenaMatch.Cmd,m_NAtagCMArenaMatch.SubCmd))] = m_NAtagCMArenaMatch
+m_NAtagCSArenaMatch=tagCSArenaMatch()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSArenaMatch.Cmd,m_NAtagCSArenaMatch.SubCmd))] = m_NAtagCSArenaMatch
 
 
 #------------------------------------------------------
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 369a2ec..fd93a81 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -193,6 +193,197 @@
 
 
 #------------------------------------------------------
+# A0 09 通用记录信息 #tagSCGameRecInfo
+
+class  tagSCGameRec(Structure):
+    Time = 0    #(DWORD Time)//时间
+    Value1 = 0    #(DWORD Value1)//值1
+    Value2 = 0    #(DWORD Value2)//值2
+    Value3 = 0    #(DWORD Value3)//值3
+    Value4 = 0    #(DWORD Value4)//值4
+    Value5 = 0    #(DWORD Value5)//值5
+    Value6 = 0    #(DWORD Value6)//值6
+    Value7 = 0    #(DWORD Value7)//值7
+    Value8 = 0    #(DWORD Value8)//值8
+    UserDataLen = 0    #(WORD UserDataLen)//扩展数据长度
+    UserData = ""    #(String UserData)//扩展数据
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.Time,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.Value1,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.Value2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.Value3,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.Value4,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.Value5,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.Value6,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.Value7,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.Value8,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.UserDataLen,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.UserData,_pos = CommFunc.ReadString(_lpData, _pos,self.UserDataLen)
+        return _pos
+
+    def Clear(self):
+        self.Time = 0
+        self.Value1 = 0
+        self.Value2 = 0
+        self.Value3 = 0
+        self.Value4 = 0
+        self.Value5 = 0
+        self.Value6 = 0
+        self.Value7 = 0
+        self.Value8 = 0
+        self.UserDataLen = 0
+        self.UserData = ""
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 2
+        length += len(self.UserData)
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteDWORD(data, self.Time)
+        data = CommFunc.WriteDWORD(data, self.Value1)
+        data = CommFunc.WriteDWORD(data, self.Value2)
+        data = CommFunc.WriteDWORD(data, self.Value3)
+        data = CommFunc.WriteDWORD(data, self.Value4)
+        data = CommFunc.WriteDWORD(data, self.Value5)
+        data = CommFunc.WriteDWORD(data, self.Value6)
+        data = CommFunc.WriteDWORD(data, self.Value7)
+        data = CommFunc.WriteDWORD(data, self.Value8)
+        data = CommFunc.WriteWORD(data, self.UserDataLen)
+        data = CommFunc.WriteString(data, self.UserDataLen, self.UserData)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Time:%d,
+                                Value1:%d,
+                                Value2:%d,
+                                Value3:%d,
+                                Value4:%d,
+                                Value5:%d,
+                                Value6:%d,
+                                Value7:%d,
+                                Value8:%d,
+                                UserDataLen:%d,
+                                UserData:%s
+                                '''\
+                                %(
+                                self.Time,
+                                self.Value1,
+                                self.Value2,
+                                self.Value3,
+                                self.Value4,
+                                self.Value5,
+                                self.Value6,
+                                self.Value7,
+                                self.Value8,
+                                self.UserDataLen,
+                                self.UserData
+                                )
+        return DumpString
+
+
+class  tagSCGameRecInfo(Structure):
+    Head = tagHead()
+    RecType = 0    #(WORD RecType)//记录类型
+    RecID = 0    #(DWORD RecID)//自定义记录ID
+    Count = 0    #(WORD Count)//数量
+    RecList = list()    #(vector<tagSCGameRec> RecList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA0
+        self.Head.SubCmd = 0x09
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.RecType,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.RecID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        for i in range(self.Count):
+            temRecList = tagSCGameRec()
+            _pos = temRecList.ReadData(_lpData, _pos)
+            self.RecList.append(temRecList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA0
+        self.Head.SubCmd = 0x09
+        self.RecType = 0
+        self.RecID = 0
+        self.Count = 0
+        self.RecList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 2
+        length += 4
+        length += 2
+        for i in range(self.Count):
+            length += self.RecList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteWORD(data, self.RecType)
+        data = CommFunc.WriteDWORD(data, self.RecID)
+        data = CommFunc.WriteWORD(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.RecList[i].GetLength(), self.RecList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                RecType:%d,
+                                RecID:%d,
+                                Count:%d,
+                                RecList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.RecType,
+                                self.RecID,
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagSCGameRecInfo=tagSCGameRecInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCGameRecInfo.Head.Cmd,m_NAtagSCGameRecInfo.Head.SubCmd))] = m_NAtagSCGameRecInfo
+
+
+#------------------------------------------------------
 # A0 07 副本地图功能线路人数 #tagGCFBLinePlayerCnt
 
 class  tagGCFBLineInfo(Structure):
@@ -421,190 +612,6 @@
 
 m_NAtagOpenServerDay=tagOpenServerDay()
 ChNetPackDict[eval("0x%02x%02x"%(m_NAtagOpenServerDay.Cmd,m_NAtagOpenServerDay.SubCmd))] = m_NAtagOpenServerDay
-
-
-#------------------------------------------------------
-# A0 08 玩家记录信息 #tagGCPlayerRecInfo
-
-class  tagGCPlayerRec(Structure):
-    Time = 0    #(DWORD Time)//时间
-    Value1 = 0    #(DWORD Value1)//值1
-    Value2 = 0    #(DWORD Value2)//值2
-    Value3 = 0    #(DWORD Value3)//值3
-    Value4 = 0    #(DWORD Value4)//值4
-    Value5 = 0    #(DWORD Value5)//值5
-    Value6 = 0    #(DWORD Value6)//值6
-    Value7 = 0    #(DWORD Value7)//值7
-    Value8 = 0    #(DWORD Value8)//值8
-    UserDataLen = 0    #(WORD UserDataLen)//扩展数据长度
-    UserData = ""    #(String UserData)//扩展数据
-    data = None
-
-    def __init__(self):
-        self.Clear()
-        return
-
-    def ReadData(self, _lpData, _pos=0, _Len=0):
-        self.Clear()
-        self.Time,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value1,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value3,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value4,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value5,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value6,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value7,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value8,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.UserDataLen,_pos = CommFunc.ReadWORD(_lpData, _pos)
-        self.UserData,_pos = CommFunc.ReadString(_lpData, _pos,self.UserDataLen)
-        return _pos
-
-    def Clear(self):
-        self.Time = 0
-        self.Value1 = 0
-        self.Value2 = 0
-        self.Value3 = 0
-        self.Value4 = 0
-        self.Value5 = 0
-        self.Value6 = 0
-        self.Value7 = 0
-        self.Value8 = 0
-        self.UserDataLen = 0
-        self.UserData = ""
-        return
-
-    def GetLength(self):
-        length = 0
-        length += 4
-        length += 4
-        length += 4
-        length += 4
-        length += 4
-        length += 4
-        length += 4
-        length += 4
-        length += 4
-        length += 2
-        length += len(self.UserData)
-
-        return length
-
-    def GetBuffer(self):
-        data = ''
-        data = CommFunc.WriteDWORD(data, self.Time)
-        data = CommFunc.WriteDWORD(data, self.Value1)
-        data = CommFunc.WriteDWORD(data, self.Value2)
-        data = CommFunc.WriteDWORD(data, self.Value3)
-        data = CommFunc.WriteDWORD(data, self.Value4)
-        data = CommFunc.WriteDWORD(data, self.Value5)
-        data = CommFunc.WriteDWORD(data, self.Value6)
-        data = CommFunc.WriteDWORD(data, self.Value7)
-        data = CommFunc.WriteDWORD(data, self.Value8)
-        data = CommFunc.WriteWORD(data, self.UserDataLen)
-        data = CommFunc.WriteString(data, self.UserDataLen, self.UserData)
-        return data
-
-    def OutputString(self):
-        DumpString = '''
-                                Time:%d,
-                                Value1:%d,
-                                Value2:%d,
-                                Value3:%d,
-                                Value4:%d,
-                                Value5:%d,
-                                Value6:%d,
-                                Value7:%d,
-                                Value8:%d,
-                                UserDataLen:%d,
-                                UserData:%s
-                                '''\
-                                %(
-                                self.Time,
-                                self.Value1,
-                                self.Value2,
-                                self.Value3,
-                                self.Value4,
-                                self.Value5,
-                                self.Value6,
-                                self.Value7,
-                                self.Value8,
-                                self.UserDataLen,
-                                self.UserData
-                                )
-        return DumpString
-
-
-class  tagGCPlayerRecInfo(Structure):
-    Head = tagHead()
-    Type = 0    #(BYTE Type)//类型
-    Count = 0    #(WORD Count)//数量
-    PlayerRecList = list()    #(vector<tagGCPlayerRec> PlayerRecList)
-    data = None
-
-    def __init__(self):
-        self.Clear()
-        self.Head.Cmd = 0xA0
-        self.Head.SubCmd = 0x08
-        return
-
-    def ReadData(self, _lpData, _pos=0, _Len=0):
-        self.Clear()
-        _pos = self.Head.ReadData(_lpData, _pos)
-        self.Type,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.Count,_pos = CommFunc.ReadWORD(_lpData, _pos)
-        for i in range(self.Count):
-            temPlayerRecList = tagGCPlayerRec()
-            _pos = temPlayerRecList.ReadData(_lpData, _pos)
-            self.PlayerRecList.append(temPlayerRecList)
-        return _pos
-
-    def Clear(self):
-        self.Head = tagHead()
-        self.Head.Clear()
-        self.Head.Cmd = 0xA0
-        self.Head.SubCmd = 0x08
-        self.Type = 0
-        self.Count = 0
-        self.PlayerRecList = list()
-        return
-
-    def GetLength(self):
-        length = 0
-        length += self.Head.GetLength()
-        length += 1
-        length += 2
-        for i in range(self.Count):
-            length += self.PlayerRecList[i].GetLength()
-
-        return length
-
-    def GetBuffer(self):
-        data = ''
-        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
-        data = CommFunc.WriteBYTE(data, self.Type)
-        data = CommFunc.WriteWORD(data, self.Count)
-        for i in range(self.Count):
-            data = CommFunc.WriteString(data, self.PlayerRecList[i].GetLength(), self.PlayerRecList[i].GetBuffer())
-        return data
-
-    def OutputString(self):
-        DumpString = '''
-                                Head:%s,
-                                Type:%d,
-                                Count:%d,
-                                PlayerRecList:%s
-                                '''\
-                                %(
-                                self.Head.OutputString(),
-                                self.Type,
-                                self.Count,
-                                "..."
-                                )
-        return DumpString
-
-
-m_NAtagGCPlayerRecInfo=tagGCPlayerRecInfo()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCPlayerRecInfo.Head.Cmd,m_NAtagGCPlayerRecInfo.Head.SubCmd))] = m_NAtagGCPlayerRecInfo
 
 
 #------------------------------------------------------
@@ -923,197 +930,6 @@
 
 m_NAtagServerGmMailInfo=tagServerGmMailInfo()
 ChNetPackDict[eval("0x%02x%02x"%(m_NAtagServerGmMailInfo.Head.Cmd,m_NAtagServerGmMailInfo.Head.SubCmd))] = m_NAtagServerGmMailInfo
-
-
-#------------------------------------------------------
-#A0 03 玩家信息通用记录 #tagUniversalGameRecInfo
-
-class  tagUniversalGameRec(Structure):
-    Time = 0    #(DWORD Time)//时间
-    StrValue1Len = 0    #(WORD StrValue1Len)//字符串1长度
-    StrValue1 = ""    #(String StrValue1)
-    StrValue2Len = 0    #(WORD StrValue2Len)//字符串2长度
-    StrValue2 = ""    #(String StrValue2)
-    StrValue3Len = 0    #(WORD StrValue3Len)//字符串3长度
-    StrValue3 = ""    #(String StrValue3)
-    Value1 = 0    #(DWORD Value1)//数值1
-    Value2 = 0    #(DWORD Value2)//数值1
-    Value3 = 0    #(DWORD Value3)//数值1
-    Value4 = 0    #(DWORD Value4)//数值1
-    Value5 = 0    #(DWORD Value5)//数值1
-    data = None
-
-    def __init__(self):
-        self.Clear()
-        return
-
-    def ReadData(self, _lpData, _pos=0, _Len=0):
-        self.Clear()
-        self.Time,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.StrValue1Len,_pos = CommFunc.ReadWORD(_lpData, _pos)
-        self.StrValue1,_pos = CommFunc.ReadString(_lpData, _pos,self.StrValue1Len)
-        self.StrValue2Len,_pos = CommFunc.ReadWORD(_lpData, _pos)
-        self.StrValue2,_pos = CommFunc.ReadString(_lpData, _pos,self.StrValue2Len)
-        self.StrValue3Len,_pos = CommFunc.ReadWORD(_lpData, _pos)
-        self.StrValue3,_pos = CommFunc.ReadString(_lpData, _pos,self.StrValue3Len)
-        self.Value1,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value3,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value4,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Value5,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        return _pos
-
-    def Clear(self):
-        self.Time = 0
-        self.StrValue1Len = 0
-        self.StrValue1 = ""
-        self.StrValue2Len = 0
-        self.StrValue2 = ""
-        self.StrValue3Len = 0
-        self.StrValue3 = ""
-        self.Value1 = 0
-        self.Value2 = 0
-        self.Value3 = 0
-        self.Value4 = 0
-        self.Value5 = 0
-        return
-
-    def GetLength(self):
-        length = 0
-        length += 4
-        length += 2
-        length += len(self.StrValue1)
-        length += 2
-        length += len(self.StrValue2)
-        length += 2
-        length += len(self.StrValue3)
-        length += 4
-        length += 4
-        length += 4
-        length += 4
-        length += 4
-
-        return length
-
-    def GetBuffer(self):
-        data = ''
-        data = CommFunc.WriteDWORD(data, self.Time)
-        data = CommFunc.WriteWORD(data, self.StrValue1Len)
-        data = CommFunc.WriteString(data, self.StrValue1Len, self.StrValue1)
-        data = CommFunc.WriteWORD(data, self.StrValue2Len)
-        data = CommFunc.WriteString(data, self.StrValue2Len, self.StrValue2)
-        data = CommFunc.WriteWORD(data, self.StrValue3Len)
-        data = CommFunc.WriteString(data, self.StrValue3Len, self.StrValue3)
-        data = CommFunc.WriteDWORD(data, self.Value1)
-        data = CommFunc.WriteDWORD(data, self.Value2)
-        data = CommFunc.WriteDWORD(data, self.Value3)
-        data = CommFunc.WriteDWORD(data, self.Value4)
-        data = CommFunc.WriteDWORD(data, self.Value5)
-        return data
-
-    def OutputString(self):
-        DumpString = '''
-                                Time:%d,
-                                StrValue1Len:%d,
-                                StrValue1:%s,
-                                StrValue2Len:%d,
-                                StrValue2:%s,
-                                StrValue3Len:%d,
-                                StrValue3:%s,
-                                Value1:%d,
-                                Value2:%d,
-                                Value3:%d,
-                                Value4:%d,
-                                Value5:%d
-                                '''\
-                                %(
-                                self.Time,
-                                self.StrValue1Len,
-                                self.StrValue1,
-                                self.StrValue2Len,
-                                self.StrValue2,
-                                self.StrValue3Len,
-                                self.StrValue3,
-                                self.Value1,
-                                self.Value2,
-                                self.Value3,
-                                self.Value4,
-                                self.Value5
-                                )
-        return DumpString
-
-
-class  tagUniversalGameRecInfo(Structure):
-    Head = tagHead()
-    Type = 0    #(BYTE Type)//类型
-    Count = 0    #(WORD Count)//数量
-    UniversalGameRec = list()    #(vector<tagUniversalGameRec> UniversalGameRec)///size = Count	
-    data = None
-
-    def __init__(self):
-        self.Clear()
-        self.Head.Cmd = 0xA0
-        self.Head.SubCmd = 0x03
-        return
-
-    def ReadData(self, _lpData, _pos=0, _Len=0):
-        self.Clear()
-        _pos = self.Head.ReadData(_lpData, _pos)
-        self.Type,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.Count,_pos = CommFunc.ReadWORD(_lpData, _pos)
-        for i in range(self.Count):
-            temUniversalGameRec = tagUniversalGameRec()
-            _pos = temUniversalGameRec.ReadData(_lpData, _pos)
-            self.UniversalGameRec.append(temUniversalGameRec)
-        return _pos
-
-    def Clear(self):
-        self.Head = tagHead()
-        self.Head.Clear()
-        self.Head.Cmd = 0xA0
-        self.Head.SubCmd = 0x03
-        self.Type = 0
-        self.Count = 0
-        self.UniversalGameRec = list()
-        return
-
-    def GetLength(self):
-        length = 0
-        length += self.Head.GetLength()
-        length += 1
-        length += 2
-        for i in range(self.Count):
-            length += self.UniversalGameRec[i].GetLength()
-
-        return length
-
-    def GetBuffer(self):
-        data = ''
-        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
-        data = CommFunc.WriteBYTE(data, self.Type)
-        data = CommFunc.WriteWORD(data, self.Count)
-        for i in range(self.Count):
-            data = CommFunc.WriteString(data, self.UniversalGameRec[i].GetLength(), self.UniversalGameRec[i].GetBuffer())
-        return data
-
-    def OutputString(self):
-        DumpString = '''
-                                Head:%s,
-                                Type:%d,
-                                Count:%d,
-                                UniversalGameRec:%s
-                                '''\
-                                %(
-                                self.Head.OutputString(),
-                                self.Type,
-                                self.Count,
-                                "..."
-                                )
-        return DumpString
-
-
-m_NAtagUniversalGameRecInfo=tagUniversalGameRecInfo()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagUniversalGameRecInfo.Head.Cmd,m_NAtagUniversalGameRecInfo.Head.SubCmd))] = m_NAtagUniversalGameRecInfo
 
 
 #------------------------------------------------------
@@ -3822,74 +3638,6 @@
 
 m_NAtagMCAllEquipAttrActiveInfo=tagMCAllEquipAttrActiveInfo()
 ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCAllEquipAttrActiveInfo.Head.Cmd,m_NAtagMCAllEquipAttrActiveInfo.Head.SubCmd))] = m_NAtagMCAllEquipAttrActiveInfo
-
-
-#------------------------------------------------------
-# A3 C3 竞技场玩家信息 #tagMCArenaPlayerInfo
-
-class  tagMCArenaPlayerInfo(Structure):
-    _pack_ = 1
-    _fields_ = [
-                  ("Cmd", c_ubyte),
-                  ("SubCmd", c_ubyte),
-                  ("IsReset", c_ubyte),    #是否是重置的
-                  ("Score", c_int),    #当前积分
-                  ("BattleCountToday", c_ubyte),    #今日已挑战次数
-                  ("MatchRefreshCount", c_ubyte),    #当前已刷新匹配列表次数,每次挑战后会重置
-                  ("ItemAddBattleCountToday", c_ubyte),    #今日已使用物品增加的挑战次数
-                  ]
-
-    def __init__(self):
-        self.Clear()
-        self.Cmd = 0xA3
-        self.SubCmd = 0xC3
-        return
-
-    def ReadData(self, stringData, _pos=0, _len=0):
-        self.Clear()
-        memmove(addressof(self), stringData[_pos:], self.GetLength())
-        return _pos + self.GetLength()
-
-    def Clear(self):
-        self.Cmd = 0xA3
-        self.SubCmd = 0xC3
-        self.IsReset = 0
-        self.Score = 0
-        self.BattleCountToday = 0
-        self.MatchRefreshCount = 0
-        self.ItemAddBattleCountToday = 0
-        return
-
-    def GetLength(self):
-        return sizeof(tagMCArenaPlayerInfo)
-
-    def GetBuffer(self):
-        return string_at(addressof(self), self.GetLength())
-
-    def OutputString(self):
-        DumpString = '''// A3 C3 竞技场玩家信息 //tagMCArenaPlayerInfo:
-                                Cmd:%s,
-                                SubCmd:%s,
-                                IsReset:%d,
-                                Score:%d,
-                                BattleCountToday:%d,
-                                MatchRefreshCount:%d,
-                                ItemAddBattleCountToday:%d
-                                '''\
-                                %(
-                                self.Cmd,
-                                self.SubCmd,
-                                self.IsReset,
-                                self.Score,
-                                self.BattleCountToday,
-                                self.MatchRefreshCount,
-                                self.ItemAddBattleCountToday
-                                )
-        return DumpString
-
-
-m_NAtagMCArenaPlayerInfo=tagMCArenaPlayerInfo()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCArenaPlayerInfo.Cmd,m_NAtagMCArenaPlayerInfo.SubCmd))] = m_NAtagMCArenaPlayerInfo
 
 
 #------------------------------------------------------
@@ -17435,6 +17183,7 @@
     RealmLV = 0    #(BYTE RealmLV)
     Face = 0    #(DWORD Face)
     FacePic = 0    #(DWORD FacePic)
+    ModelMark = 0    #(DWORD ModelMark)//变形模型mark
     TitleID = 0    #(DWORD TitleID)//佩戴的称号
     ServerID = 0    #(DWORD ServerID)
     FightPower = 0    #(DWORD FightPower)
@@ -17462,6 +17211,7 @@
         self.RealmLV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ModelMark,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.TitleID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
@@ -17485,6 +17235,7 @@
         self.RealmLV = 0
         self.Face = 0
         self.FacePic = 0
+        self.ModelMark = 0
         self.TitleID = 0
         self.ServerID = 0
         self.FightPower = 0
@@ -17511,6 +17262,7 @@
         length += 4
         length += 4
         length += 4
+        length += 4
         length += 33
         length += 4
         length += 4
@@ -17528,6 +17280,7 @@
         data = CommFunc.WriteBYTE(data, self.RealmLV)
         data = CommFunc.WriteDWORD(data, self.Face)
         data = CommFunc.WriteDWORD(data, self.FacePic)
+        data = CommFunc.WriteDWORD(data, self.ModelMark)
         data = CommFunc.WriteDWORD(data, self.TitleID)
         data = CommFunc.WriteDWORD(data, self.ServerID)
         data = CommFunc.WriteDWORD(data, self.FightPower)
@@ -17549,6 +17302,7 @@
                                 RealmLV:%d,
                                 Face:%d,
                                 FacePic:%d,
+                                ModelMark:%d,
                                 TitleID:%d,
                                 ServerID:%d,
                                 FightPower:%d,
@@ -17568,6 +17322,7 @@
                                 self.RealmLV,
                                 self.Face,
                                 self.FacePic,
+                                self.ModelMark,
                                 self.TitleID,
                                 self.ServerID,
                                 self.FightPower,
@@ -18992,127 +18747,14 @@
 
 
 #------------------------------------------------------
-# A9 26 竞技场对战玩家最新信息 #tagGCArenaBattlePlayerInfo
+# A9 22 演武场匹配玩家列表 #tagSCArenaMatchList
 
-class  tagGCArenaBattlePlayerInfo(Structure):
-    Head = tagHead()
+class  tagSCArenaMatchInfo(Structure):
     PlayerID = 0    #(DWORD PlayerID)//目标玩家ID
     PlayerName = ""    #(char PlayerName[33])
-    Job = 0    #(BYTE Job)
-    LV = 0    #(WORD LV)//等级
     RealmLV = 0    #(WORD RealmLV)//境界,机器人读境界表取等级对应境界
-    FightPower = 0    #(DWORD FightPower)//战力求余亿部分,机器人读等级表取等级对应战力
-    FightPowerEx = 0    #(DWORD FightPowerEx)//战力整除亿部分,机器人读等级表取等级对应战力
-    Score = 0    #(DWORD Score)//积分
-    data = None
-
-    def __init__(self):
-        self.Clear()
-        self.Head.Cmd = 0xA9
-        self.Head.SubCmd = 0x26
-        return
-
-    def ReadData(self, _lpData, _pos=0, _Len=0):
-        self.Clear()
-        _pos = self.Head.ReadData(_lpData, _pos)
-        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.PlayerName,_pos = CommFunc.ReadString(_lpData, _pos,33)
-        self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
-        self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
-        self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Score,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        return _pos
-
-    def Clear(self):
-        self.Head = tagHead()
-        self.Head.Clear()
-        self.Head.Cmd = 0xA9
-        self.Head.SubCmd = 0x26
-        self.PlayerID = 0
-        self.PlayerName = ""
-        self.Job = 0
-        self.LV = 0
-        self.RealmLV = 0
-        self.FightPower = 0
-        self.FightPowerEx = 0
-        self.Score = 0
-        return
-
-    def GetLength(self):
-        length = 0
-        length += self.Head.GetLength()
-        length += 4
-        length += 33
-        length += 1
-        length += 2
-        length += 2
-        length += 4
-        length += 4
-        length += 4
-
-        return length
-
-    def GetBuffer(self):
-        data = ''
-        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
-        data = CommFunc.WriteDWORD(data, self.PlayerID)
-        data = CommFunc.WriteString(data, 33, self.PlayerName)
-        data = CommFunc.WriteBYTE(data, self.Job)
-        data = CommFunc.WriteWORD(data, self.LV)
-        data = CommFunc.WriteWORD(data, self.RealmLV)
-        data = CommFunc.WriteDWORD(data, self.FightPower)
-        data = CommFunc.WriteDWORD(data, self.FightPowerEx)
-        data = CommFunc.WriteDWORD(data, self.Score)
-        return data
-
-    def OutputString(self):
-        DumpString = '''
-                                Head:%s,
-                                PlayerID:%d,
-                                PlayerName:%s,
-                                Job:%d,
-                                LV:%d,
-                                RealmLV:%d,
-                                FightPower:%d,
-                                FightPowerEx:%d,
-                                Score:%d
-                                '''\
-                                %(
-                                self.Head.OutputString(),
-                                self.PlayerID,
-                                self.PlayerName,
-                                self.Job,
-                                self.LV,
-                                self.RealmLV,
-                                self.FightPower,
-                                self.FightPowerEx,
-                                self.Score
-                                )
-        return DumpString
-
-
-m_NAtagGCArenaBattlePlayerInfo=tagGCArenaBattlePlayerInfo()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCArenaBattlePlayerInfo.Head.Cmd,m_NAtagGCArenaBattlePlayerInfo.Head.SubCmd))] = m_NAtagGCArenaBattlePlayerInfo
-
-
-#------------------------------------------------------
-# A9 23 竞技场对战记录列表 #tagGCArenaBattleRecordList
-
-class  tagGCArenaBattleRecord(Structure):
-    PlayerID = 0    #(DWORD PlayerID)//目标玩家ID,小于10000为机器人ID
-    PlayerName = ""    #(char PlayerName[33])
-    Job = 0    #(BYTE Job)
-    LV = 0    #(WORD LV)//等级
-    RealmLV = 0    #(WORD RealmLV)//境界,机器人读境界表取等级对应境界
-    FightPower = 0    #(DWORD FightPower)//战力求余亿部分,机器人读等级表取等级对应战力
-    FightPowerEx = 0    #(DWORD FightPowerEx)//战力整除亿部分,机器人读等级表取等级对应战力
-    Score = 0    #(DWORD Score)//积分
-    AddScoreLen = 0    #(BYTE AddScoreLen)
-    AddScore = ""    #(String AddScore)//本次对战增加的积分,有正负
-    IsWin = 0    #(BYTE IsWin)//是否获胜
-    Time = 0    #(DWORD Time)//时间戳
+    FightPower = 0    #(DWORD FightPower)//战力求余亿部分
+    FightPowerEx = 0    #(DWORD FightPowerEx)//战力整除亿部分
     Face = 0    #(DWORD Face)//基本脸型
     FacePic = 0    #(DWORD FacePic)//头像框
     data = None
@@ -19125,16 +18767,9 @@
         self.Clear()
         self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.PlayerName,_pos = CommFunc.ReadString(_lpData, _pos,33)
-        self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Score,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.AddScoreLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.AddScore,_pos = CommFunc.ReadString(_lpData, _pos,self.AddScoreLen)
-        self.IsWin,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.Time,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
@@ -19142,16 +18777,9 @@
     def Clear(self):
         self.PlayerID = 0
         self.PlayerName = ""
-        self.Job = 0
-        self.LV = 0
         self.RealmLV = 0
         self.FightPower = 0
         self.FightPowerEx = 0
-        self.Score = 0
-        self.AddScoreLen = 0
-        self.AddScore = ""
-        self.IsWin = 0
-        self.Time = 0
         self.Face = 0
         self.FacePic = 0
         return
@@ -19160,196 +18788,7 @@
         length = 0
         length += 4
         length += 33
-        length += 1
         length += 2
-        length += 2
-        length += 4
-        length += 4
-        length += 4
-        length += 1
-        length += len(self.AddScore)
-        length += 1
-        length += 4
-        length += 4
-        length += 4
-
-        return length
-
-    def GetBuffer(self):
-        data = ''
-        data = CommFunc.WriteDWORD(data, self.PlayerID)
-        data = CommFunc.WriteString(data, 33, self.PlayerName)
-        data = CommFunc.WriteBYTE(data, self.Job)
-        data = CommFunc.WriteWORD(data, self.LV)
-        data = CommFunc.WriteWORD(data, self.RealmLV)
-        data = CommFunc.WriteDWORD(data, self.FightPower)
-        data = CommFunc.WriteDWORD(data, self.FightPowerEx)
-        data = CommFunc.WriteDWORD(data, self.Score)
-        data = CommFunc.WriteBYTE(data, self.AddScoreLen)
-        data = CommFunc.WriteString(data, self.AddScoreLen, self.AddScore)
-        data = CommFunc.WriteBYTE(data, self.IsWin)
-        data = CommFunc.WriteDWORD(data, self.Time)
-        data = CommFunc.WriteDWORD(data, self.Face)
-        data = CommFunc.WriteDWORD(data, self.FacePic)
-        return data
-
-    def OutputString(self):
-        DumpString = '''
-                                PlayerID:%d,
-                                PlayerName:%s,
-                                Job:%d,
-                                LV:%d,
-                                RealmLV:%d,
-                                FightPower:%d,
-                                FightPowerEx:%d,
-                                Score:%d,
-                                AddScoreLen:%d,
-                                AddScore:%s,
-                                IsWin:%d,
-                                Time:%d,
-                                Face:%d,
-                                FacePic:%d
-                                '''\
-                                %(
-                                self.PlayerID,
-                                self.PlayerName,
-                                self.Job,
-                                self.LV,
-                                self.RealmLV,
-                                self.FightPower,
-                                self.FightPowerEx,
-                                self.Score,
-                                self.AddScoreLen,
-                                self.AddScore,
-                                self.IsWin,
-                                self.Time,
-                                self.Face,
-                                self.FacePic
-                                )
-        return DumpString
-
-
-class  tagGCArenaBattleRecordList(Structure):
-    Head = tagHead()
-    RecordCount = 0    #(BYTE RecordCount)
-    BattleRecordList = list()    #(vector<tagGCArenaBattleRecord> BattleRecordList)// 对战列表
-    data = None
-
-    def __init__(self):
-        self.Clear()
-        self.Head.Cmd = 0xA9
-        self.Head.SubCmd = 0x23
-        return
-
-    def ReadData(self, _lpData, _pos=0, _Len=0):
-        self.Clear()
-        _pos = self.Head.ReadData(_lpData, _pos)
-        self.RecordCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        for i in range(self.RecordCount):
-            temBattleRecordList = tagGCArenaBattleRecord()
-            _pos = temBattleRecordList.ReadData(_lpData, _pos)
-            self.BattleRecordList.append(temBattleRecordList)
-        return _pos
-
-    def Clear(self):
-        self.Head = tagHead()
-        self.Head.Clear()
-        self.Head.Cmd = 0xA9
-        self.Head.SubCmd = 0x23
-        self.RecordCount = 0
-        self.BattleRecordList = list()
-        return
-
-    def GetLength(self):
-        length = 0
-        length += self.Head.GetLength()
-        length += 1
-        for i in range(self.RecordCount):
-            length += self.BattleRecordList[i].GetLength()
-
-        return length
-
-    def GetBuffer(self):
-        data = ''
-        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
-        data = CommFunc.WriteBYTE(data, self.RecordCount)
-        for i in range(self.RecordCount):
-            data = CommFunc.WriteString(data, self.BattleRecordList[i].GetLength(), self.BattleRecordList[i].GetBuffer())
-        return data
-
-    def OutputString(self):
-        DumpString = '''
-                                Head:%s,
-                                RecordCount:%d,
-                                BattleRecordList:%s
-                                '''\
-                                %(
-                                self.Head.OutputString(),
-                                self.RecordCount,
-                                "..."
-                                )
-        return DumpString
-
-
-m_NAtagGCArenaBattleRecordList=tagGCArenaBattleRecordList()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCArenaBattleRecordList.Head.Cmd,m_NAtagGCArenaBattleRecordList.Head.SubCmd))] = m_NAtagGCArenaBattleRecordList
-
-
-#------------------------------------------------------
-# A9 22 竞技场匹配玩家列表 #tagGCArenaMatchList
-
-class  tagGCArenaMatchInfo(Structure):
-    PlayerID = 0    #(DWORD PlayerID)//目标玩家ID,小于10000为机器人ID
-    PlayerName = ""    #(char PlayerName[33])
-    Job = 0    #(BYTE Job)
-    LV = 0    #(WORD LV)//等级
-    RealmLV = 0    #(WORD RealmLV)//境界,机器人读境界表取等级对应境界
-    FightPower = 0    #(DWORD FightPower)//战力求余亿部分,机器人读等级表取等级对应战力
-    FightPowerEx = 0    #(DWORD FightPowerEx)//战力整除亿部分,机器人读等级表取等级对应战力
-    Score = 0    #(DWORD Score)//积分
-    Face = 0    #(DWORD Face)//基本脸型
-    FacePic = 0    #(DWORD FacePic)//头像框
-    data = None
-
-    def __init__(self):
-        self.Clear()
-        return
-
-    def ReadData(self, _lpData, _pos=0, _Len=0):
-        self.Clear()
-        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.PlayerName,_pos = CommFunc.ReadString(_lpData, _pos,33)
-        self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
-        self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
-        self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Score,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        return _pos
-
-    def Clear(self):
-        self.PlayerID = 0
-        self.PlayerName = ""
-        self.Job = 0
-        self.LV = 0
-        self.RealmLV = 0
-        self.FightPower = 0
-        self.FightPowerEx = 0
-        self.Score = 0
-        self.Face = 0
-        self.FacePic = 0
-        return
-
-    def GetLength(self):
-        length = 0
-        length += 4
-        length += 33
-        length += 1
-        length += 2
-        length += 2
-        length += 4
         length += 4
         length += 4
         length += 4
@@ -19361,12 +18800,9 @@
         data = ''
         data = CommFunc.WriteDWORD(data, self.PlayerID)
         data = CommFunc.WriteString(data, 33, self.PlayerName)
-        data = CommFunc.WriteBYTE(data, self.Job)
-        data = CommFunc.WriteWORD(data, self.LV)
         data = CommFunc.WriteWORD(data, self.RealmLV)
         data = CommFunc.WriteDWORD(data, self.FightPower)
         data = CommFunc.WriteDWORD(data, self.FightPowerEx)
-        data = CommFunc.WriteDWORD(data, self.Score)
         data = CommFunc.WriteDWORD(data, self.Face)
         data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
@@ -19375,34 +18811,28 @@
         DumpString = '''
                                 PlayerID:%d,
                                 PlayerName:%s,
-                                Job:%d,
-                                LV:%d,
                                 RealmLV:%d,
                                 FightPower:%d,
                                 FightPowerEx:%d,
-                                Score:%d,
                                 Face:%d,
                                 FacePic:%d
                                 '''\
                                 %(
                                 self.PlayerID,
                                 self.PlayerName,
-                                self.Job,
-                                self.LV,
                                 self.RealmLV,
                                 self.FightPower,
                                 self.FightPowerEx,
-                                self.Score,
                                 self.Face,
                                 self.FacePic
                                 )
         return DumpString
 
 
-class  tagGCArenaMatchList(Structure):
+class  tagSCArenaMatchList(Structure):
     Head = tagHead()
     MatchCount = 0    #(BYTE MatchCount)
-    MatchList = list()    #(vector<tagGCArenaMatchInfo> MatchList)// 匹配列表
+    MatchList = list()    #(vector<tagSCArenaMatchInfo> MatchList)// 匹配列表,从高分到低分
     data = None
 
     def __init__(self):
@@ -19416,7 +18846,7 @@
         _pos = self.Head.ReadData(_lpData, _pos)
         self.MatchCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         for i in range(self.MatchCount):
-            temMatchList = tagGCArenaMatchInfo()
+            temMatchList = tagSCArenaMatchInfo()
             _pos = temMatchList.ReadData(_lpData, _pos)
             self.MatchList.append(temMatchList)
         return _pos
@@ -19461,8 +18891,60 @@
         return DumpString
 
 
-m_NAtagGCArenaMatchList=tagGCArenaMatchList()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCArenaMatchList.Head.Cmd,m_NAtagGCArenaMatchList.Head.SubCmd))] = m_NAtagGCArenaMatchList
+m_NAtagSCArenaMatchList=tagSCArenaMatchList()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCArenaMatchList.Head.Cmd,m_NAtagSCArenaMatchList.Head.SubCmd))] = m_NAtagSCArenaMatchList
+
+
+#------------------------------------------------------
+# A9 23 演武场玩家信息 #tagSCArenaPlayerInfo
+
+class  tagSCArenaPlayerInfo(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("Score", c_int),    #当前积分
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA9
+        self.SubCmd = 0x23
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA9
+        self.SubCmd = 0x23
+        self.Score = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagSCArenaPlayerInfo)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A9 23 演武场玩家信息 //tagSCArenaPlayerInfo:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                Score:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.Score
+                                )
+        return DumpString
+
+
+m_NAtagSCArenaPlayerInfo=tagSCArenaPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCArenaPlayerInfo.Cmd,m_NAtagSCArenaPlayerInfo.SubCmd))] = m_NAtagSCArenaPlayerInfo
 
 
 #------------------------------------------------------
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
index 9cecba1..771998a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
@@ -1126,6 +1126,7 @@
         ('RealmLV', ctypes.c_ubyte),
         ('Face', ctypes.c_int),
         ('FacePic', ctypes.c_int),
+        ('ModelMark', ctypes.c_ulong),
         ('FamilyID', ctypes.c_ulong),
         ('FamilyName', ctypes.c_char * 33),
         ('FamilyEmblemID', ctypes.c_ushort),
@@ -1152,6 +1153,7 @@
         self.RealmLV = 0
         self.Face = 0
         self.FacePic = 0
+        self.ModelMark = 0
         self.FamilyID = 0
         self.FamilyName = ''
         self.FamilyEmblemID = 0
@@ -1177,6 +1179,7 @@
         self.RealmLV, pos = CommFunc.ReadBYTE(buf, pos)
         self.Face, pos = CommFunc.ReadDWORD(buf, pos)
         self.FacePic, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ModelMark, pos = CommFunc.ReadDWORD(buf, pos)
         self.FamilyID, pos = CommFunc.ReadDWORD(buf, pos)
         self.FamilyName, pos = CommFunc.ReadString(buf, pos, 33)
         self.FamilyEmblemID, pos = CommFunc.ReadWORD(buf, pos)
@@ -1200,6 +1203,7 @@
         buf = CommFunc.WriteBYTE(buf, self.RealmLV)
         buf = CommFunc.WriteDWORD(buf, self.Face)
         buf = CommFunc.WriteDWORD(buf, self.FacePic)
+        buf = CommFunc.WriteDWORD(buf, self.ModelMark)
         buf = CommFunc.WriteDWORD(buf, self.FamilyID)
         buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 33, self.FamilyName)
         buf = CommFunc.WriteWORD(buf, self.FamilyEmblemID)
@@ -1223,6 +1227,7 @@
         length += sizeof(ctypes.c_int)
         length += sizeof(ctypes.c_int)
         length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
         length += sizeof(ctypes.c_char) * 33
         length += sizeof(ctypes.c_ushort)
         length += sizeof(ctypes.c_ulong)
@@ -1244,6 +1249,7 @@
             RealmLV = %s,
             Face = %s,
             FacePic = %s,
+            ModelMark = %s,
             FamilyID = %s,
             FamilyName = %s,
             FamilyEmblemID = %s,
@@ -1264,6 +1270,7 @@
                 self.RealmLV,
                 self.Face,
                 self.FacePic,
+                self.ModelMark,
                 self.FamilyID,
                 self.FamilyName,
                 self.FamilyEmblemID,
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py
index fee72a3..4f1cd61 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py
@@ -490,7 +490,7 @@
                 self.__familyList.remove(family)
             family.OnDelete()
         self.__familyIDDict.pop(familyID, None)
-        if familyID > ShareDefine.FackFamilyIDMax:
+        if familyID >= ShareDefine.RealFamilyIDStart:
             PyMongoMain.GetUserCtrlDB().FreeFamilyID(familyID) # 归还仙盟ID,重复使用
         return family
     
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBGameRec.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBGameRec.py
index ca7a4f9..0118ee1 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBGameRec.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBGameRec.py
@@ -159,6 +159,7 @@
         recData = self.InitRecDataInstance(dbData)
         return recData
     
+    def GetDataList(self): return self.__dataList
     def GetCount(self): return len(self.__dataList)
     def At(self, index):
         recData = None
@@ -339,6 +340,8 @@
             recTypeIDMgr = GameRecIDMgr(recType, recID)
         return recTypeIDMgr
     
+    def DelDataByType(self, recType): return self.GetRecTypeMgr(recType).DelAllData()
+    
     # 保存数据 存数据库和realtimebackup
     def GetSaveData(self):
         savaData = ""
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py
index 1b24dc3..f6692e5 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py
@@ -18,6 +18,7 @@
 import DBComm
 import DBStruct
 import GameWorld
+import ShareDefine
 import CommFunc
 import ChConfig
 
@@ -44,6 +45,8 @@
     def SetFace(self, face): self.__dbData.Face = face
     def GetFacePic(self): return self.__dbData.FacePic
     def SetFacePic(self, facePic): self.__dbData.FacePic = facePic
+    def GetModelMark(self): return self.__dbData.ModelMark
+    def SetModelMark(self, modelMark): self.__dbData.ModelMark = modelMark
     def GetFamilyID(self): return self.__dbData.FamilyID
     def SetFamilyID(self, familyID): self.__dbData.FamilyID = familyID
     def GetFamilyName(self): return self.__dbData.FamilyName
@@ -64,6 +67,7 @@
     def GetOffTime(self): return self.__dbData.OffTime
     def SetOffTime(self, offTime): self.__dbData.OffTime = offTime
     def GetPlusDict(self): return self.__plusDict.GetData()
+    def SetPlusDict(self, value): self.__plusDict.SetData(value)
     def GetPlusData(self): return self.__plusDict.ToString()
     def GetBuffer(self):
         self.__plusDict.ToString()
@@ -170,6 +174,9 @@
         cnt = 0
         
         for dbData in self.__viewCacheList:
+            if dbData.GetPlayerID() < ShareDefine.RealPlayerIDStart:
+                # 仅保存真实玩家
+                continue
             cnt += 1
             savaData += dbData.GetBuffer()
             
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Arena.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Arena.py
index 0dd8d9e..b6586ff 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Arena.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Arena.py
@@ -28,24 +28,19 @@
 #  @return None
 #  @remarks 函数详细说明.
 def OnExec(curPlayer, msgList):
-    
     if not msgList:
         GameWorld.DebugAnswer(curPlayer, "重置玩家竞技场: Arena 0")
         GameWorld.DebugAnswer(curPlayer, "设置玩家榜积分: Arena 积分")
-        GameWorld.DebugAnswer(curPlayer, "设置玩家榜积分: Arena 2 对手ID 积分")
-        GameWorld.DebugAnswer(curPlayer, "直接匹配到目标: Arena 1 对手ID 对手ID ...")
-        GameWorld.DebugAnswer(curPlayer, "重置赛季直接用 test_OnWeek (需开服7天后)")
+        GameWorld.DebugAnswer(curPlayer, "直接匹配到目标: Arena m 对手ID 对手ID ...")
+        GameWorld.DebugAnswer(curPlayer, "重置赛季直接用 test_OnWeek")
         return
     
     if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Arena):
         GameWorld.DebugAnswer(curPlayer, "竞技场功能未开启!")
         return
     
-    isSendGameServer = False
     value1 = msgList[0]
     if value1 <= 0:
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaOSSeasonState, 0)
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaHighestScore, 0)
         PlayerArena.__DoArenaSeasonReset(curPlayer)
         GameWorld.DebugAnswer(curPlayer, "重置成功!")
         return
@@ -55,18 +50,9 @@
         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, value1)
         PlayerArena.Sync_ArenaInfo(curPlayer)
         
-        isSendGameServer = True
-        
-    elif len(msgList) >= 2 and value1 == 1:
+    elif value1 == "m":
         gmMatchIDList = msgList[1:]
         PlayerArena.GMArenaMatch(curPlayer, gmMatchIDList)
         
-    elif len(msgList) >= 3 and value1 == 2:
-        
-        isSendGameServer = True
-        
-    else:
-        pass
-    
-    return isSendGameServer
+    return
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py
index eda747d..e3b4bb4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py
@@ -26,16 +26,15 @@
         GameWorld.DebugAnswer(curPlayer, errInfo)
     GameWorld.DebugAnswer(curPlayer, "新增榜单假数据: Billboard 类型 分组值1 分组值2 条数 比较值1可选参数(比较值2 常规值1~5)")
     GameWorld.DebugAnswer(curPlayer, "删除榜单假数据: Billboard 类型 分组值1 分组值2")
-    GameWorld.DebugAnswer(curPlayer, "榜单类型:0-战力,1-龙魂,2-灵瑶,4-等级,5-坐骑,6-灵宠,7-符印,8-脱机,9-境界,19-助战")
-    GameWorld.DebugAnswer(curPlayer, "开服活动榜类型:11-强化,12-坐骑,13-宝石,14-冲级,15-境界,16-战力,18-符印,20-神兵,21-充值,22-灵宠,24-灵根,25-升星,26-洗练")
-    GameWorld.DebugAnswer(curPlayer, "运营活动榜类型:17-仙界盛典,23-仙界盛典2,33-boss凭证,36-boss凭证仙盟,38-仙匣,39-古宝,40-骑宠")
-    GameWorld.DebugAnswer(curPlayer, "魅力榜单类型:30-总榜,31-周榜,32-日榜")
-    GameWorld.DebugAnswer(curPlayer, "运营活动榜类型:150-充值(分组值1配置ID)")
-    GameWorld.DebugAnswer(curPlayer, "运营活动榜类型:158-boss凭证,160-凭证仙盟,162-仙匣,163-古宝,164-骑宠")
-    GameWorld.DebugAnswer(curPlayer, "古神战场榜类型:151-参与榜,152-召集榜,153-积分榜")
-    GameWorld.DebugAnswer(curPlayer, "逐鹿万界榜类型:156-单场榜,157-周榜")
-    GameWorld.DebugAnswer(curPlayer, "跨服竞技场榜单:165,分组值1-分区,分组值2-赛季,value2-段位")
+    GameWorld.DebugAnswer(curPlayer, "输出排行榜数据: Billboard p 类型 分组值1 分组值2")
     GameWorld.DebugAnswer(curPlayer, "注:如果没有特殊说明,本服榜单分组值均为0,跨服榜单分组值1为分区ID,分组2为0")
+    
+    nameTypeList = ShareDefine.BillboardNameDict.keys()
+    nameTypeList.sort()
+    for billboardType in nameTypeList:
+        bName = ShareDefine.BillboardNameDict[billboardType]
+        GameWorld.DebugAnswer(curPlayer, "(%s) %s" % (billboardType, bName))
+        
     return
 
 ## 执行逻辑
@@ -55,7 +54,7 @@
         return
     
     billboardIndex = value
-    if billboardIndex >= ShareDefine.BillboardTypeAllList:
+    if billboardIndex not in ShareDefine.BillboardTypeAllList:
         __Help(curPlayer, "榜单类型不存在!")
         return
     
@@ -138,7 +137,7 @@
     return
 
 def __GetBillTypeSign(billboardType, groupValue1, groupValue2):
-    billTypeSign = "%s" % billboardType
+    billTypeSign = "Type:%s" % billboardType
     if groupValue1:
         billTypeSign = "%s-%s" % (billTypeSign, groupValue1)
     if groupValue2:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py
index 3937f10..ea6973a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py
@@ -233,7 +233,7 @@
             else:
                 memFightPower = avgValue + memCnt / 2 - m
                 memFightPowerTotal -= memFightPower
-            viewCache = PlayerViewCache.FindViewCache(memID, True)
+            viewCache = PlayerViewCache.FindViewCache(memID)
             viewCache.SetFightPowerTotal(memFightPower)
             GameWorld.DebugLog("    仙盟成员: memID=%s,memFightPower=%s,fmLV=%s" % (memID, memFightPower, fmLV))
             member.RefreshMemberByID(memID)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Robot.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Robot.py
new file mode 100644
index 0000000..c7d7a83
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Robot.py
@@ -0,0 +1,46 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.Robot
+#
+# @todo:机器人
+# @author hxp
+# @date 2025-09-12
+# @version 1.0
+#
+# 详细描述: 机器人
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-09-12 10:30"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PlayerViewCache
+
+## GM命令执行入口
+#  @param curPlayer 当前玩家
+#  @param msgList 参数列表 
+#  @return None
+#  @remarks 函数详细说明.
+def OnExec(curPlayer, msgList):
+    if not msgList:
+        GameWorld.DebugAnswer(curPlayer, "导出机器人: Robot 玩家ID")
+        return
+    
+    value = msgList[0]
+    if len(msgList) == 1:
+        tagPlayerID = value if value else curPlayer.GetPlayerID()
+        viewCache = PlayerViewCache.FindViewCache(tagPlayerID)
+        if not viewCache:
+            GameWorld.DebugAnswer(curPlayer, "没有该玩家缓存无法导出! %s" % tagPlayerID)
+            return
+        robotDict = PlayerViewCache.GetRobotByViewCache(viewCache)
+        GameWorld.DebugLog("robotDict:%s" % robotDict)
+        GameWorld.DebugAnswer(curPlayer, "已导出!可拷贝到机器人表")
+        return
+    
+    return
+
+
+    
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Arena.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Arena.py
new file mode 100644
index 0000000..ec1dd8f
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Arena.py
@@ -0,0 +1,207 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GameWorldLogic.FBProcess.GameLogic_Arena
+#
+# @todo:演武场
+# @author hxp
+# @date 2025-09-12
+# @version 1.0
+#
+# 详细描述: 演武场
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-09-12 10:30"""
+#-------------------------------------------------------------------------------
+
+import DBDataMgr
+import GameWorld
+import TurnAttack
+import ShareDefine
+import PlayerControl
+import IpyGameDataPY
+import PlayerBillboard
+import ItemControler
+import PlayerArena
+import PyGameData
+import FBCommon
+import ChConfig
+
+def __checkCanAtkTagPlayer(curPlayer, tagPlayerID):
+    '''检查可否攻击目标
+    @return: None - 不可攻击
+    @return: >=0 - 在匹配列表里的索引
+    @return: -1 - 可反击的
+    '''
+    playerID = curPlayer.GetPlayerID()
+    matchIDList = PyGameData.g_arenaPlayerMatchDict.get(playerID, [])
+    #if tagPlayerID in matchIDList:
+    #    return matchIDList.index(tagPlayerID)
+    
+    gameRecMgr = DBDataMgr.GetGameRecMgr()
+    atkRecMgr = gameRecMgr.GetRecTypeIDMgr(ShareDefine.Def_GameRecType_ArenaRecord, playerID)
+    for index in range(atkRecMgr.GetCount())[::-1]:
+        recData = atkRecMgr.At(index)
+        if PlayerArena.GetRecAtkType(recData) != PlayerArena.RecAtkType_Def:
+            # 被攻击的才能反击
+            continue
+        if tagPlayerID != PlayerArena.GetRecTagPlayerID(recData):
+            continue
+        if GameWorld.CheckTimeIsSameWeek(recData.GetTime()):
+            return -1
+        break
+    
+    GameWorld.DebugLog("演武场不可攻击不在匹配列表里或可复仇的目标! tagPlayerID=%s,matchIDList=%s" % (tagPlayerID, matchIDList), playerID)
+    return
+
+def OnTurnFightRequest(curPlayer, mapID, funcLineID, tagType, tagID, valueList):
+    ## 回合战斗请求 
+    
+    if __checkCanAtkTagPlayer(curPlayer, tagID) == None:
+        return
+    
+    if not PlayerControl.HaveMoney(curPlayer, ShareDefine.TYPE_Price_ArenaTicket, 1):
+        return
+    
+    return True
+
+def GetFBPlayerLineupID(curPlayer, mapID, funcLineID):
+    ## 获取玩家使用的攻防阵容ID
+    # @return: 攻击方阵容ID, 防守方阵容ID
+    return ShareDefine.Lineup_Arena, ShareDefine.Lineup_ArenaDef
+
+def OnTurnFightOver(curPlayer, turnFight, mapID, funcLineID, overMsg):
+    ## 回合战斗结束
+    if not curPlayer:
+        return
+    
+    playerID = curPlayer.GetPlayerID()
+    tagPlayerID = turnFight.tagPlayerID
+    isWin = turnFight.isWin
+    
+    canAtkRet = __checkCanAtkTagPlayer(curPlayer, tagPlayerID)
+    GameWorld.DebugLog("结算竞技场! isWin=%s,tagPlayerID=%s,canAtkRet=%s" % (isWin, tagPlayerID, canAtkRet), playerID)
+    if canAtkRet == None:
+        return
+    
+    billboardMgr = DBDataMgr.GetBillboardMgr()
+    billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Arena)
+    
+    atkAddScore, defDecScore = 0, 0
+    if isWin:
+        winScoreList = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 1)
+        scoreCnt = len(winScoreList)
+        scoreIndex = scoreCnt - 1 # 默认最低分档
+        # 匹配的
+        if canAtkRet >= 0: 
+            if canAtkRet < scoreCnt:
+                scoreIndex = canAtkRet
+                GameWorld.DebugLog("在匹配中的! scoreIndex=%s" % scoreIndex, playerID)
+                
+        # 复仇的
+        else:
+            # 按排名差
+            fromLowerCnt, matchPerRank = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 2)
+            
+            curPlayerRank = billBoard.IndexOfByID(playerID) + 1
+            tagPlayerRank = billBoard.IndexOfByID(tagPlayerID) + 1
+            if curPlayerRank >= 1 and tagPlayerRank >= 1:
+                fromRank = curPlayerRank - (scoreCnt - fromLowerCnt) * matchPerRank
+                for index in range(scoreCnt):
+                    toRank = fromRank + matchPerRank - 1
+                    if fromRank <= tagPlayerRank <= toRank:
+                        scoreIndex = index
+                        break
+                    fromRank = toRank + 1
+                    
+            GameWorld.DebugLog("在复仇中的! curPlayerRank=%s,tagPlayerRank=%s,scoreIndex=%s" % (curPlayerRank, tagPlayerRank, scoreIndex), playerID)
+            
+        winScoreInfo = winScoreList[scoreIndex] if scoreIndex < scoreCnt else winScoreList[-1]
+        atkAddScore, defDecScore = winScoreInfo
+        GameWorld.DebugLog("scoreIndex=%s,winScoreInfo=%s" % (scoreIndex, winScoreInfo), playerID)
+        
+    if not PlayerControl.PayMoney(curPlayer, ShareDefine.TYPE_Price_ArenaTicket, 1):
+        return
+    
+    # 无论胜负,只要挑战都给固定奖励
+    awardItemList = IpyGameDataPY.GetFuncEvalCfg("ArenaSet", 4)
+    ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["Arena", False, {}], isNotifyAward=False)
+    
+    __updArenaBatRecord(curPlayer, turnFight, tagPlayerID, isWin, atkAddScore, defDecScore)
+    
+    overMsg.update({"tagPlayerID":tagPlayerID, "atkAddScore":atkAddScore, "defDecScore":defDecScore,
+                    FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(awardItemList)})
+    
+    PlayerArena.Sync_ArenaInfo(curPlayer)
+    
+    # 战斗结束系统强制刷新匹配
+    PlayerArena.DoArenaMatchRefresh(curPlayer, True, isSys=True)
+    return
+
+def __updArenaBatRecord(curPlayer, turnFight, tagPlayerID, isWin, atkAddScore, defDecScore):
+    ## 更新战斗相关日志、榜单等
+    
+    playerID = curPlayer.GetPlayerID()
+    maxCount = min(50, IpyGameDataPY.GetFuncCfg("ArenaSet", 2))
+    score = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
+    updScore = max(0, score + atkAddScore)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, updScore)
+    GameWorld.DebugLog("score=%s,atkAddScore=%s,updScore=%s" % (score, atkAddScore, updScore), playerID)
+    
+    tagViewCache = turnFight.tagViewCache
+    gameRecMgr = DBDataMgr.GetGameRecMgr()
+    atkRecMgr = gameRecMgr.GetRecTypeIDMgr(ShareDefine.Def_GameRecType_ArenaRecord, playerID)
+    recData = atkRecMgr.AddRecData(maxCount)
+    PlayerArena.SetRecUpdScore(recData, updScore)
+    PlayerArena.SetRecAtkType(recData, PlayerArena.RecAtkType_Atk)
+    PlayerArena.SetRecTagPlayerID(recData, tagPlayerID)
+    PlayerArena.SetRecIsWin(recData, isWin)
+    PlayerArena.SetRecFace(recData, tagViewCache.GetFace())
+    PlayerArena.SetRecFacePic(recData, tagViewCache.GetFacePic())
+    PlayerArena.SetRecRealmLV(recData, tagViewCache.GetRealmLV())
+    PlayerArena.SetRecLV(recData, tagViewCache.GetLV())
+    # 名字、变更积分 +-、战力
+    # 战力统一记录防守阵容
+    fightPower = TurnAttack.GetCacheLineupFightPower(tagViewCache, ShareDefine.Lineup_ArenaDef)
+    recData.SetUserData({"Name":tagViewCache.GetPlayerName(), "AddScore":atkAddScore, "FightPower":fightPower})
+    # 攻击方仅在积分变更或者初始积分时更新榜单
+    if atkAddScore or updScore == IpyGameDataPY.GetFuncCfg("ArenaSet", 1):
+        PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_Arena, updScore)
+        
+    # 被击方
+    if tagPlayerID < ShareDefine.RealPlayerIDStart:
+        GameWorld.DebugLog("目标非真实玩家不处理! tagPlayerID=%s" % tagPlayerID, playerID)
+        return
+    
+    # 以战斗记录作为最新积分的更新记录,支持离线玩家上线后更新最新积分
+    # 由于非榜单上的玩家不会被匹配到,所以被匹配到的可以理解为一定有战斗记录,因为要上榜必须战斗过
+    defRecMgr = gameRecMgr.GetRecTypeIDMgr(ShareDefine.Def_GameRecType_ArenaRecord, tagPlayerID)
+    if not defRecMgr.GetCount():
+        GameWorld.DebugLog("目标没有对战记录不处理! tagPlayerID=%s" % tagPlayerID, playerID)
+        return
+    
+    finalRecData = defRecMgr.At(defRecMgr.GetCount() - 1)
+    if not GameWorld.CheckTimeIsSameWeek(finalRecData.GetTime()):
+        GameWorld.DebugLog("目标本周没有对战记录不处理! tagPlayerID=%s" % tagPlayerID, playerID)
+        return
+    
+    defScore = PlayerArena.GetRecUpdScore(finalRecData)
+    updScore = max(0, defScore - defDecScore)
+    GameWorld.DebugLog("defScore=%s,defDecScore=%s,updScore=%s" % (defScore, defDecScore, updScore), playerID)
+    
+    recData = defRecMgr.AddRecData(maxCount)
+    PlayerArena.SetRecUpdScore(recData, updScore)
+    PlayerArena.SetRecAtkType(recData, PlayerArena.RecAtkType_Def)
+    PlayerArena.SetRecTagPlayerID(recData, playerID)
+    PlayerArena.SetRecIsWin(recData, not isWin)
+    PlayerArena.SetRecFace(recData, curPlayer.GetFace())
+    PlayerArena.SetRecFacePic(recData, curPlayer.GetFacePic())
+    PlayerArena.SetRecRealmLV(recData, curPlayer.GetOfficialRank())
+    PlayerArena.SetRecLV(recData, curPlayer.GetLV())
+    # 名字、变更积分 +-、战力
+    fightPower = TurnAttack.GetPlayerLineupFightPower(curPlayer, ShareDefine.Lineup_ArenaDef)
+    recData.SetUserData({"Name":curPlayer.GetPlayerName(), "AddScore":-defDecScore, "FightPower":fightPower})
+    if defDecScore: # 防守方仅变更时更新
+        PlayerBillboard.UpdateBillboardByID(tagPlayerID, ShareDefine.Def_BT_Arena, updScore)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py
index 123be33..69d3df3 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py
@@ -25,6 +25,7 @@
 import ItemControler
 import IPY_GameWorld
 import NetPackCommon
+import PlayerArena
 import ItemCommon
 import PlayerTask
 import NPCCommon
@@ -130,6 +131,22 @@
         if dropBootyCnt <= 0:
             continue
         
+        itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)
+        if not itemData:
+            continue
+        
+        # 判断挑战券
+        if itemData.GetType() == ChConfig.Def_ItemType_AutoUseMoney:
+            curEff = itemData.GetEffectByIndex(0)
+            effID = curEff.GetEffectID()
+            moneyType = curEff.GetEffectValue(1)
+            if effID == ChConfig.Def_Effect_ItemGiveMoney and moneyType == ShareDefine.TYPE_Price_ArenaTicket:
+                curMoney = PlayerControl.GetMoney(curPlayer, ShareDefine.TYPE_Price_ArenaTicket)
+                storeMax = PlayerArena.GetArenaTicketStoreMax(curPlayer)
+                if curMoney >= storeMax:
+                    GameWorld.DebugLog("挑战券已达存储上限! itemID=%s,curMoney=%s >= %s" % (itemID, curMoney, storeMax), playerID)
+                    continue
+                
         dropCntRange = bootyDropCntDict[itemID]
         if not isinstance(dropCntRange, (list, tuple)) or len(dropCntRange) != 2:
             continue
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index 861ba0c..a7b8e5e 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -2565,6 +2565,11 @@
                         ("BYTE", "WorkerMax", 0),
                         ("BYTE", "NeedSeconds", 0),
                         ),
+
+                "Robot":(
+                        ("DWORD", "ID", 1),
+                        ("char", "ViewCache", 0),
+                        ),
                 }
 
 
@@ -6388,6 +6393,16 @@
     def GetRefreshWeight(self): return self.attrTuple[4] # 常规刷新权重 DWORD
     def GetWorkerMax(self): return self.attrTuple[5] # 监工上限 BYTE
     def GetNeedSeconds(self): return self.attrTuple[6] # 耗时秒 BYTE
+
+# 机器人
+class IPY_Robot():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetID(self): return self.attrTuple[0] # 机器人ID,同玩家ID DWORD
+    def GetViewCache(self): return self.attrTuple[1] # 机器人缓存 char
 
 
 def Log(msg, playerID=0, par=0):
@@ -6702,6 +6717,7 @@
         self.__LoadFileData("GoldRushCamp", onlyCheck)
         self.__LoadFileData("GoldRushWorker", onlyCheck)
         self.__LoadFileData("GoldRushItem", onlyCheck)
+        self.__LoadFileData("Robot", onlyCheck)
         Log("IPY_DataMgr ReloadOK! onlyCheck=%s" % onlyCheck)
         return
     
@@ -8718,6 +8734,13 @@
     def GetGoldRushItemByIndex(self, index):
         self.CheckLoadData("GoldRushItem")
         return self.ipyGoldRushItemCache[index]
+
+    def GetRobotCount(self):
+        self.CheckLoadData("Robot")
+        return self.ipyRobotLen
+    def GetRobotByIndex(self, index):
+        self.CheckLoadData("Robot")
+        return self.ipyRobotCache[index]
 
 IPYData = IPY_DataMgr()
 def IPY_Data(): return IPYData
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
index 989a0ce..36d166c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
@@ -704,7 +704,6 @@
                             ChConfig.Def_Effect_TrainRealmLV:"Item_TrainRealmLV", # 境界培养卡
                             ChConfig.Def_Effect_ResetBossKillCnt:"Item_ResetBossKillCnt", # 重置boss击杀疲劳
                             ChConfig.Def_Effect_AddFBCnt:"Item_AddFBCnt", # 增加副本可进入次数
-                            ChConfig.Def_Effect_AddArenaBattleCount:"Item_AddArenaBattleCount", # 增加竞技场挑战次数
                             ChConfig.Def_Effect_AddKillBossCnt:"Item_AddKillBossCnt", # 增加BOSS可击杀次数
                             ChConfig.Def_Effect_AddMagicWeaponUpExp:"Item_AddMagicWeaponUpExp", # 增加法宝升星经验
                             ChConfig.Def_Effect_ChatBubbleBox:"Item_ChatBubbleBox", # 激活聊天气泡框
@@ -715,6 +714,7 @@
                             ChConfig.Def_Effect_AddRealmExpRate:"Item_AddRealmExpRate", # 增加聚灵效率
                             ChConfig.Def_Effect_TouchMission:"Item_TouchMission",  # 触发任务接口
                             ChConfig.Def_Effect_HeroSkin:"Item_HeroSkin",  # 武将皮肤
+                            #ChConfig.Def_Effect_AddArenaBattleCount:"Item_AddArenaBattleCount", # 增加竞技场挑战次数
                             #ChConfig.Def_Effect_FamilyImpeach:"Item_FamilyImpeach",  # 弹劾符
                             #ChConfig.Def_Effect_ClothesCoatSkin:"Item_ClothesCoatSkin", #激活时装皮肤
                             #ChConfig.Def_Effect_AddOfficialExp:"Item_AddOfficialExp", # 增加爵位经验
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_AddArenaBattleCount.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_AddArenaBattleCount.py
deleted file mode 100644
index cfe6ed8..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_AddArenaBattleCount.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#-------------------------------------------------------------------------------
-#
-##@package UseItem.Item_AddArenaBattleCount
-#
-# @todo:增加竞技场挑战次数
-# @author hxp
-# @date 2020-12-07
-# @version 1.0
-#
-# 详细描述: 增加竞技场挑战次数
-#
-#-------------------------------------------------------------------------------
-#"""Version = 2020-12-07 19:30"""
-#-------------------------------------------------------------------------------
-
-import ItemCommon
-import PlayerControl
-import PlayerArena
-import ChConfig
-
-#------------------------------------------------------------------------------ 
-
-#------------------------------------------------------------------------------ 
-##使用物品,触发物品附加效果 增加BOSS可击杀次数
-# @param curPlayer 玩家实例
-# @param curRoleItem 物品实例
-# @param tick 时间戳
-# @return 是否使用物品成功
-# @remarks 使用物品,触发物品附加效果
-def BatchUseItem(curPlayer, curRoleItem, tick, useCnt, exData):
-    useItemEff = curRoleItem.GetEffectByIndex(0)
-    addCnt = useItemEff.GetEffectValue(0) * useCnt
-    if addCnt <= 0:
-        return
-    
-    updItemAddCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaItemAddCount) + addCnt
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaItemAddCount, updItemAddCount)
-    PlayerArena.Sync_ArenaInfo(curPlayer)
-    
-    #扣除物品
-    ItemCommon.DelItem(curPlayer, curRoleItem, useCnt)
-    
-    # 竞技场挑战次数增加<color=#109d06FF>%s0</color>次
-    PlayerControl.NotifyCode(curPlayer, "ArenaBattleCountAdd", [addCnt])
-    return True
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
index 2a3f9d4..d6271f0 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -4054,3 +4054,50 @@
     #PlayerControl.SetRealmDifficulty(curPlayer, clientData.RealmDifficulty)
     return
 
+#// A0 08 查看通用记录 #tagCSViewGameRec
+#
+#struct    tagCSViewGameRec
+#{
+#    tagHead        Head;
+#    WORD         RecType;        //记录类型
+#    DWORD         RecID;        //自定义记录ID
+#};
+def OnViewGameRec(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    recType = clientData.RecType
+    recID = clientData.RecID
+    if recType not in ShareDefine.Def_GameRecTypeList:
+        return
+    if recType in ShareDefine.Def_ViewGameRecSelfList:
+        recID = curPlayer.GetPlayerID()
+    recTypeIDMgr = DBDataMgr.GetGameRecMgr().GetRecTypeIDMgr(recType, recID)
+    SyncGameRecInfo(curPlayer, recType, recID, recTypeIDMgr.GetDataList())
+    return
+
+def SyncGameRecInfo(curPlayer, recType, recID, recDataList):
+    recList = []
+    for recData in recDataList:
+        if not recData:
+            continue
+        rec = ChPyNetSendPack.tagSCGameRec()
+        rec.Time = recData.GetTime()
+        rec.Value1 = recData.GetValue1()
+        rec.Value2 = recData.GetValue2()
+        rec.Value3 = recData.GetValue3()
+        rec.Value4 = recData.GetValue4()
+        rec.Value5 = recData.GetValue5()
+        rec.Value6 = recData.GetValue6()
+        rec.Value7 = recData.GetValue7()
+        rec.Value8 = recData.GetValue8()
+        rec.UserData = recData.GetUserData()
+        rec.UserDataLen = len(rec.UserData)
+        recList.append(rec)
+        
+    clientPack = ChPyNetSendPack.tagSCGameRecInfo()
+    clientPack.Clear()
+    clientPack.RecType = recType
+    clientPack.RecID = recID
+    clientPack.RecList = recList
+    clientPack.Count = len(clientPack.RecList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerArena.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerArena.py
index 93d59c1..5db30f2 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerArena.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerArena.py
@@ -4,366 +4,346 @@
 #
 ##@package Player.PlayerArena
 #
-# @todo:竞技场 - 本服
+# @todo:演武场
 # @author hxp
-# @date 2020-12-07
+# @date 2025-09-12
 # @version 1.0
 #
-# 详细描述: 竞技场 - 本服
+# 详细描述: 演武场
 #
 #-------------------------------------------------------------------------------
-#"""Version = 2020-12-07 19:30"""
+#"""Version = 2025-09-12 10:30"""
 #-------------------------------------------------------------------------------
 
+import DBDataMgr
+import PlayerMail
 import ShareDefine
 import GameFuncComm
 import PlayerControl
 import IpyGameDataPY
 import ChPyNetSendPack
+import PlayerViewCache
 import NetPackCommon
+import PyGameData
 import GameWorld
 import ChConfig
-import FBCommon
-import IPY_GameWorld
-import ItemControler
-import PlayerActTask
-import PlayerWeekParty
-import PlayerFeastTravel
-import PlayerActivity
-import PlayerSuccess
-import PlayerGubao
+import random
 
-def DoArenaOpen(curPlayer):
-    ## 竞技场功能开启
-    __DoArenaSeasonReset(curPlayer)
+# 记录攻击类型
+RecAtkType_Atk = 1 # 发起攻击
+RecAtkType_Def = 2 # 被攻击的
+
+def GetRecUpdScore(recData): return recData.GetValue1() # 更新积分
+def SetRecUpdScore(recData, score): return recData.SetValue1(score)
+def GetRecAtkType(recData): return recData.GetValue2() # 攻击类型 1-发起攻击的,2-被攻击的
+def SetRecAtkType(recData, atkType): return recData.SetValue2(atkType)
+def GetRecTagPlayerID(recData): return recData.GetValue3() # 相对攻击类型的目标玩家ID
+def SetRecTagPlayerID(recData, tagPlayerID): return recData.SetValue3(tagPlayerID)
+def GetRecIsWin(recData): return recData.GetValue4() # 是否获胜 1-获胜;2-失败
+def SetRecIsWin(recData, isWin): return recData.SetValue4(1 if isWin else 0)
+def GetRecFace(recData): return recData.GetValue5() # 目标头像
+def SetRecFace(recData, face): return recData.SetValue5(face)
+def GetRecFacePic(recData): return recData.GetValue6()
+def SetRecFacePic(recData, facePic): return recData.SetValue6(facePic)
+def GetRecRealmLV(recData): return recData.GetValue7()
+def SetRecRealmLV(recData, realmLV): return recData.SetValue7(realmLV)
+def GetRecLV(recData): return recData.GetValue8()
+def SetRecLV(recData, tagLV): return recData.SetValue8(tagLV)
+#SetUserData 名字、变更积分 +-、战力
+
+def OnWeek():
+    DoArenaReset()
+    return
+
+def OnDay():
+    __DoGiveBillboardAward("Day")
+    return
+
+def DoArenaReset():
+    ''' 赛季重置
+    '''
+    GameWorld.Log("=============== 重置竞技场 ===============")
+    
+    PyGameData.g_arenaPlayerMatchDict = {}
+    
+    # 结算上赛季排行奖励
+    __DoGiveBillboardAward("Week")
+    
+    # 重置排行榜
+    DBDataMgr.GetBillboardMgr().RemoveBillboard(ShareDefine.Def_BT_Arena)
+    # 重置记录
+    #DBDataMgr.GetGameRecMgr().DelDataByType(ShareDefine.Def_GameRecType_ArenaRecord) # 挑战记录不重置
+    
+    GameWorld.Log("==========================================")
+    return True
+
+def __DoGiveBillboardAward(awardType):
+    ## 竞技场结算排行奖励, 每日、赛季通用
+    
+    GameWorld.Log("=== 竞技场结算排行奖励! === %s" % awardType)
+    
+    billboardMgr = DBDataMgr.GetBillboardMgr()
+    billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Arena)
+    if not billBoard:
+        return
+    
+    if awardType == "Day":
+        billboradAwardDict = IpyGameDataPY.GetFuncEvalCfg("ArenaBillboradAward", 1, {})
+    elif awardType == "Week":
+        billboradAwardDict = IpyGameDataPY.GetFuncEvalCfg("ArenaBillboradAward", 2, {})
+    else:
+        return
+    
+    orderList = [int(orderStr) for orderStr in billboradAwardDict.keys()]
+    orderList.sort()
+    GameWorld.Log("    奖励名次列表: %s" % orderList)
+    
+    awardOrder = orderList[0]
+    orderPlayerIDDict = {}
+    billboardCount, billboardMaxCount = billBoard.GetCount(), billBoard.GetMaxCount()
+    GameWorld.Log("    榜单数据数! billboardCount=%s,billboardMaxCount=%s" % (billboardCount, billboardMaxCount))
+    for index in xrange(billboardCount):
+        billBoardData = billBoard.At(index)
+        if not billBoardData:
+            continue
+        order = index + 1
+        
+        if order > awardOrder:
+            nextOrderIndex = orderList.index(awardOrder) + 1
+            if nextOrderIndex >= len(orderList):
+                break
+            awardOrder = orderList[nextOrderIndex]
+            
+        playerID = billBoardData.GetID()
+        if playerID < ShareDefine.RealPlayerIDStart:
+            # 非真人不处理
+            continue
+        
+        orderPlayerIDDict[playerID] = [order, awardOrder]
+        
+        paramList = [order]
+        awardList = billboradAwardDict[str(awardOrder)]
+        PlayerMail.SendMailByKey("ArenaBillboardAward%s" % awardType, playerID, awardList, paramList)
+        
+    GameWorld.Log("    奖励玩家名次信息: %s" % orderPlayerIDDict)
     return
 
 def OnLogin(curPlayer):
     if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Arena):
         return
-    OSSeasonState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaOSSeasonState)
-    if not OSSeasonState:
-        __DoArenaSeasonReset(curPlayer)
-    else:
-        Sync_ArenaInfo(curPlayer)
+    __loginUpdPlayerScore(curPlayer)
+    Sync_ArenaInfo(curPlayer)
+    return
+
+def __loginUpdPlayerScore(curPlayer):
+    playerID = curPlayer.GetPlayerID()
+    recMgr = DBDataMgr.GetGameRecMgr()
+    recIDMgr = recMgr.GetRecTypeIDMgr(ShareDefine.Def_GameRecType_ArenaRecord, playerID)
+    if not recIDMgr.GetCount():
+        return
+    finalRecData = recIDMgr.At(recIDMgr.GetCount() - 1)
+    recTime = finalRecData.GetTime()
+    if not GameWorld.CheckTimeIsSameWeek(recTime):
+        GameWorld.Log("玩家上线演武场记录积分非本周不更新! recTime=%s" % GameWorld.ChangeTimeNumToStr(recTime), playerID)
+        return
+    updScore = GetRecUpdScore(finalRecData)
+    befScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, updScore)
+    GameWorld.Log("玩家上线更新演武场积分: befScore=%s,updScore=%s,recTime=%s" % (befScore, updScore, GameWorld.ChangeTimeNumToStr(recTime)), playerID)
     return
 
 def OnDayEx(curPlayer):
     if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Arena):
         return
-    
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaItemAddCount, 0)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaBattleCountDay, 0)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaMatchRefreshCount, 0)
     Sync_ArenaInfo(curPlayer)
-    
-    openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1
-    customMaxServerDay = IpyGameDataPY.GetFuncCfg("OperationAction", 1)
-    if openServerDay <= customMaxServerDay:
-        GameWorld.DebugLog("OnDayEx时竞技场开服定制赛季进行中,不处理! openServerDay=%s <= %s" % (openServerDay, customMaxServerDay))
-        return
-    
-    OSSeasonState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaOSSeasonState)
-    if OSSeasonState > 1:
-        GameWorld.DebugLog("OnDayEx时竞技场开服定制赛季已结算过,不处理! OSSeasonState=%s" % (OSSeasonState))
-        return
-    
-    __DoArenaSeasonReset(curPlayer)
     return
 
 def OnWeekEx(curPlayer):
     if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Arena):
         return
-    
-    openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1
-    customMaxServerDay = IpyGameDataPY.GetFuncCfg("OperationAction", 1)
-    if openServerDay <= customMaxServerDay:
-        GameWorld.DebugLog("OnWeekEx时在开服定制天内,不处理竞技场赛季重置! openServerDay=%s <= %s" % (openServerDay, customMaxServerDay))
-        return
-    
-    OSSeasonState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaOSSeasonState)
-    if not OSSeasonState or OSSeasonState == 1 or OSSeasonState == openServerDay:
-        GameWorld.DebugLog("OnWeekEx时竞技场开服定制赛季进行中或同一天结算,不处理重置! openServerDay=%s,OSSeasonState=%s" % (openServerDay, OSSeasonState))     
-        return
-    
+    __DoArenaSeasonReset(curPlayer)
+    return
+
+def DoArenaOpen(curPlayer):
     __DoArenaSeasonReset(curPlayer)
     return
 
 def __DoArenaSeasonReset(curPlayer):
     ## 玩家重置竞技场
-    
-    OSSeasonState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaOSSeasonState)
-    openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1
-    
-    customMaxServerDay = IpyGameDataPY.GetFuncCfg("OperationAction", 1)
-    if openServerDay <= customMaxServerDay and OSSeasonState != 0:
-        GameWorld.DebugLog("开服定制天内不能重置!")
-        return
-    
-    setScoreMin, setScoreMax, refScoreMax = IpyGameDataPY.GetFuncEvalCfg("ArenaSet", 2)
-    setScore = setScoreMin
-    if openServerDay <= customMaxServerDay and OSSeasonState == 0:
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaOSSeasonState, 1)
-        GameWorld.DebugLog("竞技场开服定制赛季! setScore=%s" % setScore)
-    else:
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaOSSeasonState, customMaxServerDay + 1)
-        
-        preSeasonscore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
-        if preSeasonscore <= setScoreMin:
-            setScore = setScoreMin
-        elif preSeasonscore >= refScoreMax:
-            setScore = setScoreMax
-        else:
-            # 按比例降低积分,都减去最低分的差值算比例
-            calcScore = preSeasonscore - setScoreMin
-            setScore = setScoreMin + int(calcScore * (setScoreMax - setScoreMin) / float(refScoreMax - setScoreMin))
-            
-        GameWorld.DebugLog("竞技场赛季重置! preSeasonscore=%s,setScore=%s" % (preSeasonscore, setScore))
-        
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, setScore)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaItemAddCount, 0)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaBattleCountDay, 0)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaMatchRefreshCount, 0)
-    Sync_ArenaInfo(curPlayer, True)
+    initScore = IpyGameDataPY.GetFuncCfg("ArenaSet", 1)
+    GameWorld.DebugLog("竞技场赛季重置!initScore=%s" % (initScore))
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, initScore)
+    Sync_ArenaInfo(curPlayer)
     return
 
-def CheckArenaBattleCount(curPlayer):
-    ## 验证是否还有对战次数
-    todayBattleCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleCountDay)
-    itemAddCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaItemAddCount)
-    dayFreeCount = IpyGameDataPY.GetFuncCfg("ArenaSet", 3)
-    return todayBattleCount < (dayFreeCount + itemAddCount)
+def GetArenaTicketStoreMax(curPlayer):
+    ## 获取挑战券存储上限
+    baseCnt = IpyGameDataPY.GetFuncCfg("ArenaSet", 3)
+    
+    # 其他特权提升上限
+    
+    storeMax = baseCnt
+    return storeMax
 
-#// B2 09 竞技场匹配玩家 #tagCMArenaMatch
+#// B2 09 演武场匹配玩家 #tagCSArenaMatch
 #
-#struct    tagCMArenaMatch
+#struct    tagCSArenaMatch
 #{
 #    tagHead         Head;
-#    BYTE        IsRefresh;    // 0-打开界面无匹配数据时时查询,1-强制刷新匹配列表
+#    BYTE        IsRefresh;    // 0-打开界面无匹配数据时查询,1-强制刷新匹配列表
 #};
 def OnArenaMatch(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
     isRefresh = clientData.IsRefresh
-    
-    playerID = curPlayer.GetPlayerID()
-    refreshCountLimit = IpyGameDataPY.GetFuncCfg("ArenaSet", 5)
-    if isRefresh and refreshCountLimit:
-        refreshCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaMatchRefreshCount)
-        if refreshCount >= refreshCountLimit:
-            GameWorld.DebugLog("竞技场刷新匹配玩家次数已满!refreshCount=%s >= %s" % (refreshCount, refreshCountLimit), playerID)
-            return
-        
-    if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_Arena, tick):
-        GameWorld.DebugLog("竞技场匹配操作CD中...", playerID)
-        PlayerControl.NotifyCode(curPlayer, "RequestLater")
-        return
-    
-    playerLV = curPlayer.GetLV()
-    playerScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
-    msgInfo = str(["MatchRefresh", {"isRefresh":isRefresh, "playerLV":playerLV, "playerScore":playerScore}])
-    GameWorld.DebugLog("竞技场发送GameServer匹配: %s" % msgInfo, playerID)
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, "Arena", msgInfo, len(msgInfo))
+    DoArenaMatchRefresh(curPlayer, isRefresh)
     return
 
 def GMArenaMatch(curPlayer, gmMatchIDList):
-    playerID = curPlayer.GetPlayerID()
-    playerLV = curPlayer.GetLV()
-    playerScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
-    msgInfo = str(["MatchRefresh", {"isRefresh":1, "playerLV":playerLV, "playerScore":playerScore, "gmMatchIDList":gmMatchIDList}])
-    GameWorld.DebugLog("竞技场发送GameServer匹配: %s" % msgInfo, playerID)
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, "Arena", msgInfo, len(msgInfo))
+    ## GM直接匹配
+    isRefresh = True
+    DoArenaMatchRefresh(curPlayer, isRefresh, gmMatchIDList)
     return
 
-#// B2 10 竞技场挑战玩家 #tagCMArenaBattle
-#
-#struct    tagCMArenaBattle
-#{
-#    tagHead         Head;
-#    DWORD        TagPlayerID;    // 目标玩家ID或机器人ID
-#    BYTE        Result;    // 0-进入自定义场景发送通知后端;1-胜利(后端处理,暂时不需要发送此状态);2-失败(前端被对手击杀需要发送此状态)
-#};
-def OnArenaBattle(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+def DoArenaMatchRefresh(curPlayer, isRefresh, gmMatchIDList=None, isSys=False):
+    ## 玩家刷新匹配对手
+    
     playerID = curPlayer.GetPlayerID()
-    tagPlayerID = clientData.TagPlayerID
-    result = clientData.Result
+    playerScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
+    matchScoreList = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 1)
     
-    GameWorld.DebugLog("竞技场挑战玩家! tagPlayerID=%s,result=%s" % (tagPlayerID, result), playerID)
-    if not tagPlayerID:
+    GameWorld.DebugLog("竞技场玩家刷新匹配列表: isRefresh=%s,playerScore=%s,gmMatchIDList=%s,isSys=%s" % (isRefresh, playerScore, gmMatchIDList, isSys), playerID)
+    GameWorld.DebugLog("    matchScoreList=%s" % (matchScoreList), playerID)
+    
+    # 匹配对象缓存
+    needMatchCount = len(matchScoreList)
+    if playerID not in PyGameData.g_arenaPlayerMatchDict:
+        PyGameData.g_arenaPlayerMatchDict[playerID] = []
+    matchIDList = PyGameData.g_arenaPlayerMatchDict[playerID]
+    if len(matchIDList) > needMatchCount:
+        matchIDList = matchIDList[:needMatchCount] # 删除多余的个数,一般都是相同的,除非修改匹配数重读配置
+    if not isRefresh and len(matchIDList) == needMatchCount:
+        # 非刷新的并且已经有记录的直接同步
+        GameWorld.DebugLog("    非刷新且有数据,直接同步!", playerID)
+        __SyncMatchList(curPlayer, matchIDList)
         return
-    
-    if not result:
-        GameWorld.DebugLog("更新竞技场对战对手ID! tagPlayerID=%s" % tagPlayerID, playerID)
-        # 记录对手ID
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaBattleTagID, tagPlayerID)
-        return
-    
-    if tagPlayerID >= 10000:
-        if result:
-            GameWorld.DebugLog("真人由后端镜像PK决定胜负! tagPlayerID=%s" % tagPlayerID, playerID)
+    if isRefresh and not gmMatchIDList and not isSys:
+        costMoney, moneyValue = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 4)
+        if not costMoney or not moneyValue or not PlayerControl.PayMoney(curPlayer, costMoney, moneyValue, "Arena"):
             return
         
-    isWin = 1 if result == 1 else 0
-#    # 木桩被击杀,后端判断,其他前端同步
-#    if isWin:
-#        GameWorld.ErrLog("前端不能同步竞技场胜利状态!", playerID)
-#        return
-    
-    recTagPlayerID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleTagID)
-    if tagPlayerID != recTagPlayerID:
-        GameWorld.ErrLog("竞技场结算时对手ID不一致! tagPlayerID(%s) != recTagPlayerID(%s)" % (tagPlayerID, recTagPlayerID), playerID)
-        __DoArenaBattleOver(curPlayer)
+    billboardMgr = DBDataMgr.GetBillboardMgr()
+    billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Arena)
+    if not billBoard:
         return
+    maxOrder = billBoard.GetCount()
+    playerOrder = billBoard.IndexOfByID(playerID) + 1  # 玩家在排行榜中的名次,没有名次为-1
     
-    # 失败结算入口: 前端同步
-    SendGameServer_ArenaBattleOver(curPlayer, isWin)
-    return
-
-def OnKillBattleNPC(curPlayer, curNPC):
-#    ## 击杀对手,前端本,使用木桩NPC作为对手
-#    
-#    if curNPC.GetGameObjType() != IPY_GameWorld.gotNPC or curNPC.GetType() not in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]:
-#        GameWorld.DebugLog("击杀非木桩NPC,不结算!")
-#        return
-#    
-#    # 胜利结算入口:后端验证击杀对手
-#    tagPlayerID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleTagID)
-#    GameWorld.DebugLog("竞技场击杀对手! tagPlayerID=%s" % tagPlayerID, curPlayer.GetPlayerID())
-#    isWin = 1
-#    SendGameServer_ArenaBattleOver(curPlayer, isWin)
-    return
-
-def SendGameServer_ArenaBattleOver(curPlayer, isWin):
-    ## 发送GameServer通知战斗结算
+    matchRobotCntDict = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 3)
+    if playerOrder > 0:
+        matchRobotRange = GameWorld.GetOrderValueByDict(matchRobotCntDict, playerOrder)
+        matchRobotCnt = random.randint(matchRobotRange[0], matchRobotRange[1])
+    else:
+        matchRobotCnt = needMatchCount
+    matchPlayerCnt = needMatchCount - matchRobotCnt
+    GameWorld.DebugLog("    maxOrder=%s,playerOrder=%s,matchRobotCnt=%s,matchPlayerCnt=%s" % (maxOrder, playerOrder, matchRobotCnt, matchPlayerCnt), playerID)
     
-    playerID = curPlayer.GetPlayerID()
-    tagPlayerID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleTagID)
-    if not tagPlayerID:
-        GameWorld.ErrLog("竞技场结算时没有对手ID!", playerID)
-        __DoArenaBattleOver(curPlayer)
-        return
-    
-    if not CheckArenaBattleCount(curPlayer):
-        GameWorld.ErrLog("竞技场已经没有对战次数!", playerID)
-        __DoArenaBattleOver(curPlayer)
-        return
-    
-    tick = GameWorld.GetGameWorld().GetTick()
-    if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_Arena, tick):
-        GameWorld.ErrLog("结算竞技场CD中!tagPlayerID=%s" % tagPlayerID, playerID)
-        return
-    
-    playerLV = curPlayer.GetLV()
-    playerScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
-    msgInfo = str(["BattleResult", {"tagPlayerID":tagPlayerID, "isWin":isWin, "playerLV":playerLV, "playerScore":playerScore, 
-                                    "realmLV":curPlayer.GetOfficialRank(), "fightPower":PlayerControl.GetFightPower(curPlayer)}])
-    GameWorld.DebugLog("竞技场发送GameServer结算: %s" % msgInfo, playerID)
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, "Arena", msgInfo, len(msgInfo))
-    return
-
-def __DoArenaBattleOver(curPlayer, retDict={}):
-    ## 主动战斗结算奖励
-    # @param isOK: True时才结算奖励,防止某些异常情况无法结算通知前端FBOver,导致卡副本
-    
-    GameWorld.DebugLog("结算竞技场对战奖励! retDict=%s" % retDict)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaBattleTagID, 0)
-    
-    isOK = retDict.get("isOK", False)
-    isWin = retDict.get("isWin", 0)
-    if not isOK:
-        # 一直异常的情况直接同步结束包,防止不结算卡副本
-        FBCommon.NotifyFBOver(curPlayer, ChConfig.Def_FBMapID_ArenaBattle, 0, isWin)
-        return
-    
-    #GameServer MapServer 同步有一定时间差,本功能存在被动挑战引发积分变动的情况,
-    #curScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
-    addScore = retDict["addScore"]
-    updScore = retDict["updScore"]
-    curOrder = retDict["curOrder"]
-    updOrder = retDict["updOrder"]
-    offlineRecTime = retDict.get("offlineRecTime", 0)
-    
-    # 扣次数
-    if not offlineRecTime or GameWorld.CheckTimeIsSameServerDayEx(offlineRecTime):
-        todayBattleCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleCountDay) + 1
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaBattleCountDay, todayBattleCount)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaMatchRefreshCount, 0)
+    fromLowerCnt, matchPerRank = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 2)
+    toOrder = playerOrder + fromLowerCnt * matchPerRank # 从低名次往高名次匹配
+    GameWorld.DebugLog("    fromLowerCnt=%s,matchPerRank=%s,toOrder=%s" % (fromLowerCnt, matchPerRank, toOrder), playerID)
+    matchOrderList = [] # 匹配到的名次
+    for _ in range(matchPlayerCnt):
+        fromOrder = max(1, toOrder - matchPerRank)
+        if toOrder <= fromOrder:
+            break
+        orderList = range(fromOrder, toOrder)
+        random.shuffle(orderList)
+        if playerOrder in orderList:
+            orderList.remove(playerOrder) # 不包含自己
+        if not orderList:
+            break
         
-    # 更新积分
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, updScore)
-    highestScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaHighestScore)
-    if updScore > highestScore:
-        highestScore = updScore
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaHighestScore, highestScore)
-        GameWorld.DebugLog("    更新竞技场历史最高分! %s" % highestScore)
+        if fromOrder == 1:
+            for order in orderList:
+                if order > maxOrder:
+                    continue
+                matchOrderList.append(order)
+                if len(matchOrderList) >= matchPlayerCnt:
+                    break
+        else:
+            order = orderList[0]
+            if order <= maxOrder:
+                matchOrderList.append(order)
+                
+        GameWorld.DebugLog("    匹配玩家: fromOrder=%s,toOrder=%s,matchOrderList=%s" % (fromOrder, toOrder, matchOrderList), playerID)
+        toOrder = fromOrder - 1
         
-    # 胜利给额外奖励
-    itemList = retDict.get("awardItemList", [])
-    ItemControler.GivePlayerItemOrMail(curPlayer, itemList)
-    jsonItemList = FBCommon.GetJsonItemList(itemList)
-    
-    overDict = {FBCommon.Over_itemInfo:jsonItemList, "addScore":addScore, "updScore":updScore, "curOrder":curOrder, "updOrder":updOrder}
-    FBCommon.NotifyFBOver(curPlayer, ChConfig.Def_FBMapID_ArenaBattle, 0, isWin, overDict)
-    Sync_ArenaInfo(curPlayer)
-    
-    PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_Arena, 1)
-    PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_Arena, 1)
-    PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_Arena, 1)
-    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_Arena, 1)
-    PlayerGubao.AddGubaoItemEffValue(curPlayer, PlayerGubao.GubaoEffType_Arena, 1)
-    PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_Arena)
-    return
-
-def __DoUpdateArenaScore(curPlayer, cmdDict={}):
-    ''' 玩家直接更新积分,有以下几种情况,都是被挑战的,只更新积分
-    1. 被动挑战在线时直接更新积分
-    2. 离线/脱机时被挑战,上线后同步最新积分
-    '''
-    
-    playerScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
-    updScore = cmdDict.get("updScore", playerScore)
-    if updScore == playerScore:
-        return
-    
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, updScore)
-    Sync_ArenaInfo(curPlayer)
-    return
-
-def GameServer_ArenaResult(curPlayer, msgList, tick):
-    if not msgList:
-        return
-    
-    cmd = msgList[0]
-    cmdDict = msgList[1] if len(msgList) > 1 else {}
-    retDict = msgList[2] if len(msgList) > 2 else {}
-    
-    # 刷新匹配
-    if cmd == "MatchRefresh":
-        isRefresh = cmdDict.get("isRefresh", False)
-        refreshCountLimit = IpyGameDataPY.GetFuncCfg("ArenaSet", 5)
-        if isRefresh and refreshCountLimit:
-            updRefreshCount = min(250, curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaMatchRefreshCount) + 1)
-            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaMatchRefreshCount, updRefreshCount)
-            GameWorld.DebugLog("更新竞技场刷新匹配次数! updRefreshCount=%s" % updRefreshCount)
-            Sync_ArenaInfo(curPlayer)
+    # GM指定匹配测试
+    if gmMatchIDList != None and curPlayer.GetGMLevel():
+        for gmMatchID in gmMatchIDList:
+            if gmMatchID == playerID:
+                GameWorld.DebugAnswer(curPlayer, "目标ID不能是自己!无法匹配!%s" % gmMatchID)
+                continue
             
-    # 主动对战结果
-    elif cmd == "BattleResult":
-        __DoArenaBattleOver(curPlayer, retDict)
+            gmMatchOrder = billBoard.IndexOfByID(gmMatchID) + 1
+            if gmMatchOrder <= 0:
+                GameWorld.DebugAnswer(curPlayer, "目标ID不在榜单上!无法匹配!%s" % gmMatchID)
+                continue
+            GameWorld.DebugAnswer(curPlayer, "指定匹配ID(%s),order(%s)" % (gmMatchID, gmMatchOrder))
+            if gmMatchID not in matchOrderList:
+                matchOrderList.insert(0, gmMatchOrder)
+        matchOrderList = matchOrderList[:needMatchCount]
         
-    # 被动挑战更新积分
-    elif cmd == "UpdScore":
-        __DoUpdateArenaScore(curPlayer, cmdDict)
+    matchOrderList.sort()
+    matchIDList = [] # 最终匹配的玩家ID列表
+    for matchOrder in matchOrderList:
+        if matchOrder > maxOrder or matchOrder <= 0:
+            break
+        billData = billBoard.At(matchOrder - 1)
+        matchIDList.append(billData.GetID())
         
+    needRobotCnt = needMatchCount - len(matchIDList)
+    GameWorld.DebugLog("    匹配榜单结果: matchIDList=%s,matchOrderList=%s,needRobotCnt=%s" % (matchIDList, matchOrderList, needRobotCnt), playerID)
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    robotMax = ipyDataMgr.GetRobotCount()
+    doCnt = 100
+    while doCnt > 0 and needRobotCnt > 0 and robotMax:
+        doCnt -= 1
+        robotIndex = random.randint(0, robotMax - 1)
+        robotIpyData = ipyDataMgr.GetRobotByIndex(robotIndex)
+        robotID = robotIpyData.GetID()
+        if robotID not in matchIDList:
+            matchIDList.append(robotID)
+            needRobotCnt -= 1
+    GameWorld.DebugLog("    最终匹配结果: matchIDList=%s" % matchIDList, playerID)
+    
+    PyGameData.g_arenaPlayerMatchDict[playerID] = matchIDList
+    __SyncMatchList(curPlayer, matchIDList)
     return
 
-def Sync_ArenaInfo(curPlayer, isReset=False):
-    clientPack = ChPyNetSendPack.tagMCArenaPlayerInfo()
-    clientPack.IsReset = 1 if isReset else 0
-    clientPack.Score = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
-    clientPack.BattleCountToday = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleCountDay)
-    clientPack.MatchRefreshCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaMatchRefreshCount)
-    clientPack.ItemAddBattleCountToday = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaItemAddCount)
+def __SyncMatchList(curPlayer, matchIDList):
+    ## 同步匹配列表
+    clientPack = ChPyNetSendPack.tagSCArenaMatchList()
+    clientPack.MatchList = []
+    for matchID in matchIDList:
+        viewCache = PlayerViewCache.FindViewCache(matchID)
+        matchInfo = ChPyNetSendPack.tagSCArenaMatchInfo()
+        matchInfo.PlayerID = matchID
+        if viewCache:
+            matchInfo.PlayerName = viewCache.GetPlayerName()
+            matchInfo.RealmLV = viewCache.GetRealmLV()
+            matchInfo.Face = viewCache.GetFace()
+            matchInfo.FacePic = viewCache.GetFacePic()
+            matchInfo.FightPower = viewCache.GetFightPower()
+            matchInfo.FightPowerEx = viewCache.GetFightPowerEx()
+        else:
+            matchInfo.PlayerName = "p%s" % matchID
+        clientPack.MatchList.append(matchInfo)
+    clientPack.MatchCount = len(clientPack.MatchList)
     NetPackCommon.SendFakePack(curPlayer, clientPack)
     return
 
+def Sync_ArenaInfo(curPlayer):
+    clientPack = ChPyNetSendPack.tagSCArenaPlayerInfo()
+    clientPack.Score = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
index bb56211..bde256f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
@@ -61,10 +61,6 @@
         # 跨服服务器不用更新本服榜
         return
     
-    UpdatePlayerFPTotalBillboard(curPlayer, True) # 战斗力榜
-    UpdateHorseBillboard(curPlayer, True, False) # 坐骑榜
-    UpdatePyPetBillboard(curPlayer, True, False) # 灵宠榜
-    UpdateRealmBillboard(curPlayer) # 境界榜
     return
 
 def UpdatePlayerFPTotalBillboard(curPlayer, isForceUpdate=False, isCheckRule=True):
@@ -149,39 +145,83 @@
     ##境界榜
     return
 
-def __CanPlayerBillboardComm(curPlayer):
-    ## 玩家可否上榜通用检查
-    if not GameWorld.IsNormalPlayer(curPlayer):
-        return False
-    #if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Billboard):
-    #    GameWorld.DebugLog("排行榜未开启,无法上榜!curLV=%s" % (curPlayer.GetLV()), curPlayer.GetPlayerID())
-    #    return False
-    
-    return True
+#def __CanPlayerBillboardComm(curPlayer):
+#    ## 玩家可否上榜通用检查
+#    if not GameWorld.IsNormalPlayer(curPlayer):
+#        return False
+#    #if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Billboard):
+#    #    GameWorld.DebugLog("排行榜未开启,无法上榜!curLV=%s" % (curPlayer.GetLV()), curPlayer.GetPlayerID())
+#    #    return False
+#    
+#    return True
 
-def UpdatePlayerBillboard(curPlayer, bType, cmpValue, cmpValue2=0, cmpValue3=0, value1=0, value2=0, autoSort=False, **kwargs):
+def UpdatePlayerBillboard(curPlayer, bType, cmpValue, cmpValue2=0, cmpValue3=0, value1=None, value2=0, autoSort=False, **kwargs):
     ## 更新玩家排行榜
     
     #if not cmpValue and not cmpValue2 and not cmpValue3:
     #    return
     
-    if not __CanPlayerBillboardComm(curPlayer):
-        return
-    
     playerJob = GetBillboardJob(curPlayer)
     playerID = curPlayer.GetID()
-    playerName = curPlayer.GetName()
+    playerName = curPlayer.GetPlayerName()
     playerOpInfo = GetBillboardOperateInfo(curPlayer)
+    if value1 == None:
+        value1 = curPlayer.GetOfficialRank()
     kwargs["value3"] = curPlayer.GetFace()
     kwargs["value4"] = curPlayer.GetFacePic()
-    if bType in ShareDefine.BTValue1_OfficialRankList:
-        value1 = curPlayer.GetOfficialRank()
-        
+    kwargs["value5"] = curPlayer.GetModelMark()
+    
     groupValue1 = 0
     UpdateBillboard(bType, groupValue1, playerID, playerName, playerOpInfo, playerJob, value1, value2, 
                     cmpValue, cmpValue2, cmpValue3, autoSort=autoSort, **kwargs)
     return
 
+def UpdateBillboardByID(dataID, billboardType, cmpValue, cmpValue2=0, cmpValue3=0, autoSort=False):
+    ## 直接根据榜单ID修改榜单排行相关值,其他值不修改
+    if GameWorld.IsCrossServer():
+        if billboardType not in ShareDefine.CrossBillboardTypeList:
+            return
+    else:
+        if billboardType not in ShareDefine.BillboardTypeList:
+            return
+        
+    if not dataID:
+        return
+    
+    groupValue1, groupValue2 = 0, 0
+    billboardMgr = DBDataMgr.GetBillboardMgr()
+    billboardObj = billboardMgr.GetBillboard(billboardType, groupValue1, groupValue2)
+    billboardData = billboardObj.FindByID(dataID)
+    if not billboardData:
+        return
+    
+    isNewData = False
+    cmpValueChange = isNewData or billboardData.GetCmpValue() != cmpValue or billboardData.GetCmpValue2() != cmpValue2 \
+        or (cmpValue3 and billboardData.GetCmpValue3() != cmpValue3)
+        
+    # 没设置值默认为时间time,先上榜的排前面
+    if cmpValue3 == 0:
+        # 时间权值仅在比较值变更的情况下才更新, 防止其他附属值更新时导致比较值相同的玩家名次间会变动的问题
+        if cmpValueChange:
+            calcTime = GameWorld.ChangeTimeStrToNum("2090-01-01 00:00:00")
+            cmpValue3 = max(0, calcTime - int(time.time())) # 比较值3如果没指定值则默认存当前更新的time
+        else:
+            cmpValue3 = billboardData.GetCmpValue3()
+            
+    billboardData.SetCmpValue(cmpValue)
+    billboardData.SetCmpValue2(cmpValue2)
+    billboardData.SetCmpValue3(cmpValue3)
+    
+    GameWorld.DebugLog("更新排行榜值: billboardType=%s,groupValue1=%s,groupValue2=%s,dataID=%s,cmpValueChange=%s,cmpValue=%s,cmpValue2=%s,cmpValue3=%s" 
+                       % (billboardType, groupValue1, groupValue2, dataID, cmpValueChange,
+                          cmpValue, cmpValue2, cmpValue3), dataID)
+    if not autoSort:
+        if isNewData or cmpValueChange:
+            billboardObj.SetSortDelay()
+    else:
+        billboardObj.SortData()
+    return True
+
 def UpdateBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2, cmpValue,
                     cmpValue2=0, cmpValue3=0, groupValue2=0, id2=0, autoSort=True, **kwargs):
     ''' 更新排行榜
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index bf664fa..97e58b5 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -4373,6 +4373,8 @@
     value = ComMainLevelValue(chapterID, levelNum, wave)
     SetMainLevelPassValue(curPlayer, value)
     if wave == 0:
+        lvID = chapterID * 100 + levelNum
+        PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_MainLevel, lvID)
         PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_MainLevel)
     return value
 def GetMainLevelPassInfo(curPlayer):
@@ -4559,7 +4561,7 @@
         NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_HighestEx, highestFightPower / ChConfig.Def_PerPointValue)
         
     GameWorld.DebugLog("总战力: %s, 历史最高战力: %s, beforeFightPower=%s" % (value, highestFightPower, beforeFightPower), curPlayer.GetPlayerID())
-    PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer)
+    #PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer)
     # 记录开服活动数据
     #OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_FightPower, totalFightPower)
     #if beforeFightPower != totalFightPower:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
index 0d76246..6361081 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -115,6 +115,7 @@
     
     #仙盟
     PlayerFamily.FamilyOnDay()
+    PlayerArena.OnDay()
     
     PlayerOfflineSupport.OnDay()
     playerManager = GameWorld.GetPlayerManager()
@@ -154,6 +155,8 @@
 def DoLogic_OnWeek(tick):
     GameWorld.Log("MapServer -> OnWeek!")
     
+    PlayerArena.OnWeek()
+    
     playerManager = GameWorld.GetPlayerManager()
     for i in xrange(playerManager.GetPlayerCount()):
         curPlayer = playerManager.GetPlayerByIndex(i)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py
index d0c9d72..2f18a62 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py
@@ -156,6 +156,8 @@
         
         # 主线战斗
         self.mainFight = TurnAttack.MainFight(playerID)
+        
+        self._lastBatBufferInfo = [] # 最后一场战斗临时回放 ["guid", "buffer"]
         return
     
     def OnClear(self):
@@ -247,6 +249,11 @@
         GameWorld.DebugLog("武将物品养成更新索引: %s, 影响阵容:%s" % (itemIndexList, effLineupIDList), self.playerID)
         return effLineupIDList
     
+    def GetLastBatBuffer(self): return self._lastBatBufferInfo
+    def SetLastBatBuffer(self, guid, batBuffer):
+        self._lastBatBufferInfo = [guid, batBuffer]
+        return
+    
 class OnlineMgr():
     ## 准在线玩家管理
     
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
index 01a1dc0..1201f24 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
@@ -22,9 +22,10 @@
 import NetPackCommon
 import ChPyNetSendPack
 import IpyGameDataPY
+import IPY_GameWorld
 import ShareDefine
+import TurnAttack
 import DBDataMgr
-import GameObj
 
 import random
 import time
@@ -36,13 +37,19 @@
     return
 
 def OnPlayerLogout(curPlayer):
-    if curPlayer.GetLV() < 10:
+    if curPlayer.GetLV() < IpyGameDataPY.GetFuncCfg("PlayerViewCache", 1):
         return
     
-    curCache = UpdPlayerViewCache(curPlayer)
-    if curCache and not IsSaveDBViewCache(curCache):
+    playerID = curPlayer.GetPlayerID()
+    curCache = FindViewCache(playerID)
+    if not curCache:
+        return
+    
+    UpdPlayerViewCache(curPlayer, True)
+    if not IsSaveDBViewCache(curCache):
         DBDataMgr.GetPlayerViewCacheMgr().DelPlayerViewCache(curPlayer.GetPlayerID())
-        
+        return
+    
     return
 
 def DelOutofTimeViewCacheData():
@@ -53,6 +60,8 @@
     for index in range(viewCacheMgr.GetCount())[::-1]: # 有删除需倒序遍历
         viewCache = viewCacheMgr.At(index)
         playerID = viewCache.GetPlayerID()
+        if playerID < ShareDefine.RealPlayerIDStart:
+            continue
         curPlayer = playerManager.FindPlayerByID(playerID)
         if curPlayer:
             continue
@@ -68,6 +77,9 @@
         return False
     
     playerID = viewCache.GetPlayerID()
+    if playerID < ShareDefine.RealPlayerIDStart:
+        #非真实玩家不入库
+        return False
     
     #某个功能中不能删除的
     #...
@@ -100,7 +112,7 @@
         
     return False
 
-def FindViewCache(playerID, isAdd=False):
+def FindViewCache(playerID):
     '''查找玩家缓存,如果不存在,则会有额外逻辑,如从redis、db直接找,
             本服玩家理论上一定有查看缓存,因为如果不存在会直接从db读,除非该玩家数据被删除
             跨服玩家理论上也一定有缓存,只是通过跨服或从子服查询,延迟获得
@@ -115,7 +127,7 @@
             curCache = updCache
             
     # 真实玩家
-    elif playerID > ShareDefine.FackPlayerIDMax:
+    elif playerID >= ShareDefine.RealPlayerIDStart:
         curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
         # 本服在线玩家,直接生成新数据
         if curPlayer:
@@ -133,6 +145,10 @@
             # 跨服玩家,去子服拉取数据,理论上也一定有,但是如果需要拉数据,有一定延迟
             # 逻辑待扩展
             
+    # 机器人
+    elif ShareDefine.RobotIDStart <= playerID <= ShareDefine.RobotIDMax:
+        curCache = UpdRobotViewCache(playerID)
+        
     # 假玩家,默认添加
     elif ShareDefine.FackPlayerIDStart <= playerID <= ShareDefine.FackPlayerIDMax:
         serverID = playerID % 100 + 1 # 1 ~ 100 服
@@ -152,7 +168,7 @@
     return curCache
 
 def __CheckUpdViewCache(playerID):
-    if playerID <= ShareDefine.FackPlayerIDMax:
+    if playerID < ShareDefine.RealPlayerIDStart:
         return
     curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
     if not curPlayer:
@@ -188,6 +204,7 @@
     curCache.SetRealmLV(curPlayer.GetOfficialRank())
     curCache.SetFace(curPlayer.GetFace())
     curCache.SetFacePic(curPlayer.GetFacePic())
+    curCache.SetModelMark(curPlayer.GetModelMark())
     curCache.SetFamilyID(curPlayer.GetFamilyID())
     curCache.SetFamilyName(curPlayer.GetFamilyName())
     curCache.SetFamilyEmblemID(PlayerControl.GetFamilyEmblemID(curPlayer))
@@ -197,22 +214,30 @@
     if isOffline:
         curCache.SetOffTime(int(time.time()))
         
-    plusDict = curCache.GetPlusDict()
+    # 装备
+    equipDict = {}
+    equipPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)
+    for equipPlace in ChConfig.Def_MainEquipPlaces:
+        equipIndex = equipPlace - 1
+        if equipIndex < 0 or equipIndex >= equipPack.GetCount():
+            continue
+        curEquip = equipPack.GetAt(equipIndex)
+        if not curEquip or curEquip.IsEmpty():
+            continue
+        equipDict["%s" % equipIndex] = {"ItemID":curEquip.GetItemTypeID(), "UserData":curEquip.GetUserData()}
         
-    #战斗属性
-    plusDict.update({
-                     "MinAtk":curPlayer.GetMinAtk(),
-                     "MaxAtk":curPlayer.GetMaxAtk(),
-                     "Def":curPlayer.GetDef(),
-                     "MaxHP":GameObj.GetMaxHP(curPlayer),
-                     "Hit":curPlayer.GetHit(),
-                     "Miss":curPlayer.GetMiss(),
-                     "SuperHitRate":curPlayer.GetSuperHitRate(), # 暴击率
-                     })
-    
-    # 功能数据
+    # 阵容
+    lineupDict = {}
+    for lineupID in ShareDefine.LineupList:
+        lineupInfo = TurnAttack.GetPlayerLineupInfo(curPlayer, lineupID)
+        if not lineupInfo:
+            continue
+        lineupDict["%s" % lineupID] = lineupInfo
     
     # 其他
+    
+    plusDict= {"Equip":equipDict, "Lineup":lineupDict}
+    curCache.SetPlusDict(plusDict)
     
     return curCache
 
@@ -237,6 +262,7 @@
     curCache.SetRealmLV(dbPlayer.OfficialRank)
     curCache.SetFace(dbPlayer.Face)
     curCache.SetFacePic(dbPlayer.FacePic)
+    curCache.SetModelMark(dbPlayer.ModelMark)
     curCache.SetFamilyID(familyID)
     family = DBDataMgr.GetFamilyMgr().FindFamily(familyID)
     curCache.SetFamilyName(family.GetName() if family else "")
@@ -245,6 +271,58 @@
     curCache.SetFightPowerTotal(dbPlayer.FightPowerEx * ChConfig.Def_PerPointValue + dbPlayer.FightPower)
     curCache.SetServerID(GameWorld.GetAccIDServerID(dbPlayer.AccID))
     curCache.SetOffTime(GameWorld.ChangeTimeStrToNum(dbPlayer.LogoffTime) if dbPlayer.LogoffTime else 0)
+    return curCache
+
+def GetRobotByViewCache(curCache):
+    ## 根据缓存内容获取机器人数据
+    if not curCache:
+        return
+    robotDict = {
+                 "PlayerName" : curCache.GetPlayerName(),
+                 "LV" : curCache.GetLV(),
+                 "Job" : curCache.GetJob(),
+                 "RealmLV" : curCache.GetRealmLV(),
+                 "Face" : curCache.GetFace(),
+                 "FacePic" : curCache.GetFacePic(),
+                 "ModelMark" : curCache.GetModelMark(),
+                 "FightPower" : curCache.GetFightPowerTotal(),
+                 "PlusData" : curCache.GetPlusDict(),
+                 }
+    return robotDict
+
+def UpdRobotViewCache(robotID):
+    ## 更新机器人查看缓存
+    robotIpyData = IpyGameDataPY.GetIpyGameData("Robot", robotID)
+    if not robotIpyData:
+        return
+    try:
+        robotInfo = eval(robotIpyData.GetViewCache())
+    except:
+        return
+    
+    viewCacheMgr = DBDataMgr.GetPlayerViewCacheMgr()
+    curCache = viewCacheMgr.GetPlayerViewCache(robotID)
+    if not curCache:
+        curCache = viewCacheMgr.AddPlayerViewCache(robotID)
+    #curCache.SetAccID(dbPlayer.AccID)
+    
+    curCache.SetPlayerName(robotInfo.get("PlayerName", "p%s" % robotID))
+    curCache.SetLV(robotInfo.get("LV", 1))
+    curCache.SetJob(robotInfo.get("Job", 1))
+    curCache.SetRealmLV(robotInfo.get("RealmLV", 0))
+    curCache.SetFace(robotInfo.get("Face", 0))
+    curCache.SetFacePic(robotInfo.get("FacePic", 0))
+    curCache.SetModelMark(robotInfo.get("ModelMark", 0))
+    #机器人暂定没有仙盟、称号
+    #curCache.SetFamilyID(familyID)
+    #family = DBDataMgr.GetFamilyMgr().FindFamily(familyID)
+    #curCache.SetFamilyName(family.GetName() if family else "")
+    #curCache.SetFamilyEmblemID(family.GetEmblemID() if family else 0)
+    #curCache.SetTitleID(PlayerControl.GetTitleID(curPlayer))
+    curCache.SetFightPowerTotal(robotInfo.get("FightPower", 1))
+    curCache.SetServerID(GameWorld.GetGameWorld().GetServerID()) # 默认本服
+    curCache.SetPlusDict(robotInfo.get("PlusData", {}))
+    #curCache.SetOffTime(0)
     return curCache
 
 #//A2 12 查看玩家详细信息#tagCMViewPlayerInfo
@@ -285,6 +363,7 @@
     clientPack.RealmLV = curCache.GetRealmLV()
     clientPack.Face = curCache.GetFace()
     clientPack.FacePic = curCache.GetFacePic()
+    clientPack.ModelMark = curCache.GetModelMark()
     clientPack.TitleID = curCache.GetTitleID()
     clientPack.ServerID = curCache.GetServerID()
     clientPack.FightPower = curCache.GetFightPower()
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_Arena.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_Arena.py
deleted file mode 100644
index b5f40cc..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_Arena.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#-------------------------------------------------------------------------------
-#
-##@package Player.RemoteQuery.GY_Query_Arena
-#
-# @todo:竞技场
-# @author hxp
-# @date 2020-12-07
-# @version 1.0
-#
-# 详细描述: 竞技场
-#
-#-------------------------------------------------------------------------------
-#"""Version = 2020-12-07 19:30"""
-#-------------------------------------------------------------------------------
-
-import GameWorld
-import PlayerArena
-import ChConfig
-
-#---------------------------------------------------------------------
-#逻辑实现
-## 请求逻辑
-#  @param query_Type 请求类型
-#  @param query_ID 请求的玩家ID
-#  @param packCMDList 发包命令 [ ]
-#  @param tick 当前时间
-#  @return "True" or "False" or ""
-#  @remarks 函数详细说明.
-def DoLogic(query_Type, query_ID, packCMDList, tick):
-    GameWorld.DebugLog("GY_Query_Arena DoLogic %s" % str(packCMDList), query_ID)
-    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(query_ID)
-    if not curPlayer or curPlayer.IsEmpty():
-        return
-    PlayerArena.GameServer_ArenaResult(curPlayer, packCMDList, tick)
-    return ""
-
-#---------------------------------------------------------------------
-#执行结果
-## 执行结果
-#  @param curPlayer 发出请求的玩家
-#  @param callFunName 功能名称
-#  @param funResult 查询的结果
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
-def DoResult(curPlayer, callFunName, funResult, tick):
-    GameWorld.DebugLog("GY_Query_Arena DoResult %s" % str(funResult), curPlayer.GetPlayerID())
-    if funResult != "":
-        PlayerArena.GameServer_ArenaResult(curPlayer, eval(funResult), tick)
-    curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_Arena, 0)
-    return
-
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
index 127ea96..e3ba0a0 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -35,6 +35,8 @@
 
 g_turnFightMgr = None
 
+g_arenaPlayerMatchDict = {} # 本服竞技场玩家匹配记录缓存 {playerID:[tagPlayerID, ...], ...}
+
 g_mapIDTxtInfo = {} # MapID.txt 加载的信息
 g_realmDiffPlayerDict = {} # 境界难度玩家信息 {realm:[playerID, ...], ...}
 g_realmDiffNPCRefresh = {} # {(lineID, realm):{refreshID:tagNPCRefresh, ...}}
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py
index 375b3b6..a2e642b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py
@@ -25884,6 +25884,7 @@
         ('RealmLV', ctypes.c_ubyte),
         ('Face', ctypes.c_int),
         ('FacePic', ctypes.c_int),
+        ('ModelMark', ctypes.c_ulong),
         ('FamilyID', ctypes.c_ulong),
         ('FamilyName', ctypes.c_char * 33),
         ('FamilyEmblemID', ctypes.c_ushort),
@@ -25910,6 +25911,7 @@
         self.RealmLV = 0
         self.Face = 0
         self.FacePic = 0
+        self.ModelMark = 0
         self.FamilyID = 0
         self.FamilyName = ''
         self.FamilyEmblemID = 0
@@ -25938,6 +25940,7 @@
         self.RealmLV, pos = CommFunc.ReadBYTE(buf, pos)
         self.Face, pos = CommFunc.ReadDWORD(buf, pos)
         self.FacePic, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ModelMark, pos = CommFunc.ReadDWORD(buf, pos)
         self.FamilyID, pos = CommFunc.ReadDWORD(buf, pos)
         self.FamilyName, pos = CommFunc.ReadString(buf, pos, 33)
         self.FamilyEmblemID, pos = CommFunc.ReadWORD(buf, pos)
@@ -25961,6 +25964,7 @@
         buf = CommFunc.WriteBYTE(buf, self.RealmLV)
         buf = CommFunc.WriteDWORD(buf, self.Face)
         buf = CommFunc.WriteDWORD(buf, self.FacePic)
+        buf = CommFunc.WriteDWORD(buf, self.ModelMark)
         buf = CommFunc.WriteDWORD(buf, self.FamilyID)
         buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 33, self.FamilyName)
         buf = CommFunc.WriteWORD(buf, self.FamilyEmblemID)
@@ -25984,6 +25988,7 @@
         length += sizeof(ctypes.c_int)
         length += sizeof(ctypes.c_int)
         length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
         length += sizeof(ctypes.c_char) * 33
         length += sizeof(ctypes.c_ushort)
         length += sizeof(ctypes.c_ulong)
@@ -26006,6 +26011,7 @@
         rec[u'RealmLV'] = self.RealmLV
         rec[u'Face'] = self.Face
         rec[u'FacePic'] = self.FacePic
+        rec[u'ModelMark'] = self.ModelMark
         rec[u'FamilyID'] = self.FamilyID
         rec[u'FamilyName'] = fix_incomingText(self.FamilyName)
         rec[u'FamilyEmblemID'] = self.FamilyEmblemID
@@ -26028,6 +26034,7 @@
         self.RealmLV = rec.get(u'RealmLV', 0)
         self.Face = rec.get(u'Face', 0)
         self.FacePic = rec.get(u'FacePic', 0)
+        self.ModelMark = rec.get(u'ModelMark', 0)
         self.FamilyID = rec.get(u'FamilyID', 0)
         self.FamilyName = fix_outgoingText(rec.get(u'FamilyName', u''))
         self.FamilyEmblemID = rec.get(u'FamilyEmblemID', 0)
@@ -26149,6 +26156,7 @@
             RealmLV = %s,
             Face = %s,
             FacePic = %s,
+            ModelMark = %s,
             FamilyID = %s,
             FamilyName = %s,
             FamilyEmblemID = %s,
@@ -26169,6 +26177,7 @@
                 self.RealmLV,
                 self.Face,
                 self.FacePic,
+                self.ModelMark,
                 self.FamilyID,
                 self.FamilyName,
                 self.FamilyEmblemID,
@@ -26184,7 +26193,7 @@
         return output
 
     def dumpString(self):
-        output = '''%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s'''%(
+        output = '''%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s'''%(
                 self.PlayerID,
                 self.AccID,
                 self.PlayerName,
@@ -26193,6 +26202,7 @@
                 self.RealmLV,
                 self.Face,
                 self.FacePic,
+                self.ModelMark,
                 self.FamilyID,
                 self.FamilyName,
                 self.FamilyEmblemID,
@@ -28174,223 +28184,6 @@
         else:
             self.Name = Str[:33]
             
-
-
-# 通用记录表新 #tagDBGameRec
-class tagDBGameRec(Structure):
-    _pack_ = 1
-    _fields_ = [
-        ('RecType', ctypes.c_ushort),
-        ('RecID', ctypes.c_ulong),
-        ('Time', ctypes.c_double),
-        ('Value1', ctypes.c_ulong),
-        ('Value2', ctypes.c_ulong),
-        ('Value3', ctypes.c_ulong),
-        ('Value4', ctypes.c_ulong),
-        ('Value5', ctypes.c_ulong),
-        ('Value6', ctypes.c_ulong),
-        ('Value7', ctypes.c_ulong),
-        ('Value8', ctypes.c_ulong),
-        ('UserDataLen', ctypes.c_ushort),
-        ('UserData', ctypes.c_char_p),
-        ('ADOResult', ctypes.c_ulong),
-    ]
-
-    def __init__(self):
-        Structure.__init__(self)
-        self.clear()
-
-    def clear(self):
-        self.RecType = 0
-        self.RecID = 0
-        self.Time = 0.0
-        self.Value1 = 0
-        self.Value2 = 0
-        self.Value3 = 0
-        self.Value4 = 0
-        self.Value5 = 0
-        self.Value6 = 0
-        self.Value7 = 0
-        self.Value8 = 0
-        self.UserDataLen = 0
-        self.UserData = ''
-
-    def readData(self, buf, pos = 0, length = 0):
-        if not pos <= length:
-            msg = error.formatMsg('error', error.ERROR_NO_148, '(pos = %s) > (length = %s)'%(pos, length))
-            mylog.error(msg)
-            return -1
-        if len(buf) < pos + self.getLength():
-            msg = error.formatMsg('error', error.ERROR_NO_149, 'len = %s while %s expected!'%(len(buf) - pos, self.getLength()))
-            mylog.error(msg)
-        self.clear()
-        self.RecType, pos = CommFunc.ReadWORD(buf, pos)
-        self.RecID, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Time, pos = CommFunc.ReadDouble(buf, pos)
-        self.Value1, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Value2, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Value3, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Value4, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Value5, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Value6, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Value7, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Value8, pos = CommFunc.ReadDWORD(buf, pos)
-        self.UserDataLen, pos = CommFunc.ReadWORD(buf, pos)
-        tmp, pos = CommFunc.ReadString(buf, pos, self.UserDataLen)
-        self.UserData = ctypes.c_char_p(tmp)
-        return self.getLength()
-
-    def getBuffer(self):
-        buf = ''
-        buf = CommFunc.WriteWORD(buf, self.RecType)
-        buf = CommFunc.WriteDWORD(buf, self.RecID)
-        buf = CommFunc.WriteDouble(buf, self.Time)
-        buf = CommFunc.WriteDWORD(buf, self.Value1)
-        buf = CommFunc.WriteDWORD(buf, self.Value2)
-        buf = CommFunc.WriteDWORD(buf, self.Value3)
-        buf = CommFunc.WriteDWORD(buf, self.Value4)
-        buf = CommFunc.WriteDWORD(buf, self.Value5)
-        buf = CommFunc.WriteDWORD(buf, self.Value6)
-        buf = CommFunc.WriteDWORD(buf, self.Value7)
-        buf = CommFunc.WriteDWORD(buf, self.Value8)
-        buf = CommFunc.WriteWORD(buf, self.UserDataLen)
-        buf = CommFunc.WriteString(buf, self.UserDataLen, self.UserData)
-        return buf
-
-    def getLength(self):
-        length = 0
-        length += sizeof(ctypes.c_ushort)
-        length += sizeof(ctypes.c_ulong)
-        length += sizeof(ctypes.c_double)
-        length += sizeof(ctypes.c_ulong)
-        length += sizeof(ctypes.c_ulong)
-        length += sizeof(ctypes.c_ulong)
-        length += sizeof(ctypes.c_ulong)
-        length += sizeof(ctypes.c_ulong)
-        length += sizeof(ctypes.c_ulong)
-        length += sizeof(ctypes.c_ulong)
-        length += sizeof(ctypes.c_ulong)
-        length += sizeof(ctypes.c_ushort)
-        length += self.UserDataLen
-        return length
-
-    def getRecord(self):
-        '''组织存储记录'''
-        rec = {}
-        rec[u'RecType'] = self.RecType
-        rec[u'RecID'] = self.RecID
-        rec[u'Time'] = self.Time
-        rec[u'Value1'] = self.Value1
-        rec[u'Value2'] = self.Value2
-        rec[u'Value3'] = self.Value3
-        rec[u'Value4'] = self.Value4
-        rec[u'Value5'] = self.Value5
-        rec[u'Value6'] = self.Value6
-        rec[u'Value7'] = self.Value7
-        rec[u'Value8'] = self.Value8
-        rec[u'UserDataLen'] = self.UserDataLen
-        rec[u'UserData'] = fix_incomingText(self.UserData)
-        return rec
-
-    def readRecord(self, rec):
-        '''由于MongoDB读出来是unicode,所有字符串需要进行转换'''
-        self.RecType = rec.get(u'RecType', 0)
-        self.RecID = rec.get(u'RecID', 0)
-        self.Time = rec.get(u'Time', 0)
-        self.Value1 = rec.get(u'Value1', 0)
-        self.Value2 = rec.get(u'Value2', 0)
-        self.Value3 = rec.get(u'Value3', 0)
-        self.Value4 = rec.get(u'Value4', 0)
-        self.Value5 = rec.get(u'Value5', 0)
-        self.Value6 = rec.get(u'Value6', 0)
-        self.Value7 = rec.get(u'Value7', 0)
-        self.Value8 = rec.get(u'Value8', 0)
-        self.UserDataLen = rec.get(u'UserDataLen', 0)
-        self.UserData = fix_outgoingText(rec.get(u'UserData', u''))
-
-#Can not implement adoLoadStr method:No key defined!
-#Can not implement adoInsertStr method:No key defined!
-#Can not implement adoUpdateStr method:No key defined!
-#Can not implement adoUpdateStr method:No key defined!
-#Can not implement adoCheckUpdateStr method:No key defined!
-#Can not implement adoCheckUpdateExStr method:No key defined!
-
-    def getAdoRecords(self, resultCollection):
-        '''查询结果打包成二进制流'''
-        result = ''
-        result = CommFunc.WriteDWORD(result, resultCollection.count())
-        for rec in resultCollection:
-            self.readRecord(rec)
-            result += self.getBuffer()
-        return result
-
-#Can not implement adoQueryIndexStr method:No key defined!
-
-    def adoQueryCustom(self, collection, queryDict):
-        '''自定义查询'''
-        resultCollection = collection.find(queryDict)
-
-        return self.getAdoRecords(resultCollection)
-
-
-    def adoQueryAll(self, collection):
-        '''查询所有''' 
-        resultCollection = collection.find()
-         
-        return self.getAdoRecords(resultCollection)
-
-#Can not implement adoDeleteByIndexStr method:No key defined!
-    def outputString(self):
-        output = '''// 通用记录表新 #tagDBGameRec:
-            RecType = %s,
-            RecID = %s,
-            Time = %s,
-            Value1 = %s,
-            Value2 = %s,
-            Value3 = %s,
-            Value4 = %s,
-            Value5 = %s,
-            Value6 = %s,
-            Value7 = %s,
-            Value8 = %s,
-            UserDataLen = %s,
-            UserData = %s,
-            ADOResult = %s,
-            '''%(
-                self.RecType,
-                self.RecID,
-                self.Time,
-                self.Value1,
-                self.Value2,
-                self.Value3,
-                self.Value4,
-                self.Value5,
-                self.Value6,
-                self.Value7,
-                self.Value8,
-                self.UserDataLen,
-                self.UserData,
-                self.ADOResult,
-            )
-        return output
-
-    def dumpString(self):
-        output = '''%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s'''%(
-                self.RecType,
-                self.RecID,
-                self.Time,
-                self.Value1,
-                self.Value2,
-                self.Value3,
-                self.Value4,
-                self.Value5,
-                self.Value6,
-                self.Value7,
-                self.Value8,
-                self.UserDataLen,
-                self.UserData,
-            )
-        return output
 
 
 # 功能队伍表 #tagDBFuncTeam
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/ProjSpecialProcess.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/ProjSpecialProcess.py
index 066fc38..bfa759a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/ProjSpecialProcess.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/ProjSpecialProcess.py
@@ -325,7 +325,9 @@
             elif isinstance(ret, tuple):
                 execType = ret[0]
                 execInfo = ret[1]
-                
+        else:
+            execType = GMCommon.Def_GMCmdNone
+            
         GetGMOrderMgr().PopCmd(self.orderId)
         GMCommandResult(self.orderId, self.funcName, execType, execInfo)
         
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index cf177ef..57cc487 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -62,8 +62,15 @@
 #支持超20亿数值的数值点单位数值, 1亿
 Def_PerPointValue = 100000000
 
-#真实玩家ID、仙盟ID是从100000开始
-#假玩家ID
+#真实玩家ID、仙盟ID是从 1000000 开始
+RealPlayerIDStart = 1000000
+RealFamilyIDStart = 1000000
+
+#机器人ID - 供功能用,线上版本支持的机器人
+RobotIDStart = 10001
+RobotIDMax = 19999
+
+#假玩家ID - 供内部功能测试用,一般线上版本没有,仅内部功能开发、测试用
 FackPlayerIDStart = 1
 FackPlayerIDMax = 9999
 
@@ -466,7 +473,8 @@
 #此地方改动需要通知修改ChConfig.Def_BT_Cnt, ChConfig.Def_BT_SaveType
 BillboardTypeList = (
 Def_BT_MainLevel,    # 主线关卡过关榜 0
-) = range(0, 1) 
+Def_BT_Arena,    # 演武场积分周榜 1
+) = range(0, 2) 
 
 ''' 跨服排行榜类型, 从 150 开始,最大条数在功能配置表 CrossBillboardSet 配置,没配默认100
 与本服榜单存储的是不一样的数据库表格,理论上类型可以和本服榜单类型重复,为了做下区分防误导,跨服榜单从 150 开始
@@ -479,11 +487,10 @@
 
 BillboardTypeAllList = BillboardTypeList + CrossBillboardTypeList
 
+BillboardNameDict = {Def_BT_MainLevel:"主线过关榜", Def_BT_Arena:"演武场积分周榜"}
+
 #仙盟榜单类型
 FamilyBillboardList = []
-
-#排行榜Value1存储境界信息的榜单列表
-BTValue1_OfficialRankList = [Def_BT_MainLevel]
 
 ##---比率---
 #百分率
@@ -727,7 +734,8 @@
 CDBPlayerRefresh_DOTPer, # 持续增伤 283
 CDBPlayerRefresh_DOTPerDef, # 持续减伤 284
 CDBPlayerRefresh_GoldRushEnergy, # 淘金令 285
-) = range(146, 286)
+CDBPlayerRefresh_ArenaTicket, # 挑战券 286
+) = range(146, 287)
 
 TYPE_Price_Gold_Paper_Money = 5    # 金钱类型,(先用礼券,再用金子)
 TYPE_Price_Family_Contribution = 6 # 战盟贡献度(活跃度转换得来)
@@ -768,12 +776,13 @@
 TYPE_Price_HuanjinggeScore = 50    # 幻境阁积分
 TYPE_Price_HeroScore = 51    # 招募积分
 TYPE_Price_GoldRushEnergy = 52    # 淘金令体力
+TYPE_Price_ArenaTicket = 53    # 演武场挑战券
 TYPE_Price_PayCoinDay = 98    # 代币时效,每日过天重置
 TYPE_Price_PayCoin = 99    # 代币
 
 #key可用于遍历所有货币,value仅GM相关会用到
 MoneyNameDict = {
-                 1:"金币", 41:"战锤", 42:"将星玉髓", 51:"招募积分", 52:"淘金令",
+                 1:"金币", 41:"战锤", 42:"将星玉髓", 51:"招募积分", 52:"淘金令", 53:"挑战券",
                  98:"代币时效", 99:"代币"
                  }
 #MoneyNameDict = {
@@ -787,11 +796,6 @@
 
 #需要记录累计消耗的货币类型
 UseTotalPriceTypeList = [TYPE_Price_TiandaoFruit]
-
-#以下是旧的金钱类型
-TYPE_Price_Magic_Integral = 101      # 魔方寻宝积分
-TYPE_Price_GongXun = 105    # 功勋点
-TYPE_Price_ArrestPoint = 110    # 悬赏积分
 
 # 自定义积分及通知字典 {货币类型:通知客户端刷新类型, ...} , 如果不通知的话刷新类型则配置 None
 TYPE_Price_CurrencyDict = {
@@ -825,6 +829,7 @@
                            TYPE_Price_HuanjinggeScore:CDBPlayerRefresh_HuanjinggeScore,
                            TYPE_Price_HeroScore:CDBPlayerRefresh_HeroScore,
                            TYPE_Price_GoldRushEnergy:CDBPlayerRefresh_GoldRushEnergy,
+                           TYPE_Price_ArenaTicket:CDBPlayerRefresh_ArenaTicket,
                            TYPE_Price_PayCoinDay:CDBPlayerRefresh_PayCoinDay,
                            }
 
@@ -927,11 +932,14 @@
                        Def_GameRecType_FamilyGCZCityWall, # 仙盟攻城战城池信息, zoneID 305
                        Def_GameRecType_TalkCache, # 聊天缓存,频道 306
                        Def_GameRecType_PlayerOfflineUnprocessed, # 离线玩家待处理事件,playerID 307
-                       ) = range(300, 1 + 307)
+                       Def_GameRecType_ArenaRecord, # 演武场玩家挑战记录,playerID 308
+                       ) = range(300, 1 + 308)
 #通用信息记录新 - 字典key配置,如果有配置,则可额外按对应记录Value值存储字典,方便快速取值,可配置Value编号 1~8,配空默认 Value1
 Def_GameRecValueKeyDict = {
                            Def_GameRecType_Xiangong:[1],
                            }
+#仅查看自己的记录
+Def_ViewGameRecSelfList = [Def_GameRecType_ArenaRecord]
 
 #通用信息记录类型
 Def_UniversalGameRecTypeList = (
@@ -1326,9 +1334,9 @@
 
 # 阵容定义
 LineupList = (
-Lineup_Main, # 主阵容
-Lineup_Arena, # 竞技场进攻阵容
-Lineup_ArenaDef, # 竞技场防守阵容
+Lineup_Main, # 主阵容 1
+Lineup_Arena, # 竞技场进攻阵容 2
+Lineup_ArenaDef, # 竞技场防守阵容 3
 ) = range(1, 1 + 3)
 
 # 宠物物品数据状态

--
Gitblit v1.8.0