From 860db4b0dc36c4bde60e0069c442446c80bd72b6 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 02 九月 2025 17:07:49 +0800
Subject: [PATCH] 129 【战斗】战斗系统-服务端(关卡boss改为B410请求战斗,支持多小队一次性完整战报;B420增加状态6代表结束并休息;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py |  228 +++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 134 insertions(+), 94 deletions(-)

diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py
index bae12fc..cef5c8b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py
@@ -17,17 +17,20 @@
 
 import ChConfig
 import GameWorld
+import TurnAttack
 import ShareDefine
-import SkillCommon
 import IpyGameDataPY
 import PlayerControl
 import ChPyNetSendPack
 import ItemControler
 import IPY_GameWorld
 import NetPackCommon
-import TurnAttack
 import ItemCommon
+import PlayerTask
 import NPCCommon
+import ChEquip
+import ObjPool
+
 import random
 
 def OnFBPlayerOnLogin(curPlayer):
@@ -41,6 +44,7 @@
 def ResetBootyDropToday(curPlayer):
     bootyItemIDList = GetBootyItemIDList()
     for itemID in bootyItemIDList:
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntBooty % itemID, 0)
         if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BootyDropToday % itemID):
             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BootyDropToday % itemID, 0)
     SyncDropBootyInfo(curPlayer)
@@ -62,63 +66,21 @@
     ipyData = ipyDataMgr.GetMainChapterByIndex(chapterCount - 1)
     return [booty[0] for booty in ipyData.GetDailyBootyUpperList()]
 
-def OnPlayerLineupAttackSuccess(curPlayer, atkObj, defObj, curSkill, mapID, funcLineID):
-    ## 回合战斗主动发起的玩家阵容释放技能成功
+def OnPlayerLineupAttackResult(curPlayer, atkObj, killObjIDList, useSkill, mapID, funcLineID):
+    ## 回合战斗主动发起的玩家阵容攻击结果额外处理 ,一般处理副本相关的掉落、奖励等
     
     if mapID == ChConfig.Def_FBMapID_Main:
-        __doCostZhanchui(curPlayer, atkObj, curSkill)
+        __doKillAward(curPlayer, atkObj, killObjIDList)
         
     return
 
-def __doCostZhanchui(curPlayer, atkObj, curSkill):
-    ## 扣除战锤消耗
-    costZhanchui = 0
-    isXP = SkillCommon.isXPSkill(curSkill)
-    turnBattleType = atkObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnBattleType)
-    if isXP:
-        costZhanchui = IpyGameDataPY.GetFuncCfg("ZhanchuiCost", 2)
-    elif turnBattleType == ChConfig.TurnBattleType_Combo:
-        costZhanchui = IpyGameDataPY.GetFuncCfg("ZhanchuiCost", 3)
-    elif turnBattleType == ChConfig.TurnBattleType_AtkBack:
-        costZhanchui = IpyGameDataPY.GetFuncCfg("ZhanchuiCost", 4)
-    elif SkillCommon.isTurnNormalAtkSkill(curSkill):
-        costZhanchui = IpyGameDataPY.GetFuncCfg("ZhanchuiCost", 1)
-        
-    if costZhanchui <= 0:
-        return
-    
-    fightPoint = max(curPlayer.GetFightPoint(), 1) # 主线战斗消耗倍值,默认1
-    costZhanchuiTotal = costZhanchui * fightPoint
-    if not PlayerControl.PayMoney(curPlayer, ShareDefine.TYPE_Price_Xiantao, costZhanchuiTotal, isNotify=False):
-        # 不足时,有多少扣多少
-        nowMoney = PlayerControl.GetMoney(curPlayer, ShareDefine.TYPE_Price_Xiantao)
-        PlayerControl.PayMoney(curPlayer, ShareDefine.TYPE_Price_Xiantao, min(nowMoney, costZhanchuiTotal), isNotify=False)
-        
-    return
-
-def OnPlayerLineupAttackResult(curPlayer, atkObj, defObj, curSkill, mapID, funcLineID):
-    
-    if mapID == ChConfig.Def_FBMapID_Main:
-        __doKillAward(curPlayer, atkObj, mapID, funcLineID)
-        
-    return
-
-def __doKillAward(curPlayer, atkObj, mapID, funcLineID):
+def __doKillAward(curPlayer, atkObj, killObjIDList):
     ## 计算击杀奖励
