hch
2 天以前 3bc2e9aae7e595d5be896a9db4c909b76fa6f5be
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -35,12 +35,14 @@
import ItemControler
import SkillCommon
import SkillShell
import BaseAttack
import AttackCommon
import FBLogic
import random
import time
import json
FighterNPCID = 100 # 战斗NPCID,仅后端用,除怪物外,所有玩家武将均使用该NPCID
PosNumMax = 10 # 最大站位编号
ActionNumStart = -1 # 起始行动位置编号,一般是从1开始,如果有加主公、红颜等则扣除相应位置值,如从0或-1开始
@@ -235,6 +237,9 @@
        
        self.startTime = 0 # 开始时间戳,支持毫秒小数
        self.costTime = 0 # 单场战斗总耗时,支持毫秒小数
        #玩家武将行动后击杀目标
        self.playerKillObjIDList = [] # [objID, ...]
        return
    
    def setTurn(self, mapID, funcLineID, turnMax, isNeedReport=False, msgDict={}):
@@ -374,6 +379,8 @@
                    tfObj = ChPyNetSendPack.tagSCTurnFightObj()
                    tfObj.ObjID = curNPC.GetID()
                    tfObj.NPCID = curNPC.GetNPCID()
                    tfObj.HeroID = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_HeroID)
                    tfObj.SkinID = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_SkinID)
                    tfObj.HP = curNPC.GetHP()
                    tfObj.HPEx = curNPC.GetHPEx()
                    tfObj.MaxHP = curNPC.GetMaxHP()
@@ -571,18 +578,24 @@
        heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
        if not heroIpyData:
            continue
        npcID = heroIpyData.GetSkinNPCIDList()[0]
        skinIDList = heroIpyData.GetSkinIDList()
        skinIndex = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroSkin)
        if skinIndex < 0 or skinIndex >= len(skinIDList):
            continue
        skinID = skinIDList[skinIndex]
        heroDict[str(posNum)] = {
                                 "ID":heroID,
                                 "HeroID":heroID,
                                 "SkinID":skinID,
                                 "Data":heroItem.GetUserData(),
                                 "NPCID":npcID
                                 }
        
        heroCount += 1
        if heroCount >= ShareDefine.LineupObjMax:
            break
        
    if not heroDict:
        return {}
    # 主公属性
    lordAttrDict = PlayerControl.GetLordAttr(curPlayer)
    
@@ -653,27 +666,33 @@
    tick = GameWorld.GetGameWorld().GetTick()
    
    initXP = IpyGameDataPY.GetFuncCfg("AngerXP", 1)
    baseAtkSkillIDList = IpyGameDataPY.GetFuncEvalCfg("ParryCfg", 3)
    tfMgr = GetTurnFightMgr()
    space = 3
    for posNumKey, heroInfo in heroDict.items():
        posNum = int(posNumKey)
        
        heroID, skinID = 0, 0
        baseAtkSkillID = 0 # 基础普攻ID
        skillIDList = []
        if lineupPlayerID:
            heroID = heroInfo.get("ID", 0)
            npcID = heroInfo.get("NPCID", 0)
            heroID = heroInfo.get("HeroID", 0)
            skinID = heroInfo.get("SkinID", 0)
            npcID = FighterNPCID
            heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
            if not heroIpyData:
                continue
            normalSkillID = heroIpyData.GetNormalSkillID()
            angerSkillID = heroIpyData.GetAngerSkillID()
            skillIDList += [normalSkillID, angerSkillID]
            atkDistType = heroIpyData.GetAtkDistType()
        else:
            npcID = heroInfo.get("NPCID", 0)
            npcDataEx = NPCCommon.GetNPCDataEx(npcID)
            if not npcDataEx:
                continue
            skillIDList += npcDataEx.GetSkillIDList()
            atkDistType = npcDataEx.GetAtkDistType()
            
        if not npcID:
            continue
