From e17fcba64e93fceb1459b12cbe70663039d40314 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期四, 11 一月 2024 18:22:45 +0800
Subject: [PATCH] 10019 【砍树】回合战斗(回合战斗buff持续时间处理及持续性buff定时触发时机处理支持;增加回合战斗死亡及复活支持;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py |  255 ++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 211 insertions(+), 44 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 1a11598..4b650a9 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -30,6 +30,7 @@
 import GameWorld
 import GameObj
 import PetControl
+import SkillShell
 
 (
 FightState_Start,
@@ -38,6 +39,10 @@
 FightState_Fail,
 FightState_Over,
 ) = range(5)
+
+(
+RebornType_PetSkill,
+) = range(1, 1 + 1)
 
 def GetObjName(gameObj):
     objName = gameObj.GetName()
@@ -121,10 +126,14 @@
     factionListB = fightPetObjListB + [tagObj]
     atkFactionList = [factionListA, factionListB]
     
+    # 设置战斗主体
+    curPlayer.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1)
+    tagObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1)
+    
     # 战斗前初始化,可能会改变攻速,所以先初始化
     for faction, factionObjList in enumerate(atkFactionList, 1):
         for gameObj in factionObjList:
-            TurnFightObjStartInit(gameObj, faction, tick)
+            TurnFightObjStartInit(playerID, gameObj, faction, tick)
             
     #一个回合攻击顺序,为了后续逻辑统一,都是先确定好顺序
     sortType = 2 # 攻击顺序排序方式
@@ -150,13 +159,29 @@
         for gameObj in fightObjList:
             TurnFightObjPerTurnStart(gameObj, turnNum, tick)
             
+        isWin = CheckIswin(curPlayer, tagObj)
+        if isWin != None:
+            break
+        
         # 回合战斗: 轮流依次攻击
-        for gameObj in fightObjList:
-            if not gameObj or GameObj.GetHP(gameObj) <= 0:
+        for actionNum, gameObj in enumerate(fightObjList, 1):
+            if not gameObj:
+                # 没有对象可视为没有该节点
                 continue
-            faction = GameObj.GetFaction(gameObj)
+            
+            for obj in fightObjList:
+                TurnFightObjPerTurnActionnum(turnNum, actionNum, obj, tick)
+                                                
             objType = gameObj.GetGameObjType()
             objID = gameObj.GetID()
+            SyncTurnFightObjAction(curPlayer, turnNum, objType, objID)
+            
+            if GameObj.GetHP(gameObj) <= 0:
+                # 复活时机在自己行动节点
+                if not DoReborn(gameObj):
+                    continue
+                    
+            faction = GameObj.GetFaction(gameObj)
             objName = GetObjName(gameObj)
             curHP = GameObj.GetHP(gameObj)
             
@@ -165,28 +190,16 @@
             tagObjID = tagGameObj.GetID()
             tagHP = GameObj.GetHP(tagGameObj)
             
-            GameWorld.DebugLog("    ★回合%s %s 行动 : objType-ID-HP(%s-%s-%s), tagType-ID-HP(%s-%s-%s)" 
-                               % (turnNum, objName, objType, objID, curHP, tagObjType, tagObjID, tagHP))
-            SyncTurnFightObjAction(curPlayer, turnNum, objType, objID)
+            GameWorld.DebugLog("    ★回合%s.%s %s 行动 : objType-ID-HP(%s-%s-%s),curAtk=%s, tagType-ID-HP(%s-%s-%s)" 
+                               % (turnNum, actionNum, objName, objType, objID, curHP, gameObj.GetMaxAtk(), tagObjType, tagObjID, tagHP))
             
-            DoAttack(gameObj, tagGameObj, tick)
-            
-            playerDead = GameObj.GetHP(curPlayer) <= 0
-            tagObjDead = (not tagObj or GameObj.GetHP(tagObj) <= 0)
-            if not playerDead and not tagObjDead:
+            if not DoAttack(gameObj, tagGameObj, tick):
                 continue
             
-            if playerDead and tagObjDead:
-                isWin = False # 平局算失败
-                GameWorld.DebugLog("        双方被击杀,平局算失败: isWin=%s" % isWin)
-            elif playerDead:
-                isWin = False
-                GameWorld.DebugLog("        玩家被击杀,失败: isWin=%s" % isWin)
-            elif tagObjDead:
-                isWin = True # 胜利
-                GameWorld.DebugLog("        对手被击杀,胜利: isWin=%s" % isWin)
-            break
-        
+            isWin = CheckIswin(curPlayer, tagObj)
+            if isWin != None:
+                break
+            
         if isWin != None:
             break
         
