hxp
2024-05-16 2bca56e5df150d46e0f218a4e1af5e3dd81a0bcb
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -54,6 +54,72 @@
RebornType_ShentongSkill, # 神通复活 - 由主角自己触发,灵宠触发的神通技能归为灵宠复活
) = range(1, 1 + 3)
Def_FactionA = 1
Def_FactionB = 2
class TurnFightBattle():
    def __init__(self):
        self.CleaerBat()
        return
    def CleaerBat(self):
        self.curPlayer = None
        self.mapID = 0
        self.funcLineID = 0
        self.tagType = 0
        self.tagID = 0
        self.valueList = []
        self.factionObjListDict = {} # 阵营所有战斗实例,包含主体、灵宠 {阵营:[obj, ...], ...}
        self.factionMainObjListDict = {} # 阵营所有战斗主体, {阵营:[obj, ...], ...}
        self.objTotalHurtDict = {} # 战斗实例累计输出 {objID:totalHurtValue, ...}
        self.factionTotalHurtDict = {} # 阵营累计输出 {faction:totalHurtValue, ...}
        self.fbData = {} # 战斗关联副本自定义相关数据 {key:value, ...}
        return
    def SetBattle(self, curPlayer, mapID, funcLineID, tagType, tagID, valueList):
        self.curPlayer = curPlayer
        self.mapID = mapID
        self.funcLineID = funcLineID
        self.tagType = tagType
        self.tagID = tagID
        self.valueList = valueList
        return
    def SetFactionObj(self, faction, objList, mainObjList):
        self.factionObjListDict[faction] = objList
        self.factionMainObjListDict[faction] = mainObjList
        return
    def GetTagMainObj(self):
        ## 获取对方战斗主体
        if Def_FactionB not in self.factionMainObjListDict:
            return
        mainObjList = self.factionMainObjListDict[Def_FactionB]
        if not mainObjList:
            return
        return mainObjList[0]
    def AddObjHurtValue(self, curObj, hurtValue):
        objID = curObj.GetID()
        faction = GameObj.GetFaction(curObj)
        updHurtValue = self.objTotalHurtDict.get(objID, 0) + hurtValue
        self.objTotalHurtDict[objID] = updHurtValue
        factionHurtValue = self.factionTotalHurtDict.get(faction, 0) + hurtValue
        self.factionTotalHurtDict[faction] = factionHurtValue
        # 玩家阵营
        if faction == Def_FactionA:
            FBLogic.OnTurnFightPlayerFactionHurt(self.curPlayer, self.mapID, self.funcLineID, curObj, hurtValue, factionHurtValue)
        return updHurtValue
g_turnFightBattle = TurnFightBattle()
def GetTurnFightBattle():
    global g_turnFightBattle
    return g_turnFightBattle
def GetObjName(gameObj):
    objName = gameObj.GetName()
    faction = GameObj.GetFaction(gameObj)
@@ -61,7 +127,7 @@
    curID = gameObj.GetDictByKey(ChConfig.Def_NPC_Dict_MirrorPlayerID)
    if not curID and gameObj.GetGameObjType() == IPY_GameWorld.gotNPC:
        curID = gameObj.GetNPCID()
    return "%s%s %s[%s-%s]" % ("A" if faction == 1 else "B", fightPlaceNum, objName, gameObj.GetID(), curID)
    return "%s%s %s[%s-%s]" % ("A" if faction == Def_FactionA else "B", fightPlaceNum, objName, gameObj.GetID(), curID)
#// B4 10 回合制战斗 #tagCMTurnFight
#
@@ -178,62 +244,12 @@
        factionInfoB = {"npcID":npcID, "pet":petCacheInfo, "skillIDExList":skillIDExList}
    else:
        return
    fightRet = ProcessAutoTurnFight(mapID, funcLineID, tagType, tagID, factionInfoA, factionInfoB, tick, curPlayer)
    if not fightRet:
        return
    isWin, turnNum, turnMax, factionTotalHurtDict, playbackID = fightRet
    
    needSendGameServer, awardItemList, overInfoEx = False, [], {}
    overRet = FBLogic.OnTurnFightOver(curPlayer, mapID, funcLineID, tagType, tagID, valueList, fightRet)
    if overRet != None:
        needSendGameServer, awardItemList, overInfoEx = overRet
    if needSendGameServer or mapID in ChConfig.Def_TFMapID_SendToGameServer:
        SendToGameServer_TurnFight(curPlayer, "TurnFightOver", [mapID, funcLineID, tagType, tagID, valueList, fightRet, awardItemList])
    overMsg = {"isWin":isWin, FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(awardItemList), "totalHurt":factionTotalHurtDict.get(1, 0)}
    playbackID and overMsg.update({"playbackID":playbackID})
    overInfoEx and overMsg.update(overInfoEx)
    SyncTurnFightState(curPlayer, mapID, funcLineID, tagType, tagID, FightState_Award, turnNum, turnMax, overMsg)
    return
