| | |
| | | import NPCCommon |
| | | import GameWorld |
| | | import GameObj |
| | | import PetControl |
| | | |
| | | ( |
| | | FightState_Start, |
| | |
| | | FightState_Fail, |
| | | FightState_Over, |
| | | ) = range(5) |
| | | |
| | | def GetObjName(gameObj): |
| | | objName = gameObj.GetName() |
| | | faction = GameObj.GetFaction(gameObj) |
| | | fightPlaceNum = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_FightPetPlaceNum) |
| | | return "%s%s %s" % ("A" if faction == 1 else "B", fightPlaceNum, objName) |
| | | |
| | | #// B4 10 回合制战斗 #tagCMTurnFight |
| | | # |
| | |
| | | SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Start) |
| | | |
| | | if tagPlayerID: |
| | | PlayerViewCacheTube.GetPlayerPropDataCall(curPlayer, tagPlayerID, DoTrunFightVSPlayer, [mapID, funcLineID]) |
| | | PlayerViewCacheTube.GetPlayerPropDataCall(curPlayer, tagPlayerID, DoTrunFightVSPlayer, [mapID, funcLineID], True) |
| | | return |
| | | |
| | | DoTrunFight(curPlayer, mapID, funcLineID, tagPlayerID, tick) |
| | |
| | | def DoTrunFight(curPlayer, mapID, funcLineID, tagPlayerID, tick): |
| | | playerID = curPlayer.GetPlayerID() |
| | | posX, posY = curPlayer.GetPosX(), curPlayer.GetPosY() |
| | | |
| | | factionListA, factionListB = [], [] |
| | | factionListA.append(curPlayer) |
| | | curPet = curPlayer.GetPetMgr().GetFightPet() |
| | | curPet and factionListA.append(curPet) |
| | | |
| | | # 玩家阵营的其他战斗实例,可扩展... |
| | | assistNPCID = 0 # 协助召唤兽 |
| | | if assistNPCID: |
| | | assistNPC = NPCCommon.SummonNPC(curPlayer, assistNPCID, posX, posY) |
| | | assistNPC and factionListA.append(assistNPC) |
| | | |
| | | GameWorld.DebugLog("===== 执行回合制战斗: mapID=%s,funcLineID=%s,tagPlayerID=%s" % (mapID, funcLineID, tagPlayerID), playerID) |
| | | tagObj = None |
| | | if tagPlayerID: |
| | | npcID = ChConfig.Def_NPCID_PVP |
| | | tagObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=playerID, pvpPlayerID=tagPlayerID) |
| | | if not tagObj: |
| | | return |
| | | factionListB.append(tagObj) |
| | | |
| | | # 对手玩家镜像的其他战斗实例... |
| | | |
| | | PlusData = PlayerViewCacheTube.GetPlayerPropPlusDictByID(playerID)[1] # 从缓存中获取 |
| | | petCacheInfo = PlusData.get("Pet") |
| | | fightPetObjListB = PetControl.CalloutFightPet(tagObj, petCacheInfo) |
| | | else: |
| | | ipyData = IpyGameDataPY.GetIpyGameData("FBTurn", mapID, funcLineID) |
| | | if not ipyData: |
| | |
| | | tagObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=playerID) |
| | | if not tagObj: |
| | | return |
| | | factionListB.append(tagObj) |
| | | summerNPCID = ipyData.GetSummerNPCID() |
| | | if summerNPCID: |
| | | summerNPC = NPCCommon.SummonNPC(tagObj, summerNPCID, posX, posY) |
| | | summerNPC and factionListB.append(summerNPC) |
| | | |
| | | if not factionListB: |
| | | return |
| | | |
| | | for gameObj in factionListA: |
| | | GameObj.SetFaction(gameObj, 1) |
| | | for gameObj in factionListB: |
| | | GameObj.SetFaction(gameObj, 2) |
| | | 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) |
| | | |
| | | #一个回合攻击顺序,由攻击速度决定,攻速相同下阵营1先攻击,还相同则由ID决定 |
| | | fightObjList = factionListA + factionListB |
| | | fightObjList.sort(key=lambda o: (GameObj.GetAtkSpeed(o), (10 - GameObj.GetFaction(o)), o.GetID()), reverse=True) |
| | | |
| | | turnMax = IpyGameDataPY.GetFuncCfg("TurnFight", 1) |
| | | GameWorld.DebugLog("===== 执行回合制战斗: mapID=%s,funcLineID=%s,tagPlayerID=%s,tagObjID=%s" |
| | | % (mapID, funcLineID, tagPlayerID, tagObj.GetID()), playerID) |
| | | # 战斗前初始化 |
| | | for gameObj in fightObjList: |
| | | TurnFightObjStartInit(gameObj) |
| | | |
| | | # 宠物先攻击 |
| | | fightPetObjListA = PetControl.CalloutFightPet(curPlayer) |
| | | factionListA = fightPetObjListA + [curPlayer] |
| | | factionListB = fightPetObjListB + [tagObj] |
| | | atkFactionList = [factionListA, factionListB] |
| | | |
| | | # 战斗前初始化,可能会改变攻速,所以先初始化 |
| | | for faction, factionObjList in enumerate(atkFactionList, 1): |
| | | for gameObj in factionObjList: |
| | | TurnFightObjStartInit(gameObj, faction, tick) |
| | | |
| | | #一个回合攻击顺序,为了后续逻辑统一,都是先确定好顺序 |
| | | sortType = 2 # 攻击顺序排序方式 |
| | | fightObjList = [] |
| | | #方式1: 纯由攻击速度决定,攻速相同下阵营1先攻击,还相同则由ID决定 |
| | | if sortType == 1: |
| | | fightObjList = factionListA + factionListB |
| | | 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): |
| | | atkFactionList = [factionListB, factionListA] |
| | | for i in range(len(factionListA)): |
| | | for factionObjList in atkFactionList: |
| | | fightObjList.append(factionObjList[i]) |
| | | |
| | | isWin = None |
| | | for turnNum in range(1, turnMax + 1): |
| | | GameWorld.DebugLog("----- 回合制战斗轮次: %s -----" % turnNum, playerID) |
| | | GameWorld.DebugLog("【----- 回合制战斗轮次: %s -----】" % turnNum) |
| | | SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Fighting, turnNum, turnMax) |
| | | |
| | | # 回合开始: 做一些每回合重置逻辑或者某些根据回合触发的效果等 |
| | |
| | | TurnFightObjPerTurnStart(gameObj, turnNum, tick) |
| | | |
| | | # 回合战斗: 轮流依次攻击 |
| | | for actNum, gameObj in enumerate(fightObjList, 1): |
| | | if not gameObj: |
| | | for gameObj in fightObjList: |
| | | if not gameObj or GameObj.GetHP(gameObj) <= 0: |
| | | continue |
| | | faction = GameObj.GetFaction(gameObj) |
| | | tagGameObj = tagObj if faction == 1 else curPlayer |
| | | objType = gameObj.GetGameObjType() |
| | | objID = gameObj.GetID() |
| | | objName = GetObjName(gameObj) |
| | | curHP = GameObj.GetHP(gameObj) |
| | | |
| | | tagGameObj = tagObj if faction == 1 else curPlayer |
| | | tagObjType = tagGameObj.GetGameObjType() |
| | | tagObjID = tagGameObj.GetID() |
| | | tagHP = GameObj.GetHP(tagGameObj) |
| | | |
| | | GameWorld.DebugLog(" 行动: turnNum=%s,actNum=%s,faction=%s,objType=%s,objID=%s,tagObjType=%s,tagObjID=%s" |
| | | % (turnNum, actNum, faction, objType, objID, tagObjType, tagObjID)) |
| | | 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) |
| | | |
| | | DoAttack(gameObj, tagGameObj, tick) |
| | |
| | | % (mapID, funcLineID, tagPlayerID, isWin, overState), playerID) |
| | | return |
| | | |
| | | def TurnFightObjStartInit(gameObj): |
| | | def TurnFightObjStartInit(gameObj, faction, tick): |
| | | ## 回合制战斗实例初始化 |
| | | if not gameObj: |
| | | return |
| | | |
| | | gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightNum, 1) |
| | | GameObj.SetFaction(gameObj, faction) |
| | | GameObj.SetHPFull(gameObj) |
| | | gameObj.RefreshView() |
| | | |
| | | objType = gameObj.GetGameObjType() |
| | | npcID = gameObj.GetNPCID() if objType == IPY_GameWorld.gotNPC else 0 |
| | | GameWorld.DebugLog("初始化实例: objID=%s,npcID=%s,faction=%s,atkSpeed=%s,HP=%s,Atk=%s,Def=%s" |
| | | % (gameObj.GetID(), npcID, GameObj.GetFaction(gameObj), GameObj.GetAtkSpeed(gameObj), GameObj.GetHP(gameObj), gameObj.GetMaxAtk(), gameObj.GetDef())) |
| | | GameWorld.DebugLog(" 闪命(%s,%s),闪避(%s,%s),暴击(%s,%s),击晕(%s,%s),连击(%s,%s),反击(%s,%s),吸血(%s,%s)" |
| | | % (gameObj.GetMiss(), gameObj.GetHit(), |
| | | GameObj.GetMissRate(gameObj), GameObj.GetMissDefRate(gameObj), |
| | | 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),暴击(%s,%s),击晕(%s,%s),连击(%s,%s),反击(%s,%s),吸血(%s,%s)" |
| | | % (GameObj.GetMissRate(gameObj), GameObj.GetMissDefRate(gameObj), |
| | | GameObj.GetSuperHitRate(gameObj), GameObj.GetSuperHitRateReduce(gameObj), |
| | | GameObj.GetFaintRate(gameObj), GameObj.GetFaintDefRate(gameObj), |
| | | GameObj.GetComboRate(gameObj), GameObj.GetComboDefRate(gameObj), |
| | |
| | | if objType == IPY_GameWorld.gotPlayer: |
| | | skillManager = gameObj.GetSkillManager() |
| | | for i in range(skillManager.GetSkillCount()): |
| | | skill = skillManager.GetSkillByIndex(i) |
| | | skill.SetRemainTime(0) |
| | | curSkill = skillManager.GetSkillByIndex(i) |
| | | curSkill.SetRemainTime(0) |
| | | |
| | | elif objType == IPY_GameWorld.gotNPC: |
| | | pass |
| | | skillIDList = [] |
| | | skillManager = gameObj.GetSkillManager() |
| | | for i in range(skillManager.GetSkillCount()): |
| | | curSkill = skillManager.GetSkillByIndex(i) |
| | | if not curSkill: |
| | | continue |
| | | skillIDList.append(curSkill.GetSkillID()) |
| | | if fightPlaceNum: |
| | | # 灵宠技能开始时直接进入CD |
| | | curSkill.SetLastUseTick(tick) |
| | | curSkill.SetRemainTime(curSkill.GetCoolDownTime()) |
| | | GameWorld.DebugLog(" NPC技能: npcID=%s,skillIDList=%s" % (npcID, skillIDList)) |
| | | |
| | | return |
| | | |
| | | def TurnFightObjPerTurnStart(gameObj, turnNum, tick): |
| | |
| | | |
| | | objType = gameObj.GetGameObjType() |
| | | objID = gameObj.GetID() |
| | | GameWorld.DebugLog("ObjPerTurnStart: faction=%s,objType=%s,objID=%s,turnNum=%s,HP=%s" % (GameObj.GetFaction(gameObj), objType, objID, turnNum, GameObj.GetHP(gameObj))) |
| | | objName = GetObjName(gameObj) |
| | | GameWorld.DebugLog("ObjPerTurnStart: 回合%s, %s objType-ID-HP(%s-%s-%s)" % (turnNum, objName, objType, objID, GameObj.GetHP(gameObj))) |
| | | |
| | | # 每回合开始减技能CD |
| | | skillManager = gameObj.GetSkillManager() |
| | |
| | | |
| | | def CanAtkBack(atkObj, defObj): |
| | | ## 可否反击 |
| | | |
| | | if atkObj.GetDictByKey(ChConfig.Def_Obj_Dict_FightPetPlaceNum) > 0: |
| | | #GameWorld.DebugLog(" 被灵宠攻击时无法触发反击") |
| | | return False |
| | | defAtkBackRate = GameObj.GetAtkBackRate(defObj) # 防方反击率 |
| | | atkBackNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnAtkBackNum) # 已反击次数 |
| | | if atkBackNum > 10: |
| | |
| | | ## NPC攻击 |
| | | if not curObj: |
| | | return |
| | | |
| | | objName = "● %s" % GetObjName(curObj) |
| | | #有值代表灵宠上阵位置,判断是否有概率攻击 |
| | | fightPlaceNum = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_FightPetPlaceNum) |
| | | if fightPlaceNum > 0: |
| | | fightRateList = IpyGameDataPY.GetFuncEvalCfg("PetGoOutFight", 2) |
| | | if fightPlaceNum > len(fightRateList): |
| | | return |
| | | fightRatePer = fightRateList[fightPlaceNum - 1] |
| | | |
| | | qualityAddRateInfo = IpyGameDataPY.GetFuncEvalCfg("PetGoOutFight", 3, {}) |
| | | petQuality = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_FightPetQuality) |
| | | qualityAddPer = qualityAddRateInfo.get(str(petQuality), 0) |
| | | fightRatePer += qualityAddPer |
| | | if fightRatePer < 100 and not GameWorld.CanHappen(fightRatePer, 100): |
| | | GameWorld.DebugLog(" 灵宠概率不攻击: curID=%s,fightPlaceNum=%s,petQuality=%s,fightRatePer=%s" |
| | | % (curObj.GetID(), fightPlaceNum, petQuality, fightRatePer)) |
| | | return |
| | | |
| | | tagDist = 0 |
| | | atkOK = AICommon.DoAutoUseSkill(curObj, tagObj, tagDist, tick) |
| | | #---优先释放技能--- |
| | | if not atkOK: |
| | | #普通攻击 |
| | | atkOK = BaseAttack.Attack(curObj, tagObj, None, tick) |
| | | if atkOK: |
| | | GameWorld.DebugLog(" NPC普通攻击: curID=%s,tagID=%s,atkOK=%s" % (curObj.GetID(), tagObj.GetID(), atkOK)) |
| | | if fightPlaceNum: |
| | | GameWorld.DebugLog(" 灵宠不可普通攻击: curID=%s,fightPlaceNum=%s" % (curObj.GetID(), fightPlaceNum)) |
| | | else: |
| | | GameWorld.DebugLog(" NPC攻击失败: curID=%s,tagID=%s,atkOK=%s" % (curObj.GetID(), tagObj.GetID(), atkOK)) |
| | | #普通攻击 |
| | | atkOK = BaseAttack.Attack(curObj, tagObj, None, tick) |
| | | if atkOK: |
| | | GameWorld.DebugLog(" %s 普通攻击: curID=%s,tagID=%s,atkOK=%s" % (objName, curObj.GetID(), tagObj.GetID(), atkOK)) |
| | | else: |
| | | GameWorld.DebugLog(" %s 攻击失败: curID=%s,tagID=%s,atkOK=%s" % (objName, curObj.GetID(), tagObj.GetID(), atkOK)) |
| | | else: |
| | | GameWorld.DebugLog(" NPC技能攻击: curID=%s,tagID=%s,atkOK=%s" % (curObj.GetID(), tagObj.GetID(), atkOK)) |
| | | GameWorld.DebugLog(" %s 技能攻击: curID=%s,tagID=%s,atkOK=%s" % (objName, curObj.GetID(), tagObj.GetID(), atkOK)) |
| | | return atkOK |
| | | |
| | | def PlayerAttack(curPlayer, tagObj, tick): |
| | |
| | | posX, posY = tagPosX, tagPosY = curPlayer.GetPosX(), curPlayer.GetPosY() |
| | | tagObjType, tagObjID = tagObj.GetGameObjType(), tagObj.GetID() |
| | | |
| | | objName = "● %s" % GetObjName(curPlayer) |
| | | curPlayer.ClearUseSkillRec() |
| | | curPlayer.SetAttackTargetPos(posX, posY) |
| | | curPlayer.SetUseSkillPosX(tagPosX) |
| | |
| | | curPlayer.SetUseSkill(curSkill.GetSkillData()) |
| | | useSkillData = curPlayer.GetUseSkill() |
| | | if not PlayerState.__DoClientUseSkillEx(curPlayer, useSkillData, tick): |
| | | GameWorld.DebugLog(" 玩家技能攻击失败: playerID=%s,tagID=%s,skillID=%s" % (playerID, tagObjID, skillID)) |
| | | GameWorld.DebugLog(" %s 技能攻击失败: playerID=%s,tagID=%s,skillID=%s" % (objName, playerID, tagObjID, skillID)) |
| | | continue |
| | | useSkillResult = True |
| | | GameWorld.DebugLog(" 玩家技能攻击成功: playerID=%s,tagID=%s,skillID=%s" % (playerID, tagObjID, skillID)) |
| | | GameWorld.DebugLog(" %s 技能攻击成功: playerID=%s,tagID=%s,skillID=%s" % (objName, playerID, tagObjID, skillID)) |
| | | |
| | | break |
| | | |
| | |
| | | atkOK = BaseAttack.Attack(curPlayer, tagObj, None, tick) |
| | | if atkOK: |
| | | useSkillResult = True |
| | | GameWorld.DebugLog(" 玩家普通攻击: curID=%s,tagID=%s,atkOK=%s" % (playerID, tagObjID, atkOK)) |
| | | GameWorld.DebugLog(" %s 普通攻击: curID=%s,tagID=%s,atkOK=%s" % (objName, playerID, tagObjID, atkOK)) |
| | | else: |
| | | GameWorld.DebugLog(" 玩家攻击失败: curID=%s,tagID=%s,atkOK=%s" % (playerID, tagObjID, atkOK)) |
| | | GameWorld.DebugLog(" %s 攻击失败: curID=%s,tagID=%s,atkOK=%s" % (objName, playerID, tagObjID, atkOK)) |
| | | return useSkillResult |
| | | |
| | | def SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, state, turnNum=0, turnMax=0): |