From edc3910a9d090e5df4deb2dbc37709a740375938 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期四, 12 六月 2025 12:18:42 +0800
Subject: [PATCH] 121 【武将】武将系统-服务端(图鉴;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py |  178 +++++++++++++++++++++-
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini               |   10 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py       |   60 +++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py   |   20 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py     |   63 ++++++-
 PySysDB/PySysDBPY.h                                                                      |   26 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py         |   26 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py  |   37 ++--
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py          |    3 
 9 files changed, 369 insertions(+), 54 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 772f55b..c083348 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -30,12 +30,15 @@
 struct	Hero
 {
 	DWORD		_HeroID;	//英雄ID
-	WORD		HeroIndex;	// 记录索引
 	BYTE		Country;	// 国家
 	BYTE		Quality;	// 品质
 	list		SkinNPCIDList;	// 皮肤NPCID列表
 	DWORD		AtkSkillID;	//普攻技能ID
 	DWORD		AngerSkillID;	//怒气技能ID
+	WORD		AtkInheritPer;	//攻击继承
+	WORD		DefInheritPer;	//防御继承
+	WORD		HPInheritPer;	//生命继承
+	dict		BatAttrDict;	//其他战斗属性字典 {"属性ID":值, ...}
 };
 
 //武将星级天赋表
@@ -71,6 +74,15 @@
 	BYTE		AddStarUpper;	// 增加星级上限
 };
 
+//武将羁绊表
+struct	HeroFetter
+{
+	WORD		_FetterID;	//羁绊ID
+	list		HeroIDList;	// 武将ID组合列表
+	list		AttrIDList;	// 属性ID列表
+	list		AttrValueList;	// 属性值列表
+};
+
 //武将皮肤表
 struct	HeroSkin
 {
@@ -88,10 +100,14 @@
 	list		UPCostItem;	// 升级消耗道具
 	list		InitTalentWeight;	// 初始天赋数权重
 	BYTE		InitStarUpper;	// 初始星级上限
-	DWORD		InitAddPer;	// 初始加成万分率
-	DWORD		LVAddPer;	// 每等级加成
-	DWORD		BreakLVAddPer;	// 每突破等级加成
-	DWORD		StarAddPer;	// 每星级加成
+	DWORD		InitAddPer;	// 上阵初始加成万分率
+	DWORD		LVAddPer;	// 上阵每等级加成
+	DWORD		BreakLVAddPer;	// 上阵每突破等级加成
+	DWORD		StarAddPer;	// 上阵每星级加成
+	list		BookActAwardMoney;	// 图鉴激活奖励货币 类型|值
+	DWORD		BookInitAddPer;	// 图鉴初始加成
+	DWORD		BookStarAddPer;	// 图鉴每星级加成
+	DWORD		BookBreakLVAddPer;	// 图鉴每突破等级加成
 };
 
 //武将品质突破表
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index c847a2f..f0662d7 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -1940,6 +1940,10 @@
 PacketSubCMD_7=0x36
 PacketCallFunc_7=OnHeroWearSkin
 
-PacketCMD_8=0xB4
-PacketSubCMD_8=0x12
-PacketCallFunc_8=OnHeroBattlePosSave
+PacketCMD_8=0xB2
+PacketSubCMD_8=0x37
+PacketCallFunc_8=OnHeroBookUP
+
+PacketCMD_9=0xB4
+PacketSubCMD_9=0x12
+PacketCallFunc_9=OnHeroBattlePosSave
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 5f25ed4..f32577c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -4420,9 +4420,8 @@
 Def_PDict_TiandaoAward = "TiandaoAward_%s" # 天道树领奖记录,按奖励索引记录是否已领取,参数(key编号)
 
 #武将
-Def_PDict_HeroActState = "HeroActState_%s" # 武将解锁状态,按记录索引二进制存储,参数(key编号)
 Def_PDict_HeroSkin = "HeroSkin_%s" # 武将皮肤解锁状态,按皮肤索引二进制存储,参数(武将ID)
