| | |
| | | import BuffSkill |
| | | import FBCommon |
| | | import ItemControler |
| | | import PlayerPet |
| | | |
| | | # 回合战斗流程状态 |
| | | ( |
| | | FightState_Start, |
| | | FightState_Fighting, |
| | | FightState_Win, |
| | | FightState_Fail, |
| | | FightState_Over, |
| | | ) = range(5) |
| | | FightState_Start, # 0 起始状态,无特殊意义,仅代表开始了,与Over对应 |
| | | FightState_PrepareOK, # 1 准备完毕,包含对战NPC召唤OK、其他等 |
| | | FightState_Fighting, # 2 战斗中 |
| | | FightState_FightEnd, # 3 战斗结束 |
| | | FightState_Award, # 4 结算奖励 |
| | | FightState_Over, # 5 结束状态,无特殊意义,仅代表所有处理结束了,与Start对应 |
| | | ) = range(6) |
| | | |
| | | # 回合战斗复活类型 |
| | | ( |
| | | RebornType_PetSkill, |
| | | ) = range(1, 1 + 1) |
| | | |
| | | def GetObjName(gameObj): |
| | | objName = gameObj.GetName() |
| | | mirrorPlayerID = gameObj.GetDictByKey(ChConfig.Def_NPC_Dict_MirrorPlayerID) |
| | | if mirrorPlayerID: |
| | | objName = "%s[%s]" % (objName, mirrorPlayerID) |
| | | faction = GameObj.GetFaction(gameObj) |
| | | fightPlaceNum = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_FightPetPlaceNum) |
| | | curID = gameObj.GetNPCID() if gameObj.GetGameObjType() == IPY_GameWorld.gotNPC else "" |
| | | return "%s%s %s%s" % ("A" if faction == 1 else "B", fightPlaceNum, objName, curID) |
| | | curID = gameObj.GetDictByKey(ChConfig.Def_NPC_Dict_MirrorPlayerID) |
| | | if not curID and gameObj.GetGameObjType() == IPY_GameWorld.gotNPC: |
| | | curID = gameObj.GetNPCID() |
| | | return "%s%s %s[%s-%s]" % ("A" if faction == 1 else "B", fightPlaceNum, objName, gameObj.GetID(), curID) |
| | | |
| | | #// B4 10 回合制战斗 #tagCMTurnFight |
| | | # |
| | |
| | | |
| | | def DoTrunFight(curPlayer, mapID, funcLineID, tagPlayerID, tick): |
| | | playerID = curPlayer.GetPlayerID() |
| | | posX, posY = curPlayer.GetPosX(), curPlayer.GetPosY() |
| | | GameWorld.DebugLog("===== 执行回合制战斗: mapID=%s,funcLineID=%s,playerID=%s,tagPlayerID=%s" % (mapID, funcLineID, playerID, tagPlayerID)) |
| | | |
| | | PlayerViewCacheTube.UpdPlayerPropPlusCache(curPlayer) # 强制刷一下自己的镜像缓存 |
| | | factionInfoA = {"playerID":playerID, "pet":PlayerPet.GetPetCacheInfo(curPlayer)} |
| | | factionInfoB = {} |
| | | ipyData = None |
| | | tagObj = None |
| | | if tagPlayerID: |
| | | npcID = ChConfig.Def_NPCID_PVP |
| | | tagObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=playerID, mirrorPlayerID=tagPlayerID) |
| | | if not tagObj: |
| | | return |
| | | PlusData = PlayerViewCacheTube.GetPlayerPropPlusDictByID(playerID)[1] # 从缓存中获取 |
| | | petCacheInfo = PlusData.get("Pet") |
| | | fightPetObjListB = PetControl.CalloutFightPet(tagObj, petCacheInfo) |
| | | PlusData = PlayerViewCacheTube.GetPlayerPropPlusDictByID(tagPlayerID)[1] # 从缓存中获取 |
| | | factionInfoB = {"playerID":tagPlayerID, "pet":PlusData.get("Pet")} |
| | | else: |
| | | ipyData = IpyGameDataPY.GetIpyGameData("FBTurn", mapID, funcLineID) |
| | | if not ipyData: |
| | |
| | | npcID = ipyData.GetNPCID() |
| | | if not npcID: |
| | | return |
| | | tagObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=playerID) |
| | | if not tagObj: |
| | | return |
| | | petNPCIDList = ipyData.GetPetNPCIDList() |
| | | petCacheInfo = [] # 从配表中读取组合,技能默认取NPC表配置的 |
| | | for state, petNPCID in enumerate(petNPCIDList, 1): |
| | | petCacheInfo.append({"npcID":petNPCID, "state":state, "quality":0}) |
| | | fightPetObjListB = PetControl.CalloutFightPet(tagObj, petCacheInfo) |
| | | factionInfoB = {"npcID":npcID, "pet":petCacheInfo} |
| | | |
| | | ret = ProcessAutoTurnFight(mapID, funcLineID, factionInfoA, factionInfoB, tick, curPlayer) |
| | | if not ret: |
| | | return |
| | | isWin, turnNum, turnMax, factionTotalHurtDict, playbackID = ret |
| | | |
| | | # 结算奖励...待扩展 |
| | | awardItemList = [] |
| | | if isWin and ipyData: |
| | | # 山寨测试先默认都是首次奖励,正式后需删除 |
| | | awardItemList = ipyData.GetAwardItemListFirst() |
| | | |
| | | GameWorld.DebugLog("奖励物品: %s" % awardItemList) |
| | | ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["TurnFight", False, {"mapID":mapID, "funcLineID":funcLineID}]) |
| | | |
| | | overMsg = {"isWin":isWin, "itemInfo":FBCommon.GetJsonItemList(awardItemList), "totalHurt":factionTotalHurtDict.get(1, 0)} |
| | | playbackID and overMsg.update({"playbackID":playbackID}) |
| | | SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Award, turnNum, turnMax, overMsg) |
| | | return |
| | | |
| | | def ProcessAutoTurnFight(mapID, funcLineID, factionInfoA, factionInfoB, tick, syncPlayer=None, isSavePlayback=False): |
| | | ''' 处理自动回合战斗过程,仅做战斗流程处理,不做及其他功能逻辑 |
| | | @param mapID: 可视为功能ID |
| | | @param funcLineID: 对功能ID的扩展 |
| | | @param factionInfoA: A方阵营信息,playerID 和 npcID 二选一 {"playerID":主体玩家镜像ID, "npcID":主体NPCID, "pet":[{出战灵宠信息兼容玩家缓存的灵宠信息k:v, ...}, ...]} |
| | | @param factionInfoB: B方阵营信息 |
| | | @param syncPlayer: 需要通知的玩家,可能为None,注意仅做通知用,该玩家可能和AB阵营无任何关系 |
| | | @param isSavePlayback: 是否保存战斗回放 |
| | | @return: None-无结果;或 (isWin, turnNum, turnMax, factionTotalHurtDict) |
| | | isWin: 是否获胜 |
| | | turnNum: 打了几回合 |
| | | factionTotalHurtDict: 双方伤血统计 |
| | | ''' |
| | | if syncPlayer: |
| | | syncPlayer.SetCanAttack(False) # 该玩家设置为不可被攻击 |
| | | playerID = syncPlayer.GetPlayerID() |
| | | sightLevel, posX, posY = playerID, syncPlayer.GetPosX(), syncPlayer.GetPosY() |
| | | else: |
| | | playerID = 0 |
| | | sightLevel, posX, posY = 99, 192, 109 # 系统默认处理的层级及坐标 |
| | | |
| | | objRetA = __SummonFactionObjs(factionInfoA, sightLevel, posX, posY) |
| | | objRetB = __SummonFactionObjs(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: |
| | | return |
| | | playerIDA = objA.GetDictByKey(ChConfig.Def_NPC_Dict_MirrorPlayerID) # 可能为0,非玩家镜像时为0 |
| | | playerIDB = objB.GetDictByKey(ChConfig.Def_NPC_Dict_MirrorPlayerID) # 可能为0,非玩家镜像时为0 |
| | | |
| | | objNameA = GetObjName(objA) |
| | | objNameB = GetObjName(objB) |
| | | GameWorld.DebugLog("===== 执行回合制战斗: %s VS %s =====" % (objNameA, objNameB)) |
| | | |
| | | turnMax = IpyGameDataPY.GetFuncCfg("TurnFight", 1) |
| | | # 宠物先攻击 |
| | | fightPetObjListA = PetControl.CalloutFightPet(curPlayer) |
| | | factionListA = fightPetObjListA + [curPlayer] |
| | | factionListB = fightPetObjListB + [tagObj] |
| | | factionListA = petObjListA + [objA] |
| | | factionListB = petObjListB + [objB] |
| | | atkFactionList = [factionListA, factionListB] |
| | | |
| | | # 设置战斗主体 |
| | | curPlayer.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1) |
| | | tagObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1) |
| | | objA.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1) |
| | | objB.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1) |
| | | |
| | | # 战斗前初始化,可能会改变攻速,所以先初始化 |
| | | for faction, factionObjList in enumerate(atkFactionList, 1): |
| | |
| | | fightObjList.sort(key=lambda o: (GameObj.GetAtkSpeed(o), (10 - GameObj.GetFaction(o)), o.GetID()), reverse=True) |
| | | #方式2:根据阵营主角攻速决定先手,然后每个阵营轮流固定位置攻击 |
| | | elif sortType == 2: |
| | | if GameObj.GetAtkSpeed(curPlayer) < GameObj.GetAtkSpeed(tagObj): |
| | | if GameObj.GetAtkSpeed(objA) < GameObj.GetAtkSpeed(objB): |
| | | atkFactionList = [factionListB, factionListA] |
| | | for i in range(len(factionListA)): |
| | | for factionObjList in atkFactionList: |
| | | fightObjList.append(factionObjList[i]) |
| | | |
| | | SyncTurnFightState(syncPlayer, mapID, funcLineID, playerIDB, FightState_PrepareOK, msg=[factionSyncInfoA, factionSyncInfoB]) |
| | | |
| | | isWin = None |
| | | for turnNum in range(1, turnMax + 1): |
| | | GameWorld.DebugLog("【----- 回合制战斗轮次: %s -----】" % turnNum) |
| | | SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Fighting, turnNum, turnMax) |
| | | SyncTurnFightState(syncPlayer, mapID, funcLineID, playerIDB, FightState_Fighting, turnNum, turnMax) |
| | | |
| | | # 回合开始: 做一些每回合重置逻辑或者某些根据回合触发的效果等 |
| | | for gameObj in fightObjList: |
| | | TurnFightObjPerTurnStart(gameObj, turnNum, tick) |
| | | |
| | | isWin = CheckIswin(curPlayer, tagObj) |
| | | isWin = CheckIswin(objA, objB) |
| | | if isWin != None: |
| | | break |
| | | |
| | |
| | | |
| | | objType = gameObj.GetGameObjType() |
| | | objID = gameObj.GetID() |
| | | SyncTurnFightObjAction(curPlayer, turnNum, objType, objID) |
| | | SyncTurnFightObjAction(syncPlayer, turnNum, objType, objID) |
| | | |
| | | if GameObj.GetHP(gameObj) <= 0: |
| | | # 复活时机在自己行动节点 |
| | |
| | | objName = GetObjName(gameObj) |
| | | curHP = GameObj.GetHP(gameObj) |
| | | |
| | | tagGameObj = tagObj if faction == 1 else curPlayer |
| | | tagGameObj = objB if faction == 1 else objA |
| | | tagObjType = tagGameObj.GetGameObjType() |
| | | tagObjID = tagGameObj.GetID() |
| | | tagHP = GameObj.GetHP(tagGameObj) |
| | |
| | | if not DoAttack(gameObj, tagGameObj, tick): |
| | | continue |
| | | |
| | | isWin = CheckIswin(curPlayer, tagObj) |
| | | isWin = CheckIswin(objA, objB) |
| | | if isWin != None: |
| | | break |
| | | |
| | | if isWin != None: |
| | | break |
| | | |
| | | GameWorld.DebugLog("--- 战斗结束处理 ---") |
| | | |
| | | GameWorld.DebugLog("--- 战斗结束处理 --- isWin=%s" % isWin) |
| | | isWin = 1 if isWin else 0 |
| | | |
| | | # 统计总伤害 |
| | | factionTotalHurtDict = {} |
| | | for gameObj in fightObjList: |
| | |
| | | for faction, totalHurt in factionTotalHurtDict.items(): |
| | | GameWorld.DebugLog("faction=%s, 阵营总输出: %s" % (faction, totalHurt)) |
| | | |
| | | GameWorld.DebugLog("玩家剩余血量: %s / %s" % (GameObj.GetHP(curPlayer), GameObj.GetMaxHP(curPlayer))) |
| | | GameWorld.DebugLog("对方剩余血量: %s / %s" % (GameObj.GetHP(tagObj), GameObj.GetMaxHP(tagObj))) |
| | | GameWorld.DebugLog("A剩余血量: %s / %s" % (GameObj.GetHP(objA), GameObj.GetMaxHP(objA))) |
| | | GameWorld.DebugLog("B剩余血量: %s / %s" % (GameObj.GetHP(objB), GameObj.GetMaxHP(objB))) |
| | | |
| | | # 结算奖励...待扩展 |
| | | awardItemList = [] |
| | | if isWin and ipyData: |
| | | # 山寨测试先默认都是首次奖励,正式后需删除 |
| | | awardItemList = ipyData.GetAwardItemListFirst() |
| | | |
| | | GameWorld.DebugLog("奖励物品: %s" % awardItemList) |
| | | ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["TurnFight", False, {"mapID":mapID, "funcLineID":funcLineID}]) |
| | | |
| | | overMsg = {"itemInfo":FBCommon.GetJsonItemList(awardItemList), "totalHurt":factionTotalHurtDict.get(1, 0)} |
| | | overState = FightState_Win if isWin else FightState_Fail |
| | | SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, overState, turnNum, turnMax, str(overMsg)) |
| | | SyncTurnFightState(syncPlayer, mapID, funcLineID, playerIDB, FightState_FightEnd, turnNum, turnMax) |
| | | |
| | | for gameObj in fightObjList: |
| | | TurnFightObjOverReset(gameObj, tick) |
| | | |
| | | GameWorld.DebugLog("===== 回合制战斗结束: mapID=%s,funcLineID=%s,playerID=%s,tagPlayerID=%s,isWin=%s,overState=%s" |
| | | % (mapID, funcLineID, playerID, tagPlayerID, isWin, overState)) |
| | | return |
| | | playbackID = 0 # 战斗回放ID,可根据该ID查看回放 |
| | | #playbackInfo = "" # 战斗回放信息 |
| | | if isSavePlayback: |
| | | pass |
| | | |
| | | GameWorld.DebugLog("===== 回合制战斗结束: mapID=%s,funcLineID=%s,playerIDA=%s,playerIDB=%s,isWin=%s" |
| | | % (mapID, funcLineID, playerIDA, playerIDB, isWin)) |
| | | return isWin, turnNum, turnMax, factionTotalHurtDict, playbackID |
| | | |
| | | def __SummonFactionObjs(factionInfo, sightLevel, posX, posY): |
| | | ## 召唤阵营战斗实例 |
| | | factionSyncInfo = {} # 同步前端的阵营信息,包含主ID、灵宠、其他灵通等 |
| | | playerID = factionInfo.get("playerID") |
| | | npcID = factionInfo.get("npcID") |
| | | if playerID: |
| | | npcID = ChConfig.Def_NPCID_PVP |
| | | mainObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=sightLevel, mirrorPlayerID=playerID) |
| | | factionSyncInfo["playerID"] = playerID |
| | | elif npcID: |
| | | mainObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=sightLevel) |
| | | factionSyncInfo["npcID"] = npcID |
| | | else: |
| | | return |
| | | if not mainObj: |
| | | return |
| | | petObjList = PetControl.CalloutFightPet(mainObj, factionInfo.get("pet")) |
| | | petObjIDList = [] |
| | | for petObj in petObjList: |
| | | if petObj: |
| | | petObjIDList.append(petObj.GetID()) |
| | | factionSyncInfo.update({"objID":mainObj.GetID(), "petObjIDList":petObjIDList}) |
| | | return mainObj, petObjList, factionSyncInfo |
| | | |
| | | def CheckIswin(curPlayer, tagObj): |
| | | ## 检查是否结束 |
| | |
| | | return useSkillResult |
| | | |
| | | def SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, state, turnNum=0, turnMax=0, msg=""): |
| | | if not curPlayer: |
| | | return |
| | | clientPack = ChPyNetSendPack.tagMCTurnFightState() |
| | | clientPack.Clear() |
| | | clientPack.MapID = mapID |
| | |
| | | clientPack.State = state |
| | | clientPack.TurnNum = turnNum |
| | | clientPack.TurnMax = turnMax |
| | | clientPack.Msg = msg |
| | | clientPack.Msg = str(msg) |
| | | clientPack.Len = len(clientPack.Msg) |
| | | NetPackCommon.SendFakePack(curPlayer, clientPack) |
| | | return |
| | | |
| | | def SyncTurnFightObjAction(curPlayer, turnNum, objType, objID): |
| | | if not curPlayer: |
| | | return |
| | | clientPack = ChPyNetSendPack.tagMCTurnFightObjAction() |
| | | clientPack.Clear() |
| | | clientPack.TurnNum = turnNum |