def GetPlayerFactionInfoByCache(playerID):
    ## 根据玩家缓存数据获取对阵玩家阵营信息字典
    PropDict, PlusDict = PlayerViewCacheTube.GetPlayerPropPlusDictByID(playerID, True) # 从缓存中获取,强刷一次最新属性
    skillIDList = []
    SkillInfo = PlusDict.get("SkillInfo", {})
    for _, skillLVDict in SkillInfo.items():
        for skillID, _ in skillLVDict.items():
            skillID = GameWorld.ToIntDef(skillID)
            skillData = GameWorld.GetGameData().GetSkillBySkillID(skillID)
            if not skillData:
                continue
            skillIDList.append(skillID)
    return {"playerID":playerID, "pet":PlusDict.get("Pet"), "skillIDList":skillIDList, "ModelMark":PropDict.get("ModelMark", 0)}
def ProcessAutoTurnFight(mapID, funcLineID, tagType, tagID, factionInfoA, factionInfoB, tick, syncPlayer=None, isSavePlayback=False):
    ''' 处理自动回合战斗过程,仅做战斗流程处理,不做及其他功能逻辑
    @param mapID: 可视为功能ID
    @param funcLineID: 对功能ID的扩展
    @param factionInfoA: A方阵营信息,playerID 和 npcID 二选一 {"playerID":主体玩家镜像ID, "npcID":主体NPCID, "pet":[{出战灵宠信息兼容玩家缓存的灵宠信息k:v, ...}, ...]}
    @param factionInfoB: B方阵营信息
    @param syncPlayer: 需要通知的玩家,可能为None,注意仅做通知用,该玩家可能和AB阵营无任何关系
    @param isSavePlayback: 是否保存战斗回放
    @return: None-无结果;或 (isWin, turnNum, turnMax, factionTotalHurtDict)
                        isWin: 是否获胜
                        turnNum: 打了几回合
                        factionTotalHurtDict: 双方伤血统计
    '''
    if syncPlayer:
        syncPlayer.SetCanAttack(False) # 该玩家设置为不可被攻击
        playerID = syncPlayer.GetPlayerID()
        sightLevel, posX, posY = playerID, syncPlayer.GetPosX(), syncPlayer.GetPosY()
    else:
        playerID = 0
        sightLevel, posX, posY = 99, 192, 109 # 系统默认处理的层级及坐标
    factionA, factionB, mainRolePlace = 1, 2, 1
    curPlayer.SetCanAttack(False) # 该玩家设置为不可被攻击
    playerID = curPlayer.GetPlayerID()
    sightLevel, posX, posY = playerID, curPlayer.GetPosX(), curPlayer.GetPosY()
    factionA, factionB, mainRolePlace = Def_FactionA, Def_FactionB, 1
    objRetA = __SummonFactionObjs(factionA, mainRolePlace, factionInfoA, sightLevel, posX, posY)
    objRetB = __SummonFactionObjs(factionB, mainRolePlace, factionInfoB, sightLevel, posX, posY)
    objA, petObjListA, factionSyncInfoA = objRetA if objRetA else (None, [], {})
@@ -243,6 +259,11 @@
        for gameObj in fightObjList:
            TurnFightObjOverReset(gameObj, tick)
        return
    tfBattle = GetTurnFightBattle()
    tfBattle.CleaerBat()
    tfBattle.SetBattle(curPlayer, mapID, funcLineID, tagType, tagID, valueList)
    playerIDA = objA.GetDictByKey(ChConfig.Def_NPC_Dict_MirrorPlayerID) # 可能为0,非玩家镜像时为0
    playerIDB = objB.GetDictByKey(ChConfig.Def_NPC_Dict_MirrorPlayerID) # 可能为0,非玩家镜像时为0
    
@@ -255,6 +276,8 @@
    factionListA = petObjListA + [objA]
    factionListB = petObjListB + [objB]
    atkFactionList = [factionListA, factionListB]
    tfBattle.SetFactionObj(factionA, factionListA, [objA])
    tfBattle.SetFactionObj(factionB, factionListB, [objB])
    
    # 设置战斗主体
    objA.SetDict(ChConfig.Def_Obj_Dict_TurnEnemyID, objB.GetID())