-
+Def_PDict_HeroBook = "HeroBook_%s" # 武将图鉴激活等级,参数(武将ID) cccbbba a-初始激活状态1-英雄激活,2-初始图鉴激活; bbb-存星级图鉴激活等级;ccc-存突破图鉴激活等级
 #-------------------------------------------------------------------------------
 #可以从07 41封包购买的背包类型,和对应字典{背包类型:[字典key, 默认格子数]}
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index cae4322..89d132b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -17372,6 +17372,66 @@
 
 
 #------------------------------------------------------
+# B2 37 武将图鉴激活升级 #tagCSHeroBookUP
+
+class  tagCSHeroBookUP(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("HeroID", c_int),    #武将ID
+                  ("ItemIndex", c_ushort),    #关联武将物品所在武将背包索引,激活时可不用发
+                  ("BookType", c_ubyte),    #图鉴激活类型: 0-初始激活;1-星级升级;2-突破等级升级
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x37
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xB2
+        self.SubCmd = 0x37
+        self.HeroID = 0
+        self.ItemIndex = 0
+        self.BookType = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCSHeroBookUP)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 37 武将图鉴激活升级 //tagCSHeroBookUP:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                HeroID:%d,
+                                ItemIndex:%d,
+                                BookType:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.HeroID,
+                                self.ItemIndex,
+                                self.BookType
+                                )
+        return DumpString
+
+
+m_NAtagCSHeroBookUP=tagCSHeroBookUP()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHeroBookUP.Cmd,m_NAtagCSHeroBookUP.SubCmd))] = m_NAtagCSHeroBookUP
+
+
+#------------------------------------------------------
 # B2 32 武将突破 #tagCSHeroBreak
 
 class  tagCSHeroBreak(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 50f951f..bad86e4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -44100,8 +44100,10 @@
     _pack_ = 1
     _fields_ = [
                   ("HeroID", c_int),    # 武将ID
-                  ("IsActive", c_ubyte),    # 是否已激活
                   ("SkinState", c_int),    # 武将皮肤已解锁状态信息,按皮肤所在索引二进制位运算判断是否解锁,0索引位默认皮肤,不用验证
+                  ("BookInitState", c_ubyte),    # 图鉴激活状态:0-未激活;1-可激活;2-已激活
+                  ("BookStarLV", c_ushort),    # 图鉴星级等级
+                  ("BookBreakLV", c_ushort),    # 图鉴突破等级
                   ]
 
     def __init__(self):
@@ -44115,8 +44117,10 @@
 
     def Clear(self):
         self.HeroID = 0
-        self.IsActive = 0
         self.SkinState = 0
+        self.BookInitState = 0
+        self.BookStarLV = 0
+        self.BookBreakLV = 0
         return
 
     def GetLength(self):
@@ -44128,13 +44132,17 @@
     def OutputString(self):
         DumpString = '''// B1 22 武将信息 //tagSCHeroInfo:
                                 HeroID:%d,
-                                IsActive:%d,
-                                SkinState:%d
+                                SkinState:%d,
+                                BookInitState:%d,
+                                BookStarLV:%d,
+                                BookBreakLV:%d
                                 '''\
                                 %(
                                 self.HeroID,
-                                self.IsActive,
-                                self.SkinState
+                                self.SkinState,
+                                self.BookInitState,
+                                self.BookStarLV,
+                                self.BookBreakLV
                                 )
         return DumpString
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py
index cb4faeb..302bd9d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py
@@ -18,6 +18,7 @@
 import PlayerHero
 import ShareDefine
 import IpyGameDataPY
+import PlayerControl
 import GameWorld
 import ChConfig
 
@@ -34,7 +35,7 @@
         GameWorld.DebugAnswer(curPlayer, "武将升星: Hero s 背包位置 升x星")
         GameWorld.DebugAnswer(curPlayer, "武将突破: Hero b 背包位置 设置等级")
         GameWorld.DebugAnswer(curPlayer, "武将觉醒: Hero a 背包位置 设置等级")
-        GameWorld.DebugAnswer(curPlayer, "武将图鉴: Hero t 武将ID 是否激活")
+        GameWorld.DebugAnswer(curPlayer, "武将图鉴: Hero t 武将ID 图鉴星级 图鉴突破等级")
         GameWorld.DebugAnswer(curPlayer, "重置图鉴: Hero t 0")
         GameWorld.DebugAnswer(curPlayer, "武将皮肤: Hero sk 武将ID 皮肤索引 是否解锁")
         GameWorld.DebugAnswer(curPlayer, "清空武将: ClearPack 35")
@@ -46,7 +47,6 @@
     
     # 图鉴
     if value == "t":
-        isAct = 0
         if not value2:
             heroIDList = []
             ipyDataMgr = IpyGameDataPY.IPY_Data()
@@ -54,25 +54,28 @@
                 ipyData = ipyDataMgr.GetHeroByIndex(index)
                 heroIDList.append(ipyData.GetHeroID())
         else:
-            isAct = msgList[2] if len(msgList) > 2 else 0
             heroIDList = [value2]
-        
-        syncHeroIDList = []
-        for heroID in heroIDList:
-            heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
-            if not heroIpyData:
-                continue
-            heroIndex = heroIpyData.GetHeroIndex()
-            if GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HeroActState, heroIndex) == isAct:
-                continue
-            GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HeroActState, heroIndex, isAct)
-            syncHeroIDList.append(heroID)
             
