From 81d4c82d07f4d5aff78c40579049ae70a94163d5 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 06 二月 2024 18:08:13 +0800
Subject: [PATCH] 10019 【砍树】回合战斗(增加道法技能支持;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py |  164 +++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 135 insertions(+), 29 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 dd30895..833acea 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -9,7 +9,7 @@
 # @date 2023-11-30
 # @version 1.0
 #
-# 详细描述: 回合制攻击逻辑
+# 详细描述: 回合制攻击逻辑,均使用NPC实例作为战斗主体
 #
 #-------------------------------------------------------------------------------
 #"""Version = 2023-11-30 15:30"""
@@ -174,8 +174,9 @@
         playerID = 0
         sightLevel, posX, posY = 99, 192, 109 # 系统默认处理的层级及坐标
         
-    objRetA = __SummonFactionObjs(factionInfoA, sightLevel, posX, posY)
-    objRetB = __SummonFactionObjs(factionInfoB, sightLevel, posX, posY)
+    factionA, factionB, mainRolePlace = 1, 2, 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, [])
     objB, petObjListB, factionSyncInfoB = objRetB if objRetB else (None, [])
     if not objA or not objB:
@@ -194,15 +195,13 @@
     atkFactionList = [factionListA, factionListB]
     
     # 设置战斗主体
-    objA.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1)
-    objB.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1)
     objA.SetDict(ChConfig.Def_Obj_Dict_TurnEnemyID, objB.GetID())
     objB.SetDict(ChConfig.Def_Obj_Dict_TurnEnemyID, objA.GetID())
     
     # 战斗前初始化,可能会改变攻速,所以先初始化
-    for faction, factionObjList in enumerate(atkFactionList, 1):
+    for factionObjList in atkFactionList:
         for gameObj in factionObjList:
-            TurnFightObjStartInit(playerID, gameObj, faction, tick)
+            TurnFightObjStartInit(playerID, gameObj, tick)
             
     #一个回合攻击顺序,为了后续逻辑统一,都是先确定好顺序
     sortType = 2 # 攻击顺序排序方式
@@ -268,7 +267,7 @@
             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))
             
-            if not DoAttack(gameObj, tagGameObj, tick):
+            if not DoAttack(gameObj, tagGameObj, tick, checkUseXP=True):
                 continue
             
             isWin = CheckIswin(objA, objB)
@@ -313,13 +312,17 @@
                        % (mapID, funcLineID, playerIDA, playerIDB, isWin))
     return isWin, turnNum, turnMax, factionTotalHurtDict, playbackID
 
-def __SummonFactionObjs(factionInfo, sightLevel, posX, posY):
-    ## 召唤阵营战斗实例
+def __SummonFactionObjs(faction, mainRolePlace, objInfo, sightLevel, posX, posY):
+    '''召唤阵营战斗实例
+    @param faction: 所属阵营,目前支持两个阵营,1或2
+    @param mainRolePlace: 战斗主体在该阵营上阵位置,1V1时默认1,多对多时,代表所在阵营位置
+    @param objInfo: 该战斗主体出战信息
+    '''
     factionSyncInfo = {} # 同步前端的阵营信息,包含主ID、灵宠、其他灵通等
-    playerID = factionInfo.get("playerID")
-    npcID = factionInfo.get("npcID")
-    skillIDList = factionInfo.get("skillIDList") # 技能ID列表
-    skillIDExList = factionInfo.get("skillIDExList") # 附加技能ID列表
+    playerID = objInfo.get("playerID")
+    npcID = objInfo.get("npcID")
+    skillIDList = objInfo.get("skillIDList") # 技能ID列表
+    skillIDExList = objInfo.get("skillIDExList") # 附加技能ID列表
     if playerID:
         npcID = ChConfig.Def_NPCID_PVP
         mainObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=sightLevel, mirrorPlayerID=playerID, skillIDList=skillIDList, skillIDExList=skillIDExList)
@@ -331,7 +334,9 @@
         return
     if not mainObj:
         return
-    petObjList = PetControl.CalloutFightPet(mainObj, factionInfo.get("pet"))
+    GameObj.SetFaction(mainObj, faction)
+    mainObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRolePlace, mainRolePlace)
+    petObjList = PetControl.CalloutFightPet(mainObj, objInfo.get("pet"))
     petObjIDList = []
     for petObj in petObjList:
         if petObj:
