From 3d04d70ff41fe87919a5f2e8b0b9f76b890ec620 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期四, 12 九月 2024 12:07:35 +0800
Subject: [PATCH] 10261 【越南】【砍树】仙盟徽章,头像框,头像(动态),聊天气泡,聊天表情(增加头像、头像框)

---
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerBillboard.py                                   |   47 +
 ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py                                            |   46 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py                         |  208 +++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                     |  305 +++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py                         |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_GMTFace.py |   98 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py              |   13 
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py                                              |  208 +++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameServerRefresh.py            |    4 
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py                                          |  305 +++++++
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldArena.py                            |    8 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Face.py                    |  157 +++
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py                                   |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                       |  120 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py                     |    5 
 PySysDB/PySysDBPY.h                                                                                        |   46 +
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerTalk.py                                        |    3 
 ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py                                              |    7 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py                |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerDienstgrad.py             |    6 
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldSkyTower.py                         |    1 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerRequest.py                                     |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py          |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestRunnerValue.py     |    2 
 ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py                                         |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTalk.py                   |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                         |    7 
 ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py                                          |    4 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerSocial.py                                      |    6 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFriend.py                                      |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py                  |   18 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTJG.py                    |    2 
 ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_Face.py                                     |   74 +
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py                                      |    5 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini                                 |   24 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFace.py                   |  564 ++++++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_Face.py              |   37 
 PySysDB/PySysDBG.h                                                                                         |   16 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                            |   24 
 39 files changed, 2,331 insertions(+), 63 deletions(-)

diff --git a/PySysDB/PySysDBG.h b/PySysDB/PySysDBG.h
index b3c90d0..fa31ed2 100644
--- a/PySysDB/PySysDBG.h
+++ b/PySysDB/PySysDBG.h
@@ -29,6 +29,22 @@
 	list		LimitServerGroupIDList;	//限制创角的服务器组ID列表
 };
 
+//头像表
+
+struct	tagPlayerFace
+{
+	DWORD		_FaceID;	//头像ID
+	BYTE		UnlockDefault;	//是否默认激活
+};
+
+//头像框表
+
+struct	tagPlayerFacePic
+{
+	DWORD		_FacePicID;	//头像框ID
+	BYTE		UnlockDefault;	//是否默认激活
+};
+
 //世界等级表格 #tagWorldLV
 
 struct	tagWorldLV
diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 7df4c0e..0ca77f1 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -21,6 +21,52 @@
 	list		StarAttrValue;	//累计总属性值
 };
 
+//头像表
+
+struct	tagPlayerFace
+{
+	DWORD		_FaceID;	//头像ID
+	BYTE		UnlockDefault;	//是否默认激活
+    DWORD		ExpireMinutes;	//时效分钟,0永久
+	list		LightAttrType;	//点亮属性类型
+	list		LightAttrValue;	//点亮属性值
+    DWORD		LightFightPower;	//点亮附加战力
+};
+
+//头像升星表
+
+struct tagPlayerFaceStar
+{
+	DWORD		_FaceID;	//头像ID
+	BYTE		_FaceStar;	//头像星级
+	list		StarUpNeedItemList;	//升该星所需物品 [[物品ID,个数], ...]
+	list		StarAttrType;	//累计总属性类型
+	list		StarAttrValue;	//累计总属性值
+};
+
+//头像框表
+
+struct	tagPlayerFacePic
+{
+	DWORD		_FacePicID;	//头像框ID
+	BYTE		UnlockDefault;	//是否默认激活
+    DWORD		ExpireMinutes;	//时效分钟,0永久
+	list		LightAttrType;	//点亮属性类型
+	list		LightAttrValue;	//点亮属性值
+    DWORD		LightFightPower;	//点亮附加战力
+};
+
+//头像框升星表
+
+struct tagPlayerFacePicStar
+{
+	DWORD		_FacePicID;	//头像框ID
+	BYTE		_FacePicStar;	//头像框星级
+	list		StarUpNeedItemList;	//升该星所需物品 [[物品ID,个数], ...]
+	list		StarAttrType;	//累计总属性类型
+	list		StarAttrValue;	//累计总属性值
+};
+
 //创角表
 
 struct	tagCreateRole
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
index 2f32ce0..b32ec8f 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -19416,6 +19416,214 @@
 
 
 #------------------------------------------------------
