ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -97,7 +97,7 @@
    curPet = curPlayer.GetPetMgr().GetFightPet()
    tagPet = None
    
    GameWorld.DebugLog("执行回合制战斗: mapID=%s,funcLineID=%s,tagPlayerID=%s,tagObjID=%s"
    GameWorld.DebugLog("===== 执行回合制战斗: mapID=%s,funcLineID=%s,tagPlayerID=%s,tagObjID=%s"
                       % (mapID, funcLineID, tagPlayerID, tagObj.GetID()), playerID)
    GameWorld.DebugLog("curPlayer.GetSightLevel=%s,tagObj.GetSightLevel=%s" 
                       % (curPlayer.GetSightLevel(), tagObj.GetSightLevel()), playerID)
@@ -117,16 +117,23 @@
        for gameObj in objList:
            TurnFightObjStartInit(gameObj)
            
    curSpeed = 0
    tagSpeed = 0
    orderList = [1, 2] if curSpeed >= tagSpeed else [2, 1]
    GameWorld.DebugLog("playerHP=%s,tagHP=%s,curSpeed=%s,tagSpeed=%s"
                       % (GameObj.GetHP(curPlayer), GameObj.GetHP(tagObj), curSpeed, tagSpeed), playerID)
    curAtkSpeed = GameObj.GetAtkSpeed(curPlayer)
    tagAtkSpeed = GameObj.GetAtkSpeed(tagObj)
    orderList = [1, 2] if curAtkSpeed >= tagAtkSpeed else [2, 1]
    GameWorld.DebugLog("playerHP=%s,tagHP=%s,curAtkSpeed=%s,tagAtkSpeed=%s"
                       % (GameObj.GetHP(curPlayer), GameObj.GetHP(tagObj), curAtkSpeed, tagAtkSpeed), playerID)
    
    isWin = None
    for turnNum in range(1, turnMax + 1):
        GameWorld.DebugLog("回合制战斗轮次: %s" % turnNum, playerID)
        GameWorld.DebugLog("----- 回合制战斗轮次: %s -----" % turnNum, playerID)
        SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Fighting, turnNum, turnMax)
        # 回合开始: 做一些每回合重置逻辑或者某些根据回合触发的效果等
        for objList in factionObjDict.values():
            for gameObj in objList:
                TurnFightObjTurnStart(gameObj, turnNum)
        # 回合战斗: 轮流依次攻击
        for index in range(factionObjMax):
            for faction in orderList:
                objList = factionObjDict[faction]
@@ -135,7 +142,7 @@
                gameObj = objList[index]
                if not gameObj:
                    continue
                gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightNum, turnNum)
                tagGameObj = tagObj if faction == 1 else curPlayer
                objType = gameObj.GetGameObjType()
                objID = gameObj.GetID()
@@ -144,17 +151,13 @@
                
                GameWorld.DebugLog("    行动: turnNum=%s,index=%s,faction=%s,objType=%s,objID=%s,tagObjType=%s,tagObjID=%s" 
                                   % (turnNum, index, faction, objType, objID, tagObjType, tagObjID), playerID)
                if objType == IPY_GameWorld.gotPlayer:
                    PlayerAttack(gameObj, tagGameObj, tick)
                else:
                    NPCAttack(gameObj, tagGameObj, tick)
                DoAttack(gameObj, tagGameObj, tick)
                if tagGameObj and GameObj.GetHP(tagGameObj) > 0:
                    GameWorld.DebugLog("        playerHP=%s,tagHP=%s" % (GameObj.GetHP(curPlayer), GameObj.GetHP(tagObj)), playerID)
                    continue
                
                isWin = faction == 1
                GameWorld.DebugLog("        tagObjType=%s,tagObjID=%s,被击杀,结束战斗: isWin=%s" % (tagObjType, tagObjID, isWin), playerID)
                GameWorld.DebugLog("        tagObjType=%s,tagObjID=%s,被击杀,结束战斗: isWin=%s" % (tagObjType, tagObjID, isWin))
                break
            
            if isWin != None:
