#!/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 time import math import PlayerActivity 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): PassiveBuffEffMng.GetPassiveEffManager().RemovePassiveEff((curNPC.GetID(), IPY_GameWorld.gotNPC)) # ÕÙ»½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 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 if curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo): #GameWorld.DebugLog("»ØºÏÖÆNPC²»´¦ÀíAI!", curNPC.GetID()) 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 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