ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -27,6 +27,8 @@
import NetPackCommon
import PlayerControl
import GameWorld
import PlayerLLMJ
import PlayerPrestigeSys
import IpyGameDataPY
import PlayerOnline
import NPCCommon
@@ -45,6 +47,8 @@
import random
import time
import json
g_gmTestFightReq = []
PosNumMax = 7 # 最大站位编号
ActionNumStart = -1 # 起始行动位置编号,一般是从1开始,如果有加主公、红颜等则扣除相应位置值,如从0或-1开始
@@ -71,6 +75,7 @@
        self.shapeType = 0 # 阵型
        self.fightPower = 0 # 阵容总战力
        self.posObjIDDict = {} # 站位对应战斗实体 {站位编号:batObjID, ...}, 站位编号小于0为非主战单位,如主公、红颜等
        self.heroObjIDDict = {} # 武将ID对应ObjID {heroID:batObjID, ...}
        self.lingshouObjIDDict = {} # 灵兽战斗单位 {位置编号:batObjID, ...}
        self.beautyObjIDDict = {} # 红颜战斗单位 {位置编号:batObjID, ...}
        self.actionNum = ActionNumStart # 行动位置,从1开始
@@ -107,6 +112,7 @@
        for objID in self.beautyObjIDDict.values():
            batObjMgr.delBatObj(objID)
        self.posObjIDDict = {}
        self.heroObjIDDict = {}
        self.lingshouObjIDDict = {}
        self.beautyObjIDDict = {}
        self.fightPower = 0
@@ -182,6 +188,7 @@
        self.isNeedReport = isNeedReport # 是否需要战报
        self.msgDict = {} # 扩展信息字典,一般由MapID绑定的功能决定信息内容  {k:v, ...}
        self._kvDict = {} # 自定义信息字典,不会被重置  {k:v, ...}
        self.awardData = None # 战斗奖励设置的数据,可以是任意数据格式,由功能自行决定,会传递给 OnTurnFightAward 处理
        
        self.factionDict = {} # 战斗阵营 {faction:BatFaction, ...},一般是只有两个阵营,faction为1或2,每个阵营支持多个阵容
        self.actionSortList = [] # 阵容行动顺序 [[faction, num], ...]
@@ -211,6 +218,7 @@
        self.setPVP()
        self.msgDict = {}
        self._kvDict = {}
        self.awardData = None
        self.nextTurnFight(msgDict)
        return
    
@@ -225,6 +233,8 @@
        self.tagPlayerID = tagPlayerID
        self.tagViewCache = tagViewCache
        return
    def getPVPPlayerID(self): return self.tagPlayerID # 获取PVP目标玩家ID,也可用于判断是否PVP
    
    def isFBMap(self):
        ## 是否副本地图中,非主线的均视为副本
@@ -512,6 +522,18 @@
        self.waveMax = 6 # 本关最大波数,每波有多个小队,每个小队即为一张战斗 TurnFight
        self.wave = 0 # 当前刷怪波,注意不是玩家当前进度波,比如被击杀会回退一波
        self.turnFight = GetTurnFightMgr().addTurnFight(ChConfig.Def_FBMapID_Main, 0, playerID)
        # 主线小怪战斗额外数据,一般用于分割与主线战斗表现无关的附加功能内容
        self.useZhanchui = 0
        self.mjExp = 0 # 历练秘笈额外经验
        self.killNPCCnt = 0
        return
    def resetMainFightExDataRec(self):
        ## 重置主线战斗相关的额外数据记录,每次前端请求主线小怪战斗处理后需要重置
        self.useZhanchui = 0
        self.mjExp = 0
        self.killNPCCnt = 0
        return
    
    def isLevelBoss(self):
@@ -605,7 +627,10 @@
    # @param lineupID: 阵容ID
    # @param npcLV: 成长NPC等级
    # @param difficulty: 成长NPC难度系数
    # @return: 阵容全部信息json字典,前端通用格式
    # @return: 阵容全部信息json字典,前端通用格式
    lineupInfo = GetGMTestNPCLineupInfo(lineupID, strongerLV, difficulty)
    if lineupInfo:
        return lineupInfo
    ipyData = IpyGameDataPY.GetIpyGameData("NPCLineup", lineupID)
    if not ipyData:
        return {}
