#!/usr/bin/python
|
# -*- coding: GBK -*-
|
#-------------------------------------------------------------------------------
|
#
|
#-------------------------------------------------------------------------------
|
#
|
##@package AIType_186
|
#
|
# @todo: NPCͨ¹ý±í¶ÁÈ¡Êͷż¼ÄÜ
|
# @author Alee
|
# @date 2011-05-18 18:00
|
# @version 2.2
|
#
|
# ÏêϸÃèÊö:
|
# @change: "2013-06-18 22:30" Alee С¹Ö³ðºÞÊýËõС
|
# @change: "2014-01-28 15:30" hxp Ôö¼ÓÄêÊÞÊ£ÓàѪÁ¿¹ã²¥
|
# @change: "2014-02-21 14:20" hxp Ôö¼ÓÊÀ½çbossÂß¼£¬¹¥»÷»ÆÃû£¬Ê£ÓàѪÁ¿¹ã²¥
|
# @change: "2014-02-27 12:00" hxp Ôö¼ÓNPCѪÁ¿°Ù·Ö±ÈÂß¼Èë¿Ú
|
# @change: "2014-03-11 19:30" hxp ÐÞ¸ÄÃþÊÀ½çboss»ÆÃûbuffID
|
# @change: "2014-04-14 12:00" hxp Ôö¼ÓbossËÀÍöÕÙ»½²É¼¯Îï
|
# @change: "2014-09-24 17:00" hxp ÃþÊÀ½çbossbuffÌí¼ÓÂß¼ÐÞ¸Ä
|
# @change: "2014-10-27 21:00" hxp ¹¥»÷bossÊÇ·ñ»ñµÃbuff¿ª³öÅäÖÃ
|
# @change: "2014-12-08 21:30" hxp ÓÅ»¯AI
|
# @change: "2014-12-15 07:20" Alee ½µµÍNPCAIÏûºÄ
|
# @change: "2014-12-31 14:40" Alee ½µµÍNPCAIÏûºÄ
|
# @change: "2016-11-22 21:00" hxp Ö§³ÖÌí¼Ó×î´ó³ðºÞbuff
|
#------------------------------------------------------------------------------
|
#"""Version = 2016-11-22 21:00"""
|
#-------------------------------------------------------------------------------
|
import ChConfig
|
import NPCCommon
|
import AICommon
|
import IPY_GameWorld
|
import FamilyRobBoss
|
import AttackCommon
|
import GameWorld
|
import BaseAttack
|
import PlayerState
|
import SkillCommon
|
import PyGameData
|
import BuffSkill
|
import GameObj
|
|
## ³õʼ»¯
|
# @param curNPC µ±Ç°npc
|
# @return None
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def DoInit(curNPC):
|
angryCount = ChConfig.Def_NormalNPCAngryCount
|
if ChConfig.IsGameBoss(curNPC):
|
angryCount = ChConfig.Def_SuperFBBossAngryCount
|
# ³ðºÞ¹éÊôÒòΪÐèÒª¶ÓԱͬʱ¼Ó³ðºÞ£¬ËùÒÔ³ðºÞÊýÉèÖôóµã
|
if NPCCommon.GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_MaxAngry:
|
angryCount = ChConfig.Def_SuperBossAngryCount
|
|
curNPC.GetNPCAngry().Init(angryCount)
|
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 curNPC.IsAlive() != True:
|
#NPCËÀÍö, ½øÈëËÀÍöµ¹¼ÆÊ±
|
if npcControl.DieTick(tick) == 0:
|
return
|
|
#Ë¢ÐÂ×Ô¼ºµÄbuff
|
if curNPC.GetIsBoss():
|
npcControl.RefreshBuffState(tick)
|
if GameObj.GetHP(curNPC) == 0 :
|
# BUFFË¢ÐÂÖпÉÄܻᵼÖÂNPCËÀÍö
|
return
|
curNPCAction = curNPC.GetCurAction()
|
if curNPCAction == IPY_GameWorld.laNPCMove and curNPC.GetCurMoveType() == IPY_GameWorld.mtRun:
|
AICommon.NormalNPCFast_Move(curNPC, tick)
|
return
|
|
tagObj = __RefreshDropOwner(curNPC, tick)
|
|
if not curNPC.GetIsNeedProcess() or not tagObj:
|
# ÏÈ»ØÑª£¬µÈ»ØÂúÔÙ×öÆäËûÊÂÇé
|
if curNPCAction == IPY_GameWorld.laNPCNull and not npcControl.ProcessHPRestore(tick):
|
AICommon.NormalNPCFree_Move(curNPC, tick)
|
return
|
|
#¹¥»÷Âß¼
|
__NPCFight(curNPC, tagObj, tick)
|
|
npcControl.DoHPPerLogic(ChConfig.Def_NPCHurtTypeAll, 0)
|
return
|
|
def __RefreshDropOwner(curNPC, tick, refreshInterval=3000, isDead=False):
|
## Ë¢ÐÂbossµôÂä¹éÊô
|
# @return: ¿É¹¥»÷µÄµôÂä¹éÊôÄ¿±êÍæ¼Ò
|
|
npcControl = NPCCommon.NPCControl(curNPC)
|
tagObj = None # ¼´½«¹¥»÷µÄÄ¿±ê, ¹éÊô×î´óÉËѪȡ×î´óÉËÑªÍæ¼Ò»ò¶ÓÎé¶ÓÔ±£¬ÆäËûÈ¡×î´ó³ðºÞ
|
ownerType, ownerID = 0, 0
|
dropOwnerType = NPCCommon.GetDropOwnerType(curNPC)
|
if dropOwnerType == ChConfig.DropOwnerType_MaxHurt:
|
maxHurtObj = npcControl.RefreshHurtList(tick, refreshInterval)
|
if maxHurtObj:
|
ownerType, ownerID = maxHurtObj.GetValueType(), maxHurtObj.GetValueID()
|
if ownerType == ChConfig.Def_NPCHurtTypeTeam:
|
tagObj = __GetMaxHurtTeamPlayer(curNPC, npcControl, ownerID)
|
elif ownerType == ChConfig.Def_NPCHurtTypePlayer:
|
tagObj = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)
|
|
elif dropOwnerType == ChConfig.DropOwnerType_Family:
|
ownerInfo = FamilyRobBoss.RefreshFamilyOwnerNPCHurt(npcControl, curNPC, tick, refreshInterval)
|
if ownerInfo:
|
tagObj, ownerFamilyID = ownerInfo
|
ownerType, ownerID = ChConfig.Def_NPCHurtTypeFamily, ownerFamilyID
|
|
# ûÓй¥»÷Ä¿±ê£¬ÔòˢгðºÞ£¬Ö§³ÖÖ÷¶¯¹Ö
|
if not tagObj:
|
angryObjType, maxAngryObj = None, None
|
npcControl.RefreshAngryList(tick, refreshInterval, isUpdAngry=True)
|
maxAngry = npcControl.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:
|
teamID = maxAngryObj.GetTeamID()
|
if teamID:
|
ownerType, ownerID = ChConfig.Def_NPCHurtTypeTeam, teamID
|
else:
|
ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, maxAngryObj.GetPlayerID()
|
__RefreshBossDropOwnerObjBuff(curNPC, npcControl, tick, ownerType, ownerID, isDead)
|
return tagObj
|
|
def __GetMaxHurtTeamPlayer(curNPC, npcControl, teamID):
|
## »ñÈ¡×î´óÉËѪ¶ÓÎéÖй¥»÷µÄÄ¿±ê¶ÓÔ±
|
curTeam = GameWorld.GetTeamManager().FindTeam(teamID)
|
if curTeam:
|
refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
|
for i in xrange(curTeam.GetMemberCount()):
|
curTeamPlayer = curTeam.GetMember(i)
|
if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
|
continue
|
if curTeamPlayer.GetHP() <= 0:
|
continue
|
if npcControl.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint):
|
return curTeamPlayer
|
return
|
|
def __RefreshBossDropOwnerObjBuff(curNPC, npcControl, tick, ownerType=0, ownerID=0, isDead=False):
|
npcID = curNPC.GetNPCID()
|
dropOwnerType = NPCCommon.GetDropOwnerType(curNPC)
|
if dropOwnerType not in [ChConfig.DropOwnerType_MaxHurt, ChConfig.DropOwnerType_MaxAngry, ChConfig.DropOwnerType_Family]:
|
#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)
|
|
if lastDropOwnerID and (lastDropOwnerType != ownerType or lastDropOwnerID != ownerID):
|
GameWorld.DebugLog("¹éÊô±ä¸ü, Çå³ý¾É¹éÊô! ownerType=%s,ownerID=%s,lastDropOwnerType=%s,lastDropOwnerID=%s"
|
% (ownerType, ownerID, lastDropOwnerType, lastDropOwnerID))
|
__DelBossDropOwnerBuff(curNPC, 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 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
|
__AddBossDropOwnerPlayerBuff(curPlayer, tick, curNPC)
|
|
elif ownerType == ChConfig.Def_NPCHurtTypeTeam:
|
curTeam = GameWorld.GetTeamManager().FindTeam(ownerID)
|
if not curTeam:
|
return
|
|
# ÒòΪÓл÷ɱ´ÎÊýÏÞÖÆ£¬ËùÒÔ²»ÊÇËùÓеĶÓÔ±¶¼¿ÉÒÔ»ñµÃ¹éÊô£¬ËùÒÔÕâÀïÉèÖÃÎªÌØÊâÖ¸¶¨Íæ¼ÒµôÂä
|
hurtType, hurtID = ChConfig.Def_NPCHurtTypeSpecial, 0
|
|
refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
|
for i in xrange(curTeam.GetMemberCount()):
|
curTeamPlayer = curTeam.GetMember(i)
|
if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
|
continue
|
|
if curTeamPlayer.GetCopyMapID() == GameWorld.GetGameWorld().GetCopyMapID() \
|
and npcControl.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint) \
|
and AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False):
|
__AddBossDropOwnerPlayerBuff(curTeamPlayer, tick, curNPC)
|
killerDict[curTeamPlayer.GetPlayerID()] = curTeamPlayer
|
|
# ²»Í¬Ïß¡¢»òÕß¾àÀ볬³ö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()))
|
|
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 npcControl.GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint):
|
__AddBossDropOwnerPlayerBuff(player, tick, curNPC)
|
|
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 __AddBossDropOwnerPlayerBuff(curPlayer, tick, curNPC):
|
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 __DelBossDropOwnerBuff(curNPC, ownerType, ownerID, tick):
|
|
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)
|
|
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 __DelayBossDropOwnerBuff(curNPC):
|
''' ÑÓ³ÙbossµôÂä¹éÊôbuffÏûʧʱ¼ä '''
|
|
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
|
__SetBossDropOwnerBuffDisappearTime(curPlayer, curNPC)
|
|
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
|
__SetBossDropOwnerBuffDisappearTime(curTeamPlayer, curNPC)
|
elif ownerType == ChConfig.Def_NPCHurtTypeFamily:
|
copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()
|
for index in xrange(copyPlayerMgr.GetPlayerCount()):
|
player = copyPlayerMgr.GetPlayerByIndex(index)
|
if not player:
|
continue
|
__SetBossDropOwnerBuffDisappearTime(player, curNPC)
|
|
return
|
|
def __SetBossDropOwnerBuffDisappearTime(curPlayer, curNPC):
|
|
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
|
|
## ÿ´Î±»¹¥»÷´¦Àí½á¹û
|
# @param atkObj ¹¥»÷·¢ÆðÕß
|
# @param defObj ±»¹¥»÷Õß
|
# @param skill ¹¥»÷¼¼ÄÜ
|
# @param tick
|
# @return ¾ßÌåÉ˺¦Öµ
|
def OnAttacked(atkObj, curNPC, skill, tick):
|
if atkObj.GetGameObjType() == IPY_GameWorld.gotPlayer:
|
PlayerState.SetBossStateTick(atkObj, tick)
|
return
|
|
## NPC±»Íæ¼ÒɱËÀ
|
def OnAttackDieByPlayer(curNPC, curPlayer, skill):
|
tick = GameWorld.GetGameWorld().GetTick()
|
PlayerState.SetBossStateTick(curPlayer, tick)
|
|
#±»»÷É±Ê±Ç¿ÖÆË¢Ð¹éÊô
|
__RefreshDropOwner(curNPC, tick, 0, True)
|
return
|
|
## NPCËÀÍö´¦Àí
|
# @param curNPC ËÀÍöNPC
|
# @param HurtType µôÂäÀàÐÍ
|
# @param HurtID ¶ÔÓ¦ÓµÓÐÕßid
|
# @param modulus µôÂäϵÊý
|
# @return None
|
def OnDie(curNPC, HurtType, HurtID):
|
AICommon.DoNPCUseSkillOnDie(curNPC)
|
__DelayBossDropOwnerBuff(curNPC)
|
return
|
|
## npc¹¥»÷Âß¼
|
# @param curNPC µ±Ç°npc
|
# @param tagID curNPCAngryID
|
# @param tagType curNPCAngryType
|
# @param tick µ±Ç°Ê±¼ä
|
# @return None
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def __NPCFight(curNPC, curTag, tick):
|
#Ô¤¾¯´¦Àí
|
if AICommon.DoNPCSkillWarningProcess(curNPC, tick):
|
return
|
|
#ÉèÖýøÈëÕ½¶·×´Ì¬
|
NPCCommon.SetNPCInBattleState(curNPC)
|
|
npcControl = NPCCommon.NPCControl(curNPC)
|
|
#²»ÔÚÒÆ¶¯·¶Î§
|
if npcControl.IsInRefreshArea() != True:
|
#×·»÷·µ»Ø
|
npcControl.MoveBack()
|
return
|
|
#¿ªÊ¼¹¥»÷
|
if curTag == None or GameObj.GetHP(curTag) <= 0:
|
return
|
|
tagDist = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), curTag.GetPosX(), curTag.GetPosY())
|
|
#---ÓÅÏÈÊͷż¼ÄÜ---
|
if AICommon.DoAutoUseSkill(curNPC, curTag, tagDist, tick):
|
return
|
|
#---ÊÍ·ÅÆÕͨ¹¥»÷---
|
|
#³¬¹ý¹¥»÷¾àÀë,ÒÆ¶¯¹ýÈ¥
|
if tagDist > curNPC.GetAtkDist():
|
npcControl.MoveToObj_Detel(curTag)
|
return
|
|
if tick - curNPC.GetAttackTick() < curNPC.GetAtkInterval():
|
#¹¥»÷¼ä¸ôûÓе½, ·µ»Ø
|
return
|
|
if npcControl.FixTagPos(curTag.GetPosX(), curTag.GetPosY()):
|
#ÐÞÕýÕâ¸öNPCµÄÕ¾Á¢Î»ÖÃ
|
return
|
|
#ÆÕͨ¹¥»÷
|
BaseAttack.Attack(curNPC, curTag, None, tick)
|
return
|
|