-        PlayerHero.Sync_HeroInfo(curPlayer, syncHeroIDList)
-        if not value2:
+        if value2 == 0:
+            syncHeroIDList = []
+            for heroID in heroIDList:
+                if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID):
+                    continue
+                syncHeroIDList.append(heroID)
+                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroBook % heroID, 0)
             GameWorld.DebugAnswer(curPlayer, "重置图鉴OK!")
         else:
-            GameWorld.DebugAnswer(curPlayer, "设置武将(%s),激活(%s)" % (value2, isAct))
+            heroID = value2
+            syncHeroIDList = [heroID]
+            bookStarLV = msgList[2] if len(msgList) > 2 else 0
+            bookBreakLV = msgList[3] if len(msgList) > 3 else 0
+            if (bookStarLV or bookStarLV) and not PlayerHero.GetHeroBookInitState(curPlayer, heroID):
+                PlayerHero.SetHeroBookInitState(curPlayer, heroID, 1)
+            PlayerHero.SetHeroBookStarLV(curPlayer, heroID, bookStarLV)
+            PlayerHero.SetHeroBookBreakLV(curPlayer, heroID, bookBreakLV)
+            GameWorld.DebugAnswer(curPlayer, "设置武将(%s)图鉴星级(%s),突破(%s)" % (heroID, bookStarLV, bookBreakLV))
+            
+        PlayerHero.Sync_HeroInfo(curPlayer, syncHeroIDList)
         return
     
     # 皮肤
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
index a9dcf21..a08a79c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
@@ -2103,6 +2103,32 @@
     numValue += pow(10, dataIndex)*(dataValue - lastTagLV)
     return numValue
 