@@ -627,6 +652,93 @@
    lineupInfo = {"NPCLineupID":lineupID, "Hero":heroDict, "BossID":bossID, "BossPosView":bossPosView}
    return lineupInfo
def GMTestFight(curPlayer, heroIDList, isAllSkill):
    ## GM测试战斗,指定武将
    global g_gmTestFightReq
    g_gmTestFightReq = [heroIDList, isAllSkill]
    __doMainLevelWave(curPlayer, True)
    g_gmTestFightReq = []
    return
def GetGMTestNPCLineupInfo(lineupID, strongerLV=0, difficulty=0):
    ## 获取GM测试战斗阵容信息
    if not g_gmTestFightReq:
        return
    heroIDList, isAllSkill = g_gmTestFightReq
    lineupIpyData = IpyGameDataPY.GetIpyGameData("NPCLineup", lineupID)
    if not lineupIpyData:
        return
    npcDict = {}
    heroNPCIDDict = {}
    for posNum in range(1, 1 + 6):
        if not hasattr(lineupIpyData, "GetPosNPCID%s" % posNum):
            break
        npcID = getattr(lineupIpyData, "GetPosNPCID%s" % posNum)()
        if not npcID:
            continue
        battleDict = GetNPCBattleDict(lineupIpyData, npcID, strongerLV, difficulty)
        if not battleDict:
            continue
        npcDict[npcID] = battleDict
        heroID = battleDict["HeroID"]
        heroNPCIDDict[heroID] = npcID
    if not npcDict:
        return
    heroDict = {}
    # 原先阵容刚好有的直接用
    for posNum, heroID in enumerate(heroIDList, 1):
        if heroID not in heroNPCIDDict:
            continue
        npcID = heroNPCIDDict[heroID]
        heroDict[str(posNum)] = npcDict[npcID]
        heroIDList[posNum - 1] = 0
    lineupNPCID = npcDict.keys()[0]
    ipyNPCIDList = []
    ipyHeroIDList = []
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for index in xrange(ipyDataMgr.GetNPCCount()):
        ipyData = ipyDataMgr.GetNPCByIndex(index)
        heroID = ipyData.GetRelatedHeroID()
        npcID = ipyData.GetNPCID()
        ipyNPCIDList.append(npcID)
        ipyHeroIDList.append(heroID)
    lineupNPCIndex = ipyNPCIDList.index(lineupNPCID)
    # 从参考阵容先往前检索,再往后检索,还没有对应武将的NPC
    loopIndexList = range(lineupNPCIndex + 1)[::-1] + range(lineupNPCIndex + 1, ipyDataMgr.GetNPCCount())
    for index in loopIndexList:
        npcID = ipyNPCIDList[index]
        heroID = ipyHeroIDList[index]
        if heroID not in heroIDList:
            continue
        battleDict = GetNPCBattleDict(lineupIpyData, npcID, strongerLV, difficulty)
        if not battleDict:
            continue
        for posNum, posHeroID in enumerate(heroIDList, 1):
            if not posHeroID or heroID != posHeroID:
                continue
            heroIDList[posNum - 1] = 0
            heroDict[str(posNum)] = battleDict
        if heroIDList.count(0) == len(heroIDList):
            break
    if isAllSkill:
        for battleDict in heroDict.values():
            heroID = battleDict["HeroID"]
            heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID) if heroID else None
            skillIDList = GetNPCHeroSkillIDList(heroID, heroIpyData, 99999, 99999) # 默认取突破、觉醒都满级时的技能
            battleDict["SkillIDList"] = skillIDList
    lineupInfo = {"NPCLineupID":lineupID, "Hero":heroDict, "BossID":0, "BossPosView":0}
    return lineupInfo
def GetNPCBattleDict(lineupIpyData, npcID, strongerLV=0, difficulty=0):
    ## 获取NPC战斗相关字典,支持成长NPC
    # @param strongerLV: 成长等级