-    turnFight = TurnAttack.GetTurnFightMgr().getNPCTurnFight(atkObj.GetID())
-    if not turnFight:
+    if not killObjIDList:
+        GameWorld.DebugLog("没有击杀不需要处理!")
         return
-    
-    unXiantaoCntExp = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntExp)
-    if not turnFight.playerKillObjIDList:
-        unXiantaoCntEquip = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip)
-        GameWorld.DebugLog("没有击杀不需要处理! unXiantaoCntExp=%s,unXiantaoCntEquip=%s" % (unXiantaoCntExp, unXiantaoCntEquip))
-        return
-    killCnt = len(turnFight.playerKillObjIDList)
-    # 直接重置,防止异常时重复结算
-    turnFight.playerKillObjIDList = []
-    
     # 结算经验
+    unXiantaoCntExp = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntExp)
     if unXiantaoCntExp:
         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntExp, 0)
         perExp = IpyGameDataPY.GetFuncCfg("Mainline", 1) # 每个战锤增加经验
@@ -126,76 +88,93 @@
         GameWorld.DebugLog("增加经验: totalExp=%s,unXiantaoCntExp=%s" % (totalExp, unXiantaoCntExp))
         PlayerControl.PlayerControl(curPlayer).AddExp(totalExp, ShareDefine.Def_ViewExpType_KillNPC)
         
-    __doMainDrop(curPlayer, killCnt)
+    __doMainDrop(curPlayer)
     return
 
-def __doMainDrop(curPlayer, killCnt):
+def __doMainDrop(curPlayer):
     # 装备掉落
-    __doDropEquip(curPlayer)
+    if __doDropEquip(curPlayer) == -1:
+        return
     
     playerID = curPlayer.GetPlayerID()
-    DailyBootyUpperList, BootyWeightList = [], []
+    DailyBootyUpperList = []
     chapterID = PlayerControl.GetMainLevelNowInfo(curPlayer)[0]
     chapterIpyData = IpyGameDataPY.GetIpyGameData("MainChapter", chapterID)
     if chapterIpyData:
         DailyBootyUpperList = chapterIpyData.GetDailyBootyUpperList()
-        BootyWeightList = chapterIpyData.GetBootyWeightList()
-        
-    bootyDropUpperDict = {k:v for k, v in DailyBootyUpperList}    
-    GameWorld.DebugLog("可掉落战利品上限: chapterID=%s,%s,killCnt=%s" % (chapterID, bootyDropUpperDict, killCnt), playerID)
+           
+    GameWorld.DebugLog("可掉落战利品上限: chapterID=%s, %s" % (chapterID, DailyBootyUpperList), playerID)
+    
+    # 战利品掉落默认不堆叠,故最多只能掉落剩余空格子个数的物品
+    spaceCount = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptIdentify)
     
     # 其他战利品掉落
-    for _ in range(killCnt):
-        dropInfo = GameWorld.GetResultByWeightList(BootyWeightList)
-        if not dropInfo:
-            continue
-        itemID = dropInfo[0]
-        if not itemID:
-            GameWorld.DebugLog("本次不掉落战利品!", playerID)
-            continue
-        if itemID not in bootyDropUpperDict:
-            GameWorld.DebugLog("该战利品未解锁! itemID=%s" % itemID, playerID)
+    bootyDropNeedDict = IpyGameDataPY.GetFuncEvalCfg("MainBootyDrop", 1, {})
+    bootyDropCntDict = IpyGameDataPY.GetFuncEvalCfg("MainBootyDrop", 2, {})
+    for itemID, dropUpper in DailyBootyUpperList:
+        if spaceCount <= 0:
+            GameWorld.DebugLog("掉落背包已满!", playerID)
+            break
+        if dropUpper <= 0:
             continue
         todyDropCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BootyDropToday % itemID)