@@ -362,7 +367,7 @@
     return isWin
 
 def SetKilled(gameObj, killer=None):
-    if not gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightMainRole):
+    if not gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightMainRolePlace):
         #GameWorld.DebugLog("非回合战斗主体被击杀: curID=%s" % gameObj.GetID())
         return
     
@@ -406,7 +411,7 @@
     if not gameObj:
         return
     
-    if not gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightMainRole):
+    if not gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightMainRolePlace):
         # 仅主体可复活
         return
     
@@ -504,6 +509,7 @@
     NetPackCommon.SendFakePack(curPlayer, clientPack)
     return True
 
+def GetTurnNum(timeline): return timeline / 100
 def SetTimeline(gameObj, turnNum, actionNum):
     '''设置回合制战斗所在时间节点
     @param turnNum: 第几回合,如果在回合制战斗中,则回合数一定大于0,
@@ -512,17 +518,17 @@
     gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightTimeline, turnNum * 100 + actionNum)
     return
 
-def TurnFightObjStartInit(playerID, gameObj, faction, tick):
+def TurnFightObjStartInit(playerID, gameObj, tick):
     ## 回合制战斗实例初始化
     if not gameObj:
         return
-    isMainRole = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightMainRole)
+    mainRolePlace = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightMainRolePlace)
     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)
     SetTimeline(gameObj, 1, 0)
-    GameObj.SetFaction(gameObj, faction)
+    faction = GameObj.GetFaction(gameObj)
     GameObj.SetHPFull(gameObj, True)
     gameObj.RefreshView()
     
@@ -531,10 +537,10 @@
     objName = GetObjName(gameObj)
     fightPlaceNum = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_FightPetPlaceNum)
     
-    GameWorld.DebugLog("【 %s 初始化 %s 】 objID=%s,npcID=%s,atkSpeed=%s,isMainRole=%s" 
-                       % (objName, BaseAttack.GetObjAttackName(gameObj), gameObj.GetID(), npcID, GameObj.GetAtkSpeed(gameObj), isMainRole))
-    __logGameObjAttr(gameObj)
+    GameWorld.DebugLog("【 %s 初始化 %s 】 objID=%s,npcID=%s,atkSpeed=%s,faction=%s,mainRolePlace=%s" 
+                       % (objName, BaseAttack.GetObjAttackName(gameObj), gameObj.GetID(), npcID, GameObj.GetAtkSpeed(gameObj), faction, mainRolePlace))
     
+    haveXPSkill = False
     # 重置技能CD、战斗buff
     if objType == IPY_GameWorld.gotPlayer:            
         skillManager = gameObj.GetSkillManager()
@@ -549,6 +555,8 @@
             curSkill = skillManager.GetSkillByIndex(i)
             if not curSkill:
                 continue
+            if mainRolePlace and curSkill.GetXP():
+                haveXPSkill = True
             skillIDList.append(curSkill.GetSkillID())
             if fightPlaceNum:
                 if curSkill.GetSkillType() != ChConfig.Def_SkillType_Revive:
@@ -557,12 +565,19 @@
                     curSkill.SetRemainTime(curSkill.GetCoolDownTime())
         GameWorld.DebugLog("    NPC技能: npcID=%s,skillIDList=%s" % (npcID, skillIDList))
         
+    if haveXPSkill:
+        GameObj.SetMaxXP(gameObj, IpyGameDataPY.GetFuncCfg("TurnFightXP", 1))
+        GameObj.SetXP(gameObj, 0) # 进行设置一次通知前端,视为告知前端该实例有XP
+        gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkAddXPCount, 0)
+        gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnXPFullTimeline, 0)
+        
+    __logGameObjAttr(gameObj)
     return
 
 def __logGameObjAttr(gameObj):
-    GameWorld.DebugLog("    HP=%s/%s,atk=%s~%s,Def=%s,atkSpeed=%s" 
-                       % (GameObj.GetHP(gameObj), GameObj.GetMaxHP(gameObj), gameObj.GetMinAtk(), gameObj.GetMaxAtk(), 
-                          gameObj.GetDef(), GameObj.GetAtkSpeed(gameObj)))
+    GameWorld.DebugLog("    HP=%s/%s,atk=%s~%s,Def=%s,atkSpeed=%s,XP=%s/%s" 
+                       % (GameObj.GetHP(gameObj), GameObj.GetMaxHP(gameObj), gameObj.GetMinAtk(), gameObj.GetMaxAtk(),
+                          gameObj.GetDef(), GameObj.GetAtkSpeed(gameObj), GameObj.GetXP(gameObj), GameObj.GetMaxXP(gameObj)))
     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),
@@ -582,6 +597,8 @@
     # 重置连击、反击数
     gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, 0)
     gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkBackNum, 0)
+    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkAddXPCount, 0)
+    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnXPUseState, 0)
     gameObj.SetDict(ChConfig.Def_PlayerKey_AttrFaintCD, 0) # 击晕CD
     
     objType = gameObj.GetGameObjType()
@@ -718,7 +735,7 @@
     NPCCommon.SetDeadEx(gameObj)
     return
 
-def AddTurnObjHurtValue(curObj, tagObj, hurtType, hurtValue, curSkill=None):
+def AddTurnObjHurtValue(curObj, tagObj, hurtType, hurtValue, lostHP, curSkill=None):
     if not curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightTimeline):
         return
     skillID = curSkill.GetSkillID() if curSkill else 0
@@ -728,13 +745,103 @@
     curObj.SetDict(ChConfig.Def_Obj_Dict_TurnTotalHurtEx, totalHurt / ChConfig.Def_PerPointValue)
     GameWorld.DebugLog("        伤血: curTD=%s,tagID=%s,skillID=%s,hurtType=%s,hurtValue=%s,totalHurt=%s,tagHP=%s" 
                        % (curObj.GetID(), tagObj.GetID(), skillID, hurtType, hurtValue, totalHurt, GameObj.GetHP(tagObj)))
+    
+    if lostHP:
+        AddTurnFightXP(tagObj, __GetAddXP_Defender(tagObj, lostHP), "skillID:%s" % skillID)
+        AddTurnFightXP(curObj, __GetAddXP_Attack(curObj, curSkill), "skillID:%s" % skillID)
     return
 
-def DoAttack(curObj, tagObj, tick, turnBattleType=ChConfig.TurnBattleType_Normal):
+def __GetAddXP_Attack(attack, curSkill):
+    ## 攻击方增加的XP值根据主动攻击次数获得
+    isAddXPSkill = not curSkill or curSkill.GetSkillType() == ChConfig.Def_SkillType_Atk
+    if not isAddXPSkill:
+        return 0
+    atkAddXPCount = attack.GetDictByKey(ChConfig.Def_Obj_Dict_TurnAtkAddXPCount)
+    addXPList = IpyGameDataPY.GetFuncEvalCfg("TurnFightXP", 2)
+    if atkAddXPCount >= len(addXPList):
+        return 0
+    attack.SetDict(ChConfig.Def_Obj_Dict_TurnAtkAddXPCount, atkAddXPCount + 1)
+    return addXPList[atkAddXPCount]
+
+def __GetAddXP_Defender(defender, lostHP):
+    ## 掉血方增加的XP值根据掉血百分比获得
+    maxXP = GameObj.GetMaxXP(defender)
+    if not maxXP:
+        return 0
+    maxHP = GameObj.GetMaxHP(defender)
+    lostHPPer = lostHP / float(maxHP)
+    #GameWorld.DebugLog("        lostHP=%s,lostHPPer=%s" % (lostHP, lostHPPer))
+    return eval(IpyGameDataPY.GetFuncCompileCfg("TurnFightXP", 3))
+
+def AddTurnFightXP(gameObj, addXP, reason=""):
+    ## 回合战斗增加XP
+    if not addXP:
+        #GameWorld.DebugLog("        没有增加XP! curID=%s" % (gameObj.GetID()))
+        return
+    maxXP = GameObj.GetMaxXP(gameObj)
+    if not maxXP:
+        #GameWorld.DebugLog("        无最大XP值,不更新! curID=%s" % (gameObj.GetID()))
+        return
+    curXP = GameObj.GetXP(gameObj)
+    if curXP >= maxXP:
+        #GameWorld.DebugLog("        XP值已满,不更新! curID=%s,curXP=%s" % (gameObj.GetID(), curXP))
+        return
+    updXP = min(curXP + addXP, maxXP)
+    GameObj.SetXP(gameObj, updXP)
+    GameWorld.DebugLog("        更新XP: curID=%s,curXP=%s,addXP=%s,updXP=%s,reason=%s" % (gameObj.GetID(), curXP, addXP, updXP, reason))
+    return
+
+def __CheckUseXPSkill(curObj, tagObj, tick):
+    ## 使用XP技能 - 道法技能
+    maxXP = GameObj.GetMaxXP(curObj)
+    curXP = GameObj.GetXP(curObj)
+    if not maxXP or curXP < maxXP:
+        #GameWorld.DebugLog("        没有XP或XP未满,无法释放XP! curID=%s,curXP=%s" % (curObj.GetID(), curXP))
+        return
+    turnNum = GetTurnNum(curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightTimeline))
+    xpFullTurnNum = GetTurnNum(curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnXPFullTimeline))
+    if turnNum <= xpFullTurnNum:
+        #GameWorld.DebugLog("        XP技能在本回合无法释放! curID=%s, turnNum=%s <= %s" % (curObj.GetID(), turnNum, xpFullTurnNum))
+        return
+    
+    curObj.SetDict(ChConfig.Def_Obj_Dict_TurnXPUseState, 1) # 设置可用
+    
+    tagDist = 0
+    skillManager = curObj.GetSkillManager()
+    for index in range(0, skillManager.GetSkillCount()):
+        curSkill = skillManager.GetSkillByIndex(index)
+        if not curSkill or curSkill.GetSkillTypeID() == 0:
+            break
+        skillID = curSkill.GetSkillID()
+        #被动技能无法使用
+        if SkillCommon.isPassiveSkill(curSkill):
+            continue
+        #还在冷却时间内无法释放
+        if SkillCommon.RefreshSkillRemainTime(curSkill, tick) != 0:
+            continue
+        needXP = curSkill.GetXP()
+        if not needXP or needXP < curXP:
+            continue
+        curID = curObj.GetID()
+        tagID = tagObj.GetID()
+        if not AICommon.DoNPCUseSkill(curObj, tagObj, curSkill, tagDist, tick):
+            GameWorld.DebugLog("        XP技能攻击失败: curID=%s,tagID=%s,skillID=%s" % (curID, tagID, skillID))
+            continue
+        GameWorld.DebugLog("        XP技能攻击成功: curID=%s,tagID=%s,skillID=%s" % (curID, tagID, skillID))
+        curObj.SetDict(ChConfig.Def_Obj_Dict_TurnXPUseState, 2) # 设置已用
+        return skillID
+    
+    return
+
+def DoAttack(curObj, tagObj, tick, turnBattleType=ChConfig.TurnBattleType_Normal, checkUseXP=False):
     curID = curObj.GetID()
     tagID = tagObj.GetID()
     objName = GetObjName(curObj)
     GameWorld.DebugLog("    ● %s DoAttack: curID=%s,tagID=%s,turnBattleType=%s" % (objName, curID, tagID, turnBattleType))
+    if checkUseXP:
+        if __CheckUseXPSkill(curObj, tagObj, tick):
+            return True
+        
     if turnBattleType == ChConfig.TurnBattleType_AtkBack:
         PassiveBuffEffMng.OnPassiveSkillTrigger(curObj, tagObj, None, ChConfig.TriggerType_AtkBackBef, tick)
         
@@ -878,7 +985,6 @@
             continue
         
         if not AICommon.DoNPCUseSkill(playerNPC, tagObj, curSkill, tagDist, tick):
-            GameWorld.DebugLog("        技能攻击失败: playerID=%s,tagID=%s,skillID=%s" % (playerID, tagObjID, skillID))
             continue
         GameWorld.DebugLog("        技能攻击成功: playerID=%s,tagID=%s,skillID=%s" % (playerID, tagObjID, skillID))
         return skillID

--
Gitblit v1.8.0