@@ -200,11 +213,154 @@
                        % (mapID, funcLineID, tagPlayerID, isWin, overState), playerID)
     return
 
-def TurnFightObjStartInit(gameObj, faction, tick):
+def CheckIswin(curPlayer, tagObj):
+    ## 检查是否结束
+    # @return: None-未结束;True-获胜;False-失败
+    playerDead = GameObj.GetHP(curPlayer) <= 0 and GetRebornTypeInfo(curPlayer) == None
+    tagObjDead = (not tagObj or GameObj.GetHP(tagObj) <= 0) and GetRebornTypeInfo(tagObj) == None
+    
+    if not playerDead and not tagObjDead:
+        return
+    
+    isWin = None
+    if playerDead and tagObjDead:
+        isWin = False # 平局算失败
+        GameWorld.DebugLog("        双方被击杀,平局算失败: isWin=%s" % isWin)
+    elif playerDead:
+        isWin = False
+        GameWorld.DebugLog("        玩家被击杀,失败: isWin=%s" % isWin)
+    elif tagObjDead:
+        isWin = True # 胜利
+        GameWorld.DebugLog("        对手被击杀,胜利: isWin=%s" % isWin)
+        
+    return isWin
+
+def SetKilled(gameObj, killer=None):
+    if not gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightMainRole):
+        #GameWorld.DebugLog("非回合战斗主体被击杀: curID=%s" % gameObj.GetID())
+        return
+    
+    GameWorld.DebugLog("        %s 回合战斗主体被击杀: curID=%s" % (GetObjName(gameObj), gameObj.GetID()))
+    GameObj.SetHP(gameObj, 0)
+    
+    playerID = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightID)
+    if not playerID:
+        return
+    curPlayer = GameWorld.GetMapCopyPlayerManager().FindPlayerByID(playerID)
+    if not curPlayer:
+        return
+    
+    # 通知前端
+    clientPack = ChPyNetSendPack.tagMCTurnFightObjDead()
+    clientPack.ObjID = gameObj.GetID()
+    clientPack.ObjType = gameObj.GetGameObjType()
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return True
+
+def GetRebornTypeInfo(gameObj):
+    ''' 获取可复活的方式信息
+    @return: None-代表不可复活
+    '''
+    if not gameObj:
+        return
+    
+    if not gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightMainRole):
+        # 仅主体可复活
+        return
+    
+    rebornCountMax = 1
+    curRebornCount = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnRebornCount)
+    if curRebornCount >= rebornCountMax:
+        GameWorld.DebugLog("%s 已经超过复活次数,不能再复活! curID=%s,curRebornCount=%s" % (GetObjName(gameObj), gameObj.GetID(), curRebornCount))
+        return
+    
+    # 检查是否有灵宠复活技能
+    for index in range(gameObj.GetSummonCount()):
+        curSummonNPC = gameObj.GetSummonNPCAt(index)
+        if not curSummonNPC:
+            continue
+        if not PetControl.IsPetNPC(curSummonNPC):
+            continue
+        skillManager = curSummonNPC.GetSkillManager()
+        for skillIndex in range(skillManager.GetSkillCount()):
+            skill = skillManager.GetSkillByIndex(skillIndex)
+            if skill.GetSkillType() != ChConfig.Def_SkillType_Revive:
+                continue
+            if not skill.GetRemainTime():
+                return RebornType_PetSkill, curSummonNPC, skill
+            
+    # 检查其他功能复活,待扩展...
+    
+    #GameWorld.DebugLog("    没有可以复活的方式!")
+    return
+
+def DoReborn(gameObj, hpPer=ChConfig.Def_MaxRateValue):
+    ## 执行复活
+    rebornTypeInfo = GetRebornTypeInfo(gameObj)
+    if rebornTypeInfo == None:
+        return
+    
+    objName = GetObjName(gameObj)
+    objID = gameObj.GetID()
+    objType = gameObj.GetGameObjType()
+    
+    rebornType = rebornTypeInfo[0]
+    rebornValue1, rebornValue2 = 0, 0
+    if rebornType == RebornType_PetSkill:
+        petNPC, skill = rebornTypeInfo[1:]
+        skill.SetRemainTime(skill.GetCoolDownTime())
+        hpPer = skill.GetEffect(0).GetEffectValue(0)
+        rebornValue1 = petNPC.GetID()
+        rebornValue2 = skill.GetSkillID()
+        
+    rebornCount = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnRebornCount) + 1
+    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnRebornCount, rebornCount)
+    setHP = int(GameObj.GetMaxHP(gameObj) * hpPer / float(ChConfig.Def_MaxRateValue))
+    GameObj.SetHP(gameObj, setHP)
+    
+    if objType == IPY_GameWorld.gotPlayer:
+        gameObj.ChangeAction(IPY_GameWorld.paNull)
+    else:
+        gameObj.ChangeAction(IPY_GameWorld.laNPCNull)
+        
+    curHP = GameObj.GetHP(gameObj)
+    GameWorld.DebugLog("复活 %s: rebornType=%s,objID=%s,hpPer=%s,curHP=%s,rebornCount=%s" % (objName, rebornType, objID, hpPer, curHP, rebornCount))
+    
+    playerID = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightID)
+    if not playerID:
+        return
+    curPlayer = GameWorld.GetMapCopyPlayerManager().FindPlayerByID(playerID)
+    if not curPlayer:
+        return
+    
+    # 通知前端
+    clientPack = ChPyNetSendPack.tagMCTurnFightObjReborn()
+    clientPack.ObjID = gameObj.GetID()
+    clientPack.ObjType = gameObj.GetGameObjType()
+    clientPack.HP = curHP % ChConfig.Def_PerPointValue
+    clientPack.HPEx = curHP / ChConfig.Def_PerPointValue
+    clientPack.RebornType = rebornType
+    clientPack.RebornValue1 = rebornValue1
+    clientPack.RebornValue2 = rebornValue2
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return True
+
+def SetTimeline(gameObj, turnNum, actionNum):
+    '''设置回合制战斗所在时间节点
+    @param turnNum: 第几回合,如果在回合制战斗中,则回合数一定大于0,
+    @param actionNum: 第几个行动节点,每回合的行动节点会重置,也就是说行动节点0可视为每回合的起始节点,1位第一个行动目标节点,以此类推
+    '''
+    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightTimeline, turnNum * 100 + actionNum)
+    return
+
+def TurnFightObjStartInit(playerID, gameObj, faction, tick):
     ## 回合制战斗实例初始化
     if not gameObj:
         return