-        dropUpper = bootyDropUpperDict.get(itemID, 0)
         if todyDropCnt >= dropUpper:
             GameWorld.DebugLog("战利品已达今日掉落上限! itemID=%s,todyDropCnt=%s >= %s" % (itemID, todyDropCnt, dropUpper), playerID)
             continue
+        if itemID not in bootyDropNeedDict or itemID not in bootyDropCntDict:
+            continue
+        dropOneNeed = bootyDropNeedDict[itemID]
+        unXiantaoCntBooty = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntBooty % itemID)
+        dropBootyCnt = unXiantaoCntBooty / dropOneNeed
+        if dropBootyCnt <= 0:
+            continue
         
-        dropMin = dropInfo[1] if len(dropInfo) > 1 else 1
-        dropMax = dropInfo[2] if len(dropInfo) > 2 else 1
+        dropCntRange = bootyDropCntDict[itemID]
+        if not isinstance(dropCntRange, (list, tuple)) or len(dropCntRange) != 2:
+            continue
+        dropMin = dropCntRange[0]
+        dropMax = dropCntRange[1]
         
-        if dropMin == dropMax:
-            dropCnt = dropMin
-        else:
-            dropCnt = random.randint(dropMin, dropMax)
-        dropCnt = min(dropCnt, dropUpper - todyDropCnt)
+        dropCntTotal = 0
+        for _ in range(dropBootyCnt):
+            if dropMin == dropMax:
+                dropCnt = dropMin
+            else:
+                dropCnt = random.randint(dropMin, dropMax)
+            dropCntTotal += dropCnt
+        dropCntTotal = min(dropCntTotal, dropUpper - todyDropCnt)
+        if dropCntTotal <= 0:
+            continue
         
-        GameWorld.DebugLog("掉落战利品! itemID=%s,dropCnt=%s" % (itemID, dropCnt), playerID)
-        curItem = ItemControler.GetOutPutItemObj(itemID, dropCnt, False, curPlayer=curPlayer)
+        GameWorld.DebugLog("掉落战利品! itemID=%s,unXiantaoCntBooty=%s,次数=%s,dropCntTotal=%s,spaceCount=%s" 
+                           % (itemID, unXiantaoCntBooty, dropBootyCnt, dropCntTotal, spaceCount), playerID)
+        curItem = ItemControler.GetOutPutItemObj(itemID, dropCntTotal, False, curPlayer=curPlayer)
         if curItem == None:
             continue
         curItem.SetIsBind(1) # 为1时代表是掉落
         if not ItemControler.DoLogic_PutItemInPack(curPlayer, curItem, packIndexList=[IPY_GameWorld.rptIdentify]):
             continue
-        SetBootyDropToday(curPlayer, itemID, todyDropCnt + dropCnt)
-                
+        unXiantaoCntBooty = unXiantaoCntBooty % dropOneNeed
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntBooty % itemID, unXiantaoCntBooty)
+        SetBootyDropToday(curPlayer, itemID, todyDropCnt + dropCntTotal)
+        spaceCount -= 1
+        
     return
 
 def __doDropEquip(curPlayer):
     ## 主线掉落装备
+    playerID = curPlayer.GetPlayerID()
     unXiantaoCntEquip = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip)
     dropOneNeed = IpyGameDataPY.GetFuncCfg("MainEquipDrop", 1) # 每消耗X个战锤掉落一件装备
     dropEquipCnt = unXiantaoCntEquip / dropOneNeed
     if dropEquipCnt <= 0:
-        GameWorld.DebugLog("主线暂不能掉落! unXiantaoCntEquip=%s,dropOneNeed=%s,dropEquipCnt=%s" % (unXiantaoCntEquip, dropOneNeed, dropEquipCnt))
+        GameWorld.DebugLog("主线暂不能掉落! unXiantaoCntEquip=%s,dropOneNeed=%s,dropEquipCnt=%s" % (unXiantaoCntEquip, dropOneNeed, dropEquipCnt), playerID)
         return
     dropEquipCnt = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptIdentify, dropEquipCnt)
     if not dropEquipCnt:
