From 1ea73e1885835466265ce788d93556b7030ee0e8 Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期日, 30 十二月 2018 18:42:00 +0800 Subject: [PATCH] 5424 【后端】【1.4】跨服竞技场开发(GM工具增加子服服务器维护,文字翻译版) --- ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py | 363 ++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 314 insertions(+), 49 deletions(-) diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py index 926c040..dae7c55 100644 --- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py +++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py @@ -41,7 +41,7 @@ import PlayerTruck #import PlayerPrestigeSys import PlayerFamily -import BossHurtMng +#import BossHurtMng import PassiveBuffEffMng import PlayerSuccess import GameFuncComm @@ -56,7 +56,9 @@ import PlayerState import ChPyNetSendPack import NetPackCommon +import FamilyRobBoss import FBCommon +import ChNPC import datetime import math @@ -440,6 +442,18 @@ return ChConfig.Def_BattleRelationType_PVE +# 判断PK关系是否可攻击 Def_BattleRelationType_CommNoBoss也可攻击 只是攻击无效果 +def CheckBattleRelationType(skillBattleType, battleRelationType): + if skillBattleType in [ChConfig.Def_BattleRelationType_Comm, ChConfig.Def_BattleRelationType_CommNoBoss]: + return True + + #if battleRelationType in [ChConfig.Def_BattleRelationType_Comm, ChConfig.Def_BattleRelationType_CommNoBoss]: + # return True + + if skillBattleType != battleRelationType: + # PK模式的判定 + return False + return True ## 获取攻击类型 # @param attack 攻击方对象 @@ -610,7 +624,7 @@ # @remarks 获得curPlayer是否是新手 def GetIsNewGuy(curPlayer): - if curPlayer.GetLV() < ReadChConfig.GetEvalChConfig("MinPKLV"): + if curPlayer.GetLV() < IpyGameDataPY.GetFuncCfg("PKConfig", 5): return True return False @@ -679,7 +693,8 @@ defNPCHurtList = curTagObj.GetPlayerHurtList() curObjType = curObj.GetGameObjType() if curObjType == IPY_GameWorld.gotPlayer: - BossHurtMng.BossAddPlayerInHurtList(curObj, curTagObj, hurtHP) + #BossHurtMng.BossAddPlayerInHurtList(curObj, curTagObj, hurtHP) + FamilyRobBoss.OnPlayerHurtFamilyOwnerBoss(curObj, curTagObj, hurtHP) if curTagObj.GetGameObjType() == IPY_GameWorld.gotNPC: FBLogic.DoFB_Player_HurtNPC(curObj, curTagObj, hurtHP) if GameObj.GetHP(curTagObj) == 0: @@ -748,6 +763,10 @@ if not CheckKillNPCByCnt(attacker, defender): return False + #仙盟归属NPC判断 + if not CheckCanAttackFamilyOwnerNPC(attacker, defender): + return False + # NPC打玩家,反过来判断 elif atkObjType == IPY_GameWorld.gotNPC and defObjType == IPY_GameWorld.gotPlayer: ##攻击次数判断 @@ -758,12 +777,19 @@ if not CheckKillNPCByCnt(defender, attacker, False): return False + #仙盟归属NPC判断 + if not CheckCanAttackFamilyOwnerNPC(defender, attacker, False): + return False # NPC打NPC elif atkObjType == IPY_GameWorld.gotNPC and defObjType == IPY_GameWorld.gotNPC: if PetControl.IsPet(attacker) or attacker.GetGameNPCObjType()== IPY_GameWorld.gnotSummon: #击杀次数判断 if not CheckKillNPCByCnt(attacker, defender, False): + return False + + #仙盟归属NPC判断 + if not CheckCanAttackFamilyOwnerNPC(attacker, defender, False): return False #攻击NPC等级限制 @@ -817,6 +843,34 @@ return False +def CheckCanAttackFamilyOwnerNPC(attacker, defender, isNotify=True): + ''' 判断可否攻击仙盟归属的NPC ''' + if defender.GetGameObjType() != IPY_GameWorld.gotNPC: + #GameWorld.DebugLog("只判断被攻击的是NPC的情况") + return True + + if NPCCommon.GetDropOwnerType(defender) != ChConfig.DropOwnerType_Family: + return True + + atkPlayer, npcObjType = GetAttackPlayer(attacker) + # 攻击者非玩家不限制 + if not atkPlayer: + #GameWorld.DebugLog("攻击者非玩家不限制") + return True + + atkLimitNotifyMark = "" + if GetIsNewGuy(atkPlayer): + atkLimitNotifyMark = "FairyGrabBossNotAtk" + elif not atkPlayer.GetFamilyID(): + atkLimitNotifyMark = "FairyGrabBossNoFairy" + + if atkLimitNotifyMark: + if npcObjType is None and isNotify: + PlayerControl.NotifyCode(atkPlayer, atkLimitNotifyMark) + return False + + return True + def CheckKillNPCByCnt(attacker, defender, isNotify=True): ''' 判断当日击杀该NPC次数是否已满 ''' if defender.GetGameObjType() != IPY_GameWorld.gotNPC: @@ -853,9 +907,9 @@ if hasKillCnt >= limitCnt + itemAddKillCnt: - if BossHurtMng.GetPlayerBossHurt(atkPlayer, defender): - GameWorld.DebugLog("攻击过该boss可继续攻击") - return True + #if BossHurtMng.GetPlayerBossHurt(atkPlayer, defender): + # GameWorld.DebugLog("攻击过该boss可继续攻击") + # return True #次数不足 # 实际攻击者类型None则需要提示玩家 if npcObjType is None: @@ -888,9 +942,9 @@ hasAttackCnt = atkPlayer.NomalDictGetProperty(ChConfig.Def_PDict_WorldBoss_HurtCnt, 0) if hasAttackCnt >= limitCnt: - if BossHurtMng.GetPlayerBossHurt(atkPlayer, defender): - GameWorld.DebugLog("攻击过该boss可继续攻击") - return True + #if BossHurtMng.GetPlayerBossHurt(atkPlayer, defender): + # GameWorld.DebugLog("攻击过该boss可继续攻击") + # return True #次数不足 # 实际攻击者类型None则需要提示玩家 if npcObjType is None: @@ -1417,11 +1471,58 @@ if npcType == IPY_GameWorld.ntElf: # ntElf 定义为人物使用对地持续性技能,并且人物可以移动,则需要ntElf做依托物的情况 # 那么ntElf执行人物的伤害计算和被动触发效果 - owner = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer, attacker) + # 2018-11-16 Elf 支持主人为NPC + # owner = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer, attacker) + + owner = NPCCommon.GetSummonOwnerDetel(attacker) return attacker if not owner else owner return attacker + +# 检查对象是否属于玩家,比如用于纯PVP验证 +def CheckIsPlayerOnwer(gameObj): + if not gameObj: + return False + objType = gameObj.GetGameObjType() + + if objType == IPY_GameWorld.gotPlayer: + return True + + objNPCType = gameObj.GetGameNPCObjType() + if objNPCType == IPY_GameWorld.gnotNormal: + return False + + if objNPCType == IPY_GameWorld.gnotSummon: + owner = NPCCommon.GetSummonOwnerDetel(gameObj) + if not owner: + return False + if owner.GetGameObjType() != IPY_GameWorld.gotPlayer: + return False + + return True + +# 攻击时防守方神兵护盾的处理 +def CalcAtkProDef(atkObj, defObj, hurtValue, curSkill, tick): + if defObj.GetGameObjType() != IPY_GameWorld.gotPlayer: + return hurtValue + + if not CheckIsPlayerOnwer(atkObj): + return hurtValue + + curProDef = PlayerControl.GetProDef(defObj) + if not curProDef: + return hurtValue + + absortValue = min(PlayerControl.GetProDefAbsorb(defObj)*hurtValue/ChConfig.Def_MaxRateValue, curProDef) + + PlayerControl.SetProDef(defObj, curProDef - absortValue) + + # 被动技能触发 + defObj.SetDict(ChConfig.Def_PlayerKey_GodWeaponBeforeProDef, curProDef) + PassiveBuffEffMng.OnPassiveSkillTrigger(defObj, atkObj, None, ChConfig.TriggerType_ProDefValue, tick) + return hurtValue - absortValue + ## 计算伤血值 # @param atkObj 攻击者 # @param defObj 防御者 @@ -1433,8 +1534,8 @@ # @param finalHurtPer 对最终计算出来的伤害影响效果(有正负,默认10000) # @return None or HurtType 伤害结构体类 # @remarks 函数详细说明. -def GetHurtHP(atkObj, defObj, curSkill, atkSkillValue, atkSkillPer, tick): - atkObj = ElfChangeAttacker(atkObj) # Elf灵为替身攻击,要取玩家的属性 +def GetHurtHP(attacker, defObj, curSkill, atkSkillValue, atkSkillPer, tick): + atkObj = ElfChangeAttacker(attacker) # Elf灵为替身攻击,要取玩家的属性 resultHurtType = HurtType() defObjType = defObj.GetGameObjType() @@ -1454,7 +1555,7 @@ # 理论伤害一致, 多加点预算伤害避免计算误差 #hurtValue = min(ShareDefine.Def_UpperLimit_DWord, hurtValue+10) #atkObj.SetDict(ChConfig.Def_PlayerKey_ClientMaxHurtValue, int(hurtValue*1.2)) - hurtValue = atkObj.GetMaxAtk()*atkSkillPer*10 + atkObj.GetSuperHit() # 加入被动计算不准确改成估算 + hurtValue = atkObj.GetMaxAtk()*atkSkillPer*20 # 加入被动计算不准确改成估算 clientValue, hurtType = SkillShell.GetClientHurtByObj(defObj.GetID(), defObjType) if clientValue <= hurtValue: @@ -1466,8 +1567,23 @@ #GameWorld.DebugAnswer(atkObj, "客户端伤害 %s 服务端伤害 %s"%([defObj.GetID(), clientValue, hurtType], hurtValue)) else: - hurtValue, hurtType = CalcHurtHP(atkObj, defObj, curSkill, atkSkillValue, atkSkillPer, tick) + hurtValue, hurtType = CalcHurtHP(atkObj, defObj, curSkill, atkSkillValue, atkSkillPer, tick, orgAtkObj=attacker) + # 优先处理神兵护盾 + hurtValue = CalcAtkProDef(atkObj, defObj, hurtValue, curSkill, tick) + + # 伤害吸收盾回血型 + buffManager = defObj.GetBuffState() + curEffect, plusValue, skillID = BuffSkill.FindBuffEffectPlusByEffectID(buffManager, ChConfig.Def_Skill_Effect_AbsorbShieldXMZJ) + if skillID: + absortValue = hurtValue*curEffect.GetEffectValue(0)/ShareDefine.Def_MaxRateValue + if absortValue: + hurtValue -= absortValue + findBuff = SkillCommon.FindBuffByID(defObj, skillID)[0] + if findBuff: + # 用于回血 + findBuff.SetValue(int(findBuff.GetValue() + absortValue)) + if defObj.GetDictByKey(ChConfig.Def_PlayerKey_AbsorbShieldValue): # 麒麟护盾吸收伤害,将抵消的伤害存储 absortValue = int(defObj.GetDictByKey(ChConfig.Def_PlayerKey_AbsorbShieldValue)/float(ShareDefine.Def_MaxRateValue)*hurtValue) @@ -1478,15 +1594,16 @@ if absorbHurt <= defObj.GetDictByKey(ChConfig.Def_PlayerKey_AbsorbShieldMax): maxValue = min(absorbHurt + absortValue, defObj.GetDictByKey(ChConfig.Def_PlayerKey_AbsorbShieldMax)) defObj.SetDict(ChConfig.Def_PlayerKey_AbsorbShield, maxValue) # 记录护盾吸收的伤害用于爆炸 - + # buff减少伤害百分比 reducePer = PassiveBuffEffMng.GetValueByPassiveBuffTriggerType(defObj, atkObj, None, ChConfig.TriggerType_ReduceHurtHPPer) + # 被攻击被动技能特殊减免 受到单次伤害超过生命上限10%时候,减免50%伤害,CD10秒 defObj.SetDict(ChConfig.Def_PlayerKey_curHurtValue, hurtValue) reducePer += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(defObj, atkObj, None, ChConfig.TriggerType_ReduceHurtHPPer) hurtValue = int(hurtValue*(max(ChConfig.Def_MaxRateValue - reducePer, 0))*1.0/ChConfig.Def_MaxRateValue) - + # 斩杀,濒死等情况的处理 if PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(atkObj, defObj, curSkill, ChConfig.TriggerType_AttackKill): # 斩杀 @@ -1506,13 +1623,24 @@ # 血盾 hurtValue = CalcBloodShield(atkObj, defObj, hurtValue) - remainHP = min(dMaxHP, max(0, dHP - hurtValue)) # 剩余血量 remainHP = int(remainHP) #防范 - if defObjType == IPY_GameWorld.gotPlayer: + curHP = GameObj.GetHP(defObj) GameObj.SetHP(defObj, remainHP, False) + + lockHPPer = PassiveBuffEffMng.OnObjsPassiveSkillLockHP(defObj, atkObj, curSkill, ChConfig.TriggerType_LockHP, tick) + if lockHPPer: + # 锁血情况 + lockHP = GameObj.GetMaxHP(defObj)*lockHPPer/ChConfig.Def_MaxRateValue + if lockHP < curHP and remainHP < lockHP: + remainHP = lockHP + elif lockHP >= curHP: + remainHP = curHP + + #锁血纠正血量 + GameObj.SetHP(defObj, remainHP, False) elif defObjType == IPY_GameWorld.gotNPC: if defObj.GetGameNPCObjType() == IPY_GameWorld.gnotPet: @@ -1522,12 +1650,23 @@ elif defObj.GetGameNPCObjType() == IPY_GameWorld.gnotTruck: remainHP = max(PlayerTruck.GetTruckDestroyMinHP(defObj), remainHP) GameObj.SetHP(defObj, remainHP) + + elif defObj.GetType() == ChConfig.ntHelpBattleRobot: + remainHP = min(dHP, max(GameObj.GetMaxHP(defObj)/2, remainHP)) # 助战机器人剩余血量不能少于一半 + GameObj.SetHP(defObj, remainHP) + else: #防守方是怪物NPC,只扣其血 GameObj.SetHP(defObj, remainHP) else: GameWorld.ErrLog('计算伤血值时,防守方类型错误:defObjType = %s' % (defObjType)) return resultHurtType + + if GameObj.GetHP(defObj) > 0: + # 被攻击者将部分伤害转化为血量, 返回转化的百分比(小数点) + changePer = PassiveBuffEffMng.GetValueByPassiveBuffTriggerType(defObj, atkObj, None, ChConfig.TriggerType_ChangeHurtToHP) + if changePer: + SkillCommon.SkillAddHP(defObj, 0, int(changePer*hurtValue)) lostValue = dHP - GameObj.GetHP(defObj) # 实际掉血量 resultHurtType.LostHP = lostValue @@ -1536,7 +1675,7 @@ #攻击触发事件, 该代码应该放在DoAttack函数中处理逻辑比较清晰,也不会破坏GetHurtHP函数 #因为DoAttack修改点比较多,暂不迁移,相关攻击事件逻辑,就往此函数中添加 - AttackEventTrigger(atkObj, defObj, resultHurtType, tick) + AttackEventTrigger(atkObj, defObj, curSkill, resultHurtType, tick) #=========================================================================== # if atkObj.GetGameObjType() == IPY_GameWorld.gotPlayer: # GameWorld.DebugAnswer(atkObj, "--%s剩余血量 %s"%(defObj.GetID(), defObj.GetHP())) @@ -1557,13 +1696,27 @@ # 计算攻击伤害 # maxHurt参数用于模拟计算最大伤害,防范客户端攻击伤害过高 -def CalcHurtHP(atkObj, defObj, curSkill, atkSkillValue, atkSkillPer, tick, happenState=None, maxHurt=False): +def CalcHurtHP(atkObj, defObj, curSkill, atkSkillValue, atkSkillPer, tick, happenState=None, **atkwargs): # 翻滚闪避特殊处理 if tick - defObj.GetDictByKey(ChConfig.Def_PlayerKey_SomersaultTime) < 500: return 0, ChConfig.Def_HurtType_Miss + summonAtkPer = 1 # 召唤继承提高基础攻击力,取表 + summonAtkObj = atkwargs.get('orgAtkObj', None) if atkwargs.get('orgAtkObj', None) else atkObj + if summonAtkObj.GetGameObjType() == IPY_GameWorld.gotNPC and summonAtkObj.GetGameNPCObjType() == IPY_GameWorld.gnotSummon: + summonAtkPerValue = summonAtkObj.GetDictByKey(ChConfig.Def_GameObjKey_InheritOwner) + if summonAtkPerValue > 0: + # 暴风雪类召唤兽转化为主人计算伤害 + ownerAtkObj = NPCCommon.GetSummonOwnerDetel(summonAtkObj) + if not ownerAtkObj: + return 0, ChConfig.Def_HurtType_Miss + + summonAtkPer = summonAtkPerValue*1.0/ChConfig.Def_MaxRateValue + #GameWorld.DebugLog("召唤兽取主人---------%s-%s-%s-%s"%(ownerAtkObj.GetID(), atkSkillPer, atkSkillValue, summonAtkPer)) + atkObjType = atkObj.GetGameObjType() defObjType = defObj.GetGameObjType() + atkType = GetBattleType(atkObj, curSkill) happenState = happenState if happenState else SkillShell.GetHappenState(curSkill) @@ -1580,14 +1733,23 @@ dMissSuccessRate += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(defObj, atkObj, None, ChConfig.TriggerType_MissSuccessPer) skillID = curSkill.GetSkillID() if curSkill else 0 + atkIsBoss = 0 # 攻击方是否boss suppressValueLV = 0 # 等级最终压制值, 由压制规则及相关参数计算得出,可作为伤害公式计算参数使用 suppressValueFP = 0 # 战力最终压制值, 由压制规则及相关参数计算得出,可作为伤害公式计算参数使用 suppressLV, suppressFightPower = 0, 0 # 压制等级差、战力差 suppressReMaxHP = 0 # NPC压制等级生命值, 等级表中NPC等级对应的数据, 压制等级差大于0时才有值 suppressNPCFightPower = 0 # 压制NPC战力 + fbFightPower, fbBaseHurt = 0, 0 # 副本战力, 副本保底伤害 #当攻击方为NPC,防守方为玩家时,计算压制等级 及 压制战力 if atkObjType == IPY_GameWorld.gotNPC and defObjType == IPY_GameWorld.gotPlayer: + + if curSkill and curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_RealmSuppress: + # 境界压制技能不对高等级境界玩家产生攻击 + aRealmLV, dRealmLV = GetPVERealmLVs(atkObj, defObj, atkObjType, defObjType) + if aRealmLV <= dRealmLV: + return 0, ChConfig.Def_HurtType_Immune # 免疫 + atkIsBoss = 1 if ChConfig.IsGameBoss(atkObj) else 0 if NPCCommon.GetIsLVSuppress(atkObj): suppressLV = max(0, aLV - dLV) @@ -1598,11 +1760,26 @@ if suppressNPCFightPower: suppressFightPower = max(0, suppressNPCFightPower - defObj.GetFightPower()) + mustHit = False + helpBattleFormatKey = "" + if atkObjType == IPY_GameWorld.gotNPC and atkObj.GetType() == ChConfig.ntHelpBattleRobot: + mustHit = True + suppressNPCFightPower = NPCCommon.GetSuppressFightPower(atkObj) + fbFightPower = GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.FBPD_HelpBattleFBFightPower) + fbBaseHurt = GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.FBPD_HelpBattleFBBaseHurt) + helpBattleFormatKey = "HelpRobot_Atk" + if defObjType == IPY_GameWorld.gotNPC and defObj.GetType() == ChConfig.ntHelpBattleRobot: + mustHit = True + suppressNPCFightPower = NPCCommon.GetSuppressFightPower(defObj) + fbFightPower = GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.FBPD_HelpBattleFBFightPower) + fbBaseHurt = GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.FBPD_HelpBattleFBBaseHurt) + helpBattleFormatKey = "HelpRobot_Def" + #命中公式 攻击方类型不同,公式不同 hitFormula = ReadChConfig.GetChConfig('CalcCanHit') - if not maxHurt and not PassiveBuffEffMng.GetValueByPassiveBuffTriggerType(atkObj, defObj, curSkill, - ChConfig.TriggerType_Buff_MustBeHit): # maxHurt用于模拟计算, 被动有必命中效果 + if not mustHit and not PassiveBuffEffMng.GetValueByPassiveBuffTriggerType(atkObj, defObj, curSkill, + ChConfig.TriggerType_Buff_MustBeHit): # 技能对指定BOSS无效果的返回MISS if defObjType == IPY_GameWorld.gotNPC and defObj.GetIsBoss() not in ChConfig.Def_SkillAttack_NPCIsBoss \ and SkillCommon.GetSkillBattleType(curSkill) == ChConfig.Def_BattleRelationType_CommNoBoss: @@ -1618,27 +1795,26 @@ and eval(hitFormula) < 0: return 0, ChConfig.Def_HurtType_Miss - if maxHurt: # 用于模拟计算最大伤害 - rand = 1 - isLuckyHit, aLuckyHit, dLuckyHitReduce = True, atkObj.GetLuckyHitVal(), 0 - isSuperHit, aSuperHit, dSuperHitReduce = True, atkObj.GetSuperHit(), 0 - dDamChanceDef = 0 - hurtType = ChConfig.Def_HurtType_SuperHit - else: - hurtType, hurtTypeResultDict = CalcHurtTypeResult(atkObj, defObj, atkObjType, defObjType, happenState) - #GameWorld.DebugLog("GetHurtHP hurtType=%s, hurtTypeResultDict=%s" % (hurtType, hurtTypeResultDict)) - isLuckyHit, aLuckyHit, dLuckyHitReduce = hurtTypeResultDict[ChConfig.Def_HurtType_LuckyHit] # 幸运一击 - isSuperHit, aSuperHit, dSuperHitReduce = hurtTypeResultDict[ChConfig.Def_HurtType_SuperHit] # 暴击 - dDamChanceDef = hurtTypeResultDict[ChConfig.Def_HurtType_Parry][2] # 抵御, 大于0代表触发抵御效果 + + hurtType, hurtTypeResultDict = CalcHurtTypeResult(atkObj, defObj, atkObjType, defObjType, happenState) + #GameWorld.DebugLog("GetHurtHP hurtType=%s, hurtTypeResultDict=%s" % (hurtType, hurtTypeResultDict)) + isLuckyHit, aLuckyHit, dLuckyHitReduce = hurtTypeResultDict[ChConfig.Def_HurtType_LuckyHit] # 幸运一击 + isSuperHit, aSuperHit, dSuperHitReduce = hurtTypeResultDict[ChConfig.Def_HurtType_SuperHit] # 暴击 + dDamChanceDef = hurtTypeResultDict[ChConfig.Def_HurtType_Parry][2] # 抵御, 大于0代表触发抵御效果 if PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(defObj, atkObj, None, ChConfig.TriggerType_OneDamage): return 1, hurtType + + worldLV = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv) + wLVIpyData = PlayerControl.GetPlayerLVIpyData(worldLV) + wReFightPower = 0 if not wLVIpyData else wLVIpyData.GetReFightPower() # 当前世界等级参考战力 # 改变技能伤害 atkSkillPer, atkSkillValue = ChangeSkillHurt(atkObj, defObj, curSkill, atkSkillPer, atkSkillValue) # atkSkillPer 包含普攻,所以不是用技能增强处理 atkSkillPer += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(atkObj, defObj, curSkill, ChConfig.TriggerType_AttackAddSkillPer) + atkSkillPer += PassiveBuffEffMng.GetValueByPassiveBuffTriggerType(atkObj, defObj, curSkill, ChConfig.TriggerType_AttackAddSkillPer) @@ -1654,12 +1830,19 @@ # 暴击增加技能伤害 atkSkillPer += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(atkObj, defObj, curSkill, ChConfig.TriggerType_SuperHitSkillPer) + if isLuckyHit: + # 会心一击时增加会心伤害百分比 + aLuckyHit += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(atkObj, defObj, curSkill, ChConfig.TriggerType_LuckyHit) + aLuckyHit -= PassiveBuffEffMng.GetValueByPassiveBuffTriggerType(defObj, atkObj, curSkill, ChConfig.TriggerType_BeLuckyHitSubPer) + aLuckyHit = max(aLuckyHit, 0) + #参与运算的数值 rand = random.random() #种子数 0~1 #------- 攻击方 - aMinAtk = atkObj.GetMinAtk() # 攻击方最小攻击 - aMaxAtk = atkObj.GetMaxAtk() # 攻击方最大攻击 + aMinAtk = atkObj.GetMinAtk() * summonAtkPer # 攻击方最小攻击 + aMaxAtk = atkObj.GetMaxAtk() * summonAtkPer # 攻击方最大攻击 + aIceAtk = atkObj.GetIceAtk() # 冰攻, 元素真伤, 玩家及NPC通用 aIceAtk += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(atkObj, defObj, curSkill, ChConfig.TriggerType_AddIceAtk) #------- 防守方 @@ -1679,7 +1862,11 @@ aDamagePer += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(atkObj, defObj, curSkill, ChConfig.TriggerType_AddDamagePer) aDamagePer += PassiveBuffEffMng.GetValueByPassiveBuffTriggerType(atkObj, defObj, curSkill, ChConfig.TriggerType_AddDamagePer) + aNPCHurtAddPer = PlayerControl.GetNPCHurtAddPer(atkObj) # PVE伤害加成 aDamagePerPVP = PlayerControl.GetDamagePerPVP(atkObj) # 外层PVP伤害加成 + aFinalHurtPer = PlayerControl.GetFinalHurtPer(atkObj) # 最外层伤害加成, 可能为负值 + aFinalHurtPer += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(atkObj, defObj, curSkill, ChConfig.TriggerType_AttackAddFinalPer) + aFinalHurt = PlayerControl.GetFinalHurt(atkObj) # 最终固定伤害 # 被动增加最终伤害 aFinalHurt += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(atkObj, defObj, curSkill, ChConfig.TriggerType_AttackAddFinalValue) @@ -1690,14 +1877,16 @@ else: aIgnoreDefRate = 0 # 无视防御比率 + aFinalHurtPer = GameObj.GetPetDamPer(atkObj) # 最外层伤害加成, 可能为负值 aSkillAtkRate = NPCCommon.GetSkillAtkRate(atkObj) # 技能攻击力加成 if atkObjType == IPY_GameWorld.gotNPC and atkObj.GetGameNPCObjType() == IPY_GameWorld.gnotPet: aSkillAtkRate += atkObj.GetSkillAtkRate() + + aNPCHurtAddPer = 0 # PVE伤害加成 aDamagePer = 0 # 外层伤害加成 aDamagePerPVP = 0 # 外层PVP伤害加成 aFinalHurt = NPCCommon.GetFinalHurt(atkObj) # 最终固定伤害 aFightPower = NPCCommon.GetSuppressFightPower(atkObj) - #防守方的类型 if defObjType == IPY_GameWorld.gotPlayer: @@ -1734,7 +1923,7 @@ suppressFPFormula = hurtDist[suppressFormulaKeyFP] suppressValueFP = eval(FormulaControl.GetCompileFormula(suppressFormulaKeyFP, suppressFPFormula)) - # 境界压制百分比, 仅限PVP + # 境界压制百分比 SuppressValueRealmRate = 10000 # 默认值 suppressRealm = 0 if atkObjType == IPY_GameWorld.gotPlayer and defObjType == IPY_GameWorld.gotPlayer: @@ -1753,17 +1942,47 @@ #GameWorld.DebugLog("境界压制:aRealmLV=%s,dRealmLV=%s,aRealmGroup=%s,dRealmGroup=%s,SuppressValueRealmRate=%s" # % (aRealmLV, dRealmLV, aRealmGroup, dRealmGroup, SuppressValueRealmRate)) - else: - #PVE 境界压制 + elif atkObjType == IPY_GameWorld.gotNPC and defObjType == IPY_GameWorld.gotPlayer: + # EVP 境界压制 aRealmLV, dRealmLV = GetPVERealmLVs(atkObj, defObj, atkObjType, defObjType) if aRealmLV + dRealmLV != 0: #有压制 - suppressRealm = aRealmLV - dRealmLV + suppressRealm = aRealmLV - dRealmLV # 存在负数 + suppressRealmHurtPer = GetRealmHurtPer(aRealmLV, dRealmLV, 2) # 境界压制加成百分比,存在负数 + suppressFormulaKeyRealm = "EVPSuppressValueRealm" + if suppressFormulaKeyRealm in hurtDist: + SuppressValueRealmRate = int(eval(FormulaControl.GetCompileFormula(suppressFormulaKeyRealm, hurtDist[suppressFormulaKeyRealm]))) + + elif atkObjType == IPY_GameWorld.gotPlayer and defObjType == IPY_GameWorld.gotNPC: + # PVE 境界压制 + aRealmLV, dRealmLV = GetPVERealmLVs(atkObj, defObj, atkObjType, defObjType) + if aRealmLV + dRealmLV != 0: + #有压制 + suppressRealm = aRealmLV - dRealmLV # 存在负数 + suppressRealmHurtPer = GetRealmHurtPer(aRealmLV, dRealmLV, 3) # 境界压制加成百分比,存在负数 suppressFormulaKeyRealm = "PVESuppressValueRealm" if suppressFormulaKeyRealm in hurtDist: SuppressValueRealmRate = int(eval(FormulaControl.GetCompileFormula(suppressFormulaKeyRealm, hurtDist[suppressFormulaKeyRealm]))) - - + + + # 骑宠争夺最终伤害衰减 + if defObjType == IPY_GameWorld.gotNPC and FamilyRobBoss.IsHorsePetRobBoss(defObj.GetNPCID()): + ownerPlayer = None + # 召唤兽和宠物需要从人物获取状态 + if atkObj.GetGameObjType() == IPY_GameWorld.gotNPC: + if atkObj.GetGameNPCObjType() == IPY_GameWorld.gnotPet: + ownerPlayer = PetControl.GetPetOwner(atkObj) + elif atkObj.GetGameNPCObjType() == IPY_GameWorld.gnotSummon: + ownerPlayer = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer, atkObj) + else: + ownerPlayer = atkObj + + if ownerPlayer: + findBuff = SkillCommon.FindBuffByID(ownerPlayer, ChConfig.Def_SkillID_HorsePetRobBossKillCntBuff)[0] + if findBuff: + reduceFinalHurtPer = findBuff.GetSkill().GetEffect(0).GetEffectValue(0) + aFinalHurtPer -= reduceFinalHurtPer + atkStateMark = GetObjAtkStateMark(atkObj) defStateMark = GetObjAtkStateMark(defObj) hurtFormulaKey = "%sV%s_%s" % (atkStateMark, defStateMark, atkType) @@ -1782,16 +2001,43 @@ suppressLVHurtKey = "%s_%s" % (hurtFormulaKey, suppressLVGroup) if suppressLVHurtKey in hurtDist: hurtFormulaKey = suppressLVHurtKey - + + # 助战机器人特殊伤血key + if helpBattleFormatKey: + hurtFormulaKey = helpBattleFormatKey + if hurtFormulaKey not in hurtDist: GameWorld.ErrLog("CalcAttackValue.txt 伤害公式未配置, key=%s" % (hurtFormulaKey)) return 0, ChConfig.Def_HurtType_Miss hurtFormula = hurtDist[hurtFormulaKey] hurtValue = int(eval(FormulaControl.GetCompileFormula(hurtFormulaKey, hurtFormula))) + + if hurtType == ChConfig.Def_HurtType_Normal and SuppressValueRealmRate > 10000: + # 存在压制 + return hurtValue, ChConfig.Def_HurtType_RealmSupress return hurtValue, hurtType +# 获取EVP和PVE伤害百分比差,PVE无境界压制, 境界等级对应列表的index,越界取最高 +def GetRealmHurtPer(aRealmLV, dRealmLV, gridIndex): + suppressRealmHurtPer = 0 + suppressRealmDict = IpyGameDataPY.GetFuncEvalCfg("RealmGroup", gridIndex) + + plus_minus = 1 # 负数为反压制 + if aRealmLV >= dRealmLV: + suppressList = range(dRealmLV+1, aRealmLV+1) + else: + suppressList = range(aRealmLV+1, dRealmLV+1) + plus_minus = -1 + + + for realmLV in suppressList: + suppressRealmHurtPer += suppressRealmDict.get(realmLV, 0) + + return suppressRealmHurtPer*plus_minus + +# 获取双方境界值 def GetPVERealmLVs(atkObj, defObj, atkObjType, defObjType): if atkObjType == IPY_GameWorld.gotNPC: aRealmLV = NPCCommon.GetRealmLV(atkObj) @@ -1815,16 +2061,18 @@ ## 攻击时事件处理,反弹吸血或者额外触发技能等 # @param resultHurtType 伤害结构体 # @return -def AttackEventTrigger(atkObj, defObj, resultHurtType, tick): +def AttackEventTrigger(atkObj, defObj, curSkill, resultHurtType, tick): #反弹伤害 CalcBounceHP(atkObj, defObj, resultHurtType.LostHP, resultHurtType.HurtType) #吸血 - CalcSuckBlood(atkObj, defObj, resultHurtType.RealHurtHP, tick) + CalcSuckBlood(atkObj, defObj, curSkill, resultHurtType.RealHurtHP, tick) if atkObj.GetGameObjType() == IPY_GameWorld.gotPlayer: # 记录最后一次伤害值 atkObj.SetDict(ChConfig.Def_PlayerKey_LastHurtValue, resultHurtType.RealHurtHP) + if defObj.GetGameObjType() == IPY_GameWorld.gotNPC: + atkObj.SetDict(ChConfig.Def_PlayerKey_LastHurtNPCObjID, defObj.GetID()) return @@ -1835,6 +2083,12 @@ if objType == IPY_GameWorld.gotPlayer: return "P" + if objType == IPY_GameWorld.gotNPC: + if obj.GetType() == ChConfig.ntRobot: + return "Robot" + if obj.GetType() == ChConfig.ntHelpBattleRobot: + return "HelpRobot" + objType = obj.GetGameNPCObjType() if objType == IPY_GameWorld.gnotPet: return "Pet" @@ -1942,7 +2196,7 @@ # @param atkObj 攻击者 # @param defObj 防守者 # @return None -def CalcSuckBlood(atkObj, defObj, hurtValue, tick): +def CalcSuckBlood(atkObj, defObj, curSkill, hurtValue, tick): if atkObj.GetGameObjType() != IPY_GameWorld.gotPlayer: return @@ -1968,7 +2222,9 @@ #PVP 攻击回血 atkBackHP += PlayerControl.GetPVPAtkBackHP(atkObj) # 百分比吸血 - atkBackHPPer = PassiveBuffEffMng.GetValueByPassiveBuffTriggerType(atkObj, None, None, ChConfig.TriggerType_Buff_SuckBloodPer) + atkBackHPPer = PassiveBuffEffMng.GetValueByPassiveBuffTriggerType(atkObj, defObj, None, ChConfig.TriggerType_Buff_SuckBloodPer) + atkBackHPPer += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(atkObj, defObj, curSkill, ChConfig.TriggerType_Buff_SuckBloodPer) + atkBackHP += int(hurtValue * atkBackHPPer*1.0 / ChConfig.Def_MaxRateValue) suckHP += atkBackHP @@ -2152,6 +2408,12 @@ if tagPlayer.GetPlayerAction() == IPY_GameWorld.paSit: return ChConfig.Type_Relation_None, ChConfig.Def_PASysMessage_SitNotPK + if GetIsNewGuy(curPlayer): + return ChConfig.Type_Relation_None, ChConfig.Def_PASysMessage_NewGuy + + if GetIsNewGuy(tagPlayer): + return ChConfig.Type_Relation_None, ChConfig.Def_PASysMessage_NotAttackNewGuy + #攻守双方同一队伍,不可PK,可加增益buff #if curPlayerAreaType not in [ShareDefine.gatManor] and CanAlikeTeam(curPlayer, tagPlayer): # #副本队友特殊判断 @@ -2316,7 +2578,7 @@ # @param curObjDetel 对象实例 # @return 返回值无意义 # @remarks 理对象死亡逻辑 -def DoLogic_ObjDead(curObjDetel): +def DoLogic_ObjDead(atkObj, curObjDetel, curSkill, tick): if GameObj.GetHP(curObjDetel) > 0: return @@ -2327,6 +2589,9 @@ return #---NPC处理--- + if not ChNPC.OnCheckCanDie(atkObj, curObjDetel, curSkill, tick): + return + npcControl = NPCCommon.NPCControl(curObjDetel) npcControl.SetKilled() return -- Gitblit v1.8.0