From afea2d9d4b9cb6d0982c02a775e8198fc2421c53 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 08 十二月 2023 18:21:28 +0800
Subject: [PATCH] 10019 【砍树】回合战斗(增加抗连击、反击、抗反击、吸血、抗吸血属性,玩家及NPC属性接口通用;连击、反击属性效果支持;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py |  157 +++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 136 insertions(+), 21 deletions(-)

diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
index 7f2d67d..375d744 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/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()

--
Gitblit v1.8.0