-    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightNum, 1)
+    isMainRole = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightMainRole)
+    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightID, playerID)
+    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnRebornCount, 0)
+    SetTimeline(gameObj, 1, 0)
     GameObj.SetFaction(gameObj, faction)
     GameObj.SetHPFull(gameObj)
     gameObj.RefreshView()
@@ -214,9 +370,9 @@
     objName = GetObjName(gameObj)
     fightPlaceNum = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_FightPetPlaceNum)
     
-    GameWorld.DebugLog("【 %s 初始化 %s 】 objID=%s,npcID=%s,atkSpeed=%s,HP=%s,Atk=%s,Def=%s" 
-                       % (objName, BaseAttack.GetObjAttackName(gameObj), gameObj.GetID(), npcID, 
-                          GameObj.GetAtkSpeed(gameObj), GameObj.GetHP(gameObj), gameObj.GetMaxAtk(), gameObj.GetDef()))
+    GameWorld.DebugLog("【 %s 初始化 %s 】 objID=%s,npcID=%s,atkSpeed=%s,HP=%s,Atk=%s,Def=%s,isMainRole=%s" 
+                       % (objName, BaseAttack.GetObjAttackName(gameObj), gameObj.GetID(), npcID,
+                          GameObj.GetAtkSpeed(gameObj), GameObj.GetHP(gameObj), gameObj.GetMaxAtk(), gameObj.GetDef(), isMainRole))
     GameWorld.DebugLog("    闪避(%s,%s),暴击(%s,%s),击晕(%s,%s),连击(%s,%s),反击(%s,%s),吸血(%s,%s)" 
                        % (GameObj.GetMissRate(gameObj), GameObj.GetMissDefRate(gameObj),
                           GameObj.GetSuperHitRate(gameObj), GameObj.GetSuperHitRateReduce(gameObj),
@@ -242,9 +398,10 @@
                 continue
             skillIDList.append(curSkill.GetSkillID())
             if fightPlaceNum:
-                # 灵宠技能开始时直接进入CD
-                curSkill.SetLastUseTick(tick)
-                curSkill.SetRemainTime(curSkill.GetCoolDownTime())
+                if curSkill.GetSkillType() != ChConfig.Def_SkillType_Revive:
+                    # 灵宠技能开始时直接进入CD
+                    curSkill.SetLastUseTick(tick)
+                    curSkill.SetRemainTime(curSkill.GetCoolDownTime())
         GameWorld.DebugLog("    NPC技能: npcID=%s,skillIDList=%s" % (npcID, skillIDList))
         
     return
@@ -254,7 +411,7 @@
     if not gameObj:
         return
     
-    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightNum, turnNum)
+    SetTimeline(gameObj, turnNum, 0)
     # 重置连击、反击数
     gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, 0)
     gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkBackNum, 0)
