ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_186.py
@@ -31,16 +31,10 @@
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
import ItemCommon
## 初始化
#  @param curNPC 当前npc
@@ -81,7 +75,8 @@
        AICommon.NormalNPCFast_Move(curNPC, tick)
        return
    
    tagObj = __RefreshDropOwner(curNPC, tick)
    #默认攻击归属者
    tagObj = npcControl.RefreshDropOwner(tick)
    
    if not curNPC.GetIsNeedProcess() or not tagObj:
        # 先回血,等回满再做其他事情
@@ -93,285 +88,6 @@
    __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 isDead:
        GameWorld.Log("Boss死亡: lineID=%s,objID=%s,npcID=%s,dropOwnerType=%s"
                      % (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), curNPC.GetNPCID(), dropOwnerType))
    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, isDead)
            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 isDead:
        GameWorld.Log("ownerType=%s, ownerID=%s, tagObjID=%s" % (ownerType, ownerID, 0 if not tagObj else tagObj.GetPlayerID()))
    # 没有攻击目标,则刷新仇恨,支持主动怪
    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()
        if isDead:
            GameWorld.Log("angryObj, ownerType=%s, ownerID=%s" % (ownerType, ownerID))
    __RefreshBossDropOwnerObjBuff(curNPC, npcControl, tick, ownerType, ownerID, isDead)
    return tagObj
def __GetMaxHurtTeamPlayer(curNPC, npcControl, teamID, isDead):
    ## 获取最大伤血队伍中攻击的目标队员
    curTeam = GameWorld.GetTeamManager().FindTeam(teamID)
    if curTeam:
        refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
        if isDead:
            GameWorld.Log("队伍成员数: teamID=%s,memberCount=%s" % (teamID, curTeam.GetMemberCount()))
        for i in xrange(curTeam.GetMemberCount()):
            curTeamPlayer = curTeam.GetMember(i)
            if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
                if isDead:
                    GameWorld.Log("    i=%s, 队员为空!" % i)
                continue
            if curTeamPlayer.GetHP() <= 0:
                if isDead:
                    GameWorld.Log("    i=%s, 队员血量为0!, memPlayerID=%s" % (i, curTeamPlayer.GetPlayerID()))
                continue
            if not curTeamPlayer.GetVisible():
                if isDead:
                    GameWorld.Log("    i=%s, 队员不可见!, memPlayerID=%s" % (i, curTeamPlayer.GetPlayerID()))
                continue
            if isDead:
                GameWorld.Log("    i=%s, 队员坐标(%s, %s)! memPlayerID=%s" % (i, curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), curTeamPlayer.GetPlayerID()))
            if npcControl.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint):
                return curTeamPlayer
    else:
        GameWorld.ErrLog("找不到该队伍: teamID=%s" % teamID)
    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)
    key = (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), npcID)
    if lastDropOwnerID and (lastDropOwnerType != ownerType or lastDropOwnerID != ownerID):
        GameWorld.Log("归属变更, 清除旧归属! key=%s,ownerType=%s,ownerID=%s,lastDropOwnerType=%s,lastDropOwnerID=%s"
                      % (key, 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 isDead:
        GameWorld.Log("Boss归属: key=%s,ownerType=%s,ownerID=%s" % (key, ownerType, ownerID))
    # 刷新归属
    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
        if isDead:
            GameWorld.Log("队伍成员数: %s" % (curTeam.GetMemberCount()))
        refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
        for i in xrange(curTeam.GetMemberCount()):
            curTeamPlayer = curTeam.GetMember(i)
            if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
                if isDead:
                    GameWorld.Log("    i=%s, 成员不存在!" % (i))
                continue
            if curTeamPlayer.GetCopyMapID() == GameWorld.GetGameWorld().GetCopyMapID() \
                and npcControl.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint) \
                and AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False) and curTeamPlayer.GetVisible():
                __AddBossDropOwnerPlayerBuff(curTeamPlayer, tick, curNPC)
                killerDict[curTeamPlayer.GetPlayerID()] = curTeamPlayer
                if isDead:
                    GameWorld.Log("    i=%s, 成员有归属权! memPlayerID=%s,背包剩余空格=%s"
                                  % (i, curTeamPlayer.GetPlayerID(), ItemCommon.GetItemPackSpace(curTeamPlayer, IPY_GameWorld.rptItem)))
            # 不同线、或者距离超出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()))
                if isDead:
                    GameWorld.Log("    i=%s, 成员无归属权! memPlayerID=%s,copyMapID=%s,pos(%s,%s),CheckKillNPCByCnt=%s"
                                  % (i, curTeamPlayer.GetPlayerID(), curTeamPlayer.GetCopyMapID(),
                                     curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(),
                                     AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False)))
    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) and player.GetVisible():
                __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
## 每次被攻击处理结果
@@ -390,7 +106,8 @@
    dropOwnerType = NPCCommon.GetDropOwnerType(curNPC)
    if dropOwnerType not in [ChConfig.DropOwnerType_MaxHurt]:
        return True
    tagObj = __RefreshDropOwner(curNPC, tick, 0)
    npcControl = NPCCommon.NPCControl(curNPC)
    tagObj = npcControl.RefreshDropOwner(tick, 0)
    if not atkObj or not tagObj:
        GameObj.SetHP(curNPC, 1)
        GameWorld.ErrLog("Boss当前状态下不可以死亡!npcID=%s" % curNPC.GetNPCID())
@@ -403,7 +120,8 @@
    PlayerState.SetBossStateTick(curPlayer, tick)
    
    #被击杀时强制刷新归属
    __RefreshDropOwner(curNPC, tick, 0, True)
    npcControl = NPCCommon.NPCControl(curNPC)
    npcControl.RefreshDropOwner(tick, 0, True)
    return
## NPC死亡处理
@@ -417,7 +135,8 @@
    return
def OnNPCSetDead(curNPC):
    __DelayBossDropOwnerBuff(curNPC)
    npcControl = NPCCommon.NPCControl(curNPC)
    npcControl.DelayDropOwnerBuffDisappearTime()
    return
## npc攻击逻辑