| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package NPCHurtManager  | 
| #  | 
| # @todo:NPCÉËѪ¹ÜÀí  | 
| # @author hxp  | 
| # @date 2019-12-06  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: NPCÉËѪ¹ÜÀí  | 
| #          ÒòΪ¼ÓÈëÁËÐÖúϵͳ£¬ÐÖúÍæ¼ÒÔÝÎÞÉÏÏÞÏÞÖÆ£¬ËùÒÔ×ÜÉ˺¦»á³¬¹ý20ÒÚ  | 
| #          ÔÉËѪÁÐ±í²»Ö§³ÖÐÖú¡¢²»Ö§³Ö×ÜÉ˺¦³¬¹ý20ÒÚ£¬¹ÊÖØÐ´Ò»Ì×py°æÉËѪ¹ÜÀí£¬º¯ÊýÃüÃûÓëc++½Ó¿ÚÌṩµÄº¯ÊýÃûÒ»Ö  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2019-12-06 21:00"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import GameWorld  | 
| import PyGameData  | 
| import PlayerAssist  | 
| import AttackCommon  | 
| import IPY_GameWorld  | 
| import PlayerControl  | 
| import ChPyNetSendPack  | 
| import ItemControler  | 
| import NetPackCommon  | 
| import IpyGameDataPY  | 
| import ShareDefine  | 
| import PlayerTeam  | 
| import NPCCommon  | 
| import FBCommon  | 
| import ChConfig  | 
|   | 
| import time  | 
|   | 
|   | 
| class HurtValueObj():  | 
|     ''' ÉËѪ¶ÔÏ󣬿ÉÄÜÊÇÍæ¼Ò¡¢¶ÓÎéµÈ£¬Ö§³ÖÐÖúÐÅÏ¢µÈ  | 
|     '''  | 
|       | 
|     def __init__(self):  | 
|         self.__hurtID = 0  | 
|         self.__hurtType = ChConfig.Def_NPCHurtTypePlayer # ¾ùĬÈÏÊÇÍæ¼Ò  | 
|         self.__hurtName = ""  | 
|         self.__hurtValue = 0  | 
|         self.__isFriend = 0  | 
|         return  | 
|       | 
|     def GetValueID(self): return self.__hurtID  | 
|     def SetValueID(self, hurtID): self.__hurtID = hurtID  | 
|     def GetValueType(self): return self.__hurtType  | 
|     def SetValueType(self, hurtType): self.__hurtType = hurtType  | 
|     def GetHurtName(self): return self.__hurtName  | 
|     def SetHurtName(self, hurtName): self.__hurtName = hurtName  | 
|     def GetHurtValue(self): return self.__hurtValue  | 
|     def SetHurtValue(self, hurtValue): self.__hurtValue = hurtValue  | 
|     def GetIsFriend(self): return self.__isFriend  | 
|     def SetIsFriend(self, isFriend): self.__isFriend = isFriend  | 
|       | 
| class PlayerHurtList():  | 
|     ''' ÉËѪÁбí, ÀàËÆ IPY_GameObj.IPY_PlayerHurtList  | 
|     '''  | 
|       | 
|     def __init__(self, lineID, objID, npcID):  | 
|         GameWorld.DebugLog("³õʼ»¯NPCÉËѪÁбíʵÀý!", npcID, lineID)  | 
|         self.lineID = lineID  | 
|         self.objID = objID  | 
|         self.npcID = npcID  | 
|         self.curNPC = GameWorld.FindNPCByID(objID)  | 
|         self.__noAssitPlayerIDDict = {} # ·ÇÐÖúÍæ¼ÒID×Öµä {playerID:[assistPlayerID, ...], ...}  | 
|         self.__assistPlayerIDDict = {} # ÐÖúÍæ¼Ò¶ÔӦĿ±êID×Öµä {assistPlayerID:tagPlayerID, ...}  | 
|         self.__hurtPlayerDict = {} # ËùÓÐÉËÑªÍæ¼Ò¸öÌåʵÀý×ֵ䣬º¬ÐÖúÍæ¼Ò {playerID:HurtValueObj, ...}  | 
|           | 
|         self.__hurtSortList = []  | 
|         self.__hurtDict = {} # ÉËѪÁбíʵÀý×ֵ䣬ʵ¼ÊµÄNPCÉËѪÁбíʵÀý£¬¿ÉÄܲ»ÊÇÍæ¼Ò{(hurtID, hurtType):HurtValueObj, ...}  | 
|           | 
|         self.__assistAwardItemID = 0 # ÐÖú½±ÀøÀñºÐID  | 
|         self.__assistAwardResult = {} # {playerID:{assistPlayerID:{ÐÖúÍæ¼ÒÐÅÏ¢Êý¾Ý×Öµä}, ...}}  | 
|         return  | 
|       | 
|     def Clear(self):  | 
|         # ÔÚNPC´¥·¢ÖØÖÃÉËÑªÊ±ÖØÖ㬲»ÖØÖÃÐÖú¹ØÏµ¼°ÉËÑªÍæ¼ÒʵÀý£¬Ö»ÖØÖÃÉËѪֵ  | 
|           | 
|         GameWorld.DebugLog("ClearÖØÖÃNPCÉËѪ!", self.npcID, self.lineID)  | 
|         self.__hurtSortList = []  | 
|         self.__hurtDict = {}  | 
|         # ÖØÖÃËùÓÐÍæ¼ÒÉËѪֵ  | 
|         for hurtObj in self.__hurtPlayerDict.values():  | 
|             hurtObj.SetHurtValue(0)  | 
|         return  | 
|       | 
|     def OnDelete(self):  | 
|         # É¾³ýÉËѪÁÐ±í£¬NPCËÀÍöµ÷Óà  | 
|           | 
|         noAssistPlayerIDList = self.__noAssitPlayerIDDict.keys()  | 
|         if noAssistPlayerIDList:  | 
|             mapID = GameWorld.GetMap().GetMapID()  | 
|             queryData = [mapID, self.lineID, self.npcID, self.objID, noAssistPlayerIDList, self.__assistAwardItemID, self.__assistAwardResult]  | 
|             PlayerAssist.QueryGameServer_PlayerAssist(0, "OnBossAssistOver", queryData)  | 
|               | 
|         return  | 
|       | 
|     def __GetHurtTypeObj(self, hurtID, hurtType, hurtName=""):  | 
|         ## »ñÈ¡ÉËѪÁбíÉËѪÀàÐÍʵÀý  | 
|         hurtObj = None  | 
|         hurtKey = (hurtID, hurtType)  | 
|         if hurtKey not in self.__hurtDict:  | 
|             GameWorld.DebugLog("Ìí¼ÓÉËѪÁбí¶ÔÏó: hurtID=%s,hurtType=%s" % (hurtID, hurtType), self.npcID, self.lineID)  | 
|             hurtObj = HurtValueObj()  | 
|             hurtObj.SetValueID(hurtID)  | 
|             hurtObj.SetValueType(hurtType)  | 
|             hurtObj.SetHurtName(hurtName)  | 
|             self.__hurtDict[hurtKey] = hurtObj  | 
|         hurtObj = self.__hurtDict[hurtKey]  | 
|         return hurtObj  | 
|       | 
|     def __GetHurtPlayer(self, playerID, playerName=""):  | 
|         ## »ñÈ¡ÉËÑªÍæ¼ÒʵÀý, Ã¿¸öÍæ¼Ò¶ÀÁ¢, ÇÒÉËѪ¶ÀÁ¢Í³¼Æ  | 
|         hurtPlayer = None  | 
|         if playerID not in self.__hurtPlayerDict:  | 
|             GameWorld.DebugLog("Ìí¼ÓÉËÑªÍæ¼Ò: playerID=%s,playerName=%s" % (playerID, playerName), self.npcID, self.lineID)  | 
|             hurtPlayer = HurtValueObj()  | 
|             hurtPlayer.SetValueID(playerID)  | 
|             #hurtPlayer.SetHurtName(playerName)  | 
|             self.__hurtPlayerDict[playerID] = hurtPlayer  | 
|         hurtPlayer = self.__hurtPlayerDict[playerID]  | 
|         # ÒòΪÉËÑªÍæ¼Ò¿ÉÄÜÔÚijЩÇé¿öÏ´´½¨ÁËûÓÐÃû×ÖµÄʵÀý£¬ËùÒÔÕâÀïÔÚÓд«ÈëÃû×Öʱ½øÐÐÇ¿ÖÆ¸üР | 
|         if playerName:  | 
|             hurtPlayer.SetHurtName(playerName)  | 
|         return hurtPlayer  | 
|       | 
|     def AddAssistPlayer(self, assistPlayerID, assistPlayerName, isFriend, tagPlayerID, tagPlayerName, tagTeamID):  | 
|         ## Ìí¼ÓÖúÕ½Íæ¼Ò  | 
|         # @param assistPlayerID: ÐÖúÍæ¼ÒID  | 
|         # @param tagPlayerID: Ä¿±êÍæ¼ÒID£¬¼´·¢²¼ÐÖúµÄÍæ¼ÒID  | 
|                   | 
|         if assistPlayerID == tagPlayerID:  | 
|             # ²»ÄÜÐÖú×Ô¼º  | 
|             return  | 
|           | 
|         if tagPlayerID not in self.__noAssitPlayerIDDict or tagPlayerID not in self.__hurtPlayerDict:  | 
|             GameWorld.ErrLog("ÐÂÔöÐÖúÍæ¼ÒÒì³££¬²»´æÔڸ󣹿ÉËÑªÍæ¼Ò£¬ÎÞ·¨ÐÖúËû!assistPlayerID=%s,tagPlayerID=%s"   | 
|                              % (assistPlayerID, tagPlayerID), self.npcID, self.lineID)  | 
|             return  | 
|           | 
|         GameWorld.DebugLog("ÐÂÔöÐÖúÍæ¼Ò: assistPlayerID=%s,tagPlayerID=%s,tagTeamID=%s,isFriend=%s"   | 
|                            % (assistPlayerID, tagPlayerID, tagTeamID, isFriend), self.npcID, self.lineID)  | 
|           | 
|         if assistPlayerID in self.__noAssitPlayerIDDict:  | 
|             GameWorld.DebugLog("ÔÀ´Îª³£¹æÍæ¼Ò£¬ÐèÒªÏÈɾ³ý£¡", self.npcID, self.lineID)  | 
|             self.DelHurtPlayer(assistPlayerID, "BecomeAssistPlayer")  | 
|               | 
|         assistPlayerIDList = self.__noAssitPlayerIDDict[tagPlayerID]  | 
|         if assistPlayerID not in assistPlayerIDList:  | 
|             assistPlayerIDList.append(assistPlayerID)  | 
|         self.__assistPlayerIDDict[assistPlayerID] = tagPlayerID  | 
|           | 
|         assistHurtPlayer = self.__GetHurtPlayer(assistPlayerID, assistPlayerName)  | 
|         assistHurtPlayer.SetIsFriend(isFriend)  | 
|         GameWorld.DebugLog("    self.__noAssitPlayerIDDict=%s" % (self.__noAssitPlayerIDDict), self.npcID, self.lineID)  | 
|         GameWorld.DebugLog("    self.__assistPlayerIDDict=%s" % (self.__assistPlayerIDDict), self.npcID, self.lineID)  | 
|         return  | 
|       | 
|     def DelHurtPlayer(self, playerID, reason, isMapServerDel=True):  | 
|         ## É¾³ýÉËÑªÍæ¼Ò, ¿ÉÄÜÓɵØÍ¼¡¢GameServer´¥·¢É¾³ý  | 
|           | 
|         if playerID not in self.__hurtPlayerDict:  | 
|             return  | 
|           | 
|         GameWorld.DebugLog("ɾ³ýÉËÑªÍæ¼Ò: playerID=%s,reason=%s,isMapServerDel=%s" % (playerID, reason, isMapServerDel), self.npcID, self.lineID)  | 
|               | 
|         #·ÇÐÖúÍæ¼Ò  | 
|         if playerID in self.__noAssitPlayerIDDict:  | 
|             # ÏÈÇåÍæ¼ÒÉËѪ  | 
|             self.__ClearPlayerHurt(playerID)  | 
|               | 
|             assistPlayerIDList = self.__noAssitPlayerIDDict.pop(playerID, [])  | 
|             GameWorld.DebugLog("    Êdz£¹æÍæ¼Ò£¬Í¬Ê±É¾³ýÐÖúÍæ¼Ò: assistPlayerIDList=%s" % assistPlayerIDList, self.npcID, self.lineID)  | 
|               | 
|             # Ç¿ÖÆÉ¾³ýËùÓÐÐÖú¸ÃÍæ¼Ò£¬ÁÐ±íµ¹Ðòɾ  | 
|             for assistPlayerID in assistPlayerIDList[::-1]:  | 
|                 self.DelHurtPlayer(assistPlayerID, "RequestPlayerCancel_%s" % reason, isMapServerDel)  | 
|                   | 
|             # µØÍ¼É¾³ýµÄͬ²½GameServer  | 
|             if isMapServerDel:  | 
|                 mapID = GameWorld.GetMap().GetMapID()  | 
|                 queryData = [mapID, self.lineID, self.npcID, self.objID, reason]  | 
|                 PlayerAssist.QueryGameServer_PlayerAssist(playerID, "OnCancelBossRequestAssist", queryData)  | 
|                   | 
|         # ÐÖúÍæ¼Ò  | 
|         elif playerID in self.__assistPlayerIDDict:  | 
|             # ÏÈÇåÍæ¼ÒÉËѪ  | 
|             self.__ClearPlayerHurt(playerID)  | 
|               | 
|             tagPlayerID = self.__assistPlayerIDDict.pop(playerID, 0)  | 
|               | 
|             # ÒƳýÐÖú¶ÔÓ¦¹ØÏµ  | 
|             if tagPlayerID in self.__noAssitPlayerIDDict:  | 
|                 assistPlayerIDList = self.__noAssitPlayerIDDict[tagPlayerID]  | 
|                 if playerID in assistPlayerIDList:  | 
|                     assistPlayerIDList.remove(playerID)  | 
|                     GameWorld.DebugLog("    ÊÇÐÖúÍæ¼Ò£¬É¾³ýÐÖú¹ØÏµ: tagPlayerID=%s,assistPlayerIDList=%s"   | 
|                                        % (tagPlayerID, self.__noAssitPlayerIDDict[tagPlayerID]), self.npcID, self.lineID)  | 
|               | 
|             # µØÍ¼É¾³ýµÄͬ²½GameServer  | 
|             if isMapServerDel:  | 
|                 mapID = GameWorld.GetMap().GetMapID()  | 
|                 queryData = [mapID, self.lineID, self.npcID, self.objID, reason]  | 
|                 PlayerAssist.QueryGameServer_PlayerAssist(playerID, "OnCancelBossAssist", queryData)  | 
|                   | 
|         self.__hurtPlayerDict.pop(playerID) # ·ÅÔÚ×îºópopÉËѪʵÀý  | 
|           | 
|         if not self.__hurtPlayerDict:  | 
|             GameWorld.DebugLog("ûÓÐÉËÑªÍæ¼ÒÁË!", self.npcID, self.lineID)  | 
|             self.Clear()  | 
|               | 
|         return  | 
|       | 
|     def HaveHurtValue(self, playerID):  | 
|         ## ÊÇ·ñ¶Ô¸ÃbossÓÐÉ˺¦¹±Ï×  | 
|           | 
|         if playerID not in self.__hurtPlayerDict:  | 
|             return False  | 
|           | 
|         hurtPlayer = self.__GetHurtPlayer(playerID)  | 
|         if hurtPlayer.GetHurtValue():  | 
|             return True  | 
|           | 
|         if playerID in self.__noAssitPlayerIDDict:  | 
|             assistPlayerIDList = self.__noAssitPlayerIDDict[playerID]  | 
|             for assistPlayerID in assistPlayerIDList:  | 
|                 assHurtPlayer = self.__GetHurtPlayer(assistPlayerID)  | 
|                 if assHurtPlayer.GetHurtValue():  | 
|                     return True  | 
|                   | 
|         return False  | 
|       | 
|     def GetPlayerHurtDetail(self, playerID):  | 
|         ## Íæ¼ÒÉËѪÊä³öÃ÷ϸ - ÔÝʱGMÃüÁîÊä³öÊý¾ÝÓà  | 
|         # @return: hurtValue, {assistPlayerID:hurtValue, ...}  | 
|           | 
|         if playerID in self.__noAssitPlayerIDDict:  | 
|             hurtPlayer = self.__GetHurtPlayer(playerID)  | 
|             assistPlayerHurtDict = {}  | 
|             assistPlayerIDList = self.__noAssitPlayerIDDict[playerID]  | 
|             for assistPlayerID in assistPlayerIDList:  | 
|                 assHurtPlayer = self.__GetHurtPlayer(assistPlayerID)  | 
|                 assistPlayerHurtDict[assistPlayerID] = assHurtPlayer.GetHurtValue()  | 
|             return hurtPlayer.GetHurtValue(), assistPlayerHurtDict  | 
|           | 
|         if playerID in self.__assistPlayerIDDict:  | 
|             assHurtPlayer = self.__GetHurtPlayer(playerID)  | 
|             return assHurtPlayer.GetHurtValue(), {}  | 
|           | 
|         return 0, {}  | 
|       | 
|     def GetNoAssitPlayerIDDict(self): return self.__noAssitPlayerIDDict  | 
|     def GetAssistPlayerIDDict(self): return self.__assistPlayerIDDict  | 
|       | 
|     def IsNoAssistPlayer(self, playerID):  | 
|         ## ÊÇ·ñ·ÇÖúÕ½ÉËÑªÍæ¼Ò  | 
|         return  playerID in self.__noAssitPlayerIDDict  | 
|       | 
|     def IsAssistPlayer(self, playerID):  | 
|         ## ÊÇ·ñÖúÕ½ÉËÑªÍæ¼Ò  | 
|         return playerID in self.__assistPlayerIDDict  | 
|           | 
|     def IsAssistRelation(self, playerID, tagPlayerID):  | 
|         ## Íæ¼ÒË«·½ÊÇ·ñ´æÔÚÐÖú¹ØÏµ  | 
|           | 
|         # AÐÖúB  | 
|         if playerID in self.__assistPlayerIDDict:  | 
|             if self.__assistPlayerIDDict[playerID] == tagPlayerID:  | 
|                 #GameWorld.DebugLog("%s ÐÖú  %s" % (playerID, tagPlayerID))  | 
|                 return True  | 
|               | 
|         # BÐÖúA  | 
|         elif tagPlayerID in self.__assistPlayerIDDict:  | 
|             if self.__assistPlayerIDDict[tagPlayerID] == playerID:  | 
|                 #GameWorld.DebugLog("%s ÐÖú  %s" % (tagPlayerID, playerID))  | 
|                 return True  | 
|               | 
|         # ÐÖúͬһ¸öÍæ¼Ò  | 
|         for assPlayerIDList in self.__noAssitPlayerIDDict.values():  | 
|             if playerID in assPlayerIDList and tagPlayerID in assPlayerIDList:  | 
|                 #GameWorld.DebugLog("ÐÖúÍ¬Ò»Íæ¼Ò! %s %s" % (playerID, tagPlayerID))  | 
|                 return True  | 
|               | 
|         return False  | 
|       | 
|     def OnHurtPlayerEnterTeam(self, playerID, playerName, befTeamID, newTeam, tick):  | 
|         ''' ÉËÑªÍæ¼Ò¼ÓÈë¶ÓÎé  | 
|                                 ¸öÈËÉ˺¦²¢Èë¶ÓÎéÉ˺¦£¬¸öÈËËùÓÐÐÖúÍæ¼ÒÉ˺¦ÖØÐÂͳ¼Æ£¬±íÏÖÔÚÐÖúÉ˺¦ÅÅÐаñ£¬ÐÖúÍæ¼ÒÖ®ºóµÄÉ˺¦¼ÆÈë¶ÓÎéÉ˺¦  | 
|         '''  | 
|         if playerID not in self.__noAssitPlayerIDDict:  | 
|             # Ö»´¦Àí·ÇÐÖúÍæ¼Ò  | 
|             return  | 
|           | 
|         newTeamID = newTeam.GetTeamID()  | 
|           | 
|         if befTeamID:  | 
|             # ÒòΪ±ØÐëÊÇÏÈÍ˶ÓÔÙ½ø¶ÓµÄ£¬ËùÒÔ½øÈë¶ÓÎéʱ²»´æÔÚÓÐ֮ǰ¶ÓÎéIDµÄÇé¿ö  | 
|             GameWorld.ErrLog("Íæ¼Ò½øÈëʱÒÑÓжÓÎé!playerID=%s,befTeamID=%s,newTeamID=%s" % (playerID, befTeamID, newTeamID), self.npcID, self.lineID)  | 
|             return  | 
|           | 
|         # ¸üÐÂÍæ¼Ò¸öÈËÉËѪÀàÐÍ¡¢ID  | 
|         hurtPlayer = self.__GetHurtPlayer(playerID, playerName)  | 
|         hurtPlayer.SetValueType(ChConfig.Def_NPCHurtTypeTeam)  | 
|         hurtPlayer.SetValueID(newTeamID)  | 
|           | 
|         # É¾³ý¸öÈËÉËѪÁбíʵÀý  | 
|         playerTotalHurt = 0  | 
|         playerHurtKey = (playerID , ChConfig.Def_NPCHurtTypePlayer)  | 
|         if playerHurtKey in self.__hurtDict:  | 
|             playerHurtObj = self.__hurtDict.pop(playerHurtKey)  | 
|             playerTotalHurt = playerHurtObj.GetHurtValue()  | 
|               | 
|         GameWorld.DebugLog("³£¹æÉËÑªÍæ¼Ò¼ÓÈë¶ÓÎé: playerID=%s,playerTotalHurt=%s,newTeamID=%s"   | 
|                            % (playerID, playerTotalHurt, newTeamID), self.npcID, self.lineID)  | 
|           | 
|         # ÉËѪ²¢Èë¶ÓÎéÉËѪ  | 
|         if playerTotalHurt:  | 
|             teamHurtObj = self.__GetHurtTypeObj(newTeamID , ChConfig.Def_NPCHurtTypeTeam, playerName)  | 
|             teamHurtValue = teamHurtObj.GetHurtValue()  | 
|             updTeamHurtValue = teamHurtValue + playerTotalHurt  | 
|             teamHurtObj.SetHurtValue(updTeamHurtValue)  | 
|             GameWorld.DebugLog("    ¸öÈË×ÜÉËѪ²¢ÈëжÓÎéÉËѪ: teamHurtValue=%s,playerTotalHurt=%s,updTeamHurtValue=%s"   | 
|                                % (teamHurtValue, playerTotalHurt, updTeamHurtValue), self.npcID, self.lineID)  | 
|             self.__UpdHurtTeamName(newTeamID)  | 
|                 | 
|         self.Sort()  | 
|         return  | 
|       | 
|     def OnHurtPlayerLeaveTeam(self, playerID, leaveTeamID, tick):  | 
|         ''' ÉËÑªÍæ¼ÒÍ˳ö¶ÓÎé  | 
|                                 Ô¶ÓÎéÉ˺¦²»±ä£¬¸öÈ˼°ËùÓÐÐÖúÍæ¼ÒÉ˺¦ÖØÐ¼ÆË㣬ÐÖúÍæ¼ÒÖ®ºóµÄÉ˺¦¼ÆÈë¸öÈËÉ˺¦£»  | 
|                               ÀëÏß±»ÌßÀë¶ÓµÄÇé¿öÐÖúÍæ¼Ò¿É¼ÌÐøÐÖúÊä³ö²¢»ñµÃÐÖú½±Àø£¬É˺¦¼ÆÈë¸öÈË£¬µ«ÊÇÀëÏßÍæ¼ÒÎÞ·¨»ñµÃ¹éÊô  | 
|         '''  | 
|         if playerID not in self.__noAssitPlayerIDDict:  | 
|             # Ö»´¦Àí·ÇÐÖúÍæ¼Ò  | 
|             return  | 
|           | 
|         # Íæ¼Ò¸öÈËÉËѪÀàÐÍ¡¢ID  | 
|         hurtPlayer = self.__GetHurtPlayer(playerID)  | 
|         hurtPlayer.SetValueType(ChConfig.Def_NPCHurtTypePlayer)  | 
|         hurtPlayer.SetValueID(playerID)  | 
|           | 
|         # Í³¼Æ¸öÈ˼°ÐÖú×ÜÉ˺¦  | 
|         playerTotalHurt = hurtPlayer.GetHurtValue()  | 
|         assistPlayerIDList = self.__noAssitPlayerIDDict.get(playerID, [])  | 
|         for assistPlayerID in assistPlayerIDList:  | 
|             assistHurtPlayer = self.__GetHurtPlayer(assistPlayerID)  | 
|             playerTotalHurt += assistHurtPlayer.GetHurtValue()  | 
|           | 
|         GameWorld.DebugLog("³£¹æÉËÑªÍæ¼ÒÀ뿪¶ÓÎé: playerID=%s,playerTotalHurt=%s,leaveTeamID=%s"   | 
|                            % (playerID, playerTotalHurt, leaveTeamID), self.npcID, self.lineID)  | 
|           | 
|         if not playerTotalHurt:  | 
|             return  | 
|           | 
|         # Ô¶ÓÎé¿Û³ý¶ÔÓ¦É˺¦  | 
|         teamHurtKey = (leaveTeamID , ChConfig.Def_NPCHurtTypeTeam)  | 
|         if teamHurtKey in self.__hurtDict:  | 
|             teamHurtObj = self.__hurtDict[teamHurtKey]  | 
|             teamHurtValue = teamHurtObj.GetHurtValue()  | 
|             updTeamHurtValue = max(0, teamHurtValue - playerTotalHurt)  | 
|             teamHurtObj.SetHurtValue(updTeamHurtValue)  | 
|             GameWorld.DebugLog("    Ô¶ÓÎéÉ˺¦¿Û³ý: teamHurtValue=%s,playerTotalHurt=%s,updTeamHurtValue=%s"   | 
|                                % (teamHurtValue, playerTotalHurt, updTeamHurtValue), self.npcID, self.lineID)  | 
|             self.__UpdHurtTeamName(leaveTeamID)  | 
|               | 
|         # ´´½¨Ð¸öÈËÉ˺¦ÁбíʵÀý  | 
|         newHurtObj = self.__GetHurtTypeObj(playerID, ChConfig.Def_NPCHurtTypePlayer, hurtPlayer.GetHurtName())  | 
|         newHurtObj.SetHurtValue(playerTotalHurt)  | 
|           | 
|         self.Sort()  | 
|         return  | 
|       | 
|     def __UpdHurtTeamName(self, teamID):  | 
|         ## ¸üжÓÎéÉËѪÃû³Æ£¬¶Ó³¤ÔÚÓÅÏÈʹÓöӳ¤Ãû×Ö£¬·ñÔòʹÓÃÈÎÒâÒ»¸öÔÚÏß¹¥»÷´ËbossµÄ·ÇÐÖú¶ÓÔ±Ãû  | 
|           | 
|         hurtTeamObj = self.__GetHurtTypeObj(teamID , ChConfig.Def_NPCHurtTypeTeam)  | 
|           | 
|         updName = ""  | 
|         copyPlayerManager = GameWorld.GetMapCopyPlayerManager()  | 
|         mapTeamPlayerIDList = PlayerTeam.GetMapTeamPlayerIDList(teamID)  | 
|         for memPlayerID in mapTeamPlayerIDList:  | 
|             if memPlayerID not in self.__noAssitPlayerIDDict:  | 
|                 continue  | 
|             player = copyPlayerManager.FindPlayerByID(memPlayerID)  | 
|             if not player:  | 
|                 continue  | 
|             playerName = player.GetPlayerName()  | 
|             if player.GetTeamLV() == IPY_GameWorld.tmlLeader:  | 
|                 hurtTeamObj.SetHurtName(playerName)  | 
|                 GameWorld.DebugLog("    ¸üжÓÎéÃû³Æ£¬Ê¹Óöӳ¤Ãû³Æ!teamID=%s" % teamID, self.npcID, self.lineID)  | 
|                 return  | 
|             if not updName:  | 
|                 updName = playerName  | 
|                   | 
|         if updName:  | 
|             hurtTeamObj.SetHurtName(updName)  | 
|             GameWorld.DebugLog("    ¸üжÓÎéÃû³Æ£¬Ê¹ÓöÓÔ±Ãû³Æ!teamID=%s" % teamID, self.npcID, self.lineID)  | 
|         return  | 
|       | 
|     def AddPlayerHurtValue(self, atkPlayerID, atkName, value, atkTeamID=0, isSort=False):  | 
|         ## Ìí¼ÓÍæ¼ÒÉËѪ  | 
|           | 
|         tagPlayerID = 0 # ÐÖúÄ¿±êÍæ¼ÒID  | 
|         atkHurtPlayer = self.__GetHurtPlayer(atkPlayerID, atkName)  | 
|         if atkPlayerID in self.__assistPlayerIDDict:  | 
|             tagPlayerID = self.__assistPlayerIDDict[atkPlayerID]  | 
|             tagHurtPlayer = self.__GetHurtPlayer(tagPlayerID)  | 
|             tagPlayerName = tagHurtPlayer.GetHurtName()  | 
|             hurtID, hurtType = tagHurtPlayer.GetValueID(), tagHurtPlayer.GetValueType()  | 
|             #GameWorld.DebugLog("ÐÖúÍæ¼ÒÉËѪ: atkPlayerID=%s,value=%s,tagPlayerID=%s" % (atkPlayerID, value, tagPlayerID), self.npcID, self.lineID)  | 
|               | 
|         else:  | 
|             if atkTeamID:  | 
|                 hurtID, hurtType = atkTeamID, ChConfig.Def_NPCHurtTypeTeam  | 
|             else:  | 
|                 hurtID, hurtType = atkPlayerID, ChConfig.Def_NPCHurtTypePlayer  | 
|             atkHurtPlayer.SetValueType(hurtType)  | 
|             atkHurtPlayer.SetValueID(hurtID)  | 
|             if atkPlayerID not in self.__noAssitPlayerIDDict:  | 
|                 self.__noAssitPlayerIDDict[atkPlayerID] = []  | 
|                 GameWorld.DebugLog("ÐÂÔö³£¹æÍæ¼Ò: atkPlayerID=%s" % (atkPlayerID), self.npcID, self.lineID)  | 
|             #GameWorld.DebugLog("³£¹æÍæ¼ÒÉËѪ: atkPlayerID=%s,value=%s" % (atkPlayerID, value), self.npcID, self.lineID)  | 
|               | 
|         hurtObj = self.__GetHurtTypeObj(hurtID, hurtType, tagPlayerName if tagPlayerID else atkName)  | 
|           | 
|         # ÉËѪÁбíÉËѪÀÛ¼Ó  | 
|         befValue = hurtObj.GetHurtValue()  | 
|         updValue = befValue + value  | 
|         hurtObj.SetHurtValue(updValue)  | 
|         isNewHurt = befValue == 0 and updValue > 0  | 
|           | 
|         # ÉËÑªÍæ¼ÒÉËѪÀÛ¼Ó£¬Õâ¸ö½öÉËÑªÍæ¼Ò×Ô¼ºµÄ¸öÈËÊä³ö£¬·ÇÉËѪÁбíÖеĻã×ÜÊä³ö  | 
|         updAtkHurtValue = atkHurtPlayer.GetHurtValue() + value  | 
|         atkHurtPlayer.SetHurtValue(updAtkHurtValue)  | 
|           | 
|         #GameWorld.DebugLog("    hurtID=%s,hurtType=%s,hurtValue=%s (%s + %s) updAtkHurtValue=%s"   | 
|         #                   % (hurtID, hurtType, updValue, befValue, value, updAtkHurtValue), self.npcID, self.lineID)  | 
|           | 
|         if isNewHurt or isSort:  | 
|             self.Sort()  | 
|                   | 
|         return  | 
|       | 
|     def RefreshHurtList(self, tick, refreshInterval=3000, isDead=False):  | 
|         ## Ë¢ÐÂÉËѪÁÐ±í  | 
|         # @return: atkPlayer, hurtID, hurtType  | 
|           | 
|         curNPC = self.curNPC  | 
|           | 
|         if not isDead:  | 
|             if refreshInterval and tick - curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastRefreshHurtTick) < refreshInterval:  | 
|                 return self.__GetAtkObjByHurtList(isDead)  | 
|               | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_LastRefreshHurtTick, tick)  | 
|           | 
|         hurtPlayerDict = {} # {playerID:teamID, ...}  | 
|         refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|         for hurtKey in self.__hurtDict.keys():  | 
|             #»ñµÃÉËѪ¶ÔÏó  | 
|             hurtID, hurtType = hurtKey  | 
|             if not hurtID:  | 
|                 continue  | 
|               | 
|             if hurtType == ChConfig.Def_NPCHurtTypePlayer:  | 
|                 teamID = 0  | 
|                 playerID = hurtID  | 
|                 if self.__UnAssistPlayerHurtValidLogic(playerID, refreshPoint, tick):  | 
|                     hurtPlayerDict[playerID] = teamID  | 
|                       | 
|             elif hurtType == ChConfig.Def_NPCHurtTypeTeam:  | 
|                 teamID = hurtID  | 
|                 mapTeamPlayerIDList = PlayerTeam.GetMapTeamPlayerIDList(teamID)  | 
|                 for teamPlayerID in mapTeamPlayerIDList:  | 
|                     if self.__UnAssistPlayerHurtValidLogic(teamPlayerID, refreshPoint, tick):  | 
|                         hurtPlayerDict[teamPlayerID] = teamID  | 
|                           | 
|         mapID = GameWorld.GetMap().GetMapID()  | 
|         if NPCCommon.IsMapNeedBossShunt(mapID):  | 
|             self.__UpdBossShuntInfo(mapID, hurtPlayerDict, tick)  | 
|               | 
|         self.Sort()  | 
|           | 
|         if isDead:  | 
|             self.__DoGiveAssistAward()  | 
|               | 
|         isInHurt = self.__hurtSortList != []  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_InHurtProtect, isInHurt)  | 
|         return self.__GetAtkObjByHurtList(isDead)  | 
|       | 
|     def __UnAssistPlayerHurtValidLogic(self, playerID, refreshPoint, tick):  | 
|         ## ·ÇÐÖúÍæ¼ÒÉËѪÓÐЧÐÔ¼ì²éÂß¼  | 
|           | 
|         valid = False  | 
|         checkPlayerIDList = [playerID] + self.__noAssitPlayerIDDict.get(playerID, []) # ¼ì²éËùÓÐÓйØÏµµÄÍæ¼ÒID  | 
|         for checkPlayerID in checkPlayerIDList:  | 
|             if self.__IsPlayerHurtValid(checkPlayerID, refreshPoint, tick):  | 
|                 valid = True  | 
|             else:  | 
|                 self.__ClearPlayerHurt(checkPlayerID)  | 
|                   | 
|         return valid  | 
|       | 
|     def __IsPlayerHurtValid(self, playerID, refreshPoint, tick):  | 
|         ## Íæ¼ÒÉËѪÊÇ·ñ»¹ÓÐЧ  | 
|           | 
|         if playerID not in self.__hurtPlayerDict:  | 
|             return False  | 
|           | 
|         hurtPlayer = self.__GetHurtPlayer(playerID)  | 
|         hurtValue = hurtPlayer.GetHurtValue()  | 
|         if not hurtValue:  | 
|             return False  | 
|           | 
|         player = GameWorld.GetMapCopyPlayerManager().FindPlayerByID(playerID)  | 
|         if player:  | 
|             if playerID in self.__noAssitPlayerIDDict:  | 
|                 if not AttackCommon.CheckKillNPCByCnt(player, self.curNPC, False):  | 
|                     GameWorld.DebugLog("·ÇÐÖúÉËÑªÍæ¼ÒûÓй¥»÷boss´ÎÊý£¬²»¼Æ£¡playerID=%s" % playerID, self.npcID, self.lineID)  | 
|                     return False  | 
|                   | 
|             if player.GetInitOK() and (not player.GetVisible() or player.GetSightLevel() != self.curNPC.GetSightLevel()):  | 
|                 GameWorld.DebugLog("ÉËÑªÍæ¼Ò²»¿É¼û£¬²»¼Æ£¡playerID=%s" % playerID, self.npcID, self.lineID)  | 
|                 return False  | 
|               | 
|             if player.GetHP() <= 0 or player.GetPlayerAction() == IPY_GameWorld.paDie:  | 
|                 deadTime = player.NomalDictGetProperty(ChConfig.Def_Player_Dict_DeadTime)  | 
|                 if time.time() - deadTime >= IpyGameDataPY.GetFuncCfg("BossHurtValue", 1):  | 
|                     GameWorld.DebugLog("ÉËÑªÍæ¼ÒËÀÍö³¬¹ýÉËѪ±£»¤Ê±³¤£¬²»¼Æ!playerID=%s" % playerID, self.npcID, self.lineID)  | 
|                     return False  | 
|                   | 
|             if not self.__GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint):  | 
|                 GameWorld.DebugLog("ÉËÑªÍæ¼Ò²»ÔÚboss·¶Î§ÄÚ£¬²»¼Æ£¡playerID=%s" % playerID, self.npcID, self.lineID)  | 
|                 return False  | 
|               | 
|             return True  | 
|           | 
|         else:  | 
|               | 
|             # ÊÇ·ñÀëÏß³¬¹ý3·ÖÖÓ£¬ÏÂÏß×ø±êÊÇ·ñ²»ÔÚbossÇøÓòµÈ  | 
|             leaveTick = PlayerControl.GetPlayerLeaveServerTick(playerID)  | 
|             leavePos = PlayerControl.GetPlayerLeaveServerPos(playerID)  | 
|             if not leaveTick or not leavePos:  | 
|                 GameWorld.DebugLog("ÉËÑªÍæ¼Ò²»ÔÚ±¾µØÍ¼»òÒѳ¤¾ÃÀëÏߣ¬²»¼Æ£¡playerID=%s" % playerID, self.npcID, self.lineID)  | 
|                 return False  | 
|               | 
|             if tick - leaveTick > ChConfig.Def_PlayerOfflineProtectTime:  | 
|                 GameWorld.DebugLog("ÉËѪÀëÏßÍæ¼Ò³¬¹ý±£»¤Ê±³¤£¬²»¼Æ£¡playerID=%s,tick=%s,leaveTick=%s" % (playerID, tick, leaveTick), self.npcID, self.lineID)  | 
|                 return False  | 
|               | 
|             if not self.__GetIsInRefreshPoint(leavePos[0], leavePos[1], refreshPoint):  | 
|                 GameWorld.DebugLog("ÉËѪÀëÏßÍæ¼Ò²»ÔÚ±£»¤ÇøÓòÄÚ£¬²»¼Æ£¡playerID=%s,leavePos=%s" % (playerID, leavePos), self.npcID, self.lineID)  | 
|                 return False  | 
|               | 
|             return True  | 
|           | 
|         return False  | 
|       | 
|     def __ClearPlayerHurt(self, playerID):  | 
|         ## Çå³ýÍæ¼ÒÉËѪ£¬²»É¾ÊµÀý  | 
|           | 
|         if playerID not in self.__hurtPlayerDict:  | 
|             return  | 
|           | 
|         hurtPlayer = self.__GetHurtPlayer(playerID)  | 
|         hurtValue = hurtPlayer.GetHurtValue()  | 
|         if not hurtValue:  | 
|             return  | 
|         hurtPlayer.SetHurtValue(0)  | 
|           | 
|         # ÐÖúÍæ¼Ò  | 
|         if playerID in self.__assistPlayerIDDict:  | 
|             tagPlayerID = self.__assistPlayerIDDict[playerID]  | 
|             tagHurtPlayer = self.__GetHurtPlayer(tagPlayerID)  | 
|             hurtID = tagHurtPlayer.GetValueID()  | 
|             hurtType = tagHurtPlayer.GetValueType()  | 
|         else:  | 
|             hurtID = hurtPlayer.GetValueID()  | 
|             hurtType = hurtPlayer.GetValueType()  | 
|           | 
|         GameWorld.DebugLog("    Çå³ýÍæ¼ÒÉËѪ: playerID=%s,hurtValue=%s,hurtID=%s,hurtType=%s"   | 
|                            % (playerID, hurtValue, hurtID, hurtType), self.npcID, self.lineID)  | 
|           | 
|         hurtKey = (hurtID, hurtType)  | 
|         if hurtKey not in self.__hurtDict:  | 
|             return  | 
|           | 
|         # ¿Û³ýÉËѪÁбíʵÀýÉËѪ  | 
|         hurtObj = self.__GetHurtTypeObj(hurtID, hurtType)  | 
|         befValue = hurtObj.GetHurtValue()  | 
|         updValue = max(0, befValue - hurtValue)  | 
|         hurtObj.SetHurtValue(updValue)  | 
|         GameWorld.DebugLog("    ¿Û³ýÉËѪ¸üÐÂ: hurtID=%s,hurtType=%s,befValue=%s,updValue=%s"   | 
|                            % (hurtID, hurtType, befValue, updValue), self.npcID, self.lineID)  | 
|           | 
|         if not updValue:  | 
|             self.__hurtDict.pop(hurtKey)  | 
|         else:  | 
|             # Èç¹ûÊÇ·ÇÐÖúÍæ¼Ò¶ÓÎé¶ÓÔ±ÉËѪ±»Ç壬Ôò¸üÐÂÉËѪ¶ÓÎéÃû³Æ  | 
|             if playerID in self.__noAssitPlayerIDDict and hurtType == ChConfig.Def_NPCHurtTypeTeam:  | 
|                 self.__UpdHurtTeamName(hurtID)  | 
|                   | 
|         return  | 
|       | 
|     def __GetAtkObjByHurtList(self, isDead):  | 
|         '''µÚÒ»¸ö¿É¹¥»÷µÄ×î´óÉËѪ¶ÔÏó£¬Ò²ÊÇʵ¼ÊµÄ¹éÊôÕß»ò¶ÓÎé  | 
|         ÒòÎªÍæ¼ÒÉËѪµôÏß¡¢ËÀÍöÓÐÒ»¶¨Ê±¼äµÄ±£Áô»úÖÆ£¬¹Ê×î´óÉËѪ²»Ò»¶¨Êǿɹ¥»÷Ä¿±ê(¹éÊôÕß)  | 
|         ×¢Òâ: ¸Ã¹æÔò±ØÐëÓë×îÖÕËã¹éÊôµÄ¹æÔòÒ»Ö£¬²»È»¿ÉÄܵ¼Ö¹éÊô´íÂÒ  | 
|         @return: atkPlayer, hurtType, hurtID  | 
|         '''  | 
|           | 
|         atkPlayer, atkHurtType, atkHurtID = None, 0, 0  | 
|         curNPC = self.curNPC  | 
|         refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|         for rank, hurtObj in enumerate(self.__hurtSortList, 1):  | 
|               | 
|             hurtID = hurtObj.GetValueID()  | 
|             hurtType = hurtObj.GetValueType()  | 
|               | 
|             playerIDList = []  | 
|             if hurtType == ChConfig.Def_NPCHurtTypePlayer:  | 
|                 assistPlayerIDList = self.__noAssitPlayerIDDict.get(hurtID, [])  | 
|                 playerIDList = [hurtID] + assistPlayerIDList  | 
|                   | 
|             elif hurtType == ChConfig.Def_NPCHurtTypeTeam:  | 
|                 teamID = hurtID  | 
|                 mapTeamPlayerIDList = PlayerTeam.GetMapTeamPlayerIDList(teamID)  | 
|                 for teamPlayerID in mapTeamPlayerIDList:  | 
|                     if teamPlayerID not in self.__noAssitPlayerIDDict:  | 
|                         continue  | 
|                     playerIDList.append(teamPlayerID)  | 
|                     assistPlayerIDList = self.__noAssitPlayerIDDict.get(teamPlayerID, [])  | 
|                     playerIDList.extend(assistPlayerIDList)  | 
|                       | 
|             else:  | 
|                 continue  | 
|               | 
|             playerDisableReason = {}  | 
|             maxHurtValue = 0  | 
|             for playerID in playerIDList:  | 
|                   | 
|                 player = GameWorld.GetObj(playerID, IPY_GameWorld.gotPlayer)  | 
|                 if player == None:  | 
|                     continue  | 
|                   | 
|                 if player.GetHP() <= 0 or player.GetPlayerAction() == IPY_GameWorld.paDie:  | 
|                     playerDisableReason[playerID] = "dead"  | 
|                     continue  | 
|                   | 
|                 if not player.GetVisible() or player.GetSightLevel() != curNPC.GetSightLevel():  | 
|                     playerDisableReason[playerID] = "no visible or sightLevel different"  | 
|                     continue  | 
|                   | 
|                 if not self.__GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint):  | 
|                     playerDisableReason[playerID] = "not in boss area"  | 
|                     continue  | 
|                   | 
|                 if playerID not in self.__hurtPlayerDict:  | 
|                     playerDisableReason[playerID] = "no hurt"  | 
|                     continue  | 
|                 hurtPlayer = self.__hurtPlayerDict[playerID]  | 
|                 hurtValue = hurtPlayer.GetHurtValue()                  | 
|                 if hurtValue > maxHurtValue:  | 
|                     maxHurtValue = hurtValue  | 
|                     atkPlayer, atkHurtType, atkHurtID = player, hurtType, hurtID  | 
|                       | 
|             if maxHurtValue:  | 
|                 return atkPlayer, atkHurtType, atkHurtID  | 
|               | 
|             if rank == 1 and isDead:  | 
|                 GameWorld.Log("bossËÀÍöʱ£¬µÚÒ»ÃûÍŶÓûÓйéÊôȨ! playerDisableReason=%s" % playerDisableReason)  | 
|                   | 
|         return atkPlayer, atkHurtType, atkHurtID  | 
|       | 
|     def __GetIsInRefreshPoint(self, curPosX, curPosY, refreshPoint):  | 
|         if not refreshPoint:  | 
|             return False  | 
|           | 
|         if (curPosX >= refreshPoint.GetPosX() - refreshPoint.GetMoveDist() and  | 
|                 curPosX <= refreshPoint.GetPosX() + refreshPoint.GetMoveDist() and  | 
|                 curPosY >= refreshPoint.GetPosY() - refreshPoint.GetMoveDist() and  | 
|                 curPosY <= refreshPoint.GetPosY() + refreshPoint.GetMoveDist()):  | 
|             return True  | 
|           | 
|         return False  | 
|       | 
|     def __UpdBossShuntInfo(self, mapID, hurtPlayerDict, tick):  | 
|         ## ¸üб¾µØÍ¼Ïß·boss·ÖÁ÷ÐÅÏ¢  | 
|         npcID = self.npcID  | 
|         lineID = self.lineID  | 
|         key = (mapID, lineID)  | 
|         shuntPlayerDict = PyGameData.g_bossShuntPlayerInfo.get(key, {})  | 
|           | 
|         shuntChange = False  | 
|         for playerID, shuntInfo in shuntPlayerDict.items():  | 
|             bossID, teamID, relatedTick = shuntInfo  | 
|             if bossID != npcID:  | 
|                 # ²»ÊǸÃbossµÄÉ˺¦²»´¦Àí  | 
|                 continue  | 
|               | 
|             # »¹ÔÚÉËѪÖÐ  | 
|             if playerID in hurtPlayerDict:  | 
|                 newTeamID = hurtPlayerDict[playerID]  | 
|                 if newTeamID != teamID:  | 
|                     shuntPlayerDict[playerID] = [npcID, newTeamID, 0]  | 
|                     shuntChange = True  | 
|                     GameWorld.DebugLog("boss·ÖÁ÷ -> Íæ¼Ò¶Ô¸ÃbossµÄÉ˺¦±ä¸ü¶ÓÎé!playerID=%s,npcID=%s,teamID=%s,newTeamID=%s"   | 
|                                        % (playerID, npcID, teamID, newTeamID), lineID)  | 
|                 elif relatedTick:  | 
|                     shuntPlayerDict[playerID] = [npcID, newTeamID, 0]  | 
|                     shuntChange = True  | 
|                     GameWorld.DebugLog("boss·ÖÁ÷ -> Íæ¼Ò¶Ô¸ÃbossµÄ¹ØÁª×´Ì¬×ªÎªÉ˺¦×´Ì¬!playerID=%s,npcID=%s,teamID=%s,newTeamID=%s"   | 
|                                        % (playerID, npcID, teamID, newTeamID), lineID)  | 
|                       | 
|             # ²»ÔÚÉËѪÖУ¬¸üйØÁªtick  | 
|             elif not relatedTick:  | 
|                 shuntPlayerDict[playerID] = [npcID, teamID, tick]  | 
|                 shuntChange = True  | 
|                 GameWorld.DebugLog("boss·ÖÁ÷ -> Íæ¼Ò²»ÔÚ¸ÃbossÉËѪÖУ¬ÉèÖÃΪ¹ØÁª×´Ì¬!playerID=%s,npcID=%s,teamID=%s,tick=%s"   | 
|                                    % (playerID, npcID, teamID, tick), lineID)  | 
|                   | 
|         # ÉËÏÈÓÅÏȼ¶×î¸ß£¬¿ÉÖ±½Ó¸²¸Ç¸üР | 
|         for playerID, teamID in hurtPlayerDict.items():  | 
|             if playerID not in shuntPlayerDict:  | 
|                 shuntPlayerDict[playerID] = [npcID, teamID, 0]  | 
|                 shuntChange = True  | 
|                 GameWorld.DebugLog("boss·ÖÁ÷ -> ÐÂÔöÍæ¼Ò¶ÔbossÉ˺¦!playerID=%s,npcID=%s,teamID=%s" % (playerID, npcID, teamID), lineID)  | 
|                   | 
|             elif shuntPlayerDict[playerID][0] != npcID:  | 
|                 shuntPlayerDict[playerID] = [npcID, teamID, 0]  | 
|                 shuntChange = True  | 
|                 GameWorld.DebugLog("boss·ÖÁ÷ -> É˺¦×ªÒƵ½±¾bossÉÏ!playerID=%s,npcID=%s,teamID=%s" % (playerID, npcID, teamID), lineID)  | 
|                   | 
|         if shuntChange:  | 
|             PyGameData.g_bossShuntPlayerInfo[key] = shuntPlayerDict  | 
|             NPCCommon.GameServer_WorldBossShuntInfo(mapID, lineID)  | 
|         return  | 
|       | 
|     def __DoGiveAssistAward(self):  | 
|         ''' Ö´ÐÐÐÖú½±ÀøÂß¼  | 
|         '''  | 
|           | 
|         self.__assistAwardResult = {}  | 
|           | 
|         liheItemID, assistMoney = 0, 0  | 
|         mapAssistGiftDict = IpyGameDataPY.GetFuncEvalCfg("AssistAward", 2, {})  | 
|         mapID = FBCommon.GetRecordMapID(GameWorld.GetMap().GetMapID())  | 
|         if str(mapID) in mapAssistGiftDict:  | 
|             liheItemID, assistMoney = mapAssistGiftDict[str(mapID)]  | 
|         else:  | 
|             killBossCntLimitDict = IpyGameDataPY.GetFuncEvalCfg('KillBossCntLimit')   | 
|             index = GameWorld.GetDictValueByKey(killBossCntLimitDict, self.npcID)  | 
|             if index == None:  | 
|                 return  | 
|             bossAssistGiftDict = IpyGameDataPY.GetFuncEvalCfg("AssistAward", 1, {})  | 
|             if str(index) not in bossAssistGiftDict:  | 
|                 GameWorld.DebugLog("¸ÃbossûÓÐÐÖú¶îÍâ½±Àø!index=%s" % index, self.npcID)  | 
|                 return  | 
|             liheItemID, assistMoney = bossAssistGiftDict[str(index)]  | 
|               | 
|         if not liheItemID or not assistMoney:  | 
|             GameWorld.DebugLog("¸Ã¸±±¾»òbossûÓÐÐÖú¶îÍâ½±Àø!mapID=%s" % (mapID), self.npcID)  | 
|             return  | 
|         self.__assistAwardItemID = liheItemID  | 
|           | 
|         fbType = GameWorld.GetMap().GetMapFBTypeByMapID(mapID)  | 
|         GameWorld.DebugLog("Ö´ÐÐÐÖú½±ÀøÂß¼", self.npcID, self.lineID)  | 
|         copyPlayerManager = GameWorld.GetMapCopyPlayerManager()  | 
|         for playerID, assistPlayerIDList in self.__noAssitPlayerIDDict.items():  | 
|             if not assistPlayerIDList:  | 
|                 GameWorld.DebugLog("·¢²¼·½Ã»Óз¢²¼ÐÖú£¬²»´¦Àí: playerID=%s" % playerID, self.npcID, self.lineID)  | 
|                 continue  | 
|               | 
|             noAssistPlayer = copyPlayerManager.FindPlayerByID(playerID)  | 
|               | 
|             assistAwardPlayerDict = {}  | 
|             # ¼´Ê¹·¢²¼·½²»ÔÚÏߣ¬ÐÖú·½Íê³ÉºóÒ²¿É»ñµÃ»îÔ¾Áî½±Àø£¬Ö»ÊDz»Ò»¶¨»ñµÃÀñºÐ¸Ðл½±Àø£¨ÀñºÐ¸Ðл½±ÀøÐèË«·½¶¼ÔÚÏߣ©  | 
|             for assistPlayerID in assistPlayerIDList:  | 
|                 assistHurtPlayer = self.__GetHurtPlayer(assistPlayerID)  | 
|                 if not assistHurtPlayer.GetHurtValue():  | 
|                     GameWorld.DebugLog("ÐÖú·½Ã»ÓÐÊä³ö£¬²»¸ø½±Àø: assistPlayerID=%s" % assistPlayerID, self.npcID, self.lineID)  | 
|                     continue  | 
|                 assistPlayer = copyPlayerManager.FindPlayerByID(assistPlayerID)  | 
|                 if not assistPlayer:  | 
|                     GameWorld.DebugLog("ÐÖú·½ÀëÏß»ò²»ÔÚ±¾µØÍ¼£¬²»¸ø»îÔ¾Áî½±Àø: assistPlayerID=%s" % assistPlayerID, self.npcID, self.lineID)  | 
|                     continue  | 
|                 isFriend = assistHurtPlayer.GetIsFriend()  | 
|                 assistMoneyType = ShareDefine.TYPE_Price_FamilyActivity  | 
|                 addAssistMoney = PlayerAssist.AddTodayAssistMoney(assistPlayer, assistMoneyType, assistMoney, isFriend)  | 
|                 GameWorld.DebugLog("ÐÖú·½¸ø»îÔ¾Áî½±Àø: assistPlayerID=%s,assistMoney=%s,isFriend=%s,addAssistMoney=%s"   | 
|                                    % (assistPlayerID, assistMoney, isFriend, addAssistMoney), self.npcID, self.lineID)  | 
|                 if fbType == IPY_GameWorld.fbtNull:  | 
|                     PlayerControl.NotifyCode(assistPlayer, "AssistSuccess")  | 
|                 else:  | 
|                     overDict = {FBCommon.Over_isAssist:1, FBCommon.Over_money:FBCommon.GetJsonMoneyList({assistMoneyType:addAssistMoney}),  | 
|                                 FBCommon.Over_itemInfo:[]}  | 
|                     FBCommon.NotifyFBOver(assistPlayer, mapID, PlayerControl.GetFBFuncLineID(assistPlayer), 1, overDict)  | 
|                     assistPlayer.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, 10000, True)  | 
|                       | 
|                 if noAssistPlayer:  | 
|                     todayGiftCount = assistPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GetThanksGiftCount % liheItemID)  | 
|                     assistAwardPlayerDict[assistPlayerID] = {"PlayerName":assistPlayer.GetPlayerName(), "Job":assistPlayer.GetJob(),   | 
|                                                              "LV":assistPlayer.GetLV(), "RealmLV":assistPlayer.GetOfficialRank(),  | 
|                                                              "TodayGiftCount":todayGiftCount}  | 
|                       | 
|                     notifyParam = [assistPlayer.GetPlayerName(), noAssistPlayer.GetPlayerName(), mapID, self.curNPC.GetLV(), self.npcID]  | 
|                     PlayerControl.FamilyNotify(assistPlayer.GetFamilyID(), "AssistBossFinish", notifyParam)  | 
|                       | 
|             if not noAssistPlayer or not assistAwardPlayerDict:  | 
|                 GameWorld.DebugLog("·¢²¼·½ÀëÏß»òÎÞÓÐЧÐÖúÍæ¼ÒÔÚÏߣ¬²»¸ø¸ÐлÀñºÐ½±Àø: playerID=%s" % playerID, self.npcID, self.lineID)  | 
|                 continue  | 
|               | 
|             GameWorld.DebugLog("·¢²¼·½¸ø¸ÐлÀñºÐ½±Àø: playerID=%s" % playerID, self.npcID, self.lineID)  | 
|             ItemControler.GivePlayerItemOrMail(noAssistPlayer, [[liheItemID, 1, 0]])  | 
|             self.__assistAwardResult[playerID] = assistAwardPlayerDict  | 
|               | 
|         return  | 
|       | 
|     def __CmpHurtValue(self, hurtObjA, hurtObjB):  | 
|         ## É˺¦ÅÅÐò±È½Ïº¯Êý  | 
|         if hurtObjA.GetHurtValue() > hurtObjB.GetHurtValue():  | 
|             return 1  | 
|         if hurtObjA.GetHurtValue() == hurtObjB.GetHurtValue():  | 
|             return 0  | 
|         return -1  | 
|       | 
|     def Sort(self, isSync=True):  | 
|         ## ÉËѪÅÅÐò  | 
|         self.__hurtSortList = sorted(self.__hurtDict.values(), cmp=self.__CmpHurtValue, reverse=True)  | 
|           | 
|         if not isSync:  | 
|             return  | 
|           | 
|         syncPlayerIDList = self.__noAssitPlayerIDDict.keys() + self.__assistPlayerIDDict.keys()  | 
|         if not syncPlayerIDList:  | 
|             return  | 
|           | 
|         # Ôݶ¨ÅÅÐòºóĬÈÏͬ²½ÉËѪÁÐ±í¸øËùÓÐÏà¹ØÍæ¼Ò£¬ÉËѪΪ0µÄ²»Í¬²½Ç°¶Ë£¬½öÓÃÓÚºó¶ËÂß¼Óà  | 
|         hurtValueList = []  | 
|         for hurtObj in self.__hurtSortList:  | 
|             hurtValue = hurtObj.GetHurtValue()  | 
|             if not hurtValue:  | 
|                 continue  | 
|             hurtValueObj = ChPyNetSendPack.tagMCBossHurtValue()  | 
|             hurtValueObj.HurtID = hurtObj.GetValueID()  | 
|             hurtValueObj.HurtType = hurtObj.GetValueType()  | 
|             hurtValueObj.HurtName = hurtObj.GetHurtName()  | 
|             hurtValueObj.HurtValue = hurtValue % ShareDefine.Def_PerPointValue  | 
|             hurtValueObj.HurtValueEx = hurtValue / ShareDefine.Def_PerPointValue  | 
|             hurtValueList.append(hurtValueObj)  | 
|           | 
|         bossHurtInfoPack = ChPyNetSendPack.tagMCBossHurtValueRankInfo()  | 
|         bossHurtInfoPack.ObjID = self.objID  | 
|         bossHurtInfoPack.HurtValueList = hurtValueList  | 
|         bossHurtInfoPack.HurtCount = len(hurtValueList)  | 
|           | 
|         curNPC = self.curNPC  | 
|         assistHurtValueListDict = {}  | 
|         copyPlayerManager = GameWorld.GetMapCopyPlayerManager()  | 
|         for playerID in syncPlayerIDList:  | 
|             player = copyPlayerManager.FindPlayerByID(playerID)  | 
|             if not player:  | 
|                 continue  | 
|             if not player.CanSeeOther(curNPC):  | 
|                 continue  | 
|             if playerID in self.__noAssitPlayerIDDict:  | 
|                 assTagPlayerID = playerID  | 
|             elif playerID in self.__assistPlayerIDDict:  | 
|                 assTagPlayerID = self.__assistPlayerIDDict[playerID]  | 
|             else:  | 
|                 continue  | 
|               | 
|             if assTagPlayerID not in assistHurtValueListDict:      | 
|                 assistPlayerIDList = self.__noAssitPlayerIDDict[assTagPlayerID]  | 
|                 assistHurtValueList = []  | 
|                 for assistPlayerID in assistPlayerIDList:  | 
|                     assHurtPlayer = self.__GetHurtPlayer(assistPlayerID)  | 
|                     assHurtValue = assHurtPlayer.GetHurtValue()  | 
|                     if not assHurtValue:  | 
|                         continue  | 
|                     assHurtValueObj = ChPyNetSendPack.tagMCBossHurtValueAssist()  | 
|                     assHurtValueObj.PlayerID = assHurtPlayer.GetValueID()  | 
|                     assHurtValueObj.PlayerName = assHurtPlayer.GetHurtName()  | 
|                     assHurtValueObj.HurtValue = assHurtValue % ShareDefine.Def_PerPointValue  | 
|                     assHurtValueObj.HurtValueEx = assHurtValue / ShareDefine.Def_PerPointValue  | 
|                     assistHurtValueList.append(assHurtValueObj)  | 
|                 assistHurtValueListDict[assTagPlayerID] = assistHurtValueList  | 
|                   | 
|             assistHurtValueList = assistHurtValueListDict[assTagPlayerID]  | 
|             bossHurtInfoPack.AssistHurtValueList = assistHurtValueList  | 
|             bossHurtInfoPack.AssistHurtCount = len(assistHurtValueList)  | 
|             NetPackCommon.SendFakePack(player, bossHurtInfoPack)  | 
|               | 
|         return  | 
|       | 
|     def GetHurtCount(self): return len(self.__hurtSortList)  | 
|     def GetHurtAt(self, index): return self.__hurtSortList[index]  | 
|       | 
|     def GetMaxHurtValue(self): return None if not self.__hurtSortList else self.__hurtSortList[0]  | 
|     def GetLastTimeHurtValue(self):  | 
|         return  | 
|   | 
| def OnPlayerLeaveMap(curPlayer):  | 
|     ## Íæ¼ÒÀ뿪µØÍ¼´¦Àí  | 
|       | 
|     mapID = curPlayer.GetMapID()  | 
|     mapType = GameWorld.GetMap().GetMapFBType()  | 
|     changeMapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ChangeMapID)  | 
|     changeLineID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ChangeLineID)  | 
|       | 
|     playerID = curPlayer.GetPlayerID()  | 
|     for hurtList in PyGameData.g_npcHurtDict.values():  | 
|         if hurtList.IsNoAssistPlayer(playerID) or hurtList.IsAssistPlayer(playerID):  | 
|             if mapType == IPY_GameWorld.fbtNull and mapID == changeMapID and changeLineID == hurtList.lineID:  | 
|                 #GameWorld.DebugLog("Íæ¼ÒͬµØÍ¼ÇÐÏߣ¬µ±Ç°ÉËѪlineIDΪĿ±êÏß·£¬²»ÇåÉËѪ!changeLineID=%s" % changeLineID, playerID)  | 
|                 continue  | 
|             GameWorld.DebugLog("Íæ¼ÒÀ뿪µØÍ¼, É¾³ýbossÉËÑªÍæ¼Ò!npcID=%s" % (hurtList.npcID), playerID)  | 
|             hurtList.DelHurtPlayer(playerID, "LeaveMap")  | 
|             break  | 
|           | 
|     return  | 
|   | 
| def OnSetAssistTagPlayerID(curPlayer, value):  | 
|     '''Íæ¼Ò¸üÐÂÁËеÄÐÖú¶ÔÏóÍæ¼ÒID  | 
|         ÐèÒª Çå³ý±¾µØÍ¼ÖÐÍæ¼ÒÒÔ·ÇÐÖúÉí·ÝÕýÔÚ¹¥»÷µÄboss  | 
|           | 
|         ÒÔÐÖúÉí·Ý¹¥»÷µÄͨ¹ýGameServer½øÐÐÇå³ý£¬ÒòÎªÍæ¼Ò¿ÉÄܲ»ºÍÐÖúÄ¿±êͬһ¸öµØÍ¼  | 
|         ±ÈÈçÏȵãÁËÐÖúAÍæ¼Ò£¬»¹Ã»¹ýÈ¥µÄʱºò£¬ÓÖµãÁËÐÖúBÍæ¼Ò£¬ËùÒÔÐèҪͨ¹ýGameServerÇå³ýÐÖúÄ¿±êµÄÏà¹ØÊý¾Ý  | 
|     '''  | 
|           | 
|     if not value:  | 
|         # Ö»´¦ÀíÓÐÐÖúÄ¿±êµÄÇé¿ö  | 
|         return  | 
|       | 
|     playerID = curPlayer.GetPlayerID()  | 
|     for hurtList in PyGameData.g_npcHurtDict.values():  | 
|         if hurtList.IsNoAssistPlayer(playerID):  | 
|             GameWorld.DebugLog("Íæ¼Ò¿ªÊ¼ÐÖúÆäËûÈË, É¾³ý¸ÃbossÉËѪ!npcID=%s" % (hurtList.npcID), playerID)  | 
|             hurtList.DelHurtPlayer(playerID, "StartAssistBoss")  | 
|             break  | 
|           | 
|     return  | 
|   | 
| def ClearPlayerHurtList(curNPC):  | 
|     ## Çå¿ÕÉËѪÁÐ±í  | 
|     defendHurtList = GetPlayerHurtList(curNPC)  | 
|     if not defendHurtList:  | 
|         return  | 
|     defendHurtList.Clear()  | 
|     return  | 
|   | 
| def GetBossLineID(npcID):  | 
|     sealDemonIpyData = IpyGameDataPY.GetIpyGameDataNotLog("SealDemon", npcID)  | 
|     if sealDemonIpyData:  | 
|         lineID = sealDemonIpyData.GetLineID()  | 
|     else:  | 
|         lineID = GameWorld.GetGameWorld().GetLineID()  | 
|     return lineID  | 
|   | 
| def DeletePlayerHurtList(curNPC):  | 
|     ## É¾³ýÉËѪÁÐ±í  | 
|     objID = curNPC.GetID()  | 
|     npcID = curNPC.GetNPCID()  | 
|     lineID = GetBossLineID(npcID)  | 
|     key = (lineID, objID, npcID)  | 
|     if key in PyGameData.g_npcHurtDict:  | 
|         hurtList =PyGameData.g_npcHurtDict.pop(key)  | 
|         hurtList.OnDelete()  | 
|           | 
|     return  | 
|   | 
| def GetPlayerHurtList(curNPC):  | 
|     ## »ñÈ¡ÉËѪÁÐ±í£¬¿ÉÄÜΪNone  | 
|     objID = curNPC.GetID()  | 
|     npcID = curNPC.GetNPCID()  | 
|     lineID = GetBossLineID(npcID)  | 
|     return GetPlayerHurtListEx(lineID, objID, npcID)  | 
| def GetPlayerHurtListEx(lineID, objID, npcID):  | 
|     ## »ñÈ¡ÉËѪÁÐ±í£¬¿ÉÄÜΪNone  | 
|     key = (lineID, objID, npcID)  | 
|     defendHurtList = None  | 
|     if key not in PyGameData.g_npcHurtDict:  | 
|         ## Ö»Í³¼Æ×î´óÉËѪ¹éÊôµÄboss  | 
|         npcData = GameWorld.GetGameData().FindNPCDataByID(npcID)  | 
|         if not npcData or not ChConfig.IsGameBoss(npcData):  | 
|             return defendHurtList  | 
|         if NPCCommon.GetDropOwnerType(npcData) != ChConfig.DropOwnerType_MaxHurt:  | 
|             mapID = GameWorld.GetMap().GetMapID()  | 
|             if mapID not in [ChConfig.Def_FBMapID_SealDemon]:  | 
|                 return defendHurtList  | 
|         defendHurtList = PlayerHurtList(lineID, objID, npcID)  | 
|         PyGameData.g_npcHurtDict[key] = defendHurtList  | 
|     defendHurtList = PyGameData.g_npcHurtDict[key]  | 
|     if not defendHurtList.curNPC:  | 
|         hurtList = PyGameData.g_npcHurtDict.pop(key)  | 
|         hurtList.OnDelete()  | 
|         return  | 
|     return defendHurtList  | 
|   | 
| def OnNPCHurtPlayerEnterTeam(playerID, playerName, befTeamID, newTeam, tick):  | 
|     ## ÉËÑªÍæ¼Ò¼ÓÈë¶ÓÎé  | 
|     for hurtList in PyGameData.g_npcHurtDict.values():  | 
|         hurtList.OnHurtPlayerEnterTeam(playerID, playerName, befTeamID, newTeam, tick)  | 
|     return  | 
|   | 
| def OnNPCHurtPlayerLeaveTeam(playerID, leaveTeamID, tick):  | 
|     ## ÉËÑªÍæ¼ÒÀ뿪¶ÓÎé  | 
|     for hurtList in PyGameData.g_npcHurtDict.values():  | 
|         hurtList.OnHurtPlayerLeaveTeam(playerID, leaveTeamID, tick)  | 
|     return  | 
|   | 
| def AddHurtValue(atkPlayer, defNPC, value, isBounce):  | 
|     '''Ìí¼ÓÉËѪ  | 
|     @param isBounce: ÊÇ·ñ·´µ¯É˺¦£¬·´µ¯É˺¦²»¼ÆÈë·ÇÖ÷¶¯¹¥»÷µÄÍæ¼ÒÉËѪ£¬ÒòΪ¹æ¶¨Íæ¼Ò¹¥»÷ÁíÒ»¸öbossÔòÒªÇå³ýͬµØÍ¼ÉÏÒ»¸öbossµÄ¸ÃÍæ¼ÒÉ˺¦  | 
|                                                         ·ÀÖ¹ËÀÍö»Ø¸´»îµãÅÜͼÖб»Ö÷¶¯ÐÍboss¹¥»÷¼ÆÈëÉËѪµ¼ÖÂÇå³ýͬµØÍ¼ÉÏÒ»¸öÖ÷¶¯¹¥»÷µÄbossÉËѪ  | 
|     '''  | 
|       | 
|     defendHurtList = GetPlayerHurtList(defNPC)  | 
|     if not defendHurtList:  | 
|         return  | 
|     atkPlayerID = atkPlayer.GetPlayerID()  | 
|       | 
|     if isBounce and not defendHurtList.HaveHurtValue(atkPlayerID):  | 
|         GameWorld.DebugLog("»¹Ã»ÓÐÉ˺¦Êä³öʱ·´µ¯É˺¦²»¼ÆÈë!", atkPlayerID)  | 
|         return  | 
|       | 
|     objID = defNPC.GetID()  | 
|     npcID = defNPC.GetNPCID()  | 
|     # É¾³ýÆäËûbossÉËѪ¡¢ÐÖú  | 
|     for hurtList in PyGameData.g_npcHurtDict.values():  | 
|         if hurtList.npcID == npcID and hurtList.objID == objID:  | 
|             continue  | 
|         if not hurtList.IsNoAssistPlayer(atkPlayerID) and not hurtList.IsAssistPlayer(atkPlayerID):  | 
|             continue  | 
|         GameWorld.Log("Íæ¼ÒÖ÷¶¯¹¥»÷ÁËÆäËûboss£¬È¡ÏûÔbossÉËѪÐÖúµÈÊý¾Ý! befNPCID=%s,newNPCID=%s" % (hurtList.npcID, npcID))  | 
|         hurtList.DelHurtPlayer(atkPlayerID, "AttackNewBoss")  | 
|           | 
|     defendHurtList.AddPlayerHurtValue(atkPlayerID, atkPlayer.GetPlayerName(), value, atkPlayer.GetTeamID())  | 
|     return True  | 
|   | 
| def RefreshHurtList(curNPC, tick, refreshInterval=3000, isDead=False):  | 
|     ## Ë¢ÐÂÉËѪÁÐ±í  | 
|     # @return: atkPlayer, ownerType, ownerID  | 
|     defendHurtList = GetPlayerHurtList(curNPC)  | 
|     if not defendHurtList:  | 
|         return  | 
|     return defendHurtList.RefreshHurtList(tick, refreshInterval, isDead)  | 
|   | 
| def IsAssistPlayer(playerID, defNPC):  | 
|     ## ÊÇ·ñÐÖúÖеÄÍæ¼Ò  | 
|     defendHurtList = GetPlayerHurtList(defNPC)  | 
|     if not defendHurtList:  | 
|         return False  | 
|     return defendHurtList.IsAssistPlayer(playerID)  | 
|   | 
| def IsAssistRelation(curPlayer, tagPlayer):  | 
|     ## Ë«·½ÊÇ·ñÐÖú¹ØÏµ  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     tagPlayerID = tagPlayer.GetPlayerID()  | 
|     for hurtList in PyGameData.g_npcHurtDict.values():  | 
|         if hurtList.IsAssistRelation(playerID, tagPlayerID):  | 
|             return True  | 
|     return False  | 
|   | 
| def CheckPlayerCanAttackFBNPC(curPlayer, curNPC, mapID, isNotify=False):  | 
|     ## ¼ì²éÍæ¼Ò¿É·ñ¹¥»÷Óи±±¾´ÎÊýµÄNPC  | 
|     enterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_EnterFbCntDay % mapID)  | 
|     if enterCnt < FBCommon.GetEnterFBMaxCnt(curPlayer, mapID):  | 
|         return True  | 
|       | 
|     # Ã»ÓдÎÊýµÄ£¬Èç¹ûÊÇÖúÕ½Íæ¼ÒÒ²¿É¹¥»÷  | 
|     if IsAssistPlayer(curPlayer.GetPlayerID(), curNPC):  | 
|         return True  | 
|       | 
|     if isNotify:  | 
|         PlayerControl.NotifyCode(curPlayer, "AttackFBBossLimit")  | 
|           | 
|     return False  | 
|   |