@@ -266,8 +289,8 @@
            if not gameObj:
                continue
            faction = GameObj.GetFaction(gameObj)
            tagGameObj = objB if faction == 1 else objA
            TurnFightObjStartInit(playerID, gameObj, tagGameObj, tick)
            tagGameObj = objB if faction == Def_FactionA else objA
            TurnFightObjStartInit(mapID, playerID, gameObj, tagGameObj, tick)
            
    #一个回合攻击顺序,为了后续逻辑统一,都是先确定好顺序
    sortType = 2 # 攻击顺序排序方式
@@ -284,19 +307,19 @@
            for factionObjList in atkFactionList:
                fightObjList.append(factionObjList[i])
                
    SyncTurnFightState(syncPlayer, mapID, funcLineID, tagType, tagID, FightState_PrepareOK, msg=[factionSyncInfoA, factionSyncInfoB])
    SyncTurnFightState(curPlayer, mapID, funcLineID, tagType, tagID, FightState_PrepareOK, msg=[factionSyncInfoA, factionSyncInfoB])
    
    isWin = None
    for turnNum in range(1, turnMax + 1):
        GameWorld.DebugLog("【----- 回合制战斗轮次: %s -----】" % turnNum)
        SyncTurnFightState(syncPlayer, mapID, funcLineID, tagType, tagID, FightState_Fighting, turnNum, turnMax)
        SyncTurnFightState(curPlayer, mapID, funcLineID, tagType, tagID, FightState_Fighting, turnNum, turnMax)
        
        # 回合开始: 做一些每回合重置逻辑或者某些根据回合触发的效果等
        for gameObj in fightObjList:
            if not gameObj:
                continue
            faction = GameObj.GetFaction(gameObj)
            tagGameObj = objB if faction == 1 else objA
            tagGameObj = objB if faction == Def_FactionA else objA
            TurnFightObjPerTurnStart(gameObj, tagGameObj, turnNum, tick)
            
        isWin = CheckIswin(objA, objB)
@@ -314,7 +337,7 @@
                
            objType = gameObj.GetGameObjType()
            objID = gameObj.GetID()
            SyncTurnFightObjAction(syncPlayer, turnNum, objType, objID)
            SyncTurnFightObjAction(curPlayer, turnNum, objType, objID)
            
            if GameObj.GetHP(gameObj) <= 0:
                # 复活时机在自己行动节点
@@ -325,7 +348,7 @@
            objName = GetObjName(gameObj)
            curHP = GameObj.GetHP(gameObj)
            
            tagGameObj = objB if faction == 1 else objA
            tagGameObj = objB if faction == Def_FactionA else objA
            tagObjType = tagGameObj.GetGameObjType()
            tagObjID = tagGameObj.GetID()
            tagHP = GameObj.GetHP(tagGameObj)
@@ -343,20 +366,19 @@
        if isWin != None:
            break
        
    isWin = FBLogic.OnTurnFightIsWin(curPlayer, mapID, funcLineID, tagType, tagID, valueList, isWin)
    GameWorld.DebugLog("--- 战斗结束处理 --- isWin=%s" % isWin)
    isWin = 1 if isWin else 0
    
    # 统计总伤害
    factionTotalHurtDict = {}
    factionTotalHurtDict = tfBattle.factionTotalHurtDict
    for gameObj in fightObjList:
        if not gameObj:
            continue
        faction = GameObj.GetFaction(gameObj)
        objName = GetObjName(gameObj)
        objID = gameObj.GetID()
        totalHurtEx = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnTotalHurtEx) * ChConfig.Def_PerPointValue
        totalHurt = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnTotalHurt) + totalHurtEx
        factionTotalHurtDict[faction] = factionTotalHurtDict.get(faction, 0) + totalHurt
        totalHurt = tfBattle.objTotalHurtDict.get(objID, 0)
        GameWorld.DebugLog("%s objID=%s,faction=%s, 总输出: %s" % (objName, objID, faction, totalHurt))
    for faction, totalHurt in factionTotalHurtDict.items():
        GameWorld.DebugLog("faction=%s, 阵营总输出: %s" % (faction, totalHurt))