@@ -170,7 +173,7 @@
        for gameObj in objList:
            TurnFightObjOverReset(gameObj)
            
    GameWorld.DebugLog("回合制战斗结束: mapID=%s,funcLineID=%s,tagPlayerID=%s,isWin=%s,overState=%s"
    GameWorld.DebugLog("===== 回合制战斗结束: mapID=%s,funcLineID=%s,tagPlayerID=%s,isWin=%s,overState=%s"
                       % (mapID, funcLineID, tagPlayerID, isWin, overState), playerID)
    return
@@ -195,11 +198,31 @@
        pass
    return
def TurnFightObjTurnStart(gameObj, turnNum):
    ## 回合制战斗实例 - 每回合开始时处理
    if not gameObj:
        return
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightNum, turnNum)
    # 重置连击、反击数
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, 0)
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkBackNum, 0)
    objType = gameObj.GetGameObjType()
    if objType == IPY_GameWorld.gotPlayer:
        pass
    elif objType == IPY_GameWorld.gotNPC:
        pass
    return
def TurnFightObjOverReset(gameObj):
    ## 回合制战斗实例结束重置
    if not gameObj:
        return
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightNum, 0)
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, 0)
    
    objType = gameObj.GetGameObjType()
    if objType == IPY_GameWorld.gotPlayer:
@@ -212,17 +235,107 @@
            
    return
def DoAttack(curObj, tagObj, tick):
    curID = curObj.GetID()
    tagID = tagObj.GetID()
    if curObj.GetGameObjType() == IPY_GameWorld.gotPlayer:
        atkRet = PlayerAttack(curObj, tagObj, tick)
    else:
        atkRet = NPCAttack(curObj, tagObj, tick)
    turnBattleType = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnBattleType)
    curObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, 0) # 无论攻击成功与否都重置战斗类型
    if not atkRet:
        return
    if turnBattleType == ChConfig.TurnBattleType_Combo:
        comboNum = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnComboNum) + 1
        curObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, comboNum)
        GameWorld.DebugLog("            连击: comboID=%s,comboNum=%s" % (curID, comboNum))
    elif turnBattleType == ChConfig.TurnBattleType_AtkBack:
        atkBackNum = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnAtkBackNum) + 1
        curObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkBackNum, atkBackNum)
        GameWorld.DebugLog("            反击: atkBackID=%s,atkBackNum=%s" % (curID, atkBackNum))
    GameWorld.DebugLog("            curID-HP=(%s-%s),tagID-HP=(%s-%s)" % (curID, GameObj.GetHP(curObj), tagID, GameObj.GetHP(tagObj)))
    # 反击,反击可打断连击,所以优先判断
    if CanAtkBack(curObj, tagObj):
        DoAttack(tagObj, curObj, tick)
        return
    # 连击
    if CanCombo(curObj, tagObj):
        DoAttack(curObj, tagObj, tick)
    return
def CanAtkBack(atkObj, defObj):
    ## 可否反击
    defAtkBackRate = GameObj.GetAtkBackRate(defObj) # 防方反击率
    atkBackNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnAtkBackNum) # 已反击次数
    if atkBackNum > 10:
        # 内置最高反击数防范
        return False
    if atkBackNum > 0:
        validPerList = IpyGameDataPY.GetFuncEvalCfg("TurnFight", 4)
        vaildPer = validPerList[atkBackNum - 1] if len(validPerList) >= atkBackNum else 0
        defAtkBackRate = int(defAtkBackRate * vaildPer / 100.0)
    atkAtkBackDefRate = GameObj.GetAtkBackDefRate(atkObj) # 攻方抵抗反击率
    atkBackRate = max(0, defAtkBackRate - atkAtkBackDefRate)
    if atkBackRate <= 0 or not GameWorld.CanHappen(atkBackRate):
        GameWorld.DebugLog("            无法反击: defID=%s,atkBackNum=%s,atkBackRate=%s=(defAtkBackRate=%s - atkAtkBackDefRate=%s)"
                           % (defObj.GetID(), atkBackNum, atkBackRate, defAtkBackRate, atkAtkBackDefRate))
        return False
    GameWorld.DebugLog("            可以反击: defID=%s,atkBackNum=%s,atkBackRate=%s=(defAtkBackRate=%s - atkAtkBackDefRate=%s)"
                       % (defObj.GetID(), atkBackNum, atkBackRate, defAtkBackRate, atkAtkBackDefRate))
    defObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, ChConfig.TurnBattleType_AtkBack)
    return True
