From 34520d2b2a4ac78f832169b7ea120651b7f43c26 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 06 一月 2026 13:02:05 +0800
Subject: [PATCH] 412 【挑战】定军阁-服务端(效果属性暂时无效;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFB.py                              |   22 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py                       |   14 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini                                          |   16 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                                  |    5 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py                                  |  134 ++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                              |  167 ++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                                |   85 ++++
 PySysDB/PySysDBPY.h                                                                                                 |   29 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Dingjunge.py                        |   77 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py                            |    9 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Dingjunge.py |  582 +++++++++++++++++++++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                                     |   15 
 12 files changed, 1,129 insertions(+), 26 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 802b26e..6e63716 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -1171,6 +1171,35 @@
 	list		RandWeightItemList;	//宝箱随机物品权重列表,[[权重,物品ID,数量], ...]
 };
 
+//定军阁关卡表
+struct	FBDJGLevel
+{
+	WORD		_LayerNum;	//层数
+	BYTE		_LevelNum;	//关卡编号
+	list		PassAwardList;	// 过关奖励列表,[[物品ID,个数], ...]
+	list		AwardList;	// 挑战奖励,[[物品ID,个数], ...]
+	list		LineupIDList;	// 阵容ID列表,小队1阵容ID|小队2阵容ID|...
+	WORD		NPCLV;	//NPC等级
+	float		Difficulty;	//难度系数
+};
+
+//定军阁速战奖励表
+struct	FBDJGQuick
+{
+	WORD		_NeedLayer;	//所需层数
+	list		QuickAwardList;	// 速战奖励列表,[[物品ID,个数], ...]
+};
+
+//定军阁效果表
+struct	FBDJGEffect
+{
+	DWORD		_EffID;	//效果ID
+	BYTE		EffQuality;	// 效果品质
+	BYTE		AttrID;	// 属性ID
+	DWORD		AttrValue;	// 属性值
+	DWORD		RandWeight;	// 随机权重
+};
+
 //广告奖励表
 
 struct ADAward
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index 29922f9..8419b3a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -1183,6 +1183,22 @@
 PacketSubCMD_1=0x15
 PacketCallFunc_1=OnMainDropItemOP
 
+;定军阁
+[GameLogic_Dingjunge]
+ScriptName = GameWorldLogic\FBProcess\GameLogic_Dingjunge.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 2
+
+PacketCMD_1=0xB1
+PacketSubCMD_1=0x01
+PacketCallFunc_1=OnDingjungeEffSet
+
+PacketCMD_2=0xB1
+PacketSubCMD_2=0x02
+PacketCallFunc_2=OnDingjungeEffSelect
+
 ;回合攻击
 [TurnAttack]
 ScriptName = Attack\TurnAttack.py
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 3a0d9a0..8b292e4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -1087,13 +1087,14 @@
     if not reqRet:
         return
     funcLineID = reqRet[1] if len(reqRet) > 1 else funcLineID
+    GameWorld.DebugLogEx("    funcLineID=%s", funcLineID, playerID)
     
     fbIpyData = FBCommon.GetFBIpyData(mapID)
     fbLineIpyData = FBCommon.GetFBLineIpyData(mapID, funcLineID, False)
     if fbIpyData:
-        if not fbLineIpyData:
-            GameWorld.DebugLogEx("不存在该副本功能线路! mapID=%s,funcLineID=%s", mapID, funcLineID)
-            return
+        #if not fbLineIpyData:
+        #    GameWorld.DebugLogEx("不存在该副本功能线路! mapID=%s,funcLineID=%s", mapID, funcLineID)
+        #    return
         if FBCommon.CheckCanEnterFBComm(curPlayer, mapID, funcLineID, fbIpyData, fbLineIpyData) != ShareDefine.EntFBAskRet_OK:
             return
         
@@ -1277,7 +1278,7 @@
     
     for index, lineupID in enumerate(npcLineupIDList):
         turnFight.lineupIndex = index
-        GameWorld.DebugLogEx("对战NPC阵容: index=%s, lineupID=%s", index, lineupID)
+        GameWorld.DebugLogEx("对战NPC阵容: mapID=%s,funcLineID=%s,index=%s,lineupID=%s", mapID, funcLineID, index, lineupID)
         if index > 0:
             turnFight.nextTurnFight()
         turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID, strongerLV, difficulty)})
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 133bd9d..0e906ee 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -1897,9 +1897,10 @@
 
 Def_FBMapID_Zhanchui = 30010 # 白骨盈野/战锤秘境
 Def_FBMapID_Tianzi = 30020 # 天子考验
+Def_FBMapID_Dingjunge = 30030 # 定军阁
 
 #线路未过关时免费的地图
-UnPassFreeMapIDList = [Def_FBMapID_Zhanchui]
+UnPassFreeMapIDList = [Def_FBMapID_Zhanchui, Def_FBMapID_Dingjunge]
 #按星级记录过关的地图
 PassByStarMapIDList = []
 #扫荡不需要检查是否已过关的地图
@@ -1907,7 +1908,7 @@
 #固定玩家获胜的地图
 PlayerWinMapIDList = [Def_FBMapID_Tianzi]
 #需要汇报中心副本过关进度的地图
-ReportCenterMapIDList = [Def_FBMapID_Zhanchui]
+ReportCenterMapIDList = [Def_FBMapID_Zhanchui, Def_FBMapID_Dingjunge]
 
 #注册上传跨服服务器数据后直接进入跨服服务器的地图
 RegisterEnter_CrossServerMapIDList = []
@@ -1981,6 +1982,7 @@
                 'Arena':[Def_FBMapID_ArenaBattle],
                 'Zhanchui':[Def_FBMapID_Zhanchui],
                 'Tianzi':[Def_FBMapID_Tianzi],
+                'Dingjunge':[Def_FBMapID_Dingjunge],
                 }
 
 #特殊副本ID, 由系统分配, 进入时候不验证IsMapCopyFull
@@ -3885,6 +3887,15 @@
 Def_PDict_TianziHisHurtEx = "TianziHisHurtEx_%s" # 历史最高伤害,整除亿部分,参数(bossID)
 Def_PDict_TianziTodayHurt = "TianziTodayHurt" # 今日最高伤害,求余亿部分
 Def_PDict_TianziTodayHurtEx = "TianziTodayHurtEx" # 今日最高伤害,整除亿部分
+
+#定军阁
+Def_PDict_DJGLineID = "DJGLineID"  # 今日已过关的线路ID 层 * 100 + 关卡编号
+Def_PDict_DJGEffect = "DJGEff_%s"  # 已生效的加成效果,参数(index)  effID * 100 + 效果等级
+Def_PDict_DJGSelectEffect = "DJGSelectEff_%s"  # 当前待选择的加成效果,参数(index) effID
+Def_PDict_DJGUnSelectCnt = "DJGUnSelectCnt"  # 还有几个未选择的效果
+Def_PDict_DJGEffAuto = "DJGEffAuto"  # 是否自动选择效果
+Def_PDict_DJGEffSet = "DJGEffSet_%s"  # 预设优先选择属性ID,参数(优先index)
+
 #-------------------------------------------------------------------------------
 
 #物品效果(ID或指定类型)对应的属性计算信息 {效果(ID/指定类型):[[属性索引, ...], 是否基础属性,(非)线性]}
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index 664f69a..4aacc12 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -10984,6 +10984,140 @@
 
 
 #------------------------------------------------------
