From 19956b8576f2c2c68c4c4d811acbc3e2af3d97b4 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 30 九月 2025 19:25:46 +0800
Subject: [PATCH] 165 【挑战】天子的考验-服务端

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFB.py                             |    8 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py                      |   32 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                                 |    5 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                             |  231 ++-----------------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py                           |   43 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerArena.py                          |    1 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Tianzi.py   |  300 +++++++++++++++++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Zhanchui.py |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py                            |   10 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                               |   41 +++
 PySysDB/PySysDBPY.h                                                                                                |   19 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py                   |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                                    |    9 
 13 files changed, 478 insertions(+), 227 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index f89fdb0..0e8beea 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -1228,9 +1228,9 @@
 
 };
 
-//副本功能线路表
+//副本表
 
-struct tagFBLine
+struct FBLine
 {
 	DWORD		_DataMapID;	//数据地图ID
 	BYTE		_LineID;	//功能线路ID
@@ -1238,6 +1238,21 @@
 	list		PassAwardList;	//过关奖励
 	list		SweepAwardList;	//扫荡奖励
 	list		LineupIDList;	//阵容ID列表
+	WORD		NPCLV;	//NPC等级
+	float		Difficulty;	//难度系数
+};
+
+//天子考验
+
+struct Tianzi
+{
+	DWORD		_BossID;
+	BYTE		HPNum;
+	DWORD		Atk;
+	DWORD		Def;
+	DWORD		MaxHP;
+	dict		OtherAttrDict;	//其他属性 {attrID:attrValue, ...}
+	list		RandWeightItemList;	//宝箱随机物品权重列表,[[权重,物品ID,数量], ...]
 };
 
 //广告奖励表
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py
index df3016b..5437571 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py
@@ -806,13 +806,14 @@
         ## 回合重置
         self._skillTurnUseCntDict = {}
         
-    def UpdInitBatAttr(self, initAttrDict, skillIDList):
+    def UpdInitBatAttr(self, initAttrDict, skillIDList=None):
         ## 更新战斗属性,一般只有主阵容需要更新,战斗中养成、装备变化等引起的主阵容属性变更时需要实时更新
         self._initAttrDict = initAttrDict
         learnNewSkill = False
-        for skillID in skillIDList:
-            if self._skillMgr.LearnSkillByID(skillID):
-                learnNewSkill = True
+        if skillIDList:
+            for skillID in skillIDList:
+                if self._skillMgr.LearnSkillByID(skillID):
+                    learnNewSkill = True
         TurnBuff.RefreshBuffAttr(self)
         if learnNewSkill: # 有学新技能时重刷技能被动
             self._passiveEffMgr.RefreshSkillPassiveEffect()
@@ -1014,6 +1015,7 @@
         ## 统计承伤
         self.defStat += lostHP
         return self.defStat
+    def GetStatDefValue(self): return self.defStat # 获取累计总承伤
     
     def StatCureValue(self, cureValue):
         ## 统计治疗
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 8491e7f..f6db1f1 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -74,6 +74,7 @@
         self.lingshouObjIDDict = {} # 灵兽战斗单位 {位置编号:batObjID, ...}
         self.beautyObjIDDict = {} # 红颜战斗单位 {位置编号:batObjID, ...}
         self.actionNum = ActionNumStart # 行动位置,从1开始
+        self.totalHurt = 0 # 阵容总输出
         return
     
     def getPlayerID(self): return self.turnFight.playerID # 发起的玩家ID
@@ -103,6 +104,7 @@
         self.lingshouObjIDDict = {}
         self.beautyObjIDDict = {}
         self.fightPower = 0
+        self.totalHurt = 0
         return
     
 class BatFaction():
@@ -112,6 +114,7 @@
         self.turnFight = turnFight # TurnFight
         self.faction = faction
         self.lineupDict = {} # 该阵营所有阵容信息 {编号:BatLineup, ...}
+        self.totalHurt = 0 # 阵营总输出
         return
     
     def getBatlineup(self, num=1):
@@ -123,6 +126,8 @@
             lineup = BatLineup(self.faction, num, self.turnFight)
             self.lineupDict[num] = lineup
         return lineup
+    
+    def getTotalHurt(self): return self.totalHurt # 阵营总输出
     
     def clearLineups(self):
         ## 清除所有战斗阵容
@@ -156,6 +161,7 @@
         self.batBuffer = "" # 战报buffer,战报暂时只保留最后一个小队的
         self.isNeedReport = isNeedReport # 是否需要战报
         self.msgDict = {} # 扩展信息字典,一般由MapID绑定的功能决定信息内容  {k:v, ...}
+        self._kvDict = {} # 自定义信息字典,不会被重置  {k:v, ...}
         
         self.factionDict = {} # 战斗阵营 {faction:BatFaction, ...},一般是只有两个阵营,faction为1或2,每个阵营支持多个阵容
         self.actionSortList = [] # 阵容行动顺序 [[faction, num], ...]
@@ -185,6 +191,7 @@
         self.setPVE()
         self.setPVP()
         self.msgDict = {}
+        self._kvDict = {}
         self.nextTurnFight(msgDict)
         return
     
@@ -199,6 +206,13 @@
         self.tagPlayerID = tagPlayerID
         self.tagViewCache = tagViewCache
         return
+    
+    def isFBMap(self):
+        ## 是否副本地图中,非主线的均视为副本
+        return self.mapID not in [ChConfig.Def_FBMapID_Main, ChConfig.Def_FBMapID_MainBoss]
+    
+    def GetDictByKey(self, key): return self._kvDict.get(key, 0)
+    def SetDict(self, key, value): self._kvDict[key] = value
     
     #def setPVPTeam(self):
     #    return
@@ -382,6 +396,11 @@
             clientPack.FactionList.append(tfFaction)
         clientPack.FactionCnt = len(clientPack.FactionList)
         self.addBatPack(clientPack)
