| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package NPCAI.AIType_196  | 
| #  | 
| # @todo:µÁ±¦¸ç²¼ÁÖ/±¦Ïä¹Ö  | 
| # @author hxp  | 
| # @date 2019-04-18  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: µÁ±¦¸ç²¼ÁÖ/±¦Ïä¹Ö  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2019-04-18 15:00"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import GameMap  | 
| import ChConfig  | 
| import GameWorld  | 
| import NPCCommon  | 
| import IPY_GameWorld  | 
| import AICommon  | 
| import GameObj  | 
|   | 
| import random  | 
|   | 
| #---------------------------------------------------------------------  | 
|   | 
| Def_NPCKey_Goblin_AttackedTick = 'Goblin_AttackedTick'  # ¸ç²¼ÁÖ±»¹¥»÷ʱ¼ä  | 
| Def_NPCKey_Goblin_MoveDir = 'Goblin_MoveDir'  # ¸ç²¼ÁÖÒÆ¶¯·½Ïò  | 
|   | 
| # Òƶ¯·½Ïò  | 
| MoveDirList = (  | 
| Def_MoveDir_Up, # ÉÏ  | 
| Def_MoveDir_Down, # ÏÂ  | 
| Def_MoveDir_Left, # ×ó  | 
| Def_MoveDir_Right, # ÓÒ  | 
| Def_MoveDir_LeftUp, # ×óÉÏ  | 
| Def_MoveDir_LeftDown, # ×óÏÂ  | 
| Def_MoveDir_RightUp, # ÓÒÉÏ  | 
| Def_MoveDir_RightDown, # ÓÒÏÂ  | 
| ) = range(8)  | 
|   | 
| #---------------------------------------------------------------------  | 
|   | 
|   | 
| ## ³õʼ»¯  | 
| #  @param curNPC µ±Ç°npc  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def DoInit(curNPC):  | 
|     curNPC.GetNPCAngry().Init(ChConfig.Def_NormalNPCAngryCount)  | 
|     #curNPC.SetDict(Def_NPCKey_Goblin_AttackedTick, 0) # ÉèÖñ»¹¥»÷ʱ¼ä  | 
|     return  | 
|   | 
|   | 
| ## Ö´ÐÐAI  | 
| #  @param curNPC µ±Ç°npc  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def ProcessAI(curNPC, tick):  | 
|       | 
|     npcControl = NPCCommon.NPCControl(curNPC)  | 
|     if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():  | 
|         #NPCËÀÍö, ½øÈëËÀÍöµ¹¼ÆÊ±  | 
|         if npcControl.DieTick(tick) == 0:  | 
|             return  | 
|           | 
|     # ÉÏÒ»´Î±»¹¥»÷ʱ¼ä  | 
|     attackedTick = curNPC.GetDictByKey(Def_NPCKey_Goblin_AttackedTick)  | 
|       | 
|     # Î´±»¹¥»÷£¬Õ¾Á¢²»¶¯  | 
|     if attackedTick <= 0:  | 
|         __CheckCorrectGoblinPos(curNPC)  | 
|         return  | 
|       | 
|     # Ò»¶¨Ê±¼äÄÚδ±»¹¥»÷£¬ÔòÍ£Ö¹  | 
|     if tick - attackedTick >= 3000:  | 
|         __GoblinStop(curNPC)  | 
|         return  | 
|       | 
|     curNPCAction = curNPC.GetCurAction()  | 
|     # Èç¹û²»ÊÇÒÆ¶¯×´Ì¬£¬ÔòÖ´ÐÐÒÆ¶¯  | 
|     if curNPCAction != IPY_GameWorld.laNPCMove:  | 
|         __Runaway(curNPC, npcControl, tick)  | 
|           | 
|     return  | 
|   | 
|   | 
| ## ¼ì²é²¢¾ÀÕý¸ç²¼ÁÖλÖà  | 
| #  @param curNPC   | 
| #  @return None  | 
| def __CheckCorrectGoblinPos(curNPC):  | 
|     curNPCAction = curNPC.GetCurAction()  | 
|     if curNPCAction != IPY_GameWorld.laNPCNull:  | 
|         return  | 
|       | 
|     gameMap = GameWorld.GetMap()  | 
|     posX = curNPC.GetPosX()  | 
|     posY = curNPC.GetPosY()  | 
|       | 
|     isCorrectPos = False  | 
|     if GameMap.GetAreaTypeByMapPos(posX, posY) == IPY_GameWorld.gatSafe:  | 
|         isCorrectPos = True  | 
|         GameWorld.DebugLog("µ±Ç°´¦ÔÚ°²È«Çø!(%s,%s)" % (posX, posY))  | 
|           | 
|     if not gameMap.CanMove(posX, posY):  | 
|         isCorrectPos = True  | 
|         GameWorld.DebugLog("µ±Ç°Õϰµã²»¿ÉÒÆ¶¯!(%s,%s)" % (posX, posY))  | 
|             | 
|     if not isCorrectPos:  | 
|         return  | 
|       | 
|     dist = ChConfig.Def_Screen_Area * 2  | 
|     cPosX, cPosY = 0, 0  | 
|     for _ in xrange(0, dist * dist):  | 
|         cPosX = random.randint(posX - dist, posX + dist)  | 
|         cPosY = random.randint(posY - dist, posY + dist)  | 
|           | 
|         if gameMap.CanMove(cPosX, cPosY) and GameMap.GetAreaTypeByMapPos(cPosX, cPosY) != IPY_GameWorld.gatSafe:  | 
|             curNPC.ResetPos(cPosX, cPosY)  | 
|             GameWorld.Log("¸ç²¼ÁÖ´¦ÓÚ²»¿ÉÒÆ¶¯µã£¬ÖØÖÃλÖã¡(%s,%s) to (%s,%s)" % (posX, posY, cPosX, cPosY))  | 
|             break  | 
|     return  | 
|   | 
| ## ¸ç²¼ÁÖÍ£Ö¹ÒÆ¶¯  | 
| #  @param curNPC µ±Ç°npc  | 
| #  @return None  | 
| def __GoblinStop(curNPC):  | 
|     #curNPC.Move(curNPC.GetPosX(), curNPC.GetPosY()) # Í£Ö¹ÔÚµ±Ç°µã  | 
|     curNPC.SetDict(Def_NPCKey_Goblin_AttackedTick, 0) # ÉèÖñ»¹¥»÷ʱ¼ä  | 
|     return  | 
|   | 
|   | 
| ## Òƶ¯×ß¿ª  | 
| def __Runaway(curNPC, npcControl, tick):  | 
|     posX = curNPC.GetPosX()  | 
|     posY = curNPC.GetPosY()  | 
|     moveArea = curNPC.GetMoveArea() # µ¥´ÎÒÆ¶¯·¶Î§  | 
|     moveDir = curNPC.GetDictByKey(Def_NPCKey_Goblin_MoveDir) # µ±Ç°·½Ïò  | 
|     tagPosX, tagPosY = 0, 0  | 
|       | 
|     # Ñ°ÕÒÄ¿±ê×ø±êµã  | 
|     for _ in range(len(MoveDirList)):  | 
|         tagPosX, tagPosY = __GetRandomPos(posX, posY, moveArea, moveDir)  | 
|         # Èç¹û·µ»Ø0,0µã£¬»òÕßλÖò»±ä£¬Ôò¸Ä±äÒÆ¶¯·½Ïò  | 
|         if (tagPosX == 0 and tagPosY == 0) or (tagPosX == posX and tagPosY == posY):  | 
|             moveDir = __ChangeMoveDir(curNPC, moveDir)  | 
|           | 
|         # Èç¹ûÕÒµ½Ä¿±êµãÔòÌø³ö  | 
|         else:  | 
|             break  | 
|               | 
|     # ÉèÖÃΪ¼«ËÙ״̬  | 
|     # NPCCommon.ChangeNPCMoveType(curNPC, IPY_GameWorld.mtRun, True)  | 
|     # Òƶ¯µ½Ä¿±êµã  | 
|     curNPC.Move(tagPosX, tagPosY)  | 
|     return  | 
|   | 
| ## ¸ù¾Ýµ±Ç°·½Ïò¸Ä±äÒÆ¶¯·½Ïò  | 
| #  @param curNPC µ±Ç°npc  | 
| #  @param moveDir µ±Ç°·½Ïò  | 
| #  @return ¸Ä±äºóµÄ·½Ïò  | 
| def __ChangeMoveDir(curNPC, moveDir):  | 
|       | 
|     if moveDir == Def_MoveDir_Up: # ÉÏ  | 
|         nextDir = random.choice([Def_MoveDir_Left, Def_MoveDir_Right, Def_MoveDir_LeftDown, Def_MoveDir_RightDown])  | 
|     elif moveDir == Def_MoveDir_Down: # ÏÂ  | 
|         nextDir = random.choice([Def_MoveDir_Left, Def_MoveDir_Right, Def_MoveDir_LeftUp, Def_MoveDir_RightUp])  | 
|     elif moveDir == Def_MoveDir_Left: # ×ó  | 
|         nextDir = random.choice([Def_MoveDir_Up, Def_MoveDir_Down, Def_MoveDir_RightUp, Def_MoveDir_RightDown])  | 
|     elif moveDir == Def_MoveDir_Right: # ÓÒ  | 
|         nextDir = random.choice([Def_MoveDir_Up, Def_MoveDir_Down, Def_MoveDir_LeftUp, Def_MoveDir_LeftDown])  | 
|     elif moveDir == Def_MoveDir_LeftUp: # ×óÉÏ  | 
|         nextDir = random.choice([Def_MoveDir_Right, Def_MoveDir_Down, Def_MoveDir_RightUp, Def_MoveDir_LeftDown])  | 
|     elif moveDir == Def_MoveDir_LeftDown: # ×óÏÂ  | 
|         nextDir = random.choice([Def_MoveDir_Right, Def_MoveDir_Up, Def_MoveDir_RightDown, Def_MoveDir_LeftUp])  | 
|     elif moveDir == Def_MoveDir_RightUp: # ÓÒÉÏ  | 
|         nextDir = random.choice([Def_MoveDir_Left, Def_MoveDir_Down, Def_MoveDir_LeftUp, Def_MoveDir_RightDown])  | 
|     elif moveDir == Def_MoveDir_RightDown: # ÓÒÏÂ  | 
|         nextDir = random.choice([Def_MoveDir_Left, Def_MoveDir_Up, Def_MoveDir_LeftDown, Def_MoveDir_RightUp])  | 
|     else:  | 
|         nextDir = random.choice(MoveDirList)  | 
|           | 
|     curNPC.SetDict(Def_NPCKey_Goblin_MoveDir, nextDir) # ÉèÖÃз½Ïò  | 
|     return nextDir  | 
|   | 
|   | 
| ##  Ëæ»ú»ñµÃµ±Ç°µØÍ¼¸ø¶¨×ø±êµÄx,yÔÚdist·¶Î§ÄڵĿÉÒÔÒÆ¶¯µÄÒ»µã Èç¹ûûÓÐÒ»µã¿ÉÒÔÒÆ¶¯Ôò·µ»Ø 0, 0  | 
| #   @param posX: ×ø±êX  | 
| #   @param posY: ×ø±êY  | 
| #   @param dist: ÖÜΧµÄ¾àÀë    | 
| #   @param moveDir: Ïà¶Ô¸ø¶¨×ø±ê·½Ïò    | 
| #   @return: posX,posY ×ø±ê Èç¹ûûÓÐÕÒµ½·µ»Ø0, 0  | 
| #   @remarks: Èç¹û·µ»Ø0, 0ÔÚµ÷Óøú¯ÊýµÄÄ£¿éÖÐÐèÒª×öÅж¨£¬Èç¹ûÊÇ0, 0×öÌØÊâ´¦Àí  | 
| def __GetRandomPos(posX, posY, dist, moveDir):  | 
|       | 
|     if moveDir not in MoveDirList:  | 
|         GameWorld.ErrLog("moveDir=%s not in MoveDirList" % moveDir)  | 
|         return (0, 0)  | 
|        | 
|     for _ in range(0, dist * dist):  | 
|         if moveDir == Def_MoveDir_Up: # ÉÏ  | 
|             resultX = posX  | 
|             resultY = posY + dist  | 
|         elif moveDir == Def_MoveDir_Down: # ÏÂ  | 
|             resultX = posX  | 
|             resultY = posY - dist  | 
|         elif moveDir == Def_MoveDir_Left: # ×ó  | 
|             resultX = posX - dist  | 
|             resultY = posY  | 
|         elif moveDir == Def_MoveDir_Right: # ÓÒ  | 
|             resultX = posX + dist  | 
|             resultY = posY  | 
|         elif moveDir == Def_MoveDir_LeftUp: # ×óÉÏ  | 
|             resultX = posX - dist  | 
|             resultY = posY + dist  | 
|         elif moveDir == Def_MoveDir_LeftDown: # ×óÏÂ  | 
|             resultX = posX - dist  | 
|             resultY = posY - dist  | 
|         elif moveDir == Def_MoveDir_RightUp: # ÓÒÉÏ  | 
|             resultX = posX + dist  | 
|             resultY = posY + dist  | 
|         elif moveDir == Def_MoveDir_RightDown: # ÓÒÏÂ  | 
|             resultX = posX + dist  | 
|             resultY = posY - dist  | 
|           | 
|         # ¿ÉÒÆ¶¯£¬·Ç°²È«Çø  | 
|         if GameMap.GetAreaTypeByMapPos(resultX, resultY) \  | 
|                                                         != IPY_GameWorld.gatSafe:  | 
|             newPoint = GameWorld.GetMap().LineNearToPos(posX, posY, resultX, resultY, 0)  | 
|             return (newPoint.GetPosX(), newPoint.GetPosY())  | 
|   | 
|     return (0, 0)  | 
|   | 
| ## Ã¿´Î±»¹¥»÷´¦Àí½á¹û  | 
| #  @param atkObj ¹¥»÷·¢ÆðÕß  | 
| #  @param defObj ±»¹¥»÷Õß  | 
| #  @param skill ¹¥»÷¼¼ÄÜ  | 
| #  @param tick   | 
| #  @return ¾ßÌåÉ˺¦Öµ  | 
| def OnAttacked(atkObj, curNPC, skill, tick):  | 
|     if GameObj.GetHP(curNPC) < GameObj.GetMaxHP(curNPC) / 2:  | 
|         GameObj.SetHP(curNPC, GameObj.GetMaxHP(curNPC))  | 
|         GameWorld.DebugLog("°ëѪ»ØÂúѪ!")  | 
|     curNPC.SetDict(Def_NPCKey_Goblin_AttackedTick, tick) # ÉèÖñ»¹¥»÷ʱ¼ä  | 
|     return  | 
|   | 
| def OnCheckCanDie(atkObj, curNPC, skill, tick):  | 
|     ## ¼ì²éNPCÊÇ·ñ¿ÉËÀÍö  | 
|     GameObj.SetHP(curNPC, GameObj.GetMaxHP(curNPC))  | 
|     GameWorld.DebugLog("ËÀÍö»ØÂúѪ!")  | 
|     return False  | 
|   |