+# B2 26 头像幻化 #tagCMFaceChange
+
+class  tagCMFaceChange(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("FaceID", c_int),    # 幻化的ID
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x26
+        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 = 0x26
+        self.FaceID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMFaceChange)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 26 头像幻化 //tagCMFaceChange:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                FaceID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.FaceID
+                                )
+        return DumpString
+
+
+m_NAtagCMFaceChange=tagCMFaceChange()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFaceChange.Cmd,m_NAtagCMFaceChange.SubCmd))] = m_NAtagCMFaceChange
+
+
+#------------------------------------------------------
+# B2 28 头像框幻化 #tagCMFacePicChange
+
+class  tagCMFacePicChange(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("FacePicID", c_int),    # 幻化的ID
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x28
+        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 = 0x28
+        self.FacePicID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMFacePicChange)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 28 头像框幻化 //tagCMFacePicChange:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                FacePicID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.FacePicID
+                                )
+        return DumpString
+
+
+m_NAtagCMFacePicChange=tagCMFacePicChange()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFacePicChange.Cmd,m_NAtagCMFacePicChange.SubCmd))] = m_NAtagCMFacePicChange
+
+
+#------------------------------------------------------
+# B2 29 头像框升星 #tagCMFacePicStarUP
+
+class  tagCMFacePicStarUP(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("FacePicID", c_int),    
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x29
+        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 = 0x29
+        self.FacePicID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMFacePicStarUP)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 29 头像框升星 //tagCMFacePicStarUP:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                FacePicID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.FacePicID
+                                )
+        return DumpString
+
+
+m_NAtagCMFacePicStarUP=tagCMFacePicStarUP()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFacePicStarUP.Cmd,m_NAtagCMFacePicStarUP.SubCmd))] = m_NAtagCMFacePicStarUP
+
+
+#------------------------------------------------------
+# B2 27 头像升星 #tagCMFaceStarUP
+
+class  tagCMFaceStarUP(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("FaceID", c_int),    
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x27
+        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 = 0x27
+        self.FaceID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMFaceStarUP)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 27 头像升星 //tagCMFaceStarUP:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                FaceID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.FaceID
+                                )
+        return DumpString
+
+
+m_NAtagCMFaceStarUP=tagCMFaceStarUP()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFaceStarUP.Cmd,m_NAtagCMFaceStarUP.SubCmd))] = m_NAtagCMFaceStarUP
+
+
+#------------------------------------------------------
 # B2 25 新聚魂操作 #tagCMGatherTheSoulOP
 
 class  tagCMGatherTheSoulOP(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index 86a210a..369ee95 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -1180,6 +1180,7 @@
     Job = 0    #(BYTE Job)// 玩家职业
     RealmLV = 0    #(WORD RealmLV)// 玩家境界等级
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -1198,6 +1199,7 @@
         self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -1212,6 +1214,7 @@
         self.Job = 0
         self.RealmLV = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -1223,6 +1226,7 @@
         length += 2
         length += 1
         length += 2
+        length += 4
         length += 4
 
         return length
@@ -1237,6 +1241,7 @@
         data = CommFunc.WriteBYTE(data, self.Job)
         data = CommFunc.WriteWORD(data, self.RealmLV)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -1248,7 +1253,8 @@
                                 LV:%d,
                                 Job:%d,
                                 RealmLV:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.Head.OutputString(),
@@ -1258,7 +1264,8 @@
                                 self.LV,
                                 self.Job,
                                 self.RealmLV,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -5276,6 +5283,7 @@
     Job = 0    #(BYTE Job)
     RealmLV = 0    #(WORD RealmLV)//境界	
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -5290,6 +5298,7 @@
         self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -5299,6 +5308,7 @@
         self.Job = 0
         self.RealmLV = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -5308,6 +5318,7 @@
         length += 4
         length += 1
         length += 2
+        length += 4
         length += 4
 
         return length
@@ -5320,6 +5331,7 @@
         data = CommFunc.WriteBYTE(data, self.Job)
         data = CommFunc.WriteWORD(data, self.RealmLV)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -5329,7 +5341,8 @@
                                 LV:%d,
                                 Job:%d,
                                 RealmLV:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.ID,
@@ -5337,7 +5350,8 @@
                                 self.LV,
                                 self.Job,
                                 self.RealmLV,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -5418,6 +5432,7 @@
     LV = 0    #(WORD LV)//等级
     RealmLV = 0    #(WORD RealmLV)//境界
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -5432,6 +5447,7 @@
         self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -5441,6 +5457,7 @@
         self.LV = 0
         self.RealmLV = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -5450,6 +5467,7 @@
         length += 1
         length += 2
         length += 2
+        length += 4
         length += 4
 
         return length
@@ -5462,6 +5480,7 @@
         data = CommFunc.WriteWORD(data, self.LV)
         data = CommFunc.WriteWORD(data, self.RealmLV)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -5471,7 +5490,8 @@
                                 Job:%d,
                                 LV:%d,
                                 RealmLV:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.PlayerID,
@@ -5479,7 +5499,8 @@
                                 self.Job,
                                 self.LV,
                                 self.RealmLV,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -9314,6 +9335,7 @@
     LV = 0    #(WORD LV)
     RealmLV = 0    #(WORD RealmLV)//境界等级
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -9330,6 +9352,7 @@
         self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -9342,6 +9365,7 @@
         self.LV = 0
         self.RealmLV = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -9351,6 +9375,7 @@
         length += 33
         length += 2
         length += 2
+        length += 4
         length += 4
 
         return length
@@ -9363,6 +9388,7 @@
         data = CommFunc.WriteWORD(data, self.LV)
         data = CommFunc.WriteWORD(data, self.RealmLV)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -9372,7 +9398,8 @@
                                 Name:%s,
                                 LV:%d,
                                 RealmLV:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.Head.OutputString(),
@@ -9380,7 +9407,8 @@
                                 self.Name,
                                 self.LV,
                                 self.RealmLV,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -10511,6 +10539,7 @@
     IsInTeam = 0    #(BYTE IsInTeam)//是否有队伍
     ServerGroupID = 0    #(DWORD ServerGroupID)//服务器组ID
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -10531,6 +10560,7 @@
         self.IsInTeam,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         self.ServerGroupID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -10547,6 +10577,7 @@
         self.IsInTeam = 0
         self.ServerGroupID = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -10559,6 +10590,7 @@
         length += 2
         length += 1
         length += 1
+        length += 4
         length += 4
         length += 4
 
@@ -10576,6 +10608,7 @@
         data = CommFunc.WriteBYTE(data, self.IsInTeam)
         data = CommFunc.WriteDWORD(data, self.ServerGroupID)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -10589,7 +10622,8 @@
                                 OnlineType:%d,
                                 IsInTeam:%d,
                                 ServerGroupID:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.Head.OutputString(),
@@ -10601,7 +10635,8 @@
                                 self.OnlineType,
                                 self.IsInTeam,
                                 self.ServerGroupID,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -10677,6 +10712,7 @@
     RealmLV = 0    #(WORD RealmLV)//境界
     OnlineType = 0    #(BYTE OnlineType)//0不在线 1在线 2脱机在线
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -10692,6 +10728,7 @@
         self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.OnlineType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -10702,6 +10739,7 @@
         self.RealmLV = 0
         self.OnlineType = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -10712,6 +10750,7 @@
         length += 2
         length += 2
         length += 1
+        length += 4
         length += 4
 
         return length
@@ -10725,6 +10764,7 @@
         data = CommFunc.WriteWORD(data, self.RealmLV)
         data = CommFunc.WriteBYTE(data, self.OnlineType)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -10735,7 +10775,8 @@
                                 LV:%d,
                                 RealmLV:%d,
                                 OnlineType:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.PlayerID,
@@ -10744,7 +10785,8 @@
                                 self.LV,
                                 self.RealmLV,
                                 self.OnlineType,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -19110,6 +19152,7 @@
     ExAttr20 = 0    #(DWORD ExAttr20)//预留的扩展属性字段,用来存放项目特定的属性
     HPEx = 0    #(DWORD HPEx)//当前血量 超过E的记录
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     RoleType = 0    #(DWORD RoleType)//角色类型(各项目可自定义含义,如种族,与职业区分)
     data = None
 
@@ -19218,6 +19261,7 @@
         self.ExAttr20,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.HPEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.RoleType,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
@@ -19322,6 +19366,7 @@
         self.ExAttr20 = 0
         self.HPEx = 0
         self.Face = 0
+        self.FacePic = 0
         self.RoleType = 0
         return
 
@@ -19415,6 +19460,7 @@
         length += 4
         length += 4
         length += 15
+        length += 4
         length += 4
         length += 4
         length += 4
@@ -19527,6 +19573,7 @@
         data = CommFunc.WriteDWORD(data, self.ExAttr20)
         data = CommFunc.WriteDWORD(data, self.HPEx)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         data = CommFunc.WriteDWORD(data, self.RoleType)
         return data
 
@@ -19629,6 +19676,7 @@
                                 ExAttr20:%d,
                                 HPEx:%d,
                                 Face:%d,
+                                FacePic:%d,
                                 RoleType:%d
                                 '''\
                                 %(
@@ -19729,6 +19777,7 @@
                                 self.ExAttr20,
                                 self.HPEx,
                                 self.Face,
+                                self.FacePic,
                                 self.RoleType
                                 )
         return DumpString
@@ -49893,6 +49942,238 @@
 
 
 #------------------------------------------------------
+# B1 17 头像信息 #tagMCFaceInfo
+
+class  tagMCFace(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("FaceID", c_int),    #头像ID
+                  ("LightTime", c_int),    #点亮时间戳
+                  ("ExpireTime", c_int),    #有效时间秒,0为配表固定时间,如果配表时间也为0即代表永久;到期时间=点亮时间+有效时间
+                  ("Star", 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.FaceID = 0
+        self.LightTime = 0
+        self.ExpireTime = 0
+        self.Star = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCFace)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B1 17 头像信息 //tagMCFaceInfo:
+                                FaceID:%d,
+                                LightTime:%d,
+                                ExpireTime:%d,
+                                Star:%d
+                                '''\
+                                %(
+                                self.FaceID,
+                                self.LightTime,
+                                self.ExpireTime,
+                                self.Star
+                                )
+        return DumpString
+
+
+class  tagMCFaceInfo(Structure):
+    Head = tagHead()
+    Count = 0    #(BYTE Count)
+    FaceList = list()    #(vector<tagMCFace> FaceList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x17
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temFaceList = tagMCFace()
+            _pos = temFaceList.ReadData(_lpData, _pos)
+            self.FaceList.append(temFaceList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x17
+        self.Count = 0
+        self.FaceList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        for i in range(self.Count):
+            length += self.FaceList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.FaceList[i].GetLength(), self.FaceList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Count:%d,
+                                FaceList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCFaceInfo=tagMCFaceInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFaceInfo.Head.Cmd,m_NAtagMCFaceInfo.Head.SubCmd))] = m_NAtagMCFaceInfo
+
+
+#------------------------------------------------------
+# B1 18 头像框信息 #tagMCFacePicInfo
+
+class  tagMCFacePic(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("FacePicID", c_int),    #头像框ID
+                  ("LightTime", c_int),    #点亮时间戳
+                  ("ExpireTime", c_int),    #有效时间秒,0为配表固定时间,如果配表时间也为0即代表永久;到期时间=点亮时间+有效时间
+                  ("Star", 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.FacePicID = 0
+        self.LightTime = 0
+        self.ExpireTime = 0
+        self.Star = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCFacePic)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B1 18 头像框信息 //tagMCFacePicInfo:
+                                FacePicID:%d,
+                                LightTime:%d,
+                                ExpireTime:%d,
+                                Star:%d
+                                '''\
+                                %(
+                                self.FacePicID,
+                                self.LightTime,
+                                self.ExpireTime,
+                                self.Star
+                                )
+        return DumpString
+
+
+class  tagMCFacePicInfo(Structure):
+    Head = tagHead()
+    Count = 0    #(BYTE Count)
+    FacePicList = list()    #(vector<tagMCFacePic> FacePicList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x18
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temFacePicList = tagMCFacePic()
+            _pos = temFacePicList.ReadData(_lpData, _pos)
+            self.FacePicList.append(temFacePicList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x18
+        self.Count = 0
+        self.FacePicList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        for i in range(self.Count):
+            length += self.FacePicList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.FacePicList[i].GetLength(), self.FacePicList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Count:%d,
+                                FacePicList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCFacePicInfo=tagMCFacePicInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFacePicInfo.Head.Cmd,m_NAtagMCFacePicInfo.Head.SubCmd))] = m_NAtagMCFacePicInfo
+
+
+#------------------------------------------------------
 # B1 11 功能系统特权信息 #tagMCFuncSysPrivilegeInfoList
 
 class  tagMCFuncSysPrivilegeInfo(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_Face.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_Face.py
new file mode 100644
index 0000000..55c499a
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_Face.py
@@ -0,0 +1,74 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.GMT_Face
+#
+# @todo:头像管理
+# @author hxp
+# @date 2024-09-12
+# @version 1.0
+#
+# 详细描述: 头像管理
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-12 12:00"""
+#-------------------------------------------------------------------------------
+
+import GMCommon
+import ChConfig
+import GameWorld
+
+## 执行逻辑
+#  @param curPlayer 当前玩家
+#  @param gmCmdDict: 命令字典
+#  @return None
+#  @remarks 函数详细说明.
+def OnExec(orderId, gmCmdDict):
+    queryType = gmCmdDict.get(GMCommon.Def_GMKey_QueryType, '')
+    playerFind = gmCmdDict.get(GMCommon.Def_GMKey_PlayerFind, '')
+    opID = GameWorld.ToIntDef(gmCmdDict.get('opID', ''), 0)
+    expireTime = GameWorld.ToIntDef(gmCmdDict.get('expireTime', ''), None)
+    faceType = gmCmdDict.get('faceType', '')
+    opType = gmCmdDict.get('opType', '')
+    
+    if opID <= 0:
+        GMCommon.GMCommandResult(orderId, gmCmdDict, GMCommon.Def_ParamErr)
+        return
+    
+    tagPlayer = None
+    playerManager = GameWorld.GetPlayerManager()
+    
+    if queryType == GMCommon.Def_GMKey_PlayerAccID:
+        queryType = ChConfig.queryType_sqtPlayerByAccID
+        tagPlayer = playerManager.FindPlayerByAccID(str(playerFind))
+    
+    elif queryType == GMCommon.Def_GMKey_PlayerName:
+        queryType = ChConfig.queryType_sqtPlayerByName
+        tagPlayer = playerManager.FindPlayerByName(str(playerFind))
+    
+    else:
+        GMCommon.GMCommandResult(orderId, gmCmdDict, GMCommon.Def_ParamErr)
+        return
+    
+    if not tagPlayer:
+        GMCommon.GMCommandResult(orderId, gmCmdDict, GMCommon.Def_PlayerOfLine)
+#        # 玩家不在线,先记录,等玩家上线后处理
+#        GMShell.AddOfflinePlayerGMTInfo(orderId, queryType, playerFind, gmCmdDict)
+        return
+    
+    isOnlineGMT = True # 是否是在线接收的GM工具命令
+    GMCommon.GMTool_MapServer_Query(queryType, orderId, playerFind, gmCmdDict, "GMTFace", [orderId, isOnlineGMT, faceType, opID, expireTime, opType], False)
+    return
+
+#def OnOfflineGMTInfo(curPlayer, tagMapID, gmCmdDict):
+#    orderId = gmCmdDict.get('orderId', '')
+#    titleID = GameWorld.ToIntDef(gmCmdDict.get('titleID', ''), 0)
+#    expireTime = GameWorld.ToIntDef(gmCmdDict.get('expireTime', ''), 0)
+#    isOnlineGMT = False # 是否是在线接收的GM工具命令
+#    cmdStr = str([orderId, isOnlineGMT, titleID, expireTime])
+#    GameWorld.GetPlayerManager().MapServer_QueryPlayer(0, 0, curPlayer.GetPlayerID(), tagMapID, 'GMTAddTitle',
+#                                                       cmdStr, len(cmdStr), curPlayer.GetRouteServerIndex())
+#    return
+
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldArena.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldArena.py
index 1ea70bf..316afc6 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldArena.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldArena.py
@@ -986,8 +986,10 @@
     curOrder = billBoard.IndexOfByID(playerID) + 1  # 更新前获取名次
     cmpValue2 = fightPower / ShareDefine.Def_PerPointValue
     cmpValue3 = fightPower % ShareDefine.Def_PerPointValue
+    face = curPlayer.GetFace()
+    facePic =  curPlayer.GetFacePic()
     PlayerBillboard.UpdatePlayerBillboard(playerID, playerName, opInfo, ShareDefine.Def_BT_Arena, playerJob,
-                                          realmLV, playerLV, updScore, autoSort=False, cmpValue2=cmpValue2, cmpValue3=cmpValue3)
+                                          realmLV, playerLV, updScore, autoSort=False, cmpValue2=cmpValue2, cmpValue3=cmpValue3, value3=face, value4=facePic)
     
     awardItemList = []
     if isWin:
@@ -1014,8 +1016,10 @@
             tagAccID = cacheDict["AccID"]
             tagCmpValue2 = tagFightPower / ShareDefine.Def_PerPointValue
             tagCmpValue3 = tagFightPower % ShareDefine.Def_PerPointValue
+            tagFace = cacheDict.get("Face", 0)
+            tagFacePic = cacheDict.get("FacePic", 0)
             PlayerBillboard.UpdatePlayerBillboard(tagPlayerID, tagPlayerName, tagOpInfo, ShareDefine.Def_BT_Arena, tagJob,
-                                                  tagRealmLV, tagLV, updTagScore, autoSort=False, cmpValue2=tagCmpValue2, cmpValue3=tagCmpValue3)
+                                                  tagRealmLV, tagLV, updTagScore, autoSort=False, cmpValue2=tagCmpValue2, cmpValue3=tagCmpValue3, value3=tagFace, value4=tagFacePic)
     else:
         robotBillboardData = billBoard.FindByID(tagPlayerID)
         if robotBillboardData:
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldSkyTower.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldSkyTower.py
index db63e2a..97f2b0b 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldSkyTower.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldSkyTower.py
@@ -227,6 +227,7 @@
         playerInfo.LV = cacheDict.get("LV", 1)
         playerInfo.RealmLV = cacheDict.get("RealmLV", 0)
         playerInfo.Face = cacheDict.get("Face", 0)
+        playerInfo.FacePic = cacheDict.get("FacePic", 0)
         
         passPlayerList.append(playerInfo)
         
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
index 7bdeb3a..7b88456 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -55,6 +55,16 @@
                         ("list", "LimitServerGroupIDList", 0),
                         ),
 
+                "PlayerFace":(
+                        ("DWORD", "FaceID", 1),
+                        ("BYTE", "UnlockDefault", 0),
+                        ),
+
+                "PlayerFacePic":(
+                        ("DWORD", "FacePicID", 1),
+                        ("BYTE", "UnlockDefault", 0),
+                        ),
+
                 "WorldLV":(
                         ("WORD", "WorldLV", 1),
                         ("DWORD", "OpenServerSecond", 0),
@@ -1207,6 +1217,26 @@
         
     def GetLimitServerGroupIDRangeList(self): return self.attrTuple[0] # 限制创角的服务器组ID范围列表 list
     def GetLimitServerGroupIDList(self): return self.attrTuple[1] # 限制创角的服务器组ID列表 list
+
+# 头像表
+class IPY_PlayerFace():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetFaceID(self): return self.attrTuple[0] # 头像ID DWORD
+    def GetUnlockDefault(self): return self.attrTuple[1] # 是否默认激活 BYTE
+
+# 头像框表
+class IPY_PlayerFacePic():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetFacePicID(self): return self.attrTuple[0] # 头像框ID DWORD
+    def GetUnlockDefault(self): return self.attrTuple[1] # 是否默认激活 BYTE
 
 # 世界等级表格
 class IPY_WorldLV():
@@ -2900,6 +2930,8 @@
         self.__LoadFileData("FuncConfig", onlyCheck)
         self.__LoadFileData("CreateRole", onlyCheck)
         self.__LoadFileData("CreateRoleLimitServer", onlyCheck)
+        self.__LoadFileData("PlayerFace", onlyCheck)
+        self.__LoadFileData("PlayerFacePic", onlyCheck)
         self.__LoadFileData("WorldLV", onlyCheck)
         self.__LoadFileData("Family", onlyCheck)
         self.__LoadFileData("FamilyEmblem", onlyCheck)
@@ -3230,6 +3262,20 @@
         self.CheckLoadData("CreateRoleLimitServer")
         return self.ipyCreateRoleLimitServerCache[index]
 
+    def GetPlayerFaceCount(self):
+        self.CheckLoadData("PlayerFace")
+        return self.ipyPlayerFaceLen
+    def GetPlayerFaceByIndex(self, index):
+        self.CheckLoadData("PlayerFace")
+        return self.ipyPlayerFaceCache[index]
+
+    def GetPlayerFacePicCount(self):
+        self.CheckLoadData("PlayerFacePic")
+        return self.ipyPlayerFacePicLen
+    def GetPlayerFacePicByIndex(self, index):
+        self.CheckLoadData("PlayerFacePic")
+        return self.ipyPlayerFacePicCache[index]
+
     def GetWorldLVCount(self):
         self.CheckLoadData("WorldLV")
         return self.ipyWorldLVLen
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
index b3ced27..1ae0888 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
@@ -931,6 +931,10 @@
     elif packType == IPY_GameServer.CDBPlayerRefresh_Face:
         curPlayer.SetFace(packValue)
         PlayerBillboard.UpdateBillboardFace(curPlayer)
+    elif packType == IPY_GameServer.CDBPlayerRefresh_HairColor:
+        #c++头像外框 用头发颜色通知  - 遗漏问题
+        curPlayer.SetFacePic(packValue)
+        PlayerBillboard.UpdateBillboardFacePic(curPlayer)
         
     #社交信息
     PlayerSocial.UpdateSocialInfo(curPlayer.GetID(), packType, packValue)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerBillboard.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerBillboard.py
index 58dc777..f20f2c6 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerBillboard.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerBillboard.py
@@ -642,11 +642,10 @@
 
 def GetBillboardOperateInfo(curPlayer):
     # 排行榜中所保存的运营商相关信息
-    return curPlayer.GetFace()
-#    platform = curPlayer.GetAccID()
-#    if platform in ["tencent"]:
-#        return curPlayer.GetOperateInfo()
-#    return platform
+    platform = curPlayer.GetAccID()
+    if platform in ["tencent"]:
+        return curPlayer.GetOperateInfo()
+    return platform
 
 def UpdateFamilyBillboard(bType, familyBillInfo, cmpValue, cmpValue2=0):
     ## 更新仙盟排行榜
@@ -675,6 +674,8 @@
     playerJob = 0
     playerName = ""
     playerRealmLV = 0
+    face = 0
+    facePic = 0
     
     if curPlayer:
         playerID = curPlayer.GetID()
@@ -682,12 +683,16 @@
         playerName = curPlayer.GetName()
         playerRealmLV = curPlayer.GetOfficialRank()
         playerOpInfo = GetBillboardOperateInfo(curPlayer)
+        face = curPlayer.GetFace()
+        facePic = curPlayer.GetFacePic()
     else:
         socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(playerID)
         if socialPlayer:
             playerJob = socialPlayer.playerInfo.Job
             playerName = socialPlayer.playerInfo.PlayerName
             playerRealmLV = socialPlayer.playerInfo.RealmLV
+            face = socialPlayer.playerInfo.Face
+            facePic = socialPlayer.playerInfo.FacePic
         else:
             curCache = PlayerViewCache.FindViewCache(playerID)
             if curCache:
@@ -695,6 +700,8 @@
                 playerJob = cacheDict["Job"]
                 playerName = cacheDict["Name"]
                 playerRealmLV = cacheDict["RealmLV"]
+                face = cacheDict.get("Face", 0)
+                facePic = cacheDict.get("FacePic", 0)
                 
     if not playerName and playerID < 10000:
         playerJob = random.choice([1, 2])
@@ -711,7 +718,7 @@
     if autoSort:
         gameWorld.SetDict(Def_Key_BillboardSortTick % bType, tick)
         
-    UpdatePlayerBillboard(playerID, playerName, playerOpInfo, bType, playerJob, value1, value2, cmpValue, autoSort, cmpValue2, cmpValue3)
+    UpdatePlayerBillboard(playerID, playerName, playerOpInfo, bType, playerJob, value1, value2, cmpValue, autoSort, cmpValue2, cmpValue3, value3=face, value4=facePic)
     return
 
 #---------------------------------------------------------------------
@@ -975,6 +982,8 @@
     
     billboardMgr = GameWorld.GetBillboard()
     for billboardIndex in ShareDefine.BillboardTypeList:
+        if billboardIndex in ShareDefine.FamilyBillboardList:
+            continue
         billBoard = billboardMgr.FindBillboard(billboardIndex)
         if not billBoard:
             #找不到这类型排行榜
@@ -985,6 +994,30 @@
             #该玩家没有在排行榜上
             continue
         
-        playerBillBoardData.SetName2(str(curFace))
+        playerBillBoardData.SetValue3(curFace)
+        
+    return
+
+def UpdateBillboardFacePic(curPlayer):
+    ## 更新排行榜中的玩家头像
+    
+    curPlayerID = curPlayer.GetID()
+    curFacePic = curPlayer.GetFacePic()
+    
+    billboardMgr = GameWorld.GetBillboard()
+    for billboardIndex in ShareDefine.BillboardTypeList:
+        if billboardIndex in ShareDefine.FamilyBillboardList:
+            continue
+        billBoard = billboardMgr.FindBillboard(billboardIndex)
+        if not billBoard:
+            #找不到这类型排行榜
+            continue
+        
+        playerBillBoardData = billBoard.FindByID(curPlayerID)
+        if not playerBillBoardData:
+            #该玩家没有在排行榜上
+            continue
+        
+        playerBillBoardData.SetValue4(curFacePic)
         
     return
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
index 0a354b1..f3eaaaa 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
@@ -2153,8 +2153,10 @@
     curMember.SetLV(curPlayer.GetLV())
     curMember.SetReincarnationLv(curPlayer.GetReincarnationLv())
     curMember.SetJob(curPlayer.GetJob())
-    curMember.SetOperateInfo(curPlayer.GetFace()) #curPlayer.GetOperateInfo()
+    curMember.SetOperateInfo(curPlayer.GetOperateInfo())
     curMember.SetOfficialRank(curPlayer.GetOfficialRank())
+    curMember.SetFace(curPlayer.GetFace())
+    curMember.SetFacePic(curPlayer.GetFacePic())
     return
 #---------------------------------------------------------------------
 ## 玩家刷新
@@ -3743,6 +3745,7 @@
     clientPack.Job = curPlayer.GetJob()
     clientPack.RealmLV = curPlayer.GetOfficialRank()
     clientPack.Face = curPlayer.GetFace()
+    clientPack.FacePic = curPlayer.GetFacePic()
     NetPackCommon.SendFakePack(tagPlayer, clientPack)
     GameWorld.DebugLog("邀请传功: tagPlayerID=%s, %s" % (tagPlayerID, PyGameData.g_chuangongPlayerDict), playerID)
     return
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFriend.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFriend.py
index 2b5adfb..82dad65 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFriend.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFriend.py
@@ -127,6 +127,7 @@
         askFriendPack.LV = curPlayer.GetLV()
         askFriendPack.RealmLV = curPlayer.GetOfficialRank()
         askFriendPack.Face = curPlayer.GetFace()
+        askFriendPack.FacePic = curPlayer.GetFacePic()
         
         NetPackCommon.SendFakePack(tagPlayer, askFriendPack) 
 
@@ -660,6 +661,7 @@
         rceFriendsData.Job = tagPlayer.GetJob()
         rceFriendsData.RealmLV = tagPlayer.GetOfficialRank()
         rceFriendsData.Face = tagPlayer.GetFace()
+        rceFriendsData.FacePic = tagPlayer.GetFacePic()
         sendPack.FriendsList.append(rceFriendsData)
         
     #GameWorld.DebugLog("Client_RecommendFriends:%s"%sendPack.FriendsList)
@@ -721,6 +723,7 @@
         rceFriendsData.Job = tagPlayer.GetJob()
         rceFriendsData.RealmLV = tagPlayer.GetOfficialRank()
         rceFriendsData.Face = tagPlayer.GetFace()
+        rceFriendsData.FacePic = tagPlayer.GetFacePic()
         sendPack.FriendsList.append(rceFriendsData)
         
     
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerRequest.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerRequest.py
index f0db17a..9364f66 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerRequest.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerRequest.py
@@ -116,7 +116,8 @@
     PyGameData.g_playerRequests[curTagPlayerID][(curPlayer.GetID(), requestType)] = [curPlayer.GetName(), 
                                                                                      curPlayer.GetLV(),
                                                                                      curPlayer.GetOfficialRank(),
-                                                                                     curPlayer.GetFace()]
+                                                                                     curPlayer.GetFace(),
+                                                                                     curPlayer.GetFacePic()]
     return
 
 
@@ -159,6 +160,7 @@
         askFriendPack.LV = playerInfo[1]
         askFriendPack.RealmLV = playerInfo[2]
         askFriendPack.Face = playerInfo[3]
+        askFriendPack.FacePic = playerInfo[4]
         NetPackCommon.SendFakePack(curPlayer, askFriendPack) 
     
     return
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerSocial.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerSocial.py
index 24c92d0..778d090 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerSocial.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerSocial.py
@@ -842,6 +842,7 @@
         self.playerInfo.RealmLV = curPlayer.GetOfficialRank()
         self.playerInfo.OnlineType = 1      # 0 不在线  1 在线 2 脱机在线  
         self.playerInfo.Face = curPlayer.GetFace()
+        self.playerInfo.FacePic = curPlayer.GetFacePic()
         if not self.playerInfo.RefCount:
             self.playerInfo.RefCount = 1
         return
@@ -855,6 +856,7 @@
         packStruct.RealmLV = self.playerInfo.RealmLV
         packStruct.OnlineType = self.playerInfo.OnlineType
         packStruct.Face = self.playerInfo.Face
+        packStruct.FacePic = self.playerInfo.FacePic
         return packStruct
     
     # 更新玩家数据引用, 根据需求是否更新玩家数据
@@ -903,6 +905,7 @@
             playerSocial.RealmLV = 1
             playerSocial.OnlineType = ChConfig.Def_Offline
             playerSocial.Face = 0
+            playerSocial.FacePic = 0
         else:
             cacheDict = PlayerViewCache.GetCachePropDataDict(curCache)
     
@@ -914,6 +917,7 @@
             playerSocial.RealmLV = cacheDict["RealmLV"]
             playerSocial.OnlineType = ChConfig.Def_Offline
             playerSocial.Face = cacheDict.get("Face", 0)
+            playerSocial.FacePic = cacheDict.get("FacePic", 0)
             
         self.SocialInfo[playerID] = SocialPlayerData(playerSocial)
         socialPlayer = self.SocialInfo[playerID]
@@ -1087,6 +1091,8 @@
         socialPlayer.playerInfo.PlayerName = value
     elif notifyType == IPY_PlayerDefine.CDBPlayerRefresh_Face:
         socialPlayer.playerInfo.Face = value
+    elif notifyType == IPY_PlayerDefine.CDBPlayerRefresh_HairColor:
+        socialPlayer.playerInfo.FacePic = value
     else:
         return
     
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerTalk.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerTalk.py
index 0a3d524..c1f7cf3 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerTalk.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerTalk.py
@@ -465,7 +465,8 @@
         coupleJob = couple.GetCoupleJob(playerID)
         bridePriceMaxID = couple.BridePriceMaxID
     face = player.GetFace()
-    extraValueStr = "%s|%s|%s|%s|%s" % (extraValueStr, coupleName, coupleJob, bridePriceMaxID, face)
+    facePic = player.GetFacePic()
+    extraValueStr = "%s|%s|%s|%s|%s|%s" % (extraValueStr, coupleName, coupleJob, bridePriceMaxID, face, facePic)
     return extraValueStr
 
 
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
index 6c146c4..c37c7cc 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
@@ -429,6 +429,7 @@
             answerPack.OnlineType = ChConfig.Def_Offline
             answerPack.ServerGroupID = 0
             answerPack.Face = 0
+            answerPack.FacePic = 0
         else:
             cacheDict = GetCachePropDataDict(curCache)
             answerPack.PlayerID = clientPack.PlayerID
@@ -438,6 +439,7 @@
             answerPack.RealmLV = cacheDict["RealmLV"]
             answerPack.OnlineType = ChConfig.Def_Offline
             answerPack.Face = cacheDict.get("Face", 0)
+            answerPack.FacePic = cacheDict.get("FacePic", 0)
             
             if GameWorld.IsCrossServer():
                 answerPack.ServerGroupID = cacheDict.get("ServerGroupID", 0)
@@ -453,6 +455,7 @@
         answerPack.IsInTeam = tagPlayer.GetTeamID() > 0
         answerPack.ServerGroupID = PlayerControl.GetPlayerServerGroupID(tagPlayer)
         answerPack.Face = tagPlayer.GetFace()
+        answerPack.FacePic = tagPlayer.GetFacePic()
 
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
     NetPackCommon.SendFakePack(curPlayer, answerPack)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py b/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
index 92b6bac..695641c 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
@@ -2400,6 +2400,7 @@
         ('OnlineType', ctypes.c_ubyte),
         ('RefCount', ctypes.c_ulong),
         ('Face', ctypes.c_ulong),
+        ('FacePic', ctypes.c_ulong),
         ('ADOResult', ctypes.c_ulong),
     ]
 
@@ -2425,6 +2426,7 @@
         self.OnlineType, pos = CommFunc.ReadBYTE(buf, pos)
         self.RefCount, pos = CommFunc.ReadDWORD(buf, pos)
         self.Face, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FacePic, pos = CommFunc.ReadDWORD(buf, pos)
         return self.getLength()
 
 
@@ -2446,6 +2448,7 @@
             OnlineType = %s,
             RefCount = %s,
             Face = %s,
+            FacePic = %s,
             ADOResult = %s,
             '''%(
                 self.PlayerID,
@@ -2456,6 +2459,7 @@
                 self.OnlineType,
                 self.RefCount,
                 self.Face,
+                self.FacePic,
                 self.ADOResult,
             )
         return output
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
index f61d80a..26cd0af 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -907,6 +907,9 @@
                              Def_BT_SkyTower, Def_BT_CharmTotal, Def_BT_CharmWeek, Def_BT_CharmDay, Def_BT_AlineInvade
                              ]
 