+        return
+    
+    def syncHelp(self, msgDict):
+        ## 通知帮助信息,一般是副本用
+        self.syncState(self.state, msgDict)
         return
     
     def syncState(self, state, msgDict={}):
@@ -733,7 +752,8 @@
         if not curPlayer:
             return
         
-    tfGUID = batLineup.turnFight.guid
+    turnFight = batLineup.turnFight
+    tfGUID = turnFight.guid
     lineupPlayerID = lineupInfo.get("PlayerID", 0) # 阵容所属玩家ID
     heroDict = lineupInfo.get("Hero", {})
     
@@ -801,6 +821,12 @@
             
         batLineup.posObjIDDict[posNum] = objID
         GameWorld.DebugLog("AddBatObj %s,skill=%s" % (GetObjName(batObj), skillManager.GetSkillIDList()))
+        if npcID:
+            #副本指定NPC属性
+            fbNPCInitAttrDict = FBLogic.GetFBNPCInitAttr(curPlayer, turnFight, batObj)
+            if fbNPCInitAttrDict:
+                GameWorld.DebugLog("副本指定NPC初始化属性: npcID=%s, %s" % (npcID, fbNPCInitAttrDict))
+                attrDict = {str(k):v for k, v in fbNPCInitAttrDict.items()} # 统一格式
         batObj.InitBatAttr({int(k):v for k, v in attrDict.items()}, initXP)
         
     return
@@ -890,6 +916,8 @@
         npcLineupIDList, strongerLV, difficulty = [], 0, 0
         if fbLineIpyData:
             npcLineupIDList = fbLineIpyData.GetLineupIDList()
+            strongerLV = fbLineIpyData.GetNPCLV()
+            difficulty = fbLineIpyData.GetDifficulty()
             
         if not npcLineupIDList:
             ret = FBLogic.GetFBNPCLineupInfo(curPlayer, mapID, funcLineID)
@@ -1599,6 +1627,14 @@
     return True
 
 def SetObjKilled(turnFight, gameObj, killer=None, useSkill=None):
+    curPlayer = turnFight.curPlayer
+    npcID = gameObj.GetNPCID()
+    
+    # 非主线的PVE目标怪物
+    if npcID and curPlayer and turnFight.isFBMap() and gameObj.GetFaction() != ChConfig.Def_FactionA:
+        if not FBLogic.OnFBNPCKilledBefore(curPlayer, turnFight, gameObj, killer):
+            return
+        
     objID = gameObj.GetID()
     killerObjID = killer.GetID() if killer else 0
     skillID = useSkill.GetSkillID() if useSkill else 0
@@ -1611,7 +1647,6 @@
     clientPack.SkillID = skillID
     turnFight.addBatPack(clientPack)
     
-    curPlayer = turnFight.curPlayer
     # 暂时只算主线小怪
     if curPlayer and turnFight.mapID == ChConfig.Def_FBMapID_Main and gameObj.GetFaction() != ChConfig.Def_FactionA:
         PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_KillNPC, 1)    
@@ -1657,11 +1692,13 @@
             statInfo[str(faction)] = {}
         facStatInfo = statInfo[str(faction)]
         batFaction = turnFight.getBatFaction(faction)
+        batFaction.totalHurt = 0
         for num in batFaction.lineupDict.keys():
             if str(num) not in facStatInfo:
                 facStatInfo[str(num)] = {}
             lineupStatInfo = facStatInfo[str(num)]
             batLineup = batFaction.getBatlineup(num)
+            batLineup.totalHurt = 0
             GameWorld.DebugLog("阵容明细: faction=%s,num=%s" % (faction, num))
             for posNum, objID in batLineup.posObjIDDict.items():
                 batObj = batObjMgr.getBatObj(objID)
@@ -1673,6 +1710,8 @@
                 atkHurt = batObj.hurtStat
                 defHurt = batObj.defStat
                 cureHP = batObj.cureStat
+                batLineup.totalHurt += atkHurt
+                batFaction.totalHurt += atkHurt
                 GameWorld.DebugLog("    Pos:%s ID=%s,npcID=%s,heroID=%s,HP=%s/%s, 输出=%s,承伤=%s,治疗=%s" 
                                    % (posNum, objID, npcID, heroID, batObj.GetHP(), batObj.GetMaxHP(), atkHurt, defHurt, cureHP))
                 lineupStatInfo[str(posNum)] = {"ObjID":objID, "HeroID":heroID, "NPCID":npcID, "AtkHurt":atkHurt, "DefHurt":defHurt, "CureHP":cureHP}
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 7480422..62f5172 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -1916,9 +1916,11 @@
 Def_FBMapID_Tianzi = 30020 # 天子考验
 
 #线路未过关时免费的地图
-UnPassFreeMapIDList = [Def_FBMapID_ArenaBattle]
+UnPassFreeMapIDList = [Def_FBMapID_Zhanchui]
 #按星级记录过关的地图
 PassByStarMapIDList = []
+#扫荡不需要检查是否已过关的地图
+SweepUnCheckPassMapIDList = [Def_FBMapID_Tianzi]
 
 #注册上传跨服服务器数据后直接进入跨服服务器的地图
 RegisterEnter_CrossServerMapIDList = []
@@ -4010,6 +4012,11 @@
 Def_PDict_UnXiantaoCntBooty = "UnXiantaoCntBooty_%s" # 累计未结算战利品掉落的战锤数,参数(itemID)
 Def_PDict_BootyDropToday = "BootyDropToday_%s" # 今日已累计掉落战利品数量,参数(itemID)
 
