From e17fcba64e93fceb1459b12cbe70663039d40314 Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期四, 11 一月 2024 18:22:45 +0800 Subject: [PATCH] 10019 【砍树】回合战斗(回合战斗buff持续时间处理及持续性buff定时触发时机处理支持;增加回合战斗死亡及复活支持;) --- ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py | 255 ++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 211 insertions(+), 44 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 1a11598..4b650a9 100644 --- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py +++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py @@ -30,6 +30,7 @@ import GameWorld import GameObj import PetControl +import SkillShell ( FightState_Start, @@ -38,6 +39,10 @@ FightState_Fail, FightState_Over, ) = range(5) + +( +RebornType_PetSkill, +) = range(1, 1 + 1) def GetObjName(gameObj): objName = gameObj.GetName() @@ -121,10 +126,14 @@ 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 # 攻击顺序排序方式 @@ -150,13 +159,29 @@ 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) @@ -165,28 +190,16 @@ 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 @@ -200,11 +213,154 @@ % (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() @@ -214,9 +370,9 @@ 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), @@ -242,9 +398,10 @@ 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 @@ -254,7 +411,7 @@ 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) @@ -277,14 +434,23 @@ 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) @@ -311,7 +477,7 @@ ## 回合制战斗实例结束重置 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) @@ -324,6 +490,9 @@ 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())) @@ -333,9 +502,7 @@ 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 @@ -370,18 +537,18 @@ 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): ## 可否反击 -- Gitblit v1.8.0