@@ -698,19 +717,28 @@
        curSummon.SetVisible(True)
        curSummon.SetDict(ChConfig.Def_Obj_Dict_TurnFightPosInfo, num * 100 + posNum)
        curSummon.SetDict(ChConfig.Def_Obj_Dict_LineupPlayerID, lineupPlayerID)
        curSummon.SetDict(ChConfig.Def_Obj_Dict_HeroID, heroID)
        curSummon.SetDict(ChConfig.Def_Obj_Dict_SkinID, skinID)
        GameObj.SetFaction(curSummon, faction)
        GameObj.SetXP(curSummon, initXP, False)
        
        if atkDistType == ChConfig.AtkDistType_Short:
            baseAtkSkillID = baseAtkSkillIDList[0] if len(baseAtkSkillIDList) > 0 else 0
        elif atkDistType == ChConfig.AtkDistType_Long:
            baseAtkSkillID = baseAtkSkillIDList[1] if len(baseAtkSkillIDList) > 1 else 0
        skillManager = curSummon.GetSkillManager()
        #有指定的技能,重新学习
        if skillIDList:
            skillManager.ResetSkill()
            for skillID in skillIDList:
                skillManager.LVUPSkillByID(skillID)
        if baseAtkSkillID:
            skillManager.LVUPSkillByID(baseAtkSkillID)
        rebornX = posX - space + (faction - 1) * space * 3 + ((posNum - 1) / 3 * space * 2 * (-1 if faction == 1 else 1))
        rebornY = posY + (posNum - 1) % 3 * space
        #GameWorld.DebugLog("Reborn ID:%s, faction:%s,posNum=%s, (%s,%s), %s" % (curSummon.GetID(), faction, posNum, rebornX, rebornY, skillIDList))
        GameWorld.DebugLog("SummonNPC ID:%s,faction:%s,num=%s,posNum=%s,baseAtkSkillID=%s,%s" % (curSummon.GetID(), faction, num, posNum, baseAtkSkillID, skillIDList))
        curSummon.Reborn(rebornX, rebornY, False)
        NPCCommon.NPCControl(curSummon).DoNPCRebornCommLogic(tick)
        
@@ -783,12 +811,9 @@
    # @param isRestStart: 是否从休息状态重新开始的
    playerID = curPlayer.GetPlayerID()
    chapterID, levelNum, wave = PlayerControl.GetMainLevelNowInfo(curPlayer)
    if not chapterID:
        chapterID = 1
    if not levelNum:
        levelNum =1
    if not wave:
        wave = 1
    if not chapterID and not levelNum:
        PlayerControl.SetMainLevelNowInfo(curPlayer, 1, 1, 1)
        chapterID, levelNum, wave = PlayerControl.GetMainLevelNowInfo(curPlayer)
    GameWorld.DebugLog("请求关卡波战斗: chapterID=%s,levelNum=%s,wave=%s,isRestStart=%s" % (chapterID, levelNum, wave, isRestStart), playerID)
    fightPoint = max(curPlayer.GetFightPoint(), 1)
    if not PlayerControl.HaveMoney(curPlayer, ShareDefine.TYPE_Price_Xiantao, fightPoint):
@@ -824,6 +849,11 @@
    teamNum = 1
    lineupID = waveLineupList[teamNum - 1] # NPC阵容ID
    
    lineupMainInfo = GetPlayerLineup(curPlayer, ShareDefine.Lineup_Main)
    if not lineupMainInfo:
        GameWorld.DebugLog("没有设置主阵容!", playerID)
        return
    mainFightMgr = GetMainFightMgr(curPlayer)
    mainFightMgr.nextTeam = False
    mainFightMgr.chapterID = chapterID
