From 3beded4a9ae2e126158d89a4e7048f595ea0bc1b Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 25 八月 2025 12:01:24 +0800
Subject: [PATCH] 129 【战斗】战斗系统-服务端(技能触发来源触发逻辑优化;增加承伤盾支持,0428通知buff相关值;增加嘲讽支持,优化技能选择目标逻辑;增加连击、反击、格挡、暴击、通用击晕支持;)
---
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5001.py | 2
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py | 16
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py | 226 -------
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py | 739 ++++++++++++++++++++-------
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5010.py | 69 ++
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py | 116 +++-
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5011.py | 58 ++
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py | 187 ++++--
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py | 32
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py | 34
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1001.py | 11
PySysDB/PySysDBPY.h | 10
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py | 4
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py | 66 ++
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1003.py | 27 +
15 files changed, 1,069 insertions(+), 528 deletions(-)
diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 447571b..8811fba 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -79,22 +79,21 @@
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; //最大层数
@@ -102,6 +101,7 @@
DWORD DieContinue; //Buff死亡存在
list EnhanceSkillList; //触发技能ID列表
DWORD FightPower; //技能战斗力
+ char SkillMotionName; //技能动作名
};
//武将表
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py
index 55da264..89f6bc2 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py
@@ -33,41 +33,45 @@
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 = []
- # 技能
- key = (triggerWay, connSkillID)
- 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)
- 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)
- effDict = self._AffectBuffDict.get(key, {})
- for buffID, effIDList in effDict.items():
- effList.append(["buff", buffID, effIDList])
-
+
+ # 优先取关联技能的
+ if connSkillTypeID and connSkillTypeID not in [ChConfig.TriggerSrc_Skill, ChConfig.TriggerSrc_Buff]:
+ # 技能
+ key = (triggerWay, connSkillTypeID)
+ if key in self._AffectSkillDict:
+ effDict = self._AffectSkillDict[key]
+ for skillID, effIDList in effDict.items():
+ effList.append(["skill", skillID, effIDList])
+
+ # buff
+ key = (triggerWay, connSkillTypeID)
+ if key in self._AffectBuffDict:
+ effDict = self._AffectBuffDict[key]
+ for buffID, effIDList in effDict.items():
+ effList.append(["buff", buffID, effIDList])
+
+ # 所有技能有效的
+ 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])
+
return effList
def RefreshSkillPassiveEffect(self):
@@ -91,16 +95,16 @@
## 添加技能被动效果
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]
@@ -133,15 +137,16 @@
'''
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]
@@ -170,7 +175,8 @@
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 # 吸血量
@@ -190,6 +196,8 @@
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
@@ -235,6 +243,7 @@
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()
@@ -259,7 +268,7 @@
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()
@@ -267,6 +276,7 @@
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():
@@ -277,7 +287,9 @@
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
@@ -292,9 +304,20 @@
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管理器
@@ -336,6 +359,7 @@
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]
@@ -344,12 +368,15 @@
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
@@ -357,17 +384,19 @@
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 = []
@@ -402,7 +431,6 @@
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):
@@ -413,14 +441,14 @@
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
@@ -444,11 +472,11 @@
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()
@@ -456,6 +484,7 @@
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
@@ -464,12 +493,18 @@
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()
@@ -550,6 +585,7 @@
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
@@ -557,6 +593,7 @@
self.posNum = 0 # 所在阵容站位
self._hp = 0 # 当前生命值
self._xp = 0 # 当前怒气值
+ self._isAlive = True # 是否活着
self._initAttrDict = {} # 初始化时的属性,固定不变,初始化时已经算好的属性 {attrID:value, ...}
self._batAttrDict = {} # 实际战斗属性,包含buff层级的实际属性
self._skillTempAttrDict = {} # 某次技能释放中临时的属性增减 {attrID:+-value, ...}
@@ -605,6 +642,8 @@
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
@@ -646,7 +685,41 @@
## 是否处于某种状态下
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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
index 31df10d..a12550f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -267,12 +267,12 @@
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
@@ -556,7 +556,7 @@
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)
@@ -597,6 +597,7 @@
batObj.SetLineupPos(posNum, num)
batObj.SetFightPower(fightPower)
batObj.SetLV(lv)
+ batObj.SetAtkDistType(atkDistType)
if npcID:
batObj.SetNPCID(npcID)
elif lineupPlayerID:
@@ -1112,6 +1113,7 @@
return
def OnTimelineChange(turnFight):
+ ## 每个时间节点变化时处理
nowTimeline = turnFight.getTimeline()
@@ -1120,8 +1122,14 @@
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()):
@@ -1148,10 +1156,12 @@
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)
@@ -1194,40 +1204,6 @@
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):
@@ -1271,6 +1247,8 @@
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:
@@ -1279,7 +1257,7 @@
% (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))
@@ -1303,12 +1281,11 @@
objName = GetObjName(curBatObj)
# 是否可行动状态判断
- canAction = True
-
+ canAction = curBatObj.CanAction()
if not canAction:
GameWorld.DebugLog("★回合%s %s 当前状态不可行动!" % (turnNum, objName))
return
-
+
atk = curBatObj.GetAtk()
curXP = curBatObj.GetXP()
GameWorld.DebugLog("★回合%s %s 行动 : atk=%s,curHP=%s/%s,curXP=%s" % (turnNum, objName, atk, curHP, curBatObj.GetMaxHP(), curXP))
@@ -1338,6 +1315,9 @@
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)
@@ -1354,166 +1334,12 @@
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
@@ -1551,7 +1377,7 @@
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()
@@ -1577,7 +1403,7 @@
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}
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 63e2843..3cde4bd 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -954,8 +954,11 @@
Def_SkillID_Peace = 23048 # 玩家间和平buff
#----------------------------------------------------------------------
-#战斗类型
-Def_ChanceDefRate = 2000 # 抵御伤害概率, 目前固定20%概率
+
+#技能释放后需要额外处理逻辑
+AfterLogic_DelBuff = "DelBuff"
+AfterLogic_AddBuff = "AddBuff"
+AfterLogic_SyncBuff = "SyncBuff"
#伤害类型
(
@@ -1312,6 +1315,17 @@
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
@@ -1339,6 +1353,22 @@
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
@@ -1356,7 +1386,8 @@
SkillTagAffect_HPLowest, # 血量最低 1
SkillTagAffect_HPHighest, # 血量最高 2
SkillTagAffect_Death, # 死亡单位 3
-) = range(4)
+SkillTagAffect_UncontrolledPriority, # 未被控制优先 4
+) = range(5)
#技能施法目标
Def_UseSkillAim_Type = 3
@@ -3060,11 +3091,13 @@
# 回合攻击战斗类型
(
-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时长
@@ -3158,7 +3191,11 @@
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 = (
@@ -4465,7 +4502,16 @@
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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 5fabeab..abf348a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -49970,6 +49970,9 @@
("LastTime", c_int), # 剩余时长毫秒/回合数
("Layer", c_ushort), # 层数,不需要默认0
("OwnerID", c_int), # buff来源者,即施法方
+ ("Value1", c_int),
+ ("Value2", c_int),
+ ("Value3", c_int),
]
def __init__(self):
@@ -49993,6 +49996,9 @@
self.LastTime = 0
self.Layer = 0
self.OwnerID = 0
+ self.Value1 = 0
+ self.Value2 = 0
+ self.Value3 = 0
return
def GetLength(self):
@@ -50011,7 +50017,10 @@
RelatedSkillID:%d,
LastTime:%d,
Layer:%d,
- OwnerID:%d
+ OwnerID:%d,
+ Value1:%d,
+ Value2:%d,
+ Value3:%d
'''\
%(
self.Cmd,
@@ -50022,7 +50031,10 @@
self.RelatedSkillID,
self.LastTime,
self.Layer,
- self.OwnerID
+ self.OwnerID,
+ self.Value1,
+ self.Value2,
+ self.Value3
)
return DumpString
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index e98a113..00776b9 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -116,10 +116,9 @@
("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),
@@ -127,6 +126,7 @@
("DWORD", "DieContinue", 0),
("list", "EnhanceSkillList", 0),
("DWORD", "FightPower", 0),
+ ("char", "SkillMotionName", 0),
),
"Hero":(
@@ -2989,29 +2989,29 @@
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():
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
index f04ff00..5560b0a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
@@ -1848,6 +1848,10 @@
#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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5001.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5001.py
index c5e745b..391f7aa 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5001.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5001.py
@@ -17,7 +17,7 @@
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结算单次
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5010.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5010.py
new file mode 100644
index 0000000..c1a41be
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5010.py
@@ -0,0 +1,69 @@
+#!/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)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5011.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5011.py
new file mode 100644
index 0000000..bf90eff
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5011.py
@@ -0,0 +1,58 @@
+#!/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)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py
index 27ddea2..68799eb 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py
@@ -18,44 +18,70 @@
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()
@@ -71,11 +97,13 @@
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)
@@ -101,7 +129,7 @@
continue
if curEffect.GetTriggerWay():
- if curEffect.GetTriggerSrc() == 2:
+ if curEffect.GetTriggerSrc() != ChConfig.TriggerSrc_Skill:
passiveEffMgr.AddBuffPassiveEffect(addBuff, buffSkill, curEffect)
elif effectID in ChConfig.AttrIDList:
@@ -117,12 +145,24 @@
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()
@@ -135,7 +175,7 @@
continue
if curEffect.GetTriggerWay():
- if curEffect.GetTriggerSrc() == 2:
+ if curEffect.GetTriggerSrc() != ChConfig.TriggerSrc_Skill:
haveBuffPassiveEff = True
elif effectID in ChConfig.AttrIDList:
@@ -149,16 +189,27 @@
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):
@@ -245,12 +296,15 @@
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)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1001.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1001.py
index 5cdb4f1..485606d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1001.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1001.py
@@ -16,19 +16,20 @@
#-------------------------------------------------------------------------------
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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1003.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1003.py
new file mode 100644
index 0000000..f8077ad
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1003.py
@@ -0,0 +1,27 @@
+#!/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]
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py
index c1e7a9b..5dfbcf4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py
@@ -31,31 +31,49 @@
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
+
+ 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, buffID, effIDList, connSkill=None):
+def __doTriggerPassiveEffectByBuff(turnFight, batObj, tagObj, buffID, effIDList, connSkill=None):
buffMgr = batObj.GetBuffManager()
curBuff = buffMgr.GetBuff(buffID)
if not curBuff:
@@ -70,7 +88,7 @@
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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
index b35f747..5701a0c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
@@ -24,6 +24,7 @@
import ChPyNetSendPack
import PlayerControl
import ShareDefine
+import TurnPassive
import TurnAttack
import TurnBuff
import ObjPool
@@ -44,7 +45,7 @@
## 是否无视防御
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: 由哪个技能额外触发的,比如附加触发的技能或被动技能均可能由某个技能触发
@@ -76,8 +77,8 @@
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()
@@ -87,11 +88,10 @@
# 统一使用 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:
@@ -99,7 +99,11 @@
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)
@@ -108,12 +112,10 @@
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.Tag = useTag
@@ -121,6 +123,9 @@
clientPack.Sign = 1
turnFight.addBatPack(clientPack)
+ # 处理反击 或 连击
+ DoCombo(turnFight, curBatObj, useSkill)
+
# 最后重置、回收对象
useSkill.ResetUseRec()
if usePoolSkill:
@@ -128,18 +133,28 @@
return True
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()
posNum = curBatObj.GetPosNum()
@@ -159,123 +174,224 @@
# 对位
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:
- continue
- tagObjID = batLineup.posObjIDDict[pNum]
- tagBatObj = batObjMgr.getBatObj(tagObjID)
- if not __skillTagFilter(tagBatObj, tagAffect):
- continue
- aimObjList.append(tagBatObj)
+ 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 not __skillTagFilter(tagBatObj, tagAffect):
+ continue
+ aimObjList.append(tagBatObj)
+
# 目标细分
# 血量最低
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)
- aimObjList = aimObjList[:tagCount]
+ # 嘲讽优先
+ 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):
@@ -284,7 +400,6 @@
for tagBatObj in useSkill.GetTagObjList():
TurnBuff.OnAddBuff(turnFight, tagBatObj, useSkill, buffOwner=curBatObj)
- DoAttackResult(turnFight, curBatObj, useSkill)
return
def __doUseSkill(turnFight, curBatObj, useSkill):
@@ -294,50 +409,36 @@
# 通用攻击
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):
@@ -366,7 +467,6 @@
TurnAttack.AddTurnObjCureHP(tagBatObj, curBatObj, cureHP, realCureHP, skillID)
- DoAttackResult(turnFight, curBatObj, useSkill)
return
def SkillModule_6(turnFight, curBatObj, useSkill, opType):
@@ -432,7 +532,6 @@
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):
@@ -451,52 +550,192 @@
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)
+ __doCostZhanchui(turnFight, curBatObj, useSkill)
+ __doSkillUserAnger(turnFight, curBatObj, useSkill)
- # 最后处理反击 或 连击
-
+ DoBeAttackResult(turnFight, curBatObj, useSkill)
return
-def DoBeAttackOver(turnFight, curBatObj, useSkill):
- '''被攻击结果
- @param curBatObj: 施法方或buff归属方
+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 __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 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 __doCostZhanchui(turnFight, curBatObj, useSkill):
@@ -573,15 +812,13 @@
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)
@@ -589,7 +826,7 @@
continue
# 继承主技能目标
if enhanceSkillData.GetTagAim() == ChConfig.SkillTagAim_MainSkill:
- GameWorld.DebugLog(" 额外触发技能,继承主技能目标! enhanceSkillID=%s" % enhanceSkillID)
+ GameWorld.DebugLog("额外触发技能,继承主技能目标! enhanceSkillID=%s" % enhanceSkillID)
# 额外触发的技能直接在外层检查概率,如果都没有触发则不需要再处理
enhanceRate = enhanceSkillData.GetHappenRate()
enchanceTagObjList = []
@@ -602,7 +839,7 @@
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
@@ -616,16 +853,16 @@
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)
+ GameWorld.DebugLog("额外触发技能,重新锁定目标! enhanceSkillID=%s" % enhanceSkillID)
+ OnUseSkill(turnFight, curBatObj, enhanceSkillData, batType=ChConfig.TurnBattleType_Enhance, bySkill=useSkill)
return
-def __doSkillHurtHP(attacker, defObj, curSkill):
+def __doSkillHurtHP(turnFight, attacker, defObj, curSkill):
## 执行技能伤血,只计算伤血,其他逻辑等技能同步后再处理
# @return: None - 没有执行成功,即忽略该目标
@@ -647,33 +884,32 @@
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)
@@ -696,6 +932,9 @@
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() # 抗闪避率 - 命中
@@ -703,19 +942,26 @@
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)
@@ -723,7 +969,7 @@
hurtTypes |= pow(2, ChConfig.HurtType_IgnoreDef)
#参与运算的数值
- rand = random.random() #种子数 0~1
+ #rand = random.random() #种子数 0~1
aAtk = atkObj.GetBatAttrValue(ChConfig.AttrID_Atk) # 攻击方最大攻击
@@ -759,6 +1005,8 @@
dAngerSkillPerDef /= 10000.0
aPMDamPer /= 10000.0
dPMDamPerDef /= 10000.0
+ aSuperDamPer /= 10000.0
+ dSuperDamPerDef /= 10000.0
aFinalDamPer /= 10000.0
dFinalDamPerDef /= 10000.0
@@ -782,35 +1030,132 @@
hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("HurtFormula", 4))
GameWorld.DebugLog(" 其他伤害=%s" % (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
@@ -821,7 +1166,7 @@
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)
@@ -830,21 +1175,12 @@
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)
# 回合制
@@ -874,6 +1210,18 @@
% (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()
@@ -887,34 +1235,39 @@
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)
--
Gitblit v1.8.0