+# B1 02 定军阁效果选择 #tagCSDingjungeEffSelect
+
+class  tagCSDingjungeEffSelect(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("SelectType", c_ubyte),    #0-手动选择,1-放弃本次选择,2-一键选择(仅开启了自动选择时有效)
+                  ("SelectIndex", c_ubyte),    #手动选择索引 0~n
+                  ("ReplaceHole", c_ubyte),    #手动选择替换槽位 1~n,槽位=槽索引+1,升级时可直接发0
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB1
+        self.SubCmd = 0x02
+        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 = 0xB1
+        self.SubCmd = 0x02
+        self.SelectType = 0
+        self.SelectIndex = 0
+        self.ReplaceHole = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCSDingjungeEffSelect)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B1 02 定军阁效果选择 //tagCSDingjungeEffSelect:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                SelectType:%d,
+                                SelectIndex:%d,
+                                ReplaceHole:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.SelectType,
+                                self.SelectIndex,
+                                self.ReplaceHole
+                                )
+        return DumpString
+
+
+m_NAtagCSDingjungeEffSelect=tagCSDingjungeEffSelect()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSDingjungeEffSelect.Cmd,m_NAtagCSDingjungeEffSelect.SubCmd))] = m_NAtagCSDingjungeEffSelect
+
+
+#------------------------------------------------------
+# B1 01 定军阁效果预设 #tagCSDingjungeEffSet
+
+class  tagCSDingjungeEffSet(Structure):
+    Head = tagHead()
+    SelectAuto = 0    #(BYTE SelectAuto)//是否启用自动选择
+    SelectSetCnt = 0    #(BYTE SelectSetCnt)
+    SelectSetAttrIDList = list()    #(vector<WORD> SelectSetAttrIDList)//预设优先选择属性ID列表 [优先级1属性ID, ...]
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x01
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.SelectAuto,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.SelectSetCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.SelectSetCnt):
+            value,_pos=CommFunc.ReadWORD(_lpData,_pos)
+            self.SelectSetAttrIDList.append(value)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x01
+        self.SelectAuto = 0
+        self.SelectSetCnt = 0
+        self.SelectSetAttrIDList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        length += 2 * self.SelectSetCnt
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.SelectAuto)
+        data = CommFunc.WriteBYTE(data, self.SelectSetCnt)
+        for i in range(self.SelectSetCnt):
+            data = CommFunc.WriteWORD(data, self.SelectSetAttrIDList[i])
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                SelectAuto:%d,
+                                SelectSetCnt:%d,
+                                SelectSetAttrIDList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.SelectAuto,
+                                self.SelectSetCnt,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagCSDingjungeEffSet=tagCSDingjungeEffSet()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSDingjungeEffSet.Head.Cmd,m_NAtagCSDingjungeEffSet.Head.SubCmd))] = m_NAtagCSDingjungeEffSet
+
+
+#------------------------------------------------------
 # B1 08 快速一键过关副本 #tagCMFBQuickPass
 
 class  tagCMFBQuickPass(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index b7fb943..edb273c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -33232,6 +33232,173 @@
 
 
 #------------------------------------------------------
+# B2 02 定军阁信息 #tagSCDingjungeInfo
+
+class  tagSCDingjungeEff(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("EffIndex", c_ubyte),    #槽索引,0~n
+                  ("EffID", c_ushort),    
+                  ("EffLV", c_ubyte),    
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        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.EffIndex = 0
+        self.EffID = 0
+        self.EffLV = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagSCDingjungeEff)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 02 定军阁信息 //tagSCDingjungeInfo:
+                                EffIndex:%d,
+                                EffID:%d,
+                                EffLV:%d
+                                '''\
+                                %(
+                                self.EffIndex,
+                                self.EffID,
+                                self.EffLV
+                                )
+        return DumpString
+
+
+class  tagSCDingjungeInfo(Structure):
+    Head = tagHead()
+    TodayPass = 0    #(DWORD TodayPass)//今日过关进度 层*100+关卡编号,历史最高过关记录取A320中的PassLineID
+    EffCnt = 0    #(BYTE EffCnt)
+    EffList = list()    #(vector<tagSCDingjungeEff> EffList)//已生效的效果列表
+    SelectEffCnt = 0    #(BYTE SelectEffCnt)
+    SelectEffList = list()    #(vector<DWORD> SelectEffList)//待手动选择的效果ID列表
+    UnSelectCnt = 0    #(WORD UnSelectCnt)//还有几个未选择的效果
+    SelectAuto = 0    #(BYTE SelectAuto)//是否启用自动选择
+    SelectSetCnt = 0    #(BYTE SelectSetCnt)
+    SelectSetAttrIDList = list()    #(vector<WORD> SelectSetAttrIDList)//预设优先选择属性ID列表 [优先级1属性ID, ...]
+    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.TodayPass,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.EffCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.EffCnt):
+            temEffList = tagSCDingjungeEff()
+            _pos = temEffList.ReadData(_lpData, _pos)
+            self.EffList.append(temEffList)
+        self.SelectEffCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.SelectEffCnt):
+            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+            self.SelectEffList.append(value)
+        self.UnSelectCnt,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.SelectAuto,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.SelectSetCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.SelectSetCnt):
+            value,_pos=CommFunc.ReadWORD(_lpData,_pos)
+            self.SelectSetAttrIDList.append(value)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB2
+        self.Head.SubCmd = 0x02
+        self.TodayPass = 0
+        self.EffCnt = 0
+        self.EffList = list()
+        self.SelectEffCnt = 0
+        self.SelectEffList = list()
+        self.UnSelectCnt = 0
+        self.SelectAuto = 0
+        self.SelectSetCnt = 0
+        self.SelectSetAttrIDList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 4
+        length += 1
+        for i in range(self.EffCnt):
+            length += self.EffList[i].GetLength()
+        length += 1
+        length += 4 * self.SelectEffCnt
+        length += 2
+        length += 1
+        length += 1
+        length += 2 * self.SelectSetCnt
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteDWORD(data, self.TodayPass)
+        data = CommFunc.WriteBYTE(data, self.EffCnt)
+        for i in range(self.EffCnt):
+            data = CommFunc.WriteString(data, self.EffList[i].GetLength(), self.EffList[i].GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.SelectEffCnt)
+        for i in range(self.SelectEffCnt):
+            data = CommFunc.WriteDWORD(data, self.SelectEffList[i])
+        data = CommFunc.WriteWORD(data, self.UnSelectCnt)
+        data = CommFunc.WriteBYTE(data, self.SelectAuto)
+        data = CommFunc.WriteBYTE(data, self.SelectSetCnt)
+        for i in range(self.SelectSetCnt):
+            data = CommFunc.WriteWORD(data, self.SelectSetAttrIDList[i])
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                TodayPass:%d,
+                                EffCnt:%d,
+                                EffList:%s,
+                                SelectEffCnt:%d,
+                                SelectEffList:%s,
+                                UnSelectCnt:%d,
+                                SelectAuto:%d,
+                                SelectSetCnt:%d,
+                                SelectSetAttrIDList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.TodayPass,
+                                self.EffCnt,
+                                "...",
+                                self.SelectEffCnt,
+                                "...",
+                                self.UnSelectCnt,
+                                self.SelectAuto,
+                                self.SelectSetCnt,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagSCDingjungeInfo=tagSCDingjungeInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCDingjungeInfo.Head.Cmd,m_NAtagSCDingjungeInfo.Head.SubCmd))] = m_NAtagSCDingjungeInfo
+
+
+#------------------------------------------------------
 # B2 01 天子考验信息 #tagSCTianziKYInfo
 
 class  tagSCTianziKYInfo(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Dingjunge.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Dingjunge.py
new file mode 100644
index 0000000..41143e0
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Dingjunge.py
@@ -0,0 +1,77 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.Dingjunge
+#
+# @todo:定军阁
+# @author hxp
+# @date 2026-01-06
+# @version 1.0
+#
+# 详细描述: 定军阁
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2026-01-06 13:30"""
+#-------------------------------------------------------------------------------
+
+import FBCommon
+import GameWorld
+import IpyGameDataPY
+import GameLogic_Dingjunge
+import PlayerControl
+import ChConfig
+
+def OnExec(curPlayer, paramList):
+    
+    if not paramList:
+        GameWorld.DebugAnswer(curPlayer, "定军阁进度: Dingjunge 今日关卡ID 历史关卡ID")
+        GameWorld.DebugAnswer(curPlayer, "增加效果数: Dingjunge e 增加效果次数")
+        GameWorld.DebugAnswer(curPlayer, "待选择效果: Dingjunge s 效果ID [效果ID ...]")
+        return
+    mapID = ChConfig.Def_FBMapID_Dingjunge
+    value1 = paramList[0]
+    
+    if value1 == "e":
+        addEffCnt = paramList[1] if len(paramList) > 1 else 1
+        GameLogic_Dingjunge.GivePassLayerEff(curPlayer, addEffCnt)
+    elif value1 == "s":
+        setEffIDList = paramList[1:]
+        sEffIDList = []
+        for sIndex in range(IpyGameDataPY.GetFuncCfg("DingjungeEff", 3)):
+            effID = setEffIDList[sIndex] if len(setEffIDList) > sIndex else 0
+            if effID and not IpyGameDataPY.GetIpyGameDataNotLog("FBDJGEffect", effID):
+                GameWorld.DebugAnswer(curPlayer, "效果ID不存在:%s" % effID)
+                effID = 0
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGSelectEffect % sIndex, effID)
+            sEffIDList.append(effID)
+        GameWorld.DebugAnswer(curPlayer, "待选效果ID:%s" % sEffIDList)
+    else:
+        todayLineID = value1
+        highestLineID = paramList[1] if len(paramList) > 1 else None
+        if not highestLineID:
+            highestLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FBPassLineID % mapID)
+            
+        layerNum, levelNum = todayLineID / 100, todayLineID % 100
+        ipyData = IpyGameDataPY.GetIpyGameDataNotLog("FBDJGLevel", layerNum, levelNum)
+        if not ipyData:
+            GameWorld.DebugAnswer(curPlayer, "不存在该层关卡:%s-%s" % (layerNum, levelNum))
+            return
+        
+        if highestLineID:
+            if todayLineID > highestLineID:
+                highestLineID = todayLineID
+            hLayerNum, hLevelNum = highestLineID / 100, highestLineID % 100
+            if not IpyGameDataPY.GetIpyGameDataNotLog("FBDJGLevel", hLayerNum, hLevelNum):
+                GameWorld.DebugAnswer(curPlayer, "不存在该层关:%s-%s" % (hLayerNum, hLevelNum))
+                return
+            
+            GameWorld.DebugAnswer(curPlayer, "历史最高层关:%s-%s" % (hLayerNum, hLevelNum))
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FBPassLineID % mapID, highestLineID)
+            FBCommon.Sync_FBPlayerFBInfoData(curPlayer, mapID)
+            
+        GameWorld.DebugAnswer(curPlayer, "今日层关:%s-%s" % (layerNum, levelNum))
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGLineID, todayLineID)
+        
+    GameLogic_Dingjunge.SyncDingjungeInfo(curPlayer)
+    return
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 20c26fb..1e4d80c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py
@@ -1549,10 +1549,12 @@
 def OnPlayerFBQuickPass(curPlayer, mapID, lineID):
     '''副本快速过关验证
     @param mapID: 数据地图ID
-    @param lineID: 目标关卡线路ID,可一次性跳多关,由前端发包决定
-    @return: (bossID, quickCnt) 或  None
-    @note: bossID 目标NPCID - 目标关卡所需要挑战的主NPCID,一般是boss,用于验证战力是否满足快速过关
-    @note: quickCnt 本次总共跳过几关 - 默认1
+    @param lineID: 目标关卡线路ID,可一次性跳多关,根据功能由前端发包决定或后端直接决定
+    @return: (lineID, quickCnt, quickFightPower, quickData) 或  None
+    @note: lineID 由后端决定的快速过关到哪,如果前端决定的则直接返回 lineID
+    @note: quickCnt 本次总共跳过几关 
+    @note: quickFightPower 目标阵容战力,用于验证战力是否满足快速过关
+    @note: quickData 扩展数据,功能自定义,传给 OnPlayerFBQuickPassResult
     '''
     do_FBLogic_ID = __GetFBLogic_MapID(mapID)
     
@@ -1564,7 +1566,7 @@
     
     return callFunc(curPlayer, mapID, lineID)
 
-def OnPlayerFBQuickPassResult(curPlayer, mapID, lineID):
+def OnPlayerFBQuickPassResult(curPlayer, mapID, lineID, quickData):
     '''副本快速过关结果
     '''
     do_FBLogic_ID = __GetFBLogic_MapID(mapID)
@@ -1574,7 +1576,7 @@
     if callFunc == None:
         return
 
-    return callFunc(curPlayer, mapID, lineID)
+    return callFunc(curPlayer, mapID, lineID, quickData)
 
 #---------------------------------------------------------------------
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Dingjunge.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Dingjunge.py
new file mode 100644
index 0000000..069562e
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Dingjunge.py
@@ -0,0 +1,582 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GameWorldLogic.FBProcess.GameLogic_Dingjunge
+#
+# @todo:定军阁
+# @author hxp
+# @date 2026-01-06
+# @version 1.0
+#
+# 详细描述: 定军阁
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2026-01-06 13:30"""
+#-------------------------------------------------------------------------------
+
+import FBCommon
+import GameWorld
+import ShareDefine
+import PlayerControl
+import PlayerBillboard
+import ChPyNetSendPack
+import ItemControler
+import IpyGameDataPY
+import NetPackCommon
+import ChConfig
+
+# 自动选择排序优先级索引
+(
+Priority_InSet, # 0
+Priority_EffQuality, # 1
+Priority_SetPriority, # 2
+Priority_EIndex, # 3
+Priority_EffInfo, # 4
+Priority_EffID, # 5
+Priority_AttrID, # 6
+) = range(7)
+
+def OnFBPlayerOnLogin(curPlayer):
+    SyncDingjungeInfo(curPlayer)
+    return
+
+def OnFBPlayerOnDay(curPlayer):
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGLineID, 0)
+    for eIndex in range(len(IpyGameDataPY.GetFuncEvalCfg("DingjungeEff", 1))):
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGEffect % eIndex, 0)
+    for sIndex in range(IpyGameDataPY.GetFuncCfg("DingjungeEff", 3)):
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGSelectEffect % sIndex, 0)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGUnSelectCnt, 0)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGEffAuto, 0) # 每日重置自动开关
+    SyncDingjungeInfo(curPlayer)
+    return
+
+def GetNextIpyData(curPlayer):
+    ## 获取下一关ipyData
+    todayLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGLineID)
+    layerNum, levelNum = todayLineID / 100, todayLineID % 100
+    if not layerNum:
+        ipyData = IpyGameDataPY.GetIpyGameData("FBDJGLevel", 1, 1)
+    elif not levelNum:
+        ipyData = IpyGameDataPY.GetIpyGameData("FBDJGLevel", layerNum, 1)
+    else:
+        nextLayerNum = layerNum
+        nextLevelNum = levelNum + 1 # 下一关
+        ipyData = IpyGameDataPY.GetIpyGameDataNotLog("FBDJGLevel", nextLayerNum, nextLevelNum)
+        if not ipyData:# 没有下一关取下一层
+            nextLayerNum = layerNum + 1
+            nextLevelNum = 1
+            ipyData = IpyGameDataPY.GetIpyGameDataNotLog("FBDJGLevel", nextLayerNum, nextLevelNum)
+    if ipyData:
+        return ipyData
+    GameWorld.DebugLog("已通关或找不到下一关数据! layerNum=%s,levelNum=%s" % (layerNum, levelNum))
+    return
+
+def GetPassLayerMax(curPlayer):
+    ## 获取已通关的最大层级
+    mapID = ChConfig.Def_FBMapID_Dingjunge
+    highestLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FBPassLineID % mapID)
+    hLayerNum, hLevelNum = highestLineID / 100, highestLineID % 100
+    passLayerMax = max(0, hLayerNum - 1) # 默认通关的是上一层
+    # 如果过关记录在本层,且没有下一关了,也算通关了本层
+    if hLayerNum and hLevelNum and not IpyGameDataPY.GetIpyGameDataNotLog("FBDJGLevel", hLayerNum, hLevelNum + 1):
+        passLayerMax = hLayerNum
+    return passLayerMax
+
+def GetQuickStartLayer(curPlayer):
+    ## 获取快速挑战的起始层级
+    # @return: >1-可快速挑战的起始层级
+    passLayerMax = GetPassLayerMax(curPlayer)
+    backLayers = IpyGameDataPY.GetFuncCfg("Dingjunge", 1)
+    quickStartLayer = passLayerMax + 1 - backLayers # 需要+1层
+    if quickStartLayer > 1:
+        return quickStartLayer
+    return 0
+
+def OnTurnFightRequest(curPlayer, mapID, funcLineID, tagType, tagID, valueList):
+    ## 回合战斗请求 
+    highestLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FBPassLineID % mapID)
+    quickStartLayer = GetQuickStartLayer(curPlayer)
+    if quickStartLayer:
+        todayLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGLineID)
+        if not todayLineID:
+            GameWorld.DebugLog("今日还未快速战斗无法手动挑战! highestLineID=%s,quickStartLayer=%s" % (highestLineID, quickStartLayer))
+            return
+    nextIpyData = GetNextIpyData(curPlayer)
+    if not nextIpyData:
+        return
+    layerNum = nextIpyData.GetLayerNum()
+    levelNum = nextIpyData.GetLevelNum()
+    funcLineID = layerNum * 100 + levelNum
+    return True, funcLineID
+
+def GetFBNPCLineupInfo(curPlayer, mapID, funcLineID):
+    ## 获取NPC阵容相关
+    # @return: npcLineupIDList, strongerLV, difficulty
+    
+    layerNum, levelNum = funcLineID / 100, funcLineID % 100
+    ipyData = IpyGameDataPY.GetIpyGameData("FBDJGLevel", layerNum, levelNum)
+    if not ipyData:
+        return
+    
+    npcLineupIDList = ipyData.GetLineupIDList()
+    strongerLV = ipyData.GetNPCLV()
+    difficulty = ipyData.GetDifficulty()
+    
+    return npcLineupIDList, strongerLV, difficulty
+
+def OnTurnFightAward(curPlayer, guid, mapID, funcLineID, winFaction, statMsg, dateStr, reqData, awardDict):
+    ## 回合战斗结算奖励
+    if not curPlayer:
+        return
+    
+    isWin = winFaction == ChConfig.Def_FactionA
+    
+    if not isWin:
+        return
+    
+    todayLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGLineID)
+    GameWorld.DebugLog("定军阁结算: funcLineID=%s,todayLineID=%s" % (funcLineID, todayLineID))
+    if todayLineID >= funcLineID:
+        GameWorld.DebugLog("今日已过关的不重复结算奖励! todayLineID=%s >= %s" % (todayLineID, funcLineID))
+        return
+    
+    layerNum, levelNum = funcLineID / 100, funcLineID % 100
+    ipyData = IpyGameDataPY.GetIpyGameData("FBDJGLevel", layerNum, levelNum)
+    if not ipyData:
+        return
+    
+    awardItemList = []
+    highestLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FBPassLineID % mapID)
+    # 首通
+    if funcLineID > highestLineID:
+        firstPassAwardList = ipyData.GetPassAwardList()
+        awardItemList += firstPassAwardList
+        GameWorld.DebugLog("首次过关: highestLineID=%s,firstPassAwardList=%s" % (highestLineID, firstPassAwardList))
+        FBCommon.SetFBPass(curPlayer, mapID, funcLineID)
+        PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_Dingjunge, funcLineID)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGLineID, funcLineID)
+    
+    awardItemList += ipyData.GetAwardList() # 挑战奖励
+    GameWorld.DebugLog("最终奖励: mapID=%s,layerNum=%s,levelNum=%s,awardItemList=%s" % (mapID, layerNum, levelNum, awardItemList))
+    awardDict.update({FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(awardItemList)})
+    
+    ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["Dingjunge", False, {}], isNotifyAward=False)
+    
+    if not IpyGameDataPY.GetIpyGameDataNotLog("FBDJGLevel", layerNum, levelNum + 1):
+        GameWorld.DebugLog("本层没有下一关了,通关本层!: layerNum=%s,levelNum=%s" % (layerNum, levelNum))
+        GivePassLayerEff(curPlayer, 1)
+        
+    SyncDingjungeInfo(curPlayer)
+    return
+
+def OnPlayerFBQuickPass(curPlayer, mapID, lineID):
+    '''副本快速过关验证
+    @param mapID: 数据地图ID
+    @param lineID: 目标关卡线路ID,可一次性跳多关,根据功能由前端发包决定或后端直接决定
+    @return: (lineID, quickCnt, quickFightPower, quickData) 或  None
+    @note: lineID 由后端决定的快速过关到哪,如果前端决定的则直接返回 lineID
+    @note: quickCnt 本次总共跳过几关 
+    @note: quickFightPower 目标阵容战力,用于验证战力是否满足快速过关
+    @note: quickData 扩展数据,功能自定义,传给 OnPlayerFBQuickPassResult
+    '''
+    
+    todayLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGLineID)
+    if todayLineID:
+        GameWorld.DebugLog("今日已经在手动战斗了,无法快速挑战! todayLineID=%s" % (todayLineID))
+        return
+    
+    highestLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FBPassLineID % mapID)
+    quickStartLayer = GetQuickStartLayer(curPlayer)
+    if not quickStartLayer:
+        GameWorld.DebugLog("还未达到可快速挑战的层级! highestLineID=%s" % (highestLineID))
+        return
+    quickData = [highestLineID, quickStartLayer]
+    quickCnt = 0
+    quickFightPower = 0
+    return lineID, quickCnt, quickFightPower, quickData
+
+def OnPlayerFBQuickPassResult(curPlayer, mapID, lineID, quickData):
+    ## 副本快速过关结果
+    
+    highestLineID, quickStartLayer = quickData
+    playerID = curPlayer.GetPlayerID()
+    passLayerMax = GetPassLayerMax(curPlayer) # 历史最大过关层级
+    todayLineID = quickStartLayer * 100 + 0 # 先设置已过到起始层第0关,前端如果有问题再设置为上一层最后一关
+    GameWorld.DebugLog("定军阁快速战斗: highestLineID=%s,passLayerMax=%s,quickStartLayer=%s,todayLineID=%s" 
+                       % (highestLineID, passLayerMax, quickStartLayer, todayLineID), playerID)
+    
+    # 快速过关奖励按历史最大过关层级领取
+    awardItemDict = {}
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetFBDJGQuickCount()):
+        quickIpyData = ipyDataMgr.GetFBDJGQuickByIndex(index)
+        needLayer = quickIpyData.GetNeedLayer()
+        if needLayer > passLayerMax:
+            break
+        quickItemList = quickIpyData.GetQuickAwardList()
+        for itemInfo in quickItemList:
+            itemID, itemCount = itemInfo[:2]
+            awardItemDict[itemID] = awardItemDict.get(itemID, 0) + itemCount
+    awardItemList = [[itemID, itemCount] for itemID, itemCount in awardItemDict.items()]
+    
+    # 设置起始层关卡
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGLineID, todayLineID)
+    
+    addEffCnt = quickStartLayer - 1 # -1是代表加成效果结算到起始的上一层,每过1层+1次
+    GivePassLayerEff(curPlayer, addEffCnt)
+    SyncDingjungeInfo(curPlayer)
+    
+    ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["Dingjunge", False, {}])
+    return
+
+def GivePassLayerEff(curPlayer, addEffCnt=1):
+    unSelectCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGUnSelectCnt) + addEffCnt
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGUnSelectCnt, unSelectCnt)
+    GameWorld.DebugLog("增加效果加成次数: addEffCnt=%s,unSelectCnt=%s" % (addEffCnt, unSelectCnt))
+    if not __doAutoSelectAll(curPlayer):
+        __randSelectEff(curPlayer)
+    return
+
+#// B1 01 定军阁效果预设 #tagCSDingjungeEffSet
+#
+#struct    tagCSDingjungeEffSet
+#{
+#    tagHead         Head;
+#    BYTE        SelectAuto;    //是否启用自动选择
+#    BYTE        SelectSetCnt;
+#    WORD        SelectSetAttrIDList[SelectSetCnt];    //预设优先选择属性ID列表 [优先级1属性ID, ...]
+#};
+def OnDingjungeEffSet(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    selectAuto = 1 if clientData.SelectAuto else 0
+    selectSetAttrIDList = clientData.SelectSetAttrIDList
+    
+    canSetAttrIDList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetFBDJGEffectCount()):
+        ipyData = ipyDataMgr.GetFBDJGEffectByIndex(index)
+        attrID = ipyData.GetAttrID()
+        if attrID not in canSetAttrIDList:
+            canSetAttrIDList.append(attrID)
+    canSetAttrIDList.sort()
+    
+    GameWorld.DebugLog("效果预设: selectAuto=%s,selectSetAttrIDList=%s,canSetAttrIDList=%s" % (selectAuto, selectSetAttrIDList, canSetAttrIDList))
+    
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGEffAuto, selectAuto)
+    for ssIndex in range(IpyGameDataPY.GetFuncCfg("DingjungeEff", 4)):
+        attrID = selectSetAttrIDList[ssIndex] if len(selectSetAttrIDList) > ssIndex else 0
+        if attrID not in canSetAttrIDList:
+            attrID = 0
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGEffSet % ssIndex, attrID)
+    SyncDingjungeInfo(curPlayer)
+    return
+
+#// B1 02 定军阁效果选择 #tagCSDingjungeEffSelect
+#
+#struct    tagCSDingjungeEffSelect
+#{
+#    tagHead         Head;
+#    BYTE        SelectType;    //0-手动选择,1-放弃本次选择,2-一键选择(仅开启了自动选择时有效)
+#    BYTE        SelectIndex;    //手动选择索引 0~n
+#    BYTE        ReplaceHole;    //手动选择替换槽位 1~n,槽位=槽索引+1,升级时可直接发0
+#};
+def OnDingjungeEffSelect(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    selectType = clientData.SelectType
+    selectIndex = clientData.SelectIndex
+    replaceHole = clientData.ReplaceHole
+    
+    if selectType == 2:
+        __doAutoSelectAll(curPlayer)
+    elif selectType == 1:
+        __randSelectEff(curPlayer, isReset=True)
+    else:
+        if __doSelectEff(curPlayer, selectIndex, replaceHole):
+            __randSelectEff(curPlayer, isReset=True)
+            
+    SyncDingjungeInfo(curPlayer)
+    return
+
+def __doAutoSelectAll(curPlayer):
+    if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGEffAuto):
+        GameWorld.DebugLog("未开启自动选择!")
+        return
+    unSelectCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGUnSelectCnt)
+    
+    selectSetAttrIDList = [] # 效果选择预设
+    for ssIndex in range(IpyGameDataPY.GetFuncCfg("DingjungeEff", 4)):
+        attrID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGEffSet % ssIndex)
+        if attrID:
+            selectSetAttrIDList.append(attrID)
+            
+    effHoleCnt = __getUnlockEffHoleCnt(curPlayer)
+        
+    GameWorld.DebugLog("执行一键选择加成效果: unSelectCnt=%s,effHoleCnt=%s,selectSetAttrIDList=%s" % (unSelectCnt, effHoleCnt, selectSetAttrIDList))
+    
+    randEffCnt = IpyGameDataPY.GetFuncCfg("DingjungeEff", 3)
+    for _ in range(unSelectCnt):
+        effIDList = __randSelectEff(curPlayer, randEffCnt)
+        if not effIDList:
+            break
+        if not __doAutoSelectEff(curPlayer, effIDList, selectSetAttrIDList, effHoleCnt):
+            # 不需要自动选择,直接退出,玩家手动选择
+            break
+        # 自动选择后重置
+        for sIndex in range(randEffCnt):
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGSelectEffect % sIndex, 0)
+    return True
+
+def __getUnlockEffHoleCnt(curPlayer):
+    ## 获取已解锁的效果槽数
+    todayLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGLineID)
+    effHoleNeedLVIDList = IpyGameDataPY.GetFuncEvalCfg("DingjungeEff", 1)
+    effHoleCnt = 0 # 已解锁的效果槽数
+    for needLVID in effHoleNeedLVIDList:
+        if todayLineID >= needLVID:
+            effHoleCnt += 1
+    return effHoleCnt
+
+def __randSelectEff(curPlayer, randEffCnt=0, isReset=False):
+    ## 随机生成待选择加成效果
+    unSelectCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGUnSelectCnt)
+    if unSelectCnt <= 0:
+        GameWorld.DebugLog("没有未处理的加成效果次数了")
+        return
+    if not randEffCnt:
+        randEffCnt = IpyGameDataPY.GetFuncCfg("DingjungeEff", 3)
+    effIDList = []
+    if isReset:
+        # 重置
+        for sIndex in range(randEffCnt):
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGSelectEffect % sIndex, 0)
+    else:
+        for sIndex in range(randEffCnt):
+            effID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGSelectEffect % sIndex)
+            if not effID:
+                break
+            effIDList.append(effID)
+    if effIDList:
+        GameWorld.DebugLog("已存在未选择的加成效果等选择后再生成: effIDList=%s,unSelectCnt=%s" % (effIDList, unSelectCnt))
+        return effIDList
+    
+    fullLVEffIDList = [] # 已满级的效果ID列表
+    effMaxLV = IpyGameDataPY.GetFuncCfg("DingjungeEff", 2)
+    for eIndex in range(len(IpyGameDataPY.GetFuncEvalCfg("DingjungeEff", 1))):
+        effInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGEffect % eIndex)
+        if not effInfo:
+            break
+        effID, effLV = effInfo / 100, effInfo % 100
+        if effLV >= effMaxLV:
+            fullLVEffIDList.append(effID)
+            
+    randWeightList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetFBDJGEffectCount()):
+        ipyData = ipyDataMgr.GetFBDJGEffectByIndex(index)
+        effID = ipyData.GetEffID()
+        if effID in fullLVEffIDList:
+            # 排除满级的
+            continue
+        randWeight = ipyData.GetRandWeight()
+        if randWeight:
+            randWeightList.append([randWeight, effID])
+        
+    # 随机效果,不重复
+    randCnt = 200
+    while len(effIDList) < randEffCnt and randCnt > 0:
+        randCnt -= 1
+        randEffID = GameWorld.GetResultByWeightList(randWeightList)
+        if randEffID not in effIDList:
+            effIDList.append(randEffID)
+            
+    unSelectCnt -= 1
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGUnSelectCnt, unSelectCnt)
+    for sIndex in range(randEffCnt):
+        effID = effIDList[sIndex] if len(effIDList) > sIndex else 0
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGSelectEffect % sIndex, effID)
+    #GameWorld.DebugLog("随机生成加成效果: effIDList=%s,unSelectCnt=%s,fullLVEffIDList=%s" % (effIDList, unSelectCnt, fullLVEffIDList))
+    return effIDList
+
+def __doAutoSelectEff(curPlayer, selectEffIDList, selectSetAttrIDList, effHoleCnt):
+    ## 自动选择加成
+            
+    # 若随机出了多种预设内的的属性,则优先选择品质高的,只出现单种预设内属性的话,则预设优先
+    priorityEffList = [] # 品质优先
+    for effID in selectEffIDList:
+        effIpyData = IpyGameDataPY.GetIpyGameData("FBDJGEffect", effID)
+        if not effIpyData:
+            continue
+        effQuality = effIpyData.GetEffQuality()
+        attrID = effIpyData.GetAttrID()
+        inSet = 0 # 预设优先,但多个预设同时出现时,先品质优先,再预设优先级
+        setPriority = 0 # 预设排序优先级
+        if attrID in selectSetAttrIDList:
+            inSet = 1
+            setPriority = len(selectSetAttrIDList) - selectSetAttrIDList.index(attrID)
+            
+        effLV = 1 # 初始1级
+        effInfo = effID * 100 + effLV
+        eIndex = -1 # 生效索引,设为-1,比已生效的低
+        priorityEffList.append([inSet, effQuality, setPriority, eIndex, effInfo, effID, attrID])
+        
+    priorityEffList.sort(reverse=True)
+    if not priorityEffList:
+        return
+    #GameWorld.DebugLog("    排序优先级: [inSet, effQuality, setPriority, eIndex, effInfo, effID, attrID]")
+    #GameWorld.DebugLog("    待选择排序: %s" % priorityEffList)
+    selectEff = priorityEffList[0] # 自动选择第一个
+    #selectAttrID = selectEff[Priority_AttrID]
+    selectEffID = selectEff[Priority_EffID]
+    selectEffInfo = selectEff[Priority_EffInfo]
+            
+    effMaxLV = IpyGameDataPY.GetFuncCfg("DingjungeEff", 2)
+    emptyIndex = -1
+    effList = [] # 已生效的效果
+    for eIndex in range(effHoleCnt):
+        effInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGEffect % eIndex)
+        if not effInfo:
+            if emptyIndex == -1:
+                #GameWorld.DebugLog("    还有空槽: eIndex=%s" % eIndex)
+                emptyIndex = eIndex
+            continue
+        
+        effID, effLV = effInfo / 100, effInfo % 100
+        
+        effIpyData = IpyGameDataPY.GetIpyGameData("FBDJGEffect", effID)
+        if not effIpyData:
+            continue
+        effQuality = effIpyData.GetEffQuality()
+        attrID = effIpyData.GetAttrID()
+        
+        # 已存在,升级
+        if effID == selectEffID and effLV < effMaxLV:
+            effLV += 1
+            effInfo = effID * 100 + effLV
+            #GameWorld.DebugLog("    已存在该效果直接升级: eIndex=%s,effID=%s,effLV=%s,attrID=%s" % (eIndex, effID, effLV, attrID))
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGEffect % eIndex, effInfo)
+            return True
+        
+        inSet = 0 # 预设优先,但多个预设同时出现时,先品质优先,再预设优先级
+        setPriority = 0 # 预设排序优先级
+        if attrID in selectSetAttrIDList:
+            inSet = 1
+            setPriority = len(selectSetAttrIDList) - selectSetAttrIDList.index(attrID)
+            
+        effList.append([inSet, effQuality, setPriority, eIndex, effInfo, effID, attrID])
+        
+    # 空槽
+    if emptyIndex != -1:
+        eIndex = emptyIndex
+        effID = selectEffID
+        effLV = 1
+        effInfo = effID * 100 + effLV
+        #GameWorld.DebugLog("    空槽直接设置: emptyIndex=%s,effID=%s,effLV=%s,attrID=%s,effList=%s" % (eIndex, effID, effLV, selectAttrID, effList))
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGEffect % eIndex, effInfo)
+        return True
+    
+    # 替换逻辑
+    effList.append(selectEff) # 选择项再与生效的一起排序
+    effList.sort(reverse=True)
+    
+    lastEff = effList[-1]
+    lastEIndex = lastEff[Priority_EIndex]
+    #lastEffID = lastEff[Priority_EffID]
+    #lastAttrID = lastEff[Priority_AttrID]
+    if lastEIndex == -1:
+        pass
+        #GameWorld.DebugLog("    优先级比已生效的低,直接舍弃! lastEIndex=%s,lastEffID=%s,lastAttrID=%s,effList=%s" % (lastEIndex, lastEffID, lastAttrID, effList))
+    else:
+        replaceIndex = lastEIndex
+        effInfo = selectEffInfo
+        #GameWorld.DebugLog("    优先级比已生效的高,直接替换! replaceIndex=%s,selectAttrID=%s,effInfo=%s,effList=%s" % (replaceIndex, selectAttrID, effInfo, effList))
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGEffect % replaceIndex, effInfo)
+            
+    return True
+
+def __doSelectEff(curPlayer, selectIndex, replaceHole):
+    ## 手动选择效果
+    selectEffID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGSelectEffect % selectIndex)
+    GameWorld.DebugLog("手动选择效果: selectIndex=%s,selectEffID=%s,replaceHole=%s" % (selectIndex, selectEffID, replaceHole))
+    if not selectEffID:
+        return
+    effHoleCnt = __getUnlockEffHoleCnt(curPlayer)
+    effMaxLV = IpyGameDataPY.GetFuncCfg("DingjungeEff", 2)
+    emptyIndex = -1
+    for eIndex in range(effHoleCnt):
+        effInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGEffect % eIndex)
+        if not effInfo:
+            if emptyIndex == -1:
+                GameWorld.DebugLog("    还有空槽: eIndex=%s" % eIndex)
+                emptyIndex = eIndex
+            continue
+        effID, effLV = effInfo / 100, effInfo % 100
+        # 已存在,升级
+        if effID == selectEffID:
+            if effLV >= effMaxLV:
+                GameWorld.DebugLog("    已存在该效果且已满级: eIndex=%s,effID=%s,effLV=%s" % (eIndex, effID, effLV))
+                return
+            effLV += 1
+            effInfo = effID * 100 + effLV
+            GameWorld.DebugLog("    已存在该效果直接升级: eIndex=%s,effID=%s,effLV=%s" % (eIndex, effID, effLV))
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGEffect % eIndex, effInfo)
+            return True
+        
+    # 空槽
+    if emptyIndex != -1:
+        eIndex = emptyIndex
+        effID = selectEffID
+        effLV = 1
+        effInfo = effID * 100 + effLV
+        GameWorld.DebugLog("    空槽直接设置: emptyIndex=%s,effID=%s,effLV=%s" % (eIndex, effID, effLV))
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGEffect % eIndex, effInfo)
+        return True
+    
+    # 替换逻辑
+    if replaceHole < 1 or replaceHole > effHoleCnt:
+        GameWorld.DebugLog("    替换的目标槽位不可用: replaceHole=%s,effHoleCnt=%s" % (replaceHole, effHoleCnt))
+        return
+    
+    effLV = 1
+    selectEffInfo = selectEffID * 100 + effLV
+    replaceIndex = replaceHole - 1
+    effInfo = selectEffInfo
+    GameWorld.DebugLog("    手动选择替换! replaceIndex=%s,effInfo=%s" % (replaceIndex, effInfo))
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DJGEffect % replaceIndex, effInfo)
+    return True
+
+def SyncDingjungeInfo(curPlayer):
+    clientPack = ChPyNetSendPack.tagSCDingjungeInfo()
+    clientPack.TodayPass = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGLineID)
+    effList = [] # 已生效的效果
+    for eIndex in range(len(IpyGameDataPY.GetFuncEvalCfg("DingjungeEff", 1))):
+        effInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGEffect % eIndex)
+        if not effInfo:
+            break
+        effID, effLV = effInfo / 100, effInfo % 100
+        eff = ChPyNetSendPack.tagSCDingjungeEff()
+        eff.EffIndex = eIndex
+        eff.EffID = effID
+        eff.EffLV = effLV
+        effList.append(eff)
+    clientPack.EffList = effList
+    clientPack.EffCnt = len(clientPack.EffList)
+    selectEffList = [] # 待选择的效果
+    for sIndex in range(IpyGameDataPY.GetFuncCfg("DingjungeEff", 3)):
+        effID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGSelectEffect % sIndex)
+        if not effID:
+            break
+        selectEffList.append(effID)
+    clientPack.SelectEffList = selectEffList
+    clientPack.SelectEffCnt = len(clientPack.SelectEffList)
+    clientPack.UnSelectCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGUnSelectCnt)
+    clientPack.SelectAuto = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGEffAuto)
+    selectSetAttrIDList = [] # 效果选择预设
+    for ssIndex in range(IpyGameDataPY.GetFuncCfg("DingjungeEff", 4)):
+        attrID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DJGEffSet % ssIndex)
+        selectSetAttrIDList.append(attrID)
+    clientPack.SelectSetAttrIDList = selectSetAttrIDList
+    clientPack.SelectSetCnt = len(clientPack.SelectSetAttrIDList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index ab8a339..9f0122e 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -964,6 +964,29 @@
                         ("list", "RandWeightItemList", 0),
                         ),
 
+                "FBDJGLevel":(
+                        ("WORD", "LayerNum", 1),
+                        ("BYTE", "LevelNum", 1),
+                        ("list", "PassAwardList", 0),
+                        ("list", "AwardList", 0),
+                        ("list", "LineupIDList", 0),
+                        ("WORD", "NPCLV", 0),
+                        ("float", "Difficulty", 0),
+                        ),
+
+                "FBDJGQuick":(
+                        ("WORD", "NeedLayer", 1),
+                        ("list", "QuickAwardList", 0),
+                        ),
+
+                "FBDJGEffect":(
+                        ("DWORD", "EffID", 1),
+                        ("BYTE", "EffQuality", 0),
+                        ("BYTE", "AttrID", 0),
+                        ("DWORD", "AttrValue", 0),
+                        ("DWORD", "RandWeight", 0),
+                        ),
+
                 "ADAward":(
                         ("DWORD", "ADID", 1),
                         ("BYTE", "ADCntMax", 0),
@@ -3584,6 +3607,44 @@
     def GetOtherAttrDict(self): return self.attrTuple[5] # 其他属性 {attrID:attrValue, ...} dict
     def GetRandWeightItemList(self): return self.attrTuple[6] # 宝箱随机物品权重列表,[[权重,物品ID,数量], ...] list
 
+# 定军阁关卡表
+class IPY_FBDJGLevel():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetLayerNum(self): return self.attrTuple[0] # 层数 WORD
+    def GetLevelNum(self): return self.attrTuple[1] # 关卡编号 BYTE
+    def GetPassAwardList(self): return self.attrTuple[2] #  过关奖励列表,[[物品ID,个数], ...] list
+    def GetAwardList(self): return self.attrTuple[3] #  挑战奖励,[[物品ID,个数], ...] list
+    def GetLineupIDList(self): return self.attrTuple[4] #  阵容ID列表,小队1阵容ID|小队2阵容ID|... list
+    def GetNPCLV(self): return self.attrTuple[5] # NPC等级 WORD
+    def GetDifficulty(self): return self.attrTuple[6] # 难度系数 float
+
+# 定军阁速战奖励表
+class IPY_FBDJGQuick():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetNeedLayer(self): return self.attrTuple[0] # 所需层数 WORD
+    def GetQuickAwardList(self): return self.attrTuple[1] #  速战奖励列表,[[物品ID,个数], ...] list
+
+# 定军阁效果表
+class IPY_FBDJGEffect():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetEffID(self): return self.attrTuple[0] # 效果ID DWORD
+    def GetEffQuality(self): return self.attrTuple[1] #  效果品质 BYTE
+    def GetAttrID(self): return self.attrTuple[2] #  属性ID BYTE
+    def GetAttrValue(self): return self.attrTuple[3] #  属性值 DWORD
+    def GetRandWeight(self): return self.attrTuple[4] #  随机权重 DWORD
+
 # 广告奖励表
 class IPY_ADAward():
     
@@ -5674,6 +5735,9 @@
         self.__LoadFileData("FBFunc", onlyCheck)
         self.__LoadFileData("FBLine", onlyCheck)
         self.__LoadFileData("Tianzi", onlyCheck)
+        self.__LoadFileData("FBDJGLevel", onlyCheck)
+        self.__LoadFileData("FBDJGQuick", onlyCheck)
+        self.__LoadFileData("FBDJGEffect", onlyCheck)
         self.__LoadFileData("ADAward", onlyCheck)
         self.__LoadFileData("Success", onlyCheck)
         self.__LoadFileData("TongTianLV", onlyCheck)
@@ -6632,6 +6696,27 @@
         self.CheckLoadData("Tianzi")
         return self.ipyTianziCache[index]
 
+    def GetFBDJGLevelCount(self):
+        self.CheckLoadData("FBDJGLevel")
+        return self.ipyFBDJGLevelLen
+    def GetFBDJGLevelByIndex(self, index):
+        self.CheckLoadData("FBDJGLevel")
+        return self.ipyFBDJGLevelCache[index]
+
+    def GetFBDJGQuickCount(self):
+        self.CheckLoadData("FBDJGQuick")
+        return self.ipyFBDJGQuickLen
+    def GetFBDJGQuickByIndex(self, index):
+        self.CheckLoadData("FBDJGQuick")
+        return self.ipyFBDJGQuickCache[index]
+
+    def GetFBDJGEffectCount(self):
+        self.CheckLoadData("FBDJGEffect")
+        return self.ipyFBDJGEffectLen
+    def GetFBDJGEffectByIndex(self, index):
+        self.CheckLoadData("FBDJGEffect")
+        return self.ipyFBDJGEffectCache[index]
+
     def GetADAwardCount(self):
         self.CheckLoadData("ADAward")
         return self.ipyADAwardLen
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 1a9ca69..b370c04 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFB.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFB.py
@@ -29,7 +29,6 @@
 import FBLogic
 import IpyGameDataPY
 import ShareDefine
-import NPCCommon
 import ChConfig
 
 #---------------------------------------------------------------------
@@ -120,21 +119,20 @@
         return
     
     reqRet = FBLogic.OnPlayerFBQuickPass(curPlayer, mapID, lineID)
-    if not reqRet or len(reqRet) != 2:
+    if not reqRet:
         GameWorld.DebugLog("无法一键过关副本: mapID=%s,lineID=%s" % (mapID, lineID), playerID)
         return
-    bossID, quickCnt = reqRet
-    if bossID:
-        npcData = GameWorld.GetGameData().FindNPCDataByID(bossID)
-        if not npcData:
-            return
-        npcFightPower = NPCCommon.GetSuppressFightPower(npcData)
+    lineID = reqRet[0]
+    quickCnt = reqRet[1] if len(reqRet) > 1 else 0
+    quickFightPower = reqRet[2] if len(reqRet) > 2 else 0
+    quickData = reqRet[3] if len(reqRet) > 3 else []
+    if quickFightPower:
         quickNeedRatio = IpyGameDataPY.GetFuncCfg("FBQuickPass", 1)
-        quickNeedFightPower = int(npcFightPower * quickNeedRatio)
+        quickNeedFightPower = int(quickFightPower * quickNeedRatio)
         curFightPower = PlayerControl.GetFightPower(curPlayer)
         if quickNeedFightPower and curFightPower < quickNeedFightPower:
-            GameWorld.DebugLog("无法一键过关副本! 战力限制: mapID=%s,lineID=%s,bossID=%s,npcFightPower=%s,quickNeedFightPower=%s > %s" 
-                               % (mapID, lineID, bossID, npcFightPower, quickNeedFightPower, curFightPower), playerID)
+            GameWorld.DebugLog("无法一键过关副本! 战力限制: mapID=%s,lineID=%s,quickFightPower=%s,quickNeedFightPower=%s > %s" 
+                               % (mapID, lineID, quickFightPower, quickNeedFightPower, curFightPower), playerID)
             PlayerControl.NotifyCode(curPlayer, 'TaskFeedback4')
             return
         
@@ -146,6 +144,6 @@
         FBCommon.AddEnterFBCount(curPlayer, mapID, quickCnt)
         
     #扫荡结果给奖励等
-    FBLogic.OnPlayerFBQuickPassResult(curPlayer, mapID, lineID)
+    FBLogic.OnPlayerFBQuickPassResult(curPlayer, mapID, lineID, quickData)
     return
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index 3d10148..082dd5b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -433,7 +433,8 @@
 Def_BT_Tianzi,    # 天子考验伤害榜 2
 Def_BT_OSA_MainLevel,    # 开服关卡榜 3
 Def_BT_OSA_HeroCall,    # 开服招募榜 4
-) = range(0, 5) 
+Def_BT_Dingjunge,    # 定军阁过关榜 5
+) = range(0, 6) 
 
 ''' 跨服排行榜类型, 从 150 开始,最大条数在功能配置表 CrossBillboardSet 配置,没配默认100
 与本服榜单存储的是不一样的数据库表格,理论上类型可以和本服榜单类型重复,为了做下区分防误导,跨服榜单从 150 开始
@@ -447,7 +448,7 @@
 BillboardTypeAllList = BillboardTypeList + CrossBillboardTypeList
 
 BillboardNameDict = {Def_BT_MainLevel:"主线过关榜", Def_BT_Arena:"演武场积分周榜", Def_BT_Tianzi:"天子考验伤害榜", 
-                     Def_BT_OSA_MainLevel:"开服关卡榜", Def_BT_OSA_HeroCall:"开服招募榜"}
+                     Def_BT_OSA_MainLevel:"开服关卡榜", Def_BT_OSA_HeroCall:"开服招募榜", Def_BT_Dingjunge:"定军阁过关榜"}
 
 #仙盟榜单类型
 FamilyBillboardList = []

--
Gitblit v1.8.0