@@ -840,7 +870,7 @@
    
    turnFight = mainFightMgr.turnFight
    turnFight.setTurn(mapID, funcLineID, turnMax, False, {"teamNum":teamNum, "teamMax":teamMax})
    turnFight.setFactionLineup(Def_FactionA, {1:GetPlayerLineup(curPlayer, ShareDefine.Lineup_Main)}, True)
    turnFight.setFactionLineup(Def_FactionA, {1:lineupMainInfo}, True)
    turnFight.setFactionLineup(Def_FactionB, {1:GetNPCLineup(lineupID)})
    turnFight.sortActionQueue()
    turnFight.syncInit()
@@ -893,6 +923,11 @@
    
    wave = waveMax = 1 # 关卡boss固定只有一波
    
    lineupMainInfo = GetPlayerLineup(curPlayer, ShareDefine.Lineup_Main)
    if not lineupMainInfo:
        GameWorld.DebugLog("没有设置主阵容!", playerID)
        return
    mainFightMgr = GetMainFightMgr(curPlayer)
    mainFightMgr.nextTeam = False
    mainFightMgr.chapterID = chapterID
@@ -909,7 +944,7 @@
    
    turnFight = mainFightMgr.turnFight
    turnFight.setTurn(mapID, funcLineID, turnMax, False, {"teamNum":teamNum, "teamMax":teamMax})
    turnFight.setFactionLineup(Def_FactionA, {1:GetPlayerLineup(curPlayer, ShareDefine.Lineup_Main)}, True)
    turnFight.setFactionLineup(Def_FactionA, {1:lineupMainInfo}, True)
    turnFight.setFactionLineup(Def_FactionB, {1:GetNPCLineup(lineupID)})
    turnFight.sortActionQueue()
    turnFight.syncInit()
@@ -931,7 +966,6 @@
            teamNum = mainFightMgr.teamNum = mainFightMgr.teamNum + 1
            GameWorld.DebugLog("开始进入下一小队: teamNum=%s" % teamNum)
            if teamNum < 1 or teamNum > len(mainFightMgr.waveLineupList):
                GameWorld.DebugLog("111111 teamNum=%s,mainFightMgr.waveLineupList=%s" % (teamNum, mainFightMgr.waveLineupList))
                return
            lineupID = mainFightMgr.waveLineupList[teamNum - 1] # NPC阵容ID
            GameWorld.DebugLog("teamNum=%s,lineupID=%s" % (teamNum, lineupID))
@@ -968,8 +1002,7 @@
    overLineupList = [] # 本回合已经结束行动的阵容列表 [(faction, num), ...], 所有阵容全部结束代表本回合结束
    
    turnNum = turnFight.turnNum
    unXiantaoCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCnt)
    GameWorld.DebugLog("unXiantaoCnt=%s,turnNum=%s,doMax=%s,actionIndex=%s,%s" % (unXiantaoCnt, turnNum, doMax, turnFight.actionIndex, turnFight.actionSortList))
    GameWorld.DebugLog("turnNum=%s,doMax=%s,actionIndex=%s,%s" % (turnNum, doMax, turnFight.actionIndex, turnFight.actionSortList))
    while doCnt < doMax and len(overLineupList) < len(turnFight.actionSortList):
        doCnt += 1
        turnNum = turnFight.turnNum
@@ -992,6 +1025,7 @@
        if turnFight.actionIndex >= len(turnFight.actionSortList):
            turnFight.actionIndex = 0
            
        playerHeroAtk = False # 玩家阵容行动标记
        faction, num = turnFight.actionSortList[turnFight.actionIndex]
        batFaction = turnFight.getBatFaction(faction)
        batLineup = batFaction.getBatlineup(num)
@@ -1038,8 +1072,8 @@
                    continue
                
                if faction == Def_FactionA:
                    if not PlayerControl.PayMoney(curPlayer, ShareDefine.TYPE_Price_Xiantao, fightPoint, isNotify=False):
                        return
                    playerHeroAtk = True
                break
            
        turnFight.actionIndex += 1