+#仙盟榜单类型
+FamilyBillboardList = [Def_BT_BossTrialSubmitFamily, Def_BT_BossTrialSubmitFamilyBak]
+
 ##---比率---
 #百分率
 Def_Percentage = 100
@@ -1802,7 +1805,7 @@
 )=range(5)
 
 # 战斗力模块类型
-Def_MFPType_Max = 34
+Def_MFPType_Max = 36
 ModuleFightPowerTypeList = (
 Def_MFPType_Role, # 角色 0
 Def_MFPType_Equip, # 装备(装备本身) 1
@@ -1837,6 +1840,8 @@
 Def_MFPType_Shentong, # 神通 30
 Def_MFPType_FamilyZhenfa, # 阵法 31
 Def_MFPType_GatherTheSoul, # 聚魂新 32
+Def_MFPType_Face, # 头像 33
+Def_MFPType_FacePic, # 头像框 34
 Def_MFPType_Other, # 其他
 ) = range(Def_MFPType_Max)
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index cb537c8..0e693f8 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -299,6 +299,30 @@
 PacketSubCMD_1=0x36
 PacketCallFunc_1=OnTitleStarUp
 
+;头像
+[PlayerFace]
+ScriptName = Player\PlayerFace.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 4
+
+PacketCMD_1=0xB2
+PacketSubCMD_1=0x26
+PacketCallFunc_1=OnFaceChange
+
+PacketCMD_2=0xB2
+PacketSubCMD_2=0x27
+PacketCallFunc_2=OnFaceStarUP
+
+PacketCMD_3=0xB2
+PacketSubCMD_3=0x28
+PacketCallFunc_3=OnFacePicChange
+
+PacketCMD_4=0xB2
+PacketSubCMD_4=0x29
+PacketCallFunc_4=OnFacePicStarUP
+
 ;事件
 [EventShell]
 ScriptName = Event\EventShell.py
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 0ecb5fb..5dd5a34 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -518,6 +518,8 @@
 Def_Effect_GubaoPiece = 270     #古宝碎片效果ID, A值-古宝ID
 Def_Effect_TrainRealmLV = 272     #境界培养卡,值A-功能(1-坐骑;2-灵宠;3-灵器), 值B-境界
 Def_Effect_TiandaoQiyun = 273   #增加天道树气运;A值-增加值   效果值B: 领取是否默认直接使用
+Def_Effect_Face = 274   #头像物品;A值-头像ID
+Def_Effect_FacePic = 275   #头像框物品;A值-头像框ID
 #----以下未使用或代码依然存在的---
 Def_Effect_ItemGiveGongXun = 1920        #使用道具给予功勋
 Def_Effect_ItemGiveRuneJH = 1925       #使用道具给予符印精华
@@ -2323,7 +2325,7 @@
                          1000 * 5,                         # 玩家领取战盟战奖励处理间隔
                          1000,                              #XP回复间隔
                          1000 * 5,                         #查询地图NPC信息tick
-                         1000 * 60 * 10,                         #玩家称号时效
+                         1000 * 60,                         #每分钟处理
                          400,                               #吸血
                          400,                               #吸蓝
                          1000 * 3,                         # 仓库整理间隔
@@ -2406,7 +2408,7 @@
 TYPE_Player_Tick_FamilysWarAward,    # 玩家领取战盟战奖励处理间隔
 TYPE_Player_Tick_AddXPTick,         #增加XP值的tick
 TYPE_Player_Tick_QueryMapNPCInfo,   #查询地图NPC信息tick
-TYPE_Player_Tick_Dienstgrad,        #玩家称号时效
+TYPE_Player_Tick_Minute,        #每分钟处理
 TYPE_Player_Tick_SuckBlood,        #吸血
 TYPE_Player_Tick_SuckMagic,        #吸蓝
 TYPE_Player_Tick_WareHouseSort,    # 仓库整理间隔
@@ -4028,6 +4030,14 @@
 Def_PDict_WishingWellItem = "WishingWellItem_%s_%s"  # 物品ID,是否极品、是否绑定信息 参数(类型,物品数据)
 Def_PDict_WishingWellItemCnt = "WishingWellItemCnt_%s_%s"  # 物品数量记录 参数(类型,物品数据)
 