@@ -755,7 +867,9 @@
    @param lineupInfo: 阵容信息
    @param playerID: 发起的玩家ID,系统场次为0
    '''
    GameWorld.DebugLog("SummonLineupObjs faction:%s,num:%s,lineupInfo=%s" % (faction, num, lineupInfo), playerID)
    lineupPlayerID = lineupInfo.get("PlayerID", 0) # 阵容所属玩家ID
    npcLineupID = lineupInfo.get("NPCLineupID", 0)
    GameWorld.DebugLog("SummonLineupObjs faction:%s,num:%s,npcLineupID=%s,lineupPlayerID=%s" % (faction, num, npcLineupID, lineupPlayerID), playerID)
    if playerID:
        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
        if not curPlayer:
@@ -763,7 +877,6 @@
        
    turnFight = batLineup.turnFight
    tfGUID = turnFight.guid
    lineupPlayerID = lineupInfo.get("PlayerID", 0) # 阵容所属玩家ID
    heroDict = lineupInfo.get("Hero", {})
    
    batObjMgr = BattleObj.GetBatObjMgr()
@@ -829,6 +942,7 @@
            skillManager.LearnSkillByID(skillID)
            
        batLineup.posObjIDDict[posNum] = objID
        batLineup.heroObjIDDict[heroID] = objID
        GameWorld.DebugLog("AddBatObj %s,skill=%s" % (GetObjName(batObj), skillManager.GetSkillIDList()))
        ResetObjSkill(batObj)
        
@@ -1011,7 +1125,9 @@
            break
        
    PlayerOnline.GetOnlinePlayer(curPlayer).SetLastBatBuffer(guid, turnFight.batBuffer)
    SyncTurnFightReport(curPlayer, guid, turnFight.batBuffer)
    SyncTurnFightReport(curPlayer, guid, turnFight.batBuffer) # 同步战报
    #在同步战报后再处理结算奖励,与战斗表现分离
    FBLogic.OnTurnFightAward(curPlayer, turnFight, mapID, funcLineID, turnFight.awardData)
    tfMgr.delTurnFight(guid)
    return True
@@ -1050,6 +1166,7 @@
    
    PlayerOnline.GetOnlinePlayer(curPlayer).SetLastBatBuffer(guid, turnFight.batBuffer)
    SyncTurnFightReport(curPlayer, guid, turnFight.batBuffer)
    FBLogic.OnTurnFightAward(curPlayer, turnFight, mapID, funcLineID, turnFight.awardData)
    tfMgr.delTurnFight(guid)
    return True
@@ -1080,6 +1197,9 @@
        return
    
    GameWorld.DebugLog("------------------- 主线战斗请求: reqType=%s" % reqType, curPlayer.GetPlayerID())
    mainFightMgr = GetMainFightMgr(curPlayer)
    mainFightMgr.resetMainFightExDataRec() # 请求时补重置,防止异常时重复结算逻辑
    clientPack = ChPyNetSendPack.tagSCTurnFightReportSign()
    clientPack.Sign = 0
    NetPackCommon.SendFakePack(curPlayer, clientPack) # 标记开始
@@ -1094,6 +1214,34 @@
    # 标记结束
    clientPack.Sign = 1
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    __doMainFightExDataFunc(curPlayer)
    return
def __doMainFightExDataFunc(curPlayer):
    mainFightMgr = GetMainFightMgr(curPlayer)
    # 本次消耗战锤数
    useZhanchui = mainFightMgr.useZhanchui
    if useZhanchui > 0:
        PlayerLLMJ.AddUseZhanchui(curPlayer, useZhanchui)
        PlayerPrestigeSys.AddRealmTaskValue(curPlayer, PlayerPrestigeSys.RealmTaskType_UseXiantao, useZhanchui)
        PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_CutTree, useZhanchui)
        PlayerActivity.AddDailyTaskValue(curPlayer, ChConfig.DailyTask_CutTree, useZhanchui)
    # 历练秘境额外经验
    mjExp = mainFightMgr.mjExp
    if mjExp > 0:
        PlayerLLMJ.AddExpEx(curPlayer, mjExp)
    # 击杀怪物
    killNPCCnt = mainFightMgr.killNPCCnt
    if killNPCCnt > 0:
        PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_KillNPC, killNPCCnt)
        PlayerActivity.AddDailyTaskValue(curPlayer, ChConfig.DailyTask_KillNPC, killNPCCnt)
    # 结算逻辑最后重置数据
    mainFightMgr.resetMainFightExDataRec()
    return
def __doExitMainFight(curPlayer):
@@ -1412,7 +1560,7 @@
    
    batObjMgr = BattleObj.GetBatObjMgr()
    for faction, num in turnFight.actionSortList:
        GameWorld.DebugLog("大回合开始逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num))
        GameWorld.DebugLog("大回合开始逻辑: turnNum=%s,faction=%s,num=%s" % (turnNum, faction, num))
        batFaction = turnFight.getBatFaction(faction)
        batLineup = batFaction.getBatlineup(num)
        batLineup.actionNum = 1
@@ -1426,8 +1574,9 @@
            turnFight.ResetOneActionUseSkillCnt()
            batObj.SetTiming(ChConfig.TurnTiming_Before) # 重置时机到回合前
            if turnNum > 1: # 第1回合不用刷新技能
                RefreshObjSkillByTurn(batObj)
                RefreshObjSkillByBigTurn(batObj)
                RefreshObjByBigTurn(turnFight, batObj)
            batObj.ResetBigTurn() # 每大回合重置
            TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_BigTurnStart)
            
    return
@@ -1502,7 +1651,7 @@
        
    return
def RefreshObjSkillByTurn(batObj):
def RefreshObjSkillByBigTurn(batObj):
    '''按回合刷新技能:默认以大回合统一减1回合
    '''
    curID = batObj.GetID()
@@ -1522,8 +1671,31 @@
        remainTime -= 1
        curSkill.SetRemainTime(remainTime)
        GameWorld.DebugLog("    更新技能CD: curID=%s,skillID=%s,remainTime=%s" % (curID, skillID, remainTime))
    batObj.ResetSkillTurnUseCnt() # 重置回合使用次数,放刷新CD后重置
    return
def RefreshObjByBigTurn(turnFight, batObj):
    ## 根据大回合开始刷新buff持续时间,每个大回合-1,第1回合不处理
    curID = batObj.GetID()
    buffMgr = batObj.GetBuffManager()
    for index in range(buffMgr.GetBuffCount())[::-1]:
        buff = buffMgr.GetBuffByIndex(index)
        buffID = buff.GetBuffID()
        skillID = buff.GetSkillID()
        skillData = buff.GetSkillData()
        if skillData.GetLastTimeType() != ChConfig.BuffLastTimeType_BigTurn:
            continue
        if skillData.GetSkillType() in ChConfig.Def_LstBuff_List:
            #GameWorld.DebugLog("    持续类buff由触发时机决定剩余时间! curID=%s,index=%s,skillID=%s,buffID=%s" % (curID, index, skillID, buffID))
            continue
        if skillData.GetSkillType() == ChConfig.Def_SkillType_Halo and buff.GetOwnerID() != curID:
            GameWorld.DebugLog("    光环buff非光源不处理! curID=%s,index=%s,skillID=%s,buffID=%s" % (curID, index, skillID, buffID))
            continue
        remainTime = buff.GetRemainTime()
        if remainTime <= 0:
            continue
        remainTime -= 1
        GameWorld.DebugLog("    更新buff回合: curID=%s,buffID=%s,skillID=%s,remainTime=%s" % (curID, buffID, skillID, remainTime))
        TurnBuff.SetBuffRemainTime(turnFight, batObj, buff, remainTime)
    return
def RefreshObjBuffTime(turnFight, batObj):
@@ -1538,8 +1710,13 @@
        buffID = buff.GetBuffID()
        skillID = buff.GetSkillID()
        skillData = buff.GetSkillData()
        if skillData.GetLastTimeType() != ChConfig.BuffLastTimeType_Default:
            continue
        if skillData.GetSkillType() in ChConfig.Def_LstBuff_List:
            #GameWorld.DebugLog("    持续类buff由触发时机决定剩余时间! curID=%s,index=%s,skillID=%s,buffID=%s" % (curID, index, skillID, buffID))
            continue
        if skillData.GetSkillType() == ChConfig.Def_SkillType_Halo and buff.GetOwnerID() != curID:
            GameWorld.DebugLog("    光环buff非光源不处理! curID=%s,index=%s,skillID=%s,buffID=%s" % (curID, index, skillID, buffID))
            continue
        remainTime = buff.GetRemainTime()
        if remainTime <= 0:
@@ -1556,13 +1733,9 @@
            continue
        remainTime -= 1
        GameWorld.DebugLog("    更新buff回合: curID=%s,buffID=%s,skillID=%s,remainTime=%s,addTiming=%s" % (curID, buffID, skillID, remainTime, addTiming))
        if remainTime > 0:
            buff.SetRemainTime(remainTime)
            TurnBuff.SyncBuffRefresh(turnFight, batObj, buff)
        else:
            TurnBuff.DoBuffDel(turnFight, batObj, buff)
        TurnBuff.SetBuffRemainTime(turnFight, batObj, buff, remainTime)
    return
def AddTurnObjCureHP(curObj, srcObj, addValue, cureHP, skillID=0):
    ## 回合对象添加治疗值
    # @param curObj: 获得治疗的对象
@@ -1579,22 +1752,21 @@
        
    return
def AddTurnObjHurtValue(curBatObj, tagBatObj, hurtValue, lostHP, skillID=0, isBounce=False):
def AddTurnObjHurtValue(curBatObj, tagBatObj, hurtValue, lostHP, skillID=0, lostType=""):
    ## 回合对象添加伤害值
    # @param isBounce: 是否反弹伤害
    if hurtValue <= 0:
        return
    curID = curBatObj.GetID()
    tagID = tagBatObj.GetID()
    if curID != tagID:
        updStatValue = curBatObj.StatHurtValue(hurtValue)
        GameWorld.DebugLog("        统计伤血: curID=%s,tagID=%s,skillID=%s,hurtValue=%s,lostHP=%s,updStatValue=%s,tagHP=%s,isBounce=%s"
                       % (curID, tagID, skillID, hurtValue, lostHP, updStatValue, tagBatObj.GetHP(), isBounce))
        GameWorld.DebugLog("        统计输出: curID=%s,tagID=%s,skillID=%s,hurtValue=%s,lostHP=%s,updStatValue=%s,tagHP=%s,lostType=%s"
                       % (curID, tagID, skillID, hurtValue, lostHP, updStatValue, tagBatObj.GetHP(), lostType))
        
        if tagBatObj:
            updStatValue = tagBatObj.StatDefValue(hurtValue)
            GameWorld.DebugLog("        统计承伤: curID=%s,tagID=%s,skillID=%s,hurtValue=%s,lostHP=%s,updStatValue=%s,curHP=%s,isBounce=%s"
                           % (tagID, curID, skillID, hurtValue, lostHP, updStatValue, tagBatObj.GetHP(), isBounce))
            GameWorld.DebugLog("        统计承伤: curID=%s,tagID=%s,skillID=%s,hurtValue=%s,lostHP=%s,updStatValue=%s,curHP=%s,lostType=%s"
                           % (tagID, curID, skillID, hurtValue, lostHP, updStatValue, tagBatObj.GetHP(), lostType))
            
    else:
        # 如换血类技能,自残的伤害不算输出
@@ -1697,8 +1869,20 @@
    
    # 暂时只算主线小怪
    if curPlayer and turnFight.mapID == ChConfig.Def_FBMapID_Main and gameObj.GetFaction() != ChConfig.Def_FactionA:
        PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_KillNPC, 1)
        PlayerActivity.AddDailyTaskValue(curPlayer, ChConfig.DailyTask_KillNPC, 1)
        GetMainFightMgr(curPlayer).killNPCCnt += 1
    # 清除光源buff
    buffMgr = gameObj.GetBuffManager()
    for index in range(buffMgr.GetBuffCount())[::-1]:
        buff = buffMgr.GetBuffByIndex(index)
        skillID = buff.GetSkillID()
        skillData = buff.GetSkillData()
        if skillData.GetSkillType() != ChConfig.Def_SkillType_Halo:
            continue
        if buff.GetOwnerID() != objID:
            continue
        GameWorld.DebugLog("删除光环buff: objID=%s,skillID=%s" % (objID, skillID))
        TurnBuff.DoBuffDel(turnFight, gameObj, buff)
    return True
def OnTurnAllOver(guid):