@@ -1052,10 +1086,9 @@
        if turnFight.checkOverByKilled():
            break
        
        nowUnXiantaoCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCnt)
        if unXiantaoCnt != nowUnXiantaoCnt:
            # 玩家有消耗战锤则停止,一段段执行
            GameWorld.DebugLog("玩家有消耗战锤则停止,nowUnXiantaoCnt=%s" % (nowUnXiantaoCnt))
        if playerHeroAtk:
            # 玩家武将有行动则停止,一段段执行
            GameWorld.DebugLog("玩家武将有行动则停止!")
            break
        
    if turnFight.winFaction:
@@ -1191,8 +1224,10 @@
    objName = gameObj.GetName()
    faction = GameObj.GetFaction(gameObj)
    posInfo = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo)
    npcID = gameObj.GetNPCID()
    return "%s%s %s[%s-%s]" % ("A" if faction == Def_FactionA else "B", posInfo, objName, gameObj.GetID(), npcID)
    heroID = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_HeroID)
    if not heroID:
        heroID = gameObj.GetNPCID()
    return "%s%s %s[%s-%s]" % ("A" if faction == Def_FactionA else "B", posInfo, objName, gameObj.GetID(), heroID)
def EntryLogic(turnFight):
    ## 执行进场逻辑
@@ -1308,23 +1343,10 @@
        GameWorld.DebugLog("        自残: curTD=%s,tagID=%s,skillID=%s,hurtType=%s,hurtValue=%s,lostHP=%s,curHP=%s" 
                           % (curID, tagID, skillID, hurtType, hurtValue, lostHP, GameObj.GetHP(curObj)))
        
    if lostHP and curID != tagID:
        AddTurnFightXP(tagObj, __GetAddXP_Defender(tagObj, lostHP), "skillID:%s" % skillID)
    if lostHP > 0 and curID != tagID:
        addXP = IpyGameDataPY.GetFuncCfg("AngerXP", 4)
        AddTurnFightXP(tagObj, addXP, "skillID:%s" % skillID)
    return
def __GetAddXP_Attack(attack, curSkill):
    ## 攻击方增加的XP值根据主动普攻技能获得
    if not curSkill:
        return 0
    if not SkillCommon.isNormalAtkSkill(curSkill):
        return 0
    return IpyGameDataPY.GetFuncCfg("AngerXP", 3)
def __GetAddXP_Defender(defender, lostHP):
    ## 掉血方增加的XP值根据掉血百分比获得
    if lostHP <= 0:
        return 0
    return IpyGameDataPY.GetFuncCfg("AngerXP", 4)
def AddTurnFightXP(gameObj, addXP, reason=""):
    ## 回合战斗增加XP
@@ -1354,7 +1376,16 @@
    if turnBattleType == ChConfig.TurnBattleType_AtkBack:
        if not tagObj:
            return
        atkOK = BaseAttack.Attack(curNPC, tagObj, None, tick) # 反击为单体普攻
        skillManager = curNPC.GetSkillManager()
        for index in range(0, skillManager.GetSkillCount()):
            skill = skillManager.GetSkillByIndex(index)
            #已经到尾部了
            if not skill or skill.GetSkillTypeID() == 0:
                break
            if skill.GetFuncType() == ChConfig.Def_SkillFuncType_NormalAttack:
                useSkill = skill
                break
        atkOK = SkillShell.DoLogic_UseSkill(curNPC, tagObj, useSkill, tick)
    elif turnBattleType == ChConfig.TurnBattleType_Combo:
        if not tagObj:
            return
@@ -1364,12 +1395,15 @@
        xpMax = IpyGameDataPY.GetFuncCfg("AngerXP", 2) 
        skillManager = curNPC.GetSkillManager()
        useSkillList = []
        GameWorld.DebugLog('skillCount=%s' % skillManager.GetSkillCount(), npcID)
        #GameWorld.DebugLog('skillCount=%s' % skillManager.GetSkillCount(), npcID)
        for index in range(0, skillManager.GetSkillCount()):
            useSkill = skillManager.GetSkillByIndex(index)
            #已经到尾部了
            if not useSkill or useSkill.GetSkillTypeID() == 0:
                break
            if useSkill.GetFuncType() in [ChConfig.Def_SkillFuncType_NormalAttack]:
                #基础普攻不能主动释放,目前仅用于反击
                continue
            #被动技能无法使用
            if SkillCommon.isPassiveSkill(useSkill):
                continue