@@ -364,19 +386,51 @@
    GameWorld.DebugLog("A剩余血量: %s / %s" % (GameObj.GetHP(objA), GameObj.GetMaxHP(objA)))
    GameWorld.DebugLog("B剩余血量: %s / %s" % (GameObj.GetHP(objB), GameObj.GetMaxHP(objB)))
    
    SyncTurnFightState(syncPlayer, mapID, funcLineID, tagType, tagID, FightState_FightEnd, turnNum, turnMax)
    for gameObj in fightObjList:
        TurnFightObjOverReset(gameObj, tick)
    SyncTurnFightState(curPlayer, mapID, funcLineID, tagType, tagID, FightState_FightEnd, turnNum, turnMax)
        
    playbackID = 0 # 战斗回放ID,可根据该ID查看回放
    #playbackInfo = "" # 战斗回放信息
    if isSavePlayback:
        pass
    #if isSavePlayback:
    #    pass
    
    GameWorld.DebugLog("===== 回合制战斗结束: mapID=%s,funcLineID=%s,playerIDA=%s,playerIDB=%s,isWin=%s" 
                       % (mapID, funcLineID, playerIDA, playerIDB, isWin))
    return isWin, turnNum, turnMax, factionTotalHurtDict, playbackID
    # 战斗结束后处理
    fightRet = [isWin, turnNum, turnMax, factionTotalHurtDict, playbackID]
    needSendGameServer, awardItemList, overInfoEx = False, [], {}
    overRet = FBLogic.OnTurnFightOver(curPlayer, mapID, funcLineID, tagType, tagID, valueList, fightRet)
    if overRet != None:
        needSendGameServer, awardItemList, overInfoEx = overRet
    if needSendGameServer or mapID in ChConfig.Def_TFMapID_SendToGameServer:
        SendToGameServer_TurnFight(curPlayer, "TurnFightOver", [mapID, funcLineID, tagType, tagID, valueList, fightRet, awardItemList])
    overMsg = {"isWin":isWin, FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(awardItemList), "totalHurt":factionTotalHurtDict.get(Def_FactionA, 0)}
    playbackID and overMsg.update({"playbackID":playbackID})
    overInfoEx and overMsg.update(overInfoEx)
    SyncTurnFightState(curPlayer, mapID, funcLineID, tagType, tagID, FightState_Award, turnNum, turnMax, overMsg)
    # 都处理完毕了,回收对象,重置数据
    for gameObj in fightObjList:
        TurnFightObjOverReset(gameObj, tick)
    tfBattle.CleaerBat()
    return
def GetPlayerFactionInfoByCache(playerID):
    ## 根据玩家缓存数据获取对阵玩家阵营信息字典
    PropDict, PlusDict = PlayerViewCacheTube.GetPlayerPropPlusDictByID(playerID, True) # 从缓存中获取,强刷一次最新属性
    skillIDList = []
    SkillInfo = PlusDict.get("SkillInfo", {})
    for _, skillLVDict in SkillInfo.items():
        for skillID, _ in skillLVDict.items():
            skillID = GameWorld.ToIntDef(skillID)
            skillData = GameWorld.GetGameData().GetSkillBySkillID(skillID)
            if not skillData:
                continue
            skillIDList.append(skillID)
    return {"playerID":playerID, "pet":PlusDict.get("Pet"), "skillIDList":skillIDList, "ModelMark":PropDict.get("ModelMark", 0)}
def __SummonFactionObjs(faction, mainRolePlace, objInfo, sightLevel, posX, posY):
    '''召唤阵营战斗实例
@@ -608,15 +662,14 @@
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightTimeline, turnNum * 100 + actionNum)
    return
def TurnFightObjStartInit(playerID, gameObj, tagObj, tick):
def TurnFightObjStartInit(mapID, playerID, gameObj, tagObj, tick):
    ## 回合制战斗实例初始化
    if not gameObj:
        return
    mainRolePlace = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightMainRolePlace)
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightMapID, mapID)
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightID, playerID)
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnRebornCount, 0)
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnTotalHurt, 0)
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnTotalHurtEx, 0)
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnSkillSuccessPetState, 0)
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnAttackOverPetState, 0)
    SetTimeline(gameObj, 1, 0)
@@ -839,15 +892,12 @@
def AddTurnObjHurtValue(curObj, tagObj, hurtType, hurtValue, lostHP, curSkill=None):
    if not curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightTimeline):
        return
    tfBattle = GetTurnFightBattle()
    curID = curObj.GetID()
    tagID = tagObj.GetID()
    skillID = curSkill.GetSkillID() if curSkill else 0
    totalHurtEx = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnTotalHurtEx) * ChConfig.Def_PerPointValue
    totalHurt = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnTotalHurt) + totalHurtEx
    if curID != tagID:
        totalHurt += hurtValue
        curObj.SetDict(ChConfig.Def_Obj_Dict_TurnTotalHurt, totalHurt % ChConfig.Def_PerPointValue)
        curObj.SetDict(ChConfig.Def_Obj_Dict_TurnTotalHurtEx, totalHurt / ChConfig.Def_PerPointValue)
        totalHurt = tfBattle.AddObjHurtValue(curObj, hurtValue)
        GameWorld.DebugLog("        伤血: curTD=%s,tagID=%s,skillID=%s,hurtType=%s,hurtValue=%s,totalHurt=%s,lostHP=%s,tagHP=%s" 
                           % (curID, tagID, skillID, hurtType, hurtValue, totalHurt, lostHP, GameObj.GetHP(tagObj)))
    else: