| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #  | 
| ##@package AICommon  | 
| #NPC AI¹ÜÀíÆ÷  | 
| #  | 
| # @author panwei  | 
| # @date 2010-4-23  | 
| # @version 1.7  | 
| #  | 
| # @change: "2013-03-11 18:00" wdb È¥³ý¶ÔÖÅ  | 
| # @change: "2013-06-18 22:30" Alee Ð¡¹Ö²»»ØÑª  | 
| # @change: "2013-12-17 14:50" hxp »Ö¸´Ð¡¹Ö»ØÑª  | 
| # @change: "2013-12-20 15:35" Alee ÆÕͨ¹Ö·Ç¹¥»÷ÒÆ¶¯·À·¶  | 
| # @change: "2014-04-18 20:15" Alee ²É¼¯È¡ÏûÆäËû¶ÔÏóÌí¼Ó·À¿Õ  | 
| # @change: "2014-09-10 11:30" hxp Ôö¼ÓÕÙ»½Ê޿ɶÔÖ÷ÈËÊͷż¼ÄÜ  | 
| # @change: "2016-05-25 13:30" hxp NPCÊͷż¼ÄÜÑ¡ÔñÓÅ»¯£¬¸ù¾Ý×ÜÊÍ·Å´ÎÊýÓÅÏÈÊÍ·Å´ÎÊýµÍµÄ  | 
| #------------------------------------------------------------------------------------------------------------   | 
| #"""Version = 2016-05-25 13:30"""  | 
| #---------------------------------------------------------------------  | 
| import NPCCommon  | 
| import IPY_GameWorld  | 
| import GameWorld  | 
| import ChConfig  | 
| import BaseAttack  | 
| import random  | 
| import PlayerControl  | 
| import OperControlManager  | 
| import SkillCommon  | 
| import SkillShell  | 
| import PetControl  | 
| import ReadChConfig  | 
| import GameObj  | 
| import FBLogic  | 
| #---------------------------------------------------------------------  | 
|   | 
| #---------------------------------------------------------------------  | 
| ## ÊÇ·ñ´æÔÚ,ÕÙ»½ÊÞ¿ÉÒÔ¹¥»÷µÄ , Ö÷È˹¥»÷µÄ¶ÔÏó  | 
| #  @param curNPC ÕÙ»½ÊÞ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param noSpeed Òƶ¯ËÙ¶È  | 
| #  @return None or ¹¥»÷¶ÔÏó  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def PlayerSummonAkObj(curNPC , tick , noSpeed = True):  | 
|       | 
|     if curNPC.GetCurAction() == IPY_GameWorld.laNPCMove :  | 
|         return  | 
|       | 
|     curPlayer = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer , curNPC)  | 
|       | 
|     if not curPlayer:  | 
|         #ûÓÐÖ÷ÈË, ²»¶¯×÷  | 
|         return  | 
|       | 
| #    if not curPlayer.GetIsConfronting():  | 
| #        #Ö÷È˲»ÔÚ¶ÔÖÅ״̬ÖÐ  | 
| #        return  | 
|   | 
|     #Íæ¼ÒÊÇ·ñÔÚÕ½¶·×´Ì¬  | 
|     if not PlayerControl.IsPlayerInFight(curPlayer):  | 
|         return  | 
|       | 
|     masterAttackObj = curPlayer.GetActionObj()  | 
|           | 
|     if not masterAttackObj or not masterAttackObj.IsAlive():  | 
|         return  | 
|       | 
|     attackObjType = masterAttackObj.GetGameObjType()  | 
|       | 
|     if attackObjType == IPY_GameWorld.gotNPC :  | 
|         #»ñµÃNPCÀà  | 
|         attackObjDetel = GameWorld.GetObj(masterAttackObj.GetID(), IPY_GameWorld.gotNPC)  | 
|     elif attackObjType == IPY_GameWorld.gotPlayer:  | 
|         #»ñµÃÍæ¼ÒÀà  | 
|         attackObjDetel = GameWorld.GetObj(masterAttackObj.GetID(), IPY_GameWorld.gotPlayer)  | 
|     else:  | 
|         GameWorld.Log("###curNPC = %s ÎÞ·¨²éÕÒÖ÷È˹¥»÷¶ÔÏóÀàÐÍ%s"%(curNPC.GetName() , attackObjType) , curPlayer.GetPlayerID())  | 
|         return  | 
|       | 
|     if attackObjDetel == None:  | 
|         return  | 
|       | 
|     if not attackObjDetel.GetCanAttack():  | 
|         #²»¿É¹¥»÷  | 
|         return  | 
|       | 
|     #ÅжÏÊÇ·ñµÐ¶Ô¹ØÏµ  | 
|     relation = BaseAttack.GetTagRelation(curPlayer, attackObjDetel, None, tick)[0]  | 
|       | 
|     if relation != ChConfig.Type_Relation_Enemy:  | 
|         return  | 
|       | 
|     #ÅжÏÓë×Ô¼ºµÄ¹ØÏµ  | 
|     relation = BaseAttack.GetTagRelation(curNPC, attackObjDetel, None, tick)[0]  | 
|       | 
|     if relation != ChConfig.Type_Relation_Enemy:  | 
|         return  | 
|       | 
|     #ÎÞÒÆ¶¯ËÙ¶È  | 
|     if noSpeed:  | 
|         #ÅжϺÍÄ¿±êµÄ¹¥»÷¾àÀë  | 
|         atkDist = GameWorld.GetDist(  | 
|                                     masterAttackObj.GetPosX(), masterAttackObj.GetPosY(),   | 
|                                     curNPC.GetPosX(), curNPC.GetPosY()  | 
|                                     )  | 
|       | 
|         if atkDist > curNPC.GetAtkDist() :  | 
|             return  | 
|       | 
|     return masterAttackObj  | 
| #---------------------------------------------------------------------  | 
| ## ÆÕͨNPC¿ÕÏÐ״̬ -> Ëæ»úÒÆ¶¯  | 
| #  @param curNPC µ±Ç°npc  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def NormalNPCFree_Move(curNPC , tick):  | 
|     if curNPC.GetType() != IPY_GameWorld.ntMonster:  | 
|         return  | 
|   | 
|     npcControl = NPCCommon.NPCControl(curNPC)  | 
|     curNPCAction = curNPC.GetCurAction()  | 
|       | 
|     #ÎÞ³ðºÞ,µ«ÊÇÓÐÉ˺¦Ä¿±ê  | 
|     if curNPC.GetPlayerHurtList().GetHurtCount() != 0:  | 
|         npcControl.ResetNPC_Init()  | 
|           | 
|     elif curNPCAction == IPY_GameWorld.laNPCAttack:  | 
|         curNPC.SetCurAction(IPY_GameWorld.laNPCNull)  | 
|         #ÖØÖÃÉÏ´ÎÒÆ¶¯Ê±¼ä,ÈÃ×·»÷Íæ¼ÒµÄNPC¿ÉÒÔÉ¢¿ª  | 
|         curNPC.SetActionTick(0)  | 
|           | 
|     elif curNPCAction == IPY_GameWorld.laNPCNull:  | 
|         #¿ÕÏÐ״̬»ØÑª  | 
|         npcControl.ProcessHPRestore(tick)  | 
|         #ÅжÏÊÇ·ñÖØÖÃ״̬  | 
|         __ReSetBattleState(curNPC)  | 
|         #ÆÕͨС¹ÖÒÆ¶¯  | 
|         npcControl.DoNormalNPCMove(tick)  | 
|               | 
|     return  | 
| #---------------------------------------------------------------------  | 
| ## ÆÕͨNPC¿ìËÙÒÆ¶¯  | 
| #  @param curNPC µ±Ç°Ê±¼ä  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def NormalNPCFast_Move(curNPC , tick):  | 
|     npcControl = NPCCommon.NPCControl(curNPC)  | 
|     #³¬¹ýˢеãÁË,ÅÜ»ØÀ´  | 
|     if not npcControl.IsInRefreshArea():  | 
|         npcControl.MoveBack()  | 
|         return  | 
|       | 
|     #ÎÞÈ˹¥»÷Ëû,ÕýÔÚÅÜ»ØË¢Ð嵋  | 
|     if curNPC.GetPlayerHurtList().GetHurtCount() == 0:  | 
|         #·ÇÕ½¶·»ØÑª  | 
|         npcControl.ProcessHPRestore(tick)  | 
|     #×·»÷Íæ¼Ò  | 
|     else:  | 
|         #Õ½¶·ÖлØÑª  | 
|         npcControl.ProcessBattleHPRestore(tick)  | 
|               | 
|     return  | 
| #---------------------------------------------------------------------  | 
| ## ÖØÖÃNPCÕ½¶·×´Ì¬  | 
| #  @param curNPC µ±Ç°npc  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __ReSetBattleState(curNPC):  | 
|     #´ôÖͲ»´¦Àí  | 
|     if not curNPC.GetIsNeedProcess():  | 
|         return  | 
|       | 
|     if curNPC.GetIsNeedProcess():  | 
|         curNPC.SetIsNeedProcess(False)  | 
|         # SetIsNeedProcess(False) Ó¦¸Ã¼°Ê±ÇåÀí³ðºÞ£¬»ØÑª¿ÉÒÔ²»Óü´Ê±  | 
|         curNPC.GetNPCAngry().Clear()  | 
|           | 
| #    if GameObj.GetHP(curNPC) != GameObj.GetMaxHP(curNPC):  | 
| #        if curNPC.GetIsBoss() != ChConfig.Def_NPCType_Ogre_Normal:  | 
| #            return  | 
| #          | 
| #        #ÆÕͨNPC²»»ØÑª£¬Í˳öÕ½¶·4Ãëºó½øÈë´ôÖÍ״̬  | 
| #        battleTick = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_QuitBattleTick)  | 
| #        tick = GameWorld.GetGameWorld().GetTick()          | 
| #        if battleTick == 0:  | 
| #            curNPC.SetDict(ChConfig.Def_NPC_Dict_QuitBattleTick, tick)  | 
| #            return  | 
| #          | 
| #        if tick - battleTick < 4000:  | 
| #            return  | 
| #  | 
| #    if curNPC.GetIsNeedProcess():  | 
| #        curNPC.SetIsNeedProcess(False)  | 
| #        #ÖØÖÃС¹ÖÕ½¶·CD  | 
| #        if curNPC.GetIsBoss() == ChConfig.Def_NPCType_Ogre_Normal:  | 
| #            curNPC.SetDict(ChConfig.Def_NPC_Dict_QuitBattleTick, 0)  | 
|       | 
|     return  | 
| #---------------------------------------------------------------------  | 
| ## Ëæ»ú»ñµÃѲÂßµã  | 
| #  @param curNPC Ñ²ÂßNPC  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetPatrolPos(curNPC):  | 
|     patrolCount = curNPC.GetPatrolPosCount()  | 
|     #Èç¹ûNPCÓÐѲÂßµã, »Øµ½Ëæ»úÒ»¸öѲÂßµã, Èç¹ûûÓÐ, ÔòËæ»úÔÚˢз¶Î§ÄÚÕÒÒ»¸öµã  | 
|     if patrolCount > 0:  | 
|         patrolIndex = random.randint(0, patrolCount-1)  | 
|         patrolPos = curNPC.GetPatrolPosAt(patrolIndex)  | 
|         posX = patrolPos.GetPosX()  | 
|         posY = patrolPos.GetPosY()  | 
|   | 
|     else:  | 
|         npcControl = NPCCommon.NPCControl(curNPC)  | 
|         posX, posY = npcControl.GetRandPosInRefreshArea()  | 
|   | 
|     return posX, posY  | 
|   | 
| #---------------------------------------------------------------------  | 
| ## Çå¿ÕNPCÉËѪÁбí, ²¢Çå¿ÕÍæ¼ÒLoading½ø¶ÈÌõ״̬  | 
| #  @param curNPC µ±Ç°NPC  | 
| #  @return None  | 
| #  @remarks Çå¿ÕNPCÉËѪÁбí, ²¢Çå¿ÕÍæ¼ÒLoading½ø¶ÈÌõ״̬  | 
| def ClearPlayerPreparing(curNPC, srcPlayer=None):  | 
|     curNPC_HurtList = curNPC.GetPlayerHurtList()  | 
|     for i in range(curNPC_HurtList.GetHurtCount()):  | 
|         hurtValue = curNPC_HurtList.GetHurtAt(i)  | 
|         if hurtValue == None:  | 
|             continue  | 
|         hurtObjID = hurtValue.GetValueID()  | 
|         curPlayer = GameWorld.GetObj(hurtObjID, IPY_GameWorld.gotPlayer)  | 
|           | 
|         #ÎÞ·¨²éÕÒÍæ¼Ò,»òÕßÒѾËÀÍö  | 
|         if curPlayer == None or GameObj.GetHP(curPlayer) <= 0:  | 
|             continue  | 
|           | 
|         if srcPlayer and curPlayer.GetID() == srcPlayer.GetID():  | 
|             # ×Ô¼º²É¼¯µÄÍâ²ã´¦ÀíChangePlayerAction  | 
|             continue  | 
|           | 
|         #²»ÔÚLoaning״̬  | 
|         if curPlayer.GetPlayerAction() != IPY_GameWorld.paPreparing:  | 
|             continue  | 
|           | 
|         hurtObjActionObj = curPlayer.GetActionObj()  | 
|           | 
|         if hurtObjActionObj == None:  | 
|             continue  | 
|           | 
|         if hurtObjActionObj.GetID() != curNPC.GetID():  | 
|             continue  | 
|           | 
|         #ÉèÖÿÕÏÐ״̬  | 
|         PlayerControl.ChangePlayerAction(curPlayer, IPY_GameWorld.paNull)  | 
|       | 
|     #Çå¿ÕÕâ¸öNPCµÄÉËѪÁÐ±í  | 
|     curNPC_HurtList.Clear()  | 
|   | 
|   | 
| def GetPassiveRandomSkill(curSkill):  | 
|     skillIDList = []  | 
|     #Ëæ»ú¼¼ÄÜ, ¿ÉÒÔ¶àÅäÖü¸¸öͬÑùЧ¹ûID  | 
|     effectID = ChConfig.Def_Skill_Effect_RandSkill  | 
|     for i in xrange(0, curSkill.GetEffectCount()):  | 
|         curEffect = curSkill.GetEffect(i)  | 
|         curEffectID = curEffect.GetEffectID()  | 
|           | 
|         if not curEffectID:  | 
|             #²ß»®ÓпÉÄÜÖÐ;ɾ³ý£¬²»ÓÃreturn  | 
|             continue  | 
|           | 
|         #²»ÊÇÐèÒªµÄЧ¹û  | 
|         if curEffectID != effectID:  | 
|             continue  | 
|           | 
|         for j in xrange(curEffect.GetEffectValueCount()):  | 
|             skillID = curEffect.GetEffectValue(j)  | 
|             if not skillID:  | 
|                 continue  | 
|             skillIDList.append(skillID)  | 
|       | 
|     if not skillIDList:  | 
|         return  | 
|       | 
|     curSkillID = random.choice(skillIDList)  | 
|     return GameWorld.GetGameData().GetSkillBySkillID(curSkillID)  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##NPCÊͷż¼ÄÜ  | 
| # @param curNPC NPCʵÀý  | 
| # @param curTag ¹¥»÷Ä¿±ê  | 
| # @param useSkill ÒªÊͷŵļ¼ÄÜ  | 
| # @param tagDist Ë«·½µÄ¾àÀë  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ²¼¶ûÖµ  | 
| def DoNPCUseSkill(curNPC, curTag, useSkill, tagDist, tick):  | 
|     #ÒѾµ½Î²²¿ÁË  | 
|     if not useSkill or useSkill.GetSkillTypeID() == 0:  | 
|         return False  | 
|   | 
|     #±»¶¯¼¼Äܲ»ÊÍ·Å  | 
|     if SkillCommon.isPassiveSkill(useSkill):  | 
|         #GameWorld.Log('±»¶¯¼¼Äܲ»ÊͷŲ»ÊÍ·Å = %s'%(useSkill.GetSkillName()))  | 
|         return False  | 
|   | 
|     #CDʱ¼ä  | 
|     if tick - useSkill.GetLastUseTick() < useSkill.GetCoolDownTime():  | 
|         #GameWorld.Log('¼ì²éCDʱ¼ä´¥·¢Ê§°Ü = %s'%(useSkill.GetSkillName()))  | 
|         return False  | 
|       | 
|     curSkillUseTag = SkillShell.GetSkillAffectTag(useSkill)  | 
|     if curSkillUseTag == ChConfig.Def_UseSkillTag_CanAttackPlayer:  | 
|         if curTag.GetGameObjType() != IPY_GameWorld.gotPlayer:  | 
|             return False  | 
|       | 
|     #¼ì²éÊÇ·ñ¼¸ÂÊ´¥·¢  | 
|     rate = useSkill.GetHappenRate()  | 
|     if rate != ChConfig.Def_MaxRateValue and not GameWorld.CanHappen(rate, ChConfig.Def_MaxRateValue):  | 
|         #GameWorld.Log('¼ì²éÊÇ·ñ¼¸ÂÊ´¥·¢ = %sʧ°Ü = %s'%(rate, useSkill.GetSkillName()))  | 
|         return False  | 
|       | 
|     #Ëæ»ú¼¼ÄÜ  | 
|     changeSkill = GetPassiveRandomSkill(useSkill)  | 
|     if changeSkill:  | 
|         # useSkill ½øÈëCD  | 
|         skillTypeID = useSkill.GetSkillTypeID()  | 
|           | 
|         #¼¼ÄÜʹÓóɹ¦  | 
|         curNPCSkill = curNPC.GetSkillManager().FindSkillBySkillTypeID(skillTypeID)  | 
|         if curNPCSkill:  | 
|             SkillCommon.SetSkillRemainTime(curNPCSkill, 0, tick, curNPC)  | 
|         useSkill = changeSkill  | 
|         #GameWorld.DebugLog("----Ëæ»ú¼¼ÄÜ %s"%useSkill.GetSkillID())  | 
|         | 
|     #===========================================================================  | 
|     # ¸Ä³É±»¶¯´¥·¢  | 
|     # if PetControl.IsPet(curNPC):  | 
|     #    petOwner = PetControl.GetPetOwner(curNPC)  | 
|     #      | 
|     #    if petOwner == None:  | 
|     #        GameWorld.ErrLog("³èÎ%s£©ÕÒ²»µ½Ö÷ÈË"%curNPC.GetRolePet().PetID)  | 
|     #        return False  | 
|     #      | 
|     #    #ѪÁ¿Ìõ¼þÅж¨  | 
|     #    effect = SkillCommon.GetSkillEffectByEffectID(useSkill, ChConfig.Def_Skill_Effect_HPPerLimit)  | 
|     #    if effect:  | 
|     #        if GameObj.GetHP(petOwner)*ChConfig.Def_MaxRateValue/GameObj.GetMaxHP(petOwner) >= effect.GetEffectValue(0):  | 
|     #            return False  | 
|     #===========================================================================  | 
|       | 
|     skillTag = SkillShell.GetSkillAffectTag(useSkill)  | 
|     skillAim = SkillShell.GetSkillFireAim(useSkill)  | 
|   | 
|     #---¶Ô×Ô¼ºÊÍ·Å,»òÕßÎÞÄ¿±ê¼¼ÄÜ---  | 
|     if skillTag in ChConfig.Def_ST_CanNPCUseSkill or skillAim == ChConfig.Def_UseSkillAim_None:  | 
|         #ÊÍ·Å×ÔÉíÀ༼ÄÜ  | 
|         return SkillShell.NPCUseSkill(curNPC, useSkill, tick)  | 
|       | 
|     #---¶Ô³èÎïÖ÷ÈËÊÍ·Å---  | 
|     if skillTag == ChConfig.Def_UseSkillTag_PetMaster:  | 
|         if not PetControl.IsPet(curNPC):  | 
|             GameWorld.ErrLog("¸ÃNPC·Ç³èÎÎÞ·¨»ñµÃÖ÷ÈËÊͷż¼ÄÜ")  | 
|             return False  | 
|           | 
|         petOwner = PetControl.GetPetOwner(curNPC)  | 
|           | 
|         if petOwner == None:  | 
|             GameWorld.ErrLog("³èÎ%s£©¶ÔÖ÷ÈËÊͷż¼ÄÜ£¬ÕÒ²»µ½Ö÷ÈË"%curNPC.GetRolePet().PetID)  | 
|             return False  | 
|           | 
|         curTag = petOwner  | 
|           | 
|     # ÕÙ»½ÊÞ¶ÔÖ÷ÈËÊͷż¼ÄÜ  | 
|     elif skillTag == ChConfig.Def_UseSkillTag_SummonMaster:  | 
|         if not NPCCommon.IsSummonNPC(curNPC):  | 
|             GameWorld.ErrLog("¸ÃNPC·ÇÕÙ»½ÊÞ£¬ÎÞ·¨»ñµÃÖ÷ÈËÊͷż¼ÄÜ")  | 
|             return False  | 
|           | 
|         curSummonOwner =  NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer, curNPC)      | 
|         if curSummonOwner == None:  | 
|             curSummonOwner = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotNPC, curNPC)  | 
|           | 
|         if curSummonOwner == None:  | 
|             GameWorld.ErrLog("ÕÙ»½ÊÞ£¨%s£©¶ÔÖ÷ÈËÊͷż¼ÄÜ£¬ÕÒ²»µ½Ö÷ÈË" % curNPC.GetNPCID())  | 
|             return  | 
|       | 
|         curTag = curSummonOwner  | 
|           | 
|     #---¶ÔÄ¿±êÊͷż¼ÄÜ---  | 
|     if tagDist > useSkill.GetAtkDist():  | 
|         #GameWorld.Log('¶ÔÄ¿±êÊͷż¼ÄÜ = %s, ¾àÀë¹ýÔ¶ = %s'%(useSkill.GetSkillName(), useSkill.GetAtkDist()))  | 
|         return False  | 
|       | 
|     #GameWorld.Log('ÊÍ·ÅÄ¿±êÀ༼ÄÜ')  | 
|     #ÊÍ·ÅÄ¿±êÀ༼ÄÜ  | 
|     return SkillShell.NPCUseSkillTag(curNPC, curTag, useSkill, tick)  | 
|   | 
|       | 
| #---------------------------------------------------------------------  | 
|   | 
|   | 
| def GetCanUseRealmSuppressSkll(curNPC, curSkill):  | 
|     if curSkill.GetFuncType() != ChConfig.Def_SkillFuncType_RealmSuppress:  | 
|         # ·Ç¾³½çÑ¹ÖÆ¼¼ÄÜ·µ»Ø¿ÉÓà  | 
|         return True  | 
|       | 
|     # ¾³½çÑ¹ÖÆ¼¼ÄÜÐèÅжϠÖÜΧÊÇ·ñÓе;³½çÍæ¼Ò  | 
|     npcRealmLV = NPCCommon.GetRealmLV(curNPC)  | 
|     angryManager = curNPC.GetNPCAngry()  | 
|       | 
|     for i in range(0, angryManager.GetAngryCount()) :  | 
|         curAngry = angryManager.GetAngryValueTag(i)  | 
|         if curAngry == None or curAngry.GetObjID() == 0:  | 
|             continue  | 
|           | 
|         #³ðºÞÖµ  | 
|         curAngryValue = GameObj.GetAngryValue(curAngry)  | 
|         if curAngryValue == 0:  | 
|             continue  | 
|           | 
|         if curAngry.GetIsDisable():  | 
|             continue  | 
|           | 
|         angryID = curAngry.GetObjID()  | 
|         angryObjType = curAngry.GetObjType()  | 
|         if angryObjType != IPY_GameWorld.gotPlayer:  | 
|             continue  | 
|           | 
|         curTag = GameWorld.GetObj(angryID, angryObjType)  | 
|         if not curTag:  | 
|             continue  | 
|         if curTag.GetOfficialRank() < npcRealmLV:  | 
|             return True  | 
|           | 
|     return False  | 
|           | 
|           | 
| ##NPC×Ô¶¯Êͷż¼ÄÜ  | 
| # @param curNPC NPCʵÀý  | 
| # @param curTag ¹¥»÷Ä¿±ê  | 
| # @param tagDist Ë«·½µÄ¾àÀë  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ²¼¶ûÖµ  | 
| # @remarks ×Ô¶¯Êͷż¼ÄÜÁбíÖеķDZ»¶¯¼¼ÄÜ  | 
| def DoAutoUseSkill(curNPC, curTag, tagDist, tick):  | 
|     #¹¥»÷½©³ÖÖÐ  | 
|     if tick - curNPC.GetAttackTick() < curNPC.GetAtkInterval():  | 
|         if not (PetControl.IsPet(curNPC) or curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightNum)):  | 
|             #GameWorld.Log('¹¥»÷½©³ÖÖÐ')  | 
|             return False  | 
|       | 
|     npcID = curNPC.GetNPCID()  | 
|     npcAITrigger = ReadChConfig.GetEvalChConfig("NPCLogic_AI186_Trigger")  | 
|     triggerDict = {}  | 
|     if npcID in npcAITrigger:  | 
|         triggerDict = npcAITrigger[npcID]  | 
|           | 
|     useSkillIDOnDie = 0  | 
|     npcUseSkillOnDieDict = ReadChConfig.GetEvalChConfig("NPCLogic_AI_UseSkillOnDie")  | 
|     if npcID in npcUseSkillOnDieDict:  | 
|         useSkillIDOnDie = npcUseSkillOnDieDict[npcID][0]  | 
|           | 
|     useSkillAfterOtherDieDict = {}  | 
|     useSkillAfterOtherDieNPCDict = ReadChConfig.GetEvalChConfig("NPCLogic_AI_UseSkillAfterOtherDie")  | 
|     if npcID in useSkillAfterOtherDieNPCDict:  | 
|         useSkillAfterOtherDieDict = useSkillAfterOtherDieNPCDict[npcID]  | 
|       | 
|     skillManager = curNPC.GetSkillManager()  | 
|     tagObjType = curTag.GetGameObjType()  | 
|       | 
|     useSkillList = []  | 
|     for index in range(0, skillManager.GetSkillCount()):  | 
|         useSkill = skillManager.GetSkillByIndex(index)  | 
|         #ÒѾµ½Î²²¿ÁË  | 
|         if not useSkill or useSkill.GetSkillTypeID() == 0:  | 
|             break  | 
|           | 
|         if useSkillIDOnDie and useSkillIDOnDie == useSkill.GetSkillID():  | 
|             #GameWorld.DebugLog("ËÀÍöÊͷŵļ¼ÄܽöÔÚËÀÍöʱ²ÅÄÜÊÍ·Å£¡useSkillIDOnDie=%s" % useSkillIDOnDie)  | 
|             continue  | 
|           | 
|         skillTypeID = useSkill.GetSkillTypeID()  | 
|         if skillTypeID in useSkillAfterOtherDieDict:  | 
|             checkIsDeadNPCID = useSkillAfterOtherDieDict[skillTypeID]  | 
|             if GameWorld.FindNPCByNPCID(checkIsDeadNPCID):  | 
|                 #GameWorld.DebugLog("Ä¿±êNPC»¹»î×Å£¬¸Ã¼¼ÄÜδ½âËø£¬ÎÞ·¨ÊÍ·Å£¡npcID=%s,skillTypeID=%s,checkIsDeadNPCID=%s"   | 
|                 #                   % (npcID, skillTypeID, checkIsDeadNPCID))  | 
|                 continue  | 
|               | 
|         #±»¶¯¼¼Äܲ»ÊÍ·Å  | 
|         if SkillCommon.isPassiveSkill(useSkill):  | 
|             #GameWorld.Log('±»¶¯¼¼Äܲ»ÊͷŲ»ÊÍ·Å = %s'%(useSkill.GetSkillName()))  | 
|             continue  | 
|           | 
|         if SkillShell.GetSkillFireAim(useSkill) == ChConfig.Def_UseSkillAim_Obj:  | 
|             # Ö÷Ä¿±ê¶ÔÏóÅж¨, ²»ÄÜÊÍ·ÅÔò²»½øÈë¶ÓÁÐ  | 
|             curSkillUseTag = SkillShell.GetSkillAffectTag(useSkill)  | 
|             if curSkillUseTag != ChConfig.Def_UseSkillTag_AppointNPC:  | 
|                 hurtTypeList = ChConfig.Def_Dict_UseSkillTag_ObjType.get(curSkillUseTag)  | 
|                 if not hurtTypeList:  | 
|                     continue  | 
|                   | 
|                 if tagObjType not in hurtTypeList:  | 
|                     continue  | 
|           | 
|         if triggerDict != {}:  | 
|             if not CheckSkillTrigger(curNPC, triggerDict, index, tick):  | 
|                 continue  | 
|               | 
|         # ¾³½çÑ¹ÖÆÐèÒª¸ù¾Ý³ðºÞÁбíÖеÄÍæ¼ÒÊÇ·ñÓÐÑ¹ÖÆ  | 
|         if not GetCanUseRealmSuppressSkll(curNPC, useSkill):  | 
|             continue  | 
|           | 
|         useCnt = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillUseCnt % useSkill.GetSkillTypeID()) # ¸Ã¼¼ÄÜÒÑʹÓôÎÊý  | 
|         useSkillList.append([useCnt, index, useSkill])  | 
|           | 
|     if not useSkillList:  | 
|         return False  | 
|       | 
|     useSkillList.sort() # °´Ê¹ÓôÎÊýÓÅÏÈÉýÐòÅÅ£¬Ê¹ÓôÎÊýµÍµÄÓÅÏÈÅжÏʹÓà  | 
|     #GameWorld.DebugLog('¼¼ÄÜʹÓÃ˳Ðò = useSkillList%s' % str(useSkillList), curNPC.GetID())  | 
|       | 
|     for useCnt, index, useSkill in useSkillList:  | 
|         skillID = useSkill.GetSkillID()  | 
|         if DoNPCUseSkill(curNPC, curTag, useSkill, tagDist, tick):  | 
|             return skillID  | 
|           | 
|     #ÎÞ¼¼ÄÜ¿ÉÒÔÊÍ·Å  | 
|     return False  | 
|   | 
| ##¼ì²é¼¼ÄÜ´¥·¢Æ÷  | 
| # @param curNPC NPCʵÀý  | 
| # @param triggerDict ´¥·¢Æ÷×Öµä  | 
| # @param npcSkillindex NPCÊͷż¼ÄܵÄË÷Òý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ²¼¶ûÖµ  | 
| def CheckSkillTrigger(curNPC, triggerDict, npcSkillindex, tick):  | 
|     skillInfo = triggerDict.get(npcSkillindex)  | 
|   | 
|     if skillInfo != None:  | 
|         #µ±Ç°ÑªÁ¿  | 
|         hpPercent = int(GameObj.GetHP(curNPC)/float(GameObj.GetMaxHP(curNPC))*100)  | 
|         checkHP = skillInfo[0]  | 
|           | 
|         #ѪÁ¿Î´µ½  | 
|         if checkHP != 0 and hpPercent > checkHP:  | 
|             return False  | 
|           | 
|         #ÈËÊýδµ½  | 
|         if not NPCCommon.CheckCanAttackTagLimitCountInSight_NPC(curNPC, skillInfo[1], skillInfo[2], tick):  | 
|             return False  | 
|       | 
|     return True  | 
|   | 
| def DoNPCUseSkillOnDie(curNPC):  | 
|     ## NPCËÀÍöÊͷż¼ÄÜ  | 
|     ## @remarks:  ËÀÍöµÄʱºò·Å¼¼ÄÜ ÒòΪNPCËÀÁËËùÒÔÐèÒªÏÈÉèHP 1 Èƹý¼ì²é È»ºóÔÙÉè³É0  | 
|     npcID = curNPC.GetNPCID()  | 
|     npcUseSkillOnDieDict = ReadChConfig.GetEvalChConfig("NPCLogic_AI_UseSkillOnDie")  | 
|     if npcID not in npcUseSkillOnDieDict:  | 
|         #GameWorld.DebugLog("¸ÃNPCûÓÐËÀÍöÊͷż¼ÄÜÂß¼£¡npcID=%s" % (npcID), curNPC.GetID())  | 
|         return  | 
|     skillID, tagNPCID = npcUseSkillOnDieDict[npcID]  | 
|     skillManager = curNPC.GetSkillManager()  | 
|     useSkill = skillManager.FindSkillBySkillID(skillID)  | 
|     #GameWorld.DebugLog("NPCËÀÍöÊͷż¼ÄÜÂß¼£¡npcID=%s,skillID=%s" % (npcID, skillID), curNPC.GetID())  | 
|     if not useSkill:  | 
|         return  | 
|       | 
|     tagDist = 0  | 
|     curTag = None  | 
|     if tagNPCID:  | 
|         # Ö¸¶¨NPCIDµÄÔݲ»ÊÕ¾àÀëÏÞÖÆ  | 
|         curTag = GameWorld.FindNPCByNPCID(tagNPCID)  | 
|         if not curTag:  | 
|             #GameWorld.DebugLog("    ÕÒ²»µ½Ä¿±ê tagNPCID: %s" % tagNPCID, curNPC.GetID())  | 
|             return  | 
|     else:  | 
|         # ¸ù¾Ý¼¼ÄÜÊÍ·ÅÄ¿±ê»ñȡĿ±ê¶ÔÏ󣬴ýÀ©Õ¹...  | 
|         #curTag = ...  | 
|         if curTag:  | 
|             tagDist = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), curTag.GetPosX(), curTag.GetPosY())  | 
|               | 
|     tick = GameWorld.GetGameWorld().GetTick()  | 
|     GameObj.SetHP(curNPC, 1)  | 
|     isOK = DoNPCUseSkill(curNPC, curTag, useSkill, tagDist, tick)  | 
|     #GameWorld.DebugLog("    ËÀÍöÊͷż¼ÄÜ: isOK=%s" % isOK, curNPC.GetID())  | 
|     GameObj.SetHP(curNPC, 0)  | 
|     return  | 
|   | 
| def DoNPCSkillWarningProcess(curNPC, tick):  | 
|     '''Ô¤¾¯¼¼ÄÜÕ½¶·´¦Àí  | 
|     @return: 0-·ÇÔ¤¾¯×´Ì¬£»1-Ô¤¾¯´¦Àí½áÊø£¬³É¹¦Ö´ÐУ»2-Ô¤¾¯ÖУ»  | 
|     '''  | 
|     if curNPC.GetCurAction() != IPY_GameWorld.laNPCSkillWarning:  | 
|         #GameWorld.DebugLog("    ·Ç¼¼ÄÜÔ¤¾¯×´Ì¬²»´¦Àí")  | 
|         return 0  | 
|       | 
|     warnSkillID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnSkillID)  | 
|     useSkill = curNPC.GetSkillManager().FindSkillBySkillID(warnSkillID)  | 
|     if not useSkill:  | 
|         GameWorld.DebugLog("    Ô¤¾¯×´Ì¬ÏÂÔ¤¾¯¼¼Äܲ»´æÔÚ, ÖØÖÃ״̬!warnSkillID=%s" % warnSkillID)  | 
|         curNPC.SetCurAction(IPY_GameWorld.laNPCNull)  | 
|         __ClearNPCSkillWarn(curNPC)  | 
|         return 0  | 
|       | 
|     warnTime = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnTime)  | 
|     passTick = max(0, tick - curNPC.GetActionTick())  | 
|     if passTick < warnTime:  | 
|         #GameWorld.DebugLog("Ô¤¾¯Ê±¼äδµ½£¡npcID=%s,passTick=%s,warnTime=%s" % (curNPC.GetNPCID(), passTick, warnTime))  | 
|         return 2  | 
|       | 
|     curNPC.SetCurAction(IPY_GameWorld.laNPCAttack)  | 
|       | 
|     if useSkill.GetSkillType() == ChConfig.Def_SkillType_Summon:  | 
|         #GameWorld.DebugLog("    Ô¤¾¯Ê±¼äµ½£¬ÊÍ·ÅÕÙ»½¼¼ÄÜ warnSkillID=%s,passTick=%s,warnTime=%s" % (warnSkillID, passTick, warnTime))  | 
|         SkillShell.DoLogic_UseSkill(curNPC, curNPC, useSkill, tick)  | 
|     else:  | 
|         posX = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnPosX % 0)  | 
|         posY = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnPosY % 0)  | 
|         if posX + posY == 0:  | 
|             posX = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX)  | 
|             posY = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosY)  | 
|         #GameWorld.DebugLog("    Ô¤¾¯Ê±¼äµ½£¬Êͷż¼ÄÜ warnSkillID=%s,passTick=%s,warnTime=%s,posX=%s,posY=%s" % (warnSkillID, passTick, warnTime, posX, posY))  | 
|         SkillShell.DoLogic_UseSkill(curNPC, None, useSkill, tick, posX, posY)  | 
|         if curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX) != 0:  | 
|             curNPC.ChangePos(curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX),   | 
|                              curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosY))  | 
|             curNPC.SetDict(ChConfig.Def_NPC_Dict_AtkMovePosX, 0)  | 
|             curNPC.SetDict(ChConfig.Def_NPC_Dict_AtkMovePosY, 0)  | 
|           | 
|     __ClearNPCSkillWarn(curNPC)  | 
|     return 1  | 
|   | 
| def __ClearNPCSkillWarn(curNPC):  | 
|     posCnt = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnPosCnt)  | 
|     curNPC.SetDict(ChConfig.Def_NPC_Dict_SkillWarnSkillID, 0)  | 
|     curNPC.SetDict(ChConfig.Def_NPC_Dict_SkillWarnTime, 0)  | 
|     curNPC.SetDict(ChConfig.Def_NPC_Dict_SkillWarnPosCnt, 0)  | 
|     for i in xrange(posCnt):  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_SkillWarnPosX % i, 0)  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_SkillWarnPosY % i, 0)  | 
|     return  | 
|   | 
|   | 
| def NPCMoveByPointList(curNPC, movePointList, tick):  | 
|     if not movePointList:  | 
|         return  | 
|     pointIndex = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_MovePointIndex)  | 
|     destPosX, destPosY = movePointList[pointIndex]  | 
|     curPosX, curPosY = curNPC.GetPosX(), curNPC.GetPosY()  | 
|     curDis = GameWorld.GetDist(curPosX, curPosY, destPosX, destPosY)  | 
|     #Èç¹ûÀëÄ¿±êµã±È½Ï½üµÄ»° È¡ÏÂÒ»¸öÄ¿±êµã  | 
|     while curDis <= 6 and pointIndex < len(movePointList) - 1:  | 
|         pointIndex += 1  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_MovePointIndex, pointIndex)  | 
|         destPosX, destPosY = movePointList[pointIndex]  | 
|         curDis = GameWorld.GetDist(curPosX, curPosY, destPosX, destPosY)  | 
|           | 
|     if curDis != 0:  | 
|         if curNPC.GetCurAction() == IPY_GameWorld.laNPCMove:  | 
|             return  | 
|           | 
|         #²»¿ÉÒÆ¶¯ÐÐΪ״̬, ·þÎñ¶ËÏÞÖÆ  | 
|         if not OperControlManager.IsObjCanDoAction(curNPC,  | 
|                                                    ChConfig.Def_Obj_ActState_ServerAct,  | 
|                                                    IPY_GameWorld.oalMove):  | 
|             return    | 
|           | 
|         curNPC.Move(destPosX, destPosY)  | 
|         return  | 
|       | 
|     # µ½´ïÖÕµã  | 
|     if pointIndex == (len(movePointList) - 1):  | 
|         FBLogic.OnTDNPCReachTheGoal(curNPC, tick)  | 
|           | 
|     return  | 
|   |