@@ -1391,18 +1425,11 @@
        
        for useInfo in useSkillList:
            useSkill = useInfo[-1]
            skillID = useSkill.GetSkillID()
            #skillID = useSkill.GetSkillID()
            atkOK, tagObj = DoNPCUseSkill(curNPC, useSkill, tick)
            if atkOK:
                AddTurnFightXP(curNPC, __GetAddXP_Attack(curNPC, useSkill), "skillID:%s" % skillID)
                break
            
        if not atkOK:
            tagObj = GetEnemyObj(curNPC)
            if tagObj:
                GameWorld.DebugLog('    无技能可攻击,直接使用普攻! tagID=%s(%s)' % (tagObj.GetID(), GetObjName(tagObj)), npcID)
                atkOK = BaseAttack.Attack(curNPC, tagObj, None, tick)
    curNPC.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, 0) # 无论攻击成功与否都重置战斗类型
    
    tagID = 0
@@ -1445,6 +1472,11 @@
    if posNum <= 0:
        GameWorld.DebugLog("            被非主战单位攻击时无法触发反击: atkID=%s,posNum=%s" % (atkObj.GetID(), posNum))
        return False
    atkDistType = AttackCommon.GetAtkDistType(defObj)
    if atkDistType == ChConfig.AtkDistType_Long:
        if not IpyGameDataPY.GetFuncCfg("ParryCfg", 2):
            GameWorld.DebugLog("            远程单位不可反击: defID=%s" % (defObj.GetID()))
            return False
    defAtkBackRate = GameObj.GetAtkBackRate(defObj) # 防方反击率
    atkBackNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnAtkBackNum) # 已反击次数
    if atkBackNum > 10:
@@ -1631,22 +1663,81 @@
            return tagNPC
    return
def SetKilled(gameObj, killer=None):
def SetTurnObjKilled(gameObj, killer=None):
    if not gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo):
        #GameWorld.DebugLog("非回合战斗主体被击杀: curID=%s" % gameObj.GetID())
        return
    
    GameWorld.DebugLog("        %s 回合战斗主体被击杀: curID=%s" % (GetObjName(gameObj), gameObj.GetID()))
    GameObj.SetHP(gameObj, 0) # 回合制死亡仅设置为0,实例暂时不回收
    objID = gameObj.GetID()
    GameWorld.DebugLog("        %s 回合战斗主体被击杀: curID=%s" % (GetObjName(gameObj), objID))
    gameObj.SetCurAction(IPY_GameWorld.laNPCDie)
    if GameObj.GetHP(gameObj) != 0:
        GameObj.SetHP(gameObj, 0) # 回合制死亡仅设置为0,实例暂时不回收
    gameObj.SetVisible(False)
    
    turnFight = GetTurnFightMgr().getNPCTurnFight(gameObj.GetID())
    if turnFight:
        clientPack = ChPyNetSendPack.tagMCTurnFightObjDead()
        clientPack.ObjID = gameObj.GetID()
        turnFight.addBatPack(clientPack)
    turnFight = GetTurnFightMgr().getNPCTurnFight(objID)
    if not turnFight:
        return True
    clientPack = ChPyNetSendPack.tagMCTurnFightObjDead()
    clientPack.ObjID = objID
    turnFight.addBatPack(clientPack)
    # 记录主动发起的玩家阵营击杀
    curPlayer = turnFight.curPlayer
    if killer and curPlayer and killer.GetDictByKey(ChConfig.Def_Obj_Dict_LineupPlayerID) == curPlayer.GetPlayerID():
        if objID not in turnFight.playerKillObjIDList:
            turnFight.playerKillObjIDList.append(objID)
        GameWorld.DebugLog("玩家单次击杀统计: %s" % turnFight.playerKillObjIDList)
        
    return True