+#天子考验
+Def_PDict_TianziHisHurt = "TianziHisHurt_%s" # 历史最高伤害,求余亿部分,参数(bossID)
+Def_PDict_TianziHisHurtEx = "TianziHisHurtEx_%s" # 历史最高伤害,整除亿部分,参数(bossID)
+Def_PDict_TianziTodayHurt = "TianziTodayHurt" # 今日最高伤害,求余亿部分
+Def_PDict_TianziTodayHurtEx = "TianziTodayHurtEx" # 今日最高伤害,整除亿部分
 #-------------------------------------------------------------------------------
 
 #物品效果(ID或指定类型)对应的属性计算信息 {效果(ID/指定类型):[[属性索引, ...], 是否基础属性,(非)线性]}
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index dafb1ce..c32e6bf 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -38643,135 +38643,18 @@
 
 
 #------------------------------------------------------
-# B2 08 获得仙缘币信息 #tagMCAddXianyuanCoinMsg
+# B2 01 天子考验信息 #tagSCTianziKYInfo
 
-class  tagMCAddXianyuanCoinMsg(Structure):
-    Head = tagHead()
-    MapID = 0    #(DWORD MapID)
-    FuncLineID = 0    #(BYTE FuncLineID)
-    Relation = 0    #(BYTE Relation)// 当时的关系:0-无,1-好友,2-盟友
-    RelationCoinAdd = 0    #(BYTE RelationCoinAdd)// 社交关系总加成
-    XianyuanCoinAdd = 0    #(WORD XianyuanCoinAdd)// 实际增加的仙缘币
-    Reason = 0    #(BYTE Reason)//仙缘币为0时的原因:1-助战次数上限;2-每日获得上限
-    CallPlayerID = 0    #(DWORD CallPlayerID)// 助战的玩家ID,有值时代表真实助战,没有值时为自己打的
-    NameLen = 0    #(BYTE NameLen)
-    CallPlayerName = ""    #(String CallPlayerName)// 助战的玩家名,size = NameLen
-    IsSweep = 0    #(BYTE IsSweep)// 是否扫荡
-    data = None
-
-    def __init__(self):
-        self.Clear()
-        self.Head.Cmd = 0xB2
-        self.Head.SubCmd = 0x08
-        return
-
-    def ReadData(self, _lpData, _pos=0, _Len=0):
-        self.Clear()
-        _pos = self.Head.ReadData(_lpData, _pos)
-        self.MapID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.FuncLineID,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.Relation,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.RelationCoinAdd,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.XianyuanCoinAdd,_pos = CommFunc.ReadWORD(_lpData, _pos)
-        self.Reason,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.CallPlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.NameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.CallPlayerName,_pos = CommFunc.ReadString(_lpData, _pos,self.NameLen)
-        self.IsSweep,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        return _pos
-
-    def Clear(self):
-        self.Head = tagHead()
-        self.Head.Clear()
-        self.Head.Cmd = 0xB2
-        self.Head.SubCmd = 0x08
-        self.MapID = 0
-        self.FuncLineID = 0
-        self.Relation = 0
-        self.RelationCoinAdd = 0
-        self.XianyuanCoinAdd = 0
-        self.Reason = 0
-        self.CallPlayerID = 0
-        self.NameLen = 0
-        self.CallPlayerName = ""
-        self.IsSweep = 0
-        return
-
-    def GetLength(self):
-        length = 0
-        length += self.Head.GetLength()
-        length += 4
-        length += 1
-        length += 1
-        length += 1
-        length += 2
-        length += 1
-        length += 4
-        length += 1
-        length += len(self.CallPlayerName)
-        length += 1
-
-        return length
-
-    def GetBuffer(self):
-        data = ''
-        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
-        data = CommFunc.WriteDWORD(data, self.MapID)
-        data = CommFunc.WriteBYTE(data, self.FuncLineID)
-        data = CommFunc.WriteBYTE(data, self.Relation)
-        data = CommFunc.WriteBYTE(data, self.RelationCoinAdd)
-        data = CommFunc.WriteWORD(data, self.XianyuanCoinAdd)
-        data = CommFunc.WriteBYTE(data, self.Reason)
-        data = CommFunc.WriteDWORD(data, self.CallPlayerID)
-        data = CommFunc.WriteBYTE(data, self.NameLen)
-        data = CommFunc.WriteString(data, self.NameLen, self.CallPlayerName)
-        data = CommFunc.WriteBYTE(data, self.IsSweep)
-        return data
-
-    def OutputString(self):
-        DumpString = '''
-                                Head:%s,
-                                MapID:%d,
-                                FuncLineID:%d,
-                                Relation:%d,
-                                RelationCoinAdd:%d,
-                                XianyuanCoinAdd:%d,
-                                Reason:%d,
-                                CallPlayerID:%d,
-                                NameLen:%d,
-                                CallPlayerName:%s,
-                                IsSweep:%d
-                                '''\
-                                %(
-                                self.Head.OutputString(),
-                                self.MapID,
-                                self.FuncLineID,
-                                self.Relation,
-                                self.RelationCoinAdd,
-                                self.XianyuanCoinAdd,
-                                self.Reason,
-                                self.CallPlayerID,
-                                self.NameLen,
-                                self.CallPlayerName,
-                                self.IsSweep
-                                )
-        return DumpString
-
-
-m_NAtagMCAddXianyuanCoinMsg=tagMCAddXianyuanCoinMsg()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCAddXianyuanCoinMsg.Head.Cmd,m_NAtagMCAddXianyuanCoinMsg.Head.SubCmd))] = m_NAtagMCAddXianyuanCoinMsg
-
-
-#------------------------------------------------------
-# B2 01 通知封魔坛双倍击杀状态 #tagMCFMTDoubleState
-
-class  tagMCFMTDoubleState(Structure):
+class  tagSCTianziKYInfo(Structure):
     _pack_ = 1
     _fields_ = [
                   ("Cmd", c_ubyte),
                   ("SubCmd", c_ubyte),
-                  ("IsDouble", c_ubyte),    #是否双倍
-                  ("OldDouble", c_ubyte),    #是否曾经允许双倍
+                  ("LineID", c_ubyte),    #今日是哪个lineID,对应副本表的功能线路ID
+                  ("HistoryHurt", c_int),    #本考验历史最大伤害,求余亿部分
+                  ("HistoryHurtEx", c_int),    #本考验历史最大伤害,整除亿部分
+                  ("TodayHurt", c_int),    #本考验今日最大伤害,求余亿部分
+                  ("TodayHurtEx", c_int),    #本考验今日最大伤害,整除亿部分
                   ]
 
     def __init__(self):
