129 【战斗】战斗系统-服务端(技能触发来源触发逻辑优化;增加承伤盾支持,0428通知buff相关值;增加嘲讽支持,优化技能选择目标逻辑;增加连击、反击、格挡、暴击、通用击晕支持;)
| | |
| | | DWORD EffectID1; //效果ID1
|
| | | list EffectValues1; //效果值列表1
|
| | | BYTE TriggerWay1; //触发方式
|
| | | BYTE TriggerSrc1; //触发来源
|
| | | BYTE TriggerSrc1; //有效来源
|
| | | list TriggerParams1; //触发参数
|
| | | DWORD EffectID2; //效果ID2
|
| | | list EffectValues2; //效果值列表2
|
| | | BYTE TriggerWay2; //触发方式
|
| | | BYTE TriggerSrc2; //触发来源
|
| | | BYTE TriggerSrc2; //有效来源
|
| | | list TriggerParams2; //触发参数
|
| | | DWORD EffectID3; //效果ID3
|
| | | list EffectValues3; //效果值列表3
|
| | | BYTE TriggerWay3; //触发方式
|
| | | BYTE TriggerSrc3; //触发来源
|
| | | BYTE TriggerSrc3; //有效来源
|
| | | list TriggerParams3; //触发参数
|
| | | DWORD ConnSkill; //关联技能
|
| | | WORD CoolDownTime; //技能冷却时间
|
| | | list IgnoreStates; //无视限制列表
|
| | | list BuffStates; //Buff״ֵ̬
|
| | | BYTE CurBuffState; //Buff״ֵ̬
|
| | | WORD LastTime; //持续时间
|
| | | BYTE LayerCnt; //Buff层数
|
| | | BYTE LayerMax; //最大层数
|
| | |
| | | DWORD DieContinue; //Buff死亡存在
|
| | | list EnhanceSkillList; //触发技能ID列表
|
| | | DWORD FightPower; //技能战斗力
|
| | | char SkillMotionName; //技能动作名
|
| | | };
|
| | |
|
| | | //武将表
|
| | |
| | | def __init__(self, batObj):
|
| | | self._batObj = batObj
|
| | | # 被影响的技能ID: 0为所有技能
|
| | | self._AffectSkillDict = {} # 被动技能 {(触发方式, 被影响的技能ID):{技能ID:[effID, ...], ...}, ...}
|
| | | self._AffectBuffDict = {} # 被动buff {(触发方式, 被影响的技能ID):{buffID:[effID, ...], ...}, ...}
|
| | | self._AffectSkillDict = {} # 被动技能 {(触发方式, 有效来源):{技能ID:[effID, ...], ...}, ...}
|
| | | self._AffectBuffDict = {} # 被动buff {(触发方式, 有效来源):{buffID:[effID, ...], ...}, ...}
|
| | | return
|
| | |
|
| | | def GetPassiveEffByTrigger(self, triggerWay, connSkill=None):
|
| | | def GetPassiveEffByTrigger(self, triggerWay, connSkillTypeID=0):
|
| | | '''获取可触发的效果列表,技能跟buff根据触发优先级按顺序触发,优先级越高越先执行,相同时技能优先
|
| | | 优先级之后有需要再扩展
|
| | | @return: [["skill/buff", skillID/buffID, effIDList], ...]
|
| | | '''
|
| | | connSkillID = connSkill.GetSkillTypeID() if connSkill else 0
|
| | | effList = []
|
| | | |
| | | # 优先取关联技能的
|
| | | if connSkillTypeID and connSkillTypeID not in [ChConfig.TriggerSrc_Skill, ChConfig.TriggerSrc_Buff]:
|
| | | # 技能
|
| | | key = (triggerWay, connSkillID)
|
| | | key = (triggerWay, connSkillTypeID)
|
| | | if key in self._AffectSkillDict:
|
| | | effDict = self._AffectSkillDict[key]
|
| | | for skillID, effIDList in effDict.items():
|
| | | effList.append(["skill", skillID, effIDList])
|
| | | if connSkillID != 0:
|
| | | key = (triggerWay, 0)
|
| | | effDict = self._AffectSkillDict.get(key, {})
|
| | | for skillID, effIDList in effDict.items():
|
| | | effList.append(["skill", skillID, effIDList])
|
| | |
|
| | | # buff
|
| | | key = (triggerWay, connSkillID)
|
| | | key = (triggerWay, connSkillTypeID)
|
| | | if key in self._AffectBuffDict:
|
| | | effDict = self._AffectBuffDict[key]
|
| | | for buffID, effIDList in effDict.items():
|
| | | effList.append(["buff", buffID, effIDList])
|
| | | if connSkillID != 0:
|
| | | key = (triggerWay, 0)
|
| | | |
| | | # 所有技能有效的
|
| | | key = (triggerWay, ChConfig.TriggerSrc_Skill)
|
| | | effDict = self._AffectSkillDict.get(key, {})
|
| | | for skillID, effIDList in effDict.items():
|
| | | effList.append(["skill", skillID, effIDList])
|
| | | |
| | | # 所有buff有效的
|
| | | key = (triggerWay, ChConfig.TriggerSrc_Buff)
|
| | | effDict = self._AffectBuffDict.get(key, {})
|
| | | for buffID, effIDList in effDict.items():
|
| | | effList.append(["buff", buffID, effIDList])
|
| | |
| | | ## 添加技能被动效果
|
| | | triggerWay = effect.GetTriggerWay()
|
| | | triggerSrc = effect.GetTriggerSrc()
|
| | | if not triggerWay or triggerSrc != 1:
|
| | | if not triggerWay:
|
| | | return
|
| | | if triggerSrc == ChConfig.TriggerSrc_Buff:
|
| | | # buff有效的不加进来
|
| | | return
|
| | |
|
| | | skillID = curSkill.GetSkillID()
|
| | | connSkillID = curSkill.GetConnSkill()
|
| | | #priority = curSkill.GetPriority()
|
| | | |
| | | effectID = effect.GetEffectID()
|
| | |
|
| | | key = (triggerWay, connSkillID)
|
| | | key = (triggerWay, triggerSrc)
|
| | | if key not in self._AffectSkillDict:
|
| | | self._AffectSkillDict[key] = {}
|
| | | effDict = self._AffectSkillDict[key]
|
| | |
| | | '''
|
| | | triggerWay = effect.GetTriggerWay()
|
| | | triggerSrc = effect.GetTriggerSrc()
|
| | | if not triggerWay or triggerSrc != 2:
|
| | | if not triggerWay:
|
| | | return
|
| | | if triggerSrc == ChConfig.TriggerSrc_Skill:
|
| | | # 技能有效的不加进来
|
| | | return
|
| | |
|
| | | buffID = buff.GetBuffID()
|
| | | connSkillID = skillData.GetConnSkill()
|
| | | #priority = skillData.GetPriority()
|
| | | |
| | | effectID = effect.GetEffectID()
|
| | | key = (triggerWay, connSkillID)
|
| | | |
| | | key = (triggerWay, triggerSrc)
|
| | | if key not in self._AffectBuffDict:
|
| | | self._AffectBuffDict[key] = {}
|
| | | effDict = self._AffectBuffDict[key]
|
| | |
| | | def Clear(self):
|
| | | self._objID = 0
|
| | | self._hurtTypes = 0 # 本次伤血类型,如闪避、暴击、格挡等,通过二进制或运算得到最终值,支持多种同时出现,如暴击的同时被格挡
|
| | | self._hurtHP = 0 # 伤血值
|
| | | self._hurtHP = 0 # 公式最终计算的伤害值,一般用于飘血
|
| | | self._realHurtHP = 0 # 真实伤血值,被承伤盾抵扣后的可伤血的值
|
| | | self._lostHP = 0 # 实际掉血值
|
| | | self._curHP = 0 # 更新血量
|
| | | self._suckHP = 0 # 吸血量
|
| | |
| | | return self._hurtTypes & pow(2, hurtType)
|
| | | def GetHurtHP(self): return self._hurtHP
|
| | | def SetHurtHP(self, hurtHP): self._hurtHP = hurtHP
|
| | | def GetRealHurtHP(self): return self._realHurtHP
|
| | | def SetRealHurtHP(self, realHurtHP): self._realHurtHP = realHurtHP
|
| | | def GetLostHP(self): return self._lostHP
|
| | | def SetLostHP(self, lostHP): self._lostHP = lostHP
|
| | | def GetCurHP(self): return self._curHP
|
| | |
| | | self._effDict[effID] = effect
|
| | | return
|
| | |
|
| | | def GetIpyData(self): return self._ipyData
|
| | | def GetSkillID(self): return self._ipyData.GetSkillID()
|
| | | def GetSkillTypeID(self): return self._ipyData.GetSkillTypeID()
|
| | | def GetSkillLV(self): return self._ipyData.GetSkillLV()
|
| | |
| | | def GetConnSkill(self): return self._ipyData.GetConnSkill()
|
| | | def GetCoolDownTime(self): return self._ipyData.GetCoolDownTime()
|
| | | def GetIgnoreStates(self): return self._ipyData.GetIgnoreStates() # 无视限制列表
|
| | | def GetBuffStates(self): return self._ipyData.GetBuffStates()
|
| | | def GetCurBuffState(self): return self._ipyData.GetCurBuffState()
|
| | | def GetLastTime(self): return self._ipyData.GetLastTime() # 持续时间
|
| | | def GetLayerCnt(self): return self._ipyData.GetLayerCnt()
|
| | | def GetLayerMax(self): return self._ipyData.GetLayerMax()
|
| | |
| | | def GetDieContinue(self): return self._ipyData.GetDieContinue() # Buff死亡存在
|
| | | def GetEnhanceSkillList(self): return self._ipyData.GetEnhanceSkillList() # 额外触发的技能ID列表
|
| | | def GetFightPower(self): return self._ipyData.GetFightPower()
|
| | | def GetSkillMotionName(self): return self._ipyData.GetSkillMotionName()
|
| | |
|
| | | class PyBuff():
|
| | |
|
| | |
| | | self._layer = 0
|
| | | self._calcTime = 0
|
| | | self._remainTime = 0
|
| | | self._valueList = []
|
| | | self._value1 = 0 # 值需要通知前端,开发时注意20亿问题
|
| | | self._value2 = 0
|
| | | self._value3 = 0
|
| | | return
|
| | |
|
| | | def GetSkillData(self): return self._skillData
|
| | |
| | | def SetCalcTime(self, calcTime): self._calcTime = calcTime
|
| | | def GetRemainTime(self): return self._remainTime
|
| | | def SetRemainTime(self, remainTime): self._remainTime = remainTime
|
| | | def SetBuffValueList(self, valueList): self._valueList = valueList
|
| | | def GetBuffValue(self, index):
|
| | | return self._valueList[index] if len(self._valueList) > index else 0
|
| | | def SetBuffValueList(self, valueList):
|
| | | for index, value in enumerate(valueList):
|
| | | if index == 0:
|
| | | self.SetValue1(value)
|
| | | elif index == 1:
|
| | | self.SetValue2(value)
|
| | | elif index == 2:
|
| | | self.SetValue3(value)
|
| | | def GetValue1(self): return self._value1
|
| | | def SetValue1(self, value): self._value1 = value
|
| | | def GetValue2(self): return self._value2
|
| | | def SetValue2(self, value): self._value2 = value
|
| | | def GetValue3(self): return self._value3
|
| | | def SetValue3(self, value): self._value3 = value
|
| | |
|
| | | class BuffManager():
|
| | | ## 战斗对象buff管理器
|
| | |
| | |
|
| | | self._buffList.append(buff)
|
| | | self._buffIDDict[buffID] = buff
|
| | | #GameWorld.DebugLog("ObjBuff:%s, AddBuff buffID=%s, %s, %s, %s, %s, %s" % (self._batObj.GetID(), buffID, buff, len(self._buffList), len(self._buffIDDict), self._buffList, self._buffIDDict))
|
| | | if skillTypeID not in self._skillTypeIDBuffIDs:
|
| | | self._skillTypeIDBuffIDs[skillTypeID] = []
|
| | | buffIDs = self._skillTypeIDBuffIDs[skillTypeID]
|
| | |
| | |
|
| | | return buff
|
| | |
|
| | | def DelBuff(self, buffID):
|
| | | def DelBuff(self, buffID, release=True):
|
| | | if buffID not in self._buffIDDict:
|
| | | #GameWorld.DebugLog("ObjBuff:%s, DelBuff not in self._buffIDDict, buffID=%s, %s" % (self._batObj.GetID(), buffID, self._buffIDDict.keys()))
|
| | | return
|
| | | #GameWorld.DebugLog("ObjBuff:%s, DelBuff %s, buffID=%s, dict:%s, len:%s, list:%s" % (self._batObj.GetID(), release, buffID, self._buffIDDict, len(self._buffList), self._buffList))
|
| | | buff = self._buffIDDict.pop(buffID)
|
| | | if buff in self._buffList:
|
| | | self._buffList.remove(buff)
|
| | | #GameWorld.DebugLog(" ObjBuff:%s, buffID=%s, dict:%s, len:%s, dictKeys:%s, list:%s" % (self._batObj.GetID(), buffID, len(self._buffIDDict), len(self._buffList), self._buffIDDict.keys(), self._buffList))
|
| | | for skillTypeID, buffIDList in self._skillTypeIDBuffIDs.items():
|
| | | if buffID not in buffIDList:
|
| | | continue
|
| | |
| | | if not buffIDList:
|
| | | self._skillTypeIDBuffIDs.pop(skillTypeID)
|
| | | break
|
| | | if release:
|
| | | ObjPool.GetPoolMgr().release(buff)
|
| | | return
|
| | |
|
| | | def GetBuff(self, buffID): return self._buffIDDict.get(buffID, None)
|
| | | def FindBuffIDBySkillID(self, skillID):
|
| | | ## 返回该技能ID的所有buffID列表
|
| | | def FindBuffBySkillID(self, skillID):
|
| | | ## 返回该技能ID的所有buff列表
|
| | | skillData = IpyGameDataPY.GetIpyGameData("Skill", skillID)
|
| | | if not skillData:
|
| | | return []
|
| | | return self.FindBuffIDBySkillTypeID(skillData.GetSkillTypeID())
|
| | | def FindBuffIDBySkillTypeID(self, skillTypeID):
|
| | | ## 返回该技能TypeID的所有buffID列表
|
| | | return self.FindBuffBySkillTypeID(skillData.GetSkillTypeID())
|
| | | def FindBuffBySkillTypeID(self, skillTypeID):
|
| | | ## 返回该技能TypeID的所有buff列表
|
| | | if skillTypeID not in self._skillTypeIDBuffIDs:
|
| | | return []
|
| | | buffs = []
|
| | |
| | | def IsInBuffState(self, state): return state in self._buffStateDict ## 是否处于某种状态下
|
| | | def GetStateBuffIDList(self, state): return self._buffStateDict.get(state, []) # 获取某种状态的所有buffID列表
|
| | |
|
| | | |
| | | class PySkill():
|
| | |
|
| | | def __init__(self, ipyData):
|
| | |
| | | self._tagObjList = [] # 本次技能目标列表 [BatObj, ...]
|
| | | self._hurtList = [] # 本次伤血列表,可能同一个对象有多个伤害,如弹射等 [HurtObj, ...]
|
| | | self._bySkill = None # 由哪个技能触发的
|
| | | self._isEnhanceSkill = False # 是否由主技能额外触发的(非被动触发,即主技能的EnhanceSkillList字段中的技能)
|
| | | self._afterLogicList = [] # 技能释放后需要处理逻辑 [[logicType, logicParams], ...]
|
| | | return
|
| | |
|
| | | def ResetUseRec(self):
|
| | | self._batType = 0
|
| | | self._tagObjList = []
|
| | | self._bySkill = None
|
| | | self._isEnhanceSkill = False
|
| | | self._afterLogicList = []
|
| | | self.ClearHurtObj()
|
| | | return
|
| | |
|
| | |
| | | def GetHappenRate(self): return self._skillData.GetHappenRate() # 触发概率
|
| | | def GetEffect(self, index): return self._skillData.GetEffect(index)
|
| | | def GetEffectCount(self): return self._skillData.GetEffectCount()
|
| | | def GetEffectByID(self, effID): return self._skillData.GetEffectByID()
|
| | | def GetEffectByID(self, effID): return self._skillData.GetEffectByID(effID)
|
| | | def GetConnSkill(self): return self._skillData.GetConnSkill()
|
| | | def GetCoolDownTime(self): return self._skillData.GetCoolDownTime()
|
| | | def GetIgnoreStates(self): return self._skillData.GetIgnoreStates() # 无视限制列表
|
| | | def GetBuffStates(self): return self._skillData.GetBuffStates()
|
| | | def GetCurBuffState(self): return self._skillData.GetCurBuffState()
|
| | | def GetLastTime(self): return self._skillData.GetLastTime() # 持续时间
|
| | | def GetLayerCnt(self): return self._skillData.GetLayerCnt()
|
| | | def GetLayerMax(self): return self._skillData.GetLayerMax()
|
| | |
| | | def GetDieContinue(self): return self._skillData.GetDieContinue() # Buff死亡存在
|
| | | def GetEnhanceSkillList(self): return self._skillData.GetEnhanceSkillList() # 额外触发的技能ID列表
|
| | | def GetFightPower(self): return self._skillData.GetFightPower()
|
| | | def GetSkillMotionName(self): return self._skillData.GetSkillMotionName()
|
| | |
|
| | | ## ---------------------------------- 非技能表内容 ----------------------------------
|
| | | def GetCalcTime(self): return self._calcTime
|
| | |
| | | def SetRemainTime(self, remainTime): self._remainTime = remainTime
|
| | | def GetBatType(self): return self._batType
|
| | | def SetBatType(self, batType): self._batType = batType
|
| | | def GetIsEnhanceSkill(self): return self._isEnhanceSkill
|
| | | def SetIsEnhanceSkill(self, isEnhanceSkill): self._isEnhanceSkill = isEnhanceSkill
|
| | | def GetBySkill(self): return self._bySkill
|
| | | def SetBySkill(self, bySkill): self._bySkill = bySkill
|
| | | def GetTagObjList(self): return self._tagObjList # 技能目标列表
|
| | | def SetTagObjList(self, tagObjList): self._tagObjList = tagObjList
|
| | | def GetAfterLogicList(self): return self._afterLogicList
|
| | | def AddAfterLogic(self, logicType, logicData):
|
| | | '''添加技能释放后需要处理额外逻辑
|
| | | @param logicType: 逻辑类型
|
| | | @param logicData: 逻辑对应的数据
|
| | | '''
|
| | | self._afterLogicList.append([logicType, logicData])
|
| | | return
|
| | | def ClearHurtObj(self):
|
| | | ## 清空伤血统计
|
| | | poolMgr = ObjPool.GetPoolMgr()
|
| | |
| | | self.ownerID = 0 # 所属玩家ID,可能为0,0代表非玩家的战斗实体
|
| | | self.heroID = 0
|
| | | self.skinID = 0
|
| | | self.atkDistType = 0
|
| | | self.lv = 1
|
| | | self.fightPower = 0
|
| | | self.faction = 0 # 所属阵营,一般只有双方阵营, 1 或 2,发起方默认1
|
| | |
| | | self.posNum = 0 # 所在阵容站位
|
| | | self._hp = 0 # 当前生命值
|
| | | self._xp = 0 # 当前怒气值
|
| | | self._isAlive = True # 是否活着
|
| | | self._initAttrDict = {} # 初始化时的属性,固定不变,初始化时已经算好的属性 {attrID:value, ...}
|
| | | self._batAttrDict = {} # 实际战斗属性,包含buff层级的实际属性
|
| | | self._skillTempAttrDict = {} # 某次技能释放中临时的属性增减 {attrID:+-value, ...}
|
| | |
| | | def GetID(self): return self.objID
|
| | | def GetName(self): return self.objName
|
| | | def SetName(self, name): self.objName = name
|
| | | def GetAtkDistType(self): return self.atkDistType
|
| | | def SetAtkDistType(self, atkDistType): self.atkDistType = atkDistType
|
| | | def GetNPCID(self): return self.npcID # 如果是NPC战斗单位,则该值非0
|
| | | def SetNPCID(self, npcID): self.npcID = npcID # 设置所属的NPCID
|
| | | def GetOwnerID(self): return self.ownerID # 如果是玩家战斗单位,则该值非0,为所属玩家ID
|
| | |
| | | ## 是否处于某种状态下
|
| | | return self._buffMgr.IsInBuffState(state)
|
| | |
|
| | | def IsInControlled(self):
|
| | | ## 是否被控制中
|
| | | for state in ChConfig.InControlledStateList:
|
| | | if self.IsInState(state):
|
| | | return True
|
| | | return False
|
| | | |
| | | def CanAction(self):
|
| | | ## 是否可以行动
|
| | | if not self.IsAlive():
|
| | | return False
|
| | | if self.IsInControlled():
|
| | | return False
|
| | | return True
|
| | | |
| | | def GetSneerTagObj(self):
|
| | | ## 获取被嘲讽的目标,如果存在则一定是活着的目标
|
| | | buffIDList = self._buffMgr.GetStateBuffIDList(ChConfig.BatObjState_Sneer)
|
| | | if not buffIDList:
|
| | | return
|
| | | objMgr = GetBatObjMgr()
|
| | | for buffID in buffIDList:
|
| | | buff = self._buffMgr.GetBuff(buffID)
|
| | | if not buff:
|
| | | continue
|
| | | tagObj = objMgr.getBatObj(buff.GetOwnerID())
|
| | | if tagObj and tagObj.IsAlive(): # 活着才有效
|
| | | return tagObj
|
| | | return
|
| | | |
| | | # 战斗属性
|
| | | def IsAlive(self): return self._isAlive # 是否活着
|
| | | def SetDead(self):
|
| | | self._isAlive = False
|
| | | self._hp = 0
|
| | | def GetMaxHP(self): return self._batAttrDict.get(ChConfig.AttrID_MaxHP, 0)
|
| | | def SetMaxHP(self, maxHP, isNotify=False):
|
| | | self._batAttrDict[ChConfig.AttrID_MaxHP] = maxHP
|
| | |
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | if not batObj:
|
| | | continue
|
| | | if batObj.GetHP() > 0:
|
| | | if batObj.IsAlive():
|
| | | allKilled = False
|
| | | break
|
| | |
|
| | | if allKilled:
|
| | | self.winFaction = ChConfig.Def_FactionA if faction == ChConfig.Def_FactionB else ChConfig.Def_FactionA
|
| | | self.winFaction = ChConfig.Def_FactionA if faction == ChConfig.Def_FactionB else ChConfig.Def_FactionB
|
| | | DoTurnFightOver(self.guid)
|
| | | return self.winFaction
|
| | |
|
| | |
| | |
|
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | initXP = IpyGameDataPY.GetFuncCfg("AngerXP", 1)
|
| | | atkBackSkillIDList = IpyGameDataPY.GetFuncEvalCfg("ParryCfg", 3)
|
| | | atkBackSkillIDList = IpyGameDataPY.GetFuncEvalCfg("ParryCfg", 2)
|
| | | for posNumKey, heroInfo in heroDict.items():
|
| | | posNum = int(posNumKey)
|
| | |
|
| | |
| | | batObj.SetLineupPos(posNum, num)
|
| | | batObj.SetFightPower(fightPower)
|
| | | batObj.SetLV(lv)
|
| | | batObj.SetAtkDistType(atkDistType)
|
| | | if npcID:
|
| | | batObj.SetNPCID(npcID)
|
| | | elif lineupPlayerID:
|
| | |
| | | return
|
| | |
|
| | | def OnTimelineChange(turnFight):
|
| | | ## 每个时间节点变化时处理
|
| | |
|
| | | nowTimeline = turnFight.getTimeline()
|
| | |
|
| | |
| | | for batLineup in batFaction.lineupDict.values():
|
| | | for objID in batLineup.posObjIDDict.values():
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | if not batObj or batObj.GetHP() <= 0:
|
| | | #GameWorld.DebugLog("OnTimelineChange! objID=%s" % (objID))
|
| | | if not batObj or not batObj.IsAlive():
|
| | | continue
|
| | | |
| | | batObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, 0)
|
| | | batObj.SetDict(ChConfig.Def_Obj_Dict_TurnMissNum, 0)
|
| | | batObj.SetDict(ChConfig.Def_Obj_Dict_TurnParryNum, 0)
|
| | | |
| | | curID = batObj.GetID()
|
| | | skillManager = batObj.GetSkillManager()
|
| | | for index in range(0, skillManager.GetSkillCount()):
|
| | |
| | | remainTime = buff.GetRemainTime()
|
| | | if not remainTime:
|
| | | # 永久buff不处理
|
| | | #GameWorld.DebugLog(" 永久buff不处理! curID=%s,index=%s,skillID=%s" % (curID, index, buff.GetSkillID()))
|
| | | continue
|
| | | calcTimeline = buff.GetCalcTime()
|
| | | passTurn = __calcPassturn(calcTimeline, nowTimeline, False)
|
| | | if passTurn <= 0:
|
| | | #GameWorld.DebugLog(" passTurn <= 0 passTurn=%s,calcTimeline=%s,nowTimeline=%s,skillID=%s" % (passTurn, calcTimeline, nowTimeline, buff.GetSkillID()))
|
| | | continue
|
| | |
|
| | | updRemainTime = max(0, remainTime - passTurn)
|
| | |
| | | return
|
| | |
|
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_BigTurnStart)
|
| | | |
| | | # SetTimeline(gameObj, turnNum, 0)
|
| | | # # 重置连击、反击数
|
| | | # gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, 0)
|
| | | # gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkBackNum, 0)
|
| | | # gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnParryNum, 0)
|
| | | # gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnMissNum, 0)
|
| | | # gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkAddXPCount, 0)
|
| | | # gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnXPUseState, 0)
|
| | | # gameObj.SetDict(ChConfig.Def_PlayerKey_AttrFaintCD, 0) # 击晕CD
|
| | | # |
| | | # objType = gameObj.GetGameObjType()
|
| | | # objID = gameObj.GetID()
|
| | | # 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()
|
| | | # for i in range(skillManager.GetSkillCount()):
|
| | | # skill = skillManager.GetSkillByIndex(i)
|
| | | # remainTime = skill.GetRemainTime()
|
| | | # if not remainTime:
|
| | | # continue
|
| | | # skillID = skill.GetSkillID()
|
| | | # updRemainTime = max(0, remainTime - ChConfig.Def_PerTurnTick)
|
| | | # skill.SetRemainTime(updRemainTime)
|
| | | # GameWorld.DebugLog(" skillID=%s,remainTime=%s,updRemainTime=%s" % (skillID, remainTime, updRemainTime))
|
| | | # |
| | | # # 刷新定时处理的buff效果
|
| | | # SkillShell.ProcessPersistBuff(gameObj, tick)
|
| | | # |
| | | # PassiveBuffEffMng.OnPassiveSkillTrigger(gameObj, tagObj, None, ChConfig.TriggerType_TurnNum, tick)
|
| | | # |
| | | # __logGameObjAttr(gameObj)
|
| | | return
|
| | |
|
| | | def TurnFightPerTurnBigEnd(turnFight, batObj, turnNum):
|
| | |
| | | def AddTurnObjHurtValue(curBatObj, tagBatObj, hurtValue, lostHP, skillID=0, isBounce=False):
|
| | | ## 回合对象添加伤害值
|
| | | # @param isBounce: 是否反弹伤害
|
| | | if hurtValue <= 0:
|
| | | return
|
| | | curID = curBatObj.GetID()
|
| | | tagID = tagBatObj.GetID()
|
| | | if curID != tagID:
|
| | |
| | | % (curID, tagID, skillID, hurtValue, lostHP, updStatValue, tagBatObj.GetHP(), isBounce))
|
| | |
|
| | | if tagBatObj:
|
| | | updStatValue = tagBatObj.StatDefValue(lostHP)
|
| | | updStatValue = tagBatObj.StatDefValue(hurtValue)
|
| | | GameWorld.DebugLog(" 统计承伤: curID=%s,tagID=%s,skillID=%s,hurtValue=%s,lostHP=%s,updStatValue=%s,curHP=%s,isBounce=%s"
|
| | | % (tagID, curID, skillID, hurtValue, lostHP, updStatValue, tagBatObj.GetHP(), isBounce))
|
| | |
|
| | |
| | | objName = GetObjName(curBatObj)
|
| | |
|
| | | # 是否可行动状态判断
|
| | | canAction = True
|
| | | |
| | | canAction = curBatObj.CanAction()
|
| | | if not canAction:
|
| | | GameWorld.DebugLog("★回合%s %s 当前状态不可行动!" % (turnNum, objName))
|
| | | return
|
| | |
| | | if SkillCommon.isAngerSkill(useSkill):
|
| | | if curXP < xpMax:
|
| | | continue
|
| | | if curBatObj.IsInState(ChConfig.BatObjState_Sneer):
|
| | | GameWorld.DebugLog("嘲讽状态下,无法主动释放怒技!") # 可被动释放怒技,如怒技追击
|
| | | continue
|
| | | useCnt = -1 # xp技能优先释放
|
| | | else:
|
| | | useCnt = curBatObj.GetSkillUseCnt(skillID)
|
| | |
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, curBatObj, ChConfig.TriggerWay_HeroActionEnd)
|
| | | return True
|
| | |
|
| | | def DoAttack(curBatObj, tagBatObj, tick, turnBattleType=ChConfig.TurnBattleType_Normal, useSkill=None):
|
| | | # curID = curBatObj.GetID()
|
| | | # npcID = curBatObj.GetNPCID()
|
| | | # objName = GetObjName(curBatObj)
|
| | | # GameWorld.DebugLog(" ● %s DoAttack: curID=%s,,turnBattleType=%s" % (objName, curID, turnBattleType))
|
| | | # |
| | | # atkOK = False
|
| | | # curBatObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, turnBattleType)
|
| | | # |
| | | # if turnBattleType == ChConfig.TurnBattleType_AtkBack:
|
| | | # if not tagBatObj:
|
| | | # return
|
| | | # skillManager = curBatObj.GetSkillManager()
|
| | | # for index in range(0, skillManager.GetSkillCount()):
|
| | | # skill = skillManager.GetSkillByIndex(index)
|
| | | # if not skill:
|
| | | # continue
|
| | | # if skill.GetFuncType() == ChConfig.Def_SkillFuncType_AtkbackSkill:
|
| | | # useSkill = skill
|
| | | # break
|
| | | # atkOK = SkillShell.DoLogic_UseSkill(curBatObj, tagBatObj, useSkill, tick)
|
| | | # elif turnBattleType == ChConfig.TurnBattleType_Combo:
|
| | | # if not tagBatObj:
|
| | | # return
|
| | | # atkOK = SkillShell.DoLogic_UseSkill(curBatObj, tagBatObj, useSkill, tick)
|
| | | # else:
|
| | | # curXP = GameObj.GetXP(curBatObj)
|
| | | # xpMax = IpyGameDataPY.GetFuncCfg("AngerXP", 2) |
| | | # skillManager = curBatObj.GetSkillManager()
|
| | | # useSkillList = []
|
| | | # #GameWorld.DebugLog('skillCount=%s' % skillManager.GetSkillCount(), npcID)
|
| | | # for index in range(0, skillManager.GetSkillCount()):
|
| | | # useSkill = skillManager.GetSkillByIndex(index)
|
| | | # if not useSkill:
|
| | | # continue
|
| | | # if useSkill.GetFuncType() in [ChConfig.Def_SkillFuncType_AtkbackSkill]:
|
| | | # #基础普攻不能主动释放,目前仅用于反击
|
| | | # continue
|
| | | # #被动技能无法使用
|
| | | # if SkillCommon.isPassiveSkill(useSkill):
|
| | | # continue
|
| | | # #还在冷却时间内无法释放
|
| | | # if useSkill.GetRemainTime():
|
| | | # continue
|
| | | # skillID = useSkill.GetSkillID()
|
| | | # # 常规攻击优先xp
|
| | | # if SkillCommon.isAngerSkill(useSkill) and turnBattleType == ChConfig.TurnBattleType_Normal:
|
| | | # if curXP < xpMax:
|
| | | # continue
|
| | | # useCnt = -1 # xp技能优先释放
|
| | | # else:
|
| | | # useCnt = curBatObj.GetDictByKey(ChConfig.Def_NPC_Dict_SkillUseCnt % skillID) # 该技能已使用次数
|
| | | # useSkillList.append([useCnt, index, skillID, useSkill])
|
| | | # |
| | | # useSkillList.sort() # 按使用次数优先升序排,使用次数低的优先判断使用
|
| | | # #GameWorld.DebugLog(' 技能使用顺序 = useSkillList%s' % str(useSkillList), npcID)
|
| | | # |
| | | # for useInfo in useSkillList:
|
| | | # useSkill = useInfo[-1]
|
| | | # #skillID = useSkill.GetSkillID()
|
| | | # atkOK, tagBatObj = OnUseSkill(curBatObj, useSkill, tick)
|
| | | # if atkOK:
|
| | | # break
|
| | | # |
| | | # curBatObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, 0) # 无论攻击成功与否都重置战斗类型
|
| | | # |
| | | # tagID = 0
|
| | | # tagHP = 0
|
| | | # if tagObj:
|
| | | # tagID = tagObj.GetID()
|
| | | # tagHP = GameObj.GetHP(tagObj)
|
| | | # GameWorld.DebugLog(' atkOK=%s,tagID=%s,tagHP=%s' % (atkOK, tagID, tagHP), npcID)
|
| | | # if not atkOK:
|
| | | # return
|
| | | # |
| | | # if not tagObj:
|
| | | # return
|
| | | # |
| | | # if GameObj.GetFaction(curNPC) == GameObj.GetFaction(tagObj):
|
| | | # # 同阵营直接返回,不处理连击、反击
|
| | | # return True
|
| | | # |
| | | # curHP = GameObj.GetHP(curNPC)
|
| | | # tagHP = GameObj.GetHP(tagObj)
|
| | | # tagID = tagObj.GetID()
|
| | | # GameWorld.DebugLog(" curID-HP=(%s-%s),tagID-HP=(%s-%s)" % (curID, curHP, tagID, tagHP))
|
| | | # if tagHP <= 0 or curHP <= 0:
|
| | | # return True
|
| | | # |
| | | # # 反击,反击可打断连击,所以优先判断
|
| | | # if CanAtkBack(curNPC, tagObj):
|
| | | # DoAttack(tagObj, curNPC, tick, ChConfig.TurnBattleType_AtkBack)
|
| | | # return True
|
| | | # |
| | | # # 连击
|
| | | # if CanCombo(curNPC, tagObj):
|
| | | # DoAttack(curNPC, tagObj, tick, ChConfig.TurnBattleType_Combo, useSkill)
|
| | | # |
| | | return True
|
| | |
|
| | | def CanAtkBack(atkObj, defObj):
|
| | | ## 可否反击
|
| | | posNum = atkObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo) % 100
|
| | | if posNum <= 0:
|
| | | GameWorld.DebugLog(" 被非主战单位攻击时无法触发反击: atkID=%s,posNum=%s" % (atkObj.GetID(), posNum))
|
| | | return False
|
| | | atkDistType = AttackCommon.GetAtkDistType(defObj)
|
| | | if atkDistType == ChConfig.AtkDistType_Long:
|
| | | if not IpyGameDataPY.GetFuncCfg("ParryCfg", 2):
|
| | | GameWorld.DebugLog(" 远程单位不可反击: defID=%s" % (defObj.GetID()))
|
| | | return False
|
| | | defAtkBackRate = GameObj.GetAtkBackRate(defObj) # 防方反击率
|
| | | atkBackNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnAtkBackNum) # 已反击次数
|
| | | if atkBackNum > 10:
|
| | | # 内置最高反击数防范
|
| | | return False
|
| | | if atkBackNum > 0:
|
| | | validPerList = IpyGameDataPY.GetFuncEvalCfg("TurnFight", 4)
|
| | | vaildPer = validPerList[atkBackNum - 1] if len(validPerList) >= atkBackNum else 0
|
| | | defAtkBackRate = int(defAtkBackRate * vaildPer / 100.0)
|
| | | |
| | | atkAtkBackDefRate = GameObj.GetAtkBackDefRate(atkObj) # 攻方抵抗反击率
|
| | | atkBackRate = max(0, defAtkBackRate - atkAtkBackDefRate)
|
| | | if atkBackRate <= 0 or not GameWorld.CanHappen(atkBackRate):
|
| | | GameWorld.DebugLog(" 无法反击: defID=%s,atkBackNum=%s,atkBackRate=%s=(defAtkBackRate=%s - atkAtkBackDefRate=%s)" |
| | | % (defObj.GetID(), atkBackNum, atkBackRate, defAtkBackRate, atkAtkBackDefRate))
|
| | | return False
|
| | | GameWorld.DebugLog(" 可以反击: defID=%s,atkBackNum=%s,atkBackRate=%s=(defAtkBackRate=%s - atkAtkBackDefRate=%s)" |
| | | % (defObj.GetID(), atkBackNum, atkBackRate, defAtkBackRate, atkAtkBackDefRate))
|
| | | return True
|
| | |
|
| | | def CanCombo(atkObj, defObj):
|
| | | ## 可否连击
|
| | | |
| | | atkComboRate = GameObj.GetComboRate(atkObj) # 攻方连击率
|
| | | comboNum = atkObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnComboNum) # 已连击次数
|
| | | if comboNum > 10:
|
| | | # 内置最高连击数防范
|
| | | return False
|
| | | if comboNum > 0:
|
| | | validPerList = IpyGameDataPY.GetFuncEvalCfg("TurnFight", 3)
|
| | | vaildPer = validPerList[comboNum - 1] if len(validPerList) >= comboNum else 0
|
| | | atkComboRate = int(atkComboRate * vaildPer / 100.0)
|
| | | |
| | | defComboReduce = GameObj.GetComboDefRate(defObj) # 防方抵抗连击率
|
| | | comboRate = max(0, atkComboRate - defComboReduce)
|
| | | if comboRate <= 0 or not GameWorld.CanHappen(comboRate):
|
| | | GameWorld.DebugLog(" 无法连击: atkID=%s,comboNum=%s,comboRate=%s=(atkComboRate=%s - defComboReduce=%s)" |
| | | % (atkObj.GetID(), comboNum, comboRate, atkComboRate, defComboReduce))
|
| | | return False
|
| | | GameWorld.DebugLog(" 可以连击: atkID=%s,comboNum=%s,comboRate=%s=(atkComboRate=%s - defComboReduce=%s)" |
| | | % (atkObj.GetID(), comboNum, comboRate, atkComboRate, defComboReduce))
|
| | | return True
|
| | |
|
| | | def SetObjKilled(turnFight, gameObj, killer=None, useSkill=None):
|
| | | objID = gameObj.GetID()
|
| | | GameWorld.DebugLog(" %s 回合战斗主体被击杀: curID=%s" % (GetObjName(gameObj), objID))
|
| | | gameObj.SetHP(0)
|
| | | killerObjID = killer.GetID() if killer else 0
|
| | | skillID = useSkill.GetSkillID() if useSkill else 0
|
| | | GameWorld.DebugLog(" %s 回合战斗主体被击杀: curID=%s,killerObjID=%s,skillID=%s" % (GetObjName(gameObj), objID, killerObjID, skillID))
|
| | | gameObj.SetDead()
|
| | |
|
| | | clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagMCTurnFightObjDead)
|
| | | clientPack.ObjID = objID
|
| | |
| | |
|
| | | turnFight.costTime = time.time() - turnFight.startTime
|
| | | winFaction = turnFight.winFaction
|
| | | GameWorld.DebugLog("--- 战斗结束处理 --- %s, winFaction=%s, costTime=%ss" % (guid, winFaction, turnFight.costTime))
|
| | | GameWorld.DebugLog("--- 战斗结束处理 ---, winFaction=%s, costTime=%ss, %s" % (winFaction, turnFight.costTime, guid))
|
| | |
|
| | | # 统计明细
|
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | |
| | | atkHurt = batObj.hurtStat
|
| | | defHurt = batObj.defStat
|
| | | cureHP = batObj.cureStat
|
| | | GameWorld.DebugLog(" Pos:%s ID=%s-%s-%s,,HP=%s/%s, 输出=%s,承伤=%s,治疗=%s" |
| | | GameWorld.DebugLog(" Pos:%s ID=%s,npcID=%s,heroID=%s,HP=%s/%s, 输出=%s,承伤=%s,治疗=%s" |
| | | % (posNum, objID, npcID, heroID, batObj.GetHP(), batObj.GetMaxHP(), atkHurt, defHurt, cureHP))
|
| | | lineupStatInfo[str(posNum)] = {"ObjID":objID, "HeroID":heroID, "NPCID":npcID, "AtkHurt":atkHurt, "DefHurt":defHurt, "CureHP":cureHP}
|
| | |
|
| | |
| | |
|
| | | Def_SkillID_Peace = 23048 # 玩家间和平buff
|
| | | #----------------------------------------------------------------------
|
| | | #战斗类型
|
| | | Def_ChanceDefRate = 2000 # 抵御伤害概率, 目前固定20%概率
|
| | |
|
| | | #技能释放后需要额外处理逻辑
|
| | | AfterLogic_DelBuff = "DelBuff"
|
| | | AfterLogic_AddBuff = "AddBuff"
|
| | | AfterLogic_SyncBuff = "SyncBuff"
|
| | |
|
| | | #伤害类型
|
| | | (
|
| | |
| | | CampType_Justice = ShareDefine.CampType_Justice # 正义
|
| | | CampType_Evil = ShareDefine.CampType_Evil # 邪恶
|
| | |
|
| | | #buff释放类型
|
| | | BuffAtkType_DamageShield = 1003 # 承伤盾
|
| | |
|
| | | #计算类型
|
| | | Def_CalcTypeList = (
|
| | | Def_Calc_Attack, # 攻击 0
|
| | | Def_Calc_MaxHP, # 最大生命值 1
|
| | | Def_Calc_HurtValue, # 伤害值 2
|
| | | Def_Calc_TagMaxHP, # 目标最大生命值 3
|
| | | ) = range(4)
|
| | |
|
| | | #治疗类型(影响公式参数)
|
| | | Def_CureTypeList = (
|
| | | Def_Cure_Attack, # 攻击 0
|
| | |
| | | Def_Skill_HappenState_LuckyHit = 0x0004 # 必会心一击
|
| | | Def_Skill_HappenState_ThumpHit = 0x0008 # 必重击
|
| | |
|
| | | # 回合战斗行列数
|
| | | TurnFightRows = 2
|
| | | TurnFightCols = 3
|
| | |
|
| | | def GetInColNum(posNum):
|
| | | ## 获取站位编号所在列编号
|
| | | # @param posNum: 在阵容中的站位 1 ~ n
|
| | | # @return: 1 ~ 总列数
|
| | | return (posNum - 1) % TurnFightCols + 1
|
| | |
|
| | | def GetInRowNum(posNum):
|
| | | ## 获取站位编号所在行编号
|
| | | # @param posNum: 在阵容中的站位 1 ~ n
|
| | | # @return: 1 ~ 总行数
|
| | | return (posNum - 1) / TurnFightCols + 1
|
| | |
|
| | | # 技能目标 - 瞄准范围
|
| | | (
|
| | | SkillTagAim_All, # 全部 0
|
| | |
| | | SkillTagAffect_HPLowest, # 血量最低 1
|
| | | SkillTagAffect_HPHighest, # 血量最高 2
|
| | | SkillTagAffect_Death, # 死亡单位 3
|
| | | ) = range(4)
|
| | | SkillTagAffect_UncontrolledPriority, # 未被控制优先 4
|
| | | ) = range(5)
|
| | |
|
| | | #技能施法目标
|
| | | Def_UseSkillAim_Type = 3
|
| | |
| | |
|
| | | # 回合攻击战斗类型
|
| | | (
|
| | | TurnBattleType_Normal, # 常规攻击
|
| | | TurnBattleType_Combo, # 连击
|
| | | TurnBattleType_AtkBack, # 反击
|
| | | TurnBattleType_Pursue , # 追击
|
| | | ) = range(4)
|
| | | TurnBattleType_Normal, # 常规攻击 0
|
| | | TurnBattleType_Combo, # 连击 1
|
| | | TurnBattleType_AtkBack, # 反击 2
|
| | | TurnBattleType_Pursue, # 追击 3
|
| | | TurnBattleType_Enhance, # 额外技能 4
|
| | | TurnBattleType_Passive, # 被动技能 5
|
| | | ) = range(6)
|
| | |
|
| | | Def_PerTurnTick = 1000 # 每回合等同于常规tick时长
|
| | |
|
| | |
| | | BatObjState_Sneer, # 嘲讽 9
|
| | | BatObjState_LimitSkill, # 沉默 10
|
| | | BatObjState_LimitAddHP, # 禁疗 11
|
| | | ) = range(12)
|
| | | BatObjState_Stone, # 石化 12
|
| | | ) = range(13)
|
| | |
|
| | | # 被控制的状态列表,无法行动,处于某些控制类buff影响状态下,如晕眩,冰冻,石化
|
| | | InControlledStateList = [BatObjState_Frozen, BatObjState_Stun, BatObjState_Stone]
|
| | |
|
| | | #玩家状态定义,不能超过31个,如超过,需扩展多个key支持
|
| | | Def_PlayerStateList = (
|
| | |
| | | TriggerWay_HeroTurnEnd, # 武将回合开始时 5
|
| | | TriggerWay_HeroActionStart, # 武将行动前 6
|
| | | TriggerWay_HeroActionEnd, # 武将行动后 7
|
| | | ) = range(1, 1 + 7)
|
| | | TriggerWay_CalcTagInState, # 攻击计算时对方处于xx状态时(参数:状态1|2|...)一般用于攻击时属性计算 8
|
| | | TriggerWay_AttackOverTagInState, # 攻击计算后对方处于xx状态时(参数:状态1|2|...)一般用于攻击后触发效果 9
|
| | | TriggerWay_AttackOverDirect, # 直接攻击后 (非buff攻击)10
|
| | | TriggerWay_BeAttackedDirect, # 受到直接攻击时 (非buff攻击)11
|
| | | TriggerWay_ShieldBroken, # 承伤盾被击破时 12
|
| | | ) = range(1, 1 + 12)
|
| | |
|
| | | # 被动触发有效来源
|
| | | TriggerSrc_Skill = 1
|
| | | TriggerSrc_Buff = 2
|
| | |
|
| | | (
|
| | | TriggerType_BeSuperHit, # 被暴击触发技能 1
|
| | |
| | | ("LastTime", c_int), # 剩余时长毫秒/回合数
|
| | | ("Layer", c_ushort), # 层数,不需要默认0
|
| | | ("OwnerID", c_int), # buff来源者,即施法方
|
| | | ("Value1", c_int), |
| | | ("Value2", c_int), |
| | | ("Value3", c_int), |
| | | ]
|
| | |
|
| | | def __init__(self):
|
| | |
| | | self.LastTime = 0
|
| | | self.Layer = 0
|
| | | self.OwnerID = 0
|
| | | self.Value1 = 0
|
| | | self.Value2 = 0
|
| | | self.Value3 = 0
|
| | | return
|
| | |
|
| | | def GetLength(self):
|
| | |
| | | RelatedSkillID:%d,
|
| | | LastTime:%d,
|
| | | Layer:%d,
|
| | | OwnerID:%d
|
| | | OwnerID:%d,
|
| | | Value1:%d,
|
| | | Value2:%d,
|
| | | Value3:%d
|
| | | '''\
|
| | | %(
|
| | | self.Cmd,
|
| | |
| | | self.RelatedSkillID,
|
| | | self.LastTime,
|
| | | self.Layer,
|
| | | self.OwnerID
|
| | | self.OwnerID,
|
| | | self.Value1,
|
| | | self.Value2,
|
| | | self.Value3
|
| | | )
|
| | | return DumpString
|
| | |
|
| | |
| | | ("BYTE", "TriggerWay3", 0),
|
| | | ("BYTE", "TriggerSrc3", 0),
|
| | | ("list", "TriggerParams3", 0),
|
| | | ("DWORD", "ConnSkill", 0),
|
| | | ("WORD", "CoolDownTime", 0),
|
| | | ("list", "IgnoreStates", 0),
|
| | | ("list", "BuffStates", 0),
|
| | | ("BYTE", "CurBuffState", 0),
|
| | | ("WORD", "LastTime", 0),
|
| | | ("BYTE", "LayerCnt", 0),
|
| | | ("BYTE", "LayerMax", 0),
|
| | |
| | | ("DWORD", "DieContinue", 0),
|
| | | ("list", "EnhanceSkillList", 0),
|
| | | ("DWORD", "FightPower", 0),
|
| | | ("char", "SkillMotionName", 0),
|
| | | ),
|
| | |
|
| | | "Hero":(
|
| | |
| | | def GetEffectID1(self): return self.attrTuple[17] # 效果ID1 DWORD
|
| | | def GetEffectValues1(self): return self.attrTuple[18] # 效果值列表1 list
|
| | | def GetTriggerWay1(self): return self.attrTuple[19] # 触发方式 BYTE
|
| | | def GetTriggerSrc1(self): return self.attrTuple[20] # 触发来源 BYTE
|
| | | def GetTriggerSrc1(self): return self.attrTuple[20] # 有效来源 BYTE
|
| | | def GetTriggerParams1(self): return self.attrTuple[21] # 触发参数 list
|
| | | def GetEffectID2(self): return self.attrTuple[22] # 效果ID2 DWORD
|
| | | def GetEffectValues2(self): return self.attrTuple[23] # 效果值列表2 list
|
| | | def GetTriggerWay2(self): return self.attrTuple[24] # 触发方式 BYTE
|
| | | def GetTriggerSrc2(self): return self.attrTuple[25] # 触发来源 BYTE
|
| | | def GetTriggerSrc2(self): return self.attrTuple[25] # 有效来源 BYTE
|
| | | def GetTriggerParams2(self): return self.attrTuple[26] # 触发参数 list
|
| | | def GetEffectID3(self): return self.attrTuple[27] # 效果ID3 DWORD
|
| | | def GetEffectValues3(self): return self.attrTuple[28] # 效果值列表3 list
|
| | | def GetTriggerWay3(self): return self.attrTuple[29] # 触发方式 BYTE
|
| | | def GetTriggerSrc3(self): return self.attrTuple[30] # 触发来源 BYTE
|
| | | def GetTriggerSrc3(self): return self.attrTuple[30] # 有效来源 BYTE
|
| | | def GetTriggerParams3(self): return self.attrTuple[31] # 触发参数 list
|
| | | def GetConnSkill(self): return self.attrTuple[32] # 关联技能 DWORD
|
| | | def GetCoolDownTime(self): return self.attrTuple[33] # 技能冷却时间 WORD
|
| | | def GetIgnoreStates(self): return self.attrTuple[34] # 无视限制列表 list
|
| | | def GetBuffStates(self): return self.attrTuple[35] # Buff״ֵ̬ list
|
| | | def GetLastTime(self): return self.attrTuple[36] # 持续时间 WORD
|
| | | def GetLayerCnt(self): return self.attrTuple[37] # Buff层数 BYTE
|
| | | def GetLayerMax(self): return self.attrTuple[38] # 最大层数 BYTE
|
| | | def GetBuffRepeat(self): return self.attrTuple[39] # Buff叠加规则 DWORD
|
| | | def GetDieContinue(self): return self.attrTuple[40] # Buff死亡存在 DWORD
|
| | | def GetEnhanceSkillList(self): return self.attrTuple[41] # 触发技能ID列表 list
|
| | | def GetFightPower(self): return self.attrTuple[42] # 技能战斗力 DWORD |
| | | def GetCoolDownTime(self): return self.attrTuple[32] # 技能冷却时间 WORD
|
| | | def GetIgnoreStates(self): return self.attrTuple[33] # 无视限制列表 list
|
| | | def GetCurBuffState(self): return self.attrTuple[34] # Buff״ֵ̬ BYTE
|
| | | def GetLastTime(self): return self.attrTuple[35] # 持续时间 WORD
|
| | | def GetLayerCnt(self): return self.attrTuple[36] # Buff层数 BYTE
|
| | | def GetLayerMax(self): return self.attrTuple[37] # 最大层数 BYTE
|
| | | def GetBuffRepeat(self): return self.attrTuple[38] # Buff叠加规则 DWORD
|
| | | def GetDieContinue(self): return self.attrTuple[39] # Buff死亡存在 DWORD
|
| | | def GetEnhanceSkillList(self): return self.attrTuple[40] # 触发技能ID列表 list
|
| | | def GetFightPower(self): return self.attrTuple[41] # 技能战斗力 DWORD
|
| | | def GetSkillMotionName(self): return self.attrTuple[42] # 技能动作名 char |
| | | |
| | | # 武将表 |
| | | class IPY_Hero(): |
| | |
| | | #0通哟 1 PVP类型 2PVE类型
|
| | | return curSkill.GetHurtType() % 10
|
| | |
|
| | | def isDamageShieldSkill(skillData):
|
| | | ## 是否承伤盾技能
|
| | | return skillData.GetAtkType() == ChConfig.BuffAtkType_DamageShield
|
| | |
|
| | | def isAngerSkill(curSkill):
|
| | | ## 是否怒气技能
|
| | | return curSkill and curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_AngerSkill
|
| | |
| | |
|
| | | import TurnBuff
|
| | |
|
| | | def DoBuffEffectLogic(turnFight, batObj, curBuff, curEffect, connSkill):
|
| | | def DoBuffEffectLogic(turnFight, batObj, tagObj, curBuff, curEffect, connSkill):
|
| | | singleLayerCnt = max(1, curEffect.GetEffectValue(0)) # 单次消耗层数/次数
|
| | | noDel = curEffect.GetEffectValue(1) # 是否不扣除层数,默认0-扣除 1-不扣除
|
| | | isAll = curEffect.GetEffectValue(2) # 是否结算剩余全部层数/次数,默认0结算单次
|
| New file |
| | |
| | | #!/usr/bin/python
|
| | | # -*- coding: GBK -*-
|
| | | #-------------------------------------------------------------------------------
|
| | | #
|
| | | ##@package Skill.PassiveTrigger.PassiveEff_5010
|
| | | #
|
| | | # @todo:攻击方触发释放技能(可继承主技能目标或重新设置目标)
|
| | | # @author hxp
|
| | | # @date 2025-08-25
|
| | | # @version 1.0
|
| | | #
|
| | | # 详细描述: 攻击方触发释放技能(可继承主技能目标或重新设置目标)
|
| | | #
|
| | | #-------------------------------------------------------------------------------
|
| | | #"""Version = 2025-08-25 12:00"""
|
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | import TurnSkill
|
| | | import IpyGameDataPY
|
| | | import GameWorld
|
| | | import ChConfig
|
| | |
|
| | | def DoSkillEffectLogic(turnFight, batObj, tagObj, effSkill, curEffect, connSkill):
|
| | | effectID = curEffect.GetEffectID()
|
| | | skillID = curEffect.GetEffectValue(0)
|
| | | if not skillID:
|
| | | passiveSkill = effSkill
|
| | | else:
|
| | | passiveSkill = IpyGameDataPY.GetIpyGameData("Skill", skillID)
|
| | | if not passiveSkill:
|
| | | return
|
| | | passiveSkillID = passiveSkill.GetSkillID()
|
| | | tagObjList = connSkill.GetTagObjList() if connSkill else []
|
| | | # 继承主技能目标
|
| | | if passiveSkill.GetTagAim() == ChConfig.SkillTagAim_MainSkill and tagObjList:
|
| | | happenRate = passiveSkill.GetHappenRate()
|
| | | GameWorld.DebugLog("被动触发技能,继承主技能目标! effectID=%s,passiveSkillID=%s,happenRate=%s" % (effectID, passiveSkillID, happenRate))
|
| | | passiveTagObjList = []
|
| | | for tagObj in tagObjList:
|
| | | tagID = tagObj.GetID()
|
| | | if tagObj.GetHP() <= 0:
|
| | | GameWorld.DebugLog(" 已被击杀不触发: tagID=%s" % (tagID))
|
| | | continue
|
| | | inHurt = False
|
| | | for hurtObj in connSkill.GetHurtObjList():
|
| | | if hurtObj.GetObjID() != tagID:
|
| | | continue
|
| | | if not hurtObj.GetHurtHP() or hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
|
| | | continue
|
| | | inHurt = True
|
| | | break
|
| | | if not inHurt:
|
| | | GameWorld.DebugLog(" 没有伤血不触发: tagID=%s" % (tagID))
|
| | | continue
|
| | | if happenRate and happenRate != ChConfig.Def_MaxRateValue and not GameWorld.CanHappen(happenRate, ChConfig.Def_MaxRateValue):
|
| | | GameWorld.DebugLog(" 概率不触发: tagID=%s,happenRate=%s" % (tagID, happenRate))
|
| | | continue
|
| | | passiveTagObjList.append(tagObj)
|
| | | |
| | | if passiveTagObjList:
|
| | | TurnSkill.OnUseSkill(turnFight, batObj, passiveSkill, passiveTagObjList, batType=ChConfig.TurnBattleType_Passive, bySkill=connSkill)
|
| | | else:
|
| | | GameWorld.DebugLog("被动触发技能,重新锁定目标! effectID=%s,passiveSkillID=%s" % (effectID, passiveSkillID))
|
| | | TurnSkill.OnUseSkill(turnFight, batObj, passiveSkill, batType=ChConfig.TurnBattleType_Passive, bySkill=connSkill)
|
| | | |
| | | return
|
| | |
|
| | | def DoBuffEffectLogic(turnFight, batObj, tagObj, curBuff, curEffect, connSkill):
|
| | | return DoSkillEffectLogic(turnFight, batObj, tagObj, None, curEffect, connSkill)
|
| New file |
| | |
| | | #!/usr/bin/python
|
| | | # -*- coding: GBK -*-
|
| | | #-------------------------------------------------------------------------------
|
| | | #
|
| | | ##@package Skill.PassiveTrigger.PassiveEff_5011
|
| | | #
|
| | | # @todo:被击方触发释放技能(对攻击方或重新设置目标)
|
| | | # @author hxp
|
| | | # @date 2025-08-25
|
| | | # @version 1.0
|
| | | #
|
| | | # 详细描述: 被击方触发释放技能(对攻击方或重新设置目标)
|
| | | #
|
| | | #-------------------------------------------------------------------------------
|
| | | #"""Version = 2025-08-25 12:00"""
|
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | import TurnSkill
|
| | | import IpyGameDataPY
|
| | | import GameWorld
|
| | | import ChConfig
|
| | |
|
| | | def DoSkillEffectLogic(turnFight, batObj, tagObj, effSkill, curEffect, connSkill):
|
| | | effectID = curEffect.GetEffectID()
|
| | | skillID = curEffect.GetEffectValue(0)
|
| | | if not skillID:
|
| | | passiveSkill = effSkill
|
| | | else:
|
| | | passiveSkill = IpyGameDataPY.GetIpyGameData("Skill", skillID)
|
| | | if not passiveSkill:
|
| | | return
|
| | | passiveSkillID = passiveSkill.GetSkillID()
|
| | | # 继承主技能目标
|
| | | if passiveSkill.GetTagAim() == ChConfig.SkillTagAim_MainSkill:
|
| | | happenRate = passiveSkill.GetHappenRate()
|
| | | GameWorld.DebugLog("被动触发技能,继承主技能目标! effectID=%s,passiveSkillID=%s,happenRate=%s" % (effectID, passiveSkillID, happenRate))
|
| | | tagObjList = [tagObj]
|
| | | passiveTagObjList = []
|
| | | for tagObj in tagObjList:
|
| | | tagID = tagObj.GetID()
|
| | | if tagObj.GetHP() <= 0:
|
| | | GameWorld.DebugLog(" 已被击杀不触发: tagID=%s" % (tagID))
|
| | | continue
|
| | | if happenRate and happenRate != ChConfig.Def_MaxRateValue and not GameWorld.CanHappen(happenRate, ChConfig.Def_MaxRateValue):
|
| | | GameWorld.DebugLog(" 概率不触发: tagID=%s,happenRate=%s" % (tagID, happenRate))
|
| | | continue
|
| | | passiveTagObjList.append(tagObj)
|
| | | |
| | | if passiveTagObjList:
|
| | | TurnSkill.OnUseSkill(turnFight, batObj, passiveSkill, passiveTagObjList, batType=ChConfig.TurnBattleType_Passive, bySkill=connSkill)
|
| | | else:
|
| | | GameWorld.DebugLog("被动触发技能,重新锁定目标! effectID=%s,passiveSkillID=%s" % (effectID, passiveSkillID))
|
| | | TurnSkill.OnUseSkill(turnFight, batObj, passiveSkill, batType=ChConfig.TurnBattleType_Passive, bySkill=connSkill)
|
| | | |
| | | return
|
| | |
|
| | | def DoBuffEffectLogic(turnFight, batObj, tagObj, curBuff, curEffect, connSkill):
|
| | | return DoSkillEffectLogic(turnFight, batObj, tagObj, None, curEffect, connSkill)
|
| | |
| | | import ChConfig
|
| | | import GameWorld
|
| | | import ChPyNetSendPack
|
| | | import IpyGameDataPY
|
| | | import TurnBuffs
|
| | | import BattleObj
|
| | | import ObjPool
|
| | |
|
| | | GameWorld.ImportAll("Script\\Skill\\", "TurnBuffs")
|
| | |
|
| | | def GetAddBuffValue(attacker, defender, curSkill):
|
| | | def GetAddBuffValue(turnFight, attacker, defender, curSkill):
|
| | | callFunc = GameWorld.GetExecFunc(TurnBuffs, "BuffAtkType_%d.%s" % (curSkill.GetAtkType(), "CalcBuffValue"))
|
| | | if not callFunc:
|
| | | return []
|
| | | return callFunc(attacker, defender, curSkill)
|
| | | return callFunc(turnFight, attacker, defender, curSkill)
|
| | |
|
| | | def OnAddBuff(turnFight, batObj, buffSkill, buffOwner=None):
|
| | | def DoAddBuffBySkillID(turnFight, batObj, skillID, buffOwner=None, bySkill=None, afterLogic=False):
|
| | | ## 根据技能ID添加buff
|
| | | if not skillID:
|
| | | return
|
| | | skillIpyData = IpyGameDataPY.GetIpyGameData("Skill", skillID)
|
| | | if not skillIpyData:
|
| | | return
|
| | | tagObjList = [batObj]
|
| | | poolMgr = ObjPool.GetPoolMgr()
|
| | | useSkill = poolMgr.acquire(BattleObj.PySkill, skillIpyData)
|
| | | useSkill.SetTagObjList(tagObjList)
|
| | | |
| | | OnAddBuff(turnFight, batObj, useSkill, buffOwner, bySkill, afterLogic)
|
| | | |
| | | poolMgr.release(useSkill)
|
| | | return
|
| | |
|
| | | def OnAddBuff(turnFight, batObj, buffSkill, buffOwner=None, bySkill=None, afterLogic=False):
|
| | | skillID = buffSkill.GetSkillID()
|
| | | bySkill = buffSkill.GetBySkill()
|
| | | bySkill = buffSkill.GetBySkill() if not bySkill else bySkill
|
| | | relatedSkillID = bySkill.GetSkillID() if bySkill else 0
|
| | | curID = batObj.GetID()
|
| | | if not buffOwner:
|
| | | buffOwner = batObj
|
| | | ownerID = buffOwner.GetID()
|
| | | buffValueList = GetAddBuffValue(buffOwner, batObj, buffSkill)
|
| | | GameWorld.DebugLog("OnAddBuff: curID=%s,skillID=%s,ownerID=%s,relatedSkillID=%s,buffValueList=%s" % (curID, skillID, ownerID, relatedSkillID, buffValueList))
|
| | | 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))
|
| | |
|
| | | skillTypeID = buffSkill.GetSkillTypeID()
|
| | | # 先简单做下能加上即可
|
| | | buffMgr = batObj.GetBuffManager()
|
| | | buffIDList = buffMgr.FindBuffIDBySkillTypeID(skillTypeID)
|
| | | if buffIDList:
|
| | | GameWorld.DebugLog(" 已经存在该buff: skillTypeID=%s,buffIDList=%s" % (skillTypeID, buffIDList))
|
| | | # buff堆叠逻辑
|
| | | buffList = buffMgr.FindBuffBySkillTypeID(skillTypeID)
|
| | | if buffList:
|
| | | # buff堆叠逻辑,待处理,先直接通知
|
| | | for buff in buffList:
|
| | | if not buff:
|
| | | continue
|
| | | GameWorld.DebugLog(" 已经存在该buff: buffID=%s,skillTypeID=%s" % (buff.GetBuffID(), skillTypeID))
|
| | | if afterLogic and bySkill:
|
| | | bySkill.AddAfterLogic(ChConfig.AfterLogic_AddBuff, [batObj, buff, buffOwner])
|
| | | else:
|
| | | SyncBuffRefresh(turnFight, batObj, buff, relatedSkillID)
|
| | |
|
| | | return True
|
| | |
|
| | | __AddNewBuff(turnFight, batObj, buffMgr, buffSkill, buffValueList, buffOwner)
|
| | | __AddNewBuff(turnFight, batObj, buffMgr, buffSkill, buffValueList, buffOwner, bySkill, afterLogic)
|
| | | return True
|
| | |
|
| | | def __AddNewBuff(turnFight, batObj, buffMgr, buffSkill, buffValueList, buffOwner):
|
| | | def __AddNewBuff(turnFight, batObj, buffMgr, buffSkill, buffValueList, buffOwner, bySkill=None, afterLogic=False):
|
| | | skillID = buffSkill.GetSkillID()
|
| | | bySkill = buffSkill.GetBySkill()
|
| | | relatedSkillID = bySkill.GetSkillID() if bySkill else 0
|
| | | curID = batObj.GetID()
|
| | | ownerID = buffOwner.GetID()
|
| | |
| | | buff.SetRemainTime(buffSkill.GetLastTime())
|
| | | buff.SetLayer(buffSkill.GetLayerCnt())
|
| | | buff.SetBuffValueList(buffValueList)
|
| | | buffStates = buffSkill.GetBuffStates()
|
| | | for buffState in buffStates:
|
| | | buffMgr.AddBuffState(buffState, buffID)
|
| | | isNotify = True
|
| | | if isNotify:
|
| | | curBuffState = buffSkill.GetCurBuffState()
|
| | | if curBuffState:
|
| | | buffMgr.AddBuffState(curBuffState, buffID)
|
| | | |
| | | if afterLogic and bySkill:
|
| | | bySkill.AddAfterLogic(ChConfig.AfterLogic_AddBuff, [batObj, buff, buffOwner])
|
| | | else:
|
| | | SyncBuffRefresh(turnFight, batObj, buff, relatedSkillID)
|
| | |
|
| | | DoBuffAddOver(turnFight, batObj, buffSkill, buff, buffOwner)
|
| | |
| | | continue
|
| | |
|
| | | if curEffect.GetTriggerWay():
|
| | | if curEffect.GetTriggerSrc() == 2:
|
| | | if curEffect.GetTriggerSrc() != ChConfig.TriggerSrc_Skill:
|
| | | passiveEffMgr.AddBuffPassiveEffect(addBuff, buffSkill, curEffect)
|
| | |
|
| | | elif effectID in ChConfig.AttrIDList:
|
| | |
| | |
|
| | | return
|
| | |
|
| | | def DoBuffDel(turnFight, batObj, curBuff):
|
| | | ## 删除buff
|
| | | def DoBuffDel(turnFight, batObj, curBuff, relatedSkill=None, afterLogic=False, tagObj=None):
|
| | | '''删除buff
|
| | | @param relatedSkill: 关联的技能
|
| | | @param afterLogic: 是否需要在关联技能处理完毕后才处理删除后续逻辑,如通知,触发被动等
|
| | | @param tagObj: 由谁引起的buff删除
|
| | | '''
|
| | | |
| | | release = True
|
| | | isSync = True
|
| | | relatedSkillID = relatedSkill.GetSkillID() if relatedSkill else 0
|
| | | if afterLogic and relatedSkill:
|
| | | release = False
|
| | | isSync = False
|
| | |
|
| | | isRefreshAttr = False # 是否刷属性
|
| | | haveBuffPassiveEff = False
|
| | |
|
| | | buffObjID = batObj.GetID()
|
| | | buffMgr = batObj.GetBuffManager()
|
| | | buffID = curBuff.GetBuffID()
|
| | | skillData = curBuff.GetSkillData()
|
| | |
| | | continue
|
| | |
|
| | | if curEffect.GetTriggerWay():
|
| | | if curEffect.GetTriggerSrc() == 2:
|
| | | if curEffect.GetTriggerSrc() != ChConfig.TriggerSrc_Skill:
|
| | | haveBuffPassiveEff = True
|
| | |
|
| | | elif effectID in ChConfig.AttrIDList:
|
| | |
| | | if haveBuffPassiveEff:
|
| | | batObj.GetPassiveEffManager().DelBuffPassiveEffect(buffID)
|
| | |
|
| | | buffStates = skillData.GetBuffStates()
|
| | | for buffState in buffStates:
|
| | | buffMgr.DelBuffState(buffState, buffID)
|
| | | curBuffState = skillData.GetCurBuffState()
|
| | | if curBuffState:
|
| | | buffMgr.DelBuffState(curBuffState, buffID)
|
| | |
|
| | | # 最后删除buff、通知
|
| | | buffMgr.DelBuff(buffID)
|
| | | SyncBuffDel(turnFight, batObj, buffID)
|
| | | buffMgr.DelBuff(buffID, release)
|
| | | if isSync:
|
| | | SyncBuffDel(turnFight, buffObjID, buffID, relatedSkillID)
|
| | | if afterLogic and relatedSkill:
|
| | | tagObjID = tagObj.GetID() if tagObj else buffObjID
|
| | | relatedSkill.AddAfterLogic(ChConfig.AfterLogic_DelBuff, [buffObjID, curBuff, tagObjID])
|
| | |
|
| | | if isRefreshAttr:
|
| | | RefreshBuffAttr(batObj)
|
| | | return
|
| | |
|
| | | def DoBuffDelAfterLogicOver(turnFight, buffObjID, curBuff, relatedSkill):
|
| | | ## buff删除后续处理逻辑处理完毕
|
| | | relatedSkillID = relatedSkill.GetSkillID() if relatedSkill else 0
|
| | | SyncBuffDel(turnFight, buffObjID, curBuff.GetBuffID(), relatedSkillID)
|
| | | ObjPool.GetPoolMgr().release(curBuff)
|
| | | return
|
| | |
|
| | | def DoBuffProcess(turnFight, batObj, curBuff):
|
| | |
| | | clientPack.LastTime = curBuff.GetRemainTime()
|
| | | clientPack.Layer = curBuff.GetLayer()
|
| | | clientPack.OwnerID = curBuff.GetOwnerID()
|
| | | clientPack.Value1 = curBuff.GetValue1()
|
| | | clientPack.Value2 = curBuff.GetValue2()
|
| | | clientPack.Value3 = curBuff.GetValue3()
|
| | | turnFight.addBatPack(clientPack)
|
| | | return
|
| | |
|
| | | def SyncBuffDel(turnFight, curBatObj, buffID, relatedSkillID=0):
|
| | | def SyncBuffDel(turnFight, objID, buffID, relatedSkillID=0):
|
| | | clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCBuffDel)
|
| | | clientPack.ObjID = curBatObj.GetID()
|
| | | clientPack.ObjID = objID
|
| | | clientPack.BuffID = buffID
|
| | | clientPack.RelatedSkillID = relatedSkillID
|
| | | turnFight.addBatPack(clientPack)
|
| | |
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | import TurnSkill
|
| | | import ChConfig
|
| | |
|
| | | def CalcBuffValue(attacker, defender, curSkill):
|
| | | def CalcBuffValue(turnFight, attacker, defender, curSkill):
|
| | | #calcType = curSkill.GetCalcType()
|
| | | skillPer = curSkill.GetSkillPer()
|
| | | skillValue = curSkill.GetSkillValue()
|
| | |
|
| | | hurtValue, hurtTypes = TurnSkill.CalcHurtHP(attacker, defender, curSkill, skillValue, skillPer, damageoftime=1)
|
| | | return [hurtValue, hurtTypes]
|
| | | hurtValue, hurtTypes = TurnSkill.CalcHurtHP(turnFight, attacker, defender, curSkill, skillValue, skillPer, damageoftime=1)
|
| | | return [hurtValue % ChConfig.Def_PerPointValue, hurtValue / ChConfig.Def_PerPointValue, hurtTypes]
|
| | |
|
| | | def DoBuffProcess(turnFight, batObj, curBuff):
|
| | | ## 执行单次逻辑
|
| | | hurtValue = curBuff.GetBuffValue(0) # 单次伤害
|
| | | hurtTypes = curBuff.GetBuffValue(1)
|
| | | hurtValue = curBuff.GetValue1() + curBuff.GetValue2() * ChConfig.Def_PerPointValue # 单次伤害
|
| | | hurtTypes = curBuff.GetValue3()
|
| | | TurnSkill.DoDOTAttack(turnFight, batObj, curBuff, hurtValue, hurtTypes)
|
| | | return
|
| | |
|
| New file |
| | |
| | | #!/usr/bin/python
|
| | | # -*- coding: GBK -*-
|
| | | #-------------------------------------------------------------------------------
|
| | | #
|
| | | ##@package Skill.TurnBuffs.BuffAtkType_1003
|
| | | #
|
| | | # @todo:承伤护盾
|
| | | # @author hxp
|
| | | # @date 2025-08-25
|
| | | # @version 1.0
|
| | | #
|
| | | # 详细描述: 承伤护盾
|
| | | #
|
| | | #-------------------------------------------------------------------------------
|
| | | #"""Version = 2025-08-25 12:00"""
|
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | import TurnSkill
|
| | | import ChConfig
|
| | |
|
| | | def CalcBuffValue(turnFight, attacker, defender, curSkill):
|
| | | calcType = curSkill.GetCalcType()
|
| | | skillPer = curSkill.GetSkillPer()
|
| | | skillValue = curSkill.GetSkillValue()
|
| | | baseValue = TurnSkill.GetCalcBaseValue(calcType, attacker, defender)
|
| | | shieldValue = int(baseValue * skillPer / 10000.0) + skillValue
|
| | | return [shieldValue % ChConfig.Def_PerPointValue, shieldValue / ChConfig.Def_PerPointValue]
|
| | |
| | | buffEffInfo and GameWorld.DebugLog(" 被动Buff效果: %s" % buffEffInfo)
|
| | | return
|
| | |
|
| | | def OnTriggerPassiveEffect(turnFight, batObj, triggerType, connSkill=None):
|
| | | def OnTriggerPassiveEffect(turnFight, batObj, triggerType, tagObj=None, connSkill=None, connSkillTypeID=0):
|
| | | ''' 触发被动效果,可能触发技能、buff,需根据优先级触发
|
| | | '''
|
| | | passiveEffMgr = batObj.GetPassiveEffManager()
|
| | | effInfoList = passiveEffMgr.GetPassiveEffByTrigger(triggerType, connSkill=connSkill)
|
| | | if not connSkillTypeID and connSkill:
|
| | | connSkillTypeID = connSkill.GetSkillTypeID()
|
| | | effInfoList = passiveEffMgr.GetPassiveEffByTrigger(triggerType, connSkillTypeID)
|
| | | if not effInfoList:
|
| | | return
|
| | | # [["skill/buff", skillID/buffID, effIDList], ...]
|
| | | GameWorld.DebugLog("触发被动: triggerType=%s,objID=%s,%s" % (triggerType, batObj.GetID(), effInfoList))
|
| | | tagID = tagObj.GetID() if tagObj else 0
|
| | | GameWorld.DebugLog("触发被动: triggerType=%s,objID=%s,tagID=%s,%s" % (triggerType, batObj.GetID(), tagID, effInfoList))
|
| | | for effInfo in effInfoList:
|
| | | sign = effInfo[0]
|
| | | if sign == "skill":
|
| | | skillID, effIDList = effInfo[1:]
|
| | | __doTriggerPassiveEffectBySkill(turnFight, batObj, skillID, effIDList, connSkill)
|
| | | __doTriggerPassiveEffectBySkill(turnFight, batObj, tagObj, skillID, effIDList, connSkill)
|
| | |
|
| | | elif sign == "buff":
|
| | | buffID, effIDList = effInfo[1:]
|
| | | __doTriggerPassiveEffectByBuff(turnFight, batObj, buffID, effIDList, connSkill)
|
| | | __doTriggerPassiveEffectByBuff(turnFight, batObj, tagObj, buffID, effIDList, connSkill)
|
| | |
|
| | | return
|
| | |
|
| | | def __doTriggerPassiveEffectBySkill(turnFight, batObj, skillID, effIDList, connSkill=None):
|
| | | def __doTriggerPassiveEffectBySkill(turnFight, batObj, tagObj, skillID, effIDList, connSkill=None):
|
| | | skillMgr = batObj.GetSkillManager()
|
| | | effSkill = skillMgr.FindSkillByID(skillID)
|
| | | if not effSkill:
|
| | | return
|
| | |
|
| | | def __doTriggerPassiveEffectByBuff(turnFight, batObj, buffID, effIDList, connSkill=None):
|
| | | for effID in effIDList:
|
| | | curEffect = effSkill.GetEffectByID(effID)
|
| | | if not curEffect:
|
| | | continue
|
| | | pyName = "PassiveEff_%s" % effID
|
| | | callFunc = GameWorld.GetExecFunc(PassiveTrigger, "%s.%s" % (pyName, "DoSkillEffectLogic"))
|
| | | if not callFunc:
|
| | | continue
|
| | | callFunc(turnFight, batObj, tagObj, effSkill, curEffect, connSkill)
|
| | | |
| | | return
|
| | |
|
| | | def __doTriggerPassiveEffectByBuff(turnFight, batObj, tagObj, buffID, effIDList, connSkill=None):
|
| | | buffMgr = batObj.GetBuffManager()
|
| | | curBuff = buffMgr.GetBuff(buffID)
|
| | | if not curBuff:
|
| | |
| | | callFunc = GameWorld.GetExecFunc(PassiveTrigger, "%s.%s" % (pyName, "DoBuffEffectLogic"))
|
| | | if not callFunc:
|
| | | continue
|
| | | callFunc(turnFight, batObj, curBuff, curEffect, connSkill)
|
| | | callFunc(turnFight, batObj, tagObj, curBuff, curEffect, connSkill)
|
| | |
|
| | | return
|
| | |
|
| | |
| | | import ChPyNetSendPack
|
| | | import PlayerControl
|
| | | import ShareDefine
|
| | | import TurnPassive
|
| | | import TurnAttack
|
| | | import TurnBuff
|
| | | import ObjPool
|
| | |
| | | ## 是否无视防御
|
| | | return useSkill.GetHurtType() / 10 == 1 # 2为真伤,待扩展
|
| | |
|
| | | def OnUseSkill(turnFight, curBatObj, useSkill, tagObjList=None, batType=ChConfig.TurnBattleType_Normal, bySkill=None, isEnhanceSkill=False):
|
| | | def OnUseSkill(turnFight, curBatObj, useSkill, tagObjList=None, batType=ChConfig.TurnBattleType_Normal, bySkill=None):
|
| | | '''使用技能通用入口
|
| | | @param useSkill: 使用的技能,注意并不一定是身上的技能,可能只是 SkillData 表数据
|
| | | @param bySkill: 由哪个技能额外触发的,比如附加触发的技能或被动技能均可能由某个技能触发
|
| | |
| | | return
|
| | |
|
| | | bySkillID = bySkill.GetSkillID() if bySkill else 0
|
| | | GameWorld.DebugLog("使用技能: curID=%s,skillID=%s,tagCnt=%s,batType=%s,bySkillID=%s,isEnhanceSkill=%s" |
| | | % (curBatObj.GetID(), skillID, len(tagObjList), batType, bySkillID, isEnhanceSkill))
|
| | | GameWorld.DebugLog("使用技能: curID=%s,skillID=%s,tagCnt=%s,batType=%s,bySkillID=%s" |
| | | % (curBatObj.GetID(), skillID, len(tagObjList), batType, bySkillID))
|
| | | # 以下为技能可以使用的处理,之后的逻辑默认技能使用成功
|
| | |
|
| | | poolMgr = ObjPool.GetPoolMgr()
|
| | |
| | | # 统一使用 BattleObj.PySkill
|
| | | useSkill = poolMgr.acquire(BattleObj.PySkill, useSkill)
|
| | |
|
| | | useSkill.ResetUseRec()
|
| | | useSkill.SetTagObjList(tagObjList)
|
| | | useSkill.SetBatType(batType)
|
| | | useSkill.SetBySkill(bySkill)
|
| | | useSkill.SetIsEnhanceSkill(isEnhanceSkill)
|
| | | useSkill.ClearHurtObj()
|
| | |
|
| | | curBatObj.ClearSkillTempAttr()
|
| | | for tagObj in tagObjList:
|
| | |
| | |
|
| | | objID = curBatObj.GetID()
|
| | | useTag = ""
|
| | | if not isEnhanceSkill:
|
| | | |
| | | #这个技能是Buff
|
| | | if SkillCommon.IsBuff(useSkill):
|
| | | __doAddBuff(turnFight, curBatObj, useSkill)
|
| | | else:
|
| | | # 因为可能触发连击,所以标记需带上累计使用技能次数,确保唯一
|
| | | useTag = "Skill_%s_%s_%s" % (objID, skillID, curBatObj.GetSkillUseCnt(skillID) + 1)
|
| | | clientPack = poolMgr.acquire(ChPyNetSendPack.tagSCTurnFightTag)
|
| | |
| | | clientPack.Sign = 0
|
| | | turnFight.addBatPack(clientPack)
|
| | |
|
| | | #这个技能是Buff
|
| | | if SkillCommon.IsBuff(useSkill):
|
| | | __doAddBuff(turnFight, curBatObj, useSkill)
|
| | | else:
|
| | | __doUseSkill(turnFight, curBatObj, useSkill)
|
| | | |
| | | DoAttackResult(turnFight, curBatObj, useSkill)
|
| | |
|
| | | if useTag:
|
| | | clientPack = poolMgr.acquire(ChPyNetSendPack.tagSCTurnFightTag)
|
| | |
| | | clientPack.Len = len(clientPack.Tag)
|
| | | clientPack.Sign = 1
|
| | | turnFight.addBatPack(clientPack)
|
| | | |
| | | # 处理反击 或 连击
|
| | | DoCombo(turnFight, curBatObj, useSkill)
|
| | |
|
| | | # 最后重置、回收对象
|
| | | useSkill.ResetUseRec()
|
| | |
| | |
|
| | | def GetSkillTags(turnFight, curBatObj, tagAim, tagFriendly, tagAffect, tagCount):
|
| | | ## 获取技能目标
|
| | | # @return: [主目标, 目标2, ...]
|
| | | |
| | | curFaction = curBatObj.GetFaction()
|
| | |
|
| | | # 自己,直接返回
|
| | | if tagAim == ChConfig.SkillTagAim_Self:
|
| | | return [curBatObj]
|
| | |
|
| | | sneerObj = None # 嘲讽目标
|
| | | sneerObjID, sneerObjPosNum = 0, 0
|
| | | if tagFriendly:
|
| | | tagFaction = curFaction
|
| | | else:
|
| | | tagFaction = ChConfig.Def_FactionB if curFaction == ChConfig.Def_FactionA else ChConfig.Def_FactionA
|
| | | sneerObj = curBatObj.GetSneerTagObj() # 被嘲讽的目标,对敌的强制锁定被嘲讽目标
|
| | | |
| | | sneerObjFirst = True # 嘲讽目标优先
|
| | | if sneerObj:
|
| | | sneerObjID = sneerObj.GetID()
|
| | | sneerObjPosNum = sneerObj.GetPosNum()
|
| | |
|
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | lineupNum = curBatObj.GetLineupNum()
|
| | |
| | |
|
| | | # 对位
|
| | | if tagAim == ChConfig.SkillTagAim_Relative:
|
| | | posNumList = [posNum] # 优先对位位置,再其他位置按顺序遍历
|
| | | pNumList = batLineup.posObjIDDict.keys()
|
| | | pNumList.sort()
|
| | | for pNum in pNumList:
|
| | | if pNum > 0 and pNum not in posNumList:
|
| | | posNumList.append(pNum)
|
| | | for pNum in posNumList:
|
| | | if pNum not in batLineup.posObjIDDict:
|
| | | continue
|
| | | tagObjID = batLineup.posObjIDDict[pNum]
|
| | | tagBatObj = batObjMgr.getBatObj(tagObjID)
|
| | | if not __skillTagFilter(tagBatObj, tagAffect):
|
| | | continue
|
| | | aimObjList.append(tagBatObj) # 对位的默认只选1个
|
| | | break
|
| | | if sneerObj:
|
| | | aimObjList.append(sneerObj)
|
| | | else:
|
| | | relativeObj = __GetRelativeObjDefault(batObjMgr, curBatObj, posNum, batLineup)
|
| | | if relativeObj:
|
| | | aimObjList.append(relativeObj)
|
| | |
|
| | | # 前排
|
| | | elif tagAim == ChConfig.SkillTagAim_FrontRow:
|
| | | # 优先前排,如果没有则后排亦是前排
|
| | | for pNumList in [[1, 2, 3], [4, 5, 6]]:
|
| | | hasObj = False
|
| | | for pNum in pNumList:
|
| | | if pNum not in batLineup.posObjIDDict:
|
| | | continue
|
| | | tagObjID = batLineup.posObjIDDict[pNum]
|
| | | tagBatObj = batObjMgr.getBatObj(tagObjID)
|
| | | if not __skillTagFilter(tagBatObj, tagAffect):
|
| | | continue
|
| | | hasObj = True
|
| | | aimObjList.append(tagBatObj)
|
| | | if hasObj:
|
| | | break
|
| | | aimObjList = __getRowAimObjList(batObjMgr, posNum, sneerObj, batLineup, tagAffect, False)
|
| | |
|
| | | # 后排
|
| | | elif tagAim == ChConfig.SkillTagAim_BackRow:
|
| | | # 优先后排,如果没有则前排亦是后排
|
| | | for pNumList in [[4, 5, 6], [1, 2, 3]]:
|
| | | hasObj = False
|
| | | for pNum in pNumList:
|
| | | if pNum not in batLineup.posObjIDDict:
|
| | | continue
|
| | | tagObjID = batLineup.posObjIDDict[pNum]
|
| | | tagBatObj = batObjMgr.getBatObj(tagObjID)
|
| | | if not __skillTagFilter(tagBatObj, tagAffect):
|
| | | continue
|
| | | hasObj = True
|
| | | aimObjList.append(tagBatObj)
|
| | | if hasObj:
|
| | | break
|
| | | aimObjList = __getRowAimObjList(batObjMgr, posNum, sneerObj, batLineup, tagAffect, True)
|
| | |
|
| | | # 竖排/纵排
|
| | | elif tagAim == ChConfig.SkillTagAim_Vertical:
|
| | | verticalNumList = [[1, 4], [2, 5], [3, 6]]
|
| | | for pNumList in verticalNumList:
|
| | | # 优先对位排
|
| | | if posNum in pNumList:
|
| | | verticalNumList.remove(pNumList)
|
| | | verticalNumList.insert(0, pNumList)
|
| | | break
|
| | | for pNumList in verticalNumList:
|
| | | hasObj = False
|
| | | for pNum in pNumList:
|
| | | # 优先自己所在纵
|
| | | inColNum = ChConfig.GetInColNum(posNum)
|
| | | colNumList = range(1, 1 + ChConfig.TurnFightCols)
|
| | | if inColNum in colNumList:
|
| | | colNumList.remove(inColNum)
|
| | | colNumList.insert(0, inColNum)
|
| | | |
| | | # 优先嘲讽所在纵
|
| | | if sneerObj:
|
| | | sneerInColNum = ChConfig.GetInColNum(sneerObjPosNum)
|
| | | if sneerInColNum in colNumList:
|
| | | colNumList.remove(sneerInColNum)
|
| | | colNumList.insert(0, sneerInColNum)
|
| | | |
| | | GameWorld.DebugLog("纵排: colNumList=%s,sneerObjID-PosNum=%s-%s" % (colNumList, sneerObjID, sneerObjPosNum))
|
| | | for col in colNumList:
|
| | | for row in range(1, 1 + ChConfig.TurnFightRows):
|
| | | pNum = (row - 1) * ChConfig.TurnFightCols + col
|
| | | #GameWorld.DebugLog(" col=%s,row=%s,pNum=%s" % (col, row, pNum))
|
| | | if pNum not in batLineup.posObjIDDict:
|
| | | continue
|
| | | tagObjID = batLineup.posObjIDDict[pNum]
|
| | | tagBatObj = batObjMgr.getBatObj(tagObjID)
|
| | | if not __skillTagFilter(tagBatObj, tagAffect):
|
| | | continue
|
| | | hasObj = True
|
| | | aimObjList.append(tagBatObj)
|
| | | if hasObj:
|
| | | if aimObjList:
|
| | | break
|
| | |
|
| | | # 其他,默认全部
|
| | | else:
|
| | | pNumList = batLineup.posObjIDDict.keys()
|
| | | for pNum in pNumList:
|
| | | if pNum <= 0:
|
| | | inColNum = ChConfig.GetInColNum(posNum) # 玩家所在纵列
|
| | | # 优先自己所在纵
|
| | | colNumList = range(1, 1 + ChConfig.TurnFightCols)
|
| | | if inColNum in colNumList:
|
| | | colNumList.remove(inColNum)
|
| | | colNumList.insert(0, inColNum)
|
| | | |
| | | GameWorld.DebugLog("全部: colNumList=%s,sneerObjID-PosNum=%s-%s" % (colNumList, sneerObjID, sneerObjPosNum))
|
| | | # 按前排优先原则
|
| | | for row in range(1, 1 + ChConfig.TurnFightRows):
|
| | | for col in colNumList:
|
| | | pNum = (row - 1) * ChConfig.TurnFightCols + col
|
| | | #GameWorld.DebugLog(" col=%s,row=%s,pNum=%s" % (col, row, pNum))
|
| | | if pNum not in batLineup.posObjIDDict:
|
| | | continue
|
| | | tagObjID = batLineup.posObjIDDict[pNum]
|
| | | tagBatObj = batObjMgr.getBatObj(tagObjID)
|
| | |
| | | if tagAffect == ChConfig.SkillTagAffect_HPLowest:
|
| | | aimObjList.sort(key=lambda o:(o.GetHP()), reverse=False)
|
| | | #GameWorld.DebugLog("血量最低排序: %s" % [[o.GetID(), o.GetHP(), o.GetMaxHP()] for o in aimObjList])
|
| | | aimObjList = aimObjList[:tagCount]
|
| | |
|
| | | # 血量最高
|
| | | elif tagAffect == ChConfig.SkillTagAffect_HPHighest:
|
| | | aimObjList.sort(key=lambda o:(o.GetHP()), reverse=True)
|
| | | #GameWorld.DebugLog("血量最高排序: %s" % [[o.GetID(), o.GetHP(), o.GetMaxHP()] for o in aimObjList])
|
| | | aimObjList = aimObjList[:tagCount]
|
| | | |
| | | # 未被控制优先
|
| | | elif tagAffect == ChConfig.SkillTagAffect_UncontrolledPriority:
|
| | | sneerObjFirst = False
|
| | | aimObjList.sort(key=lambda o:(o.IsInControlled()))
|
| | | GameWorld.DebugLog("未被控制优先: %s" % [[o.GetID(), o.IsInControlled()] for o in aimObjList])
|
| | |
|
| | | else:
|
| | | # 范围目标超过个数,则随机取
|
| | | if tagCount and len(aimObjList) > tagCount:
|
| | | random.shuffle(aimObjList)
|
| | | |
| | | # 嘲讽优先
|
| | | if sneerObjFirst and sneerObj:
|
| | | if sneerObj in aimObjList and aimObjList.index(sneerObj) != 0:
|
| | | aimObjList.remove(sneerObj)
|
| | | aimObjList.insert(0, sneerObj)
|
| | | |
| | | if tagCount and len(aimObjList) > tagCount:
|
| | | aimObjList = aimObjList[:tagCount]
|
| | |
|
| | | return aimObjList
|
| | |
|
| | | def __getRowAimObjList(batObjMgr, posNum, sneerObj, batLineup, tagAffect, rowReverse):
|
| | | ## 获取行排目标对象列表
|
| | | # @param rowReverse: 是否后排优先原则
|
| | | |
| | | # 前后排顺序
|
| | | if rowReverse:
|
| | | rowNumList = range(1, 1 + ChConfig.TurnFightRows)[::-1]
|
| | | else:
|
| | | rowNumList = range(1, 1 + ChConfig.TurnFightRows)
|
| | | |
| | | # 优先嘲讽对象所在行
|
| | | sneerObjID, sneerObjPosNum = 0, 0
|
| | | if sneerObj:
|
| | | sneerObjID = sneerObj.GetID()
|
| | | sneerObjPosNum = sneerObj.GetPosNum()
|
| | | sneerInRowNum = ChConfig.GetInRowNum(sneerObjPosNum) # 所在行排
|
| | | if sneerInRowNum in rowNumList:
|
| | | rowNumList.remove(sneerInRowNum)
|
| | | rowNumList.insert(0, sneerInRowNum)
|
| | | |
| | | inColNum = ChConfig.GetInColNum(posNum) # 玩家所在纵列
|
| | | # 优先自己所在纵,为主目标
|
| | | colNumList = range(1, 1 + ChConfig.TurnFightCols)
|
| | | if inColNum in colNumList:
|
| | | colNumList.remove(inColNum)
|
| | | colNumList.insert(0, inColNum)
|
| | | |
| | | GameWorld.DebugLog("前后排: rowNumList=%s,colNumList=%s,sneerObjID-PosNum=%s-%s" % (rowNumList, colNumList, sneerObjID, sneerObjPosNum))
|
| | | aimObjList = []
|
| | | for row in rowNumList:
|
| | | for col in colNumList:
|
| | | pNum = (row - 1) * ChConfig.TurnFightCols + col
|
| | | #GameWorld.DebugLog(" row=%s,col=%s,pNum=%s" % (row, col, pNum))
|
| | | if pNum not in batLineup.posObjIDDict:
|
| | | continue
|
| | | tagObjID = batLineup.posObjIDDict[pNum]
|
| | | tagBatObj = batObjMgr.getBatObj(tagObjID)
|
| | | if not __skillTagFilter(tagBatObj, tagAffect):
|
| | | continue
|
| | | aimObjList.append(tagBatObj)
|
| | | if aimObjList:
|
| | | break
|
| | | |
| | | return aimObjList
|
| | |
|
| | | def GetRelativeObj(turnFight, curBatObj):
|
| | | '''获取对位目标,嘲讽时优先对位嘲讽目标
|
| | | 对位目标用途: |
| | | 1. 对位目标并不代表仅攻击该目标
|
| | | 2. 攻击时根据技能攻击目标范围优先攻击对位目标所在的横排或纵排
|
| | | 3. 对位目标可用于判断连击、弱疗
|
| | | '''
|
| | | sneerObj = curBatObj.GetSneerTagObj()
|
| | | if sneerObj:
|
| | | # 有嘲讽目标优先直接对位
|
| | | return sneerObj
|
| | | |
| | | curFaction = curBatObj.GetFaction()
|
| | | # 默认对位敌对阵营
|
| | | tagFaction = ChConfig.Def_FactionB if curFaction == ChConfig.Def_FactionA else ChConfig.Def_FactionA
|
| | | |
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | lineupNum = curBatObj.GetLineupNum()
|
| | | posNum = curBatObj.GetPosNum()
|
| | | |
| | | batFaction = turnFight.getBatFaction(tagFaction)
|
| | | lineupNumList = [lineupNum] # 敌方优先对位阵容,再其他阵容,支持多阵容对战
|
| | | for tagNum in batFaction.lineupDict.keys():
|
| | | if tagNum not in lineupNumList:
|
| | | lineupNumList.append(tagNum)
|
| | | |
| | | for num in lineupNumList:
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | relativeObj = __GetRelativeObjDefault(batObjMgr, curBatObj, posNum, batLineup)
|
| | | if relativeObj:
|
| | | return relativeObj
|
| | | |
| | | # 理论上只要战斗没有结束,一定会有对位目标,这里默认返回自己,外层可不需要判断是否存在对位目标
|
| | | return curBatObj
|
| | |
|
| | | def __GetRelativeObjDefault(batObjMgr, curBatObj, posNum, batLineup):
|
| | | ## 获取在某一阵营中的默认对位目标
|
| | | |
| | | tagAffect = ChConfig.SkillTagAffect_None # 默认对位目标不需要细分目标,默认规则即可
|
| | | inColNum = ChConfig.GetInColNum(posNum) # 玩家所在纵列
|
| | | # 优先自己所在纵
|
| | | colNumList = range(1, 1 + ChConfig.TurnFightCols)
|
| | | if inColNum in colNumList:
|
| | | colNumList.remove(inColNum)
|
| | | colNumList.insert(0, inColNum)
|
| | | |
| | | # 按前排优先原则
|
| | | for row in range(ChConfig.TurnFightRows):
|
| | | for col in colNumList:
|
| | | pNum = row * ChConfig.TurnFightCols + col
|
| | | if pNum not in batLineup.posObjIDDict:
|
| | | continue
|
| | | tagObjID = batLineup.posObjIDDict[pNum]
|
| | | tagBatObj = batObjMgr.getBatObj(tagObjID)
|
| | | if not __skillTagFilter(tagBatObj, tagAffect):
|
| | | continue
|
| | | return tagBatObj
|
| | | |
| | | return
|
| | |
|
| | | def __skillTagFilter(tagBatObj, tagAffect):
|
| | | ## 技能目标过滤器
|
| | | # @return: 是否允许添加该单位
|
| | | if not tagBatObj:
|
| | | return False
|
| | | if tagAffect != ChConfig.SkillTagAffect_Death and tagBatObj.GetHP() <= 0:
|
| | | if tagAffect != ChConfig.SkillTagAffect_Death and not tagBatObj.IsAlive():
|
| | | return False
|
| | | if tagAffect == ChConfig.SkillTagAffect_Death and tagBatObj.GetHP() > 0:
|
| | | if tagAffect == ChConfig.SkillTagAffect_Death and tagBatObj.IsAlive():
|
| | | return False
|
| | | if not tagBatObj.GetCanAttack():
|
| | | return False
|
| | | #if not tagBatObj.GetCanAttack(): 策划要求不可攻击的对象也要可选中
|
| | | # return False
|
| | | return True
|
| | |
|
| | | def __doAddBuff(turnFight, curBatObj, useSkill):
|
| | |
| | | for tagBatObj in useSkill.GetTagObjList():
|
| | | TurnBuff.OnAddBuff(turnFight, tagBatObj, useSkill, buffOwner=curBatObj)
|
| | |
|
| | | DoAttackResult(turnFight, curBatObj, useSkill)
|
| | | return
|
| | |
|
| | | def __doUseSkill(turnFight, curBatObj, useSkill):
|
| | |
| | | # 通用攻击
|
| | | if atkType == 1:
|
| | | SkillModule_1(turnFight, curBatObj, useSkill)
|
| | | return
|
| | | |
| | | # 治疗
|
| | | if atkType == 2:
|
| | | SkillModule_2(turnFight, curBatObj, useSkill)
|
| | | return
|
| | | |
| | | # 复活
|
| | | if atkType == 3:
|
| | | return
|
| | | |
| | | elif atkType == 3:
|
| | | pass
|
| | | # 多次攻击(锁目标多次伤害,非前端的多段飘血)
|
| | | if atkType == 4:
|
| | | return
|
| | | |
| | | elif atkType == 4:
|
| | | pass
|
| | | # 弹射(多次攻击,切换目标)
|
| | | if atkType == 5:
|
| | | return
|
| | | |
| | | elif atkType == 5:
|
| | | pass
|
| | | # 怒气增
|
| | | if atkType == 6:
|
| | | elif atkType == 6:
|
| | | SkillModule_6(turnFight, curBatObj, useSkill, "Increase")
|
| | | return
|
| | | |
| | | # 怒气减
|
| | | if atkType == 7:
|
| | | elif atkType == 7:
|
| | | SkillModule_6(turnFight, curBatObj, useSkill, "Reduce")
|
| | | return
|
| | | |
| | | # 怒气偷
|
| | | if atkType == 8:
|
| | | elif atkType == 8:
|
| | | SkillModule_6(turnFight, curBatObj, useSkill, "Steal")
|
| | | return
|
| | |
|
| | | return
|
| | |
|
| | | def SkillModule_1(turnFight, curBatObj, useSkill):
|
| | | ## 通用攻击,单攻、群攻
|
| | |
|
| | | #执行攻击结果
|
| | | for tagBatObj in useSkill.GetTagObjList():
|
| | | __doSkillHurtHP(curBatObj, tagBatObj, useSkill)
|
| | | __doSkillHurtHP(turnFight, curBatObj, tagBatObj, useSkill)
|
| | |
|
| | | DoAttackResult(turnFight, curBatObj, useSkill)
|
| | | return
|
| | |
|
| | | def SkillModule_2(turnFight, curBatObj, useSkill):
|
| | |
| | |
|
| | | TurnAttack.AddTurnObjCureHP(tagBatObj, curBatObj, cureHP, realCureHP, skillID)
|
| | |
|
| | | DoAttackResult(turnFight, curBatObj, useSkill)
|
| | | return
|
| | |
|
| | | def SkillModule_6(turnFight, curBatObj, useSkill, opType):
|
| | |
| | | GameWorld.DebugLog(" 加总怒气: curID=%s,curStealTotal=%s,curXP=%s,updXP=%s" % (curID, curStealTotal, curXP, updValue))
|
| | | Sync_PropertyRefreshView(turnFight, curBatObj, attrID, updValue, diffValue, diffType, skillID, relatedSkillID)
|
| | |
|
| | | DoAttackResult(turnFight, curBatObj, useSkill)
|
| | | return
|
| | |
|
| | | def DoAttackResult(turnFight, curBatObj, useSkill):
|
| | |
| | | useSkill.SetCalcTime(turnFight.getTimeline())
|
| | | useSkill.SetRemainTime(useSkill.GetCoolDownTime())
|
| | |
|
| | | # 需先通知伤血 - 前端按顺序优先表现技能释放内容,
|
| | | isEnhanceSkill = useSkill.GetIsEnhanceSkill()
|
| | | if not isEnhanceSkill or len(useSkill.GetHurtObjList()):
|
| | | # 需先技能使用 - 前端按顺序优先表现技能释放内容,前端需要动作或有伤血则通知
|
| | | if useSkill.GetSkillMotionName() or len(useSkill.GetHurtObjList()):
|
| | | Sync_UseSkill(turnFight, curBatObj, useSkill)
|
| | | if not isEnhanceSkill:
|
| | | |
| | | __doCostZhanchui(turnFight, curBatObj, useSkill)
|
| | | __doSkillUserAnger(turnFight, curBatObj, useSkill)
|
| | |
|
| | | DoBeAttackOver(turnFight, curBatObj, useSkill)
|
| | | DoBeAttackResult(turnFight, curBatObj, useSkill)
|
| | | return
|
| | |
|
| | | # 最后处理反击 或 连击
|
| | | def DoCombo(turnFight, curBatObj, useSkill):
|
| | | '''
|
| | | 格挡、反击、连击规则
|
| | | 1. 所有武将或怪物均可能产生格挡,群攻时格挡一对一判断,均可能产生格挡
|
| | | 2. 仅普攻时可被反击,反判断本次技能目标中的主目标(即对位目标)是否产生格挡,且是近战武将,是的话可反击
|
| | | |
| | | 连击:
|
| | | 1. 仅普攻可连击,反击打断连击
|
| | | 2. 非对敌技能,如奶妈回血普攻,判断对位目标抗连属性是否可连击
|
| | | 3. 对敌技能,判断本次技能目标中的主目标(即对位目标)抗连属性是否可连击
|
| | | |
| | | 对敌技能主目标:
|
| | | 单体: 默认该目标
|
| | | 嘲讽: 优先被嘲讽的目标
|
| | | 横排: 优先该排中与自己同列的,否则按顺序
|
| | | 纵排: 优先前面的单位
|
| | | '''
|
| | | |
| | | if not SkillCommon.isTurnNormalSkill(useSkill):
|
| | | #GameWorld.DebugLog("非普攻不处理反击连击")
|
| | | return
|
| | | |
| | | tagFriendly = useSkill.GetTagFriendly()
|
| | | if tagFriendly:
|
| | | tagObj = GetRelativeObj(turnFight, curBatObj)
|
| | | else:
|
| | | tagObjList = useSkill.GetTagObjList()
|
| | | if not tagObjList:
|
| | | return
|
| | | tagObj = tagObjList[0] # 第一个默认为主目标,技能对象选择逻辑时决定主目标
|
| | | atkBackSkill = __getCanAtkBackSkill(useSkill, tagObj)
|
| | | if atkBackSkill:
|
| | | # 可以反击,打断连击
|
| | | GameWorld.DebugLog("● %s 【反击】" % TurnAttack.GetObjName(tagObj))
|
| | | OnUseSkill(turnFight, tagObj, atkBackSkill, [curBatObj], ChConfig.TurnBattleType_AtkBack)
|
| | | return
|
| | | |
| | | if not tagObj:
|
| | | return
|
| | | |
| | | if CanCombo(curBatObj, tagObj):
|
| | | # 连击根据技能目标配置逻辑重新选择目标
|
| | | GameWorld.DebugLog("● %s 【连击】" % TurnAttack.GetObjName(curBatObj))
|
| | | OnUseSkill(turnFight, curBatObj, useSkill, batType=ChConfig.TurnBattleType_Combo)
|
| | |
|
| | | return
|
| | |
|
| | | def DoBeAttackOver(turnFight, curBatObj, useSkill):
|
| | | def __getCanAtkBackSkill(useSkill, tagObj):
|
| | | ## 获取是否可反击及反击技能
|
| | | if not tagObj:
|
| | | return
|
| | | |
| | | tagID = tagObj.GetID()
|
| | | if tagObj.GetAtkDistType() != ChConfig.AtkDistType_Short:
|
| | | GameWorld.DebugLog("非近战不可反击! tagID=%s" % tagID)
|
| | | return
|
| | | |
| | | canAtkBack = False
|
| | | for hurtObj in useSkill.GetHurtObjList():
|
| | | if hurtObj.GetObjID() != tagID:
|
| | | continue
|
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_Parry): # 格挡时可反击
|
| | | canAtkBack = True
|
| | | break
|
| | | |
| | | if not canAtkBack:
|
| | | GameWorld.DebugLog("没有格挡不可反击! tagID=%s" % tagID)
|
| | | return
|
| | | |
| | | skillManager = tagObj.GetSkillManager()
|
| | | for index in range(0, skillManager.GetSkillCount()):
|
| | | useSkill = skillManager.GetSkillByIndex(index)
|
| | | if not useSkill:
|
| | | continue
|
| | | if useSkill.GetFuncType() == ChConfig.Def_SkillFuncType_AtkbackSkill:
|
| | | GameWorld.DebugLog("可以反击! tagID=%s" % tagID)
|
| | | return useSkill
|
| | | return
|
| | |
|
| | | def CanCombo(atkObj, defObj):
|
| | | ## 可否连击
|
| | | comboNum = atkObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnComboNum)
|
| | | aComboRate = atkObj.GetBatAttrValue(ChConfig.AttrID_ComboRate)
|
| | | dComboRateDef = defObj.GetBatAttrValue(ChConfig.AttrID_ComboRateDef)
|
| | | happenRate = eval(IpyGameDataPY.GetFuncCompileCfg("ComboCfg", 1))
|
| | | if GameWorld.CanHappen(happenRate):
|
| | | GameWorld.DebugLog("可以连击! atkID=%s,happenRate=%s,aComboRate=%s,dComboRateDef=%s,comboNum=%s" |
| | | % (atkObj.GetID(), happenRate, aComboRate, dComboRateDef, comboNum))
|
| | | atkObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, comboNum + 1)
|
| | | return True
|
| | | GameWorld.DebugLog("无法连击! atkID=%s,happenRate=%s,aComboRate=%s,dComboRateDef=%s,comboNum=%s" |
| | | % (atkObj.GetID(), happenRate, aComboRate, dComboRateDef, comboNum))
|
| | | return False
|
| | |
|
| | | def DoBeAttackResult(turnFight, curObj, useSkill):
|
| | | '''被攻击结果
|
| | | @param curBatObj: 施法方或buff归属方
|
| | | @param curObj: 施法方或buff归属方
|
| | | '''
|
| | |
|
| | | curID = curObj.GetID()
|
| | | isTurnNormalSkill = SkillCommon.isTurnNormalSkill(useSkill)
|
| | | isAngerSkill = SkillCommon.isAngerSkill(useSkill)
|
| | |
|
| | | # 统计死亡
|
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | |
| | | # 优先处理afterLogic,可再预先汇总一些会触发被动的信息
|
| | | relatedSkillID = useSkill.GetSkillID()
|
| | | shieldBrokenList = [] # 记录盾破
|
| | | afterLogicList = useSkill.GetAfterLogicList()
|
| | | for logicType, logicData in afterLogicList:
|
| | | if logicType == ChConfig.AfterLogic_DelBuff:
|
| | | buffObjID, buff, tagObjID = logicData
|
| | | buffSkillData = buff.GetSkillData()
|
| | | buffSkillTypeID = buffSkillData.GetSkillTypeID()
|
| | | TurnBuff.DoBuffDelAfterLogicOver(turnFight, buffObjID, buff, useSkill)
|
| | | if SkillCommon.isDamageShieldSkill(buffSkillData):
|
| | | shieldBrokenList.append([buffObjID, tagObjID, buffSkillTypeID])
|
| | | |
| | | elif logicType == ChConfig.AfterLogic_AddBuff:
|
| | | batObj, buff, _ = logicData
|
| | | TurnBuff.SyncBuffRefresh(turnFight, batObj, buff, relatedSkillID)
|
| | | |
| | | elif logicType == ChConfig.AfterLogic_SyncBuff:
|
| | | buffObj, buff, _, _ = logicData
|
| | | TurnBuff.SyncBuffRefresh(turnFight, buffObj, buff, relatedSkillID)
|
| | | |
| | | # 统计结果
|
| | | killObjIDList = [] # 击杀的目标ID列表
|
| | | for tagObj in useSkill.GetTagObjList():
|
| | | tagID = tagObj.GetID()
|
| | | # 可能单个技能对同一目标造成多次伤害,所以这里遍历,如弹射等
|
| | | for hurtObj in useSkill.GetHurtObjList():
|
| | | if hurtObj.GetObjID() == tagID and not hurtObj.HaveHurtType(ChConfig.HurtTYpe_Recovery) and (isTurnNormalSkill or isAngerSkill):
|
| | | __doSkillHurtAnger(tagObj, hurtObj.GetLostHP(), useSkill)
|
| | | if tagObj.GetHP() <= 0:
|
| | | if tagObj.IsAlive() and tagObj.GetHP() <= 0:
|
| | | killObjIDList.append(tagID)
|
| | | TurnAttack.SetObjKilled(turnFight, tagObj, curBatObj, useSkill)
|
| | | if curBatObj and curBatObj.GetHP() <= 0:
|
| | | TurnAttack.SetObjKilled(turnFight, curBatObj)
|
| | | TurnAttack.SetObjKilled(turnFight, tagObj, curObj, useSkill)
|
| | | if curObj and curObj.IsAlive() and curObj.GetHP() <= 0:
|
| | | TurnAttack.SetObjKilled(turnFight, curObj)
|
| | | |
| | | # 可能单个技能对同一目标造成多次伤害
|
| | | missObjIDList = []
|
| | | 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():
|
| | | __doSkillHurtAnger(tagObj, hurtObj.GetLostHP(), useSkill)
|
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
|
| | | missObjIDList.append(hurtObjID)
|
| | |
|
| | | # 结算副本相关的攻击结果,仅主动发起玩家阵容武将触发
|
| | | curPlayer = turnFight.curPlayer
|
| | | if curPlayer and curBatObj and curBatObj.GetOwnerID() == curPlayer.GetPlayerID():
|
| | | FBLogic.OnPlayerLineupAttackResult(curPlayer, curBatObj, killObjIDList, useSkill, turnFight.mapID, turnFight.funcLineID)
|
| | | if curPlayer and curObj and curObj.GetOwnerID() == curPlayer.GetPlayerID():
|
| | | FBLogic.OnPlayerLineupAttackResult(curPlayer, curObj, killObjIDList, useSkill, turnFight.mapID, turnFight.funcLineID)
|
| | |
|
| | | # 额外触发技能
|
| | | __doUseEnhanceSkill(turnFight, curBatObj, useSkill)
|
| | | __doUseEnhanceSkill(turnFight, curObj, useSkill)
|
| | |
|
| | | # 循环触发被动,待扩展
|
| | | # ========== 以下触发被动 ==========
|
| | | |
| | | # 破盾时
|
| | | for buffObjID, tagObjID, buffSkillTypeID in shieldBrokenList:
|
| | | buffObj = batObjMgr.getBatObj(buffObjID)
|
| | | tagObj = batObjMgr.getBatObj(tagObjID)
|
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, buffObj, ChConfig.TriggerWay_ShieldBroken, tagObj, connSkillTypeID=buffSkillTypeID)
|
| | | |
| | | for tagObj in useSkill.GetTagObjList():
|
| | | tagID = tagObj.GetID()
|
| | | if tagID == curID or tagID in missObjIDList:
|
| | | # 自己或对方闪避了不再触发被动
|
| | | continue
|
| | | |
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, curObj, ChConfig.TriggerWay_AttackOverTagInState, tagObj, connSkill=useSkill)
|
| | | # 直接攻击
|
| | | if not SkillCommon.IsBuff(useSkill):
|
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, curObj, ChConfig.TriggerWay_AttackOverDirect, tagObj, connSkill=useSkill)
|
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, tagObj, ChConfig.TriggerWay_BeAttackedDirect, curObj, connSkill=useSkill)
|
| | |
|
| | | return
|
| | |
|
| | |
| | | def __doUseEnhanceSkill(turnFight, curBatObj, useSkill):
|
| | | if not curBatObj:
|
| | | return
|
| | | if useSkill.GetIsEnhanceSkill():
|
| | | if useSkill.GetBatType() == ChConfig.TurnBattleType_Enhance:
|
| | | #GameWorld.DebugLog("自身为额外触发的技能不再触发额外技能! skillID=%s" % useSkill.GetSkillID())
|
| | | return
|
| | | enhanceSkillIDList = useSkill.GetEnhanceSkillList()
|
| | | if not enhanceSkillIDList:
|
| | | return
|
| | | GameWorld.DebugLog("额外触发的技能! skillID=%s,enhanceSkillIDList=%s" % (useSkill.GetSkillID(), enhanceSkillIDList))
|
| | | # 根据触发技能的特点决定是触发一次还是 触发多次
|
| | | # 群体BUFF的请参考 IsPlayerUseSkill 客户端决定对象,一样可以实现同样效果
|
| | | tagObjList = useSkill.GetTagObjList()
|
| | | for enhanceSkillID in enhanceSkillIDList:
|
| | | enhanceSkillData = IpyGameDataPY.GetIpyGameData("Skill", enhanceSkillID)
|
| | |
| | | for hurtObj in useSkill.GetHurtObjList():
|
| | | if hurtObj.GetObjID() != tagID:
|
| | | continue
|
| | | if not hurtObj.GetHurtHP() or hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
|
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
|
| | | continue
|
| | | inHurt = True
|
| | | break
|
| | |
| | | enchanceTagObjList.append(tagObj)
|
| | |
|
| | | if enchanceTagObjList:
|
| | | OnUseSkill(turnFight, curBatObj, enhanceSkillData, enchanceTagObjList, bySkill=useSkill, isEnhanceSkill=True)
|
| | | OnUseSkill(turnFight, curBatObj, enhanceSkillData, enchanceTagObjList, batType=ChConfig.TurnBattleType_Enhance, bySkill=useSkill)
|
| | |
|
| | | continue
|
| | |
|
| | | GameWorld.DebugLog(" 额外触发技能,重新锁定目标! enhanceSkillID=%s" % enhanceSkillID)
|
| | | OnUseSkill(turnFight, curBatObj, enhanceSkillData, bySkill=useSkill, isEnhanceSkill=True)
|
| | | OnUseSkill(turnFight, curBatObj, enhanceSkillData, batType=ChConfig.TurnBattleType_Enhance, bySkill=useSkill)
|
| | |
|
| | | return
|
| | |
|
| | | def __doSkillHurtHP(attacker, defObj, curSkill):
|
| | | def __doSkillHurtHP(turnFight, attacker, defObj, curSkill):
|
| | | ## 执行技能伤血,只计算伤血,其他逻辑等技能同步后再处理
|
| | | # @return: None - 没有执行成功,即忽略该目标
|
| | |
|
| | |
| | | pass
|
| | |
|
| | | else:
|
| | | hurtValue, hurtTypes = CalcHurtHP(atkObj, defObj, curSkill, atkSkillValue, atkSkillPer)
|
| | | |
| | | # 各种减伤 吸收盾处理
|
| | | #hurtValue = CalcHurtHPWithBuff(atkObj, defObj, hurtValue, curSkill, tick)
|
| | | hurtValue, hurtTypes = CalcHurtHP(turnFight, atkObj, defObj, curSkill, atkSkillValue, atkSkillPer)
|
| | | hurtValue, realHurtHP = CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue)
|
| | |
|
| | | #伤害结构体
|
| | | hurtObj.SetHurtTypes(hurtTypes)
|
| | | hurtObj.SetHurtHP(hurtValue)
|
| | | remainHP = min(dMaxHP, max(0, dHP - hurtValue)) # 剩余血量
|
| | | hurtObj.SetRealHurtHP(realHurtHP)
|
| | | remainHP = min(dMaxHP, max(0, dHP - realHurtHP)) # 剩余血量
|
| | |
|
| | | remainHP = int(remainHP) #防范
|
| | | lostHP = dHP - remainHP # 实际掉血量
|
| | | hurtObj.SetLostHP(lostHP)
|
| | | hurtObj.SetCurHP(remainHP)
|
| | | defObj.SetHP(remainHP)
|
| | | GameWorld.DebugLog(" 伤血: atkID=%s,defID=%s,hurtValue=%s,lostHP=%s,%s/%s" % (atkID, defID, hurtValue, lostHP, defObj.GetHP(), defObj.GetMaxHP()))
|
| | | 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)
|
| | |
|
| | | #反弹伤害
|
| | | CalcBounceHP(atkObj, defObj, hurtObj, curSkill)
|
| | | CalcBounceHP(turnFight, atkObj, defObj, hurtObj, curSkill)
|
| | |
|
| | | #吸血
|
| | | CalcSuckBlood(atkObj, defObj, hurtObj, curSkill)
|
| | | |
| | | TurnAttack.AddTurnObjHurtValue(atkObj, defObj, hurtValue, lostHP, skillID)
|
| | | return
|
| | |
|
| | | def CalcHurtHP(atkObj, defObj, curSkill, atkSkillValue, atkSkillPer, **kwargs):
|
| | | def CalcHurtHP(turnFight, atkObj, defObj, curSkill, atkSkillValue, atkSkillPer, **kwargs):
|
| | | '''计算伤害,默认按攻击计算
|
| | | '''
|
| | | pmType = GetPMType(atkObj, curSkill)
|
| | |
| | | angerOverflow = max(atkObj.GetXP() - IpyGameDataPY.GetFuncCfg("AngerXP", 2), 0)
|
| | | GameWorld.DebugLog("XP必命中! curXP=%s,angerOverflow=%s" % (curXP, angerOverflow))
|
| | |
|
| | | if isDot:
|
| | | mustHit = True
|
| | | |
| | | #命中公式 攻击方类型不同,公式不同
|
| | | if not mustHit:
|
| | | aMissRateDef = atkObj.GetBatAttrValue(ChConfig.AttrID_MissRateDef) #atkObj.GetHit() # 抗闪避率 - 命中
|
| | |
| | | missNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnMissNum)
|
| | | missRate = eval(IpyGameDataPY.GetFuncCompileCfg("MissCfg", 1))
|
| | | if GameWorld.CanHappen(missRate):
|
| | | GameWorld.DebugLog("闪避了! missRate=%s,dMissRate=%s,aMissRateDef=%s,missNum=%s" % (missRate, dMissRate, aMissRateDef, missNum))
|
| | | defObj.SetDict(ChConfig.Def_Obj_Dict_TurnMissNum, missRate + 1)
|
| | | return 0, pow(2, ChConfig.HurtType_Miss)
|
| | |
|
| | | hurtTypes = pow(2, ChConfig.HurtType_Normal)
|
| | |
|
| | | #calcType = curSkill.GetCalcType() 目前暂时按攻击算伤害,之后可以扩展其他
|
| | |
|
| | | isSuperHit = False # 是否暴击
|
| | | if isDot:
|
| | | isSuperHit = False
|
| | | isSuperHit, isParry = False, False
|
| | | aSuperDamPer, dSuperDamPerDef = 0, 0
|
| | | if not isDot:
|
| | | isSuperHit = CanSuperHit(atkObj, defObj) # 是否暴击
|
| | | isParry = (isTurnNormalSkill and CanParry(atkObj, defObj)) # 是否格挡,仅针对普攻
|
| | | CanStun(turnFight, atkObj, defObj, curSkill) # 是否击晕
|
| | | |
| | | if isSuperHit:
|
| | | hurtTypes |= pow(2, ChConfig.HurtType_SuperHit)
|
| | | aSuperDamPer = atkObj.GetBatAttrValue(ChConfig.AttrID_SuperDamPer)
|
| | | dSuperDamPerDef = atkObj.GetBatAttrValue(ChConfig.AttrID_SuperDamPerDef)
|
| | |
|
| | | isParry = False # 是否格挡
|
| | | if isParry:
|
| | | hurtTypes |= pow(2, ChConfig.HurtType_Parry)
|
| | |
|
| | |
| | | hurtTypes |= pow(2, ChConfig.HurtType_IgnoreDef)
|
| | |
|
| | | #参与运算的数值
|
| | | rand = random.random() #种子数 0~1
|
| | | #rand = random.random() #种子数 0~1
|
| | |
|
| | | aAtk = atkObj.GetBatAttrValue(ChConfig.AttrID_Atk) # 攻击方最大攻击
|
| | |
|
| | |
| | | dAngerSkillPerDef /= 10000.0
|
| | | aPMDamPer /= 10000.0
|
| | | dPMDamPerDef /= 10000.0
|
| | | aSuperDamPer /= 10000.0
|
| | | dSuperDamPerDef /= 10000.0
|
| | | aFinalDamPer /= 10000.0
|
| | | dFinalDamPerDef /= 10000.0
|
| | |
|
| | |
| | | hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("HurtFormula", 4))
|
| | | GameWorld.DebugLog(" 其他伤害=%s" % (hurtValue))
|
| | |
|
| | | hurtValue = max(1, int(hurtValue)) # 负值、保底防范
|
| | | if isParry:
|
| | | parryReduceRatio = IpyGameDataPY.GetFuncCfg("ParryCfg", 3)
|
| | | hurtValue = hurtValue * (1 - parryReduceRatio)
|
| | | GameWorld.DebugLog(" 格挡后伤害=%s,parryReduceRatio=%s" % (hurtValue, parryReduceRatio))
|
| | |
|
| | | hurtValue = max(1, int(hurtValue)) # 负值、保底防范
|
| | | return hurtValue, hurtTypes
|
| | |
|
| | | def CalcBounceHP(atkObj, defObj, hurtObj, curSkill):
|
| | | def CanSuperHit(atkObj, defObj):
|
| | | aSuperHitRate = atkObj.GetBatAttrValue(ChConfig.AttrID_SuperHitRate)
|
| | | dSuperHitRateDef = defObj.GetBatAttrValue(ChConfig.AttrID_SuperHitRateDef)
|
| | | happenRate = eval(IpyGameDataPY.GetFuncCompileCfg("SuperHitCfg", 1))
|
| | | if GameWorld.CanHappen(happenRate):
|
| | | GameWorld.DebugLog("暴击了: happenRate=%s,aSuperHitRate=%s,dSuperHitRateDef=%s" % (happenRate, aSuperHitRate, dSuperHitRateDef))
|
| | | return True
|
| | | return False
|
| | |
|
| | | def CanStun(turnFight, atkObj, defObj, curSkill):
|
| | | aStunRate = atkObj.GetBatAttrValue(ChConfig.AttrID_StunRate)
|
| | | dStunRateDef = defObj.GetBatAttrValue(ChConfig.AttrID_StunRateDef)
|
| | | 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
|
| | |
|
| | | def CanParry(atkObj, defObj):
|
| | | if defObj.IsInControlled():
|
| | | #被控制无法格挡
|
| | | return False
|
| | | aParryRateDef = atkObj.GetBatAttrValue(ChConfig.AttrID_ParryRateDef)
|
| | | dParryRate = defObj.GetBatAttrValue(ChConfig.AttrID_ParryRate)
|
| | | parryNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnParryNum)
|
| | | happenRate = eval(IpyGameDataPY.GetFuncCompileCfg("ParryCfg", 1))
|
| | | if GameWorld.CanHappen(happenRate):
|
| | | GameWorld.DebugLog("格挡了: happenRate=%s,aParryRateDef=%s,dParryRate=%s,parryNum=%s" % (happenRate, aParryRateDef, dParryRate, parryNum))
|
| | | defObj.SetDict(ChConfig.Def_Obj_Dict_TurnParryNum, parryNum + 1)
|
| | | return True
|
| | | return False
|
| | |
|
| | | def CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue):
|
| | | ## 计算伤害后,因各种buff和状态的影响处理
|
| | | # @return: hurtValue, realHurtHP
|
| | | |
| | | if hurtValue <= 0:
|
| | | return 0, 0
|
| | | |
| | | # 减伤盾减伤, 会改变 hurtValue
|
| | | hurtValue = max(0, hurtValue)
|
| | | |
| | | # 承伤盾承伤,剩余时间短的优先承伤,承伤不影响输出,相当于额外的HP,仅用于抵扣掉血,仅 改变 realHurtHP
|
| | | realHurtHP = hurtValue
|
| | | shieldBuffList = []
|
| | | buffMgr = defObj.GetBuffManager()
|
| | | for index in range(buffMgr.GetBuffCount()):
|
| | | buff = buffMgr.GetBuffByIndex(index)
|
| | | skillData = buff.GetSkillData()
|
| | | # 承伤盾
|
| | | if SkillCommon.isDamageShieldSkill(skillData):
|
| | | remainTime = buff.GetRemainTime() # 剩余回合
|
| | | if not skillData.GetLastTime():
|
| | | remainTime = 999 # 永久盾
|
| | | buffValue = buff.GetValue1() + buff.GetValue2() * ChConfig.Def_PerPointValue # 剩余盾值
|
| | | shieldBuffList.append([remainTime, buffValue, buff])
|
| | | |
| | | if shieldBuffList:
|
| | | shieldBuffList.sort()
|
| | | for _, buffValue, buff in shieldBuffList:
|
| | | if realHurtHP <= 0:
|
| | | break
|
| | | buffID = buff.GetBuffID()
|
| | | if realHurtHP < buffValue:
|
| | | damageShieldValue = realHurtHP
|
| | | else:
|
| | | damageShieldValue = buffValue
|
| | | GameWorld.DebugLog(" 承伤盾: buffID=%s,buffValue=%s,realHurtHP=%s,damageShieldValue=%s" % (buffID, buffValue, realHurtHP, damageShieldValue))
|
| | | realHurtHP -= damageShieldValue # 承伤值
|
| | | if damageShieldValue >= buffValue:
|
| | | GameWorld.DebugLog(" 删除盾: buffID=%s,realHurtHP=%s" % (buffID, realHurtHP))
|
| | | TurnBuff.DoBuffDel(turnFight, defObj, buff, relatedSkill=curSkill, afterLogic=True, tagObj=atkObj)
|
| | | else:
|
| | | updShieldValue = buffValue - damageShieldValue
|
| | | GameWorld.DebugLog(" 更新盾值: updShieldValue=%s,realHurtHP=%s" % (updShieldValue, realHurtHP))
|
| | | buff.SetValue1(updShieldValue % ChConfig.Def_PerPointValue)
|
| | | buff.SetValue2(updShieldValue / ChConfig.Def_PerPointValue)
|
| | | curSkill.AddAfterLogic(ChConfig.AfterLogic_SyncBuff, [defObj, buff, atkObj, "ReduceShieldValue"])
|
| | | |
| | | return hurtValue, max(0, realHurtHP)
|
| | |
|
| | | def CalcBounceHP(turnFight, atkObj, defObj, hurtObj, curSkill):
|
| | | '''计算反弹反弹伤害
|
| | | '''
|
| | | if not atkObj.GetCanAttack():
|
| | | return
|
| | |
|
| | | bounceHP = int(hurtObj.GetHurtHP() * random.uniform(0.1, 0.2))
|
| | | |
| | | if bounceHP <= 0:
|
| | | return
|
| | |
|
| | | remainHP = atkObj.GetHP() - bounceHP # 反弹允许弹到负值,如果最终吸血没有吸到正值则算死亡
|
| | | GameWorld.DebugLog(" 反弹伤害=%s,%s/%s" % (bounceHP, atkObj.GetHP(), atkObj.GetMaxHP()))
|
| | | bounceHP, realBounceHP = CalcHurtHPWithBuff(turnFight, defObj, atkObj, curSkill, bounceHP)
|
| | | if bounceHP <= 0:
|
| | | return
|
| | | hurtObj.SetBounceHP(bounceHP)
|
| | | atkObj.SetHP(remainHP)
|
| | | GameWorld.DebugLog(" 反弹伤害=%s,remainHP=%s/%s" % (bounceHP, remainHP, atkObj.GetMaxHP()))
|
| | |
|
| | | TurnAttack.AddTurnObjHurtValue(defObj, atkObj, bounceHP, bounceHP, isBounce=True)
|
| | | if realBounceHP > 0:
|
| | | remainHP = atkObj.GetHP() - realBounceHP # 反弹允许弹到负值,如果最终吸血没有吸到正值则算死亡
|
| | | atkObj.SetHP(remainHP)
|
| | | GameWorld.DebugLog(" bounceHP=%s,realBounceHP=%s,%s/%s" % (bounceHP, realBounceHP, atkObj.GetHP(), atkObj.GetMaxHP()))
|
| | | |
| | | TurnAttack.AddTurnObjHurtValue(defObj, atkObj, bounceHP, realBounceHP, isBounce=True)
|
| | | return
|
| | |
|
| | | def CalcSuckBlood(atkObj, defObj, hurtObj, curSkill):
|
| | | '''计算吸血
|
| | | '''
|
| | |
|
| | | suckHP = int(hurtObj.GetHurtHP() * random.uniform(0.1, 0.2))
|
| | | hurtHP = hurtObj.GetHurtHP()
|
| | | if hurtHP <= 1:
|
| | | return
|
| | |
|
| | | aSuckHPPer = atkObj.GetBatAttrValue(ChConfig.AttrID_SuckHPPer)
|
| | | dSuckHPPerDef = defObj.GetBatAttrValue(ChConfig.AttrID_SuckHPPerDef)
|
| | | suckHP = int(eval(IpyGameDataPY.GetFuncCompileCfg("SuckHPCfg", 1)))
|
| | | if suckHP <= 0:
|
| | | return
|
| | |
|
| | |
| | |
|
| | | hurtObj.SetSuckHP(suckHP)
|
| | | atkObj.SetHP(remainHP)
|
| | | GameWorld.DebugLog(" 吸血=%s,remainHP=%s/%s" % (suckHP, remainHP, maxHP))
|
| | | GameWorld.DebugLog(" 吸血=%s,remainHP=%s/%s,aSuckHPPer=%s,dSuckHPPerDef=%s" % (suckHP, remainHP, maxHP, aSuckHPPer, dSuckHPPerDef))
|
| | |
|
| | | # 吸血暂定算治疗
|
| | | TurnAttack.AddTurnObjCureHP(atkObj, atkObj, suckHP, cureHP)
|
| | |
| | | def CalcCureHP(userObj, tagObj, curSkill, largeNum=False):
|
| | | ''' 计算治疗值
|
| | | '''
|
| | | cureBaseValue = 0 #治疗基础值
|
| | | cureType = curSkill.GetCalcType()
|
| | | skillPer = curSkill.GetSkillPer()
|
| | | #skillValue = curSkill.GetSkillValue()
|
| | |
|
| | | #获得基础治疗值
|
| | | if cureType == ChConfig.Def_Cure_Attack:
|
| | | cureBaseValue = userObj.GetAtk()
|
| | | elif cureType == ChConfig.Def_Cure_MaxHP:
|
| | | cureBaseValue = userObj.GetMaxHP()
|
| | | #elif cureType == ChConfig.Def_Cure_HurtValue:
|
| | | # cureBaseValue = GameObj.GetLastHurtValue(userObj)
|
| | | elif cureType == ChConfig.Def_Cure_TagMaxHP:
|
| | | cureBaseValue = 0 if not tagObj else tagObj.GetMaxHP()
|
| | | cureBaseValue = GetCalcBaseValue(cureType, userObj, tagObj)
|
| | |
|
| | | #skillPer += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(userObj, None, curSkill, ChConfig.TriggerType_AddHP)
|
| | |
|
| | |
| | | % (cureHP, curSkill.GetSkillID(), cureType, baseValue, skillPer, curePer, cureDefPer, angerOverflow))
|
| | | return cureHP
|
| | |
|
| | | def GetCalcBaseValue(calcType, curObj, tagObj):
|
| | | ##获得基础计算值
|
| | | if calcType == ChConfig.Def_Calc_Attack:
|
| | | baseValue = curObj.GetAtk()
|
| | | elif calcType == ChConfig.Def_Calc_MaxHP:
|
| | | baseValue = curObj.GetMaxHP()
|
| | | #elif cureType == ChConfig.Def_Calc_HurtValue:
|
| | | # baseValue = GameObj.GetLastHurtValue(userObj)
|
| | | elif calcType == ChConfig.Def_Calc_TagMaxHP:
|
| | | baseValue = 0 if not tagObj else tagObj.GetMaxHP()
|
| | | return baseValue
|
| | |
|
| | | def DoDOTAttack(turnFight, batObj, curBuff, hurtValue, hurtTypes):
|
| | | ## 执行单次dot逻辑
|
| | | skillID = curBuff.GetSkillID()
|
| | |
| | | atkObj = buffOwner
|
| | | defObj = batObj
|
| | |
|
| | | tagObjList = [defObj]
|
| | | dHP = defObj.GetHP()
|
| | | defID = defObj.GetID()
|
| | | GameWorld.DebugLog("结算dot: defID=%s,buffID=%s,skillID=%s,ownerID=%s,hurtValue=%s,hurtTypes=%s,dHP=%s/%s" |
| | | % (defID, buffID, skillID, ownerID, hurtValue, hurtTypes, dHP, defObj.GetMaxHP()))
|
| | | tagObjList = [defObj]
|
| | |
|
| | | poolMgr = ObjPool.GetPoolMgr()
|
| | | useSkill = poolMgr.acquire(BattleObj.PySkill, skillIpyData)
|
| | | useSkill.SetTagObjList(tagObjList)
|
| | | useSkill.ClearHurtObj()
|
| | | hurtObj = useSkill.AddHurtObj(defID)
|
| | |
|
| | | remainHP = max(0, dHP - hurtValue) # 剩余血量
|
| | | dHP = defObj.GetHP()
|
| | | GameWorld.DebugLog("结算dot: defID=%s,buffID=%s,skillID=%s,ownerID=%s,hurtValue=%s,hurtTypes=%s,dHP=%s" |
| | | % (defID, buffID, skillID, ownerID, hurtValue, hurtTypes, dHP))
|
| | | hurtValue, realHurtHP = CalcHurtHPWithBuff(turnFight, atkObj, defObj, useSkill, hurtValue)
|
| | | |
| | | # dot的反弹、吸血待定
|
| | | |
| | | remainHP = max(0, dHP - realHurtHP) # 剩余血量
|
| | | lostHP = dHP - remainHP # 实际掉血量
|
| | | defObj.SetHP(remainHP)
|
| | |
|
| | | hurtObj = useSkill.AddHurtObj(defID)
|
| | | GameWorld.DebugLog(" hurtValue=%s,realHurtHP=%s,lostHP=%s,%s/%s" % (hurtValue, realHurtHP, lostHP, defObj.GetHP(), defObj.GetMaxHP()))
|
| | | |
| | | hurtObj.SetHurtTypes(hurtTypes)
|
| | | hurtObj.SetHurtHP(hurtValue)
|
| | | hurtObj.SetRealHurtHP(realHurtHP)
|
| | | hurtObj.SetLostHP(lostHP)
|
| | | hurtObj.SetCurHP(remainHP)
|
| | | |
| | | # dot的反弹、吸血待定
|
| | |
|
| | | TurnAttack.AddTurnObjHurtValue(atkObj, batObj, hurtValue, lostHP, skillID)
|
| | |
|
| | | Sync_PropertyRefreshView(turnFight, defObj, ChConfig.AttrID_HP, remainHP, hurtValue, diffType=0, skillID=skillID, hurtTypes=hurtTypes)
|
| | |
|
| | | DoBeAttackOver(turnFight, atkObj, useSkill)
|
| | | DoBeAttackResult(turnFight, atkObj, useSkill)
|
| | |
|
| | | useSkill.ResetUseRec()
|
| | | poolMgr.release(useSkill)
|