+#头像
+Def_PDict_FaceLightTime = "FaceLightTime_%s"  # 头像点亮时间戳,参数(头像ID)
+Def_PDict_FaceExpireTimes = "FaceExpireTimes_%s"  # 头像有效时长秒,参数(头像ID)
+Def_PDict_FaceStar = "FaceStar_%s"  # 头像星级,参数(头像ID)
+Def_PDict_FacePicLightTime = "FacePicLightTime_%s"  # 头像框点亮时间戳,参数(头像ID)
+Def_PDict_FacePicExpireTimes = "FacePicExpireTimes_%s"  # 头像框有效时长秒,参数(头像ID)
+Def_PDict_FacePicStar = "FacePicStar_%s"  # 头像框星级,参数(头像ID)
+
 #聊天气泡
 Def_PDict_ChatBubbleBoxState = "ChatBubbleBoxState_%s"  # 聊天气泡状态, 参数(key编号)
 
@@ -5081,7 +5091,9 @@
 Def_CalcAttrFunc_FamilyZhenfa, # 仙盟阵法 60
 Def_CalcAttrFunc_GatherTheSoul, # 聚魂新 61
 Def_CalcAttrFunc_GubaoResonance, # 古宝共鸣 62
-) = range(63)
+Def_CalcAttrFunc_Face, # 头像 63
+Def_CalcAttrFunc_FacePic, # 头像框 64
+) = range(65)
 
 # 技能功能点列表  - 默认不算战力,不享受百分比加成,技能功能点暂时配置,之后优化技能属性逻辑后可去掉
 CalcAttrFuncSkillList = [Def_CalcAttrFunc_HorseSkill, Def_CalcAttrFunc_PetSkill, Def_CalcAttrFunc_DogzBattleSkill]
@@ -5124,6 +5136,8 @@
                             ShareDefine.Def_MFPType_Coat:[Def_CalcAttrFunc_Coat],
                             ShareDefine.Def_MFPType_Dogz:[Def_CalcAttrFunc_Dogz, Def_CalcAttrFunc_DogzEquip, Def_CalcAttrFunc_DogzEquipPlus, Def_CalcAttrFunc_DogzBattleSkill],
                             ShareDefine.Def_MFPType_FamilyZhenfa:[Def_CalcAttrFunc_FamilyZhenfa],
+                            ShareDefine.Def_MFPType_Face:[Def_CalcAttrFunc_Face],
+                            ShareDefine.Def_MFPType_FacePic:[Def_CalcAttrFunc_FacePic],
                             ShareDefine.Def_MFPType_Other:[Def_CalcAttrFunc_Success, Def_CalcAttrFunc_FamilyTech, Def_CalcAttrFunc_EquipDecompose],
                             }
 
@@ -5135,7 +5149,7 @@
                ShareDefine.Def_MFPType_PetSoul:"宠魂", ShareDefine.Def_MFPType_HorseSoul:"骑魂", ShareDefine.Def_MFPType_FaQi:"法器", ShareDefine.Def_MFPType_Dogz:"神兽",
                ShareDefine.Def_MFPType_Coat:"时装", ShareDefine.Def_MFPType_Love:"情缘", ShareDefine.Def_MFPType_Charm:"魅力", ShareDefine.Def_MFPType_LianTi:"炼体",
                ShareDefine.Def_MFPType_Enchant:"附魔", ShareDefine.Def_MFPType_Gubao:"古宝", ShareDefine.Def_MFPType_Shentong:"神通", ShareDefine.Def_MFPType_FamilyZhenfa:"阵法", 
-               ShareDefine.Def_MFPType_GatherTheSoul:"聚魂新", ShareDefine.Def_MFPType_Other:"其他",
+               ShareDefine.Def_MFPType_GatherTheSoul:"聚魂新", ShareDefine.Def_MFPType_Face:"头像", ShareDefine.Def_MFPType_FacePic:"头像框", ShareDefine.Def_MFPType_Other:"其他",
                }
 
 FuncIndexName = {
@@ -5154,7 +5168,7 @@
                  Def_CalcAttrFunc_LoveRing:"情戒基础", Def_CalcAttrFunc_LoveRingCouple:"情戒仙侣", Def_CalcAttrFunc_Charm:"魅力", Def_CalcAttrFunc_LianTi:"炼体",
                  Def_CalcAttrFunc_Enchant:"附魔", Def_CalcAttrFunc_LingQiEnchant:"灵器附魔", Def_CalcAttrFunc_Gubao:"古宝", Def_CalcAttrFunc_Shentong:"神通",
                  Def_CalcAttrFunc_HorseStar:"坐骑星级", Def_CalcAttrFunc_PetStar:"宠物星级", Def_CalcAttrFunc_TitleStar:"称号星级", Def_CalcAttrFunc_FamilyZhenfa:"阵法",
-                 Def_CalcAttrFunc_GatherTheSoul:"聚魂新", Def_CalcAttrFunc_GubaoResonance:"古宝共鸣",
+                 Def_CalcAttrFunc_GatherTheSoul:"聚魂新", Def_CalcAttrFunc_GubaoResonance:"古宝共鸣", Def_CalcAttrFunc_Face:"头像", Def_CalcAttrFunc_FacePic:"头像框",
                  }
 #-------------------------------------------------------------------------------
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index 2f32ce0..b32ec8f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -19416,6 +19416,214 @@
 
 
 #------------------------------------------------------