@@ -38788,105 +38671,43 @@
     def Clear(self):
         self.Cmd = 0xB2
         self.SubCmd = 0x01
-        self.IsDouble = 0
-        self.OldDouble = 0
+        self.LineID = 0
+        self.HistoryHurt = 0
+        self.HistoryHurtEx = 0
+        self.TodayHurt = 0
+        self.TodayHurtEx = 0
         return
 
     def GetLength(self):
-        return sizeof(tagMCFMTDoubleState)
+        return sizeof(tagSCTianziKYInfo)
 
     def GetBuffer(self):
         return string_at(addressof(self), self.GetLength())
 
     def OutputString(self):
-        DumpString = '''// B2 01 通知封魔坛双倍击杀状态 //tagMCFMTDoubleState:
+        DumpString = '''// B2 01 天子考验信息 //tagSCTianziKYInfo:
                                 Cmd:%s,
                                 SubCmd:%s,
-                                IsDouble:%d,
-                                OldDouble:%d
+                                LineID:%d,
+                                HistoryHurt:%d,
+                                HistoryHurtEx:%d,
+                                TodayHurt:%d,
+                                TodayHurtEx:%d
                                 '''\
                                 %(
                                 self.Cmd,
                                 self.SubCmd,
-                                self.IsDouble,
-                                self.OldDouble
+                                self.LineID,
+                                self.HistoryHurt,
+                                self.HistoryHurtEx,
+                                self.TodayHurt,
+                                self.TodayHurtEx
                                 )
         return DumpString
 
 
-m_NAtagMCFMTDoubleState=tagMCFMTDoubleState()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFMTDoubleState.Cmd,m_NAtagMCFMTDoubleState.SubCmd))] = m_NAtagMCFMTDoubleState
-
-
-#------------------------------------------------------
-#B2 02 推送提醒设置通知 #tagMCPushNotificationsSetting
-
-class  tagMCPushNotificationsSetting(Structure):
-    Head = tagHead()
-    OnoffBit = 0    #(DWORD OnoffBit)// 按位约定开关
-    TimeLen = 0    #(BYTE TimeLen)
-    TimeStr = ""    #(String TimeStr)// 时间字符串  01:02-05:00
-    data = None
-
-    def __init__(self):
-        self.Clear()
-        self.Head.Cmd = 0xB2
-        self.Head.SubCmd = 0x02
-        return
-
-    def ReadData(self, _lpData, _pos=0, _Len=0):
-        self.Clear()
-        _pos = self.Head.ReadData(_lpData, _pos)
-        self.OnoffBit,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.TimeLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
-        self.TimeStr,_pos = CommFunc.ReadString(_lpData, _pos,self.TimeLen)
-        return _pos
-
-    def Clear(self):
-        self.Head = tagHead()
-        self.Head.Clear()
-        self.Head.Cmd = 0xB2
-        self.Head.SubCmd = 0x02
-        self.OnoffBit = 0
-        self.TimeLen = 0
-        self.TimeStr = ""
-        return
-
-    def GetLength(self):
-        length = 0
-        length += self.Head.GetLength()
-        length += 4
-        length += 1
-        length += len(self.TimeStr)
-
-        return length
-
-    def GetBuffer(self):
-        data = ''
-        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
-        data = CommFunc.WriteDWORD(data, self.OnoffBit)
-        data = CommFunc.WriteBYTE(data, self.TimeLen)
-        data = CommFunc.WriteString(data, self.TimeLen, self.TimeStr)
-        return data
-
-    def OutputString(self):
-        DumpString = '''
-                                Head:%s,
-                                OnoffBit:%d,
-                                TimeLen:%d,
-                                TimeStr:%s
-                                '''\
-                                %(
-                                self.Head.OutputString(),
-                                self.OnoffBit,
-                                self.TimeLen,
-                                self.TimeStr
-                                )
-        return DumpString
-
-
-m_NAtagMCPushNotificationsSetting=tagMCPushNotificationsSetting()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCPushNotificationsSetting.Head.Cmd,m_NAtagMCPushNotificationsSetting.Head.SubCmd))] = m_NAtagMCPushNotificationsSetting
+m_NAtagSCTianziKYInfo=tagSCTianziKYInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCTianziKYInfo.Cmd,m_NAtagSCTianziKYInfo.SubCmd))] = m_NAtagSCTianziKYInfo
 
 
 #------------------------------------------------------
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py
index a993db4..322f90c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py
@@ -1523,8 +1523,10 @@
     
     return callFunc(curPlayer, addExp, expViewType)
 
-## 副本扫荡询问
 def OnPlayerFBSweepAsk(curPlayer, mapID, lineID, cnt, dataEx):
+    ## 副本扫荡询问
+    # @return: None - 不可扫荡
+    # @return: 非None - 可以扫荡,且返回值直接传给 OnPlayerFBSweepResult
     do_FBLogic_ID = __GetFBLogic_MapID(mapID)
     
     callFunc = GameWorld.GetExecFunc(FBProcess, "GameLogic_%s.%s" % (do_FBLogic_ID, "OnPlayerFBSweepAsk"))
@@ -1534,8 +1536,8 @@
 
     return callFunc(curPlayer, mapID, lineID, cnt, dataEx)
 
-## 副本扫荡结果
-def OnPlayerFBSweepResult(curPlayer, mapID, lineID, cnt, dataEx):
+def OnPlayerFBSweepResult(curPlayer, mapID, lineID, cnt, dataEx, askRet):
+    ## 副本扫荡结果
     do_FBLogic_ID = __GetFBLogic_MapID(mapID)
     
     callFunc = GameWorld.GetExecFunc(FBProcess, "GameLogic_%s.%s" % (do_FBLogic_ID, "OnPlayerFBSweepResult"))
@@ -1543,7 +1545,7 @@
     if callFunc == None:
         return False
 
-    return callFunc(curPlayer, mapID, lineID, cnt, dataEx)
+    return callFunc(curPlayer, mapID, lineID, cnt, dataEx, askRet)
 
 ## 开始公共CD副本扫荡
 def OnStartPubCDFBSweep(curPlayer, mapID, lineID, cnt, dataEx):
@@ -2279,6 +2281,28 @@
     
     return callFunc(curPlayer, mapID, funcLineID)
 
+def GetFBNPCInitAttr(curPlayer, turnFight, npcObj):
+    ## 获取副本指定NPC初始化属性
+    do_FBLogic_ID = __GetFBLogic_MapID(turnFight.mapID)
+    
+    callFunc = GameWorld.GetExecFunc(FBProcess, "GameLogic_%s.%s" % (do_FBLogic_ID, "GetFBNPCInitAttr"))
+    if callFunc == None:
+        return
+    
+    return callFunc(curPlayer, turnFight, npcObj)
+
+def OnFBNPCKilledBefore(curPlayer, turnFight, gameObj, killer):
+    ## 副本NPC被击杀前处理,一般用于处理一些不被击杀的副本NPC逻辑
+    # @return: 可否被正常击杀
+    do_FBLogic_ID = __GetFBLogic_MapID(turnFight.mapID)
+    
+    callFunc = GameWorld.GetExecFunc(FBProcess, "GameLogic_%s.%s" % (do_FBLogic_ID, "OnFBNPCKilledBefore"))
+    if callFunc == None:
+        # 不需要逻辑时默认可被正常击杀
+        return True
+    
+    return callFunc(curPlayer, turnFight, gameObj, killer)
+
 def OnPlayerLineupAttackResult(curPlayer, atkObj, killObjList, useSkill, mapID, funcLineID):
     ## 回合战斗主动发起的玩家阵容攻击结果额外处理 ,一般处理副本相关的掉落、奖励等
     do_FBLogic_ID = __GetFBLogic_MapID(mapID)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Tianzi.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Tianzi.py
new file mode 100644
index 0000000..c419aac
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Tianzi.py
@@ -0,0 +1,300 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GameWorldLogic.FBProcess.GameLogic_Tianzi
+#
+# @todo:天子考验
+# @author hxp
+# @date 2025-09-30
+# @version 1.0
+#
+# 详细描述: 天子考验
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-09-30 19:30"""
+#-------------------------------------------------------------------------------
+
+import ChConfig
+import FBCommon
+import GameWorld
+import ItemControler
+import PlayerControl
+import PlayerBillboard
+import ChPyNetSendPack
+import NetPackCommon
+import IpyGameDataPY
+import ShareDefine
+import PlayerMail
+import DBDataMgr
+import ObjPool
+
+def OnDay():
+    ## 结算昨日奖励
+    __DoGiveTianziDayAward()
+    return
+
+def OnFBPlayerOnDay(curPlayer):
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TianziTodayHurt, 0)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TianziTodayHurtEx, 0)
+    SyncTianziInfo(curPlayer)
+    return
+
+def OnFBPlayerOnLogin(curPlayer):
+    SyncTianziInfo(curPlayer)
+    return
+
+def GetTianziTodayInfo(curPlayer):
+    ## 获取今日天子考验信息
+    # @return: lineID, bossID
+    
+    lineList = []
+    for lineID in range(10):
+        ipyData = IpyGameDataPY.GetIpyGameDataNotLog("FBLine", ChConfig.Def_FBMapID_Tianzi, lineID)
+        if ipyData:
+            lineList.append(ipyData)
+        elif lineID > 0:
+            break
+    if not lineList:
+        return 0, 0
+    
+    ServerDay = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_ServerDay)
+    todayIpyData = lineList[ServerDay % len(lineList)]
+    lineID = todayIpyData.GetLineID()
+    bossID = 0
+    for lineupID in todayIpyData.GetLineupIDList():
+        lineupIpyData = IpyGameDataPY.GetIpyGameData("NPCLineup", lineupID)
+        if not lineupIpyData:
+            continue
+        bossID = lineupIpyData.GetBossID()
+        if bossID:
+            break
+        
+    return lineID, bossID
+
+def OnTurnFightRequest(curPlayer, mapID, funcLineID, tagType, tagID, valueList):
+    ## 回合战斗请求 
+    
+    lineID, bossID = GetTianziTodayInfo(curPlayer)
+    if funcLineID != lineID:
+        GameWorld.DebugLog("非今日天子考验! mapID=%s,funcLineID=%s != %s,bossID=%s" % (mapID, funcLineID, lineID, bossID))
+        return
+    
+    return True
+
+def GetFBNPCInitAttr(curPlayer, turnFight, npcObj):
+    ## 获取副本指定NPC初始化属性
+    bossID = npcObj.GetNPCID()
+    ipyDataList = IpyGameDataPY.GetIpyGameDataList("Tianzi", bossID)
+    if not ipyDataList:
+        return {}
+    return __getBossAttrDict(ipyDataList[0])
+
+def OnFBNPCKilledBefore(curPlayer, turnFight, gameObj, killer):
+    ## 副本NPC被击杀前处理,一般用于处理一些不被击杀的副本NPC逻辑
+    # @return: 可否被正常击杀
+    
+    # 本副本不可被击杀,直到所有血条抵扣完
+    bossID = gameObj.GetNPCID()
+    ipyDataList = IpyGameDataPY.GetIpyGameDataList("Tianzi", bossID)
+    if not ipyDataList:
+        return True
+    
+    statDefValueTotal = gameObj.GetStatDefValue() # 当前总承伤
+    hpNum = 1
+    totalHPMax = 0
+    ipyDataNow = None
+    for ipyData in ipyDataList:
+        hpNum = ipyData.GetHPNum()
+        maxHP = ipyData.GetMaxHP()
+        ipyDataNow = ipyData
+        totalHPMax += maxHP
+        if statDefValueTotal < totalHPMax:
+            break
+        
+    if not ipyDataNow:
+        return True
+    
+    hp = max(0, totalHPMax - statDefValueTotal)
+    if hp <= 0:
+        GameWorld.Log("天子考验全部血条被击杀! totalHPMax=%s,statDefValueTotal=%s" % (totalHPMax, statDefValueTotal))
+        return True
+    
+    gameObj.SetMaxHP(ipyDataNow.GetMaxHP(), True)
+    gameObj.SetHP(hp, True)
+    GameWorld.DebugLog("更新NPC血条: hpNum=%s,hp=%s/%s, statDefValueTotal=%s" % (hpNum, gameObj.GetHP(), gameObj.GetMaxHP(), statDefValueTotal))
+    turnFight.SetDict("hpNum", hpNum)
+    turnFight.syncHelp({"hpNum":hpNum})
+    gameObj.UpdInitBatAttr(__getBossAttrDict(ipyDataNow))
+    return False
+
+def __getBossAttrDict(ipyData):
+    attrDict = {ChConfig.AttrID_Atk:ipyData.GetAtk(),
+                ChConfig.AttrID_Def:ipyData.GetDef(),
+                ChConfig.AttrID_MaxHP:ipyData.GetMaxHP(),
+                }
+    attrDict.update(ipyData.GetOtherAttrDict())
+    return attrDict
+
+def OnTurnFightOver(curPlayer, turnFight, mapID, funcLineID, overMsg):
+    ## 回合战斗结束
+    
+    if not curPlayer:
+        return
+    
+    #isWin = turnFight.isWin
+    lineID, bossID = GetTianziTodayInfo(curPlayer)
+    if lineID != funcLineID:
+        GameWorld.ErrLog("结算时非今日天子考验! mapID=%s,funcLineID=%s != %s,bossID=%s" % (mapID, funcLineID, lineID, bossID))
+        return
+    
+    hpNum = turnFight.GetDictByKey("hpNum")
+    batFaction = turnFight.getBatFaction(ChConfig.Def_FactionA)
+    totalHurt = batFaction.getTotalHurt()
+    
+    historyHurt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TianziHisHurt % bossID)
+    historyHurtEx = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TianziHisHurtEx % bossID)
+    historyHurtTotal = historyHurtEx * ChConfig.Def_PerPointValue + historyHurt
+    todayHurt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TianziTodayHurt)
+    todayHurtEx = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TianziTodayHurtEx)
+    todayHurtTotal = todayHurtEx * ChConfig.Def_PerPointValue + todayHurt
+    
+    GameWorld.DebugLog("天子考验结算: lineID=%s,bossID=%s,hpNum=%s,totalHurt=%s,todayHurtTotal=%s,historyHurtTotal=%s" 
+                       % (lineID, bossID, hpNum, totalHurt, todayHurtTotal, historyHurtTotal))
+    if totalHurt > historyHurtTotal:
+        historyHurtTotal = totalHurt
+        historyHurt = historyHurtTotal % ChConfig.Def_PerPointValue
+        historyHurtEx = historyHurtTotal / ChConfig.Def_PerPointValue
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TianziHisHurt % bossID, historyHurt)
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TianziHisHurtEx % bossID, historyHurtEx)
+        GameWorld.DebugLog("更新历史最高伤害: %s" % historyHurtTotal)
+        
+    if totalHurt > todayHurtTotal:
+        todayHurtTotal = totalHurt
+        todayHurt = todayHurtTotal % ChConfig.Def_PerPointValue
+        todayHurtEx = todayHurtTotal / ChConfig.Def_PerPointValue
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TianziTodayHurt, todayHurt)
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TianziTodayHurtEx, todayHurtEx)
+        GameWorld.DebugLog("更新今日最高伤害: %s" % todayHurtTotal)
+        #更新榜单
+        PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_Tianzi, todayHurtEx, todayHurt)
+        
+    itemList = __getTianziAwardList(todayHurt, bossID)
+    FBCommon.AddEnterFBCount(curPlayer, mapID)
+    ItemControler.GivePlayerItemOrMail(curPlayer, itemList, event=["Tianzi", False, {}], isNotifyAward=False)
+    overMsg.update({FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(itemList), "totalHurt":totalHurt, "todayHurtTotal":todayHurtTotal})
+    SyncTianziInfo(curPlayer, lineID, bossID)
+    return
+
+def __getTianziAwardList(todayHurt, bossID, sweepCnt=1):
+    ## 获取结算奖励
+    GameWorld.DebugLog("天子考验结算奖励: hurtValue=%s,bossID=%s" % (todayHurt, bossID))
+    ipyDataList = IpyGameDataPY.GetIpyGameDataList("Tianzi", bossID)
+    if not ipyDataList:
+        return []
+    awardDict = {}
+    totalHPMax = 0
+    for ipyData in ipyDataList:
+        hpNum = ipyData.GetHPNum()
+        maxHP = ipyData.GetMaxHP()
+        totalHPMax += maxHP
+        if todayHurt < totalHPMax:
+            break
+        randWeightItemList = ipyData.GetRandWeightItemList()
+        randItemInfo = GameWorld.GetResultByWeightList(randWeightItemList)
+        if not randItemInfo or len(randItemInfo) < 2:
+            continue
+        itemID = randItemInfo[0]
+        itemCount = randItemInfo[1]
+        awardDict[itemID] = awardDict.get(itemID, 0) + itemCount * sweepCnt
+        GameWorld.DebugLog("血条编号: %s,itemID=%s,itemID=%s,%s" % (hpNum, itemID, itemCount, awardDict))
+        
+    itemList = [[itemID, itemCount] for itemID, itemCount in awardDict.items()]
+    GameWorld.DebugLog("最终奖励: %s" % itemList)
+    return itemList
+
+def OnPlayerFBSweepAsk(curPlayer, mapID, lineID, sweepCnt, dataEx):
+    ## 可否扫荡
+    
+    _, bossID = GetTianziTodayInfo(curPlayer)
+    todayHurt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TianziTodayHurt)
+    todayHurtEx = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TianziTodayHurtEx)
+    todayHurtTotal = todayHurtEx * ChConfig.Def_PerPointValue + todayHurt
+    
+    if not bossID or not todayHurtTotal:
+        GameWorld.DebugLog("天子考验今日还没有伤害无法扫荡!")
+        return
+    
+    return bossID, todayHurtTotal
+
+def OnPlayerFBSweepResult(curPlayer, mapID, lineID, sweepCnt, dataEx, askRet):
+    ## 扫荡结果,次数消耗已在外层处理扣除
+    
+    bossID, todayHurtTotal = askRet
+    GameWorld.DebugLog("天子考验扫荡: mapID=%s,lineID=%s,sweepCnt=%s,todayHurtTotal=%s,bossID=%s" 
+                       % (mapID, lineID, sweepCnt, todayHurtTotal, bossID))
+    itemList = __getTianziAwardList(todayHurtTotal, bossID, sweepCnt)
+    ItemControler.GivePlayerItemOrMail(curPlayer, itemList, event=["Tianzi", False, {}], isNotifyAward=False)
+    
+    isPass = 1
+    overDict = {FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(itemList), FBCommon.Over_isSweep:1, 
+                "totalHurt":todayHurtTotal, "todayHurtTotal":todayHurtTotal}
+    FBCommon.NotifyFBOver(curPlayer, mapID, lineID, isPass, overDict)
+    return True
+
+def SyncTianziInfo(curPlayer, lineID=None, bossID=None):
+    if lineID == None:
+        lineID, bossID = GetTianziTodayInfo(curPlayer)
+    clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCTianziKYInfo)
+    clientPack.LineID = lineID
+    clientPack.HistoryHurt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TianziHisHurt % bossID)
+    clientPack.HistoryHurtEx = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TianziHisHurtEx % bossID)
+    clientPack.TodayHurt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TianziTodayHurt)
+    clientPack.TodayHurtEx = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TianziTodayHurtEx)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def __DoGiveTianziDayAward():    
+    GameWorld.Log("=== 天子考验结算排行奖励! ===")
+    
+    billboardMgr = DBDataMgr.GetBillboardMgr()
+    billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Tianzi)
+    if not billBoard:
+        return
+    billBoard.SortDelayDo()
+    
+    billboradAwardDict = IpyGameDataPY.GetFuncEvalCfg("TianziBillboradAward", 1, {})
+    
+    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("TianziBillboardAward", playerID, awardList, paramList)
+        
+    GameWorld.Log("    奖励玩家名次信息: %s" % orderPlayerIDDict)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Zhanchui.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Zhanchui.py
index 151f780..d64b5af 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Zhanchui.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Zhanchui.py
@@ -57,7 +57,7 @@
     
     return True
 
-def OnPlayerFBSweepResult(curPlayer, mapID, lineID, sweepCnt, dataEx):
+def OnPlayerFBSweepResult(curPlayer, mapID, lineID, sweepCnt, dataEx, askRet):
     ## 扫荡结果,次数消耗已在外层处理扣除
     
     itemList = FBCommon.GetSweepAwardList(mapID, lineID, sweepCnt)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index 77feefe..6ccfe53 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -1009,6 +1009,18 @@
                         ("list", "PassAwardList", 0),
                         ("list", "SweepAwardList", 0),
                         ("list", "LineupIDList", 0),
+                        ("WORD", "NPCLV", 0),
+                        ("float", "Difficulty", 0),
+                        ),
+
+                "Tianzi":(
+                        ("DWORD", "BossID", 1),
+                        ("BYTE", "HPNum", 0),
+                        ("DWORD", "Atk", 0),
+                        ("DWORD", "Def", 0),
+                        ("DWORD", "MaxHP", 0),
+                        ("dict", "OtherAttrDict", 0),
+                        ("list", "RandWeightItemList", 0),
                         ),
 
                 "ADAward":(
@@ -3971,7 +3983,7 @@
     def GetPayMoneyType(self): return self.attrTuple[3] # 消耗货币类型 BYTE
     def GetPayMoneyValues(self): return self.attrTuple[4] # 消耗货币值列表 list
 
-# 副本功能线路表
+# 副本表
 class IPY_FBLine():
     
     def __init__(self):
@@ -3983,7 +3995,24 @@
     def GetLVLimitMin(self): return self.attrTuple[2] # 最低等级限制, 0为不限制 WORD
     def GetPassAwardList(self): return self.attrTuple[3] # 过关奖励 list
     def GetSweepAwardList(self): return self.attrTuple[4] # 扫荡奖励 list
-    def GetLineupIDList(self): return self.attrTuple[5] # 阵容ID列表 list
+    def GetLineupIDList(self): return self.attrTuple[5] # 阵容ID列表 list
+    def GetNPCLV(self): return self.attrTuple[6] # NPC等级 WORD
+    def GetDifficulty(self): return self.attrTuple[7] # 难度系数 float
+
+# 天子考验
+class IPY_Tianzi():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetBossID(self): return self.attrTuple[0] # DWORD
+    def GetHPNum(self): return self.attrTuple[1] # BYTE
+    def GetAtk(self): return self.attrTuple[2] # DWORD
+    def GetDef(self): return self.attrTuple[3] # DWORD
+    def GetMaxHP(self): return self.attrTuple[4] # DWORD
+    def GetOtherAttrDict(self): return self.attrTuple[5] # 其他属性 {attrID:attrValue, ...} dict
+    def GetRandWeightItemList(self): return self.attrTuple[6] # 宝箱随机物品权重列表,[[权重,物品ID,数量], ...] list
 
 # 广告奖励表
 class IPY_ADAward():
@@ -6498,6 +6527,7 @@
         self.__LoadFileData("ChinMap", onlyCheck)
         self.__LoadFileData("FBFunc", onlyCheck)
         self.__LoadFileData("FBLine", onlyCheck)
+        self.__LoadFileData("Tianzi", onlyCheck)
         self.__LoadFileData("ADAward", onlyCheck)
         self.__LoadFileData("FBGeneralTrain", onlyCheck)
         self.__LoadFileData("DailyAction", onlyCheck)
@@ -7526,6 +7556,13 @@
         self.CheckLoadData("FBLine")
         return self.ipyFBLineCache[index]
 
+    def GetTianziCount(self):
+        self.CheckLoadData("Tianzi")
+        return self.ipyTianziLen
+    def GetTianziByIndex(self, index):
+        self.CheckLoadData("Tianzi")
+        return self.ipyTianziCache[index]
+
     def GetADAwardCount(self):
         self.CheckLoadData("ADAward")
         return self.ipyADAwardLen
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 5db30f2..4033b07 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerArena.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerArena.py
@@ -94,6 +94,7 @@
     else:
         return
     
+    billBoard.SortDelayDo()
     orderList = [int(orderStr) for orderStr in billboradAwardDict.keys()]
     orderList.sort()
     GameWorld.Log("    奖励名次列表: %s" % orderList)
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 bc2b1ed..279e30b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -38,6 +38,7 @@
 import PlayerSuccess
 import PlayerFreeGoods
 import ChItem
+import GameLogic_Tianzi
 import PlayerGoldInvest
 import PlayerCrossRealmPK
 import PlayerCrossChampionship
@@ -110,11 +111,12 @@
 def DoLogic_OnDay(tick):
     GameWorld.Log("MapServer -> OnDay!")
     #副本OnDay事件响应
-    FBLogic.OnDay(tick)
+    #FBLogic.OnDay(tick)
     
     #仙盟
     PlayerFamily.FamilyOnDay()
     PlayerArena.OnDay()
+    GameLogic_Tianzi.OnDay()
     
     PlayerOfflineSupport.OnDay()
     playerManager = GameWorld.GetPlayerManager()
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFB.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFB.py
index fce4034..71ebe8c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFB.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFB.py
@@ -30,6 +30,7 @@
 import IpyGameDataPY
 import ShareDefine
 import NPCCommon
+import ChConfig
 
 #---------------------------------------------------------------------
 def OnLogin(curPlayer):
@@ -74,7 +75,7 @@
         GameWorld.DebugLog("不存在该副本或线路无法扫荡!mapID=%s, lineID=%s" % (mapID, lineID))
         return
     
-    if not FBCommon.IsFBPass(curPlayer, mapID, lineID):
+    if mapID not in ChConfig.SweepUnCheckPassMapIDList and not FBCommon.IsFBPass(curPlayer, mapID, lineID):
         GameWorld.DebugLog("未过关无法扫荡!mapID=%s, lineID=%s" % (mapID, lineID))
         return
     
@@ -82,7 +83,8 @@
         return
     
     # 副本是否可扫荡, 这里只判断副本自身的特殊条件, 公共条件上面已经判断
-    if not FBLogic.OnPlayerFBSweepAsk(curPlayer, mapID, lineID, cnt, dataEx):
+    askRet = FBLogic.OnPlayerFBSweepAsk(curPlayer, mapID, lineID, cnt, dataEx)
+    if not askRet:
         GameWorld.DebugLog("该副本当前无法扫荡!mapID=%s, lineID=%s" % (mapID, lineID))
         return
     
@@ -96,7 +98,7 @@
         FBCommon.AddEnterFBCount(curPlayer, mapID, cnt)
         
     #扫荡结果给奖励等
-    FBLogic.OnPlayerFBSweepResult(curPlayer, mapID, lineID, cnt, dataEx)
+    FBLogic.OnPlayerFBSweepResult(curPlayer, mapID, lineID, cnt, dataEx, askRet)
     return
 
 #// B1 08 快速一键过关副本 #tagCMFBQuickPass
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index 64df0b4..187a20a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -474,7 +474,8 @@
 BillboardTypeList = (
 Def_BT_MainLevel,    # 主线关卡过关榜 0
 Def_BT_Arena,    # 演武场积分周榜 1
-) = range(0, 2) 
+Def_BT_Tianzi,    # 天子考验伤害榜 2
+) = range(0, 3) 
 
 ''' 跨服排行榜类型, 从 150 开始,最大条数在功能配置表 CrossBillboardSet 配置,没配默认100
 与本服榜单存储的是不一样的数据库表格,理论上类型可以和本服榜单类型重复,为了做下区分防误导,跨服榜单从 150 开始
@@ -487,7 +488,7 @@
 
 BillboardTypeAllList = BillboardTypeList + CrossBillboardTypeList
 
-BillboardNameDict = {Def_BT_MainLevel:"主线过关榜", Def_BT_Arena:"演武场积分周榜"}
+BillboardNameDict = {Def_BT_MainLevel:"主线过关榜", Def_BT_Arena:"演武场积分周榜", Def_BT_Tianzi:"天子考验伤害榜"}
 
 #仙盟榜单类型
 FamilyBillboardList = []

--
Gitblit v1.8.0