| #!/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  | 
|         if ipyData.GetCustomPlayerID():  | 
|             # Íæ¼Ò¶¨ÖƵIJ»´¦Àí  | 
|             continue  | 
|         if not GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_FaceState, faceID):  | 
|             # Î´¼¤»îµÄ²»´¦Àí  | 
|             continue  | 
|         endTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceEndTime % faceID)  | 
|         if not endTime or 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  | 
|         if not GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_FacePicState, facePicID):  | 
|             # Î´¼¤»îµÄ²»´¦Àí  | 
|             continue  | 
|         endTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicEndTime % facePicID)  | 
|         if not endTime or 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  | 
|     if ipyData.GetCustomPlayerID():  | 
|         GameWorld.DebugLog("Íæ¼Ò¶¨ÖƵÄÍ·Ïñ²»ÓÃÌí¼Ó: faceID=%s" % (faceID), playerID)  | 
|         return  | 
|     ipyExpireSeconds = ipyData.GetExpireMinutes() * 60  | 
|       | 
|     curTime = int(time.time())  | 
|     state = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_FaceState, faceID)  | 
|     endTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceEndTime % faceID)  | 
|     GameWorld.Log("Ìí¼ÓÍ·Ïñ: faceID=%s,setExpireTimes=%s,state=%s,endTime=%s,ipyExpireSeconds=%s,curTime=%s"   | 
|                   % (faceID, setExpireTimes, state, endTime, ipyExpireSeconds, curTime), playerID)  | 
|     updEndTime = endTime  | 
|       | 
|     # Ö¸¶¨Ê±³¤µÄ£¬ÈçGMÖ¸¶¨  | 
|     if setExpireTimes > 0:  | 
|         updEndTime = curTime + setExpireTimes  | 
|         GameWorld.Log("    Ö¸¶¨Í·Ïñʱ³¤: faceID=%s,updEndTime=%s" % (faceID, updEndTime), playerID)  | 
|           | 
|     # ÓÀ¾Ã  | 
|     elif ipyExpireSeconds == 0 or setExpireTimes == 0:  | 
|         updEndTime = 0  | 
|         GameWorld.Log("    Ìí¼ÓÓÀ¾ÃÍ·Ïñ: faceID=%s,updEndTime=%s" % (faceID, updEndTime), playerID)  | 
|           | 
|     else:  | 
|         # Î´¹ýÆÚ  | 
|         if endTime > curTime:  | 
|             updEndTime = endTime + ipyExpireSeconds  | 
|             GameWorld.Log("    ÀÛ¼ÓÍ·Ïñʱ³¤: faceID=%s,updEndTime=%s" % (faceID, updEndTime), playerID)  | 
|         else:  | 
|             updEndTime = curTime + ipyExpireSeconds  | 
|             GameWorld.Log("    ÖØÐ¼¤»îÍ·Ïñ: faceID=%s,updEndTime=%s" % (faceID, updEndTime), playerID)  | 
|               | 
|     GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_FaceState, faceID, 1)  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceEndTime % faceID, updEndTime)  | 
|     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  | 
|     if ipyData.GetCustomPlayerID():  | 
|         return  | 
|     GameWorld.Log("ɾ³ýÍ·Ïñ: faceID=%s,notifyMail=%s" % (faceID, notifyMail), playerID)  | 
|     GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_FaceState, faceID, 0)  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceEndTime % 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())  | 
|     state = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_FacePicState, facePicID)  | 
|     endTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicEndTime % facePicID)  | 
|     GameWorld.Log("Ìí¼ÓÍ·Ïñ¿ò: facePicID=%s,setExpireTimes=%s,state=%s,endTime=%s,ipyExpireSeconds=%s,curTime=%s"   | 
|                   % (facePicID, setExpireTimes, state, endTime, ipyExpireSeconds, curTime), playerID)  | 
|     updEndTime = endTime  | 
|       | 
|     # Ö¸¶¨Ê±³¤µÄ£¬ÈçGMÖ¸¶¨  | 
|     if setExpireTimes > 0:  | 
|         updEndTime = curTime + setExpireTimes  | 
|         GameWorld.Log("    Ö¸¶¨Í·Ïñ¿òʱ³¤: facePicID=%s,updEndTime=%s" % (facePicID, updEndTime), playerID)  | 
|           | 
|     # ÓÀ¾Ã  | 
|     elif ipyExpireSeconds == 0 or setExpireTimes == 0:  | 
|         updEndTime = 0  | 
|         GameWorld.Log("    Ìí¼ÓÓÀ¾ÃÍ·Ïñ¿ò: facePicID=%s,updEndTime=%s" % (facePicID, updEndTime), playerID)  | 
|           | 
|     else:  | 
|         # Î´¹ýÆÚ  | 
|         if endTime > curTime:  | 
|             updEndTime = endTime + ipyExpireSeconds  | 
|             GameWorld.Log("    ÀÛ¼ÓÍ·Ïñ¿òʱ³¤: facePicID=%s,updEndTime=%s" % (facePicID, updEndTime), playerID)  | 
|         else:  | 
|             updEndTime = curTime + ipyExpireSeconds  | 
|             GameWorld.Log("    ÖØÐ¼¤»îÍ·Ïñ¿ò: facePicID=%s,updEndTime=%s" % (facePicID, updEndTime), playerID)  | 
|               | 
|     GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_FacePicState, facePicID, 1)  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicEndTime % facePicID, updEndTime)  | 
|     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)  | 
|     GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_FacePicState, facePicID, 0)  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicEndTime % 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 IsFaceCanUse(curPlayer, faceID, ipyData=None):  | 
|     ## Í·ÏñÊÇ·ñ¿ÉÓà  | 
|     state = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_FaceState, faceID)  | 
|     if state:  | 
|         return True  | 
|       | 
|     if not ipyData:  | 
|         ipyData = IpyGameDataPY.GetIpyGameData("PlayerFace", faceID)  | 
|     if ipyData:  | 
|         if ipyData.GetUnlockDefault():  | 
|             return True  | 
|         if ipyData.GetCustomPlayerID() and ipyData.GetCustomPlayerID() == curPlayer.GetPlayerID():  | 
|             return True  | 
|           | 
|     return False  | 
|   | 
| def IsFacePicCanUse(curPlayer, facePicID, ipyData=None):  | 
|     ## Í·Ïñ¿òÊÇ·ñ¿ÉÓà  | 
|     state = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_FacePicState, facePicID)  | 
|     if state:  | 
|         return True  | 
|       | 
|     if not ipyData:  | 
|         ipyData = IpyGameDataPY.GetIpyGameData("PlayerFacePic", facePicID)  | 
|     if ipyData:  | 
|         if ipyData.GetUnlockDefault():  | 
|             return True  | 
|           | 
|     return False  | 
|   | 
| 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)  | 
|     PlayerControl.SetMFPExFightPower(curPlayer, 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)  | 
|     PlayerControl.SetMFPExFightPower(curPlayer, 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  | 
|   | 
| def GMSetFaceStar(curPlayer, faceID, setValue=None):  | 
|     ## GMÉèÖÃÐǼ¶  | 
|       | 
|     if not IsFaceCanUse(curPlayer, faceID):  | 
|         return False, "The player has not activated the faceID(%s)" % faceID  | 
|       | 
|     if setValue == None:  | 
|         curStar = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceStar % faceID)  | 
|         setStar = curStar + 1 # Ã»Ö¸¶¨ÐǼ¶Ê±Ä¬ÈÏÉýÐÇ  | 
|     else:  | 
|         setStar = setValue  | 
|           | 
|     if setStar > 0:  | 
|         if not IpyGameDataPY.GetIpyGameData("PlayerFaceStar", faceID, setStar):  | 
|             return False, "The faceID(%s) star(%s) is not exist." % (faceID, setStar)  | 
|           | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FaceStar % faceID, setStar)  | 
|     GameWorld.Log("GMÉèÖÃÍ·ÏñÐǼ¶: faceID=%s,setStar=%s" % (faceID, setStar), curPlayer.GetPlayerID())  | 
|       | 
|     RefreshFaceAttr(curPlayer)  | 
|     SyncFaceInfo(curPlayer, [faceID])  | 
|     return True, ""  | 
|   | 
| #// 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 GMSetFacePicStar(curPlayer, facePicID, setValue=None):  | 
|     ## GMÉèÖÃÐǼ¶  | 
|       | 
|     if not IsFacePicCanUse(curPlayer, facePicID):  | 
|         return False, "The player has not activated the facePicID(%s)" % facePicID  | 
|       | 
|     if setValue == None:  | 
|         curStar = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicStar % facePicID)  | 
|         setStar = curStar + 1 # Ã»Ö¸¶¨ÐǼ¶Ê±Ä¬ÈÏÉýÐÇ  | 
|     else:  | 
|         setStar = setValue  | 
|           | 
|     if setStar > 0:  | 
|         if not IpyGameDataPY.GetIpyGameData("PlayerFacePicStar", facePicID, setStar):  | 
|             return False, "The setStar(%s) star(%s) is not exist." % (setStar, setStar)  | 
|           | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FacePicStar % facePicID, setStar)  | 
|     GameWorld.Log("GMÉèÖÃÍ·Ïñ¿òÐǼ¶: facePicID=%s,setStar=%s" % (facePicID, setStar), curPlayer.GetPlayerID())  | 
|       | 
|     RefreshFacePicAttr(curPlayer)  | 
|     SyncFacePicInfo(curPlayer, [facePicID])  | 
|     return True, ""  | 
|   | 
| 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:  | 
|         state = 1 if IsFaceCanUse(curPlayer, faceID) else 0  | 
|         if not state and faceIDList == None:  | 
|             continue  | 
|         face = ChPyNetSendPack.tagMCFace()  | 
|         face.FaceID = faceID  | 
|         face.State = state  | 
|         face.EndTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FaceEndTime % 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:  | 
|         state = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_FacePicState, facePicID)  | 
|         if not state and facePicIDList == None:  | 
|             continue  | 
|         facePic = ChPyNetSendPack.tagMCFacePic()  | 
|         facePic.FacePicID = facePicID  | 
|         facePic.State = state  | 
|         facePic.EndTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FacePicEndTime % 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  |