def CanCombo(atkObj, defObj):
    ## 可否连击
    atkComboRate = GameObj.GetComboRate(atkObj) # 攻方连击率
    comboNum = atkObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnComboNum) # 已连击次数
    if comboNum > 10:
        # 内置最高连击数防范
        return False
    if comboNum > 0:
        validPerList = IpyGameDataPY.GetFuncEvalCfg("TurnFight", 3)
        vaildPer = validPerList[comboNum - 1] if len(validPerList) >= comboNum else 0
        atkComboRate = int(atkComboRate * vaildPer / 100.0)
    defComboReduce = GameObj.GetComboDefRate(defObj) # 防方抵抗连击率
    comboRate = max(0, atkComboRate - defComboReduce)
    if comboRate <= 0 or not GameWorld.CanHappen(comboRate):
        GameWorld.DebugLog("            无法连击: atkID=%s,comboNum=%s,comboRate=%s=(atkComboRate=%s - defComboReduce=%s)"
                           % (atkObj.GetID(), comboNum, comboRate, atkComboRate, defComboReduce))
        return False
    GameWorld.DebugLog("            可以连击: atkID=%s,comboNum=%s,comboRate=%s=(atkComboRate=%s - defComboReduce=%s)"
                       % (atkObj.GetID(), comboNum, comboRate, atkComboRate, defComboReduce))
    atkObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, ChConfig.TurnBattleType_Combo)
    return True
def NPCAttack(curObj, tagObj, tick):
    ## NPC攻击
    if not curObj:
        return
    tagDist = 0
    atkRet = AICommon.DoAutoUseSkill(curObj, tagObj, tagDist, tick)
    #---优先释放技能---
    if not AICommon.DoAutoUseSkill(curObj, tagObj, tagDist, tick):
    if not atkRet:
        #普通攻击
        isOK = BaseAttack.Attack(curObj, tagObj, None, tick)
        GameWorld.DebugLog("        NPC普通攻击: curID=%s,tagID=%s,isOK=%s" % (curObj.GetID(), tagObj.GetID(), isOK))
    return
        atkRet = BaseAttack.Attack(curObj, tagObj, None, tick)
        if atkRet:
            GameWorld.DebugLog("        NPC普通攻击: curID=%s,tagID=%s,atkRet=%s" % (curObj.GetID(), tagObj.GetID(), atkRet))
        else:
            GameWorld.DebugLog("        NPC攻击失败: curID=%s,tagID=%s,atkRet=%s" % (curObj.GetID(), tagObj.GetID(), atkRet))
    else:
        GameWorld.DebugLog("        NPC技能攻击: curID=%s,tagID=%s,atkRet=%s" % (curObj.GetID(), tagObj.GetID(), atkRet))
    return atkRet
def PlayerAttack(curPlayer, tagObj, tick):
    ## 玩家攻击, 参考技能使用 #def UseSkillEx(index, clientData, tick):
@@ -246,6 +359,7 @@
    #PlayerControl.SetIsNeedProcess(curPlayer, True)
    #PlayerControl.ChangePlayerAction(curPlayer, IPY_GameWorld.paAttack)
    
    useSkillResult = False
    skillMgr = curPlayer.GetSkillManager()
    for skillID in skillList:
        curSkill = skillMgr.FindSkillBySkillID(skillID)
@@ -265,12 +379,13 @@
        if not PlayerState.__DoClientUseSkillEx(curPlayer, useSkillData, tick):
            GameWorld.DebugLog("        技能攻击失败%s" % skillID, playerID)
            continue
        useSkillResult = True
        GameWorld.DebugLog("        技能攻击成功%s" % skillID, playerID)
        
        break
    
    curPlayer.ClearUseSkillRec()
    return
    return useSkillResult
def SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, state, turnNum=0, turnMax=0):
    clientPack = ChPyNetSendPack.tagMCTurnFightState()