@@ -277,14 +434,23 @@
         skill.SetRemainTime(updRemainTime)
         GameWorld.DebugLog("    skillID=%s,remainTime=%s,updRemainTime=%s" % (skillID, remainTime, updRemainTime))
         
+    # 刷新定时处理的buff效果
+    SkillShell.ProcessPersistBuff(gameObj, tick)
+    return
+
+def TurnFightObjPerTurnActionnum(turnNum, actionNum, gameObj, tick):
+    ## 回合制战斗实例 - 每个行动节点处理
+    if not gameObj:
+        return
+    
+    SetTimeline(gameObj, turnNum, actionNum)
+    
+    objType = gameObj.GetGameObjType()
     if objType == IPY_GameWorld.gotPlayer:
+        #刷新玩家Buff时长
         gameObj.SetTickByType(ChConfig.TYPE_Player_Tick_Buff, 0)
-        gameObj.SetPersistBuffTick(0)
-        
-        #刷新玩家Buff
         reFlashBuff = PlayerState.ProcessRefreshBuffState(gameObj, tick)
-        #刷新玩家场景buff效果
-        PlayerState.ProcessPlayerBuffEffect(gameObj, tick)
+        #SkillShell.ProcessPersistBuff(gameObj, tick) # 定时处理的在每个时间节点有需要再开启,目前默认回合开始处理
         
         attrBuffResult, actBuffResult = PlayerState.ProcessRefreshActionBuffState(gameObj, tick)
         playerControl = PlayerControl.PlayerControl(gameObj)
@@ -311,7 +477,7 @@
     ## 回合制战斗实例结束重置
     if not gameObj:
         return
-    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightNum, 0)
+    SetTimeline(gameObj, 0, 0)
     gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, 0)
     GameObj.SetFaction(gameObj, 0)
     
@@ -324,6 +490,9 @@
     return
 
 def RecycleObj(gameObj):
+    ## 释放回合制战斗对象
+    
+    #灵宠跟召唤兽由主人回收时触发回收,不然会导致报错
     npcObjType = gameObj.GetGameNPCObjType()
     if npcObjType == IPY_GameWorld.gnotPet:
         #GameWorld.DebugLog("RecycleObj 灵宠不回收 objID=%s,npcObjType=%s,%s" % (gameObj.GetID(), npcObjType, gameObj.GetNPCID()))
@@ -333,9 +502,7 @@
         if curOwner and curOwner.GetGameObjType() == IPY_GameWorld.gotNPC:
             #GameWorld.DebugLog("RecycleObj 召唤兽主人是NPC不回收 objID=%s,npcObjType=%s,%s,ownerID=%s" % (gameObj.GetID(), npcObjType, gameObj.GetNPCID(), curOwner.GetID()))
             return
-    if GameObj.GetHP(gameObj) <= 0:
-        #GameWorld.DebugLog("RecycleObj 已死亡,不用重复回收 objID=%s,npcObjType=%s,%s" % (gameObj.GetID(), npcObjType, gameObj.GetNPCID()))
-        return
+        
     #GameWorld.DebugLog("RecycleObj: objID=%s,npcObjType=%s,%s" % (gameObj.GetID(), npcObjType, gameObj.GetNPCID()))
     NPCCommon.SetDeadEx(gameObj)
     return
@@ -370,18 +537,18 @@
     tagHP = GameObj.GetHP(tagObj)
     GameWorld.DebugLog("            curID-HP=(%s-%s),tagID-HP=(%s-%s)" % (curID, curHP, tagID, tagHP))
     if tagHP <= 0 or curHP <= 0:
-        return
+        return True
     
     # 反击,反击可打断连击,所以优先判断
     if CanAtkBack(curObj, tagObj):
         DoAttack(tagObj, curObj, tick)
-        return
+        return True
     
     # 连击
     if CanCombo(curObj, tagObj):
         DoAttack(curObj, tagObj, tick)
         
-    return
+    return True
 
 def CanAtkBack(atkObj, defObj):
     ## 可否反击

--
Gitblit v1.8.0