-        GameWorld.DebugLog("掉落鉴定背包没有空间!")
-        return
+        GameWorld.DebugLog("掉落背包已满!", playerID)
+        return -1
     
-    playerID = curPlayer.GetPlayerID()    
     treeLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TreeLV)
     ipyData = IpyGameDataPY.GetIpyGameData("TreeLV", treeLV)
     if not ipyData:
@@ -222,7 +201,7 @@
         itemColor = GameWorld.GetResultByRandomList(colorRateList)
         if not itemColor:
             continue
-        equipIDList = NPCCommon.__GetEquipIDList(0, color=itemColor, findType="MainEquipDrop")
+        equipIDList = NPCCommon.__GetEquipIDList(0, color=itemColor, placeList=ChConfig.Def_MainEquipPlaces, findType="MainEquipDrop")
         if not equipIDList:
             continue
         randEquipID = random.choice(equipIDList)
@@ -241,14 +220,23 @@
         
     return
 
-def GMTestKillDrop(curPlayer, killCnt):
+def GMTestKillDrop(curPlayer, unXiantao):
     ## GM测试掉落
-    unXiantaoCntEquip = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip) + killCnt
+    unXiantaoCntEquip = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip) + unXiantao
     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntEquip, unXiantaoCntEquip)
-    __doMainDrop(curPlayer, killCnt)
-    
-    unXiantaoCntEquip = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip)
-    GameWorld.DebugAnswer(curPlayer, "剩余未结算装备掉落战锤数:%s" % unXiantaoCntEquip)
+    GameWorld.DebugAnswer(curPlayer, "未结算装备战锤数: %s" % unXiantaoCntEquip)
+    chapterID = PlayerControl.GetMainLevelNowInfo(curPlayer)[0]
+    chapterIpyData = IpyGameDataPY.GetIpyGameData("MainChapter", chapterID)
+    if chapterIpyData:
+        DailyBootyUpperList = chapterIpyData.GetDailyBootyUpperList()
+        for itemID, upperCnt in DailyBootyUpperList:
+            if upperCnt <= 0:
+                continue
+            unXiantaoCntBooty = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntBooty % itemID) + unXiantao
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntBooty % itemID, unXiantaoCntBooty)
+            GameWorld.DebugAnswer(curPlayer, "未结算战利品(%s)战锤数: %s" % (itemID, unXiantaoCntBooty))
+            
+    __doMainDrop(curPlayer)
     return
 
 #// B4 15 主线掉落物品操作 #tagCSMainDropItemOP
@@ -274,6 +262,7 @@
     else:
         __doPickupMainItem(curPlayer, itemIndexList)
         
+    ItemCommon.SyncMakeItemAnswer(curPlayer, ShareDefine.Def_mitMainDropItemOP, ChConfig.Def_ComposeState_Sucess, opType)
     return
 
 def __doEquipMainEquip(curPlayer, itemIndexList, isAutoDecompose):
@@ -319,7 +308,9 @@
         __doDecomposeMainEquip(curPlayer, decomposeIndexList)
         
     # 刷属性
+    ChEquip.RefreshRoleEquipAttr(curPlayer)
     
+    PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_EquipColor)
     return
 
 def __doDecomposeMainEquip(curPlayer, itemIndexList):
@@ -333,6 +324,7 @@
     
     moneyTotal = 0
     
+    decomposeCnt = 0
     decomposeIndexList = []
     for itemIndex in itemIndexList:
         if itemIndex < 0 or itemIndex >= IdentifyPack.GetCount():
@@ -363,11 +355,13 @@
         
         ItemCommon.DelItem(curPlayer, curEquip, curEquip.GetCount(), True, ChConfig.ItemDel_EquipDecompose)
         decomposeIndexList.append(itemIndex)