+# B2 26 头像幻化 #tagCMFaceChange
+
+class  tagCMFaceChange(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("FaceID", c_int),    # 幻化的ID
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x26
+        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 = 0x26
+        self.FaceID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMFaceChange)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 26 头像幻化 //tagCMFaceChange:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                FaceID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.FaceID
+                                )
+        return DumpString
+
+
+m_NAtagCMFaceChange=tagCMFaceChange()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFaceChange.Cmd,m_NAtagCMFaceChange.SubCmd))] = m_NAtagCMFaceChange
+
+
+#------------------------------------------------------
+# B2 28 头像框幻化 #tagCMFacePicChange
+
+class  tagCMFacePicChange(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("FacePicID", c_int),    # 幻化的ID
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x28
+        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 = 0x28
+        self.FacePicID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMFacePicChange)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 28 头像框幻化 //tagCMFacePicChange:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                FacePicID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.FacePicID
+                                )
+        return DumpString
+
+
+m_NAtagCMFacePicChange=tagCMFacePicChange()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFacePicChange.Cmd,m_NAtagCMFacePicChange.SubCmd))] = m_NAtagCMFacePicChange
+
+
+#------------------------------------------------------
+# B2 29 头像框升星 #tagCMFacePicStarUP
+
+class  tagCMFacePicStarUP(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("FacePicID", c_int),    
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x29
+        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 = 0x29
+        self.FacePicID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMFacePicStarUP)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 29 头像框升星 //tagCMFacePicStarUP:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                FacePicID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.FacePicID
+                                )
+        return DumpString
+
+
+m_NAtagCMFacePicStarUP=tagCMFacePicStarUP()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFacePicStarUP.Cmd,m_NAtagCMFacePicStarUP.SubCmd))] = m_NAtagCMFacePicStarUP
+
+
+#------------------------------------------------------
+# B2 27 头像升星 #tagCMFaceStarUP
+
+class  tagCMFaceStarUP(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("FaceID", c_int),    
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x27
+        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 = 0x27
+        self.FaceID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMFaceStarUP)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 27 头像升星 //tagCMFaceStarUP:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                FaceID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.FaceID
+                                )
+        return DumpString
+
+
+m_NAtagCMFaceStarUP=tagCMFaceStarUP()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFaceStarUP.Cmd,m_NAtagCMFaceStarUP.SubCmd))] = m_NAtagCMFaceStarUP
+
+
+#------------------------------------------------------
 # B2 25 新聚魂操作 #tagCMGatherTheSoulOP
 
 class  tagCMGatherTheSoulOP(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 86a210a..369ee95 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -1180,6 +1180,7 @@
     Job = 0    #(BYTE Job)// 玩家职业
     RealmLV = 0    #(WORD RealmLV)// 玩家境界等级
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -1198,6 +1199,7 @@
         self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -1212,6 +1214,7 @@
         self.Job = 0
         self.RealmLV = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -1223,6 +1226,7 @@
         length += 2
         length += 1
         length += 2
+        length += 4
         length += 4
 
         return length
@@ -1237,6 +1241,7 @@
         data = CommFunc.WriteBYTE(data, self.Job)
         data = CommFunc.WriteWORD(data, self.RealmLV)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -1248,7 +1253,8 @@
                                 LV:%d,
                                 Job:%d,
                                 RealmLV:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.Head.OutputString(),
@@ -1258,7 +1264,8 @@
                                 self.LV,
                                 self.Job,
                                 self.RealmLV,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -5276,6 +5283,7 @@
     Job = 0    #(BYTE Job)
     RealmLV = 0    #(WORD RealmLV)//境界	
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -5290,6 +5298,7 @@
         self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -5299,6 +5308,7 @@
         self.Job = 0
         self.RealmLV = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -5308,6 +5318,7 @@
         length += 4
         length += 1
         length += 2
+        length += 4
         length += 4
 
         return length
@@ -5320,6 +5331,7 @@
         data = CommFunc.WriteBYTE(data, self.Job)
         data = CommFunc.WriteWORD(data, self.RealmLV)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -5329,7 +5341,8 @@
                                 LV:%d,
                                 Job:%d,
                                 RealmLV:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.ID,
@@ -5337,7 +5350,8 @@
                                 self.LV,
                                 self.Job,
                                 self.RealmLV,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -5418,6 +5432,7 @@
     LV = 0    #(WORD LV)//等级
     RealmLV = 0    #(WORD RealmLV)//境界
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -5432,6 +5447,7 @@
         self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -5441,6 +5457,7 @@
         self.LV = 0
         self.RealmLV = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -5450,6 +5467,7 @@
         length += 1
         length += 2
         length += 2
+        length += 4
         length += 4
 
         return length
@@ -5462,6 +5480,7 @@
         data = CommFunc.WriteWORD(data, self.LV)
         data = CommFunc.WriteWORD(data, self.RealmLV)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -5471,7 +5490,8 @@
                                 Job:%d,
                                 LV:%d,
                                 RealmLV:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.PlayerID,
@@ -5479,7 +5499,8 @@
                                 self.Job,
                                 self.LV,
                                 self.RealmLV,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -9314,6 +9335,7 @@
     LV = 0    #(WORD LV)
     RealmLV = 0    #(WORD RealmLV)//境界等级
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -9330,6 +9352,7 @@
         self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -9342,6 +9365,7 @@
         self.LV = 0
         self.RealmLV = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -9351,6 +9375,7 @@
         length += 33
         length += 2
         length += 2
+        length += 4
         length += 4
 
         return length
@@ -9363,6 +9388,7 @@
         data = CommFunc.WriteWORD(data, self.LV)
         data = CommFunc.WriteWORD(data, self.RealmLV)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -9372,7 +9398,8 @@
                                 Name:%s,
                                 LV:%d,
                                 RealmLV:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.Head.OutputString(),
@@ -9380,7 +9407,8 @@
                                 self.Name,
                                 self.LV,
                                 self.RealmLV,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -10511,6 +10539,7 @@
     IsInTeam = 0    #(BYTE IsInTeam)//是否有队伍
     ServerGroupID = 0    #(DWORD ServerGroupID)//服务器组ID
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -10531,6 +10560,7 @@
         self.IsInTeam,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         self.ServerGroupID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -10547,6 +10577,7 @@
         self.IsInTeam = 0
         self.ServerGroupID = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -10559,6 +10590,7 @@
         length += 2
         length += 1
         length += 1
+        length += 4
         length += 4
         length += 4
 
@@ -10576,6 +10608,7 @@
         data = CommFunc.WriteBYTE(data, self.IsInTeam)
         data = CommFunc.WriteDWORD(data, self.ServerGroupID)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -10589,7 +10622,8 @@
                                 OnlineType:%d,
                                 IsInTeam:%d,
                                 ServerGroupID:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.Head.OutputString(),
@@ -10601,7 +10635,8 @@
                                 self.OnlineType,
                                 self.IsInTeam,
                                 self.ServerGroupID,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -10677,6 +10712,7 @@
     RealmLV = 0    #(WORD RealmLV)//境界
     OnlineType = 0    #(BYTE OnlineType)//0不在线 1在线 2脱机在线
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     data = None
 
     def __init__(self):
@@ -10692,6 +10728,7 @@
         self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
         self.OnlineType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -10702,6 +10739,7 @@
         self.RealmLV = 0
         self.OnlineType = 0
         self.Face = 0
+        self.FacePic = 0
         return
 
     def GetLength(self):
@@ -10712,6 +10750,7 @@
         length += 2
         length += 2
         length += 1
+        length += 4
         length += 4
 
         return length
@@ -10725,6 +10764,7 @@
         data = CommFunc.WriteWORD(data, self.RealmLV)
         data = CommFunc.WriteBYTE(data, self.OnlineType)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         return data
 
     def OutputString(self):
@@ -10735,7 +10775,8 @@
                                 LV:%d,
                                 RealmLV:%d,
                                 OnlineType:%d,
-                                Face:%d
+                                Face:%d,
+                                FacePic:%d
                                 '''\
                                 %(
                                 self.PlayerID,
@@ -10744,7 +10785,8 @@
                                 self.LV,
                                 self.RealmLV,
                                 self.OnlineType,
-                                self.Face
+                                self.Face,
+                                self.FacePic
                                 )
         return DumpString
 
@@ -19110,6 +19152,7 @@
     ExAttr20 = 0    #(DWORD ExAttr20)//预留的扩展属性字段,用来存放项目特定的属性
     HPEx = 0    #(DWORD HPEx)//当前血量 超过E的记录
     Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
     RoleType = 0    #(DWORD RoleType)//角色类型(各项目可自定义含义,如种族,与职业区分)
     data = None
 
@@ -19218,6 +19261,7 @@
         self.ExAttr20,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.HPEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.RoleType,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
@@ -19322,6 +19366,7 @@
         self.ExAttr20 = 0
         self.HPEx = 0
         self.Face = 0
+        self.FacePic = 0
         self.RoleType = 0
         return
 
@@ -19415,6 +19460,7 @@
         length += 4
         length += 4
         length += 15
+        length += 4
         length += 4
         length += 4
         length += 4
@@ -19527,6 +19573,7 @@
         data = CommFunc.WriteDWORD(data, self.ExAttr20)
         data = CommFunc.WriteDWORD(data, self.HPEx)
         data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
         data = CommFunc.WriteDWORD(data, self.RoleType)
         return data
 
@@ -19629,6 +19676,7 @@
                                 ExAttr20:%d,
                                 HPEx:%d,
                                 Face:%d,
+                                FacePic:%d,
                                 RoleType:%d
                                 '''\
                                 %(
@@ -19729,6 +19777,7 @@
                                 self.ExAttr20,
                                 self.HPEx,
                                 self.Face,
+                                self.FacePic,
                                 self.RoleType
                                 )
         return DumpString
@@ -49893,6 +49942,238 @@
 
 
 #------------------------------------------------------
+# B1 17 头像信息 #tagMCFaceInfo
+
+class  tagMCFace(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("FaceID", c_int),    #头像ID
+                  ("LightTime", c_int),    #点亮时间戳
+                  ("ExpireTime", c_int),    #有效时间秒,0为配表固定时间,如果配表时间也为0即代表永久;到期时间=点亮时间+有效时间
+                  ("Star", 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.FaceID = 0
+        self.LightTime = 0
+        self.ExpireTime = 0
+        self.Star = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCFace)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B1 17 头像信息 //tagMCFaceInfo:
+                                FaceID:%d,
+                                LightTime:%d,
+                                ExpireTime:%d,
+                                Star:%d
+                                '''\
+                                %(
+                                self.FaceID,
+                                self.LightTime,
+                                self.ExpireTime,
+                                self.Star
+                                )
+        return DumpString
+
+
+class  tagMCFaceInfo(Structure):
+    Head = tagHead()
+    Count = 0    #(BYTE Count)
+    FaceList = list()    #(vector<tagMCFace> FaceList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x17
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temFaceList = tagMCFace()
+            _pos = temFaceList.ReadData(_lpData, _pos)
+            self.FaceList.append(temFaceList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x17
+        self.Count = 0
+        self.FaceList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        for i in range(self.Count):
+            length += self.FaceList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.FaceList[i].GetLength(), self.FaceList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Count:%d,
+                                FaceList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCFaceInfo=tagMCFaceInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFaceInfo.Head.Cmd,m_NAtagMCFaceInfo.Head.SubCmd))] = m_NAtagMCFaceInfo
+
+
+#------------------------------------------------------
+# B1 18 头像框信息 #tagMCFacePicInfo
+
+class  tagMCFacePic(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("FacePicID", c_int),    #头像框ID
+                  ("LightTime", c_int),    #点亮时间戳
+                  ("ExpireTime", c_int),    #有效时间秒,0为配表固定时间,如果配表时间也为0即代表永久;到期时间=点亮时间+有效时间
+                  ("Star", 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.FacePicID = 0
+        self.LightTime = 0
+        self.ExpireTime = 0
+        self.Star = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCFacePic)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B1 18 头像框信息 //tagMCFacePicInfo:
+                                FacePicID:%d,
+                                LightTime:%d,
+                                ExpireTime:%d,
+                                Star:%d
+                                '''\
+                                %(
+                                self.FacePicID,
+                                self.LightTime,
+                                self.ExpireTime,
+                                self.Star
+                                )
+        return DumpString
+
+
+class  tagMCFacePicInfo(Structure):
+    Head = tagHead()
+    Count = 0    #(BYTE Count)
+    FacePicList = list()    #(vector<tagMCFacePic> FacePicList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x18
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temFacePicList = tagMCFacePic()
+            _pos = temFacePicList.ReadData(_lpData, _pos)
+            self.FacePicList.append(temFacePicList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x18
+        self.Count = 0
+        self.FacePicList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        for i in range(self.Count):
+            length += self.FacePicList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.FacePicList[i].GetLength(), self.FacePicList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Count:%d,
+                                FacePicList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCFacePicInfo=tagMCFacePicInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFacePicInfo.Head.Cmd,m_NAtagMCFacePicInfo.Head.SubCmd))] = m_NAtagMCFacePicInfo
+
+
+#------------------------------------------------------
 # B1 11 功能系统特权信息 #tagMCFuncSysPrivilegeInfoList
 
 class  tagMCFuncSysPrivilegeInfo(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestRunnerValue.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestRunnerValue.py
index 3210293..1fc83bb 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestRunnerValue.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestRunnerValue.py
@@ -408,7 +408,7 @@
 # @return 返回值, 替换的值
 # @remarks 功勋替换
 def __GetTalkReplace_Country_Hornor(curPlayer, curMission, type, parList):
-    return curPlayer.GetCountryLastWeekHornor()  
+    return 0  
 
 #---------------------------------------------------------------------
 ##家族工资:上周累积家族活跃度显示
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Face.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Face.py
new file mode 100644
index 0000000..2df79e7
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Face.py
@@ -0,0 +1,157 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.Face
+#
+# @todo:头像头像框
+# @author hxp
+# @date 2024-09-12
+# @version 1.0
+#
+# 详细描述: 头像头像框
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-12 12:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import IpyGameDataPY
+import PlayerControl
+import PlayerFace
+import ChConfig
+
+#逻辑实现
+## GM命令执行入口
+#  @param curPlayer 当前玩家
+#  @param msgList 参数列表
+#  @return None
+#  @remarks 函数详细说明.
+def OnExec(curPlayer, msgList):
+    
+    if not msgList:
+        GameWorld.DebugAnswer(curPlayer, "---------- %s" % GameWorld.GetCurrentDataTimeStr())
+        GameWorld.DebugAnswer(curPlayer, "添加头像: Face f1 头像ID [有效秒]")
+        GameWorld.DebugAnswer(curPlayer, "删除头像: Face f0 [头像ID]")
+        GameWorld.DebugAnswer(curPlayer, "头像星级: Face fs 头像ID 星级")
+        GameWorld.DebugAnswer(curPlayer, "添加头框: Face p1 头框ID [有效秒]")
+        GameWorld.DebugAnswer(curPlayer, "删除头框: Face p0 [头框ID]")
+        GameWorld.DebugAnswer(curPlayer, "头框星级: Face ps 头框ID 星级")
+        GameWorld.DebugAnswer(curPlayer, "有效秒:不填读表,0-永久,>0指定有效秒")
+        return
+    
+    syncFaceIDList = []
+    syncFacePicIDList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    value1 = msgList[0]
+    
+    # 删除头像
+    if value1 == "f0":
+        faceID = msgList[1] if len(msgList) > 1 else 0
+        if not faceID:
+            for index in range(ipyDataMgr.GetPlayerFaceCount()):
+                ipyData = ipyDataMgr.GetPlayerFaceByIndex(index)
+                faceID = ipyData.GetFaceID()
+                if ipyData.GetUnlockDefault():
+                    continue
+                if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceLightTime % faceID):
+                    continue
+                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceLightTime % faceID, 0)
+                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceExpireTimes % faceID, 0)
+                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceStar % faceID, 0)
+                syncFaceIDList.append(faceID)
+        else:
+            ipyData = IpyGameDataPY.GetIpyGameData("PlayerFace", faceID)
+            if not ipyData:
+                GameWorld.DebugAnswer(curPlayer, "该头像不存在:%s" % faceID)
+                return
+            if ipyData.GetUnlockDefault():
+                GameWorld.DebugAnswer(curPlayer, "该头像默认激活:%s" % faceID)
+                return
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceLightTime % faceID, 0)
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceExpireTimes % faceID, 0)
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceStar % faceID, 0)
+            syncFaceIDList.append(faceID)
+        GameWorld.DebugAnswer(curPlayer, "删除头像:%s" % syncFaceIDList)
+        
+    # 添加头像
+    elif value1 == "f1":
+        faceID = msgList[1] if len(msgList) > 1 else 0
+        expireTimes = msgList[2] if len(msgList) > 2 else None
+        if PlayerFace.AddFace(curPlayer, faceID, expireTimes):
+            endTimeStr = PlayerFace.GetEndTimeStr(PlayerFace.GetFaceEndTime(curPlayer, faceID))
+            GameWorld.DebugAnswer(curPlayer, "添加头像成功:%s,%s" % (faceID, endTimeStr))
+        else:
+            GameWorld.DebugAnswer(curPlayer, "添加头像失败:%s" % (faceID))
+                    
+    # 头像星级
+    elif value1 == "fs":
+        faceID = msgList[1] if len(msgList) > 1 else 0
+        faceStar = msgList[2] if len(msgList) > 2 else 0
+        starIpyData = IpyGameDataPY.GetIpyGameData("PlayerFaceStar", faceID, faceStar)
+        if not starIpyData:
+            GameWorld.DebugAnswer(curPlayer, "头像星级不存在:%s,star:%s" % (faceID, faceStar))
+            return
+        GameWorld.DebugAnswer(curPlayer, "设置头像星级:%s,星:%s" % (faceID, faceStar))
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceStar % faceID, faceStar)
+        syncFaceIDList.append(faceID)
+        
+    # 删除头像框
+    elif value1 == "p0":
+        facePicID = msgList[1] if len(msgList) > 1 else 0
+        if not facePicID:
+            for index in range(ipyDataMgr.GetPlayerFacePicCount()):
+                ipyData = ipyDataMgr.GetPlayerFacePicByIndex(index)
+                facePicID = ipyData.GetFacePicID()
+                if ipyData.GetUnlockDefault():
+                    continue
+                if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicLightTime % facePicID):
+                    continue
+                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicLightTime % facePicID, 0)
+                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicExpireTimes % facePicID, 0)
+                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicStar % facePicID, 0)
+                syncFacePicIDList.append(facePicID)
+        else:
+            ipyData = IpyGameDataPY.GetIpyGameData("PlayerFacePic", facePicID)
+            if not ipyData:
+                GameWorld.DebugAnswer(curPlayer, "该头像框不存在:%s" % facePicID)
+                return
+            if ipyData.GetUnlockDefault():
+                GameWorld.DebugAnswer(curPlayer, "该头像框默认激活:%s" % facePicID)
+                return
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicLightTime % facePicID, 0)
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicExpireTimes % facePicID, 0)
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicStar % facePicID, 0)
+            syncFacePicIDList.append(facePicID)
+        GameWorld.DebugAnswer(curPlayer, "删除头像框:%s" % syncFacePicIDList)
+        
+    # 添加头像框
+    elif value1 == "p1":
+        facePicID = msgList[1] if len(msgList) > 1 else 0
+        expireTimes = msgList[2] if len(msgList) > 2 else None
+        if PlayerFace.AddFacePic(curPlayer, facePicID, expireTimes):
+            endTimeStr = PlayerFace.GetEndTimeStr(PlayerFace.GetFacePicEndTime(curPlayer, facePicID))
+            GameWorld.DebugAnswer(curPlayer, "添加头像框成功:%s,%s" % (facePicID, endTimeStr))
+        else:
+            GameWorld.DebugAnswer(curPlayer, "添加头像框失败:%s" % (facePicID))
+                    
+    # 头像框星级
+    elif value1 == "ps":
+        facePicID = msgList[1] if len(msgList) > 1 else 0
+        facePicStar = msgList[2] if len(msgList) > 2 else 0
+        starIpyData = IpyGameDataPY.GetIpyGameData("PlayerFacePicStar", facePicID, facePicStar)
+        if not starIpyData:
+            GameWorld.DebugAnswer(curPlayer, "头像框星级不存在:%s,star:%s" % (facePicID, facePicStar))
+            return
+        GameWorld.DebugAnswer(curPlayer, "设置头像框星级:%s,星:%s" % (facePicID, facePicStar))
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicStar % facePicID, facePicStar)
+        syncFacePicIDList.append(facePicID)
+        
+    if syncFaceIDList:
+        PlayerFace.RefreshFaceAttr(curPlayer)
+        PlayerFace.SyncFaceInfo(curPlayer, syncFaceIDList)
+        
+    if syncFacePicIDList:
+        PlayerFace.RefreshFacePicAttr(curPlayer)
+        PlayerFace.SyncFacePicInfo(curPlayer, syncFacePicIDList)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index 84ec2aa..9e3c2e6 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -50,6 +50,40 @@
                         ("list", "StarAttrValue", 0),
                         ),
 