def OnTurnfightAttackSuccess(curObj, tagObj, curSkill):
    ## 回合战斗攻击成功额外处理,AttackResult之前,一般处理技能相关
    if curObj.GetGameObjType() != IPY_GameWorld.gotNPC:
        return
    if not curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo):
        return
    objID = curObj.GetID()
    turnFight = GetTurnFightMgr().getNPCTurnFight(objID)
    if not turnFight:
        return
    skillID = curSkill.GetSkillID() if curSkill else 0
    isXP = SkillCommon.isXPSkill(curSkill)
    if isXP:
        GameObj.SetXP(curObj, 0)
    elif curSkill:
        if SkillCommon.isTurnNormalAtkSkill(curSkill):
            addXP = IpyGameDataPY.GetFuncCfg("AngerXP", 3)
            AddTurnFightXP(curObj, addXP, "skillID:%s" % skillID)
    curPlayer = turnFight.curPlayer
    # 仅主动发起玩家阵容触发
    if curPlayer and curObj.GetDictByKey(ChConfig.Def_Obj_Dict_LineupPlayerID) == curPlayer.GetPlayerID():
        FBLogic.OnPlayerLineupAttackSuccess(curPlayer, curObj, tagObj, curSkill, turnFight.mapID, turnFight.funcLineID)
    return
def OnTurnfightAttackResult(curObj, tagObj, curSkill):
    ## 回合战斗攻击结果额外处理,AttackResult 之后,一般处理击杀结算相关
    if curObj.GetGameObjType() != IPY_GameWorld.gotNPC:
        return
    if not curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo):
        return
    objID = curObj.GetID()
    turnFight = GetTurnFightMgr().getNPCTurnFight(objID)
    if not turnFight:
        return
    curPlayer = turnFight.curPlayer
    # 仅主动发起玩家阵容触发
    if curPlayer and curObj.GetDictByKey(ChConfig.Def_Obj_Dict_LineupPlayerID) == curPlayer.GetPlayerID():
        FBLogic.OnPlayerLineupAttackResult(curPlayer, curObj, tagObj, curSkill, turnFight.mapID, turnFight.funcLineID)
    turnFight.playerKillObjIDList = []
    return
def OnTurnAllOver(guid):
    ## 所有回合已经全部执行完毕
@@ -1698,12 +1789,13 @@
            for posNum, curNPC in batLineup.npcPosDict.items():
                objID = curNPC.GetID()
                npcID = curNPC.GetNPCID()
                heroID = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_HeroID)
                atkHurt = hurtStatDict.get(objID, 0)
                defHurt = defStatDict.get(objID, 0)
                cureHP = cureStatDict.get(objID, 0)
                GameWorld.DebugLog("    Pos:%s ID=%s-%s,,HP=%s/%s, 输出=%s,承伤=%s,治疗=%s"
                                   % (posNum, objID, npcID, GameObj.GetHP(curNPC), GameObj.GetMaxHP(curNPC), atkHurt, defHurt, cureHP))
                lineupStatInfo[str(posNum)] = {"ObjID":objID, "NPCID":npcID, "AtkHurt":atkHurt, "DefHurt":defHurt, "CureHP":cureHP}
                GameWorld.DebugLog("    Pos:%s ID=%s-%s-%s,,HP=%s/%s, 输出=%s,承伤=%s,治疗=%s"
                                   % (posNum, objID, npcID, heroID, GameObj.GetHP(curNPC), GameObj.GetMaxHP(curNPC), atkHurt, defHurt, cureHP))
                lineupStatInfo[str(posNum)] = {"ObjID":objID, "HeroID":heroID, "NPCID":npcID, "AtkHurt":atkHurt, "DefHurt":defHurt, "CureHP":cureHP}
                
    awardItemList = []
    playerID = turnFight.playerID