#!/usr/bin/python
|
# -*- coding: GBK -*-
|
#---------------------------------------------------------------------
|
#
|
#---------------------------------------------------------------------
|
##@package FBDefenseCommon
|
# @todo: ÊØ»¤Å®ÉñËùÓйÖÎïAIµÄ¹«¹²Êý¾ÝºÍº¯Êý
|
#
|
# @author adaws
|
# @date 2009-11-17 19:00
|
# @version 2.2
|
#
|
# @note:
|
#
|
# @change: "2010-11-18 11:00" adaws ¼ÓNPC´æ»îʱ¼äÈ¡½Ó¿Ú½è ²»ÊÇÿ¸öNPC¶¼ÓÐ
|
# @change: "2010-11-18 18:00" adaws AIѰ·ÐÞ¸Ä ÔÚ¹¥»÷ÖеĶàÓàRefreshAllStateÈ¥µô
|
# @change: "2010-11-19 12:00" adaws ÓÐÄ¿±êµÄ·Å¼¼ÄÜÔö¼Ó »Øµ÷ÐÞ¸Ä
|
# @change: "2010-11-20 17:40" adaws AI×ß·ÐÞ¸Ä NormalCheck¼ì²é¼ÓÈëÊÇ·ñÔÚ¿ìËÙÒÆ¶¯Ïà¹Ø ¿ìËÙÒÆ¶¯µ«ÊDz»»ØË¢ÐµãÐÞ¸Ä
|
# @change: "2010-11-22 12:15" Alee NPC¿ØÖÆÐÞ¸Ä
|
# @change: "2010-11-22 17:30" adaws NPC·Å¼¼ÄܵÄʱºò¸ù¾Ý¼¼ÄܵÄÄ¿±êÊÇ·ñÊǶÔ×Ô¼º·ÅµÄÑ¡²»Í¬µÄÄ¿±ê
|
# @change: "2010-11-26 10:00" adaws ɾ³ýÉÏÒ»´ÎµÄÍ·¶¥BUFF ÑéÖ¤ È¥µôÕ½¶·»ØÑª ¼ÓBUFF²»Ë¢×´Ì¬
|
# @change: "2010-12-16 20:50" Alee Ð޸ĺ¯ÊýÃû
|
# @change: "2010-12-31 17:43" Alee ÐÞ¸ÄBUFF¹ÜÀíÆ÷ÑéÖ¤
|
# @change: "2011-06-15 11:40" chenxuewei Ôö¼ÓÊØ»¤Å®Éñ¶¯Ì¬°æµÄbossµÄkey
|
#
|
# @change: "2011-06-16 16:40" chenxuewei AIÔö¼ÓÒì×åÎ×Ò½µÄÌØÊâ¼¼ÄÜÊÍ·Å
|
# @change: "2015-03-30 12:00" hxp ÐÞ¸ÄΪ֧³ÖͨÓÃTDË¢¹ÖÐÐ×ß·Ïß
|
#
|
#---------------------------------------------------------------------
|
"""Version = 2015-03-30 12:00"""
|
#---------------------------------------------------------------------
|
import SkillShell
|
import GameWorld
|
import NPCCommon
|
import IPY_GameWorld
|
import OperControlManager
|
import BaseAttack
|
import ChConfig
|
import ReadChConfig
|
import AICommon
|
import GameObj
|
|
import random
|
|
#---ÏÂÃæ¶¼ÊÇNPCµÄ×ÖµäKEY---
|
NPCKey_PassedPointCount = 'PassedCount' # NPC×ß¹ýµÄµãµÄ¸öÊý ²Èµã×ß·¨
|
NPCKey_CurLvUp_Step = 'LvUpStep' # µ±Ç°Í·¶¥BUFFµÄµÚ¼¸¸ö Í·¶¥BUFFµÈ¼¶
|
NPCKey_UseSkillHpPercent = 'UseSkillPercent' # ʹÓü¼ÄÜÉúÃü°Ù·Ö±È·§Öµ
|
SingleMoveArea = 5 # NPCµ¥´ÎÒÆ¶¯¾àÀë
|
Dis_Differ = 3 # ÔÚÑ¡µãÒÆ¶¯µÄʱºò Ñ¡µãµÄ·¶Î§ ±ÜÃâÖØµþ
|
#MovePointList = [(53, 125), (73, 125), (93, 125), (113, 125), (133, 125), (146,125)]
|
#MovePointList = ReadChConfig.GetEvalChConfig('TDMovePointList')
|
Def_MaxDis = 999999
|
|
|
## ¸±±¾ÖеÄNPCµÄÒÆ¶¯Âß¼ ²ÈµãÒÆ¶¯
|
# @param curNpc: µ±Ç°NPC
|
# @param movePointList: ²ÈµãÁÐ±í£¨×ø±êX£¬×ø±êY£¬¾àÀëÄ¿±êµãµÄÒÆ¶¯¾àÀ룩
|
# @param tick: µ±Ç°tick
|
# @return: ÎÞ
|
# @remarks: ¸±±¾ÖÐNPC²ÈµãÒÆ¶¯
|
def NpcMoveByMovePointList(curNPC, movePointList, tick):
|
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)
|
|
curPassedPointCount = curNPC.GetDictByKey(NPCKey_PassedPointCount)
|
needMoveToPointIndex = min(curPassedPointCount, len(movePointList) - 1)
|
|
#µ±Ç°×ø±ê Ä¿
|
curPosX, curPosY = curNPC.GetPosX(), curNPC.GetPosY()
|
destPosX, destPosY = movePointList[needMoveToPointIndex]
|
curDis = GameWorld.GetDist(curPosX, curPosY, destPosX, destPosY)
|
|
#Èç¹ûÀëÄ¿±êµã±È½Ï½üµÄ»° È¡ÏÂÒ»¸öÄ¿±êµã
|
if curDis <= Dis_Differ*2:
|
nextIndex = min(needMoveToPointIndex + 1, len(movePointList) - 1)
|
#Èç¹û»¹²»ÊÇ×îºóÒ»¸öÄ¿±êµã ÔòÈ¡ÏÂÒ»¸öÄ¿±êµãÐèÒªÒÆµÄλÖÃ
|
if nextIndex != needMoveToPointIndex:
|
curNPC.SetDict(NPCKey_PassedPointCount, needMoveToPointIndex + 1)
|
destPosX, destPosY = movePointList[nextIndex]
|
curDis = GameWorld.GetDist(curPosX, curPosY, destPosX, destPosY)
|
|
#---Èç¹ûÀëÄ¿±êµã±È½Ï½ü»òÕß ÒѾȥ¹ýÄ¿±êµãÔòѡĿ±êµãÖÜΧµÄÒ»µã×ß
|
moveDestX, moveDestY = npcControl.GetMoveNearPos(destPosX, destPosY, 1)
|
npcControl.MoveToPosStepByStep(moveDestX, moveDestY, SingleMoveArea)
|
|
|
|
## Å®Éñ¸±±¾ÖеÄNPCÒÆ¶¯
|
# @param curNpc: µ±Ç°NPC
|
# @param tick: µ±Ç°tick
|
# @return: ÎÞ
|
# @remarks: Å®Éñ¸±±¾ÖÐNPC²ÈµãÒÆ¶¯ µ÷¸±±¾²ÈµãÒÆ¶¯º¯Êý ¸ø¶¨²ÈµãÁбí
|
def FBDefenceMove(curNPC, tick):
|
#GameWorld.DebugLog("FBDefenceMove isboss=%s" % curNPC.GetIsBoss())
|
fromRefreshValue = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_FromRefreshValue)
|
fromRefreshMark = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_FromRefreshMark)
|
|
MovePointList = ReadChConfig.GetEvalChConfig('TDMovePointList')
|
if fromRefreshValue > 0:
|
movePointDict = ReadChConfig.GetEvalChConfig('TD_%s_Move' % fromRefreshValue)
|
if fromRefreshMark in movePointDict:
|
MovePointList = movePointDict[fromRefreshMark]
|
|
#NpcMoveByMovePointList(curNPC, MovePointList, tick)
|
AICommon.NPCMoveByPointList(curNPC, MovePointList)
|
return
|
|
## Å®Éñ¸±±¾µÄÆÕͨ¼ì²é
|
# @param curNPC: µ±Ç°NPC
|
# @param tick: µ±Ç°Tick
|
# @return: ÊÇ·ñ¿ÉÒÔ¹¥»÷»òÖ´ÐÐÆäËüµÄ¶¯×÷
|
# @remarks: ¼ì²éNPCËÀÍö ÊÇ·ñÓÐÒ쳣״̬²»Äܶ¯µÄ ÊÇ·ñÐèÒªËÀÍöµÈ
|
def NormalCheck(curNPC, tick):
|
if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():
|
#NPCËÀÍö, ½øÈëËÀÍöµ¹¼ÆÊ±
|
return False
|
|
npcControl = NPCCommon.NPCControl(curNPC)
|
npcControl.RefreshBuffState(tick)
|
if GameObj.GetHP(curNPC) == 0 :
|
# BUFFË¢ÐÂÖпÉÄܻᵼÖÂNPCËÀÍö
|
return
|
|
npcLastTime = 0
|
npcObjType = curNPC.GetGameNPCObjType()
|
if npcObjType == IPY_GameWorld.gnotSummon:
|
npcLastTime = curNPC.GetLastTime()
|
|
#ÕÙ»½ÊÞ³¬¹ý´æ»îʱ¼ä, ÉèÖÃËÀÍö
|
if npcLastTime != 0 and tick - curNPC.GetBornTime() >= npcLastTime:
|
npcControl.SetKilled()
|
return False
|
|
#ÅжÏÒ쳣״̬
|
# if curNPC.GetAbnormalState() == IPY_GameWorld.sctFaint:
|
# return False
|
|
curNPCAction = curNPC.GetCurAction()
|
#NPC¿ìËÙ±¼ÅÜÖÐ, ²»´¦Àí
|
if curNPCAction == IPY_GameWorld.laNPCMove and curNPC.GetCurMoveType() == IPY_GameWorld.mtRun:
|
FastMoveNotMoveBack(curNPC, tick)
|
return False
|
|
return True
|
|
|
##¿ìËÙÒÆ¶¯µ«ÊDz»»ØË¢Ðµã
|
# @param curNPC: µ±Ç°NPC
|
# @param tick: µ±Ç°Tick
|
# @return: ÎÞ
|
# @remarks: NPC¿ìËÙÒÆ¶¯ µ«ÊDz»»ØË¢Ðµã
|
def FastMoveNotMoveBack(curNPC, tick):
|
npcControl = NPCCommon.NPCControl(curNPC)
|
if curNPC.GetPlayerHurtList().GetHurtCount() == 0:
|
npcControl.ProcessHPRestore(tick)
|
else:
|
npcControl.ProcessBattleHPRestore(tick)
|
return
|
|
## Å®Éñ¸±±¾µÄAIͨÓù¥»÷
|
# @param curNPC: µ±Ç°NPC
|
# @param tick: µ±Ç°Tick
|
# @param canMove: NPCÊÇ·ñ¿ÉÒÔÒÆ¶¯
|
# @param callbackList: ·Å¼¼Äܵļì²é»Øµ÷
|
# @param isWuYi: µ±Ç°NPCÊÇ·ñÊÇÒì×åÎ×Ò½£¬Ä¬Èϲ»ÊÇ
|
# @return: ÎÞ
|
# @remarks: Å®Éñ¸±±¾µÄAIͨÓù¥»÷ °üÀ¨·Å¼¼ÄÜ Èç¹ûʲô¼¼ÄÜÒ²²»·Å²»¸ø¼ì²é»Øµ÷¼´¿É Èç¹û²»·ÅµÚ¼¸¸ö¼¼ÄÜÐèҪдһ¸ö»Øµ÷ÓÀ²»µ÷ÓÃ
|
def NormalFight(curNPC, tick, canMove=True, refreshInterval=ChConfig.Def_NPCRefreshAngryValueInterval, isUpdAngry=False):
|
npcControl = NPCCommon.NPCControl(curNPC)
|
|
#Ë¢ÐÂ×Ô¼º³ðºÞ¶ÈÁбí
|
if not isUpdAngry:
|
angryObj = None
|
curNPCAngry = npcControl.GetMaxAngryTag()
|
if curNPCAngry:
|
angryObj = GameWorld.GetObj(curNPCAngry.GetObjID(), curNPCAngry.GetObjType())
|
if not angryObj or (angryObj and GameObj.GetHP(angryObj) <= 0):
|
npcControl.RefreshAngryList(tick, refreshInterval, isUpdAngry)
|
curNPCAngry = npcControl.GetMaxAngryTag()
|
else:
|
npcControl.RefreshAngryList(tick, refreshInterval, isUpdAngry)
|
curNPCAngry = npcControl.GetMaxAngryTag()
|
|
#³ðºÞ¶ÈÁбíÖеÄÈËΪ¿Õ
|
if curNPCAngry == None:
|
if not canMove:
|
return
|
FBDefenceMove(curNPC, tick)
|
return
|
|
#³ðºÞ¶ÔÏóÀàÐÍ,³ðºÞ¶ÔÏóID
|
curNPCAngryType = curNPCAngry.GetObjType()
|
curNPCAngryID = curNPCAngry.GetObjID()
|
#Õ½¶·ÖлØÑª
|
# npcControl.ProcessBattleHPRestore(tick)
|
|
#Ö´Ðй¥»÷Âß¼
|
__NPCFight(curNPC, curNPCAngryID, curNPCAngryType, tick, canMove)
|
return
|
|
|
## npc¹¥»÷Âß¼ ¸ù¾ÝNPCÊÇ·ñ¿ÉÒÔÒÆ¶¯ ¼¼Äܼì²é»Øµ÷Áбí·Å¼¼ÄÜ
|
# @param curNPC µ±Ç°npc
|
# @param tagID curNPCAngryID
|
# @param tagType curNPCAngryType
|
# @param tick µ±Ç°Ê±¼ä
|
# @param canMove£º NPCÊÇ·ñÒªÒÔÒÆ¶¯
|
# @param callbackList£º ·Å¼¼Äܵļì²é»Øµ÷Áбí
|
# @param isWuYi: µ±Ç°NPCÊÇ·ñÊÇÒì×åÎ×Ò½£¬Ä¬Èϲ»ÊÇ
|
# @return None
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def __NPCFight(curNPC, tagID, tagType, tick, canMove):
|
#ÉèÖýøÈëÕ½¶·×´Ì¬
|
NPCCommon.SetNPCInBattleState(curNPC)
|
npcControl = NPCCommon.NPCControl(curNPC)
|
|
#¿ªÊ¼¹¥»÷
|
curTag = GameWorld.GetObj(tagID, tagType)
|
|
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():
|
if not canMove:
|
return
|
|
npcControl.MoveToObj_Detel(curTag)
|
return
|
|
#¹¥»÷¼ä¸ôûÓе½, ·µ»Ø
|
if tick - curNPC.GetAttackTick() < curNPC.GetAtkInterval():
|
return
|
|
#ÐÞÕýÕâ¸öNPCµÄÕ¾Á¢Î»Öà Èç¹û¿ÉÒÔ¶¯µÄ»°
|
if canMove:
|
if npcControl.FixTagPos(curTag.GetPosX(), curTag.GetPosY()):
|
return
|
|
#if SeriesSkillByCallBackList(curNPC, curTag, tick, callbackList):
|
# return
|
|
#ÆÕͨ¹¥»÷
|
BaseAttack.Attack(curNPC, curTag, None, tick)
|
return
|
|
## ¸ù¾Ýindex ·ÅNPCÖеĵÚindex¸ö¼¼ÄÜ
|
# @param curNPC£º µ±Ç°NPC
|
# @param index£º ·ÅµÚ¼¸¸ö¼¼ÄÜ
|
# @return ÎÞ
|
# @remarks º¯ÊýÏêϸ˵Ã÷.¸ù¾Ýindex ·ÅNPCÖеĵÚindex¸ö¼¼ÄÜ
|
def UseSkillByIndex(curNPC, index):
|
if index < 0:
|
return
|
|
skillManager = curNPC.GetSkillManager()
|
if skillManager.GetSkillCount() <= index:
|
return
|
|
curSkill = skillManager.GetSkillByIndex(index)
|
if not curSkill:
|
return
|
|
tick = GameWorld.GetGameWorld().GetTick()
|
SkillShell.NPCUseSkill(curNPC, curSkill, tick)
|
|
|
## ËÀÍöµÄʱºò·Å¼¼ÄÜ ÒòΪNPCËÀÁËËùÒÔÐèÒªÏÈÉèHP 1 ÈÆ¹ý¼ì²é È»ºóÔÙÉè³É0
|
# @param curNPC: µ±Ç°NPC
|
# @param index: Òª·ÅµÄ¼¼ÄÜindex
|
# @return: ÎÞ
|
# @remarks: ËÀÍöµÄʱºò·Å¼¼ÄÜ ÒòΪNPCËÀÁËËùÒÔÐèÒªÏÈÉèHP 1 ÈÆ¹ý¼ì²é È»ºóÔÙÉè³É0
|
def DeadUseSkillByIndex(curNPC, index):
|
GameObj.SetHP(curNPC, 1)
|
UseSkillByIndex(curNPC, index)
|
GameObj.SetHP(curNPC, 0)
|
|
|
## »Øµ÷¼ì²é NPC ÊÇ·ñµ½ÁËNPC×ÖµäÖеÄÏàӦѪÁ¿°Ù·Ö±È
|
# @param curNPC: µ±Ç°NPC
|
# @return: ÊÇ·ñµ½ÁËNPC×ÖµäÖеÄÏàӦѪÁ¿°Ù·Ö±È£¨NPC ѪÁ¿µ½·§ÖµÊ±ºò ÐèÒª·Å¼¼Äܵġ££©
|
# @remarks: »Øµ÷¼ì²é ÊÇ·ñµ½ÁËNPC×ÖµäÖеÄÏàӦѪÁ¿°Ù·Ö±È
|
def CallbackCheckHpPercent(curNPC):
|
curHp = GameObj.GetHP(curNPC)
|
maxHp = GameObj.GetMaxHP(curNPC)
|
npcUseSkillHpPercent = curNPC.GetDictByKey(NPCKey_UseSkillHpPercent)
|
realPercent = float(npcUseSkillHpPercent)/ChConfig.Def_MaxRateValue
|
|
#ѪÁ¿²»¹»°Ù·Ö±ÈÐèÒª·Å¼¼ÄÜ
|
if curHp < maxHp*realPercent:
|
return True
|
else:
|
return False
|
|
## ¸ù¾Ý¼ì²é»Øµ÷ ÊͷŶÔÓ¦NPCµÄ¼¼ÄÜ Èç¹û²»³É¹¦·µ»ØFalse
|
# @param curNPC: µ±Ç°NPC
|
# @param skillIndex: Òª·ÅµÄ¼¼ÄÜindex
|
# @param tick: µ±Ç°Tick
|
# @param skillIndex: ¼ì²é»Øµ÷
|
# @return: ·Å¼¼ÄÜÊÇ·ñÊͷųɹ¦
|
# @remarks: ¸ù¾Ý¼ì²é»Øµ÷ ÊͷŶÔÓ¦NPCµÄ¼¼ÄÜ Èç¹û²»³É¹¦·µ»ØFalse
|
def SkillCheckCallback(curNPC, curTag, skillIndex, tick, callback=None):
|
#---¹¥»÷¼ä¸ô²»µ½ »òÕ߻ص÷ûÓв»´¦Àí---
|
if tick - curNPC.GetAttackTick() < curNPC.GetAtkInterval():
|
return False
|
|
skillManager = curNPC.GetSkillManager()
|
skillTotalCount = skillManager.GetSkillCount()
|
if skillTotalCount <= skillIndex:
|
return False
|
|
#Èç¹ûÊǸºµÄÔò´Ó×îºóÒ»¸ö¼¼ÄÜÍùǰÊý ×îСΪ0¼´µÚÒ»¸ö
|
if skillIndex < 0:
|
skillIndex = min(0, skillTotalCount + skillIndex)
|
|
curSkill = skillManager.GetSkillByIndex(skillIndex)
|
|
if not curSkill:
|
return False
|
|
#CDδµ½²»´¦Àí curSkill.GetCoolDownTime()
|
if tick - curSkill.GetLastUseTick() < curSkill.GetCoolDownTime():
|
return False
|
|
#¼ì²é»Øµ÷²»Í¨¹ý
|
if callback != None and not callback(curNPC):
|
return False
|
|
#¶Ô×ÔÒѷŵļ¼ÄÜ
|
if SkillShell.GetSkillAffectTag(curSkill) in ChConfig.Def_ST_CanNPCUseSkill:
|
curTag = curNPC
|
|
#ÉÏÃæµÄÌõ¼þ¶¼Âú×ã·Å¼¼ÄÜ
|
SkillShell.DoLogic_UseSkill(curNPC, curTag, curSkill, tick)
|
return True
|
|
|
## ¸ù¾Ý¼ì²é»Øµ÷Áбí ÊͷŶÔÓ¦NPCµÄ¼¼ÄÜ »Øµ÷ÁбíÓÃÓÚÅж¨µ±Öеļ¼ÄÜÊÇ·ñÄÜ·Å
|
# @param curNPC: µ±Ç°NPC
|
# @param tick: µ±Ç°Tick
|
# @param callbackList: ¼ì²é»Øµ÷Áбí
|
# @return: ·Å¼¼ÄÜÊÇ·ñÊͷųɹ¦
|
# @remarks: ¸ù¾Ý¼ì²é»Øµ÷Áбí ÊͷŶÔÓ¦NPCµÄ¼¼ÄÜ »Øµ÷ÁбíÓÃÓÚÅж¨µ±Öеļ¼ÄÜÊÇ·ñÄÜ·Å »Øµ÷¼ì²éº¯Êý¿ÉÒÔÊÇ×Ô¼ºµÄPYµÄ
|
def SeriesSkillByCallBackList(curNPC, curTag, tick, callbackList):
|
if callbackList == []:
|
return False
|
|
skillManager = curNPC.GetSkillManager()
|
|
#---×î¶à¿ÉÒÔ·ÅNPC¼¼ÄܹÜÀíÆ÷ÖÐÓеļ¼ÄÜ---
|
skillTotalCount = skillManager.GetSkillCount()
|
callBackList = callbackList[:skillTotalCount]
|
|
for index, curCallback in enumerate(callBackList):
|
if SkillCheckCallback(curNPC, curTag, index, tick, curCallback):
|
return True
|
|
return False
|
|
|
|