+                "PlayerFace":(
+                        ("DWORD", "FaceID", 1),
+                        ("BYTE", "UnlockDefault", 0),
+                        ("DWORD", "ExpireMinutes", 0),
+                        ("list", "LightAttrType", 0),
+                        ("list", "LightAttrValue", 0),
+                        ("DWORD", "LightFightPower", 0),
+                        ),
+
+                "PlayerFaceStar":(
+                        ("DWORD", "FaceID", 1),
+                        ("BYTE", "FaceStar", 1),
+                        ("list", "StarUpNeedItemList", 0),
+                        ("list", "StarAttrType", 0),
+                        ("list", "StarAttrValue", 0),
+                        ),
+
+                "PlayerFacePic":(
+                        ("DWORD", "FacePicID", 1),
+                        ("BYTE", "UnlockDefault", 0),
+                        ("DWORD", "ExpireMinutes", 0),
+                        ("list", "LightAttrType", 0),
+                        ("list", "LightAttrValue", 0),
+                        ("DWORD", "LightFightPower", 0),
+                        ),
+
+                "PlayerFacePicStar":(
+                        ("DWORD", "FacePicID", 1),
+                        ("BYTE", "FacePicStar", 1),
+                        ("list", "StarUpNeedItemList", 0),
+                        ("list", "StarAttrType", 0),
+                        ("list", "StarAttrValue", 0),
+                        ),
+
                 "CreateRole":(
                         ("BYTE", "RoleType", 1),
                         ("list", "BaseAttrIDList", 0),
@@ -2533,6 +2567,60 @@
     def GetTitleID(self): return self.attrTuple[0] # 称号NPCID DWORD
     def GetTitleStar(self): return self.attrTuple[1] # 称号星级 BYTE
     def GetStarUpNeedItemList(self): return self.attrTuple[2] # 升下一星所需道具 [[物品ID,个数], ...] list
+    def GetStarAttrType(self): return self.attrTuple[3] # 累计总属性类型 list
+    def GetStarAttrValue(self): return self.attrTuple[4] # 累计总属性值 list
+
+# 头像表
+class IPY_PlayerFace():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetFaceID(self): return self.attrTuple[0] # 头像ID DWORD
+    def GetUnlockDefault(self): return self.attrTuple[1] # 是否默认激活 BYTE
+    def GetExpireMinutes(self): return self.attrTuple[2] # 时效分钟,0永久 DWORD
+    def GetLightAttrType(self): return self.attrTuple[3] # 点亮属性类型 list
+    def GetLightAttrValue(self): return self.attrTuple[4] # 点亮属性值 list
+    def GetLightFightPower(self): return self.attrTuple[5] # 点亮附加战力 DWORD
+
+# 头像升星表
+class IPY_PlayerFaceStar():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetFaceID(self): return self.attrTuple[0] # 头像ID DWORD
+    def GetFaceStar(self): return self.attrTuple[1] # 头像星级 BYTE
+    def GetStarUpNeedItemList(self): return self.attrTuple[2] # 升该星所需物品 [[物品ID,个数], ...] list
+    def GetStarAttrType(self): return self.attrTuple[3] # 累计总属性类型 list
+    def GetStarAttrValue(self): return self.attrTuple[4] # 累计总属性值 list
+
+# 头像框表
+class IPY_PlayerFacePic():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetFacePicID(self): return self.attrTuple[0] # 头像框ID DWORD
+    def GetUnlockDefault(self): return self.attrTuple[1] # 是否默认激活 BYTE
+    def GetExpireMinutes(self): return self.attrTuple[2] # 时效分钟,0永久 DWORD
+    def GetLightAttrType(self): return self.attrTuple[3] # 点亮属性类型 list
+    def GetLightAttrValue(self): return self.attrTuple[4] # 点亮属性值 list
+    def GetLightFightPower(self): return self.attrTuple[5] # 点亮附加战力 DWORD
+
+# 头像框升星表
+class IPY_PlayerFacePicStar():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetFacePicID(self): return self.attrTuple[0] # 头像框ID DWORD
+    def GetFacePicStar(self): return self.attrTuple[1] # 头像框星级 BYTE
+    def GetStarUpNeedItemList(self): return self.attrTuple[2] # 升该星所需物品 [[物品ID,个数], ...] list
     def GetStarAttrType(self): return self.attrTuple[3] # 累计总属性类型 list
     def GetStarAttrValue(self): return self.attrTuple[4] # 累计总属性值 list
 
@@ -6295,6 +6383,10 @@
             self.ipyConfigEx = {}
         self.__LoadFileData("Dienstgrad", onlyCheck)
         self.__LoadFileData("TitleStarUp", onlyCheck)
+        self.__LoadFileData("PlayerFace", onlyCheck)
+        self.__LoadFileData("PlayerFaceStar", onlyCheck)
+        self.__LoadFileData("PlayerFacePic", onlyCheck)
+        self.__LoadFileData("PlayerFacePicStar", onlyCheck)
         self.__LoadFileData("CreateRole", onlyCheck)
         self.__LoadFileData("RolePoint", onlyCheck)
         self.__LoadFileData("LingQiAttr", onlyCheck)
@@ -6763,6 +6855,34 @@
         self.CheckLoadData("TitleStarUp")
         return self.ipyTitleStarUpCache[index]
 
+    def GetPlayerFaceCount(self):
+        self.CheckLoadData("PlayerFace")
+        return self.ipyPlayerFaceLen
+    def GetPlayerFaceByIndex(self, index):
+        self.CheckLoadData("PlayerFace")
+        return self.ipyPlayerFaceCache[index]
+
+    def GetPlayerFaceStarCount(self):
+        self.CheckLoadData("PlayerFaceStar")
+        return self.ipyPlayerFaceStarLen
+    def GetPlayerFaceStarByIndex(self, index):
+        self.CheckLoadData("PlayerFaceStar")
+        return self.ipyPlayerFaceStarCache[index]
+
+    def GetPlayerFacePicCount(self):
+        self.CheckLoadData("PlayerFacePic")
+        return self.ipyPlayerFacePicLen
+    def GetPlayerFacePicByIndex(self, index):
+        self.CheckLoadData("PlayerFacePic")
+        return self.ipyPlayerFacePicCache[index]
+
+    def GetPlayerFacePicStarCount(self):
+        self.CheckLoadData("PlayerFacePicStar")
+        return self.ipyPlayerFacePicStarLen
+    def GetPlayerFacePicStarByIndex(self, index):
+        self.CheckLoadData("PlayerFacePicStar")
+        return self.ipyPlayerFacePicStarCache[index]
+
     def GetCreateRoleCount(self):
         self.CheckLoadData("CreateRole")
         return self.ipyCreateRoleLen
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
index 6b25d7e..17c0566 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
@@ -719,6 +719,8 @@
     itemEffIdCallFuncDic = {
                             ChConfig.Def_Effect_UseItemGiveZhenQi:"Item_UseItemGiveZhenQi", # 使用道具给予真气
                             ChConfig.Def_Effect_AddDienstgrad:"Item_AddDienstgrad", #道具获得称号
+                            ChConfig.Def_Effect_Face:"Item_Face",
+                            ChConfig.Def_Effect_FacePic:"Item_Face",
                             ChConfig.Def_Effect_ItemAddLV:"Item_AddLV", #升级道具
                             ChConfig.Def_Effect_TJGAddTime:"Item_TJGAddTime", #增加脱机挂时间
                             ChConfig.Def_Effect_GuajiAward:"Item_GuajiAward", #直接给挂机收益
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_Face.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_Face.py
new file mode 100644
index 0000000..ea4b5d3
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_Face.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package UseItem.Item_Face
+#
+# @todo:激活头像
+# @author hxp
+# @date 2024-09-12
+# @version 1.0
+#
+# 详细描述: 激活头像
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-12 12:00"""
+#-------------------------------------------------------------------------------
+
+import ChConfig
+import ItemCommon
+import PlayerFace
+
+def UseItem(curPlayer, curRoleItem, tick):
+    useItemEff = curRoleItem.GetEffectByIndex(0)
+    curEffID = useItemEff.GetEffectID()
+    effectA1 = useItemEff.GetEffectValue(0) 
+    if effectA1 == 0:
+        return
+    if curEffID == ChConfig.Def_Effect_Face:
+        if not PlayerFace.AddFace(curPlayer, effectA1):
+            return
+    elif curEffID == ChConfig.Def_Effect_FacePic:
+        if not PlayerFace.AddFacePic(curPlayer, effectA1):
+            return
+    else:
+        return
+    ItemCommon.DelItem(curPlayer, curRoleItem, 1)
+    return True
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
index 615a2eb..4189dc5 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -162,6 +162,7 @@
 import GameObj
 import PlayerChangeJob
 import PlayerGuaji
+import PlayerFace
 import PlayerXiangong
 import PlayerMineArea
 import PlayerActLoginNew
@@ -468,6 +469,7 @@
     dbPlayer.ExAttr19 = curPlayer.GetExAttr19()
     dbPlayer.ExAttr20 = curPlayer.GetExAttr20()
     dbPlayer.Face = curPlayer.GetFace()
+    dbPlayer.FacePic = curPlayer.GetFacePic()
     dbPlayer.RoleType = curPlayer.GetRoleType()
     NetPackCommon.SendFakePack(curPlayer, dbPlayer)
     return
@@ -961,7 +963,7 @@
         Sync_RewardGetRecordInfo(curPlayer, ChConfig.Def_RewardType_GoodGame, goodGameAwardState)
         
     curPlayer.SetState(0)   # 脱机挂恢复为正常上线
-    curPlayer.SetFacePic(0) # 通知数据库是否保存还是下线,做一次恢复,1为保存 0为正常下线
+    curPlayer.SetCountryLastWeekHornor(0) # 通知数据库是否保存还是下线,做一次恢复,1为保存 0为正常下线
     #tjgTime = PlayerTJG.GetTJGTime(curPlayer)
     #if tjgTime:
     #    PlayerControl.SendGameServerRefreshState(curPlayer, IPY_GameWorld.CDBPlayerRefresh_HappyPoint, tjgTime)
@@ -986,6 +988,7 @@
         pass
     
     else:
+        PlayerFace.OnPlayerLogin(curPlayer)
         PlayerXiangong.OnPlayerLogin(curPlayer)
         PlayerGubao.OnPlayerLogin(curPlayer)
         PlayerShentong.OnPlayerLogin(curPlayer)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameServerRefresh.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameServerRefresh.py
index e078916..5b3a176 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameServerRefresh.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameServerRefresh.py
@@ -346,9 +346,9 @@
         return
     
     # 1为保存 0为正常下线
-    curPlayer.SetFacePic(1) # 利用此字段通知为保存数据,非下线数据
+    curPlayer.SetCountryLastWeekHornor(1) # 利用此字段通知为保存数据,非下线数据
     curPlayer.PushSaveData()
-    curPlayer.SetFacePic(0) # 利用此字段通知为保存数据,非下线数据
+    curPlayer.SetCountryLastWeekHornor(0) # 利用此字段通知为保存数据,非下线数据
     return
 
 #===============================================================================
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
index 24cc467..205fe95 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
@@ -32,11 +32,10 @@
 
 def GetBillboardOperateInfo(curPlayer):
     # 排行榜中所保存的运营商相关信息
-    return curPlayer.GetFace()
-#    platform = curPlayer.GetAccID()
-#    if platform in ["tencent"]:
-#        return curPlayer.GetOperateInfo()
-#    return platform
+    platform = curPlayer.GetAccID()
+    if platform in ["tencent"]:
+        return curPlayer.GetOperateInfo()
+    return platform
 
 def GetBillboardJob(curPlayer): return curPlayer.GetJob()
 
@@ -80,6 +79,8 @@
     playerID = curPlayer.GetID()
     playerName = curPlayer.GetName()
     playerOpInfo = GetBillboardOperateInfo(curPlayer)
+    kwargs["value3"] = curPlayer.GetFace()
+    kwargs["value4"] = curPlayer.GetFacePic()
     if bType in ShareDefine.BTValue1_OfficialRankList:
         value1 = curPlayer.GetOfficialRank()
     GameServer_UpdateBillboard(bType, playerJob, playerID, playerName, playerOpInfo,
@@ -122,6 +123,8 @@
     playerID = curPlayer.GetID()
     playerName = CrossRealmPlayer.GetCrossPlayerName(curPlayer)
     playerOpInfo = GetBillboardOperateInfo(curPlayer)
+    kwargs["value3"] = curPlayer.GetFace()
+    kwargs["value4"] = curPlayer.GetFacePic()
     if bType in ShareDefine.BTValue1_OfficialRankList:
         value1 = curPlayer.GetOfficialRank()
     id2 = 0
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index 87613ec..e9d3a38 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -103,6 +103,7 @@
 import PlayerGubao
 import PlayerShentong
 import PlayerCharm
+import PlayerFace
 import PlayerTask
 import ChPlayer
 import GMShell
@@ -4625,6 +4626,8 @@
         PlayerLianTi.CalcLianTiAttr(curPlayer)
         PlayerShentong.CalcShentongAttr(curPlayer)
         PlayerFamilyZhenfa.CalcZhenfaAttr(curPlayer)
+        PlayerFace.CalcFaceAttr(curPlayer)
+        PlayerFace.CalcFacePicAttr(curPlayer)
         self.RefreshAllState(isForce=True)
         GameWorld.DebugLog("End ReCalcAllState!!!")
         return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerDienstgrad.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerDienstgrad.py
index affb7a9..b2d9218 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerDienstgrad.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerDienstgrad.py
@@ -569,12 +569,6 @@
 #  @param curPlayer
 #  @return None
 def CheckDienstgradTimeout(curPlayer):
-    tick = int(time.time())
-    lastTick = curPlayer.GetTickByType(ChConfig.TYPE_Player_Tick_Dienstgrad)
-    if tick - lastTick < (ChConfig.TYPE_Player_Tick_Time[ChConfig.TYPE_Player_Tick_Dienstgrad] / 1000):
-        return
-    curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_Dienstgrad, tick)
-    
     gradCnt = curPlayer.GetDienstgradManager().GetCount()
     needClearList = []
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFace.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFace.py
new file mode 100644
index 0000000..3ed5639
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFace.py
@@ -0,0 +1,564 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.PlayerFace
+#
+# @todo:头像头像框
+# @author hxp
+# @date 2024-09-12
+# @version 1.0
+#
+# 详细描述: 头像头像框
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-12 12:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import ShareDefine
+import PlayerControl
+import IPY_GameWorld
+import ChPyNetSendPack
+import IpyGameDataPY
+import NetPackCommon
+import ItemCommon
+import ChConfig
+
+import random
+import time
+
+def OnPlayerLogin(curPlayer):
+    SyncFaceInfo(curPlayer)
+    SyncFacePicInfo(curPlayer)
+    return
+
+def OnMinute(curPlayer):
+    curTime = int(time.time())
+    
+    delFaceList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetPlayerFaceCount()):
+        ipyData = ipyDataMgr.GetPlayerFaceByIndex(index)
+        faceID = ipyData.GetFaceID()
+        if ipyData.GetUnlockDefault():
+            # 默认激活的不处理
+            continue
+        lightTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceLightTime % faceID)
+        expireTimes = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceExpireTimes % faceID) # 有效时长,秒
+        if not lightTime or not expireTimes:
+            # 未激活或永久的不处理
+            continue
+        endTime = lightTime + expireTimes
+        if endTime > curTime:
+            continue
+        if DelFace(curPlayer, faceID, False, "FaceTimeout"):
+            delFaceList.append(faceID)
+            
+    if delFaceList:
+        RefreshFaceAttr(curPlayer)
+        
+    delFacePicList = []
+    for index in range(ipyDataMgr.GetPlayerFacePicCount()):
+        ipyData = ipyDataMgr.GetPlayerFacePicByIndex(index)
+        facePicID = ipyData.GetFacePicID()
+        if ipyData.GetUnlockDefault():
+            # 默认激活的不处理
+            continue
+        lightTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicLightTime % facePicID)
+        expireTimes = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicExpireTimes % facePicID) # 有效时长,秒
+        if not lightTime or not expireTimes:
+            # 未激活或永久的不处理
+            continue
+        endTime = lightTime + expireTimes
+        if endTime > curTime:
+            continue
+        if DelFacePic(curPlayer, facePicID, False, "FacePicTimeout"):
+            delFacePicList.append(facePicID)
+            
+    if delFacePicList:
+        RefreshFacePicAttr(curPlayer)
+    return
+
+def AddFace(curPlayer, faceID, setExpireTimes=None):
+    if faceID <= 0:
+        return
+    playerID = curPlayer.GetPlayerID()
+    ipyData = IpyGameDataPY.GetIpyGameData("PlayerFace", faceID)
+    if not ipyData:
+        return
+    if ipyData.GetUnlockDefault():
+        GameWorld.DebugLog("默认解锁的头像不用添加: faceID=%s" % (faceID), playerID)
+        return
+    ipyExpireSeconds = ipyData.GetExpireMinutes() * 60
+    
+    curTime = int(time.time())
+    lightTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceLightTime % faceID)
+    expireTimes = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceExpireTimes % faceID) # 有效时长,秒
+    GameWorld.Log("添加头像: faceID=%s,setExpireTimes=%s,lightTime=%s,expireTimes=%s,ipyExpireSeconds=%s,curTime=%s" 
+                  % (faceID, setExpireTimes, lightTime, expireTimes, ipyExpireSeconds, curTime), playerID)
+    updLightTime = lightTime
+    updExpireTimes = expireTimes
+    
+    # 指定时长的,如GM指定
+    if setExpireTimes >= 0:
+        updLightTime = curTime
+        updExpireTimes = setExpireTimes
+        GameWorld.Log("    指定头像时长: faceID=%s,updLightTime=%s,updExpireTimes=%s" % (faceID, updLightTime, updExpireTimes), playerID)
+        
+    # 永久
+    elif ipyExpireSeconds == 0:
+        updLightTime = curTime
+        updExpireTimes = 0
+        GameWorld.Log("    添加永久头像: faceID=%s,updLightTime=%s,updExpireTimes=%s" % (faceID, updLightTime, updExpireTimes), playerID)
+        
+    else:
+        # 未过期
+        if lightTime and expireTimes and (lightTime + expireTimes) > curTime:
+            updExpireTimes = expireTimes + ipyExpireSeconds
+            GameWorld.Log("    累加头像时长: faceID=%s,updLightTime=%s,updExpireTimes=%s" % (faceID, updLightTime, updExpireTimes), playerID)
+        else:
+            updLightTime = curTime
+            updExpireTimes = ipyExpireSeconds
+            GameWorld.Log("    重新激活头像: faceID=%s,updLightTime=%s,updExpireTimes=%s" % (faceID, updLightTime, updExpireTimes), playerID)
+            
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceLightTime % faceID, updLightTime)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceExpireTimes % faceID, updExpireTimes)
+    RefreshFaceAttr(curPlayer)
+    SyncFaceInfo(curPlayer, [faceID])
+    return True
+
+def DelFace(curPlayer, faceID, isRefreshAttr=True, notifyMail=""):
+    playerID = curPlayer.GetPlayerID()
+    ipyData = IpyGameDataPY.GetIpyGameData("PlayerFace", faceID)
+    if not ipyData:
+        return
+    if ipyData.GetUnlockDefault():
+        return
+    GameWorld.Log("删除头像: faceID=%s,notifyMail=%s" % (faceID, notifyMail), playerID)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceLightTime % faceID, 0)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceExpireTimes % faceID, 0)
+    # 星级不重置,重新激活后再次生效
+    
+    if curPlayer.GetFace() == faceID:
+        defaultFaceIDList = GetDefaultFaceIDList()
+        randFace = random.choice(defaultFaceIDList) if defaultFaceIDList else 0
+        curPlayer.SetFace(randFace)
+        GameWorld.DebugLog("玩家佩戴的头像被删除,随机重置默认头像! randFace=%s" % randFace, playerID)
+        
+    if isRefreshAttr:
+        RefreshFaceAttr(curPlayer)
+    SyncFaceInfo(curPlayer, [faceID])
+    if notifyMail:
+        PlayerControl.SendMailByKey(notifyMail, [playerID], [], [faceID])
+        
+    return True
+
+def GetDefaultFaceIDList():
+    defaultFaceIDList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetPlayerFaceCount()):
+        ipyData = ipyDataMgr.GetPlayerFaceByIndex(index)
+        faceID = ipyData.GetFaceID()
+        if not ipyData.GetUnlockDefault():
+            continue
+        defaultFaceIDList.append(faceID)
+    return defaultFaceIDList
+
+def GetDefaultFacePicIDList():
+    defaultFacePicIDList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetPlayerFacePicCount()):
+        ipyData = ipyDataMgr.GetPlayerFacePicByIndex(index)
+        facePicID = ipyData.GetFacePicID()
+        if not ipyData.GetUnlockDefault():
+            continue
+        defaultFacePicIDList.append(facePicID)
+    return defaultFacePicIDList
+
+def AddFacePic(curPlayer, facePicID, setExpireTimes=None):
+    if facePicID <= 0:
+        return
+    playerID = curPlayer.GetPlayerID()
+    ipyData = IpyGameDataPY.GetIpyGameData("PlayerFacePic", facePicID)
+    if not ipyData:
+        return
+    if ipyData.GetUnlockDefault():
+        GameWorld.DebugLog("默认解锁的头像框不用添加: facePicID=%s" % (facePicID), playerID)
+        return
+    ipyExpireSeconds = ipyData.GetExpireMinutes() * 60
+    
+    curTime = int(time.time())
+    lightTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicLightTime % facePicID)
+    expireTimes = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicExpireTimes % facePicID) # 有效时长,秒
+    GameWorld.Log("添加头像框: facePicID=%s,setExpireTimes=%s,lightTime=%s,expireTimes=%s,ipyExpireSeconds=%s,curTime=%s" 
+                  % (facePicID, setExpireTimes, lightTime, expireTimes, ipyExpireSeconds, curTime), playerID)
+    updLightTime = lightTime
+    updExpireTimes = expireTimes
+    
+    # 指定时长的,如GM指定
+    if setExpireTimes >= 0:
+        updLightTime = curTime
+        updExpireTimes = setExpireTimes
+        GameWorld.Log("    指定头像框时长: facePicID=%s,updLightTime=%s,updExpireTimes=%s" % (facePicID, updLightTime, updExpireTimes), playerID)
+        
+    # 永久
+    elif ipyExpireSeconds == 0:
+        updLightTime = curTime
+        updExpireTimes = 0
+        GameWorld.Log("    添加永久头像框: facePicID=%s,updLightTime=%s,updExpireTimes=%s" % (facePicID, updLightTime, updExpireTimes), playerID)
+        
+    else:
+        # 未过期
+        if lightTime and expireTimes and (lightTime + expireTimes) > curTime:
+            updExpireTimes = expireTimes + ipyExpireSeconds
+            GameWorld.Log("    累加头像框时长: facePicID=%s,updLightTime=%s,updExpireTimes=%s" % (facePicID, updLightTime, updExpireTimes), playerID)
+        else:
+            updLightTime = curTime
+            updExpireTimes = ipyExpireSeconds
+            GameWorld.Log("    重新激活头像框: facePicID=%s,updLightTime=%s,updExpireTimes=%s" % (facePicID, updLightTime, updExpireTimes), playerID)
+            
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicLightTime % facePicID, updLightTime)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicExpireTimes % facePicID, updExpireTimes)
+    RefreshFacePicAttr(curPlayer)
+    SyncFacePicInfo(curPlayer, [facePicID])
+    return True
+
+def DelFacePic(curPlayer, facePicID, isRefreshAttr=True, notifyMail=""):
+    playerID = curPlayer.GetPlayerID()
+    ipyData = IpyGameDataPY.GetIpyGameData("PlayerFacePic", facePicID)
+    if not ipyData:
+        return
+    if ipyData.GetUnlockDefault():
+        return
+    GameWorld.Log("删除头像框: facePicID=%s,notifyMail=%s" % (facePicID, notifyMail), playerID)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicLightTime % facePicID, 0)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicExpireTimes % facePicID, 0)
+    # 星级不重置,重新激活后再次生效
+    
+    if curPlayer.GetFacePic() == facePicID:
+        defaultFacePicIDList = GetDefaultFacePicIDList()
+        randFacePic = random.choice(defaultFacePicIDList) if defaultFacePicIDList else 0
+        curPlayer.SetFacePic(randFacePic)
+        GameWorld.DebugLog("玩家佩戴的头像框过期,随机重置默认头像框! randFacePic=%s" % randFacePic, playerID)
+        
+    if isRefreshAttr:
+        RefreshFacePicAttr(curPlayer)
+    SyncFacePicInfo(curPlayer, [facePicID])
+    if notifyMail:
+        PlayerControl.SendMailByKey(notifyMail, [playerID], [], [facePicID])
+    return True
+
+def GetFaceEndTime(curPlayer, faceID, ipyData=None):
+    ## 头像结束时间戳
+    # @return: -1-未激活;0-永久;>0-具体结束时间戳
+    lightTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceLightTime % faceID)
+    expireTimes = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceExpireTimes % faceID)
+    if lightTime:
+        if expireTimes:
+            return lightTime + expireTimes
+        return 0
+    if not ipyData:
+        ipyData = IpyGameDataPY.GetIpyGameData("PlayerFace", faceID)
+    if ipyData and ipyData.GetUnlockDefault():
+        return 0
+    return -1
+
+def IsFaceCanUse(curPlayer, faceID, ipyData=None):
+    ## 头像是否可用
+    # 这里不判断严谨的过期时间,即不对比当前时间,只要endTime>=0即可
+    # 过期逻辑由过期函数定时处理删除即可,可能有1分钟延迟
+    return GetFaceEndTime(curPlayer, faceID, ipyData) >= 0
+
+def GetFacePicEndTime(curPlayer, facePicID, ipyData=None):
+    ## 头像框结束时间戳
+    # @return: -1-未激活;0-永久;>0-具体结束时间戳
+    lightTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicLightTime % facePicID)
+    expireTimes = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicExpireTimes % facePicID)
+    if lightTime:
+        if expireTimes:
+            return lightTime + expireTimes
+        return 0
+    if not ipyData:
+        ipyData = IpyGameDataPY.GetIpyGameData("PlayerFacePic", facePicID)
+    if ipyData and ipyData.GetUnlockDefault():
+        return 0
+    return -1
+
+def IsFacePicCanUse(curPlayer, facePicID, ipyData=None):
+    ## 头像框是否可用
+    # 这里不判断严谨的过期时间,即不对比当前时间,只要endTime>=0即可
+    # 过期逻辑由过期函数定时处理删除即可,可能有1分钟延迟
+    return GetFacePicEndTime(curPlayer, facePicID, ipyData) >= 0
+
+def GetEndTimeStr(endTime):
+    endTimeStr = "未激活"
+    if endTime == 0:
+        endTimeStr = "永久"
+    elif endTime > 0:
+        endTimeStr = GameWorld.ChangeTimeNumToStr(endTime)
+    return endTimeStr
+
+def RefreshFaceAttr(curPlayer):
+    CalcFaceAttr(curPlayer)
+    PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState()
+    return
+
+def RefreshFacePicAttr(curPlayer):
+    CalcFacePicAttr(curPlayer)
+    PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState()
+    return
+
+def CalcFaceAttr(curPlayer):
+    ## 计算头像属性
+    
+    fightPowerEx = 0
+    allAttrList = [{} for i in range(4)]
+    
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetPlayerFaceCount()):
+        ipyData = ipyDataMgr.GetPlayerFaceByIndex(index)
+        faceID = ipyData.GetFaceID()
+        if not IsFaceCanUse(curPlayer, faceID, ipyData):
+            continue
+                
+        fightPowerEx += ipyData.GetLightFightPower()
+        # 激活属性
+        lightAttrType = ipyData.GetLightAttrType()
+        lightAttrValue = ipyData.GetLightAttrValue()
+        for i, attrID in enumerate(lightAttrType):
+            attrValue = lightAttrValue[i]
+            PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrList)
+        
+        # 星级属性
+        faceStar = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceStar % faceID)
+        starIpyData = IpyGameDataPY.GetIpyGameDataNotLog("PlayerFaceStar", faceID, faceStar)
+        if starIpyData:
+            starAttrType = starIpyData.GetStarAttrType()
+            starAttrValue = starIpyData.GetStarAttrValue()
+            for i, attrID in enumerate(starAttrType):
+                attrValue = starAttrValue[i]
+                PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrList)
+                
+    # 保存计算值
+    PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_Face, allAttrList)
+    curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPEx % ShareDefine.Def_MFPType_Face, fightPowerEx)
+    return
+
+def CalcFacePicAttr(curPlayer):
+    ## 计算头像框属性
+    
+    fightPowerEx = 0
+    allAttrList = [{} for _ in range(4)]
+    
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetPlayerFacePicCount()):
+        ipyData = ipyDataMgr.GetPlayerFacePicByIndex(index)
+        facePicID = ipyData.GetFacePicID()
+        if not IsFacePicCanUse(curPlayer, facePicID, ipyData):
+            continue
+                
+        fightPowerEx += ipyData.GetLightFightPower()
+        # 激活属性
+        lightAttrType = ipyData.GetLightAttrType()
+        lightAttrValue = ipyData.GetLightAttrValue()
+        for i, attrID in enumerate(lightAttrType):
+            attrValue = lightAttrValue[i]
+            PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrList)
+        
+        # 星级属性
+        facePicStar = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicStar % facePicID)
+        starIpyData = IpyGameDataPY.GetIpyGameDataNotLog("PlayerFacePicStar", facePicID, facePicStar)
+        if starIpyData:
+            starAttrType = starIpyData.GetStarAttrType()
+            starAttrValue = starIpyData.GetStarAttrValue()
+            for i, attrID in enumerate(starAttrType):
+                attrValue = starAttrValue[i]
+                PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrList)
+                
+    # 保存计算值
+    PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_FacePic, allAttrList)
+    curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPEx % ShareDefine.Def_MFPType_FacePic, fightPowerEx)
+    return
+
+#// B2 26 头像幻化 #tagCMFaceChange
+#
+#struct    tagCMFaceChange
+#{
+#    tagHead        Head;
+#    DWORD        FaceID;    // 幻化的ID
+#};
+def OnFaceChange(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    playerID = curPlayer.GetPlayerID()
+    faceID = clientData.FaceID
+    
+    if not IsFaceCanUse(curPlayer, faceID):
+        GameWorld.DebugLog("该头像不可用! faceID=%s" % (faceID), playerID)
+        return    
+    GameWorld.DebugLog("头像幻化! faceID=%s" % (faceID), playerID)
+    curPlayer.SetFace(faceID)
+    return
+
+#// B2 27 头像升星 #tagCMFaceStarUP
+#
+#struct    tagCMFaceStarUP
+#{
+#    tagHead        Head;
+#    DWORD        FaceID;
+#};
+def OnFaceStarUP(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    playerID = curPlayer.GetPlayerID()
+    faceID = clientData.FaceID
+    
+    if not IsFaceCanUse(curPlayer, faceID):
+        GameWorld.DebugLog("该头像不可用! faceID=%s" % (faceID), playerID)
+        return
+    
+    curStar = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceStar % faceID)        
+    nextStar = curStar + 1
+    nextIpyData = IpyGameDataPY.GetIpyGameData("PlayerFaceStar", faceID, nextStar)
+    if not nextIpyData:
+        GameWorld.DebugLog("不存在该头像星级! faceID=%s,nextStar=%s" % (faceID, nextStar), playerID)
+        return
+    needItemList = nextIpyData.GetStarUpNeedItemList()
+    if not needItemList:
+        return
+    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
+    lackItemDict, delInfoDict = ItemCommon.GetCostItemIndexList(needItemList, itemPack)
+    if lackItemDict:
+        GameWorld.DebugLog("头像升星所需物品不足! faceID=%s,nextStar=%s,needItemList=%s,lackItemDict=%s" 
+                           % (faceID, nextStar, needItemList, lackItemDict), playerID)
+        return
+    ItemCommon.DelCostItem(curPlayer, itemPack, delInfoDict, "FaceStarUP")
+    
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceStar % faceID, nextStar)
+    
+    GameWorld.DebugLog("头像升星! faceID=%s,curStar=%s,nextStar=%s" % (faceID, curStar, nextStar), playerID)
+    
+    RefreshFaceAttr(curPlayer)
+    SyncFaceInfo(curPlayer, [faceID])
+    return
+
+#// B2 28 头像框幻化 #tagCMFacePicChange
+#
+#struct    tagCMFacePicChange
+#{
+#    tagHead        Head;
+#    DWORD        FacePicID;    // 幻化的ID
+#};
+def OnFacePicChange(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    playerID = curPlayer.GetPlayerID()
+    facePicID = clientData.FacePicID
+    
+    if not IsFacePicCanUse(curPlayer, facePicID):
+        GameWorld.DebugLog("该头像框不可用! facePicID=%s" % (facePicID), playerID)
+        return    
+    GameWorld.DebugLog("头像框幻化! facePicID=%s" % (facePicID), playerID)
+    curPlayer.SetFacePic(facePicID)
+    return
+
+#// B2 29 头像框升星 #tagCMFacePicStarUP
+#
+#struct    tagCMFacePicStarUP
+#{
+#    tagHead        Head;
+#    DWORD        FacePicID;
+#};
+def OnFacePicStarUP(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    playerID = curPlayer.GetPlayerID()
+    facePicID = clientData.FacePicID
+    
+    if not IsFacePicCanUse(curPlayer, facePicID):
+        GameWorld.DebugLog("该头像框不可用! facePicID=%s" % (facePicID), playerID)
+        return
+    
+    curStar = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicStar % facePicID)        
+    nextStar = curStar + 1
+    nextIpyData = IpyGameDataPY.GetIpyGameData("PlayerFacePicStar", facePicID, nextStar)
+    if not nextIpyData:
+        GameWorld.DebugLog("不存在该头像框星级! facePicID=%s,nextStar=%s" % (facePicID, nextStar), playerID)
+        return
+    needItemList = nextIpyData.GetStarUpNeedItemList()
+    if not needItemList:
+        return
+    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
+    lackItemDict, delInfoDict = ItemCommon.GetCostItemIndexList(needItemList, itemPack)
+    if lackItemDict:
+        GameWorld.DebugLog("头像框升星所需物品不足! facePicID=%s,nextStar=%s,needItemList=%s,lackItemDict=%s" 
+                           % (facePicID, nextStar, needItemList, lackItemDict), playerID)
+        return
+    ItemCommon.DelCostItem(curPlayer, itemPack, delInfoDict, "FacePicStarUP")
+    
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicStar % facePicID, nextStar)
+    
+    GameWorld.DebugLog("头像框升星! facePicID=%s,curStar=%s,nextStar=%s" % (facePicID, curStar, nextStar), playerID)
+    
+    RefreshFacePicAttr(curPlayer)
+    SyncFacePicInfo(curPlayer, [facePicID])
+    return
+
+def SyncFaceInfo(curPlayer, faceIDList=None):
+    if faceIDList == None:
+        syncIDList = []
+        ipyDataMgr = IpyGameDataPY.IPY_Data()
+        for index in range(ipyDataMgr.GetPlayerFaceCount()):
+            ipyData = ipyDataMgr.GetPlayerFaceByIndex(index)
+            syncIDList.append(ipyData.GetFaceID())
+    else:
+        syncIDList = faceIDList
+        
+    faceList = []
+    for faceID in syncIDList:
+        lightTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceLightTime % faceID)
+        if not lightTime and faceIDList == None:
+            continue
+        face = ChPyNetSendPack.tagMCFace()
+        face.FaceID = faceID
+        face.LightTime = lightTime
+        face.ExpireTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceExpireTimes % faceID)
+        face.Star = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceStar % faceID)
+        faceList.append(face)
+    
+    if not faceList:
+        return
+    
+    clientPack = ChPyNetSendPack.tagMCFaceInfo()
+    clientPack.FaceList = faceList
+    clientPack.Count = len(clientPack.FaceList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def SyncFacePicInfo(curPlayer, facePicIDList=None):
+    if facePicIDList == None:
+        syncIDList = []
+        ipyDataMgr = IpyGameDataPY.IPY_Data()
+        for index in range(ipyDataMgr.GetPlayerFacePicCount()):
+            ipyData = ipyDataMgr.GetPlayerFacePicByIndex(index)
+            syncIDList.append(ipyData.GetFacePicID())
+    else:
+        syncIDList = facePicIDList
+        
+    facePicList = []
+    for facePicID in syncIDList:
+        lightTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicLightTime % facePicID)
+        if not lightTime and facePicIDList == None:
+            continue
+        facePic = ChPyNetSendPack.tagMCFacePic()
+        facePic.FacePicID = facePicID
+        facePic.LightTime = lightTime
+        facePic.ExpireTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicExpireTimes % facePicID)
+        facePic.Star = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicStar % facePicID)
+        facePicList.append(facePic)
+        
+    if not facePicList:
+        return
+    
+    clientPack = ChPyNetSendPack.tagMCFacePicInfo()
+    clientPack.FacePicList = facePicList
+    clientPack.Count = len(clientPack.FacePicList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
index 4088f35..22be231 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
@@ -55,6 +55,7 @@
 import FormulaControl
 import PlayerGoldGift
 import PlayerFlashSale
+import PlayerFace
 import PlayerWing
 import ChEquip
 import PlayerYinji
@@ -1196,9 +1197,8 @@
     reFlashList.append(reFlash)
 #    GameWorld.Log('刷新以单位时间(分钟)消耗耐久的物品 %s'%(time.clock() - curTime))
 #    curTime = time.clock()
-
-    # 时效称号
-    PlayerDienstgrad.CheckDienstgradTimeout(curPlayer)
+    
+    ProcessPlayerMinute(curPlayer, tick)
     
     #vip体验
     reFlash = PlayerVip.CheckVIPExperience(curPlayer, tick)
@@ -1292,6 +1292,18 @@
     CrossPlayerData.ProcessCrossPlayer(curPlayer, tick)
     return
 
+def ProcessPlayerMinute(curPlayer, tick):
+    #玩家每分钟处理
+    lastTick = curPlayer.GetTickByType(ChConfig.TYPE_Player_Tick_Minute)
+    if tick - lastTick < (ChConfig.TYPE_Player_Tick_Time[ChConfig.TYPE_Player_Tick_Minute]):
+        return
+    curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_Minute, tick)
+    
+    # 时效称号
+    PlayerDienstgrad.CheckDienstgradTimeout(curPlayer)
+    # 时效头像
+    PlayerFace.OnMinute(curPlayer)
+    return
 
 # 一定时间自动释放的被动技能
 def ProcessPassiveSkill(curPlayer, tick):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTJG.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTJG.py
index 8604536..984eee3 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTJG.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTJG.py
@@ -19,7 +19,7 @@
     # 5.脱机挂玩家防沉迷逻辑修正,根据4条件
     # 6.在线人数区分脱机挂玩家
     # 7.03 10 退出副本#tagCExitFB到对应挂机点
-    # 8.利用FacePic字段控制保存数据是否是真实下线
+    # 8.利用CountryLastWeekHornor字段控制保存数据是否是真实下线
 #---------------------------------------------------------------------
     
 import GameWorld
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTalk.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTalk.py
index b97d8eb..948b30f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTalk.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTalk.py
@@ -400,7 +400,8 @@
     coupleJob = PlayerControl.GetCoupleJob(objTalk)
     bridePriceMaxID = PlayerControl.GetBridePriceMaxID(objTalk)
     face = objTalk.GetFace()
-    extraValueStr = "%s|%s|%s|%s|%s" % (extraValueStr, coupleName, coupleJob, bridePriceMaxID, face)
+    facePic = objTalk.GetFacePic()
+    extraValueStr = "%s|%s|%s|%s|%s|%s" % (extraValueStr, coupleName, coupleJob, bridePriceMaxID, face, facePic)
     return extraValueStr
 
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py
index 12e2c5c..6a22007 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py
@@ -174,6 +174,8 @@
     curPlayerPropDict["ModelMark"] = curPlayer.GetModelMark()
     curPlayerPropDict["VIPLV"] = curPlayer.GetVIPLv()
     curPlayerPropDict["Name"] = curPlayer.GetPlayerName()
+    curPlayerPropDict["Face"] = curPlayer.GetFace()
+    curPlayerPropDict["FacePic"] = curPlayer.GetFacePic()
     curPlayerPropDict["FamilyID"] = curPlayer.GetFamilyID()
     curPlayerPropDict["FamilyName"] = curPlayer.GetFamilyName()
     curPlayerPropDict["FamilyEmblemID"] = PlayerControl.GetFamilyEmblemID(curPlayer)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_GMTFace.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_GMTFace.py
new file mode 100644
index 0000000..e1f89df
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_GMTFace.py
@@ -0,0 +1,98 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.RemoteQuery.GY_Query_GMTFace
+#
+# @todo:头像头像框
+# @author hxp
+# @date 2024-09-12
+# @version 1.0
+#
+# 详细描述: 头像头像框
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-12 12:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import DataRecordPack
+import PlayerFace
+import GMCommon
+
+#---------------------------------------------------------------------
+#全局变量
+#---------------------------------------------------------------------
+#---------------------------------------------------------------------
+#逻辑实现 
+## 请求逻辑  
+#  @param query_Type 请求类型
+#  @param query_ID 玩家ID
+#  @param packCMDList 发包命令 
+#  @param tick 当前时间
+#  @return "True" or "False" or ""
+#  @remarks 函数详细说明.
+def DoLogic(query_Type, query_ID, packCMDList, tick):
+    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(query_ID)
+    
+    if not curPlayer or curPlayer.IsEmpty():
+        return
+    
+    Result = GMCommon.Def_Success
+    orderId, isOnlineGMT, faceType, opID, expireTime, opType = packCMDList
+    
+    endTime = -1
+    isOK = False
+    if faceType == "face":
+        if opType == "add":
+            isOK = PlayerFace.AddFace(curPlayer, opID, expireTime)
+        elif opType == "del":
+            isOK = PlayerFace.DelFace(curPlayer, opID)
+        endTime = PlayerFace.GetFaceEndTime(curPlayer, opID)
+    elif faceType == "facePic":
+        if opType == "add":
+            isOK = PlayerFace.AddFacePic(curPlayer, opID, expireTime)
+        elif opType == "del":
+            isOK = PlayerFace.DelFacePic(curPlayer, opID)
+        endTime = PlayerFace.GetFacePicEndTime(curPlayer, opID)
+        
+    if not isOK:
+        errorMsg = "%s %s fail! Please check that the ID(%s) is correct." % (opType, faceType, opID)
+        GameWorld.Log("GMT_AddTitle, errorMsg=%s" % errorMsg, curPlayer.GetPlayerID())
+        resultMsg = str([orderId, errorMsg, 'GMT_AddTitle', GMCommon.Def_Unknow])
+        GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GMToolResult', resultMsg, len(resultMsg))
+        return
+    
+    endTimeStr = PlayerFace.GetEndTimeStr(endTime)
+    resultDict = {"opID":opID, "expireTime":expireTime, "isOnlineGMT":isOnlineGMT, "opType":opType, 
+                  "faceType":faceType, "endTime":endTime, "endTimeStr":endTimeStr}
+    GameWorld.Log("GMT_Face, isOnlineGMT=%s,resultDict=%s" % (isOnlineGMT, resultDict), curPlayer.GetPlayerID())
+    #流向 记录
+    DataRecordPack.DR_ToolGMOperate(query_ID, curPlayer.GetPlayerName(), curPlayer.GetAccID(), 'GMT_Face', resultDict)
+    
+    if isOnlineGMT:
+        resultMsg = str([orderId, resultDict, 'GMT_Face', Result])
+        GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GMToolResult', resultMsg, len(resultMsg))
+        
+    return
+
+#---------------------------------------------------------------------
+#执行结果
+## 执行结果
+#  @param curPlayer 发出请求的玩家
+#  @param callFunName 功能名称
+#  @param funResult 查询的结果
+#  @param tick 当前时间
+#  @return None
+#  @remarks 函数详细说明.
+def DoResult(curPlayer, callFunName, funResult, tick):
+    return
+
+
+
+
+
+
+
+
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index f61d80a..26cd0af 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -907,6 +907,9 @@
                              Def_BT_SkyTower, Def_BT_CharmTotal, Def_BT_CharmWeek, Def_BT_CharmDay, Def_BT_AlineInvade
                              ]
 
+#仙盟榜单类型
+FamilyBillboardList = [Def_BT_BossTrialSubmitFamily, Def_BT_BossTrialSubmitFamilyBak]
+
 ##---比率---
 #百分率
 Def_Percentage = 100
@@ -1802,7 +1805,7 @@
 )=range(5)
 
 # 战斗力模块类型
-Def_MFPType_Max = 34
+Def_MFPType_Max = 36
 ModuleFightPowerTypeList = (
 Def_MFPType_Role, # 角色 0
 Def_MFPType_Equip, # 装备(装备本身) 1
@@ -1837,6 +1840,8 @@
 Def_MFPType_Shentong, # 神通 30
 Def_MFPType_FamilyZhenfa, # 阵法 31
 Def_MFPType_GatherTheSoul, # 聚魂新 32
+Def_MFPType_Face, # 头像 33
+Def_MFPType_FacePic, # 头像框 34
 Def_MFPType_Other, # 其他
 ) = range(Def_MFPType_Max)
 

--
Gitblit v1.8.0