| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #---------------------------------------------------------------------  | 
| #  | 
| #---------------------------------------------------------------------  | 
| ##@package NPCCommon  | 
| #npcͨÓÃÄ£¿é  | 
| #  | 
| # @author Alee  | 
| # @date 2010-02-20 16:30  | 
| # @version 1.1  | 
| #  | 
| # @change: "2018-07-09 15:30" hxp ×°±¸µôÂäÑÕÉ«¶ÔÓ¦¼þÊýÉÏÏÞÓÉÔÀ´µÄÖ»ÏÞÖÆ¶ÀÁ¢¸ÅÂʸÄΪ¹«¹²ÏÞÖÆÌõ¼þ  | 
| #  | 
| #------------------------------------------------------------------------------   | 
| #"""Version = 2018-07-09 15:30"""  | 
| #---------------------------------------------------------------------  | 
| import IPY_GameWorld  | 
| import GameWorld  | 
| import PlayerControl  | 
| import GameMap  | 
| import ChConfig  | 
| import EventShell  | 
| import SkillShell  | 
| import BuffSkill  | 
| import BaseAttack  | 
| import ChNetSendPack  | 
| import SkillCommon  | 
| import AttackCommon  | 
| import ItemControler  | 
| import ItemCommon  | 
| import FBLogic  | 
| import ReadChConfig  | 
| import PetControl  | 
| import NPCAI  | 
| import OperControlManager  | 
| import ShareDefine  | 
| import ChItem  | 
| #import AICommon  | 
| import ChPyNetSendPack  | 
| import DataRecordPack  | 
| import NetPackCommon  | 
| import FBCommon  | 
| import PlayerActivity  | 
| import PlayerSuccess  | 
| import BossHurtMng  | 
| import GameLogic_FamilyInvade  | 
| import GameLogic_GatherSoul  | 
| import FormulaControl  | 
| import PlayerBossReborn  | 
| import PlayerFairyCeremony  | 
| import PlayerNewFairyCeremony  | 
| import GameLogic_CrossGrassland  | 
| import PlayerWeekParty  | 
| import PlayerActLogin  | 
| import FamilyRobBoss  | 
| import IpyGameDataPY  | 
| import PlayerState  | 
| import PyGameData  | 
| import PlayerTeam  | 
| import PlayerVip  | 
| import GameObj  | 
| import ChNPC  | 
|   | 
| import random  | 
| import math  | 
| import time  | 
| #---------------------------------------------------------------------  | 
|   | 
| OnNPCDie = None  | 
|   | 
| # NPCÊôÐԳɳ¤ÅäÖÃÏà¹ØË÷Òý  | 
| (  | 
| NPCAttr_ParamDict, # ¹ý³Ì²ÎÊý¹«Ê½  | 
| NPCAttr_AttrStrengthenList, # µÈ¼¶³É³¤ÊôÐÔ¹«Ê½  | 
| NPCAttr_PlayerCntCoefficient, # µØÍ¼ÈËÊý¶ÔÓ¦ÊôÐÔ¶îÍâ³É³¤ÏµÊý {mapID:{"ÊôÐÔÃû":{×é¶Ó½øÈëÈËÊý:ϵÊý, ...}, ...}, ...}  | 
| NPCAttr_NPCPlayerCntCoefficient, # NPCÌØÊâ³É³¤ÈËÊý¶ÔÓ¦ÊôÐÔ¶îÍâ³É³¤ÏµÊý {npcID:{"ÊôÐÔÃû":{ÈËÊý:ϵÊý, ...}, ...}, ...}, ÓÅÏȼ¶´óÓÚµØÍ¼ÈËÊýϵÊý  | 
| NPCAttr_DynNPCLVMap, # ¶¯Ì¬µÈ¼¶µÄµØÍ¼IDÁÐ±í£¬Ä¬ÈÏÒÑˢгöÀ´µÄNPCµÈ¼¶²»»áÔÙ±ä¸ü£¬Ï´ÎË¢³öÀ´µÄ¹ÖÎïµÈ¼¶±ä¸ü [µØÍ¼ID, ...]  | 
| NPCAttr_DynPCCoefficientMap, # ¶¯Ì¬ÈËÊýϵÊýµÄµØÍ¼ID {µØÍ¼ID:ÊÇ·ñÂíÉÏË¢ÐÂÊôÐÔ, ...}  | 
| ) = range(6)  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##NPC³õʼ»¯->³öÉúµ÷Óà  | 
| # @param curNPC NPCʵÀý  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks NPC³õʼ»¯->³öÉúµ÷Óà  | 
| def InitNPC(curNPC):  | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%d.%s" % (curNPC.GetAIType(), "DoInit"))  | 
|     if callFunc == None:  | 
|         #NPCAI²»¿ÉʹÓà  | 
|         #ĬÈÏÉ趨³ðºÞ¶È×î´ó¸öÊý  | 
|         curNPC.GetNPCAngry().Init(ChConfig.Def_Default_NPC_Angry_Count)  | 
|     else:  | 
|         callFunc(curNPC)  | 
|           | 
|     #³õʼ»¯´¦Àí¼ä¸ô  | 
|     curNPC.SetIsNeedProcess(False)  | 
|     #³õʼ»¯Õâ¸öNPCµÄʱÖÓ  | 
|     curNPC.SetTickTypeCount(ChConfig.TYPE_NPC_Tick_Count)  | 
|     return  | 
|   | 
| def GetNPCLV(curNPC):  | 
|     # NPCµÈ¼¶  | 
|     if hasattr(curNPC, "GetCurLV"):  | 
|         return max(curNPC.GetCurLV(), curNPC.GetLV())  | 
|     return curNPC.GetLV()  | 
|   | 
| def GetRealmLV(curNPC): return curNPC.GetMAtkMin()      # NPC±íÖдË×ֶκ¬Òå¸Ä³É¾³½çµÈ¼¶  | 
| def SetRealmLV(curNPC, realmLV): return curNPC.SetMAtkMin(realmLV)      # NPC±íÖдË×ֶκ¬Òå¸Ä³É¾³½çµÈ¼¶  | 
| def GetIsLVSuppress(curNPC): return curNPC.GetWindDef() # ·ç·À´ú±íÊÇ·ñµÈ¼¶Ñ¹ÖÆ  | 
| def GetSuppressFightPower(curNPC): return curNPC.GetThunderDef() # À×·À´ú±íÑ¹ÖÆÕ½Á¦  | 
| def SetSuppressFightPower(curNPC, value): return curNPC.SetThunderDef(value)  | 
| def GetCommendFightPower(curNPC): return curNPC.GetFireDef() # »ð·À´ú±íÍÆ¼öÕ½Á¦  | 
| def GetDropOwnerType(curNPC): return curNPC.GetThunderAtk() # À×¹¥´ú±íµôÂä¹éÊôÀàÐÍ  | 
| def GetFaction(curNPC): return curNPC.GetCountry()  | 
| def GetSkillAtkRate(curNPC): return curNPC.GetPoisionAtk() # ¶¾¹¥´ú±íNPC¼¼ÄÜÉ˺¦¼Ó³ÉÍò·ÖÂÊ  | 
| def GetFinalHurt(curNPC): return curNPC.GetFireAtk() # »ð¹¥´ú±íNPC×îÖչ̶¨É˺¦¼Ó³É, ÆÕ¹¥Ò²ÓÐЧ¹û  | 
| def SetFinalHurt(curNPC, hurt): return curNPC.SetFireAtk(hurt) # »ð¹¥´ú±íNPC×îÖչ̶¨É˺¦¼Ó³É, ÆÕ¹¥Ò²ÓÐЧ¹û  | 
| def GetSkillEnhance(curNPC): return curNPC.GetWindAtk() # ·ç¹¥´ú±íNPC ¡¶ÆÕ¹¥¡· µÄ¼¼Äܸ½¼ÓÉ˺¦¹Ì¶¨Öµ  | 
| def GetNPCSeries(curNPC): return curNPC.GetPoisionDef() # ¶¾·À×ֶδú±íNPCϵ£¬°´¶þ½øÖÆÎ»Çø·Ö  | 
|   | 
| def DoNPCAttrStrengthen(curNPC, isReborn, isDyn=False):  | 
|     '''NPCÊôÐÔÔöÇ¿, NPCÊôÐԳɳ¤ÓÉÁ½¸öÒòËØ¾ö¶¨  | 
|     1.NPC³É³¤µÈ¼¶£¬³É³¤µÈ¼¶¾ö¶¨³É³¤ÊôÐÔ£¬Óë³É³¤±í½áºÏʹÓà  | 
|             ¿ÉÉèÖõØÍ¼NPCµÈ¼¶¶¯Ì¬³É³¤£¬µ«ÊÇÒѾˢгöÀ´µÄNPCµÈ¼¶²»±ä£¬¶¯Ì¬µÈ¼¶±ä¸üºóˢеÄNPCµÈ¼¶²Å»áʹÓÃ×îеȼ¶  | 
|               | 
|     2.Íæ¼ÒÈËÊýÒòËØ£¬¾ö¶¨NPCÊôÐԵĶîÍâ³É³¤ÏµÊý£¬¿Éµ¥¶ÀʹÓ㬻òÕߺÍ1Ò»ÆðʹÓà  | 
|             ¿ÉÉèÖÃÂíÉÏË¢ÐÂNPCÊôÐÔ  | 
|             ³ýѪÁ¿Í⣬ÆäËûÊôÐÔ»á¸ù¾Ý¶¯Ì¬ÒòËØÖ±½Ó±ä¸ü  | 
|             ÑªÁ¿»á¸ù¾ÝѪÁ¿°Ù·Ö±È¶¯Ì¬±ä¸üÖÁÏàÓ¦µÄ°Ù·Ö±È  | 
|     '''  | 
|     npcID = curNPC.GetNPCID()  | 
|     strengthenIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCStrengthen", npcID)  | 
|     if not strengthenIpyData:  | 
|         #GameWorld.DebugLog("¸ÃNPCÊôÐÔ²»³É³¤£¡npcID=%s" % npcID)  | 
|         return  | 
|       | 
|     strengthenLV = 0  | 
|     strengthenPlayerCnt = 0  | 
|       | 
|     gameFB = GameWorld.GetGameFB()  | 
|       | 
|     if strengthenIpyData.GetIsStrengthenByPlayerCount():  | 
|         if FamilyRobBoss.IsHorsePetRobBoss(npcID):  | 
|             strengthenPlayerCnt = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_HorsePetRobBossPlayerCount)  | 
|         else:  | 
|             strengthenPlayerCnt = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenPlayerCnt)  | 
|             if not strengthenPlayerCnt:  | 
|                 GameWorld.ErrLog("NPCÅäÖÃÁ˰´Íæ¼ÒÈËÊý³É³¤ÀàÐÍ£¬µ«ÊÇÎÞ·¨»ñÈ¡µ½¶ÔÓ¦µÄÍæ¼ÒÈËÊý£¡npcID=%s" % (npcID))  | 
|                 return  | 
|               | 
|     lvStrengthenType = strengthenIpyData.GetLVStrengthenType()  | 
|     # ¸ù¾ÝÊÀ½çµÈ¼¶  | 
|     if lvStrengthenType == 3:  | 
|         strengthenLV = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)  | 
|     # ¸ù¾Ý×î´óµÈ¼¶  | 
|     elif lvStrengthenType == 2:  | 
|         strengthenLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMaxLV)  | 
|     # ¸ù¾Ýƽ¾ùµÈ¼¶  | 
|     elif lvStrengthenType == 1:  | 
|         strengthenLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenAverageLV)  | 
|     # ¸ù¾Ý°´³É³¤µÈ¼¶µÄÉÏÏÂÏÞËæ»ú  | 
|     elif lvStrengthenType == 4:  | 
|         randMinLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMinLV)  | 
|         randMaxLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMaxLV)  | 
|         strengthenLV = random.randint(randMinLV, randMaxLV)  | 
|           | 
|     # Ä¾×®¹Ö×î´ó¡¢Æ½¾ù³É³¤µÈ¼¶´¦Àí£¬Ö±½ÓÈ¡¹éÊôÍæ¼ÒµÈ¼¶  | 
|     if lvStrengthenType in [1, 2] and curNPC.GetType() in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]:  | 
|         owner = None  | 
|         summonPlayerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_PriWoodPilePlayerID)  | 
|         if summonPlayerID:  | 
|             owner = GameWorld.GetObj(summonPlayerID, IPY_GameWorld.gotPlayer)  | 
|         if owner:  | 
|             strengthenLV = owner.GetLV()  | 
|               | 
|     if strengthenIpyData.GetCmpNPCBaseLV():  | 
|         strengthenLV = max(strengthenLV, curNPC.GetLV())  | 
|       | 
|     if lvStrengthenType in [1, 2] and not strengthenLV:  | 
|         GameWorld.ErrLog("NPCÅäÖÃÁ˳ɳ¤µÈ¼¶ÀàÐÍ£¬µ«ÊÇÎÞ·¨»ñÈ¡µ½¶ÔÓ¦µÄ³É³¤µÈ¼¶Öµ£¡npcID=%s,lvStrengthenType=%s" % (npcID, lvStrengthenType))  | 
|         return  | 
|       | 
|     # ¸±±¾ÌØÊâÖ¸¶¨  | 
|     npcFBAttrDict = FBLogic.GetFBNPCStrengthenAttr(curNPC, isReborn)  | 
|     if "LV" in npcFBAttrDict:  | 
|         strengthenLV = npcFBAttrDict["LV"]  | 
|           | 
|     attrDict = GetNPCStrengthenAttrDict(npcID, strengthenLV, strengthenPlayerCnt, strengthenIpyData)  | 
|     attrDict.update(npcFBAttrDict) # Èç¹û¸±±¾ÓÐÖ¸¶¨ÊôÐÔ£¬ÔòÒÔ¸±±¾ÎªÖ÷  | 
|     if not attrDict:  | 
|         return  | 
|       | 
|     # ³É³¤µÈ¼¶Ö»ÔÚÖØÉúµÄʱºòÉèÖÃÒ»´Î  | 
|     if isReborn and curNPC.GetCurLV() != strengthenLV:  | 
|         curNPC.SetCurLV(strengthenLV, False) # ÖØÉúµÄ²»Í¨ÖªµÈ¼¶±ä¸ü£¬ÊôÐԳɳ¤Ë¢ÐºóÓÉNPC³öÏÖ°ü֪ͨ  | 
|           | 
|     befMaxHP = GameObj.GetMaxHP(curNPC)  | 
|     befHP = GameObj.GetHP(curNPC)  | 
|     #GameWorld.DebugLog("NPCÊôÐԳɳ¤Ë¢Ð£¬isReborn=%s,npcID=%s,LV=%s,curLV=%s,befMaxHP=%s,befHP=%s,attrDict=%s"   | 
|     #                   % (isReborn, npcID, curNPC.GetLV(), curNPC.GetCurLV(), befMaxHP, befHP, attrDict))  | 
|     for attrKey, strengthenValue in attrDict.items():  | 
|         if not hasattr(curNPC, "Set%s" % attrKey):  | 
|             if attrKey == "FightPower":  | 
|                 SetSuppressFightPower(curNPC, strengthenValue)  | 
|             continue  | 
|           | 
|         if attrKey == "MaxHP":  | 
|             GameObj.SetMaxHP(curNPC, strengthenValue)  | 
|         else:  | 
|             strengthenValue = min(strengthenValue, ChConfig.Def_UpperLimit_DWord)  | 
|             getattr(curNPC, "Set%s" % attrKey)(strengthenValue)  | 
|         #GameWorld.DebugLog("    %s=%s" % (attrKey, strengthenValue))  | 
|           | 
|     aftMaxHP = GameObj.GetMaxHP(curNPC)  | 
|     if befMaxHP != aftMaxHP:  | 
|         if isReborn:  | 
|             GameObj.SetHP(curNPC, aftMaxHP)  | 
|         elif isDyn:  | 
|             # ¶¯Ì¬Ë¢ÐÂÊôÐԵģ¬ÑªÁ¿°´°Ù·Ö±È¼Ì³Ð  | 
|             aftHP = int(aftMaxHP * befHP / befMaxHP)  | 
|             GameObj.SetHP(curNPC, aftHP)  | 
|             curNPC.Notify_HPEx()  | 
|             curNPC.Notify_MaxHPEx()  | 
|             #GameWorld.DebugLog("    aftHP=%s,aftMaxHP=%s" % (aftHP, aftMaxHP))  | 
|       | 
|     # »úÆ÷È˸´»î³õʼ»¯¸ø¼¼ÄÜ  | 
|     if isReborn and curNPC.GetType() == ChConfig.ntRobot:  | 
|         __OnFBRobotReborn(curNPC, strengthenLV)  | 
|           | 
|     return  | 
|   | 
| def __OnFBRobotReborn(curNPC, npcLV):  | 
|     tick = GameWorld.GetGameWorld().GetTick()  | 
|     lineID = GameWorld.GetGameWorld().GetLineID()  | 
|     objID = curNPC.GetID()  | 
|     jobSkillDict = IpyGameDataPY.GetFuncEvalCfg("FBRobotCfg", 1)  | 
|     robotJob = random.choice(jobSkillDict.keys())  | 
|     lineRobotJobDict = PyGameData.g_fbRobotJobDict.get(lineID, {})  | 
|     lineRobotJobDict[objID] = robotJob  | 
|     PyGameData.g_fbRobotJobDict[lineID] = lineRobotJobDict  | 
|     skillInfoDict = jobSkillDict[robotJob]  | 
|     skillIDList = []  | 
|     for skillInfo, needLV in skillInfoDict.items():  | 
|         if npcLV < needLV:  | 
|             continue  | 
|         if isinstance(skillInfo, int):  | 
|             skillIDList.append(skillInfo)  | 
|         else:  | 
|             skillIDList += list(skillInfo)  | 
|     GameWorld.DebugLog("¸ø»úÆ÷ÈËNPC¼¼ÄÜ: objID=%s,robotJob=%s,npcLV=%s, %s" % (objID, robotJob, npcLV, skillIDList))  | 
|     skillManager = curNPC.GetSkillManager()  | 
|     for skillID in skillIDList:  | 
|         skillManager.LearnSkillByID(skillID)  | 
|     playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for index in xrange(playerManager.GetPlayerCount()):  | 
|         curPlayer = playerManager.GetPlayerByIndex(index)  | 
|         if not curPlayer:  | 
|             continue  | 
|         FBLogic.DoFBHelp(curPlayer, tick)  | 
|     return  | 
|   | 
|   | 
| def __DoGiveVSPlayerNPCSkill(curNPC, job, npcLV):  | 
|     skillManager = curNPC.GetSkillManager()  | 
|     jobSkillDict = IpyGameDataPY.GetFuncEvalCfg("XMZZRobotSkill", 1)  | 
|     if job not in jobSkillDict:  | 
|         return  | 
|     skillInfoDict = jobSkillDict[job]  | 
|     #{1:{(100, 101, 102, 103):1, 50000:100, 50100:200, 50400:300}, 2:{(200, 201, 202, 203):1, 55000:100, 55100:200, 55200:300}}  | 
|     skillIDList = []  | 
|     for skillInfo, needLV in skillInfoDict.items():  | 
|         if npcLV < needLV:  | 
|             continue  | 
|         if isinstance(skillInfo, int):  | 
|             skillIDList.append(skillInfo)  | 
|         else:  | 
|             skillIDList += list(skillInfo)  | 
|     GameWorld.DebugLog("¸øNPC¼¼ÄÜ: job=%s,npcLV=%s, %s" % (job, npcLV, skillIDList))  | 
|     for skillID in skillIDList:  | 
|         skillManager.LearnSkillByID(skillID)  | 
|     return  | 
|   | 
| def GetNPCStrengthenAttrDict(npcID, strengthenLV=0, strengthenPlayerCnt=0, strengthenIpyData=None):  | 
|     if not strengthenLV and not strengthenPlayerCnt:  | 
|         return {}  | 
|     npcData = GameWorld.GetGameData().FindNPCDataByID(npcID)  | 
|     if not npcData:  | 
|         return {}  | 
|       | 
|     attrStrengthenInfo = ReadChConfig.GetEvalChConfig("NPCAttrStrengthen")  | 
|     if not attrStrengthenInfo:  | 
|         return {}  | 
|       | 
|     attrDict = {}  | 
|     paramDict = attrStrengthenInfo[NPCAttr_ParamDict] # ¹ý³Ì²ÎÊý¹«Ê½×Öµä  | 
|     attrStrengthenDict = attrStrengthenInfo[NPCAttr_AttrStrengthenList] # ÊôÐԳɳ¤¹«Ê½×Öµä  | 
|     playerCntCoefficient = attrStrengthenInfo[NPCAttr_PlayerCntCoefficient] # ÈËÊýϵÊý  | 
|     npcIDPlayerCntCoefficient = attrStrengthenInfo[NPCAttr_NPCPlayerCntCoefficient] # ÌØÊâNPCÈËÊýϵÊý  | 
|     baseMaxHP = npcData.GetHPEx() * ShareDefine.Def_PerPointValue + npcData.GetHP()  | 
|       | 
|     if strengthenLV:  | 
|         if not strengthenIpyData:  | 
|             strengthenIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCStrengthen", npcID)  | 
|         if not strengthenIpyData:  | 
|             return {}  | 
|           | 
|         playerCurLVIpyData = PlayerControl.GetPlayerLVIpyData(strengthenLV) # È¡ÔöÇ¿¹ÖÎïµÈ¼¶¶ÔÓ¦´ËµÈ¼¶µÄÍæ¼Ò²Î¿¼ÊôÐÔÖµ  | 
|         if not playerCurLVIpyData:  | 
|             return {}  | 
|           | 
|         # NPC±í¿ÉÓòÎÊý  | 
|         SkillAtkRate = GetSkillAtkRate(npcData) # ¼¼ÄÜÉ˺¦  | 
|         FinalHurt = GetFinalHurt(npcData)  | 
|           | 
|         # ²Î¿¼Íæ¼ÒÊôÐÔ²ÎÊý  | 
|         ReMaxHP = playerCurLVIpyData.GetReMaxHP() # ×î´óÉúÃüÖµ  | 
|         ReAtk = playerCurLVIpyData.GetReAtk() # ¹¥»÷£¨×îС¡¢×î´ó¹¥»÷£©  | 
|         ReDef = playerCurLVIpyData.GetReDef() # ·ÀÓù  | 
|         ReHit = playerCurLVIpyData.GetReHit() # ÃüÖÐ  | 
|         ReMiss = playerCurLVIpyData.GetReMiss() # ÉÁ±Ü  | 
|         ReAtkSpeed = playerCurLVIpyData.GetReAtkSpeed() # ¹¥»÷ËÙ¶È  | 
|         ReSkillAtkRate = playerCurLVIpyData.GetReSkillAtkRate() # ¼¼ÄÜÉ˺¦±ÈÀý  | 
|         ReDamagePer = playerCurLVIpyData.GetReDamagePer() # Ôö¼ÓÉ˺¦  | 
|         ReDamReduce = playerCurLVIpyData.GetReDamReduce() # ¼õÉÙÉ˺¦  | 
|         ReIgnoreDefRate = playerCurLVIpyData.GetReIgnoreDefRate() # ÎÞÊÓ·ÀÓù±ÈÀý  | 
|         ReLuckyHitRate = playerCurLVIpyData.GetReLuckyHitRate() # »áÐÄÒ»»÷ÂÊ  | 
|         ReLuckyHit = playerCurLVIpyData.GetReLuckyHit() # »áÐÄÒ»»÷É˺¦  | 
|         ReBleedDamage = playerCurLVIpyData.GetReBleedDamage() # Á÷ѪÉ˺¦Ôö¼Ó  | 
|         ReIceAtk = playerCurLVIpyData.GetReIceAtk() # ÕæÊµÉ˺¦  | 
|         ReIceDef = playerCurLVIpyData.GetReIceDef() # ÕæÊµµÖÓù  | 
|         RePetAtk = playerCurLVIpyData.GetRePetAtk() # Áé³è¹¥»÷  | 
|         RePetSkillAtkRate = playerCurLVIpyData.GetRePetSkillAtkRate() # Áé³è¼¼ÄÜ  | 
|         RePetDamPer = playerCurLVIpyData.GetRePetDamPer() # Áé³èÉ˺¦Ôö¼Ó  | 
|         ReFinalHurt = playerCurLVIpyData.GetReFinalHurt() # ¹Ì¶¨É˺¦Ôö¼Ó  | 
|         ReFinalHurtReduce = playerCurLVIpyData.GetReFinalHurtReduce() # ¹Ì¶¨É˺¦¼õÉÙ  | 
|         RePotionReply = playerCurLVIpyData.GetRePotionReply() # ÑªÆ¿»Ö¸´Á¿  | 
|         RePotionCD = playerCurLVIpyData.GetRePotionCD() # ÑªÆ¿CD  | 
|         ReFightPower = playerCurLVIpyData.GetReFightPower() # Õ½¶·Á¦  | 
|           | 
|         # Ôö¼ÓNPCÊôÐÔ²ÎÊý  | 
|         HitTime = strengthenIpyData.GetHitTime() # ¹ÖÎïÊÜ»÷´ÎÊý  | 
|         DefCoefficient = strengthenIpyData.GetDefCoefficient() # ÈËÎï·ÀÓùϵÊý  | 
|         AtkCoefficient = strengthenIpyData.GetAtkCoefficient() # ÈËÎï¹¥»÷ϵÊý  | 
|         AdjustCoefficient = strengthenIpyData.GetAdjustCoefficient() # µ÷ÕûϵÊý±ÈÀý  | 
|         AtkInterval = strengthenIpyData.GetAtkInterval() # ¹ÖÎï¹¥»÷¼ä¸ô  | 
|         HitRate = strengthenIpyData.GetHitRate() # ¶ÔÈËÎïµÄÃüÖÐÂÊ  | 
|         MissRate = strengthenIpyData.GetMissRate() # ¶ÔÈËÎïµÄÉÁ±ÜÂÊ  | 
|         MonterNum = strengthenIpyData.GetMonterNum() # ¹ÖÎïÊý  | 
|         IceAtkCoefficient = strengthenIpyData.GetIceAtkCoefficient() # ÔªËع¥»÷±ÈÀý  | 
|         IceDefCoefficient = strengthenIpyData.GetIceDefCoefficient() # ÔªËØ¿¹ÐÔ±ÈÀý  | 
|         MaxEnduranceTime = strengthenIpyData.GetMaxEnduranceTime() # Íæ¼Ò×î´ó³ÐÊÜÉ˺¦Ê±¼ä  | 
|         FightPowerCoefficient = strengthenIpyData.GetFightPowerCoefficient() # Ñ¹ÖÆÕ½¶·Á¦ÏµÊý  | 
|           | 
|         # ¹ý³Ì²ÎÊý  | 
|         AtkReplyCoefficient = eval(FormulaControl.GetCompileFormula("NPCParam_AtkReplyCoefficient",  | 
|                                                                     paramDict["AtkReplyCoefficient"])) # ¹ÖÎï¹¥»÷»Ø¸´µ÷ÕûÖµ  | 
|         MonterHurt = eval(FormulaControl.GetCompileFormula("NPCParam_MonterHurt", paramDict["MonterHurt"])) # ¹ÖÎï¹Ì¶¨É˺¦  | 
|         LostHPPerSecond = eval(FormulaControl.GetCompileFormula("NPCParam_LostHPPerSecond", paramDict["LostHPPerSecond"])) # Íæ¼ÒÿÃëµôѪÁ¿  | 
|         LVStrengthenMark = strengthenIpyData.GetLVStrengthenMark()  | 
|         attrStrengthenList = attrStrengthenDict.get(LVStrengthenMark, [])  | 
|         for attrKey, strengthenFormat in attrStrengthenList:  | 
|             strengthenValue = int(eval(FormulaControl.GetCompileFormula("NPCStrengthen_%s_%s" % (attrKey,LVStrengthenMark), strengthenFormat)))  | 
|             #GameWorld.DebugLog("    %s=%s" % (attrKey, strengthenValue))  | 
|             locals()[attrKey] = strengthenValue # ´´½¨¸ÃÊôÐÔ¾Ö²¿±äÁ¿×÷Ϊ²ÎÊýÌṩ¸øºóÃæÊôÐÔ¼ÆËãʱÓà  | 
|             attrDict[attrKey] = strengthenValue  | 
|               | 
|         # µ±Õ½Á¦ÏµÊýΪ0ʱ£¬NPCÕ½Á¦Ä¬ÈÏΪNPC±íÑ¹ÖÆÕ½Á¦  | 
|         if FightPowerCoefficient:  | 
|             attrDict["FightPower"] = int(ReFightPower * FightPowerCoefficient / 10000.0)  | 
|               | 
|     if strengthenPlayerCnt:  | 
|         mapID = GameWorld.GetMap().GetMapID()  | 
|         dataMapID = FBCommon.GetRecordMapID(mapID)  | 
|         formulaKey = "MapCoefficient_%s" % mapID  | 
|         playerCntAttrCoefficient = playerCntCoefficient.get(mapID, {})  | 
|         if not playerCntAttrCoefficient and dataMapID in playerCntCoefficient:  | 
|             playerCntAttrCoefficient = playerCntCoefficient[dataMapID]  | 
|             formulaKey = "MapCoefficient_%s" % dataMapID  | 
|         if npcID in npcIDPlayerCntCoefficient:  | 
|             playerCntAttrCoefficient = npcIDPlayerCntCoefficient[npcID]  | 
|             formulaKey = "NPCCoefficient_%s" % npcID  | 
|         for attrKey, coefficientDict in playerCntAttrCoefficient.items():  | 
|             if attrKey in attrDict:  | 
|                 attrValue = attrDict[attrKey]  | 
|             elif attrKey == "MaxHP":  | 
|                 attrValue = baseMaxHP  | 
|             else:  | 
|                 attrFuncName = "Get%s" % attrKey  | 
|                 if not hasattr(npcData, attrFuncName):  | 
|                     continue  | 
|                 attrValue = getattr(npcData, attrFuncName)()  | 
|             # °´×ÖµäÅäÖà  | 
|             if isinstance(coefficientDict, dict):  | 
|                 coefficient = GameWorld.GetDictValueByRangeKey(coefficientDict, strengthenPlayerCnt, 1)  | 
|             # °´¹«Ê½ÅäÖà  | 
|             elif isinstance(coefficientDict, str):  | 
|                 formulaKey = "%s_%s" % (formulaKey, attrKey)  | 
|                 coefficient = eval(FormulaControl.GetCompileFormula(formulaKey, coefficientDict))  | 
|             else:  | 
|                 coefficient = 1  | 
|             attrDict[attrKey] = int(attrValue * coefficient)  | 
|               | 
|     #GameWorld.DebugLog("¼ÆËãNPCÊôÐԳɳ¤: npcID=%s,strengthenLV=%s,strengthenPlayerCnt=%s,baseMaxHP=%s,attrDict=%s"   | 
|     #                   % (npcID, strengthenLV, strengthenPlayerCnt, baseMaxHP, attrDict))  | 
|     return attrDict  | 
|   | 
| def GiveKillNPCDropPrize(curPlayer, mapID, npcCountDict, exp_rate=None, mailTypeKey=None, isMail=False,   | 
|                          extraItemList=[], prizeMultiple=1, dropItemMapInfo=[], curGrade=0, isVirtualDrop=False):  | 
|     '''¸øÍæ¼Ò»÷ɱNPCµôÂä½±Àø  | 
|     @param mapID: »÷ɱµÄNPCËùÔÚµØÍ¼ID£¬×¢Òâ´ÎµØÍ¼²¢²»Ò»¶¨ÊÇÍæ¼Òµ±Ç°µØÍ¼  | 
|     @param npcCountDict: Ö´Ðе¥´ÎʱËù»÷ɱµÄnpcÊýÁ¿×Öµä {npcID:count, ...}  | 
|     @param exp_rate: »÷ɱ¹ÖÎïÏíÊܵľÑé±ÈÀý  | 
|     @param mailTypeKey: »ñÈ¡ÎïÆ·±³°ü¿Õ¼ä²»×ãʱ·¢Ë͵ÄÓʼþÄ£°åkey  | 
|     @param isMail: ÊÇ·ñÇ¿ÖÆ·¢ËÍÓʼþ£¬ÈôÊÇÔò²»¿¼ÂDZ³°ü¿Õ¼ä£¬·ñµÄ»°Ö»ÔÚ±³°ü¿Õ¼ä²»×ãʱ²Å·¢ËÍÓʼþ  | 
|     @param extraItemList: ¹Ì¶¨¸½¼ÓÎïÆ·ÁÐ±í£¬Èç¹ûÐèÖ´Ðжà´Î£¬Ôò´Ë¹Ì¶¨²ú³öÁбíÐèÔÚÍâ²ã´¦ÀíºÃ£¬Äڲ㲻×ö¶à´ÎÖ´Ðд¦Àí¡£[[itemID, itemCount, isAuctionItem], ...]  | 
|     @param prizeMultiple: ½±Àø±¶Öµ, ¶ÔËùÓн±ÀøÓÐЧ£¬µÈÓÚ»÷ɱ¶à´ÎNPC£¬¶à±¶¸½¼ÓÎïÆ·  | 
|     @param dropItemMapInfo: µôÂ䵨°åÐÅÏ¢ [dropPosX, dropPosY, ÊÇ·ñ½ö×Ô¼º¿É¼û, ¶ÑµþÎïÆ·ÊÇ·ñÉ¢¿ª]  | 
|     @param curGrade: ÆÀ¼¶  | 
|     @param isVirtualDrop: ÊÇ·ñ¸øÎïÆ·ÐéÄâµôÂä±íÏÖ  | 
|     '''  | 
|     if not exp_rate:  | 
|         exp_rate = PlayerControl.GetPlayerExpRate(curPlayer)  | 
|           | 
|     npcID = 0  | 
|     totalExp = 0  | 
|     totalMoney = 0  | 
|     itemCountDict = {}  | 
|     auctionItemIDList = []  | 
|       | 
|     if prizeMultiple > 1:  | 
|         hadDropItemKeyList, hadDropItemPlaceList = [], [] # ÒѾµôÂä¹ýµÄÎïÆ·¼¯ºÏkeyÁÐ±í£¬ ÒѾµôÂä¹ýµÄ×°±¸²¿Î»ÁÐ±í  | 
|         mPrizeItemIDList = IpyGameDataPY.GetFuncEvalCfg("SealDemonDoubleDrop", 1) # ÔÊÐí¶à±¶½±ÀøµÄÎïÆ·IDÁÐ±í  | 
|         mPrizePlaceList = IpyGameDataPY.GetFuncEvalCfg("SealDemonDoubleDrop", 2) # ÔÊÐí¶à±¶½±ÀøµÄ×°±¸²¿Î»  | 
|         mPrizeItemKeyList = IpyGameDataPY.GetFuncEvalCfg("SealDemonDoubleDrop", 3) # ÔÊÐí¶à±¶½±ÀøµÄÎïÆ·ID¼¯ºÏ  | 
|           | 
|         itemKeyDict = IpyGameDataPY.GetFuncEvalCfg("JobItemDropSets") # {ÎïÆ·ID¼¯ºÏkey:[ְҵ˳ÐòÎïÆ·IDÁбí], ...}  | 
|         itemIDKeyDict = {}  | 
|         for itemKey, itemIDList in itemKeyDict.items():  | 
|             for itemID in itemIDList:  | 
|                 itemIDKeyDict[itemID] = itemKey  | 
|       | 
|     for npcID, count in npcCountDict.items():  | 
|         baseExp = GetNPCExp(curPlayer, npcID)  | 
|         addExp = int(baseExp * exp_rate / float(ChConfig.Def_MaxRateValue)) # »ù´¡¼Ó³É  | 
|         totalCount = count * prizeMultiple  | 
|         totalExp += (addExp * totalCount)  | 
|           | 
|         # µôÂäÓиÅÂÊÒòËØ£¬Ðè¶à´ÎÖ´ÐÐ  | 
|         for dCount in xrange(1, totalCount + 1):  | 
|             isKillCountDrop = dCount == 1 # Í¬Ò»Ö»NPCÒ»´Î´¦ÀíÖжà´Î»÷ɱµÄÇé¿ö£¬Ö»ËãÒ»´Î¸½¼Ó×°±¸´¦Àí  | 
|             dropInfo = GetNPCDropInfo(curPlayer, mapID, npcID, isKillCountDrop=isKillCountDrop, curGrade=curGrade)  | 
|             if not dropInfo:  | 
|                 continue  | 
|             dropIDList, auctionIDList, dropMoneyCnt, moneyValue = dropInfo  | 
|             totalMoney += (dropMoneyCnt * moneyValue)  | 
|               | 
|             for itemID in dropIDList:  | 
|                 if prizeMultiple > 1:  | 
|                     itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)  | 
|                     if not itemData:  | 
|                         continue  | 
|                     itemPlace = itemData.GetEquipPlace()  | 
|                     itemKey = itemIDKeyDict.get(itemID)  | 
|                       | 
|                     # ³¬¹ýÖ¸¶¨×î´óÖ»Êýʱ£¬´ú±í¶à±¶½±Àø£¬¶à±¶½±ÀøµÄÎïÆ·Ö»ÔÊÐí¸øÖ¸¶¨¹æÔòÄÚµÄÎïÆ·£¬Ö»¶ÔÒѾµô¹ýµÄÎïÆ·ÓÐÏÞÖÆ  | 
|                     if dCount > count:  | 
|                         if ItemCommon.GetIsEquip(itemData):  | 
|                             if itemPlace in hadDropItemPlaceList and itemPlace not in mPrizePlaceList:  | 
|                                 GameWorld.DebugLog("    ¶à±¶½±Àø²»ÄܸøµÄÎïÆ·²¿Î»: itemID=%s,itemPlace=%s" % (itemID, itemPlace))  | 
|                                 continue  | 
|                         elif itemKey != None:  | 
|                             if itemKey in hadDropItemKeyList and itemKey not in mPrizeItemKeyList:  | 
|                                 GameWorld.DebugLog("    ¶à±¶½±Àø²»ÄܸøµÄÎïÆ·ID¼¯ºÏ: itemID=%s,itemKey=%s" % (itemID, itemKey))  | 
|                                 continue  | 
|                         else:  | 
|                             if itemID in itemCountDict and itemID not in mPrizeItemIDList:  | 
|                                 GameWorld.DebugLog("    ¶à±¶½±Àø²»ÄܸøµÄÎïÆ·ID: itemID=%s" % (itemID))  | 
|                                 continue  | 
|                               | 
|                     if itemPlace and itemPlace not in hadDropItemPlaceList:  | 
|                         hadDropItemPlaceList.append(itemPlace)  | 
|                     if itemKey != None and itemKey not in hadDropItemKeyList:  | 
|                         hadDropItemKeyList.append(itemKey)  | 
|                           | 
|                 itemCountDict[itemID] = itemCountDict.get(itemID, 0) + 1  | 
|                 if itemID in auctionIDList and itemID not in auctionItemIDList:  | 
|                     auctionItemIDList.append(itemID)  | 
|                   | 
|     # ¹Ì¶¨¸½¼ÓÎïÆ·  | 
|     for itemID, itemCount, isAuctionItem in extraItemList:  | 
|         itemCountDict[itemID] = itemCountDict.get(itemID, 0) + itemCount * prizeMultiple  | 
|         if isAuctionItem and itemID not in auctionItemIDList:  | 
|             auctionItemIDList.append(itemID)  | 
|           | 
|     needSpace = 0  | 
|     prizeItemList = []  | 
|     jsonItemList = []  | 
|     for itemID, itemCount in itemCountDict.items():  | 
|         itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)  | 
|         if not itemData:  | 
|             continue  | 
|           | 
|         isAuctionItem = itemID in auctionItemIDList  | 
|           | 
|         if ItemCommon.GetIsEquip(itemData):  | 
|             for _ in xrange(itemCount):  | 
|                 curItem = ItemControler.GetOutPutItemObj(itemID, 1, isAuctionItem, curPlayer=curPlayer)  | 
|                 if curItem:  | 
|                     needSpace += 1  | 
|                     prizeItemList.append(curItem)  | 
|                     jsonItemList.append(ItemCommon.GetJsonItem(curItem))  | 
|         else:  | 
|             needSpace += ItemControler.GetItemNeedPackCount(IPY_GameWorld.rptItem, itemData, itemCount, isAuctionItem)  | 
|             prizeItemList.append([itemID, itemCount, isAuctionItem])  | 
|             jsonItemList.append(ItemCommon.GetJsonItem([itemID, itemCount, isAuctionItem]))  | 
|         #³É¾Í  | 
|         if not dropItemMapInfo:  | 
|             PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_PickUpItem, itemCount, [itemID])  | 
|           | 
|     ## Ö±½ÓµôµØ°åÉÏ  | 
|     if dropItemMapInfo:  | 
|         dropPosX, dropPosY = dropItemMapInfo[:2]  | 
|         isOnlySelfSee = dropItemMapInfo[2] if len(dropItemMapInfo) > 2 else False # ÊÇ·ñ½ö×Ô¼º¿É¼û  | 
|         isDropDisperse = dropItemMapInfo[3] if len(dropItemMapInfo) > 3 else False # ¶ÑµþµÄÎïÆ·ÊÇ·ñÉ¢¿ªµôÂä  | 
|         ## ÐéÄâµôÂä±íÏÖ      | 
|         if isVirtualDrop:  | 
|             DoGiveItemByVirtualDrop(curPlayer, prizeItemList, npcID, dropPosX, dropPosY, isDropDisperse, mailTypeKey)  | 
|         else:  | 
|             DoMapDropPrizeItem(curPlayer, prizeItemList, npcID, dropPosX, dropPosY, isDropDisperse, isOnlySelfSee)  | 
|               | 
|     ## ·¢Óʼþ »ò ±³°ü¿Õ¼ä²»×ã  | 
|     elif isMail or needSpace > ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, needSpace):  | 
|         mailItemList = []  | 
|         for prizeItem in prizeItemList:  | 
|             if isinstance(prizeItem, list):  | 
|                 mailItemList.append(prizeItem)  | 
|             else:  | 
|                 mailItemList.append(ItemCommon.GetMailItemDict(prizeItem))  | 
|                 prizeItem.Clear() # ·¢ÓʼþÒѾ´´½¨µÄÎïÆ·ÊµÀýÒªÇå¿Õ, ²»È»»áµ¼ÖÂÄÚ´æÐ¹Â¶  | 
|         #if totalExp:  | 
|         #    expItemID = 0  | 
|         #    mailItemList.append([expItemID, totalExp, 1])  | 
|         PlayerControl.SendMailByKey(mailTypeKey, [curPlayer.GetPlayerID()], mailItemList, silver=totalMoney)  | 
|           | 
|     ## Ö±½Ó·ÅÈë±³°ü  | 
|     else:  | 
|         event = [ChConfig.ItemGive_NPCDrop, False, {"NPCID":npcID}]  | 
|         for prizeItem in prizeItemList:  | 
|             if isinstance(prizeItem, list):  | 
|                 itemID, itemCount, isAuctionItem = prizeItem  | 
|                 ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem],   | 
|                                              event=event)  | 
|             else:  | 
|                 ItemControler.DoLogic_PutItemInPack(curPlayer, prizeItem, event=event)  | 
|                   | 
|         if totalExp:  | 
|             PlayerControl.PlayerControl(curPlayer).AddExp(totalExp)  | 
|               | 
|         if totalMoney:  | 
|             PlayerControl.GiveMoney(curPlayer, IPY_GameWorld.TYPE_Price_Silver_Money, totalMoney)  | 
|               | 
|     #GameWorld.DebugLog("¸øÍæ¼Ò»÷ɱNPCµôÂä½±Àø:  mapID=%s,npcCountDict=%s,exp_rate=%s,mailTypeKey=%s,isMail=%s,extraItemList=%s"   | 
|     #                   % (mapID, npcCountDict, exp_rate, mailTypeKey, isMail, extraItemList))  | 
|     #GameWorld.DebugLog("    totalExp=%s,totalMoney=%s,needSpace=%s,jsonItemList=%s" % (totalExp, totalMoney, needSpace, jsonItemList))  | 
|     return jsonItemList, totalExp, totalMoney  | 
|   | 
| def DoMapDropPrizeItem(curPlayer, prizeItemList, npcID, dropPosX, dropPosY, isDropDisperse=True, isOnlySelfSee=True):  | 
|     ## ½±ÀøÎïÆ·ÕæÊµµôÂäµØÍ¼£¬ÏȲ𿪷ÖÉ¢ÔÙµôÂä  | 
|       | 
|     if isDropDisperse:  | 
|         dropItemList = []  | 
|         for itemInfo in prizeItemList:  | 
|             if isinstance(itemInfo, list):  | 
|                 itemID, itemCount, isAuctionItem = itemInfo  | 
|                 for _ in xrange(itemCount):  | 
|                     dropItemList.append([itemID, 1, isAuctionItem])  | 
|             else:  | 
|                 dropItemList.append(itemInfo)  | 
|     else:  | 
|         dropItemList = prizeItemList  | 
|     index = 0  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     gameMap = GameWorld.GetMap()  | 
|     for posX, posY in ChConfig.Def_DropItemAreaMatrix:  | 
|         resultX = dropPosX + posX  | 
|         resultY = dropPosY + posY  | 
|           | 
|         if not gameMap.CanMove(resultX, resultY):  | 
|             #Íæ¼Ò²»¿ÉÒÆ¶¯Õâ¸öµã  | 
|             continue  | 
|           | 
|         if index > len(dropItemList) - 1:  | 
|             break  | 
|           | 
|         curItem = dropItemList[index]  | 
|         index += 1  | 
|         if isinstance(curItem, list):  | 
|             itemID, itemCount, isAuctionItem = curItem  | 
|             curItem = ItemControler.GetOutPutItemObj(itemID, itemCount, isAuctionItem, curPlayer=curPlayer)  | 
|               | 
|         if not curItem:  | 
|             continue  | 
|           | 
|         ChItem.AddMapDropItem(resultX, resultY, curItem, ownerInfo=[ChConfig.Def_NPCHurtTypePlayer, playerID],   | 
|                               dropNPCID=npcID, isOnlySelfSee=isOnlySelfSee)  | 
|     return  | 
|   | 
| def DoGiveItemByVirtualDrop(curPlayer, giveItemList, npcID, dropPosX=0, dropPosY=0, isDropDisperse=True, mailTypeKey="ItemNoPickUp"):  | 
|     ## ¸øÎïÆ·²¢ÇÒ×ö¼ÙµôÂä±íÏÖ£¬Ö±½ÓÏȶѵþ¸øÎïÆ·£¬ÔÙ²ð¿ª×öÐé¼ÙµôÂä±íÏÖ  | 
|       | 
|     mapID = PlayerControl.GetCustomMapID(curPlayer)  | 
|     lineID = PlayerControl.GetCustomLineID(curPlayer)  | 
|     if not mapID:  | 
|         mapID = GameWorld.GetGameWorld().GetMapID()  | 
|           | 
|     playerID = curPlayer.GetPlayerID()  | 
|     giveItemObjList = []  | 
|     virtualItemDropList = []  | 
|     itemControl = ItemControler.PlayerItemControler(curPlayer)  | 
|     for itemInfo in giveItemList:  | 
|         if isinstance(itemInfo, list):  | 
|             itemID, itemCount, isAuctionItem = itemInfo  | 
|             curItem = ItemControler.GetOutPutItemObj(itemID, itemCount, isAuctionItem, curPlayer=curPlayer)  | 
|             if not curItem:  | 
|                 continue  | 
|         else:  | 
|             curItem = itemInfo  | 
|             itemID = curItem.GetItemTypeID()  | 
|             itemCount = curItem.GetCount()  | 
|             isAuctionItem = ItemControler.GetIsAuctionItem(curItem)  | 
|         dropItemDataStr = ChItem.GetMapDropItemDataStr(curItem)  | 
|         giveItemObjList.append(curItem)  | 
|               | 
|         # É¢¿ªµôÂä  | 
|         if isDropDisperse:  | 
|             for _ in xrange(itemCount):  | 
|                 virtualItemDropList.append([itemID, dropItemDataStr])  | 
|         else:  | 
|             virtualItemDropList.append([itemID, dropItemDataStr])  | 
|           | 
|     # ÏÈ֪ͨµôÂ䣬ÔÙ¸øÎïÆ·£¬ÒòΪǰ¶Ë±íÏÖµ¯¿òÐèÒªÕâ¸ö˳ÐòÐèÇó  | 
|     gameMap = GameWorld.GetMap()  | 
|     index = 0  | 
|     for posX, posY in ChConfig.Def_DropItemAreaMatrix:  | 
|         if dropPosX or dropPosY:  | 
|             resultX = dropPosX + posX  | 
|             resultY = dropPosY + posY  | 
|             if not gameMap.CanMove(resultX, resultY):  | 
|                 #Íæ¼Ò²»¿ÉÒÆ¶¯Õâ¸öµã  | 
|                 continue  | 
|         else:  | 
|             resultX, resultY = 0, 0  | 
|         if index > len(virtualItemDropList) - 1:  | 
|             break  | 
|         itemID, dropItemDataStr = virtualItemDropList[index]  | 
|         index += 1  | 
|         SendVirtualItemDrop(curPlayer, itemID, resultX, resultY, dropItemDataStr)  | 
|           | 
|     # ÔÙ¸øÎïÆ·  | 
|     mailItemList = []  | 
|     for itemObj in giveItemObjList:  | 
|         itemID = itemObj.GetItemTypeID()  | 
|         mailItem = ItemCommon.GetMailItemDict(itemObj)  | 
|         equipInfo = [itemObj.GetEquipPlace(), ItemCommon.GetItemClassLV(itemObj), itemObj.GetItemColor(),   | 
|                      itemObj.GetItemQuality(), itemObj.GetUserData()]  | 
|         packIndex = ChConfig.GetItemPackType(itemObj.GetType())  | 
|         if not itemControl.PutInItem(packIndex, itemObj, event=[ChConfig.ItemGive_Pickup, False, {"NPCID":npcID}]):  | 
|             mailItemList.append(mailItem)  | 
|               | 
|         if npcID:  | 
|             SendGameServerGoodItemRecord(curPlayer, mapID, lineID, npcID, itemID, equipInfo)  | 
|            | 
|     # ·Å²»Ïµķ¢Óʼþ     | 
|     if mailItemList:  | 
|         PlayerControl.SendMailByKey(mailTypeKey, [playerID], mailItemList, [mapID])  | 
|     return  | 
|   | 
| ################################### NPCµôÂä ###################################  | 
| Def_NPCMaxDropRate = 1000000 # NPCµôÂäÏà¹ØµÄ×î´ó¸ÅÂÊ, ÊýÖµÉ趨  | 
|   | 
| def GetNPCDropIpyData(npcID):  | 
|     ipyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("NPCDropItem", npcID)  | 
|     if not ipyDataList:  | 
|         GameWorld.DebugLog("¸ÃNPCûÅäÖõôÂ䣡npcID=%s" % npcID)  | 
|         return  | 
|     ipyDrop = None  | 
|     maxWorldLV = 0  | 
|     curWorldLV = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)  | 
|     if len(ipyDataList) == 1:  | 
|         ipyDrop = ipyDataList[0]  | 
|         maxWorldLV = ipyDrop.GetMaxWorldLV()  | 
|         if maxWorldLV and curWorldLV > maxWorldLV:  | 
|             GameWorld.DebugLog("¸ÃNPCµ±Ç°ÊÀ½çµÈ¼¶ÎÞ·¨µôÂäÎïÆ·!npcID=%s,curWorldLV(%s) > maxWorldLV(%s)" % (npcID, curWorldLV, maxWorldLV))  | 
|             return  | 
|     else:  | 
|         for ipyData in ipyDataList:  | 
|             maxWorldLV = ipyData.GetMaxWorldLV()  | 
|             if curWorldLV <= maxWorldLV:  | 
|                 ipyDrop = ipyData  | 
|                 break  | 
|         if not ipyDrop:  | 
|             GameWorld.DebugLog("¸ÃNPCµ±Ç°ÊÀ½çµÈ¼¶ÎÞ·¨µôÂäÎïÆ·!npcID=%s,curWorldLV=%s,maxWorldLV=%s" % (npcID, curWorldLV, maxWorldLV))  | 
|             return  | 
|     return ipyDrop  | 
|   | 
| def GetNPCDropInfoTJG(dropPlayer, mapID, npcID, killCount):  | 
|     '''ÍÑ»ú¹Òɱ¹ÖµôÂäרÓú¯Êý  | 
|     Ö»Ëã: 1.±ýͼװ±¸µôÂä + 2.Ö¸¶¨ÎïÆ·IDµôÂä + 3.½ð±ÒµôÂä  | 
|     '''  | 
|     ipyDrop = GetNPCDropIpyData(npcID)  | 
|     if not ipyDrop:  | 
|         return  | 
|       | 
|     playerLV = dropPlayer.GetLV()  | 
|     maxDropLV = ipyDrop.GetMaxDropLV()  | 
|     if maxDropLV and playerLV > maxDropLV:  | 
|         GameWorld.DebugLog("³¬¹ý×î´ó¿ÉµôÂäµÈ¼¶£¬²»µôÂäÎïÆ·£¡npcID=%s,playerLV(%s) > maxDropLV(%s)" % (npcID, playerLV, maxDropLV))  | 
|         return  | 
|       | 
|     playerID = dropPlayer.GetPlayerID()  | 
|     npcData = GameWorld.GetGameData().FindNPCDataByID(npcID)  | 
|     if not npcData:  | 
|         return  | 
|       | 
|     dropIDList = [] # µôÂäµÄIDÁÐ±í  | 
|     itemJobList = [dropPlayer.GetJob()] if ipyDrop.GetIsDropJobSelf() else IpyGameDataPY.GetFuncEvalCfg("OpenJob", 1) # µôÂä×°±¸Ö°ÒµÁÐ±í  | 
|       | 
|     equipDropRatePlus = PlayerControl.GetDropEquipPer(dropPlayer)  | 
|     equipDropDoCountPlus = PlayerControl.GetDropEquipDoCount(dropPlayer)  | 
|       | 
|     dropRatePlusValue = ipyDrop.GetCanDropRatePlus()  | 
|     if not dropRatePlusValue & pow(2, 0):  | 
|         equipDropRatePlus = 0  | 
|           | 
|     if not dropRatePlusValue & pow(2, 1):  | 
|         equipDropDoCountPlus = 0  | 
|           | 
|     doCountAdd = 0  | 
|     doCountRate = ChConfig.Def_MaxRateValue  | 
|       | 
|     GameWorld.DebugLog("ÍÑ»ú¹Òɱ¹ÖµôÂä: npcID=%s,killCount=%s,itemJobList=%s,dropRatePlusValue=%s,equipDropRatePlus=%s,equipDropDoCountPlus=%s"   | 
|                        % (npcID, killCount, itemJobList, dropRatePlusValue, equipDropRatePlus, equipDropDoCountPlus), playerID)  | 
|       | 
|     dropEquipInfoList = [] # [(½×,ÑÕÉ«, ¼þÊý), ...]  | 
|     # 1.×°±¸Ö»Ëã±ýͼ¸ÅÂÊ  | 
|     pieRateDoCnt = ipyDrop.GetPieRateDoCnt()  | 
|     if pieRateDoCnt and ipyDrop.GetPieRateDrop():  | 
|         pieRateDoCnt = __GetNPCDropDoCountChange(pieRateDoCnt, doCountRate + equipDropDoCountPlus, doCountAdd)  | 
|         pieRateDoCnt *= killCount  | 
|         pieRateDropList = ipyDrop.GetPieRateDrop() # [(¸ÅÂÊ,0),(¸ÅÂÊ,(½×,ÑÕÉ«)),...]  | 
|         if equipDropRatePlus:  | 
|             dropRateList = GameWorld.GetPlusPieList(pieRateDropList, equipDropRatePlus)  | 
|             GameWorld.DebugLog("    ×°±¸ÅäÖñýͼ: %s,equipDropRatePlus=%s" % (pieRateDropList, equipDropRatePlus), playerID)  | 
|         else:  | 
|             dropRateList = pieRateDropList  | 
|         preRate = 0  | 
|         maxRate = dropRateList[-1][0]  | 
|         GameWorld.DebugLog("    ×°±¸µôÂä±ýͼ: %s,maxRate=%s" % (dropRateList, maxRate), playerID)  | 
|         for rateInfo in dropRateList:  | 
|             rate, equipInfo = rateInfo  | 
|             curRate = rate - preRate  | 
|             if not curRate:  | 
|                 break  | 
|             preRate = rate  | 
|             if not equipInfo:  | 
|                 continue  | 
|             classLV, color = equipInfo  | 
|             totalRate = curRate * pieRateDoCnt # ×ܸÅÂÊ  | 
|             dropCount = totalRate / maxRate # ¿ÉµôÂä¼þÊý  | 
|             rateEx = totalRate % maxRate # Ê£Óà¸ÅÂÊ  | 
|             if GameWorld.CanHappen(rateEx, maxRate):  | 
|                 dropCount += 1  | 
|             GameWorld.DebugLog("    ×°±¸µôÂÊ: curRate=%s,totalRate=%s,rateEx=%s,dropCount=%s,classLV=%s,color=%s"   | 
|                                % (curRate, totalRate, rateEx, dropCount, classLV, color), playerID)  | 
|             if not dropCount:  | 
|                 continue  | 
|             dropEquipInfoList.append([classLV, color, dropCount])  | 
|         GameWorld.DebugLog("    ×°±¸µôÂä½á¹û: killCount=%s,[½×,ÑÕÉ«,¼þÊý]=%s" % (killCount, dropEquipInfoList), playerID)  | 
|           | 
|     placeKeyListDict = IpyGameDataPY.GetFuncCfg("EquipDropPartSets", 1)  | 
|     colorSuitRateDict = ipyDrop.GetEquipColorSuitInfo() # ×°±¸ÑÕÉ«¶ÔÓ¦Ì××°¸ÅÂÊ {ÑÕÉ«:Ì××°¸ÅÂÊ, ...}  | 
|     colorSuitPlaceKeyInfoDict = ipyDrop.GetEquipPartKeyRateInfo() # ×°±¸²¿Î»¼¯ºÏÐÅÏ¢ {(ÑÕÉ«,ÊÇ·ñÌ××°):²¿Î»¼¯ºÏkey, ...}  | 
|     dropEquipIDDict = {}  | 
|     for classLV, color, dropCount in dropEquipInfoList:  | 
|         suitCountDict = {} # {Ì××°:¼þÊý, ...}  | 
|         if color in colorSuitRateDict:  | 
|             suitRate = colorSuitRateDict[color]  | 
|             for _ in xrange(dropCount):  | 
|                 isSuit = GameWorld.CanHappen(suitRate, maxRate=Def_NPCMaxDropRate)  | 
|                 suitCountDict[isSuit] = suitCountDict.get(isSuit, 0) + 1  | 
|         else:  | 
|             suitCountDict[0] = dropCount  | 
|               | 
|         for isSuit, curDropCount in suitCountDict.items():  | 
|             colorSuitKey = (color, isSuit)  | 
|             if colorSuitKey not in colorSuitPlaceKeyInfoDict:  | 
|                 GameWorld.ErrLog("δÅäÖÃÑÕÉ«ÊÇ·ñÌ××°¶ÔÓ¦²¿Î»¼¯ºÏkey! npcID=%s,color=%s,isSuit=%s" % (npcID, color, isSuit))  | 
|                 continue  | 
|             placeKey = colorSuitPlaceKeyInfoDict[colorSuitKey]  | 
|             if placeKey not in placeKeyListDict:  | 
|                 GameWorld.ErrLog("²¿Î»¼¯ºÏkey²»´æÔÚ!npcID=%s,placeKey=%s" % (npcID, placeKey))  | 
|                 continue  | 
|             placeList = placeKeyListDict[placeKey]  | 
|             randEquipIDList = __GetEquipIDList(npcID, classLV, color, isSuit, placeList, itemJobList)  | 
|             if not randEquipIDList:  | 
|                 continue  | 
|             for _ in xrange(curDropCount):  | 
|                 randItemID = random.choice(randEquipIDList)  | 
|                 dropIDList.append(randItemID)  | 
|                 dropEquipIDDict[randItemID] = [color, placeKey]  | 
|                 GameWorld.DebugLog("    µôÂä×°±¸: npcID=%s,itemID=%s,classLV=%s,color=%s,isSuit=%s,placeKey=%s,itemJobList=%s,randEquipIDList=%s"   | 
|                                    % (npcID, randItemID, classLV, color, isSuit, placeKey, itemJobList, randEquipIDList), playerID)  | 
|                   | 
|     # 2. Ö¸¶¨ÎïÆ·ID¿â  | 
|     itemIDDropRateDict = ipyDrop.GetItemIDDropRate() # {ÎïÆ·ID:¸ÅÂÊ, ...}  | 
|     itemIDDropMaxCntDict = ipyDrop.GetItemIDMaxDropCount() # {ÎïÆ·ID:×î´óµôÂä¸öÊý,...}  | 
|     for itemID, dropRate in itemIDDropRateDict.items():  | 
|           | 
|         if not dropRate:  | 
|             continue  | 
|           | 
|         doCnt = itemIDDropMaxCntDict.get(itemID, 1) # Ä¬ÈÏ1¸ö  | 
|         doCnt = __GetNPCDropDoCountChange(doCnt, doCountRate, doCountAdd)  | 
|         doCnt *= killCount  | 
|           | 
|         totalRate = dropRate * doCnt  | 
|         dropCount = totalRate / maxRate # ¿ÉµôÂä¼þÊý  | 
|         rateEx = totalRate % maxRate # Ê£Óà¸ÅÂÊ  | 
|         if GameWorld.CanHappen(rateEx, Def_NPCMaxDropRate):  | 
|             dropCount += 1  | 
|         dropIDList += [itemID] * dropCount  | 
|         GameWorld.DebugLog("    Ö¸¶¨ÎïÆ·µôÂä: itemID=%s,dropRate=%s,doCnt=%s,totalRate=%s,dropCount=%s"   | 
|                            % (itemID, dropRate, doCnt, totalRate, dropCount), playerID)  | 
|       | 
|     # ¼ì²éµôÂ以³âID×é  | 
|     dropIDList = __RemoveMutexDropID(dropIDList, IpyGameDataPY.GetFuncCfg("MutexDrop", 1))  | 
|       | 
|     # µôÂä½ð±Ò  | 
|     dropMoneyDoCnt = ipyDrop.GetDropMoneyDoCnt()  | 
|     dropMoneyRate = ipyDrop.GetDropMoneyRate()  | 
|     moneyTotalRate = dropMoneyRate * dropMoneyDoCnt * killCount  | 
|     dropMoneyCnt = moneyTotalRate / ChConfig.Def_NPCMapDropRate  | 
|     if GameWorld.CanHappen(moneyTotalRate % ChConfig.Def_NPCMapDropRate, ChConfig.Def_NPCMapDropRate):  | 
|         dropMoneyCnt += 1  | 
|     dropMoney = 0  | 
|     if dropMoneyCnt:  | 
|         dropMoney = __GetDropMoneyValue(dropPlayer, ipyDrop) * dropMoneyCnt  | 
|         GameWorld.DebugLog("    ½ð±ÒµôÂÊ: dropMoneyRate=%s,moneyTotalRate=%s,dropMoneyCnt=%s,dropMoney=%s"   | 
|                            % (dropMoneyRate, moneyTotalRate, dropMoneyCnt, dropMoney), playerID)  | 
|     dropIDCountDict = {}  | 
|     for dropID in dropIDList:  | 
|         dropIDCountDict[dropID] = dropIDCountDict.get(dropID, 0) + 1  | 
|           | 
|     auctionIDList = []  | 
|     if ipyDrop.GetAucionItemCanSell():  | 
|         for dropID in dropIDCountDict.keys():  | 
|             if IpyGameDataPY.GetIpyGameDataNotLog("AuctionItem", dropID):  | 
|                 auctionIDList.append(dropID)  | 
|                   | 
|     if dropIDCountDict:  | 
|         GameWorld.DebugLog("    ×îÖÕµôÂä: npcID=%s,killCount=%s,dropIDCountDict=%s,auctionIDList=%s,dropMoney=%s"   | 
|                            % (npcID, killCount, dropIDCountDict, auctionIDList, dropMoney), playerID)  | 
|     return dropIDCountDict, auctionIDList, dropMoney  | 
|   | 
| def GetNPCDropInfo(dropPlayer, mapID, npcID, ownerPlayerList=[], ipyDrop=None, isSingle=True, isKillCountDrop=True, curGrade=0):  | 
|     '''»ñÈ¡NPCµôÂäÐÅÏ¢, »÷ɱ¼°É¨µ´Í¨Ó㬵÷Óøú¯Êý»ñµÃµôÂäÐÅÏ¢£¬È»ºóÔÙ¿´µôÂ䵨°åÉÏ»¹ÊÇÖ±½Ó·ÅÈë±³°ü  | 
|         @param dropPlayer: ÓÃÓÚÅжϵ÷ÓÃÏà¹ØÓõÄÍæ¼ÒʾÀý£¬¸ÃÍæ¼Ò²¢²»Ò»¶¨ÊÇ»÷ɱÕߣ¬Ö»Êǰ´Ò»¶¨¹æÔòÉ趨µÄµôÂäÅжÏÒÀ¾ÝµÄÍæ¼Ò  | 
|                             Èç¶ÓÎ飬ȡµÈ¼¶×î´óµÄÍæ¼Ò£¬¸ÃÍæ¼Ò²¢²»Ò»¶¨ÊÇ»÷ɱÕß  | 
|         @param mapID: µôÂäÎïÆ·ËùÊôµØÍ¼£¬×¢Òâ´ËµØÍ¼²¢²»Ò»¶¨Êǵ±Ç°µØÍ¼£¬Èçɨµ´Ê±ÐèʹÓÃÄ¿±ê¸±±¾µØÍ¼  | 
|         @param npcID: µôÂäÎïÆ·µÄNPCID  | 
|         @param ownerPlayerList: ÓйéÊôµÄÍæ¼ÒÁÐ±í  | 
|         @param isSingle: ÊÇ·ñÖ»´¦Àíµ¥¶ÀÍæ¼ÒµôÂäÂß¼£¬Ò»°ã¶¼Ä¬ÈÏTrue£¬Ä¿Ç°Ö»Óг¡¾°É±¹ÖµôÂäÐèÒª¿¼ÂÇÃþ¹ÖµÄÇé¿öϲÅΪFalse£¨Íâ²ãÌØÊâ´¦Àí£©  | 
|         @return: dropIDList, auctionIDList, dropMoneyCnt, moneyValue  | 
|                 None-ûÓеôÂä  | 
|                 ---------------  | 
|                 dropIDList        -    µôÂäµÄÎïÆ·IDÁбí, Í¬¸öitemID¿ÉÄÜÔÚÁбíÖÐÓжà¸ö [itemID, itemID, ...]  | 
|                 auctionIDList    -    µôÂäµÄÅÄÆ·ÎïÆ·IDÁбí, [itemID, itemID, ...]  | 
|                 dropMoneyCnt      -    µôÂä½ð±ÒλÖÃÊý  | 
|                 moneyValue        -    Ã¿¸öλÖõĽð±ÒÊýÁ¿  | 
|     '''  | 
|     if not ipyDrop:  | 
|         ipyDrop = GetNPCDropIpyData(npcID)  | 
|         if not ipyDrop:  | 
|             return  | 
|           | 
|     if not ownerPlayerList:  | 
|         ownerPlayerList = [dropPlayer]  | 
|           | 
|     playerID = dropPlayer.GetPlayerID()  | 
|     playerLV = dropPlayer.GetLV()  | 
|     maxDropLV = ipyDrop.GetMaxDropLV()  | 
|     if maxDropLV and playerLV > maxDropLV:  | 
|         GameWorld.DebugLog("³¬¹ý×î´ó¿ÉµôÂäµÈ¼¶£¬²»µôÂäÎïÆ·£¡npcID=%s,playerLV(%s) > maxDropLV(%s)" % (npcID, playerLV, maxDropLV))  | 
|         return  | 
|       | 
|     npcData = GameWorld.GetGameData().FindNPCDataByID(npcID)  | 
|     if not npcData:  | 
|         GameWorld.ErrLog("»ñÈ¡NPCµôÂäÅäÖôíÎó!±í²»´æÔÚ¸ÃNPCID=%s" % npcID, playerID)  | 
|         return  | 
|       | 
|     dropIDList = [] # µôÂäµÄIDÁÐ±í  | 
|     auctionIDList = []  | 
|     dropMoneyCnt, moneyValue = 0, 0  | 
|     itemJobList = [dropPlayer.GetJob()] if ipyDrop.GetIsDropJobSelf() else IpyGameDataPY.GetFuncEvalCfg("OpenJob", 1) # µôÂä×°±¸Ö°ÒµÁÐ±í  | 
|                       | 
|     # Í¨ÓõôÂÊÏà¹Ø  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     doCountAdd = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_DropDoCountAdd)  | 
|     doCountRate = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_DropDoCountRate) # Ö±½Ó¸²¸Ç»ùÖµ, ÎÞֵʱȡĬÈÏÖµ  | 
|     if not doCountRate:  | 
|         doCountRate = ChConfig.Def_MaxRateValue  | 
|           | 
|     # ¹éÊôÕßÏà¹ØÐÅÏ¢  | 
|     tagJob = 0  | 
|     dropEquipKillCountPub = 0 # ×°±¸¸½¼ÓµôÂä×ۺϻ÷ɱ´ÎÊý£¬È¡´ÎÊý×î´óµÄÄǸö£¬ÖÁÉÙµÚÒ»´Î  | 
|     dropItemIDKillCountPub = 0 # ÎïÆ·ID¸½¼ÓµôÂä×ۺϻ÷ɱ´ÎÊý£¬È¡´ÎÊý×î´óµÄÄǸö£¬ÖÁÉÙµÚÒ»´Î  | 
|     equipDropRatePlus = 0 # ×°±¸µôÂä¸ÅÂÊÌáÉý  | 
|     equipDropDoCountPlus = 0 # ×°±¸µôÂäÖ´ÐдÎÊýÌáÉý  | 
|     for ownerPlayer in ownerPlayerList:  | 
|         killCountValue = ownerPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCKillCount % npcID)  | 
|         equipPubKillCount = killCountValue % 100 + 1  | 
|         itemIDPubKillCount = killCountValue % 10000 / 100 + 1  | 
|           | 
|         if dropEquipKillCountPub < equipPubKillCount:  | 
|             dropEquipKillCountPub = equipPubKillCount  | 
|             tagJob = ownerPlayer.GetJob()  | 
|               | 
|         if dropItemIDKillCountPub < itemIDPubKillCount:  | 
|             dropItemIDKillCountPub = itemIDPubKillCount  | 
|               | 
|         equipDropRatePlus = max(equipDropRatePlus, PlayerControl.GetDropEquipPer(ownerPlayer))  | 
|         equipDropDoCountPlus = max(equipDropDoCountPlus, PlayerControl.GetDropEquipDoCount(ownerPlayer))  | 
|           | 
|     dropRatePlusValue = ipyDrop.GetCanDropRatePlus()  | 
|     if not dropRatePlusValue & pow(2, 0):  | 
|         equipDropRatePlus = 0  | 
|           | 
|     if not dropRatePlusValue & pow(2, 1):  | 
|         equipDropDoCountPlus = 0  | 
|           | 
|     #GameWorld.DebugLog("NPCµôÂä: npcID=%s,itemJobList=%s,dropRatePlusValue=%s,equipDropRatePlus=%s,equipDropDoCountPlus=%s,doCountRate=%s,doCountAdd=%s"   | 
|     #                   % (npcID, itemJobList, dropRatePlusValue, equipDropRatePlus, equipDropDoCountPlus, doCountRate, doCountAdd), playerID)  | 
|       | 
|     dropEquipInfoList = [] # [(½×,ÑÕÉ«), ...]  | 
|     # 1. ×°±¸¿â - ±ýͼ¸ÅÂÊ  | 
|     pieRateDoCnt = ipyDrop.GetPieRateDoCnt()  | 
|     if pieRateDoCnt:  | 
|         pieRateDoCnt = __GetNPCDropDoCountChange(pieRateDoCnt, doCountRate + equipDropDoCountPlus, doCountAdd)  | 
|         dropEquipInfoList += __GetNPCPieRateEquipDrop(ipyDrop, pieRateDoCnt, equipDropRatePlus)  | 
|           | 
|     # 2. ×°±¸¿â -  ¶ÀÁ¢¸ÅÂÊ  | 
|     indepRateDoCnt = ipyDrop.GetIndepRateDoCnt()  | 
|     if indepRateDoCnt:  | 
|         indepRateDoCnt = __GetNPCDropDoCountChange(indepRateDoCnt, doCountRate + equipDropDoCountPlus, doCountAdd)  | 
|         dropEquipInfoList += __GetNPCIndepRateEquipDrop(ipyDrop, indepRateDoCnt, equipDropRatePlus, curGrade)      | 
|     #GameWorld.DebugLog("½×,ÑÕÉ« key,dropEquipInfoList=%s" % (dropEquipInfoList))  | 
|       | 
|     # 3. µÚx´Î»÷ɱ£¬ ¹éÊôÕß¹«¹²¸½¼ÓµôÂ䣬ËùÓйéÊôÕß¶¼Ôö¼Ó»÷ɱ´ÎÊý£»   | 
|     tagClassLV, tagColor, tagIsSuit, tagPlaceKey = 0, 0, 0, 0  | 
|     killCountDropEquipPub = ipyDrop.GetKillCountDropEquipPub() # µÚx´Î»÷ɱ¸½¼Ó±Øµô×°±¸ {´ÎÊý:[½×,ÑÕÉ«,ÊÇ·ñÌ××°,²¿Î»¼¯ºÏkey], ...}  | 
|     killCountDropItemPub = ipyDrop.GetKillCountDropPub() # »÷ɱ´ÎÊý±Øµô£¨¹«¹²£©{»÷ɱ´ÎÊý:[[ÎïÆ·ID, ...], [Ëæ»úÎïÆ·ID, ...]], ...}  | 
|     maxRecordDropEquipKillCountPub = 0 if not killCountDropEquipPub else max(killCountDropEquipPub) # ÐèÒª¼Ç¼µÄ×î´ó»÷ɱ´ÎÊý, ³¬¹ý´Ë»÷ɱ´ÎÊýºóÔÝʱ²»ÀۼӼǼ  | 
|     maxRecordDropItemIDKillCountPub = 0 if not killCountDropItemPub else max(killCountDropItemPub)  | 
|     #GameWorld.DebugLog("maxRecordDropEquipKillCountPub=%s,maxRecordDropItemIDKillCountPub=%s" % (maxRecordDropEquipKillCountPub, maxRecordDropItemIDKillCountPub))  | 
|     #GameWorld.DebugLog("dropEquipKillCountPub=%s,dropItemIDKillCountPub=%s" % (dropEquipKillCountPub, dropItemIDKillCountPub))  | 
|     if isKillCountDrop and killCountDropEquipPub and dropEquipKillCountPub in killCountDropEquipPub:  | 
|         tagClassLV, tagColor, tagIsSuit, tagPlaceKey = killCountDropEquipPub[dropEquipKillCountPub]  | 
|         if (tagClassLV, tagColor) not in dropEquipInfoList:  | 
|             dropEquipInfoList.insert(0, (tagClassLV, tagColor, tagIsSuit, tagPlaceKey, tagJob))  | 
|         else:  | 
|             tagIndex = dropEquipInfoList.index((tagClassLV, tagColor))  | 
|             dropEquipInfoList[tagIndex] = (tagClassLV, tagColor, tagIsSuit, tagPlaceKey, tagJob)  | 
|         GameWorld.DebugLog("µÚ%s´Î»÷ɱµôÂäÖ¸¶¨Ä¿±ê×°±¸ÐÅÏ¢: npcID=%s,tagClassLV=%s,tagColor=%s,tagIsSuit=%s,tagPlaceKey=%s,tagJob=%s,dropEquipInfoList=%s"   | 
|                            % (dropEquipKillCountPub, npcID, tagClassLV, tagColor, tagIsSuit, tagPlaceKey, tagJob, dropEquipInfoList), playerID)  | 
|     elif isKillCountDrop and killCountDropItemPub and dropItemIDKillCountPub in killCountDropItemPub:  | 
|         killCountItemIDList, killCountRandItemIDList = killCountDropItemPub[dropItemIDKillCountPub]  | 
|         if killCountItemIDList:  | 
|             dropIDList += killCountItemIDList  | 
|         if killCountRandItemIDList:  | 
|             klllCountRandItemID = random.choice(killCountRandItemIDList)  | 
|             dropIDList.append(klllCountRandItemID)  | 
|         GameWorld.DebugLog("µÚ%s´Î»÷ɱµôÂäÖ¸¶¨Ä¿±êÎïÆ·ÐÅÏ¢: npcID=%s,killCountItemIDList=%s,killCountRandItemIDList=%s,dropIDList=%s"   | 
|                            % (dropItemIDKillCountPub, npcID, killCountItemIDList, killCountRandItemIDList, dropIDList), playerID)  | 
|               | 
|     for ownerPlayer in ownerPlayerList:  | 
|         # Ôö¼Ó»÷ɱ´ÎÊý  | 
|         killCountValue = ownerPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCKillCount % npcID)  | 
|         equipPubKillCount = killCountValue % 100  | 
|         itemIDPubKillCount = killCountValue % 10000 / 100  | 
|         isUpd = False  | 
|         if equipPubKillCount < maxRecordDropEquipKillCountPub:  | 
|             equipPubKillCount += 1  | 
|             isUpd = True  | 
|         if itemIDPubKillCount < maxRecordDropItemIDKillCountPub:  | 
|             itemIDPubKillCount += 1  | 
|             isUpd = True  | 
|               | 
|         if isUpd:  | 
|             itemIDPriKillCount = killCountValue / 10000  | 
|             updKillCountValue = itemIDPriKillCount * 10000 + itemIDPubKillCount * 100 + equipPubKillCount  | 
|             PlayerControl.NomalDictSetProperty(ownerPlayer, ChConfig.Def_PDict_NPCKillCount % npcID, updKillCountValue)  | 
|             GameWorld.DebugLog("¸üÐÂÍæ¼Ò»÷ɱ´ÎÊýÖµ: npcID=%s,killCountValue=%s,updKillCountValue=%s" % (npcID, killCountValue, updKillCountValue), ownerPlayer.GetPlayerID())  | 
|               | 
|     gradeColorSuitRateDict = {}  | 
|     fbGradeColorSuitRateDict = IpyGameDataPY.GetFuncEvalCfg("FBGradeEquipDropRate", 2) # ÆÀ¼¶Ó°ÏìÑÕÉ«Ì××°¸ÅÂÊ {npcID:{ÑÕÉ«:[D¼¶Ó°Ïì¸ÅÂÊ, ..., S¼¶Ó°Ïì¸ÅÂÊ], ...}, ...}  | 
|     if npcID in fbGradeColorSuitRateDict:  | 
|         gradeColorSuitRateDict = fbGradeColorSuitRateDict[npcID]  | 
|         curGrade = curGrade if curGrade else GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Def_FB_Grade)  | 
|           | 
|     placeKeyListDict = IpyGameDataPY.GetFuncCfg("EquipDropPartSets", 1)  | 
|     colorDropCntDict = {} # ×°±¸ÑÕÉ«ÒѾµôÂäÊý {ÑÕÉ«:ÊýÁ¿, ...}  | 
|     colorMaxDropCntDict = ipyDrop.GetEquipColorMaxDropCount() # {ÑÕÉ«:ÉÏÏÞÊýÁ¿,...}  | 
|     colorSuitRateDict = ipyDrop.GetEquipColorSuitInfo() # ×°±¸ÑÕÉ«¶ÔÓ¦Ì××°¸ÅÂÊ {ÑÕÉ«:Ì××°¸ÅÂÊ, ...}  | 
|     colorSuitPlaceKeyInfoDict = ipyDrop.GetEquipPartKeyRateInfo() # ×°±¸²¿Î»¼¯ºÏÐÅÏ¢ {(ÑÕÉ«,ÊÇ·ñÌ××°):²¿Î»¼¯ºÏkey, ...}  | 
|     colorSuitPartOptimization = ipyDrop.GetColorSuitPartOptimization() # ²¿Î»ÑÕÉ«ÌׯÀ·ÖÓÅÑ¡µôÂ䣬ʮλ´ú±íÑÕÉ«£¬¸öλ´ú±íÌ××°  | 
|     optColor, optIsSuit = colorSuitPartOptimization / 10, colorSuitPartOptimization % 10  | 
|     optPlace = None # ÓÅÑ¡²¿Î»  | 
|       | 
|     for dropEquipInfo in dropEquipInfoList:  | 
|         classLV, color = dropEquipInfo[:2]  | 
|         if color in colorMaxDropCntDict:  | 
|             maxCount = colorMaxDropCntDict[color]  | 
|             dropCount = colorDropCntDict.get(color, 0)  | 
|             if dropCount >= maxCount:  | 
|                 GameWorld.DebugLog("Òѳ¬¹ý¸ÃÑÕɫװ±¸×î´óµôÂäÊý£¬²»µô£¡color=%s,maxCount=%s" % (color, maxCount), playerID)  | 
|                 continue  | 
|               | 
|         if len(dropEquipInfo) == 5:  | 
|             isSuit, placeKey, tagJob = dropEquipInfo[2:]  | 
|             jobList = [tagJob]  | 
|         else:  | 
|             isSuit = 0  | 
|             if color in colorSuitRateDict:  | 
|                 suitRate = colorSuitRateDict[color]  | 
|                 # ÆÀ¼¶¶ÔÌ××°ÂʵÄÓ°Ïì  | 
|                 if color in gradeColorSuitRateDict:  | 
|                     suitRateEffList = gradeColorSuitRateDict[color]  | 
|                     suitRateEff = 10000 if (curGrade <= 0 or curGrade > len(suitRateEffList)) else suitRateEffList[curGrade - 1]  | 
|                     suitRate = int(suitRate * suitRateEff / 10000.0)  | 
|                 isSuit = GameWorld.CanHappen(suitRate, maxRate=Def_NPCMaxDropRate)  | 
|             colorSuitKey = (color, isSuit)  | 
|             if colorSuitKey not in colorSuitPlaceKeyInfoDict:  | 
|                 GameWorld.ErrLog("δÅäÖÃÑÕÉ«ÊÇ·ñÌ××°¶ÔÓ¦²¿Î»¼¯ºÏkey! npcID=%s,color=%s,isSuit=%s" % (npcID, color, isSuit))  | 
|                 continue  | 
|             placeKey = colorSuitPlaceKeyInfoDict[colorSuitKey]  | 
|             # µôÂäÓÅÑ¡²¿Î»´¦Àí  | 
|             if color == optColor and isSuit == optIsSuit and placeKey in placeKeyListDict and optPlace == None:  | 
|                 optPlace = __GetOptimizationEquipPlace(dropPlayer, classLV, optColor, optIsSuit, placeKeyListDict[placeKey])  | 
|             jobList = itemJobList  | 
|         if placeKey not in placeKeyListDict:  | 
|             GameWorld.ErrLog("²¿Î»¼¯ºÏkey²»´æÔÚ!npcID=%s,placeKey=%s" % (npcID, placeKey))  | 
|             continue  | 
|         if optPlace > 0:  | 
|             GameWorld.DebugLog("    ×îÖÕÓÅÑ¡²¿Î»: %s" % optPlace)  | 
|             placeList = [optPlace]  | 
|             jobList = [dropPlayer.GetJob()]  | 
|             optPlace = 0 # Ö»ÓÐÒ»´ÎÐԵģ¬ÖÃΪ0  | 
|         else:  | 
|             placeList = placeKeyListDict[placeKey]  | 
|         randEquipIDList = __GetEquipIDList(npcID, classLV, color, isSuit, placeList, jobList)  | 
|         if not randEquipIDList:  | 
|             continue  | 
|         if color in colorMaxDropCntDict:  | 
|             colorDropCntDict[color] = dropCount + 1  | 
|         randItemID = random.choice(randEquipIDList)  | 
|         dropIDList.append(randItemID)  | 
|         GameWorld.DebugLog("µôÂä×°±¸: npcID=%s,itemID=%s,classLV=%s,color=%s,isSuit=%s,placeKey=%s,jobList=%s,randEquipIDList=%s"   | 
|                            % (npcID, randItemID, classLV, color, isSuit, placeKey, jobList, randEquipIDList), playerID)  | 
|           | 
|     # 4. Ö¸¶¨ÎïÆ·ID¿â  | 
|     dropIDList += __GetAppointDropItemIDList(dropPlayer, npcID, ipyDrop, doCountRate, doCountAdd)  | 
|       | 
|     # 5. Ë½ÓеôÂä  | 
|     if isSingle:  | 
|         # »÷ɱ´ÎÊýµôÂä  | 
|         killCountDropInfo = ipyDrop.GetKillCountDropPri()  | 
|         if killCountDropInfo:  | 
|             needKillCount, killDropItemList = killCountDropInfo[:2]  | 
|             killCountDropIDList = GetKillCountDropItemList(dropPlayer, npcID, needKillCount, killDropItemList)  | 
|             for kDropItemID in killCountDropIDList:  | 
|                 dropIDList.append(kDropItemID) # µ¥¶ÀÍæ¼ÒµôÂä´¦ÀíµÄ£¬Ö±½Ó¼Óµ½µôÂäÁбíÀ²»¿¼ÂÇÊÇ·ñ·ÅÈë±³°ü»òµôÂäµÄÇé¿ö£¬ÓÉʹÓõŦÄÜ×ÔÐд¦Àí  | 
|                 #GameWorld.DebugLog("»÷ɱ´ÎÊýµôÂä: kDropItemID=%s,needKillCount=%s" % (kDropItemID, needKillCount))  | 
|                   | 
|         # ¹Ì¶¨²ú³ö£¬ËùÓеôÂä¹éÊôÕßÿÈËÒ»·Ý£¬Ä¬Èϰ󶨣¬²»Çø·ÖÖ°Òµ  | 
|         fbGradePriItemIDDropDict = IpyGameDataPY.GetFuncEvalCfg("FBGradeEquipDropRate", 3)  | 
|         if npcID in fbGradePriItemIDDropDict:  | 
|             gradePriItemIDDropDict = fbGradePriItemIDDropDict[npcID]  | 
|             curGrade = curGrade if curGrade else GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Def_FB_Grade)  | 
|             priDropInfoList = gradePriItemIDDropDict.get(curGrade, [])  | 
|             priDropIDList = []  | 
|             for priItemID, priItemCount in priDropInfoList:  | 
|                 priDropIDList += [priItemID] * priItemCount  | 
|         else:  | 
|             priDropIDList = ipyDrop.GetPriItemIDDrop()  | 
|         for priDropID in priDropIDList:  | 
|             dropIDList.append(priDropID)  | 
|             #GameWorld.DebugLog("˽ÓÐÎïÆ·µôÂä: priDropID=%s" % priDropID)  | 
|               | 
|     # ¼ì²éµôÂ以³âID×é  | 
|     dropIDList = __RemoveMutexDropID(dropIDList, IpyGameDataPY.GetFuncCfg("MutexDrop", 1))  | 
|           | 
|     # µôÂä½ð±Ò  | 
|     dropMoneyDoCnt = ipyDrop.GetDropMoneyDoCnt()  | 
|     dropMoneyRate = ipyDrop.GetDropMoneyRate()  | 
|     if dropMoneyRate == ChConfig.Def_NPCMapDropRate:  | 
|         dropMoneyCnt = dropMoneyDoCnt  | 
|     else:  | 
|         dropMoneyCnt = 0  | 
|         for _ in xrange(dropMoneyDoCnt):  | 
|             if GameWorld.CanHappen(dropMoneyRate, ChConfig.Def_NPCMapDropRate):  | 
|                 dropMoneyCnt += 1  | 
|                   | 
|     #GameWorld.DebugLog("NPCID=%s,½ð±ÒµôÂÊ: %s, Ö´ÐдÎÊý=%s, µôÂä½ð±ÒÊý=%s" % (npcID, dropMoneyRate, dropMoneyDoCnt, dropMoneyCnt))  | 
|     if dropMoneyCnt:  | 
|         moneyValue = __GetDropMoneyValue(dropPlayer, ipyDrop)  | 
|         #GameWorld.DebugLog("    µôÂä½ð±Òvalue=%s" % (moneyValue))  | 
|           | 
|     if dropIDList:  | 
|         if ipyDrop.GetAucionItemCanSell():  | 
|             for dropID in dropIDList:  | 
|                 if IpyGameDataPY.GetIpyGameDataNotLog("AuctionItem", dropID):  | 
|                     auctionIDList.append(dropID)  | 
|         GameWorld.DebugLog("×îÖÕµôÂäÎïÆ·: npcID=%s,dropIDList=%s" % (npcID, dropIDList), playerID)  | 
|         GameWorld.DebugLog("    auctionIDList=%s" % (auctionIDList), playerID)  | 
|     elif ChConfig.IsGameBoss(npcData):  | 
|         GameWorld.ErrLog("BossûÓеôÂäÎïÆ·,NPCID=%s" % (npcID), dropPlayer.GetPlayerID())  | 
|     return dropIDList, auctionIDList, dropMoneyCnt, moneyValue  | 
|   | 
| def __GetOptimizationEquipPlace(dropPlayer, classLV, optColor, optIsSuit, optPlaceList):  | 
|     ''' »ñÈ¡µôÂäÓÅÑ¡²¿Î»  | 
|         ¼¸¸öĬÈϹæÔò  | 
|     1. ÑÕÉ«´óÓÚÖ¸¶¨ÓÅÑ¡ÑÕÉ«µÄ£¬ÎÞÂÛÊÇ·ñÌ××°¶¼²»¼ÆËãÔÚÄÚ  | 
|     2. ÑÕɫСÓÚÖ¸¶¨ÓÅÑ¡ÑÕÉ«µÄ£¬ÎÞÂÛÊÇ·ñÌ××°¶¼¼ÆËãÔÚÄÚ  | 
|     '''  | 
|     #GameWorld.DebugLog("´¦ÀíÓÅÑ¡²¿Î»µôÂä: classLV=%s,optColor=%s,optIsSuit=%s,optPlaceList=%s" % (classLV, optColor, optIsSuit, optPlaceList))  | 
|     minGSPlace = None  | 
|     minGS = None  | 
|     equipPack = dropPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)  | 
|     for optPlace in optPlaceList:  | 
|         ipyData = IpyGameDataPY.GetIpyGameData('EquipPlaceIndexMap', classLV, optPlace)  | 
|         if not ipyData:  | 
|             continue  | 
|         equipIndex = ipyData.GetGridIndex()  | 
|         curEquip = equipPack.GetAt(equipIndex)  | 
|         if not curEquip or curEquip.IsEmpty():  | 
|             #GameWorld.DebugLog("    Ã»´©×°±¸£¬Ö±½ÓĬÈÏ·µ»Ø¸Ã²¿Î»: optPlace=%s" % optPlace)  | 
|             return optPlace  | 
|         curColor = curEquip.GetItemColor()  | 
|         curIsSuit = 1 if curEquip.GetSuiteID() else 0  | 
|         if curColor > optColor:  | 
|             # ³¬¹ýÓÅѡָ¶¨ÑÕÉ«µÄ²»Ë㣬ÎÞÂÛÊÇ·ñÓÐÌ××°  | 
|             #GameWorld.DebugLog("    ÑÕÉ«³¬¹ýÓÅÑ¡ÑÕÉ«£¬²»Ëã¸Ã²¿Î»: optPlace=%s,curColor=%s,curIsSuit=%s" % (optPlace, curColor, curIsSuit))  | 
|             continue  | 
|         if curColor == optColor and curIsSuit >= optIsSuit:  | 
|             # ÓëÓÅѡָ¶¨ÑÕÉ«Ïàͬ£¬ÇÒÂú×ãÊÇ·ñÌ××°µÄ²»Ëã  | 
|             #GameWorld.DebugLog("    ÑÕÉ«Ì××°Âú×ãÓÅÑ¡£¬²»Ëã¸Ã²¿Î»: optPlace=%s,curColor=%s,curIsSuit=%s" % (optPlace, curColor, curIsSuit))  | 
|             continue  | 
|         curGS = ItemCommon.GetEquipGearScore(curEquip)  | 
|         if minGS == None or curGS < minGS:  | 
|             minGS = curGS  | 
|             minGSPlace = optPlace  | 
|               | 
|     return minGSPlace  | 
|   | 
| def __GetNPCDropDoCountChange(doCount, doCountRate, doCountAdd):  | 
|     ## »ñÈ¡µôÂäÖ´ÐдÎÊý±ä¸ü½á¹û£¬¿ÉÄÜÔö¼Ó »ò ¼õÉÙ  | 
|     if doCountRate != ChConfig.Def_MaxRateValue:  | 
|         doCount = max(1, int(doCount * doCountRate / 10000.0))  | 
|     if doCountAdd:  | 
|         doCount = max(1, doCount + doCountAdd) # Ö§³ÖÕý¸º£¬±£µ×1£¬¸ºÖµ´ýÀ©Õ¹  | 
|     return doCount  | 
|   | 
| def __RemoveMutexDropID(dropIDList, mutexDropInfo):  | 
|     ## ÒƳý»¥³âµÄµôÂäÎïÆ·£¬Ã¿×黥³âµÄID×î¶àÖ»ÄܵôÂäÒ»¸ö£¬Áбí˳ÐòΪµôÂäÓÅÏȼ¶ [[»¥³â×é1ID, ID, ...], [»¥³â×é2ID, ID, ...], ...]  | 
|     for mutexDropList in mutexDropInfo:  | 
|         isMutex = False  | 
|         for mutexID in mutexDropList:  | 
|             if mutexID not in dropIDList:  | 
|                 continue  | 
|             if not isMutex:  | 
|                 isMutex = True  | 
|                 curDropIDCnt = dropIDList.count(mutexID)  | 
|                 # Èç¹û³¬¹ý1¸ö£¬ÔòÒÆ³ý¶àÓàµÄ£¬Ö»±£ÁôÒ»¸ö  | 
|                 if curDropIDCnt > 1:  | 
|                     for _ in xrange(curDropIDCnt - 1):  | 
|                         dropIDList.remove(mutexID)  | 
|                 continue  | 
|               | 
|             # ÒѾÊÇ»¥³âµÄÁË£¬¸ÃID²»¿ÉµôÂ䣬ȫ²¿ÒƳý  | 
|             while mutexID in dropIDList:  | 
|                 dropIDList.remove(mutexID)  | 
|                   | 
|     return dropIDList  | 
|   | 
| def __GetAppointDropItemIDList(curPlayer, npcID, ipyDrop, doCountRate, doCountAdd):  | 
|     ## Ö¸¶¨ÎïÆ·IDµôÂä  | 
|       | 
|     dropItemIDList = []  | 
|       | 
|     # 1. Ö°ÒµÎïÆ·ID¼¯ºÏ  | 
|     job = curPlayer.GetJob()  | 
|     JobItemDropSets = IpyGameDataPY.GetFuncCfg("JobItemDropSets", 1) # {ÎïÆ·ID¼¯ºÏkey:[ְҵ˳ÐòÎïÆ·IDÁбí], ...}  | 
|     itemDropSets = IpyGameDataPY.GetFuncCfg("JobItemDropSets", 2) # {ÎïÆ·ID¼¯ºÏkey:[Ëæ»úÎïÆ·IDÁбí], ...}  | 
|     itemDropRateSets = IpyGameDataPY.GetFuncCfg("JobItemDropSets", 3) # {ÎïÆ·ID¼¯ºÏkey:[Ëæ»úÎïÆ·ID±ýͼÁбí], ...}  | 
|     ItemKeyMaxDropCountDict = ipyDrop.GetItemKeyMaxDropCount() # {ÎïÆ·ID¼¯ºÏkey:Ëæ»ú´ÎÊý,...}  | 
|       | 
|     #     1.1 Ö»µô±¾Ö°ÒµµÄ  | 
|     ItemKeyDropRateJobDict = ipyDrop.GetItemKeyDropRateJob() # {ÎïÆ·ID¼¯ºÏkey:¸ÅÂÊ, ...}£¬ Ö»µô±¾Ö°ÒµµÄ£¬ÓÅÏȼ¶¸ß  | 
|     if ItemKeyDropRateJobDict:  | 
|         for jobItemKey, dropRate in ItemKeyDropRateJobDict.items():  | 
|             if jobItemKey not in JobItemDropSets:  | 
|                 continue  | 
|             jobItemList = JobItemDropSets[jobItemKey]  | 
|             if len(jobItemList) < job:  | 
|                 GameWorld.ErrLog("Ö°ÒµÎïÆ·¼¯ºÏkeyûÓÐÅäÖöÔÓ¦Ö°ÒµID: npcID=%s,jobItemKey=%s,job=%s" % (npcID, jobItemKey, job))  | 
|                 continue  | 
|             mustDropCount = dropRate / Def_NPCMaxDropRate  | 
|             dropRate = dropRate % Def_NPCMaxDropRate # »ù´¡¸ÅÂÊ  | 
|             canDropCount = mustDropCount  | 
|             doCnt = ItemKeyMaxDropCountDict.get(jobItemKey, 1) # Ä¬ÈÏ1¸ö  | 
|             doCnt = __GetNPCDropDoCountChange(doCnt, doCountRate, doCountAdd)  | 
|             for _ in xrange(doCnt):  | 
|                 if not GameWorld.CanHappen(dropRate, maxRate=Def_NPCMaxDropRate):  | 
|                     continue  | 
|                 canDropCount += 1  | 
|                   | 
|             jobItemID = jobItemList[job - 1]  | 
|             for _ in xrange(canDropCount):  | 
|                 dropItemIDList.append(jobItemID)  | 
|                 #GameWorld.DebugLog("µôÂä×ÔÉíÖ°ÒµÖ¸¶¨ÎïÆ·ID: jobItemKey=%s,jobItemID=%s" % (jobItemKey, jobItemID))  | 
|                   | 
|     #     1.2 Ëæ»úµôÂäÒ»¸ö  | 
|     ItemKeyDropRateDict = ipyDrop.GetItemKeyDropRate() # {ÎïÆ·ID¼¯ºÏkey:¸ÅÂÊ, ...}£¬ Ëæ»úµôÒ»¸ö£¬ÓÅÏȼ¶µÍ  | 
|     if ItemKeyDropRateDict:  | 
|         for itemKey, dropRate in ItemKeyDropRateDict.items():  | 
|             # ÔÚÖ»µô±¾Ö°ÒµÀïµÄ²»´¦Àí  | 
|             if itemKey in ItemKeyDropRateJobDict:  | 
|                 continue  | 
|             mustDropCount = dropRate / Def_NPCMaxDropRate  | 
|             dropRate = dropRate % Def_NPCMaxDropRate # »ù´¡¸ÅÂÊ  | 
|             canDropCount = mustDropCount  | 
|             doCnt = ItemKeyMaxDropCountDict.get(itemKey, 1) # Ä¬ÈÏ1¸ö  | 
|             doCnt = __GetNPCDropDoCountChange(doCnt, doCountRate, doCountAdd)  | 
|             for _ in xrange(doCnt):  | 
|                 if not GameWorld.CanHappen(dropRate, maxRate=Def_NPCMaxDropRate):  | 
|                     continue  | 
|                 canDropCount += 1  | 
|                   | 
|             for _ in xrange(canDropCount):  | 
|                 if itemKey in itemDropRateSets:  | 
|                     randItemRateList = itemDropRateSets[itemKey]  | 
|                     randItemID = GameWorld.GetResultByRandomList(randItemRateList)  | 
|                     #GameWorld.DebugLog("µôÂä±ýͼÎïÆ·ID: itemKey=%s,randItemRateList=%s,randItemID=%s" % (itemKey, randItemRateList, randItemID))  | 
|                 elif itemKey in itemDropSets:  | 
|                     randItemList = itemDropSets[itemKey]  | 
|                     randItemID = random.choice(randItemList)  | 
|                     #GameWorld.DebugLog("µôÂäËæ»úÎïÆ·ID: itemKey=%s,randItemList=%s,randItemID=%s" % (itemKey, randItemList, randItemID))  | 
|                 else:  | 
|                     continue  | 
|                 if not randItemID:  | 
|                     continue  | 
|                 dropItemIDList.append(randItemID)  | 
|                 #GameWorld.DebugLog("µôÂäËæ»úÖ¸¶¨ÎïÆ·ID: itemKey=%s,randItemID=%s" % (itemKey, randItemID))  | 
|                   | 
|     # 2. Ö¸¶¨µôÂäID´¦Àí, ÊÜÈ«¾ÖÉ趨ӰÏì  | 
|     itemIDDropRateDict = ipyDrop.GetItemIDDropRate() # {ÎïÆ·ID:¸ÅÂÊ, ...}  | 
|     itemIDDropMaxCntDict = ipyDrop.GetItemIDMaxDropCount() # {ÎïÆ·ID:×î´óµôÂä¸öÊý,...}  | 
|       | 
|     # È«¾Ö²ÄÁϵôÂä¿ØÖÆ  | 
|     globalDropCDDict = IpyGameDataPY.GetFuncCfg("GlobalDropCD", 1) # {ÎïÆ·ID:·ÖÖÓ, ...}  | 
|     globalDropRateDict = IpyGameDataPY.GetFuncCfg("NPCGlobalDropRate", 1) # {ÎïÆ·ID:[[npcIDÁбí], "¸ÅÂʹ«Ê½"], ...}  | 
|     gw = GameWorld.GetGameWorld()  | 
|       | 
|     for itemID, dropRate in itemIDDropRateDict.items():  | 
|           | 
|         if not dropRate:  | 
|             continue  | 
|           | 
|         # ¸ù¾Ý»÷ɱ´ÎÊýÀ´µÄÁíÍâ¼ÆË㣬²»ÔÚ´ËÅÐ¶Ï  | 
|         if itemID in globalDropRateDict:  | 
|             continue  | 
|           | 
|         doCnt = itemIDDropMaxCntDict.get(itemID, 1) # Ä¬ÈÏ1¸ö  | 
|           | 
|         # ÅжÏÊÇ·ñÈ«¾ÖµôÂäCDÖÐ  | 
|         if itemID in globalDropCDDict:  | 
|             curTime = int(time.time())  | 
|             lastDropTime = gw.GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_LastDropTime % itemID)  | 
|             cdTime = globalDropCDDict[itemID] * 60  | 
|             remainTime = cdTime - (curTime - lastDropTime)  | 
|             if remainTime > 0:  | 
|                 GameWorld.DebugLog("¸ÃÎïÆ·È«¾ÖµôÂäCDÖУ¬²»µôÂ䣡itemID=%s,cdTime=%s,curTime=%s,lastDrop=%s,remainTime=%s"   | 
|                                    % (itemID, cdTime, curTime, lastDropTime, remainTime))  | 
|                 continue  | 
|         else:  | 
|             doCnt = __GetNPCDropDoCountChange(doCnt, doCountRate, doCountAdd)  | 
|               | 
|         #GameWorld.DebugLog("    Ö¸¶¨ÅжÏ: itemID=%s, dropRate=%s, doCnt=%s" % (itemID, dropRate, doCnt))  | 
|         for _ in xrange(doCnt):  | 
|             if not GameWorld.CanHappen(dropRate, maxRate=Def_NPCMaxDropRate):  | 
|                 continue  | 
|               | 
|             dropItemIDList.append(itemID)  | 
|             if itemID in globalDropCDDict:  | 
|                 # Í¨ÖªGameServer¼Ç¼  | 
|                 msgInfo = str([itemID, curTime])  | 
|                 GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "GlobalDropCD", msgInfo, len(msgInfo))  | 
|                 DataRecordPack.DR_GlobalDropCD(curPlayer, npcID, itemID)  | 
|                 break  | 
|               | 
|     # 3. Ö¸¶¨»÷ɱ´ÎÊýÈ«¾ÖµôÂÊ  | 
|     for itemID, dropInfo in globalDropRateDict.items():  | 
|         npcIDList, rateFormat = dropInfo  | 
|         if npcID not in npcIDList:  | 
|             continue  | 
|           | 
|         killedCnt = gw.GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_DropNPCKilledCnt % itemID)  | 
|         dropRate = eval(FormulaControl.GetCompileFormula("KilledCntDropRate_%s" % itemID, rateFormat))  | 
|         isDrop = GameWorld.CanHappen(dropRate, maxRate=Def_NPCMaxDropRate)  | 
|         if isDrop:  | 
|             dropItemIDList.append(itemID)  | 
|             DataRecordPack.DR_GlobalDropRate(curPlayer, npcID, itemID, killedCnt, dropRate)  | 
|               | 
|         # Í¨ÖªGameServer¼Ç¼  | 
|         updKilledCnt = 0 if isDrop else (killedCnt + 1)  | 
|         msgInfo = str([itemID, updKilledCnt])  | 
|         GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "GlobalDropRate", msgInfo, len(msgInfo))  | 
|            | 
|     # 4. Ö¸¶¨È«·þ»÷ɱ´ÎÊý±Øµô£¬Ëã¶îÍâµôÂä  | 
|     globalKillDropDict = IpyGameDataPY.GetFuncEvalCfg("GlobalDropCD", 2) # {NPCID:{»÷ɱ´ÎÊý:[ÊÇ·ñ±¾Ö°Òµ, {ÎïÆ·ID:¸öÊý, ...}, [[Ëæ»úÎïÆ·ID,¸öÊý], ...]]}, ...}  | 
|     if npcID in globalKillDropDict:  | 
|         killCountDropDict = globalKillDropDict[npcID]  | 
|         updNPCKilledCount = min(gw.GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_NPCKilledCount % npcID) + 1, ShareDefine.Def_UpperLimit_DWord)  | 
|         GameWorld.Log("¸üÐÂÈ«·þ»÷ɱ´ÎÊý£ºnpcID=%s, %s" % (npcID, updNPCKilledCount))  | 
|         # Í¨ÖªGameServer¼Ç¼  | 
|         msgInfo = str([npcID, updNPCKilledCount])  | 
|         GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "GlobalKillCount", msgInfo, len(msgInfo))  | 
|         if updNPCKilledCount in killCountDropDict:  | 
|             isJobLimit, itemIDCountDict, randItemIDCountList = killCountDropDict[updNPCKilledCount]  | 
|             for itemID, itemCount in itemIDCountDict.items():  | 
|                 if isJobLimit:  | 
|                     itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)  | 
|                     if not itemData:  | 
|                         continue  | 
|                     itemJob = itemData.GetJobLimit()  | 
|                     if itemJob and itemJob != curPlayer.GetJob():  | 
|                         # ·Ç±¾Ö°Òµ¿ÉÓ㬲»µôÂä  | 
|                         GameWorld.DebugLog("È«·þ»÷ɱ´ÎÊý±Øµô£¬·Ç±¾Ö°Òµ¿ÉÓ㬲»µôÂä! itemID=%s" % itemID)  | 
|                         continue  | 
|                 dropItemIDList += [itemID] * itemCount  | 
|                 GameWorld.Log("È«·þ»÷ɱ´ÎÊý±ØµôÎïÆ·: itemID=%s,itemCount=%s" % (itemID, itemCount))  | 
|             if randItemIDCountList:  | 
|                 if isJobLimit:  | 
|                     randJobItemList = []  | 
|                     for rItemID, rItemCount in randItemIDCountList:  | 
|                         itemData = GameWorld.GetGameData().GetItemByTypeID(rItemID)  | 
|                         if not itemData:  | 
|                             continue  | 
|                         itemJob = itemData.GetJobLimit()  | 
|                         if itemJob and itemJob != curPlayer.GetJob():  | 
|                             # ·Ç±¾Ö°Òµ¿ÉÓ㬲»µôÂä  | 
|                             GameWorld.DebugLog("È«·þ»÷ɱ´ÎÊý±ØµôËæ»ú£¬·Ç±¾Ö°Òµ¿ÉÓ㬲»µôÂä! rItemID=%s" % rItemID)  | 
|                             continue  | 
|                         randJobItemList.append([rItemID, rItemCount])  | 
|                     randItemID, randItemCount = random.choice(randJobItemList)  | 
|                 else:  | 
|                     randItemID, randItemCount = random.choice(randItemIDCountList)  | 
|                 dropItemIDList += [randItemID] * randItemCount  | 
|                 GameWorld.Log("È«·þ»÷ɱ´ÎÊý±ØµôËæ»úÎïÆ·: randItemID=%s,randItemCount=%s" % (randItemID, randItemCount))  | 
|                   | 
|     return dropItemIDList  | 
|   | 
| def __GetEquipIDList(findID, classLV, color, isSuit, placeList, itemJobList, findType="NPC"):  | 
|     #´æÒ»¸öÂú×ãÒªÇóµÄËùÓеÄÎïÆ·µÄÁбí È»ºó´Óµ±ÖÐËæ»úѡһ¸ö  | 
|     #×¢£º ½×¡¢ÑÕÉ«¡¢Ì××°ID¡¢Ö°Òµ¡¢²¿Î»£¬Õâ5¸öÌõ¼þ¿ÉÈ·ÈÏΨһһ¼þ×°±¸  | 
|     key = "%s_%s" % (classLV, color)  | 
|       | 
|     if key in PyGameData.g_filterEquipDict:  | 
|         filterItemIDDict = PyGameData.g_filterEquipDict[key]  | 
|     else:  | 
|         filterItemIDDict = {}  | 
|         gameData = GameWorld.GetGameData()  | 
|         for itemTypeList in ChConfig.Def_PlaceEquipType.values():  | 
|             for itemType in itemTypeList:  | 
|                 gameData.FilterItemByType(itemType)  | 
|                 for i in xrange(gameData.GetFilterItemCount()):  | 
|                     itemData = gameData.GetFilterItem(i)  | 
|                       | 
|                     # NPC²»µôÂäµÄ  | 
|                     if not itemData.GetCanNPCDrop():  | 
|                         continue  | 
|                       | 
|                     if ItemCommon.GetItemClassLV(itemData) != classLV:  | 
|                         continue  | 
|                     if itemData.GetItemColor() != color:  | 
|                         continue  | 
|                     suiteID = itemData.GetSuiteID()  | 
|                     itemJob = itemData.GetJobLimit()  | 
|                     itemPlace = itemData.GetEquipPlace()  | 
|                     itemID = itemData.GetItemTypeID()  | 
|                     if itemPlace not in filterItemIDDict:  | 
|                         filterItemIDDict[itemPlace] = []  | 
|                     placeItemList = filterItemIDDict[itemPlace]  | 
|                     placeItemList.append([itemJob, suiteID, itemID])  | 
|         PyGameData.g_filterEquipDict[key] = filterItemIDDict  | 
|         GameWorld.Log("»º´æ²ú³ö×°±¸ID: classLV_color=%s, %s, %s" % (key, filterItemIDDict, PyGameData.g_filterEquipDict))  | 
|           | 
|     itemIDList = []  | 
|     for itemPlace, placeItemList in filterItemIDDict.items():  | 
|         if placeList and itemPlace not in placeList:  | 
|             continue  | 
|         for itemInfo in placeItemList:  | 
|             itemJob, suiteID, itemID = itemInfo  | 
|             if itemJob and itemJobList and itemJob not in itemJobList:  | 
|                 continue  | 
|             curIsSuit = suiteID > 0  | 
|             if curIsSuit != isSuit:  | 
|                 continue  | 
|             itemIDList.append(itemID)  | 
|               | 
|     if not itemIDList:  | 
|         GameWorld.ErrLog("ÕÒ²»µ½¿É²ú³öµÄ×°±¸ID: %sID=%s,classLV=%s,color=%s,isSuit=%s,placeList=%s,itemJobList=%s"   | 
|                          % (findType, findID, classLV, color, isSuit, placeList, itemJobList))  | 
|     return itemIDList  | 
|   | 
| def __GetNPCPieRateEquipDrop(ipyDrop, doCnt, equipDropPlus):  | 
|     ## »ñÈ¡NPC±ýͼµôÂÊ×°±¸µôÂäÐÅÏ¢  | 
|     dropEquipInfoList = []  | 
|     pieRateDropList = ipyDrop.GetPieRateDrop()  # ±ýͼ¸ÅÂʵôÂäÐÅÏ¢ [(¸ÅÂÊ,0),(¸ÅÂÊ,(½×,ÑÕÉ«)),...]  | 
|     dropRateList = pieRateDropList if not equipDropPlus else GameWorld.GetPlusPieList(pieRateDropList, equipDropPlus)  | 
|     #GameWorld.DebugLog("µôÂä±ýͼ¸ÅÂÊ: %s, equipDropPlus=%s" % (pieRateDropList, equipDropPlus))  | 
|     #GameWorld.DebugLog("ʵ¼Ê±ýͼ¸ÅÂÊ: %s" % (dropRateList))  | 
|     for _ in xrange(doCnt):  | 
|         dropInfo = GameWorld.GetResultByRandomList(dropRateList)  | 
|         if dropInfo:  | 
|             dropEquipInfoList.append(dropInfo)  | 
|     #GameWorld.DebugLog("±ýͼװ±¸µôÂä½á¹û: doCnt=%s, %s" % (doCnt, dropEquipInfoList))  | 
|     return dropEquipInfoList  | 
|   | 
| def __GetNPCIndepRateEquipDrop(ipyDrop, doCnt, equipDropPlus, curGrade=0):  | 
|     ## »ñÈ¡NPC¶ÀÁ¢µôÂÊ×°±¸µôÂäÐÅÏ¢  | 
|     npcID = ipyDrop.GetNPCID()  | 
|     indepRateDict = ipyDrop.GetIndepRateDrop() # ¶ÀÁ¢¸ÅÂʵôÂäÐÅÏ¢ {(½×,ÑÕÉ«):¸ÅÂÊ,...}  | 
|     #GameWorld.DebugLog("¶ÀÁ¢¸ÅÂÊ×°±¸µôÂä´¦Àí: indepRateDict=%s,equipDropPlus=%s" % (indepRateDict, equipDropPlus))  | 
|     gradeColorRateDict = {}  | 
|     fbGradeColorRateDict = IpyGameDataPY.GetFuncEvalCfg("FBGradeEquipDropRate", 1) #{npcID:{ÑÕÉ«:[D¼¶Ó°Ïì¸ÅÂÊ, ..., S¼¶Ó°Ïì¸ÅÂÊ], ...}, ...}  | 
|     if npcID in fbGradeColorRateDict:  | 
|         gradeColorRateDict = fbGradeColorRateDict[npcID]  | 
|         curGrade = curGrade if curGrade else GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Def_FB_Grade)  | 
|           | 
|     #colorDropCntDict = {} # ×°±¸ÑÕÉ«ÒѾµôÂäÊý {ÑÕÉ«:ÊýÁ¿, ...}  | 
|     dropEquipInfoList = []  | 
|     for _ in xrange(doCnt):  | 
|         for dropInfo, rate in indepRateDict.iteritems():  | 
|             dropRate = rate  | 
|             color = dropInfo[1]  | 
|             if color in gradeColorRateDict:  | 
|                 colorRateList = gradeColorRateDict[color]  | 
|                 colorRate = 10000 if (curGrade <= 0 or curGrade > len(colorRateList)) else colorRateList[curGrade - 1]  | 
|                 dropRate = int(dropRate * colorRate / 10000.0)  | 
|                 #GameWorld.DebugLog("    ÆÀ¼¶Ó°ÏìÑÕÉ«¸ÅÂÊ: curGrade=%s,colorRate=%s,dropRate=%s" % (curGrade, colorRate, dropRate))  | 
|                   | 
|             dropRate = dropRate if not equipDropPlus else (dropRate + int(dropRate * equipDropPlus / 10000.0))  | 
|             mustDropCount = dropRate / Def_NPCMaxDropRate  | 
|             dropRate = dropRate % Def_NPCMaxDropRate # »ù´¡¸ÅÂÊ  | 
|             #GameWorld.DebugLog("    dropInfo=%s,rate=%s,mustDropCount=%s,dropRate=%s" % (dropInfo, rate, mustDropCount, dropRate))  | 
|             curDropCount = mustDropCount  | 
|             if GameWorld.CanHappen(dropRate, maxRate=Def_NPCMaxDropRate):  | 
|                 curDropCount += 1  | 
|             if not curDropCount:  | 
|                 continue  | 
|               | 
|             for _ in xrange(curDropCount):  | 
|                 dropEquipInfoList.append(dropInfo)  | 
|     #GameWorld.DebugLog("¶ÀÁ¢¸ÅÂÊ×°±¸µôÂä½á¹û: doCnt=%s, %s" % (doCnt, dropEquipInfoList))  | 
|     return dropEquipInfoList  | 
|   | 
| def __GetDropMoneyValue(curPlayer, ipyDrop):  | 
|     baseMoney = FBLogic.OnGetNPCDropMoney(curPlayer)  | 
|     if baseMoney <= 0:  | 
|         # »ñµÃµôÂäÊýÁ¿  | 
|         baseMoney = random.randint(ipyDrop.GetDropMoneyMin(), ipyDrop.GetDropMoneyMax())  | 
|       | 
|     if baseMoney <= 0:  | 
|         return 0  | 
|       | 
|     moneyValue = baseMoney  | 
|     # Íæ¼Ò½ðÇ®µôÂä¼Ó³É  | 
|     if curPlayer != None:  | 
|           | 
|         addRateEx = 0  | 
|               | 
|         addRate = float(curPlayer.GetGoldFoundRate() + addRateEx) / ShareDefine.Def_MaxRateValue  | 
|         moneyValue = int(moneyValue + moneyValue * addRate)  | 
|         #ÌØÊâµØÍ¼É±¹Ö½ð±ÒÍâ²ã¼Ó³É  | 
|         outerMoneyRate = FBLogic.OnGetOuterMoneyRate(curPlayer)  | 
|         if outerMoneyRate > 0:  | 
|             moneyValue = int(moneyValue * outerMoneyRate / float(ShareDefine.Def_MaxRateValue))  | 
|               | 
|     if moneyValue >= 65535:  | 
|         moneyValue = random.randint(65000, 65530)  | 
|     return moneyValue  | 
|   | 
| def GetKillCountDropItemList(curPlayer, npcID, needKillCount, killDropItemList):  | 
|     ## »ñÈ¡»÷ɱ´ÎÊý¶îÍâµôÂä  | 
|     killCountValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCKillCount % npcID)  | 
|     killCountPri = killCountValue / 10000  | 
|     if killCountPri >= needKillCount:  | 
|         #GameWorld.DebugLog("ɱµô´ÎÊýÒѾµôÂä¹ý! npcID=%s,killCountValue=%s,dropRecord=%s" % (npcID, killCountValue, dropRecord), curPlayer.GetPlayerID())  | 
|         return []  | 
|       | 
|     killCountPri += 1  | 
|     updRecordValue = killCountPri * 10000 + killCountValue % 10000  | 
|       | 
|     jobDropInfo = []  | 
|     if killCountPri >= needKillCount:  | 
|         isJobLimit = 1  | 
|         #[itemID,...]  | 
|         for dropItemID in killDropItemList:  | 
|             itemData = GameWorld.GetGameData().GetItemByTypeID(dropItemID)  | 
|             if not itemData:  | 
|                 GameWorld.ErrLog("µôÂäÎïÆ·ID²»´æÔÚ, dropItemID=%s" % dropItemID)  | 
|                 continue  | 
|             itemJob = itemData.GetJobLimit()  | 
|             if isJobLimit and itemJob and itemJob != curPlayer.GetJob():  | 
|                 # ·Ç±¾Ö°Òµ¿ÉÓ㬲»µôÂä  | 
|                 #GameWorld.DebugLog("·Ç±¾Ö°Òµ¿ÉÓ㬲»µôÂä! dropItemID=%s" % dropItemID)  | 
|                 continue  | 
|             jobDropInfo.append(dropItemID)  | 
|         GameWorld.DebugLog("»÷ɱ´ÎÊý±ØµôÂä! npcID=%s,needKillCount=%s,jobDropInfo=%s,killDropItemList=%s,updRecordValue=%s"   | 
|                            % (npcID, needKillCount, jobDropInfo, killDropItemList, updRecordValue), curPlayer.GetPlayerID())  | 
|                   | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_NPCKillCount % npcID, updRecordValue)  | 
|     GameWorld.DebugLog("¸üл÷ɱ´ÎÊý±ÈµôÂäÖµ: killCountValue=%s,killCountPri=%s,updRecordValue=%s" % (killCountValue, killCountPri, updRecordValue), curPlayer.GetPlayerID())  | 
|     return jobDropInfo  | 
| ######################################################################  | 
| #---------------------------------------------------------------------  | 
| #ÒÆ¶¯Ïà¹Ø  | 
| ##NPCÊÇ·ñµ½Òƶ¯Ê±¼ä  | 
| # @param minTime ×îСʱ¼ä  | 
| # @param maxTime ×î´óʱ¼ä  | 
| # @param curTick Ê±¼ä´Á  | 
| # @param lastActionTick ÉÏ´ÎÒÆ¶¯µÄʱ¼ä  | 
| # @return ·µ»ØÖµÕæ, ¿ÉÒÔÒÆ¶¯  | 
| # @remarks NPCÊÇ·ñµ½Òƶ¯Ê±¼ä  | 
| #def IsInActionTime(minTime, maxTime, curTick, lastActionTick):  | 
| def IsInActionTime(curTick, lastActionTick):  | 
|     #Ëæ»úÊÇΪÁËÈÃNPC µÚÒ»´Î½øÈëÊÓÒ°Ö®ºó£¬²»Í¬Ê±Òƶ¯£¬lastActionTickµ½ÕâÀïºÜÉÙΪ0  | 
|     curTime = random.randint(0, 16)  | 
|     if curTime < 12:  | 
|         return 0  | 
|       | 
|     if curTick - lastActionTick >= curTime * 1000 :  | 
|         return 1  | 
|       | 
|     return 0  | 
| #---------------------------------------------------------------------  | 
| ##ÅжÏÊÇ·ñΪÕÙ»½ÊÞ  | 
| # @param curNPC NPCʵÀý  | 
| # @return ·µ»ØÖµÕæ, ÊÇÕÙ»½ÊÞ  | 
| # @remarks ÅжÏÊÇ·ñΪÕÙ»½ÊÞ  | 
| def IsSummonNPC(curNPC):  | 
|     if (curNPC.GetGameNPCObjType() == IPY_GameWorld.gnotSummon):  | 
|         return  True  | 
|       | 
|     return False  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##Çå¿ÕÍæ¼ÒËùÓÐÕÙ»½Ê޵ijðºÞ  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks Çå¿ÕÍæ¼ÒËùÓÐÕÙ»½Ê޵ijðºÞ  | 
| def ClearSummonAngry_Player(curPlayer):  | 
|     for i in range(0, curPlayer.GetSummonCount()):  | 
|         summonNPC = curPlayer.GetSummonNPCAt(i)  | 
|         angry = summonNPC.GetNPCAngry()  | 
|         angry.Clear()  | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡ÕÙ»½ÊÞÓµÓÐÕßʵÀý  | 
| # @param summonNPC ÕÙ»½NPC  | 
| # @return ÓµÓÐÕßʵÀý»òNone  | 
| # @remarks »ñÈ¡ÕÙ»½ÊÞÓµÓÐÕßʵÀý  | 
| def GetSummonOwnerDetel(summonNPC):  | 
|     #»ñÈ¡¶ÔÏóObjÀà  | 
|     curSummonOwner = summonNPC.GetOwner()  | 
|       | 
|     if curSummonOwner == None:  | 
|         return  | 
|       | 
|     #»ñÈ¡¶ÔÏó×ÓÀà(ÈçNPC, Íæ¼Ò)  | 
|     return GameWorld.GetObjDetail(curSummonOwner)  | 
|   | 
|   | 
| ##»ñÈ¡NPCÖ÷ÈËÊÇ·ñÊÇÍæ¼Ò  | 
| # @param npcObj NPCʵÀý  | 
| # @return Ö÷ÈËÊÇ·ñÊÇÍæ¼Ò  | 
| def GetNpcObjOwnerIsPlayer(npcObj):  | 
|     ownerDetail = GetNpcObjOwnerDetail(npcObj)  | 
|       | 
|     if not ownerDetail:  | 
|         #ûÓÐÖ÷ÈË  | 
|         return False  | 
|       | 
|     if ownerDetail.GetGameObjType() != IPY_GameWorld.gotPlayer:  | 
|         #Ö÷È˲»ÊÇÍæ¼Ò  | 
|         return False  | 
|       | 
|     return True  | 
|   | 
|   | 
| ##»ñÈ¡NPCÖ÷ÈË£¨ÓÃÓÚÕÙ»½Ê޺ͳèÎ  | 
| # @param npcObj NPCʵÀý  | 
| # @return ÓµÓÐÕßʵÀý»òNone  | 
| def GetNpcObjOwnerDetail(npcObj):  | 
|     npcObjType = npcObj.GetGameNPCObjType()  | 
|       | 
|     ownerDetail = None  | 
|       | 
|     if npcObjType == IPY_GameWorld.gnotSummon:  | 
|         #²éÕÒÕÙ»½ÊÞÖ÷ÈË  | 
|         ownerDetail = GetSummonOwnerDetel(npcObj)  | 
|           | 
|     elif npcObjType == IPY_GameWorld.gnotPet:  | 
|         #²éÕÒ³èÎïÖ÷ÈË  | 
|         ownerDetail = PetControl.GetPetOwner(npcObj)    | 
|   | 
|     return ownerDetail  | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃÕÙ»½µÄÓµÓÐÕß  | 
| # @param curobjType ÓµÓÐÕßÀàÐÍ(Íæ¼Ò,NPC)  | 
| # @param curSummon ÕÙ»½ÊÞ  | 
| # @return ·µ»ØÖµ, ÕÙ»½ÊÞÓµÓÐÕß(ʵÀý)  | 
| # @remarks »ñµÃÕÙ»½µÄÓµÓÐÕß  | 
| def GetSummonNPCOwner(curobjType, curSummon):  | 
|     if curSummon == None:  | 
|         return  | 
|       | 
|     # ¿ÉÄÜÊÇIPY_GameWorld.gnotSummon µ«ÊÇ ·Ç IPY_SummonNPC ÊµÀý£¬ ÔÝʱÏÈ×ö¸ö·À·¶  | 
|     if not hasattr(curSummon, "GetOwner"):  | 
|         #GameWorld.DebugLog("ÊÇIPY_GameWorld.gnotSummon µ«ÊÇ ·Ç IPY_SummonNPC ÊµÀý£¬ ÔÝʱÏÈ×ö¸ö·À·¶")  | 
|         summonPlayerID = curSummon.GetDictByKey(ChConfig.Def_NPC_Dict_SummonMapNPCPlayerID)  | 
|         if summonPlayerID:  | 
|             return GameWorld.GetObj(summonPlayerID, IPY_GameWorld.gotPlayer)  | 
|         return  | 
|       | 
|     #»ñÈ¡¶ÔÏóObjÀà  | 
|     curSummonOwner = curSummon.GetOwner()  | 
|       | 
|     if curSummonOwner == None:  | 
|         return  | 
|       | 
|     #»ñÈ¡¶ÔÏó×ÓÀà(ÈçNPC, Íæ¼Ò)  | 
|     curSummonOwnerDetel = GameWorld.GetObj(curSummonOwner.GetID(), curobjType)  | 
|       | 
|     #ÈËÎïÐèÒªÅжÏÊÇ·ñΪ¿Õ  | 
|     if curSummonOwnerDetel != None and curobjType == IPY_GameWorld.gotPlayer and curSummonOwnerDetel.IsEmpty():  | 
|         return  | 
|       | 
|     return curSummonOwnerDetel  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃÖ¸¶¨Êý×鷶ΧÄÚÍæ¼ÒµÄÊýÁ¿  | 
| # @param curNPC NPCʵÀý  | 
| # @param matrix ÇøÓòÊý×é  | 
| # @return ·µ»ØÖµ, ÇøÓòÊý×éÄÚµÄÍæ¼ÒÊý  | 
| # @remarks »ñµÃÖ¸¶¨Êý×鷶ΧÄÚÍæ¼ÒµÄÊýÁ¿  | 
| def GetPlayerCountInSightByMatrix(curNPC, matrix):  | 
|     gameMap = GameWorld.GetMap()  | 
|     srcPosX = curNPC.GetPosX()  | 
|     srcPosY = curNPC.GetPosY()  | 
|     curPlayerCount = 0  | 
|       | 
|     for curPos in matrix:  | 
|         #¼ì²éÓÐûÓÐÍæ¼ÒÔÚÕâÒ»µãÉÏ  | 
|         mapObj = gameMap.GetPosObj(srcPosX + curPos[0], srcPosY + curPos[1])  | 
|           | 
|         if not mapObj:  | 
|             continue  | 
|           | 
|         #±éÀúµ±Ç°µã¶ÔÏó  | 
|         for i in range(0, mapObj.GetObjCount()):  | 
|             curObj = mapObj.GetObjByIndex(i)  | 
|               | 
|             if GameObj.GetHP(curObj) <= 0:  | 
|                 #¶ÔÏó²»´æÔÚ»òÕßÒѾËÀÍö  | 
|                 continue  | 
|               | 
|             if curObj.GetGameObjType() != IPY_GameWorld.gotPlayer :  | 
|                 continue  | 
|           | 
|             curPlayerCount += 1  | 
|       | 
|     return curPlayerCount  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃNPCÊÓÒ°ÖеÄÍæ¼ÒÁÐ±í  | 
| # @param curNPC NPCʵÀý  | 
| # @return ·µ»ØÖµ, Íæ¼ÒÁÐ±í  | 
| # @remarks »ñµÃNPCÊÓÒ°ÖеÄÍæ¼ÒÁÐ±í  | 
| def GetInSightPlayerList_NPC(curNPC):  | 
|     playList = []  | 
|     seeObjCount = curNPC.GetInSightObjCount()  | 
|     for i in range(0, seeObjCount):  | 
|         seeObj = curNPC.GetInSightObjByIndex(i)  | 
|           | 
|         #ÓпÉÄÜΪ¿Õ  | 
|         if seeObj == None :  | 
|             continue  | 
|           | 
|         #ÒþÉí  | 
|         if seeObj.GetVisible() == False:  | 
|             continue  | 
|           | 
|         seeObjType = seeObj.GetGameObjType()  | 
|           | 
|         #²»ÊÇÍæ¼Ò  | 
|         if seeObjType != IPY_GameWorld.gotPlayer :  | 
|             continue  | 
|           | 
|         if seeObj.IsEmpty():  | 
|             continue  | 
|           | 
|         #ÒѾËÀÍö  | 
|         if GameObj.GetHP(seeObj) <= 0 :  | 
|             continue  | 
|           | 
|         curTagPlayer = GameWorld.GetObj(seeObj.GetID(), seeObjType)  | 
|           | 
|         if not curTagPlayer:  | 
|             continue  | 
|           | 
|         playList.append(curTagPlayer)  | 
|   | 
|     return playList  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃÕÙ»½ÊÞÊÓÒ°ÖеÄÍæ¼ÒÁÐ±í  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param summonNPC ÕÙ»½NPCʵÀý  | 
| # @param checkTeam ÊÇ·ñ¼ì²éͬһ¶ÓÎé  | 
| # @return ·µ»ØÖµ, Íæ¼ÒÁÐ±í  | 
| # @remarks »ñµÃÕÙ»½ÊÞÊÓÒ°ÖеÄÍæ¼ÒÁÐ±í  | 
| def GetInSightPlayerList_SummonNPC(curPlayer, summonNPC, checkTeam):  | 
|     playList = []  | 
|     seePlayerCount = summonNPC.GetInSightObjCount()  | 
|     for i in range(0, seePlayerCount):  | 
|         seeObj = summonNPC.GetInSightObjByIndex(i)  | 
|           | 
|         #ÓпÉÄÜΪ¿Õ  | 
|         if seeObj == None :  | 
|             continue  | 
|           | 
|         if seeObj.GetVisible() == False:  | 
|             continue  | 
|           | 
|         seeObjType = seeObj.GetGameObjType()  | 
|           | 
|         #²»ÊÇÍæ¼Ò  | 
|         if seeObjType != IPY_GameWorld.gotPlayer :  | 
|             continue  | 
|           | 
|         if seeObj.IsEmpty():  | 
|             continue  | 
|           | 
|         #ÒѾËÀÍö  | 
|         if GameObj.GetHP(seeObj) <= 0 :  | 
|             continue  | 
|           | 
|         seeObjID = seeObj.GetID()  | 
|           | 
|         #ÊÇÖ÷ÈË  | 
|         if seeObjID == curPlayer.GetID():  | 
|             playList.append(curPlayer)  | 
|             continue  | 
|           | 
|         #ÊÇ·ñ¼ì²é×é¶Ó  | 
|         if not checkTeam :  | 
|             continue  | 
|           | 
|         #ÐèÒª¼ì²é×é¶Ó  | 
|         curPlayTeam = curPlayer.GetTeam()  | 
|         curTagPlayer = GameWorld.GetObj(seeObjID, seeObjType)  | 
|           | 
|         if not curTagPlayer:  | 
|             continue  | 
|           | 
|         curTagTeam = curTagPlayer.GetTeam()  | 
|           | 
|         if curPlayTeam == None or curTagTeam == None :  | 
|             continue  | 
|           | 
|         if curPlayTeam.GetTeamID() != curTagTeam.GetTeamID():  | 
|             continue  | 
|           | 
|         playList.append(curTagPlayer)  | 
|   | 
|     return playList  | 
|   | 
| ##¼ì²éNPCÊÓÒ°Äڿɹ¥»÷¶ÔÏóµÄÊýÁ¿£¨ÓÐÉÏÏÞÏÞÖÆ£©  | 
| # @param curNPC µ±Ç°NPC  | 
| # @param checkDist ¼ì²é¾àÀë  | 
| # @param checkCount ¼ì²éÊýÁ¿  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÌõ¼þÅжÏÊÇ·ñ³É¹¦  | 
| def CheckCanAttackTagLimitCountInSight_NPC(curNPC, checkDist, checkCount, tick):  | 
|     count = 0  | 
|     maxCount = 13    # ×î´óËÑË÷ÊýÁ¿  | 
|       | 
|     #Èç¹ûÁ½¸öÌõ¼þÓÐÒ»¸öΪ0 Ôò²»ÑéÖ¤  | 
|     if checkDist == 0 or checkCount == 0:  | 
|         return True  | 
|       | 
|     for i in range(0, curNPC.GetInSightObjCount()):  | 
|         seeObj = curNPC.GetInSightObjByIndex(i)  | 
|           | 
|         #ÓпÉÄÜΪ¿Õ  | 
|         if seeObj == None :  | 
|             continue  | 
|           | 
|         #ʬÌå²»Ìí¼Ó  | 
|         if GameObj.GetHP(seeObj) <= 0:  | 
|             continue  | 
|           | 
|         if not seeObj.GetVisible():  | 
|             continue  | 
|   | 
|         if GameWorld.IsSameObj(curNPC, seeObj):  | 
|             continue  | 
|           | 
|         tagDist = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), seeObj.GetPosX(), seeObj.GetPosY())  | 
|         #²»ÊÇÖ¸¶¨·¶Î§  | 
|         if tagDist > checkDist:  | 
|             continue  | 
|           | 
|         seeObjDetail = GameWorld.GetObj(seeObj.GetID(), seeObj.GetGameObjType())  | 
|         if seeObjDetail == None:  | 
|             GameWorld.Log("curNPC = %s ²éÕÒ¶ÔÏó, »ñµÃ¶ÔÏóʵÀýʧ°Ü" % (curNPC.GetNPCID()))  | 
|             continue  | 
|           | 
|         if not AttackCommon.CheckCanAttackTag(curNPC, seeObjDetail):  | 
|             continue  | 
|           | 
|         relation = BaseAttack.GetTagRelation(curNPC, seeObjDetail, None, tick)[0]  | 
|         if relation != ChConfig.Type_Relation_Enemy:  | 
|             continue  | 
|           | 
|           | 
|         #ÊýÁ¿¼Ó1£¬¼ì²éÊÇ·ñµ½´ï×î´óÊýÁ¿, ±ÜÃâÊýÁ¿¹ý¶àÎÞЧ±éÀú  | 
|         count += 1  | 
|         if count == maxCount or count >= checkCount:  | 
|             return True  | 
|   | 
|     return False  | 
| #---------------------------------------------------------------------  | 
| ##ÔÚNPC³ðºÞÁбíÖÐÌæ»»¶ÔÏó  | 
| # @param curNPC NPCʵÀý  | 
| # @param oldTag ³ðºÞÖоɵĶÔÏó  | 
| # @param newTag ³ðºÞÖÐÒªÌí¼ÓµÄжÔÏó  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks ÔÚNPC³ðºÞÁбíÖÐÌæ»»¶ÔÏó  | 
| #===============================================================================  | 
| # def ReplaceNPCAngryFromOldToNew(curNPC, oldTag, newTag):  | 
| #    #ÅжÏÊÇ·ñÔÚÊÓÒ°¾àÀëÄÚ  | 
| #    dist = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(),  | 
| #                                 newTag.GetPosX(), newTag.GetPosY())  | 
| #      | 
| #    if dist > ChConfig.Def_Screen_Area:  | 
| #        #GameWorld.Log("curNPC = %s , id = %s Ìæ»»³ðºÞ,ÒòжÔÏó²»ÔÚÆÁÄ»ÖÐ,ÎÞ·¨Ìæ»»"%(curNPC.GetName(),curNPC.GetID()))  | 
| #        return  | 
| #      | 
| #    tagID = oldTag.GetID()  | 
| #    tagType = oldTag.GetGameObjType()  | 
| #    newTagID = newTag.GetID()  | 
| #    newTagType = newTag.GetGameObjType()  | 
| #      | 
| #    npcAngry = curNPC.GetNPCAngry()  | 
| #      | 
| #    for i in range(0, npcAngry.GetAngryCount()):  | 
| #        curAngry = npcAngry.GetAngryValueTag(i)  | 
| #        angryObjID = curAngry.GetObjID()  | 
| #          | 
| #        if angryObjID == 0:  | 
| #            continue  | 
| #          | 
| #        angryObjType = curAngry.GetObjType()  | 
| #        angryObjValue = curAngry.GetAngryValue()  | 
| #          | 
| #        #ɾ³ý¾ÉµÄ³ðºÞ,Ìí¼ÓеijðºÞ  | 
| #        if angryObjID == tagID and angryObjType == tagType:  | 
| #            npcAngry.DeleteAngry(tagID, tagType)  | 
| #            npcAngry.AddAngry(newTagID, newTagType, angryObjValue)  | 
| #            #GameWorld.Log("Ìæ»»³ðºÞ³É¹¦ NPC = %s,¾É¶ÔÏó = %s,жÔÏó = %s"%(curNPC.GetID(),tagID,newTag.GetID()))  | 
| #            break  | 
| #      | 
| #    return True  | 
| #===============================================================================  | 
|   | 
| def GetDefaultMaxAngryNPCIDList():  | 
|     return GameLogic_FamilyInvade.GetDefaultMaxAngryNPCIDList()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##NPC½øÈëÕ½¶·×´Ì¬  | 
| # @param curNPC NPCʵÀý  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks NPC½øÈëÕ½¶·×´Ì¬  | 
| def SetNPCInBattleState(curNPC):  | 
|     if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie:  | 
|         return  | 
|       | 
|     #ÉèÖÃ  | 
|     if not curNPC.GetIsNeedProcess() :  | 
|         curNPC.SetIsNeedProcess(True)  | 
|       | 
|     #@Bug: ÕâÀï²»¿É±ä¸ü±»¹¥»÷NPC״̬Ϊ¹¥»÷, ÒòΪÕâ¸öʱºò, ÓпÉÄÜÕâ¸öNPCÔÚ×·»÷Ä¿±ê, ÖØÖÃ״̬ºó, ½«µ¼Ö¿¨×¡  | 
| #===============================================================================  | 
| #    if curNPC.GetCurAction() != IPY_GameWorld.laNPCAttack :  | 
| #        curNPC.SetCurAction(IPY_GameWorld.laNPCAttack)  | 
| #===============================================================================  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃNPCµÄ×î´ó¹¥»÷¾àÀë  | 
| # @param curNPC NPCʵÀý  | 
| # @return ·µ»ØÖµ, ×î´ó¹¥»÷¾àÀë  | 
| # @remarks »ñµÃNPCµÄ×î´ó¹¥»÷¾àÀë  | 
| def GetNPCMaxAtkDist(curNPC):  | 
|     distList = [ curNPC.GetAtkDist() ]  | 
|       | 
|     skillManager = curNPC.GetSkillManager()  | 
|       | 
|     for index in range(skillManager.GetSkillCount()):  | 
|         skill = skillManager.GetSkillByIndex(index)  | 
|           | 
|         if not skill:  | 
|             continue  | 
|           | 
|         distList.append(skill.GetAtkDist())  | 
|       | 
|     #»ñÈ¡ÆÕ¹¥ + ¼¼ÄÜÖÐ, ×îÔ¶µÄ¹¥»÷¾àÀë  | 
|     return max(distList)  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃNPCË¢ÐÂЧ¹û¼¼ÄܹÜÀíÆ÷  | 
| # @param curNPC NPCʵÀý  | 
| # @return ¼¼ÄܹÜÀíÆ÷Áбí[[BuffState, CanPileup], [BuffState, CanPileup]]  | 
| # @remarks »ñµÃNPCË¢ÐÂЧ¹û¼¼ÄܹÜÀíÆ÷  | 
| def GetNPCBuffRefreshList(curNPC, getActionBuff=False, getAuraBuff=True):  | 
|     #[[BuffState, CanPileup]]  | 
|     buffRefreshList = [  | 
|                        [curNPC.GetBuffState(), False], [curNPC.GetDeBuffState(), False],  | 
|                        [curNPC.GetProcessBuffState(), False], [curNPC.GetProcessDeBuffState(), False],  | 
|                        ]  | 
|       | 
|     if getAuraBuff:  | 
|         buffRefreshList.append([curNPC.GetAura(), False])  | 
|           | 
|     #³èÎï¶àÒ»¸ö±»¶¯¹ÜÀíÆ÷  | 
|     if curNPC.GetGameNPCObjType() == IPY_GameWorld.gnotPet:  | 
|         buffRefreshList.append([curNPC.GetPassiveBuf(), True])  | 
|       | 
|     #»ñµÃÊÇ·ñÌí¼ÓÐÐΪBUFF¹ÜÀíÆ÷  | 
|     if getActionBuff:  | 
|         buffRefreshList.append([curNPC.GetActionBuffManager(), False])  | 
|           | 
|     return buffRefreshList  | 
| #---------------------------------------------------------------------  | 
| ##NPCÇл»Òƶ¯×´Ì¬  | 
| # @param curNPC NPCʵÀý  | 
| # @param changMoveType Çл»µÄÒÆ¶¯ÀàÐÍ  | 
| # @param changeSuperSpeed ÊÇ·ñÇл»ÖÁ³¬¼¶Òƶ¯ËÙ¶È  | 
| # @return None  | 
| # @remarks NPCÇл»Òƶ¯×´Ì¬, mtRun, mtSlow  | 
| def ChangeNPCMoveType(curNPC, changMoveType, changeSuperSpeed=True):  | 
|     #²»Öظ´±ä¸ü״̬  | 
|     if curNPC.GetCurMoveType() == changMoveType:  | 
|         return  | 
|   | 
|     #NPCµ±Ç°Òƶ¯ËÙ¶È  | 
|     curNPCSpeed = curNPC.GetSpeed()  | 
|     #NPC»ù´¡Òƶ¯ËÙ¶È  | 
|     curNPCBaseSpeed = curNPC.GetOrgSpeed()  | 
|       | 
|     #Çл»µ½¿ìËÙÒÆ¶¯×´Ì¬  | 
|     if changMoveType == IPY_GameWorld.mtRun:  | 
|         curNPC.SetCurMoveType(changMoveType)  | 
|         #Çл»ÖÁ³¬¼¶Òƶ¯ËÙ¶È  | 
|         if curNPCSpeed != int(curNPCBaseSpeed / 2) and not curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SpeedPer):  | 
|             curNPC.SetSpeed(int(curNPCBaseSpeed / 2))  | 
|   | 
|         return  | 
|       | 
|     #Çл»ÂýËÙÒÆ¶¯×´Ì¬  | 
|     elif changMoveType == IPY_GameWorld.mtSlow:  | 
|         curNPC.SetCurMoveType(changMoveType)  | 
|         #Çл»ÂýËÙÒÆ¶¯  | 
|         if curNPCSpeed != curNPCBaseSpeed * 2 and not curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SpeedPer):  | 
|             curNPC.SetSpeed(curNPCBaseSpeed * 2)  | 
|           | 
|         return  | 
|     elif changMoveType == IPY_GameWorld.mtNormal:  | 
|         curNPC.SetCurMoveType(IPY_GameWorld.mtNormal)  | 
|         if not curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SpeedPer):  | 
|             curNPC.SetSpeed(curNPCBaseSpeed)  | 
|         return  | 
|   | 
|     #Ò쳣״̬²»´¦Àí  | 
|     GameWorld.ErrLog('ChangeNPCMoveType unKnowType = %s, curNPC = %s' % (changMoveType, curNPC.GetNPCID()))  | 
|     return  | 
|   | 
|   | 
| ## ÔÚµØÍ¼ÀïÕÙ»½NPC ¸ù¾ÝNPCID ³öÉúµã AIÀàÐÍ ºÍTICK  | 
| # @param npcId£º ÒªÕÙµÄNPCµÄNPCID  | 
| # @param rebornX£º ³öÉúµãX  | 
| # @param rebornY£º ³öÉúµãX  | 
| # @param aiType£º AIÀàÐÍ  | 
| # @return Èç¹ûÕÙ»½Ê§°Ü·µ»ØNone ·ñÔò·µ»ØÕÙ»½µÄNPCµÄʵÀý  | 
| # @remarks ÔÚµØÍ¼ÀïÕÙ»½NPC ¸ù¾ÝNPCID ³öÉúµã AIÀàÐÍ ºÍTICK  | 
| def SummonMapNpc(npcId, rebornX, rebornY, aiType=0, lastTime=0, playerID=0):  | 
|     curSummon = GameWorld.GetNPCManager().AddPlayerSummonNPC()  | 
|     if not curSummon:  | 
|         return  | 
|       | 
|     tick = GameWorld.GetGameWorld().GetTick()  | 
|     #---³õʼ»¯NPCÏà¹Ø ÉèNPCID ×î´ó³ðºÞÊý AIÀàÐÍ ³öÉúµã ³öÉúʱ¼ä---  | 
|     curSummon.SetNPCTypeID(npcId)  | 
|     curSummon.Reborn(rebornX, rebornY)  | 
|     curSummon.SetBornTime(tick)  | 
|     if aiType > 0:  | 
|         curSummon.SetAIType(aiType)  | 
|     InitNPC(curSummon)       | 
|   | 
|     if lastTime > 0:  | 
|         curSummon.SetLastTime(lastTime)  | 
|       | 
|     if playerID > 0:  | 
|         curSummon.SetDict(ChConfig.Def_NPC_Dict_SummonMapNPCPlayerID, playerID)  | 
|       | 
|     FBLogic.DoFBRebornSummonNPC(curSummon, tick)  | 
|     __NotifyMapPlayerSummonMapNPC(npcId, rebornX, rebornY)  | 
|     return curSummon  | 
|   | 
| ## Í¨ÖªµØÍ¼ÄÚÍæ¼Ò£¬µØÍ¼³öÏÖÕÙ»½NPC  | 
| # @param npcId£º NPCID  | 
| # @param rebornX£º ³öÉúµãX  | 
| # @param rebornY£º ³öÉúµãX  | 
| # @return None  | 
| def __NotifyMapPlayerSummonMapNPC(summonID, rebornPosX, rebornPosY):  | 
|     mapNPC = ChPyNetSendPack.tagMCSummonMapNPC()  | 
|     mapNPC.Clear()  | 
|     mapNPC.NPCID = summonID  | 
|     mapNPC.PosX = rebornPosX  | 
|     mapNPC.PosY = rebornPosY  | 
|       | 
|     playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for index in range(playerManager.GetPlayerCount()):  | 
|         curPlayer = playerManager.GetPlayerByIndex(index)  | 
|         if not curPlayer:  | 
|             continue  | 
|         NetPackCommon.SendFakePack(curPlayer, mapNPC)  | 
|           | 
|     return  | 
|   | 
| #// B4 0F »ØÊÕ˽ÓÐרÊôľ׮¹Ö #tagCMRecyclePriWoodPile  | 
| #  | 
| #struct    tagCMRecyclePriWoodPile  | 
| #{  | 
| #    tagHead        Head;  | 
| #    DWORD        ObjID;  | 
| #};  | 
| def OnRecyclePriWoodPile(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     objID = clientData.ObjID  | 
|     curNPC = GameWorld.FindNPCByID(objID)  | 
|     if not curNPC:  | 
|         return  | 
|     if curNPC.GetType() not in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]:  | 
|         return  | 
|     summonPlayerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_PriWoodPilePlayerID)  | 
|     if curPlayer.GetPlayerID() != summonPlayerID:  | 
|         #GameWorld.DebugLog("·ÇÍæ¼Ò˽ÓÐľ׮...")  | 
|         return  | 
|     SetDeadEx(curNPC)  | 
|     return  | 
|   | 
| #// B4 0C ÕÙ»½Ë½ÓÐרÊôľ׮¹Ö #tagCMSummonPriWoodPile  | 
| #  | 
| #struct    tagCMSummonPriWoodPile  | 
| #{  | 
| #    tagHead        Head;  | 
| #    DWORD        NPCID;  | 
| #    BYTE        Count;    //ĬÈÏ1¸ö£¬×î¶à5¸ö  | 
| #    DWORD        HP;    //ĬÈÏ0È¡×î´óÖµ£¬ÆäÖÐÒ»¸öѪÁ¿ÊýÖµ´óÓÚ0ÔòÓÃÖ¸¶¨ÑªÁ¿  | 
| #    DWORD        HPEx;    //ĬÈÏ0È¡×î´óÖµ£¬ÆäÖÐÒ»¸öѪÁ¿ÊýÖµ´óÓÚ0ÔòÓÃÖ¸¶¨ÑªÁ¿  | 
| #};  | 
| def OnSummonPriWoodPile(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     npcID = clientData.NPCID  | 
|     count = clientData.Count  | 
|     hp = clientData.HP  | 
|     hpEx = clientData.HPEx  | 
|     SummonPriWoodPile(curPlayer, npcID, count, hp, hpEx)  | 
|     return  | 
|   | 
| def SummonPriWoodPile(curPlayer, npcID, count, hp=0, hpEx=0):  | 
|     ''' ÕÙ»½Ë½ÓÐרÊôľ׮¹Ö  | 
|     '''  | 
|       | 
|     mapID = PlayerControl.GetCustomMapID(curPlayer)  | 
|     lineID = PlayerControl.GetCustomLineID(curPlayer)  | 
|     if mapID:  | 
|         if not FBLogic.OnCanSummonPriWoodPile(curPlayer, mapID, lineID, npcID, count):  | 
|             GameWorld.ErrLog("ÎÞ·¨ÕÙ»½Ä¾×®¹Ö!mapID=%s,lineID=%s,npcID=%s,count=%s" % (mapID, lineID, npcID, count))  | 
|             return  | 
|           | 
|     if count != 1:  | 
|         hp, hpEx = 0, 0 # Ö¸¶¨ÑªÁ¿µÄÔݽöÊÊÓÃÓÚµ¥Ö»µÄ  | 
|           | 
|     playerID = curPlayer.GetPlayerID()  | 
|     if playerID not in PyGameData.g_playerPriWoodPileNPCDict:  | 
|         PyGameData.g_playerPriWoodPileNPCDict[playerID] = []  | 
|     playerPriWoodNPCList = PyGameData.g_playerPriWoodPileNPCDict[playerID]  | 
|     maxCount = 3  | 
|     nowCount = len(playerPriWoodNPCList)  | 
|     summonCount = min(count, maxCount - nowCount)  | 
|     GameWorld.DebugLog("ÕÙ»½Ä¾×®: npcID=%s,count=%s,maxCount=%s,nowCount=%s,summonCount=%s,hp=%s,hpEx=%s"   | 
|                        % (npcID, count, maxCount, nowCount, summonCount, hp, hpEx))  | 
|     if summonCount <= 0:  | 
|         return  | 
|       | 
|     npcManager = GameWorld.GetNPCManager()  | 
|     for _ in xrange(summonCount):  | 
|         #summonNPC = curPlayer.SummonNewNPC()  | 
|         summonNPC = npcManager.AddPlayerSummonNPC()  | 
|           | 
|         #ÉèÖÃÕÙ»½ÊÞ»ù´¡ÐÅÏ¢  | 
|         summonNPC.SetNPCTypeID(npcID)  | 
|         summonNPC.SetSightLevel(curPlayer.GetSightLevel())  | 
|         #³õʼ»¯  | 
|         InitNPC(summonNPC)  | 
|           | 
|         #Íæ¼ÒÕÙ»½ÊÞÁбíÌí¼ÓÕÙ»½ÊÞ,ÕÙ»½ÊÞÌí¼ÓÖ÷ÈË  | 
|         #summonNPC.SetOwner(curPlayer)  | 
|         summonNPC.SetDict(ChConfig.Def_NPC_Dict_PriWoodPilePlayerID, playerID)  | 
|           | 
|         #½«ÕÙ»½ÊÞÕÙ»½³öÀ´  | 
|         #Íæ¼ÒÖÜÎ§Ëæ»ú³öÉúµã  | 
|         #¼¼ÄÜÕÙ»½×ø±ê ChConfig.Def_SummonAppearDist  | 
|         summonPos = GameMap.GetEmptyPlaceInArea(curPlayer.GetPosX(), curPlayer.GetPosY(), 3)  | 
|         summonNPC.Reborn(summonPos.GetPosX(), summonPos.GetPosY(), False)  | 
|         NPCControl(summonNPC).ResetNPC_Init(isReborn=True)  | 
|         if hp or hpEx:  | 
|             summonNPC.SetHP(hp)  | 
|             summonNPC.SetHPEx(hpEx)  | 
|         summonNPC.NotifyAppear() # ×îÖÕͳһ֪ͨNPC³öÏÖ  | 
|         playerPriWoodNPCList.append(summonNPC)  | 
|           | 
|     return  | 
|   | 
| def ClearPriWoodPile(curPlayer):  | 
|     ## Çå³ý˽ÓÐľ׮  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     if playerID not in PyGameData.g_playerPriWoodPileNPCDict:  | 
|         return  | 
|     playerPriWoodNPCList = PyGameData.g_playerPriWoodPileNPCDict.pop(playerID)  | 
|     for summonNPC in playerPriWoodNPCList:  | 
|         if not summonNPC:  | 
|             continue  | 
|         SetDeadEx(summonNPC)  | 
|     return  | 
|   | 
| ## ÉèÖÃnpcËÀÍö¼°×ÔÉí´¦Àí(Çë²»Òª½«ÓÎÏ·Âß¼¼ÓÔڴ˺¯ÊýÖÐ)  | 
| #  @param curNPC£ºnpcʵÀý  | 
| #  @return   | 
| def SetDeadEx(curNPC):  | 
|     summon_List = []  | 
|     npcid = curNPC.GetNPCID()  | 
|     #½«Éæ¼°µ½C++ÖÐÁбíɾ³ýµÄ¹¦ÄÜ,ͳһ¸Ä³É -> ¸´ÖÆPyÁбíºó,È»ºó½øÐÐɾ³ýÂß¼   | 
|     for index in range(curNPC.GetSummonCount()):  | 
|         curSummonNPC = curNPC.GetSummonNPCAt(index)  | 
|         summon_List.append(curSummonNPC)  | 
|       | 
|     for summonNPC in summon_List:         | 
|         # ÉèÖÃnpcËÀÍö¼°×ÔÉí´¦Àí  | 
|         SetDeadEx(summonNPC)  | 
|           | 
|     if curNPC.GetGameObjType() == IPY_GameWorld.gotNPC:  | 
|         FBLogic.DoFB_NPCDead(curNPC)  | 
|       | 
|     summonPlayerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SummonMapNPCPlayerID)  | 
|     if summonPlayerID > 0:  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_SummonMapNPCPlayerID, 0)  | 
|       | 
|     # °µ½ðboss  | 
|     if ChConfig.IsGameBoss(curNPC):   | 
|         # Í¨ÖªGameServer boss״̬ ·âħ̳ÔÚ¸±±¾Àïµ¥¶À´¦Àí  | 
|         ipyData = IpyGameDataPY.GetIpyGameDataNotLog('BOSSInfo', npcid)  | 
|         if ipyData and ipyData.GetMapID() not in [ChConfig.Def_FBMapID_SealDemon, ChConfig.Def_FBMapID_ZhuXianBoss]:  | 
|             GameServe_GameWorldBossState(npcid, 0)  | 
|             #GameWorld.GetGameWorld().SetGameWorldDict(ChConfig.Map_NPC_WorldBossDeadTick % npcid, GameWorld.GetGameWorld().GetTick())  | 
|             #ÒòΪ´æÔÚboss·ÖÁ÷£¬ËùÒÔÓÃgameFB×ֵ䣬µ«ÊÇ´æ»î״̬»¹ÊÇÓÃGameWorld×Öµä  | 
|             GameWorld.GetGameFB().SetGameFBDict(ChConfig.Map_NPC_WorldBossDeadTick % npcid, GameWorld.GetGameWorld().GetTick())  | 
|           | 
|             if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:  | 
|                 FamilyRobBoss.ClearFamilyOwnerBossHurt(curNPC)  | 
|         ChNPC.OnNPCSetDead(curNPC)  | 
|           | 
|       | 
|     # Çå³ý¶ÓÎé³ÉÔ±ÉËѪÁÐ±í  | 
|     AttackCommon.ClearTeamPlayerHurtValue(curNPC)  | 
|     # Çå³ý×Ô¶¨ÒåÉËѪÁÐ±í  | 
|     #BossHurtMng.ClearHurtValueList(curNPC)  | 
|     if curNPC.GetType() == ChConfig.ntRobot:  | 
|         lineID = GameWorld.GetGameWorld().GetLineID()  | 
|         lineRobotJobDict = PyGameData.g_fbRobotJobDict.get(lineID, {})  | 
|         lineRobotJobDict.pop(curNPC.GetID(), 0)  | 
|         PyGameData.g_fbRobotJobDict[lineID] = lineRobotJobDict  | 
|           | 
|     priWoodPilePlayerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_PriWoodPilePlayerID)  | 
|     if priWoodPilePlayerID > 0 and priWoodPilePlayerID in PyGameData.g_playerPriWoodPileNPCDict:  | 
|         priWoodPileNPCList = PyGameData.g_playerPriWoodPileNPCDict[priWoodPilePlayerID]  | 
|         for priWoodNPC in priWoodPileNPCList:  | 
|             if priWoodNPC and priWoodNPC.GetID() == curNPC.GetID():  | 
|                 priWoodPileNPCList.remove(priWoodNPC)  | 
|                 if not priWoodPileNPCList:  | 
|                     PyGameData.g_playerPriWoodPileNPCDict.pop(priWoodPilePlayerID)  | 
|                 break  | 
|               | 
|     # C++ÉèÖÃnpcËÀÍö  | 
|     curNPC.SetDead(curNPC.GetDictByKey(ChConfig.Def_NPCDead_Reason),  | 
|                    curNPC.GetDictByKey(ChConfig.Def_NPCDead_KillerType),  | 
|                    curNPC.GetDictByKey(ChConfig.Def_NPCDead_KillerID))  | 
|     return  | 
|   | 
| def GameServer_KillGameWorldBoss(bossID, killPlayerName, hurtValue, isNotify=True, killerIDList=[]):  | 
|     mapID = GameWorld.GetGameWorld().GetMapID()  | 
|     realMapID = GameWorld.GetGameWorld().GetRealMapID()  | 
|     copyMapID = GameWorld.GetGameWorld().GetCopyMapID()  | 
|     killMsg = str([bossID, killPlayerName, hurtValue, isNotify, mapID, realMapID, copyMapID, killerIDList])  | 
|     GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'KillGameWorldBoss', killMsg, len(killMsg))  | 
|     GameWorld.DebugLog("Boss±»»÷ɱ: bossID=%s,mapID=%s,realMapID=%s,copyMapID=%s,killerIDList=%s" % (bossID, mapID, realMapID, copyMapID, killerIDList))  | 
|     return  | 
|   | 
| def GameServe_GameWorldBossState(bossID, isAlive):  | 
|     mapID = GameWorld.GetGameWorld().GetMapID()  | 
|     realMapID = GameWorld.GetGameWorld().GetRealMapID()  | 
|     copyMapID = GameWorld.GetGameWorld().GetCopyMapID()  | 
|     stateMsg = str([bossID, isAlive, mapID, realMapID, copyMapID])  | 
|     GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GameWorldBossState', '%s' % stateMsg, len(stateMsg))  | 
|     GameWorld.DebugLog("Boss״̬±ä¸ü: bossID=%s,isAlive=%s,mapID=%s,realMapID=%s,copyMapID=%s"   | 
|                        % (bossID, isAlive, mapID, realMapID, copyMapID))  | 
|     if not isAlive:  | 
|         if mapID in ChConfig.Def_CrossZoneMapTableName:  | 
|             tableName = ChConfig.Def_CrossZoneMapTableName[mapID]  | 
|             realMapID = GameWorld.GetGameWorld().GetRealMapID()  | 
|             copyMapID = GameWorld.GetGameWorld().GetCopyMapID()  | 
|             zoneIpyData = IpyGameDataPY.GetIpyGameData(tableName, realMapID, mapID, copyMapID)  | 
|             if not zoneIpyData:  | 
|                 return  | 
|             zoneID = zoneIpyData.GetZoneID()  | 
|             GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID), 0)  | 
|         elif mapID in ChConfig.Def_CrossDynamicLineMap:  | 
|             zoneID = FBCommon.GetCrossDynamicLineMapZoneID()  | 
|             GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID), 0)  | 
|         else:  | 
|             GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % bossID, 0)  | 
|     return  | 
|   | 
| def OnPlayerKillBoss(curPlayer, npcID, mapID, isCrossServer):                  | 
|     killBossCntLimitDict = IpyGameDataPY.GetFuncCfg('KillBossCntLimit', 1)  | 
|     limitIndex = GameWorld.GetDictValueByKey(killBossCntLimitDict, npcID)  | 
|     if limitIndex != None:  | 
|         #½ñÈÕɱ¹Ö´ÎÊý+1  | 
|         key = ChConfig.Def_PDict_Boss_KillCnt % limitIndex  | 
|         newCnt = curPlayer.NomalDictGetProperty(key, 0) + 1  | 
|         PlayerControl.NomalDictSetProperty(curPlayer, key, newCnt)  | 
|         BossHurtMng.NotifyAttackBossCnt(curPlayer, limitIndex)  | 
|         GameWorld.DebugLog("½ñÈÕɱ¹Ö´ÎÊý  playerID=%s, newCnt=%s" % (curPlayer.GetPlayerID(), newCnt))  | 
|           | 
|         dataDict = {"objID":npcID, "bossID":npcID, "touchCnt":newCnt,  | 
|                     "AccID":curPlayer.GetAccID(), "PlayerID":curPlayer.GetPlayerID()}  | 
|         DataRecordPack.SendEventPack("AddKillBossCnt", dataDict, curPlayer)  | 
|         PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FeastRedPack_KillBoss, 1, [limitIndex])  | 
|           | 
|     if isCrossServer:  | 
|         return  | 
|       | 
|     if limitIndex == ShareDefine.Def_Boss_Func_World:  | 
|         # ÊÀ½çBOSS»÷ɱ³É¾Í  | 
|         PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillWorldBoss, 1)  | 
|         # Ã¿Èջ  | 
|         PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_WorldBOSS)  | 
|         PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_WorldBOSS, 1)  | 
|         PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_WorldBoss, 1)  | 
|         PlayerNewFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_WorldBoss, 1)  | 
|         PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_WorldBOSS, 1)  | 
|         PlayerActLogin.AddLoginAwardActionCnt(curPlayer, ChConfig.Def_LoginAct_WorldBOSS, 1)  | 
|           | 
|     if mapID == ChConfig.Def_FBMapID_BossHome:  | 
|         #BOSSÖ®¼Ò  | 
|         # BOSSÖ®¼ÒBOSS»÷ɱ³É¾Í  | 
|         PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillBossHomeBoss, 1)  | 
|         # Ã¿Èջ  | 
|         PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_BOSSHome)  | 
|         PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_BOSSHome, 1)  | 
|         PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_BossHome, 1)  | 
|         PlayerNewFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_BossHome, 1)  | 
|         PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_BOSSHome, 1)  | 
|     return  | 
|       | 
| #################################################  | 
| ## NPC¿ØÖƶ¨Òå  | 
| #  | 
| #  ¹ÜÀíNPCËÀÍö, Ë¢ÐµÈÐÅÏ¢  | 
| class NPCControl:  | 
|     __Instance = None  | 
|     #---------------------------------------------------------------------  | 
|     ## Àà³õʼ»¯  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param iNPC NPCʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Àà³õʼ»¯  | 
|     def __init__(self, iNPC):  | 
|         self.__Instance = iNPC  | 
|         self.__MaxHurtPlayer = None  # ×î´óÉËѪÕߣ¬¶ÓÎéÈ¡¶Ó³¤  | 
|         self.__LastHurtPlayer = None    # ×îºóÒ»»÷µÄÍæ¼Ò  | 
|         self.__Killer = None # »÷ɱÕß, Óɸ÷ÖÖ¹æÔòµÃ³ö, Ò»°ãÒ²ÊÇÎïÆ·¹éÊôµÄ´ú±í, ÓÃÓڹ㲥¡¢¼Ç¼µÈÈ·±£Óë¹éÊôÒ»Ö  | 
|         self.__AllKillerDict = {} # ËùÓл÷ɱµÄÍæ¼ÒID¶ÔÓ¦×Öµä, ·Ç¶ÓÎé, Ò»°ãÒ²ÊǹéÊôµÄÓµÓÐÕß  | 
|         self.__FeelPlayerList = [] # ËùÓÐÃþ¹ÖÍæ¼ÒÁÐ±í£¬´¦ÀíÈÎÎñ¼°Ä³Ð©Âß¼Óà  | 
|         self.__ownerPlayerList = [] # ¹éÊôÕßÁÐ±í  | 
|           | 
|         self.__OwnerHurtType = 0  | 
|         self.__OwnerHurtID = 0  | 
|         return  | 
|     #---------------------------------------------------------------------  | 
|     ## Òƶ¯µ½Ä³Ò»¸öµãµÄ¸½½üµã  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param destX Ä¿±ê×ø±êY  | 
|     #  @param destY Ä¿±ê×ø±êX  | 
|     #  @param dist ¾àÀë  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Òƶ¯µ½Ä³Ò»¸öµãµÄ¸½½üµã  | 
|     def GetMoveNearPos(self, destX, destY, dist, fixPos=True):  | 
|         curNPC = self.__Instance  | 
|         posX = curNPC.GetPosX()  | 
|         posY = curNPC.GetPosY()  | 
|         #ÅжÏÄ¿±êÔÚµÚ¼¸ÏóÏÞ  | 
|         dirX = posX - destX  | 
|         dirY = posY - destY  | 
|         #·ûºÅ * size  | 
|         if abs(dirX) > dist:  | 
|             dirX = dirX / abs(dirX) * dist  | 
|         if abs(dirY) > dist:  | 
|             dirY = dirY / abs(dirY) * dist  | 
|   | 
|         moveDestX = destX + dirX  | 
|         moveDestY = destY + dirY    | 
|         gameMap = GameWorld.GetMap()  | 
|         if not gameMap.CanMove(moveDestX, moveDestY) and fixPos:  | 
|             #Õâ¸öλÖò»¿É×ß, ¿ªÊ¼Ëæ»úÕÒµ½¿É×ßµã, ×ß¹ýÈ¥  | 
|             resultPos = GameMap.GetEmptyPlaceInArea(destX, destY, dist)  | 
|             moveDestX = resultPos.GetPosX()  | 
|             moveDestY = resultPos.GetPosY()  | 
|           | 
|         return moveDestX, moveDestY  | 
|       | 
|     # ¸ù¾ÝÁ½ÕßÖ®¼äÒ»ÌõÏßÉϵÄ×ø±ê  | 
|     def GetMoveNearPosEx(self, playerX, playerY, dist, fixPos=True):  | 
|         curNPC = self.__Instance  | 
|         posX = curNPC.GetPosX()  | 
|         posY = curNPC.GetPosY()  | 
|         moveDestX, moveDestY = GameWorld.PosInLineByDist(dist, playerX, playerY, posX, posY)  | 
|         gameMap = GameWorld.GetMap()  | 
|         if not gameMap.CanMove(moveDestX, moveDestY) and fixPos:  | 
|             #Õâ¸öλÖò»¿É×ß, ¿ªÊ¼Ëæ»úÕÒµ½¿É×ßµã, ×ß¹ýÈ¥  | 
|             resultPos = GameMap.GetEmptyPlaceInArea(moveDestX, moveDestY, 2)  | 
|             moveDestX = resultPos.GetPosX()  | 
|             moveDestY = resultPos.GetPosY()  | 
|           | 
|         return moveDestX, moveDestY  | 
|     #---------------------------------------------------------------------  | 
|     ## Òƶ¯µ½Ò»¸ö¶ÔÏó  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param objID Ä¿±ê¶ÔÏóID  | 
|     #  @param objType Ä¿±ê¶ÔÏóÀàÐÍ  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Òƶ¯µ½Ò»¸ö¶ÔÏó  | 
|     def MoveToObj(self, objID, objType):  | 
|         curNPC = self.__Instance  | 
|         #ÕÒµ½Íæ¼Ò¶ÔÏó  | 
|         tagObjDetel = GameWorld.GetObj(objID, objType)  | 
|         if not tagObjDetel:  | 
|             GameWorld.Log("NPCÒÆ¶¯µ½Ä¿±êʧ°Ü,NPCID = %s Ä¿±êID=%d,Type=%d" % (curNPC.GetName(), objID, objType))  | 
|             return  | 
|           | 
|         return self.MoveToObj_Detel(tagObjDetel)  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## Òƶ¯µ½Ò»¸öµØÖ· Ò»´ÎÖ»ÒÆ¶¯ sigleMoveDis¾àÀë  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param destPosX Ä¿±êµØµãX  | 
|     #  @param destPosY Ä¿±êµØµãY  | 
|     #  @param sigleMoveDis µ¥´ÎÒÆ¶¯¾àÀë  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Òƶ¯µ½Ò»¸ö¶ÔÏó      | 
|     def MoveToPosStepByStep(self, destPosX, destPosY, sigleMoveDis=4):  | 
|         curNPC = self.__Instance  | 
|         curPosX, curPosY = curNPC.GetPosX(), curNPC.GetPosY()  | 
|         curDis = GameWorld.GetDist(curPosX, curPosY, destPosX, destPosY)  | 
|         if curDis > sigleMoveDis and curDis > 0:  | 
|             destPosX = curPosX + (destPosX - curPosX) * sigleMoveDis / curDis  | 
|             destPosY = curPosY + (destPosY - curPosY) * sigleMoveDis / curDis  | 
|         curNPC.Move(destPosX, destPosY)  | 
|           | 
|     #---------------------------------------------------------------------  | 
|     ## Òƶ¯µ½Ò»¸ö¶ÔÏó  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tagObjDetel Ä¿±êʵÀý  | 
|     #  @param moveAreaDist Òƶ¯ÇøÓò¾àÀë  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Òƶ¯µ½Ò»¸ö¶ÔÏó  | 
|     def MoveToObj_Detel(self, tagObjDetel, moveAreaDist=0):  | 
|         curNPC = self.__Instance  | 
|           | 
|         #²»¿ÉÒÆ¶¯ÐÐΪ״̬, ·þÎñ¶ËÏÞÖÆ  | 
|         if not OperControlManager.IsObjCanDoAction(curNPC,  | 
|                                                    ChConfig.Def_Obj_ActState_ServerAct,  | 
|                                                    IPY_GameWorld.oalMove):  | 
|             return    | 
|           | 
|         posX = curNPC.GetPosX()  | 
|         posY = curNPC.GetPosY()  | 
|         destX = tagObjDetel.GetPosX()  | 
|         destY = tagObjDetel.GetPosY()  | 
|           | 
|         #×î½üµÄÒÆ¶¯ÇøÓò¾àÀë, ÈçûÓÐÖ¸¶¨, °´ÕÕ¹¥»÷¾àÀëÀ´²éÕÒ, Ô¶¹¥µÄ¹ÖÎï¾Í¿ÉÒÔÖ±½Óµ½Éä³Ì¹¥»÷  | 
|         if moveAreaDist == 0:  | 
|             # ËõСÁ½¸ñ×ÓÓÃÓÚǰ·½Ò»Ð¡Æ¬ÇøÓò  | 
|             moveAreaDist = max(curNPC.GetAtkDist()-1 , 1)  | 
|           | 
|         #¼ì²éÊÇ·ñ³¬³ö»î¶¯·¶Î§  | 
|         if curNPC.GetRefreshPosCount() > 0:  | 
|             curRefreshPos = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|             moveDist = GameWorld.GetDist(posX, posY, curRefreshPos.GetPosX(), curRefreshPos.GetPosY())  | 
|             if curRefreshPos.GetMoveDist() != 0 and moveDist > curRefreshPos.GetMoveDist():  | 
|                 #Èç¹ûNPC³¬¹ý×Ô¼ºµÄÒÆ¶¯·¶Î§, ¾Í×Ô¶¯·µ»Ø  | 
|                 self.MoveBack()  | 
|                 return  | 
|           | 
|         #С¹Ö²»¿ÉÐнøÍ¨µÀ²»×·»÷  | 
|         #=======================================================================  | 
|         # if not AttackCommon.CanAttackByPath(curNPC, tagObjDetel):  | 
|         #    #GameWorld.DebugLog("С¹Ö²»¿ÉÐнøÍ¨µÀ²»×·»÷")  | 
|         #    tick = GameWorld.GetGameWorld().GetTick()  | 
|         #    AICommon.NormalNPCFree_Move(curNPC , tick)  | 
|         #    return  | 
|         #=======================================================================  | 
|           | 
|         # ËõСÁ½¸ñ×ÓÓÃÓÚǰ·½Ò»Ð¡Æ¬ÇøÓò  | 
|         moveDestX, moveDestY = self.GetMoveNearPosEx(destX, destY, moveAreaDist)  | 
|         resultPos = GameMap.GetEmptyPlaceInArea(moveDestX, moveDestY, 1)  | 
|         moveDestX = resultPos.GetPosX()  | 
|         moveDestY = resultPos.GetPosY()  | 
|           | 
|         if curNPC.GetCurAction() == IPY_GameWorld.laNPCMove and \  | 
|         (GameWorld.GetGameWorld().GetTick() - curNPC.GetActionTick()) < 800:  | 
|             # .Move( ½Ó¿Úµ÷ÓÃÌ«¿ì»áµ¼ÖÂÒÆ¶¯Ê±¼ä²»¹»³¤(²»×ãÒ»¸ñ)µ¼ÖÂÎÞ·¨Òƶ¯ »òÕßÒÆ¶¯¹ýÂýÎÊÌâ  | 
|             # SetDestPos µ÷ÓûᵼÖ·´ÏòÒÆ¶¯Æ«¿ì  | 
|             curNPC.SetDestPos(moveDestX, moveDestY)  | 
|             return  | 
|         #=======================================================================  | 
|         # if curNPC.GetIsBoss() <= 1:  | 
|         #    # Ð¡¹Ö±È½Ï¶à£¬ ±ÜÃâµÚÒ»´Î×·»÷¾Íվͬһ¸öµã, µÚÒ»ÏóÏÞÖ±Ïß¾àÀë×·»÷£¬ÆäËûÏóÏÞ¾¡Á¿¿¿½üÄ¿±ê  | 
|         #    if moveAreaDist > 6 or random.randint(0, 3) == 1:  | 
|         #        moveDestX, moveDestY = self.GetMoveNearPosEx(destX, destY, moveAreaDist, False)  | 
|         #    else:  | 
|         #        resultPos = GameMap.GetEmptyPlaceInSurround(destX, destY, 3)  | 
|         #        moveDestX = resultPos.GetPosX()  | 
|         #        moveDestY = resultPos.GetPosY()  | 
|         # else:  | 
|         #    moveDestX, moveDestY = self.GetMoveNearPosEx(destX, destY, moveAreaDist)  | 
|         #=======================================================================  | 
|         ChangeNPCMoveType(curNPC, IPY_GameWorld.mtNormal)  | 
|   | 
|         return curNPC.Move(moveDestX, moveDestY)  | 
|   | 
|     #---------------------------------------------------------------------  | 
|     ## ÐÞÕý×ø±ê  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param posX Ä¿±ê×ø±êX  | 
|     #  @param posY Ä¿±ê×ø±êY  | 
|     #  @param fixAreaDist ½ÃÕýÇøÓò¾àÀë  | 
|     #  @return ·µ»ØÖµÕæ, ÐÞÕý³É¹¦  | 
|     #  @remarks ÐÞÕý×ø±ê  | 
|     def FixTagPos(self, posX, posY, fixAreaDist=0):  | 
|         curNPC = self.__Instance  | 
|         #²»¿ÉÒÆ¶¯ÐÐΪ״̬, ·þÎñ¶ËÏÞÖÆ  | 
|         if not OperControlManager.IsObjCanDoAction(curNPC,  | 
|                                                    ChConfig.Def_Obj_ActState_ServerAct,  | 
|                                                    IPY_GameWorld.oalMove):  | 
|             return    | 
|           | 
|         gameMap = GameWorld.GetMap()  | 
|         npcPosX = curNPC.GetPosX()  | 
|         npcPosY = curNPC.GetPosY()  | 
|         mapObj = gameMap.GetPosObj(npcPosX, npcPosY)  | 
|           | 
|         #---Õâ¸öλÖÿÉÒÔÕ¾Á¢---  | 
|         if not mapObj:  | 
|             return False  | 
|           | 
|         if mapObj.GetObjCount() <= 1:  | 
|             return False  | 
|           | 
|         #±éÀúµ±Ç°µã¶ÔÏó  | 
|         for i in xrange(mapObj.GetObjCount()):  | 
|             curObj = mapObj.GetObjByIndex(i)  | 
|             curObjType = curObj.GetGameObjType()  | 
|             if curObjType != IPY_GameWorld.gotNPC:  | 
|                 continue  | 
|             curTag = GameWorld.GetObj(curObj.GetID(), curObjType)  | 
|             if not curTag:  | 
|                 continue  | 
|             if curTag.GetGameNPCObjType() == IPY_GameWorld.gnotSummon and curTag.GetOwner() and curTag.GetID() != curNPC.GetID():  | 
|                 #Èç¹¥»÷ÀàÕÙ»½ÊÞ±©·çÑ©µÈ£¬·ÀÖ¹NPCÒÆ¶¯ºóµ¼ÖÂÕÙ»½ÊÞ¹¥»÷²»µ½NPC£¬Èç¹ûÐèÒªÉ趨NPC¸ü´ÏÃ÷£¬¿É¿ª³öÊÇ·ñ¶ã±ÜÕÙ»½ÊÞ¹¥»÷É趨  | 
|                 #GameWorld.DebugLog("    µ±Ç°µã´æÔÚÕÙ»½ÊÞ£¬²»ÐÞÕý×ø±ê!i=%s,%s" % (i, curTag.GetName()))  | 
|                 return False  | 
|               | 
|         #ÓëÄ¿±êͬһλÖò»ÐÞÕý×ø±ê(ÈçÐý·çÕ¶ÒýÆðµÄÖØµþ)  | 
|         if npcPosX == posX and npcPosX == posY:  | 
|             return False  | 
|           | 
|         #--Õâ¸öλÖò»¿ÉÕ¾Á¢---  | 
|         if fixAreaDist == 0:  | 
|             #ĬÈϼì²â¾àÀëΪNPCµÄ¹¥»÷¾àÀë  | 
|             fixAreaDist = min(curNPC.GetAtkDist(), 2)  | 
|           | 
|         resultPos = GameMap.GetEmptyPlaceInArea(npcPosX, npcPosY, fixAreaDist)  | 
|         moveDestX = resultPos.GetPosX()  | 
|         moveDestY = resultPos.GetPosY()  | 
|           | 
|         if moveDestX != npcPosX or moveDestY != npcPosY:  | 
|             #Çл»ÖÁ¿ìËÙÒÆ¶¯×´Ì¬  | 
|             #ChangeNPCMoveType(curNPC, IPY_GameWorld.mtRun)  | 
|             #NPC¿ªÊ¼Òƶ¯  | 
|             curNPC.Move(moveDestX, moveDestY)  | 
|             return True  | 
|           | 
|         return False  | 
|     #---------------------------------------------------------------------  | 
|     ## È¡µÃ¶ÔÏó¾àÀë  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tagID ¶ÔÏóID  | 
|     #  @param tagType ¶ÔÏóÀàÐÍ  | 
|     #  @return ·µ»ØÖµ, ºÍ¶ÔÏó¼äµÄ¾àÀë  | 
|     #  @remarks È¡µÃ¶ÔÏó¾àÀë  | 
|     def GetTagDist(self, tagID, tagType):  | 
|         curNPC = self.__Instance  | 
|         posX = curNPC.GetPosX()  | 
|         posY = curNPC.GetPosY()  | 
|         tagObj = GameWorld.GetObj(tagID, tagType)  | 
|         if tagObj == None:  | 
|             return ChConfig.Def_NPCErrorMaxDist;  | 
|   | 
|         if tagObj.GetID() == 0:  | 
|             return ChConfig.Def_NPCErrorMaxDist;  | 
|   | 
|         return GameWorld.GetDist(posX, posY, tagObj.GetPosX(), tagObj.GetPosY())  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ##¼ì²éÌí¼Ó³ðºÞÁÐ±í  | 
|     # @param self ÀàʵÀý  | 
|     # @param seeObj ÊÓÒ°ÖеĶÔÏó  | 
|     # @param tick Ê±¼ä´Á  | 
|     # @return ·µ»ØÖµÕæ, ¿ÉÒÔÌí¼ÓÕâ¸ö¶ÔÏó  | 
|     # @remarks ¼ì²éÌí¼Ó³ðºÞÁÐ±í  | 
|     def __CheckAddToAngryList(self, seeObj, tick):  | 
|         curNPC = self.__Instance  | 
|         seeObjType = seeObj.GetGameObjType()  | 
|           | 
|         if seeObjType == IPY_GameWorld.gotItem:  | 
|             #²»´¦Àí¿´µ½µÄÎïÆ·  | 
|             return False  | 
|           | 
|         #״̬¼ì²é  | 
|         if GameWorld.IsSameObj(curNPC, seeObj):  | 
|             #²»Ìí¼Ó×Ô¼ºµ½³ðºÞ¶È  | 
|             return False  | 
|           | 
|         seeObjID = seeObj.GetID()  | 
|           | 
|         npcAngry = curNPC.GetNPCAngry()  | 
|         angryValue = npcAngry.FindNPCAngry(seeObjID, seeObjType)  | 
|           | 
|         if angryValue != None and angryValue.GetAngryValue() != 0 :  | 
|             #¸Ã¶ÔÏóÒѾÔÚ³ðºÞÁбíÖÐ,²»Öظ´Ìí¼Ó  | 
|             return False  | 
|           | 
|         seeObjDetail = GameWorld.GetObj(seeObjID, seeObjType)  | 
|           | 
|         if seeObjDetail == None:  | 
|             GameWorld.Log("curNPC = %s ²éÕÒ¶ÔÏó, »ñµÃ¶ÔÏóʵÀýʧ°Ü" % (curNPC.GetNPCID()))  | 
|             return False  | 
|           | 
|         #ÊØÎÀ¹¥»÷ïÚ³µ,³ðºÞÌØÊâ´¦Àí  | 
|         if self.__GuaedAttackTruck(seeObjDetail , tick):  | 
|             return True  | 
|           | 
|         #С¹Ö²»¿ÉÐнøÍ¨µÀ¾Íµ±×÷¿´²»¼û  | 
|         if not AttackCommon.CanAttackByPath(curNPC, seeObjDetail):  | 
|             #GameWorld.DebugLog("ÓÐÕϰ  ¿´¼ûÒ²²»¼Ó³ðºÞ")  | 
|             return False  | 
|           | 
|         #ÕâÀï²»Äܵ÷ÓÃBaseAttack.GetCanAttack,ÒòΪÄÇÀïÓÐÅжϹ¥»÷¾àÀë  | 
|         #GetCanAttack Èç¹ûÓÃÓÚ¼¼ÄÜÉè¼ÆÔò»áÓ°Ïì³ðºÞ  | 
|         if not AttackCommon.CheckCanAttackTag(curNPC, seeObjDetail):  | 
|             return False  | 
|           | 
|         relation = BaseAttack.GetTagRelation(curNPC, seeObjDetail, None, tick)[0]  | 
|           | 
|         if relation != ChConfig.Type_Relation_Enemy:  | 
|             #GameWorld.Log("%sÌí¼Ó³ðºÞ%sʧ°Ü"%(curNPC.GetName(), seeObjDetail.GetName()))  | 
|             return False  | 
|           | 
|         #GameWorld.Log("%sÌí¼Ó³ðºÞ%s³É¹¦"%(curNPC.GetName(), seeObjDetail.GetName()))  | 
|         return True  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ##ÊØÎÀ¹¥»÷ïÚ³µ,ÌØÊâ´¦Àí  | 
|     # @param self ÀàʵÀý  | 
|     # @param seeObj ÊÓÒ°ÖеĶÔÏó  | 
|     # @param tick Ê±¼ä´Á  | 
|     # @return ·µ»ØÖµÕæ, ¿ÉÒÔÌí¼ÓÕâ¸ö¶ÔÏó  | 
|     # @remarks ÊØÎÀ¹¥»÷ïÚ³µ,ÌØÊâ´¦Àí  | 
|     def __GuaedAttackTruck(self, seeObj, tick) :  | 
|         curNPC = self.__Instance  | 
|           | 
|         if curNPC.GetType() != IPY_GameWorld.ntGuard:  | 
|             return  | 
|           | 
|         if seeObj.GetGameObjType() != IPY_GameWorld.gotNPC or \  | 
|             seeObj.GetGameNPCObjType() != IPY_GameWorld.gnotTruck :  | 
|             return  | 
|           | 
|         #Èç¹ûÊÇÔ¶³ÌµÄÊØÎÀ,²»¿¼Âǹ¥»÷¾àÀë,×·»÷  | 
|         #²»¿ÉÒÆ¶¯µÄ¹Ì¶¨ÊØÎÀ,³¬³ö¹¥»÷¾àÀë,·µ»Ø  | 
|         if curNPC.GetSpeed() == 0 and not BaseAttack.GetCanAttack(curNPC, seeObj, None, tick):  | 
|             return  | 
|           | 
|         relation = BaseAttack.GetTagRelation(curNPC, seeObj, None, tick)[0]  | 
|           | 
|         if relation != ChConfig.Type_Relation_Enemy :  | 
|             return  | 
|           | 
|         return True  | 
|       | 
|   | 
|   | 
|     def GetIsBossView(self):  | 
|         # Ö÷¶¯ÊÓÒ°Çé¿ö£¬GetIsBoss 0 1 4 ÎªÆÕͨNPCÊÓÒ°£¨ÓÐÊÓÒ°·¶Î§ÅäÖ㬵«È¥³ýÊÓҰˢУ©£¬ÆäËûΪBOSSÀàÊÓÒ°ÓÐˢР | 
|         curNPC = self.__Instance  | 
|         if not ChConfig.IsGameBoss(curNPC) and not GetFaction(curNPC) and curNPC.GetType() != ChConfig.ntRobot:  | 
|             return False  | 
|           | 
|         return True  | 
|   | 
|   | 
|     ##Ìí¼ÓÊÓÒ°ÖеĶÔÏó½ø³ðºÞÁÐ±í  | 
|     # @param self ÀàʵÀý  | 
|     # @param tick Ê±¼ä´Á  | 
|     # @return ·µ»ØÖµÎÞÒâÒå  | 
|     # @remarks Ìí¼ÓÊÓÒ°ÖеĶÔÏó½ø³ðºÞÁÐ±í  | 
|     def AddInSightObjToAngryList(self, tick, isUpdAngry=False):  | 
|         curNPC = self.__Instance  | 
|         needResort = False  | 
|         #Èç¹ûÊÇÖ÷¶¯¹Ö, ¼ì²éÖÜΧµÄÍæ¼ÒÊÇ·ñÔÚ×Ô¼ºµÄ³ðºÞ¶ÈÖÐ, Èç¹û²»ÔÚ, ¾ÍÌí¼Ó  | 
|         if curNPC.GetAtkType() == 1:  | 
|             # 1Ϊ·ÇÖ÷¶¯¹Ö  | 
|             return needResort  | 
|           | 
|         curAngry = curNPC.GetNPCAngry().GetAngryValueTag(0)  | 
|         if not isUpdAngry and self.__IsValidAngryObj(curAngry):  | 
|             # Ö»Ö÷¶¯¼ÓÒ»¸öÈ˵ÄÊÓÒ°³ðºÞ£¬ÆäËû¹¥»÷²ÅÓгðºÞ  | 
|             return needResort  | 
|   | 
|         mapType = GameWorld.GetMap().GetMapFBType()  | 
|         mapID = GameWorld.GetMap().GetMapID()  | 
|         # Ö÷¶¯ÊÓÒ°Çé¿ö£¬GetIsBoss 0 1 4 ÎªÆÕͨNPCÊÓÒ°£¨ÓÐÊÓÒ°·¶Î§ÅäÖ㬵«È¥³ýÊÓҰˢУ©£¬ÆäËûΪBOSSÀàÊÓÒ°ÓÐˢР | 
|         # 1. ËùÓÐNPC¶ÔÍæ¼Ò£ºÍæ¼ÒÖ÷¶¯¿´µ½NPC£¬¼Ç¼µ½NPCÁÐ±í£¬²»±éÀúNPCÊÓÒ°£¬¿ØÖƵ±Ç°NPC¹¥»÷Ò»¸öÍæ¼ÒµÄÊýÁ¿  | 
|         # 2. Íæ¼ÒÕÙ»½ÊÞ»ò³èÎï¶ÔNPC£º·ÇÖ÷¶¯ÔòΪ¹¥»÷Íæ¼ÒÄ¿±ê£¨Ä¿Ç°ÓÎÏ·Çé¿öÓÉAI¿ØÖÆÕ½¶·£©;¿ÉÖ÷¶¯¹¥»÷µÄÇé¿öÏ£¬Íæ¼ÒÓб»³ðºÞ¶ÔÏó²Å±éÀúÒ»´ÎÊÓÒ°£¨Î´¿ª·¢£©  | 
|         # 3. BOSS¶ÔÆäËû£ºÊµÊ±Ë¢ÐÂÊÓÒ°£¬¿É×·»÷Íæ¼Ò£¬ÆäËûOBJ¸ù¾Ý¾ßÌåÉ趨  | 
|         # 4. ÕóÓªÀàNPC£¨ÊØÎÀ£©¶ÔNPC£º¼ÓÈëBOSSÊÓҰˢжÓÁÐ; NPCÕ½¶·»á·¢ÉúÔÚ·ÇÍæ¼ÒÊÓÒ°ÄÚµÄÇé¿ö£¬ÀàDOTA¸ù¾ÝÇé¿öÁíÍ⿪·¢  | 
|         if not self.GetIsBossView():  | 
|             recordMapID = FBCommon.GetRecordMapID(mapID)  | 
|             mapAngryNPCCountDict = IpyGameDataPY.GetFuncEvalCfg("AngryNPCCount", 1)  | 
|             if recordMapID in mapAngryNPCCountDict:  | 
|                 angryNPCCountLimit = mapAngryNPCCountDict[recordMapID]  | 
|             elif mapType == IPY_GameWorld.fbtNull:  | 
|                 angryNPCCountLimit = IpyGameDataPY.GetFuncCfg("AngryNPCCount", 2)  | 
|             else:  | 
|                 angryNPCCountLimit = 0  | 
|             # Ã»ÓÐÊÓÒ°¶ÔÏóµÄNPC  | 
|             seePlayerCount = curNPC.GetAttentionPlayersCount()  | 
|             for i in range(0, seePlayerCount):  | 
|                 seeObj = curNPC.GetAttentionPlayerByIndex(i)  | 
|                   | 
|                 #ÓпÉÄÜΪ¿Õ  | 
|                 if seeObj == None :  | 
|                     continue  | 
|                   | 
|                 #ʬÌå²»Ìí¼Ó  | 
|                 if GameObj.GetHP(seeObj) <= 0:  | 
|                     continue  | 
|                   | 
|                 if not seeObj.GetVisible():  | 
|                     continue  | 
|                   | 
|                 if not self.__CheckAddToAngryList(seeObj, tick):  | 
|                     continue  | 
|                 dist = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), seeObj.GetPosX(), seeObj.GetPosY())  | 
|                 if dist > curNPC.GetSight():  | 
|                     continue  | 
|                   | 
|                 #Ìí¼ÓµÄ³ðºÞÖµ = µÚÒ»´Î¿´¼û¶ÔÏóµÄ³ðºÞ + (ÆÁÄ»¾àÀë - ºÍ¶ÔÏóµÄ¾àÀë)  | 
|                 addAngryValue = ChConfig.Def_NPCFirstSightAngryValue + (ChConfig.Def_Screen_Area - dist)  | 
|       | 
|                 #Èç¹ûÊÇÍæ¼Ò, ¶à¼Ó20µã  | 
|                 if seeObj.GetGameObjType() == IPY_GameWorld.gotPlayer:  | 
|                     if angryNPCCountLimit and seeObj.GetAngryNPCCount() >= angryNPCCountLimit:  | 
|                         continue  | 
|                     addAngryValue += ChConfig.Def_NPC_SeePlayerAddAngry  | 
|                   | 
|                 #Ìí¼Ó¶ÔÏó  | 
|                 if self.AddObjToAngryList(seeObj, addAngryValue, False, False):  | 
|                     needResort = True  | 
|           | 
|         else:  | 
|             # ÓÐÊÓÒ°¶ÔÏóµÄNPC  | 
|             refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|             seePlayerCount = curNPC.GetInSightObjCount()  | 
|             for i in range(0, seePlayerCount):  | 
|                 seeObj = curNPC.GetInSightObjByIndex(i)  | 
|                   | 
|                 #ÓпÉÄÜΪ¿Õ  | 
|                 if seeObj == None :  | 
|                     continue  | 
|                   | 
|                 #ʬÌå²»Ìí¼Ó  | 
|                 if GameObj.GetHP(seeObj) <= 0:  | 
|                     continue  | 
|                   | 
|                 if not seeObj.GetVisible():  | 
|                     continue  | 
|                   | 
|                 if not self.__CheckAddToAngryList(seeObj, tick):  | 
|                     continue  | 
|                   | 
|                 #bossÊÓÒ°µÄÖ»¹¥»÷×·»÷·¶Î§ÄÚµÄÄ¿±ê, ·ÇbossÊÓÒ°µÄÒ²¿ÉÒÔ¼Ó´ËÂß¼£¬²»¼ÓÒ²ÐÐ  | 
|                 if ChConfig.IsGameBoss(curNPC) and not self.GetIsInRefreshPoint(seeObj.GetPosX(), seeObj.GetPosY(), refreshPoint):  | 
|                     continue  | 
|                   | 
|                 dist = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), seeObj.GetPosX(), seeObj.GetPosY())  | 
|                 #Ìí¼ÓµÄ³ðºÞÖµ = µÚÒ»´Î¿´¼û¶ÔÏóµÄ³ðºÞ + (ÆÁÄ»¾àÀë - ºÍ¶ÔÏóµÄ¾àÀë)  | 
|                 addAngryValue = ChConfig.Def_NPCFirstSightAngryValue + (ChConfig.Def_Screen_Area - dist)  | 
|       | 
|                 #Èç¹ûÊÇÍæ¼Ò, ¶à¼Ó20µã  | 
|                 if seeObj.GetGameObjType() == IPY_GameWorld.gotPlayer:  | 
|                     addAngryValue += ChConfig.Def_NPC_SeePlayerAddAngry  | 
|                   | 
|                 #Ìí¼Ó¶ÔÏó  | 
|                 if self.AddObjToAngryList(seeObj, addAngryValue, False, False):  | 
|                     needResort = True  | 
|           | 
|         return needResort  | 
|   | 
|   | 
|     #---------------------------------------------------------------------  | 
|     ##Ç¿ÖÆÌí¼Ó¶ÔÏó½ø³ðºÞÁбí.  | 
|     # @param objDetel ¶ÔÏóʵÀý  | 
|     # @param hurtValue É˺¦Á¿  | 
|     # @param useSkill ¼¼ÄÜʵÀý  | 
|     # @return ·µ»ØÖµÎÞÒâÒå  | 
|     # @remarks Ç¿ÖÆÌí¼Ó¶ÔÏó½ø³ðºÞÁÐ±í  | 
|     def AddObjDetelToAngryList_ByAttack(self, objDetel, hurtValue, useSkill):  | 
|         #BUG ÒþÉí·Å¼¼ÄÜ»áA  | 
|         if not objDetel:  | 
|             return  | 
|                   | 
|         #Èç¹û¹¥»÷·½ÊÇNPC²¢ÇÒÊÇÏÝÚåÔò²»Ìí¼Ó³ðºÞ  | 
|         if objDetel.GetGameObjType() == IPY_GameWorld.gotNPC and \  | 
|         objDetel.GetType() == IPY_GameWorld.ntFairy:  | 
|             return  | 
|   | 
|         #Ìí¼Ó³ðºÞ = ¼¼ÄܳðºÞ + ÉËѪֵ  | 
|         addAngry = hurtValue  | 
|           | 
|         if useSkill != None:  | 
|             addAngry += useSkill.GetSkillAngry()  | 
|               | 
|         # Íæ¼Ò¹¥»÷Ôö¼Ó¶îÍâ³ðºÞ  | 
|         if objDetel.GetGameObjType() == IPY_GameWorld.gotPlayer:  | 
|             addAngry += PlayerControl.GetAddAngry(objDetel)  | 
|                       | 
|         self.AddObjToAngryList(objDetel, addAngry)  | 
|         return  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ##Ç¿ÖÆÌí¼Ó¶ÔÏó½ø³ðºÞÁÐ±í  | 
|     # @param self ÀàʵÀý  | 
|     # @param curObj ¶ÔÏó  | 
|     # @param plusAngryValue Öµ  | 
|     # @param canPile ÊÇ·ñÀÛ¼Ó  | 
|     # @param check ÊÇ·ñ¼ì²é  | 
|     # @return ·µ»ØÖµÎÞÒâÒå  | 
|     # @remarks Ç¿ÖÆÌí¼Ó¶ÔÏó½ø³ðºÞÁÐ±í  | 
|     def AddObjToAngryList(self, curObj, plusAngryValue, canPile=True, check=True):  | 
|         curNPC = self.__Instance  | 
|               | 
|         if GameWorld.IsSameObj(curNPC, curObj):  | 
|             #²»Ìí¼Ó×Ô¼ºµ½³ðºÞ¶È  | 
|             return False  | 
|           | 
|         #Õâ¸öÄ¿±ê²»¿É¹¥»÷ ²»Ìí¼Ó  | 
|         if not AttackCommon.CheckObjCanDoLogic(curObj):  | 
|             return False  | 
|           | 
|         curObjType = curObj.GetGameObjType()  | 
|         curObjID = curObj.GetID()  | 
|           | 
|         if (check and not self.__CheckCanAddAngry(curObjID , curObjType)):  | 
|             #²»¿ÉÌí¼Ó³ðºÞ  | 
|             return False  | 
|           | 
|         addAngryTeam = None  | 
|         if curObjType == IPY_GameWorld.gotPlayer:  | 
|             # Èç¹ûÊdzðºÞµôÂä¹éÊôµÄÔòÈ«¶Ó¼Ó³ðºÞ  | 
|             if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_MaxAngry:  | 
|                 curPlayer = GameWorld.GetObj(curObjID, curObjType)  | 
|                 if curPlayer and curPlayer.GetTeamID() > 0:  | 
|                     addAngryTeam = GameWorld.GetTeamManager().FindTeam(curPlayer.GetTeamID())  | 
|           | 
|         #×ÜѪÁ¿Óг¬¹ýDWORDµÄÇé¿ö  | 
|         plusAngryValue = FixValueByValueEx(curNPC.GetMaxHPEx(), plusAngryValue)  | 
|               | 
|         #×îСÌí¼Ó³ðºÞֵΪ1  | 
|         plusAngryValue = max(plusAngryValue , 1)  | 
|         npcAngry = curNPC.GetNPCAngry()  | 
|           | 
|         if addAngryTeam:  | 
|             GameWorld.DebugLog("NPCÌí¼Ó¶ÓÎé³ðºÞ: teamID=%s,plusAngryValue=%s" % (addAngryTeam.GetTeamID(), plusAngryValue))  | 
|             for i in xrange(addAngryTeam.GetMemberCount()):  | 
|                 curTeamPlayer = addAngryTeam.GetMember(i)  | 
|                 if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:  | 
|                     continue  | 
|                   | 
|                 teamPlayerID = curTeamPlayer.GetPlayerID()  | 
|                 # ¹¥»÷Õß¶à1µã³ðºÞ, È·±£ÔÚ¶ÓԱͬ³ðºÞµÄÇé¿öÏÂÓÅÏȹ¥»÷¸Ã¶ÓÔ±  | 
|                 addAngryValue = plusAngryValue + 1 if teamPlayerID == curObjID else plusAngryValue  | 
|                 GameWorld.DebugLog("    i=%s,playerID=%s,addAngryValue=%s" % (i, teamPlayerID, addAngryValue))  | 
|                 self.__AddAngryValue(npcAngry, teamPlayerID, curObjType, addAngryValue, canPile)  | 
|         else:  | 
|             self.__AddAngryValue(npcAngry, curObjID, curObjType, plusAngryValue, canPile)  | 
|           | 
|         #¼¤»î´ôÖ͵ÄNPC  | 
|         if GameObj.GetHP(curNPC) > 0 and not curNPC.GetIsNeedProcess() :  | 
|             curNPC.SetIsNeedProcess(True)  | 
|   | 
|           | 
|         return True  | 
|       | 
|     def __AddAngryValue(self, npcAngry, curObjID, curObjType, plusAngryValue, canPile):  | 
|         angryValue = npcAngry.FindNPCAngry(curObjID, curObjType)  | 
|       | 
|         #δ·¢ÏÖ,Ìí¼Ó  | 
|         if angryValue == None or angryValue.GetAngryValue() == 0:  | 
|             npcAngry.AddAngry(curObjID, curObjType, plusAngryValue)  | 
|           | 
|         #Èç¹ûÐèÒª,µþ¼Ó  | 
|         elif canPile:  | 
|             angryValue.SetAngryValue(min(angryValue.GetAngryValue() + plusAngryValue, ChConfig.Def_UpperLimit_DWord))  | 
|         return  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## ¼ì²éÊÇ·ñ¿ÉÒÔÌí¼Ó³ðºÞ  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tagID ¶ÔÏóID  | 
|     #  @param tagType ¶ÔÏóÀàÐÍ  | 
|     #  @return ·µ»ØÖµ, ÊÇ·ñ¼ì²éͨ¹ý  | 
|     #  @remarks ¼ì²éÊÇ·ñ¿ÉÒÔÌí¼Ó³ðºÞ  | 
|     def __CheckCanAddAngry(self , curObjID , curObjType):  | 
|         curNPC = self.__Instance  | 
|   | 
|         #bug ÒÔǰ·µ»ØTrueµ¼ÖÂÒþÉíÍæ¼Ò·Å·¶Î§¼¼ÄܵÄʱºò·þÎñ¶ËA  | 
|         curObjDetel = GameWorld.GetObj(curObjID, curObjType)  | 
|         if not curObjDetel:  | 
|             GameWorld.Log('###Ìí¼Ó³ðºÞ,ÎÞ·¨²éÕÒÄ¿±êʵÀý = %s , %s' % (curObjID , curObjType))  | 
|             return False  | 
|   | 
|         relation = BaseAttack.GetTagRelation(curNPC, curObjDetel, None, 0)[0]  | 
|         if relation != ChConfig.Type_Relation_Enemy:  | 
|             return False  | 
|           | 
|         #²»ÊÇÕÙ»½ÊÞ¹¥»÷Ä¿±ê, Ä¿±êÖ±½ÓÌí¼Ó³ðºÞ  | 
|         if curNPC.GetGameNPCObjType() != IPY_GameWorld.gnotSummon:  | 
|             return True  | 
|           | 
|         curNPCDetel = GameWorld.GetObj(curNPC.GetID(), IPY_GameWorld.gotNPC)  | 
|         curNPCOwner = GetSummonNPCOwner(IPY_GameWorld.gotPlayer, curNPCDetel)  | 
|           | 
|         if not curNPCOwner:  | 
|             #ϵͳµÄÕÙ»½ÊÞ , Ä¿±êÖ±½ÓÌí¼Ó³ðºÞ  | 
|             return True  | 
|           | 
|         #ÕÙ»½ÊÞvsÍæ¼Ò  | 
|         if curObjType == IPY_GameWorld.gotPlayer:  | 
|                   | 
|             #×Ô¼º´ò×Ô¼º  | 
|             if GameWorld.IsSameObj(curNPCOwner, curObjDetel):  | 
|                 return False  | 
|           | 
|             #¼ì²é¹¥»÷ģʽ  | 
|             if not AttackCommon.CheckPlayerAttackMode_Player(curNPCOwner, curObjDetel):  | 
|                 return False  | 
|               | 
|         #ÕÙ»½ÊÞvsNPC  | 
|         elif curObjType == IPY_GameWorld.gotNPC :  | 
|               | 
|             if curObjDetel.GetGameNPCObjType() != IPY_GameWorld.gnotSummon:  | 
|                 #ÕÙ»½ÊÞvsÕÙ»½ÊÞ,,Ö±½ÓÌí¼Ó³ðºÞ  | 
|                 return True  | 
|               | 
|             curObjOwner = GetSummonNPCOwner(IPY_GameWorld.gotPlayer, curObjDetel)  | 
|               | 
|             if not curObjOwner:  | 
|                 #²»Êǹ¥»÷Íæ¼ÒµÄÕÙ»½ÊÞ,Ö±½ÓÌí¼Ó³ðºÞ  | 
|                 return True  | 
|                   | 
|             #ͬһÖ÷È˵ÄÕÙ»½ÊÞ²»¹¥»÷  | 
|             if GameWorld.IsSameObj(curNPCOwner, curObjOwner):  | 
|                 return False  | 
|               | 
|             if not AttackCommon.CheckPlayerAttackMode_Player(curNPCOwner, curObjOwner):  | 
|                 return False  | 
|           | 
|         #Ö±½ÓÌí¼Ó  | 
|         return True  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ##ÔÚ³ðºÞ¶ÈÁбíÖÐɾ³ýËÀÍöµÄ¶ÔÏó  | 
|     # @param self ÀàʵÀý  | 
|     # @param tick Ê±¼ä´Á  | 
|     # @return ·µ»ØÖµÎÞÒâÒå  | 
|     # @remarks ÔÚ³ðºÞ¶ÈÁбíÖÐɾ³ýËÀÍöµÄ¶ÔÏó  | 
|     def RemoveDeathInAngryList(self, tick):  | 
|         curNPC = self.__Instance  | 
|         npcAngry = curNPC.GetNPCAngry()  | 
|         defaultMaxAngryNPCIDList = GetDefaultMaxAngryNPCIDList()  | 
|           | 
|         needResort = False  | 
|         refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|           | 
|         #³ðºÞÁбíΪ¹Ì¶¨³¤¶ÈÁбí, ¿ÉÒÔÔÚforÖÐɾ³ý  | 
|         for i in range(0, npcAngry.GetAngryCount()):  | 
|               | 
|             angryValue = npcAngry.GetAngryValueTag(i)  | 
|             angryID = angryValue.GetObjID()  | 
|             angryType = angryValue.GetObjType()  | 
|               | 
|             #²»¼ì²é¿ÕID  | 
|             if not angryID:  | 
|                 continue  | 
|               | 
|             curObj = GameWorld.GetObj(angryID, angryType)  | 
|               | 
|             if not curObj:  | 
|                 #Õâ¸ö¶ÔÏó²»´æÔÚÁË,ɾ³ý  | 
|                 npcAngry.DeleteAngry(angryID, angryType)  | 
|                 needResort = True  | 
|                 continue  | 
|               | 
|             if angryType == IPY_GameWorld.gotNPC:  | 
|                 #ĬÈϳðºÞ¶ÔÏó²»ÒƳý  | 
|                 if curObj.GetNPCID() in defaultMaxAngryNPCIDList:  | 
|                     continue  | 
|                   | 
|             if not AttackCommon.CheckCanAttackTag(curNPC, curObj):  | 
|                 #²»¿É¹¥»÷Õâ¸ö¶ÔÏóÁË,ɾ³ý  | 
|                 npcAngry.DeleteAngry(angryID, angryType)  | 
|                 needResort = True  | 
|                 continue  | 
|               | 
|             if not self.GetIsInRefreshPoint(curObj.GetPosX(), curObj.GetPosY(), refreshPoint):  | 
|                 npcAngry.DeleteAngry(angryID, angryType)  | 
|                 needResort = True  | 
|                 continue  | 
|               | 
|             dist = GameWorld.GetDist(curObj.GetPosX() , curObj.GetPosY() , curNPC.GetPosX() , curNPC.GetPosY())  | 
|             # ³¬³öÊÓÒ°  | 
|             if dist > curNPC.GetSight():  | 
|                 npcAngry.DeleteAngry(angryID, angryType)  | 
|                 needResort = True  | 
|                 continue  | 
|             #¹Ì¶¨NPC£¬³¬³öÊÓÒ°»òÕß¹¥»÷¾àÀë¾Í·ÅÆúÄ¿±ê  | 
|             if not curNPC.GetSpeed() :  | 
|                   | 
|                 if not curNPC.CanSeeOther(curObj):  | 
|                     npcAngry.DeleteAngry(angryID, angryType)  | 
|                     needResort = True  | 
|                     continue  | 
|                   | 
|                 if dist > GetNPCMaxAtkDist(curNPC):  | 
|                     npcAngry.DeleteAngry(angryID, angryType)  | 
|                     needResort = True  | 
|                     continue  | 
|               | 
|             #---------------ÒÔÏÂÂß¼Åж¨¹ØÏµ,³ÇÃųýÍâ  | 
|             if GameWorld.GetNPC_Is_Gate(curNPC):  | 
|                 #³ÇÃŲ»¼ì²éµÐÈ˹ØÏµ,ÒòΪ³ÇÃųðºÞÓÃÀ´·Å¼¼ÄÜ  | 
|                 continue  | 
|               | 
|             relation = BaseAttack.GetTagRelation(curNPC, curObj, None, tick)  | 
|               | 
|             if relation[0] != ChConfig.Type_Relation_Enemy :  | 
|                 #Õâ¸ö¶ÔÏó²»ÊǵÐÈ˹ØÏµÁË,ɾ³ý  | 
|                 npcAngry.DeleteAngry(angryID, angryType)  | 
|                 needResort = True  | 
|                 continue  | 
|               | 
|         return needResort  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ##Íⲿµ÷ÓÃ, NPCˢгðºÞÁÐ±í  | 
|     # @param tick Ê±¼ä´Á  | 
|     # @return ·µ»ØÖµÎÞÒâÒå  | 
|     # @remarks Íⲿµ÷ÓÃ, NPCˢгðºÞÁÐ±í  | 
|     def RefreshAngryList(self, tick, refreshInterval=ChConfig.Def_NPCRefreshAngryValueInterval, isUpdAngry=False):  | 
|         curNPC = self.__Instance  | 
|         npcAngry = curNPC.GetNPCAngry()  | 
|           | 
|         #---¼ì²â¼ä¸ô  | 
|         lastTick = tick - npcAngry.GetLastResortTick()  | 
|           | 
|         # resort»áÖØÖÃtick  | 
|         if lastTick < (refreshInterval):  | 
|             return  | 
|           | 
|         #ɾ³ý²»¿É¹¥»÷µÄ¶ÔÏó GetIsNeedProcess ÎªfalseʱӦ¸Ã±£Ö¤³ðºÞÒ²ÊÇ¿ÕµÄ  | 
|         #if not curNPC.GetIsNeedProcess():  | 
|         removeRsort = self.RemoveDeathInAngryList(tick)  | 
|   | 
|         #Ö÷¶¯¹ÖÌí¼ÓÊÓÒ°¶ÔÏó³ðºÞ  | 
|         needResort = self.AddInSightObjToAngryList(tick, isUpdAngry) or removeRsort  | 
|           | 
|         #ѪÁ¿²»Îª0ʱ²Å MoveBack£¬²»È»»áµ¼ÖÂËÀÍöʱˢеÄʱºò³ðºÞÁÐ±í¡¢ÉËѪÁÐ±í±»Çå¿Õ; ÓÐÕóÓªµÄ²»´¦Àí MoveBack  | 
|         if removeRsort and self.GetMaxAngryTag() == None and GameObj.GetHP(curNPC) and not GetFaction(curNPC):  | 
|             # ³ðºÞÇå¿ÕʱÎÞгðºÞ¼°Ê±»ØÎ»  | 
|             if curNPC.GetSpeed() != 0:  | 
|                 self.MoveBack()  | 
|               | 
|         if isUpdAngry or needResort:  | 
|             #ÅÅÐò³ðºÞ  | 
|             npcAngry.Resort(tick)  | 
|         else:  | 
|             npcAngry.SetLastResortTick(tick)  | 
|         return  | 
|     #---------------------------------------------------------------------  | 
|     ## »ñµÃ×î´ó³ðºÞ¶ÔÏó  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµ, ×î´ó³ðºÞ¶ÔÏó  | 
|     #  @remarks »ñµÃ×î´ó³ðºÞ¶ÔÏó  | 
|     def GetMaxAngryTag(self):  | 
|         curNPC = self.__Instance  | 
|           | 
|         angryManager = curNPC.GetNPCAngry()  | 
|           | 
|         for i in range(0, angryManager.GetAngryCount()) :  | 
|             curAngry = angryManager.GetAngryValueTag(i)  | 
|               | 
|             if not self.__IsValidAngryObj(curAngry):  | 
|                 continue  | 
|               | 
|             #ÓÐÕâ¸ö³ðºÞ¶È, ²¢ÇÒ¿ÉÒÔ¹¥»÷Õâ¸öÈË  | 
|             #ÔÚÇ°ÃæÒѾÅÅÐò¹ýÁË  | 
|             return curAngry  | 
|           | 
|         return None  | 
|       | 
|       | 
|     ## Åж¨³ðºÞ¶ÔÏóÊÇ·ñÓÐЧ  | 
|     #  @param self curAngry ÀàʵÀý  | 
|     #  @return ·µ»Ø¶ÔÏó  | 
|     def __IsValidAngryObj(self, curAngry):  | 
|         if curAngry == None or curAngry.GetObjID() == 0:  | 
|             return None  | 
|           | 
|         #³ðºÞÖµ  | 
|         curAngryValue = curAngry.GetAngryValue()  | 
|           | 
|         if curAngryValue == 0:  | 
|             return None  | 
|           | 
|         if curAngry.GetIsDisable():  | 
|             return None  | 
|       | 
|         return curAngry  | 
|       | 
|       | 
|     ## Çå¿ÕNPC³ðºÞ  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Çå¿ÕNPC³ðºÞ  | 
|     def ClearNPCAngry(self):  | 
|         curNPC = self.__Instance  | 
|         curAngry = curNPC.GetNPCAngry()  | 
|         curAngry.Clear()  | 
|         return True  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## Çå¿ÕNPCÉËѪÁÐ±í  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Çå¿ÕNPCÉËѪÁÐ±í  | 
|     def ClearNPCHurtList(self):  | 
|         curNPC = self.__Instance  | 
|         #Çå¿ÕÉËѪÁÐ±í  | 
|         npcHurtList = curNPC.GetPlayerHurtList()  | 
|         npcHurtList.Clear()  | 
|         return True  | 
|       | 
|     def __IsBossHurtOfflineProtect(self, refreshPoint, playerID, tick):  | 
|         ## bossÉËѪÊÇ·ñµôÏß±£»¤ÖÐ  | 
|         # ÊÇ·ñÀëÏß³¬¹ý3·ÖÖÓ£¬ÏÂÏß×ø±êÊÇ·ñ²»ÔÚbossÇøÓòµÈ  | 
|         leaveTick = PlayerControl.GetPlayerLeaveServerTick(playerID)  | 
|         leavePos = PlayerControl.GetPlayerLeaveServerPos(playerID)  | 
|         if not leaveTick or not leavePos:  | 
|             GameWorld.DebugLog("Íæ¼Ò²»ÔÚ±¾µØÍ¼»òÒѳ¤¾ÃÀëÏߣ¡Çå³ý¸ÃÉËѪ£¡playerID=%s" % playerID)  | 
|             return False  | 
|           | 
|         if tick - leaveTick > ChConfig.Def_PlayerOfflineProtectTime:  | 
|             GameWorld.DebugLog("±¾µØÍ¼ÀëÏßÍæ¼Ò³¬¹ý±£»¤Ê±³¤£¡Çå³ý¸ÃÉËѪ£¡playerID=%s,tick=%s,leaveTick=%s" % (playerID, tick, leaveTick))  | 
|             return False  | 
|           | 
|         if not self.GetIsInRefreshPoint(leavePos[0], leavePos[1], refreshPoint):  | 
|             GameWorld.DebugLog("±¾µØÍ¼ÀëÏßÍæ¼Ò²»ÔÚ±£»¤ÇøÓòÄÚ£¡playerID=%s,leavePos=%s" % (playerID, leavePos))  | 
|             return False  | 
|           | 
|         return True  | 
|       | 
|     def __IsClearPlayerHurt(self, hurtPlayer, refreshPoint, hurtID, tick):  | 
|         if hurtPlayer == None:  | 
|             if not self.__IsBossHurtOfflineProtect(refreshPoint, hurtID, tick):  | 
|                 return True  | 
|               | 
|             #GameWorld.DebugLog("±¾µØÍ¼ÀëÏßÍæ¼ÒÉËѪֵ±£»¤ÖУ¡playerID=%s" % (hurtID))  | 
|             return False  | 
|                                           | 
|         #if hurtPlayer.GetHP() <= 0:  | 
|         #    GameWorld.DebugLog("ÉËÑªÍæ¼ÒѪÁ¿Îª0£¬Çå³ý¸ÃÉËѪ!playerID=%s" % hurtID)  | 
|         #    return True  | 
|           | 
|         if hurtPlayer.GetInitOK() and not hurtPlayer.GetVisible():  | 
|             GameWorld.DebugLog("ÉËÑªÍæ¼Ò²»¿É¼û£¬Çå³ý¸ÃÉËѪ!playerID=%s" % hurtID)  | 
|             return True  | 
|           | 
|         if not self.GetIsInRefreshPoint(hurtPlayer.GetPosX(), hurtPlayer.GetPosY(), refreshPoint):  | 
|             GameWorld.DebugLog("ÉËÑªÍæ¼Ò²»ÔÚboss·¶Î§ÀÇå³ý¸ÃÉËѪ!playerID=%s" % hurtID)  | 
|             return True  | 
|           | 
|         if hurtPlayer.GetTeamID():  | 
|             # ÕâÖÖÇé¿öÒ»°ãÊÇÍæ¼Òδ¼ÓÈë¶ÓÎéǰ¶Ô¸ÃNPCÓÐÉËѪ£¬¼ÓÈ뵽ij¸ö¶ÓÎéºó£¬½«¸ÃÉ˺¦×ªÒƵ½¶ÓÎéÖÐ  | 
|             return True  | 
|           | 
|         if hurtPlayer.GetHP() <= 0 or hurtPlayer.GetPlayerAction() == IPY_GameWorld.paDie:  | 
|             deadTime = hurtPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_DeadTime)  | 
|             if time.time() - deadTime >= IpyGameDataPY.GetFuncCfg("BossHurtValue", 1):  | 
|                 #GameWorld.DebugLog("ÉËÑªÍæ¼ÒËÀÍö³¬¹ýÉËѪ±£»¤Ê±³¤£¬Çå³ý¸ÃÉËѪ!playerID=%s" % hurtID)  | 
|                 return True  | 
|               | 
|         #GameWorld.DebugLog("Õý³£Íæ¼ÒÉËѪ±£»¤ÖУ¡playerID=%s" % hurtID)  | 
|         return False  | 
|       | 
|     def __GetTeamHurtNPCPlayerIDList(self, refreshPoint, teamID, tick):  | 
|           | 
|         curNPC = self.__Instance  | 
|         teamHurtPlayerIDList = []  | 
|         # Èç¹ûûÓÐÔÚÏß¶ÓÔ±ÔÚÓÐЧ·¶Î§ÄÚ£¬Ôò½øÒ»²½ÅжÏÀëÏß¶ÓÔ±ÊÇ·ñÓÐÉËѪ±£»¤ÖÐµÄ  | 
|         playerMgr = GameWorld.GetPlayerManager()  | 
|         copyMapID = GameWorld.GetGameWorld().GetCopyMapID()  | 
|         mapTeamPlayerIDList = PlayerTeam.GetMapTeamPlayerIDList(teamID) # ÒòΪÐèÒªÅжÏÀëÏß¶ÓÔ±£¬ËùÒÔÖ»ÄÜÓú¬ÀëÏߵĶÓÎ黺´æ  | 
|         for playerID in mapTeamPlayerIDList:  | 
|               | 
|             curTeamPlayer = playerMgr.FindPlayerByID(playerID)  | 
|             if curTeamPlayer:  | 
|                 if curTeamPlayer.GetCopyMapID() != copyMapID:  | 
|                     #GameWorld.DebugLog("¶ÓÔ±²»ÔÚ±¾Ïß·£¬²»¼Æ£¡playerID=%s" % playerID)  | 
|                     continue  | 
|                   | 
|                 if curTeamPlayer.GetInitOK() and not curTeamPlayer.GetVisible():  | 
|                     #GameWorld.DebugLog("¶ÓÔ±²»¿É¼û£¬²»¼Æ£¡playerID=%s" % playerID)  | 
|                     continue  | 
|                   | 
|                 if curTeamPlayer.GetHP() <= 0 or curTeamPlayer.GetPlayerAction() == IPY_GameWorld.paDie:  | 
|                     deadTime = curTeamPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_DeadTime)  | 
|                     if time.time() - deadTime >= IpyGameDataPY.GetFuncCfg("BossHurtValue", 1):  | 
|                         #GameWorld.DebugLog("ÉËѪ¶ÓÔ±ËÀÍö³¬¹ýÉËѪ±£»¤Ê±³¤£¬²»¼Æ!playerID=%s" % playerID)  | 
|                         continue  | 
|                       | 
|                 #if curTeamPlayer.GetHP() > 0 and self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint):  | 
|                 if self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint) \  | 
|                     and AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False):  | 
|                     #GameWorld.DebugLog("ÓжÓÔ±ÔÚboss·¶Î§ÄÚ£¬±£Áô¶ÓÎéÉËѪ£¡teamID=%s,playerID=%s" % (teamID, curTeamPlayer.GetPlayerID()))  | 
|                     teamHurtPlayerIDList.append(playerID)  | 
|             else:  | 
|                 if self.__IsBossHurtOfflineProtect(refreshPoint, playerID, tick):  | 
|                     #GameWorld.DebugLog("ÓжÓÔ±¶ÔbossÀëÏßÉËѪ±£»¤ÖУ¡teamID=%s,playerID=%s" % (teamID, playerID))  | 
|                     teamHurtPlayerIDList.append(playerID)  | 
|                       | 
|         if not teamHurtPlayerIDList:  | 
|             GameWorld.DebugLog("ÉËѪ¶ÓÎéûÓзûºÏÌõ¼þµÄ¶ÓÔ±ÔÚbossÇøÓòÄÚ£¬Çå³ý¸ÃÉËѪ!teamID=%s,mapTeamPlayerIDList=%s" % (teamID, mapTeamPlayerIDList))  | 
|         return teamHurtPlayerIDList  | 
|       | 
|     def RefreshHurtList(self, tick, refreshInterval=3000):  | 
|         ## Ë¢ÐÂÉËѪÁÐ±í  | 
|         # @return: ¿É¹¥»÷µÄ×î´óÉËѪÊýÖµ¶ÔÏó IPY_PlayerHurtValue  | 
|           | 
|         curNPC = self.__Instance  | 
|         if not curNPC.GetIsBoss() or GetDropOwnerType(curNPC) != ChConfig.DropOwnerType_MaxHurt:  | 
|             return  | 
|           | 
|         npcHurtList = curNPC.GetPlayerHurtList()  | 
|         if tick - curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastRefreshHurtTick) < (refreshInterval):  | 
|             if npcHurtList.GetHurtCount():  | 
|                 return self.__GetAtkObjByHurtList(npcHurtList)  | 
|             return  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_LastRefreshHurtTick, tick)  | 
|           | 
|         hurtPlayerDict = {} # {playerID:teamID, ...}  | 
|         refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|         hurtCount = npcHurtList.GetHurtCount()  | 
|         isInHurt = 0  | 
|         for index in xrange(hurtCount):  | 
|             #»ñµÃÉËѪ¶ÔÏó  | 
|             hurtObj = npcHurtList.GetHurtAt(index)  | 
|             hurtType = hurtObj.GetValueType()  | 
|             hurtID = hurtObj.GetValueID()  | 
|             hurtValue = hurtObj.GetHurtValue()  | 
|             if not hurtID:  | 
|                 continue  | 
|               | 
|             # Clear()Ö»»á°ÑÉËѪÀàÐͼ°ÊýÖµÖØÖÃΪ0£¬²»»áÇå³ý¸ÃÉËѪÊýÖµ¶ÔÏó  | 
|               | 
|             if hurtType == ChConfig.Def_NPCHurtTypePlayer:  | 
|                 hurtPlayer = GameWorld.GetObj(hurtID, IPY_GameWorld.gotPlayer)  | 
|                 if self.__IsClearPlayerHurt(hurtPlayer, refreshPoint, hurtID, tick):  | 
|                     hurtObj.Clear()  | 
|                     teamID = 0 if not hurtPlayer else hurtPlayer.GetTeamID()  | 
|                     if teamID:  | 
|                         GameWorld.DebugLog("¼ÓÈë¶ÓÎé£¬Ö®ÆøµÄÉËÑª×ªÒÆµ½¶ÓÎéÖУ¡playerID=%s,teamID=%s" % (hurtID, teamID))  | 
|                         AttackCommon.AddHurtValue(curNPC, teamID, ChConfig.Def_NPCHurtTypeTeam, hurtValue)  | 
|                 else:  | 
|                     isInHurt = 1  | 
|                     hurtPlayerDict[hurtID] = 0  | 
|                       | 
|             elif hurtType == ChConfig.Def_NPCHurtTypeTeam:  | 
|                 teamHurtPlayerIDList = self.__GetTeamHurtNPCPlayerIDList(refreshPoint, hurtID, tick)  | 
|                 if not teamHurtPlayerIDList:  | 
|                     hurtObj.Clear()  | 
|                 else:  | 
|                     isInHurt = 1  | 
|                     for tPlayerID in teamHurtPlayerIDList:  | 
|                         hurtPlayerDict[tPlayerID] = hurtID  | 
|                           | 
|         mapID = GameWorld.GetMap().GetMapID()  | 
|         if IsMapNeedBossShunt(mapID):  | 
|             self.__UpdBossShuntInfo(mapID, hurtPlayerDict, tick)  | 
|           | 
|         #GameWorld.DebugLog("RefreshHurtList, hurtCount=%s,isInHurt=%s" % (hurtCount, isInHurt))  | 
|         npcHurtList.Sort()  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_InHurtProtect, isInHurt)  | 
|           | 
|         if hurtCount:  | 
|             # ÅÅÐòºóµÄ£¬µÚÒ»¸ö¿É¹¥»÷µÄ×î´óÉËѪ¶ÔÏó  | 
|             return self.__GetAtkObjByHurtList(npcHurtList)  | 
|         return  | 
|       | 
|     def __UpdBossShuntInfo(self, mapID, hurtPlayerDict, tick):  | 
|         ## ¸üб¾µØÍ¼Ïß·boss·ÖÁ÷ÐÅÏ¢  | 
|         curNPC = self.__Instance  | 
|         npcID = curNPC.GetNPCID()  | 
|         lineID = GameWorld.GetGameWorld().GetLineID()  | 
|         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  | 
|             GameServer_WorldBossShuntInfo(mapID, lineID)  | 
|         return  | 
|       | 
|     def __GetAtkObjByHurtList(self, npcHurtList):  | 
|         '''µÚÒ»¸ö¿É¹¥»÷µÄ×î´óÉËѪ¶ÔÏó£¬Ò²ÊÇʵ¼ÊµÄ¹éÊôÕß»ò¶ÓÎé  | 
|         ÒòÎªÍæ¼ÒÉËѪµôÏß¡¢ËÀÍöÓÐÒ»¶¨Ê±¼äµÄ±£Áô»úÖÆ£¬¹Ê×î´óÉËѪ²»Ò»¶¨Êǿɹ¥»÷Ä¿±ê(¹éÊôÕß)  | 
|         ×¢Òâ: ¸Ã¹æÔò±ØÐëÓë×îÖÕËã¹éÊôµÄ¹æÔòÒ»Ö£¬²»È»¿ÉÄܵ¼Ö¹éÊô´íÂÒ  | 
|         '''  | 
|         for index in xrange(npcHurtList.GetHurtCount()):  | 
|             #»ñµÃÉËѪ¶ÔÏó  | 
|             hurtObj = npcHurtList.GetHurtAt(index)  | 
|               | 
|             curPlayer, curTeam = self.__GetTagByHurtObj(hurtObj, True)  | 
|               | 
|             if curPlayer or curTeam:  | 
|                 return hurtObj  | 
|         return  | 
|       | 
|     def IsInHurtProtect(self):  | 
|         '''NPCÊÇ·ñÉËѪ±£»¤ÖÐ  | 
|         ÒòΪÊÖÓαȽϻá³öÏÖÍøÂçÇл»µÄÇé¿ö£¬´Ëʱ»á¿ÉÄÜ»áÒýÆðµôÏßÖØÁ¬  | 
|         ËùÒÔÕë¶ÔÊÖÓÎ×öÁ˵ôÏß3·ÖÖÓÄÚÉËѪ±£»¤£¬·ÀÖ¹Íæ¼ÒÖØÁ¬ºóÉËѪ±»Çå¿Õ£¬ÌåÑé²»ºÃ£»  | 
|         '''  | 
|         curNPC = self.__Instance  | 
|         return curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_InHurtProtect)  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## Çå¿ÕËùÓÐBuff  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Çå¿ÕËùÓÐBuff  | 
|     def ClearAllBuff(self, isClearAuraBuff=True):  | 
|         curNPC = self.__Instance  | 
|         #»ñµÃNPCBuff¹ÜÀíÆ÷  | 
|         buffRefreshList = GetNPCBuffRefreshList(curNPC, True, isClearAuraBuff)  | 
|           | 
|         for buffState, canPileup in buffRefreshList:  | 
|             buffState.Clear()  | 
|   | 
|         return  | 
|     #---------------------------------------------------------------------  | 
|     ## Çå¿ÕËùÓÐNPC״̬  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Çå¿ÕËùÓÐNPC״̬  | 
|     def __ClearNPCAllState(self, isClearAuraBuff=True):  | 
|         #Çå³ý³ðºÞ  | 
|         self.ClearNPCAngry()  | 
|         #Çå³ýÉËѪÁÐ±í  | 
|         self.ClearNPCHurtList()  | 
|         #Çå³ýËùÓÐÉíÉÏbuff  | 
|         self.ClearAllBuff(isClearAuraBuff)  | 
|         return True  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## ÖØÖÃNPC״̬  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks ÖØÖÃNPC״̬  | 
|     def ResetNPC_Init(self, isReborn=False):  | 
|         curNPC = self.__Instance  | 
|         #Çå³ý״̬  | 
|         self.__ClearNPCAllState(False)  | 
|         #Ö»ÔÚÖØÉú»òÕßÂúѪµÄ״̬ϲÅÖØÖÃÒÔÏÂÄÚÈÝ  | 
|         if isReborn or GameObj.GetHP(curNPC) >= GameObj.GetMaxHP(curNPC):  | 
|             #³õʼ»¯ÕÙ»½ÊÞ  | 
|             self.__InitNPCSummon()  | 
|             #ÖØÖü¼ÄÜCD  | 
|             self.__NormalNPCInItCD()  | 
|               | 
|         #ÖØË¢ÊôÐÔ  | 
|         self.RefreshNPCState(isReborn=isReborn)  | 
|         #֪ͨѪÁ¿, ¸´»îµÄÇé¿ö²»Í¨ÖªÑªÁ¿£¬ÓÉNPC³öÏÖ°ü֪ͨ  | 
|         if not isReborn:  | 
|             curNPC.Notify_HPEx()  | 
|   | 
|         #ÕâÀï²»ÉèÖÃΪÂýËÙ´¦Àí,ÒòΪNPCÓпÉÄÜδÂúѪ   | 
|         #¸ÄΪÔÚ¿ÕÏлØÑª,Èç¹ûÂúѪµÄʱºòÉèÖÃΪÂýËÙ´¦Àí  | 
|         #curNPC.SetIsNeedProcess(False)  | 
|         return True  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## »¹Ô¼¼ÄÜCD  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks »¹Ô¼¼ÄÜCD  | 
|     def __NormalNPCInItCD(self):  | 
|         curNPC = self.__Instance  | 
|         #»¹ÔÆÕ¹¥¼ä¸ô  | 
|         curNPC.SetAttackTick(0)  | 
|         #»¹Ô¼¼Äܹ«¹²¼ä¸ô  | 
|         curNPC.SetUseSkillTick(0)  | 
|         curNPCManager = curNPC.GetSkillManager()  | 
|         #»¹Ôµ¥¸ö¼¼Äܼä¸ô  | 
|         for i in range(curNPCManager.GetSkillCount()):  | 
|             curNPCSkill = curNPCManager.GetSkillByIndex(i)  | 
|             if curNPCSkill == None:  | 
|                 continue  | 
|             curNPCSkill.SetLastUseTick(0)  | 
|               | 
|         return  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## ³õʼ»¯NPCÕÙ»½ÊÞ  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks ³õʼ»¯NPCÕÙ»½ÊÞ  | 
|     def __InitNPCSummon(self):  | 
|         #½«Éæ¼°µ½C++ÖÐÁбíɾ³ýµÄ¹¦ÄÜ,ͳһ¸Ä³É -> ¸´ÖÆPyÁбíºó,È»ºó½øÐÐɾ³ýÂß¼ (ÒòWhileÓм¸Âʽ«µ¼ÖÂËÀËø)  | 
|         curNPC = self.__Instance  | 
|         curNPC_Summon_List = []  | 
|         for index in range(curNPC.GetSummonCount()):  | 
|             summonNPC = curNPC.GetSummonNPCAt(index)  | 
|             curNPC_Summon_List.append(summonNPC)  | 
|           | 
|         for curSummonNPC in curNPC_Summon_List:  | 
|             SetDeadEx(curSummonNPC)  | 
|           | 
|         return  | 
|           | 
|     #---------------------------------------------------------------------  | 
|     ## NPC×ßѲÂßµãÒÆ¶¯  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tick Ê±¼ä´Á  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks NPC×ßѲÂßµãÒÆ¶¯  | 
|     def __PatrolMove(self, tick):  | 
|         curNPC = self.__Instance  | 
|         #NPC×ßѲÂߵ㣬»ñȡѲÂßµã×ø±ê  | 
|         patrolIndex = curNPC.GetCurPatrolIndex()  | 
|         patrolPos = curNPC.GetPatrolPosAt(patrolIndex)  | 
|         patrolPosX = patrolPos.GetPosX()  | 
|         patrolPosY = patrolPos.GetPosY()  | 
|         curNPC_PosX = curNPC.GetPosX()  | 
|         curNPC_PosY = curNPC.GetPosY()  | 
|           | 
|         #---µ±Ç°Î»Öò»ÔÚѲÂßµã×ø±ê, ¿ìËÙ±¼ÅÜÖÁѲÂßµã  | 
|         if curNPC.GetCurMoveType() != IPY_GameWorld.mtSlow and \  | 
|                 (curNPC_PosX != patrolPosX or curNPC_PosY != patrolPosY):  | 
|             #Çл»ÖÁ¿ìËÙÒÆ¶¯×´Ì¬  | 
|             ChangeNPCMoveType(curNPC, IPY_GameWorld.mtRun)  | 
|             #GameWorld.Log('%s - ¼ì²éµ±Ç°Î»ÖÃÊÇ·ñΪѲÂßµã×ø±ê speed = %s, patrolPosX=%s, patrolPosY=%s'%(curNPC.GetName(), curNPC.GetSpeed(), patrolPosX, patrolPosY))  | 
|             curNPC.Move(patrolPosX, patrolPosY)  | 
|             return  | 
|           | 
|         #---½ÇÉ«ÒѾÔÚѲÂßµãÉÏ, Òƶ¯µ½ÏÂÒ»¸öѲÂßµã---  | 
|           | 
|         #»¹Î´µ½¿ÉÒÔÒÆ¶¯µÄʱ¼ä  | 
|         #if not IsInActionTime(patrolPos.GetMinStopTime(), patrolPos.GetMaxStopTime(), tick, curNPC.GetActionTick()):  | 
|         if not IsInActionTime(tick, curNPC.GetActionTick()):  | 
|             return  | 
|          | 
|         #ÊÇ·ñΪ×îºóÒ»¸öѲÂßµã,  | 
|         patrolIndex = patrolIndex + 1  | 
|           | 
|         if patrolIndex >= curNPC.GetPatrolPosCount():  | 
|             patrolIndex = 0  | 
|           | 
|         #ÉèÖÃÏÂÒ»¸öѲÂߵ㠠   | 
|         curNPC.SetCurPatrolIndex(patrolIndex)  | 
|         #»ñÈ¡ÏÂÒ»¸öѲÂßµã×ø±ê  | 
|         patrolPos = curNPC.GetPatrolPosAt(patrolIndex)  | 
|         patrolPosX = patrolPos.GetPosX()  | 
|         patrolPosY = patrolPos.GetPosY()  | 
|           | 
|         #¼ÓÈëÒ»¸ö·À·¶, Èç¹ûÖ»ÓÐÒ»¸öˢеã, »òÕßË¢ÐÂµã²¼ÖØ¸´, NPC²»Òƶ¯  | 
|         if curNPC_PosX == patrolPosX and curNPC_PosY == patrolPosY:  | 
|             return  | 
|               | 
|         #ÒÆ¶¯µ½Ñ²Âßµã  | 
|         #Çл»ÖÁÂýËÙÒÆ¶¯×´Ì¬  | 
|         ChangeNPCMoveType(curNPC, IPY_GameWorld.mtSlow)  | 
|         curNPC.Move(patrolPosX, patrolPosY)  | 
|         return  | 
|     #---------------------------------------------------------------------  | 
|     ## NPCÆÕÍ¨ÒÆ¶¯  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tick Ê±¼ä´Á  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks NPCÆÕÍ¨ÒÆ¶¯  | 
|     def DoNormalNPCMove(self, tick):  | 
|         curNPC = self.__Instance  | 
|           | 
|         if curNPC.GetPatrolPosCount() > 0:  | 
|             self.__PatrolMove(tick)  | 
|             return  | 
|           | 
|         #µÃµ½·¶Î§ÄÚËæ»úÒ»¸öµã, ÆÕͨС¹Ö×ß·¨  | 
|         PosMap = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|         if not PosMap:  | 
|             return  | 
|         moveArea = min(curNPC.GetMoveArea(), 2)  | 
|   | 
|         posX = curNPC.GetPosX()  | 
|         posY = curNPC.GetPosY()  | 
|         minMovePosX = posX - moveArea  | 
|         maxMovePosX = posX + moveArea  | 
|         minMovePosY = posY - moveArea  | 
|         maxMovePosY = posY + moveArea  | 
|   | 
|         #·¶Î§Ð£Ñé  | 
|         posMapX = PosMap.GetPosX()  | 
|         posMapY = PosMap.GetPosY()  | 
|         posMapArea = PosMap.GetArea()  | 
|           | 
|         minMovePosX = max(minMovePosX, posMapX - posMapArea)  | 
|         maxMovePosX = min(maxMovePosX, posMapX + posMapArea)  | 
|         minMovePosY = max(minMovePosY, posMapY - posMapArea)  | 
|         maxMovePosY = min(maxMovePosY, posMapY + posMapArea)  | 
|           | 
|         if minMovePosX > maxMovePosX:  | 
|             #NPCÒÆ¶¯Òì³£, Ë³ÒÆ»ØÈ¥  | 
|             self.MoveBack()  | 
|             return  | 
|           | 
|           | 
|         if minMovePosY > maxMovePosY:  | 
|             #NPCÒÆ¶¯Òì³£, Ë³ÒÆ»ØÈ¥  | 
|             self.MoveBack()  | 
|             return  | 
|           | 
|         #δµ½Òƶ¯Ê±¼ä  | 
|         #if not IsInActionTime(curNPC.GetMinStopTime(), curNPC.GetMaxStopTime(), tick, curNPC.GetActionTick()):  | 
|         if not IsInActionTime(tick, curNPC.GetActionTick()):      | 
|             return  | 
|           | 
|         posX = random.randint(minMovePosX, maxMovePosX)  | 
|         posY = random.randint(minMovePosY, maxMovePosY)  | 
|           | 
|         #Çл»ÖÁÂýËÙÒÆ¶¯×´Ì¬  | 
|         ChangeNPCMoveType(curNPC, IPY_GameWorld.mtSlow)  | 
|         #»ñµÃÒÆ¶¯µÄµã  | 
|         newPoint = GameWorld.GetMap().LineNearToPos(curNPC.GetPosX(), curNPC.GetPosY(),  | 
|                                                         posX, posY, 0)  | 
| #       if posX != newPoint.GetPosX() or posY != newPoint.GetPosY():  | 
| #           GameWorld.Log("Ô×ø±êX = %s,Y = %s ,ÐÞÕý×ø±ê X= %s,Y = %s"%(posX,posY,newPoint.GetPosX(),newPoint.GetPosY()))  | 
|         #NPCÒÆ¶¯  | 
|         curNPC.Move(newPoint.GetPosX(), newPoint.GetPosY())  | 
|         return  | 
|     #---------------------------------------------------------------------  | 
|     ## µÃµ½Ë¢Ð·¶Î§ÄÚËæ»úµÄÒ»µã×ø±ê[x,y]  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return [x,y]  | 
|     #  @remarks µÃµ½Ë¢Ð·¶Î§ÄÚËæ»úµÄÒ»µã×ø±êX  | 
|     def GetRandPosInRefreshArea(self):  | 
|         return GameWorld.GetPsycoFunc(self.__Func_GetRandPosInRefreshArea)()  | 
|       | 
|     ## µÃµ½Ë¢Ð·¶Î§ÄÚËæ»úµÄÒ»µã×ø±ê[x,y]  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return [x,y]  | 
|     #  @remarks µÃµ½Ë¢Ð·¶Î§ÄÚËæ»úµÄÒ»µã×ø±êX  | 
|     def __Func_GetRandPosInRefreshArea(self):  | 
|         curNPC = self.__Instance  | 
|         #µÃµ½µØÍ¼Ë¢Ð嵋  | 
|         posMap = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|         #·¶Î§Ð£Ñé  | 
|         posMapX = posMap.GetPosX()  | 
|         posMapY = posMap.GetPosY()  | 
|           | 
|         if curNPC.GetType() == IPY_GameWorld.ntFunctionNPC: #¹¦ÄÜNPC  | 
|             posMapArea = 0  | 
|         else:  | 
|             posMapArea = posMap.GetArea()  | 
|           | 
|         #»ñÈ¡·¶Î§ÄÚÒ»µã¿ÉÒÔÒÆ¶¯µÄµã  | 
|         posX, poxY = GameMap.GetNearbyPosByDis(posMapX, posMapY, posMapArea)  | 
|           | 
|         if posX == 0 and poxY == 0:  | 
|             return [posMapX, posMapY]  | 
|           | 
|         return posX, poxY  | 
|   | 
|     #---------------------------------------------------------------------  | 
|     ## ÊÇ·ñÔÚÒÆ¶¯·¶Î§ÄÚ  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÕæ, ÔÚÒÆ¶¯·¶Î§ÄÚ  | 
|     #  @remarks ÊÇ·ñÔÚÒÆ¶¯·¶Î§ÄÚ  | 
|     def IsInRefreshArea(self):  | 
|         #Õâ¸öNPCÊÇ·ñÔÚÒÆ¶¯·¶Î§ÄÚ  | 
|         curNPC = self.__Instance  | 
|         refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|         #GameWorld.Log("posX = %d posY = %d, dist = %d"%(refreshPoint.GetPosX(), refreshPoint.GetPosY(), refreshPoint.GetMoveDist()))  | 
|         if self.GetIsInRefreshPoint(curNPC.GetPosX() , curNPC.GetPosY() , refreshPoint):  | 
|             return True  | 
|           | 
|         #ÅжÏÊÇ·ñÕýÔÚÅÜ»ØÄ¿µÄµØ  | 
|         if curNPC.GetCurAction() == IPY_GameWorld.laNPCMove and \  | 
|                     curNPC.GetCurMoveType() == IPY_GameWorld.mtRun :  | 
|             #ÅжÏÄ¿µÄµØÊÇ·ñÔÚˢеãÄÚ  | 
|             if self.GetIsInRefreshPoint(curNPC.GetDestPosX() , curNPC.GetDestPosY() , refreshPoint):  | 
|                 return True  | 
|           | 
|         return False  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## ÊÇ·ñÔÚˢеãÄÚ  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param curPosX ×ø±êX  | 
|     #  @param curPosY ×ø±êY  | 
|     #  @param refreshPoint Ë¢ÐµãʵÀý  | 
|     #  @return ·µ»ØÖµÕæ, ÔÚˢеãÄÚ  | 
|     #  @remarks ÊÇ·ñÔÚˢеãÄÚ  | 
|     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  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## »Øµ½Ë¢Ð嵋  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks »Øµ½Ë¢Ð嵋  | 
|     def MoveBack(self):  | 
|         curNPC = self.__Instance  | 
|           | 
|         patrolCount = curNPC.GetPatrolPosCount()  | 
|         #Èç¹ûNPCÓÐѲÂßµã, »Øµ½Ëæ»úÒ»¸öѲÂßµã, Èç¹ûûÓÐ, ÔòËæ»úÔÚˢз¶Î§ÄÚÕÒÒ»¸öµã  | 
|         if patrolCount > 0:  | 
|             patrolIndex = random.randint(0, patrolCount - 1)  | 
|             patrolPos = curNPC.GetPatrolPosAt(patrolIndex)  | 
|             posX = patrolPos.GetPosX()  | 
|             posY = patrolPos.GetPosY()  | 
|         else:  | 
|             posX, posY = self.GetRandPosInRefreshArea()  | 
|           | 
|         #---×ß·»ØÈ¥Âß¼---  | 
|           | 
|         #³õʼ»¯, ·ÇÉËѪ±£»¤ÖвÅÖØÖà  | 
|         if not self.IsInHurtProtect():  | 
|             self.ResetNPC_Init()  | 
|         #Çл»ÖÁ¿ìËÙÒÆ¶¯×´Ì¬, ²¢ÇÒ¼¤»î³¬¼¶Òƶ¯  | 
|         ChangeNPCMoveType(curNPC, IPY_GameWorld.mtRun, True)  | 
|         curNPC.Move(posX, posY)  | 
|         #Ë²ÒÆ»ØÈ¥  | 
|         #curNPC.ResetPos(posX, posY)  | 
|         return  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## ÖØÉú  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tick Ê±¼ä´Á  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks ÖØÉú  | 
|     def DoNPCReborn(self, tick):  | 
|         curNPC = self.__Instance  | 
|         #ÖØÖÃNPCµÄÖØÉúµã  | 
|         curNPC.SetCurRefreshPointIndex(random.randint(0 , curNPC.GetRefreshPosCount() - 1))  | 
|         #¿ªÊ¼ÖØÉú  | 
|         posX, posY = self.GetRandPosInRefreshArea()  | 
|         #¸´»î  | 
|         curNPC.Reborn(posX, posY, False)  | 
|         self.DoNPCRebornCommLogic(tick)  | 
|         return 1  | 
|       | 
|     ## NPCÖØÉúͨÓÃÂß¼(²¼¹Öµã¼°Ë¢Ð±êʶµãͨÓÃ)  | 
|     def DoNPCRebornCommLogic(self, tick):   | 
|         curNPC = self.__Instance  | 
|         #³õʼ»¯  | 
|         self.ResetNPC_Init(True)  | 
|         #ÉèÖÃΪ×î´óѪÁ¿  | 
|         GameObj.SetHP(curNPC, GameObj.GetMaxHP(curNPC))  | 
|         #ÉèÖÃˢгðºÞ¼ä¸ô  | 
|         curNPC.GetNPCAngry().SetLastResortTick(tick)  | 
|         #֪ͨ¸´»îÌáʾ  | 
|         self.RebornNotify()  | 
|         #ÖØÖðٷֱÈÂß¼±êʶ  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_HPPerLogicMark, 0)  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_RebornPreNotifyIndex, 0)  | 
|         ChNPC.OnNPCReborn(curNPC)  | 
|         FBLogic.DoFBRebornNPC(curNPC, tick)  | 
|           | 
|         curNPCID = curNPC.GetNPCID()  | 
|               | 
|         # °µ½ðboss  | 
|         if ChConfig.IsGameBoss(curNPC):  | 
|             # Í¨Öª¿Í»§¶ËbossË¢ÐÂÌáÐÑ¿ªÆô  | 
|             #PlayerControl.WorldNotify(0, "Old_andyshao_671654", [curNPCID])  | 
|             # Í¨ÖªGameServer bossˢгɹ¦  | 
|             ipyData = IpyGameDataPY.GetIpyGameDataNotLog('BOSSInfo', curNPCID)  | 
|             if ipyData:  | 
|                 GameServe_GameWorldBossState(curNPCID, 1)  | 
|                 if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:  | 
|                     FamilyRobBoss.FamilyOwnerBossOnReborn(curNPC)  | 
|                       | 
|         # ¼ì²éÊÇ·ñÓй⻷, ÔÚÖØÉúʱ´¦Àí£¬²»È»¿ÉÄܵ¼ÖÂÓÐЩÎÞÕ½¶·Âß¼µÄ¹ÖÎïÎÞ·¨Ì×ÉϹ⻷buff  | 
|         skillManager = curNPC.GetSkillManager()  | 
|         for index in xrange(skillManager.GetSkillCount()):  | 
|             useSkill = skillManager.GetSkillByIndex(index)  | 
|             #ÒѾµ½Î²²¿ÁË  | 
|             if not useSkill or useSkill.GetSkillTypeID() == 0:  | 
|                 break  | 
|             if useSkill.GetSkillType() != ChConfig.Def_SkillType_Aura:  | 
|                 continue  | 
|             GameWorld.DebugLog("NPC¸´»î£¬Ì×ÉϹ⻷: objID=%s,npcID=%s,skillID=%s" % (curNPC.GetID(), curNPC.GetNPCID(), useSkill.GetSkillID()))  | 
|             SkillShell.NPCUseSkill(curNPC, useSkill, tick)  | 
|               | 
|         curNPC.NotifyAppear() # ×îÖÕͳһ֪ͨNPC³öÏÖ  | 
|         self.NotifyNPCShow(curNPCID, tick) # ¹ã²¥NPCÐã  | 
|         return  | 
|       | 
|     def NotifyNPCShow(self, npcID, tick):  | 
|         ## ¹ã²¥NPCÐã  | 
|         mapID = GameWorld.GetMap().GetMapID()  | 
|         npcShowIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCShow", npcID, mapID)  | 
|         if not npcShowIpyData:  | 
|             #GameWorld.DebugLog("²»ÐèÒªNPCÐã: npcID=%s" % npcID)  | 
|             return  | 
|         #if npcShowIpyData.GetBindMissionID():  | 
|         #    #GameWorld.DebugLog("Óаó¶¨ÈÎÎñIDµÄ£¬Ç°¶Ë×Ô¼ºÕ¹Ê¾NPCÐ㣡mapID=%s,npcID=%s" % (mapID, npcID))  | 
|         #    return  | 
|         if npcShowIpyData.GetShowType():  | 
|             #GameWorld.DebugLog("ǰ¶Ë×Ô¼ºÕ¹Ê¾µÄNPCÐ㣡mapID=%s,npcID=%s" % (mapID, npcID))  | 
|             return  | 
|         endTick = GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Def_FBDict_NPCShowEndTick % npcID)  | 
|         if endTick:  | 
|             #GameWorld.DebugLog("ÒѾ´æÔÚͬ¸öNPCIDµÄNPCÐ㣬²»Öظ´Õ¹Ê¾£¡npcID=%s" % (npcID))  | 
|             return  | 
|         endTick = tick + npcShowIpyData.GetProtectTime()  | 
|         GameWorld.GetGameFB().SetGameFBDict(ChConfig.Def_FBDict_NPCShowEndTick % npcID, endTick)  | 
|           | 
|         # ¹ã²¥µØÍ¼ÄÚÍæ¼ÒչʾNPCÐã  | 
|         npcShowPack = ChPyNetSendPack.tagMCNPCShow()  | 
|         npcShowPack.NPCID = npcID  | 
|         playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|         for index in xrange(playerManager.GetPlayerCount()):  | 
|             player = playerManager.GetPlayerByIndex(index)  | 
|             if not player.GetPlayerID():  | 
|                 continue  | 
|             NetPackCommon.SendFakePack(player, npcShowPack)  | 
|               | 
|         GameWorld.DebugLog("¿ªÊ¼NPCÐã: npcID=%s,tick=%s,endTick=%s" % (npcID, tick, endTick))  | 
|         return  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## ÖØÉúÈ«·þ¹ã²¥  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     def RebornNotify(self):  | 
|         #֪ͨ¸´»îÌáʾ  | 
|         #self.__NotifyBossReborn()  | 
|       | 
|         #֪ͨnpc¸´»îÌáʾ  | 
|         #self.__NotifySpecialNPCReborn()  | 
|         return  | 
|   | 
|     #---------------------------------------------------------------------  | 
|   | 
|     ## NPCÊ£ÓàѪÁ¿°Ù·Ö±ÈÂß¼  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param dropType µôÂäÀàÐÍ  | 
|     #  @param ownerID ÓµÓÐÕßid  | 
|     #  @return  | 
|     def DoHPPerLogic(self, dropType, ownerID):  | 
|         curNPC = self.__Instance  | 
|         curNPCID = curNPC.GetNPCID()  | 
|           | 
|         hpPerLogicNPCIDDict = IpyGameDataPY.GetFuncEvalCfg('BossHPInformation', 1, {})  | 
|         hpPerLogicList = GameWorld.GetDictValueByKey(hpPerLogicNPCIDDict, curNPCID)  | 
|         if not hpPerLogicList:  | 
|             return  | 
|         hpPerList, sysMark = hpPerLogicList  | 
|         hpPerList = sorted(hpPerList, reverse=True)  | 
|         nowHPPer = GameObj.GetHP(curNPC) * 100 / GameObj.GetMaxHP(curNPC) # µ±Ç°°Ù·Ö±È  | 
|         hpPerLogicMark = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_HPPerLogicMark)  | 
|         logicHPPerList = hpPerList[hpPerLogicMark:]  | 
|         #[80, 60, 40, 20, 10, 5]  | 
|         for hpPer in logicHPPerList:  | 
|               | 
|             if nowHPPer > hpPer:  | 
|                 break  | 
|               | 
|             #GameWorld.DebugLog("DoHPPerLogic npcID=%s,hpPerLogicDict=%s,nowHPPer=%s,hpPerLogicMark=%s,logicHPPerList=%s"   | 
|             #                   % (curNPCID, str(hpPerLogicDict), nowHPPer, hpPerLogicMark, str(logicHPPerList)))  | 
|               | 
|   | 
|             PlayerControl.WorldNotify(0, sysMark, [curNPCID, hpPer])  | 
|               | 
| #            if dropItemTemplate > 0:  | 
| #                self.__DropItemByTemplate(dropItemTemplate, dropType, ownerID)  | 
| #                PlayerControl.WorldNotify(0, "GeRen_admin_481766", [GameWorld.GetMap().GetMapID(), curNPCID, curNPCID])  | 
|               | 
|             hpPerLogicMark += 1  | 
|             #GameWorld.DebugLog("DoHPPerLogic update hpPerLogicMark=%s" % (hpPerLogicMark))  | 
|                   | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_HPPerLogicMark, hpPerLogicMark)  | 
|         return  | 
|       | 
|       | 
|     ## ¸ø¸½½üÍæ¼Ò¼Ó¹¦Ñ«  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param addPrestigeFormat ¼Ó¹¦Ñ«¹«Ê½  | 
|     #  @param matrix ·¶Î§´óС  | 
|     #  @return  | 
|     def __GiveNearbyPlayerPrestige(self, addPrestigeFormat, matrix=ChConfig.Def_Matrix_Three):  | 
| #        if addPrestigeFormat == '':  | 
| #            return  | 
| #        curNPC = self.__Instance  | 
| #        npcPosX = curNPC.GetPosX()  | 
| #        npcPosY = curNPC.GetPosY()  | 
| #        npcLV = curNPC.GetLV()  | 
| #        gameMap = GameWorld.GetMap()  | 
| #          | 
| #        for curPos in matrix:  | 
| #          | 
| #            #¼ì²éÓÐûÓжÔÏóÔÚÕâÒ»µãÉÏ  | 
| #            mapObj = gameMap.GetPosObj(npcPosX + curPos[0], npcPosY + curPos[1])  | 
| #              | 
| #            if not mapObj:  | 
| #                continue  | 
| #          | 
| #            #±éÀúµ±Ç°µã¶ÔÏó  | 
| #            for i in range(0, mapObj.GetObjCount()):  | 
| #              | 
| #                curObj = mapObj.GetObjByIndex(i)  | 
| #                curObjType = curObj.GetGameObjType()  | 
| #                  | 
| #                #²»ÊÇÍæ¼Ò£¬Ìø¹ý  | 
| #                if curObjType != IPY_GameWorld.gotPlayer:  | 
| #                    continue  | 
| #                  | 
| #                curTag = GameWorld.GetObj(curObj.GetID(), curObjType)  | 
| #                if not curTag:  | 
| #                    continue  | 
| #                playerLV = curTag.GetLV()  | 
| #                addPrestige = eval(addPrestigeFormat)  | 
| #                PlayerPrestigeSys.AddPrestigeOffcialLV(curTag, addPrestige, ChConfig.Def_AddPrestige_NPC)  | 
|   | 
|         return  | 
|           | 
|     #---------------------------------------------------------------------  | 
|     ## NPCËÀµÄʱºò, ¼ì²é×Ô¼ºÊÇ·ñÐèÒªÖØÉú. 0: tickºóÈÔÈ»ËÀÍö 1: tickºó¿ÉÒÔÖØÉú  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tick Ê±¼ä´Á  | 
|     #  @return ·µ»ØÖµÕæ, ÖØÉú³É¹¦  | 
|     #  @remarks NPCËÀµÄʱºò, ¼ì²é×Ô¼ºÊÇ·ñÐèÒªÖØÉú. 0: tickºóÈÔÈ»ËÀÍö 1: tickºó¿ÉÒÔÖØÉú  | 
|     def DieTick(self, tick):  | 
|         curNPC = self.__Instance  | 
|           | 
|         if curNPC.GetRefreshTime() == 0:  | 
|             #Ë¢ÐÂʱ¼äΪ0, ²»Ë¢Ð  | 
|             return 0  | 
|           | 
|         if curNPC.GetActionTick() == 0:  | 
|             GameWorld.DebugLog("¼ì²âµ½NPC¿ìËÙ¸´»î %s" % curNPC.GetID())  | 
|             curNPC.SetActionTick(tick)  | 
|               | 
|         remainTime = curNPC.GetRefreshTime() - (tick - curNPC.GetActionTick())  | 
|         if remainTime >= 0:  | 
|             #NPCËÀÍöʱ¼ä²»µ½Ë¢ÐÂʱ¼ä  | 
|             #self.__DoNPCRebornPreNotify(curNPC, remainTime)  | 
|             return 0  | 
|           | 
|         self.DoNPCReborn(tick)  | 
|         return 1  | 
|       | 
|     def __DoNPCRebornPreNotify(self, curNPC, remainTime):  | 
|         # ÔÝʱ¹Ø±Õ  | 
|         npcID = curNPC.GetNPCID()  | 
|         preRebornNotifyNPCDict = ReadChConfig.GetEvalChConfig("RebornPreNotifyNPC")  | 
|         if npcID not in preRebornNotifyNPCDict:  | 
|             return  | 
|         notifyMinuteList, notifyMark = preRebornNotifyNPCDict[npcID]  | 
|         notifyIndex = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_RebornPreNotifyIndex)  | 
|         if notifyIndex >= len(notifyMinuteList):  | 
|             return  | 
|           | 
|         reaminM = int(math.ceil(remainTime / 60000.0))  | 
|         notifyMinute = notifyMinuteList[notifyIndex]  | 
|         if reaminM > notifyMinute:  | 
|             return  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_RebornPreNotifyIndex, notifyIndex + 1)  | 
|         mapID = GameWorld.GetGameWorld().GetMapID()  | 
|         PlayerControl.WorldNotify(0, notifyMark, [npcID, npcID, notifyMinute, mapID, npcID, npcID])  | 
|         return  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## Ë¢ÐÂNPCÊôÐÔºÍÐÐΪ״̬  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param canSyncClient ÊÇ·ñ֪ͨ¿Í»§¶ËË¢ÐÂÐÅÏ¢(³èÎï)  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Ë¢ÐÂNPCÊôÐÔºÍÐÐΪ״̬  | 
|     def RefreshNPCState(self, canSyncClient=True, isReborn=False):  | 
|         self.RefreshNPCAttrState(canSyncClient, isReborn)  | 
|           | 
|         self.RefreshNPCActionState()  | 
|   | 
|   | 
|           | 
|     ## Ë¢ÐÂNPCÊôÐÔ  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param canSyncClient ÊÇ·ñ֪ͨ¿Í»§¶ËË¢ÐÂÐÅÏ¢(³èÎï)  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Ë¢ÐÂNPCÊôÐÔ  | 
|     def RefreshNPCAttrState(self, canSyncClient=True, isReborn=False):  | 
|         curNPC = self.__Instance  | 
|         #curNPCMaxHP_Before = GameObj.GetMaxHP(curNPC)  | 
|         #Çå¿ÕNPCÕ½¶·ÊôÐÔ  | 
|         curNPC.ClearBattleEffect()  | 
|         #--------------------------------------------  | 
|         #ÖØÖÃNPCÕ½¶·ÊôÐÔ  | 
|         curNPC.ResetNPCBattleState()  | 
|         ############################################  | 
|         #³õʼ»¯×´Ì¬  | 
|         curNPC.SetSpeed(curNPC.GetOrgSpeed())  | 
|         curNPC.SetAtkInterval(curNPC.GetBaseAtkInterval())  | 
|   | 
| #        #ÏÈÇå¿ÕÒì³£  | 
| #        if curNPC.GetAbnormalState() != IPY_GameWorld.sctInvalid:  | 
| #            curNPC.SetAbnormalState(IPY_GameWorld.sctInvalid)  | 
| #  | 
| #        #Çå¿Õ½ûÖ¹  | 
| #        curNPC.ForbiddenSkillTypeList_Clear()  | 
|       | 
|         #³èÎïÌØÊâ´¦Àí  | 
|         if curNPC.GetGameNPCObjType() == IPY_GameWorld.gnotPet:  | 
|             PetControl.RefurbishPetAttr(curNPC, canSyncClient)  | 
|             return  | 
|           | 
|         DoNPCAttrStrengthen(curNPC, isReborn)  | 
|   | 
|         #¼ÆËãbuf¶ÔÕ½¶·ÊôÐÔµÄ¸Ä±ä  | 
|         allAttrList = SkillShell.CalcBuffer_NPCBattleEffect(curNPC)  | 
|           | 
|         self.RefreshNPCSpeed(allAttrList)  | 
|         #¼ì²éѪÁ¿ÊÇ·ñ±ä»¯, Ôݲ»×öѪÁ¿Ôö¼ÓÉÏÏÞ֪ͨ£¬½öÊôÐÔÉÏÏÞÖ§³Ö£»  | 
|         #¿Í»§¶Ë×Ô¼ºËãѪÁ¿ÉÏÏÞ  | 
| #        if curNPC.GetMaxHP() != curNPCMaxHP_Before:  | 
| #            curNPC.Notify_MaxHP()  | 
|               | 
|         return  | 
|       | 
|     def SetHelpBattleRobotRebornAttr(self, fightPower):  | 
|         '''ÖúÕ½»úÆ÷ÈËÖ»ÉèÖÃѪÁ¿ÊôÐÔ  | 
|                         ÑªÁ¿Ëã·¨£¬£¨ÖúÕ½Íæ¼Ò=ÖúÕ½»úÆ÷ÈË£©£ºÃ¿¸ö¸±±¾ÅäÖÃÉ˺¦*£¨ÖúÕ½Íæ¼ÒÕ½Á¦/¸±±¾¹æ¶¨Õ½Á¦£©*ϵÊýÖµ  ÏµÊýÖµÔݶ¨Îª50  | 
|         '''  | 
|         curNPC = self.__Instance  | 
|         mapID = FBCommon.GetRecordMapID(GameWorld.GetMap().GetMapID())  | 
|         funcLineID = FBCommon.GetFBPropertyMark()  | 
|         ipyData = IpyGameDataPY.GetIpyGameData("FBHelpBattle", mapID, funcLineID)  | 
|         if not ipyData:  | 
|             return  | 
|           | 
|         SetSuppressFightPower(curNPC, fightPower)  | 
|         fbFightPower = ipyData.GetFightPowerMin()  | 
|         baseHurt = ipyData.GetRobotBaseHurt()  | 
|         hpCoefficient = ipyData.GetRobotHPCoefficient()  | 
|         maxHP = int(eval(IpyGameDataPY.GetFuncCompileCfg("HelpBattleRobot", 2)))  | 
|         GameWorld.DebugLog("ÉèÖÃÖúÕ½»úÆ÷ÈËÊôÐÔ: objID=%s,fightPower=%s,maxHP=%s" % (curNPC.GetID(), fightPower, maxHP))  | 
|         GameObj.SetMaxHP(curNPC, maxHP)  | 
|         GameObj.SetHP(curNPC, maxHP)  | 
|         curNPC.Notify_HPEx()  | 
|         curNPC.Notify_MaxHPEx()  | 
|         return  | 
|       | 
|     # NPCÒÆ¶¯ËÙ¶ÈÌØÊâ´¦Àí£¬Ö»´¦Àí°Ù·Ö±È²»ÄÜ´¦Àí¹Ì¶¨Öµ   | 
|     # ÒòΪ ChConfig.TYPE_Calc_AttrSpeed ·Ç·þÎñ¶ËÒÆ¶¯ËÙ¶È£¬ÍµÀÁ´¦Àí·¨  | 
|     def RefreshNPCSpeed(self, allAttrList):  | 
|         curNPC = self.__Instance  | 
|           | 
|         speedPer = allAttrList[ChConfig.CalcAttr_BattleNoline].get(ChConfig.TYPE_Calc_AttrSpeed, 0)  | 
|         if not speedPer:  | 
|             if curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SpeedPer):  | 
|                 curNPC.SetDict(ChConfig.Def_NPC_Dict_SpeedPer, 0)  | 
|         else:  | 
|             speed = int(curNPC.GetSpeed() * (ShareDefine.Def_MaxRateValue) / max(100.0, float(ShareDefine.Def_MaxRateValue + speedPer)))  | 
|             curNPC.SetSpeed(speed)  | 
|             curNPC.SetDict(ChConfig.Def_NPC_Dict_SpeedPer, speedPer)  | 
|         if GameWorld.GetMap().GetMapID() == ChConfig.Def_FBMapID_GatherSoul:  | 
|             #ĿǰֻÔھۻ긱±¾Àï֪ͨ  | 
|             NPCSpeedChangeNotify(curNPC, curNPC.GetSpeed())  | 
|         return  | 
|       | 
|       | 
|     ## Ë¢ÐÂNPCÐÐΪÊôÐÔ  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Ë¢ÐÂNPCÐÐΪÊôÐÔ  | 
|     def RefreshNPCActionState(self):  | 
|         curNPC = self.__Instance  | 
|         OperControlManager.ClearObjActionState(curNPC)  | 
|           | 
|         #¸ù¾ÝBUFF ¼ÓÉÏ״̬  | 
|         SkillShell.CalcBuffer_ActionState(curNPC)  | 
|           | 
|           | 
|     #---------------------------------------------------------------------  | 
|     ## Ë¢ÐÂBuff״̬  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tick Ê±¼ä´Á  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Ë¢ÐÂBuff״̬  | 
|     def RefreshBuffState(self, tick):  | 
|         #´¦Àí²»¼°Ê±Ë¢ÐµÄBUFF  | 
|         refreshA = self.RefreshBuffStateNoTimely(tick)  | 
|         #´¦Àí¼°Ê±Ë¢ÐµÄBUFF  | 
|         refreshB = self.RefreshBuffStateTimely(tick)  | 
|           | 
|         if refreshA or refreshB:  | 
|             self.RefreshNPCAttrState()  | 
|               | 
|               | 
|     ## Ë¢ÐÂBuff״̬, ´¦Àí²»Ð輰ʱˢеÄBUFF £¬¹ØºõË¢ÐÂÊôÐ﵀  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tick Ê±¼ä´Á  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Ë¢ÐÂBuff״̬,´¦Àí²»Ð輰ʱˢеÄBUFF £¬¹ØºõË¢ÐÂÊôÐ﵀  | 
|     def RefreshBuffStateNoTimely(self, tick):  | 
|         curNPC = self.__Instance  | 
|         if tick - curNPC.GetTickByType(ChConfig.TYPE_NPC_Tick_Buff) <= ChConfig.TYPE_NPC_Tick_Time[ChConfig.TYPE_NPC_Tick_Buff]:  | 
|             #ˢмä¸ôûµ½  | 
|             return  | 
|           | 
|         #¼ì²âÊÇ·ñÓÐbuffÒªÏûʧ  | 
|         curNPC.SetTickByType(ChConfig.TYPE_NPC_Tick_Buff, tick)  | 
|         refresh = False  | 
|   | 
|         result = BuffSkill.RefreshBuff(curNPC, curNPC.GetBuffState(), tick)  | 
|         refresh = refresh or result[0]  | 
|           | 
|         result = BuffSkill.RefreshBuff(curNPC, curNPC.GetDeBuffState(), tick)  | 
|         refresh = refresh or result[0]  | 
|           | 
|         result = BuffSkill.RefreshBuff(curNPC, curNPC.GetAura(), tick)  | 
|         refresh = refresh or result[0]  | 
|   | 
|         #¹â»·ÐÍBuff¼ì²é¹âÔ´  | 
|         SkillCommon.CheckAddAuraSkill(curNPC, tick)  | 
|         result = SkillCommon.CheckAuraSkill(curNPC, tick)  | 
|   | 
|         return refresh or result  | 
|               | 
|       | 
|     ## Ë¢ÐÂBuff״̬, ´¦ÀíÐ輰ʱˢеÄBUFF £¬Ä¿Ç°²»Ë¢ÐÂÊôÐÔ  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tick Ê±¼ä´Á  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Ë¢ÐÂBuff״̬ ´¦ÀíÐ輰ʱˢеÄBUFF £¬Ä¿Ç°²»Ë¢ÐÂÊôÐÔ  | 
|     def RefreshBuffStateTimely(self, tick):  | 
|         curNPC = self.__Instance  | 
|         if tick - curNPC.GetTickByType(ChConfig.TYPE_NPC_Tick_Buff_Timely) \  | 
|                 <= ChConfig.TYPE_NPC_Tick_Time[ChConfig.TYPE_NPC_Tick_Buff_Timely]:  | 
|             #ˢмä¸ôûµ½  | 
|             return  | 
|           | 
|         #¼ì²âÊÇ·ñÓÐbuffÒªÏûʧ  | 
|         curNPC.SetTickByType(ChConfig.TYPE_NPC_Tick_Buff_Timely, tick)  | 
|           | 
|         BuffSkill.RefreshBuff(curNPC, curNPC.GetProcessBuffState(), tick)  | 
|         BuffSkill.RefreshBuff(curNPC, curNPC.GetProcessDeBuffState(), tick)  | 
|   | 
|         #ÐÐΪBUFFˢР ÊÇ·ñÓÐBUFFÏûʧ  | 
|         result = BuffSkill.RefreshBuff(curNPC, curNPC.GetActionBuffManager(), tick)  | 
|   | 
|         if result[1]:  | 
|             self.RefreshNPCActionState()  | 
|           | 
|         #³ÖÐøÐÔBUFF´¦Àí  | 
|         SkillShell.ProcessPersistBuff(curNPC, tick)  | 
|           | 
|         # ÊÇ·ñÐèҪˢÊôÐÔ  | 
|         return result[0]  | 
|           | 
|     #---------------------------------------------------------------------  | 
|     ## NPCËÀÍöÏà¹ØÂß¼  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµËµÃ÷  | 
|     #  @remarks NPCËÀÍöÏà¹ØÂß¼  | 
|     def __KillLogic(self):  | 
|         curNPC = self.__Instance  | 
|         npcID = curNPC.GetNPCID()  | 
|         #######################ÌØÊâNPCµÄ´¦Àí  | 
|         #=====================================================================================================  | 
|         # if curNPC.GetGameNPCObjType() == IPY_GameWorld.gnotTruck:  | 
|         #    #Èç¹ûÊÇæô³µËÀÍö, µ÷ÓÃæô³µËÀÍöÂß¼  | 
|         #    PlayerTruck.DoTruckDestroy(curNPC)  | 
|         #=====================================================================================================  | 
|           | 
|         #bossÉËѪÅÅÐаñ»÷ɱÂß¼  | 
|         #BossHurtMng.BossOnKilled(curNPC)  | 
|           | 
|         #µôÂäÐèÒªÓõ½Ãþ¹Ö£¬ËùÒÔÔÚ´¦ÀíµôÂä½±ÀøÖ®Ç°ÉèÖà  | 
|         self.__SetFeelNPCPlayerList()  | 
|           | 
|         #ɱËÀNPC,¶ÔÏó½±Àø  | 
|         self.__GiveObjPrize()  | 
|           | 
|         #ɱËÀNPC, ´¥·¢ÈÎÎñ  | 
|         self.__EventKillNpc()  | 
|               | 
|         mapID = GameWorld.GetMap().GetMapID()  | 
|         killerName = "" if not self.__Killer else self.__Killer.GetPlayerName()  | 
|         # ¼Ç¼boss»÷ɱÐÅÏ¢µÄNPC  | 
|         bossIpyData = IpyGameDataPY.GetIpyGameDataListNotLog('BOSSInfo', npcID)  | 
|         if bossIpyData and mapID not in [ChConfig.Def_FBMapID_ZhuXianBoss, ChConfig.Def_FBMapID_SealDemon]:  | 
|             if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:  | 
|                 killerName = FamilyRobBoss.FamilyOwnerBossOnKilled(curNPC, self.__OwnerHurtID)  | 
|             #KillerJob = 0 if not self.__Killer else self.__Killer.GetJob()  | 
|             killerIDList = [player.GetPlayerID() for player in self.__ownerPlayerList]  | 
|             GameServer_KillGameWorldBoss(curNPC.GetNPCID(), killerName, 0, True, killerIDList)  | 
|         #===========================================================================================  | 
|         # # °µ½ðboss  | 
|         # if curNPC.GetIsBoss() == ChConfig.Def_NPCType_Boss_Dark:  | 
|         #    #PlayerControl.WorldNotify(0, "Old_andyshao_861048", [curNPC.GetNPCID()])  | 
|         #    if mapID == ChConfig.Def_MapID_DouHunTan:  | 
|         #        NPCCustomRefresh.DoRefreshNeutralBoss(npcID)  | 
|         #   | 
|         # # ÖÜÎ§Íæ¼Ò¼ÓÍþÍû  | 
|         # npcKilledAddPrestigeDict = ReadChConfig.GetEvalChConfig('NPCKilledAddPrestige')  | 
|         # if npcID in npcKilledAddPrestigeDict:  | 
|         #    addPrestigeFormat = npcKilledAddPrestigeDict[npcID]  | 
|         #    self.__GiveNearbyPlayerPrestige(addPrestigeFormat, ChConfig.Def_Matrix_Six)  | 
|         #===========================================================================================  | 
|                   | 
|         #Çå¿ÕNPCµÄ³ðºÞ  | 
|         curNPC.GetNPCAngry().Clear()  | 
|         return  | 
|       | 
|     def __SetFeelNPCPlayerList(self):  | 
|         ## ÉèÖÃÓÐÃþ¹ÖµÄÍæ¼ÒÁÐ±í£¬º¬»÷ɱÕß  | 
|         curNPC = self.__Instance  | 
|         self.__FeelPlayerList = []  | 
|           | 
|         npcHurtList = curNPC.GetPlayerHurtList()  | 
|         #npcHurtList.Sort()  #ÕâÀï²»ÅÅÐò£¬Ö»ÒªÓÐÉ˺¦¾ÍËã  | 
|           | 
|         eventPlayerList = []  | 
|         for index in xrange(npcHurtList.GetHurtCount()):  | 
|               | 
|             #»ñµÃÉËѪ¶ÔÏó  | 
|             hurtObj = npcHurtList.GetHurtAt(index)  | 
|             hurtObjType = self.__GetTagByHurtObj(hurtObj)  | 
|               | 
|             #µ±Ç°ÉËѪ¶ÔÏ󳬳öÖ¸¶¨·¶Î§»òÒѾËÀÍö  | 
|             if not hurtObjType :  | 
|                 continue  | 
|               | 
|             curPlayer = hurtObjType[0]  | 
|             curTeam = hurtObjType[1]  | 
|               | 
|             #¸öÈË  | 
|             if curPlayer:  | 
|                 if curPlayer not in eventPlayerList:  | 
|                     eventPlayerList.append(curPlayer)  | 
|             #¶ÓÎé  | 
|             if curTeam:  | 
|                 #¶ÓÔ±ÁÐ±í  | 
|                 playerlist = PlayerControl.GetAreaTeamMember(curTeam, curNPC.GetPosX(), curNPC.GetPosY())  | 
|                 #±éÀú¶ÓÎé,°ë¾¶ÎªÒ»ÆÁ°ëµÄ¾àÀëÄÚµÄËùÓжÓÎé/ÍŶӳÉÔ±£¬¿ÉÒÔ»ñµÃ¾Ñé  | 
|                 for teamPlayer in playerlist:  | 
|                     if teamPlayer not in eventPlayerList:  | 
|                         eventPlayerList.append(teamPlayer)  | 
|         self.__FeelPlayerList = eventPlayerList  | 
|         return  | 
|       | 
|     ## É±ËÀNPC, ´¥·¢ÈÎÎñ  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return None  | 
|     def __EventKillNpc(self):  | 
|           | 
|         # ´¥·¢¹éÊôÈÎÎñʼþ  | 
|         if self.__Killer:  | 
|             self.__MissionOnKillNPC(self.__Killer)  | 
|               | 
|         for eventPlayer in self.__FeelPlayerList:  | 
|             if self.__Killer and self.__Killer.GetPlayerID() == eventPlayer.GetPlayerID():  | 
|                 continue  | 
|             self.__MissionOnKillNPC(eventPlayer, True)  | 
|         return  | 
|       | 
|       | 
|     #---------------------------------------------------------------------  | 
|     def __GetDropMoneyModelID(self, moneyValue):  | 
|         ## »ñÈ¡µôÂä½ð±ÒÄ£ÐÍID  | 
|         if not moneyValue:  | 
|             return 0  | 
|         moneyItemList = IpyGameDataPY.GetFuncEvalCfg("GoldModel", 1) # ½ð±ÒµôÂäÊýÁ¿¶ÔӦģÐÍ-[(×î´ó½ð±ÒÊý,ÎïÆ·Ä£ÐÍID), ...]  | 
|         if not moneyItemList:  | 
|             return 0  | 
|         for count, moneyID in moneyItemList:  | 
|             if moneyValue <= count:  | 
|                 return moneyID  | 
|         return moneyItemList[-1][1]  | 
|       | 
|     def __NPCSpecialDropItem(self, dropPlayer, ownerPlayerList, ipyDrop):  | 
|         '''ÌØÊâµôÂä (˽ÓÐÌØÊâµôÂä + »÷ɱ´ÎÊýÌØÊâµôÂä), Ö§³ÖÃþ¹Ö  | 
|         @return: None  | 
|         @return: [[ownerPlayer, itemID, isAuctionItem, isDropInItemPack], ...]  | 
|         '''  | 
|         curNPC = self.__Instance  | 
|         npcID = curNPC.GetNPCID()  | 
|         specDropItemList = []  | 
|           | 
|         playerLV = dropPlayer.GetLV()  | 
|         maxDropLV = ipyDrop.GetMaxDropLV()  | 
|         if maxDropLV and playerLV > maxDropLV:  | 
|             GameWorld.DebugLog("³¬¹ý×î´ó¿ÉµôÂäµÈ¼¶£¬²»µôÂäÎïÆ·£¬ÌØÊâµôÂ䣡npcID=%s,playerLV(%s) > maxDropLV(%s)" % (npcID, playerLV, maxDropLV))  | 
|             return specDropItemList  | 
|           | 
|         auctionItemCanSell = ipyDrop.GetAucionItemCanSell()  | 
|         # »÷ɱ´ÎÊýµôÂäËãÃþ¹Ö  | 
|         killCountDropInfo = ipyDrop.GetKillCountDropPri()  | 
|         if killCountDropInfo:  | 
|             for feelPlayer in self.__FeelPlayerList:  | 
|                 needKillCount, killDropItemList, isDropInItemPack = killCountDropInfo  | 
|                 killCountDropItemList = GetKillCountDropItemList(feelPlayer, npcID, needKillCount, killDropItemList)  | 
|                 for dropItemID in killCountDropItemList:  | 
|                     isAuctionItem = 1 if auctionItemCanSell and IpyGameDataPY.GetIpyGameDataNotLog("AuctionItem", dropItemID) else 0  | 
|                     specDropItemList.append([feelPlayer, dropItemID, isAuctionItem, isDropInItemPack])  | 
|                     GameWorld.DebugLog("»÷ɱ´ÎÊý±Øµô(¿ÉÃþ¹Ö): npcID=%s,dropItemID=%s,needKillCount=%s,isDropInItemPack=%s,isAuctionItem=%s"   | 
|                                        % (npcID, dropItemID, needKillCount, isDropInItemPack, isAuctionItem), feelPlayer.GetPlayerID())  | 
|                       | 
|         # Ë½ÓеôÂä  | 
|         isDropInItemPack = False  | 
|         fbGradePriItemIDDropDict = IpyGameDataPY.GetFuncEvalCfg("FBGradeEquipDropRate", 3)  | 
|         if npcID in fbGradePriItemIDDropDict:  | 
|             gradePriItemIDDropDict = fbGradePriItemIDDropDict[npcID]  | 
|             curGrade = GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Def_FB_Grade)  | 
|             priDropInfoList = gradePriItemIDDropDict.get(curGrade, [])  | 
|             priDropIDList = []  | 
|             for priItemID, priItemCount in priDropInfoList:  | 
|                 priDropIDList += [priItemID] * priItemCount  | 
|         else:  | 
|             priDropIDList = ipyDrop.GetPriItemIDDrop()  | 
|         for dropItemID in priDropIDList:  | 
|             isAuctionItem = 1 if auctionItemCanSell and IpyGameDataPY.GetIpyGameDataNotLog("AuctionItem", dropItemID) else 0  | 
|             for ownerPlayer in ownerPlayerList:  | 
|                 specDropItemList.append([ownerPlayer, dropItemID, isAuctionItem, isDropInItemPack]) # Ä¬ÈÏ°ó¶¨  | 
|                 #GameWorld.DebugLog("˽ÓÐÎïÆ·µôÂä: dropItemID=%s" % dropItemID, ownerPlayer.GetPlayerID())  | 
|                   | 
|         return specDropItemList  | 
|   | 
|     def __NPCDropItemByPlayers(self, dropPlayerList, mapID, ipyDrop):  | 
|         '''NPCµôÂäÎïÆ·, ¶àÍæ¼ÒÿÈËÒ»·Ý, »ìºÏµôÂä'''  | 
|         curNPC = self.__Instance  | 
|         npcID = curNPC.GetNPCID()  | 
|         if not dropPlayerList:  | 
|             return  | 
|           | 
|         #GameWorld.DebugLog("NPC¶àÍæ¼Ò»ìºÏµôÂä: dropPlayerCount=%s" % len(dropPlayerList))  | 
|         auctionItemIDList = []  | 
|         dropItemList = []  | 
|         for dropPlayer in dropPlayerList:  | 
|             dropInfo = GetNPCDropInfo(dropPlayer, mapID, npcID, ipyDrop=ipyDrop)  | 
|             if not dropInfo:  | 
|                 continue  | 
|             dropIDList, auctionIDList, dropMoneyCnt, moneyValue = dropInfo  | 
|             moneyID = self.__GetDropMoneyModelID(moneyValue)  | 
|             if dropMoneyCnt:  | 
|                 dropIDList += [moneyID] * dropMoneyCnt  | 
|                   | 
|             dropPlayerID = dropPlayer.GetPlayerID()  | 
|             #GameWorld.DebugLog("    dropPlayerID=%s,dropIDList=%s" % (dropPlayerID, dropIDList))  | 
|             for dropID in dropIDList:  | 
|                 dropItemList.append([dropID, dropPlayerID])  | 
|             auctionItemIDList += auctionIDList  | 
|               | 
|         #´òÂÒÎïÆ·Ë³Ðò  | 
|         random.shuffle(dropItemList)  | 
|           | 
|         gameMap = GameWorld.GetMap()  | 
|         dropPosX, dropPosY = curNPC.GetPosX(), curNPC.GetPosY() # ÒÔNPCΪÖÐÐĵ㿪ʼµôÂä  | 
|         index = 0  | 
|         for posX, posY in ChConfig.Def_DropItemAreaMatrix:  | 
|             resultX = dropPosX + posX  | 
|             resultY = dropPosY + posY  | 
|               | 
|             if not gameMap.CanMove(resultX, resultY):  | 
|                 #Íæ¼Ò²»¿ÉÒÆ¶¯Õâ¸öµã  | 
|                 continue  | 
|               | 
|             if index > len(dropItemList) - 1:  | 
|                 break                          | 
|             itemID, ownerID = dropItemList[index]  | 
|             index += 1  | 
|             itemCnt = moneyValue if itemID == moneyID else 1  | 
|             iaAuctionItem = itemID in auctionItemIDList  | 
|             curItem = self.__CreateDropItem(curNPC, itemID, itemCnt, iaAuctionItem, dropPlayer)  | 
|             if not curItem:  | 
|                 continue  | 
|             self.__MapCreateItem(curItem, resultX, resultY, ChConfig.Def_NPCHurtTypePlayer, ownerID)  | 
|               | 
|         return  | 
|       | 
|     ## ÎïÆ·µôÂä  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param dropPlayer µôÂäÅжÏÏà¹ØÍæ¼Ò  | 
|     #  @param HurtType ÉËѪÀàÐÍ  | 
|     #  @param HurtID ÉËѪID  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     def __NPCDropItem(self, dropPlayer, hurtType, hurtID, ownerPlayerList=[]):  | 
|         if not dropPlayer:  | 
|             return  | 
|         curNPC = self.__Instance  | 
|         if curNPC.GetType() in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]:  | 
|             GameWorld.DebugLog("ľ׮¹Ö£¬²»µôÂäÎïÆ·£¡")  | 
|             return  | 
|         npcID = curNPC.GetNPCID()  | 
|         mapID = GameWorld.GetMap().GetMapID()  | 
|         mapID = FBCommon.GetRecordMapID(mapID)  | 
|         isGameBoss = ChConfig.IsGameBoss(curNPC)  | 
|         if mapID in [ChConfig.Def_FBMapID_MunekadoTrial, ChConfig.Def_FBMapID_DemonKing, ChConfig.Def_FBMapID_SealDemon, ChConfig.Def_FBMapID_ZhuXianBoss]:  | 
|             GameWorld.DebugLog("¸ÃµØÍ¼²»×ßÖ±½ÓµôÂäÎïÆ·Âß¼£¡mapID=%s" % mapID)              | 
|             return  | 
|         if isGameBoss:  | 
|             GameWorld.Log("NPC¿ªÊ¼µôÂä: npcID=%s,dropPlayerID=%s" % (npcID, dropPlayer.GetPlayerID()), dropPlayer.GetPlayerID())  | 
|         ipyDrop = GetNPCDropIpyData(npcID)  | 
|         if not ipyDrop:  | 
|             if isGameBoss:  | 
|                 curWorldLV = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)  | 
|                 GameWorld.ErrLog("È¡²»µ½NPCµôÂäÐÅÏ¢!npcID=%s,curWorldLV=%s" % (npcID, curWorldLV))  | 
|             return  | 
|           | 
|         #if mapID == ChConfig.Def_FBMapID_MunekadoTrial:  | 
|         #    dropPlayerList = GameLogic_MunekadoTrial.GetCanDropPlayerList()  | 
|         #    return self.__NPCDropItemByPlayers(dropPlayerList, mapID, ipyDrop)  | 
|           | 
|         dropIDList, auctionIDList, dropMoneyCnt, moneyValue = [], [], 0, 0  | 
|         dropInfo = GetNPCDropInfo(dropPlayer, mapID, npcID, ownerPlayerList, ipyDrop, False)  | 
|         if dropInfo:  | 
|             dropIDList, auctionIDList, dropMoneyCnt, moneyValue = dropInfo  | 
|               | 
|         moneyID = self.__GetDropMoneyModelID(moneyValue)  | 
|         if moneyID and dropMoneyCnt:  | 
|             dropIDList += [moneyID] * dropMoneyCnt  | 
|               | 
|         specItemSign = "SpecItem"  | 
|         playerSpecDropList = self.__NPCSpecialDropItem(dropPlayer, ownerPlayerList, ipyDrop) # ÌØÊâµôÂä [[ownerPlayer, itemID, isAuctionItem, isDropInItemPack], ...]  Ë½ÓÐÌØÊâµôÂä + »÷ɱ´ÎÊýÌØÊâµôÂä  | 
|         dropIDList += [specItemSign] * len(playerSpecDropList)  | 
|           | 
|         if len(dropIDList) > 5:  | 
|             #´òÂÒÎïÆ·Ë³Ðò  | 
|             random.shuffle(playerSpecDropList)  | 
|             random.shuffle(dropIDList)  | 
|               | 
|         if not dropIDList and isGameBoss:  | 
|             GameWorld.ErrLog("BossûÓеôÂä: dropPlayerLV=%s,ipyWorldLV=%s,maxDropLV=%s"   | 
|                              % (dropPlayer.GetLV(), ipyDrop.GetMaxWorldLV(), ipyDrop.GetMaxDropLV()), dropPlayer.GetPlayerID())  | 
|               | 
|         gameMap = GameWorld.GetMap()  | 
|         dropPosX, dropPosY = curNPC.GetPosX(), curNPC.GetPosY() # ÒÔNPCΪÖÐÐĵ㿪ʼµôÂä  | 
|         index = 0  | 
|         for posX, posY in ChConfig.Def_DropItemAreaMatrix:  | 
|             resultX = dropPosX + posX  | 
|             resultY = dropPosY + posY  | 
|               | 
|             if not gameMap.CanMove(resultX, resultY):  | 
|                 #Íæ¼Ò²»¿ÉÒÆ¶¯Õâ¸öµã  | 
|                 continue  | 
|               | 
|             if index > len(dropIDList) - 1:  | 
|                 break  | 
|               | 
|             isDropInItemPack = False  | 
|             itemID = dropIDList[index]  | 
|             index += 1  | 
|             if itemID == specItemSign:  | 
|                 if not playerSpecDropList:  | 
|                     continue  | 
|                 itemCnt = 1  | 
|                 ownerPlayer, itemID, isAuctionItem, isDropInItemPack = playerSpecDropList[0]  | 
|                 ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, ownerPlayer.GetPlayerID()  | 
|                 playerSpecDropList = playerSpecDropList[1:]  | 
|             else:  | 
|                 ownerPlayer = dropPlayer  | 
|                 ownerType, ownerID = hurtType, hurtID  | 
|                 itemCnt = moneyValue if itemID == moneyID else 1  | 
|                 isAuctionItem = itemID in auctionIDList  | 
|                   | 
|             curItem = self.__CreateDropItem(curNPC, itemID, itemCnt, isAuctionItem, dropPlayer)  | 
|             if not curItem:  | 
|                 continue  | 
|               | 
|             if mapID == ChConfig.Def_FBMapID_GatherSoul:#¾Û»ê¸±±¾ÌØÊâ´¦Àí  | 
|                 GameLogic_GatherSoul.KillGatherSoulNPCDropAward(itemID, itemCnt, isAuctionItem)  | 
|                 dropItemDataStr = ChItem.GetMapDropItemDataStr(curItem)  | 
|                 SendVirtualItemDrop(ownerPlayer, itemID, resultX, resultY, dropItemDataStr)  | 
|                 curItem.Clear()  | 
|                 continue  | 
|               | 
|             if isDropInItemPack:  | 
|                 curItem.SetUserAttr(ShareDefine.Def_IudetSource, ShareDefine.Item_Source_VirtualItemDrop)  | 
|                 dropItemDataStr = ChItem.GetMapDropItemDataStr(curItem)  | 
|                 #¿ÉÒÔ·ÅÈë±³°ü  | 
|                 if ItemControler.DoLogic_PutItemInPack(ownerPlayer, curItem, event=["NPCDrop", False, {"npcID":npcID}]):  | 
|                     #֪ͨ¿Í»§¶Ë  | 
|                     SendVirtualItemDrop(ownerPlayer, itemID, resultX, resultY, dropItemDataStr)  | 
|                       | 
|             else:  | 
|                 self.__MapCreateItem(curItem, resultX, resultY, ownerType, ownerID)  | 
|         return  | 
|     #---------------------------------------------------------------------  | 
|     ## NPC±»É±ËÀÂß¼´¦Àí  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks NPC±»É±ËÀÂß¼´¦Àí  | 
|     def SetKilled(self):  | 
|         curNPC = self.__Instance  | 
|         #µ÷ÓÃÍæ¼Ò½±Àø  | 
|         self.__KillLogic()  | 
|         #ÉèÖôËNPCΪ¿ÕѪ״̬  | 
|         GameObj.SetHP(curNPC, 0)  | 
|         #Ìæ»»³ðºÞ  | 
|         #self.__NPCReplaceAngry()  | 
|         #Çå³ý״̬  | 
|         self.__ClearNPCAllState()  | 
|         #»ñµÃÓÎÏ·ÖеÄNPCÀàÐÍ  | 
|         curNPC_GameNPCObjType = curNPC.GetGameNPCObjType()  | 
|         #---ÌØÊâËÀÍöÂß¼---  | 
|           | 
|         #ïÚ³µ²»ÄÜ֪ͨËÀÍö  | 
|         if curNPC_GameNPCObjType == IPY_GameWorld.gnotTruck:  | 
|             return  | 
|           | 
|         #³èÎïËÀÍöµ÷ÓöÀÁ¢½Ó¿Ú  | 
|         if curNPC_GameNPCObjType == IPY_GameWorld.gnotPet:  | 
|             PetControl.SetPetDead(curNPC)  | 
|             return  | 
|           | 
|         #---ͨÓÃËÀÍöÂß¼---  | 
|           | 
| #        #ɱËÀ×Ô¼ºµÄÕÙ»½ÊÞ  | 
| #        self.__InitNPCSummon()  | 
|         #ÉèÖô¦ÀíÖÜÆÚ  | 
|         curNPC.SetIsNeedProcess(False)  | 
|         #µ÷Óõײã -> Í¨Öª¿Í»§¶ËËÀÍö  | 
|         SetDeadEx(curNPC)  | 
|         return  | 
|     #---------------------------------------------------------------------  | 
|     ## ÕÙ»½ÊÞËÀÍö,Ìæ»»³ðºÞ  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks ÕÙ»½ÊÞËÀÍö,Ìæ»»³ðºÞ  | 
|     #===========================================================================  | 
|     # def __NPCReplaceAngry(self):  | 
|     #    curNPC = self.__Instance  | 
|     #    #½ö´¦Àí³èÎïºÍÕÙ»½ÊÞ  | 
|     #    if curNPC.GetGameNPCObjType() not in [IPY_GameWorld.gnotSummon, IPY_GameWorld.gnotPet]:  | 
|     #        return  | 
|     #      | 
|     #    if curNPC.GetType() not in [IPY_GameWorld.ntSummon, IPY_GameWorld.ntElf,  | 
|     #                                IPY_GameWorld.ntTrap, IPY_GameWorld.ntTruck,  | 
|     #                                IPY_GameWorld.ntFairy]:  | 
|     #        return  | 
|     #              | 
|     #    summonOwner = GetSummonNPCOwner(IPY_GameWorld.gotPlayer, curNPC)  | 
|     #      | 
|     #    if summonOwner == None:  | 
|     #        summonOwner = GetSummonNPCOwner(IPY_GameWorld.gotNPC, curNPC)  | 
|     #      | 
|     #    #Òì³£´íÎó  | 
|     #    if summonOwner == None:  | 
|     #        #GameWorld.Log("Ìæ»»³ðºÞ,²éÕÒÕÙ»½ÊÞÖ÷ÈËʧ°Ü curNPC = %s"%(curNPC.GetNPCID()))  | 
|     #        return  | 
|     #      | 
|     #    #³ðºÞNPCÁÐ±í  | 
|     #    angryNPCList = list()  | 
|     #    for index in range(curNPC.GetAngryNPCCount()):  | 
|     #        angryNPC = curNPC.GetAngryNPCByIndex(index)  | 
|     #        #ÒѾËÀÍö  | 
|     #        if angryNPC.GetHP() <= 0:  | 
|     #            continue  | 
|     #          | 
|     #        angryNPCList.append(angryNPC)  | 
|     #      | 
|     #    #ÔÚReplaceNPCAngryFromOldToNewµÄʱºò, »áɾ³ý³ðºÞ,   | 
|     #    #¸Ä±ä summonNPC.GetAngryNPCCount() µÄ³¤¶È, ËùÒÔ±ØÐëÏȹ¹½¨Áбí,  | 
|     #    #ÔÚÌæ»»³ðºÞ  | 
|     #    for angryListNPC in angryNPCList:  | 
|     #        #Ìæ»»³ðºÞ  | 
|     #        ReplaceNPCAngryFromOldToNew(angryListNPC, curNPC, summonOwner)  | 
|     #      | 
|     #    return  | 
|     #===========================================================================  | 
|     #---------------------------------------------------------------------  | 
|     ## NPC·ÇÕ½¶·ÖлØÑª  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tick Ê±¼ä´Á  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks NPC·ÇÕ½¶·ÖлØÑª  | 
|     def ProcessHPRestore(self, tick):  | 
|         ## NPC»ØÑª¹æÔò  | 
|         curNPC = self.__Instance  | 
|         #npcID = curNPC.GetNPCID()  | 
|         hpRestoreRate = curNPC.GetHPRestore() # Ã¿ÃëHP»Ö¸´ËÙ¶ÈÍò·ÖÂÊ  | 
|         if not hpRestoreRate:  | 
|             return False  | 
|           | 
|         curNPCMaxHP = GameObj.GetMaxHP(curNPC)  | 
|         if GameObj.GetHP(curNPC) == curNPCMaxHP:  | 
|             #ÖØÖðٷֱÈÂß¼±êʶ  | 
|             curNPC.SetDict(ChConfig.Def_NPC_Dict_HPPerLogicMark, 0)  | 
|             return False  | 
|           | 
|         #NPCÅÜ»ØÈ¥²»»ØÑª  | 
|         if curNPC.GetCurAction() != IPY_GameWorld.laNPCNull:  | 
|             return True  | 
|           | 
|         if self.IsInHurtProtect():  | 
|             #GameWorld.DebugLog("ÉËѪ±£»¤ÖУ¬²»»ØÑª£¡")  | 
|             return True  | 
|           | 
|         lastRestoreTime = curNPC.GetRestoreTime()  | 
|         if not lastRestoreTime or (tick - curNPC.GetRestoreTime()) >= ChConfig.Def_NPC_ProcessHP_Tick * 5:  | 
|             curNPC.SetRestoreTime(tick + 2000) # ÑÓ³Ù2Ãë»ØÑª, ·ÀÖ¹»ØÔµãʱËÑË÷ÏÂһĿ±êÆÚ¼ä˲»Ø  | 
|             return True  | 
|           | 
|         if tick - curNPC.GetRestoreTime() < ChConfig.Def_NPC_ProcessHP_Tick:  | 
|             #GameWorld.DebugLog("»Ö¸´Ê±¼äδµ½")  | 
|             return True  | 
|           | 
|         restoreValue = int(curNPCMaxHP * hpRestoreRate / 10000.0)  | 
|         SkillCommon.SkillAddHP(curNPC, 0, restoreValue, False)  | 
|         #ÉèÖõ±Ç°Ê±¼äΪ»Ö¸´Æðʼʱ¼ä  | 
|         curNPC.SetRestoreTime(tick)  | 
|         return True  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## NPCÕ½¶·»ØÑª  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param tick Ê±¼ä´Á  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks NPCÕ½¶·»ØÑª  | 
|     def ProcessBattleHPRestore(self, tick):  | 
|         #2010/4/30Õ½¶·»ØÑª¹¦ÄÜÔÝʱ¹Ø±Õ  | 
|         #ÕâÀï»áµ¼Ö¿ͻ§¶Ë½ÓÊÕ¹¥»÷µôѪ·â°ü,ˢѪÒì³£  | 
|         return  | 
| #===============================================================================  | 
| #        curNPC = self.__Instance  | 
| #          | 
| #        if curNPC.GetHP() == curNPC.GetMaxHP():  | 
| #            #ÂúѪÁË  | 
| #            return  | 
| #          | 
| #        if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie:  | 
| #            #ËÀÍö²»»ØÑª  | 
| #            return  | 
| #          | 
| #        if tick - curNPC.GetRestoreTime() < ChConfig.Def_NPC_ProcessBattleHP_Tick:  | 
| #            #»Ö¸´Ê±¼äδµ½  | 
| #            return  | 
| #          | 
| #        hpRestore = curNPC.GetHPRestore()  | 
| #        #Õ½¶·ÖлØÑª  | 
| #        if hpRestore != 0:  | 
| #            SkillCommon.SkillAddHP(curNPC, 0, hpRestore)  | 
| #          | 
| #        #ÉèÖõ±Ç°Ê±¼äΪ»Ö¸´Æðʼʱ¼ä  | 
| #        curNPC.SetRestoreTime(tick)  | 
| #===============================================================================  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## ÉèÖöÔÏó½±Àø  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks ÉèÖöÔÏó½±Àø  | 
|     def __GiveObjPrize(self):  | 
|         curNPC = self.__Instance  | 
|         #objID = curNPC.GetID()  | 
|         npcID = curNPC.GetNPCID()  | 
|         self.__LastHurtPlayer = self.__FindLastTimeHurtObjEx()  | 
|         self.__MaxHurtPlayer = self.__FindBossMaxHurtObj() # py×Ô¶¨ÒåÉËѪËùµÃµ½µÄBoss×î´óÉËÑªÍæ¼Ò  | 
|           | 
|         isGameBoss = ChConfig.IsGameBoss(curNPC)  | 
|         self.__AllKillerDict, curTeam, hurtType, hurtID = self.__FindNPCKillerInfo(isGameBoss)  | 
|         self.__OwnerHurtType, self.__OwnerHurtID = hurtType, hurtID  | 
|         if isGameBoss:  | 
|             GameWorld.Log("__GiveObjPrize npcID=%s,hurtType=%s,hurtID=%s" % (npcID, hurtType, hurtID))  | 
|           | 
|         #×îºóÒ»»÷´¦Àí  | 
|         self.__DoLastTimeHurtLogic()  | 
|           | 
|         #±»Íæ¼ÒɱËÀ  | 
|         if len(self.__AllKillerDict) > 0:  | 
|             dropPlayer = None  | 
|             maxPlayerLV = 0  | 
|             ownerPlayerList = []  | 
|             for curPlayer in self.__AllKillerDict.values():  | 
|                 if not self.__LastHurtPlayer:  | 
|                     self.__LastHurtPlayer = curPlayer  | 
|                 if not self.__MaxHurtPlayer:  | 
|                     self.__MaxHurtPlayer = curPlayer  | 
|                 if not self.__Killer:  | 
|                     self.__Killer = curPlayer  | 
|                       | 
|                 if maxPlayerLV < curPlayer.GetLV():  | 
|                     maxPlayerLV = curPlayer.GetLV()  | 
|                     dropPlayer = curPlayer  | 
|                 self.__KilledByPlayerSetPrize(curPlayer)  | 
|                 ownerPlayerList.append(curPlayer)  | 
|             self.__ownerPlayerList = ownerPlayerList  | 
|               | 
|             #µ÷ÓÃÎïÆ·µôÂä  | 
|             self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)  | 
|   | 
|         #±»¶ÓÎéɱËÀ  | 
|         elif curTeam != None:  | 
|             self.__KilledByTeamSetPrize(curTeam, hurtType, hurtID)  | 
|           | 
|         #±»ÏÉÃËɱËÀ  | 
|         elif hurtType == ChConfig.Def_NPCHurtTypeFamily:  | 
|             self.__KilledByFamilySetPrize(hurtType, hurtID)  | 
|               | 
|         elif isGameBoss:  | 
|             GameWorld.ErrLog("NPC¹éÊôÒì³£:npcID=%s,hurtType=%s,hurtID=%s" % (npcID, hurtType, hurtID))  | 
|           | 
|         if isGameBoss:  | 
|             dataDict = {"objID":curNPC.GetID(), "bossID":npcID, "mapID":GameWorld.GetMap().GetMapID(),  | 
|                         "lineID":GameWorld.GetGameWorld().GetLineID(), "teamID":curTeam.GetTeamID() if curTeam else 0,  | 
|                             "killerID":self.__AllKillerDict.keys(), "hurtType":hurtType,"hurtID":hurtID}  | 
|             DataRecordPack.SendEventPack("KillBossRecord", dataDict)  | 
|                   | 
|         if OnNPCDie:  | 
|             OnNPCDie(curNPC, hurtType, hurtID)  | 
|           | 
|         #Ö´ÐÐÍæ¼ÒÁ¬ÔþÂß¼  | 
|         lastTimeHurtObj = self.__FindLastTimeHurtObj()  | 
|         if lastTimeHurtObj[0] == None and lastTimeHurtObj[1] == None:  | 
|             return  | 
|            | 
|         return  | 
|       | 
|     ## ×îºóÒ»»÷´¦Àí  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     def __DoLastTimeHurtLogic(self):  | 
|         lastHurtPlayer = self.__LastHurtPlayer  | 
|         if not lastHurtPlayer:  | 
|             return  | 
|           | 
|         curObjType = lastHurtPlayer.GetGameObjType()  | 
|         if curObjType != IPY_GameWorld.gotPlayer:  | 
|             return  | 
|           | 
|         curNPC = self.__Instance  | 
|         #npcID = curNPC.GetNPCID()  | 
|         #mapID = GameWorld.GetMap().GetMapID()  | 
|         #playerName = lastHurtPlayer.GetPlayerName()  | 
|                   | 
|         #===========================================================================================  | 
|         # # ×îºóÒ»»÷½±Àø  | 
|         # lastTimeHurtBossAwardDict = ReadChConfig.GetEvalChConfig("LastTimeHurtBossAward")  | 
|         # if npcID in lastTimeHurtBossAwardDict:  | 
|         #    giveItemList = lastTimeHurtBossAwardDict[npcID]  | 
|         #    playerID = lastHurtPlayer.GetPlayerID()  | 
|         #    bossAwardMailInfo = ReadChConfig.GetEvalChConfig("LastTimeHurtBossAwardMail")  | 
|         #    title, content, getDays = bossAwardMailInfo  | 
|         #    mailContent = content % (npcID)  | 
|         #    PlayerControl.SendMail(title, mailContent, getDays, [playerID], giveItemList)  | 
|         #      | 
|         #    # ¹ã²¥  | 
|         #    if len(giveItemList) > 0:  | 
|         #        itemID = giveItemList[0][0] # Ä¬ÈÏÈ¡µÚÒ»¸ö½±ÀøÎïÆ·¹ã²¥  | 
|         #        PlayerControl.WorldNotify(0, "GeRen_liubo_698214", [playerName, mapID, npcID, itemID, itemID])  | 
|         #===========================================================================================  | 
|               | 
|         #===========================================================================================  | 
|         # # ×îºóÒ»»÷¹ã²¥  | 
|         # LastHurtNotifyDict = ReadChConfig.GetEvalChConfig("LastHurtNotify")  | 
|         # for npcIDTuple, notifyMark in LastHurtNotifyDict.items():  | 
|         #    if npcID in npcIDTuple:  | 
|         #        PlayerControl.WorldNotify(0, notifyMark, [playerName, mapID, npcID])  | 
|         #        break  | 
|         #===========================================================================================  | 
|           | 
|         # VIPɱ¹Ö¼Ó¹¥  | 
|         PlayerVip.DoAddVIPKillLVExp(lastHurtPlayer, curNPC)  | 
|           | 
|         # SPÖµ  | 
|         PlayerControl.AddZhenQiByKillNPC(lastHurtPlayer, curNPC.GetSP())  | 
|         return  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## NPCËÀÍö, ·ÖÏí¾ÑéÂß¼  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»Ø»÷É±Íæ¼ÒÐÅÏ¢Ôª×é, (Íæ¼ÒÁбíʵÀý,¶ÓÎéʵÀý,¹éÊôÀàÐÍ,¹éÊôID)  | 
|     def __FindNPCKillerInfo(self, isGameBoss):  | 
|         curNPC = self.__Instance  | 
|         npcID = curNPC.GetNPCID()  | 
|         objID = curNPC.GetID()  | 
|         key = (GameWorld.GetGameWorld().GetLineID(), objID, npcID)  | 
|         if key in PyGameData.g_npcKillerInfo:  | 
|             killerDict, killTeam, hurtType, hurtID = PyGameData.g_npcKillerInfo.pop(key)  | 
|             teamID = killTeam.GetTeamID() if killTeam else 0  | 
|             GameWorld.Log("NPC±»»÷ɱ£¬¹éÊôÐÅÏ¢: key=%s,playerIDList=%s,teamID=%s,hurtType=%s,hurtID=%s"   | 
|                           % (key, killerDict.keys(), teamID, hurtType, hurtID))  | 
|             return killerDict, killTeam, hurtType, hurtID  | 
|           | 
|         hurtType = 0  | 
|         hurtID = 0  | 
|         killerDict = {} # ÓÃÓÚÖ§³Ö¶à¸öÍæ¼ÒÌØÊâ¹éÊôµÄ£¬ÊÖÓοÉÄÜÔÝʱ²»Óã¬Ö®Ç°Ò³ÓÎÓÐÓõ½£¬Ïȱ£Áô£¬ÒªÀ©Õ¹ÔÙ˵  | 
|         killTeam = None  | 
|           | 
|         #isLog = self.__GetIsLog()  | 
|         dropOwnerType = GetDropOwnerType(curNPC)  | 
|         if isGameBoss:  | 
|             GameWorld.Log("NPC±»»÷ɱ, key=%s,dropOwnerType=%s" % (key, dropOwnerType))  | 
|               | 
|         # ×î´óÉËѪ - ÉËѪ¿ÉÄܱ»ÖØÖà  | 
|         if dropOwnerType == ChConfig.DropOwnerType_MaxHurt:  | 
|             npcHurtList = curNPC.GetPlayerHurtList()  | 
|             npcHurtList.Sort()  | 
|             if isGameBoss:  | 
|                 GameWorld.Log("hurtCount=%s" % (npcHurtList.GetHurtCount()))  | 
|             for i in xrange(npcHurtList.GetHurtCount()):  | 
|                 #»ñµÃ×î´óÉËѪ¶ÔÏó  | 
|                 maxHurtObj = npcHurtList.GetHurtAt(i)  | 
|                 if isGameBoss:  | 
|                     GameWorld.Log("hurtIndex=%s,hurtValueType=%s,valueID=%s" % (i, maxHurtObj.GetValueType(), maxHurtObj.GetValueID()))  | 
|                 curPlayer, curTeam = self.__GetTagByHurtObj(maxHurtObj, isLog=isGameBoss)  | 
|                 #µ±Ç°ÉËѪ¶ÔÏ󳬳öÖ¸¶¨·¶Î§»òÒѾËÀÍö  | 
|                 if curPlayer == None and curTeam == None:  | 
|                     if isGameBoss:  | 
|                         GameWorld.Log("    µ±Ç°ÉËѪ¶ÔÏ󳬳öÖ¸¶¨·¶Î§»òÒѾËÀÍö")  | 
|                     continue  | 
|                   | 
|                 if curPlayer:  | 
|                     playerID = curPlayer.GetPlayerID()  | 
|                     if playerID not in killerDict:  | 
|                         killerDict[playerID] = curPlayer  | 
|                     if isGameBoss:  | 
|                         GameWorld.Log("    ¹éÊô×î´óÉËÑªÍæ¼Ò: npcID=%s,dropOwnerType=%s,playerID=%s" % (npcID, dropOwnerType, playerID))  | 
|                     return killerDict, None, ChConfig.Def_NPCHurtTypePlayer, playerID  | 
|                   | 
|                 if curTeam:  | 
|                     killTeam = curTeam  | 
|                     if isGameBoss:  | 
|                         GameWorld.Log("    ¹éÊô×î´óÉËѪ¶ÓÎé: npcID=%s,dropOwnerType=%s,teamID=%s" % (npcID, dropOwnerType, curTeam.GetTeamID()))  | 
|                     return killerDict, curTeam, ChConfig.Def_NPCHurtTypeTeam, curTeam.GetTeamID()  | 
|         # ×î´óÉËÑªÍæ¼Ò - ÉËѪ²»»á±»ÖØÖà  | 
|         elif dropOwnerType == ChConfig.DropOwnerType_MaxHurtPlayer:  | 
|             if self.__MaxHurtPlayer:  | 
|                 maxHurtPlayerID = self.__MaxHurtPlayer.GetPlayerID()  | 
|                 if maxHurtPlayerID not in killerDict:  | 
|                     killerDict[maxHurtPlayerID] = self.__MaxHurtPlayer  | 
|                     #GameWorld.DebugLog("    ÌØÊâ¹éÊô×î´óÉ˺¦Íæ¼Ò: playerID=%s" % maxHurtPlayerID)  | 
|                     return killerDict, None, ChConfig.Def_NPCHurtTypePlayer, maxHurtPlayerID  | 
|                   | 
|         # ×î´ó³ðºÞ  | 
|         elif dropOwnerType == ChConfig.DropOwnerType_MaxAngry:  | 
|             maxAngryPlayer, maxAngryTeam = self.__GetMaxAngryInfo()  | 
|             if maxAngryTeam:  | 
|                 #if isLog:  | 
|                 #    GameWorld.DebugLog("    ¹éÊô×î´ó³ðºÞ¶ÓÎé: npcID=%s,teamID=%s" % (npcID, maxAngryTeam.GetTeamID()))  | 
|                 #GameWorld.DebugLog("    ¹éÊô×î´ó³ðºÞ¶ÓÎé: %s" % maxAngryTeam.GetTeamID())  | 
|                 return killerDict, maxAngryTeam, ChConfig.Def_NPCHurtTypeTeam, maxAngryTeam.GetTeamID()  | 
|             elif maxAngryPlayer:  | 
|                 killerDict[maxAngryPlayer.GetPlayerID()] = maxAngryPlayer  | 
|                 #if isLog:  | 
|                 #    GameWorld.DebugLog("    ¹éÊô×î´ó³ðºÞÍæ¼Ò: npcID=%s,playerID=%s" % (npcID, maxAngryPlayer.GetPlayerID()))  | 
|                 #GameWorld.DebugLog("    ¹éÊô×î´ó³ðºÞÍæ¼Ò: %s" % maxAngryPlayer.GetPlayerID())  | 
|                 return killerDict, None, ChConfig.Def_NPCHurtTypePlayer, maxAngryPlayer.GetPlayerID()  | 
|               | 
|         # ÆäËûĬÈÏ×îºóÒ»»÷  | 
|         if self.__LastHurtPlayer:  | 
|             lastHurtPlayerID = self.__LastHurtPlayer.GetPlayerID()  | 
|             teamID = self.__LastHurtPlayer.GetTeamID()  | 
|             if isGameBoss:  | 
|                 GameWorld.Log("    ¹éÊô×îºóÒ»»÷£¬npcID=%s,lastHurtPlayerID=%s,teamID=%s" % (npcID, lastHurtPlayerID, teamID))  | 
|             if teamID:  | 
|                 killTeam = GameWorld.GetTeamManager().FindTeam(teamID)  | 
|             if not killTeam and lastHurtPlayerID not in killerDict:  | 
|                 killerDict[lastHurtPlayerID] = self.__LastHurtPlayer  | 
|                   | 
|         if dropOwnerType == ChConfig.DropOwnerType_All:  | 
|             hurtType = ChConfig.Def_NPCHurtTypeAll  | 
|             if isGameBoss:  | 
|                 GameWorld.Log("    ÎÞ¹éÊô...npcID=%s" % npcID)  | 
|               | 
|         elif dropOwnerType == ChConfig.DropOwnerType_Faction:  | 
|             #ÕóÓª¹éÊô  | 
|             protectFaction = FBLogic.GetNPCItemProtectFaction(curNPC)  | 
|             if protectFaction > 0:  | 
|                 hurtType = ChConfig.Def_NPCHurtTypeFaction  | 
|                 hurtID = protectFaction  | 
|                 if isGameBoss:  | 
|                     GameWorld.Log("    ÕóÓª¹éÊô...factionID=%s" % protectFaction)  | 
|                   | 
|         if hurtType == 0:  | 
|             #¹éÊô¶ÓÎé  | 
|             if killTeam:  | 
|                 hurtType = ChConfig.Def_NPCHurtTypeTeam  | 
|                 hurtID = killTeam.GetTeamID()  | 
|                 if isGameBoss:  | 
|                     GameWorld.Log("    ¹éÊôĬÈ϶ÓÎé, npcID=%s,teamID=%s" % (npcID, hurtID))  | 
|             #ÉËѪ¹éÊôÍæ¼Ò  | 
|             elif killerDict:  | 
|                 hurtType = ChConfig.Def_NPCHurtTypePlayer  | 
|                 hurtID = killerDict.keys()[0]  | 
|                 if isGameBoss:  | 
|                     GameWorld.Log("    ¹éÊôĬÈÏÍæ¼Ò, npcID=%s,playerID=%s" % (npcID, hurtID))  | 
|             elif GameWorld.GetMap().GetMapID() == ChConfig.Def_FBMapID_GatherSoul:  | 
|                 player = FBCommon.GetCurSingleFBPlayer()  | 
|                 if player:  | 
|                     hurtID = player.GetPlayerID()  | 
|                     killerDict[hurtID] = player  | 
|                     hurtType = ChConfig.Def_NPCHurtTypePlayer  | 
|                     #GameWorld.Log("    ¾Û»ê¸±±¾¹éÊôĬÈÏÍæ¼Ò, npcID=%s,playerID=%s" % (npcID, hurtID))  | 
|                   | 
|         return killerDict, killTeam, hurtType, hurtID  | 
|       | 
|     def __GetMaxAngryInfo(self):  | 
|         ''' »ñÈ¡×î´ó³ðºÞËù¹éÊôµÄÍæ¼Ò, ¶ÓÎé '''  | 
|           | 
|         curAngry = self.GetMaxAngryTag()  | 
|         if not curAngry:  | 
|             return None, None  | 
|           | 
|         angryID = curAngry.GetObjID()  | 
|         angryObjType = curAngry.GetObjType()  | 
|         if angryObjType != IPY_GameWorld.gotPlayer:  | 
|             return None, None  | 
|           | 
|         curTag = GameWorld.GetObj(angryID, angryObjType)  | 
|         if not curTag:  | 
|             return None, None  | 
|           | 
|         teamID = curTag.GetTeamID()  | 
|         if not teamID:  | 
|             return curTag, None  | 
|           | 
|         return curTag, GameWorld.GetTeamManager().FindTeam(teamID)  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## »ñÈ¡²¹µ¶Õߣ¬°üº¬¶ÓÎé  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµ Íæ¼Ò»òÕßNone  | 
|     #  @remarks   | 
|     def __FindLastTimeHurtObj(self):  | 
|         curNPC = self.__Instance  | 
|         npcHurtList = curNPC.GetPlayerHurtList()  | 
|         if npcHurtList.GetHurtCount() <= 0:  | 
|             return (None, None)  | 
|           | 
|         maxHurtObj = npcHurtList.GetLastTimeHurtValue()  | 
|         return self.__GetTagByHurtObj(maxHurtObj)  | 
|   | 
|   | 
|     ## »ñÈ¡²¹µ¶Õß(Õâ¸ö¾ø¶ÔÊÇÍæ¼Ò)  | 
|     #  @param self ÀàʵÀý  | 
|     #  @return ·µ»ØÖµ Íæ¼Ò»òÕßNone  | 
|     def __FindLastTimeHurtObjEx(self):  | 
|         curNPC = self.__Instance  | 
|         playerID = curNPC.GetDictByKey(ChConfig.Def_PlayerKey_LastHurt)  | 
|           | 
|         curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)  | 
|         if not curPlayer:  | 
|             return None  | 
|           | 
|         return curPlayer  | 
|       | 
|     def __FindBossMaxHurtObj(self):  | 
|         # py×Ô¶¨ÒåÉËѪËùµÃµ½µÄBoss×î´óÉËÑªÍæ¼Ò  | 
|         curNPC = self.__Instance  | 
|         maxHurtID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_BossMaxHurtID % (curNPC.GetID(), curNPC.GetNPCID()))  | 
|           | 
|         curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(maxHurtID)  | 
|         if not curPlayer:  | 
|             return None  | 
|           | 
|         return curPlayer  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## »ñµÃÉËѪ¶ÔÏó,Ö§³ÖÇÀ¹Ö  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param maxHurtObj ×î´óÉËѪ¶ÔÏó  | 
|     #  @return ·µ»ØÖµ, ÉËѪ¶ÔÏó  | 
|     #  @remarks »ñµÃÉËѪ¶ÔÏó,Ö§³ÖÇÀ¹Ö  | 
|     def __GetTagByHurtObj(self, maxHurtObj, isCheckRefreshArea=False, isLog=False):  | 
|         #»ñµÃËÀÍöµÄNPC  | 
|         curNPC = self.__Instance  | 
|         npcID = curNPC.GetNPCID()  | 
|         # É˺¦µÄobjÀàÐÍÔª×é(Íæ¼Ò, ¶ÓÎé)  | 
|         hurtObjTuple = (None, None)  | 
|         if maxHurtObj == None:  | 
|             GameWorld.DebugLog("ÉËѪ¶ÔÏó´íÎó,npcID=%s" % (curNPC.GetNPCID()))  | 
|             return hurtObjTuple  | 
|           | 
|         refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|         #×î´óÉËѪÀàÐÍ  | 
|         maxHurtValueType = maxHurtObj.GetValueType()  | 
|           | 
|         if maxHurtValueType == ChConfig.Def_NPCHurtTypePlayer:  | 
|             curPlayer = GameWorld.GetObj(maxHurtObj.GetValueID(), IPY_GameWorld.gotPlayer)  | 
|               | 
|             if curPlayer == None:  | 
|                 if isLog:  | 
|                     GameWorld.Log("ÕÒ²»µ½¸ÃÄ¿±êÉËÑªÍæ¼Ò: npcID=%s,playerID=%s" % (npcID, maxHurtObj.GetValueID()))  | 
|                 return hurtObjTuple  | 
|               | 
|             #Ö§³ÖÇÀ¹Ö,¸öÈËɱËÀ,µ«×Ô¼ºËÀÍö,²»Ëã  | 
|             if curPlayer.GetHP() <= 0 or curPlayer.GetPlayerAction() == IPY_GameWorld.paDie:  | 
|                 if isLog:  | 
|                     GameWorld.Log("¸ÃÄ¿±êÉËÑªÍæ¼ÒÒÑËÀÍö: npcID=%s,playerID=%s" % (npcID, maxHurtObj.GetValueID()))  | 
|                 return hurtObjTuple  | 
|               | 
|             if isCheckRefreshArea:  | 
|                 if not self.GetIsInRefreshPoint(curPlayer.GetPosX(), curPlayer.GetPosY(), refreshPoint):  | 
|                     if isLog:  | 
|                         GameWorld.Log("¸ÃÄ¿±êÉËÑªÍæ¼Ò²»ÔÚNPCÇøÓòÄÚ: npcID=%s,playerID=%s,pos(%s,%s)"   | 
|                                       % (npcID, maxHurtObj.GetValueID(), curPlayer.GetPosX(), curPlayer.GetPosY()))  | 
|                     return hurtObjTuple  | 
|             #Èç¹ûÍæ¼ÒÒѾ³¬³öÖ¸¶¨¾àÀë,²»¼Ó¾Ñé  | 
|             elif GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(),  | 
|                                      curPlayer.GetPosX(), curPlayer.GetPosY()) > ChConfig.Def_Team_GetExpScreenDist:  | 
|                 if isLog:  | 
|                     GameWorld.Log("¸ÃÄ¿±êÉËÑªÍæ¼Ò³¬³öÖ¸¶¨¾àÀë: npcID=%s,playerID=%s,npcPos(%s,%s),playerPos(%s,%s)"   | 
|                                   % (npcID, maxHurtObj.GetValueID(), curNPC.GetPosX(), curNPC.GetPosY(), curPlayer.GetPosX(), curPlayer.GetPosY()))  | 
|                 return hurtObjTuple  | 
|               | 
|             #Õý³£·µ»Ø  | 
|             hurtObjTuple = (curPlayer, None)  | 
|             return curPlayer, None  | 
|           | 
|         elif maxHurtValueType == ChConfig.Def_NPCHurtTypeTeam:  | 
|             #»ñµÃµ±Ç°¶ÓÎé  | 
|             teamID = maxHurtObj.GetValueID()  | 
|             curTeam = GameWorld.GetTeamManager().FindTeam(teamID)  | 
|             if isLog:  | 
|                 GameWorld.Log("Ä¿±êÉËѪ¶ÓÎé: npcID=%s,teamID=%s" % (npcID, teamID))  | 
|             if curTeam == None:  | 
|                 if isLog:  | 
|                     GameWorld.Log("ÕÒ²»µ½Ä¿±ê¶ÓÎé, teamID=%s" % (teamID))  | 
|                 return hurtObjTuple  | 
|               | 
|             if isLog:  | 
|                 GameWorld.Log("¶ÓÎé³ÉÔ±Êý: GetMemberCount=%s" % (curTeam.GetMemberCount()))                  | 
|             #±éÀú¶ÓÎé,°ë¾¶ÎªÒ»ÆÁ°ëµÄ¾àÀëÄÚµÄËùÓжÓÎé/ÍŶӳÉÔ±£¬¿ÉÒÔ»ñµÃ¾Ñé  | 
|             for i in xrange(curTeam.GetMemberCount()):  | 
|                 curTeamPlayer = curTeam.GetMember(i)  | 
|                 if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:  | 
|                     if isLog:  | 
|                         GameWorld.Log("    i=%s, Î޸öÓÔ±£¡" % (i))  | 
|                     continue  | 
|                   | 
|                 if curTeamPlayer.GetHP() <= 0 or curTeamPlayer.GetPlayerAction() == IPY_GameWorld.paDie:  | 
|                     if isLog:  | 
|                         GameWorld.Log("    i=%s, ¶ÓÔ±ÒÑËÀÍö£¡memPlayerID=%s" % (i, curTeamPlayer.GetPlayerID()))  | 
|                     continue  | 
|                   | 
|                 if isCheckRefreshArea:  | 
|                     if not self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint):  | 
|                         if isLog:  | 
|                             GameWorld.Log("    i=%s, ¶ÓÔ±²»ÔÚNPCÇøÓòÄÚ£¡memPlayerID=%s,pos(%s,%s)"   | 
|                                           % (i, curTeamPlayer.GetPlayerID(), curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY()))  | 
|                         continue  | 
|                 elif GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), curTeamPlayer.GetPosX(),  | 
|                                        curTeamPlayer.GetPosY()) > ChConfig.Def_Team_GetExpScreenDist:  | 
|                     if isLog:  | 
|                         GameWorld.Log("    i=%s, ¶ÓÔ±³¬³öÖ¸¶¨¾àÀ룡memPlayerID=%s,npcPos(%s,%s),playerPos(%s,%s)"   | 
|                                       % (i, curTeamPlayer.GetPlayerID(), curNPC.GetPosX(), curNPC.GetPosY(), curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY()))  | 
|                     continue  | 
|                   | 
|                 hurtObjTuple = (None, curTeam)  | 
|                 return hurtObjTuple  | 
|               | 
|             return hurtObjTuple  | 
|               | 
|         #×î´óÉËѪ¶ÔÏóÊÇNPC,ÄÇôһ¶¨²»¸ø¾Ñé(Íæ¼ÒµÄÕÙ»½ÊÞÉËѪËãÍæ¼Ò)  | 
|         elif maxHurtValueType == ChConfig.Def_NPCHurtTypeNPC:  | 
|             return hurtObjTuple  | 
|           | 
|         #Òì³£ÐÅÏ¢,Ìí¼ÓÉËѪÀàÐÍ´íÎó  | 
|         else:  | 
|             pass  | 
|           | 
|         return hurtObjTuple  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## Íæ¼ÒɱËÀNPC½±ÀøÂß¼  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param curPlayer Íæ¼ÒʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks Íæ¼ÒɱËÀNPC½±ÀøÂß¼  | 
|     def __KilledByPlayerSetPrize(self, curPlayer):  | 
|         curNPC = self.__Instance  | 
|         add_Exp = self.__GetExp(curPlayer.GetLV(), False, curPlayer)  | 
|           | 
|         #if self.__GetIsLog():  | 
|         #    GameWorld.Log("Íæ¼ÒÔö¼Ó¸öÈ˾Ñé,npcID=%s,addExp=%s" % (curNPC.GetNPCID(), add_Exp), curPlayer.GetPlayerID())  | 
|         addSkillID = 0  | 
|         if curNPC.GetDictByKey(ChConfig.Def_NPCDead_KillerID) == curPlayer.GetID():  | 
|             addSkillID = curNPC.GetDictByKey(ChConfig.Def_NPCDead_Reason)  | 
|         #É趨ÈËÎï»ñµÃ¾Ñé  | 
|         playerControl = PlayerControl.PlayerControl(curPlayer)  | 
|         playerControl.AddExp(add_Exp, ShareDefine.Def_ViewExpType_KillNPC, addSkillID)  | 
|           | 
|           | 
|         self.__KillNPCFuncEx(curPlayer, curNPC, curPlayer.GetPlayerID(), False)  | 
|         #if curNPC.GetIsBoss() == ChConfig.Def_NPCType_Boss_Dark:  | 
|         #    #Ôö¼ÓÍæ¼Ò»÷ɱbossÊý  | 
|         #    PlayerControl.AddPlayerKillBossCount(curPlayer, curNPC)  | 
|           | 
|         #GameWorld.Log("¸öÈËɱËÀ¹ÖÎï½±Àø,Âß¼³É¹¦½áÊø")  | 
|         return  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## ¶ÓÎéɱËÀNPC½±ÀøÂß¼  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param curTeam ¶ÓÎéʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks ¶ÓÎéɱËÀNPC½±ÀøÂß¼  | 
|     def __KilledByTeamSetPrize(self, curTeam, hurtType, hurtID):  | 
|         curNPC = self.__Instance  | 
|         #¶ÓÔ±ÁÐ±í  | 
|         playerlist = PlayerControl.GetAreaTeamMember(curTeam, curNPC.GetPosX(), curNPC.GetPosY(), isLog=self.__GetIsLog())  | 
|         #playerlist = PlayerControl.GetMapTeamMember(curTeam)  | 
|         if not playerlist:  | 
|             GameWorld.ErrLog("½±Àø¹éÊô¶ÓÎ飬µ«ÊDz»´æÔÚ¿É»ñµÃ¸Ã½±ÀøµÄ¶ÓÔ±!npcID=%s,teamID=%s,hurtType=%s,hurtID=%s"   | 
|                              % (curNPC.GetNPCID(), curTeam.GetTeamID(), hurtType, hurtID))  | 
|             return  | 
|           | 
|         if not self.__LastHurtPlayer:  | 
|             self.__LastHurtPlayer = playerlist[0]  | 
|         if not self.__MaxHurtPlayer:  | 
|             self.__MaxHurtPlayer = playerlist[0]  | 
|         if not self.__Killer:  | 
|             self.__Killer = playerlist[0]  | 
|         maxHurtID = playerlist[0].GetPlayerID()  | 
|           | 
|         teamMaxLV = 0  | 
|         dropPlayer = None  | 
|         ownerPlayerList = []  | 
|         #±éÀú¶ÓÎé,°ë¾¶ÎªÒ»ÆÁ°ëµÄ¾àÀëÄÚµÄËùÓжÓÎé/ÍŶӳÉÔ±£¬¿ÉÒÔ»ñµÃ¾Ñé  | 
|         for curPlayer in playerlist:  | 
|             curPlayerLV = curPlayer.GetLV()  | 
|             if teamMaxLV < curPlayerLV:  | 
|                 teamMaxLV = curPlayerLV  | 
|                 dropPlayer = curPlayer  | 
|                   | 
|             ownerPlayerList.append(curPlayer)  | 
|               | 
|             self.__DoNormalTeamExp(curPlayer)  | 
|             self.__KillNPCFuncEx(curPlayer, curNPC, maxHurtID, True)  | 
|         self.__ownerPlayerList = ownerPlayerList  | 
|               | 
|         #µ÷ÓÃÎïÆ·µôÂä  | 
|         self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)  | 
|         #GameWorld.Log("¶ÓÎéɱËÀ¹ÖÎï½±Àø,Âß¼³É¹¦½áÊø")  | 
|         return  | 
|       | 
|     def __KilledByFamilySetPrize(self, hurtType, hurtID):  | 
|         ## ÏÉÃËɱËÀNPC½±ÀøÂß¼  | 
|         curNPC = self.__Instance  | 
|           | 
|         maxLV = 0  | 
|         dropPlayer = None  | 
|         ownerPlayerList = []  | 
|         refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|         copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()  | 
|         for index in xrange(copyPlayerMgr.GetPlayerCount()):  | 
|             player = copyPlayerMgr.GetPlayerByIndex(index)  | 
|             if not player:  | 
|                 continue  | 
|               | 
|             if player.GetFamilyID() != hurtID or not self.GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint):  | 
|                 continue  | 
|               | 
|             curPlayerLV = player.GetLV()  | 
|             if maxLV < curPlayerLV:  | 
|                 maxLV = curPlayerLV  | 
|                 dropPlayer = player  | 
|             ownerPlayerList.append(player)  | 
|         self.__ownerPlayerList = ownerPlayerList  | 
|               | 
|         if not ownerPlayerList:  | 
|             GameWorld.Log("½±Àø¹éÊôÏÉÃË£¬µ«ÊDz»´æÔÚ¿É»ñµÃ¸Ã½±ÀøµÄ³ÉÔ±!npcID=%s,hurtType=%s,hurtID=%s"   | 
|                           % (curNPC.GetNPCID(), hurtType, hurtID))  | 
|               | 
|         # ÒòΪÏÉÃ˹éÊôboss¹éÊôÉËѪµÚÒ»µÄÏÉÃË£¬ÏÉÃËÉËѪÓб£»¤£¬¿ÉÄÜ´æÔÚÉËѪµÚÒ»ÏÉÃËÔÚbossËÀÍöµÄʱºò¶¼²»ÔÚ  | 
|         # ´ËʱµôÂ伯ËãÍæ¼ÒËã×îºóÒ»»÷Íæ¼Ò£¬¹éÊô»¹ÊÇËãÉËѪµÚÒ»ÏÉÃ赀  | 
|         if not dropPlayer:  | 
|             dropPlayer = self.__LastHurtPlayer  | 
|               | 
|         if not dropPlayer:  | 
|             GameWorld.ErrLog("½±Àø¹éÊôÏÉÃË£¬ÕÒ²»µ½µôÂäÍæ¼Ò!npcID=%s,hurtType=%s,hurtID=%s"   | 
|                              % (curNPC.GetNPCID(), hurtType, hurtID))  | 
|             return  | 
|           | 
|         # ¸Ïʱ¼ä£¬Ïȼòµ¥´¦ÀíÖ±½ÓÈ¡×î´óµÈ¼¶µÄ£¬Ö®ºó¿É°´Êµ¼ÊÇé¿öÀ´  | 
|         if not self.__LastHurtPlayer:  | 
|             self.__LastHurtPlayer = dropPlayer  | 
|         if not self.__MaxHurtPlayer:  | 
|             self.__MaxHurtPlayer = dropPlayer  | 
|         if not self.__Killer:  | 
|             self.__Killer = dropPlayer  | 
|         maxHurtID = dropPlayer.GetPlayerID()  | 
|           | 
|         for curPlayer in ownerPlayerList:  | 
|             self.__KillNPCFuncEx(curPlayer, curNPC, maxHurtID, False)  | 
|               | 
|         #µ÷ÓÃÎïÆ·µôÂä  | 
|         self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)  | 
|         return  | 
|       | 
|     ## ¶ÓÎé»ò×Ô¼º»÷ɱNPCÀ©Õ¹¹¦ÄÜ  | 
|     #  @param curPlayer  | 
|     #  @return None  | 
|     #  @remarks: ¿É×öһЩ»÷ɱNPCºóµÄÀ©Õ¹¹¦ÄÜ(Èç³É¾Í, ³ÆºÅ, »îÔ¾¶È, ¹ã²¥µÈ)£¬¿ÉÒÔͳһдÕâ±ß£¬ÒÔǰ±È½ÏÂÒ  | 
|     def __KillNPCFuncEx(self, curPlayer, curNPC, killerID, isTeamKill):  | 
|         npcID = curNPC.GetNPCID()  | 
|         defObjType = curNPC.GetGameObjType()   | 
|         mapFBType = GameWorld.GetMap().GetMapFBType()  | 
|         mapID = FBCommon.GetRecordMapID(GameWorld.GetMap().GetMapID())  | 
|         #playerID = curPlayer.GetPlayerID()  | 
|           | 
|         # Èç¹ûÊÇNPC  | 
|         if defObjType != IPY_GameWorld.gotNPC:  | 
|             return  | 
|           | 
|         # ¿ç·þ·þÎñÆ÷´¦Àí  | 
|         if GameWorld.IsCrossServer():  | 
|             #µôÂä¹éÊô  | 
|             if mapFBType != IPY_GameWorld.fbtNull:  | 
|                 FBLogic.DoFB_DropOwner(curPlayer , curNPC)  | 
|                   | 
|             if ChConfig.IsGameBoss(curNPC):  | 
|                 OnPlayerKillBoss(curPlayer, npcID, mapID, True)  | 
|             return  | 
|           | 
|         #µôÂä¹éÊô  | 
|         if mapFBType != IPY_GameWorld.fbtNull:  | 
|             FBLogic.DoFB_DropOwner(curPlayer , curNPC)  | 
|         else:  | 
|             if curNPC.GetLV()>=curPlayer.GetLV() - IpyGameDataPY.GetFuncCfg('DailyQuestKillMonster'):  | 
|                 PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_KillNPC)  | 
|             PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FeastRedPack_KillSpecificNPC, 1, [npcID])  | 
|               | 
|         if ChConfig.IsGameBoss(curNPC):  | 
|             OnPlayerKillBoss(curPlayer, npcID, mapID, False)  | 
|         return  | 
|           | 
|     #---------------------------------------------------------------------  | 
|     ## »÷ɱNPC´¥·¢ÈÎÎñʼþ  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param curPlayer Íæ¼ÒʵÀý  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks »÷ɱNPC´¥·¢ÈÎÎñʼþ  | 
|     def __MissionOnKillNPC(self, curPlayer, isFeel=False):  | 
|         curNPC = self.__Instance  | 
|         npcObjType = curNPC.GetGameNPCObjType()  | 
|           | 
|         #NPCÓÐÖ÷ÈË, ÊÇÕÙ»½ÊÞ  | 
|         if npcObjType == IPY_GameWorld.gnotSummon:   | 
|             curNPCOwner = GetSummonNPCOwner(IPY_GameWorld.gotPlayer , curNPC)  | 
|             if curNPCOwner:  | 
|                 return  | 
|               | 
|         #²»ÊÇÆÕͨNPC      | 
|         elif npcObjType != IPY_GameWorld.gnotNormal:  | 
|             return  | 
|         npcID = curNPC.GetNPCID()  | 
|         #GameWorld.DebugLog("__MissionOnKillNPC isFeel=%s" % (isFeel), curPlayer.GetPlayerID())  | 
|         killBossCntLimitDict = IpyGameDataPY.GetFuncCfg('KillBossCntLimit', 1)  | 
|         limitIndex = GameWorld.GetDictValueByKey(killBossCntLimitDict, npcID)  | 
|         isWorldBoos = limitIndex == ShareDefine.Def_Boss_Func_World  | 
|         if isFeel:  | 
|             #»÷ɱNPC´¥·¢Ãþ¹ÖÈÎÎñʼþ  | 
|             EventShell.EventRespons_OnKillByFeel(curPlayer, curNPC)  | 
|             if isWorldBoos:  | 
|                 EventShell.EventRespons_KillWorldBossByFeel(curPlayer)  | 
|         else:  | 
|             #ÆÕͨNPC»÷ɱ´¥·¢  | 
|             EventShell.EventRespons_OnKillById(curPlayer, curNPC)  | 
|             if isWorldBoos:  | 
|                 EventShell.EventRespons_KillWorldBoss(curPlayer)  | 
|         #»÷É±ÌØ¶¨NPC³É¾Í  | 
|         PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillSpecificNPC, 1, [npcID])  | 
|         return  | 
|           | 
|     def __GetIsLog(self):  | 
|         ## ²âÊÔ²é´íÈÕÖ¾£¬ÁÙʱÓà  | 
|         ## Ïà¹Øbug£º ÏɽçÃØ¾³ÎÞ¾Ñé¡¢bossÎÞµôÂä  | 
|         return ChConfig.IsGameBoss(self.__Instance)  | 
|         #return GameWorld.GetMap().GetMapID() == ChConfig.Def_FBMapID_BZZD or ChConfig.IsGameBoss(self.__Instance)  | 
|   | 
|     #---------------------------------------------------------------------  | 
|     ## ÆÕͨ×é¶Ó¸ø¾Ñé  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param curPlayer Íæ¼ÒʵÀý  | 
|     #  @param playerCount Íæ¼ÒÊýÁ¿  | 
|     #  @param playerCountAddRate Íæ¼ÒÊýÁ¿¼Ó³É  | 
|     #  @param team_Relation ×é¶Ó¹ØÏµ¼Ó³É  | 
|     #  @param team_AverageLV ¶ÓÎ鯽¾ùµÈ¼¶  | 
|     #  @return ·µ»ØÖµÎÞÒâÒå  | 
|     #  @remarks ÆÕͨ×é¶Ó¸ø¾Ñé  | 
|     def __DoNormalTeamExp(self, curPlayer):  | 
|         curNPC = self.__Instance  | 
|         ##ÆÕͨ×é¶Ó¸öÈ˾ÑéÔö¼Ó Min(¸öÈ˾Ñé*ÈËÊý¼Ó³É*¸öÈ˵ȼ¶/µ±Ç°¶ÓÎ鯽¾ùµÈ¼¶,¸öÈ˾Ñé)*µ±Ç°×é¶Ó¹ØÏµ  | 
|         add_Exp = self.__GetExp(curPlayer.GetLV(), True, curPlayer)  | 
|         #if self.__GetIsLog():  | 
|         #   GameWorld.Log("¶ÓÔ±Ôö¼Ó¸öÈ˾Ñé,npcID=%s,addExp=%s" % (curNPC.GetNPCID(), add_Exp), curPlayer.GetPlayerID())  | 
|         if not add_Exp:  | 
|             return  | 
|         #GameWorld.Log("ÆÕͨ¶ÓÎéɱËÀ¹ÖÎï,¶ÓÎé·ÖÏíÈËÊý = %s,¸öÈ˾ÑéÔö¼Ó Íæ¼Ò = %s, Ôö¼Ó = %s"%(playerCount, curPlayer.GetPlayerID(), add_Exp))  | 
|         #É趨ÈËÎï»ñµÃ¾Ñé  | 
|         addSkillID = 0  | 
|         if curNPC.GetDictByKey(ChConfig.Def_NPCDead_KillerID) == curPlayer.GetID():  | 
|             addSkillID = curNPC.GetDictByKey(ChConfig.Def_NPCDead_Reason)  | 
|         playerControl = PlayerControl.PlayerControl(curPlayer)  | 
|         playerControl.AddExp(add_Exp, ShareDefine.Def_ViewExpType_KillNPC, addSkillID)  | 
|         return  | 
|       | 
|     #---------------------------------------------------------------------  | 
|     ## »ñµÃ¾Ñé  | 
|     #  @param self ÀàʵÀý  | 
|     #  @param curPlayerLV Íæ¼ÒµÈ¼¶  | 
|     #  @param isTeam ÊÇ·ñ×é¶Ó  | 
|     #  @return ·µ»ØÖµ, »ñµÃ¾Ñé  | 
|     #  @remarks »ñµÃ¾Ñé, ¿ÉÄÜÊÇСÊý  | 
|     def __GetExp(self, playerLV, isTeam=False, player=None):  | 
|         curNPC = self.__Instance  | 
|         baseExp = 0  | 
|         #Íæ¼Ò²»ÔÚ¸±±¾ÖÐ  | 
|         if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:  | 
|             baseExp = FBLogic.OnGetNPCExp(player, curNPC)  | 
|         if baseExp > 0:  | 
|             return baseExp  | 
|           | 
|         baseExp = curNPC.GetExp()  | 
|         if baseExp == 0:  | 
|             #GameWorld.Log("ɱ¹Ö¾ÑéÒì³£,¸ÃNPC = %s,ÎÞ¾Ñé"%(curNPC.GetID()))  | 
|             return 0  | 
|           | 
|         playerID = 0 if not player else player.GetPlayerID()  | 
|         # Èç¹ûÊǶÓÎ飬Ôò°´É˺¦¹±Ï׶ȼÆËãËù»ñµÃ¾Ñé±ÈÀý  | 
|         if isTeam:  | 
|             if not player:  | 
|                 return 0  | 
|             hurtPer = AttackCommon.GetTeamPlayerHurtPer(player, curNPC)  | 
|             if not hurtPer:  | 
|                 return 0  | 
|             #GameWorld.DebugLog("¶ÓÔ±»÷ɱ»ù´¡¾Ñé: npcID=%s,baseExp=%s,hurtPer=%s" % (curNPC.GetNPCID(), baseExp, hurtPer), playerID)  | 
|             baseExp *= hurtPer  | 
|         #else:  | 
|         #    GameWorld.DebugLog("¸öÈË»÷ɱ»ù´¡¾Ñé: npcID=%s,baseExp=%s" % (curNPC.GetNPCID(), baseExp), playerID)  | 
|           | 
|         #¾ÑéË¥¼õ¹«Ê½ = max(ɱ¹Ö¾Ñé * max(1-max(Íæ¼ÒµÈ¼¶-¹ÖÎïµÈ¼¶-10,0)*0.02)£¬0),1£©  | 
|         npcLV = curNPC.GetLV()  | 
|         exp = eval(FormulaControl.GetCompileFormula("ExpAttenuation", IpyGameDataPY.GetFuncCfg("ExpAttenuation", 1)))  | 
|         #exp = CalcNPCExp(baseExp, playerLV, npcLV)  | 
|         #GameWorld.DebugLog("»÷ɱNPC×îÖÕ»ù´¡¾Ñé: npcID=%s,npcLV=%s,playerLV=%s,baseExp=%s,exp=%s"   | 
|         #                   % (curNPC.GetNPCID(), npcLV, playerLV, baseExp, exp), playerID)  | 
|         return exp  | 
|       | 
|     #---------------------------------------------------------------------  | 
|       | 
|     ## ÔÚµØÍ¼ÉÏ´´½¨ÎïÆ·  | 
|     #  @param posX: ×ø±êX  | 
|     #  @param posY: ×ø±êY  | 
|     #  @param dropType: µôÂäÀàÐÍ  | 
|     #  @param ownerID: ¹éÊôÕß  | 
|     #  @return: None  | 
|     def __MapCreateItem(self, curItem, posX, posY, dropType, ownerID):  | 
|         if not curItem:  | 
|             return  | 
|           | 
|         curNPC = self.__Instance  | 
|         curNPCID = curNPC.GetNPCID()  | 
|           | 
|         #===========================================================================================  | 
|         # ²ß»®ÐèÇó¸ÄΪʰȡ¼Ç¼¼°¹ã²¥  | 
|         # # boss²Å´¦ÀíµôÂäÎïÆ·¼Ç¼  | 
|         # if curNPC.GetIsBoss():  | 
|         #    killerName = "" if not self.__Killer else self.__Killer.GetPlayerName()  | 
|         #    killerid = 0 if not self.__Killer else self.__Killer.GetPlayerID()  | 
|         #    SendGameServerGoodItemRecord(curMapID, curNPCID, killerName, killerid, curItem)  | 
|         #===========================================================================================  | 
|           | 
|         # ÔÚµØÉÏÌí¼ÓÎïÆ·(ͳһ½Ó¿Ú)  | 
|         dropNPCID = 0 if not ChConfig.IsGameBoss(curNPC) else curNPCID  | 
|         specOwnerIDList = self.__AllKillerDict.keys() if (len(self.__AllKillerDict) > 1 or dropType == ChConfig.Def_NPCHurtTypeSpecial) else []  | 
|         curMapItem = ChItem.AddMapDropItem(posX, posY, curItem, ownerInfo=[dropType, ownerID, specOwnerIDList], dropNPCID=dropNPCID)  | 
|           | 
|         #ÉèÖøÃÎïÆ·ÉúǰӵÓÐÕß(ÄǸöNPCµôÂäµÄ)  | 
|         if curMapItem == None:  | 
|             GameWorld.Log("µôÂäÎïÆ·,ÎÞ·¨ÕÒµ½µØÍ¼µôÂäÎïÆ·")  | 
|             return  | 
|           | 
|         curMapItem.SetByObj(curNPC.GetGameObjType(), curNPC.GetID())  | 
|         #GameWorld.Log("NPC = %s->ID = %s µôÂäÎïÆ· = %s->ID = %s"%(curNPC.GetName(),curNPC.GetID(),curMapItem.GetItem().GetName(),curMapItem.GetItem().GetItemTypeID()))  | 
|         #ÉèÖÃÎïÆ·Ê°È¡±£»¤  | 
|         #self.__SetItemProtect(curMapItem, dropType, ownerID)  | 
|         return  | 
|       | 
|     def __CreateDropItem(self, curNPC, itemID, count, isAuctionItem, dropPlayer):  | 
|         ## ´´½¨µôÂäµÄÎïÆ·  | 
|         curItem = ItemControler.GetOutPutItemObj(itemID, count, isAuctionItem, curPlayer=dropPlayer)  | 
|         if not curItem:  | 
|             return  | 
|         return curItem  | 
|       | 
|     ##----------------------------------------- ¹éÊô -----------------------------------------------  | 
|       | 
|     def RefreshDropOwner(self, tick, refreshInterval=3000, isDead=False):  | 
|         ## Ë¢ÐÂbossµôÂä¹éÊô  | 
|         # @return: ¿É¹¥»÷µÄµôÂä¹éÊôÄ¿±êÍæ¼Ò  | 
|           | 
|         curNPC = self.__Instance  | 
|         tagObj = None # ¼´½«¹¥»÷µÄÄ¿±ê, ¹éÊô×î´óÉËѪȡ×î´óÉËÑªÍæ¼Ò»ò¶ÓÎé¶ÓÔ±£¬ÆäËûÈ¡×î´ó³ðºÞ  | 
|         ownerType, ownerID = 0, 0  | 
|         dropOwnerType = GetDropOwnerType(curNPC)  | 
|         if isDead:  | 
|             GameWorld.Log("BossËÀÍö: lineID=%s,objID=%s,npcID=%s,dropOwnerType=%s"   | 
|                           % (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), curNPC.GetNPCID(), dropOwnerType))  | 
|         if dropOwnerType == ChConfig.DropOwnerType_MaxHurt:  | 
|             maxHurtObj = self.RefreshHurtList(tick, refreshInterval)  | 
|             if maxHurtObj:  | 
|                 ownerType, ownerID = maxHurtObj.GetValueType(), maxHurtObj.GetValueID()  | 
|                 if ownerType == ChConfig.Def_NPCHurtTypeTeam:  | 
|                     tagObj = self.__GetMaxHurtTeamPlayer(ownerID, isDead)  | 
|                 elif ownerType == ChConfig.Def_NPCHurtTypePlayer:  | 
|                     tagObj = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)  | 
|                       | 
|         elif dropOwnerType == ChConfig.DropOwnerType_Family:  | 
|             ownerInfo = FamilyRobBoss.RefreshFamilyOwnerNPCHurt(self, curNPC, tick, refreshInterval)  | 
|             if ownerInfo:  | 
|                 tagObj, ownerFamilyID = ownerInfo  | 
|                 ownerType, ownerID = ChConfig.Def_NPCHurtTypeFamily, ownerFamilyID  | 
|                   | 
|         elif dropOwnerType == ChConfig.DropOwnerType_Contend:  | 
|             tagObj = self.__RefreshContendOwner()  | 
|             if tagObj:  | 
|                 ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, tagObj.GetPlayerID()  | 
|                   | 
|         if isDead:  | 
|             GameWorld.Log("ownerType=%s, ownerID=%s, tagObjID=%s" % (ownerType, ownerID, 0 if not tagObj else tagObj.GetPlayerID()))  | 
|                   | 
|         # Ã»Óй¥»÷Ä¿±ê£¬ÔòˢгðºÞ£¬Ö§³ÖÖ÷¶¯¹Ö  | 
|         if not tagObj:  | 
|             angryObjType, maxAngryObj = None, None  | 
|             self.RefreshAngryList(tick, refreshInterval, isUpdAngry=True)  | 
|             maxAngry = self.GetMaxAngryTag()  | 
|             if maxAngry:  | 
|                 angryID = maxAngry.GetObjID()  | 
|                 angryObjType = maxAngry.GetObjType()  | 
|                 #GameWorld.DebugLog("×î´ó³ðºÞÄ¿±ê: ID=%s, Type=%s" % (angryID, angryObjType))  | 
|                 maxAngryObj = GameWorld.GetObj(angryID, angryObjType)  | 
|                   | 
|             tagObj = maxAngryObj  | 
|             if angryObjType == IPY_GameWorld.gotPlayer and maxAngryObj and not ownerType:  | 
|                 if dropOwnerType == ChConfig.DropOwnerType_Contend:  | 
|                     ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, maxAngryObj.GetPlayerID()  | 
|                 elif maxAngryObj.GetTeamID():  | 
|                     ownerType, ownerID = ChConfig.Def_NPCHurtTypeTeam, maxAngryObj.GetTeamID()  | 
|                 else:  | 
|                     ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, maxAngryObj.GetPlayerID()  | 
|               | 
|             if isDead:  | 
|                 GameWorld.Log("angryObj, ownerType=%s, ownerID=%s" % (ownerType, ownerID))  | 
|                   | 
|         self.UpdateDropOwner(tick, ownerType, ownerID, isDead)  | 
|         return tagObj  | 
|       | 
|     def __RefreshContendOwner(self):  | 
|         ## Ë¢ÐÂbossÕù¶á¹éÊôÕߣ¬¹éÊôÒÆ³ýʱ²»×öË¢ÐÂйéÊô£¬Ä¬ÈÏÓɺóÃæµÄ³ðºÞˢР | 
|           | 
|         curNPC = self.__Instance  | 
|         ownerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerID)  | 
|         ownerType = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerType)  | 
|         if not ownerID or ownerType != ChConfig.Def_NPCHurtTypePlayer:  | 
|             return  | 
|           | 
|         owner = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)  | 
|         if not owner:  | 
|             return  | 
|           | 
|         if not owner.GetVisible():  | 
|             GameWorld.DebugLog("¾ºÕù¹éÊôÍæ¼Ò²»¿É¼û£¬ÒƳý¹éÊô!playerID=%s" % ownerID)  | 
|             return  | 
|           | 
|         if owner.GetHP() <= 0 or owner.GetPlayerAction() == IPY_GameWorld.paDie:  | 
|             GameWorld.DebugLog("¾ºÕù¹éÊôÍæ¼ÒËÀÍö£¬ÒƳý¹éÊô!playerID=%s" % ownerID)  | 
|             return  | 
|           | 
|         refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|         if not self.GetIsInRefreshPoint(owner.GetPosX(), owner.GetPosY(), refreshPoint):  | 
|             GameWorld.DebugLog("¾ºÕù¹éÊôÍæ¼Ò²»ÔÚboss·¶Î§Àï£¬ÒÆ³ý¹éÊô!playerID=%s" % ownerID)  | 
|             return  | 
|           | 
|         #GameWorld.DebugLog("¾ºÕù¹éÊôÍæ¼Ò¹éÊôÕý³££¡playerID=%s" % ownerID)  | 
|         return owner  | 
|   | 
|     def __GetMaxHurtTeamPlayer(self, teamID, isDead):  | 
|         ## »ñÈ¡×î´óÉËѪ¶ÓÎéÖй¥»÷µÄÄ¿±ê¶ÓÔ±  | 
|           | 
|         curNPC = self.__Instance  | 
|         curTeam = GameWorld.GetTeamManager().FindTeam(teamID)  | 
|         if curTeam:  | 
|             refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|             if isDead:  | 
|                 GameWorld.Log("¶ÓÎé³ÉÔ±Êý: teamID=%s,memberCount=%s" % (teamID, curTeam.GetMemberCount()))  | 
|             for i in xrange(curTeam.GetMemberCount()):  | 
|                 curTeamPlayer = curTeam.GetMember(i)  | 
|                 if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:  | 
|                     if isDead:  | 
|                         GameWorld.Log("    i=%s, ¶ÓԱΪ¿Õ!" % i)  | 
|                     continue  | 
|                 if curTeamPlayer.GetHP() <= 0:  | 
|                     if isDead:  | 
|                         GameWorld.Log("    i=%s, ¶ÓԱѪÁ¿Îª0!, memPlayerID=%s" % (i, curTeamPlayer.GetPlayerID()))  | 
|                     continue  | 
|                 if not curTeamPlayer.GetVisible():  | 
|                     if isDead:  | 
|                         GameWorld.Log("    i=%s, ¶ÓÔ±²»¿É¼û!, memPlayerID=%s" % (i, curTeamPlayer.GetPlayerID()))  | 
|                     continue  | 
|                 if isDead:  | 
|                     GameWorld.Log("    i=%s, ¶ÓÔ±×ø±ê(%s, %s)! memPlayerID=%s" % (i, curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), curTeamPlayer.GetPlayerID()))  | 
|                 if self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint):  | 
|                     return curTeamPlayer  | 
|         else:  | 
|             GameWorld.ErrLog("ÕÒ²»µ½¸Ã¶ÓÎé: teamID=%s" % teamID)  | 
|         return  | 
|       | 
|     def UpdateDropOwner(self, tick, ownerType=0, ownerID=0, isDead=False):  | 
|           | 
|         curNPC = self.__Instance  | 
|         npcID = curNPC.GetNPCID()  | 
|         dropOwnerType = GetDropOwnerType(curNPC)  | 
|         if dropOwnerType not in [ChConfig.DropOwnerType_MaxHurt, ChConfig.DropOwnerType_MaxAngry, ChConfig.DropOwnerType_Family, ChConfig.DropOwnerType_Contend]:  | 
|             #GameWorld.DebugLog("²»ÐèҪչʾµôÂä¹éÊôµÄNPC! npcID=%s,dropOwnerType=%s" % (npcID, dropOwnerType))  | 
|             return  | 
|           | 
|         lastDropOwnerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerID)  | 
|         lastDropOwnerType = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerType)  | 
|           | 
|         key = (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), npcID)  | 
|         if lastDropOwnerID and (lastDropOwnerType != ownerType or lastDropOwnerID != ownerID):  | 
|             GameWorld.Log("¹éÊô±ä¸ü, Çå³ý¾É¹éÊô! key=%s,ownerType=%s,ownerID=%s,lastDropOwnerType=%s,lastDropOwnerID=%s"   | 
|                           % (key, ownerType, ownerID, lastDropOwnerType, lastDropOwnerID))  | 
|             self.__DelDropOwnerBuff(dropOwnerType, lastDropOwnerType, lastDropOwnerID, tick)  | 
|           | 
|         killerDict, curTeam, hurtType, hurtID = {}, None, 0, 0  | 
|           | 
|         # ¸üйéÊô  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_LastDropOwnerID, ownerID)  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_LastDropOwnerType, ownerType)  | 
|               | 
|         if isDead:  | 
|             GameWorld.Log("Boss¹éÊô: key=%s,ownerType=%s,ownerID=%s" % (key, ownerType, ownerID))  | 
|               | 
|         # Ë¢Ð¹éÊô  | 
|         if ownerType == ChConfig.Def_NPCHurtTypePlayer:  | 
|             curPlayer = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)  | 
|             if curPlayer:  | 
|                 playerID = curPlayer.GetPlayerID()  | 
|                 hurtType, hurtID = ChConfig.Def_NPCHurtTypePlayer, playerID  | 
|                 killerDict[playerID] = curPlayer  | 
|                 self.__AddDropOwnerPlayerBuff(curPlayer, tick)  | 
|                 if dropOwnerType == ChConfig.DropOwnerType_Contend:  | 
|                     curPlayer.SetDict(ChConfig.Def_PlayerKey_ContendNPCObjID, curNPC.GetID())  | 
|                       | 
|         elif ownerType == ChConfig.Def_NPCHurtTypeTeam:  | 
|             curTeam = GameWorld.GetTeamManager().FindTeam(ownerID)  | 
|             if not curTeam:  | 
|                 return  | 
|               | 
|             # ÒòΪÓл÷ɱ´ÎÊýÏÞÖÆ£¬ËùÒÔ²»ÊÇËùÓеĶÓÔ±¶¼¿ÉÒÔ»ñµÃ¹éÊô£¬ËùÒÔÕâÀïÉèÖÃÎªÌØÊâÖ¸¶¨Íæ¼ÒµôÂä  | 
|             hurtType, hurtID = ChConfig.Def_NPCHurtTypeSpecial, 0  | 
|             if isDead:  | 
|                 GameWorld.Log("¶ÓÎé³ÉÔ±Êý: %s" % (curTeam.GetMemberCount()))  | 
|             refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|             for i in xrange(curTeam.GetMemberCount()):  | 
|                 curTeamPlayer = curTeam.GetMember(i)  | 
|                 if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:  | 
|                     if isDead:  | 
|                         GameWorld.Log("    i=%s, ³ÉÔ±²»´æÔÚ!" % (i))  | 
|                     continue  | 
|                   | 
|                 if curTeamPlayer.GetCopyMapID() == GameWorld.GetGameWorld().GetCopyMapID() \  | 
|                     and self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint) \  | 
|                     and AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False) and curTeamPlayer.GetVisible():  | 
|                     self.__AddDropOwnerPlayerBuff(curTeamPlayer, tick)  | 
|                     killerDict[curTeamPlayer.GetPlayerID()] = curTeamPlayer  | 
|                     if isDead:  | 
|                         GameWorld.Log("    i=%s, ³ÉÔ±ÓйéÊôȨ! memPlayerID=%s,±³°üÊ£Óà¿Õ¸ñ=%s"   | 
|                                       % (i, curTeamPlayer.GetPlayerID(), ItemCommon.GetItemPackSpace(curTeamPlayer, IPY_GameWorld.rptItem)))  | 
|                           | 
|                 # ²»Í¬Ïß¡¢»òÕß¾àÀ볬³öboss·¶Î§µÄ¶ÓÔ±²»¼Ó¹éÊôbuff  | 
|                 else:  | 
|                     isOk = BuffSkill.DelBuffBySkillID(curTeamPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)  | 
|                     if isOk:  | 
|                         GameWorld.DebugLog("ɾ³ý¹éÊô¶ÓÔ±buff: teamID=%s,playerID=%s" % (ownerID, curTeamPlayer.GetPlayerID()))  | 
|                     if isDead:  | 
|                         GameWorld.Log("    i=%s, ³ÉÔ±ÎÞ¹éÊôȨ! memPlayerID=%s,copyMapID=%s,pos(%s,%s),CheckKillNPCByCnt=%s"   | 
|                                       % (i, curTeamPlayer.GetPlayerID(), curTeamPlayer.GetCopyMapID(),   | 
|                                          curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(),   | 
|                                          AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False)))  | 
|                           | 
|         elif ownerType == ChConfig.Def_NPCHurtTypeFamily:  | 
|               | 
|             hurtType, hurtID = ChConfig.Def_NPCHurtTypeFamily, ownerID  | 
|             refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())  | 
|             copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()  | 
|             for index in xrange(copyPlayerMgr.GetPlayerCount()):  | 
|                 player = copyPlayerMgr.GetPlayerByIndex(index)  | 
|                 if not player:  | 
|                     continue  | 
|                   | 
|                 # ¹éÊôÏÉÃË ÇÒ ÔÚbossÇøÓòÄÚ  | 
|                 if player.GetFamilyID() == ownerID and self.GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint) and player.GetVisible():  | 
|                     self.__AddDropOwnerPlayerBuff(player, tick)  | 
|                       | 
|                 else:  | 
|                     isOk = BuffSkill.DelBuffBySkillID(player, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)  | 
|                     if isOk:  | 
|                         GameWorld.DebugLog("ɾ³ý·Ç¹éÊôÏÉÃ˳ÉÔ±buff: teamID=%s,playerID=%s" % (ownerID, player.GetPlayerID()))  | 
|                   | 
|         if isDead:  | 
|             #key = (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), npcID)  | 
|             teamID = curTeam.GetTeamID() if curTeam else 0  | 
|             if killerDict:  | 
|                 PyGameData.g_npcKillerInfo[key] = killerDict, curTeam, hurtType, hurtID  | 
|             elif ownerType == ChConfig.Def_NPCHurtTypeFamily:  | 
|                 PyGameData.g_npcKillerInfo[key] = {}, None, hurtType, hurtID  | 
|                   | 
|             GameWorld.Log("Boss±»»÷ɱ: npcID=%s,key=%s,playerIDList=%s,teamID=%s,hurtType=%s,hurtID=%s"   | 
|                           % (npcID, key, killerDict.keys(), teamID, hurtType, hurtID))  | 
|         return  | 
|   | 
|     def __AddDropOwnerPlayerBuff(self, curPlayer, tick):  | 
|         curNPC = self.__Instance  | 
|         findBuff = SkillCommon.FindBuffByID(curPlayer, ChConfig.Def_SkillID_DropOwnerBuff)[0]  | 
|         if not findBuff:  | 
|             SkillCommon.AddBuffBySkillType_NoRefurbish(curPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)  | 
|             GameWorld.DebugLog("Ìí¼Ó¹éÊôbuff: playerID=%s" % curPlayer.GetPlayerID())  | 
|         return  | 
|       | 
|     def __DelDropOwnerBuff(self, dropOwnerType, ownerType, ownerID, tick):  | 
|           | 
|         curNPC = self.__Instance  | 
|         if ownerType == ChConfig.Def_NPCHurtTypePlayer:  | 
|             curPlayer = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)  | 
|             if not curPlayer:  | 
|                 return  | 
|             GameWorld.DebugLog("ɾ³ý¹éÊôÍæ¼Òbuff: playerID=%s" % (ownerID))  | 
|             BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)  | 
|             if dropOwnerType == ChConfig.DropOwnerType_Contend:  | 
|                 curPlayer.SetDict(ChConfig.Def_PlayerKey_ContendNPCObjID, 0)  | 
|                   | 
|         elif ownerType == ChConfig.Def_NPCHurtTypeTeam:  | 
|             curTeam = GameWorld.GetTeamManager().FindTeam(ownerID)  | 
|             if not curTeam:  | 
|                 return  | 
|             GameWorld.DebugLog("ɾ³ý¹éÊô¶ÓÎébuff: teamID=%s" % (ownerID))  | 
|             for i in xrange(curTeam.GetMemberCount()):  | 
|                 curTeamPlayer = curTeam.GetMember(i)  | 
|                 if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:  | 
|                     continue  | 
|                 BuffSkill.DelBuffBySkillID(curTeamPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)  | 
|         return  | 
|       | 
|     def DelayDropOwnerBuffDisappearTime(self):  | 
|         ''' ÑÓ³ÙµôÂä¹éÊôbuffÏûʧʱ¼ä '''  | 
|           | 
|         curNPC = self.__Instance  | 
|         ownerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerID)  | 
|         ownerType = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerType)  | 
|           | 
|         if ownerType == ChConfig.Def_NPCHurtTypePlayer:  | 
|             curPlayer = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)  | 
|             if not curPlayer:  | 
|                 return  | 
|             self.__SetDropOwnerBuffDisappearTime(curPlayer)  | 
|               | 
|         elif ownerType == ChConfig.Def_NPCHurtTypeTeam:  | 
|             curTeam = GameWorld.GetTeamManager().FindTeam(ownerID)  | 
|             if not curTeam:  | 
|                 return  | 
|             for i in xrange(curTeam.GetMemberCount()):  | 
|                 curTeamPlayer = curTeam.GetMember(i)  | 
|                 if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:  | 
|                     continue  | 
|                 self.__SetDropOwnerBuffDisappearTime(curTeamPlayer)  | 
|         elif ownerType == ChConfig.Def_NPCHurtTypeFamily:  | 
|             copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()  | 
|             for index in xrange(copyPlayerMgr.GetPlayerCount()):  | 
|                 player = copyPlayerMgr.GetPlayerByIndex(index)  | 
|                 if not player:  | 
|                     continue  | 
|                 self.__SetDropOwnerBuffDisappearTime(player)  | 
|                   | 
|         return  | 
|       | 
|     def __SetDropOwnerBuffDisappearTime(self, curPlayer):  | 
|         ''' ÉèÖõôÂä¹éÊôbuffÏûʧʱ¼ä '''  | 
|           | 
|         curNPC = self.__Instance  | 
|         findSkill = GameWorld.GetGameData().GetSkillBySkillID(ChConfig.Def_SkillID_DropOwnerBuff)  | 
|         if not findSkill:  | 
|             return  | 
|           | 
|         buffType = SkillCommon.GetBuffType(findSkill)  | 
|         buffTuple = SkillCommon.GetBuffManagerByBuffType(curPlayer, buffType)  | 
|         if buffTuple == ():  | 
|             return  | 
|           | 
|         RemainTime = 10000 # ÑÓ³Ù10ÃëÏûʧ  | 
|         tick = GameWorld.GetGameWorld().GetTick()  | 
|           | 
|         buffStateManager = buffTuple[0]  | 
|         for index in xrange(buffStateManager.GetBuffCount()):  | 
|             curBuff = buffStateManager.GetBuff(index)  | 
|             buffSkill = curBuff.GetSkill()  | 
|               | 
|             if buffSkill.GetSkillTypeID() != ChConfig.Def_SkillID_DropOwnerBuff:  | 
|                 continue  | 
|               | 
|             if curNPC.GetID() != curBuff.GetOwnerID():  | 
|                 #GameWorld.DebugLog("·Çbuff¹éÊô×Å£¬²»ÉèÖÃÏûʧʱ¼ä£¡", curPlayer.GetPlayerID())  | 
|                 break  | 
|               | 
|             curBuff.SetCalcStartTick(tick)   | 
|             curBuff.SetRemainTime(RemainTime)  | 
|               | 
|             # Í¨ÖªbuffˢР | 
|             buffStateManager.Sync_RefreshBuff(index, curBuff.GetRemainTime())  | 
|             #GameWorld.DebugLog("µôÂä¹éÊôbuffÏûʧʱ¼ä: RemainTime=%s" % (RemainTime), curPlayer.GetPlayerID())  | 
|             break  | 
|         return  | 
|     ##--------------------------------------------- -----------------------------------------------  | 
|       | 
| def OnPlayerKillNPCPlayer(curPlayer, defender, tick):  | 
|     ## Íæ¼Ò»÷ɱÁËNPCÏà¹ØµÄÍæ¼Ò  | 
|     contendNPCObjID = defender.GetDictByKey(ChConfig.Def_PlayerKey_ContendNPCObjID)  | 
|     if contendNPCObjID:  | 
|         curNPC = GameWorld.FindNPCByID(contendNPCObjID)  | 
|         if not curNPC:  | 
|             return  | 
|         dropOwnerType = GetDropOwnerType(curNPC)  | 
|         if dropOwnerType != ChConfig.DropOwnerType_Contend:  | 
|             return  | 
|         playerID = curPlayer.GetPlayerID()  | 
|         GameWorld.DebugLog("Íæ¼Ò»÷ɱ¾ºÕù¹éÊôÕß! defPlayerID=%s,contendNPCObjID=%s,npcID=%s"   | 
|                            % (defender.GetPlayerID(), contendNPCObjID, curNPC.GetNPCID()), playerID)  | 
|         npcControl = NPCControl(curNPC)  | 
|         npcControl.UpdateDropOwner(tick, ChConfig.Def_NPCHurtTypePlayer, playerID, False)  | 
|           | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| def SendVirtualItemDrop(player, itemID, posX, posY, userDataStr):  | 
|     #֪ͨ¿Í»§¶Ë¼ÙÎïÆ·µôÂä  | 
|     vItemDrop = ChPyNetSendPack.tagMCVirtualItemDrop()  | 
|     vItemDrop.ItemTypeID = itemID  | 
|     vItemDrop.PosX = posX  | 
|     vItemDrop.PosY = posY  | 
|     vItemDrop.UserData = userDataStr  | 
|     vItemDrop.UserDataLen = len(vItemDrop.UserData)  | 
|     NetPackCommon.SendFakePack(player, vItemDrop)  | 
|     return  | 
|       | 
| def GetNPCExp(curPlayer, npcID):  | 
|     npcData = GameWorld.GetGameData().FindNPCDataByID(npcID)  | 
|     if not npcData:  | 
|         return 0  | 
|     baseExp = npcData.GetExp()  | 
|     if not baseExp:  | 
|         return 0  | 
|     npcLV = npcData.GetLV()  | 
|     playerLV = curPlayer.GetLV()  | 
|     return CalcNPCExp(baseExp, playerLV, npcLV)  | 
|   | 
| def CalcNPCExp(baseExp, playerLV, npcLV):  | 
|     #¾ÑéË¥¼õ¹«Ê½ = max(ɱ¹Ö¾Ñé * max(1-max(Íæ¼ÒµÈ¼¶-¹ÖÎïµÈ¼¶-10,0)*0.02)£¬0),1£©  | 
|     exp = eval(FormulaControl.GetCompileFormula("ExpAttenuation", IpyGameDataPY.GetFuncCfg("ExpAttenuation", 1)))  | 
|     return exp  | 
|   | 
| ## NPC±»Íæ¼ÒɱËÀ  | 
| #  @param curNPC µ±Ç°NPC  | 
| #  @param skill   | 
| #  @param HurtID  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def OnPlayerAttackNPCDie(curNPC, curPlayer, skill):  | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%d.%s" % (curNPC.GetAIType(), "OnAttackDieByPlayer"))  | 
|     if callFunc == None:  | 
|         return None  | 
|       | 
|     callFunc(curNPC, curPlayer, skill)   | 
| #---------------------------------------------------------------------  | 
| # Ä¿±ê×ÜÖµ³¬¹ýDWORD¼Ç¼£¬ÐèÐÞÕýÊýÖµ  | 
| # È磺ÉËѪºÍ³ðºÞ³¬¹ý20EµÄÇé¿ö£¬°´¸ßλ¼Ç¼ȡÓà, ×îµÍ1  | 
| def FixValueByValueEx(valueEx, value):  | 
|     if valueEx == 0:  | 
|         return value  | 
|       | 
|     # È¡¸ßλ¼Ç¼µÄÊý×Ö³¤¶È£¬°´10N´Î·½ÇóÓà  | 
|     nlen = len(str(valueEx))  | 
|     return max(value / pow(10, nlen), 1)  | 
|   | 
|   | 
| def CheckCanCollectByNPCID(curPlayer, npcID, collectNPCIpyData):  | 
|     # ¸ù¾ÝNPCIDÅжÏÊÇ·ñ¿ÉÒԲɼ¯  | 
|       | 
|     if GameWorld.IsCrossServer():  | 
|         return True  | 
|       | 
|     limitMaxTime = collectNPCIpyData.GetMaxCollectCount()  | 
|     if limitMaxTime > 0 and GetTodayCollectCount(curPlayer, npcID) >= limitMaxTime:  | 
|         PlayerControl.NotifyCode(curPlayer, collectNPCIpyData.GetCollectCountLimitNotify(), [limitMaxTime])  | 
|         return False  | 
|       | 
|     #±³°ü¿Õ¼äÅÐ¶Ï  | 
|     if collectNPCIpyData.GetCollectAward() and not ItemCommon.CheckPackHasSpace(curPlayer, IPY_GameWorld.rptItem):  | 
|         PlayerControl.NotifyCode(curPlayer, "GeRen_lhs_202580")  | 
|         return False  | 
|       | 
|     #ÏûºÄÎïÆ·²É¼¯£¬´ýÀ©Õ¹...  | 
|       | 
|     return True  | 
|   | 
| def GetTodayCollectCount(curPlayer, npcID):  | 
|     ## »ñÈ¡²É¼¯NPC½ñÈÕÒѲɼ¯´ÎÊý  | 
|     todayCollTime = 0  | 
|     collectTimeShareIDList = IpyGameDataPY.GetFuncEvalCfg("CollectNPC", 1)  | 
|     for npcIDList in collectTimeShareIDList:  | 
|         if npcID not in npcIDList:  | 
|             continue  | 
|         for collNPCID in npcIDList:  | 
|             todayCollTime += curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % collNPCID)  | 
|         return todayCollTime  | 
|     return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID)  | 
|   | 
| def OnCollectNPCBegin(curPlayer, curNPC, tick):  | 
|     ## ²É¼¯NPC¿ªÊ¼²É¼¯  | 
|     npcID = curNPC.GetNPCID()  | 
|     collectNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("CollectNPC", npcID)  | 
|     if not collectNPCIpyData:  | 
|         #GameWorld.DebugLog("·ÇÌØ¶¨²É¼¯NPC...")  | 
|         return False  | 
|       | 
|     if collectNPCIpyData.GetIsMissionCollectNPC():  | 
|         #GameWorld.DebugLog("ÈÎÎñ²É¼¯ÎïÔݲ»´¦Àí")  | 
|         return False  | 
|       | 
|     if not CheckCanCollectByNPCID(curPlayer, npcID, collectNPCIpyData):  | 
|         return True  | 
|       | 
|     canCollTogether = 1  | 
|     collectPlayerID = GetCollectNPCPlayerID(curNPC)  | 
|     # Èç¹û²»ÔÊÐíͬʱ²É£¬ÇÒÓÐÈËÔڲɣ¬ÔòÖ±½Ó·µ»Ø  | 
|     if not canCollTogether and collectPlayerID > 0 and collectPlayerID != curPlayer.GetPlayerID():  | 
|         GameWorld.DebugLog("²»ÔÊÐíͬʱ²É¼¯£¡")  | 
|         sysMark = "GeRen_liubo_436832"  | 
|         if sysMark:  | 
|             PlayerControl.NotifyCode(curPlayer, sysMark)  | 
|         return True  | 
|       | 
|     DoCollectNPCBegin(curPlayer, curNPC, collectNPCIpyData, tick)  | 
|     return True  | 
|   | 
| def DoCollectNPCBegin(curPlayer, curNPC, collectNPCIpyData, tick):  | 
|     ## ¿ªÊ¼²É¼¯  | 
|       | 
|     canCollTogether = 1  | 
|     if not canCollTogether and not SetCollectNPC(curPlayer, curNPC):  | 
|         GameWorld.ErrLog("SetCollectNPC fail!")  | 
|         return  | 
|       | 
|     # ²É¼¯ºÄʱ  | 
|     prepareTime = collectNPCIpyData.GetPrepareTime() * 1000  | 
|     collTimeReduceRate = PlayerVip.GetPrivilegeValue(curPlayer, ChConfig.VIPPrivilege_CollTimeReduceRate)  | 
|     if collTimeReduceRate:  | 
|         prepareTime = max(1000, int(prepareTime * (ShareDefine.Def_MaxRateValue - collTimeReduceRate) / float(ShareDefine.Def_MaxRateValue)))  | 
|     PlayerControl.Sync_PrepareBegin(curPlayer, prepareTime, IPY_GameWorld.pstMissionCollecting, prepareID=curNPC.GetID())  | 
|       | 
|     if collectNPCIpyData.GetLostHPPer():  | 
|         curPlayer.SetDict(ChConfig.Def_PlayerKey_CollectLostHPTick, tick)  | 
|           | 
|     FBLogic.OnBeginCollect(curPlayer, curNPC)  | 
|     ##Ìí¼ÓÕâ¸öNPCµÄÉËѪÁÐ±í£¬ÓÃÓÚÅжϿɷñͬʱ²É¼¯£¬¸ÄΪ×ÖµäÅÐ¶Ï  | 
|     AttackCommon.AddHurtValue(curNPC, curPlayer.GetPlayerID(), ChConfig.Def_NPCHurtTypePlayer, 1)  | 
|     return  | 
|   | 
| def SetCollectNPC(curPlayer, curNPC):  | 
|     ## ÉèÖÃÍæ¼Ò²É¼¯¸ÃNPC  | 
|     curPlayerID = curPlayer.GetPlayerID()  | 
|     curNPCObjID = curNPC.GetID()  | 
|     curCollectPlayerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_CollectPlayerID)  | 
|     if curCollectPlayerID:  | 
|         curCollectPlayer = GameWorld.GetPlayerManager().FindPlayerByID(curCollectPlayerID)  | 
|         # ÓÐÈËÔڲɼ¯ÇÒ²»ÊÇͬһ¸öÈË£¬Ôò²»¿ÉÖØÐÂÉèÖòɼ¯¶ÔÏó  | 
|         if curCollectPlayer and curPlayerID != curCollectPlayerID:  | 
|             GameWorld.DebugLog("SetNPCColleced ÓÐÈËÔڲɼ¯ÇÒ²»ÊÇͬһ¸öÈË£¬Ôò²»¿ÉÖØÐÂÉèÖòɼ¯¶ÔÏó")  | 
|             return False  | 
|               | 
|     curNPC.SetDict(ChConfig.Def_NPC_Dict_CollectPlayerID, curPlayerID)  | 
|     curPlayer.SetDict(ChConfig.Def_PlayerKey_CollectNPCObjID, curNPCObjID)  | 
|     return True  | 
|   | 
|   | 
| ## »ñÈ¡²É¼¯¸ÃNPCµÄÍæ¼Òid  | 
| #  @param curNPC£º²É¼¯NPCʵÀý  | 
| #  @return Íæ¼Òid£¬Ã»Óзµ»Ø0  | 
| def GetCollectNPCPlayerID(curNPC):  | 
|     curCollectPlayerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_CollectPlayerID)  | 
|     if curCollectPlayerID <= 0:  | 
|         return 0  | 
|       | 
|     curCollectPlayer = GameWorld.GetPlayerManager().FindPlayerByID(curCollectPlayerID)  | 
|     # ÓÐÈËÔڲɼ¯ÇÒ²»ÊÇͬһ¸öÈË£¬µ«ÕÒ²»µ½¸ÃÍæ¼ÒÁË£¬ÔòÇå¿Õ²É¼¯¶ÔÏóid  | 
|     if not curCollectPlayer:  | 
|         GameWorld.DebugLog("GetCollectNPCID ÓÐcurCollectPlayerID=%s£¬µ«ÕÒ²»µ½¸ÃÍæ¼Ò£¬ÖØÖÃ!"   | 
|                            % curCollectPlayerID)  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_CollectPlayerID, 0)  | 
|         return 0  | 
|       | 
|     return curCollectPlayerID  | 
|   | 
|   | 
| ## Çå³ýÍæ¼Ò²É¼¯µÄNPCÐÅÏ¢  | 
| #  @param curNPC£º²É¼¯NPCʵÀý  | 
| #  @return  | 
| def ClearCollectNPC(curPlayer):  | 
|     collectNPCObjID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CollectNPCObjID)  | 
|     #GameWorld.DebugLog("ClearCollectNPC collectNPCObjID=%s" % collectNPCObjID)  | 
|     if collectNPCObjID <= 0:  | 
|         return  | 
|       | 
|     curNPC = GameWorld.FindNPCByID(collectNPCObjID)  | 
|     if curNPC:  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_CollectPlayerID, 0)  | 
|         #GameWorld.DebugLog("    collectNPCObjID=%s NPC set collectPlaerID 0" % collectNPCObjID)  | 
|   | 
|     curPlayer.SetDict(ChConfig.Def_PlayerKey_CollectNPCObjID, 0)  | 
|     #GameWorld.DebugLog("    set collectNPCObjID 0")  | 
|     return  | 
|   | 
| def DoCollectNPCOK(curPlayer, npcID, tick):  | 
|     ## ²É¼¯NPC²É¼¯½áÊø  | 
|     collectNPCIpyData = IpyGameDataPY.GetIpyGameData("CollectNPC", npcID)  | 
|     if not collectNPCIpyData:  | 
|         GameWorld.DebugLog("    ·ÇÌØ¶¨²É¼¯NPC...npcID=%s" % npcID)  | 
|         return  | 
|       | 
|     if collectNPCIpyData.GetIsMissionCollectNPC():  | 
|         #GameWorld.DebugLog("ÈÎÎñ²É¼¯ÎïÔݲ»´¦Àí")  | 
|         return  | 
|       | 
|     PlayerState.DoCollectingLostHP(curPlayer, collectNPCIpyData, tick, True)  | 
|       | 
|     if GameWorld.IsCrossServer():  | 
|         # ·¢Ëͻر¾·þ²É¼¯Íê³É  | 
|         serverGroupID = PlayerControl.GetPlayerServerGroupID(curPlayer)  | 
|         msgInfo = {"Result":1, "PlayerID":curPlayer.GetPlayerID(), "NPCID":npcID}  | 
|         GameWorld.SendMsgToClientServer(ShareDefine.CrossServerMsg_CollectNPCOK, msgInfo, [serverGroupID])  | 
|     else:  | 
|         DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData)  | 
|           | 
|     FBLogic.OnCollectOK(curPlayer, npcID, tick)  | 
|       | 
|     ClearCollectNPC(curPlayer)      | 
|     return True  | 
|   | 
| def CrossServerMsg_CollectNPCOK(curPlayer, msgData):  | 
|     ## ÊÕµ½¿ç·þͬ²½µÄ²É¼¯Íê³É  | 
|     if not msgData["Result"]:  | 
|         return  | 
|     npcID = msgData["NPCID"]  | 
|     collectNPCIpyData = IpyGameDataPY.GetIpyGameData("CollectNPC", npcID)  | 
|     if collectNPCIpyData:  | 
|         DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData)  | 
|     return  | 
|   | 
| #// A2 34 ×Ô¶¨Ò峡¾°ÖлñÈ¡²É¼¯½±Àø #tagCMGetCustomSceneCollectAward  | 
| #  | 
| #struct    tagCMGetCustomSceneCollectAward  | 
| #{  | 
| #    tagHead        Head;  | 
| #    DWORD        NPCID;    //²É¼¯µÄNPCID  | 
| #};  | 
| def OnGetCustomSceneCollectAward(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     npcID = clientData.NPCID  | 
|     if not curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomScene):  | 
|         GameWorld.ErrLog("·Ç×Ô¶¨Ò峡¾°ÖУ¬ÎÞ·¨»ñÈ¡¶¨Òå²É¼¯½±Àø!", playerID)  | 
|         return  | 
|     mapID = PlayerControl.GetCustomMapID(curPlayer)  | 
|     lineID = PlayerControl.GetCustomLineID(curPlayer)  | 
|     GameWorld.Log("ǰ¶Ë³¡¾°²É¼¯: mapID=%s,lineID=%s,npcID=%s" % (mapID, lineID, npcID), playerID)  | 
|     if not mapID:  | 
|         GameWorld.ErrLog("ÎÞ×Ô¶¨Ò峡¾°µØÍ¼ID£¬²»ÔÊÐí²É¼¯!", playerID)  | 
|         return  | 
|       | 
|     if not FBLogic.OnCustomSceneCollectOK(curPlayer, mapID, lineID, npcID):  | 
|         GameWorld.ErrLog("×Ô¶¨Ò峡¾°µØÍ¼²»ÔÊÐí²É¼¯! mapID=%s,lineID=%s,npcID=%s" % (mapID, lineID, npcID), playerID)  | 
|         return  | 
|       | 
|     collectNPCIpyData = IpyGameDataPY.GetIpyGameData("CollectNPC", npcID)  | 
|     if collectNPCIpyData:  | 
|         DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData)  | 
|     return  | 
|   | 
| def DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData, collectCnt=1):  | 
|     GameWorld.DebugLog("¸ø²É¼¯½±Àø: npcID=%s,collectCnt=%s" % (npcID, collectCnt))  | 
|     if collectCnt <= 0:  | 
|         return  | 
|   | 
|     if collectNPCIpyData.GetIsMissionCollectNPC():  | 
|         #GameWorld.DebugLog("ÈÎÎñ²É¼¯ÎïÔݲ»´¦Àí")  | 
|         return  | 
|       | 
|     isMaxTime = False # ÊÇ·ñ´ïµ½Á˲ɼ¯×î´ó´ÎÊý  | 
|     limitMaxTime = collectNPCIpyData.GetMaxCollectCount()  | 
|     if limitMaxTime > 0:  | 
|         todayCollTime = GetTodayCollectCount(curPlayer, npcID)  | 
|         canCollectCnt = max(0, limitMaxTime - todayCollTime)  | 
|         collectCnt = min(collectCnt, canCollectCnt)  | 
|         if collectCnt <= 0:  | 
|             GameWorld.DebugLog("    ¸ÃNPCÒÑ´ïµ½×î´ó²É¼¯´ÎÊý: npcID=%s,todayCollTime=%s,limitMaxTime=%s" % (npcID, todayCollTime, limitMaxTime))  | 
|             return  | 
|           | 
|         curCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID)  | 
|         updCollTime = curCollTime + collectCnt  | 
|         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTime % npcID, updCollTime)  | 
|         SyncCollNPCTime(curPlayer, [npcID])  | 
|         GameWorld.DebugLog("    Ôö¼Ó²É¼¯´ÎÊý: npcID=%s,todayCollTime=%s,curCollTime=%s,updCollTime=%s" % (npcID, todayCollTime, curCollTime, updCollTime))  | 
|         isMaxTime = todayCollTime + collectCnt >= limitMaxTime  | 
|           | 
|     awardItemList = []  | 
|     collectAwardCfg = collectNPCIpyData.GetCollectAward()  | 
|     collectAppointAwardCfg = collectNPCIpyData.GetCollectAppointAward()  | 
|     if collectAppointAwardCfg:  | 
|         #çÎ翲ÝÔ°µÄ²É¼¯¶¨ÖÆÓÉçÎç¿Ñ°·Ã´ÎÊý¾ö¶¨  | 
|         if collectNPCIpyData.GetCollectResetType() in [12, 14]:  | 
|             fairyDomainVisitCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FairyDomainVisitCnt)  | 
|             grasslandCollectAppointCfg = collectAppointAwardCfg.get(fairyDomainVisitCnt, {})  | 
|             curCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID)  | 
|             if curCollTime in grasslandCollectAppointCfg:  | 
|                 awardItemList.append(grasslandCollectAppointCfg[curCollTime])  | 
|             GameWorld.DebugLog("    ²ÝÔ°²É¼¯¶¨Öƽ±Àø: fairyDomainVisitCnt=%s,curCollTime=%s,awardItemList=%s" % (fairyDomainVisitCnt, curCollTime, awardItemList))  | 
|         else:  | 
|             collTotalTime = min(curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTimeTotal % npcID) + 1, ChConfig.Def_UpperLimit_DWord)  | 
|             if collTotalTime in collectAppointAwardCfg:  | 
|                 awardItemList.append(collectAppointAwardCfg[collTotalTime])  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTimeTotal % npcID, collTotalTime)  | 
|             GameWorld.DebugLog("    ²É¼¯´ÎÊý¶¨Öƽ±Àø: collTotalTime=%s,awardItemList=%s" % (collTotalTime, awardItemList))  | 
|           | 
|     if not awardItemList:  | 
|         alchemyDiffLV = collectNPCIpyData.GetAlchemyDiffLV()  | 
|         giveItemWeightList = ItemCommon.GetWeightItemListByAlchemyDiffLV(curPlayer, collectAwardCfg, alchemyDiffLV)  | 
|         GameWorld.DebugLog("    ³£¹æ²É¼¯ÎïÆ·È¨ÖØÁбí: alchemyDiffLV=%s,collectAwardCfg=%s,giveItemWeightList=%s" % (alchemyDiffLV, collectAwardCfg, giveItemWeightList))  | 
|         giveItemInfo = GameWorld.GetResultByWeightList(giveItemWeightList)  | 
|         if giveItemInfo:  | 
|             awardItemList.append(giveItemInfo)  | 
|               | 
|     GameWorld.DebugLog("    ×îÖղɼ¯½±Àø: awardItemList=%s" % awardItemList)  | 
|     if awardItemList:  | 
|         for itemID, itemCount, isAuctionItem in awardItemList:  | 
|             ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem])  | 
|         if collectNPCIpyData.GetNotifyCollectResult():  | 
|             awardPack = ChPyNetSendPack.tagMCCollectAwardItemInfo()  | 
|             awardPack.CollectNPCID = npcID  | 
|             for itemID, itemCount, isAuctionItem in awardItemList:  | 
|                 awardItem = ChPyNetSendPack.tagMCCollectAwardItem()  | 
|                 awardItem.ItemID = itemID  | 
|                 awardItem.Count = itemCount  | 
|                 awardItem.IsAuctionItem = isAuctionItem  | 
|                 awardPack.AwardItemList.append(awardItem)  | 
|             awardPack.Count = len(awardPack.AwardItemList)  | 
|             NetPackCommon.SendFakePack(curPlayer, awardPack)  | 
|         GameLogic_CrossGrassland.RecordGrasslandAward(curPlayer, awardItemList)  | 
|     else:  | 
|         GameWorld.ErrLog("²É¼¯ÎïÆ·Ã»Óн±Àø£¡npcID=%s" % (npcID))  | 
|           | 
|     #²É¼¯³É¾Í  | 
|     PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_Collect, collectCnt, [npcID])  | 
|     #SyncCollectionItemInfo(curPlayer, addExp, addMoney, addZhenQi, giveItemInfoList, npcID)  | 
|       | 
|     GameLogic_CrossGrassland.DecCustomSceneNPCCount(curPlayer, npcID)  | 
|     if isMaxTime:  | 
|         GameLogic_CrossGrassland.DoCheckUpdateGrasslandEnd(curPlayer)  | 
|           | 
|     return  | 
|   | 
| ## ²É¼¯½á¹ûͬ²½  | 
| #  @param None  | 
| #  @param None  | 
| def SyncCollectionItemInfo(curPlayer, addExp, addMoney, addZhenQi, syncItemInfoList, collectNPCID=0):  | 
|     return #Ôݲ»Í¬²½  | 
|   | 
| def SyncCollNPCTime(curPlayer, npcIDList=[]):  | 
|     ## Í¬²½²É¼¯NPC¹¦ÄܺŲɼ¯´ÎÊý  | 
|       | 
|     isSyncAll = False  | 
|     if not npcIDList:  | 
|         isSyncAll = True  | 
|         ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|         for index in xrange(ipyDataMgr.GetCollectNPCCount()):  | 
|             ipyData = ipyDataMgr.GetCollectNPCByIndex(index)  | 
|             if ipyData.GetMaxCollectCount():  | 
|                 npcIDList.append(ipyData.GetNPCID())  | 
|                   | 
|     if not npcIDList:  | 
|         return  | 
|       | 
|     syncList = []  | 
|     for npcID in npcIDList:  | 
|         collCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID)  | 
|         if isSyncAll and not collCount:  | 
|             continue  | 
|         collCntInfo = ChPyNetSendPack.tagMCNPCIDCollectionCnt()  | 
|         collCntInfo.Clear()  | 
|         collCntInfo.NPCID = npcID  | 
|         collCntInfo.CollectionCnt = collCount  | 
|         syncList.append(collCntInfo)  | 
|           | 
|     if not syncList:  | 
|         return  | 
|       | 
|     npcIDCollInfo = ChPyNetSendPack.tagMCNPCIDCollectionCntInfo()  | 
|     npcIDCollInfo.Clear()  | 
|     npcIDCollInfo.NPCCollCntList = syncList  | 
|     npcIDCollInfo.CollNPCCnt = len(npcIDCollInfo.NPCCollCntList)  | 
|     NetPackCommon.SendFakePack(curPlayer, npcIDCollInfo)  | 
|     return  | 
|   | 
| def CollNPCTimeOnDay(curPlayer):  | 
|     ## ²É¼¯NPCOnDay´¦Àí  | 
|     DoResetCollectNPCTimeByType(curPlayer, [1])  | 
|     return  | 
|   | 
| def DoResetCollectNPCTimeByType(curPlayer, resetTypeList=[]):  | 
|     '''ÖØÖòɼ¯Îï²É¼¯´ÎÊý  | 
|             ÖØÖÃÀàÐÍ: 0-²»ÖØÖã¬1-ÿÈÕ5µã£¬12-Áé²ÝÔ°ÖØÖã¬14-ÏɲÝÔ°ÖØÖà  | 
|     '''  | 
|     resetNPCIDList = []  | 
|     ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|     for index in xrange(ipyDataMgr.GetCollectNPCCount()):  | 
|         ipyData = ipyDataMgr.GetCollectNPCByIndex(index)  | 
|         npcID = ipyData.GetNPCID()  | 
|         if resetTypeList and ipyData.GetCollectResetType() not in resetTypeList:  | 
|             continue  | 
|         if not ipyData.GetMaxCollectCount():  | 
|             continue  | 
|         if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID):  | 
|             continue  | 
|         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTime % npcID, 0)  | 
|         resetNPCIDList.append(npcID)  | 
|           | 
|     if resetNPCIDList:  | 
|         #GameWorld.DebugLog("ÖØÖòɼ¯´ÎÊý: resetTypeList=%s,resetNPCIDList=%s" % (resetTypeList, resetNPCIDList), curPlayer.GetPlayerID())  | 
|         SyncCollNPCTime(curPlayer, resetNPCIDList)  | 
|     return  | 
|   | 
|   | 
| ## »ñÈ¡±¾µØÍ¼NPC״̬, Ò»°ãÓÃÓÚBossË¢¹Öµã״̬²éѯ  | 
| #  @param queryNPCIDList£º²éѯµÄNPCIDÁÐ±í  | 
| #  @param tick  | 
| #  @return {NPCID:[curHP,maxHP,Ê£Óà¶àÉÙÃëË¢ÐÂ]}  | 
| def GetNPCInfo(queryNPCIDList, tick):  | 
|     npcInfoDict = {}  | 
|   | 
|     if not queryNPCIDList:  | 
|         return npcInfoDict  | 
|       | 
|     gameNPCManager = GameWorld.GetNPCManager()  | 
|     GameWorld.DebugLog("GetNPCInfo...queryNPCIDList=%s" % (str(queryNPCIDList)))  | 
|     findNPCIDList = []  | 
|     for index in range(gameNPCManager.GetNPCCount()):  | 
|         curNPC = gameNPCManager.GetNPCByIndex(index)  | 
|         curID = curNPC.GetID()  | 
|         if curID == 0:  | 
|             continue  | 
|           | 
|         curNPCID = curNPC.GetNPCID()  | 
|           | 
|         if curNPCID not in queryNPCIDList:  | 
|             continue  | 
|           | 
|         findNPCIDList.append(curNPCID)  | 
|         isAlive = 1  | 
|         curHP = GameObj.GetHP(curNPC)  | 
|         posX = curNPC.GetPosX()  | 
|         posY = curNPC.GetPosY()  | 
|         maxHP = GameObj.GetMaxHP(curNPC)  | 
|         refreshRemaindSecond = 0 # Ê£Óà¶àÉÙÃëˢР | 
|         if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():  | 
|             isAlive = 0  | 
|             refreshTime = curNPC.GetRefreshTime()  | 
|               | 
|             if refreshTime > 0:  | 
|                 passTick = max(0, tick - curNPC.GetActionTick())  | 
|                 refreshRemaindSecond = max(1000, refreshTime - passTick) / 1000  | 
|                   | 
|                   | 
|         npcInfoDict[curID] = [curNPCID, curHP, maxHP, posX, posY, isAlive, refreshRemaindSecond]  | 
|                   | 
|     GameWorld.DebugLog("    npcInfoDict=%s" % (str(npcInfoDict)))  | 
|     return npcInfoDict  | 
|   | 
|   | 
| ## Í¬²½µØÍ¼NPCÐÅÏ¢  | 
| #  @param curPlayer£º²É¼¯Íæ¼ÒʵÀý  | 
| #  @param mapID£º  | 
| #  @param npcInfoDict£º  | 
| #  @return None  | 
| def SyncNPCInfo(curPlayer, mapID, playerCnt, npcInfoDict):  | 
|       | 
|     npcInfoPack = ChPyNetSendPack.tagMCNPCInfoList()  | 
|     npcInfoPack.Clear()  | 
|     npcInfoPack.MapID = mapID  | 
|     npcInfoPack.PlayerCnt = playerCnt  | 
|     npcInfoPack.NPCInfoList = []  | 
|   | 
|     for curID, npcInfo in npcInfoDict.items():  | 
|         curNPCID, curHP, maxHP, posX, posY, isAlive, refreshRemaindSecond = npcInfo  | 
|         npcInfo = ChPyNetSendPack.tagMCNPCInfo()  | 
|         npcInfo.Clear()  | 
|         npcInfo.ObjID = curID  | 
|         npcInfo.NPCID = curNPCID  | 
|         npcInfo.NPCHP = curHP  | 
|         npcInfo.MaxHP = maxHP  | 
|         npcInfo.PosX = posX  | 
|         npcInfo.PosY = posY  | 
|         npcInfo.IsActive = isAlive  | 
|         npcInfo.RefreshSecond = refreshRemaindSecond  | 
|         npcInfoPack.NPCInfoList.append(npcInfo)  | 
|           | 
|     npcInfoPack.NPCInfoCnt = len(npcInfoPack.NPCInfoList)  | 
|     NetPackCommon.SendFakePack(curPlayer, npcInfoPack)  | 
|     return  | 
|   | 
|   | 
| ## »ñÈ¡±¾µØÍ¼NPCÊýÁ¿  | 
| #  @param queryNPCIDList£º²éѯµÄNPCIDÁÐ±í  | 
| #  @param tick  | 
| #  @return {NPCID:cnt}  | 
| def GetNPCCntInfo(queryNPCIDList, tick, copyMapID=None):  | 
|     npcCntDict = {}  | 
|   | 
|     #if not queryNPCIDList:  | 
|     #    return npcCntDict  | 
|       | 
|     gameNPCManager = GameWorld.GetNPCManager()  | 
|     GameWorld.DebugLog("GetNPCCntInfo...queryNPCIDList=%s" % (str(queryNPCIDList)))  | 
|       | 
|     if isinstance(copyMapID, int):  | 
|         for index in xrange(gameNPCManager.GetNPCCountByGWIndex(copyMapID)):  | 
|             curNPC = gameNPCManager.GetNPCByIndexByGWIndex(copyMapID, index)  | 
|             curID = curNPC.GetID()  | 
|             if curID == 0:  | 
|                 continue  | 
|               | 
|             curNPCID = curNPC.GetNPCID()  | 
|               | 
|             if queryNPCIDList and curNPCID not in queryNPCIDList:  | 
|                 continue  | 
|             if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():  | 
|                 continue  | 
|             npcCntDict[curNPCID] = npcCntDict.get(curNPCID, 0) + 1  | 
|     else:  | 
|         for index in xrange(gameNPCManager.GetNPCCount()):  | 
|             curNPC = gameNPCManager.GetNPCByIndex(index)  | 
|             curID = curNPC.GetID()  | 
|             if curID == 0:  | 
|                 continue  | 
|               | 
|             curNPCID = curNPC.GetNPCID()  | 
|               | 
|             if queryNPCIDList and curNPCID not in queryNPCIDList:  | 
|                 continue  | 
|             if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():  | 
|                 continue  | 
|             npcCntDict[curNPCID] = npcCntDict.get(curNPCID, 0) + 1  | 
|                   | 
|     GameWorld.DebugLog("    npcCntDict=%s" % (str(npcCntDict)))  | 
|     return npcCntDict  | 
|   | 
| ## Í¬²½µØÍ¼NPCÊýÁ¿ÐÅÏ¢  | 
| #  @param curPlayer£º²É¼¯Íæ¼ÒʵÀý  | 
| #  @param mapID£º  | 
| #  @param npcInfoDict£º  | 
| #  @return None  | 
| def SyncNPCCntInfo(curPlayer, mapID, npcCntDict):  | 
|     npcInfoPack = ChPyNetSendPack.tagMCNPCCntList()  | 
|     npcInfoPack.Clear()  | 
|     npcInfoPack.MapID = mapID  | 
|     npcInfoPack.NPCInfoList = []  | 
|   | 
|     for npcid, npcCnt in npcCntDict.items():  | 
|         npcInfo = ChPyNetSendPack.tagMCNPCCntInfo()  | 
|         npcInfo.Clear()  | 
|         npcInfo.NPCID = npcid  | 
|         npcInfo.Cnt = npcCnt  | 
|         npcInfoPack.NPCInfoList.append(npcInfo)  | 
|           | 
|     npcInfoPack.NPCInfoCnt = len(npcInfoPack.NPCInfoList)  | 
|     NetPackCommon.SendFakePack(curPlayer, npcInfoPack)  | 
|     return  | 
|   | 
| def SendGameServerGoodItemRecord(curPlayer, mapID, lineID, npcID, itemID, equipInfo=[]):  | 
|     # @param equipInfo: [equipPlace, itemClassLV, itemColor, itemQuality, itemUserData]  | 
| #    GameWorld.DebugLog("¼ì²éÎïÆ·ÊÇ·ñ·¢ËÍGameServer: mapID=%s, npcID=%s, playerName=%s, itemID=%s"   | 
| #                       % (mapID, npcID, playerName, itemID))  | 
|     recBossIDList = IpyGameDataPY.GetFuncEvalCfg('DropRecordBossID', 1)  | 
|     if npcID not in recBossIDList:  | 
|         return  | 
|     recDropEquipInfoDict = IpyGameDataPY.GetFuncEvalCfg('DropRecordEquipment', 1, {})  | 
|     recSpecialItemIDList = IpyGameDataPY.GetFuncEvalCfg('DropRecordValue', 1)  | 
|     recItemIDList = IpyGameDataPY.GetFuncEvalCfg('DropRecordNormal', 1)  | 
|     # weightValue  Õäϧ¶È ÊýÖµÔ½´óÔ½Õä¹ó(ÓÃÓÚÅÅÐò)  | 
|     needRecord = False  | 
|     itemUserData = ""  | 
|     if itemID in recItemIDList:  | 
|         needRecord = True  | 
|         weightValue = recItemIDList.index(itemID)  | 
|     elif itemID in recSpecialItemIDList:  | 
|         needRecord = True  | 
|         weightValue = recSpecialItemIDList.index(itemID) + 10000  | 
|     else:  | 
|         equipPlace, itemClassLV, itemColor, itemQuality, itemUserData = equipInfo  | 
|         weightValue = itemColor*1000+itemQuality*100+itemClassLV  | 
|           | 
|         recordCondition = GameWorld.GetDictValueByKey(recDropEquipInfoDict, equipPlace)  | 
|         if recordCondition:  | 
|             needClassLV, needItemColor, needItemQuality = recordCondition  | 
|             if itemClassLV >= needClassLV and itemColor >= needItemColor and itemQuality >= needItemQuality:  | 
|                 needRecord = True  | 
|     if not needRecord:  | 
|         return  | 
|     playerID = curPlayer.GetID()  | 
|     playerName = curPlayer.GetName()  | 
|     serverGroupID = PlayerControl.GetPlayerServerGroupID(curPlayer)  | 
|     dropEquipMsg = str([playerID, playerName, mapID, lineID, npcID, itemID, itemUserData, weightValue, serverGroupID, curPlayer.GetLV()])  | 
|     GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'BossDropGoodItem', dropEquipMsg, len(dropEquipMsg))  | 
|     GameWorld.DebugLog("·¢ËÍGameServer¼Ç¼ʰȡµôÂäºÃÎïÆ·: %s" % dropEquipMsg, playerID)  | 
|     return  | 
|   | 
| #// A5 52 ¹ºÂò¹¦ÄÜNPC²É¼¯´ÎÊý #tagCMBuyCollectionCnt  | 
| #  | 
| #struct    tagCMBuyCollectionCnt  | 
| #{  | 
| #    tagHead        Head;  | 
| #    DWORD        FuncType;    //NPC¹¦ÄÜÀàÐÍ  | 
| #    BYTE        BuyCnt;    //¹ºÂò´ÎÊý  | 
| #};  | 
| ## ÁìÈ¡½±Àø  | 
| #  @param None None  | 
| #  @return None  | 
| def OnBuyCollectionCnt(index, clientData, tick):  | 
|     return  | 
|   | 
| #// A5 0A ¹ºÂò¿É»÷ɱboss´ÎÊý #tagCMBuyKillBossCnt  | 
| #  | 
| #struct    tagCMBuyKillBossCnt  | 
| #{  | 
| #    tagHead        Head;  | 
| #    WORD        KillBossMark;    // BOSSΨһË÷Òý  | 
| #};  | 
| ## ¹ºÂòBOSS¿É»÷ɱ´ÎÊý  | 
| def OnBuyKillBossCnt(index, clientData, tick):  | 
| #    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
| #    killBossMark = clientData.KillBossMark  | 
| #    killBossCntLimitDict = ReadChConfig.GetEvalChConfig("KillBossCntLimit")  | 
| #    curBossLimitInfo = []  | 
| #    for limitInfo in killBossCntLimitDict.values():  | 
| #        if killBossMark == limitInfo[0]:  | 
| #            curBossLimitInfo = limitInfo  | 
| #            break  | 
| #    if not curBossLimitInfo:  | 
| #        return  | 
| #      | 
| #    killBossMark, limitCnt, canBuyCnt, buyCost, sysMark1, sysMark2= curBossLimitInfo  | 
| #    hasKillCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Boss_KillCnt%killBossMark, 0)  | 
| #    hasBuyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Boss_KillCntBuyCnt%killBossMark, 0)  | 
| #    playerID = curPlayer.GetPlayerID()  | 
| #    if hasBuyCnt >= canBuyCnt:  | 
| #        GameWorld.Log('¹ºÂòBOSS¿É»÷ɱ´ÎÊý, ÒÑ´ïµ½½ñÈÕ×î´ó¿É¹ºÂò´ÎÊý£¬hasBuyCnt=%s, canBuyCnt=%s'%(hasBuyCnt, canBuyCnt), playerID)  | 
| #        return  | 
| #    costGold = eval(buyCost)  | 
| #    infoDict = {"index":index, ChConfig.Def_Cost_Reason_SonKey:index}  | 
| #    isOK = PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, costGold,   | 
| #                                  ChConfig.Def_Cost_BuyKillBossCnt, infoDict)  | 
| #      | 
| #    if not isOK:  | 
| #        return  | 
| #    # Ôö¼Ó¹ºÂò´ÎÊý  | 
| #    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Boss_KillCntBuyCnt%killBossMark, hasBuyCnt + 1)  | 
| #    BossHurtMng.NotifyAttackBossCnt(curPlayer)  | 
|     return  | 
|   | 
| #// A2 23 NPCÐã½áÊø #tagCMNPCShowEnd  | 
| #  | 
| #struct    tagCMNPCShowEnd  | 
| #{  | 
| #    tagHead        Head;  | 
| #    DWORD        NPCID;  | 
| #    BYTE        EndType; // 0-ĬÈÏ£»1-Ìø¹ý  | 
| #};  | 
| def OnNPCShowEnd(index, clientData, tick):  | 
|     npcID = clientData.NPCID  | 
|     endType = clientData.EndType  | 
|     endTick = GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Def_FBDict_NPCShowEndTick % npcID)  | 
|     if not endTick:  | 
|         return  | 
|     GameWorld.GetGameFB().SetGameFBDict(ChConfig.Def_FBDict_NPCShowEndTick % npcID, 0)  | 
|     GameWorld.DebugLog("ClientNPCShowEnd npcID=%s,endType=%s,tick=%s" % (npcID, endType, tick))  | 
|     return  | 
|   | 
| def IsMapNeedBossShunt(mapID):  | 
|     ## Ä¿±êµØÍ¼ÊÇ·ñÐèÒª´¦Àíboss·ÖÁ÷  | 
|     bossShuntMaxServerDay = IpyGameDataPY.GetFuncCfg("BossShunt", 3)  | 
|     openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1  | 
|     if openServerDay <= bossShuntMaxServerDay:  | 
|         bossShuntMapIDList = IpyGameDataPY.GetFuncEvalCfg("BossShunt", 1)  | 
|         return mapID in bossShuntMapIDList  | 
|     return False  | 
|   | 
| def AddBossShuntRelatedPlayer(curPlayer, mapID, lineID, npcID, tick):  | 
|     ## Ä¿±êµØÍ¼ÊÇ·ñÐèÒª´¦Àíboss·ÖÁ÷  | 
|     key = (mapID, lineID)  | 
|     shuntPlayerDict = PyGameData.g_bossShuntPlayerInfo.get(key, {})  | 
|     shuntPlayerDict[curPlayer.GetPlayerID()] = [npcID, curPlayer.GetTeamID(), tick]  | 
|     PyGameData.g_bossShuntPlayerInfo[key] = shuntPlayerDict  | 
|     GameServer_WorldBossShuntInfo(mapID, lineID)  | 
|     return  | 
|   | 
| def GameServer_WorldBossShuntInfo(mapID, lineID):  | 
|     key = (mapID, lineID)  | 
|     shuntPlayerDict = PyGameData.g_bossShuntPlayerInfo.get(key, {})  | 
|     msgStr = str([mapID, lineID, shuntPlayerDict])  | 
|     GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "WorldBossShuntInfo", msgStr, len(msgStr))  | 
|     GameWorld.DebugLog("֪ͨGameServerµØÍ¼Boss·ÖÁ÷ÐÅÏ¢: mapID=%s,lineID=%s,shuntPlayerDict=%s" % (mapID, lineID, shuntPlayerDict), lineID)  | 
|     return  | 
|   | 
| def NPCSpeedChangeNotify(curNPC, speed):  | 
|     ##֪ͨNPCËÙ¶È  | 
|     sendPack = ChNetSendPack.tagObjInfoRefresh()  | 
|     sendPack.Clear()  | 
|     sendPack.ObjID = curNPC.GetID()  | 
|     sendPack.ObjType = curNPC.GetGameObjType()  | 
|     sendPack.RefreshType = IPY_GameWorld.CDBPlayerRefresh_Speed  | 
|     sendPack.Value = speed  | 
|     curNPC.NotifyAll(sendPack.GetBuffer(), sendPack.GetLength())  | 
|     return  | 
|   | 
| def UpdateNPCAttackCount(curPlayer, npcID, attackCount, maxCount=0):  | 
|     ## ¸üÐÂÍæ¼Ò¹¥»÷NPC´ÎÊý  | 
|     if not npcID:  | 
|         return  | 
|     GameWorld.DebugLog("¸üÐÂÍæ¼Ò¹¥»÷NPC´ÎÊý: npcID=%s,attackCount=%s,maxCount=%s" % (npcID, attackCount, maxCount))  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_NPCAttackCount % npcID, attackCount)  | 
|       | 
|     if GameWorld.IsCrossServer():  | 
|         serverGroupID = PlayerControl.GetPlayerServerGroupID(curPlayer)  | 
|         msgInfo = {"PlayerID":curPlayer.GetPlayerID(), "NPCID":npcID, "AttackCount":attackCount, "MaxCount":maxCount}  | 
|         GameWorld.SendMsgToClientServer(ShareDefine.CrossServerMsg_NPCAttackCount, msgInfo, [serverGroupID])  | 
|     else:  | 
|         SyncNPCAttackCount(curPlayer, [npcID])  | 
|         if attackCount and attackCount >= maxCount:  | 
|             GameLogic_CrossGrassland.DoCheckUpdateGrasslandEnd(curPlayer)  | 
|     return  | 
|   | 
| def CrossServerMsg_NPCAttackCount(curPlayer, msgData):  | 
|     ## ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½µÄ¹¥»÷NPC´ÎÊý  | 
|     npcID = msgData["NPCID"]  | 
|     attackCount = msgData["AttackCount"]  | 
|     maxCount = msgData["MaxCount"]  | 
|     UpdateNPCAttackCount(curPlayer, npcID, attackCount, maxCount)  | 
|     return  | 
|   | 
| def SyncNPCAttackCount(curPlayer, npcIDList):  | 
|     ## Í¬²½NPC¹¥»÷´ÎÊý  | 
|     if not npcIDList:  | 
|         return  | 
|       | 
|     clientPack = ChPyNetSendPack.tagMCNPCAttackCountInfo()  | 
|     for npcID in npcIDList:  | 
|         attackCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCAttackCount % npcID)  | 
|         atkCountObj = ChPyNetSendPack.tagMCNPCAttackCount()  | 
|         atkCountObj.NPCID = npcID  | 
|         atkCountObj.AttackCount = attackCount  | 
|         clientPack.NPCAttackCountList.append(atkCountObj)  | 
|     clientPack.Count = len(clientPack.NPCAttackCountList)  | 
|     NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     return  | 
|   | 
|   | 
| def OnNPCAttacked(atkObj, curNPC, skill, tick):  | 
|     ## NPC±»¹¥»÷  | 
|     __OnAttackedDropItem(atkObj, curNPC)  | 
|     return  | 
|   | 
| ## Ã¿´Î±»¹¥»÷µôÂäÎïÆ·  | 
| #  @param atkObj ¹¥»÷·¢ÆðÕß  | 
| #  @param curNPC ±»¹¥»÷NPC  | 
| #  @return None  | 
| def __OnAttackedDropItem(atkObj, curNPC):  | 
|     attackPlayer, npcObjType = AttackCommon.GetAttackPlayer(atkObj)  | 
|     if npcObjType:  | 
|         return  | 
|     if not attackPlayer:  | 
|         return  | 
|     npcID = curNPC.GetNPCID()  | 
|     ipyData = IpyGameDataPY.GetIpyGameDataNotLog("TreasureNPC", npcID)  | 
|     if not ipyData:  | 
|         return  | 
|     attackCountDropWeightInfo = ipyData.GetAttackCountDropWeightInfo()  | 
|     attackDropWeightList = ipyData.GetAttackDropWeightList()  | 
|     attackDropWeightListEx = ipyData.GetAttackDropWeightListEx()  | 
|     dropCountEx = ipyData.GetDropCountEx()  | 
|     alchemyDiffLV = ipyData.GetAlchemyDiffLV()  | 
|       | 
|     mainItemWeightList = []  | 
|     if attackCountDropWeightInfo:  | 
|         maxCount = max(attackCountDropWeightInfo)  | 
|         attackCount = attackPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCAttackCount % npcID) + 1  | 
|         if attackCount <= maxCount:  | 
|             if attackCount in attackCountDropWeightInfo:  | 
|                 mainItemWeightList = attackCountDropWeightInfo[attackCount]  | 
|             UpdateNPCAttackCount(attackPlayer, npcID, attackCount, maxCount)  | 
|               | 
|     if mainItemWeightList:  | 
|         mainItemWeightList = ItemCommon.GetWeightItemListByAlchemyDiffLV(attackPlayer, mainItemWeightList, alchemyDiffLV)  | 
|     elif attackDropWeightList:  | 
|         mainItemWeightList = ItemCommon.GetWeightItemListByAlchemyDiffLV(attackPlayer, attackDropWeightList, alchemyDiffLV)  | 
|           | 
|     mainItemInfo = GameWorld.GetResultByWeightList(mainItemWeightList)  | 
|       | 
|     if not mainItemInfo:  | 
|         notDropNotify = ipyData.GetNotDropNotify()  | 
|         if notDropNotify:  | 
|             PlayerControl.NotifyCode(attackPlayer, notDropNotify)  | 
|         return  | 
|       | 
|     dropItemList = []  | 
|     if mainItemInfo:  | 
|         dropItemList.append(mainItemInfo)  | 
|           | 
|     if attackDropWeightListEx and dropCountEx:  | 
|         weightListEx = ItemCommon.GetWeightItemListByAlchemyDiffLV(attackPlayer, attackDropWeightListEx, alchemyDiffLV)  | 
|         for _ in xrange(dropCountEx):  | 
|             itemInfo = GameWorld.GetResultByWeightList(weightListEx)  | 
|             if itemInfo:  | 
|                 dropItemList.append(itemInfo)  | 
|                   | 
|     if not dropItemList:  | 
|         return  | 
|       | 
|     mapID = PlayerControl.GetCustomMapID(attackPlayer)  | 
|     if mapID:  | 
|         DoGiveItemByVirtualDrop(attackPlayer, dropItemList, npcID)  | 
|         GameLogic_CrossGrassland.RecordGrasslandAward(attackPlayer, dropItemList)  | 
|     else:  | 
|         dropPosX, dropPosY = curNPC.GetPosX(), curNPC.GetPosY()  | 
|         ChItem.DoMapDropItem(attackPlayer, dropItemList, npcID, dropPosX, dropPosY, isOnlySelfSee=False)  | 
|     return  | 
|   | 
|                  |