| | |
| | | import GameWorld |
| | | import GameObj |
| | | import PetControl |
| | | import SkillShell |
| | | |
| | | ( |
| | | FightState_Start, |
| | |
| | | FightState_Fail, |
| | | FightState_Over, |
| | | ) = range(5) |
| | | |
| | | ( |
| | | RebornType_PetSkill, |
| | | ) = range(1, 1 + 1) |
| | | |
| | | def GetObjName(gameObj): |
| | | objName = gameObj.GetName() |
| | |
| | | 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 # 攻击顺序排序方式 |
| | |
| | | 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) |
| | | |
| | |
| | | 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 |
| | | |
| | |
| | | % (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() |
| | |
| | | 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), |
| | |
| | | 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 |
| | |
| | | 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) |
| | |
| | | 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) |
| | |
| | | ## 回合制战斗实例结束重置 |
| | | 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) |
| | | |
| | |
| | | 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())) |
| | |
| | | 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 |
| | |
| | | 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): |
| | | ## 可否反击 |