129 【战斗】战斗系统-服务端(无敌支持,免疫伤害、dot、控制;小怪技能;)
| | |
| | | if self._buffMgr.IsInBuffState(state):
|
| | | return True
|
| | | return False
|
| | | def IsInState(self, state):
|
| | | ## 是否处于指定状态下
|
| | | return self._buffMgr.IsInBuffState(state)
|
| | |
|
| | | def IsInControlled(self):
|
| | | ## 是否被控制中
|
| | | for state in ChConfig.InControlledStateList:
|
| | | if self.IsInState(state):
|
| | | if self._buffMgr.IsInBuffState(state):
|
| | | return True
|
| | | return False
|
| | |
|
| | |
| | | if SkillCommon.isAngerSkill(useSkill):
|
| | | if curXP < xpMax:
|
| | | continue
|
| | | if curBatObj.IsInState(ChConfig.BatObjState_Sneer):
|
| | | if curBatObj.CheckInState(ChConfig.BatObjState_Sneer):
|
| | | GameWorld.DebugLog("嘲讽状态下,无法主动释放怒技!") # 可被动释放怒技,如怒技追击
|
| | | continue
|
| | | useCnt = -1 # xp技能优先释放
|
| | |
| | | HurtType_Normal, # 伤害 1
|
| | | HurtTYpe_Recovery, # 回血 2
|
| | | HurtType_3,
|
| | | HurtType_4,
|
| | | HurtType_Immune, # 免疫 4
|
| | | HurtType_Parry, # 格挡 5
|
| | | HurtType_IgnoreDef, # 无视防御/真实伤害 6
|
| | | HurtType_SuperHit, # 暴击 7
|
| | |
| | | BatObjState_Poison, # 中毒 5
|
| | | BatObjState_Bleeding, # 流血 6
|
| | | BatObjState_EasyHurt, # 易伤 7
|
| | | BatObjState_Wudi, # 无敌 8
|
| | | BatObjState_Wudi, # 无敌( 受任意伤害、控制类、dot效果,全部飘“免疫”) 8
|
| | | BatObjState_Sneer, # 嘲讽 9
|
| | | BatObjState_LimitSkill, # 沉默 10
|
| | | BatObjState_LimitAddHP, # 禁疗 11
|
| | |
| | | useSkill = poolMgr.acquire(BattleObj.PySkill, skillIpyData, ownerID)
|
| | | useSkill.SetTagObjList(tagObjList)
|
| | |
|
| | | OnAddBuff(turnFight, batObj, useSkill, buffOwner, bySkill, afterLogic)
|
| | | isOK = OnAddBuff(turnFight, batObj, useSkill, buffOwner, bySkill, afterLogic)
|
| | |
|
| | | poolMgr.release(useSkill)
|
| | | return
|
| | | return isOK
|
| | |
|
| | | def OnAddBuff(turnFight, batObj, buffSkill, buffOwner=None, bySkill=None, afterLogic=False):
|
| | | skillID = buffSkill.GetSkillID()
|
| | |
| | | if not buffOwner:
|
| | | buffOwner = batObj
|
| | | ownerID = buffOwner.GetID()
|
| | | |
| | | #无敌免疫持续减益buff、控制类buff
|
| | | if buffSkill.GetSkillType() in [ChConfig.Def_SkillType_LstDepBuff, ChConfig.Def_SkillType_Action] \
|
| | | and batObj.CheckInState(ChConfig.BatObjState_Wudi):
|
| | | GameWorld.DebugLog("无敌状态下免疫该buff: curID=%s,skillID=%s,ownerID=%s,relatedSkillID=%s" |
| | | % (curID, skillID, ownerID, relatedSkillID))
|
| | | return False
|
| | | |
| | | buffValueList = GetAddBuffValue(turnFight, buffOwner, batObj, buffSkill)
|
| | | GameWorld.DebugLog("OnAddBuff: curID=%s,skillID=%s,atkType=%s,buffValueList=%s,ownerID=%s,relatedSkillID=%s"
|
| | | % (curID, skillID, buffSkill.GetAtkType(), buffValueList, ownerID, relatedSkillID))
|
| | |
| | | buffMgr = batObj.GetBuffManager()
|
| | |
|
| | | if buffRepeat == 4: # 4 独立:回合、效果独立计算
|
| | | pass # 不处理,直接跳过添加新buff
|
| | | maxLayerCnt = buffSkill.GetLayerMax()
|
| | | # 如果有限制最大层数,达到上限时如果有新的层数进来,就替换掉持续时间最短的,只算相同来源
|
| | | if maxLayerCnt:
|
| | | buffList = buffMgr.FindBuffListBySkillTypeID(skillTypeID)
|
| | | if len(buffList) >= maxLayerCnt:
|
| | | delBuff = None
|
| | | for buff in buffList:
|
| | | if not buff:
|
| | | continue
|
| | | if buff.GetOwnerID() != ownerID:
|
| | | continue
|
| | | if not delBuff or delBuff.GetRemainTime() < buff.GetRemainTime():
|
| | | delBuff = buff
|
| | | if delBuff:
|
| | | GameWorld.DebugLog("删除独立层级多余buff: buffID=%s,ownerID=%s,remainTime=%s" % (delBuff.GetBuffID(), ownerID, delBuff.GetRemainTime()))
|
| | | DoBuffDel(turnFight, batObj, delBuff, bySkill, afterLogic, buffOwner)
|
| | | |
| | | elif buffRepeat == 5: # 5 唯一,强制覆盖不同来源同状态buff,如嘲讽状态
|
| | | buffState = buffSkill.GetCurBuffState()
|
| | | for index in range(buffMgr.GetBuffCount())[::-1]:
|
| | |
| | | DoBuffDel(turnFight, batObj, buff, bySkill, afterLogic, buffOwner)
|
| | | else:
|
| | | buffList = buffMgr.FindBuffListBySkillTypeID(skillTypeID)
|
| | | if buffList:
|
| | | for buff in buffList:
|
| | | if not buff:
|
| | | continue
|
| | | if buff.GetOwnerID() != ownerID:
|
| | | continue
|
| | | buffID = buff.GetBuffID()
|
| | | nowLayerCnt = buff.GetLayer()
|
| | | GameWorld.DebugLog(" 已经存在该buff: buffID=%s,skillTypeID=%s,ownerID=%s,buffRepeat=%s" % (buffID, skillTypeID, ownerID, buffRepeat))
|
| | | |
| | | updLayerCnt = addLayerCnt
|
| | | if buffRepeat == 3: # 叠加层级
|
| | | maxLayerCnt = buffSkill.GetLayerMax()
|
| | | updLayerCnt = nowLayerCnt + addLayerCnt
|
| | | if maxLayerCnt and updLayerCnt > maxLayerCnt:
|
| | | updLayerCnt = maxLayerCnt
|
| | | GameWorld.DebugLog(" 叠加层级: nowLayerCnt=%s,addLayerCnt=%s,updLayerCnt=%s" % (nowLayerCnt, addLayerCnt, updLayerCnt))
|
| | | else:
|
| | | GameWorld.DebugLog(" 默认覆盖")
|
| | | |
| | | # 重置回合、CD、值等
|
| | | buff.SetCalcTime(turnFight.getTimeline())
|
| | | buff.SetRemainTime(buffSkill.GetLastTime())
|
| | | buff.SetLayer(updLayerCnt)
|
| | | buff.SetBuffValueList(buffValueList)
|
| | | if afterLogic and bySkill:
|
| | | bySkill.AddAfterLogic(ChConfig.AfterLogic_AddBuff, [batObj, buff, buffOwner])
|
| | | else:
|
| | | SyncBuffRefresh(turnFight, batObj, buff, relatedSkillID, isNewAdd=True)
|
| | | |
| | | if nowLayerCnt != updLayerCnt:
|
| | | RefreshBuffEffect(turnFight, batObj, buff, False)
|
| | | break
|
| | | for buff in buffList:
|
| | | if not buff:
|
| | | continue
|
| | | if buff.GetOwnerID() != ownerID:
|
| | | continue
|
| | | buffID = buff.GetBuffID()
|
| | | nowLayerCnt = buff.GetLayer()
|
| | | GameWorld.DebugLog(" 已经存在该buff: buffID=%s,skillTypeID=%s,ownerID=%s,buffRepeat=%s" % (buffID, skillTypeID, ownerID, buffRepeat))
|
| | |
|
| | | updLayerCnt = addLayerCnt
|
| | | if buffRepeat == 3: # 叠加层级
|
| | | maxLayerCnt = buffSkill.GetLayerMax()
|
| | | updLayerCnt = nowLayerCnt + addLayerCnt
|
| | | if maxLayerCnt and updLayerCnt > maxLayerCnt:
|
| | | updLayerCnt = maxLayerCnt
|
| | | GameWorld.DebugLog(" 叠加层级: nowLayerCnt=%s,addLayerCnt=%s,updLayerCnt=%s" % (nowLayerCnt, addLayerCnt, updLayerCnt))
|
| | | else:
|
| | | GameWorld.DebugLog(" 默认覆盖")
|
| | | |
| | | # 重置回合、CD、值等
|
| | | buff.SetCalcTime(turnFight.getTimeline())
|
| | | buff.SetRemainTime(buffSkill.GetLastTime())
|
| | | buff.SetLayer(updLayerCnt)
|
| | | buff.SetBuffValueList(buffValueList)
|
| | | if afterLogic and bySkill:
|
| | | bySkill.AddAfterLogic(ChConfig.AfterLogic_AddBuff, [batObj, buff, buffOwner])
|
| | | else:
|
| | | SyncBuffRefresh(turnFight, batObj, buff, relatedSkillID, isNewAdd=True)
|
| | | |
| | | if nowLayerCnt != updLayerCnt:
|
| | | RefreshBuffEffect(turnFight, batObj, buff, False)
|
| | | return True
|
| | |
|
| | | __addNewBuff(turnFight, batObj, buffMgr, buffSkill, buffValueList, buffOwner, bySkill, afterLogic, setLayerCnt=addLayerCnt)
|
| | |
| | | TurnAttack.SetObjKilled(turnFight, curObj)
|
| | |
|
| | | # 统计伤血,可能单个技能对同一目标造成多次伤害
|
| | | totalHurtValue = 0
|
| | | isSuperHit, isStun, isSuckHP = False, False, False
|
| | | missObjIDList = []
|
| | | missObjIDList, immuneObjIDList = [], []
|
| | | for hurtObj in useSkill.GetHurtObjList():
|
| | | hurtObjID = hurtObj.GetObjID()
|
| | | tagObj = batObjMgr.getBatObj(hurtObjID)
|
| | | if not tagObj:
|
| | | continue
|
| | | if not hurtObj.HaveHurtType(ChConfig.HurtTYpe_Recovery) and (isTurnNormalSkill or isAngerSkill) and tagObj.IsAlive():
|
| | | if not hurtObj.HaveHurtType(ChConfig.HurtTYpe_Recovery) and not hurtObj.HaveHurtType(ChConfig.HurtType_Immune) \
|
| | | and (isTurnNormalSkill or isAngerSkill) and tagObj.IsAlive():
|
| | | __doSkillHurtAnger(tagObj, hurtObj.GetLostHP(), useSkill)
|
| | | |
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_Normal):
|
| | | totalHurtValue += hurtObj.GetHurtHP()
|
| | | |
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
|
| | | missObjIDList.append(hurtObjID)
|
| | | if hurtObjID not in missObjIDList:
|
| | | missObjIDList.append(hurtObjID)
|
| | | DoHeroSpecialty(turnFight, tagObj, ChConfig.HeroSpecialty_Miss, relatedSkillID)
|
| | | |
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_Immune):
|
| | | if hurtObjID not in immuneObjIDList:
|
| | | immuneObjIDList.append(hurtObjID)
|
| | | |
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_Parry):
|
| | | DoHeroSpecialty(turnFight, tagObj, ChConfig.HeroSpecialty_Parry, relatedSkillID)
|
| | | |
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_SuperHit):
|
| | | isSuperHit = True
|
| | | |
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_Stun):
|
| | | isStun = True
|
| | | |
| | | if hurtObj.GetSuckHP() > 0:
|
| | | isSuckHP = True
|
| | | |
| | | curObj.SetLastHurtValue(totalHurtValue) # 记录最后一次总伤害
|
| | | |
| | | # 群攻只触发一次特长
|
| | | if isSuperHit:
|
| | | DoHeroSpecialty(turnFight, curObj, ChConfig.HeroSpecialty_SuperHit, relatedSkillID)
|
| | |
| | | if curPlayer and curObj and curObj.GetOwnerID() == curPlayer.GetPlayerID():
|
| | | FBLogic.OnPlayerLineupAttackResult(curPlayer, curObj, killObjList, useSkill, turnFight.mapID, turnFight.funcLineID)
|
| | |
|
| | | effIgnoreObjIDList = missObjIDList + immuneObjIDList
|
| | | # 优先触发本技能额外效果,注:仅该技能释放后该技能的额外效果视为主技能的效果,优先级最高
|
| | | __DoCurSkillEff(turnFight, curObj, useSkill, missObjIDList, isUseSkill)
|
| | | __DoCurSkillEff(turnFight, curObj, useSkill, effIgnoreObjIDList, isUseSkill)
|
| | |
|
| | | # ========== 以下触发被动 ==========
|
| | |
|
| | |
| | |
|
| | | for tagObj in useSkill.GetTagObjList():
|
| | | tagID = tagObj.GetID()
|
| | | if tagID in missObjIDList:
|
| | | if tagID in effIgnoreObjIDList:
|
| | | continue
|
| | |
|
| | | # 直接攻击
|
| | |
| | | Sync_PropertyRefreshView(turnFight, gameObj, ChConfig.AttrID_XP, updXP, addXP, diffType=1, relatedSkillID=relatedSkillID)
|
| | | return
|
| | |
|
| | | def __DoCurSkillEff(turnFight, curObj, useSkill, missObjIDList, isUseSkill):
|
| | | def __DoCurSkillEff(turnFight, curObj, useSkill, effIgnoreObjIDList, isUseSkill):
|
| | | ## 执行本技能/buff释放后额外效果
|
| | | for index in xrange(useSkill.GetEffectCount()):
|
| | | curEffect = useSkill.GetEffect(index)
|
| | |
| | | continue
|
| | |
|
| | | effID = curEffect.GetEffectID()
|
| | | GameWorld.DebugLog("◆执行额外技能效果: %s, triggerWay=%s,missObjIDList=%s" % (effID, triggerWay, missObjIDList))
|
| | | GameWorld.DebugLog("◆执行额外技能效果: %s, triggerWay=%s,effIgnoreObjIDList=%s" % (effID, triggerWay, effIgnoreObjIDList))
|
| | | if effID == 5010:
|
| | | # 额外技能效果
|
| | | __doUseEnhanceSkill(turnFight, curObj, useSkill, curEffect, missObjIDList)
|
| | | __doUseEnhanceSkill(turnFight, curObj, useSkill, curEffect, effIgnoreObjIDList)
|
| | | continue
|
| | |
|
| | | for tagObj in useSkill.GetTagObjList():
|
| | | tagID = tagObj.GetID()
|
| | | if tagID in missObjIDList:
|
| | | if tagID in effIgnoreObjIDList:
|
| | | # 闪避了不触发
|
| | | continue
|
| | |
|
| | |
| | |
|
| | | return
|
| | |
|
| | | def __doUseEnhanceSkill(turnFight, curBatObj, useSkill, curEffect, missObjIDList):
|
| | | def __doUseEnhanceSkill(turnFight, curBatObj, useSkill, curEffect, effIgnoreObjIDList):
|
| | | ## 执行主技能的额外技能效果
|
| | | #if useSkill.GetBatType() == ChConfig.TurnBattleType_Enhance:
|
| | | # #GameWorld.DebugLog("自身为额外触发的技能不再触发额外技能! skillID=%s" % useSkill.GetSkillID())
|
| | |
| | | if not tagObj.IsAlive():
|
| | | GameWorld.DebugLog(" 已被击杀不触发: tagID=%s" % (tagID))
|
| | | continue
|
| | | if tagID in missObjIDList:
|
| | | GameWorld.DebugLog(" 闪避的不触发: tagID=%s" % (tagID))
|
| | | if tagID in effIgnoreObjIDList:
|
| | | GameWorld.DebugLog(" 闪避或免疫的不触发: tagID=%s" % (tagID))
|
| | | continue
|
| | | if checkInStateList:
|
| | | if not tagObj.CheckInState(checkInStateList):
|
| | |
| | |
|
| | | else:
|
| | | hurtValue, hurtTypes = CalcHurtHP(turnFight, atkObj, defObj, curSkill, atkSkillValue, atkSkillPer)
|
| | | hurtValue, realHurtHP = CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue)
|
| | | hurtValue, realHurtHP, hurtTypes = CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue, hurtTypes)
|
| | |
|
| | | #伤害结构体
|
| | | hurtObj.SetHurtTypes(hurtTypes)
|
| | |
| | | hurtObj.SetLostHP(lostHP)
|
| | | hurtObj.SetCurHP(remainHP)
|
| | | defObj.SetHP(remainHP)
|
| | | atkObj.SetLastHurtValue(hurtValue)
|
| | | GameWorld.DebugLog(" 伤血: atkID=%s,defID=%s,hurtValue=%s,realHurtHP=%s,lostHP=%s,%s/%s"
|
| | | % (atkID, defID, hurtValue, realHurtHP, lostHP, defObj.GetHP(), defObj.GetMaxHP()))
|
| | | TurnAttack.AddTurnObjHurtValue(atkObj, defObj, hurtValue, lostHP, skillID)
|
| | |
| | | happenRate = eval(IpyGameDataPY.GetFuncCompileCfg("StunCfg", 1))
|
| | | if not GameWorld.CanHappen(happenRate):
|
| | | return False
|
| | | GameWorld.DebugLog("击晕了: happenRate=%s,aStunRate=%s,dStunRateDef=%s" % (happenRate, aStunRate, dStunRateDef))
|
| | | stunSkillID = IpyGameDataPY.GetFuncCfg("StunCfg", 2)
|
| | | TurnBuff.DoAddBuffBySkillID(turnFight, defObj, stunSkillID, atkObj, curSkill, afterLogic=True)
|
| | | return True
|
| | | if TurnBuff.DoAddBuffBySkillID(turnFight, defObj, stunSkillID, atkObj, curSkill, afterLogic=True):
|
| | | GameWorld.DebugLog("击晕了: happenRate=%s,aStunRate=%s,dStunRateDef=%s" % (happenRate, aStunRate, dStunRateDef))
|
| | | return True
|
| | | return False
|
| | |
|
| | | def CanParry(turnFight, atkObj, defObj, curSkill):
|
| | | if defObj.IsInControlled():
|
| | |
| | | return True
|
| | | return False
|
| | |
|
| | | def CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue):
|
| | | def CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue, hurtTypes=0):
|
| | | ## 计算伤害后,因各种buff和状态的影响处理
|
| | | # @return: hurtValue, realHurtHP
|
| | | # @return: hurtValue, realHurtHP, hurtTypes
|
| | |
|
| | | if hurtValue <= 0:
|
| | | return 0, 0
|
| | | return 0, 0, hurtTypes
|
| | | |
| | | if defObj.CheckInState(ChConfig.BatObjState_Wudi):
|
| | | hurtTypes |= pow(2, ChConfig.HurtType_Immune) # 添加免疫
|
| | | buffMgr = defObj.GetBuffManager()
|
| | | for index in range(buffMgr.GetBuffCount()):
|
| | | buff = buffMgr.GetBuffByIndex(index)
|
| | | if not buff:
|
| | | continue
|
| | | skillData = buff.GetSkillData()
|
| | | if skillData.GetCurBuffState() != ChConfig.BatObjState_Wudi:
|
| | | continue
|
| | | # 记录免疫的积攒伤害
|
| | | buffValue = buff.GetValue1() + buff.GetValue2() * ChConfig.Def_PerPointValue
|
| | | updBuffValue = buffValue + hurtValue
|
| | | buff.SetValue1(updBuffValue % ChConfig.Def_PerPointValue)
|
| | | buff.SetValue2(updBuffValue / ChConfig.Def_PerPointValue)
|
| | | GameWorld.DebugLog(" 无敌盾免疫伤害: defID=%s,buffID=%s,skillID=%s,updBuffValue=%s" |
| | | % (defObj.GetID(), buff.GetBuffID(), skillData.GetSkillID(), updBuffValue))
|
| | | return 0, 0, hurtTypes
|
| | |
|
| | | # 减伤盾减伤, 会改变 hurtValue
|
| | | hurtValue = max(0, hurtValue)
|
| | |
| | | buff.SetValue2(updShieldValue / ChConfig.Def_PerPointValue)
|
| | | curSkill.AddAfterLogic(ChConfig.AfterLogic_SyncBuff, [defObj, buff, atkObj, "ReduceShieldValue"])
|
| | |
|
| | | return hurtValue, max(0, realHurtHP)
|
| | | return hurtValue, max(0, realHurtHP), hurtTypes
|
| | |
|
| | | def CalcBounceHP(turnFight, atkObj, defObj, hurtObj, curSkill):
|
| | | '''计算反弹反弹伤害
|
| | |
| | | return
|
| | |
|
| | | GameWorld.DebugLog(" 反弹伤害=%s,%s/%s" % (bounceHP, atkObj.GetHP(), atkObj.GetMaxHP()))
|
| | | bounceHP, realBounceHP = CalcHurtHPWithBuff(turnFight, defObj, atkObj, curSkill, bounceHP)
|
| | | bounceHP, realBounceHP, _ = CalcHurtHPWithBuff(turnFight, defObj, atkObj, curSkill, bounceHP)
|
| | | if bounceHP <= 0:
|
| | | GameWorld.DebugLog(" bounceHP=%s" % (bounceHP))
|
| | | return
|
| | | hurtObj.SetBounceHP(bounceHP)
|
| | |
|
| | |
| | | dHP = defObj.GetHP()
|
| | | GameWorld.DebugLog("结算dot: atkID=%s,defID=%s,buffID=%s,skillID=%s,ownerID=%s,hurtValue=%s,hurtTypes=%s,dHP=%s"
|
| | | % (atkID, defID, buffID, skillID, ownerID, hurtValue, hurtTypes, dHP))
|
| | | hurtValue, realHurtHP = CalcHurtHPWithBuff(turnFight, atkObj, defObj, useSkill, hurtValue)
|
| | | hurtValue, realHurtHP, hurtTypes = CalcHurtHPWithBuff(turnFight, atkObj, defObj, useSkill, hurtValue, hurtTypes)
|
| | |
|
| | | # dot的反弹、吸血待定
|
| | |
|
| | | remainHP = max(0, dHP - realHurtHP) # 剩余血量
|
| | | lostHP = dHP - remainHP # 实际掉血量
|
| | | defObj.SetHP(remainHP)
|
| | | atkObj.SetLastHurtValue(hurtValue)
|
| | | GameWorld.DebugLog(" hurtValue=%s,realHurtHP=%s,lostHP=%s,%s/%s" % (hurtValue, realHurtHP, lostHP, defObj.GetHP(), defObj.GetMaxHP()))
|
| | |
|
| | | hurtObj.SetHurtTypes(hurtTypes)
|