| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #---------------------------------------------------------------------  | 
| #  | 
| #---------------------------------------------------------------------  | 
| ##@package ChNPC  | 
| # @todo: NPCÂß¼´¦Àí  | 
| #  | 
| # @author: eggxp  | 
| # @date 22010-4-28  | 
| # @version 2.5  | 
| #  | 
| # @note:   | 
| #---------------------------------------------------------------------  | 
| # @change: "2013-04-18 17:00" wdb ÎïÆ·ÑÕɫʹÓÃÐÞ¸Ä  | 
| # @change: "2013-04-23 16:00" wdb ×°±¸µôÂä  | 
| # @change: "2013-04-25 16:30" wdb ÎïÆ·µôÂäÇø¼ä±í¿ªÅäÖà  | 
| # @change: "2013-06-04 23:00" Alee È¡ÏûÏîÁ´µôÂäÌØÊâÂß¼  | 
| # @change: "2013-06-18 22:30" Alee ÑÓ³¤ÆÕͨ¹ÖµÄAI¼ä¸ô  | 
| # @change: "2013-06-26 14:00" Alee È¡ÏûAIµÄCDÏÞÖÆÓë´ôÖͳåÍ»  | 
| # @change: "2013-11-08 18:00" hxp Ôö¼ÓNPC±»¹¥»÷ʱ´¦Àí  | 
| # @change: "2013-11-27 11:50" hxp É¾³ýProcessAIÖÐTickÅÐ¶Ï  | 
| # @change: "2014-10-11 14:30" hxp Ôö¼Ó¹¥»÷NPC´¥·¢»î¶¯¶È  | 
| # @change: "2015-08-03 11:30" hxp NPCµôÂä³õʼ»¯ÐÞ¸Ä  | 
| # @change: "2016-08-11 19:30" hxp NPCµôÂä×°±¸Ö§³Ö°´×°±¸ÀàÐÍɸѡ  | 
| # @change: "2016-09-28 21:00" hxp ¼«ÏÞ²»ËÀbossÂß¼Ö§³Ö  | 
| # @change: "2016-11-26 19:00" hxp Ôö¼ÓNPCÓëÖ÷È˵ĹØÏµÅÐ¶Ï  | 
| # @change: "2017-03-22 21:00" hxp ¶þάÂëºì°ü¹ÖÎïµØÍ¼Æô¶¯Ë¢Ð  | 
| #------------------------------------------------------------------------------------------------------------   | 
| #"""Version = 2017-03-22 21:00"""  | 
| #---------------------------------------------------------------------  | 
| import IPY_GameWorld  | 
| import GameWorld  | 
| import NPCAI  | 
| import ChConfig  | 
| import NPCCommon  | 
| import NPCCustomRefresh  | 
| import GameLogInfo  | 
| import time  | 
| import math  | 
| import ReadChConfig  | 
| import PlayerActivity  | 
| import SkillCommon  | 
| import BuffSkill  | 
| import GameObj  | 
| import SkillShell  | 
| import FBLogic  | 
| import PassiveBuffEffMng  | 
| import IpyGameDataPY  | 
| #---------------------------------------------------------------------  | 
| #µ¼ÈëËùÓеÄNPCAI  | 
| GameWorld.ImportAll("Script\\NPC\\" , "NPCAI")  | 
| GameWorld.ImportAll("Script\\NPC\\" , "")  | 
| #---------------------------------------------------------------------  | 
| ## ÖØÐ¶ÁÈ¡ËùÓÐNPCÊý¾Ý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def ReloadNPC(tick):  | 
|     scriptPath = ChConfig.GetAppPath() + "Script\\NPC\\NPCAI"  | 
|     GameWorld.ReloadScript(scriptPath, "NPCAI")  | 
|       | 
|     scriptPath = ChConfig.GetAppPath() + "Script\\NPC"  | 
|     GameWorld.ReloadScript(scriptPath, "")  | 
|       | 
|     #µ÷ÓÃNPC AI»÷ɱ´¥·¢  | 
|     NPCCommon.OnNPCDie = OnNPCDie  | 
|     return  | 
| #---------------------------------------------------------------------  | 
| ## »ñÈ¡NPCÓëÖ÷È˵ĹØÏµ  | 
| def OnGetOwnerRelation(curNPC, owner):  | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%d.%s"%(curNPC.GetAIType(), "OnGetOwnerRelation"))  | 
|     if callFunc == None:  | 
|         return ChConfig.Type_Relation_Friend , ChConfig.Def_PASysMessage_None  | 
|       | 
|     return callFunc(curNPC, owner)  | 
|   | 
| ## »ñÈ¡NPCÊÇ·ñÏÞÖÆ¹¥»÷Ä¿±ê£¬AIÌØÊâ¶îÍâÅÐ¶Ï  | 
| def GetNPCAttackTagLimit(curNPC, tagObj):  | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%d.%s"%(curNPC.GetAIType(), "GetNPCAttackTagLimit"))  | 
|     if callFunc == None:  | 
|         return  | 
|     return callFunc(curNPC, tagObj)  | 
|   | 
| ## ¸ù¾ÝAIɱ¹Ö¼ÆÊý  | 
| #  @param curNPC µ±Ç°NPC  | 
| #  @param HurtType   | 
| #  @param HurtID  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def OnNPCDie(curNPC,HurtType,HurtID):  | 
|       | 
|     # ÕÙ»½NPCËÀÍö´¥·¢±»¶¯¼¼ÄÜ  | 
|     owner = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer, curNPC)  | 
|     if owner:  | 
|         owner.SetDict("summondie", curNPC.GetNPCID())  | 
|         PassiveBuffEffMng.OnPassiveSkillTrigger(owner, None, None, ChConfig.TriggerType_SummonDie,  | 
|                                                 GameWorld.GetGameWorld().GetTick())  | 
|           | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%d.%s"%(curNPC.GetAIType(), "OnDie"))  | 
|     if callFunc == None:  | 
|         return None  | 
|       | 
|     callFunc(curNPC,HurtType,HurtID)  | 
|     return  | 
|   | 
| def OnNPCSetDead(curNPC):  | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%d.%s"%(curNPC.GetAIType(), "OnNPCSetDead"))  | 
|     if callFunc == None:  | 
|         return None  | 
|     callFunc(curNPC)  | 
|     return  | 
|   | 
| def OnNPCReborn(curNPC):  | 
|     FBLogic.OnNPCRebornInFB(curNPC)  | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%d.%s"%(curNPC.GetAIType(), "OnNPCReborn"))  | 
|     if callFunc == None:  | 
|         return None  | 
|     callFunc(curNPC)  | 
|     return  | 
|   | 
| ## ¸ù¾ÝAI´¦Àí±»¹¥»÷  | 
| #  @param curNPC µ±Ç°NPC  | 
| #  @param HurtType   | 
| #  @param HurtID  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def OnNPCAttacked(atkObj, curNPC, skill, tick):  | 
|     NPCCommon.OnNPCAttacked(atkObj, curNPC, skill, tick)  | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%d.%s"%(curNPC.GetAIType(), "OnAttacked"))  | 
|     if callFunc == None:  | 
|         return None  | 
|       | 
|     callFunc(atkObj, curNPC, skill, tick)  | 
|       | 
|     PlayerActivity.OnAttackNPCActivity(atkObj, curNPC)  | 
|     return  | 
|   | 
| def OnCheckCanDie(atkObj, curNPC, skill, tick):  | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%d.%s"%(curNPC.GetAIType(), "OnCheckCanDie"))  | 
|     if callFunc == None:  | 
|         return True  | 
|     return callFunc(atkObj, curNPC, skill, tick)  | 
|   | 
| #---------------------------------------------------------------------  | 
| ## ³õʼ»¯NPC   | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def InitNPC(tick):  | 
|     GameWorld.GetPsycoFunc(__Func_InitNPC)(tick)  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ## ³õʼ»¯NPC   | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __Func_InitNPC(tick):  | 
|     #µ÷ÓÃNPC AI»÷ɱ´¥·¢  | 
|     NPCCommon.OnNPCDie = OnNPCDie  | 
|     gameWorldIndex = GameWorld.GetGameWorld().GetCurGameWorldIndex()  | 
|     GameWorld.Log("NPC Initing...FB %d" % gameWorldIndex)  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     hideNPCIDList = [] # ÐèÒªÒþ²ØµÄNPCIDÁÐ±í  | 
|     # ÓÉÓÚijЩ³£¹æÏßbossÇøÓòÒªÖØ¸´ÀûÓã¬ËùÒԻÏß¶ÀÁ¢£¬²»¿ª·Å¸øÍæ¼Ò£¬½öÌØ¶¨»î¶¯Ê±ÏµÍ³´«Èë  | 
|     activityMapLineDict = IpyGameDataPY.GetFuncEvalCfg("MapLine", 2, {})  | 
|     if mapID in activityMapLineDict:  | 
|         activityLineID = max(0, activityMapLineDict[mapID] - 1)  | 
|         if gameWorldIndex == activityLineID:  | 
|             hideNPCIDList = IpyGameDataPY.GetFuncEvalCfg("MapLine", 3)  | 
|             GameWorld.Log("    hideNPCIDList=%s" % hideNPCIDList)  | 
|               | 
|     gameNPC = GameWorld.GetNPCManager()  | 
|     npcCount = gameNPC.GetNPCCount()  | 
|     for i in xrange(npcCount):  | 
|         curNPC = gameNPC.GetNPCByIndex(i)  | 
|         if curNPC.GetNPCID() in hideNPCIDList:  | 
|             curNPC.SetVisible(False)  | 
|             continue  | 
|         #³õʼ»¯  | 
|         NPCCommon.InitNPC(curNPC)   | 
|           | 
|         #Åж¨NPCˢйæÔò, Ñ²Âßµã Óë Ë¢Ðµã(ѲÂßµã>1,ˢеã>0½«µ¼ÖÂNPCÂÒ×ßÂÒÅÜ)  | 
|         if curNPC.GetRefreshPosCount() > 1 and curNPC.GetPatrolPosCount() > 0:  | 
|             GameWorld.Log( '###NPC²ß»®Ìî±í´íÎó£¬NPC = %s , %s , Ë¢Ðµã = %sºÍÖØÉúµã = %s´íÎó'%( curNPC.GetNPCID() , curNPC.GetName() , curNPC.GetRefreshPosCount() , curNPC.GetPatrolPosCount() ) )  | 
|             raise Exception(' ###NPC ²ß»®Ìî´í±íÀ ')  | 
|           | 
|     GameWorld.Log("NPC Init OK!")  | 
|     return  | 
|   | 
| ## Ö´ÐÐÆÕͨNPCAI  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def NormalNPCAI(tick):  | 
|   | 
|     GameWorld.GetPsycoFunc(__Func_NormalNPCAI)(tick)  | 
|     return  | 
|   | 
|   | 
| ## Ö´ÐÐÆÕͨNPCAI  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __Func_NormalNPCAI(tick):  | 
|     #½«Éæ¼°µ½C++ÖÐÁбíɾ³ýµÄ¹¦ÄÜ,ͳһ¸Ä³É -> ¸´ÖÆPyÁбíºó,È»ºó½øÐÐɾ³ýÂß¼ (ÒòWhileÓм¸Âʽ«µ¼ÖÂËÀËø)  | 
|     gameNPC = GameWorld.GetNPCManager()  | 
|     normal_NPC_List = []  | 
|   | 
|     for index in range(0, gameNPC.GetActiveNPCCount()):  | 
|         curNPC = gameNPC.GetActiveNPCByIndex(index)  | 
|   | 
|         if curNPC.GetID() == 0:  | 
|             continue  | 
|           | 
|         if curNPC.GetGameNPCObjType() == IPY_GameWorld.gnotSummon:  | 
|             #È¡µÃÒ»´ÎÕÙ»½ÊÞÊý¾Ý  | 
|             #ÓÉ2009.8.17¸Ä¶¯Òý·¢µÄ  | 
|             curNPC = GameWorld.GetObjDetail(curNPC)  | 
|               | 
|             if curNPC == None:  | 
|                 continue  | 
|               | 
|             #2018.10.9Ð޸ģºÔö¼ÓbossÌõ¼þ¹ýÂË£¬ÓñêÊÔµãË¢³öÀ´µÄbossÒ²ÊÇÕÙ»½ÊÞ£¬·ÅÔÚbossAIÖд¦Àí£¬´Ë´¦²»´¦Àí  | 
|             if ChConfig.IsGameBoss(curNPC):  | 
|                 continue  | 
|               | 
|         normal_NPC_List.append(curNPC)  | 
|       | 
|     for curNPC in normal_NPC_List:  | 
|         ProcessNPCAI(curNPC, tick)  | 
|       | 
|     return  | 
|   | 
|   | 
| #===============================================================================  | 
| #    ÕÙ»½ÊÞAI  | 
| #    ±éÀúÕÙ»½NPCµÄ·½·¨  | 
| #    ÒòΪÕÙ»½NPCÔÚProcessAIµÄʱºò, Èç¹ûʱ¼äµ½ÁË, »á×Ô¼ºÉ¾³ý×Ô¼º  | 
| #    µ¼ÖÂSummonNPCµÄCount²»¶ÔÓ¦, µ¼ÖÂÈ¡³öµÄÔªËØÎªNone  | 
| #    gameNPC.SummonRecordFirst()  | 
| #    2008.11.21  | 
| #    ¸Ä¶¯, ²»ÄÜÓÃSummonRecordFirst->SummonRecordIsEndµÄ·½Ê½  | 
| #    ÒòΪÕÙ»½ÊÞɱËÀ¶Ô·½ÕÙ»½ÊÞµÄʱºò, »á²úÉúɾ³ýÕÙ»½ÊÞµÄÂß¼, µ¼ÖÂm_SummonRecordNum--  | 
| #    ËùÒÔ¸ÄΪ´«Í³·½Ê½  | 
| #    2009.1.13,pythonËÀÑ»·µ¼Ö³þÍõ³ÇÍæ¼Ò»Øµµ  | 
| #===============================================================================  | 
| ## Ö´ÐÐBossÕÙ»½ÊÞAI(²ÎÊý-> µ±Ç°Ê±¼ä)  | 
| #  @param tick  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def BossSummonNPCAI(tick):  | 
|     GameWorld.GetPsycoFunc(__Func_BossSummonNPCAI)(tick)  | 
|     return  | 
|   | 
| ## Ö´ÐÐBossÕÙ»½ÊÞAI(²ÎÊý-> µ±Ç°Ê±¼ä)  | 
| #  @param tick  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __Func_BossSummonNPCAI(tick):  | 
|     #½«Éæ¼°µ½C++ÖÐÁбíɾ³ýµÄ¹¦ÄÜ,ͳһ¸Ä³É -> ¸´ÖÆPyÁбíºó,È»ºó½øÐÐɾ³ýÂß¼ (ÒòWhileÓм¸Âʽ«µ¼ÖÂËÀËø)  | 
|     gameNPC = GameWorld.GetNPCManager()  | 
|           | 
|     #---´¦ÀíÕÙ»½Á飨È籩·çÑ©£©µÄAI---  | 
|     gameElf_List = []  | 
|       | 
|     for index in range(0, gameNPC.GetSummonNPCCount()):  | 
|         curNPC = gameNPC.GetSummonNPCAt(index)  | 
|   | 
|         if curNPC.GetID() == 0:  | 
|             continue  | 
|   | 
|         if curNPC.GetType() != IPY_GameWorld.ntElf:  | 
|             continue  | 
|           | 
|         if curNPC.GetOwner() == None:  | 
|             #2009.8.17ÐÞ¸Ä  | 
|             #Èç¹ûÒ»¸öÕÙ»½ÊÞµÄÖ÷ÈËΪNone, »®¹éΪÆÕͨNPC, ÎªÁ˼õÉÙ¸±±¾ÖеÄCPUʹÓÃÂÊ  | 
|             continue  | 
|           | 
|         if not curNPC.IsAlive():  | 
|             #Òì³£,ÕÙ»½ÊÞËÀÍöδÇå¿Õ  | 
|             #GameWorld.Log('###ÕÙ»½ÊÞËÀÍöδÇå¿Õ , %s'%(curNPC.GetName()))  | 
|             continue  | 
|           | 
|           | 
|         gameElf_List.append(curNPC)  | 
|   | 
|     for curNPC in gameElf_List:  | 
|         #´¦ÀíÕÙ»½ÊÞAI             | 
|         ProcessNPCAI(curNPC, tick)  | 
|       | 
|     #--------ÈËÎïÕÙ»½ÁéÈ籩·çÑ©ÐèÒª¿ìËÙ´¦Àí£¬Íâ²ãµ÷ÓøÄ200ºÁÃëÒ»´Î£¬ÆäËûAIÔò¿ØÖÆÔÚ1Ãë------------------  | 
|       | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     #δµ½Ë¢Ð¼ä¸ô  | 
|     if tick - gameWorld.GetTickByType(ChConfig.TYPE_Map_Tick_BossAITick) < \  | 
|                 ChConfig.TYPE_Map_Tick_Time[ChConfig.TYPE_Map_Tick_BossAITick]:  | 
|         return  | 
|       | 
|     gameWorld.SetTickByType(ChConfig.TYPE_Map_Tick_BossAITick, tick)  | 
|   | 
|     #---´¦ÀíÕÙ»½ÊÞµÄAI---  | 
|     gameSummon_List = []  | 
|       | 
|     for index in range(0, gameNPC.GetSummonNPCCount()):  | 
|         curNPC = gameNPC.GetSummonNPCAt(index)  | 
|   | 
|         if curNPC.GetID() == 0:  | 
|             continue  | 
|           | 
|         if curNPC.GetType() == IPY_GameWorld.ntElf:  | 
|             continue  | 
|           | 
|         if curNPC.GetOwner() == None and not ChConfig.IsGameBoss(curNPC):  | 
|             #2009.8.17ÐÞ¸Ä  | 
|             #Èç¹ûÒ»¸öÕÙ»½ÊÞµÄÖ÷ÈËΪNone, »®¹éΪÆÕͨNPC, ÎªÁ˼õÉÙ¸±±¾ÖеÄCPUʹÓÃÂÊ  | 
|             #2018.10.9Ð޸ģºÔö¼ÓbossÌõ¼þ¹ýÂË£¬ÓñêÊÔµãË¢³öÀ´µÄbossÒ²ÊÇÕÙ»½ÊÞ£¬Ò²ÐèÒª´¦Àí  | 
|             continue  | 
|           | 
|         if not curNPC.IsAlive():  | 
|             #Òì³£,ÕÙ»½ÊÞËÀÍöδÇå¿Õ  | 
|             #GameWorld.Log('###ÕÙ»½ÊÞËÀÍöδÇå¿Õ , %s'%(curNPC.GetName()))  | 
|             continue  | 
|   | 
|         gameSummon_List.append(curNPC)  | 
|   | 
|     for curNPC in gameSummon_List:  | 
|         #´¦ÀíÕÙ»½ÊÞAI             | 
|         ProcessNPCAI(curNPC, tick)  | 
|   | 
|   | 
|     #---´¦ÀíBossµÄAI---  | 
|     gameBoss_List = []  | 
|       | 
|     for index in range(0, gameNPC.GetBossCount()):  | 
|         curNPC = gameNPC.GetBossAt(index)  | 
|           | 
|         if curNPC.GetID() == 0:  | 
|             continue  | 
|           | 
|         gameBoss_List.append(curNPC)  | 
|       | 
|     for curNPC in gameBoss_List:  | 
|         ProcessNPCAI(curNPC, tick)  | 
|   | 
|     #---æô³µAI---  | 
|     gameTruck_List = []  | 
|     for index in range(gameNPC.GetTruckCount()):  | 
|         curNPC = gameNPC.GetTruckAt(index)  | 
|         #ïÚ³µ²»¿ÉÄÜËÀÍöµÄ  | 
|         if not curNPC.IsAlive():  | 
|             GameWorld.Log('###ïÚ³µËÀÍö , %s'%(curNPC.GetName()))  | 
|             continue  | 
|    | 
|         gameTruck_List.append(curNPC)  | 
|       | 
|     for curNPC in gameTruck_List:  | 
|         ProcessNPCAI(curNPC, tick)  | 
|       | 
|     # ³èÎïAI  | 
|     ProcessPetAI(gameWorld, gameNPC, tick)  | 
|       | 
| # ³èÎïAIÐèÇó¼õÈõÌØÊâ´¦Àí£¬ ¼õÉÙÐÔÄÜÏûºÄ  | 
| def ProcessPetAI(gameWorld, gameNPC, tick):  | 
|     #---´¦Àí³èÎïµÄAI---  | 
|     #δµ½Ë¢Ð¼ä¸ô  | 
|     if tick - gameWorld.GetTickByType(ChConfig.TYPE_Map_Tick_PetAITick) < \  | 
|                 ChConfig.TYPE_Map_Tick_Time[ChConfig.TYPE_Map_Tick_PetAITick]:  | 
|         return  | 
|       | 
|     gameWorld.SetTickByType(ChConfig.TYPE_Map_Tick_PetAITick, tick)  | 
|       | 
|     gamePet_List = []  | 
|       | 
|     for index in range(0, gameNPC.GetPetCount()):  | 
|         curPet = gameNPC.GetPetAt(index)  | 
|           | 
|         if curPet.GetID() == 0:  | 
|             continue  | 
|           | 
|         #δ³öÕ½²»´¦Àí  | 
|         if not curPet.GetIsSummon():  | 
|             continue  | 
|           | 
|         if not curPet.IsAlive():  | 
|             #Òì³£,³èÎïËÀÍöδÇå¿Õ  | 
|             #GameWorld.Log('###³èÎïËÀÍöδÇå¿Õ , %s'%(curNPC.GetName()))  | 
|             continue  | 
|           | 
|         gamePet_List.append(curPet)  | 
|   | 
|     for curPet in gamePet_List:  | 
|         #´¦Àí³èÎïAI             | 
|         ProcessNPCAI(curPet, tick)  | 
|           | 
|     return  | 
|   | 
| ## NPCˢе㴦ÀíÂß¼  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def NPCRefreshPoint(tick):  | 
|     GameWorld.GetPsycoFunc(__Func_NPCRefreshPoint)(tick)  | 
|     return  | 
|   | 
| ## NPCˢе㴦ÀíÂß¼  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __Func_NPCRefreshPoint(tick):  | 
|     #NPCˢе㴦ÀíÂß¼  | 
|     NPCCustomRefresh.ProcessAllNPCRefresh(tick)  | 
|     return  | 
|   | 
|   | 
| ## µ÷ÓÃNPCAI   | 
| #  @param curNPC µ±Ç°NPC  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def ProcessNPCAI(curNPC, tick):  | 
|     #GameWorld.Log(curNPC.GetName())  | 
|       | 
| #    npcObjType = curNPC.GetGameNPCObjType()  | 
| #    #ÆÕͨnpc¹¥»÷ºó1Ãë ²»´¦ÀíAI  | 
| #    if npcObjType == IPY_GameWorld.gnotNormal:  | 
| #        if tick - curNPC.GetAttackTick() < ChConfig.TYPE_NPC_Tick_ProcessAI:  | 
| #            #¹¥»÷¼ä¸ôûÓе½, ·µ»Ø  | 
| #            return  | 
|     npcID = curNPC.GetNPCID()  | 
|     endTick = GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Def_FBDict_NPCShowEndTick % npcID)  | 
|     if endTick:  | 
|         if tick < endTick:  | 
|             #GameWorld.DebugLog("NPCÐãÖУ¬²»´¦ÀíAI!npcID=%s,tick=%s,endTick=%s" % (npcID, tick, endTick))  | 
|             return  | 
|         GameWorld.GetGameFB().SetGameFBDict(ChConfig.Def_FBDict_NPCShowEndTick % npcID, 0)  | 
|         GameWorld.DebugLog("NPCÐã½áÊø£¬¿ªÊ¼´¦ÀíAI!npcID=%s,tick=%s,endTick=%s" % (npcID, tick, endTick))  | 
|           | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%s.%s"%(GetAIName(curNPC), "ProcessAI"))  | 
|     if callFunc == None:  | 
|         #NPCAI²»¿ÉʹÓà  | 
| #        #ĬÈÏcallÀàÐÍ1µÄAI  | 
| #        callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_1.ProcessAI")  | 
| #        if callFunc != None:  | 
| #            callFunc(curNPC, tick)  | 
|         return  | 
|       | 
|     callFunc(curNPC, tick)  | 
|     return  | 
|   | 
| def GetAIName(curNPC):  | 
|     if curNPC.GetType() in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]:  | 
|         return "PriWood"  | 
|     return curNPC.GetAIType()  | 
|   | 
| ##################################################logic  | 
|   | 
| #---------------------------------------------------------------------  | 
| ## ²É¼¯³É¹¦  | 
| #  @param curPlayer µ±Ç°Íæ¼Ò  | 
| #  @param curNPC µ±Ç°npc  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def OnCollectEnd(curPlayer, curNPC):  | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%d.%s"%(curNPC.GetAIType(), "OnCollectEnd"))  | 
|       | 
|     if callFunc:  | 
|         return callFunc(curPlayer, curNPC)  | 
| #    GameWorld.Log('¹¦ÄÜ»òAI²»´æÔÚ£º %s'%curNPC.GetAIType())  | 
|   | 
|     return  | 
|       | 
| #===============================================================================  | 
| # def OnUndeathBossHurt(curNPC, hurtHP):  | 
| #    npcID = curNPC.GetNPCID()  | 
| #    UndeathBossDict = ReadChConfig.GetEvalChConfig("UndeathBoss")  | 
| #    if npcID not in UndeathBossDict:  | 
| #        return False  | 
| #    unitLostHP = UndeathBossDict[npcID] # µþ¼ÓÒ»²ãbuffËùÐèµôѪÁ¿  | 
| #      | 
| #    curLayerLostHP = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_Undeath_LayerLostHP)  | 
| #    updLostHP = curLayerLostHP + hurtHP  | 
| #    addLayer = updLostHP / unitLostHP # Ôö¼Óbuff²ãÊý, ¹¥»÷¸ßµÄ¿ÉÄÜÒ»´ÎÐÔ¼Ó¶à²ã  | 
| #    #GameWorld.DebugLog("²»ËÀbossµôѪ: curLayerLostHP=%s,hurtHP=%s,updLostHP=%s,unitLostHP=%s,addLayer=%s"   | 
| #    #                   % (curLayerLostHP, hurtHP, updLostHP, unitLostHP, addLayer), npcID)  | 
| #    if addLayer > 0:  | 
| #        curBuffLayer = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_Undeath_BuffLayer)  | 
| #        updBuffLyaer = curBuffLayer + addLayer  | 
| #        curNPC.SetDict(ChConfig.Def_NPC_Dict_Undeath_BuffLayer, updBuffLyaer)  | 
| #        updLostHP = updLostHP % unitLostHP # ¸üвãÀÛ¼ÓºóÊ£ÓàµÄÉ˺¦Öµ  | 
| #        #GameWorld.DebugLog("    Ôö¼ÓNPC×Öµäbuff²ã: curBuffLayer=%s,updBuffLyaer=%s,updLostHP=%s"   | 
| #        #                   % (curBuffLayer, updBuffLyaer, updLostHP), npcID)  | 
| #        __UpdBossLayerBuff(curNPC, updBuffLyaer)  | 
| #          | 
| #    curNPC.SetDict(ChConfig.Def_NPC_Dict_Undeath_LayerLostHP, updLostHP)  | 
| #    return True  | 
| #   | 
| # def __UpdBossLayerBuff(curNPC, updBuffLyaer):  | 
| #    ''' ¸üÐÂboss²ãbuff²ã¼¶ '''  | 
| #    buffType = IPY_GameWorld.bfBuff  | 
| #    buffTuple = SkillCommon.GetBuffManagerByBuffType(curNPC, buffType)  | 
| #    if buffTuple == ():  | 
| #        return  | 
| #      | 
| #    tick = GameWorld.GetGameWorld().GetTick()  | 
| #    buffState = buffTuple[0]  | 
| #    for i in range(0,buffState.GetBuffCount()):  | 
| #        curBuff = buffState.GetBuff(i)  | 
| #        curSkill = curBuff.GetSkill()  | 
| #        skillID = curSkill.GetSkillID()  | 
| #        if not skillID:  | 
| #            continue  | 
| #          | 
| #        for j in range(0, curSkill.GetEffectCount()):  | 
| #            curEffect = curSkill.GetEffect(j)  | 
| #            effectID = curEffect.GetEffectID()  | 
| #            # ²ã¼¶buffЧ¹û  | 
| #            if effectID in ChConfig.Def_BuffLayerEffectList:  | 
| #                BuffSkill.AddBuffNoRefreshState(curNPC, buffType, curSkill, tick, updBuffLyaer, curNPC)  | 
| #                #GameWorld.DebugLog("    ¸üв㼶buffЧ¹û²ãÊý: isOK=%s,skillID=%s,effID=%s,updBuffLyaer=%s"   | 
| #                #                   % (isOK, skillID, effectID, updBuffLyaer), curNPC.GetNPCID())  | 
| #                break  | 
| #              | 
| #    NPCCommon.NPCControl(curNPC).RefreshNPCAttrState()  | 
| #    return  | 
| #===============================================================================  | 
|   | 
| def OnUndeathBossAttacked(curNPC):  | 
|     npcID = curNPC.GetNPCID()  | 
|     if curNPC.GetType() != ChConfig.ntUndeath:  | 
|         return False  | 
|   | 
|     if GameObj.GetHP(curNPC) > GameObj.GetMaxHP(curNPC)/2:  | 
|         return True  | 
|       | 
|     GameObj.SetHP(curNPC, GameObj.GetMaxHP(curNPC))  | 
|     GameWorld.DebugLog("²»ËÀbossѪÁ¿Îª0ÉèÖÃÂúѪ! npcID=%s" % npcID, npcID)  | 
|     return True  | 
|   | 
|   | 
| #NPCµ±Ç°×´Ì¬ÎªlaNPCSkillWarning£¬³öÏÖʱµ÷Óà  | 
| def NPCAppearWarn(tick, objID):  | 
|     GameWorld.DebugLog("----NPCAppearWarn:%s %s"%(tick, objID))  | 
|     curNPC = GameWorld.GetNPCManager().FindNPCByID(objID)  | 
|     SkillShell.NotifyNPCSkillWarn(curNPC, tick)  | 
|     callFunc = GameWorld.GetExecFunc(NPCAI, "AIType_%d.%s"%(curNPC.GetAIType(), "NPCAppearWarn"))  | 
|     if callFunc == None:  | 
|         return None  | 
|       | 
|     callFunc(curNPC, tick)  | 
|     return  |