+        decomposeCnt += 1
         
     if not moneyTotal:
         return
     
     PlayerControl.GiveMoney(curPlayer, moneyType, moneyTotal, "DecomposeMainEquip", isSysHint=False)
+    PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_EquipDecompose, decomposeCnt)
     return
 
 def __doPickupMainItem(curPlayer, itemIndexList):
@@ -404,13 +398,59 @@
         syncItemIDList = GetBootyItemIDList()
     else:
         syncItemIDList = [itemID]
-    clientPack = ChPyNetSendPack.tagSCDropBootyInfo()
+    poolMgr = ObjPool.GetPoolMgr()
+    clientPack = poolMgr.acquire(ChPyNetSendPack.tagSCDropBootyInfo)
     clientPack.DropBootyList = []
     for itemID in syncItemIDList:
-        dropBooty = ChPyNetSendPack.tagSCDropBooty()
+        dropBooty = poolMgr.acquire(ChPyNetSendPack.tagSCDropBooty)
         dropBooty.ItemID = itemID
         dropBooty.TodayDropCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BootyDropToday % itemID)
         clientPack.DropBootyList.append(dropBooty)
     clientPack.Count = len(clientPack.DropBootyList)
     NetPackCommon.SendFakePack(curPlayer, clientPack)
     return
+
+def OnTurnFightOver(curPlayer, turnFight, mapID, funcLineID, overMsg):
+    ## 回合战斗结束
+    
+    if not curPlayer:
+        return
+    
+    #winFaction = turnFight.winFaction
+    isWin = turnFight.isWin
+    
+    playerID = curPlayer.GetPlayerID()
+    mainFightMgr = TurnAttack.GetMainFightMgr(curPlayer)
+    chapterID, levelNum, wave = PlayerControl.GetMainLevelNowInfo(curPlayer)
+    
+    if not isWin:
+        nextWave = max(1, wave - 1)
+        nowValue = PlayerControl.SetMainLevelNowInfo(curPlayer, chapterID, levelNum, nextWave)
+        GameWorld.DebugLog("主线小怪战斗失败,降一波! chapterID=%s,levelNum=%s,wave=%s,nextWave=%s,nowValue=%s" 
+                           % (chapterID, levelNum, wave, nextWave, nowValue), playerID)
+        return
+    
+    if turnFight.haveNextLineup():
+        GameWorld.DebugLog("主线小怪战斗胜利,有下一小队! chapterID=%s,levelNum=%s,wave=%s" % (chapterID, levelNum, wave), playerID)
+        return
+    
+    # 获胜过波
+    if wave < mainFightMgr.waveMax:
+        nextWave = min(mainFightMgr.waveMax, wave + 1)
+        nowValue = PlayerControl.SetMainLevelNowInfo(curPlayer, chapterID, levelNum, nextWave)
+        GameWorld.DebugLog("主线小怪波战斗胜利,下一波! chapterID=%s,levelNum=%s,wave=%s,nextWave=%s,nowValue=%s" 
+                           % (chapterID, levelNum, wave, nextWave, nowValue), playerID)
+    else:
+        GameWorld.DebugLog("主线小怪波战斗胜利,最后一波循环刷! chapterID=%s,levelNum=%s,wave=%s" % (chapterID, levelNum, wave), playerID)
+        
+    # 小怪可能会退波,所以只在有超过已过关卡进度时才更新值
+    hisPassValue = PlayerControl.GetMainLevelPassValue(curPlayer)
+    curPassValue = PlayerControl.ComMainLevelValue(chapterID, levelNum, wave)
+    if curPassValue > hisPassValue:
+        GameWorld.DebugLog("更新当前过关进度! curPassValue=%s,hisPassValue=%s" % (curPassValue, hisPassValue), playerID)
+        PlayerControl.SetMainLevelPassValue(curPlayer, curPassValue)
+    else:
+        GameWorld.DebugLog("未超过当前过关进度,不更新! curPassValue=%s <= hisPassValue=%s" % (curPassValue, hisPassValue), playerID)
+        
+    return
+

--
Gitblit v1.8.0