+def GetValue(dataValue, fromRight, bits):
+    '''获取某个数值中,从右往左数第x位开始,截图n位得到的数据
+    @param dataValue: 原始数值
+    @param fromRight: 从右往左数第x位开始,从1开始
+    @param bits: 截取n位
+    @return: 数值value
+    '''
+    lPow = pow(10, fromRight)
+    rPow = pow(10, fromRight - bits)
+    curValue = dataValue % lPow / rPow
+    return curValue
+
+def SetValue(dataValue, fromRight, bits, updValue):
+    '''修改某个数值,从右往左数第x位开始,截图n位得到的数据,替换为具体数值
+    @param dataValue: 原始数值
+    @param fromRight: 从右往左数第x位开始,从1开始
+    @param bits: 截取n位
+    @param updValue: 替换值
+    @return: 修改后的value值
+    '''
+    lPow = pow(10, fromRight)
+    rPow = pow(10, fromRight - bits)
+    leftValue = dataValue / lPow * lPow
+    rightValue = dataValue % rPow
+    return leftValue + updValue * rPow + rightValue
+    
 def GetBitValue(dataValue, index):
     """ 得到某个字节值中某一位(Bit)的值
     @param dataValue: 待取值的字节值
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index 8244a79..3b1c8ad 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -58,12 +58,15 @@
 
                 "Hero":(
                         ("DWORD", "HeroID", 1),
-                        ("WORD", "HeroIndex", 0),
                         ("BYTE", "Country", 0),
                         ("BYTE", "Quality", 0),
                         ("list", "SkinNPCIDList", 0),
                         ("DWORD", "AtkSkillID", 0),
                         ("DWORD", "AngerSkillID", 0),
+                        ("WORD", "AtkInheritPer", 0),
+                        ("WORD", "DefInheritPer", 0),
+                        ("WORD", "HPInheritPer", 0),
+                        ("dict", "BatAttrDict", 0),
                         ),
 
                 "HeroTalent":(
@@ -93,6 +96,13 @@
                         ("BYTE", "AddStarUpper", 0),
                         ),
 
+                "HeroFetter":(
+                        ("WORD", "FetterID", 1),
+                        ("list", "HeroIDList", 0),
+                        ("list", "AttrIDList", 0),
+                        ("list", "AttrValueList", 0),
+                        ),
+
                 "HeroSkin":(
                         ("DWORD", "SkinNPCID", 1),
                         ("list", "WearAttrIDList", 0),
@@ -110,6 +120,10 @@
                         ("DWORD", "LVAddPer", 0),
                         ("DWORD", "BreakLVAddPer", 0),
                         ("DWORD", "StarAddPer", 0),
+                        ("list", "BookActAwardMoney", 0),
+                        ("DWORD", "BookInitAddPer", 0),
+                        ("DWORD", "BookStarAddPer", 0),
+                        ("DWORD", "BookBreakLVAddPer", 0),
                         ),
 
                 "HeroQualityBreak":(
@@ -2767,12 +2781,15 @@
         return
         
     def GetHeroID(self): return self.attrTuple[0] # 英雄ID DWORD
-    def GetHeroIndex(self): return self.attrTuple[1] #  记录索引 WORD
-    def GetCountry(self): return self.attrTuple[2] #  国家 BYTE
-    def GetQuality(self): return self.attrTuple[3] #  品质 BYTE
-    def GetSkinNPCIDList(self): return self.attrTuple[4] #  皮肤NPCID列表 list
-    def GetAtkSkillID(self): return self.attrTuple[5] # 普攻技能ID DWORD
-    def GetAngerSkillID(self): return self.attrTuple[6] # 怒气技能ID DWORD
+    def GetCountry(self): return self.attrTuple[1] #  国家 BYTE
+    def GetQuality(self): return self.attrTuple[2] #  品质 BYTE
+    def GetSkinNPCIDList(self): return self.attrTuple[3] #  皮肤NPCID列表 list
+    def GetAtkSkillID(self): return self.attrTuple[4] # 普攻技能ID DWORD
+    def GetAngerSkillID(self): return self.attrTuple[5] # 怒气技能ID DWORD
+    def GetAtkInheritPer(self): return self.attrTuple[6] # 攻击继承 WORD
+    def GetDefInheritPer(self): return self.attrTuple[7] # 防御继承 WORD
+    def GetHPInheritPer(self): return self.attrTuple[8] # 生命继承 WORD
+    def GetBatAttrDict(self): return self.attrTuple[9] # 其他战斗属性字典 {"属性ID":值, ...} dict
 
 # 武将星级天赋表
 class IPY_HeroTalent():
@@ -2816,6 +2833,18 @@
     def GetUnlockTalentSlot(self): return self.attrTuple[5] #  解锁第x槽位 BYTE
     def GetAddStarUpper(self): return self.attrTuple[6] #  增加星级上限 BYTE
 
+# 武将羁绊表
+class IPY_HeroFetter():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetFetterID(self): return self.attrTuple[0] # 羁绊ID WORD
+    def GetHeroIDList(self): return self.attrTuple[1] #  武将ID组合列表 list
+    def GetAttrIDList(self): return self.attrTuple[2] #  属性ID列表 list
+    def GetAttrValueList(self): return self.attrTuple[3] #  属性值列表 list
+
 # 武将皮肤表
 class IPY_HeroSkin():
     
@@ -2840,10 +2869,14 @@
     def GetUPCostItem(self): return self.attrTuple[1] #  升级消耗道具 list
     def GetInitTalentWeight(self): return self.attrTuple[2] #  初始天赋数权重 list
     def GetInitStarUpper(self): return self.attrTuple[3] #  初始星级上限 BYTE
-    def GetInitAddPer(self): return self.attrTuple[4] #  初始加成万分率 DWORD
-    def GetLVAddPer(self): return self.attrTuple[5] #  每等级加成 DWORD
-    def GetBreakLVAddPer(self): return self.attrTuple[6] #  每突破等级加成 DWORD
-    def GetStarAddPer(self): return self.attrTuple[7] #  每星级加成 DWORD
+    def GetInitAddPer(self): return self.attrTuple[4] #  上阵初始加成万分率 DWORD
+    def GetLVAddPer(self): return self.attrTuple[5] #  上阵每等级加成 DWORD
+    def GetBreakLVAddPer(self): return self.attrTuple[6] #  上阵每突破等级加成 DWORD
+    def GetStarAddPer(self): return self.attrTuple[7] #  上阵每星级加成 DWORD
+    def GetBookActAwardMoney(self): return self.attrTuple[8] #  图鉴激活奖励货币 类型|值 list
+    def GetBookInitAddPer(self): return self.attrTuple[9] #  图鉴初始加成 DWORD
+    def GetBookStarAddPer(self): return self.attrTuple[10] #  图鉴每星级加成 DWORD
+    def GetBookBreakLVAddPer(self): return self.attrTuple[11] #  图鉴每突破等级加成 DWORD
 
 # 武将品质突破表
 class IPY_HeroQualityBreak():
@@ -6881,6 +6914,7 @@
         self.__LoadFileData("HeroTalent", onlyCheck)
         self.__LoadFileData("HeroBreak", onlyCheck)
         self.__LoadFileData("HeroAwake", onlyCheck)
+        self.__LoadFileData("HeroFetter", onlyCheck)
         self.__LoadFileData("HeroSkin", onlyCheck)
         self.__LoadFileData("HeroQuality", onlyCheck)
         self.__LoadFileData("HeroQualityBreak", onlyCheck)
@@ -7416,6 +7450,13 @@
         self.CheckLoadData("HeroAwake")
         return self.ipyHeroAwakeCache[index]
 
+    def GetHeroFetterCount(self):
+        self.CheckLoadData("HeroFetter")
+        return self.ipyHeroFetterLen
+    def GetHeroFetterByIndex(self, index):
+        self.CheckLoadData("HeroFetter")
+        return self.ipyHeroFetterCache[index]
+
     def GetHeroSkinCount(self):
         self.CheckLoadData("HeroSkin")
         return self.ipyHeroSkinLen
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py
index 7540395..6801516 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py
@@ -110,12 +110,75 @@
     heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
     if not heroIpyData:
         return
-    heroIndex = heroIpyData.GetHeroIndex()
-    heroActState = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HeroActState, heroIndex)
-    if not heroActState:
-        GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HeroActState, heroIndex, 1)
-        GameWorld.DebugLog("首次激活武将: heroID=%s,heroIndex=%s" % (heroID, heroIndex), curPlayer.GetPlayerID())
+    
+    if not GetHeroActivite(curPlayer, heroID):
+        SetHeroActivite(curPlayer, heroID, 1)
+        GameWorld.DebugLog("首次激活武将: heroID=%s" % (heroID), curPlayer.GetPlayerID())
+        #首次获得图鉴额外逻辑 ...
         Sync_HeroInfo(curPlayer, [heroID])
+        
+    return
+
+def GetHeroActivite(curPlayer, heroID):
+    ## 武将状态
+    # @return: 0-未激活;1-武将已获得,可激活;2-图鉴已激活
+    actState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID) % 10
+    return actState
+
+def SetHeroActivite(curPlayer, heroID, isAct=1):
+    ## 设置武将已获得,可激活状态
+    bookState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID)
+    actState = bookState % 10
+    if isAct:
+        if actState:
+            return
+        actState = 1
+    else:
+        actState = 0
+    updBookState = GameWorld.SetValue(bookState, 1, 1, actState)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroBook % heroID, updBookState)
+    GameWorld.DebugLog("设置武将激活状态:%s,bookState=%s,updBookState=%s" % (isAct, bookState, updBookState), curPlayer.GetPlayerID())
+    return
+
+def GetHeroBookInitState(curPlayer, heroID):
+    ## 武将图鉴激活状态
+    initState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID) % 10
+    return initState > 1
+def SetHeroBookInitState(curPlayer, heroID, isAct=1):
+    ## 设置武将图鉴激活状态
+    bookState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID)
+    actState = bookState % 10
+    if isAct:
+        actState = 2
+    else:
+        actState = 1 if actState else 0
+    updBookState = GameWorld.SetValue(bookState, 1, 1, actState)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroBook % heroID, updBookState)
+    GameWorld.DebugLog("设置武将图鉴激活状态:%s,bookState=%s,updBookState=%s" % (isAct, bookState, updBookState), curPlayer.GetPlayerID())
+    return
+
+def GetHeroBookStarLV(curPlayer, heroID):
+    ## 武将图鉴星级等级
+    bookState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID)
+    return GameWorld.GetValue(bookState, 4, 3)
+def SetHeroBookStarLV(curPlayer, heroID, starLV):
+    ## 设置武将图鉴星级等级,支持三位数 0~999 级
+    bookState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID)
+    updBookState = GameWorld.SetValue(bookState, 4, 3, starLV)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroBook % heroID, updBookState)
+    GameWorld.DebugLog("设置武将图鉴星级等级:%s,bookState=%s,updBookState=%s" % (starLV, bookState, updBookState), curPlayer.GetPlayerID())
+    return
+
+def GetHeroBookBreakLV(curPlayer, heroID):
+    ## 武将图鉴突破等级
+    bookState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID)
+    return GameWorld.GetValue(bookState, 7, 3)
+def SetHeroBookBreakLV(curPlayer, heroID, breakLV):
+    ## 设置武将图鉴突破等级,支持三位数 0~999 级
+    bookState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID)
+    updBookState = GameWorld.SetValue(bookState, 7, 3, breakLV)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroBook % heroID, updBookState)
+    GameWorld.DebugLog("设置武将图鉴突破等级:%s,bookState=%s,updBookState=%s" % (breakLV, bookState, updBookState), curPlayer.GetPlayerID())
     return
 
 def GetHeroItem(curPlayer, itemIndex):
@@ -811,6 +874,101 @@
     Sync_HeroInfo(curPlayer, [heroID])
     return
 
+#// B2 37 武将图鉴激活升级 #tagCSHeroBookUP
+#
+#struct    tagCSHeroBookUP
+#{
+#    tagHead        Head;
+#    DWORD        HeroID;        //武将ID
+#    WORD        ItemIndex;    //关联武将物品所在武将背包索引,激活时可不用发
+#    BYTE        BookType;    //图鉴激活类型: 0-初始激活;1-星级升级;2-突破等级升级
+#};
+def OnHeroBookUP(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    heroID = clientData.HeroID
+    itemIndex = clientData.ItemIndex
+    bookType = clientData.BookType
+    
+    if bookType == 1:
+        __doHeroBookStarLVUP(curPlayer, heroID, itemIndex)
+    elif bookType == 2:
+        __doHeroBookBreakLVUP(curPlayer, heroID, itemIndex)
+    else:
+        __doHeroBookAct(curPlayer, heroID)
+    return
+
+def __doHeroBookAct(curPlayer, heroID):
+    ## 图鉴激活
+    playerID = curPlayer.GetPlayerID()
+    if GetHeroBookInitState(curPlayer, heroID):
+        GameWorld.DebugLog("该武将图鉴已激活! heroID=%s" % heroID, playerID)
+        return
+    GameWorld.DebugLog("武将图鉴激活! heroID=%s" % heroID, playerID)
+    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+    if not heroIpyData:
+        return
+    quality = heroIpyData.GetQuality()
+    qualityIpyData = IpyGameDataPY.GetIpyGameData("HeroQuality", quality)
+    if not qualityIpyData:
+        return
+    if GetHeroActivite(curPlayer, heroID) != 1:
+        GameWorld.DebugLog("武将未获得过,不可激活图鉴! heroID=%s" % (heroID), playerID)
+        return
+    SetHeroBookInitState(curPlayer, heroID, 1)
+    
+    awardMoneyInfo = qualityIpyData.GetBookActAwardMoney()
+    if awardMoneyInfo and len(awardMoneyInfo) == 2:
+        moneyType, moneyValue = awardMoneyInfo
+        if moneyType and moneyValue:
+            PlayerControl.GiveMoney(curPlayer, moneyType, moneyValue, "HeroBookAct")
+                    
+    Sync_HeroInfo(curPlayer, [heroID])
+    return
+
+def __doHeroBookStarLVUP(curPlayer, heroID, itemIndex):
+    ## 图鉴星级升级
+    playerID = curPlayer.GetPlayerID()
+    heroItem = GetHeroItem(curPlayer, itemIndex)
+    if not heroItem:
+        return
+    if heroItem.GetItemTypeID() != heroID:
+        GameWorld.DebugLog("非该武将图鉴关联物品! heroID=%s,itemID=%s" % (heroID, heroItem.GetItemTypeID()), playerID)
+        return
+    heroStar = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroStar)
+    bookStar = GetHeroBookStarLV(curPlayer, heroID)
+    if bookStar >= heroStar:
+        GameWorld.DebugLog("该武将图鉴星级已达当前英雄星级! heroID=%s,bookStar=%s,heroStar=%s" % (heroID, bookStar, heroStar), playerID)
+        return
+    GameWorld.DebugLog("武将图鉴星级升级! heroID=%s,bookStar=%s,heroStar=%s" % (heroID, bookStar, heroStar), playerID)
+    SetHeroBookStarLV(curPlayer, heroID, bookStar + 1)
+    Sync_HeroInfo(curPlayer, [heroID])
+    
+    # 刷属性
+    
+    return
+
+def __doHeroBookBreakLVUP(curPlayer, heroID, itemIndex):
+    ## 图鉴突破升级
+    playerID = curPlayer.GetPlayerID()
+    heroItem = GetHeroItem(curPlayer, itemIndex)
+    if not heroItem:
+        return
+    if heroItem.GetItemTypeID() != heroID:
+        GameWorld.DebugLog("非该武将图鉴关联物品! heroID=%s,itemID=%s" % (heroID, heroItem.GetItemTypeID()), playerID)
+        return
+    heroBreakLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroBreakLV)
+    bookBreakLV = GetHeroBookBreakLV(curPlayer, heroID)
+    if bookBreakLV >= heroBreakLV:
+        GameWorld.DebugLog("该武将图鉴突破等级已达当前英雄突破等级! heroID=%s,bookBreakLV=%s,heroBreakLV=%s" % (heroID, bookBreakLV, heroBreakLV), playerID)
+        return
+    GameWorld.DebugLog("武将图鉴突破升级! heroID=%s,bookBreakLV=%s,heroBreakLV=%s" % (heroID, bookBreakLV, heroBreakLV), playerID)
+    SetHeroBookBreakLV(curPlayer, heroID, bookBreakLV + 1)
+    Sync_HeroInfo(curPlayer, [heroID])
+    
+    # 刷属性
+    
+    return
+
 #// B4 12 战斗阵型保存 #tagCSHeroBattlePosSave
 #
 #struct    tagCSHeroBattlePos
@@ -837,7 +995,7 @@
         posNum = posInfo.PosNum
         itemIndex = posInfo.ItemIndex
         if itemIndex in indexList:
-            # 单英雄只能一个位置,一个位置只能对应唯一英雄单位
+            # 单武将只能一个位置,一个位置只能对应唯一武将单位
             continue
         indexList.append(itemIndex)
         heroPosDict[posNum] = itemIndex
@@ -902,15 +1060,15 @@
         heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
         if not heroIpyData:
             continue
-        heroIndex = heroIpyData.GetHeroIndex()
-        heroActState = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HeroActState, heroIndex)
-        if not heroActState and heroIDList == None:
+        if heroIDList == None and not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID):
             continue
         
         hero = ChPyNetSendPack.tagSCHero()
         hero.HeroID = heroID
-        hero.IsActive = heroActState
         hero.SkinState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroSkin % heroID)
+        hero.BookInitState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID) % 10
+        hero.BookStarLV = GetHeroBookStarLV(curPlayer, heroID)
+        hero.BookBreakLV = GetHeroBookBreakLV(curPlayer, heroID)
         syncInfoList.append(hero)
         
     if not syncInfoList:

--
Gitblit v1.8.0